summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2013-02-03 20:13:33 +0000
committerattilio <attilio@FreeBSD.org>2013-02-03 20:13:33 +0000
commit0d3b58aee00948d85d75a9d3d222deb454afc98e (patch)
tree865d112b57519913a8de64b2d9ca8787633c95a2
parent561dd1163dbb481d204da7a526739ac6e43d08f2 (diff)
parent2d2c37fb592dfc24f15e4bf14c2f109b5d4b5a83 (diff)
downloadFreeBSD-src-0d3b58aee00948d85d75a9d3d222deb454afc98e.zip
FreeBSD-src-0d3b58aee00948d85d75a9d3d222deb454afc98e.tar.gz
MFC
-rw-r--r--Makefile.inc1147
-rw-r--r--ObsoleteFiles.inc13
-rw-r--r--UPDATING16
-rw-r--r--bin/cat/cat.117
-rw-r--r--bin/cat/cat.c19
-rw-r--r--bin/cp/cp.c12
-rw-r--r--bin/cp/utils.c19
-rw-r--r--bin/df/df.13
-rw-r--r--bin/df/df.c3
-rw-r--r--bin/ps/extern.h2
-rw-r--r--bin/ps/fmt.c13
-rw-r--r--bin/ps/ps.c11
-rw-r--r--bin/pwait/pwait.c2
-rw-r--r--bin/sh/TOUR4
-rw-r--r--bin/sh/eval.c54
-rw-r--r--bin/sh/exec.c49
-rw-r--r--bin/sh/expand.c13
-rw-r--r--bin/sh/expand.h1
-rw-r--r--bin/sh/init.h1
-rw-r--r--bin/sh/input.c15
-rw-r--r--bin/sh/jobs.c4
-rw-r--r--bin/sh/main.c2
-rw-r--r--bin/sh/miscbltin.c4
-rw-r--r--bin/sh/mkinit.c8
-rw-r--r--bin/sh/mksyntax.c1
-rw-r--r--bin/sh/nodetypes1
-rw-r--r--bin/sh/parser.c7
-rw-r--r--bin/sh/redir.c22
-rw-r--r--bin/sh/sh.124
-rw-r--r--bin/sh/var.c32
-rw-r--r--cddl/contrib/opensolaris/cmd/zdb/zdb.c4
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c10
-rw-r--r--cddl/lib/libdtrace/Makefile2
-rw-r--r--[-rwxr-xr-x]contrib/binutils/config/acinclude.m40
-rw-r--r--contrib/bmake/ChangeLog32
-rw-r--r--contrib/bmake/FILES64
-rw-r--r--contrib/bmake/Makefile221
-rw-r--r--contrib/bmake/Makefile.config.in16
-rw-r--r--contrib/bmake/Makefile.in190
-rw-r--r--contrib/bmake/bmake.170
-rw-r--r--contrib/bmake/bmake.cat141
-rwxr-xr-xcontrib/bmake/boot-strap267
-rw-r--r--contrib/bmake/bsd.after-import.mk30
-rw-r--r--contrib/bmake/compat.c7
-rwxr-xr-xcontrib/bmake/configure28
-rw-r--r--contrib/bmake/configure.in12
-rw-r--r--contrib/bmake/job.c38
-rw-r--r--contrib/bmake/main.c218
-rwxr-xr-xcontrib/bmake/make-bootstrap.sh.in2
-rw-r--r--contrib/bmake/make.170
-rw-r--r--contrib/bmake/makefile.in14
-rw-r--r--contrib/bmake/meta.c26
-rw-r--r--contrib/bmake/mk/ChangeLog644
-rw-r--r--contrib/bmake/mk/FILES60
-rw-r--r--contrib/bmake/mk/README401
-rw-r--r--contrib/bmake/mk/auto.dep.mk64
-rw-r--r--contrib/bmake/mk/auto.obj.mk56
-rw-r--r--contrib/bmake/mk/autoconf.mk78
-rw-r--r--contrib/bmake/mk/autodep.mk216
-rw-r--r--contrib/bmake/mk/dep.mk133
-rw-r--r--contrib/bmake/mk/dirdeps.mk414
-rw-r--r--contrib/bmake/mk/doc.mk63
-rw-r--r--contrib/bmake/mk/dpadd.mk196
-rw-r--r--contrib/bmake/mk/final.mk14
-rw-r--r--contrib/bmake/mk/gendirdeps.mk301
-rw-r--r--contrib/bmake/mk/host-target.mk31
-rw-r--r--contrib/bmake/mk/host.libnames.mk29
-rw-r--r--contrib/bmake/mk/inc.mk35
-rw-r--r--contrib/bmake/mk/init.mk44
-rw-r--r--contrib/bmake/mk/install-mk185
-rw-r--r--contrib/bmake/mk/install-new.mk53
-rw-r--r--contrib/bmake/mk/java.mk97
-rw-r--r--contrib/bmake/mk/lib.mk605
-rw-r--r--contrib/bmake/mk/libnames.mk22
-rw-r--r--contrib/bmake/mk/libs.mk54
-rw-r--r--contrib/bmake/mk/links.mk75
-rw-r--r--contrib/bmake/mk/man.mk137
-rw-r--r--contrib/bmake/mk/meta.autodep.mk262
-rw-r--r--contrib/bmake/mk/meta.stage.mk212
-rw-r--r--contrib/bmake/mk/meta.subdir.mk79
-rw-r--r--contrib/bmake/mk/meta.sys.mk139
-rwxr-xr-xcontrib/bmake/mk/meta2deps.py614
-rwxr-xr-xcontrib/bmake/mk/meta2deps.sh307
-rw-r--r--contrib/bmake/mk/mk-files.txt467
-rw-r--r--contrib/bmake/mk/nls.mk48
-rw-r--r--contrib/bmake/mk/obj.mk113
-rw-r--r--contrib/bmake/mk/options.mk58
-rw-r--r--contrib/bmake/mk/own.mk244
-rw-r--r--contrib/bmake/mk/prlist.mk36
-rw-r--r--contrib/bmake/mk/prog.mk219
-rw-r--r--contrib/bmake/mk/progs.mk87
-rw-r--r--contrib/bmake/mk/rst2htm.mk43
-rw-r--r--contrib/bmake/mk/scripts.mk52
-rw-r--r--contrib/bmake/mk/srctop.mk66
-rw-r--r--contrib/bmake/mk/subdir.mk99
-rw-r--r--contrib/bmake/mk/sys.clean-env.mk119
-rw-r--r--contrib/bmake/mk/sys.dependfile.mk47
-rw-r--r--contrib/bmake/mk/sys.mk199
-rw-r--r--contrib/bmake/mk/sys/AIX.mk197
-rw-r--r--contrib/bmake/mk/sys/Darwin.mk220
-rw-r--r--contrib/bmake/mk/sys/Generic.mk208
-rw-r--r--contrib/bmake/mk/sys/HP-UX.mk237
-rw-r--r--contrib/bmake/mk/sys/IRIX.mk199
-rw-r--r--contrib/bmake/mk/sys/Linux.mk200
-rw-r--r--contrib/bmake/mk/sys/NetBSD.mk234
-rw-r--r--contrib/bmake/mk/sys/OSF1.mk211
-rw-r--r--contrib/bmake/mk/sys/OpenBSD.mk209
-rw-r--r--contrib/bmake/mk/sys/SunOS.mk232
-rw-r--r--contrib/bmake/mk/sys/UnixWare.mk254
-rw-r--r--contrib/bmake/mk/target-flags.mk62
-rw-r--r--contrib/bmake/mk/warnings.mk148
-rw-r--r--contrib/bmake/mk/yacc.mk57
-rw-r--r--contrib/bmake/realpath.c77
-rw-r--r--contrib/bmake/unit-tests/Makefile.in4
-rw-r--r--contrib/bmake/var.c16
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/lib/tc.def0
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_target/snmp_target.30
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_target/target_snmp.c0
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_target/target_tree.def0
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_usm/snmp_usm.30
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_usm/usm_snmp.c0
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_usm/usm_tree.def0
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_vacm/snmp_vacm.30
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_vacm/vacm_snmp.c0
-rw-r--r--[-rwxr-xr-x]contrib/bsnmp/snmp_vacm/vacm_tree.def0
-rw-r--r--contrib/compiler-rt/LICENSE.TXT4
-rw-r--r--contrib/compiler-rt/lib/arm/aeabi_uldivmod.S3
-rw-r--r--contrib/compiler-rt/lib/arm/divsi3.S12
-rw-r--r--contrib/compiler-rt/lib/arm/udivsi3.S10
-rw-r--r--contrib/compiler-rt/lib/cmpdi2.c13
-rw-r--r--contrib/compiler-rt/lib/fixsfdi.c2
-rw-r--r--contrib/compiler-rt/lib/int_endianness.h15
-rw-r--r--contrib/compiler-rt/lib/int_lib.h10
-rw-r--r--contrib/compiler-rt/lib/ucmpdi2.c13
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/common.funcs0
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/copi.ifman10
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/copi.ifman20
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/copi.ifmcfg20
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/copi.ifmcfg40
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/copi.ifmcfg50
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/copi.ifpoll20
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/copi.ifreq20
-rw-r--r--[-rwxr-xr-x]contrib/dialog/samples/copifuncs/copi.sendifm20
-rw-r--r--[-rwxr-xr-x]contrib/ee/Makefile0
-rw-r--r--[-rwxr-xr-x]contrib/ee/ee.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/doc/expat.pngbin1027 -> 1027 bytes
-rw-r--r--[-rwxr-xr-x]contrib/expat/doc/valid-xhtml10.pngbin2368 -> 2368 bytes
-rw-r--r--[-rwxr-xr-x]contrib/expat/lib/expat_external.h0
-rw-r--r--[-rwxr-xr-x]contrib/expat/tests/benchmark/README.txt0
-rw-r--r--[-rwxr-xr-x]contrib/expat/tests/benchmark/benchmark.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/tests/benchmark/benchmark.dsp0
-rw-r--r--[-rwxr-xr-x]contrib/expat/tests/benchmark/benchmark.dsw0
-rw-r--r--[-rwxr-xr-x]contrib/expat/tests/minicheck.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/tests/minicheck.h0
-rw-r--r--[-rwxr-xr-x]contrib/expat/tests/runtestspp.cpp0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/codepage.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/codepage.h0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/ct.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/filemap.h0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/readfilemap.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/unixfilemap.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/win32filemap.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/xmlfile.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/xmlfile.h0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/xmlmime.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/xmlmime.h0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/xmltchar.h0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/xmlurl.h0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/xmlwf.c0
-rw-r--r--[-rwxr-xr-x]contrib/expat/xmlwf/xmlwin32url.cxx0
-rw-r--r--contrib/file/Magdir/lua1
-rw-r--r--contrib/gcc/config/arm/freebsd.h32
-rw-r--r--[-rwxr-xr-x]contrib/gcc/config/i386/host-cygwin.c0
-rw-r--r--[-rwxr-xr-x]contrib/gcc/config/i386/winnt-cxx.c0
-rw-r--r--[-rwxr-xr-x]contrib/gcc/config/i386/winnt-stubs.c0
-rw-r--r--contrib/gcc/unwind-dw2.c12
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/config/i386/nm-nto.h0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/config/i386/nto.mh0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/config/i386/nto.mt0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/config/i386/tm-nto.h0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/config/tm-nto.h0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/i386-nto-tdep.c0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/nto-procfs.c0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/nto-tdep.c0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/nto-tdep.h0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/proc-api.c0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/proc-events.c0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/proc-flags.c0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/proc-why.c0
-rw-r--r--[-rwxr-xr-x]contrib/gdb/gdb/uw-thread.c0
-rw-r--r--[-rwxr-xr-x]contrib/ipfilter/FreeBSD-4.0/ipv6-patch0
-rw-r--r--[-rwxr-xr-x]contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.00
-rw-r--r--contrib/ipfilter/ipsend/44arp.c4
-rw-r--r--contrib/jemalloc/COPYING4
-rw-r--r--contrib/jemalloc/ChangeLog17
-rw-r--r--contrib/jemalloc/FREEBSD-diffs16
-rwxr-xr-xcontrib/jemalloc/FREEBSD-upgrade1
-rw-r--r--contrib/jemalloc/VERSION2
-rw-r--r--contrib/jemalloc/doc/jemalloc.310
-rw-r--r--contrib/jemalloc/include/jemalloc/internal/arena.h84
-rw-r--r--contrib/jemalloc/include/jemalloc/internal/ckh.h8
-rw-r--r--contrib/jemalloc/include/jemalloc/internal/hash.h331
-rw-r--r--contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h51
-rw-r--r--contrib/jemalloc/include/jemalloc/internal/private_namespace.h17
-rw-r--r--contrib/jemalloc/include/jemalloc/internal/tcache.h20
-rw-r--r--contrib/jemalloc/include/jemalloc/jemalloc.h6
-rw-r--r--contrib/jemalloc/include/jemalloc/jemalloc_defs.h5
-rw-r--r--contrib/jemalloc/src/arena.c77
-rw-r--r--contrib/jemalloc/src/chunk.c35
-rw-r--r--contrib/jemalloc/src/chunk_dss.c1
-rw-r--r--contrib/jemalloc/src/ckh.c86
-rw-r--r--contrib/jemalloc/src/ctl.c20
-rw-r--r--contrib/jemalloc/src/jemalloc.c69
-rw-r--r--contrib/jemalloc/src/prof.c34
-rw-r--r--contrib/jemalloc/src/tcache.c9
-rw-r--r--contrib/libarchive/libarchive/archive_getdate.c9
-rw-r--r--contrib/libarchive/libarchive/test/test_archive_getdate.c3
-rw-r--r--contrib/libcxxrt/atomic.h29
-rw-r--r--contrib/libcxxrt/exception.cc86
-rw-r--r--contrib/libcxxrt/memory.cc33
-rw-r--r--contrib/libcxxrt/typeinfo.h18
-rw-r--r--[-rwxr-xr-x]contrib/libpcap/configure.in0
-rw-r--r--[-rwxr-xr-x]contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h0
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td2
-rw-r--r--contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp46
-rw-r--r--[-rwxr-xr-x]contrib/ntp/html/drivers/driver44.html0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/include/icom.h0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/readme.y2kfixesbin8192 -> 8192 bytes
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/clock.awk0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/dupe.awk0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/ensemble.S0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/ensemble.awk0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/etf.S0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/etf.awk0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/itf.S0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/itf.awk0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/loop.S0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/loop.awk0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/loop_summary0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/peer.awk0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/psummary.awk0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/tdata.S0
-rw-r--r--[-rwxr-xr-x]contrib/ntp/scripts/stats/tdata.awk0
-rw-r--r--[-rwxr-xr-x]contrib/tcpdump/bgp.h0
-rw-r--r--[-rwxr-xr-x]contrib/tcpdump/configure.in0
-rw-r--r--[-rwxr-xr-x]contrib/tcpdump/ipproto.c0
-rw-r--r--[-rwxr-xr-x]contrib/tcpdump/l2vpn.c0
-rw-r--r--[-rwxr-xr-x]contrib/tcpdump/l2vpn.h0
-rw-r--r--[-rwxr-xr-x]contrib/tcpdump/nlpid.c0
-rw-r--r--[-rwxr-xr-x]contrib/tcpdump/print-syslog.c0
-rw-r--r--[-rwxr-xr-x]crypto/heimdal/doc/vars.texi0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/crypto/bn/asm/s390x.S0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/crypto/bn/bn_const.c0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/crypto/ocsp/ocsp_cl.c0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/crypto/ocsp/ocsp_ext.c0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/crypto/ocsp/ocsp_lib.c0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/crypto/ocsp/ocsp_srv.c0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/crypto/rand/rand_lcl.h0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/crypto/vms_rms.h0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/util/libeay.num0
-rw-r--r--[-rwxr-xr-x]crypto/openssl/util/ssleay.num0
-rw-r--r--etc/Makefile102
-rw-r--r--etc/login.conf2
-rw-r--r--etc/mtree/BSD.usr.dist8
-rwxr-xr-xetc/rc.d/ip6addrctl28
-rwxr-xr-xetc/rc.d/jail9
-rw-r--r--etc/rc.subr2
-rw-r--r--gnu/lib/csu/Makefile4
-rw-r--r--gnu/lib/libgcc/Makefile25
-rw-r--r--gnu/lib/libgcov/Makefile5
-rw-r--r--gnu/lib/libstdc++/Makefile10
-rw-r--r--gnu/lib/libsupc++/Version.map29
-rw-r--r--gnu/usr.bin/Makefile2
-rw-r--r--gnu/usr.bin/cc/Makefile.inc4
-rw-r--r--gnu/usr.bin/cc/c++/Makefile9
-rw-r--r--gnu/usr.bin/cc/c++filt/Makefile4
-rw-r--r--gnu/usr.bin/cc/cc1/Makefile3
-rw-r--r--gnu/usr.bin/cc/cc1plus/Makefile3
-rw-r--r--gnu/usr.bin/cc/cc_int/Makefile2
-rw-r--r--gnu/usr.bin/cc/cc_tools/Makefile9
-rw-r--r--gnu/usr.bin/cc/doc/Makefile2
-rw-r--r--gnu/usr.bin/cc/gcov/Makefile2
-rw-r--r--gnu/usr.bin/cc/include/Makefile2
-rw-r--r--gnu/usr.bin/cc/libcpp/Makefile2
-rw-r--r--gnu/usr.bin/cc/libdecnumber/Makefile2
-rw-r--r--gnu/usr.bin/cc/libiberty/Makefile2
-rw-r--r--gnu/usr.bin/gdb/kgdb/main.c15
-rw-r--r--gnu/usr.bin/grep/grep.c8
-rw-r--r--gnu/usr.bin/patch/Makefile13
-rw-r--r--include/arpa/Makefile7
-rw-r--r--include/stdio.h1
-rw-r--r--include/time.h1
-rw-r--r--kerberos5/lib/libkrb5/Makefile10
-rw-r--r--lib/Makefile5
-rw-r--r--lib/clang/Makefile25
-rw-r--r--lib/clang/clang.build.mk6
-rw-r--r--lib/clang/libclanganalysis/Makefile2
-rw-r--r--lib/clang/libclangarcmigrate/Makefile2
-rw-r--r--lib/clang/libclangast/Makefile2
-rw-r--r--lib/clang/libclangbasic/Makefile2
-rw-r--r--lib/clang/libclangcodegen/Makefile2
-rw-r--r--lib/clang/libclangdriver/Makefile2
-rw-r--r--lib/clang/libclangedit/Makefile2
-rw-r--r--lib/clang/libclangfrontend/Makefile2
-rw-r--r--lib/clang/libclangfrontendtool/Makefile2
-rw-r--r--lib/clang/libclanglex/Makefile2
-rw-r--r--lib/clang/libclangparse/Makefile2
-rw-r--r--lib/clang/libclangrewritecore/Makefile2
-rw-r--r--lib/clang/libclangrewritefrontend/Makefile2
-rw-r--r--lib/clang/libclangsema/Makefile2
-rw-r--r--lib/clang/libclangserialization/Makefile2
-rw-r--r--lib/clang/libclangstaticanalyzercheckers/Makefile2
-rw-r--r--lib/clang/libclangstaticanalyzercore/Makefile2
-rw-r--r--lib/clang/libclangstaticanalyzerfrontend/Makefile2
-rw-r--r--lib/clang/libllvmarchive/Makefile2
-rw-r--r--lib/clang/libllvmarmasmparser/Makefile2
-rw-r--r--lib/clang/libllvmarmcodegen/Makefile2
-rw-r--r--lib/clang/libllvmarmdesc/Makefile2
-rw-r--r--lib/clang/libllvmarmdisassembler/Makefile2
-rw-r--r--lib/clang/libllvmarminfo/Makefile2
-rw-r--r--lib/clang/libllvmarminstprinter/Makefile2
-rw-r--r--lib/clang/libllvmasmparser/Makefile2
-rw-r--r--lib/clang/libllvmasmprinter/Makefile2
-rw-r--r--lib/clang/libllvmbitreader/Makefile2
-rw-r--r--lib/clang/libllvmbitwriter/Makefile2
-rw-r--r--lib/clang/libllvmcodegen/Makefile2
-rw-r--r--lib/clang/libllvmcore/Makefile2
-rw-r--r--lib/clang/libllvmdebuginfo/Makefile2
-rw-r--r--lib/clang/libllvmexecutionengine/Makefile2
-rw-r--r--lib/clang/libllvminstcombine/Makefile2
-rw-r--r--lib/clang/libllvminstrumentation/Makefile2
-rw-r--r--lib/clang/libllvminterpreter/Makefile2
-rw-r--r--lib/clang/libllvmjit/Makefile2
-rw-r--r--lib/clang/libllvmlinker/Makefile2
-rw-r--r--lib/clang/libllvmmcdisassembler/Makefile2
-rw-r--r--lib/clang/libllvmmcparser/Makefile2
-rw-r--r--lib/clang/libllvmmipsasmparser/Makefile2
-rw-r--r--lib/clang/libllvmmipscodegen/Makefile2
-rw-r--r--lib/clang/libllvmmipsdesc/Makefile2
-rw-r--r--lib/clang/libllvmmipsdisassembler/Makefile2
-rw-r--r--lib/clang/libllvmmipsinfo/Makefile2
-rw-r--r--lib/clang/libllvmmipsinstprinter/Makefile2
-rw-r--r--lib/clang/libllvmobject/Makefile2
-rw-r--r--lib/clang/libllvmpowerpccodegen/Makefile2
-rw-r--r--lib/clang/libllvmpowerpcdesc/Makefile2
-rw-r--r--lib/clang/libllvmpowerpcinfo/Makefile2
-rw-r--r--lib/clang/libllvmpowerpcinstprinter/Makefile2
-rw-r--r--lib/clang/libllvmruntimedyld/Makefile2
-rw-r--r--lib/clang/libllvmselectiondag/Makefile2
-rw-r--r--lib/clang/libllvmtablegen/Makefile2
-rw-r--r--lib/clang/libllvmtarget/Makefile2
-rw-r--r--lib/clang/libllvmvectorize/Makefile2
-rw-r--r--lib/clang/libllvmx86asmparser/Makefile2
-rw-r--r--lib/clang/libllvmx86codegen/Makefile2
-rw-r--r--lib/clang/libllvmx86desc/Makefile2
-rw-r--r--lib/clang/libllvmx86info/Makefile2
-rw-r--r--lib/clang/libllvmx86instprinter/Makefile2
-rw-r--r--lib/clang/libllvmx86utils/Makefile2
-rw-r--r--lib/libarchive/Makefile7
-rw-r--r--lib/libc/amd64/sys/__vdso_gettc.c11
-rw-r--r--lib/libc/arm/Makefile.inc8
-rw-r--r--lib/libc/arm/SYS.h8
-rw-r--r--lib/libc/arm/Symbol.map4
-rw-r--r--lib/libc/arm/Symbol_oabi.map16
-rw-r--r--lib/libc/arm/aeabi/Makefile.inc11
-rw-r--r--lib/libc/arm/aeabi/Symbol.map47
-rw-r--r--lib/libc/arm/aeabi/aeabi_atexit.c (renamed from sys/arm/mv/kirkwood/sheevaplug.c)22
-rw-r--r--lib/libc/arm/aeabi/aeabi_double.c101
-rw-r--r--lib/libc/arm/aeabi/aeabi_float.c101
-rw-r--r--lib/libc/arm/aeabi/aeabi_unwind_cpp.c61
-rw-r--r--lib/libc/arm/gen/Makefile.inc6
-rw-r--r--lib/libc/arm/sys/Makefile.inc2
-rw-r--r--lib/libc/arm/sys/__vdso_gettc.c48
-rw-r--r--lib/libc/gen/Makefile.inc1
-rw-r--r--lib/libc/gen/Symbol.map4
-rw-r--r--lib/libc/i386/sys/__vdso_gettc.c10
-rw-r--r--lib/libc/ia64/sys/Makefile.inc2
-rw-r--r--lib/libc/ia64/sys/__vdso_gettc.c48
-rw-r--r--lib/libc/mips/sys/Makefile.inc2
-rw-r--r--lib/libc/mips/sys/__vdso_gettc.c48
-rw-r--r--lib/libc/net/name6.c10
-rw-r--r--lib/libc/powerpc/Makefile.inc2
-rw-r--r--lib/libc/powerpc/sys/__vdso_gettc.c48
-rw-r--r--lib/libc/powerpc64/Makefile.inc2
-rw-r--r--lib/libc/powerpc64/sys/__vdso_gettc.c48
-rw-r--r--lib/libc/quad/Makefile.inc4
-rw-r--r--lib/libc/sparc64/Makefile.inc2
-rw-r--r--lib/libc/sparc64/sys/__vdso_gettc.c48
-rw-r--r--lib/libc/stdio/Makefile.inc5
-rw-r--r--lib/libc/stdio/Symbol.map1
-rw-r--r--lib/libc/stdio/fmemopen.c258
-rw-r--r--lib/libc/stdio/fopen.354
-rw-r--r--lib/libc/sys/__vdso_gettimeofday.c4
-rw-r--r--lib/libc/sys/chroot.28
-rw-r--r--lib/libc/sys/gettimeofday.c5
-rw-r--r--lib/libc/sys/kqueue.26
-rw-r--r--lib/libc/sys/posix_fadvise.22
-rw-r--r--lib/libcompiler_rt/Makefile17
-rw-r--r--lib/libcxxrt/Version.map102
-rw-r--r--lib/libedit/editline.32
-rw-r--r--lib/libedit/editrc.57
-rw-r--r--lib/libpmc/Makefile1
-rw-r--r--lib/libpmc/libpmc.c23
-rw-r--r--lib/libpmc/pmc.ivybridge.31
-rw-r--r--lib/libpmc/pmc.ivybridgexeon.3911
-rw-r--r--lib/libpmc/pmc.sandybridge.32
-rw-r--r--lib/libpmc/pmc.sandybridgexeon.31
-rw-r--r--lib/libproc/proc_rtld.c3
-rw-r--r--lib/libradius/libradius.32
-rw-r--r--lib/libstand/if_ether.h261
-rw-r--r--lib/libthr/thread/thr_init.c6
-rw-r--r--lib/libthr/thread/thr_kern.c5
-rw-r--r--lib/libutil/gr_util.c34
-rw-r--r--lib/libvmmapi/Makefile11
-rw-r--r--lib/libvmmapi/vmmapi.c723
-rw-r--r--lib/libvmmapi/vmmapi.h105
-rw-r--r--lib/libvmmapi/vmmapi_freebsd.c183
-rw-r--r--lib/ncurses/form/Makefile4
-rw-r--r--lib/ncurses/menu/Makefile4
-rw-r--r--lib/ncurses/ncurses/Makefile8
-rw-r--r--lib/ncurses/panel/Makefile4
-rw-r--r--libexec/bootpd/rtmsg.c26
-rw-r--r--libexec/rtld-elf/Makefile10
-rw-r--r--libexec/tftpd/tftp-io.c10
-rw-r--r--libexec/tftpd/tftp-options.c13
-rw-r--r--libexec/tftpd/tftp-utils.h2
-rw-r--r--libexec/tftpd/tftpd.c9
-rw-r--r--release/Makefile25
-rw-r--r--release/amd64/mkisoimages.sh3
-rwxr-xr-xrelease/generate-release.sh227
-rw-r--r--release/i386/mkisoimages.sh3
-rw-r--r--release/ia64/mkisoimages.sh4
-rw-r--r--release/pc98/mkisoimages.sh3
-rw-r--r--release/powerpc/mkisoimages.sh4
-rwxr-xr-xrelease/rc.local10
-rw-r--r--release/sparc64/mkisoimages.sh88
-rw-r--r--sbin/devd/devd.87
-rw-r--r--sbin/devd/devd.cc154
-rw-r--r--sbin/devd/devd.hh5
-rw-r--r--sbin/geom/class/part/gpart.839
-rw-r--r--sbin/geom/class/raid/graid.83
-rw-r--r--sbin/geom/class/raid3/geom_raid3.c2
-rw-r--r--sbin/geom/class/raid3/graid3.86
-rw-r--r--sbin/ifconfig/af_inet6.c2
-rw-r--r--sbin/ifconfig/af_nd6.c2
-rw-r--r--sbin/ifconfig/ifconfig.89
-rw-r--r--sbin/newfs_msdos/newfs_msdos.c8
-rw-r--r--sbin/route/route.c5
-rw-r--r--sbin/setkey/Makefile2
-rw-r--r--sbin/sysctl/sysctl.c2
-rw-r--r--secure/lib/libssh/Makefile4
-rw-r--r--secure/usr.bin/ssh/Makefile4
-rw-r--r--secure/usr.sbin/sshd/Makefile4
-rw-r--r--share/info/Makefile2
-rw-r--r--share/man/man4/Makefile2
-rw-r--r--share/man/man4/bhyve.468
-rw-r--r--share/man/man4/mfi.410
-rw-r--r--share/man/man4/rl.44
-rw-r--r--share/man/man4/stf.44
-rw-r--r--share/man/man5/make.conf.511
-rw-r--r--share/man/man5/src.conf.567
-rw-r--r--share/man/man7/release.7102
-rw-r--r--share/man/man9/VFS_SET.926
-rw-r--r--share/man/man9/vm_map_insert.95
-rw-r--r--share/man/man9/vm_map_stack.910
-rw-r--r--share/misc/committers-doc.dot5
-rw-r--r--share/misc/committers-ports.dot4
-rw-r--r--share/misc/committers-src.dot5
-rw-r--r--share/mk/Makefile1
-rw-r--r--share/mk/bsd.README2
-rw-r--r--share/mk/bsd.compat.mk41
-rw-r--r--share/mk/bsd.incs.mk2
-rw-r--r--share/mk/bsd.info.mk2
-rw-r--r--share/mk/bsd.init.mk1
-rw-r--r--share/mk/bsd.lib.mk13
-rw-r--r--share/mk/bsd.libnames.mk1
-rw-r--r--share/mk/bsd.links.mk4
-rw-r--r--share/mk/bsd.man.mk6
-rw-r--r--share/mk/bsd.own.mk99
-rw-r--r--share/mk/bsd.prog.mk3
-rw-r--r--share/mk/sys.mk1
-rw-r--r--share/monetdef/Makefile4
-rw-r--r--share/msgdef/Makefile2
-rw-r--r--share/numericdef/Makefile2
-rw-r--r--share/zoneinfo/Makefile35
-rw-r--r--sys/amd64/amd64/mp_machdep.c4
-rw-r--r--sys/amd64/amd64/pmap.c12
-rw-r--r--sys/amd64/conf/GENERIC9
-rw-r--r--sys/amd64/conf/NOTES9
-rw-r--r--sys/amd64/include/intr_machdep.h2
-rw-r--r--sys/amd64/include/vmm.h293
-rw-r--r--sys/amd64/include/vmm_dev.h215
-rw-r--r--sys/amd64/include/vmm_instruction_emul.h114
-rw-r--r--sys/amd64/linux32/linux.h153
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c1
-rw-r--r--sys/amd64/vmm/amd/amdv.c265
-rw-r--r--sys/amd64/vmm/intel/ept.c392
-rw-r--r--sys/amd64/vmm/intel/ept.h43
-rw-r--r--sys/amd64/vmm/intel/vmcs.c551
-rw-r--r--sys/amd64/vmm/intel/vmcs.h338
-rw-r--r--sys/amd64/vmm/intel/vmx.c1852
-rw-r--r--sys/amd64/vmm/intel/vmx.h120
-rw-r--r--sys/amd64/vmm/intel/vmx_controls.h92
-rw-r--r--sys/amd64/vmm/intel/vmx_cpufunc.h218
-rw-r--r--sys/amd64/vmm/intel/vmx_genassym.c89
-rw-r--r--sys/amd64/vmm/intel/vmx_msr.c172
-rw-r--r--sys/amd64/vmm/intel/vmx_msr.h78
-rw-r--r--sys/amd64/vmm/intel/vmx_support.S246
-rw-r--r--sys/amd64/vmm/intel/vtd.c677
-rw-r--r--sys/amd64/vmm/io/iommu.c277
-rw-r--r--sys/amd64/vmm/io/iommu.h75
-rw-r--r--sys/amd64/vmm/io/ppt.c619
-rw-r--r--sys/amd64/vmm/io/ppt.h41
-rw-r--r--sys/amd64/vmm/io/vdev.c270
-rw-r--r--sys/amd64/vmm/io/vdev.h84
-rw-r--r--sys/amd64/vmm/io/vlapic.c901
-rw-r--r--sys/amd64/vmm/io/vlapic.h111
-rw-r--r--sys/amd64/vmm/vmm.c1038
-rw-r--r--sys/amd64/vmm/vmm_dev.c538
-rw-r--r--sys/amd64/vmm/vmm_host.c124
-rw-r--r--sys/amd64/vmm/vmm_host.h75
-rw-r--r--sys/amd64/vmm/vmm_instruction_emul.c868
-rw-r--r--sys/amd64/vmm/vmm_ipi.c93
-rw-r--r--sys/amd64/vmm/vmm_ipi.h39
-rw-r--r--sys/amd64/vmm/vmm_ktr.h51
-rw-r--r--sys/amd64/vmm/vmm_lapic.c201
-rw-r--r--sys/amd64/vmm/vmm_lapic.h71
-rw-r--r--sys/amd64/vmm/vmm_mem.c135
-rw-r--r--sys/amd64/vmm/vmm_mem.h37
-rw-r--r--sys/amd64/vmm/vmm_msr.c254
-rw-r--r--sys/amd64/vmm/vmm_msr.h43
-rw-r--r--sys/amd64/vmm/vmm_stat.c104
-rw-r--r--sys/amd64/vmm/vmm_stat.h71
-rw-r--r--sys/amd64/vmm/vmm_support.S42
-rw-r--r--sys/amd64/vmm/vmm_util.c111
-rw-r--r--sys/amd64/vmm/vmm_util.h40
-rw-r--r--sys/amd64/vmm/x86.c202
-rw-r--r--sys/amd64/vmm/x86.h64
-rw-r--r--sys/arm/allwinner/a10_clk.c171
-rw-r--r--sys/arm/allwinner/a10_clk.h114
-rw-r--r--sys/arm/allwinner/a10_ehci.c279
-rw-r--r--sys/arm/allwinner/a10_machdep.c122
-rw-r--r--sys/arm/allwinner/aintc.c211
-rw-r--r--sys/arm/allwinner/bus_space.c113
-rw-r--r--sys/arm/allwinner/common.c63
-rw-r--r--sys/arm/allwinner/console.c142
-rw-r--r--sys/arm/allwinner/files.a1019
-rw-r--r--sys/arm/allwinner/std.a1021
-rw-r--r--sys/arm/allwinner/timer.c379
-rw-r--r--sys/arm/arm/busdma_machdep.c30
-rw-r--r--sys/arm/arm/cpufunc.c4
-rw-r--r--sys/arm/arm/cpufunc_asm_arm10.S26
-rw-r--r--sys/arm/arm/cpufunc_asm_arm9.S26
-rw-r--r--sys/arm/arm/db_trace.c416
-rw-r--r--sys/arm/arm/intr.c35
-rw-r--r--sys/arm/arm/locore.S19
-rw-r--r--sys/arm/arm/machdep.c1
-rw-r--r--sys/arm/arm/swtch.S3
-rw-r--r--sys/arm/arm/trap.c8
-rw-r--r--sys/arm/arm/vm_machdep.c6
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_fb.c25
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_machdep.c5
-rw-r--r--sys/arm/conf/BEAGLEBONE6
-rw-r--r--sys/arm/conf/CUBIEBOARD134
-rw-r--r--sys/arm/conf/DOCKSTAR2
-rw-r--r--sys/arm/conf/DREAMPLUG-1001183
-rw-r--r--sys/arm/conf/NOTES1
-rw-r--r--sys/arm/conf/SHEEVAPLUG2
-rw-r--r--sys/arm/include/atomic.h25
-rw-r--r--sys/arm/include/intr.h1
-rw-r--r--sys/arm/include/proc.h6
-rw-r--r--sys/arm/include/vmparam.h7
-rw-r--r--sys/arm/mv/kirkwood/files.sheevaplug4
-rw-r--r--sys/arm/mv/kirkwood/std.sheevaplug5
-rw-r--r--sys/arm/mv/mv_machdep.c19
-rw-r--r--sys/arm/ti/am335x/am335x_scm_padconf.c248
-rw-r--r--sys/arm/ti/cpsw/if_cpsw.c2324
-rw-r--r--sys/arm/ti/cpsw/if_cpswreg.h24
-rw-r--r--sys/arm/ti/cpsw/if_cpswvar.h139
-rw-r--r--sys/arm/ti/ti_scm.c13
-rw-r--r--sys/boot/arm/uboot/Makefile4
-rw-r--r--sys/boot/fdt/dts/beaglebone.dts57
-rw-r--r--sys/boot/fdt/dts/cubieboard.dts111
-rw-r--r--sys/boot/fdt/dts/dreamplug-1001.dts319
-rw-r--r--sys/boot/fdt/dts/dreamplug-1001N.dts340
-rw-r--r--sys/boot/i386/efi/Makefile2
-rw-r--r--sys/boot/i386/libi386/bootinfo64.c3
-rw-r--r--sys/boot/i386/libi386/comconsole.c25
-rw-r--r--sys/boot/i386/libi386/devicename.c2
-rw-r--r--sys/boot/i386/libi386/pxe.c6
-rw-r--r--sys/boot/sparc64/loader/main.c20
-rw-r--r--sys/boot/uboot/common/metadata.c15
-rw-r--r--sys/boot/usb/Makefile150
-rw-r--r--sys/boot/usb/Makefile.test61
-rw-r--r--sys/boot/usb/bsd_busspace.c207
-rw-r--r--sys/boot/usb/bsd_global.h63
-rw-r--r--sys/boot/usb/bsd_kernel.c1269
-rw-r--r--sys/boot/usb/bsd_kernel.h458
-rw-r--r--sys/boot/usb/bsd_usbloader_test.c80
-rw-r--r--sys/boot/usb/tools/sysinit.c331
-rw-r--r--sys/boot/usb/tools/sysinit.h57
-rw-r--r--sys/boot/usb/usb_busdma_loader.c619
-rw-r--r--sys/cam/ctl/ctl.c24
-rw-r--r--sys/cam/ctl/scsi_ctl.c247
-rw-r--r--sys/cam/scsi/scsi_all.c21
-rw-r--r--sys/cam/scsi/scsi_cd.c13
-rw-r--r--sys/cam/scsi/scsi_da.c83
-rw-r--r--sys/cam/scsi/scsi_enc_ses.c12
-rw-r--r--sys/cddl/compat/opensolaris/sys/kmem.h1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c26
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c9
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c5
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c73
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c143
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_asm.S44
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_isa.c83
-rw-r--r--sys/compat/linprocfs/linprocfs.c6
-rw-r--r--sys/compat/linux/linux_emul.c1
-rw-r--r--sys/compat/linux/linux_file.c1
-rw-r--r--sys/compat/linux/linux_file.h19
-rw-r--r--sys/compat/linux/linux_fork.c1
-rw-r--r--sys/compat/linux/linux_futex.c4
-rw-r--r--sys/compat/linux/linux_ioctl.h16
-rw-r--r--sys/compat/linux/linux_ipc.h44
-rw-r--r--sys/compat/linux/linux_mib.c1
-rw-r--r--sys/compat/linux/linux_misc.h48
-rw-r--r--sys/compat/linux/linux_signal.h3
-rw-r--r--sys/compat/linux/linux_socket.c28
-rw-r--r--sys/compat/linux/linux_socket.h40
-rw-r--r--sys/compat/linux/linux_sysctl.c1
-rw-r--r--sys/compat/linux/linux_time.c1
-rw-r--r--sys/conf/Makefile.arm4
-rw-r--r--sys/conf/NOTES5
-rw-r--r--sys/conf/files21
-rw-r--r--sys/conf/files.amd6417
-rw-r--r--sys/conf/files.arm2
-rw-r--r--sys/conf/files.i38612
-rw-r--r--sys/conf/files.mips1
-rw-r--r--sys/conf/ldscript.arm12
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/conf/options5
-rw-r--r--sys/contrib/dev/acpica/changes.txt152
-rw-r--r--sys/contrib/dev/acpica/common/adfile.c2
-rw-r--r--sys/contrib/dev/acpica/common/adisasm.c18
-rw-r--r--sys/contrib/dev/acpica/common/adwalk.c2
-rw-r--r--sys/contrib/dev/acpica/common/ahpredef.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmextern.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmrestag.c8
-rw-r--r--sys/contrib/dev/acpica/common/dmtable.c5
-rw-r--r--sys/contrib/dev/acpica/common/dmtbdump.c27
-rw-r--r--sys/contrib/dev/acpica/common/dmtbinfo.c53
-rw-r--r--sys/contrib/dev/acpica/common/getopt.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslanalyze.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslbtypes.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcodegen.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompile.c18
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.h49
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.l4
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.y17
-rw-r--r--sys/contrib/dev/acpica/compiler/asldefine.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslerror.c3
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfileio.c393
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfiles.c350
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfold.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslglobal.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslhex.c401
-rw-r--r--sys/contrib/dev/acpica/compiler/asllength.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asllisting.c486
-rw-r--r--sys/contrib/dev/acpica/compiler/aslload.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asllookup.c1238
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmain.c11
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmap.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmessages.h6
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmethod.c619
-rw-r--r--sys/contrib/dev/acpica/compiler/aslnamesp.c422
-rw-r--r--sys/contrib/dev/acpica/compiler/aslopcodes.c10
-rw-r--r--sys/contrib/dev/acpica/compiler/asloperands.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslopt.c8
-rw-r--r--sys/contrib/dev/acpica/compiler/aslpredef.c17
-rw-r--r--sys/contrib/dev/acpica/compiler/aslresource.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype1.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype1i.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2d.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2e.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2q.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2s.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2w.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslstartup.c4
-rw-r--r--sys/contrib/dev/acpica/compiler/aslstubs.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslsupport.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltransform.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltree.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltypes.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslutils.c5
-rw-r--r--sys/contrib/dev/acpica/compiler/asluuid.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslwalks.c573
-rw-r--r--sys/contrib/dev/acpica/compiler/aslxref.c874
-rw-r--r--sys/contrib/dev/acpica/compiler/dtcompile.c12
-rw-r--r--sys/contrib/dev/acpica/compiler/dtcompiler.h17
-rw-r--r--sys/contrib/dev/acpica/compiler/dtexpress.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtfield.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtio.c155
-rw-r--r--sys/contrib/dev/acpica/compiler/dtparser.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtparser.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtsubtable.c3
-rw-r--r--sys/contrib/dev/acpica/compiler/dttable.c90
-rw-r--r--sys/contrib/dev/acpica/compiler/dttemplate.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dttemplate.h59
-rw-r--r--sys/contrib/dev/acpica/compiler/dtutils.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/preprocess.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/prexpress.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prmacros.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prparser.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/prparser.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/prscan.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbcmds.c259
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbconvert.c525
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbdisply.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbexec.c510
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbfileio.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbhistry.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbinput.c8
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbmethod.c4
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbnames.c4
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbstats.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbutils.c4
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbxface.c6
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmbuffer.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmdeferred.c4
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmnames.c8
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmobject.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmopcode.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrc.c5
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcl.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcs.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmwalk.c27
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsargs.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dscontrol.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsfield.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsmethod.c3
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsobject.c17
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsopcode.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsutils.c12
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswexec.c6
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswload.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswload2.c4
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswscope.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswstate.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evevent.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evglock.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpe.c8
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeblk.c12
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeinit.c5
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeutil.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evhandler.c578
-rw-r--r--sys/contrib/dev/acpica/components/events/evmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evregion.c634
-rw-r--r--sys/contrib/dev/acpica/components/events/evrgnini.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evsci.c6
-rw-r--r--sys/contrib/dev/acpica/components/events/evxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfevnt.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfgpe.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfregn.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exconfig.c18
-rw-r--r--sys/contrib/dev/acpica/components/executer/exconvrt.c4
-rw-r--r--sys/contrib/dev/acpica/components/executer/excreate.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exdebug.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exdump.c14
-rw-r--r--sys/contrib/dev/acpica/components/executer/exfield.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exfldio.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exmutex.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exnames.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg1.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg2.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg3.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg6.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exprep.c6
-rw-r--r--sys/contrib/dev/acpica/components/executer/exregion.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresnte.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresolv.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresop.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstore.c27
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstoren.c4
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstorob.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exsystem.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exutils.c22
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwacpi.c14
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwesleep.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwgpe.c4
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwpci.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwregs.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwsleep.c4
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwtimer.c9
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwvalid.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwxface.c132
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwxfsleep.c4
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsaccess.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsalloc.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsdump.c9
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsdumpdv.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nseval.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsinit.c25
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsload.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsnames.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsobject.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsparse.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nspredef.c601
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsprepkg.c639
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsrepair.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsrepair2.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nssearch.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsutils.c88
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nswalk.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfeval.c4
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfname.c4
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfobj.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psargs.c10
-rw-r--r--sys/contrib/dev/acpica/components/parser/psloop.c665
-rw-r--r--sys/contrib/dev/acpica/components/parser/psobject.c683
-rw-r--r--sys/contrib/dev/acpica/components/parser/psopcode.c184
-rw-r--r--sys/contrib/dev/acpica/components/parser/psopinfo.c238
-rw-r--r--sys/contrib/dev/acpica/components/parser/psparse.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psscope.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/pstree.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psutils.c13
-rw-r--r--sys/contrib/dev/acpica/components/parser/pswalk.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsaddr.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rscalc.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rscreate.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsdump.c315
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsdumpinfo.c357
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsinfo.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsio.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsirq.c34
-rw-r--r--sys/contrib/dev/acpica/components/resources/rslist.c4
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsmemory.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsserial.c10
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsutils.c5
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsxface.c110
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbfadt.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbfind.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbinstal.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxfload.c4
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxfroot.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utaddress.c6
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utalloc.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utcache.c14
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utcopy.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdebug.c123
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdecode.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdelete.c4
-rw-r--r--sys/contrib/dev/acpica/components/utilities/uteval.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utexcep.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utglobal.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utids.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utlock.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmath.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmisc.c958
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmutex.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utobject.c4
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utosi.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utownerid.c241
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utresrc.c8
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utstate.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utstring.c674
-rw-r--r--sys/contrib/dev/acpica/components/utilities/uttrack.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxferror.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxfinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxfmutex.c2
-rw-r--r--sys/contrib/dev/acpica/include/acapps.h4
-rw-r--r--sys/contrib/dev/acpica/include/acbuffer.h2
-rw-r--r--sys/contrib/dev/acpica/include/accommon.h2
-rw-r--r--sys/contrib/dev/acpica/include/acconfig.h3
-rw-r--r--sys/contrib/dev/acpica/include/acdebug.h35
-rw-r--r--sys/contrib/dev/acpica/include/acdisasm.h4
-rw-r--r--sys/contrib/dev/acpica/include/acdispat.h2
-rw-r--r--sys/contrib/dev/acpica/include/acevents.h31
-rw-r--r--sys/contrib/dev/acpica/include/acexcep.h2
-rw-r--r--sys/contrib/dev/acpica/include/acglobal.h7
-rw-r--r--sys/contrib/dev/acpica/include/achware.h2
-rw-r--r--sys/contrib/dev/acpica/include/acinterp.h4
-rw-r--r--sys/contrib/dev/acpica/include/aclocal.h2
-rw-r--r--sys/contrib/dev/acpica/include/acmacros.h147
-rw-r--r--sys/contrib/dev/acpica/include/acnames.h2
-rw-r--r--sys/contrib/dev/acpica/include/acnamesp.h22
-rw-r--r--sys/contrib/dev/acpica/include/acobject.h2
-rw-r--r--sys/contrib/dev/acpica/include/acopcode.h2
-rw-r--r--sys/contrib/dev/acpica/include/acoutput.h183
-rw-r--r--sys/contrib/dev/acpica/include/acparser.h37
-rw-r--r--sys/contrib/dev/acpica/include/acpi.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpiosxf.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpixf.h10
-rw-r--r--sys/contrib/dev/acpica/include/acpredef.h6
-rw-r--r--sys/contrib/dev/acpica/include/acresrc.h10
-rw-r--r--sys/contrib/dev/acpica/include/acrestyp.h12
-rw-r--r--sys/contrib/dev/acpica/include/acstruct.h2
-rw-r--r--sys/contrib/dev/acpica/include/actables.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbl.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbl1.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbl2.h28
-rw-r--r--sys/contrib/dev/acpica/include/actbl3.h39
-rw-r--r--sys/contrib/dev/acpica/include/actypes.h29
-rw-r--r--sys/contrib/dev/acpica/include/acutils.h111
-rw-r--r--sys/contrib/dev/acpica/include/amlcode.h2
-rw-r--r--sys/contrib/dev/acpica/include/amlresrc.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acenv.h4
-rw-r--r--sys/contrib/dev/acpica/include/platform/acfreebsd.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acgcc.h4
-rw-r--r--sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c140
-rw-r--r--sys/contrib/octeon-sdk/cvmx-helper-board.c15
-rw-r--r--sys/dev/acpi_support/acpi_asus_wmi.c3
-rw-r--r--sys/dev/acpi_support/acpi_fujitsu.c3
-rw-r--r--sys/dev/acpi_support/acpi_hp.c3
-rw-r--r--sys/dev/acpi_support/acpi_ibm.c2
-rw-r--r--sys/dev/acpi_support/acpi_panasonic.c2
-rw-r--r--sys/dev/acpi_support/acpi_sony.c2
-rw-r--r--sys/dev/acpi_support/acpi_toshiba.c4
-rw-r--r--sys/dev/acpica/Osd/OsdSchedule.c8
-rw-r--r--sys/dev/acpica/acpi.c44
-rw-r--r--sys/dev/acpica/acpi_acad.c2
-rw-r--r--sys/dev/acpica/acpi_button.c3
-rw-r--r--sys/dev/acpica/acpi_cmbat.c2
-rw-r--r--sys/dev/acpica/acpi_dock.c2
-rw-r--r--sys/dev/acpica/acpi_ec.c2
-rw-r--r--sys/dev/acpica/acpi_hpet.c2
-rw-r--r--sys/dev/acpica/acpi_lid.c2
-rw-r--r--sys/dev/acpica/acpi_pci.c2
-rw-r--r--sys/dev/acpica/acpi_pci_link.c2
-rw-r--r--sys/dev/acpica/acpi_pcib.c9
-rw-r--r--sys/dev/acpica/acpi_pcib_pci.c2
-rw-r--r--sys/dev/acpica/acpi_perf.c3
-rw-r--r--sys/dev/acpica/acpi_resource.c2
-rw-r--r--sys/dev/acpica/acpi_smbat.c2
-rw-r--r--sys/dev/acpica/acpi_thermal.c11
-rw-r--r--sys/dev/acpica/acpi_throttle.c2
-rw-r--r--sys/dev/acpica/acpi_timer.c2
-rw-r--r--sys/dev/adlink/adlink.c3
-rw-r--r--sys/dev/agp/agp_i810.c2
-rw-r--r--sys/dev/ahci/ahci.c5
-rw-r--r--sys/dev/altera/avgen/altera_avgen.c96
-rw-r--r--sys/dev/altera/avgen/altera_avgen.h6
-rw-r--r--sys/dev/altera/avgen/altera_avgen_fdt.c154
-rw-r--r--sys/dev/altera/avgen/altera_avgen_nexus.c141
-rw-r--r--sys/dev/altera/jtag_uart/altera_jtag_uart.h2
-rw-r--r--sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c3
-rw-r--r--sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c147
-rw-r--r--sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c2
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard.c1
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard.h4
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard_fdt.c120
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard_io.c7
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard_nexus.c2
-rw-r--r--sys/dev/amdsbwd/amdsbwd.c2
-rw-r--r--sys/dev/amdtemp/amdtemp.c2
-rw-r--r--sys/dev/ata/ata-all.h10
-rw-r--r--sys/dev/ata/ata-lowlevel.c49
-rw-r--r--sys/dev/ata/ata-raid.c3
-rw-r--r--sys/dev/ath/ath_hal/ah.h2
-rw-r--r--[-rwxr-xr-x]sys/dev/ath/ath_hal/ar5211/boss.ini0
-rw-r--r--sys/dev/ath/if_ath.c588
-rw-r--r--sys/dev/ath/if_ath_beacon.c10
-rw-r--r--sys/dev/ath/if_ath_misc.h5
-rw-r--r--sys/dev/ath/if_ath_rx.c16
-rw-r--r--sys/dev/ath/if_ath_sysctl.c31
-rw-r--r--sys/dev/ath/if_ath_tx.c50
-rw-r--r--sys/dev/ath/if_ath_tx_edma.c2
-rw-r--r--sys/dev/ath/if_athvar.h13
-rw-r--r--sys/dev/atkbdc/atkbd.c174
-rw-r--r--sys/dev/atkbdc/atkbd_atkbdc.c8
-rw-r--r--sys/dev/atkbdc/atkbdreg.h5
-rw-r--r--sys/dev/auxio/auxio.c6
-rw-r--r--sys/dev/bge/if_bge.c161
-rw-r--r--[-rwxr-xr-x]sys/dev/bktr/CHANGELOG.TXT0
-rw-r--r--sys/dev/bvm/bvm_console.c240
-rw-r--r--sys/dev/bvm/bvm_dbg.c100
-rw-r--r--sys/dev/cas/if_cas.c17
-rw-r--r--sys/dev/ce/if_ce.c2
-rw-r--r--sys/dev/cfi/cfi_bus_fdt.c2
-rw-r--r--sys/dev/cfi/cfi_bus_ixp4xx.c2
-rw-r--r--sys/dev/ciss/ciss.c46
-rw-r--r--sys/dev/ciss/cissreg.h9
-rw-r--r--sys/dev/ciss/cissvar.h5
-rw-r--r--sys/dev/coretemp/coretemp.c2
-rw-r--r--sys/dev/cp/if_cp.c2
-rw-r--r--sys/dev/cpufreq/ichss.c2
-rw-r--r--sys/dev/ctau/if_ct.c3
-rw-r--r--sys/dev/cx/if_cx.c3
-rw-r--r--sys/dev/cxgbe/adapter.h60
-rw-r--r--sys/dev/cxgbe/common/jhash.h140
-rw-r--r--sys/dev/cxgbe/common/t4_msg.h2
-rw-r--r--sys/dev/cxgbe/firmware/t4fw_cfg.txt8
-rw-r--r--sys/dev/cxgbe/offload.h58
-rw-r--r--sys/dev/cxgbe/t4_l2t.c44
-rw-r--r--sys/dev/cxgbe/t4_l2t.h6
-rw-r--r--sys/dev/cxgbe/t4_main.c664
-rw-r--r--sys/dev/cxgbe/t4_sge.c2
-rw-r--r--sys/dev/cxgbe/tom/t4_connect.c127
-rw-r--r--sys/dev/cxgbe/tom/t4_cpl_io.c3
-rw-r--r--sys/dev/cxgbe/tom/t4_listen.c409
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.c240
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.h24
-rw-r--r--sys/dev/cxgbe/tom/t4_tom_l2t.c124
-rw-r--r--sys/dev/digi/digi_isa.c3
-rw-r--r--sys/dev/digi/digi_pci.c3
-rw-r--r--sys/dev/e1000/if_em.c2
-rw-r--r--sys/dev/e1000/if_igb.c6
-rw-r--r--sys/dev/e1000/if_lem.c2
-rw-r--r--sys/dev/ep/if_ep_eisa.c2
-rw-r--r--sys/dev/ep/if_ep_isa.c2
-rw-r--r--sys/dev/ep/if_ep_mca.c2
-rw-r--r--sys/dev/ep/if_ep_pccard.c2
-rw-r--r--sys/dev/fdc/fdc_acpi.c2
-rw-r--r--sys/dev/fdt/fdt_mips.c22
-rw-r--r--sys/dev/hpt27xx/hpt27xx_config.c6
-rw-r--r--sys/dev/hpt27xx/os_bsd.h6
-rw-r--r--sys/dev/hpt27xx/osm_bsd.c7
-rw-r--r--sys/dev/hwpmc/hwpmc_core.c409
-rw-r--r--sys/dev/hwpmc/hwpmc_intel.c6
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c2
-rw-r--r--sys/dev/hwpmc/hwpmc_soft.c2
-rw-r--r--sys/dev/hwpmc/pmc_events.h204
-rw-r--r--sys/dev/iicbus/ad7418.c2
-rw-r--r--sys/dev/iicbus/ds133x.c2
-rw-r--r--sys/dev/iicbus/ds1672.c2
-rw-r--r--sys/dev/iicbus/icee.c2
-rw-r--r--sys/dev/isf/isf.c1
-rw-r--r--sys/dev/isf/isf.h2
-rw-r--r--sys/dev/isf/isf_fdt.c124
-rw-r--r--sys/dev/isf/isf_nexus.c2
-rw-r--r--sys/dev/ixgb/if_ixgb.c3
-rw-r--r--sys/dev/ixgbe/ixgbe.c3
-rw-r--r--[-rwxr-xr-x]sys/dev/ixgbe/ixgbe_82598.h0
-rw-r--r--[-rwxr-xr-x]sys/dev/ixgbe/ixgbe_82599.h0
-rw-r--r--[-rwxr-xr-x]sys/dev/ixgbe/ixgbe_x540.c0
-rw-r--r--[-rwxr-xr-x]sys/dev/ixgbe/ixgbe_x540.h0
-rw-r--r--sys/dev/ixgbe/ixv.c3
-rw-r--r--sys/dev/mfi/mfi_cam.c3
-rw-r--r--sys/dev/mmc/mmc.c3
-rw-r--r--sys/dev/mmc/mmcreg.h2
-rw-r--r--sys/dev/mn/if_mn.c2
-rw-r--r--sys/dev/mxge/if_mxge.c3
-rw-r--r--sys/dev/my/if_my.c2
-rw-r--r--sys/dev/nand/nand_id.c2
-rw-r--r--sys/dev/netmap/if_em_netmap.h3
-rw-r--r--sys/dev/netmap/if_igb_netmap.h3
-rw-r--r--sys/dev/netmap/if_lem_netmap.h3
-rw-r--r--sys/dev/netmap/if_re_netmap.h3
-rw-r--r--sys/dev/netmap/ixgbe_netmap.h13
-rw-r--r--sys/dev/netmap/netmap.c338
-rw-r--r--sys/dev/netmap/netmap_kern.h8
-rw-r--r--sys/dev/netmap/netmap_mem1.c521
-rw-r--r--sys/dev/netmap/netmap_mem2.c45
-rw-r--r--sys/dev/nvram2env/nvram2env.c3
-rw-r--r--sys/dev/nxge/if_nxge.c3
-rw-r--r--sys/dev/oce/oce_if.c3
-rw-r--r--sys/dev/puc/puc.c2
-rw-r--r--sys/dev/sdhci/sdhci_pci.c2
-rw-r--r--sys/dev/sound/pci/emu10kx-midi.c2
-rw-r--r--sys/dev/sound/pci/emu10kx-pcm.c3
-rw-r--r--sys/dev/sound/pci/emu10kx.c2
-rw-r--r--sys/dev/sound/sbus/cs4231.c6
-rw-r--r--sys/dev/sound/usb/uaudio_pcm.c2
-rw-r--r--sys/dev/sym/sym_hipd.c4
-rw-r--r--sys/dev/terasic/de4led/terasic_de4led.c2
-rw-r--r--sys/dev/terasic/de4led/terasic_de4led.h2
-rw-r--r--sys/dev/terasic/de4led/terasic_de4led_fdt.c118
-rw-r--r--sys/dev/terasic/de4led/terasic_de4led_nexus.c2
-rw-r--r--sys/dev/terasic/mtl/terasic_mtl.c3
-rw-r--r--sys/dev/terasic/mtl/terasic_mtl.h2
-rw-r--r--sys/dev/terasic/mtl/terasic_mtl_fdt.c200
-rw-r--r--sys/dev/terasic/mtl/terasic_mtl_nexus.c2
-rw-r--r--sys/dev/uart/uart_bus.h1
-rw-r--r--sys/dev/uart/uart_bus_acpi.c1
-rw-r--r--sys/dev/uart/uart_bus_isa.c1
-rw-r--r--sys/dev/uart/uart_bus_pci.c1
-rw-r--r--sys/dev/uart/uart_core.c9
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c14
-rw-r--r--sys/dev/usb/controller/at91dci.c23
-rw-r--r--sys/dev/usb/controller/atmegadci.c23
-rw-r--r--sys/dev/usb/controller/avr32dci.c24
-rw-r--r--sys/dev/usb/controller/dwc_otg.c22
-rw-r--r--sys/dev/usb/controller/ehci.c9
-rw-r--r--sys/dev/usb/controller/musb_otg.c20
-rw-r--r--sys/dev/usb/controller/ohci.c9
-rw-r--r--sys/dev/usb/controller/uhci.c9
-rw-r--r--sys/dev/usb/controller/usb_controller.c22
-rw-r--r--sys/dev/usb/controller/uss820dci.c19
-rw-r--r--sys/dev/usb/controller/xhci.c15
-rw-r--r--sys/dev/usb/input/uhid.c3
-rw-r--r--sys/dev/usb/input/ukbd.c39
-rw-r--r--sys/dev/usb/input/ums.c50
-rw-r--r--sys/dev/usb/misc/udbp.c3
-rw-r--r--sys/dev/usb/misc/ufm.c3
-rw-r--r--sys/dev/usb/net/if_axe.c1
-rw-r--r--sys/dev/usb/net/if_cdce.c6
-rw-r--r--sys/dev/usb/net/if_cue.c2
-rw-r--r--sys/dev/usb/net/if_ipheth.c2
-rw-r--r--sys/dev/usb/net/if_kue.c2
-rw-r--r--sys/dev/usb/net/if_smsc.c10
-rw-r--r--sys/dev/usb/quirk/usb_quirk.c7
-rw-r--r--sys/dev/usb/serial/u3g.c1
-rw-r--r--sys/dev/usb/storage/umass.c46
-rw-r--r--sys/dev/usb/storage/urio.c3
-rw-r--r--sys/dev/usb/storage/ustorage_fs.c6
-rw-r--r--sys/dev/usb/template/usb_template.c4
-rw-r--r--sys/dev/usb/template/usb_template_audio.c30
-rw-r--r--sys/dev/usb/template/usb_template_cdce.c61
-rw-r--r--sys/dev/usb/template/usb_template_kbd.c24
-rw-r--r--sys/dev/usb/template/usb_template_modem.c24
-rw-r--r--sys/dev/usb/template/usb_template_mouse.c24
-rw-r--r--sys/dev/usb/template/usb_template_msc.c46
-rw-r--r--sys/dev/usb/template/usb_template_mtp.c42
-rw-r--r--sys/dev/usb/ufm_ioctl.h6
-rw-r--r--sys/dev/usb/usb.h20
-rw-r--r--sys/dev/usb/usb_busdma.c9
-rw-r--r--sys/dev/usb/usb_busdma.h2
-rw-r--r--sys/dev/usb/usb_compat_linux.c6
-rw-r--r--sys/dev/usb/usb_core.c9
-rw-r--r--sys/dev/usb/usb_core.h2
-rw-r--r--sys/dev/usb/usb_debug.c4
-rw-r--r--sys/dev/usb/usb_dev.c4
-rw-r--r--sys/dev/usb/usb_dev.h2
-rw-r--r--sys/dev/usb/usb_device.c4
-rw-r--r--sys/dev/usb/usb_dynamic.c4
-rw-r--r--sys/dev/usb/usb_endian.h2
-rw-r--r--sys/dev/usb/usb_error.c4
-rw-r--r--sys/dev/usb/usb_freebsd.h2
-rw-r--r--sys/dev/usb/usb_freebsd_loader.h84
-rw-r--r--sys/dev/usb/usb_generic.c4
-rw-r--r--sys/dev/usb/usb_handle_request.c4
-rw-r--r--sys/dev/usb/usb_hid.c85
-rw-r--r--sys/dev/usb/usb_hub.c4
-rw-r--r--sys/dev/usb/usb_ioctl.h2
-rw-r--r--sys/dev/usb/usb_lookup.c6
-rw-r--r--sys/dev/usb/usb_mbuf.c4
-rw-r--r--sys/dev/usb/usb_msctest.c4
-rw-r--r--sys/dev/usb/usb_parse.c5
-rw-r--r--sys/dev/usb/usb_pci.h2
-rw-r--r--sys/dev/usb/usb_pf.c7
-rw-r--r--sys/dev/usb/usb_process.c4
-rw-r--r--sys/dev/usb/usb_process.h2
-rw-r--r--sys/dev/usb/usb_request.c4
-rw-r--r--sys/dev/usb/usb_transfer.c4
-rw-r--r--sys/dev/usb/usb_util.c4
-rw-r--r--sys/dev/usb/usbdevs5
-rw-r--r--sys/dev/usb/usbdi.h11
-rw-r--r--sys/dev/usb/usbhid.h4
-rw-r--r--sys/dev/vx/if_vx_eisa.c2
-rw-r--r--sys/dev/vx/if_vx_pci.c2
-rw-r--r--sys/dev/vxge/vxge.c3
-rw-r--r--sys/dev/wbwd/wbwd.c19
-rw-r--r--sys/dev/xen/console/console.c3
-rw-r--r--sys/fs/ext2fs/ext2_alloc.c15
-rw-r--r--sys/fs/ext2fs/ext2_balloc.c2
-rw-r--r--[-rwxr-xr-x]sys/fs/ext2fs/ext2_dinode.h0
-rw-r--r--[-rwxr-xr-x]sys/fs/ext2fs/ext2_dir.h4
-rw-r--r--sys/fs/ext2fs/ext2_inode.c23
-rw-r--r--sys/fs/ext2fs/ext2_lookup.c2
-rw-r--r--sys/fs/ext2fs/ext2_vfsops.c13
-rw-r--r--[-rwxr-xr-x]sys/fs/ext2fs/ext2fs.h45
-rw-r--r--sys/fs/ext2fs/fs.h3
-rw-r--r--sys/fs/ext2fs/inode.h10
-rw-r--r--sys/fs/msdosfs/msdosfs_fat.c19
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c3
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c18
-rw-r--r--sys/fs/nfs/nfs.h1
-rw-r--r--sys/fs/nfs/nfs_commonkrpc.c20
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c8
-rw-r--r--sys/fs/nfs/nfsport.h6
-rw-r--r--sys/fs/nfsclient/nfs_clport.c6
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c2
-rw-r--r--sys/fs/nfsclient/nfs_clstate.c10
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c6
-rw-r--r--sys/fs/nfsserver/nfs_nfsdkrpc.c1
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c20
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c13
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c18
-rw-r--r--sys/fs/nullfs/null_subr.c16
-rw-r--r--sys/fs/nullfs/null_vfsops.c11
-rw-r--r--sys/fs/nullfs/null_vnops.c8
-rw-r--r--sys/geom/journal/g_journal.c2
-rw-r--r--sys/geom/mirror/g_mirror.c25
-rw-r--r--sys/geom/raid/g_raid.c6
-rw-r--r--sys/geom/raid/g_raid.h11
-rw-r--r--sys/geom/raid/md_intel.c271
-rw-r--r--sys/geom/raid/md_promise.c149
-rw-r--r--sys/geom/raid/tr_concat.c3
-rw-r--r--sys/geom/raid3/g_raid3.c21
-rw-r--r--sys/geom/raid3/g_raid3_ctl.c45
-rw-r--r--sys/i386/conf/GENERIC9
-rw-r--r--sys/i386/conf/NOTES9
-rw-r--r--sys/i386/i386/mp_machdep.c4
-rw-r--r--sys/i386/i386/pmap.c16
-rw-r--r--sys/i386/include/intr_machdep.h2
-rw-r--r--sys/i386/include/vmparam.h5
-rw-r--r--sys/i386/linux/linux.h153
-rw-r--r--sys/i386/linux/linux_ptrace.c1
-rw-r--r--sys/i386/linux/linux_sysvec.c1
-rw-r--r--sys/kern/init_main.c1
-rw-r--r--sys/kern/kern_clock.c4
-rw-r--r--sys/kern/kern_clocksource.c18
-rw-r--r--sys/kern/kern_descrip.c7
-rw-r--r--sys/kern/kern_exit.c14
-rw-r--r--sys/kern/kern_ktr.c30
-rw-r--r--sys/kern/kern_mbuf.c27
-rw-r--r--sys/kern/kern_mib.c3
-rw-r--r--sys/kern/kern_tc.c4
-rw-r--r--sys/kern/subr_bus.c2
-rw-r--r--sys/kern/subr_param.c21
-rw-r--r--sys/kern/uipc_mbuf.c73
-rw-r--r--sys/kern/vfs_hash.c19
-rw-r--r--sys/kern/vfs_subr.c14
-rw-r--r--sys/kern/vfs_syscalls.c103
-rw-r--r--sys/kern/vfs_vnops.c15
-rw-r--r--sys/libkern/arm/divsi3.S8
-rw-r--r--sys/libkern/arm/ldivmod.S67
-rw-r--r--sys/libkern/arm/ldivmod_helper.c53
-rw-r--r--sys/libkern/quad.h5
-rw-r--r--sys/libkern/ucmpdi2.c12
-rw-r--r--sys/mips/beri/beri_machdep.c44
-rw-r--r--sys/mips/beri/files.beri3
-rw-r--r--sys/mips/include/bus.h2
-rw-r--r--sys/mips/include/fdt.h2
-rw-r--r--sys/mips/include/metadata.h1
-rw-r--r--sys/mips/include/vmparam.h5
-rw-r--r--sys/mips/mips/bus_space_fdt.c212
-rw-r--r--sys/mips/nlm/dev/net/mdio.c23
-rw-r--r--sys/mips/nlm/dev/net/nae.c26
-rw-r--r--sys/mips/nlm/dev/net/sgmii.c7
-rw-r--r--sys/mips/nlm/dev/net/xlpge.c32
-rw-r--r--sys/mips/nlm/hal/fmn.c4
-rw-r--r--sys/mips/nlm/hal/mdio.h1
-rw-r--r--sys/mips/nlm/hal/sys.h13
-rw-r--r--sys/mips/nlm/hal/ucore_loader.h2
-rw-r--r--sys/mips/nlm/xlp_machdep.c21
-rw-r--r--sys/mips/nlm/xlp_pci.c7
-rw-r--r--[-rwxr-xr-x]sys/mips/rmi/msgring_xls.cfg0
-rw-r--r--sys/modules/Makefile2
-rw-r--r--sys/modules/cxgbe/tom/Makefile11
-rw-r--r--[-rwxr-xr-x]sys/modules/digi/Makefile0
-rw-r--r--[-rwxr-xr-x]sys/modules/digi/Makefile.inc0
-rw-r--r--sys/modules/hpt27xx/Makefile3
-rw-r--r--[-rwxr-xr-x]sys/modules/isci/Makefile0
-rw-r--r--[-rwxr-xr-x]sys/modules/sound/driver/ich/Makefile0
-rw-r--r--sys/modules/usb/Makefile2
-rw-r--r--sys/modules/usb/smsc/Makefile2
-rw-r--r--sys/modules/vmm/Makefile62
-rw-r--r--sys/modules/wlan/Makefile2
-rw-r--r--sys/net/bpf.c23
-rw-r--r--sys/net/if_lagg.c4
-rw-r--r--sys/net/if_llatbl.c40
-rw-r--r--sys/net/if_llatbl.h11
-rw-r--r--sys/net/netmap.h49
-rw-r--r--sys/net80211/ieee80211_adhoc.c18
-rw-r--r--sys/net80211/ieee80211_node.c62
-rw-r--r--sys/net80211/ieee80211_power.c40
-rw-r--r--sys/net80211/ieee80211_scan_sta.c24
-rw-r--r--sys/net80211/ieee80211_superg.c4
-rw-r--r--sys/netgraph/ng_ether.c60
-rw-r--r--sys/netinet/if_ether.h14
-rw-r--r--sys/netinet/in.c10
-rw-r--r--sys/netinet/in_pcb.c3
-rw-r--r--sys/netinet/libalias/alias.c16
-rw-r--r--sys/netinet/libalias/libalias.368
-rw-r--r--sys/netinet/tcp.h29
-rw-r--r--sys/netinet/tcp_input.c2
-rw-r--r--sys/netinet/tcp_reass.c8
-rw-r--r--sys/netinet/tcp_syncache.c13
-rw-r--r--sys/netinet/tcp_timer.c8
-rw-r--r--sys/netinet/tcp_usrreq.c10
-rw-r--r--sys/netinet/toecore.c81
-rw-r--r--sys/netinet/udp.h4
-rw-r--r--sys/netinet6/in6_src.c10
-rw-r--r--sys/netinet6/nd6.c6
-rw-r--r--sys/netinet6/nd6.h1
-rw-r--r--sys/netinet6/nd6_nbr.c3
-rw-r--r--sys/netinet6/scope6.c70
-rw-r--r--sys/nfs/nfs_common.c9
-rw-r--r--sys/nfs/nfs_common.h1
-rw-r--r--sys/nfsclient/nfs_krpc.c29
-rw-r--r--sys/nfsclient/nfs_subs.c4
-rw-r--r--sys/nfsclient/nfs_vnops.c6
-rw-r--r--sys/nfsserver/nfs_srvsubs.c4
-rw-r--r--sys/pc98/cbus/pckbd.c16
-rw-r--r--sys/pc98/conf/GENERIC1
-rw-r--r--sys/pci/if_rl.c2
-rw-r--r--sys/pci/if_rlreg.h5
-rw-r--r--sys/pci/ncr.c2
-rw-r--r--sys/security/audit/audit.c13
-rw-r--r--sys/security/audit/audit_bsm.c13
-rw-r--r--sys/security/audit/audit_private.h1
-rw-r--r--sys/sparc64/conf/GENERIC1
-rw-r--r--sys/sparc64/include/smp.h20
-rw-r--r--sys/sparc64/sparc64/tick.c4
-rw-r--r--sys/sys/bufobj.h10
-rw-r--r--sys/sys/kernel.h2
-rw-r--r--sys/sys/mbuf.h123
-rw-r--r--sys/sys/mount.h5
-rw-r--r--sys/sys/param.h10
-rw-r--r--sys/sys/pmc.h1
-rw-r--r--sys/sys/socket.h9
-rw-r--r--sys/sys/systm.h1
-rw-r--r--sys/sys/time.h4
-rw-r--r--sys/sys/un.h9
-rw-r--r--sys/sys/vdso.h6
-rw-r--r--sys/sys/vmmeter.h1
-rw-r--r--sys/sys/vnode.h38
-rw-r--r--sys/ufs/ffs/ffs_inode.c6
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c2
-rw-r--r--sys/ufs/ffs/ffs_softdep.c2
-rw-r--r--sys/ufs/ffs/ffs_suspend.c2
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c18
-rw-r--r--sys/vm/device_pager.c3
-rw-r--r--sys/vm/uma_core.c2
-rw-r--r--sys/vm/vm_fault.c5
-rw-r--r--sys/vm/vm_map.c16
-rw-r--r--sys/vm/vm_map.h1
-rw-r--r--sys/vm/vm_meter.c1
-rw-r--r--sys/vm/vm_mmap.c17
-rw-r--r--sys/vm/vm_object.h1
-rw-r--r--sys/vm/vm_pageout.c45
-rw-r--r--sys/vm/vm_unix.c44
-rw-r--r--sys/x86/x86/intr_machdep.c12
-rw-r--r--sys/x86/x86/local_apic.c13
-rw-r--r--sys/x86/x86/tsc.c72
-rw-r--r--tools/build/Makefile16
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc89
-rw-r--r--tools/build/options/WITHOUT_CLANG_FULL3
-rw-r--r--tools/build/options/WITHOUT_LIBCPLUSPLUS2
-rw-r--r--tools/build/options/WITHOUT_PC_SYSINSTALL4
-rw-r--r--tools/build/options/WITH_ARM_EABI2
-rw-r--r--tools/build/options/WITH_BSD_PATCH2
-rw-r--r--tools/build/options/WITH_CLANG_FULL3
-rw-r--r--tools/build/options/WITH_GPL_DTC3
-rw-r--r--tools/build/options/WITH_NMTREE9
-rw-r--r--tools/build/options/WITH_OPENSSH_NONE_CIPHER9
-rw-r--r--tools/install.sh24
-rw-r--r--tools/regression/bin/sh/execution/subshell1.06
-rw-r--r--tools/regression/bin/sh/execution/subshell1.0.stdout2
-rw-r--r--tools/regression/bin/sh/execution/subshell2.010
-rw-r--r--tools/regression/bin/sh/execution/subshell3.04
-rw-r--r--tools/regression/bin/sh/execution/subshell4.03
-rw-r--r--tools/regression/bin/sh/expansion/cmdsubst14.05
-rw-r--r--tools/regression/bin/sh/expansion/cmdsubst15.05
-rw-r--r--tools/regression/bin/sh/expansion/cmdsubst16.05
-rw-r--r--tools/regression/bin/sh/expansion/cmdsubst17.05
-rw-r--r--tools/regression/bin/sh/parser/empty-braces1.07
-rw-r--r--tools/regression/lib/libc/stdio/test-fmemopen.c252
-rw-r--r--tools/regression/lib/libc/stdio/test-fmemopen.t10
-rw-r--r--tools/test/pthread_vfork/pthread_vfork_test.c32
-rw-r--r--tools/tools/ath/athalq/ar5212_ds.c12
-rw-r--r--tools/tools/ath/athalq/ar5416_ds.c12
-rw-r--r--tools/tools/ath/athspectral/athspectral.c30
-rw-r--r--tools/tools/cxgbetool/cxgbetool.c13
-rw-r--r--tools/tools/notescheck/notescheck.py46
-rw-r--r--usr.bin/Makefile1
-rw-r--r--usr.bin/bmake/Makefile216
-rw-r--r--usr.bin/bmake/config.h6
-rw-r--r--usr.bin/bmake/unit-tests/Makefile2
-rw-r--r--usr.bin/calendar/calendars/calendar.freebsd1
-rw-r--r--usr.bin/clang/clang/Makefile22
-rw-r--r--usr.bin/dtc/HACKING65
-rw-r--r--usr.bin/dtc/Makefile11
-rw-r--r--usr.bin/dtc/checking.cc211
-rw-r--r--usr.bin/dtc/checking.hh308
-rw-r--r--usr.bin/dtc/dtb.cc312
-rw-r--r--usr.bin/dtc/dtb.hh365
-rw-r--r--usr.bin/dtc/dtc.1309
-rw-r--r--usr.bin/dtc/dtc.cc337
-rw-r--r--usr.bin/dtc/fdt.cc1361
-rw-r--r--usr.bin/dtc/fdt.hh782
-rw-r--r--usr.bin/dtc/input_buffer.cc263
-rw-r--r--usr.bin/dtc/input_buffer.hh289
-rw-r--r--usr.bin/dtc/string.cc258
-rw-r--r--usr.bin/dtc/string.hh147
-rw-r--r--usr.bin/dtc/util.hh92
-rw-r--r--usr.bin/ee/Makefile2
-rw-r--r--usr.bin/grep/grep.c4
-rw-r--r--usr.bin/man/man.12
-rwxr-xr-xusr.bin/man/man.sh2
-rw-r--r--usr.bin/netstat/inet.c2
-rw-r--r--usr.bin/patch/Makefile18
-rw-r--r--usr.bin/patch/backupfile.c246
-rw-r--r--usr.bin/patch/backupfile.h39
-rw-r--r--usr.bin/patch/common.h119
-rw-r--r--usr.bin/patch/inp.c484
-rw-r--r--usr.bin/patch/inp.h32
-rw-r--r--usr.bin/patch/mkpath.c78
-rw-r--r--usr.bin/patch/patch.1700
-rw-r--r--usr.bin/patch/patch.c1069
-rw-r--r--usr.bin/patch/pathnames.h12
-rw-r--r--usr.bin/patch/pch.c1593
-rw-r--r--usr.bin/patch/pch.h56
-rw-r--r--usr.bin/patch/util.c432
-rw-r--r--usr.bin/patch/util.h51
-rw-r--r--usr.bin/procstat/procstat.c4
-rw-r--r--usr.bin/sort/sort.c35
-rw-r--r--usr.bin/stdbuf/stdbuf.c8
-rw-r--r--usr.bin/systat/vmstat.c76
-rw-r--r--usr.bin/tr/tr.c3
-rw-r--r--usr.bin/truss/main.c11
-rw-r--r--usr.bin/vmstat/vmstat.c3
-rw-r--r--usr.bin/w/w.c6
-rw-r--r--usr.bin/xinstall/Makefile8
-rw-r--r--usr.bin/xinstall/install.1136
-rw-r--r--usr.bin/xinstall/xinstall.c732
-rw-r--r--usr.sbin/Makefile7
-rw-r--r--usr.sbin/Makefile.amd643
-rw-r--r--usr.sbin/acpi/acpidb/Makefile27
-rw-r--r--usr.sbin/acpi/iasl/Makefile32
-rw-r--r--usr.sbin/arp/arp.818
-rw-r--r--usr.sbin/arp/arp.c75
-rw-r--r--usr.sbin/bhyve/Makefile27
-rw-r--r--usr.sbin/bhyve/acpi.c844
-rw-r--r--usr.sbin/bhyve/acpi.h34
-rw-r--r--usr.sbin/bhyve/atpic.c68
-rw-r--r--usr.sbin/bhyve/bhyverun.c789
-rw-r--r--usr.sbin/bhyve/bhyverun.h53
-rw-r--r--usr.sbin/bhyve/consport.c140
-rw-r--r--usr.sbin/bhyve/dbgport.c138
-rw-r--r--usr.sbin/bhyve/dbgport.h36
-rw-r--r--usr.sbin/bhyve/elcr.c65
-rw-r--r--usr.sbin/bhyve/inout.c151
-rw-r--r--usr.sbin/bhyve/inout.h67
-rw-r--r--usr.sbin/bhyve/ioapic.c324
-rw-r--r--usr.sbin/bhyve/ioapic.h38
-rw-r--r--usr.sbin/bhyve/mem.c218
-rw-r--r--usr.sbin/bhyve/mem.h57
-rw-r--r--usr.sbin/bhyve/mevent.c432
-rw-r--r--usr.sbin/bhyve/mevent.h49
-rw-r--r--usr.sbin/bhyve/mevent_test.c180
-rw-r--r--usr.sbin/bhyve/mptbl.c398
-rw-r--r--usr.sbin/bhyve/mptbl.h35
-rw-r--r--usr.sbin/bhyve/pci_emul.c1339
-rw-r--r--usr.sbin/bhyve/pci_emul.h224
-rw-r--r--usr.sbin/bhyve/pci_hostbridge.c52
-rw-r--r--usr.sbin/bhyve/pci_passthru.c759
-rw-r--r--usr.sbin/bhyve/pci_uart.c626
-rw-r--r--usr.sbin/bhyve/pci_virtio_block.c624
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c886
-rw-r--r--usr.sbin/bhyve/pit_8254.c198
-rw-r--r--usr.sbin/bhyve/pit_8254.h45
-rw-r--r--usr.sbin/bhyve/pmtmr.c105
-rw-r--r--usr.sbin/bhyve/post.c51
-rw-r--r--usr.sbin/bhyve/rtc.c284
-rw-r--r--usr.sbin/bhyve/spinup_ap.c119
-rw-r--r--usr.sbin/bhyve/spinup_ap.h34
-rw-r--r--usr.sbin/bhyve/uart.c60
-rw-r--r--usr.sbin/bhyve/virtio.h88
-rw-r--r--usr.sbin/bhyve/xmsr.c48
-rw-r--r--usr.sbin/bhyve/xmsr.h34
-rw-r--r--usr.sbin/bhyvectl/Makefile17
-rw-r--r--usr.sbin/bhyvectl/bhyvectl.c1524
-rw-r--r--usr.sbin/bhyveload/Makefile14
-rw-r--r--usr.sbin/bhyveload/bhyveload.8127
-rw-r--r--usr.sbin/bhyveload/bhyveload.c652
-rwxr-xr-xusr.sbin/bsdconfig/bsdconfig1
-rwxr-xr-xusr.sbin/bsdconfig/console/ttys2
-rw-r--r--usr.sbin/bsdconfig/networking/share/device.subr6
-rw-r--r--usr.sbin/bsdconfig/networking/share/hostname.subr6
-rw-r--r--usr.sbin/bsdconfig/networking/share/routing.subr7
-rwxr-xr-xusr.sbin/bsdconfig/password/password2
-rw-r--r--usr.sbin/bsdconfig/password/share/password.subr4
-rwxr-xr-xusr.sbin/bsdconfig/security/kern_securelevel1
-rw-r--r--usr.sbin/bsdconfig/share/common.subr44
-rw-r--r--usr.sbin/bsdconfig/share/mustberoot.subr2
-rw-r--r--usr.sbin/bsdconfig/share/script.subr19
-rw-r--r--usr.sbin/bsdconfig/share/variable.subr4
-rwxr-xr-xusr.sbin/bsdconfig/startup/misc22
-rwxr-xr-xusr.sbin/bsdconfig/startup/rcdelete6
-rwxr-xr-xusr.sbin/bsdconfig/startup/rcvar2
-rw-r--r--usr.sbin/bsdconfig/startup/share/rcconf.subr4
-rw-r--r--usr.sbin/bsdconfig/startup/share/rcedit.subr3
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/groupinput12
-rw-r--r--usr.sbin/bsdconfig/usermgmt/share/group_input.subr6
-rw-r--r--usr.sbin/bsdconfig/usermgmt/share/user_input.subr16
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/userinput32
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/usermgmt1
-rw-r--r--usr.sbin/bsdinstall/bsdinstall.8149
-rw-r--r--usr.sbin/bsdinstall/partedit/Makefile5
-rw-r--r--usr.sbin/bsdinstall/partedit/diskeditor.c2
-rw-r--r--usr.sbin/bsdinstall/partedit/part_wizard.c15
-rw-r--r--usr.sbin/bsdinstall/partedit/partedit.c18
-rw-r--r--usr.sbin/bsdinstall/partedit/partedit.h2
-rw-r--r--usr.sbin/bsdinstall/partedit/sade.82
-rw-r--r--usr.sbin/bsdinstall/partedit/scripted.c213
-rw-r--r--usr.sbin/bsdinstall/scripts/Makefile2
-rwxr-xr-xusr.sbin/bsdinstall/scripts/script90
-rwxr-xr-xusr.sbin/bsdinstall/scripts/services2
-rwxr-xr-xusr.sbin/bsdinstall/scripts/wlanconfig2
-rw-r--r--[-rwxr-xr-x]usr.sbin/bsnmpd/modules/snmp_target/Makefile0
-rw-r--r--[-rwxr-xr-x]usr.sbin/bsnmpd/modules/snmp_usm/Makefile0
-rw-r--r--[-rwxr-xr-x]usr.sbin/bsnmpd/modules/snmp_vacm/Makefile0
-rw-r--r--[-rwxr-xr-x]usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c0
-rw-r--r--usr.sbin/cpucontrol/intel.c3
-rw-r--r--usr.sbin/cpucontrol/via.c3
-rw-r--r--usr.sbin/crunch/crunchgen/crunchgen.c33
-rw-r--r--usr.sbin/crunch/crunchide/exec_elf32.c16
-rw-r--r--usr.sbin/crunch/examples/really-big.conf2
-rw-r--r--usr.sbin/inetd/inetd.c2
-rw-r--r--usr.sbin/mtree/Makefile16
-rw-r--r--usr.sbin/ndp/ndp.811
-rw-r--r--usr.sbin/ndp/ndp.c13
-rw-r--r--usr.sbin/newsyslog/newsyslog.c27
-rw-r--r--usr.sbin/nmtree/Makefile7
-rw-r--r--usr.sbin/pciconf/cap.c26
-rw-r--r--usr.sbin/pkg/dns_utils.c3
-rw-r--r--usr.sbin/pkg_install/lib/lib.h2
-rw-r--r--usr.sbin/pkg_install/lib/pkgng.c11
-rw-r--r--usr.sbin/ppp/arp.c5
-rw-r--r--usr.sbin/pw/pw_log.c2
-rw-r--r--usr.sbin/pw/pw_user.c2
-rw-r--r--usr.sbin/rarpd/rarpd.c9
-rw-r--r--usr.sbin/tcpdrop/tcpdrop.85
-rw-r--r--usr.sbin/tcpdrop/tcpdrop.c38
-rw-r--r--usr.sbin/timed/timed/acksend.c19
-rw-r--r--usr.sbin/timed/timed/byteorder.c6
-rw-r--r--usr.sbin/timed/timed/candidate.c3
-rw-r--r--usr.sbin/timed/timed/cksum.c4
-rw-r--r--usr.sbin/timed/timed/correct.c10
-rw-r--r--usr.sbin/timed/timed/master.c41
-rw-r--r--usr.sbin/timed/timed/measure.c20
-rw-r--r--usr.sbin/timed/timed/networkdelta.c2
-rw-r--r--usr.sbin/timed/timed/readmsg.c16
-rw-r--r--usr.sbin/timed/timed/slave.c11
-rw-r--r--usr.sbin/timed/timed/timed.c46
-rw-r--r--usr.sbin/timed/timedc/cmds.c24
-rw-r--r--usr.sbin/timed/timedc/timedc.c16
-rw-r--r--usr.sbin/watchdogd/watchdogd.c10
1545 files changed, 78695 insertions, 15528 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index e486331..34369a8 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -4,6 +4,8 @@
# Make command line options:
# -DNO_CLEANDIR run ${MAKE} clean, instead of ${MAKE} cleandir
# -DNO_CLEAN do not clean at all
+# -DDB_FROM_SRC use the user/group databases in src/etc instead of
+# the system database when installing.
# -DNO_SHARE do not go into share subdir
# -DKERNFAST define NO_KERNEL{CONFIG,CLEAN,DEPEND,OBJ}
# -DNO_KERNELCONFIG do not run config in ${MAKE} buildkernel
@@ -11,8 +13,8 @@
# -DNO_KERNELDEPEND do not run ${MAKE} depend in ${MAKE} buildkernel
# -DNO_KERNELOBJ do not run ${MAKE} obj in ${MAKE} buildkernel
# -DNO_PORTSUPDATE do not update ports in ${MAKE} update
+# -DNO_ROOT install without using root privilege
# -DNO_DOCUPDATE do not update doc in ${MAKE} update
-# -DNO_WWWUPDATE do not update www in ${MAKE} update
# -DNO_CTF do not run the DTrace CTF conversion tools on built objects
# LOCAL_DIRS="list of dirs" to add additional dirs to the SUBDIR list
# LOCAL_LIB_DIRS="list of dirs" to add additional dirs to libraries target
@@ -20,9 +22,13 @@
# to be created before files are installed
# LOCAL_TOOL_DIRS="list of dirs" to add additional dirs to the build-tools
# list
+# METALOG="path to metadata log" to write permission and ownership
+# when NO_ROOT is set. (default: ${DESTDIR}/METALOG)
# TARGET="machine" to crossbuild world for a different machine type
# TARGET_ARCH= may be required when a TARGET supports multiple endians
# BUILDENV_SHELL= shell to launch for the buildenv target (def:/bin/sh)
+# WORLD_FLAGS= additional flags to pass to make(1) during buildworld
+# KERNEL_FLAGS= additional flags to pass to make(1) during buildkernel
#
# The intended user-driven targets are:
@@ -181,7 +187,7 @@ OBJTREE= ${MAKEOBJDIRPREFIX}/${TARGET}.${TARGET_ARCH}
.endif
WORLDTMP= ${OBJTREE}${.CURDIR}/tmp
# /usr/games added for fortune which depend on strfile
-BPATH= ${WORLDTMP}/legacy/usr/sbin:${WORLDTMP}/legacy/usr/bin:${WORLDTMP}/legacy/usr/games
+BPATH= ${WORLDTMP}/legacy/usr/sbin:${WORLDTMP}/legacy/usr/bin:${WORLDTMP}/legacy/usr/games:${WORLDTMP}/legacy/bin
XPATH= ${WORLDTMP}/usr/sbin:${WORLDTMP}/usr/bin:${WORLDTMP}/usr/games
STRICTTMPPATH= ${BPATH}:${XPATH}
TMPPATH= ${STRICTTMPPATH}:${PATH}
@@ -241,7 +247,7 @@ BMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \
COMPILER_TYPE=${COMPILER_TYPE}
BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \
- ${BMAKEENV} ${MAKE} -f Makefile.inc1 \
+ ${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
DESTDIR= \
BOOTSTRAPPING=${OSRELDATE} \
SSP_CFLAGS= \
@@ -251,7 +257,7 @@ BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \
# build-tools stage
TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \
- ${BMAKEENV} ${MAKE} -f Makefile.inc1 \
+ ${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
DESTDIR= \
BOOTSTRAPPING=${OSRELDATE} \
@@ -284,7 +290,7 @@ WMAKE_COMPILER_TYPE= gcc
WMAKE_COMPILER_TYPE= clang
.endif
WMAKEENV+= COMPILER_TYPE=${WMAKE_COMPILER_TYPE}
-WMAKE= ${WMAKEENV} ${MAKE} -f Makefile.inc1 DESTDIR=${WORLDTMP}
+WMAKE= ${WMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 DESTDIR=${WORLDTMP}
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
# 32 bit world
@@ -334,18 +340,20 @@ LIB32WMAKEFLAGS+= \
CXX="${CXX} ${LIB32FLAGS}" \
DESTDIR=${LIB32TMP} \
-DCOMPAT_32BIT \
+ -DLIBRARIES_ONLY \
-DNO_CPU_CFLAGS \
-DNO_CTF \
-DNO_LINT
LIB32WMAKE= ${LIB32WMAKEENV} ${MAKE} ${LIB32WMAKEFLAGS} \
-DWITHOUT_BIND -DWITHOUT_MAN -DWITHOUT_INFO -DWITHOUT_HTML
-LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} -DNO_INCS
+LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} -DNO_INCS \
+ ${IMAKE_INSTALL}
.endif
-# install stage
IMAKEENV= ${CROSSENV:N_LDSCRIPTROOT=*}
-IMAKE= ${IMAKEENV} ${MAKE} -f Makefile.inc1
+IMAKE= ${IMAKEENV} ${MAKE} -f Makefile.inc1 \
+ ${IMAKE_INSTALL} ${IMAKE_MTREE}
.if empty(.MAKEFLAGS:M-n)
IMAKEENV+= PATH=${STRICTTMPPATH}:${INSTALLTMP} \
LD_LIBRARY_PATH=${INSTALLTMP} \
@@ -354,10 +362,25 @@ IMAKE+= __MAKE_SHELL=${INSTALLTMP}/sh
.else
IMAKEENV+= PATH=${TMPPATH}:${INSTALLTMP}
.endif
+.if defined(DB_FROM_SRC)
+INSTALLFLAGS+= -N ${.CURDIR}/etc
+MTREEFLAGS+= -N ${.CURDIR}/etc
+.endif
+.if defined(NO_ROOT)
+METALOG?= ${DESTDIR}/${DISTDIR}/METALOG
+IMAKE+= -DNO_ROOT METALOG=${METALOG}
+INSTALL_DDIR= ${DESTDIR}/${DISTDIR}
+INSTALLFLAGS+= -U -M ${METALOG} -D ${INSTALL_DDIR:S://:/:g:C:/$::}
+MTREEFLAGS+= -W
+.endif
+.if defined(DB_FROM_SRC) || defined(NO_ROOT)
+IMAKE_INSTALL= INSTALL="install ${INSTALLFLAGS}"
+IMAKE_MTREE= MTREE_CMD="nmtree ${MTREEFLAGS}"
+.endif
# kernel stage
KMAKEENV= ${WMAKEENV}
-KMAKE= ${KMAKEENV} ${MAKE} KERNEL=${INSTKERNNAME}
+KMAKE= ${KMAKEENV} ${MAKE} ${KERNEL_FLAGS} KERNEL=${INSTKERNNAME}
#
# buildworld
@@ -391,7 +414,7 @@ _worldtmp:
rm -f ${OBJTREE}${.CURDIR}/usr.bin/truss/ioctl.c
.endif
.for _dir in \
- lib usr legacy/usr
+ lib usr legacy/bin legacy/usr
mkdir -p ${WORLDTMP}/${_dir}
.endfor
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
@@ -595,9 +618,11 @@ kernel-toolchain: ${TOOLCHAIN_TGTS:N_includes:N_libraries}
installcheck:
#
-# Require DESTDIR to be set if installing for a different architecture.
+# Require DESTDIR to be set if installing for a different architecture or
+# using the user/group database in the source tree.
#
-.if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${TARGET} != ${MACHINE}
+.if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${TARGET} != ${MACHINE} || \
+ defined(DB_FROM_SRC)
.if !make(distributeworld)
installcheck: installcheck_DESTDIR
installcheck_DESTDIR:
@@ -608,6 +633,7 @@ installcheck_DESTDIR:
.endif
.endif
+.if !defined(DB_FROM_SRC)
#
# Check for missing UIDs/GIDs.
#
@@ -635,6 +661,7 @@ installcheck_UGID:
false; \
fi
.endfor
+.endif
#
# Required install tools to be saved in a scratch dir for safety.
@@ -647,9 +674,9 @@ _zoneinfo= zic tzsetup
.endif
ITOOLS= [ awk cap_mkdb cat chflags chmod chown \
- date echo egrep find grep ${_install-info} \
- ln lockf make mkdir mtree mv pwd_mkdb rm sed sh sysctl \
- test true uname wc ${_zoneinfo}
+ date echo egrep find grep id install ${_install-info} \
+ ln lockf make mkdir mtree ${_nmtree_itools} mv pwd_mkdb \
+ rm sed sh sysctl test true uname wc ${_zoneinfo}
#
# distributeworld
@@ -670,6 +697,8 @@ EXTRA_DISTRIBUTIONS+= games
EXTRA_DISTRIBUTIONS+= lib32
.endif
+MTREE_MAGIC?= mtree 2.0
+
distributeworld installworld: installcheck
mkdir -p ${INSTALLTMP}
progs=$$(for prog in ${ITOOLS}; do \
@@ -692,6 +721,9 @@ distributeworld installworld: installcheck
done); \
cp $$libs $$progs ${INSTALLTMP}
cp -R $${PATH_LOCALE:-"/usr/share/locale"} ${INSTALLTMP}/locale
+.if defined(NO_ROOT)
+ echo "#${MTREE_MAGIC}" > ${METALOG}
+.endif
.if make(distributeworld)
.for dist in ${EXTRA_DISTRIBUTIONS}
-mkdir ${DESTDIR}/${DISTDIR}/${dist}
@@ -701,10 +733,20 @@ distributeworld installworld: installcheck
-p ${DESTDIR}/${DISTDIR}/${dist}/usr >/dev/null
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
-p ${DESTDIR}/${DISTDIR}/${dist}/usr/include >/dev/null
+.if defined(NO_ROOT)
+ ${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.root.dist | \
+ sed -e 's#^\./#./${dist}/#' >> ${METALOG}
+ ${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.usr.dist | \
+ sed -e 's#^\./#./${dist}/usr/#' >> ${METALOG}
+ ${IMAKEENV} nmtree -C -f ${.CURDIR}/etc/mtree/BSD.include.dist | \
+ sed -e 's#^\./#./${dist}/usr/include/#' >> ${METALOG}
+.endif
.endfor
-mkdir ${DESTDIR}/${DISTDIR}/base
- ${_+_}cd ${.CURDIR}; ${IMAKE} distrib-dirs \
- DESTDIR=${DESTDIR}/${DISTDIR}/base
+ cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
+ METALOG=${METALOG} ${IMAKE_INSTALL} ${IMAKE_MTREE} \
+ DISTBASE=/base DESTDIR=${DESTDIR}/${DISTDIR}/base \
+ LOCAL_MTREE=${LOCAL_MTREE} distrib-dirs
.endif
${_+_}cd ${.CURDIR}; ${IMAKE} re${.TARGET:S/world$//}; \
${IMAKEENV} rm -rf ${INSTALLTMP}
@@ -712,12 +754,30 @@ distributeworld installworld: installcheck
.for dist in ${EXTRA_DISTRIBUTIONS}
find ${DESTDIR}/${DISTDIR}/${dist} -empty -delete
.endfor
+.if defined(NO_ROOT)
+.for dist in base ${EXTRA_DISTRIBUTIONS}
+ @# For each file that exists in this dist, print the corresponding
+ @# line from the METALOG. This relies on the fact that
+ @# a line containing only the filename will sort immediatly before
+ @# the relevant mtree line.
+ cd ${DESTDIR}/${DISTDIR}; \
+ find ./${dist} | sort -u ${METALOG} - | \
+ awk 'BEGIN { print "#${MTREE_MAGIC}" } !/ type=/ { file = $$1 } / type=/ { if ($$1 == file) { sub(/^\.\/${dist}\//, "./"); print } }' > \
+ ${DESTDIR}/${DISTDIR}/${dist}.meta
+.endfor
+.endif
.endif
packageworld:
.for dist in base ${EXTRA_DISTRIBUTIONS}
+.if defined(NO_ROOT)
+ ${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \
+ tar cvJf ${DESTDIR}/${DISTDIR}/${dist}.txz \
+ @${DESTDIR}/${DISTDIR}/${dist}.meta
+.else
${_+_}cd ${DESTDIR}/${DISTDIR}/${dist}; \
tar cvJf ${DESTDIR}/${DISTDIR}/${dist}.txz .
+.endif
.endfor
#
@@ -753,7 +813,8 @@ redistribute:
.endif
distrib-dirs distribution:
- cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} ${.TARGET}
+ cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
+ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET}
#
# buildkernel and installkernel
@@ -905,7 +966,7 @@ reinstallkernel reinstallkernel.debug: installcheck
@echo "--------------------------------------------------------------"
cd ${KRNLOBJDIR}/${INSTALLKERNEL}; \
${CROSSENV} PATH=${TMPPATH} \
- ${MAKE} KERNEL=${INSTKERNNAME} ${.TARGET:S/kernel//}
+ ${MAKE} ${IMAKE_INSTALL} KERNEL=${INSTKERNNAME} ${.TARGET:S/kernel//}
distributekernel distributekernel.debug:
.if empty(INSTALLKERNEL)
@@ -955,6 +1016,13 @@ update:
@echo "--------------------------------------------------------------"
@echo ">>> Running ${SUP}"
@echo "--------------------------------------------------------------"
+ @echo "!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!"
+ @echo "!! Update methods with ${SUP} are deprecated."
+ @echo "!! Please see http://www.freebsd.org/handbook/svn.html"
+ @echo "!! and convert your update method to SVN_UPDATE or"
+ @echo "!! freebsd-update(8)."
+ @echo "!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!"
+ @sleep 5
.if defined(SUPFILE)
@${SUP} ${SUPFLAGS} ${SUPFILE}
.endif
@@ -970,9 +1038,6 @@ update:
.if defined(DOCSUPFILE) && !defined(NO_DOCUPDATE)
@${SUP} ${SUPFLAGS} ${DOCSUPFILE}
.endif
-.if defined(WWWSUPFILE) && !defined(NO_WWWUPDATE)
- @${SUP} ${SUPFLAGS} ${WWWSUPFILE}
-.endif
.endif
.if defined(CVS_UPDATE)
@cd ${.CURDIR} ; \
@@ -980,6 +1045,13 @@ update:
echo "--------------------------------------------------------------" ; \
echo ">>> Updating ${.CURDIR} from CVS repository" ${CVSROOT} ; \
echo "--------------------------------------------------------------" ; \
+ echo "!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!" ; \
+ echo "!! Update methods with CVS are deprecated." ; \
+ echo "!! Please see http://www.freebsd.org/handbook/svn.html" ; \
+ echo "!! and convert your update method to SVN_UPDATE or" ; \
+ echo "!! freebsd-update(8)." ; \
+ echo "!! WARNING WARNING WARNING WARNING WARNING WARNING WARNING !!" ; \
+ sleep 5 ; \
echo ${CVS} -R -q update ${CVSFLAGS} ; \
${CVS} -R -q update ${CVSFLAGS} ; \
fi
@@ -1059,6 +1131,17 @@ _lex= usr.bin/lex
_yacc= usr.bin/yacc
.endif
+.if ${BOOTSTRAPPING} < 1000026
+_nmtree= lib/libnetbsd \
+ usr.sbin/nmtree
+.else
+_nmtree_itools= nmtree
+.endif
+
+.if ${BOOTSTRAPPING} < 1000027
+_cat= bin/cat
+.endif
+
.if ${BOOTSTRAPPING} >= 900040 && ${BOOTSTRAPPING} < 900041
_awk= usr.bin/awk
.endif
@@ -1084,7 +1167,10 @@ _dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf lib/libelf \
lib/libdwarf cddl/usr.bin/ctfconvert cddl/usr.bin/ctfmerge
.endif
-.if ${MK_FDT} != "no"
+# Default to building the BSDL DTC, but build the GPL one if users explicitly
+# request it.
+_dtc= usr.bin/dtc
+.if ${MK_GPL_DTC} != "no"
_dtc= gnu/usr.bin/dtc
.endif
@@ -1111,6 +1197,7 @@ bootstrap-tools:
${_ar} \
${_dtc} \
${_awk} \
+ ${_cat} \
usr.bin/lorder \
usr.bin/makewhatis \
${_mklocale} \
@@ -1120,7 +1207,8 @@ bootstrap-tools:
${_lex} \
usr.bin/xinstall \
${_gensnmptree} \
- usr.sbin/config
+ usr.sbin/config \
+ ${_nmtree}
${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \
cd ${.CURDIR}/${_tool}; \
${MAKE} DIRPRFX=${_tool}/ obj; \
@@ -1228,11 +1316,12 @@ cross-tools:
# hierarchy - ensure that all the needed directories are present
#
hierarchy hier:
- cd ${.CURDIR}/etc; ${MAKE} distrib-dirs
-.for _mtree in ${LOCAL_MTREE}
- mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/${_mtree} \
- -p ${DESTDIR}/
-.endfor
+.if defined(NO_ROOT)
+ cd ${.CURDIR}/etc; ${MAKE} LOCAL_MTREE=${LOCAL_MTREE} \
+ -DNO_ROOT METALOG=${METALOG} distrib-dirs
+.else
+ cd ${.CURDIR}/etc; ${MAKE} LOCAL_MTREE=${LOCAL_MTREE} distrib-dirs
+.endif
#
# libraries - build all libraries, and install them under ${DESTDIR}.
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 740b92d..6fda607 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -38,6 +38,13 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20130116: removed long unused directories for .1aout section manpages
+OLD_FILES+=usr/share/man/en.ISO8859-1/man1aout
+OLD_FILES+=usr/share/man/en.UTF-8/man1aout
+OLD_DIRS+=usr/share/man/man1aout
+OLD_DIRS+=usr/share/man/cat1aout
+OLD_DIRS+=usr/share/man/en.ISO8859-1/cat1aout
+OLD_DIRS+=usr/share/man/en.UTF-8/cat1aout
# 20121230: libdisk removed
OLD_FILES+=usr/share/man/man3/libdisk.3.gz usr/include/libdisk.h
OLD_FILES+=usr/lib/libdisk.a usr/lib32/libdisk.a
@@ -1201,12 +1208,6 @@ OLD_FILES+=usr/include/sys/linedisc.h
OLD_FILES+=usr/share/man/man3/posix_openpt.3.gz
# 20080725: sgtty.h removed
OLD_FILES+=usr/include/sgtty.h
-# 20080719: sade(8) removed on all but amd64, i386 and sparc64
-.if ${TARGET_ARCH} != "amd64" && ${TARGET_ARCH} != "i386" && \
- ${TARGET_ARCH} != "sparc64"
-OLD_FILES+=usr/sbin/sade
-OLD_FILES+=usr/share/man/man8/sade.8.gz
-.endif
# 20080706: bsdlabel(8) removed on powerpc
.if ${TARGET_ARCH} == "powerpc"
OLD_FILES+=sbin/bsdlabel
diff --git a/UPDATING b/UPDATING
index ce83d3f..20e375c 100644
--- a/UPDATING
+++ b/UPDATING
@@ -26,6 +26,22 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20130129:
+ A BSD-licensed patch(1) variant has been added and is installed
+ as bsdpatch, being the GNU version the default patch.
+ To inverse the logic and use the BSD-licensed one as default,
+ while having the GNU version installed as gnupatch, rebuild
+ and install world with the WITH_BSD_PATCH knob set.
+
+20130118:
+ The install(1) option -M has changed meaning and now takes an
+ argument that is a file or path to append logs to. In the
+ unlikely event that -M was the last option on the command line
+ and the command line contained at least two files and a target
+ directory the first file will have logs appended to it. The -M
+ option served little practical purpose in the last decade so it's
+ used expected to be extremely rare.
+
20121223:
After switching to Clang as the default compiler some users of ZFS
on i386 systems started to experience stack overflow kernel panics.
diff --git a/bin/cat/cat.1 b/bin/cat/cat.1
index 4fdff3a..69f5ef6 100644
--- a/bin/cat/cat.1
+++ b/bin/cat/cat.1
@@ -32,7 +32,7 @@
.\" @(#)cat.1 8.3 (Berkeley) 5/2/95
.\" $FreeBSD$
.\"
-.Dd March 21, 2004
+.Dd January 29, 2013
.Dt CAT 1
.Os
.Sh NAME
@@ -40,7 +40,7 @@
.Nd concatenate and print files
.Sh SYNOPSIS
.Nm
-.Op Fl benstuv
+.Op Fl belnstuv
.Op Ar
.Sh DESCRIPTION
The
@@ -79,6 +79,16 @@ Display non-printing characters (see the
option), and display a dollar sign
.Pq Ql \&$
at the end of each line.
+.It Fl l
+Set an exclusive advisory lock on the standard output file descriptor.
+This lock is set using
+.Xr fcntl 2
+with the
+.Dv F_SETLKW
+command.
+If the output file is already locked,
+.Nm
+will block until the lock is acquired.
.It Fl n
Number the output lines, starting at 1.
.It Fl s
@@ -160,6 +170,7 @@ operand.
.Xr tail 1 ,
.Xr vis 1 ,
.Xr zcat 1 ,
+.Xr fcntl 2 ,
.Xr setbuf 3
.Rs
.%A Rob Pike
@@ -175,7 +186,7 @@ utility is compliant with the
specification.
.Pp
The flags
-.Op Fl benstv
+.Op Fl belnstv
are extensions to the specification.
.Sh HISTORY
A
diff --git a/bin/cat/cat.c b/bin/cat/cat.c
index 69c56c0..9e12d3e 100644
--- a/bin/cat/cat.c
+++ b/bin/cat/cat.c
@@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-static int bflag, eflag, nflag, sflag, tflag, vflag;
+static int bflag, eflag, lflag, nflag, sflag, tflag, vflag;
static int rval;
static const char *filename;
@@ -96,10 +96,11 @@ int
main(int argc, char *argv[])
{
int ch;
+ struct flock stdout_lock;
setlocale(LC_CTYPE, "");
- while ((ch = getopt(argc, argv, "benstuv")) != -1)
+ while ((ch = getopt(argc, argv, "belnstuv")) != -1)
switch (ch) {
case 'b':
bflag = nflag = 1; /* -b implies -n */
@@ -107,6 +108,9 @@ main(int argc, char *argv[])
case 'e':
eflag = vflag = 1; /* -e implies -v */
break;
+ case 'l':
+ lflag = 1;
+ break;
case 'n':
nflag = 1;
break;
@@ -127,6 +131,15 @@ main(int argc, char *argv[])
}
argv += optind;
+ if (lflag) {
+ stdout_lock.l_len = 0;
+ stdout_lock.l_start = 0;
+ stdout_lock.l_type = F_WRLCK;
+ stdout_lock.l_whence = SEEK_SET;
+ if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1)
+ err(EXIT_FAILURE, "stdout");
+ }
+
if (bflag || eflag || nflag || sflag || tflag || vflag)
scanfiles(argv, 1);
else
@@ -140,7 +153,7 @@ main(int argc, char *argv[])
static void
usage(void)
{
- fprintf(stderr, "usage: cat [-benstuv] [file ...]\n");
+ fprintf(stderr, "usage: cat [-belnstuv] [file ...]\n");
exit(1);
/* NOTREACHED */
}
diff --git a/bin/cp/cp.c b/bin/cp/cp.c
index 86dbb3c..b83eead 100644
--- a/bin/cp/cp.c
+++ b/bin/cp/cp.c
@@ -98,30 +98,28 @@ main(int argc, char *argv[])
{
struct stat to_stat, tmp_stat;
enum op type;
- int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash;
+ int Hflag, Lflag, ch, fts_options, r, have_trailing_slash;
char *target;
fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
- Hflag = Lflag = Pflag = 0;
+ Hflag = Lflag = 0;
while ((ch = getopt(argc, argv, "HLPRafilnprvx")) != -1)
switch (ch) {
case 'H':
Hflag = 1;
- Lflag = Pflag = 0;
+ Lflag = 0;
break;
case 'L':
Lflag = 1;
- Hflag = Pflag = 0;
+ Hflag = 0;
break;
case 'P':
- Pflag = 1;
Hflag = Lflag = 0;
break;
case 'R':
Rflag = 1;
break;
case 'a':
- Pflag = 1;
pflag = 1;
Rflag = 1;
Hflag = Lflag = 0;
@@ -146,7 +144,7 @@ main(int argc, char *argv[])
break;
case 'r':
rflag = Lflag = 1;
- Hflag = Pflag = 0;
+ Hflag = 0;
break;
case 'v':
vflag = 1;
diff --git a/bin/cp/utils.c b/bin/cp/utils.c
index d729bd5..ad9695c 100644
--- a/bin/cp/utils.c
+++ b/bin/cp/utils.c
@@ -104,7 +104,7 @@ copy_file(const FTSENT *entp, int dne)
if (vflag)
printf("%s not overwritten\n", to.p_path);
(void)close(from_fd);
- return (0);
+ return (1);
} else if (iflag) {
(void)fprintf(stderr, "overwrite %s? %s",
to.p_path, YESNO);
@@ -266,6 +266,11 @@ copy_link(const FTSENT *p, int exists)
int len;
char llink[PATH_MAX];
+ if (exists && nflag) {
+ if (vflag)
+ printf("%s not overwritten\n", to.p_path);
+ return (1);
+ }
if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) {
warn("readlink: %s", p->fts_path);
return (1);
@@ -285,6 +290,12 @@ copy_link(const FTSENT *p, int exists)
int
copy_fifo(struct stat *from_stat, int exists)
{
+
+ if (exists && nflag) {
+ if (vflag)
+ printf("%s not overwritten\n", to.p_path);
+ return (1);
+ }
if (exists && unlink(to.p_path)) {
warn("unlink: %s", to.p_path);
return (1);
@@ -299,6 +310,12 @@ copy_fifo(struct stat *from_stat, int exists)
int
copy_special(struct stat *from_stat, int exists)
{
+
+ if (exists && nflag) {
+ if (vflag)
+ printf("%s not overwritten\n", to.p_path);
+ return (1);
+ }
if (exists && unlink(to.p_path)) {
warn("unlink: %s", to.p_path);
return (1);
diff --git a/bin/df/df.1 b/bin/df/df.1
index f107ad3..8d14248 100644
--- a/bin/df/df.1
+++ b/bin/df/df.1
@@ -29,7 +29,7 @@
.\" @(#)df.1 8.3 (Berkeley) 5/8/95
.\" $FreeBSD$
.\"
-.Dd November 16, 2012
+.Dd January 24, 2013
.Dt DF 1
.Os
.Sh NAME
@@ -39,6 +39,7 @@
.Nm
.Op Fl b | g | H | h | k | m | P
.Op Fl acilnT
+.Op Fl \&,
.Op Fl t Ar type
.Op Ar file | filesystem ...
.Sh DESCRIPTION
diff --git a/bin/df/df.c b/bin/df/df.c
index b430608..77b7a40 100644
--- a/bin/df/df.c
+++ b/bin/df/df.c
@@ -564,7 +564,8 @@ usage(void)
{
(void)fprintf(stderr,
-"usage: df [-b | -g | -H | -h | -k | -m | -P] [-acilnT] [-t type] [-,] [file | filesystem ...]\n");
+"usage: df [-b | -g | -H | -h | -k | -m | -P] [-acilnT] [-t type] [-,]\n"
+" [file | filesystem ...]\n");
exit(EX_USAGE);
}
diff --git a/bin/ps/extern.h b/bin/ps/extern.h
index 930b85b..eb9b2cf 100644
--- a/bin/ps/extern.h
+++ b/bin/ps/extern.h
@@ -51,7 +51,7 @@ char *elapsed(KINFO *, VARENT *);
char *elapseds(KINFO *, VARENT *);
char *emulname(KINFO *, VARENT *);
VARENT *find_varentry(VAR *);
-const char *fmt_argv(char **, char *, size_t);
+const char *fmt_argv(char **, char *, char *, size_t);
double getpcpu(const KINFO *);
char *kvar(KINFO *, VARENT *);
char *label(KINFO *, VARENT *);
diff --git a/bin/ps/fmt.c b/bin/ps/fmt.c
index 1e9fed8..4db6b8d 100644
--- a/bin/ps/fmt.c
+++ b/bin/ps/fmt.c
@@ -105,7 +105,7 @@ cmdpart(char *arg0)
}
const char *
-fmt_argv(char **argv, char *cmd, size_t maxlen)
+fmt_argv(char **argv, char *cmd, char *thread, size_t maxlen)
{
size_t len;
char *ap, *cp;
@@ -122,9 +122,14 @@ fmt_argv(char **argv, char *cmd, size_t maxlen)
cp = malloc(len);
if (cp == NULL)
errx(1, "malloc failed");
- if (ap == NULL)
- sprintf(cp, "[%.*s]", (int)maxlen, cmd);
- else if (strncmp(cmdpart(argv[0]), cmd, maxlen) != 0)
+ if (ap == NULL) {
+ if (thread != NULL) {
+ asprintf(&ap, "%s/%s", cmd, thread);
+ sprintf(cp, "[%.*s]", (int)maxlen, ap);
+ free(ap);
+ } else
+ sprintf(cp, "[%.*s]", (int)maxlen, cmd);
+ } else if (strncmp(cmdpart(argv[0]), cmd, maxlen) != 0)
sprintf(cp, "%s (%.*s)", ap, (int)maxlen, cmd);
else
strcpy(cp, ap);
diff --git a/bin/ps/ps.c b/bin/ps/ps.c
index e9fc5fa..7099cc0 100644
--- a/bin/ps/ps.c
+++ b/bin/ps/ps.c
@@ -141,7 +141,7 @@ static void format_output(KINFO *);
static void *expand_list(struct listinfo *);
static const char *
fmt(char **(*)(kvm_t *, const struct kinfo_proc *, int),
- KINFO *, char *, int);
+ KINFO *, char *, char *, int);
static void free_list(struct listinfo *);
static void init_list(struct listinfo *, addelem_rtn, int, const char *);
static char *kludge_oldps_options(const char *, char *, const char *);
@@ -1163,11 +1163,12 @@ sizevars(void)
static const char *
fmt(char **(*fn)(kvm_t *, const struct kinfo_proc *, int), KINFO *ki,
- char *comm, int maxlen)
+ char *comm, char *thread, int maxlen)
{
const char *s;
- s = fmt_argv((*fn)(kd, ki->ki_p, termwidth), comm, maxlen);
+ s = fmt_argv((*fn)(kd, ki->ki_p, termwidth), comm,
+ showthreads && ki->ki_p->ki_numthreads > 1 ? thread : NULL, maxlen);
return (s);
}
@@ -1195,7 +1196,7 @@ saveuser(KINFO *ki)
ki->ki_args = strdup("<defunct>");
else if (UREADOK(ki) || (ki->ki_p->ki_args != NULL))
ki->ki_args = strdup(fmt(kvm_getargv, ki,
- ki->ki_p->ki_comm, MAXCOMLEN));
+ ki->ki_p->ki_comm, ki->ki_p->ki_tdname, MAXCOMLEN));
else
asprintf(&ki->ki_args, "(%s)", ki->ki_p->ki_comm);
if (ki->ki_args == NULL)
@@ -1206,7 +1207,7 @@ saveuser(KINFO *ki)
if (needenv) {
if (UREADOK(ki))
ki->ki_env = strdup(fmt(kvm_getenvv, ki,
- (char *)NULL, 0));
+ (char *)NULL, (char *)NULL, 0));
else
ki->ki_env = strdup("()");
if (ki->ki_env == NULL)
diff --git a/bin/pwait/pwait.c b/bin/pwait/pwait.c
index 26cf1bd..6851fad 100644
--- a/bin/pwait/pwait.c
+++ b/bin/pwait/pwait.c
@@ -141,5 +141,5 @@ main(int argc, char *argv[])
nleft -= n;
}
- return 0;
+ exit(EX_OK);
}
diff --git a/bin/sh/TOUR b/bin/sh/TOUR
index 4b61bdf..13438b5 100644
--- a/bin/sh/TOUR
+++ b/bin/sh/TOUR
@@ -33,10 +33,6 @@ programs is:
There are undoubtedly too many of these. Mkinit searches all the
C source files for entries looking like:
- INIT {
- x = 1; /* executed during initialization */
- }
-
RESET {
x = 2; /* executed when the shell does a longjmp
back to the main command loop */
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 2e1315e..66ae40e 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -92,6 +92,7 @@ static void evalfor(union node *, int);
static union node *evalcase(union node *);
static void evalsubshell(union node *, int);
static void evalredir(union node *, int);
+static void exphere(union node *, struct arglist *);
static void expredir(union node *);
static void evalpipe(union node *);
static int is_valid_fast_cmdsubst(union node *n);
@@ -193,7 +194,9 @@ evaltree(union node *n, int flags)
{
int do_etest;
union node *next;
+ struct stackmark smark;
+ setstackmark(&smark);
do_etest = 0;
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
@@ -292,8 +295,10 @@ evaltree(union node *n, int flags)
break;
}
n = next;
+ popstackmark(&smark);
} while (n != NULL);
out:
+ popstackmark(&smark);
if (pendingsigs)
dotrap();
if (eflag && exitstatus != 0 && do_etest)
@@ -347,10 +352,8 @@ evalfor(union node *n, int flags)
struct arglist arglist;
union node *argp;
struct strlist *sp;
- struct stackmark smark;
int status;
- setstackmark(&smark);
arglist.lastp = &arglist.list;
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
oexitstatus = exitstatus;
@@ -375,7 +378,6 @@ evalfor(union node *n, int flags)
}
}
loopnest--;
- popstackmark(&smark);
exitstatus = status;
}
@@ -392,16 +394,13 @@ evalcase(union node *n)
union node *cp;
union node *patp;
struct arglist arglist;
- struct stackmark smark;
- setstackmark(&smark);
arglist.lastp = &arglist.list;
oexitstatus = exitstatus;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
- popstackmark(&smark);
while (cp->nclist.next &&
cp->type == NCLISTFALLTHRU &&
cp->nclist.body == NULL)
@@ -415,7 +414,6 @@ evalcase(union node *n)
}
}
}
- popstackmark(&smark);
exitstatus = 0;
return (NULL);
}
@@ -491,6 +489,37 @@ evalredir(union node *n, int flags)
}
+static void
+exphere(union node *redir, struct arglist *fn)
+{
+ struct jmploc jmploc;
+ struct jmploc *savehandler;
+ struct localvar *savelocalvars;
+ int need_longjmp = 0;
+
+ redir->nhere.expdoc = nullstr;
+ savelocalvars = localvars;
+ localvars = NULL;
+ forcelocal++;
+ savehandler = handler;
+ if (setjmp(jmploc.loc))
+ need_longjmp = exception != EXERROR && exception != EXEXEC;
+ else {
+ handler = &jmploc;
+ expandarg(redir->nhere.doc, fn, 0);
+ redir->nhere.expdoc = fn->list->text;
+ INTOFF;
+ }
+ handler = savehandler;
+ forcelocal--;
+ poplocalvars();
+ localvars = savelocalvars;
+ if (need_longjmp)
+ longjmp(handler->loc, 1);
+ INTON;
+}
+
+
/*
* Compute the names of the files in a redirection list.
*/
@@ -519,6 +548,9 @@ expredir(union node *n)
fixredir(redir, fn.list->text, 1);
}
break;
+ case NXHERE:
+ exphere(redir, &fn);
+ break;
}
}
}
@@ -610,7 +642,7 @@ evalbackcmd(union node *n, struct backcmd *result)
{
int pip[2];
struct job *jp;
- struct stackmark smark; /* unnecessary */
+ struct stackmark smark;
struct jmploc jmploc;
struct jmploc *savehandler;
struct localvar *savelocalvars;
@@ -624,8 +656,8 @@ evalbackcmd(union node *n, struct backcmd *result)
exitstatus = 0;
goto out;
}
+ exitstatus = oexitstatus;
if (is_valid_fast_cmdsubst(n)) {
- exitstatus = oexitstatus;
savelocalvars = localvars;
localvars = NULL;
forcelocal++;
@@ -649,7 +681,6 @@ evalbackcmd(union node *n, struct backcmd *result)
poplocalvars();
localvars = savelocalvars;
} else {
- exitstatus = 0;
if (pipe(pip) < 0)
error("Pipe call failed: %s", strerror(errno));
jp = makejob(n, 1);
@@ -752,7 +783,6 @@ safe_builtin(int idx, int argc, char **argv)
static void
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
{
- struct stackmark smark;
union node *argp;
struct arglist arglist;
struct arglist varlist;
@@ -779,7 +809,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
/* First expand the arguments. */
TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
- setstackmark(&smark);
arglist.lastp = &arglist.list;
varlist.lastp = &varlist.list;
varflag = 1;
@@ -1150,7 +1179,6 @@ out:
setvar("_", lastarg, 0);
if (do_clearcmdentry)
clearcmdentry();
- popstackmark(&smark);
}
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index eb32403..7a6dbae 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -86,12 +86,12 @@ struct tblentry {
union param param; /* definition of builtin function */
int special; /* flag for special builtin commands */
signed char cmdtype; /* index identifying command */
- char rehash; /* if set, cd done since entry created */
char cmdname[]; /* name of command */
};
static struct tblentry *cmdtable[CMDTABLESIZE];
+static int cmdtable_cd = 0; /* cmdtable contains cd-dependent entries */
int exerrno = 0; /* Last exec error */
@@ -305,8 +305,6 @@ printentry(struct tblentry *cmdp, int verbose)
error("internal error: cmdtype %d", cmdp->cmdtype);
#endif
}
- if (cmdp->rehash)
- out1c('*');
out1c('\n');
}
@@ -323,12 +321,12 @@ find_command(const char *name, struct cmdentry *entry, int act,
{
struct tblentry *cmdp, loc_cmd;
int idx;
- int prev;
char *fullname;
struct stat statb;
int e;
int i;
int spec;
+ int cd;
/* If name contains a slash, don't use the hash table */
if (strchr(name, '/') != NULL) {
@@ -337,8 +335,10 @@ find_command(const char *name, struct cmdentry *entry, int act,
return;
}
+ cd = 0;
+
/* If name is in the table, and not invalidated by cd, we're done */
- if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
+ if ((cmdp = cmdlookup(name, 0)) != NULL) {
if (cmdp->cmdtype == CMDFUNCTION && act & DO_NOFUNC)
cmdp = NULL;
else
@@ -359,13 +359,6 @@ find_command(const char *name, struct cmdentry *entry, int act,
}
/* We have to search path. */
- prev = -1; /* where to start */
- if (cmdp) { /* doing a rehash */
- if (cmdp->cmdtype == CMDBUILTIN)
- prev = -1;
- else
- prev = cmdp->param.index;
- }
e = ENOENT;
idx = -1;
@@ -380,13 +373,8 @@ loop:
goto loop; /* ignore unimplemented options */
}
}
- /* if rehash, don't redo absolute path names */
- if (fullname[0] == '/' && idx <= prev) {
- if (idx < prev)
- goto loop;
- TRACE(("searchexec \"%s\": no change\n", name));
- goto success;
- }
+ if (fullname[0] != '/')
+ cd = 1;
if (stat(fullname, &statb) < 0) {
if (errno != ENOENT && errno != ENOTDIR)
e = errno;
@@ -426,9 +414,6 @@ loop:
goto success;
}
- /* We failed. If there was an entry for this command, delete it */
- if (cmdp && cmdp->cmdtype != CMDFUNCTION)
- delete_cmd_entry();
if (act & DO_ERR) {
if (e == ENOENT || e == ENOTDIR)
outfmt(out2, "%s: not found\n", name);
@@ -440,7 +425,8 @@ loop:
return;
success:
- cmdp->rehash = 0;
+ if (cd)
+ cmdtable_cd = 1;
entry->cmdtype = cmdp->cmdtype;
entry->u = cmdp->param;
entry->special = cmdp->special;
@@ -469,22 +455,15 @@ find_builtin(const char *name, int *special)
/*
- * Called when a cd is done. Marks all commands so the next time they
- * are executed they will be rehashed.
+ * Called when a cd is done. If any entry in cmdtable depends on the current
+ * directory, simply clear cmdtable completely.
*/
void
hashcd(void)
{
- struct tblentry **pp;
- struct tblentry *cmdp;
-
- for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
- for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
- if (cmdp->cmdtype == CMDNORMAL)
- cmdp->rehash = 1;
- }
- }
+ if (cmdtable_cd)
+ clearcmdentry();
}
@@ -526,6 +505,7 @@ clearcmdentry(void)
}
}
}
+ cmdtable_cd = 0;
INTON;
}
@@ -566,7 +546,6 @@ cmdlookup(const char *name, int add)
+ strlen(name) + 1);
cmdp->next = NULL;
cmdp->cmdtype = CMDUNKNOWN;
- cmdp->rehash = 0;
strcpy(cmdp->cmdname, name);
INTON;
}
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index d43cc35..107f798 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -127,19 +127,6 @@ collate_range_cmp(wchar_t c1, wchar_t c2)
return (wcscoll(s1, s2));
}
-/*
- * Expand shell variables and backquotes inside a here document.
- * union node *arg the document
- * int fd; where to write the expanded version
- */
-
-void
-expandhere(union node *arg, int fd)
-{
- expandarg(arg, (struct arglist *)NULL, 0);
- xwrite(fd, stackblock(), expdest - stackblock());
-}
-
static char *
stputs_quotes(const char *data, const char *syntax, char *p)
{
diff --git a/bin/sh/expand.h b/bin/sh/expand.h
index 8114e2b..8d44321 100644
--- a/bin/sh/expand.h
+++ b/bin/sh/expand.h
@@ -57,7 +57,6 @@ struct arglist {
union node;
-void expandhere(union node *, int);
void expandarg(union node *, struct arglist *, int);
void expari(int);
void rmescapes(char *);
diff --git a/bin/sh/init.h b/bin/sh/init.h
index dd0c4a8..384bb69 100644
--- a/bin/sh/init.h
+++ b/bin/sh/init.h
@@ -33,5 +33,4 @@
* $FreeBSD$
*/
-void init(void);
void reset(void);
diff --git a/bin/sh/input.c b/bin/sh/input.c
index 2005a87..84580ad 100644
--- a/bin/sh/input.c
+++ b/bin/sh/input.c
@@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
-MKINIT
struct strpush {
struct strpush *prev; /* preceding string on stack */
char *prevstring;
@@ -78,7 +77,6 @@ struct strpush {
* contains information about the current file being read.
*/
-MKINIT
struct parsefile {
struct parsefile *prev; /* preceding file on stack */
int linno; /* current line */
@@ -96,8 +94,11 @@ int plinno = 1; /* input line number */
int parsenleft; /* copy of parsefile->nleft */
MKINIT int parselleft; /* copy of parsefile->lleft */
char *parsenextc; /* copy of parsefile->nextc */
-MKINIT struct parsefile basepf; /* top level input file */
-char basebuf[BUFSIZ + 1]; /* buffer for top level input file */
+static char basebuf[BUFSIZ + 1];/* buffer for top level input file */
+static struct parsefile basepf = { /* top level input file */
+ .nextc = basebuf,
+ .buf = basebuf
+};
static struct parsefile *parsefile = &basepf; /* current input file */
int whichprompt; /* 1 == PS1, 2 == PS2 */
@@ -111,12 +112,6 @@ static void popstring(void);
INCLUDE "input.h"
INCLUDE "error.h"
-MKINIT char basebuf[];
-
-INIT {
- basepf.nextc = basepf.buf = basebuf;
-}
-
RESET {
popallfiles();
parselleft = parsenleft = 0; /* clear input buffer */
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index 02cf6e8..d2e1d57 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -1298,6 +1298,10 @@ until:
cmdputs(n->narg.text);
cmdputs("() ...");
break;
+ case NNOT:
+ cmdputs("! ");
+ cmdtxt(n->nnot.com);
+ break;
case NCMD:
for (np = n->ncmd.args ; np ; np = np->narg.next) {
cmdtxt(np);
diff --git a/bin/sh/main.c b/bin/sh/main.c
index b93f04e..66e1335 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -139,7 +139,7 @@ main(int argc, char *argv[])
#endif
rootpid = getpid();
rootshell = 1;
- init();
+ initvar();
setstackmark(&smark);
setstackmark(&smark2);
procargs(argc, argv);
diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c
index f602177..b81cc82 100644
--- a/bin/sh/miscbltin.c
+++ b/bin/sh/miscbltin.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
-#include <ctype.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
@@ -60,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
+#include "syntax.h"
#undef eflag
@@ -307,7 +307,7 @@ umaskcmd(int argc __unused, char **argv __unused)
out1fmt("%.4o\n", mask);
}
} else {
- if (isdigit(*ap)) {
+ if (is_digit(*ap)) {
mask = 0;
do {
if (*ap >= '8' || *ap < '0')
diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c
index 1d1d93e..d73e0e2 100644
--- a/bin/sh/mkinit.c
+++ b/bin/sh/mkinit.c
@@ -101,7 +101,7 @@ struct block {
*/
struct event {
- const char *name; /* name of event (e.g. INIT) */
+ const char *name; /* name of event (e.g. RESET) */
const char *routine; /* name of routine called on event */
const char *comment; /* comment describing routine */
struct text code; /* code for handling event */
@@ -114,11 +114,6 @@ char writer[] = "\
*/\n\
\n";
-char init[] = "\
-/*\n\
- * Initialization code.\n\
- */\n";
-
char reset[] = "\
/*\n\
* This routine is called when an error or an interrupt occurs in an\n\
@@ -127,7 +122,6 @@ char reset[] = "\
struct event event[] = {
- { "INIT", "init", init, { NULL, 0, NULL, NULL } },
{ "RESET", "reset", reset, { NULL, 0, NULL, NULL } },
{ NULL, NULL, NULL, { NULL, 0, NULL, NULL } }
};
diff --git a/bin/sh/mksyntax.c b/bin/sh/mksyntax.c
index 07dc2f1..2b8ecdb 100644
--- a/bin/sh/mksyntax.c
+++ b/bin/sh/mksyntax.c
@@ -165,7 +165,6 @@ main(int argc __unused, char **argv __unused)
}
fputs("#include <sys/cdefs.h>\n", hfile);
- fputs("#include <ctype.h>\n", hfile);
/* Generate the #define statements in the header file */
fputs("/* Syntax classes */\n", hfile);
diff --git a/bin/sh/nodetypes b/bin/sh/nodetypes
index ae4bc4a..5e70c64 100644
--- a/bin/sh/nodetypes
+++ b/bin/sh/nodetypes
@@ -138,6 +138,7 @@ NXHERE nhere # fd<<!
next nodeptr # next redirection in list
fd int # file descriptor being redirected
doc nodeptr # input to command (NARG node)
+ expdoc temp char *expdoc # actual document (for NXHERE)
NNOT nnot # ! command (actually pipeline)
type int
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index ef1aa36..665b53f 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -240,9 +240,9 @@ list(int nlflag, int erflag)
n2 = andor();
tok = readtoken();
if (tok == TBACKGND) {
- if (n2->type == NPIPE) {
+ if (n2 != NULL && n2->type == NPIPE) {
n2->npipe.backgnd = 1;
- } else if (n2->type == NREDIR) {
+ } else if (n2 != NULL && n2->type == NREDIR) {
n2->type = NBACKGND;
} else {
n3 = (union node *)stalloc(sizeof (struct nredir));
@@ -286,7 +286,8 @@ list(int nlflag, int erflag)
tokpushback++;
}
checkkwd = CHKNL | CHKKWD | CHKALIAS;
- if (!nlflag && !erflag && tokendlist[peektoken()])
+ if (!nlflag && (erflag ? peektoken() == TEOF :
+ tokendlist[peektoken()]))
return ntop;
break;
case TEOF:
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 915b2fc..c11cb71 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -251,18 +251,23 @@ movefd:
static int
openhere(union node *redir)
{
+ char *p;
int pip[2];
int len = 0;
if (pipe(pip) < 0)
error("Pipe call failed: %s", strerror(errno));
- if (redir->type == NHERE) {
- len = strlen(redir->nhere.doc->narg.text);
- if (len <= PIPESIZE) {
- xwrite(pip[1], redir->nhere.doc->narg.text, len);
- goto out;
- }
+
+ if (redir->type == NXHERE)
+ p = redir->nhere.expdoc;
+ else
+ p = redir->nhere.doc->narg.text;
+ len = strlen(p);
+ if (len <= PIPESIZE) {
+ xwrite(pip[1], p, len);
+ goto out;
}
+
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
close(pip[0]);
signal(SIGINT, SIG_IGN);
@@ -270,10 +275,7 @@ openhere(union node *redir)
signal(SIGHUP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGPIPE, SIG_DFL);
- if (redir->type == NHERE)
- xwrite(pip[1], redir->nhere.doc->narg.text, len);
- else
- expandhere(redir->nhere.doc, pip[1]);
+ xwrite(pip[1], p, len);
_exit(0);
}
out:
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 1750267..09d94f3 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd July 15, 2012
+.Dd January 22, 2013
.Dt SH 1
.Os
.Sh NAME
@@ -138,10 +138,10 @@ variable to some file by placing the following line in the file
.Pa .profile
in the home directory,
substituting for
-.Pa .shinit
+.Pa .shrc
the filename desired:
.Pp
-.Dl "ENV=$HOME/.shinit; export ENV"
+.Dl "ENV=$HOME/.shrc; export ENV"
.Pp
The first non-option argument specified on the command line
will be treated as the
@@ -2219,10 +2219,6 @@ The shell maintains a hash table which remembers the locations of commands.
With no arguments whatsoever, the
.Ic hash
command prints out the contents of this table.
-Entries which have not been looked at since the last
-.Ic cd
-command are marked with an asterisk;
-it is possible for these entries to be invalid.
.Pp
With arguments, the
.Ic hash
@@ -2678,6 +2674,17 @@ Additionally, all environment variables are turned into shell variables
at startup,
which may affect the shell as described under
.Sx Special Variables .
+.Sh FILES
+.Bl -tag -width "/etc/suid_profileXX" -compact
+.It Pa ~/.profile
+User's login profile.
+.It Pa /etc/profile
+System login profile.
+.It Pa /etc/shells
+Shell database.
+.It Pa /etc/suid_profile
+Privileged shell profile.
+.El
.Sh EXIT STATUS
Errors that are detected by the shell, such as a syntax error, will
cause the shell to exit with a non-zero exit status.
@@ -2703,7 +2710,8 @@ will return the argument.
.Xr getrlimit 2 ,
.Xr umask 2 ,
.Xr wctype 3 ,
-.Xr editrc 5
+.Xr editrc 5 ,
+.Xr shells 5
.Sh HISTORY
A
.Nm
diff --git a/bin/sh/var.c b/bin/sh/var.c
index 48a0dc5..3f29a48 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -146,29 +146,11 @@ static int varequal(const char *, const char *);
static struct var *find_var(const char *, struct var ***, int *);
static int localevar(const char *);
-/*
- * Initialize the variable symbol tables and import the environment.
- */
-
-#ifdef mkinit
-INCLUDE "var.h"
-MKINIT char **environ;
-INIT {
- char **envp;
-
- initvar();
- for (envp = environ ; *envp ; envp++) {
- if (strchr(*envp, '=')) {
- setvareq(*envp, VEXPORT|VTEXTFIXED);
- }
- }
-}
-#endif
-
+extern char **environ;
/*
- * This routine initializes the builtin variables. It is called when the
- * shell is initialized.
+ * This routine initializes the builtin variables and imports the environment.
+ * It is called when the shell is initialized.
*/
void
@@ -178,6 +160,7 @@ initvar(void)
const struct varinit *ip;
struct var *vp;
struct var **vpp;
+ char **envp;
for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
@@ -201,6 +184,11 @@ initvar(void)
fmtstr(ppid, sizeof(ppid), "%d", (int)getppid());
setvarsafe("PPID", ppid, 0);
}
+ for (envp = environ ; *envp ; envp++) {
+ if (strchr(*envp, '=')) {
+ setvareq(*envp, VEXPORT|VTEXTFIXED);
+ }
+ }
}
/*
@@ -356,7 +344,7 @@ setvareq(char *s, int flags)
* a regular variable function callback, but why bother?
*
* Note: this assumes iflag is not set to 1 initially.
- * As part of init(), this is called before arguments
+ * As part of initvar(), this is called before arguments
* are looked at.
*/
if ((vp == &vmpath || (vp == &vmail && ! mpathset())) &&
diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
index 362a405..82941af 100644
--- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c
+++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
@@ -704,7 +704,9 @@ dump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
return;
ASSERT(error == 0);
- if ((count = ddt_object_count(ddt, type, class)) == 0)
+ error = ddt_object_count(ddt, type, class, &count);
+ ASSERT(error == 0);
+ if (count == 0)
return;
dspace = doi.doi_physical_blocks_512 << 9;
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c
index 560bacd..6af5f77 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_status.c
@@ -150,6 +150,16 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t))
return (B_TRUE);
}
+ /*
+ * Check any L2 cache devs
+ */
+ if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child,
+ &children) == 0) {
+ for (c = 0; c < children; c++)
+ if (find_vdev_problem(child[c], func))
+ return (B_TRUE);
+ }
+
return (B_FALSE);
}
diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile
index 3a79e87..17f0be6 100644
--- a/cddl/lib/libdtrace/Makefile
+++ b/cddl/lib/libdtrace/Makefile
@@ -103,7 +103,7 @@ dt_names.c:
beforedepend: dt_errtags.c dt_names.c
beforeinstall:
-.if exists(${DESTDIR}/usr/lib/dtrace)
+.if !defined(LIBRARIES_ONLY) && exists(${DESTDIR}/usr/lib/dtrace)
.for file in ${DSRCS}
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} ${.CURDIR}/${file} ${DESTDIR}/usr/lib/dtrace
.endfor
diff --git a/contrib/binutils/config/acinclude.m4 b/contrib/binutils/config/acinclude.m4
index c7c0ab5..c7c0ab5 100755..100644
--- a/contrib/binutils/config/acinclude.m4
+++ b/contrib/binutils/config/acinclude.m4
diff --git a/contrib/bmake/ChangeLog b/contrib/bmake/ChangeLog
index b17fcb5..9d54c18 100644
--- a/contrib/bmake/ChangeLog
+++ b/contrib/bmake/ChangeLog
@@ -1,3 +1,35 @@
+2013-01-27 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Merge with NetBSD make, pick up
+ o make.1: more info on how shell commands are handled.
+ o job.c,main.c: detect write errors to job pipes.
+
+2013-01-25 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20130123
+ Merge with NetBSD make, pick up
+ o meta.c: if script uses .OODATE and meta_oodate() decides
+ rebuild is needed, .OODATE will be empty - set it to .ALLSRC.
+ o var.c: in debug output indicate which variabale modifiers
+ apply to.
+ o remove Check_Cwd logic the makefiles have been fixed.
+
+2012-12-12 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * makefile.in: add a simple makefile for folk who insist on
+ ./configure; make; make install
+ it just runs boot-strap
+ * include mk/* to accommodate the above
+ * boot-strap: re-work to accommodate the above
+ mksrc defaults to $Mydir/mk
+ allow op={configure,build,install,clean,all}
+ add options to facilitate install
+ * Makefile.config.in: just the bits set by configure
+ * Makefile: bump version to 20121212
+ abandon Makefile.in (NetBSD Makefile)
+ leverage mk/* instead
+ * configure.in: ensure srcdir is absolute
+
2012-11-11 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile.in (MAKE_VERSION): 20121111
diff --git a/contrib/bmake/FILES b/contrib/bmake/FILES
index e7c7861..b75cf1c 100644
--- a/contrib/bmake/FILES
+++ b/contrib/bmake/FILES
@@ -4,7 +4,9 @@ bmake.cat1
boot-strap
bsd.after-import.mk
os.sh
-Makefile.in
+makefile.in
+Makefile
+Makefile.config.in
PSD.doc/Makefile
PSD.doc/tutorial.ms
README
@@ -120,3 +122,63 @@ unit-tests/test.exp
unit-tests/unexport
unit-tests/unexport-env
unit-tests/varcmd
+mk/ChangeLog
+mk/FILES
+mk/README
+mk/auto.obj.mk
+mk/autoconf.mk
+mk/autodep.mk
+mk/auto.dep.mk
+mk/dep.mk
+mk/doc.mk
+mk/dpadd.mk
+mk/final.mk
+mk/host-target.mk
+mk/host.libnames.mk
+mk/inc.mk
+mk/init.mk
+mk/install-mk
+mk/java.mk
+mk/lib.mk
+mk/libnames.mk
+mk/libs.mk
+mk/links.mk
+mk/man.mk
+mk/mk-files.txt
+mk/nls.mk
+mk/obj.mk
+mk/options.mk
+mk/own.mk
+mk/prlist.mk
+mk/prog.mk
+mk/progs.mk
+mk/rst2htm.mk
+mk/scripts.mk
+mk/srctop.mk
+mk/subdir.mk
+mk/sys.mk
+mk/sys.clean-env.mk
+mk/sys.dependfile.mk
+mk/sys/AIX.mk
+mk/sys/Darwin.mk
+mk/sys/Generic.mk
+mk/sys/HP-UX.mk
+mk/sys/IRIX.mk
+mk/sys/Linux.mk
+mk/sys/NetBSD.mk
+mk/sys/OSF1.mk
+mk/sys/OpenBSD.mk
+mk/sys/SunOS.mk
+mk/sys/UnixWare.mk
+mk/target-flags.mk
+mk/warnings.mk
+mk/yacc.mk
+mk/dirdeps.mk
+mk/gendirdeps.mk
+mk/install-new.mk
+mk/meta2deps.py
+mk/meta2deps.sh
+mk/meta.sys.mk
+mk/meta.autodep.mk
+mk/meta.stage.mk
+mk/meta.subdir.mk
diff --git a/contrib/bmake/Makefile b/contrib/bmake/Makefile
new file mode 100644
index 0000000..3607326
--- /dev/null
+++ b/contrib/bmake/Makefile
@@ -0,0 +1,221 @@
+# $Id: Makefile,v 1.5 2013/01/28 19:31:58 sjg Exp $
+
+# Base version on src date
+MAKE_VERSION= 20130123
+
+PROG= bmake
+
+SRCS= \
+ arch.c \
+ buf.c \
+ compat.c \
+ cond.c \
+ dir.c \
+ for.c \
+ hash.c \
+ job.c \
+ main.c \
+ make.c \
+ make_malloc.c \
+ meta.c \
+ parse.c \
+ str.c \
+ strlist.c \
+ suff.c \
+ targ.c \
+ trace.c \
+ util.c \
+ var.c
+
+# from lst.lib/
+SRCS+= \
+ lstAppend.c \
+ lstAtEnd.c \
+ lstAtFront.c \
+ lstClose.c \
+ lstConcat.c \
+ lstDatum.c \
+ lstDeQueue.c \
+ lstDestroy.c \
+ lstDupl.c \
+ lstEnQueue.c \
+ lstFind.c \
+ lstFindFrom.c \
+ lstFirst.c \
+ lstForEach.c \
+ lstForEachFrom.c \
+ lstInit.c \
+ lstInsert.c \
+ lstIsAtEnd.c \
+ lstIsEmpty.c \
+ lstLast.c \
+ lstMember.c \
+ lstNext.c \
+ lstOpen.c \
+ lstPrev.c \
+ lstRemove.c \
+ lstReplace.c \
+ lstSucc.c
+
+# this file gets generated by configure
+.-include "Makefile.config"
+
+.if !empty(LIBOBJS)
+SRCS+= ${LIBOBJS:T:.o=.c}
+.endif
+
+# just in case
+prefix?= /usr
+srcdir?= ${.CURDIR}
+
+DEFAULT_SYS_PATH?= .../share/mk:${prefix}/share/mk
+
+CPPFLAGS+= -DUSE_META
+CFLAGS+= ${CPPFLAGS}
+CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"
+CFLAGS+= -I. -I${srcdir} ${XDEFS} -DMAKE_NATIVE
+CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}}
+COPTS.main.c+= "-DMAKE_VERSION=\"${MAKE_VERSION}\""
+
+# meta mode can be useful even without filemon
+FILEMON_H ?= /usr/include/dev/filemon/filemon.h
+.if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h"
+COPTS.meta.c += -DHAVE_FILEMON_H -I${FILEMON_H:H}
+.endif
+
+.PATH: ${srcdir}
+.PATH: ${srcdir}/lst.lib
+
+.if make(obj) || make(clean)
+SUBDIR+= unit-tests
+.endif
+
+# start-delete1 for bsd.after-import.mk
+# we skip a lot of this when building as part of FreeBSD etc.
+
+# list of OS's which are derrived from BSD4.4
+BSD44_LIST= NetBSD FreeBSD OpenBSD DragonFly
+# we are...
+OS!= uname -s
+# are we 4.4BSD ?
+isBSD44:=${BSD44_LIST:M${OS}}
+
+.if ${isBSD44} == ""
+MANTARGET= cat
+INSTALL?=${srcdir}/install-sh
+.if (${MACHINE} == "sun386")
+# even I don't have one of these anymore :-)
+CFLAGS+= -DPORTAR
+.elif (${MACHINE} != "sunos")
+SRCS+= sigcompat.c
+CFLAGS+= -DSIGNAL_FLAGS=SA_RESTART
+.endif
+.else
+MANTARGET?= man
+.endif
+
+# turn this on by default - ignored if we are root
+WITH_INSTALL_AS_USER=
+
+# supress with -DWITHOUT_*
+OPTIONS_DEFAULT_YES+= \
+ AUTOCONF_MK \
+ INSTALL_MK \
+ PROG_LINK
+
+OPTIONS_DEFAULT_NO+= \
+ PROG_VERSION
+
+# process options now
+.include <own.mk>
+
+.if ${MK_PROG_VERSION} == "yes"
+PROG_NAME= ${PROG}-${MAKE_VERSION}
+.if ${MK_PROG_LINK} == "yes"
+SYMLINKS+= ${PROG}-${MAKE_VERSION} ${BINDIR}/${PROG}
+.endif
+.endif
+
+EXTRACT_MAN=no
+# end-delete1
+
+MAN= ${PROG}.1
+MAN1= ${MAN}
+
+.if (${PROG} != "make")
+CLEANFILES+= my.history
+.if make(${MAN}) || !exists(${srcdir}/${MAN})
+my.history: ${MAKEFILE}
+ @(echo ".Nm"; \
+ echo "is derived from NetBSD"; \
+ echo ".Xr make 1 ."; \
+ echo "It uses autoconf to facilitate portability to other platforms."; \
+ echo ".Pp") > $@
+
+.NOPATH: ${MAN}
+${MAN}: make.1 my.history
+ @echo making $@
+ @sed -e 's/^.Nx/NetBSD/' -e '/^.Nm/s/make/${PROG}/' \
+ -e '/^.Sh HISTORY/rmy.history' \
+ -e '/^.Sh HISTORY/,$$s,^.Nm,make,' ${srcdir}/make.1 > $@
+
+all beforeinstall: ${MAN}
+_mfromdir=.
+.endif
+.endif
+
+MANTARGET?= cat
+MANDEST?= ${MANDIR}/${MANTARGET}1
+
+.if ${MANTARGET} == "cat"
+_mfromdir=${srcdir}
+.endif
+
+.include <prog.mk>
+
+CPPFLAGS+= -DMAKE_NATIVE -DHAVE_CONFIG_H
+COPTS.var.c += -Wno-cast-qual
+COPTS.job.c += -Wno-format-nonliteral
+COPTS.parse.c += -Wno-format-nonliteral
+COPTS.var.c += -Wno-format-nonliteral
+
+# Force these
+SHAREDIR= ${prefix}/share
+BINDIR= ${prefix}/bin
+MANDIR= ${SHAREDIR}/man
+
+.if !exists(.depend)
+${OBJS}: config.h
+.endif
+.if ${MK_AUTOCONF_MK} == "yes"
+.include <autoconf.mk>
+.endif
+
+# make sure that MAKE_VERSION gets updated.
+main.o: ${SRCS} ${MAKEFILE}
+
+# start-delete2 for bsd.after-import.mk
+SHARE_MK?=${SHAREDIR}/mk
+MKSRC=${srcdir}/mk
+INSTALL?=${srcdir}/install-sh
+
+.if ${MK_INSTALL_MK} == "yes"
+install: install-mk
+.endif
+
+beforeinstall:
+ test -d ${DESTDIR}${BINDIR} || ${INSTALL} -m 775 -d ${DESTDIR}${BINDIR}
+ test -d ${DESTDIR}${MANDEST} || ${INSTALL} -m 775 -d ${DESTDIR}${MANDEST}
+
+install-mk:
+.if exists(${MKSRC}/install-mk)
+ test -d ${DESTDIR}${SHARE_MK} || ${INSTALL} -m 775 -d ${DESTDIR}${SHARE_MK}
+ sh ${MKSRC}/install-mk -v -m 644 ${DESTDIR}${SHARE_MK}
+.else
+ @echo need to unpack mk.tar.gz under ${srcdir} or set MKSRC; false
+.endif
+# end-delete2
+
+# A simple unit-test driver to help catch regressions
+accept test:
+ cd ${.CURDIR}/unit-tests && MAKEFLAGS= ${.MAKE} -r -m / TEST_MAKE=${TEST_MAKE:U${.OBJDIR}/${PROG:T}} ${.TARGET}
diff --git a/contrib/bmake/Makefile.config.in b/contrib/bmake/Makefile.config.in
new file mode 100644
index 0000000..16ea66e
--- /dev/null
+++ b/contrib/bmake/Makefile.config.in
@@ -0,0 +1,16 @@
+# things set by configure
+
+prefix= @prefix@
+srcdir= @srcdir@
+CC?= @CC@
+MACHINE= @machine@
+MACHINE_ARCH= @machine_arch@
+DEFAULT_SYS_PATH= @default_sys_path@
+
+CPPFLAGS+= @CPPFLAGS@
+CFLAGS+= ${CPPFLAGS} @DEFS@
+LDFLAGS= @LDFLAGS@
+LIBOBJS= @LIBOBJS@
+LDADD= @LIBS@
+USE_META= @use_meta@
+FILEMON_H= @filemon_h@
diff --git a/contrib/bmake/Makefile.in b/contrib/bmake/Makefile.in
deleted file mode 100644
index 7936d3b..0000000
--- a/contrib/bmake/Makefile.in
+++ /dev/null
@@ -1,190 +0,0 @@
-# $NetBSD: Makefile,v 1.56 2012/05/30 21:54:23 sjg Exp $
-# @(#)Makefile 5.2 (Berkeley) 12/28/90
-
-# $Id: Makefile.in,v 1.178 2012/11/15 16:48:59 sjg Exp $
-
-PROG= bmake
-SRCS= arch.c buf.c compat.c cond.c dir.c for.c hash.c job.c main.c \
- make.c parse.c str.c suff.c targ.c trace.c var.c util.c
-SRCS+= strlist.c
-SRCS+= make_malloc.c
-SRCS+= lstAppend.c lstAtEnd.c lstAtFront.c lstClose.c lstConcat.c \
- lstDatum.c lstDeQueue.c lstDestroy.c lstDupl.c lstEnQueue.c \
- lstFind.c lstFindFrom.c lstFirst.c lstForEach.c lstForEachFrom.c \
- lstInit.c lstInsert.c lstIsAtEnd.c lstIsEmpty.c lstLast.c \
- lstMember.c lstNext.c lstOpen.c lstRemove.c lstReplace.c lstSucc.c
-SRCS += lstPrev.c
-
-# you can use this Makefile if you have an earlier version of bmake.
-prefix= @prefix@
-srcdir= @srcdir@
-CC?= @CC@
-
-# Base version on src date
-MAKE_VERSION= 20121111
-MACHINE=@machine@
-MACHINE_ARCH=@machine_arch@
-DEFAULT_SYS_PATH = @default_sys_path@
-
-CPPFLAGS+= @CPPFLAGS@
-CFLAGS+= ${CPPFLAGS}
-CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"
-CFLAGS+= -I. -I${srcdir} @DEFS@ ${XDEFS} -DMAKE_NATIVE
-CFLAGS+= ${CFLAGS_${.TARGET:T}}
-CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}}
-COPTS.main.c+= "-DMAKE_VERSION=\"${MAKE_VERSION}\""
-LDFLAGS= @LDFLAGS@
-LIBOBJS= @LIBOBJS@
-LDADD= @LIBS@
-
-.if !empty(LIBOBJS)
-SRCS+= ${LIBOBJS:T:.o=.c}
-.endif
-
-USE_META = @use_meta@
-.if ${USE_META} != "no"
-SRCS+= meta.c
-CPPFLAGS+= -DUSE_META
-FILEMON_H ?= @filemon_h@
-.if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h"
-COPTS.meta.c += -DHAVE_FILEMON_H -I${FILEMON_H:H}
-.endif
-.endif
-
-.PATH: ${srcdir}
-.PATH: ${srcdir}/lst.lib
-
-OS!= uname -s
-ARCH!= uname -p 2>/dev/null || uname -m
-
-# list of OS's which are derrived from BSD4.4
-isBSD44= NetBSD FreeBSD OpenBSD DragonFly
-
-.if ${OS} == "NetBSD"
-# Don't set these for anyone else since we don't know what the effect may be.
-# On FreeBSD WARNS=2 sets a bunch of -W flags that make does not handle.
-WFORMAT= 1
-WARNS=4
-.NOPATH: bmake.cat1
-.if make(install) && exists(${DESTDIR}/usr/share/doc)
-SUBDIR= PSD.doc
-.endif
-.endif
-
-.if defined(.PARSEDIR)
-# we cannot rely on anything but bmake to parse this correctly.
-.if empty(isBSD44:M${OS})
-MANTARGET=cat
-INSTALL?=${srcdir}/install-sh
-.if (${MACHINE} == "sun386")
-# even I don't have one of these anymore :-)
-CFLAGS+= -DPORTAR
-.elif (${MACHINE} != "sunos")
-SRCS+= sigcompat.c
-CFLAGS+= -DSIGNAL_FLAGS=SA_RESTART
-.endif
-.endif
-
-.if make(obj) || make(clean)
-SUBDIR+= unit-tests
-.endif
-.endif
-
-# many systems use gcc these days
-CC_IS_GCC=@GCC@
-.if ${CC_IS_GCC} == "yes"
-# problem with gcc3
-CFLAGS_var.o+= -Wno-cast-qual
-.endif
-
-CFLAGS_main.o+= "-D@force_machine@MACHINE=\"${MACHINE}\"" "-DMACHINE_ARCH=\"${MACHINE_ARCH}\""
-
-EXTRACT_MAN=no
-
-MAN=${PROG}.1
-.if (${PROG} != "make")
-my.history: ${MAKEFILE}
- @(echo ".Nm"; \
- echo "is derived from NetBSD"; \
- echo ".Xr make 1 ."; \
- echo "It uses autoconf to facilitate portability to other platforms."; \
- echo ".Pp") > $@
-
-${MAN}: make.1 my.history
- @echo making ${PROG}.1
- @sed -e 's/^.Nx/NetBSD/' -e '/^.Nm/s/make/${PROG}/' \
- -e '/^.Sh HISTORY/rmy.history' \
- -e '/^.Sh HISTORY/,$$s,^.Nm,make,' ${srcdir}/make.1 > $@
-
-.endif
-
-.if !empty(isBSD44:M${OS})
-.if "${OS}" != "NetBSD"
-MAN1=${MAN}
-.endif
-MANTARGET?=man
-.endif
-
-MANTARGET?= cat
-MANDEST?= ${MANDIR}/${MANTARGET}1
-
-.if ${MANTARGET} == "cat"
-_mfromdir=${srcdir}
-.endif
-
-.if exists(${srcdir}/../Makefile.inc)
-.include "${srcdir}/../Makefile.inc"
-.endif
-.-include <bsd.prog.mk>
-# sigh, FreeBSD at least includes bsd.subdir.mk via bsd.obj.mk
-# so the inclusion below, results in complaints about re-defined
-# targets. For NetBSD though we need to explicitly include it.
-.if defined(.PARSEDIR)
-.if defined(SUBDIR) && !target(${SUBDIR:[1]})
-.-include <bsd.subdir.mk>
-.endif
-.endif
-
-CPPFLAGS+= -DMAKE_NATIVE
-COPTS.var.c += -Wno-cast-qual
-COPTS.job.c += -Wno-format-nonliteral
-COPTS.parse.c += -Wno-format-nonliteral
-COPTS.var.c += -Wno-format-nonliteral
-
-# Force these
-BINDIR= ${prefix}/bin
-MANDIR= ${prefix}/man
-
-arch.o: config.h
-# make sure that MAKE_VERSION gets updated.
-main.o: ${SRCS} ${MAKEFILE}
-
-MK?=${prefix}/share/mk
-MKSRC?=@mksrc@
-INSTALL?=${srcdir}/install-sh
-
-beforeinstall:
- test -d ${DESTDIR}${BINDIR} || ${INSTALL} -m 775 -d ${DESTDIR}${BINDIR}
- test -d ${DESTDIR}${MANDEST} || ${INSTALL} -m 775 -d ${DESTDIR}${MANDEST}
-
-# latest version of *.mk includes an installer.
-# you should not need to set USE_OS
-install-mk:
-.if exists(${MKSRC}/install-mk)
- test -d ${DESTDIR}${MK} || ${INSTALL} -m 775 -d ${DESTDIR}${MK}
- ${MKSRC}/install-mk -v -m 644 ${DESTDIR}${MK} ${USE_OS}
-.else
- @echo need to unpack mk.tar.gz under ${srcdir} or set MKSRC; false
-.endif
-
-.ifdef TOOLDIR
-# this is a native netbsd build,
-# use libutil rather than the local emalloc etc.
-CPPFLAGS+= -DUSE_EMALLOC
-LDADD+=-lutil
-DPADD+=${LIBUTIL}
-.endif
-
-# A simple unit-test driver to help catch regressions
-accept test:
- cd ${.CURDIR}/unit-tests && MAKEFLAGS= ${.MAKE} -r -m / TEST_MAKE=${TEST_MAKE:U${.OBJDIR}/${PROG:T}} ${.TARGET}
diff --git a/contrib/bmake/bmake.1 b/contrib/bmake/bmake.1
index d7ed08a..82cec21 100644
--- a/contrib/bmake/bmake.1
+++ b/contrib/bmake/bmake.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.209 2012/10/08 15:09:48 christos Exp $
+.\" $NetBSD: make.1,v 1.210 2013/01/27 18:52:01 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
-.Dd October 8, 2012
+.Dd January 23, 2013
.Dt MAKE 1
.Os
.Sh NAME
@@ -468,6 +468,50 @@ except that the effect can be limited to a single line of a script.
A
.Ql Ic \-
causes any non-zero exit status of the command line to be ignored.
+.Pp
+When
+.Nm
+is run in jobs mode with
+.Fl j Ar max_jobs ,
+the entire script for the target is fed to a
+single instance of the shell.
+.Pp
+In compatibility (non-jobs) mode, each command is run in a separate process.
+If the command contains any shell meta characters
+.Pq Ql #=|^(){};&<>*?[]:$`\e\en
+it will be passed to the shell, otherwise
+.Nm
+will attempt direct execution.
+.Pp
+Since
+.Nm
+will
+.Xr chdir 2
+to
+.Ql Va .OBJDIR
+before executing any targets, each child process
+starts with that as its current working directory.
+.Pp
+Makefiles should be written so that the mode of
+.Nm
+operation does not change their behavior.
+For example, any command which needs to use
+.Dq cd
+or
+.Dq chdir ,
+without side-effect should be put in parenthesis:
+.Bd -literal -offset indent
+
+avoid-chdir-side-effects:
+ @echo Building $@ in `pwd`
+ @(cd ${.CURDIR} && ${.MAKE} $@)
+ @echo Back in `pwd`
+
+ensure-one-shell-regardless-of-mode:
+ @echo Building $@ in `pwd`; \\
+ (cd ${.CURDIR} && ${.MAKE} $@); \\
+ echo Back in `pwd`
+.Ed
.Sh VARIABLE ASSIGNMENTS
Variables in make are much like variables in the shell, and, by tradition,
consist of all upper-case letters.
@@ -2027,28 +2071,6 @@ NetBSD 5.0
so that they still appear to be variable expansions.
In particular this stops them being treated as syntax, and removes some
obscure problems using them in .if statements.
-.Pp
-Unlike other
-.Nm
-programs, this implementation by default executes all commands for a given
-target using a single shell invocation.
-This is done for both efficiency and to simplify error handling in remote
-command invocations.
-Typically this is transparent to the user, unless the target commands change
-the current working directory using
-.Dq cd
-or
-.Dq chdir .
-To be compatible with Makefiles that do this, one can use
-.Fl B
-to disable this behavior.
-.Pp
-In compatibility mode, each command is run in a separate process.
-If the command contains any shell meta characters
-.Pq Ql #=|^(){};&<>*?[]:$`\e\en
-it will be passed to the shell, otherwise
-.Nm
-will attempt direct execution.
.Sh SEE ALSO
.Xr mkdep 1
.Sh HISTORY
diff --git a/contrib/bmake/bmake.cat1 b/contrib/bmake/bmake.cat1
index 2d54ee2..7800726 100644
--- a/contrib/bmake/bmake.cat1
+++ b/contrib/bmake/bmake.cat1
@@ -284,6 +284,32 @@ SSHHEELLLL CCOOMMMMAANNDDSS
line of a script. A `--' causes any non-zero exit status of the command
line to be ignored.
+ When bbmmaakkee is run in jobs mode with --jj _m_a_x___j_o_b_s, the entire script for
+ the target is fed to a single instance of the shell.
+
+ In compatibility (non-jobs) mode, each command is run in a separate
+ process. If the command contains any shell meta characters
+ (`#=|^(){};&<>*?[]:$`\\n') it will be passed to the shell, otherwise
+ bbmmaakkee will attempt direct execution.
+
+ Since bbmmaakkee will chdir(2) to `_._O_B_J_D_I_R' before executing any targets, each
+ child process starts with that as its current working directory.
+
+ Makefiles should be written so that the mode of bbmmaakkee operation does not
+ change their behavior. For example, any command which needs to use
+ ``cd'' or ``chdir'', without side-effect should be put in parenthesis:
+
+
+ avoid-chdir-side-effects:
+ @echo Building $@ in `pwd`
+ @(cd ${.CURDIR} && ${.MAKE} $@)
+ @echo Back in `pwd`
+
+ ensure-one-shell-regardless-of-mode:
+ @echo Building $@ in `pwd`; \
+ (cd ${.CURDIR} && ${.MAKE} $@); \
+ echo Back in `pwd`
+
VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
Variables in make are much like variables in the shell, and, by tradi-
tion, consist of all upper-case letters.
@@ -1293,19 +1319,6 @@ CCOOMMPPAATTIIBBIILLIITTYY
stops them being treated as syntax, and removes some obscure problems
using them in .if statements.
- Unlike other bbmmaakkee programs, this implementation by default executes all
- commands for a given target using a single shell invocation. This is
- done for both efficiency and to simplify error handling in remote command
- invocations. Typically this is transparent to the user, unless the tar-
- get commands change the current working directory using ``cd'' or
- ``chdir''. To be compatible with Makefiles that do this, one can use --BB
- to disable this behavior.
-
- In compatibility mode, each command is run in a separate process. If the
- command contains any shell meta characters (`#=|^(){};&<>*?[]:$`\\n') it
- will be passed to the shell, otherwise bbmmaakkee will attempt direct execu-
- tion.
-
SSEEEE AALLSSOO
mkdep(1)
@@ -1327,4 +1340,4 @@ BBUUGGSS
There is no way of escaping a space character in a filename.
-NetBSD 5.1 October 8, 2012 NetBSD 5.1
+NetBSD 5.1 January 23, 2013 NetBSD 5.1
diff --git a/contrib/bmake/boot-strap b/contrib/bmake/boot-strap
index 660b766..7eff5f6 100755
--- a/contrib/bmake/boot-strap
+++ b/contrib/bmake/boot-strap
@@ -3,23 +3,52 @@
# boot-strap
#
# SYNOPSIS:
-# boot-strap [--"configure_arg" ... ][-s "srcdir"][-m "mksrc"]\\
-# ["prefix" ["bmakesrc" ["mksrc"]]]
+# boot-strap ["options"]
+# boot-strap --prefix=/opt --install
+# boot-strap --prefix=$HOME --install-host-target -DWITH_PROG_VERSION
+# boot-strap ["options"] op=build
+# boot-strap ["options"] op=install
#
# DESCRIPTION:
# This script is used to configure/build bmake it builds for
-# each OS in a subdir to keep the src clean.
-# On successful completion it echos commands to put the new
-# bmake binary into the /configs tree (if it exists)
-# (http://www.crufty.net/FreeWare/configs.html), $prefix/bin
-# and a suitable ~/*bin directory.
+# each host-target in a different subdir to keep the src clean.
+# There is no requirement for an existing make(1).
#
+# On successful completion if no '--install' flag is given,
+# it echos a command to do installation.
+#
+# The variable "op" defaults to 'all', and is affected by
+# '--install' flag as above.
+# Other values include:
+#
+# configure
+# Just run 'configure'
+#
+# build
+# If 'configure' has not been done, do it, then
+# run the build script, and finally 'test'.
+#
+# install
+# If 'build' has not been done, do it, 'test' then
+# install.
+#
+# clean
+# attempt to clean up
+#
+# test
+# run the unit-tests. Done automatically after 'build'
+# and before 'install'.
+#
+# The above are leveraged by a trivial makefile for the benefit
+# of those that have './configure; make; make install' baked
+# into them.
+#
# Options:
#
# -c "rc"
# Pick up settings from "rc".
# We look for '.bmake-boot-strap.rc' before processing
-# options.
+# options (unless SKIP_RC is set in environment).
#
# --share "share_dir"
# Where to put man pages and mk files.
@@ -28,9 +57,28 @@
#
# --mksrc "mksrc"
# Indicate where the mk files can be found.
-# Default is ./mk or ../mk, set to 'none' to force
-# building without "mksrc" but in that case a sys.mk
-# needs to exist in the default syspath ($share_dir/mk)
+# Default is $Mydir/mk
+#
+# --install
+# If build and test work, run bmake install.
+# BINDIR=$prefix/bin
+# SHAREDIR=$prefix/share
+#
+# --install-host-target
+# As for '--install' but BINDIR=$prefix/$HOST_TARGET/bin
+# This is useful when $prefix/ is shared by multiple
+# machines.
+#
+# Flags relevant when installing:
+#
+# -DWITHOUT_INSTALL_MK
+# Skip installing mk files.
+# By default they will be installed to $prefix/share/mk
+#
+# -DWITH_PROG_VERSION
+# Install 'bmake' as 'bmake-$MAKE_VERSION'
+# A symlink will be made as 'bmake' unless
+# -DWITHOUT_PROG_LINK is set.
#
# Possibly useful configure_args:
#
@@ -63,7 +111,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: boot-strap,v 1.39 2012/03/26 17:08:22 sjg Exp $
+# $Id: boot-strap,v 1.42 2013/01/25 20:20:33 sjg Exp $
#
# @(#) Copyright (c) 2001 Simon J. Gerraty
#
@@ -85,11 +133,10 @@ case "$Mydir" in
*) Mydir=`cd "$Mydir" && 'pwd'`;;
esac
-
Usage() {
[ "$1" ] && echo "ERROR: $@" >&2
echo "Usage:" >&2
- echo "$0 [--<configure_arg> ...][-s <srcdir>][-m <mksrc>][<prefix> [[<srcdir>] [<mksrc>]]]" >&2
+ echo "$0 [--<configure_arg> ...][<prefix>][--install]" >&2
exit 1
}
@@ -110,28 +157,55 @@ source_rc() {
done
}
+cmd_args="$@"
+
+# --install[-host-target] will set this
+INSTALL_PREFIX=
+# other things we pass to install step
+INSTALL_ARGS=
CONFIGURE_ARGS=
MAKESYSPATH=
# pick a useful default prefix (for me at least ;-)
for prefix in /opt/$HOST_TARGET "$HOME/$HOST_TARGET" /usr/pkg /usr/local ""
do
- [ -d "${prefix:-.}" ] && break
+ [ -d "${prefix:-.}" ] || continue
+ case "$prefix" in
+ */$HOST_TARGET)
+ p=`dirname $prefix`
+ if [ -d $p/share ]; then
+ INSTALL_BIN=$HOST_TARGET/bin
+ prefix=$p
+ fi
+ ;;
+ esac
+ echo "NOTE: default prefix=$prefix ${INSTALL_BIN:+INSTALL_BIN=$INSTALL_BIN}"
+ break
done
-srcdir=
-mksrc=
+srcdir=$Mydir
+mksrc=$Mydir/mk
objdir=
quiet=:
-source_rc .bmake-boot-strap.rc . "$Mydir/.." "$HOME"
+${SKIP_RC:+:} source_rc .bmake-boot-strap.rc . "$Mydir/.." "$HOME"
get_optarg() {
expr "x$1" : "x[^=]*=\\(.*\\)"
}
+here=`'pwd'`
+if [ $here = $Mydir ]; then
+ # avoid polution
+ OBJROOT=../
+fi
+
+op=all
+BMAKE=
+
while :
do
case "$1" in
--) shift; break;;
+ --help) sed -n -e "1d;/RCSid/,\$d" -e '/^#\.[a-z]/d' -e '/^#/s,^# *,,p' $0; exit 0;;
--prefix) prefix="$2"; shift;;
--prefix=*) prefix=`get_optarg "$1"`;;
--src=*) srcdir=`get_optarg "$1"`;;
@@ -144,6 +218,13 @@ do
--with-default-sys-path)
CONFIGURE_ARGS="$1 $2"
MAKESYSPATH="$2"; shift;;
+ --install) INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix};;
+ --install-host-target)
+ INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix}
+ INSTALL_BIN=$HOST_TARGET/bin;;
+ --install-destdir=*) INSTALL_DESTDIR=`get_optarg "$1"`;;
+ --install-prefix=*) INSTALL_PREFIX=`get_optarg "$1"`;;
+ -DWITH*) INSTALL_ARGS="$INSTALL_ARGS $1";;
-s|--src) srcdir="$2"; shift;;
-m|--mksrc) mksrc="$2"; shift;;
-o|--objdir) objdir="$2"; shift;;
@@ -261,7 +342,7 @@ none|-) # we don't want it
esac
# Ok, get to work...
-objdir="${objdir:-$OS}"
+objdir="${objdir:-$OBJROOT$HOST_TARGET}"
[ -d "$objdir" ] || mkdir -p "$objdir"
[ -d "$objdir" ] || mkdir "$objdir"
cd "$objdir" || exit 1
@@ -301,88 +382,80 @@ if [ "$mksrc" ]; then
export CFLAGS_MF CFLAGS_MD
fi
-$srcdir/configure $CONFIGURE_ARGS || exit 1
-chmod 755 make-bootstrap.sh || exit 1
-./make-bootstrap.sh || exit 1
-if [ -z "$MAKESYSPATH" ]; then
- add_path "${share_dir:-...}/mk" MAKESYSPATH
- case "$HOST_TARGET" in
- netbsd*) add_path /usr/share/mk MAKESYSPATH;;
- esac
-fi
-if [ -s "${mksrc:-/dev/null}/install-mk" ]; then
- sh "${mksrc}/install-mk" "$objdir/mk"
- case "$MAKESYSPATH" in
- .../mk*) ;;
- *) MAKESYSPATH=".../mk:${MAKESYSPATH}";;
- esac
-fi
+# this makes it easy to run the bmake we just built
+# the :tA dance is needed because 'pwd' and even /bin/pwd
+# may not give the same result as realpath().
+Bmake() {
+ (
+ cd $Mydir &&
+ MAKESYSPATH=$mksrc SRCTOP=$Mydir OBJTOP=$objdir \
+ MAKEOBJDIR='${.CURDIR:S,${SRCTOP:tA},${OBJTOP:tA},}' \
+ ${BMAKE:-$objdir/bmake} -f $Mydir/Makefile "$@"
+ )
+}
+
# make sure test below uses the same diff that configure did
TOOL_DIFF=`type diff | sed 's,[()],,g;s,^[^/][^/]*,,;q'`
-export MAKESYSPATH TOOL_DIFF
-if [ "$mksrc" ]; then
- $objdir/bmake test || exit 1
-else
- # assume nothing
- $objdir/bmake -r -m / test || exit 1
-fi
-# If -q given, we don't want all the install instructions
-$quiet exit 0
-
-make_version=`./bmake -r -m / -f ./Makefile -V MAKE_VERSION | ( read one two; echo $one )`
-bmake_version=bmake-$make_version
-
-if [ -s /usr/share/tmac/andoc.tmac ]; then
- # this should be ok
- man_subdir=man1
- man_src=$srcdir/bmake.1
-else
- # guess not
- man_subdir=cat1
- man_src=$srcdir/bmake.cat1
-fi
+export TOOL_DIFF
-install_prefix() {
- (
- bin_dir=
- share_dir=
- man_dir=
- mk_dir=
- while :
- do
- case "$1" in
- *=*) eval "$1"; shift;;
- *) break;;
- esac
- done
- bin_dir=${bin_dir:-$1/bin}
- share_dir=${share_dir:-`ShareDir "$1"`}
- man_dir=${man_dir:-$share_dir/man}
- mk_dir=${mk_dir:-$share_dir/mk}
- echo
- echo Commands to install into $1/
- echo
- echo mkdir -p $bin_dir
- echo cp $objdir/bmake $bin_dir/$bmake_version
- echo rm -f $bin_dir/bmake
- echo ln -s $bmake_version $bin_dir/bmake
- echo mkdir -p $man_dir/$man_subdir
- echo cp $man_src $man_dir/$man_subdir/bmake.1
- if [ "$mksrc" ]; then
- ev=`env | grep '_MK='`
- echo $ev sh $mksrc/install-mk $mk_dir
+op_configure() {
+ $srcdir/configure $CONFIGURE_ARGS || exit 1
+}
+
+op_build() {
+ [ -s make-bootstrap.sh ] || op_configure
+ chmod 755 make-bootstrap.sh || exit 1
+ ./make-bootstrap.sh || exit 1
+ case "$op" in
+ build) op_test;;
+ esac
+}
+
+op_test() {
+ [ -x bmake ] || op_build
+ Bmake test || exit 1
+}
+
+op_clean() {
+ if [ -x bmake ]; then
+ ln bmake bmake$$
+ BMAKE=$objdir/bmake$$ Bmake clean
+ rm -f bmake$$
+ elif [ $objdir != $srcdir ]; then
+ rm -rf *
fi
- )
}
-case "$prefix/" in
-"$HOME"/*) ;;
-*) CONFIGS=${CONFIGS:-/configs}
- [ -d $CONFIGS ] &&
- install_prefix mksrc= "$CONFIGS/$OS/$OSMAJOR.X/$MACHINE_ARCH$prefix"
- # I like to keep a copy here...
- install_prefix share_dir="$HOME/share" "$HOME/$HOST_TARGET"
- ;;
-esac
+op_install() {
+ op_test
+ case "$INSTALL_PREFIX,$INSTALL_BIN,$prefix" in
+ ,$HOST_TARGET/bin,*/$HOST_TARGET)
+ INSTALL_PREFIX=`dirname $prefix`
+ ;;
+ esac
+ INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix}
+ Bmake install prefix=$INSTALL_PREFIX BINDIR=$INSTALL_PREFIX/${INSTALL_BIN:-bin} ${INSTALL_DESTDIR:+DESTDIR=$INSTALL_DESTDIR} $INSTALL_ARGS || exit 1
+}
+
+op_all() {
+ rm -f make-bootstrap.sh bmake *.o
+ if [ -n "$INSTALL_PREFIX" ]; then
+ op_install
+ else
+ op_test
+ MAKE_VERSION=`sed -n '/^MAKE_VERSION/ { s,.*= *,,;p; }' $srcdir/Makefile`
+ echo You can install by running:
+ echo
+ echo $0 $cmd_args op=install
+ echo
+ echo "Use --install-prefix=/something to install somewhere other than $prefix"
+ echo "Use --install-destdir=/somewhere to set DESTDIR during install"
+ echo "Use --install-host-target to use INSTALL_BIN=$HOST_TARGET/bin"
+ echo "Use -DWITH_PROG_VERSION to install as bmake-$MAKE_VERSION"
+ echo "Use -DWITHOUT_PROG_LINK to supress bmake -> bmake-$MAKE_VERSION symlink"
+ echo "Use -DWITHOUT_INSTALL_MK to skip installing files to $prefix/share/mk"
+ fi
+}
-install_prefix "$prefix"
+op_$op
+exit 0
diff --git a/contrib/bmake/bsd.after-import.mk b/contrib/bmake/bsd.after-import.mk
index 6cd442a..85bd2c1 100644
--- a/contrib/bmake/bsd.after-import.mk
+++ b/contrib/bmake/bsd.after-import.mk
@@ -1,4 +1,4 @@
-# $Id: bsd.after-import.mk,v 1.9 2012/09/20 00:30:15 sjg Exp $
+# $Id: bsd.after-import.mk,v 1.11 2012/12/29 19:32:25 sjg Exp $
# This makefile is for use when integrating bmake into a BSD build
# system. Use this makefile after importing bmake.
@@ -48,36 +48,36 @@ DEFAULT_SYS_PATH= .../share/mk:/usr/share/mk
BOOTSTRAP_ARGS = \
--with-default-sys-path='${DEFAULT_SYS_PATH}' \
--prefix /usr \
- --share /usr/share \
- --mksrc none
+ --share /usr/share
+
# run boot-strap with minimal influence
bootstrap: ${BMAKE_SRC}/boot-strap ${MAKEFILE}
- HOME=/ ${BMAKE_SRC}/boot-strap ${BOOTSTRAP_ARGS} ${BOOTSTRAP_XTRAS}
+ HOME=/ ${BMAKE_SRC}/boot-strap -o ${HOST_OS} ${BOOTSTRAP_ARGS} ${BOOTSTRAP_XTRAS}
touch ${.TARGET}
# Makefiles need a little more tweaking than say config.h
MAKEFILE_SED = sed -e '/^MACHINE/d' \
-e '/^PROG/ { s,=,?=,;s,bmake,$${.CURDIR:T},; }' \
-e 's,^.-include,.sinclude,' \
+ -e '/^\..*include *</ { s,<,<bsd.,;/autoconf/d; }' \
-e 's,${SRCTOP},$${SRCTOP},g'
# These are the simple files we want to capture
-configured_files= config.h unit-tests/Makefile
+configured_files= config.h Makefile.config unit-tests/Makefile
after-import: bootstrap ${MAKEFILE}
-.for f in ${configured_files:N*Makefile}
+.for f in ${configured_files:M*.[ch]}
@echo Capturing $f
@mkdir -p ${${.CURDIR}/$f:L:H}
- @cmp -s ${.CURDIR}/$f ${HOST_OS}/$f || \
- cp ${HOST_OS}/$f ${.CURDIR}/$f
+ @(echo '/* $$${HOST_OS}$$ */'; cat ${HOST_OS}/$f) > ${.CURDIR}/$f
.endfor
-.for f in ${configured_files:M*Makefile}
+.for f in ${configured_files:M*Makefile*}
@echo Capturing $f
@mkdir -p ${${.CURDIR}/$f:L:H}
@(echo '# This is a generated file, do NOT edit!'; \
echo '# See ${_this:S,${SRCTOP}/,,}'; \
- echo '#'; echo '# $$${OS}$$'; echo; \
+ echo '#'; echo '# $$${HOST_OS}$$'; echo; \
echo 'SRCTOP?= $${.CURDIR:${${.CURDIR}/$f:L:H:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; echo; \
${MAKEFILE_SED} ${HOST_OS}/$f ) > ${.CURDIR}/$f
.endfor
@@ -87,18 +87,22 @@ _makefile: bootstrap ${MAKEFILE}
@echo Generating ${.CURDIR}/Makefile
@(echo '# This is a generated file, do NOT edit!'; \
echo '# See ${_this:S,${SRCTOP}/,,}'; \
- echo '#'; echo '# $$${OS}$$'; \
+ echo '#'; echo '# $$${HOST_OS}$$'; \
echo; echo '.sinclude "Makefile.inc"'; \
echo; echo 'SRCTOP?= $${.CURDIR:${.CURDIR:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; \
echo; echo '# look here first for config.h'; \
echo 'CFLAGS+= -I$${.CURDIR}'; echo; \
- ${MAKEFILE_SED} ${HOST_OS}/Makefile; \
+ echo '# for after-import'; \
+ echo 'CLEANDIRS+= ${HOST_OS}'; \
+ echo 'CLEANFILES+= bootstrap'; echo; \
+ ${MAKEFILE_SED} \
+ ${1 2:L:@n@-e '/start-delete$n/,/end-delete$n/d'@} \
+ ${BMAKE_SRC}/Makefile; \
echo; echo '# override some simple things'; \
echo 'BINDIR= /usr/bin'; \
echo 'MANDIR= ${MANDIR:U/usr/share/man}'; \
echo; echo '# make sure we get this'; \
echo 'CFLAGS+= $${COPTS.$${.IMPSRC:T}}'; \
- echo 'CLEANFILES+= bootstrap'; \
echo; echo 'after-import: ${_this:S,${SRCTOP},\${SRCTOP},}'; \
echo ' cd $${.CURDIR} && $${.MAKE} -f ${_this:S,${SRCTOP},\${SRCTOP},}'; \
echo ) > ${.TARGET}
diff --git a/contrib/bmake/compat.c b/contrib/bmake/compat.c
index 4cc699e..8f931cb 100644
--- a/contrib/bmake/compat.c
+++ b/contrib/bmake/compat.c
@@ -1,4 +1,4 @@
-/* $NetBSD: compat.c,v 1.90 2012/10/07 19:17:31 sjg Exp $ */
+/* $NetBSD: compat.c,v 1.91 2013/01/25 02:01:10 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: compat.c,v 1.90 2012/10/07 19:17:31 sjg Exp $";
+static char rcsid[] = "$NetBSD: compat.c,v 1.91 2013/01/25 02:01:10 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: compat.c,v 1.90 2012/10/07 19:17:31 sjg Exp $");
+__RCSID("$NetBSD: compat.c,v 1.91 2013/01/25 02:01:10 sjg Exp $");
#endif
#endif /* not lint */
#endif
@@ -377,7 +377,6 @@ again:
Fatal("Could not fork");
}
if (cpid == 0) {
- Check_Cwd(av);
Var_ExportVars();
#ifdef USE_META
if (useMeta) {
diff --git a/contrib/bmake/configure b/contrib/bmake/configure
index ee479f1..f79b26f 100755
--- a/contrib/bmake/configure
+++ b/contrib/bmake/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.64 for bmake 20120620.
+# Generated by GNU Autoconf 2.64 for bmake 20121212.
#
# Report bugs to <sjg@NetBSD.org>.
#
@@ -549,8 +549,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='bmake'
PACKAGE_TARNAME='bmake'
-PACKAGE_VERSION='20120620'
-PACKAGE_STRING='bmake 20120620'
+PACKAGE_VERSION='20121212'
+PACKAGE_STRING='bmake 20121212'
PACKAGE_BUGREPORT='sjg@NetBSD.org'
PACKAGE_URL=''
@@ -1220,7 +1220,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures bmake 20120620 to adapt to many kinds of systems.
+\`configure' configures bmake 20121212 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1281,7 +1281,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of bmake 20120620:";;
+ short | recursive ) echo "Configuration of bmake 20121212:";;
esac
cat <<\_ACEOF
@@ -1386,7 +1386,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-bmake configure 20120620
+bmake configure 20121212
generated by GNU Autoconf 2.64
Copyright (C) 2009 Free Software Foundation, Inc.
@@ -1907,7 +1907,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by bmake $as_me 20120620, which was
+It was created by bmake $as_me 20121212, which was
generated by GNU Autoconf 2.64. Invocation command line was
$ $0 $@
@@ -2257,6 +2257,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers config.h"
+case "$srcdir" in
+/*) ;;
+*) srcdir=`cd $srcdir && pwd`;;
+esac
+
# Check whether --with-defshell was given.
if test "${with_defshell+set}" = set; then :
@@ -5861,7 +5866,7 @@ fi
-ac_config_files="$ac_config_files Makefile make-bootstrap.sh unit-tests/Makefile"
+ac_config_files="$ac_config_files makefile Makefile.config make-bootstrap.sh unit-tests/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -6369,7 +6374,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by bmake $as_me 20120620, which was
+This file was extended by bmake $as_me 20121212, which was
generated by GNU Autoconf 2.64. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6429,7 +6434,7 @@ Report bugs to <sjg@NetBSD.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
-bmake config.status 20120620
+bmake config.status 20121212
configured by $0, generated by GNU Autoconf 2.64,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@@ -6544,7 +6549,8 @@ for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
- "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "makefile") CONFIG_FILES="$CONFIG_FILES makefile" ;;
+ "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;;
"make-bootstrap.sh") CONFIG_FILES="$CONFIG_FILES make-bootstrap.sh" ;;
"unit-tests/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/Makefile" ;;
diff --git a/contrib/bmake/configure.in b/contrib/bmake/configure.in
index 156034b9..0caafdf 100644
--- a/contrib/bmake/configure.in
+++ b/contrib/bmake/configure.in
@@ -1,12 +1,18 @@
dnl
dnl RCSid:
-dnl $Id: configure.in,v 1.45 2012/06/20 22:43:41 sjg Exp $
+dnl $Id: configure.in,v 1.46 2012/12/28 21:28:18 sjg Exp $
dnl
dnl Process this file with autoconf to produce a configure script
dnl
-AC_INIT([bmake], [20120620], [sjg@NetBSD.org])
+AC_INIT([bmake], [20121212], [sjg@NetBSD.org])
AC_CONFIG_HEADER(config.h)
+dnl make srcdir absolute
+case "$srcdir" in
+/*) ;;
+*) srcdir=`cd $srcdir && pwd`;;
+esac
+
dnl
AC_ARG_WITH(defshell,
[ --with-defshell=SHELL use SHELL by default - must be sh compatible, use sh or ksh to pick the internal definitions],
@@ -357,7 +363,7 @@ AC_SUBST(GCC)
AC_SUBST(diff_u)
AC_SUBST(use_meta)
AC_SUBST(filemon_h)
-AC_OUTPUT(Makefile make-bootstrap.sh unit-tests/Makefile)
+AC_OUTPUT(makefile Makefile.config make-bootstrap.sh unit-tests/Makefile)
cat <<EOF
diff --git a/contrib/bmake/job.c b/contrib/bmake/job.c
index 99e05d5..3049e60 100644
--- a/contrib/bmake/job.c
+++ b/contrib/bmake/job.c
@@ -1,4 +1,4 @@
-/* $NetBSD: job.c,v 1.163 2012/07/03 21:03:40 sjg Exp $ */
+/* $NetBSD: job.c,v 1.165 2013/01/26 15:52:59 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: job.c,v 1.163 2012/07/03 21:03:40 sjg Exp $";
+static char rcsid[] = "$NetBSD: job.c,v 1.165 2013/01/26 15:52:59 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: job.c,v 1.163 2012/07/03 21:03:40 sjg Exp $");
+__RCSID("$NetBSD: job.c,v 1.165 2013/01/26 15:52:59 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -490,7 +490,8 @@ JobCondPassSig(int signo)
static void
JobChildSig(int signo MAKE_ATTR_UNUSED)
{
- write(childExitJob.outPipe, CHILD_EXIT, 1);
+ while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN)
+ continue;
}
@@ -517,7 +518,9 @@ JobContinueSig(int signo MAKE_ATTR_UNUSED)
* Defer sending to SIGCONT to our stopped children until we return
* from the signal handler.
*/
- write(childExitJob.outPipe, DO_JOB_RESUME, 1);
+ while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 &&
+ errno == EAGAIN)
+ continue;
}
/*-
@@ -688,7 +691,6 @@ JobPrintCommand(void *cmdp, void *jobp)
char *escCmd = NULL; /* Command with quotes/backticks escaped */
char *cmd = (char *)cmdp;
Job *job = (Job *)jobp;
- char *cp, *tmp;
int i, j;
noSpecials = NoExecute(job->node);
@@ -860,11 +862,6 @@ JobPrintCommand(void *cmdp, void *jobp)
job->flags |= JOB_TRACED;
}
- if ((cp = Check_Cwd_Cmd(cmd)) != NULL) {
- DBPRINTF("test -d %s && ", cp);
- DBPRINTF("cd %s\n", cp);
- }
-
DBPRINTF(cmdTemplate, cmd);
free(cmdStart);
if (escCmd)
@@ -884,10 +881,6 @@ JobPrintCommand(void *cmdp, void *jobp)
if (shutUp && commandShell->hasEchoCtl) {
DBPRINTF("%s\n", commandShell->echoOn);
}
- if (cp != NULL) {
- DBPRINTF("test -d %s && ", cp);
- DBPRINTF("cd %s\n", Var_Value(".OBJDIR", VAR_GLOBAL, &tmp));
- }
return 0;
}
@@ -1185,7 +1178,8 @@ Job_Touch(GNode *gn, Boolean silent)
*/
if (read(streamID, &c, 1) == 1) {
(void)lseek(streamID, (off_t)0, SEEK_SET);
- (void)write(streamID, &c, 1);
+ while (write(streamID, &c, 1) == -1 && errno == EAGAIN)
+ continue;
}
(void)close(streamID);
@@ -2074,7 +2068,8 @@ Job_CatchOutput(void)
if (nready < 0 || readyfd(&childExitJob)) {
char token = 0;
nready -= 1;
- (void)read(childExitJob.inPipe, &token, 1);
+ while (read(childExitJob.inPipe, &token, 1) == -1 && errno == EAGAIN)
+ continue;
if (token == DO_JOB_RESUME[0])
/* Complete relay requested from our SIGCONT handler */
JobRestartJobs();
@@ -2805,7 +2800,8 @@ JobTokenAdd(void)
if (DEBUG(JOB))
fprintf(debug_file, "(%d) aborting %d, deposit token %c\n",
getpid(), aborting, JOB_TOKENS[aborting]);
- write(tokenWaitJob.outPipe, &tok, 1);
+ while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
+ continue;
}
/*-
@@ -2918,13 +2914,15 @@ Job_TokenWithdraw(void)
while (read(tokenWaitJob.inPipe, &tok1, 1) == 1)
continue;
/* And put the stopper back */
- write(tokenWaitJob.outPipe, &tok, 1);
+ while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
+ continue;
Fatal("A failure has been detected in another branch of the parallel make");
}
if (count == 1 && jobTokensRunning == 0)
/* We didn't want the token really */
- write(tokenWaitJob.outPipe, &tok, 1);
+ while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
+ continue;
jobTokensRunning++;
if (DEBUG(JOB))
diff --git a/contrib/bmake/main.c b/contrib/bmake/main.c
index 0b177bb..f4bd721 100644
--- a/contrib/bmake/main.c
+++ b/contrib/bmake/main.c
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.203 2012/08/31 07:00:36 sjg Exp $ */
+/* $NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,7 +69,7 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: main.c,v 1.203 2012/08/31 07:00:36 sjg Exp $";
+static char rcsid[] = "$NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
@@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
#if 0
static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: main.c,v 1.203 2012/08/31 07:00:36 sjg Exp $");
+__RCSID("$NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -176,9 +176,6 @@ Boolean varNoExportEnv; /* -X flag */
Boolean doing_depend; /* Set while reading .depend */
static Boolean jobsRunning; /* TRUE if the jobs might be running */
static const char * tracefile;
-#ifndef NO_CHECK_MAKE_CHDIR
-static char * Check_Cwd_av(int, char **, int);
-#endif
static void MainParseArgs(int, char **);
static int ReadMakefile(const void *, const void *);
static void usage(void) MAKE_ATTR_DEAD;
@@ -1204,10 +1201,6 @@ main(int argc, char **argv)
Main_ExportMAKEFLAGS(TRUE); /* initial export */
-#ifndef NO_CHECK_MAKE_CHDIR
- Check_Cwd_av(0, NULL, 0); /* initialize it */
-#endif
-
/*
* For compatibility, look at the directories in the VPATH variable
* and add them to the search path, if the variable is defined. The
@@ -1423,208 +1416,6 @@ found:
}
-/*
- * If MAKEOBJDIRPREFIX is in use, make ends up not in .CURDIR
- * in situations that would not arrise with ./obj (links or not).
- * This tends to break things like:
- *
- * build:
- * ${MAKE} includes
- *
- * This function spots when ${.MAKE:T} or ${.MAKE} is a command (as
- * opposed to an argument) in a command line and if so returns
- * ${.CURDIR} so caller can chdir() so that the assumptions made by
- * the Makefile hold true.
- *
- * If ${.MAKE} does not contain any '/', then ${.MAKE:T} is skipped.
- *
- * The chdir() only happens in the child process, and does nothing if
- * MAKEOBJDIRPREFIX and MAKEOBJDIR are not in the environment so it
- * should not break anything. Also if NOCHECKMAKECHDIR is set we
- * do nothing - to ensure historic semantics can be retained.
- */
-#ifdef NO_CHECK_MAKE_CHDIR
-char *
-Check_Cwd_Cmd(cmd)
- char *cmd;
-{
- return 0;
-}
-
-void
-Check_Cwd(argv)
- char **argv;
-{
- return;
-}
-
-#else
-
-static int Check_Cwd_Off = 0;
-
-static char *
-Check_Cwd_av(int ac, char **av, int copy)
-{
- static char *make[4];
- static char *cur_dir = NULL;
- char **mp;
- char *cp;
- int is_cmd, next_cmd;
- int i;
- int n;
-
- if (Check_Cwd_Off) {
- if (DEBUG(CWD))
- fprintf(debug_file, "check_cwd: check is off.\n");
- return NULL;
- }
-
- if (make[0] == NULL) {
- if (Var_Exists("NOCHECKMAKECHDIR", VAR_GLOBAL)) {
- Check_Cwd_Off = 1;
- if (DEBUG(CWD))
- fprintf(debug_file, "check_cwd: turning check off.\n");
- return NULL;
- }
-
- make[1] = Var_Value(".MAKE", VAR_GLOBAL, &cp);
- if ((make[0] = strrchr(make[1], '/')) == NULL) {
- make[0] = make[1];
- make[1] = NULL;
- } else
- ++make[0];
- make[2] = NULL;
- cur_dir = Var_Value(".CURDIR", VAR_GLOBAL, &cp);
- }
- if (ac == 0 || av == NULL) {
- if (DEBUG(CWD))
- fprintf(debug_file, "check_cwd: empty command.\n");
- return NULL; /* initialization only */
- }
-
- if (getenv("MAKEOBJDIR") == NULL &&
- getenv("MAKEOBJDIRPREFIX") == NULL) {
- if (DEBUG(CWD))
- fprintf(debug_file, "check_cwd: no obj dirs.\n");
- return NULL;
- }
-
-
- next_cmd = 1;
- for (i = 0; i < ac; ++i) {
- is_cmd = next_cmd;
-
- n = strlen(av[i]);
- cp = &(av[i])[n - 1];
- if (strspn(av[i], "|&;") == (size_t)n) {
- next_cmd = 1;
- continue;
- } else if (*cp == ';' || *cp == '&' || *cp == '|' || *cp == ')') {
- next_cmd = 1;
- if (copy) {
- do {
- *cp-- = '\0';
- } while (*cp == ';' || *cp == '&' || *cp == '|' ||
- *cp == ')' || *cp == '}') ;
- } else {
- /*
- * XXX this should not happen.
- */
- fprintf(stderr, "%s: WARNING: raw arg ends in shell meta '%s'\n",
- progname, av[i]);
- }
- } else
- next_cmd = 0;
-
- cp = av[i];
- if (*cp == ';' || *cp == '&' || *cp == '|')
- is_cmd = 1;
-
- if (DEBUG(CWD))
- fprintf(debug_file, "av[%d] == %s '%s'",
- i, (is_cmd) ? "cmd" : "arg", av[i]);
- if (is_cmd != 0) {
- if (*cp == '(' || *cp == '{' ||
- *cp == ';' || *cp == '&' || *cp == '|') {
- do {
- ++cp;
- } while (*cp == '(' || *cp == '{' ||
- *cp == ';' || *cp == '&' || *cp == '|');
- if (*cp == '\0') {
- next_cmd = 1;
- continue;
- }
- }
- if (strcmp(cp, "cd") == 0 || strcmp(cp, "chdir") == 0) {
- if (DEBUG(CWD))
- fprintf(debug_file, " == cd, done.\n");
- return NULL;
- }
- for (mp = make; *mp != NULL; ++mp) {
- n = strlen(*mp);
- if (strcmp(cp, *mp) == 0) {
- if (DEBUG(CWD))
- fprintf(debug_file, " %s == '%s', chdir(%s)\n",
- cp, *mp, cur_dir);
- return cur_dir;
- }
- }
- }
- if (DEBUG(CWD))
- fprintf(debug_file, "\n");
- }
- return NULL;
-}
-
-char *
-Check_Cwd_Cmd(const char *cmd)
-{
- char *cp, *bp;
- char **av;
- int ac;
-
- if (Check_Cwd_Off)
- return NULL;
-
- if (cmd) {
- av = brk_string(cmd, &ac, TRUE, &bp);
- if (DEBUG(CWD))
- fprintf(debug_file, "splitting: '%s' -> %d words\n",
- cmd, ac);
- } else {
- ac = 0;
- av = NULL;
- bp = NULL;
- }
- cp = Check_Cwd_av(ac, av, 1);
- if (bp)
- free(bp);
- if (av)
- free(av);
- return cp;
-}
-
-void
-Check_Cwd(const char **argv)
-{
- char *cp;
- int ac;
-
- if (Check_Cwd_Off)
- return;
-
- for (ac = 0; argv[ac] != NULL; ++ac)
- /* NOTHING */;
- if (ac == 3 && *argv[1] == '-') {
- cp = Check_Cwd_Cmd(argv[2]);
- } else {
- cp = Check_Cwd_av(ac, UNCONST(argv), 0);
- }
- if (cp) {
- chdir(cp);
- }
-}
-#endif /* NO_CHECK_MAKE_CHDIR */
/*-
* Cmd_Exec --
@@ -1952,7 +1743,8 @@ execError(const char *af, const char *av)
IOADD(")\n");
#ifdef USE_IOVEC
- (void)writev(2, iov, 8);
+ while (writev(2, iov, 8) == -1 && errno == EAGAIN)
+ continue;
#endif
}
diff --git a/contrib/bmake/make-bootstrap.sh.in b/contrib/bmake/make-bootstrap.sh.in
index d9ff9ff..70d7e2b 100755
--- a/contrib/bmake/make-bootstrap.sh.in
+++ b/contrib/bmake/make-bootstrap.sh.in
@@ -13,7 +13,7 @@ esac
CC="@CC@"
CFLAGS="@CFLAGS@ -I. -I${srcdir} @DEFS@ @CPPFLAGS@ -DMAKE_NATIVE ${XDEFS}"
-MAKE_VERSION=`sed -n '/^MAKE_VERSION=/s,.*=[^0-9]*,,p' Makefile`
+MAKE_VERSION=`sed -n '/^MAKE_VERSION=/s,.*=[^0-9]*,,p' $srcdir/Makefile`
MDEFS="-DMAKE_VERSION=\"$MAKE_VERSION\" \
-D@force_machine@MACHINE=\"@machine@\" -DMACHINE_ARCH=\"@machine_arch@\" \
diff --git a/contrib/bmake/make.1 b/contrib/bmake/make.1
index 702e478..198410c 100644
--- a/contrib/bmake/make.1
+++ b/contrib/bmake/make.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.209 2012/10/08 15:09:48 christos Exp $
+.\" $NetBSD: make.1,v 1.210 2013/01/27 18:52:01 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
-.Dd October 8, 2012
+.Dd January 23, 2013
.Dt MAKE 1
.Os
.Sh NAME
@@ -468,6 +468,50 @@ except that the effect can be limited to a single line of a script.
A
.Ql Ic \-
causes any non-zero exit status of the command line to be ignored.
+.Pp
+When
+.Nm
+is run in jobs mode with
+.Fl j Ar max_jobs ,
+the entire script for the target is fed to a
+single instance of the shell.
+.Pp
+In compatibility (non-jobs) mode, each command is run in a separate process.
+If the command contains any shell meta characters
+.Pq Ql #=|^(){};&<>*?[]:$`\e\en
+it will be passed to the shell, otherwise
+.Nm
+will attempt direct execution.
+.Pp
+Since
+.Nm
+will
+.Xr chdir 2
+to
+.Ql Va .OBJDIR
+before executing any targets, each child process
+starts with that as its current working directory.
+.Pp
+Makefiles should be written so that the mode of
+.Nm
+operation does not change their behavior.
+For example, any command which needs to use
+.Dq cd
+or
+.Dq chdir ,
+without side-effect should be put in parenthesis:
+.Bd -literal -offset indent
+
+avoid-chdir-side-effects:
+ @echo Building $@ in `pwd`
+ @(cd ${.CURDIR} && ${.MAKE} $@)
+ @echo Back in `pwd`
+
+ensure-one-shell-regardless-of-mode:
+ @echo Building $@ in `pwd`; \\
+ (cd ${.CURDIR} && ${.MAKE} $@); \\
+ echo Back in `pwd`
+.Ed
.Sh VARIABLE ASSIGNMENTS
Variables in make are much like variables in the shell, and, by tradition,
consist of all upper-case letters.
@@ -2027,28 +2071,6 @@ The way that .for loop variables are substituted changed after
so that they still appear to be variable expansions.
In particular this stops them being treated as syntax, and removes some
obscure problems using them in .if statements.
-.Pp
-Unlike other
-.Nm
-programs, this implementation by default executes all commands for a given
-target using a single shell invocation.
-This is done for both efficiency and to simplify error handling in remote
-command invocations.
-Typically this is transparent to the user, unless the target commands change
-the current working directory using
-.Dq cd
-or
-.Dq chdir .
-To be compatible with Makefiles that do this, one can use
-.Fl B
-to disable this behavior.
-.Pp
-In compatibility mode, each command is run in a separate process.
-If the command contains any shell meta characters
-.Pq Ql #=|^(){};&<>*?[]:$`\e\en
-it will be passed to the shell, otherwise
-.Nm
-will attempt direct execution.
.Sh SEE ALSO
.Xr mkdep 1
.Sh HISTORY
diff --git a/contrib/bmake/makefile.in b/contrib/bmake/makefile.in
new file mode 100644
index 0000000..03b980a
--- /dev/null
+++ b/contrib/bmake/makefile.in
@@ -0,0 +1,14 @@
+# $Id: makefile.in,v 1.1 2012/12/28 21:28:19 sjg Exp $
+
+# a simple makefile for those who don't like anything beyond:
+# ./configure; make; make install
+
+prefix= @prefix@
+srcdir= @srcdir@
+
+all: build
+
+build clean install test:
+ ${srcdir}/boot-strap --prefix=${prefix} -o . op=$@
+
+
diff --git a/contrib/bmake/meta.c b/contrib/bmake/meta.c
index 77af4e8..d6110d9 100644
--- a/contrib/bmake/meta.c
+++ b/contrib/bmake/meta.c
@@ -1,4 +1,4 @@
-/* $NetBSD: meta.c,v 1.25 2012/06/27 17:22:58 sjg Exp $ */
+/* $NetBSD: meta.c,v 1.26 2013/01/19 04:23:37 sjg Exp $ */
/*
* Implement 'meta' mode.
@@ -843,7 +843,7 @@ meta_oodate(GNode *gn, Boolean oodate)
static size_t cwdlen = 0;
static size_t tmplen = 0;
FILE *fp;
- Boolean ignoreOODATE = FALSE;
+ Boolean needOODATE = FALSE;
Lst missingFiles;
if (oodate)
@@ -1197,15 +1197,15 @@ meta_oodate(GNode *gn, Boolean oodate)
} else {
char *cmd = (char *)Lst_Datum(ln);
- if (!ignoreOODATE) {
+ if (!needOODATE) {
if (strstr(cmd, "$?"))
- ignoreOODATE = TRUE;
+ needOODATE = TRUE;
else if ((cp = strstr(cmd, ".OODATE"))) {
/* check for $[{(].OODATE[)}] */
if (cp > cmd + 2 && cp[-2] == '$')
- ignoreOODATE = TRUE;
+ needOODATE = TRUE;
}
- if (ignoreOODATE && DEBUG(META))
+ if (needOODATE && DEBUG(META))
fprintf(debug_file, "%s: %d: cannot compare commands using .OODATE\n", fname, lineno);
}
cmd = Var_Subst(NULL, cmd, gn, TRUE);
@@ -1235,7 +1235,7 @@ meta_oodate(GNode *gn, Boolean oodate)
if (buf[x - 1] == '\n')
buf[x - 1] = '\0';
}
- if (!ignoreOODATE &&
+ if (!needOODATE &&
!(gn->type & OP_NOMETA_CMP) &&
strcmp(p, cmd) != 0) {
if (DEBUG(META))
@@ -1279,14 +1279,16 @@ meta_oodate(GNode *gn, Boolean oodate)
oodate = TRUE;
}
}
- if (oodate && ignoreOODATE) {
+ if (oodate && needOODATE) {
/*
- * Target uses .OODATE, so we need to re-compute it.
- * We need to clean up what Make_DoAllVar() did.
+ * Target uses .OODATE which is empty; or we wouldn't be here.
+ * We have decided it is oodate, so .OODATE needs to be set.
+ * All we can sanely do is set it to .ALLSRC.
*/
- Var_Delete(ALLSRC, gn);
Var_Delete(OODATE, gn);
- gn->flags &= ~DONE_ALLSRC;
+ Var_Set(OODATE, Var_Value(ALLSRC, gn, &cp), gn, 0);
+ if (cp)
+ free(cp);
}
return oodate;
}
diff --git a/contrib/bmake/mk/ChangeLog b/contrib/bmake/mk/ChangeLog
new file mode 100644
index 0000000..fee1c90
--- /dev/null
+++ b/contrib/bmake/mk/ChangeLog
@@ -0,0 +1,644 @@
+2013-01-23 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20130123
+ * meta.stage.mk: add stage_links (hard links).
+ if doing hard links, we add dest to link as well.
+ Default the stage dir for [sym]links to STAGE_OBJTOP since
+ these are typically specified as absolute paths.
+ Add -m "mode" flag to StageFiles and StageAs.
+
+2012-11-11 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20121111
+ * autoconf.mk: avoid meta mode seeing changed commands for config.status
+ * meta.autodep.mk: pass resolved MAKESYSPATH to gendirdeps
+ in case we were found via .../mk
+ * sys.clean-env.mk: move it from examples, we and others use it
+ "as is".
+ * FILES: add srctop.mk and options.mk
+ * own.mk: convert to using options.mk
+ which is modeled after FreeBSD's handling of MK_*
+ but more flexible.
+ This allows MK_* for boolean knobs to not be confused
+ with MK* which can be commands.
+
+ * examples/sys.clean-env.mk: add WITH[OUT]_ to
+ MAKE_ENV_SAVE_PREFIX_LIST.
+ Mention that HOME=/var/empty might be a good idea.
+
+2012-11-08 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * sys.dependfile.mk: if not depend file exists, $MACHINE
+ specific ones are supported but not the default,
+ check if any exist and follow suit.
+
+2012-11-06 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20121106
+
+2012-11-05 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * import latest dirdeps.mk and meta2deps.py from Juniper.
+ * progs.mk: add MAN and CXXFLAGS to PROG_VARS
+ also add PROGS_TARGETS and pass on PROG_CXX if it seems
+ appropriate.
+
+2012-11-04 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.stage.mk: update CLEANFILES
+ remove redundant cp of .dirdep from STAGE_AS_SCRIPT.
+ * progs.mk: Add LDADD to PROG_VARS
+
+2012-10-12 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.stage.mk (STAGE_DIR_FILTER): track dirs we stage to in
+ _STAGED_DIRS so that these can be turned into filters for
+ GENDIRDEPS_FILTER.
+
+2012-10-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20121010
+ * meta.stage.mk (STAGE_DIRDEP_SCRIPT): check that an existing
+ target.dirdep matches .dirdep
+
+2012-08-08 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20120808
+ * import latest meta2deps.py from Juniper.
+
+2012-07-11 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20120711
+ * dep.mk: add explicit dependencies on SRCS after applying
+ SRCS_DEP_FILTER
+ * meta.autodep.mk: add explicit dependencies on SRCS after
+ applying SRCS_DEP_FILTER
+ * meta.autodep.mk: ensure GENDIRDEPS_FILTER is exported if needed.
+
+2012-06-26 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20120626
+ * meta.sys.mk: ignore PYTHON if it does not exist
+ compare ${.MAKE.DEPENDFILE:E} against ${MACHINE} is more reliable.
+ * meta.stage.mk: examine .MAKE.DEPENDFILE_PREFERENCE for any
+ entries ending in .${MACHINE} to decide if qualified _dirdep is
+ needed.
+ * gendirdeps.mk: only produce unqualified deps if no
+ .MAKE.DEPENDFILE_PREFERENCE ends in .${MACHINE}
+ * meta.subdir.mk: apply SUBDIREPS_FILTER
+
+2012-04-20 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20120420
+ * add sys.dependfile.mk so we can experiment with
+ .MAKE.DEPENDFILE_PREFERENCE
+ * meta.autodep.mk: _DEPENDFILE is precious!
+
+2012-03-15 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20120315
+ * install-new.mk: avoid being interrupted
+
+2012-02-26 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * man.mk: MAN might have multiple values so be careful with exists().
+
+2012-01-19 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20120112
+ * fix examples/sys.clean-env.mk so that MAKEOBJDIR is handled
+ as: MAKEOBJDIR='${.CURDIR:S,${SRCTOP},${OBJTOP},}'
+
+2011-12-03 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20111201
+ * import dirdeps.mk from Juniper sjg@
+ o more consistent handling of DEP_MACHINE, especially when
+ dealing with an odd Makefile.depend, when normally using
+ Makefile.depend.${MACHINE}
+
+2011-11-22 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20111122
+ * meta.autodep.mk: add some debug output, be more crisp about
+ updating. Use ${.ALLTARGETS:M*.o} as a clue for .depend
+
+2011-11-13 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20111111
+ it's too cool to miss
+ * import meta* updates from Juniper sjg@
+ o dirdeps.mk set DEP_MACHINE for Makefile.depend (when we are
+ normally using Makefile.depend.${MACHINE}), handy for
+ read-only manually maintained dependencies.
+ o meta2deps.py add a clear 'ERROR:' token if an exception is raised.
+ o gendirdeps.mk if ERROR: from meta2deps.py do not update
+ anything.
+
+2011-10-30 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-new.mk separate the cmp and copy logic to its own function.
+
+2011-10-28 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20111028
+ * sys.mk: include auto.obj.mk if MKOBJDIRS is set to auto
+ * subdir.mk: ensure _SUBDIRUSE is provided
+ * meta.autodep.mk: remove dependency of gendirdeps.mk on auto.obj.mk
+ * meta.subdir.mk: always allow for Makefile.depend
+
+2011-10-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20111010
+ o minor tweak to *dirdeps.mk from Juniper sjg@
+
+2011-10-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20111001
+ o add meta2deps.py from Juniper sjg@
+ o tweak gendirdeps.mk to work with meta2deps.py when not
+ cross-building
+ * autoconf.mk: add autoconf-input as a hook for regenerating
+ AUTOCONF_INPUTS (configure).
+
+2011-08-24 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.autodep.mk: if we do not have OBJS, .depend isn't a useful
+ trigger for updating Makefile.depend*
+
+2011-08-08 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20110808
+ * obj.mk: minor cleanup
+ * auto.obj.mk: improve description of Mkdirs and honor NO_OBJ too.
+
+2011-08-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * auto.obj.mk (.OBJDIR): throw an error if we cannot use the
+ specified dir.
+
+2011-06-28 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.autodep.mk: if XMAKE_META_FILE is set
+ the makefile uses a foreign make, and so dependencies
+ can only be gathered from a clean tree build.
+
+2011-06-24 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20110622
+ * meta.autodep.mk: improve bootstraping
+
+2011-06-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * yacc.mk: handle the corner case of .c being removed
+ while .h remains.
+
+2011-06-08 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * yacc.mk: do .y.h and .y.c separately
+
+2011-06-04 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20110606
+ * don't store SRC_DIRDEPS in Makefile.depend* by default
+ not everyone needs it.
+
+2011-05-04 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20110505
+ first release including meta mode makefiles
+
+2011-05-02 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.stage.mk: add STAGE_AS_SETS and stage_as
+ for things that need to be staged with different names.
+
+2011-05-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.stage.mk: add notion of STAGE_SETS
+ so a makefile can stage to multiple dirs
+
+2011-04-03 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * rst2htm.mk: convert rst to s5 (slides) or plain html depending
+ on target name.
+
+2011-03-30 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20110330
+
+2011-03-29 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * sys.mk (_DEBUG_MAKE_FLAGS): use indirection so that DEBUG_MAKE_FLAGS0
+ can be used to debug level 0 only and DEBUG_MAKE_FLAGS for the rest.
+ * sys.mk: re-define M_whence in terms of M_type.
+ M_type is useful for checking if something is a builtin.
+
+2011-03-16 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.stage.mk: add stage_symlinks and leverage StageLinks for
+ stage_libs
+
+2011-03-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * dirdeps.mk: correct value for _depdir_files depends on
+ .MAKE.DEPENDFILE
+ Add our copyright - just to make it clear we have frobbed this
+ quite a bit.
+ DEP_MACHINE needs to be set to MACHINE each time, if using only
+ Makefile.depend (cf. Makefile.depend.${MACHINE})
+
+ * meta.stage.mk: meta mode version of staging
+
+ * init.mk, final.mk: include local.*.mk to simplify customization
+
+2011-03-03 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * auto.obj.mk: just because we are doing mk destroy, we should
+ still set .OBJDIR correctly if it exists.
+
+ * install-mk (mksrc): do not exclude meta.sys.mk
+
+2011-03-01 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * host-target.mk: set/export _HOST_ARCH etc separately,
+ catch junk resulting from uname -p, so we can find sys/Linux.mk
+ correctly.
+
+2011-02-18 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.sys.mk: throw an error if /dev/filemon is missing and we
+ expected to be updating Makefile.depend*
+
+2011-02-14 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20110214
+ * meta.subdir.mk: add support for -DBOOTSTRAP_DEPENDFILES
+
+2010-09-25 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * meta.sys.mk: not valid for older bmake
+
+2010-09-24 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20100919
+ include dirdeps.mk et al from Juniper Networks,
+ for meta mode - requires filemon(9).
+ * sys.mk, subdir.mk: Add hooks for meta mode.
+ we do this as meta.sys.mk, meta.autodep.mk and meta.subdir.mk
+ to make turning it on/off simple.
+
+2010-06-16 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20100616
+ * fix typo in sys.mk
+
+2010-06-12 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20100612
+ * lib.mk: remove duplicate addition to SOBJS
+
+2010-06-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * sys.mk: Add a means of selectively turning on debug flags.
+ Eg. DEBUG_MAKE_FLAGS=-dv DEBUG_MAKE_DIRS="*lib/sjg"
+ will act as if we did make -dv if .CURDIR ends in lib/sjg
+ DEBUG_MAKE_SYS_DIRS does the same thing, but we set the flags at
+ the start of sys.mk rather than the end.
+ This only makes sense for leaf dirs, so we check that
+ .MAKE.LEVEL > 0
+
+2010-06-09 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20100608
+ * sys.mk: include sys.env.mk later so it can use M_ListToSkip et al.
+ * examples/sys.clean-env.mk: require MAKE_VERIONS >= 20100606
+ also make it easier for folk to tweak
+
+2010-06-08 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20100606
+ do not install examples/*
+ * FILES: add examples/sys.clean-env.mk
+ * examples/sys.clean-env.mk: use .export-env to handle MAKEOBJDIR
+ this requires bmake-20100606 or later to work.
+
+2010-05-13 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * sys.mk (M_tA): better simulate the result of :tA if not available.
+
+2010-05-04 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * sys.mk: canonicalize MAKE_VERSION
+ old versions reported bmake-<src-date> build-<build-date>
+ whereas we only care about <src-date>
+
+2010-04-25 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk: just warn about FORCE_{BSD,SYS}_MK being ignored
+ * lib.mk: we only build the shared lib if SHLIB_FULLVERSION
+ is !empty
+
+2010-04-22 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * dpadd.mk: use LDADD_* if defined.
+
+2010-04-21 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20100420
+ * sys/NetBSD.mk: add MACHINE_CPU to keep netbsd makefiles happy
+ * autoconf.mk allow AUTO_AUTOCONF
+
+2010-04-19 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * obj.mk: add objwarn to keep freebsd makefiles happy
+ * auto.obj.mk: ensure Mkdirs is available.
+ * FILES: add auto.dep.mk - a simpler version of autodep.mk
+ * dep.mk: auto.dep.mk does not do 'make depend' so ignore it if
+ asked to do that.
+ fix/simplify the tests for when to run mkdep.
+ * auto.dep.mk: add some explaination of how/what we do.
+ * autodep.mk: skip the .OPTIONAL frobbing of .depend
+ bmake's FROM_DEPEND flag makes it redundant.
+
+2010-04-13 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20100404
+ * subdir.mk: protect from multiple inclusion using _SUBDIRUSE.
+ * obj.mk: protect from multiple inclusion even as bsd.obj.mk
+ Also create a target _SUBDIRUSE so that we can be used without
+ subdir.mk
+
+2010-04-12 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * dep.mk: use <> when .including so can override.
+
+2010-01-11 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * lib.mk (SHLIB_LINKS): ensure a string comparison.
+
+2010-01-04 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20100102
+ * own.mk: ensure PRINTOBJDIR works
+ * autoconf.mk: pass on CONFIGURE_ARGS
+ * init.mk: handle COPTS.${.IMPSRC:T} etc.
+ * lib.mk: allow sys.mk to control SHLIB_FULLVERSION
+ fix handling of symlinks for darwin
+ * libnames.mk: add DSHLIBEXT for libs which only exist as shared.
+ * man.mk: suppress chown when not root.
+ * rst2htm.mk: allow srcs from multiple locations.
+ * sys.mk: M_whence, stop after 1st line of output.
+ * sys/Darwin.mk: Use .dylib for DSHLIBEXT and HOST_LIBEXT
+ * sys/SunOS.mk: we need to export PATH
+
+2009-12-23 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ include rst2htm.mk
+
+2009-12-17 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * sys.mk,libnames.mk add .-include <local.*>
+ this allows local customization without the need to edit the
+ distributed files.
+
+2009-12-14 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * dpadd.mk (__dpadd_libdirs): order -L's to avoid picking up
+ older versions already installed.
+
+2009-12-13 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * stage.mk (.stage-install): generalize lib.mk's .libinstall
+ * rules.mk rules for generic Makefile.
+ * inc.mk install for includes.
+
+2009-12-11 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * sys/NetBSD.mk (MAKE_VERSION): some of our *.mk want to check
+ this, so provide it if using native make.
+
+2009-12-10 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * FILES: move all the platform *.sys.mk files to sys/*.mk
+ * Rename Generic.sys.mk to sys.mk - we always want it.
+
+2009-11-17 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ * host-target.mk: only export the expensive stuff
+ * Generic.sys.mk (sys_mk): for SunOS we need to look for
+ ${HOST_OS}.${HOST_OSMAJOR} too!
+
+2009-11-07 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ * lib.mk: if sys.mk doesn't give us an lorder, don't use it.
+ based on patch from Greg Olszewski.
+ * Generic.sys.mk: if we have nothing to work with
+ set LORDER etc only if we can find it.
+
+2009-09-08 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ * man.mk: cleanman: remove CLEANMAN if defined.
+
+2009-09-04 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * SunOS.5.sys.mk (CC): Use ?= like the other *sys.mk
+
+2009-07-17 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ include auto.obj.mk
+
+
+2009-03-26 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * prog.mk,lib.mk: ensure test of USE_DPADD_MK doesn't fail.
+
+2008-11-11 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ man.mk: ensure we generate *.cat1 etc in .
+
+2008-07-16 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ add prlist.mk
+
+2007-11-25 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * Generic.sys.mk: Allow os specific sys.mk to be in a
+ subdir of ${.PARSEDIR}
+
+2007-11-22 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ * general cleanup
+ * dpadd.mk introduce DPMAGIC_LIBS_*
+
+2007-04-30 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+
+ * libs.mk, progs.mk, autodep.mk: allow for per lib/prog
+ depend files and ensure clean is called for each lib/prog.
+
+2007-03-27 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * autodep.mk (.depend): delete lines that do not start with
+ space and do not contain ':'
+
+2007-02-16 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * autodep.mk (.depend): gcc may wrap lines if pathnames are long
+ so make sure the transform for .OPTIONAL copes.
+
+2007-02-03 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+
+ * own.mk: make sure RM and LN are defined.
+
+ * obj.mk: fix a typo, and objlink target.
+
+2006-12-30 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version
+ * added libs.mk - analagous to progs.mk
+ make both of them always inlcude {lib,prog}.mk
+
+2006-12-28 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * progs.mk: add a means of building multiple apps in one dir.
+
+2006-11-26 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20061126
+
+ * warnings.mk: detect invalid WARNINGS_SET
+
+ * warnings.mk: use ${.TARGET:T:R}.o when looking for target
+ specific warnings.
+
+ * For .cc sources, turn off warnings that g++ vomits on.
+
+2006-11-08 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * own.mk: if __initialized__ target doesn't exist and we are
+ FreeBSD we got here directly from sys.mk
+
+2006-11-06 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20061106
+ add scripts.mk
+
+2006-03-18 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20060318
+
+ * autodep.mk: avoid := when modifying OBJS into __dependsrcs
+
+2006-03-02 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20060302
+ * autodep.mk: use -MF et al to help gcc+ccache DTRT.
+
+2006-03-01 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20060301
+ * autodep.mk (.depend):
+ if MAKE_VERSION is newer than 20050530 we can make .END depend on
+ .depend and make .depend depend on __depsrcs that exist.
+ * dpadd.mk: add SRC_PATHADD
+
+2005-11-04 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20051104
+ * prog.mk: remove all the LIBC?= junk, use
+ .-include libnames.mk instead (none by default).
+ also if USE_DPADD_MK is set, include that.
+
+2005-10-09 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20051001
+ Add UnixWare.sys.mk from Klaus Heinz.
+
+2005-04-05 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk: always install *.sys.mk and if need be symlink one
+ to sys.mk
+
+2005-03-22 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * subdir.mk, own.mk: use .MAKE rather than MAKE
+
+2004-02-15 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * own.mk: don't use NetBSD's _SRC_TOP_ it can
+ cause confusion. Also don't take just 'mk' as a
+ srctop indicator.
+
+2004-02-14 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * warnings.mk: overhauled, now very powerful.
+
+2004-02-03 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * Generic.sys.mk: need to use ${.PARSEDIR} with exists().
+
+2004-02-01 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): bump version to 20040201
+ * extract HOST_TARGET stuff to host-target.mk so own.mk and
+ Generic.sys.mk can share.
+ * fix typo in autodep.mk _SUBDIRUSE not _SUBDIR.
+
+2003-09-30 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): 20030930
+ * rename generic.sys.mk to Generic.sys.mk
+ so that it does not get installed (unless being used as sys.mk)
+ * set OS and ROOT_GROUP for those that we know the value.
+ for others (eg. Generic.sys.mk) wrap the != in an .ifndef so
+ we don't do it again for each sub-make.
+
+2003-09-28 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk (MK_VERSION): 20030928
+ Add some extra *.sys.mk from bootstrap-pkgsrc
+ some of these likely still need work.
+ Make everything default to root:wheel ownership,
+ sys.mk can set ROOT_GROUP accordingly.
+
+2003-08-07 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk: if FORCE_BSD_MK={cp,ln} use the ones in SYS_MK_DIR
+ not the portable ones.
+
+2003-07-31 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk: add ability to use cp -f when updating
+ destination .mk files. Also now possible to play games with
+ FORCE_SYS_MK=ln etc on *BSD machines to link /usr/share/mk/sys.mk
+ into dest - not recommended unless you seriously want to.
+
+2003-07-28 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * own.mk (IMPFLAGS): add support for COPTS.${IMPSRC:T} etc
+ for semi-compatability with NetBSD.
+
+2003-07-23 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * install-mk: add a version indicator
+
+2003-07-22 Simon J. Gerraty <sjg@void.crufty.net>
+
+ * prog.mk: don't try and use ${LIBCRT0} if its /dev/null
+
+ * install-mk: Allow FORCE_SYS_MK to come from env
+
+
+
diff --git a/contrib/bmake/mk/FILES b/contrib/bmake/mk/FILES
new file mode 100644
index 0000000..7a2bf29
--- /dev/null
+++ b/contrib/bmake/mk/FILES
@@ -0,0 +1,60 @@
+ChangeLog
+FILES
+README
+auto.obj.mk
+autoconf.mk
+autodep.mk
+auto.dep.mk
+dep.mk
+doc.mk
+dpadd.mk
+final.mk
+host-target.mk
+host.libnames.mk
+inc.mk
+init.mk
+install-mk
+java.mk
+lib.mk
+libnames.mk
+libs.mk
+links.mk
+man.mk
+mk-files.txt
+nls.mk
+obj.mk
+options.mk
+own.mk
+prlist.mk
+prog.mk
+progs.mk
+rst2htm.mk
+scripts.mk
+srctop.mk
+subdir.mk
+sys.mk
+sys.clean-env.mk
+sys.dependfile.mk
+sys/AIX.mk
+sys/Darwin.mk
+sys/Generic.mk
+sys/HP-UX.mk
+sys/IRIX.mk
+sys/Linux.mk
+sys/NetBSD.mk
+sys/OSF1.mk
+sys/OpenBSD.mk
+sys/SunOS.mk
+sys/UnixWare.mk
+target-flags.mk
+warnings.mk
+yacc.mk
+dirdeps.mk
+gendirdeps.mk
+install-new.mk
+meta2deps.py
+meta2deps.sh
+meta.sys.mk
+meta.autodep.mk
+meta.stage.mk
+meta.subdir.mk
diff --git a/contrib/bmake/mk/README b/contrib/bmake/mk/README
new file mode 100644
index 0000000..3d79b6a
--- /dev/null
+++ b/contrib/bmake/mk/README
@@ -0,0 +1,401 @@
+# $Id: README,v 1.1 1997/03/11 07:27:15 sjg Exp $
+
+This directory contains some macro's derrived from the NetBSD bsd.*.mk
+macros. They have the same names but without the bsd., separate macro
+files are needed to ensure we can make them do what we want for
+builing things outside of /usr/src. Nearly all the comments below
+apply.
+
+# $NetBSD: bsd.README,v 1.18 1997/01/13 00:54:23 mark Exp $
+# @(#)bsd.README 5.1 (Berkeley) 5/11/90
+
+This is the README file for the new make "include" files for the BSD
+source tree. The files are installed in /usr/share/mk, and are, by
+convention, named with the suffix ".mk".
+
+Note, this file is not intended to replace reading through the .mk
+files for anything tricky.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+RANDOM THINGS WORTH KNOWING:
+
+The files are simply C-style #include files, and pretty much behave like
+you'd expect. The syntax is slightly different in that a single '.' is
+used instead of the hash mark, i.e. ".include <bsd.prog.mk>".
+
+One difference that will save you lots of debugging time is that inclusion
+of the file is normally done at the *end* of the Makefile. The reason for
+this is because .mk files often modify variables and behavior based on the
+values of variables set in the Makefile. To make this work, remember that
+the FIRST target found is the target that is used, i.e. if the Makefile has:
+
+ a:
+ echo a
+ a:
+ echo a number two
+
+the command "make a" will echo "a". To make things confusing, the SECOND
+variable assignment is the overriding one, i.e. if the Makefile has:
+
+ a= foo
+ a= bar
+
+ b:
+ echo ${a}
+
+the command "make b" will echo "bar". This is for compatibility with the
+way the V7 make behaved.
+
+It's fairly difficult to make the BSD .mk files work when you're building
+multiple programs in a single directory. It's a lot easier split up the
+programs than to deal with the problem. Most of the agony comes from making
+the "obj" directory stuff work right, not because we switch to a new version
+of make. So, don't get mad at us, figure out a better way to handle multiple
+architectures so we can quit using the symbolic link stuff. (Imake doesn't
+count.)
+
+The file .depend in the source directory is expected to contain dependencies
+for the source files. This file is read automatically by make after reading
+the Makefile.
+
+The variable DESTDIR works as before. It's not set anywhere but will change
+the tree where the file gets installed.
+
+The profiled libraries are no longer built in a different directory than
+the regular libraries. A new suffix, ".po", is used to denote a profiled
+object.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The include file <sys.mk> has the default rules for all makes, in the BSD
+environment or otherwise. You probably don't want to touch this file.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The include file <bsd.man.mk> handles installing manual pages and their
+links.
+
+It has a single target:
+
+ maninstall:
+ Install the manual pages and their links.
+
+It sets/uses the following variables:
+
+MANDIR Base path for manual installation.
+
+MANGRP Manual group.
+
+MANOWN Manual owner.
+
+MANMODE Manual mode.
+
+MANSUBDIR Subdirectory under the manual page section, i.e. "/vax"
+ or "/tahoe" for machine specific manual pages.
+
+MAN The manual pages to be installed (use a .1 - .9 suffix).
+
+MLINKS List of manual page links (using a .1 - .9 suffix). The
+ linked-to file must come first, the linked file second,
+ and there may be multiple pairs. The files are soft-linked.
+
+The include file <bsd.man.mk> includes a file named "../Makefile.inc" if
+it exists.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The include file <bsd.own.mk> contains source tree configuration parameters,
+such as the owners, groups, etc. for both manual pages and binaries, and
+a few global "feature configuration" parameters.
+
+It has no targets.
+
+To get system-specific configuration parameters, bsd.own.mk will try to
+include the file specified by the "MAKECONF" variable. If MAKECONF is not
+set, or no such file exists, the system make configuration file, /etc/mk.conf
+is included. These files may define any of the variables described below.
+
+bsd.own.mk sets the following variables, if they are not already defined
+(defaults are in brackets):
+
+BSDSRCDIR The real path to the system sources, so that 'make obj'
+ will work correctly. [/usr/src]
+
+BSDOBJDIR The real path to the system 'obj' tree, so that 'make obj'
+ will work correctly. [/usr/obj]
+
+BINGRP Binary group. [bin]
+
+BINOWN Binary owner. [bin]
+
+BINMODE Binary mode. [555]
+
+NONBINMODE Mode for non-executable files. [444]
+
+MANDIR Base path for manual installation. [/usr/share/man/cat]
+
+MANGRP Manual group. [bin]
+
+MANOWN Manual owner. [bin]
+
+MANMODE Manual mode. [${NONBINMODE}]
+
+LIBDIR Base path for library installation. [/usr/lib]
+
+LINTLIBDIR Base path for lint(1) library installation. [/usr/libdata/lint]
+
+LIBGRP Library group. [${BINGRP}]
+
+LIBOWN Library owner. [${BINOWN}]
+
+LIBMODE Library mode. [${NONBINMODE}]
+
+DOCDIR Base path for system documentation (e.g. PSD, USD, etc.)
+ installation. [/usr/share/doc]
+
+DOCGRP Documentation group. [bin]
+
+DOCOWN Documentation owner. [bin]
+
+DOCMODE Documentation mode. [${NONBINMODE}]
+
+NLSDIR Base path for National Language Support files installation.
+ [/usr/share/nls]
+
+NLSGRP National Language Support files group. [bin]
+
+NLSOWN National Language Support files owner. [bin]
+
+NLSMODE National Language Support files mode. [${NONBINMODE}]
+
+STRIP The flag passed to the install program to cause the binary
+ to be stripped. This is to be used when building your
+ own install script so that the entire system can be made
+ stripped/not-stripped using a single knob. [-s]
+
+COPY The flag passed to the install program to cause the binary
+ to be copied rather than moved. This is to be used when
+ building our own install script so that the entire system
+ can either be installed with copies, or with moves using
+ a single knob. [-c]
+
+Additionally, the following variables may be set by bsd.own.mk or in a
+make configuration file to modify the behaviour of the system build
+process (default values are in brackets along with comments, if set by
+bsd.own.mk):
+
+EXPORTABLE_SYSTEM
+ Do not build /usr/src/domestic, even if it is present.
+
+SKEY Compile in support for S/key authentication. [yes, set
+ unconditionally]
+
+KERBEROS Compile in support for Kerberos 4 authentication.
+
+KERBEROS5 Compile in support for Kerberos 5 authentication.
+
+MANZ Compress manual pages at installation time.
+
+SYS_INCLUDE Copy or symlink kernel include files into /usr/include.
+ Possible values are "symlinks" or "copies" (which is
+ the same as the variable being unset).
+
+NOPROFILE Do not build profiled versions of system libraries
+
+NOPIC Do not build PIC versions of system libraries, and
+ do not build shared libraries. [set if ${MACHINE_ARCH}
+ is "mips", "vax", "alpha" or "arm32", unset otherwise.]
+
+NOLINT Do not build lint libraries. [set, set unconditionally]
+
+bsd.own.mk is generally useful when building your own Makefiles so that
+they use the same default owners etc. as the rest of the tree.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The include file <bsd.prog.mk> handles building programs from one or
+more source files, along with their manual pages. It has a limited number
+of suffixes, consistent with the current needs of the BSD tree.
+
+It has eight targets:
+
+ all:
+ build the program and its manual page
+ clean:
+ remove the program, any object files and the files a.out,
+ Errs, errs, mklog, and core.
+ cleandir:
+ remove all of the files removed by the target clean, as
+ well as .depend, tags, and any manual pages.
+ depend:
+ make the dependencies for the source files, and store
+ them in the file .depend.
+ includes:
+ install any header files.
+ install:
+ install the program and its manual pages; if the Makefile
+ does not itself define the target install, the targets
+ beforeinstall and afterinstall may also be used to cause
+ actions immediately before and after the install target
+ is executed.
+ lint:
+ run lint on the source files
+ tags:
+ create a tags file for the source files.
+
+It sets/uses the following variables:
+
+BINGRP Binary group.
+
+BINOWN Binary owner.
+
+BINMODE Binary mode.
+
+CLEANFILES Additional files to remove for the clean and cleandir targets.
+
+COPTS Additional flags to the compiler when creating C objects.
+
+HIDEGAME If HIDEGAME is defined, the binary is installed in
+ /usr/games/hide, and a symbolic link is created to
+ /usr/games/dm.
+
+LDADD Additional loader objects. Usually used for libraries.
+ For example, to load with the compatibility and utility
+ libraries, use:
+
+ LDADD+=-lutil -lcompat
+
+LDFLAGS Additional loader flags.
+
+LINKS The list of binary links; should be full pathnames, the
+ linked-to file coming first, followed by the linked
+ file. The files are hard-linked. For example, to link
+ /bin/test and /bin/[, use:
+
+ LINKS= ${DESTDIR}/bin/test ${DESTDIR}/bin/[
+
+MAN Manual pages (should end in .1 - .9). If no MAN variable is
+ defined, "MAN=${PROG}.1" is assumed.
+
+PROG The name of the program to build. If not supplied, nothing
+ is built.
+
+SRCS List of source files to build the program. If PROG is not
+ defined, it's assumed to be ${PROG}.c.
+
+DPADD Additional dependencies for the program. Usually used for
+ libraries. For example, to depend on the compatibility and
+ utility libraries use:
+
+ DPADD+=${LIBCOMPAT} ${LIBUTIL}
+
+ The following libraries are predefined for DPADD:
+
+ LIBC /lib/libc.a
+ LIBCOMPAT /usr/lib/libcompat.a
+ LIBCRYPT /usr/lib/libcrypt.a
+ LIBCURSES /usr/lib/libcurses.a
+ LIBDBM /usr/lib/libdbm.a
+ LIBDES /usr/lib/libdes.a
+ LIBL /usr/lib/libl.a
+ LIBKDB /usr/lib/libkdb.a
+ LIBKRB /usr/lib/libkrb.a
+ LIBKVM /usr/lib/libkvm.a
+ LIBM /usr/lib/libm.a
+ LIBMP /usr/lib/libmp.a
+ LIBPC /usr/lib/libpc.a
+ LIBPLOT /usr/lib/libplot.a
+ LIBRPC /usr/lib/sunrpc.a
+ LIBTERM /usr/lib/libterm.a
+ LIBUTIL /usr/lib/libutil.a
+
+SHAREDSTRINGS If defined, a new .c.o rule is used that results in shared
+ strings, using xstr(1). Note that this will not work with
+ parallel makes.
+
+STRIP The flag passed to the install program to cause the binary
+ to be stripped.
+
+SUBDIR A list of subdirectories that should be built as well.
+ Each of the targets will execute the same target in the
+ subdirectories.
+
+The include file <bsd.prog.mk> includes the file named "../Makefile.inc"
+if it exists, as well as the include file <bsd.man.mk>.
+
+Some simple examples:
+
+To build foo from foo.c with a manual page foo.1, use:
+
+ PROG= foo
+
+ .include <bsd.prog.mk>
+
+To build foo from foo.c with a manual page foo.2, add the line:
+
+ MAN= foo.2
+
+If foo does not have a manual page at all, add the line:
+
+ NOMAN= noman
+
+If foo has multiple source files, add the line:
+
+ SRCS= a.c b.c c.c d.c
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The include file <bsd.subdir.mk> contains the default targets for building
+subdirectories. It has the same eight targets as <bsd.prog.mk>: all,
+clean, cleandir, depend, includes, install, lint, and tags. For all of
+the directories listed in the variable SUBDIRS, the specified directory
+will be visited and the target made. There is also a default target which
+allows the command "make subdir" where subdir is any directory listed in
+the variable SUBDIRS.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The include file <bsd.sys.mk> is used by <bsd.prog.mk> and
+<bsd.lib.mk>. It contains overrides that are used when building
+the NetBSD source tree. For instance, if "PARALLEL" is defined by
+the program/library Makefile, it includes a set of rules for lex and
+yacc that allow multiple lex and yacc targets to be built in parallel.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The include file <bsd.lib.mk> has support for building libraries. It has
+the same eight targets as <bsd.prog.mk>: all, clean, cleandir, depend,
+includes, install, lint, and tags. It has a limited number of suffixes,
+consistent with the current needs of the BSD tree.
+
+It sets/uses the following variables:
+
+LIB The name of the library to build.
+
+LIBDIR Target directory for libraries.
+
+LINTLIBDIR Target directory for lint libraries.
+
+LIBGRP Library group.
+
+LIBOWN Library owner.
+
+LIBMODE Library mode.
+
+LDADD Additional loader objects.
+
+MAN The manual pages to be installed (use a .1 - .9 suffix).
+
+SRCS List of source files to build the library. Suffix types
+ .s, .c, and .f are supported. Note, .s files are preferred
+ to .c files of the same name. (This is not the default for
+ versions of make.)
+
+The include file <bsd.lib.mk> includes the file named "../Makefile.inc"
+if it exists, as well as the include file <bsd.man.mk>.
+
+It has rules for building profiled objects; profiled libraries are
+built by default.
+
+Libraries are ranlib'd when made.
diff --git a/contrib/bmake/mk/auto.dep.mk b/contrib/bmake/mk/auto.dep.mk
new file mode 100644
index 0000000..bb2d4c1
--- /dev/null
+++ b/contrib/bmake/mk/auto.dep.mk
@@ -0,0 +1,64 @@
+#
+# RCSid:
+# $Id: auto.dep.mk,v 1.2 2010/04/19 17:37:19 sjg Exp $
+#
+# @(#) Copyright (c) 2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# This module provides automagic dependency generation along the
+# lines suggested in the GNU make.info
+
+# set MKDEP=auto.dep and dep.mk will include us
+
+# This version differs from autodep.mk, in that
+# we use ${.TARGET:T}.d rather than ${.TARGET:T:R}.d
+# this makes it simpler to get the args to -MF and -MT right
+# and ensure we can simply include all the .d files.
+#
+# However suffix rules do not work with something like .o.d so we
+# don't even try to handle 'make depend' gracefully.
+# dep.mk will handle that itself.
+#
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+# this what bmake > 20100401 will look for
+.MAKE.DEPENDFILE ?= .depend
+
+# set this to -MMD to ignore /usr/include
+# actually it ignores <> so may not be a great idea
+CFLAGS_MD ?= -MD
+# -MF etc not available on all gcc versions.
+CFLAGS_MF ?= -MF ${.TARGET:T}.d -MT ${.TARGET:T}
+CFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
+CXXFLAGS += ${CFLAGS_MD} ${CFLAGS_MF}
+
+CLEANFILES += .depend ${.MAKE.DEPENDFILE} *.d
+
+# skip generating dependfile for misc targets
+.if ${.TARGETS:Uall:M*all} != ""
+.END: ${.MAKE.DEPENDFILE}
+.endif
+
+# doing 'make depend' isn't a big win with this model
+.if !target(depend)
+depend: ${.MAKE.DEPENDFILE}
+.endif
+
+# this is trivial
+${.MAKE.DEPENDFILE}: ${OBJS} ${POBJS} ${SOBJS}
+ -@for f in ${.ALLSRC:M*o:T:O:u:%=%.d}; do \
+ echo ".-include \"$$f\""; \
+ done > $@
+
+.endif
diff --git a/contrib/bmake/mk/auto.obj.mk b/contrib/bmake/mk/auto.obj.mk
new file mode 100644
index 0000000..adccd4b
--- /dev/null
+++ b/contrib/bmake/mk/auto.obj.mk
@@ -0,0 +1,56 @@
+# $Id: auto.obj.mk,v 1.8 2011/08/08 17:35:20 sjg Exp $
+#
+# @(#) Copyright (c) 2004, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+ECHO_TRACE ?= echo
+
+.ifndef Mkdirs
+# A race condition in some versions of mkdir, means that it can bail
+# if another process made a dir that mkdir expected to.
+# We repeat the mkdir -p a number of times to try and work around this.
+# We stop looping as soon as the dir exists.
+# If we get to the end of the loop, a plain mkdir will issue an error.
+Mkdirs= Mkdirs() { \
+ for d in $$*; do \
+ for i in 1 2 3 4 5 6; do \
+ mkdir -p $$d; \
+ test -d $$d && return 0; \
+ done > /dev/null 2>&1; \
+ mkdir $$d || exit $$?; \
+ done; }
+.endif
+
+# if MKOBJDIRS is set to auto (and NOOBJ isn't defined) do some magic...
+# This will automatically create objdirs as needed.
+# Skip it if we are just doing 'clean'.
+.if !defined(NOOBJ) && !defined(NO_OBJ) && ${MKOBJDIRS:Uno} == auto
+# Use __objdir here so it is easier to tweak without impacting
+# the logic.
+__objdir?= ${MAKEOBJDIR}
+.if ${.OBJDIR} != ${__objdir}
+# We need to chdir, make the directory if needed
+.if !exists(${__objdir}/) && \
+ (${.TARGETS} == "" || ${.TARGETS:Nclean*:N*clean:Ndestroy*} != "")
+# This will actually make it...
+__objdir_made != echo ${__objdir}/; umask ${OBJDIR_UMASK:U002}; \
+ ${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \
+ ${Mkdirs}; Mkdirs ${__objdir}
+.endif
+# This causes make to use the specified directory as .OBJDIR
+.OBJDIR: ${__objdir}
+.if ${.OBJDIR} != ${__objdir} && ${__objdir_made:Uno:M${__objdir}/*} != ""
+.error could not use ${__objdir}
+.endif
+.endif
+.endif
diff --git a/contrib/bmake/mk/autoconf.mk b/contrib/bmake/mk/autoconf.mk
new file mode 100644
index 0000000..573a715
--- /dev/null
+++ b/contrib/bmake/mk/autoconf.mk
@@ -0,0 +1,78 @@
+# $Id: autoconf.mk,v 1.8 2012/11/19 05:37:48 sjg Exp $
+#
+# @(#) Copyright (c) 1996-2009, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.NOPATH: config.h config.status
+
+.if !target(config.h)
+config.h: ${.CURDIR}/config.h.in config.status
+ ./config.status
+.endif
+
+.if !target(config.status)
+# avoid the targets behaving differently
+.if exists(${.OBJDIR}/config.status)
+config.status: config.recheck
+.else
+config.status: config.gen
+.endif
+
+config.recheck: config.h.in ${.CURDIR}/configure
+ ./config.status --recheck
+ @touch $@
+
+config.gen: config.h.in ${.CURDIR}/configure
+ CC="${CC} ${CCMODE}" ${.CURDIR}/configure --no-create ${CONFIGURE_ARGS}
+ @touch $@ config.recheck
+
+CLEANFILES+= config.recheck config.gen config.status *.meta
+.endif
+
+# avoid things blowing up if these are not here...
+# this is not quite per the autoconf manual,
+# and is extremely convoluted - but all utterly necessary!
+
+.if make(autoconf-in) || make(configure) || make(config.h.in) || ${AUTO_AUTOCONF:Uno:tl} == "yes"
+AUTOCONF ?= autoconf
+AUTOHEADER ?= autoheader
+
+# expand it to a full path
+AUTOCONF := ${AUTOCONF:${M_whence}}
+
+.if exists(${AUTOCONF})
+
+.PRECIOUS: configure config.h.in config.status
+
+ACLOCAL =
+ACCONFIG =
+
+.if exists(${.CURDIR}/aclocal.m4)
+ACLOCAL += aclocal.m4
+.endif
+# use of acconfig.h is deprecated!
+.if exists(${.CURDIR}/acconfig.h)
+ACCONFIG += acconfig.h
+.endif
+
+config.h.in: ${.CURDIR}/configure.in ${ACCONFIG}
+ (cd ${.CURDIR} && ${AUTOHEADER})
+
+configure: ${.CURDIR}/configure.in ${ACLOCAL}
+ (cd ${.CURDIR} && ${AUTOCONF})
+
+AUTOCONF_INPUTS += configure
+autoconf-input: ${AUTOCONF_INPUTS}
+
+.endif
+.endif
diff --git a/contrib/bmake/mk/autodep.mk b/contrib/bmake/mk/autodep.mk
new file mode 100644
index 0000000..744770f
--- /dev/null
+++ b/contrib/bmake/mk/autodep.mk
@@ -0,0 +1,216 @@
+#
+# RCSid:
+# $Id: autodep.mk,v 1.32 2010/04/19 17:37:56 sjg Exp $
+#
+# @(#) Copyright (c) 1999-2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+
+# This module provides automagic dependency generation along the
+# lines suggested in the GNU make.info
+# The depend target is mainly for backwards compatability,
+# dependencies are normally updated as part of compilation.
+
+# set MKDEP=autodep and dep.mk will include us
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+# different versions of bsd.dep.mk use these
+MKDEP=autodep
+MKDEPCMD=autodep
+
+DEPENDFILE?= .depend
+.for d in ${DEPENDFILE:N.depend}
+# bmake only groks .depend
+.-include "$d"
+.endfor
+
+# it does nothing if SRCS is not defined or is empty
+.if defined(SRCS) && !empty(SRCS)
+DEPSRCS?=${SRCS}
+__depsrcs=${DEPSRCS:M*.c}
+__depsrcs+=${DEPSRCS:M*.y}
+__depsrcs+=${DEPSRCS:M*.l}
+__depsrcs+=${DEPSRCS:M*.s}
+__depsrcs+=${DEPSRCS:M*.S}
+__depsrcs+=${DEPSRCS:M*.cc}
+__depsrcs+=${DEPSRCS:M*.cpp}
+__depsrcs+=${DEPSRCS:M*.C}
+__depsrcs+=${DEPSRCS:M*.cxx}
+__depsrcs+=${DEPSRCS:M*.pc}
+
+.for s in ${__depsrcs}
+${s:T:R}.d: $s
+.endfor
+
+__depsrcs:=${__depsrcs:T:R:S/$/.d/g}
+# we also need to handle makefiles where the .d's from __depsrcs
+# don't match those from OBJS
+# we avoid using := here, since the modifier applied to OBJS
+# can cause trouble if there are any undefined vars in OBJS.
+__dependsrcsx?= ${__depsrcs} ${OBJS:S/.o/.d/}
+__dependsrcs= ${__dependsrcsx:O:u}
+
+# clean up any .c files we may have generated
+#__gensrcs:= ${DEPSRCS:M*.y} ${DEPSRCS:M*.l}
+#CLEANFILES+= ${__gensrcs:T:R:S/$/.c/g}
+
+# set this to -MMD to ignore /usr/include
+# actually it ignores <> so may not be a great idea
+CFLAGS_MD?=-MD
+# -MF etc not available on all gcc versions.
+# we "fix" the .o later
+CFLAGS_MF?=-MF ${.TARGET:T:R}.d -MT ${.TARGET:T:R}.o
+CFLAGS+= ${CFLAGS_MD} ${CFLAGS_MF}
+RM?= rm
+
+# watch out for people who don't use CPPFLAGS
+CPPFLAGS_MD=${CFLAGS:M-[IUD]*} ${CPPFLAGS}
+CXXFLAGS_MD=${CXXFLAGS:M-[IUD]*} ${CPPFLAGS}
+
+# just in case these need to be different
+CC_MD?=${CC}
+CXX_MD?=${CXX}
+
+# so we can do an explicit make depend, but not otherwise
+.if make(depend)
+.SUFFIXES: .d
+
+.if empty(CFLAGS_MD)
+.y.d:
+ @echo updating dependencies for $<
+ @${YACC} ${YFLAGS} $<
+ @${SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} y.tab.c | sed '/:/s/^/$@ /' > $@" || { ${RM} -f y.tab.c $@; false; }
+ @${RM} -f y.tab.c
+
+.l.d:
+ @echo updating dependencies for $<
+ ${LEX} ${LFLAGS} $<
+ @${SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} lex.yy.c | sed '/:/s/^/$@ /' > $@" || { ${RM} -f lex.yy.c $@; false; }
+ @${RM} -f lex.yy.c
+
+.c.d:
+ @echo updating dependencies for $<
+ @${SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
+
+.s.d .S.d:
+ @echo updating dependencies for $<
+ @${SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} ${AINC} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
+
+.cc.d .cpp.d .C.d .cxx.d:
+ @echo updating dependencies for $<
+ @${SHELL} -ec "${CXX_MD} -M ${CXXFLAGS_MD} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; }
+.else
+.y.d:
+ ${YACC} ${YFLAGS} $<
+ ${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} y.tab.c > $@ || { ${RM} -f y.tab.c $@; false; }
+ ${RM} -f y.tab.c
+
+.l.d:
+ ${LEX} ${LFLAGS} $<
+ ${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} lex.yy.c > $@ || { ${RM} -f lex.yy.c $@; false; }
+ ${RM} -f lex.yy.c
+
+.c.d:
+ ${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} $< > $@ || { ${RM} -f $@; false; }
+
+.s.d .S.d:
+ ${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} ${AINC} $< > $@ || { ${RM} -f $@; false; }
+
+.cc.d .cpp.d .C.d .cxx.d:
+ ${CXX_MD} ${CFLAGS_MD:S/D//} ${CXXFLAGS_MD} $< > $@ || { ${RM} -f $@; false; }
+.endif
+
+.if !target(depend)
+depend: beforedepend ${DEPENDFILE} afterdepend _SUBDIRUSE
+
+${DEPENDFILE}: ${DEPSRCS} ${__dependsrcs}
+.NOPATH: ${__dependsrcs}
+.OPTIONAL: ${__dependsrcs}
+.endif
+.endif # make(depend)
+
+.if empty(CFLAGS_MD)
+# make sure the .d's are generated/updated
+${PROG} ${_LIBS}: ${DEPENDFILE}
+.endif
+
+.ORDER: beforedepend ${DEPENDFILE} afterdepend
+
+.if ${.OBJDIR} != ${.CURDIR}
+__depfiles= *.d
+.else
+__depfiles= ${__dependsrcs}
+.endif
+
+DEPCLEANFILES= ${DEPENDFILE} ${__depfiles} y.tab.d *.tmp.d
+
+cleandir: cleanautodepend
+cleanautodepend:
+ ${RM} -f ${DEPCLEANFILES}
+
+CLEANFILES+= ${DEPCLEANFILES}
+
+.if defined(__dependsrcs) && !empty(__dependsrcs)
+.if make(depend) || !(make(clean*) || make(destroy*) || make(obj) || make(*install) || make(install-*))
+# this ensures we do the right thing if only building a shared or
+# profiled lib
+OBJ_EXTENSIONS?=.o .po .so .So
+MDLIB_SED= -e '/:/s,^\([^\.:]*\)\.[psS]*o,${OBJ_EXTENSIONS:S,^,\1,},'
+.ifdef NOMD_SED
+.ifdef LIB
+MD_SED=sed ${MDLIB_SED}
+.else
+MD_SED=cat
+.endif
+.else
+# arrange to put some variable names into ${DEPENDFILE}
+.ifdef LIB
+MD_SED=sed ${MDLIB_SED}
+.else
+MD_SED=sed
+.endif
+SUBST_DEPVARS+= SB TOP BACKING SRC SRCDIR BASE BASEDIR
+.for v in ${SUBST_DEPVARS}
+.if defined(${v}) && !empty(${v})
+MD_SED+= -e 's,${$v},$${$v},'
+.endif
+.endfor
+.endif
+.if (${MD_SED} == "sed")
+MD_SED=cat
+.endif
+
+# this will be done whenever make finishes successfully
+.if ${MAKE_VERSION:U0:[1]:C/.*-//} < 20050530
+.END:
+.else
+.END: ${DEPENDFILE}
+# we do not want to trigger building .d's just use them if they exist
+${DEPENDFILE}: ${__dependsrcs:@d@${exists($d):?$d:}@}
+.endif
+ -@${MD_SED} ${__depfiles} > ${DEPENDFILE}.new 2> /dev/null && \
+ test -s ${DEPENDFILE}.new && mv ${DEPENDFILE}.new ${DEPENDFILE}; \
+ ${RM} -f ${DEPENDFILE}.new
+.endif
+.endif
+.else
+depend: beforedepend afterdepend _SUBDIRUSE
+.endif
+
+.if !target(beforedepend)
+beforedepend:
+.endif
+.if !target(afterdepend)
+afterdepend:
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/dep.mk b/contrib/bmake/mk/dep.mk
new file mode 100644
index 0000000..b754500
--- /dev/null
+++ b/contrib/bmake/mk/dep.mk
@@ -0,0 +1,133 @@
+# $Id: dep.mk,v 1.16 2012/11/11 22:37:02 sjg Exp $
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+# handle Proc*C as well...
+.if defined(SRCS)
+.if !empty(SRCS:M*.pc)
+.include <proc.mk>
+.endif
+
+# it would be nice to be able to query .SUFFIXES
+OBJ_EXTENSIONS+= .o .po .lo .So
+
+# explicit dependencies help short-circuit .SUFFIX searches
+SRCS_DEP_FILTER+= N*.[hly]
+.for s in ${SRCS:${SRCS_DEP_FILTER:O:u:ts:}}
+.for e in ${OBJ_EXTENSIONS:O:u}
+.if !target(${s:T:R}$e)
+${s:T:R}$e: $s
+.endif
+.endfor
+.endfor
+.endif
+
+.if exists(/usr/bin/mkdep)
+MKDEP_CMD?= mkdep
+.elif exists(/usr/local/share/bin/mkdeps.sh)
+MKDEP_CMD?= /usr/local/share/bin/mkdeps.sh -N
+.endif
+MKDEP_CMD?= mkdep
+
+MKDEP ?= ${MKDEP_CMD}
+
+.NOPATH: .depend
+
+.if ${MKDEP} == "auto.dep" && make(depend)
+# auto.dep.mk does not "do" depend
+MK_AUTODEP= no
+.endif
+
+.if ${MK_AUTODEP} == yes
+.if ${MKDEP:T:S,auto,,} != ${MKDEP:T}
+.include <${MKDEP}.mk>
+.else
+.include <autodep.mk>
+.endif
+.else
+.if ${MKDEP:T:S,auto,,} != ${MKDEP:T}
+MKDEP = ${MKDEP_CMD}
+.endif
+MKDEP_ENV_VARS += CC CXX
+.for v in ${MKDEP_ENV_VARS:O:u}
+.if !empty($v)
+MKDEP_ENV += $v='${$v}'
+.endif
+.endfor
+
+_MKDEP = ${MKDEP_ENV} ${MKDEP}
+
+# some of the rules involve .h sources, so remove them from mkdep line
+.if !target(depend)
+depend: beforedepend .depend _SUBDIRUSE afterdepend
+
+.if defined(SRCS)
+# libs can have too many SRCS for a single command line
+# so do them one at a time.
+.depend: ${SRCS} ${.PARSEDIR}/${.PASEFILE}
+ @rm -f .depend
+.ifdef LIB
+ @files="${.ALLSRC:M*.[sS]}"; \
+ set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$f; done
+ @files="${.ALLSRC:M*.c} ${.ALLSRC:M*.pc:T:.pc=.c}"; \
+ set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CFLAGS:M-[ID]*} ${CPPFLAGS} $$f; done
+ @files="${.ALLSRC:M*.cc} ${.ALLSRC:M*.C} ${.ALLSRC:M*.cxx}"; \
+ set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$f; done
+.else
+ @files="${.ALLSRC:M*.[Ss]}"; \
+ case "$$files" in *.[Ss]*) \
+ echo ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$files; \
+ ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$files;; \
+ esac
+ @files="${.ALLSRC:M*.c} ${.ALLSRC:M*.pc:T:.pc=.c}"; \
+ case "$$files" in *.c*) \
+ echo ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CFLAGS:M-[ID]*} ${CPPFLAGS} $$files; \
+ ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CFLAGS:M-[ID]*} ${CPPFLAGS} $$files;; \
+ esac
+ @files="${.ALLSRC:M*.cc} ${.ALLSRC:M*.C} ${.ALLSRC:M*.cxx}"; \
+ case "$$files" in *.[Cc]*) \
+ echo ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$files; \
+ ${_MKDEP} -a ${MKDEPFLAGS} \
+ ${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$files;; \
+ esac
+.endif
+.else
+.depend:
+.endif
+.if !target(beforedepend)
+beforedepend:
+.endif
+.if !target(afterdepend)
+afterdepend:
+.endif
+.endif
+.endif
+
+.if !target(tags)
+.if defined(SRCS)
+tags: ${SRCS} _SUBDIRUSE
+ -cd ${.CURDIR}; ctags -f /dev/stdout ${.ALLSRC:N*.h} | \
+ sed "s;\${.CURDIR}/;;" > tags
+.else
+tags:
+.endif
+.endif
+
+.if defined(SRCS)
+cleandir: cleandepend
+.if !target(cleandepend)
+cleandepend:
+ rm -f .depend ${.CURDIR}/tags
+.endif
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/dirdeps.mk b/contrib/bmake/mk/dirdeps.mk
new file mode 100644
index 0000000..9f051e9
--- /dev/null
+++ b/contrib/bmake/mk/dirdeps.mk
@@ -0,0 +1,414 @@
+# $Id: dirdeps.mk,v 1.23 2012/11/06 05:44:03 sjg Exp $
+
+# Copyright (c) 2010-2012, Juniper Networks, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE 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
+# OWNER 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.
+
+# Much of the complexity here is for supporting cross-building.
+# If a tree does not support that, simply using plain Makefile.depend
+# should provide sufficient clue.
+# Otherwise the recommendation is to use Makefile.depend.${MACHINE}
+# as expected below.
+
+# Note: this file gets multiply included.
+# This is what we do with DIRDEPS
+
+# DIRDEPS:
+# This is a list of directories - relative to SRCTOP, it is only
+# of interest to .MAKE.LEVEL 0.
+# In some cases the entry may be qualified with a .<machine>
+# suffix, for example to force building something for the pseudo
+# machines "host" or "common" regardless of current ${MACHINE}.
+# All unqualified entries end up being qualified with .${MACHINE}
+# and _DIRDEPS_USE below, uses the suffix to set MACHINE
+# correctly when visiting each entry.
+#
+# Each entry is also converted into a set of paths to look for
+# Makefile.depend.<machine> to learn the dependencies of each.
+# Each Makefile.depend.<machine> sets DEP_RELDIR to be the
+# the RELDIR (path relative to SRCTOP) for its directory, and
+# DEP_MACHINE to its suffix (<machine>), further since
+# each Makefile.depend.<machine> includes dirdeps.mk, this
+# processing is recursive and results in .MAKE.LEVEL 0 learning the
+# dependencies of the tree wrt the initial directory (_DEP_RELDIR).
+#
+# BUILD_AT_LEVEL0
+# Indicates whether .MAKE.LEVEL 0 builds anything:
+# if "no" sub-makes are used to build everything,
+# if "yes" sub-makes are only used to build for other machines.
+#
+# TARGET_SPEC_VARS
+# All the description above (and below) assumes <machine> is the
+# only data needed to control the build.
+# This is not always the case. So in addition to setting
+# MACHINE in the build environment we set TARGET_SPEC which is
+# composed of the values of TARGET_SPEC_VARS separated by
+# commas. The default is just MACHINE.
+#
+# If more that MACHINE is needed then sys.mk needs to decompose
+# TARGET_SPEC and set the relevant variables accordingly.
+# It is important that MACHINE be included in TARGET_SPEC_VARS
+# since if there is more the value passed as MACHINE will infact
+# be the TARGET_SPEC.
+# Note: TARGET_SPEC cannot contain any '.'s so the target
+# tripple used by compiler folk won't work (directly anyway).
+#
+# For example:
+#
+# # variables other than MACHINE might be optional
+# TARGET_SPEC_VARS = MACHINE TARGET_OS
+# .if ${TARGET_SPEC:Uno:M*,*} != ""
+# _tspec := ${TARGET_SPEC:S/,/ /g}
+# MACHINE := ${_tspec:[1]}
+# TARGET_OS := ${_tspec:[2]}
+# # etc.
+# .for v in ${TARGET_SPEC_VARS:O:u}
+# .if empty($v)
+# .undef $v
+# .endif
+# .endfor
+# .endif
+#
+
+.if ${.MAKE.LEVEL} == 0
+# only the first instance is interested in all this
+
+# First off, we want to know what ${MACHINE} to build for.
+# This can be complicated if we are using a mixture of ${MACHINE} specific
+# and non-specific Makefile.depend*
+
+.if !target(_DIRDEP_USE)
+# do some setup we only need once
+_CURDIR ?= ${.CURDIR}
+
+# If TARGET_SPEC_VARS is other than just MACHINE
+# it should be set by sys.mk or similar by now.
+# TARGET_SPEC must not contain any '.'s.
+TARGET_SPEC_VARS ?= MACHINE
+TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,}
+
+.if !defined(.MAKE.DEPENDFILE_PREFERENCE)
+# this makes the logic below neater?
+.MAKE.DEPENDFILE_PREFERENCE = ${_CURDIR}/${.MAKE.DEPENDFILE:T}
+.if ${.MAKE.DEPENDFILE:E} == "${TARGET_SPEC}"
+.if ${TARGET_SPEC} != ${MACHINE}
+.MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R}.$${MACHINE}
+.endif
+.MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R}
+.endif
+.endif
+
+_default_dependfile := ${.MAKE.DEPENDFILE_PREFERENCE:[1]:T}
+_machine_dependfiles := ${.MAKE.DEPENDFILE_PREFERENCE:M*.${TARGET_SPEC}} \
+ ${.MAKE.DEPENDFILE_PREFERENCE:M*.${MACHINE}}
+
+# for machine specific dependfiles we require ${MACHINE} to be at the end
+# also for the sake of sanity we require a common prefix
+.if !defined(.MAKE.DEPENDFILE_PREFIX)
+.if !empty(_machine_dependfiles)
+.MAKE.DEPENDFILE_PREFIX := ${_machine_dependfiles:[1]:T:R}
+.else
+.MAKE.DEPENDFILE_PREFIX := ${_default_dependfile:T}
+.endif
+.endif
+
+
+# this is how we identify non-machine specific dependfiles
+N_notmachine := ${.MAKE.DEPENDFILE_PREFERENCE:E:N${TARGET_SPEC}:N${MACHINE}:${M_ListToSkip}}
+
+.endif # !target(_DIRDEP_USE)
+
+_last_dependfile := ${.MAKE.MAKEFILES:M*/${.MAKE.DEPENDFILE_PREFIX}*:[-1]}
+
+# Note: if a makefile is read many times, the above
+# will not work, so we also test for DEP_MACHINE==depend below.
+.if empty(_last_dependfile)
+# we haven't included one yet
+DEP_MACHINE ?= ${TARGET_MACHINE:U${TARGET_SPEC}}
+# else it should be correctly set by ${.MAKE.DEPENDFILE}
+.elif ${_last_dependfile:E:${N_notmachine}} == "" || ${DEP_MACHINE:Uno:${N_notmachine}} == ""
+# don't rely on manually maintained files to be correct
+DEP_MACHINE := ${_DEP_MACHINE:U${TARGET_SPEC}}
+.else
+# just in case
+DEP_MACHINE ?= ${_last_dependfile:E}
+.endif
+
+# pickup customizations
+# as below you can use !target(_DIRDEP_USE) to protect things
+# which should only be done once.
+.-include "local.dirdeps.mk"
+
+# the first time we are included the _DIRDEP_USE target will not be defined
+# we can use this as a clue to do initialization and other one time things.
+.if !target(_DIRDEP_USE)
+# make sure this target exists
+dirdeps:
+
+# We normally expect to be included by Makefile.depend.*
+# which sets the DEP_* macros below.
+DEP_RELDIR ?= ${RELDIR}
+
+# this can cause lots of output!
+# set to a set of glob expressions that might match RELDIR
+DEBUG_DIRDEPS ?= no
+
+# remember the initial value of DEP_RELDIR - we test for it below.
+_DEP_RELDIR := ${DEP_RELDIR}
+
+# things we skip for host tools
+SKIP_HOSTDIR ?=
+
+NSkipHostDir = ${SKIP_HOSTDIR:N*.host:S,$,.host,:N.host:${M_ListToSkip}}
+NSkipHostDep = ${SKIP_HOSTDIR:R:@d@*/$d*.host@:${M_ListToSkip}}
+
+# things we always skip
+# SKIP_DIRDEPS allows for adding entries on command line.
+SKIP_DIR += .host *.WAIT ${SKIP_DIRDEPS}
+
+.ifdef HOSTPROG
+SKIP_DIR += ${SKIP_HOSTDIR}
+.endif
+
+NSkipDir = ${SKIP_DIR:${M_ListToSkip}}
+
+.if defined(NO_DIRDEPS) || defined(NODIRDEPS)
+# confine ourselves to the original dir
+DIRDEPS_FILTER += M${_DEP_RELDIR}*
+.endif
+
+# we supress SUBDIR when visiting the leaves
+# we assume sys.mk will set MACHINE_ARCH
+_DIRDEP_USE: .USE .MAKE
+ @for m in ${.MAKE.MAKEFILE_PREFERENCE}; do \
+ test -s ${.TARGET:R}/$$m || continue; \
+ echo "${TRACER}Checking ${.TARGET:R} for ${.TARGET:E} ..."; \
+ TARGET_SPEC=${.TARGET:E} \
+ MACHINE=${.TARGET:E} MACHINE_ARCH= NO_SUBDIR=1 \
+ ${.MAKE} -C ${.TARGET:R} || exit 1; \
+ break; \
+ done
+
+.ifdef ALL_MACHINES
+# this is how you limit it to only the machines we have been built for
+# previously.
+.if empty(ONLY_MACHINE_LIST)
+.if !empty(ALL_MACHINE_LIST)
+# ALL_MACHINE_LIST is the list of all legal machines - ignore anything else
+_machine_list != cd ${_CURDIR} && 'ls' -1 ${ALL_MACHINE_LIST:O:u:@m@${.MAKE.DEPENDFILE:T:R}.$m@} 2> /dev/null; echo
+.else
+_machine_list != 'ls' -1 ${_CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.* 2> /dev/null; echo
+.endif
+_only_machines := ${_machine_list:${NIgnoreFiles:UN*.bak}:E:O:u}
+.else
+_only_machines := ${ONLY_MACHINE_LIST}
+.endif
+
+.if empty(_only_machines)
+# we must be boot-strapping
+_only_machines := ${TARGET_MACHINE:U${ALL_MACHINE_LIST:U${DEP_MACHINE}}}
+.endif
+
+.else # ! ALL_MACHINES
+# if ONLY_MACHINE_LIST is set, we are limited to that
+# if TARGET_MACHINE is set - it is really the same as ONLY_MACHINE_LIST
+# otherwise DEP_MACHINE is it - so DEP_MACHINE will match.
+_only_machines := ${ONLY_MACHINE_LIST:U${TARGET_MACHINE:U${DEP_MACHINE}}:M${DEP_MACHINE}}
+.endif
+
+.if !empty(NOT_MACHINE_LIST)
+_only_machines := ${_only_machines:${NOT_MACHINE_LIST:${M_ListToSkip}}}
+.endif
+
+# make sure we have a starting place?
+DIRDEPS ?= ${RELDIR}
+.endif # target
+
+_debug_reldir := ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.${DEP_MACHINE}:L:M$x}@}
+_debug_search := ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.depend:L:M$x}@}
+
+# the rest is done repeatedly for every Makefile.depend we read.
+# if we are anything but the original dir we care only about the
+# machine type we were included for..
+
+.if ${DEP_RELDIR} == "."
+_this_dir := ${SRCTOP}
+.else
+_this_dir := ${SRCTOP}/${DEP_RELDIR}
+.endif
+
+# on rare occasions, there can be a need for extra help
+_dep_hack := ${_this_dir}/${.MAKE.DEPENDFILE_PREFIX}.inc
+.-include "${_dep_hack}"
+
+.if ${DEP_RELDIR} != ${_DEP_RELDIR} || ${DEP_MACHINE} != ${TARGET_SPEC}
+# this should be all
+_machines := ${DEP_MACHINE}
+.else
+# this is the machine list we actually use below
+_machines := ${_only_machines}
+
+.if defined(HOSTPROG) || ${DEP_MACHINE} == "host"
+# we need to build this guy's dependencies for host as well.
+_machines += host
+.endif
+
+_machines := ${_machines:O:u}
+.endif
+
+# reset these each time through
+_build_dirs =
+_depdir_files =
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# pickup other machines for this dir if necessary
+.if ${BUILD_AT_LEVEL0:Uyes} == "no"
+_build_dirs += ${_machines:@m@${_CURDIR}.$m@}
+.else
+_build_dirs += ${_machines:N${DEP_MACHINE}:@m@${_CURDIR}.$m@}
+.if ${DEP_MACHINE} == ${TARGET_SPEC}
+# pickup local dependencies now
+.-include <.depend>
+.endif
+.endif
+.endif
+
+.if !empty(_debug_reldir)
+.info ${DEP_RELDIR}.${DEP_MACHINE}: _last_dependfile='${_last_dependfile}'
+.info ${DEP_RELDIR}.${DEP_MACHINE}: DIRDEPS='${DIRDEPS}'
+.info ${DEP_RELDIR}.${DEP_MACHINE}: _machines='${_machines}'
+.endif
+
+.if !empty(DIRDEPS)
+
+# this is what we start with
+__depdirs := ${DIRDEPS:${NSkipDir}:${DIRDEPS_FILTER:ts:}:O:u:@d@${SRCTOP}/$d@}
+
+# some entries may be qualified with .<machine>
+# the :M*/*/*.* just tries to limit the dirs we check to likely ones.
+# the ${d:E:M*/*} ensures we don't consider junos/usr.sbin/mgd
+__qual_depdirs := ${__depdirs:M*/*/*.*:@d@${exists($d):?:${"${d:E:M*/*}":?:${exists(${d:R}):?$d:}}}@}
+__unqual_depdirs := ${__depdirs:${__qual_depdirs:Uno:${M_ListToSkip}}}
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# if it was called out - we likely need it.
+__hostdpadd := ${DPADD:U.:M${HOST_OBJTOP}/*:S,${HOST_OBJTOP}/,,:H:${NSkipDir}:${DIRDEPS_FILTER:ts:}:S,$,.host,:N.*:@d@${SRCTOP}/$d@}
+__qual_depdirs += ${__hostdpadd}
+.endif
+
+.if !empty(_debug_reldir)
+.info depdirs=${__depdirs}
+.info qualified=${__qual_depdirs}
+.info unqualified=${__unqual_depdirs}
+.endif
+
+# _build_dirs is what we will feed to _DIRDEP_USE
+_build_dirs += \
+ ${__qual_depdirs:M*.host:${NSkipHostDir}:N.host} \
+ ${__qual_depdirs:N*.host} \
+ ${_machines:@m@${__unqual_depdirs:@d@$d.$m@}@}
+
+_build_dirs := ${_build_dirs:O:u}
+
+# this is where we will pick up more dependencies from
+# the inner inline loops look complex, but save a significant
+# amount of memory compared to a .for loop.
+_depdir_files =
+.for d in ${_build_dirs}
+.if exists($d)
+# easy, we're building for ${MACHINE}
+_depdir_files += ${.MAKE.DEPENDFILE_PREFERENCE:T:@m@${exists($d/$m):?$d/$m:}@:[1]}
+.elif exists(${d:R}) && ${d:R:T} == ${d:T:R}
+# a little more complex - building for another machine
+# we will ensure the file is qualified with a machine
+# so that if necessary _DEP_MACHINE can be set below
+_depdir_files += ${.MAKE.DEPENDFILE_PREFERENCE:T:S,.${TARGET_SPEC}$,.${d:E},:S,.${MACHINE}$,.${d:E},:@m@${exists(${d:R}/$m):?${d:R}/$m:}@:[1]:@m@${"${m:M*.${d:E}}":?$m:$m.${d:E}}@}
+.endif
+.endfor
+
+# clean up
+_depdir_files := ${_depdir_files:O:u}
+
+.endif # empty DIRDEPS
+
+# Normally if doing make -V something,
+# we do not want to waste time chasing DIRDEPS
+# but if we want to count the number of Makefile.depend* read, we do.
+.if ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS}} == ""
+.if !empty(_build_dirs)
+# this makes it all happen
+dirdeps: ${_build_dirs}
+${_build_dirs}: _DIRDEP_USE
+
+.if !empty(_debug_reldir)
+.info ${DEP_RELDIR}.${DEP_MACHINE}: ${_build_dirs}
+.endif
+
+.for m in ${_machines}
+# it would be nice to do :N${.TARGET}
+.if !empty(__qual_depdirs)
+.for q in ${__qual_depdirs:E:O:u:N$m}
+.if !empty(_debug_reldir) || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != ""
+.info ${DEP_RELDIR}.$m: ${_build_dirs:M*.$q}
+.endif
+${_this_dir}.$m: ${_build_dirs:M*.$q}
+.endfor
+.endif
+.if !empty(_debug_reldir)
+.info ${DEP_RELDIR}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
+.endif
+${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
+.endfor
+
+.endif
+
+.for d in ${_depdir_files}
+.if ${.MAKE.MAKEFILES:M${d}} == ""
+.if !empty(_debug_search)
+.info Looking for $d
+.endif
+.if exists($d)
+.include <$d>
+.elif exists(${d:R})
+# an unqualified file exists, we qualified it above so we can set _DEP_MACHINE
+# it might be manually maintained and shared by all machine types
+# tell it the machine we are interested in.
+_DEP_MACHINE := ${d:E}
+.if !empty(_debug_reldir)
+.info loading ${d:R} for ${_DEP_MACHINE}
+.endif
+# pretend we read $d, so we don't come by here again.
+.MAKE.MAKEFILES += $d
+.include <${d:R}>
+.endif
+.endif
+.endfor
+.endif # -V
+
+.elif ${.MAKE.LEVEL} > 42
+.error You should have stopped recursing by now.
+.else
+_DEP_RELDIR := ${DEP_RELDIR}
+# pickup local dependencies
+.-include <.depend>
+.endif
+
diff --git a/contrib/bmake/mk/doc.mk b/contrib/bmake/mk/doc.mk
new file mode 100644
index 0000000..d496c42
--- /dev/null
+++ b/contrib/bmake/mk/doc.mk
@@ -0,0 +1,63 @@
+# $Id: doc.mk,v 1.4 2012/11/11 22:37:02 sjg Exp $
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+BIB?= bib
+EQN?= eqn
+GREMLIN?= grn
+GRIND?= vgrind -f
+INDXBIB?= indxbib
+PIC?= pic
+REFER?= refer
+ROFF?= groff -M/usr/share/tmac ${MACROS} ${PAGES}
+SOELIM?= soelim
+TBL?= tbl
+
+.PATH: ${.CURDIR}
+
+.if !target(all)
+.MAIN: all
+all: paper.ps
+.endif
+
+.if !target(paper.ps)
+paper.ps: ${SRCS}
+ ${ROFF} ${SRCS} > ${.TARGET}
+.endif
+
+.if !target(print)
+print: paper.ps
+ lpr -P${PRINTER} paper.ps
+.endif
+
+.if !target(manpages)
+manpages:
+.endif
+
+.if !target(obj)
+obj:
+.endif
+
+clean cleandir:
+ rm -f paper.* [eE]rrs mklog ${CLEANFILES}
+
+.if ${MK_DOC} == "no"
+install:
+.else
+FILES?= ${SRCS}
+install:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
+ Makefile ${FILES} ${EXTRA} ${DESTDIR}${BINDIR}/${DIR}
+.endif
+
+spell: ${SRCS}
+ spell ${SRCS} | sort | comm -23 - spell.ok > paper.spell
+
+BINDIR?= /usr/share/doc
+BINGRP?= bin
+BINOWN?= bin
+BINMODE?= 444
+
+.include <own.mk>
+.endif
diff --git a/contrib/bmake/mk/dpadd.mk b/contrib/bmake/mk/dpadd.mk
new file mode 100644
index 0000000..a940b61
--- /dev/null
+++ b/contrib/bmake/mk/dpadd.mk
@@ -0,0 +1,196 @@
+# $Id: dpadd.mk,v 1.18 2011/11/10 05:13:37 sjg Exp $
+#
+# @(#) Copyright (c) 2004, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+# sometimes we play games with .CURDIR etc
+# _* hold the original values of .*
+_OBJDIR?= ${.OBJDIR}
+_CURDIR?= ${.CURDIR}
+
+# DPLIBS helps us ensure we keep DPADD and LDADD in sync
+DPLIBS+= ${DPLIBS_LAST}
+DPADD+= ${DPLIBS}
+.for __lib in ${DPLIBS:T:R}
+LDADD+= ${LDADD_${__lib}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}}
+.endfor
+
+# DPADD can contain things other than libs
+__dpadd_libs = ${DPADD:M*/lib*}
+
+# some libs have dependencies...
+# DPLIBS_* allows bsd.libnames.mk to flag libs which must be included
+# in DPADD for a given library.
+.for __lib in ${__dpadd_libs:@d@${DPLIBS_${d:T:R}}@}
+.if "${DPADD:M${__lib}}" == ""
+DPADD+= ${__lib}
+LDADD+= ${LDADD_${__lib}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}}
+.endif
+.endfor
+# Last of all... for libc and libgcc
+DPADD+= ${DPADD_LAST}
+
+# Convert DPADD into -I and -L options and add them to CPPFLAGS and LDADD
+# For the -I's convert the path to a relative one. For separate objdirs
+# the DPADD paths will be to the obj tree so we need to subst anyway.
+
+# If USE_PROFILE is yes, then check for profiled versions of libs
+# and use them.
+
+USE_PROFILE?=no
+.if defined(LIBDL) && exists(${LIBDL})
+.if defined(PROG) && (make(${PROG}_p) || ${USE_PROFILE} == yes) && \
+ defined(LDFLAGS) && ${LDFLAGS:M-export-dynamic}
+# building profiled version of a prog that needs dlopen to work
+DPLIBS+= ${LIBDL}
+.endif
+.endif
+
+.if defined(LIBDMALLOC) && exists(${LIBDMALLOC})
+.if defined(USE_DMALLOC) && ${USE_DMALLOC} != no
+.if !defined(NO_DMALLOC)
+CPPFLAGS+= -DUSE_DMALLOC
+.endif
+DPLIBS+= ${LIBDMALLOC}
+.endif
+.endif
+
+# Order -L's to seach ours first.
+# Avoids picking up old versions already installed.
+__dpadd_libdirs := ${__dpadd_libs:R:H:S/^/-L/g:O:u:N-L}
+LDADD += ${__dpadd_libdirs:M-L${OBJTOP}/*}
+LDADD += ${__dpadd_libdirs:N-L${OBJTOP}/*}
+
+.if ${.CURDIR} == ${SRCTOP}
+RELDIR=.
+RELTOP=.
+.else
+RELDIR?= ${.CURDIR:S,${SRCTOP}/,,}
+.if ${RELDIR} == ${.CURDIR}
+RELDIR?= ${.OBJDIR:S,${OBJTOP}/,,}
+.endif
+RELTOP?= ${RELDIR:C,[^/]+,..,g}
+.endif
+RELOBJTOP?= ${OBJTOP}
+RELSRCTOP?= ${SRCTOP}
+
+.if !make(dpadd)
+.ifdef LIB
+# Each lib is its own src_lib, we want to include it in SRC_LIBS
+# so that the correct INCLUDES_* will be picked up automatically.
+SRC_LIBS+= ${_OBJDIR}/lib${LIB}.a
+.endif
+.endif
+
+#
+# This little bit of magic, assumes that SRC_libfoo will be
+# set if it cannot be correctly derrived from ${LIBFOO}
+# Note that SRC_libfoo and INCLUDES_libfoo should be named for the
+# actual libary name not the variable name that might refer to it.
+# 99% of the time the two are the same, but the DPADD logic
+# only has the libary name available, so stick to that.
+#
+
+SRC_LIBS?=
+__dpadd_libs += ${SRC_LIBS}
+DPMAGIC_LIBS += ${__dpadd_libs} \
+ ${__dpadd_libs:@d@${DPMAGIC_LIBS_${d:T:R}}@}
+
+.for __lib in ${DPMAGIC_LIBS:O:u}
+#
+# if SRC_libfoo is not set, then we assume that the srcdir corresponding
+# to where we found the library is correct.
+#
+SRC_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELSRCTOP},}
+#
+# This is a no-brainer but just to be complete...
+#
+OBJ_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELOBJTOP},}
+#
+# If INCLUDES_libfoo is not set, then we'll use ${SRC_libfoo}/h if it exists,
+# else just ${SRC_libfoo}.
+#
+INCLUDES_${__lib:T:R}?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h:${SRC_${__lib:T:R}}}
+
+.endfor
+
+# Now for the bits we actually need
+__dpadd_incs=
+.for __lib in ${__dpadd_libs:u}
+.if (make(${PROG}_p) || defined(NEED_GPROF)) && exists(${__lib:R}_p.a)
+__ldadd=-l${__lib:T:R:S,lib,,}
+LDADD := ${LDADD:S,^${__ldadd}$,${__ldadd}_p,g}
+.endif
+
+#
+# Some libs generate headers, so we potentially need both
+# the src dir and the obj dir.
+# If ${INCLUDES_libfoo} contains a word ending in /h, we assume that either
+# 1. it does not generate headers or
+# 2. INCLUDES_libfoo will have been set correctly
+# XXX it gets ugly avoiding duplicates...
+# use :? to ensure .for does not prevent correct evaluation
+#
+# We take care of duplicate suppression later.
+__dpadd_incs += ${"${INCLUDES_${__lib:T:R}:M*/h}":? :-I${OBJ_${__lib:T:R}}}
+__dpadd_incs += ${INCLUDES_${__lib:T:R}}
+.endfor
+
+#
+# eliminate any duplicates - but don't mess with the order
+# force evaluation now - to avoid giving make a headache
+#
+.for t in CFLAGS CXXFLAGS
+# avoid duplicates
+__$t_incs:=${$t:M-I*:O:u}
+.for i in ${__dpadd_incs}
+.if "${__$t_incs:M$i}" == ""
+$t+= $i
+__$t_incs+= $i
+.endif
+.endfor
+.endfor
+
+# This target is used to gather a list of
+# dir: ${DPADD}
+# entries
+.if make(*dpadd*)
+# allow overrides
+.-include "dpadd++.mk"
+
+.if !target(dpadd)
+dpadd: .NOTMAIN
+.if defined(DPADD) && ${DPADD} != ""
+ @echo "${RELDIR}: ${DPADD:S,${OBJTOP}/,,}"
+.endif
+.endif
+.endif
+
+.ifdef SRC_PATHADD
+# We don't want to assume that we need to .PATH every element of
+# SRC_LIBS, but the Makefile cannot do
+# .PATH: ${SRC_libfoo}
+# since the value of SRC_libfoo must be available at the time .PATH:
+# is read - and we only just worked it out.
+# Further, they can't wait until after include of {lib,prog}.mk as
+# the .PATH is needed before then.
+# So we let the Makefile do
+# SRC_PATHADD+= ${SRC_libfoo}
+# and we defer the .PATH: until now so that SRC_libfoo will be available.
+.PATH: ${SRC_PATHADD}
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/final.mk b/contrib/bmake/mk/final.mk
new file mode 100644
index 0000000..5f41189
--- /dev/null
+++ b/contrib/bmake/mk/final.mk
@@ -0,0 +1,14 @@
+# $Id: final.mk,v 1.5 2011/03/11 05:22:38 sjg Exp $
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+# provide a hook for folk who want to do scary stuff
+.-include "${.CURDIR}/../Makefile-final.inc"
+
+.if !empty(STAGE)
+.-include <stage.mk>
+.endif
+
+.-include <local.final.mk>
+.endif
diff --git a/contrib/bmake/mk/gendirdeps.mk b/contrib/bmake/mk/gendirdeps.mk
new file mode 100644
index 0000000..890f495
--- /dev/null
+++ b/contrib/bmake/mk/gendirdeps.mk
@@ -0,0 +1,301 @@
+# $Id: gendirdeps.mk,v 1.10 2012/06/30 00:37:50 sjg Exp $
+
+# Copyright (c) 2010, Juniper Networks, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE 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
+# OWNER 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 makefile [re]generates ${.MAKE.DEPENDFILE}
+#
+
+.include <install-new.mk>
+
+# Assumptions:
+# RELDIR is the relative path from ${SRCTOP} to ${_CURDIR}
+# (SRCTOP is ${SB}/src)
+# _CURDIR is the absolute version of ${.CURDIR}
+# _OBJDIR is the absolute version of ${.OBJDIR}
+# _objroot is realpath of ${_OBJTOP} without ${MACHINE}
+# this may be different from _OBJROOT if $SB/obj is a
+# symlink to another filesystem.
+# _objroot must be a prefix match for _objtop
+
+.MAIN: all
+
+# keep this simple
+.MAKE.MODE = compat
+
+all:
+
+_CURDIR ?= ${.CURDIR}
+_OBJDIR ?= ${.OBJDIR}
+_OBJTOP ?= ${OBJTOP}
+_OBJROOT ?= ${OBJROOT:U${_OBJTOP}}
+_objroot ?= ${_OBJROOT:tA}
+
+_this = ${.PARSEDIR}/${.PARSEFILE}
+
+# remember what to make
+_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
+
+# We do _not_ want to read our own output!
+.MAKE.DEPENDFILE = /dev/null
+
+# caller should have set this
+META_FILES ?= ${.MAKE.META.FILES}
+
+.if !empty(META_FILES)
+
+.if ${.MAKE.LEVEL} > 0 && !empty(GENDIRDEPS_FILTER)
+# so we can compare below
+.-include <${_DEPENDFILE}>
+# yes, I mean :U with no value
+_DIRDEPS := ${DIRDEPS:U:O:u}
+.endif
+
+META_FILES := ${META_FILES:T:O:u}
+.export META_FILES
+
+# pickup customizations
+.-include "local.gendirdeps.mk"
+
+# these are actually prefixes that we'll skip
+# they should all be absolute paths
+SKIP_GENDIRDEPS ?=
+.if !empty(SKIP_GENDIRDEPS)
+_skip_gendirdeps = egrep -v '^(${SKIP_GENDIRDEPS:O:u:ts|})' |
+.else
+_skip_gendirdeps =
+.endif
+
+# this (*should* be set in meta.sys.mk)
+# is the script that extracts what we want.
+META2DEPS ?= ${.PARSEDIR}/meta2deps.sh
+META2DEPS := ${META2DEPS}
+
+.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" && ${DEBUG_GENDIRDEPS:Uno:Mmeta2d*} != ""
+_time = time
+_sh_x = sh -x
+_py_d = -ddd
+.else
+_time =
+_sh_x =
+_py_d =
+.endif
+
+.if ${META2DEPS:E} == "py"
+# we can afford to do this all the time.
+DPDEPS ?= no
+META2DEPS_CMD = ${_time} ${PYTHON} ${META2DEPS} ${_py_d} \
+ -R ${RELDIR} -H ${HOST_TARGET} -O ${M2D_OBJROOT}
+.if ${DPDEPS:tl} != "no"
+META2DEPS_CMD += -D ${DPDEPS}
+.endif
+.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} == ""
+# meta2deps.py only groks objroot
+# so we need to give it what it expects
+M2D_OBJROOT = ${OBJTOP}/
+# and tell it not to add machine qualifiers
+META2DEPS_ARGS += MACHINE=none
+.else
+.if defined(SB_OBJROOT)
+M2D_OBJROOT ?= ${SB_OBJROOT}
+.else
+M2D_OBJROOT = ${OBJTOP}/
+.endif
+.endif
+.if defined(SB_BACKING_SB)
+META2DEPS_CMD += -S ${SB_BACKING_SB}/src -O ${SB_BACKING_SB}/${SB_OBJPREFIX}
+.endif
+META2DEPS_FILTER = sed 's,^src:,${SRCTOP}/,;s,^\([^/]\),${OBJTOP}/\1,' |
+.elif ${META2DEPS:E} == "sh"
+META2DEPS_CMD = ${_time} ${_sh_x} ${META2DEPS} \
+ OBJTOP=${_objtop} SB_OBJROOT=${_objroot}
+.else
+META2DEPS_CMD ?= ${META2DEPS}
+.endif
+
+# we are only interested in the dirs
+# sepecifically those we read something from.
+# we canonicalize them to keep things simple
+# if we are using a split-fs sandbox, it gets a little messier.
+_objtop := ${_OBJTOP:tA}
+dir_list != cd ${_OBJDIR} && \
+ ${META2DEPS_CMD} MACHINE=${MACHINE} \
+ SRCTOP=${SRCTOP} RELDIR=${RELDIR} CURDIR=${_CURDIR} \
+ ${META2DEPS_ARGS} \
+ ${META_FILES:O:u} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \
+ sed 's,//*$$,,;s,\.${HOST_TARGET}$$,.host,'
+
+.if ${dir_list:M*ERROR\:*} != ""
+.warning ${dir_list:tW:C,.*(ERROR),\1,}
+.warning Skipping ${_DEPENDFILE:S,${SRCTOP}/,,}
+# we are not going to update anything
+.else
+
+.if !empty(DPADD)
+_nonlibs := ${DPADD:T:Nlib*:N*include}
+.if !empty(_nonlibs)
+dir_list += ${_nonlibs:@x@${DPADD:M*/$x}@:H:tA}
+.endif
+.endif
+
+# DIRDEPS represent things that had to have been built first
+# so they should all be undir OBJTOP.
+# Note that ${_OBJTOP}/bsd/include/machine will get reported
+# to us as $SRCTOP/bsd/sys/$MACHINE_ARCH/include meaning we
+# will want to visit bsd/include
+# so we add
+# ${"${dir_list:M*bsd/sys/${MACHINE_ARCH}/include}":?bsd/include:}
+# to GENDIRDEPS_DIR_LIST_XTRAS
+dirdep_list = \
+ ${dir_list:M${_objtop}*/*:C,${_objtop}[^/]*/,,} \
+ ${GENDIRDEPS_DIR_LIST_XTRAS}
+
+# anything we use from an object dir other than ours
+# needs to be qualified with its .<machine> suffix
+# (we used the pseudo machine "host" for the HOST_TARGET).
+qualdir_list = \
+ ${dir_list:M${_objroot}*/*/*:N${SRCTOP}*:N${_objtop}*:C,${_objroot}([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,}
+
+.if ${_OBJROOT} != ${_objroot}
+dirdep_list += \
+ ${dir_list:M${_OBJTOP}*/*:C,${_OBJTOP}[^/]*/,,}
+
+qualdir_list += \
+ ${dir_list:M${_OBJROOT}*/*/*:N${SRCTOP}*:N${_OBJTOP}*:C,${_OBJROOT}([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,}
+.endif
+
+dirdep_list := ${dirdep_list:O:u}
+qualdir_list := ${qualdir_list:O:u}
+
+DIRDEPS = \
+ ${dirdep_list:N${RELDIR}:N${RELDIR}/*} \
+ ${qualdir_list:N${RELDIR}.*:N${RELDIR}/*}
+
+# We only consider things below $RELDIR/ if they have a makefile.
+# This is the same test that _DIRDEPS_USE applies.
+# We have do a double test with dirdep_list as it _may_ contain
+# qualified dirs - if we got anything from a stage dir.
+# qualdir_list we know are all qualified.
+# It would be nice do peform this check for all of DIRDEPS,
+# but we cannot assume that all of the tree is present,
+# in fact we can only assume that RELDIR is.
+DIRDEPS += \
+ ${dirdep_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/$d/$m):?$d:${exists(${SRCTOP}/${d:R}/$m):?$d:}}@}@} \
+ ${qualdir_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/${d:R}/$m):?$d:}@}@}
+
+DIRDEPS := ${DIRDEPS:${GENDIRDEPS_FILTER:UNno:ts:}:O:u}
+
+.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != ""
+.info ${RELDIR}: dir_list='${dir_list}'
+.info ${RELDIR}: dirdep_list='${dirdep_list}'
+.info ${RELDIR}: qualdir_list='${qualdir_list}'
+.info ${RELDIR}: SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS}'
+.info ${RELDIR}: GENDIRDEPS_FILTER='${GENDIRDEPS_FILTER}'
+.info ${RELDIR}: FORCE_DPADD='${DPADD}'
+.info ${RELDIR}: DIRDEPS='${DIRDEPS}'
+.endif
+
+# SRC_DIRDEPS is for checkout logic
+src_dirdep_list = \
+ ${dir_list:M${SRCTOP}/*:S,${SRCTOP}/,,}
+
+SRC_DIRDEPS = \
+ ${src_dirdep_list:N${RELDIR}:N${RELDIR}/*:C,(/h)/.*,,}
+
+SRC_DIRDEPS := ${SRC_DIRDEPS:${GENDIRDEPS_SRC_FILTER:UN/*:ts:}:O:u}
+
+# if you want to capture SRC_DIRDEPS in .MAKE.DEPENDFILE put
+# SRC_DIRDEPS_FILE = ${_DEPENDFILE}
+# in local.gendirdeps.mk
+.if ${SRC_DIRDEPS_FILE:Uno:tl} != "no"
+ECHO_SRC_DIRDEPS = echo 'SRC_DIRDEPS = \'; echo '${SRC_DIRDEPS:@d@ $d \\${.newline}@}'; echo;
+
+.if ${SRC_DIRDEPS_FILE:T} == ${_DEPENDFILE:T}
+_include_src_dirdeps = ${ECHO_SRC_DIRDEPS}
+.else
+all: ${SRC_DIRDEPS_FILE}
+.if !target(${SRC_DIRDEPS_FILE})
+${SRC_DIRDEPS_FILE}: ${META_FILES} ${_this} ${META2DEPS}
+ @(${ECHO_SRC_DIRDEPS}) > $@
+.endif
+.endif
+.endif
+_include_src_dirdeps ?=
+
+all: ${_DEPENDFILE}
+
+# if this is going to exist it would be there by now
+.if !exists(.depend)
+CAT_DEPEND = /dev/null
+.endif
+CAT_DEPEND ?= .depend
+
+.if !empty(_DIRDEPS) && ${DIRDEPS} != ${_DIRDEPS}
+# we may have changed a filter
+.PHONY: ${_DEPENDFILE}
+.endif
+
+# 'cat .depend' should suffice, but if we are mixing build modes
+# .depend may contain things we don't want.
+# The sed command at the end of the stream, allows for the filters
+# to output _{VAR} tokens which we will turn into proper ${VAR} references.
+${_DEPENDFILE}: ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS}
+ @(echo '# Autogenerated - do NOT edit!'; echo; \
+ echo 'DEP_RELDIR := $${_PARSEDIR:S,$${SRCTOP}/,,}'; echo; \
+ echo 'DEP_MACHINE := $${.PARSEFILE:E}'; echo; \
+ echo 'DIRDEPS = \'; \
+ echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
+ ${_include_src_dirdeps} \
+ echo '.include <dirdeps.mk>'; \
+ echo; \
+ echo '.if $${DEP_RELDIR} == $${_DEP_RELDIR}'; \
+ echo '# local dependencies - needed for -jN in clean tree'; \
+ [ -s ${CAT_DEPEND} ] && { grep : ${CAT_DEPEND} | grep -v '[/\\]'; }; \
+ echo '.endif' ) | sed 's,_\([{(]\),$$\1,g' > $@.new${.MAKE.PID}
+ @${InstallNew}; InstallNew -s $@.new${.MAKE.PID}
+
+.endif # meta2deps failed
+.elif !empty(SUBDIR)
+
+DIRDEPS := ${SUBDIR:S,^,${RELDIR}/,:O:u}
+
+all: ${_DEPENDFILE}
+
+${_DEPENDFILE}: ${MAKEFILE} ${_this}
+ @(echo '# Autogenerated - do NOT edit!'; echo; \
+ echo 'DEP_RELDIR := $${_PARSEDIR:S,$${SRCTOP}/,,}'; echo; \
+ echo 'DEP_MACHINE := $${.PARSEFILE:E}'; echo; \
+ echo 'DIRDEPS = \'; \
+ echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \
+ echo '.include <dirdeps.mk>'; \
+ echo ) | sed 's,_\([{(]\),$$\1,g' > $@.new
+ @${InstallNew}; InstallNew $@.new
+
+.else
+
+# nothing to do
+all ${_DEPENDFILE}:
+
+.endif
+${_DEPENDFILE}: .PRECIOUS
diff --git a/contrib/bmake/mk/host-target.mk b/contrib/bmake/mk/host-target.mk
new file mode 100644
index 0000000..c6d4562
--- /dev/null
+++ b/contrib/bmake/mk/host-target.mk
@@ -0,0 +1,31 @@
+# RCSid:
+# $Id: host-target.mk,v 1.6 2011/03/02 05:05:21 sjg Exp $
+
+# Host platform information; may be overridden
+.if !defined(_HOST_OSNAME)
+_HOST_OSNAME != uname -s
+.export _HOST_OSNAME
+.endif
+.if !defined(_HOST_OSREL)
+_HOST_OSREL != uname -r
+.export _HOST_OSREL
+.endif
+.if !defined(_HOST_ARCH)
+_HOST_ARCH != uname -p 2>/dev/null || uname -m
+# uname -p may produce garbage on linux
+.if ${_HOST_ARCH:[\#]} > 1
+_HOST_ARCH != uname -m
+.endif
+.export _HOST_ARCH
+.endif
+
+HOST_OSMAJOR := ${_HOST_OSREL:C/[^0-9].*//}
+HOST_OSTYPE := ${_HOST_OSNAME}-${_HOST_OSREL:C/\([^\)]*\)//}-${_HOST_ARCH}
+HOST_OS := ${_HOST_OSNAME}
+host_os := ${_HOST_OSNAME:tl}
+HOST_TARGET := ${host_os}${HOST_OSMAJOR}-${_HOST_ARCH}
+
+# tr is insanely non-portable, accommodate the lowest common denominator
+TR ?= tr
+toLower = ${TR} 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
+toUpper = ${TR} 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
diff --git a/contrib/bmake/mk/host.libnames.mk b/contrib/bmake/mk/host.libnames.mk
new file mode 100644
index 0000000..c0a13d7
--- /dev/null
+++ b/contrib/bmake/mk/host.libnames.mk
@@ -0,0 +1,29 @@
+# $Id: host.libnames.mk,v 1.4 2010/01/11 23:01:31 sjg Exp $
+#
+# @(#) Copyright (c) 2007-2009, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+
+DLIBEXT ?= .a
+DSHLIBEXT ?= ${DLIBEXT}
+HOST_LIBEXT ?= ${DSHLIBEXT}
+HOST_LIBDIRS ?= /usr/lib /lib
+HOST_LIBS ?=
+
+.for x in ${HOST_LIBS:O:u}
+.for d in ${HOST_LIBDIRS}
+.if exists($d/lib$x${HOST_LIBEXT})
+LIB${x:tu} ?= $d/lib$x${HOST_LIBEXT}
+.endif
+.endfor
+.endfor
diff --git a/contrib/bmake/mk/inc.mk b/contrib/bmake/mk/inc.mk
new file mode 100644
index 0000000..5d57f52
--- /dev/null
+++ b/contrib/bmake/mk/inc.mk
@@ -0,0 +1,35 @@
+# $Id: inc.mk,v 1.3 2011/03/11 05:23:05 sjg Exp $
+#
+# @(#) Copyright (c) 2008, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.include <init.mk>
+
+includes: ${INCS}
+
+.if !empty(LIBOWN)
+INC_INSTALL_OWN ?= -o ${LIBOWN} -g ${LIBGRP}
+.endif
+INCMODE ?= 444
+INC_COPY ?= -C
+INCSDIR ?= ${INCDIR}
+
+realinstall: incinstall
+.if !target(incinstall)
+incinstall:
+.if !empty(INCS)
+ [ -d ${DESTDIR}${INCSDIR} ] || \
+ ${INSTALL} -d ${INC_INSTALL_OWN} -m 775 ${DESTDIR}${INCSDIR}
+ ${INSTALL} ${INC_COPY} ${INC_INSTALL_OWN} -m ${INCMODE} ${INCS} ${DESTDIR}${INCSDIR}
+.endif
+.endif
diff --git a/contrib/bmake/mk/init.mk b/contrib/bmake/mk/init.mk
new file mode 100644
index 0000000..ed63fe6
--- /dev/null
+++ b/contrib/bmake/mk/init.mk
@@ -0,0 +1,44 @@
+# $Id: init.mk,v 1.8 2012/11/11 22:37:02 sjg Exp $
+#
+# @(#) Copyright (c) 2002, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+.if ${MAKE_VERSION:U0} > 20100408
+_this_mk_dir := ${.PARSEDIR:tA}
+.else
+_this_mk_dir := ${.PARSEDIR}
+.endif
+
+.-include <local.init.mk>
+.-include "${.CURDIR:H}/Makefile.inc"
+.include <own.mk>
+
+.MAIN: all
+
+.if !empty(WARNINGS_SET) || !empty(WARNINGS_SET_${MACHINE_ARCH})
+.include <warnings.mk>
+.endif
+
+COPTS += ${COPTS.${.IMPSRC:T}}
+CPPFLAGS += ${CPPFLAGS.${.IMPSRC:T}}
+CPUFLAGS += ${CPUFLAGS.${.IMPSRC:T}}
+
+.if ${.MAKE.LEVEL:U1} == 0 && ${BUILD_AT_LEVEL0:Uyes:tl} == "no"
+# this tells lib.mk and prog.mk to not actually build anything
+_SKIP_BUILD = not building at level 0
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/install-mk b/contrib/bmake/mk/install-mk
new file mode 100644
index 0000000..7dea1fc
--- /dev/null
+++ b/contrib/bmake/mk/install-mk
@@ -0,0 +1,185 @@
+:
+# NAME:
+# install-mk - install mk files
+#
+# SYNOPSIS:
+# install-mk [options] [var=val] [dest]
+#
+# DESCRIPTION:
+# This tool installs mk files in a semi-intelligent manner into
+# "dest".
+#
+# Options:
+#
+# -n just say what we want to do, but don't touch anything.
+#
+# -f use -f when copying sys,mk.
+#
+# -v be verbose
+#
+# -q be quiet
+#
+# -m "mode"
+# Use "mode" for installed files (444).
+#
+# -o "owner"
+# Use "owner" for installed files.
+#
+# -g "group"
+# Use "group" for installed files.
+#
+# var=val
+# Set "var" to "val". See below.
+#
+# All our *.mk files are copied to "dest" with appropriate
+# ownership and permissions.
+#
+# By default if a sys.mk can be found in a standard location
+# (that bmake will find) then no sys.mk will be put in "dest".
+#
+# SKIP_SYS_MK:
+# If set, we will avoid installing our 'sys.mk'
+# This is probably a bad idea.
+#
+# SKIP_BSD_MK:
+# If set, we will skip making bsd.*.mk links to *.mk
+#
+# sys.mk:
+#
+# By default (and provided we are not installing to the system
+# mk dir - '/usr/share/mk') we install our own 'sys.mk' which
+# includes a sys specific file, or a generic one.
+#
+#
+# AUTHOR:
+# Simon J. Gerraty <sjg@crufty.net>
+
+# RCSid:
+# $Id: install-mk,v 1.83 2013/01/24 01:02:23 sjg Exp $
+#
+# @(#) Copyright (c) 1994 Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+MK_VERSION=20130123
+OWNER=
+GROUP=
+MODE=444
+BINMODE=555
+ECHO=:
+SKIP=
+cp_f=-f
+
+while :
+do
+ case "$1" in
+ *=*) eval "$1"; shift;;
+ +f) cp_f=; shift;;
+ -f) cp_f=-f; shift;;
+ -m) MODE=$2; shift 2;;
+ -o) OWNER=$2; shift 2;;
+ -g) GROUP=$2; shift 2;;
+ -v) ECHO=echo; shift;;
+ -q) ECHO=:; shift;;
+ -n) ECHO=echo SKIP=:; shift;;
+ --) shift; break;;
+ *) break;;
+ esac
+done
+
+case $# in
+0) echo "$0 [options] <destination> [<os>]"
+ echo "eg."
+ echo "$0 -o bin -g bin -m 444 /usr/local/share/mk"
+ exit 1
+ ;;
+esac
+dest=$1
+os=${2:-`uname`}
+osrel=${3:-`uname -r`}
+
+Do() {
+ $ECHO "$@"
+ $SKIP "$@"
+}
+
+Error() {
+ echo "ERROR: $@" >&2
+ exit 1
+}
+
+Warning() {
+ echo "WARNING: $@" >&2
+}
+
+[ "$FORCE_SYS_MK" ] && Warning "ignoring: FORCE_{BSD,SYS}_MK (no longer supported)"
+
+SYS_MK_DIR=${SYS_MK_DIR:-/usr/share/mk}
+SYS_MK=${SYS_MK:-$SYS_MK_DIR/sys.mk}
+
+realpath() {
+ [ -d $1 ] && cd $1 && 'pwd' && return
+ echo $1
+}
+
+if [ -s $SYS_MK -a -d $dest ]; then
+ # if this is a BSD system we don't want to touch $SYS_MK
+ dest=`realpath $dest`
+ sys_mk_dir=`realpath $SYS_MK_DIR`
+ if [ $dest = $sys_mk_dir ]; then
+ case "$os" in
+ *BSD*) SKIP_SYS_MK=:
+ SKIP_BSD_MK=:
+ ;;
+ *) # could be fake?
+ if [ ! -d $dest/sys -a ! -s $dest/Generic.sys.mk ]; then
+ SKIP_SYS_MK=: # play safe
+ SKIP_BSD_MK=:
+ fi
+ ;;
+ esac
+ fi
+fi
+
+[ -d $dest/sys ] || Do mkdir -p $dest/sys
+[ -d $dest/sys ] || Do mkdir $dest/sys || exit 1
+[ -z "$SKIP" ] && dest=`realpath $dest`
+
+cd `dirname $0`
+mksrc=`'pwd'`
+if [ $mksrc = $dest ]; then
+ SKIP_MKFILES=:
+else
+ # we do not install the examples
+ mk_files=`grep '^[a-z].*\.mk' FILES | egrep -v '(examples/|^sys\.mk|sys/)'`
+ mk_scripts=`egrep '^[a-z].*\.(sh|py)' FILES | egrep -v '/'`
+ sys_mk_files=`grep 'sys/.*\.mk' FILES`
+ SKIP_MKFILES=
+ [ -z "$SKIP_SYS_MK" ] && mk_files="sys.mk $mk_files"
+fi
+$SKIP_MKFILES Do cp $cp_f $mk_files $dest
+$SKIP_MKFILES Do cp $cp_f $sys_mk_files $dest/sys
+$SKIP_MKFILES Do cp $cp_f $mk_scripts $dest
+$SKIP cd $dest
+$SKIP_MKFILES Do chmod $MODE $mk_files $sys_mk_files
+$SKIP_MKFILES Do chmod $BINMODE $mk_scripts
+[ "$GROUP" ] && $SKIP_MKFILES Do chgrp $GROUP $mk_files $sys_mk_files
+[ "$OWNER" ] && $SKIP_MKFILES Do chown $OWNER $mk_files $sys_mk_files
+# if this is a BSD system the bsd.*.mk should exist and be used.
+if [ -z "$SKIP_BSD_MK" ]; then
+ for f in dep doc init lib links man nls obj own prog subdir
+ do
+ b=bsd.$f.mk
+ [ -s $b ] || Do ln -s $f.mk $b
+ done
+fi
+exit 0
diff --git a/contrib/bmake/mk/install-new.mk b/contrib/bmake/mk/install-new.mk
new file mode 100644
index 0000000..ddfff20
--- /dev/null
+++ b/contrib/bmake/mk/install-new.mk
@@ -0,0 +1,53 @@
+# $Id: install-new.mk,v 1.3 2012/03/24 18:25:49 sjg Exp $
+#
+# @(#) Copyright (c) 2009, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !defined(InstallNew)
+
+# copy if src and target are different making a backup if desired
+CmpCp= CmpCp() { \
+ src=$$1 target=$$2 _bak=$$3; \
+ if ! test -s $$target || ! cmp -s $$target $$src; then \
+ trap "" 1 2 3 15; \
+ if test -s $$target; then \
+ if test "x$$_bak" != x; then \
+ rm -f $$target$$_bak; \
+ mv $$target $$target$$_bak; \
+ else \
+ rm -f $$target; \
+ fi; \
+ fi; \
+ cp $$src $$target; \
+ fi; }
+
+# If the .new file is different, we want it.
+# Note: this function will work as is for *.new$RANDOM"
+InstallNew= ${CmpCp}; InstallNew() { \
+ _t=-e; _bak=; \
+ while :; do \
+ case "$$1" in \
+ -?) _t=$$1; shift;; \
+ --bak) _bak=$$2; shift 2;; \
+ *) break;; \
+ esac; \
+ done; \
+ for new in "$$@"; do \
+ if test $$_t $$new; then \
+ target=`expr $$new : '\(.*\).new'`; \
+ CmpCp $$new $$target $$_bak; \
+ fi; \
+ rm -f $$new; \
+ done; :; }
+
+.endif
diff --git a/contrib/bmake/mk/java.mk b/contrib/bmake/mk/java.mk
new file mode 100644
index 0000000..ef4a5ea
--- /dev/null
+++ b/contrib/bmake/mk/java.mk
@@ -0,0 +1,97 @@
+#
+# RCSid:
+# $Id: java.mk,v 1.14 2007/11/22 08:16:25 sjg Exp $
+
+# @(#) Copyright (c) 1998-2001, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+.include <init.mk>
+
+CLASSPATH?=.
+
+.if defined(PROG)
+SRCS?= ${PROG:.class=.java}
+.endif
+.if !defined(SRCS) || empty(SRCS)
+SRCS!=cd ${.CURDIR} && echo *.java
+.endif
+.SUFFIXES: .class .java
+
+CLEANFILES+= *.class
+
+JAVAC?= javac
+JAVADOC?= javadoc
+
+.if !target(docs)
+docs:
+ ${JAVADOC} ${JAVADOC_FLAGS} ${SRCS}
+.endif
+
+.if defined(JAVADESTDIR) && !empty(JAVADESTDIR)
+JAVASRCDIR?=${JAVADESTDIR:H}/src
+__classdest:=${JAVADESTDIR}${.CURDIR:S,${JAVASRCDIR},,}/
+CLASSPATH:=${CLASSPATH}:${JAVADESTDIR}
+JAVAC_FLAGS+= -d ${JAVADESTDIR}
+.else
+__classdest=
+.endif
+
+JAVAC_FLAGS+= ${JAVAC_DBG}
+
+.if defined(MAKE_VERSION) && !defined(NO_CLASSES_COOKIE)
+# java works best by compiling a bunch of classes at once.
+# this lot does that but needs a recent netbsd make or
+# or its portable cousin bmake.
+.for __s in ${SRCS}
+__c:= ${__classdest}${__s:.java=.class}
+.if !target(${__c})
+# We need to do something to force __c's parent to be made.
+${__c}: ${__s}
+ @rm -f ${.TARGET}
+.endif
+SRCS_${__c}=${__s}
+__classes:= ${__classes} ${__c}
+.endfor
+__classes_cookie=${__classdest}.classes.done
+CLEANFILES+= ${__classes} ${__classes_cookie}
+
+${__classes_cookie}: ${__classes}
+ CLASSPATH=${CLASSPATH} ${JAVAC} ${JAVAC_FLAGS} ${.OODATE:@c@${SRCS_$c}@}
+ @touch ${.TARGET}
+
+all: ${__classes_cookie}
+
+.else
+# this will work with other BSD make's
+.for __s in ${SRCS}
+__c:= ${__classdest}${__s:.java=.class}
+${__c}: ${__s}
+ CLASSPATH=${CLASSPATH} ${JAVAC} ${JAVAC_FLAGS} ${.OODATE}
+.endfor
+
+all: ${SRCS:%.java=${__classdest}%.class}
+
+.endif
+
+.if !target(cleanjava)
+cleanjava:
+ rm -f [Ee]rrs mklog core *.core ${PROG} ${CLEANFILES}
+
+clean: cleanjava
+cleandir: cleanjava
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/lib.mk b/contrib/bmake/mk/lib.mk
new file mode 100644
index 0000000..24f9527
--- /dev/null
+++ b/contrib/bmake/mk/lib.mk
@@ -0,0 +1,605 @@
+# $Id: lib.mk,v 1.48 2012/11/12 04:08:18 sjg Exp $
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+.include <init.mk>
+
+.if ${OBJECT_FMT} == "ELF"
+NEED_SOLINKS?= yes
+.endif
+
+.if exists(${.CURDIR}/shlib_version)
+SHLIB_MAJOR != . ${.CURDIR}/shlib_version ; echo $$major
+SHLIB_MINOR != . ${.CURDIR}/shlib_version ; echo $$minor
+.endif
+
+print-shlib-major:
+.if defined(SHLIB_MAJOR) && ${MK_PIC} != "no"
+ @echo ${SHLIB_MAJOR}
+.else
+ @false
+.endif
+
+print-shlib-minor:
+.if defined(SHLIB_MINOR) && ${MK_PIC} != "no"
+ @echo ${SHLIB_MINOR}
+.else
+ @false
+.endif
+
+print-shlib-teeny:
+.if defined(SHLIB_TEENY) && ${MK_PIC} != "no"
+ @echo ${SHLIB_TEENY}
+.else
+ @false
+.endif
+
+SHLIB_FULLVERSION ?= ${${SHLIB_MAJOR} ${SHLIB_MINOR} ${SHLIB_TEENY}:L:ts.}
+SHLIB_FULLVERSION := ${SHLIB_FULLVERSION}
+
+# add additional suffixes not exported.
+# .po is used for profiling object files.
+# .so is used for PIC object files.
+.SUFFIXES: .out .a .ln .so .po .o .s .S .c .cc .C .m .F .f .r .y .l .cl .p .h
+.SUFFIXES: .sh .m4 .m
+
+CFLAGS+= ${COPTS}
+
+# Derrived from NetBSD-1.6
+
+# Set PICFLAGS to cc flags for producing position-independent code,
+# if not already set. Includes -DPIC, if required.
+
+# Data-driven table using make variables to control how shared libraries
+# are built for different platforms and object formats.
+# OBJECT_FMT: currently either "ELF" or "a.out", from <bsd.own.mk>
+# SHLIB_SOVERSION: version number to be compiled into a shared library
+# via -soname. Usualy ${SHLIB_MAJOR} on ELF.
+# NetBSD/pmax used to use ${SHLIB_MAJOR}[.${SHLIB_MINOR}
+# [.${SHLIB_TEENY}]]
+# SHLIB_SHFLAGS: Flags to tell ${LD} to emit shared library.
+# with ELF, also set shared-lib version for ld.so.
+# SHLIB_LDSTARTFILE: support .o file, call C++ file-level constructors
+# SHLIB_LDENDFILE: support .o file, call C++ file-level destructors
+# FPICFLAGS: flags for ${FC} to compile .[fF] files to .so objects.
+# CPPICFLAGS: flags for ${CPP} to preprocess .[sS] files for ${AS}
+# CPICFLAGS: flags for ${CC} to compile .[cC] files to .so objects.
+# CAPICFLAGS flags for {$CC} to compiling .[Ss] files
+# (usually just ${CPPPICFLAGS} ${CPICFLAGS})
+# APICFLAGS: flags for ${AS} to assemble .[sS] to .so objects.
+
+.if ${TARGET_OSNAME} == "NetBSD"
+.if ${MACHINE_ARCH} == "alpha"
+ # Alpha-specific shared library flags
+FPICFLAGS ?= -fPIC
+CPICFLAGS ?= -fPIC -DPIC
+CPPPICFLAGS?= -DPIC
+CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS}
+APICFLAGS ?=
+.elif ${MACHINE_ARCH} == "mipsel" || ${MACHINE_ARCH} == "mipseb"
+ # mips-specific shared library flags
+
+# On mips, all libs are compiled with ABIcalls, not just sharedlibs.
+MKPICLIB= no
+
+# so turn shlib PIC flags on for ${AS}.
+AINC+=-DABICALLS
+AFLAGS+= -fPIC
+AS+= -KPIC
+
+.elif ${MACHINE_ARCH} == "vax" && ${OBJECT_FMT} == "ELF"
+# On the VAX, all object are PIC by default, not just sharedlibs.
+MKPICLIB= no
+
+.elif (${MACHINE_ARCH} == "sparc" || ${MACHINE_ARCH} == "sparc64") && \
+ ${OBJECT_FMT} == "ELF"
+# If you use -fPIC you need to define BIGPIC to turn on 32-bit
+# relocations in asm code
+FPICFLAGS ?= -fPIC
+CPICFLAGS ?= -fPIC -DPIC
+CPPPICFLAGS?= -DPIC -DBIGPIC
+CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS}
+APICFLAGS ?= -KPIC
+
+.else
+
+# Platform-independent flags for NetBSD a.out shared libraries
+SHLIB_SOVERSION=${SHLIB_FULLVERSION}
+SHLIB_SHFLAGS=
+FPICFLAGS ?= -fPIC
+CPICFLAGS?= -fPIC -DPIC
+CPPPICFLAGS?= -DPIC
+CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS}
+APICFLAGS?= -k
+
+.endif
+
+# Platform-independent linker flags for ELF shared libraries
+.if ${OBJECT_FMT} == "ELF"
+SHLIB_SOVERSION= ${SHLIB_MAJOR}
+SHLIB_SHFLAGS= -soname lib${LIB}.so.${SHLIB_SOVERSION}
+SHLIB_LDSTARTFILE?= /usr/lib/crtbeginS.o
+SHLIB_LDENDFILE?= /usr/lib/crtendS.o
+.endif
+
+# for compatability with the following
+CC_PIC?= ${CPICFLAGS}
+LD_shared=${SHLIB_SHFLAGS}
+
+.endif # NetBSD
+
+.if ${TARGET_OSNAME} == "FreeBSD"
+.if ${OBJECT_FMT} == "ELF"
+SHLIB_SOVERSION= ${SHLIB_MAJOR}
+SHLIB_SHFLAGS= -soname lib${LIB}.so.${SHLIB_SOVERSION}
+.else
+SHLIB_SHFLAGS= -assert pure-text
+.endif
+SHLIB_LDSTARTFILE=
+SHLIB_LDENDFILE=
+CC_PIC?= -fpic
+LD_shared=${SHLIB_SHFLAGS}
+
+.endif # FreeBSD
+
+MKPICLIB?= yes
+
+# sys.mk can override these
+CC_PG?=-pg
+CC_PIC?=-DPIC
+
+LD_X?=-X
+LD_x?=-x
+LD_r?=-r
+
+# Non BSD machines will be using bmake.
+.if ${TARGET_OSNAME} == "SunOS"
+LD_shared=-assert pure-text
+.if ${OBJECT_FMT} == "ELF" || ${MACHINE} == "solaris"
+# Solaris
+LD_shared=-h lib${LIB}.so.${SHLIB_MAJOR} -G
+.endif
+.elif ${TARGET_OSNAME} == "HP-UX"
+LD_shared=-b
+LD_so=sl
+DLLIB=
+# HPsUX lorder does not grok anything but .o
+LD_sobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,.so,'`
+LD_pobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,.po,'`
+.elif ${TARGET_OSNAME} == "OSF1"
+LD_shared= -msym -shared -expect_unresolved '*'
+LD_solib= -all lib${LIB}_pic.a
+DLLIB=
+# lorder does not grok anything but .o
+LD_sobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,.so,'`
+LD_pobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,.po,'`
+AR_cq= -cqs
+.elif ${TARGET_OSNAME} == "FreeBSD"
+LD_solib= lib${LIB}_pic.a
+.elif ${TARGET_OSNAME} == "Linux"
+# this is ambiguous of course
+LD_shared=-shared -h lib${LIB}.so.${SHLIB_MAJOR}
+LD_solib= --whole-archive lib${LIB}_pic.a
+# Linux uses GNU ld, which is a multi-pass linker
+# so we don't need to use lorder or tsort
+LD_objs = ${OBJS}
+LD_pobjs = ${POBJS}
+LD_sobjs = ${SOBJS}
+.elif ${TARGET_OSNAME} == "Darwin"
+SHLIB_LD = ${CC}
+SHLIB_INSTALL_VERSION ?= ${SHLIB_MAJOR}
+SHLIB_COMPATABILITY_VERSION ?= ${SHLIB_MAJOR}.${SHLIB_MINOR:U0}
+SHLIB_COMPATABILITY ?= \
+ -compatibility_version ${SHLIB_COMPATABILITY_VERSION} \
+ -current_version ${SHLIB_FULLVERSION}
+LD_shared = -dynamiclib \
+ -flat_namespace -undefined suppress \
+ -install_name ${LIBDIR}/lib${LIB}.${SHLIB_INSTALL_VERSION}.${LD_solink} \
+ ${SHLIB_COMPATABILITY}
+SHLIB_LINKS =
+.for v in ${SHLIB_COMPATABILITY_VERSION} ${SHLIB_INSTALL_VERSION}
+.if "$v" != "${SHLIB_FULLVERSION}"
+SHLIB_LINKS += lib${LIB}.$v.${LD_solink}
+.endif
+.endfor
+.if ${MK_LINKLIB} != "no"
+SHLIB_LINKS += lib${LIB}.${LD_solink}
+.endif
+
+LD_so = ${SHLIB_FULLVERSION}.dylib
+LD_sobjs = ${SOBJS:O:u}
+LD_solib = ${LD_sobjs}
+SOLIB = ${LD_sobjs}
+LD_solink = dylib
+.if ${MACHINE_ARCH} == "i386"
+PICFLAG ?= -fPIC
+.else
+PICFLAG ?= -fPIC -fno-common
+.endif
+RANLIB = :
+.endif
+
+SHLIB_LD ?= ${LD}
+
+.if !empty(SHLIB_MAJOR)
+.if ${NEED_SOLINKS} && empty(SHLIB_LINKS)
+.if ${MK_LINKLIB} != "no"
+SHLIB_LINKS = lib${LIB}.${LD_solink}
+.endif
+.if "${SHLIB_FULLVERSION}" != "${SHLIB_MAJOR}"
+SHLIB_LINKS += lib${LIB}.${LD_solink}.${SHLIB_MAJOR}
+.endif
+.endif
+.endif
+
+LIBTOOL?=libtool
+LD_shared ?= -Bshareable -Bforcearchive
+LD_so ?= so.${SHLIB_FULLVERSION}
+LD_solink ?= so
+.if empty(LORDER)
+LD_objs ?= ${OBJS}
+LD_pobjs ?= ${POBJS}
+LD_sobjs ?= ${SOBJS}
+.else
+LD_objs ?= `${LORDER} ${OBJS} | ${TSORT}`
+LD_sobjs ?= `${LORDER} ${SOBJS} | ${TSORT}`
+LD_pobjs ?= `${LORDER} ${POBJS} | ${TSORT}`
+.endif
+LD_solib ?= ${LD_sobjs}
+AR_cq ?= cq
+.if exists(/netbsd) && exists(${DESTDIR}/usr/lib/libdl.so)
+DLLIB ?= -ldl
+.endif
+
+# some libs have lots of objects, and scanning all .o, .po and .So meta files
+# is a waste of time, this tells meta.autodep.mk to just pick one
+# (typically .So)
+# yes, 42 is a random number.
+.if ${MK_META_MODE} == "yes" && ${SRCS:Uno:[\#]} > 42
+OPTIMIZE_OBJECT_META_FILES ?= yes
+.endif
+
+
+.if ${MK_LIBTOOL} == "yes"
+# because libtool is so facist about naming the object files,
+# we cannot (yet) build profiled libs
+MK_PROFILE=no
+_LIBS=lib${LIB}.a
+.if exists(${.CURDIR}/shlib_version)
+SHLIB_AGE != . ${.CURDIR}/shlib_version ; echo $$age
+.endif
+.else
+# for the normal .a we do not want to strip symbols
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+
+# for the normal .a we do not want to strip symbols
+.cc.o .C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+
+.S.o .s.o:
+ @echo ${COMPILE.S} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC}
+ @${COMPILE.S} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC}
+
+.if (${LD_X} == "")
+.c.po:
+ ${COMPILE.c} ${CC_PG} ${.IMPSRC} -o ${.TARGET}
+
+.cc.po .C.po:
+ ${COMPILE.cc} -pg ${.IMPSRC} -o ${.TARGET}
+
+.S.so .s.so:
+ ${COMPILE.S} ${PICFLAG} ${CC_PIC} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}
+.else
+.c.po:
+ @echo ${COMPILE.c} ${CC_PG} ${.IMPSRC} -o ${.TARGET}
+ @${COMPILE.c} ${CC_PG} ${.IMPSRC} -o ${.TARGET}.o
+ @${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET}
+ @rm -f ${.TARGET}.o
+
+.cc.po .C.po:
+ @echo ${COMPILE.cc} -pg ${.IMPSRC} -o ${.TARGET}
+ @${COMPILE.cc} -pg ${.IMPSRC} -o ${.TARGET}.o
+ @${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET}
+ @rm -f ${.TARGET}.o
+
+.S.so .s.so:
+ @echo ${COMPILE.S} ${PICFLAG} ${CC_PIC} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}
+ @${COMPILE.S} ${PICFLAG} ${CC_PIC} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}.o
+ @${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET}
+ @rm -f ${.TARGET}.o
+.endif
+
+.if (${LD_x} == "")
+.c.so:
+ ${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}
+
+.cc.so .C.so:
+ ${COMPILE.cc} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}
+
+.S.po .s.po:
+ ${COMPILE.S} -DGPROF -DPROF ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}
+.else
+
+.c.so:
+ @echo ${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}
+ @${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}.o
+ @${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET}
+ @rm -f ${.TARGET}.o
+
+.cc.so .C.so:
+ @echo ${COMPILE.cc} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}
+ @${COMPILE.cc} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}.o
+ @${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET}
+ @rm -f ${.TARGET}.o
+
+.S.po .s.po:
+ @echo ${COMPILE.S} -DGPROF -DPROF ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}
+ @${COMPILE.S} -DGPROF -DPROF ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}.o
+ @${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET}
+ @rm -f ${.TARGET}.o
+
+.endif
+.endif
+
+.c.ln:
+ ${LINT} ${LINTFLAGS} ${CFLAGS:M-[IDU]*} -i ${.IMPSRC}
+
+.if ${MK_LIBTOOL} != "yes"
+
+.if !defined(PICFLAG)
+PICFLAG=-fpic
+.endif
+
+_LIBS=
+
+.if ${MK_ARCHIVE} != "no"
+_LIBS += lib${LIB}.a
+.endif
+
+.if ${MK_PROFILE} != "no"
+_LIBS+=lib${LIB}_p.a
+POBJS+=${OBJS:.o=.po}
+.endif
+
+.if ${MK_PIC} != "no"
+.if ${MK_PICLIB} == "no"
+SOLIB ?= lib${LIB}.a
+.else
+SOLIB=lib${LIB}_pic.a
+_LIBS+=${SOLIB}
+.endif
+.if !empty(SHLIB_FULLVERSION)
+_LIBS+=lib${LIB}.${LD_so}
+.endif
+.endif
+
+.if ${MK_LINT} != "no"
+_LIBS+=llib-l${LIB}.ln
+.endif
+
+# here is where you can define what LIB* are
+.-include <libnames.mk>
+.if ${MK_DPADD_MK} == "yes"
+# lots of cool magic, but might not suit everyone.
+.include <dpadd.mk>
+.endif
+
+.if !defined(_SKIP_BUILD)
+all: prebuild .WAIT ${_LIBS}
+# a hook for things that must be done early
+prebuild:
+.if !defined(.PARSEDIR)
+# no-op is the best we can do if not bmake.
+.WAIT:
+.endif
+.endif
+all: _SUBDIRUSE
+
+.for s in ${SRCS:N*.h:M*/*}
+${.o .so .po .lo:L:@o@${s:T:R}$o@}: $s
+.endfor
+
+OBJS+= ${SRCS:T:N*.h:R:S/$/.o/g}
+.NOPATH: ${OBJS}
+
+.if ${MK_LIBTOOL} == "yes"
+.if ${MK_PIC} == "no"
+LT_STATIC=-static
+.else
+LT_STATIC=
+.endif
+SHLIB_AGE?=0
+
+# .lo's are created as a side effect
+.s.o .S.o .c.o:
+ ${LIBTOOL} --mode=compile ${CC} ${LT_STATIC} ${CFLAGS} ${CPPFLAGS} ${IMPFLAGS} -c ${.IMPSRC}
+
+# can't really do profiled libs with libtool - its too facist about
+# naming the output...
+lib${LIB}.a:: ${OBJS}
+ @rm -f ${.TARGET}
+ ${LIBTOOL} --mode=link ${CC} ${LT_STATIC} -o ${.TARGET:.a=.la} ${OBJS:.o=.lo} -rpath ${SHLIBDIR}:/usr/lib -version-info ${SHLIB_MAJOR}:${SHLIB_MINOR}:${SHLIB_AGE}
+ @ln .libs/${.TARGET} .
+
+lib${LIB}.${LD_so}:: lib${LIB}.a
+ @[ -s ${.TARGET}.${SHLIB_AGE} ] || { ln -s .libs/lib${LIB}.${LD_so}* . 2>/dev/null; : }
+ @[ -s ${.TARGET} ] || ln -s ${.TARGET}.${SHLIB_AGE} ${.TARGET}
+
+.else # MK_LIBTOOL=yes
+
+lib${LIB}.a:: ${OBJS}
+ @echo building standard ${LIB} library
+ @rm -f ${.TARGET}
+ @${AR} ${AR_cq} ${.TARGET} ${LD_objs}
+ ${RANLIB} ${.TARGET}
+
+POBJS+= ${OBJS:.o=.po}
+.NOPATH: ${POBJS}
+lib${LIB}_p.a:: ${POBJS}
+ @echo building profiled ${LIB} library
+ @rm -f ${.TARGET}
+ @${AR} ${AR_cq} ${.TARGET} ${LD_pobjs}
+ ${RANLIB} ${.TARGET}
+
+SOBJS+= ${OBJS:.o=.so}
+.NOPATH: ${SOBJS}
+lib${LIB}_pic.a:: ${SOBJS}
+ @echo building shared object ${LIB} library
+ @rm -f ${.TARGET}
+ @${AR} ${AR_cq} ${.TARGET} ${LD_sobjs}
+ ${RANLIB} ${.TARGET}
+
+#SHLIB_LDADD?= ${LDADD}
+
+# bound to be non-portable...
+# this is known to work for NetBSD 1.6 and FreeBSD 4.2
+lib${LIB}.${LD_so}: ${SOLIB} ${DPADD}
+ @echo building shared ${LIB} library \(version ${SHLIB_FULLVERSION}\)
+ @rm -f ${.TARGET}
+.if ${TARGET_OSNAME} == "NetBSD" || ${TARGET_OSNAME} == "FreeBSD"
+.if ${OBJECT_FMT} == "ELF"
+ ${SHLIB_LD} -x -shared ${SHLIB_SHFLAGS} -o ${.TARGET} \
+ ${SHLIB_LDSTARTFILE} \
+ --whole-archive ${SOLIB} --no-whole-archive ${SHLIB_LDADD} \
+ ${SHLIB_LDENDFILE}
+.else
+ ${SHLIB_LD} ${LD_x} ${LD_shared} \
+ -o ${.TARGET} ${SOLIB} ${SHLIB_LDADD}
+.endif
+.else
+ ${SHLIB_LD} -o ${.TARGET} ${LD_shared} ${LD_solib} ${DLLIB} ${SHLIB_LDADD}
+.endif
+.endif
+.if !empty(SHLIB_LINKS)
+ rm -f ${SHLIB_LINKS}; ${SHLIB_LINKS:O:u:@x@ln -s ${.TARGET} $x;@}
+.endif
+
+LOBJS+= ${LSRCS:.c=.ln} ${SRCS:M*.c:.c=.ln}
+.NOPATH: ${LOBJS}
+LLIBS?= -lc
+llib-l${LIB}.ln: ${LOBJS}
+ @echo building llib-l${LIB}.ln
+ @rm -f llib-l${LIB}.ln
+ @${LINT} -C${LIB} ${LOBJS} ${LLIBS}
+
+.if !target(clean)
+cleanlib: .PHONY
+ rm -f a.out [Ee]rrs mklog core *.core ${CLEANFILES}
+ rm -f lib${LIB}.a ${OBJS}
+ rm -f lib${LIB}_p.a ${POBJS}
+ rm -f lib${LIB}_pic.a lib${LIB}.so.*.* ${SOBJS}
+ rm -f llib-l${LIB}.ln ${LOBJS}
+.if !empty(SHLIB_LINKS)
+ rm -f ${SHLIB_LINKS}
+.endif
+
+clean: _SUBDIRUSE cleanlib
+cleandir: _SUBDIRUSE cleanlib
+.else
+cleandir: _SUBDIRUSE clean
+.endif
+
+.if defined(SRCS) && (!defined(MKDEP) || ${MKDEP} != autodep)
+afterdepend: .depend
+ @(TMP=/tmp/_depend$$$$; \
+ sed -e 's/^\([^\.]*\).o[ ]*:/\1.o \1.po \1.so \1.ln:/' \
+ < .depend > $$TMP; \
+ mv $$TMP .depend)
+.endif
+
+.if !target(install)
+.if !target(beforeinstall)
+beforeinstall:
+.endif
+
+.if !empty(LIBOWN)
+LIB_INSTALL_OWN ?= -o ${LIBOWN} -g ${LIBGRP}
+.endif
+
+.include <links.mk>
+
+.if !target(realinstall)
+realinstall: libinstall
+.endif
+.if !target(libinstall)
+libinstall:
+ [ -d ${DESTDIR}/${LIBDIR} ] || \
+ ${INSTALL} -d ${LIB_INSTALL_OWN} -m 775 ${DESTDIR}${LIBDIR}
+.if ${MK_ARCHIVE} != "no"
+ ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 600 lib${LIB}.a \
+ ${DESTDIR}${LIBDIR}
+ ${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}.a
+ chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}.a
+.endif
+.if ${MK_PROFILE} != "no"
+ ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 600 \
+ lib${LIB}_p.a ${DESTDIR}${LIBDIR}
+ ${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}_p.a
+ chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}_p.a
+.endif
+.if ${MK_PIC} != "no"
+.if ${MK_PICLIB} != "no"
+ ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 600 \
+ lib${LIB}_pic.a ${DESTDIR}${LIBDIR}
+ ${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}_pic.a
+ chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}_pic.a
+.endif
+.if !empty(SHLIB_MAJOR)
+ ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m ${LIBMODE} \
+ lib${LIB}.${LD_so} ${DESTDIR}${LIBDIR}
+.if !empty(SHLIB_LINKS)
+ (cd ${DESTDIR}${LIBDIR} && { rm -f ${SHLIB_LINKS}; ${SHLIB_LINKS:O:u:@x@ln -s lib${LIB}.${LD_so} $x;@} })
+.endif
+.endif
+.endif
+.if ${MK_LINT} != "no" && ${MK_LINKLIB} != "no" && !empty(LOBJS)
+ ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m ${LIBMODE} \
+ llib-l${LIB}.ln ${DESTDIR}${LINTLIBDIR}
+.endif
+.if defined(LINKS) && !empty(LINKS)
+ @set ${LINKS}; ${_LINKS_SCRIPT}
+.endif
+.endif
+
+install: maninstall _SUBDIRUSE
+maninstall: afterinstall
+afterinstall: realinstall
+realinstall: beforeinstall
+.endif
+
+.if ${MK_MAN} != "no"
+.include <man.mk>
+.endif
+
+.if ${MK_NLS} != "no"
+.include <nls.mk>
+.endif
+
+.include <obj.mk>
+.include <inc.mk>
+.include <dep.mk>
+.include <subdir.mk>
+.endif
+
+# during building we usually need/want to install libs somewhere central
+# note that we do NOT ch{own,grp} as that would likely fail at this point.
+# otherwise it is the same as realinstall
+# Note that we don't need this when using dpadd.mk
+.libinstall: ${_LIBS}
+ test -d ${DESTDIR}${LIBDIR} || ${INSTALL} -d -m775 ${DESTDIR}${LIBDIR}
+.for _lib in ${_LIBS:M*.a}
+ ${INSTALL} ${COPY} -m 644 ${_lib} ${DESTDIR}${LIBDIR}
+ ${RANLIB} ${DESTDIR}${LIBDIR}/${_lib}
+.endfor
+.for _lib in ${_LIBS:M*.${LD_solink}*:O:u}
+ ${INSTALL} ${COPY} -m ${LIBMODE} ${_lib} ${DESTDIR}${LIBDIR}
+.if !empty(SHLIB_LINKS)
+ (cd ${DESTDIR}${LIBDIR} && { ${SHLIB_LINKS:O:u:@x@ln -sf ${_lib} $x;@}; })
+.endif
+.endfor
+ @touch ${.TARGET}
+
+.include <final.mk>
+.endif
diff --git a/contrib/bmake/mk/libnames.mk b/contrib/bmake/mk/libnames.mk
new file mode 100644
index 0000000..60e12eb
--- /dev/null
+++ b/contrib/bmake/mk/libnames.mk
@@ -0,0 +1,22 @@
+# $Id: libnames.mk,v 1.7 2009/12/25 07:34:03 sjg Exp $
+#
+# @(#) Copyright (c) 2007-2009, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+DLIBEXT ?= .a
+DSHLIBEXT ?= .so
+
+.-include "local.libnames.mk"
+.-include "sjg.libnames.mk"
+.-include "fwall.libnames.mk"
+.-include "host.libnames.mk"
diff --git a/contrib/bmake/mk/libs.mk b/contrib/bmake/mk/libs.mk
new file mode 100644
index 0000000..05b4506
--- /dev/null
+++ b/contrib/bmake/mk/libs.mk
@@ -0,0 +1,54 @@
+# $Id: libs.mk,v 1.2 2007/04/30 17:39:27 sjg Exp $
+#
+# @(#) Copyright (c) 2006, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.MAIN: all
+
+.if defined(LIBS)
+
+.ifndef LIB
+.for t in ${LIBS:R:T:S,^lib,,}
+.if make(lib$t)
+LIB?= $t
+lib$t: all
+.endif
+.endfor
+.endif
+
+.if defined(LIB)
+# just one of many
+.for v in DPADD SRCS CFLAGS ${LIB_VARS}
+$v += ${${v}_lib${LIB}}
+.endfor
+# ensure that we don't clobber each other's dependencies
+DEPENDFILE?= .depend.${LIB}
+# lib.mk will do the rest
+.else
+all: ${LIBS:S,^lib,,:@t@lib$t.a@} .MAKE
+.endif
+.endif
+
+# handle being called [bsd.]libs.mk
+.include <${.PARSEFILE:S,libs,lib,}>
+
+.ifndef LIB
+.for t in ${LIBS:R:T:S,^lib,,}
+lib$t.a: ${SRCS} ${DPADD} ${SRCS_lib$t} ${DPADD_lib$t}
+ (cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} LIB=$t)
+
+clean: $t.clean
+$t.clean:
+ (cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} LIB=$t ${@:E})
+.endfor
+.endif
diff --git a/contrib/bmake/mk/links.mk b/contrib/bmake/mk/links.mk
new file mode 100644
index 0000000..4ec8a01
--- /dev/null
+++ b/contrib/bmake/mk/links.mk
@@ -0,0 +1,75 @@
+# $Id: links.mk,v 1.5 2005/07/11 18:01:05 sjg Exp $
+#
+# @(#) Copyright (c) 2005, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# some platforms need something special
+LN?= ln
+ECHO?= echo
+
+LINKS?=
+SYMLINKS?=
+
+__SYMLINK_SCRIPT= \
+ ${ECHO} "$$t -> $$l"; \
+ mkdir -p `dirname $$t`; \
+ rm -f $$t; \
+ ${LN} -s $$l $$t
+
+__LINK_SCRIPT= \
+ ${ECHO} "$$t -> $$l"; \
+ mkdir -p `dirname $$t`; \
+ rm -f $$t; \
+ ${LN} $$l $$t
+
+_SYMLINKS_SCRIPT= \
+ while test $$\# -ge 2; do \
+ l=$$1; shift; \
+ t=${DESTDIR}$$1; shift; \
+ ${__SYMLINK_SCRIPT}; \
+ done; :;
+
+_LINKS_SCRIPT= \
+ while test $$\# -ge 2; do \
+ l=${DESTDIR}$$1; shift; \
+ t=${DESTDIR}$$1; shift; \
+ ${__LINK_SCRIPT}; \
+ done; :;
+
+_SYMLINKS_USE: .USE
+ @set ${$@_SYMLINKS:U${SYMLINKS}}; ${_SYMLINKS_SCRIPT}
+
+_LINKS_USE: .USE
+ @set ${$@_LINKS:U${LINKS}}; ${_LINKS_SCRIPT}
+
+
+# sometimes we want to ensure DESTDIR is ignored
+_BUILD_SYMLINKS_SCRIPT= \
+ while test $$\# -ge 2; do \
+ l=$$1; shift; \
+ t=$$1; shift; \
+ ${__SYMLINK_SCRIPT}; \
+ done; :;
+
+_BUILD_LINKS_SCRIPT= \
+ while test $$\# -ge 2; do \
+ l=$$1; shift; \
+ t=$$1; shift; \
+ ${__LINK_SCRIPT}; \
+ done; :;
+
+_BUILD_SYMLINKS_USE: .USE
+ @set ${$@_SYMLINKS:U${SYMLINKS}}; ${_BUILD_SYMLINKS_SCRIPT}
+
+_BUILD_LINKS_USE: .USE
+ @set ${$@_LINKS:U${LINKS}}; ${_BUILD_LINKS_SCRIPT}
diff --git a/contrib/bmake/mk/man.mk b/contrib/bmake/mk/man.mk
new file mode 100644
index 0000000..391b08a
--- /dev/null
+++ b/contrib/bmake/mk/man.mk
@@ -0,0 +1,137 @@
+# $Id: man.mk,v 1.20 2012/12/13 01:51:01 sjg Exp $
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+.include <init.mk>
+
+# unlike bsd.man.mk we handle 3 approaches
+# 1. install unformated nroff (default)
+# 2. install formatted pages
+# 3. install formatted pages but with extension of .0
+# sadly we cannot rely on a shell that supports ${foo#...} and ${foo%...}
+# so we have to use sed(1).
+
+# set MANTARGET=cat for formatted pages
+MANTARGET?= man
+# set this to .0 for same behavior as bsd.man.mk
+MCATEXT?=
+
+NROFF?= nroff
+MANDIR?= /usr/share/man
+MANDOC?= man
+
+.SUFFIXES: .1 .2 .3 .4 .5 .6 .7 .8 .9 .cat1 .cat2 .cat3 .cat4 .cat5 .cat6 \
+ .cat7 .cat8 .cat9
+
+.9.cat9 .8.cat8 .7.cat7 .6.cat6 .5.cat5 .4.cat4 .3.cat3 .2.cat2 .1.cat1:
+ @echo "${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T}"
+ @${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T} || ( rm -f ${.TARGET:T} ; false )
+
+.if defined(MAN) && !empty(MAN)
+
+# we use cmt2doc.pl to extract manpages from source
+# this is triggered by the setting of EXTRACT_MAN or MAN being set but
+# not existsing.
+
+.if !exists(${MAN:[1]}) && !target(${MAN:[1]})
+.if defined(EXTRACT_MAN) && ${EXTRACT_MAN} == "no"
+MAN=
+.else
+.if exists(/usr/local/share/bin/cmt2doc.pl)
+CMT2DOC?= cmt2doc.pl
+CMT2DOC_OPTS?= ${CMT2DOC_ORGOPT} -pmS${.TARGET:E}
+.endif
+.ifdef CMT2DOC
+.c.8 .c.5 .c.3 .c.4 .c.1 \
+ .cc.8 .cc.5 .cc.3 .cc.4 .cc.1 \
+ .h.8 .h.5 .h.3 .h.4 .h.1 \
+ .sh.8 .sh.5 .sh.3 .sh.4 .sh.1 \
+ .pl.8 .pl.5 .pl.3 .pl.4 .pl.1:
+ @echo "${CMT2DOC} ${.IMPSRC} > ${.TARGET:T}"
+ @${CMT2DOC} ${CMT2DOC_OPTS} ${.IMPSRC} > ${.TARGET:T} || ( rm -f ${.TARGET:T} ; false )
+.else
+MAN=
+.endif
+.endif
+.endif
+
+_mandir=${DESTDIR}${MANDIR}/${MANTARGET}`echo $$page | sed -e 's/.*\.cat/./' -e 's/.*\.//'`
+.if ${MANTARGET} == "cat"
+_mfromdir?=.
+MANALL= ${MAN:S/.1$/.cat1/g:S/.2$/.cat2/g:S/.3$/.cat3/g:S/.4$/.cat4/g:S/.5$/.cat5/g:S/.6$/.cat6/g:S/.7$/.cat7/g:S/.8$/.cat8/g:S/.9$/.cat9/g}
+.if ${MCATEXT} == ""
+_minstpage=`echo $$page | sed 's/\.cat/./'`
+.else
+_minstpage=`echo $$page | sed 's/\.cat.*//'`${MCATEXT}
+.endif
+.endif
+.if target(${MAN:[1]})
+_mfromdir?=.
+.endif
+_mfromdir?=${.CURDIR}
+MANALL?= ${MAN}
+_minstpage?=$${page}
+.endif
+
+.if !empty(MANOWN)
+MAN_INSTALL_OWN ?= -o ${MANOWN} -g ${MANGRP}
+MAN_CHOWN ?= chown
+.else
+MAN_CHOWN = :
+.endif
+
+MINSTALL= ${INSTALL} ${COPY} ${MAN_INSTALL_OWN} -m ${MANMODE}
+.if defined(MANZ)
+# chown and chmod are done afterward automatically
+MCOMPRESS= gzip -cf
+MCOMPRESSSUFFIX= .gz
+.endif
+
+maninstall:
+.if defined(MANALL) && !empty(MANALL)
+ @for page in ${MANALL:T}; do \
+ test -s ${_mfromdir}/$$page || continue; \
+ dir=${_mandir}; \
+ test -d $$dir || ${INSTALL} -d ${MAN_INSTALL_OWN} -m 775 $$dir; \
+ instpage=$${dir}${MANSUBDIR}/${_minstpage}${MCOMPRESSSUFFIX}; \
+ if [ X"${MCOMPRESS}" = X ]; then \
+ echo ${MINSTALL} ${_mfromdir}/$$page $$instpage; \
+ ${MINSTALL} ${_mfromdir}/$$page $$instpage; \
+ else \
+ rm -f $$instpage; \
+ echo ${MCOMPRESS} ${_mfromdir}/$$page \> $$instpage; \
+ ${MCOMPRESS} ${_mfromdir}/$$page > $$instpage; \
+ ${MAN_CHOWN} ${MANOWN}:${MANGRP} $$instpage; \
+ chmod ${MANMODE} $$instpage; \
+ fi \
+ done
+.if defined(MLINKS) && !empty(MLINKS)
+ @set ${MLINKS}; \
+ while test $$# -ge 2; do \
+ page=$$1; \
+ shift; \
+ dir=${_mandir}; \
+ l=${_minstpage}${MCOMPRESSSUFFIX}; \
+ page=$$1; \
+ shift; \
+ dir=${_mandir}; \
+ t=$${dir}${MANSUBDIR}/${_minstpage}${MCOMPRESSSUFFIX}; \
+ echo $$t -\> $$l; \
+ rm -f $$t; \
+ ln -s $$l $$t; \
+ done
+.endif
+.endif
+
+.if defined(MANALL) && !empty(MANALL)
+manall: ${MANALL}
+all: manall
+.endif
+
+.if defined(CLEANMAN) && !empty(CLEANMAN)
+cleandir: cleanman
+cleanman:
+ rm -f ${CLEANMAN}
+.endif
+.endif
diff --git a/contrib/bmake/mk/meta.autodep.mk b/contrib/bmake/mk/meta.autodep.mk
new file mode 100644
index 0000000..c29c26e
--- /dev/null
+++ b/contrib/bmake/mk/meta.autodep.mk
@@ -0,0 +1,262 @@
+# $Id: meta.autodep.mk,v 1.32 2012/11/13 00:44:26 sjg Exp $
+
+#
+# @(#) Copyright (c) 2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+_this ?= ${.PARSEFILE}
+.if !target(__${_this}__)
+__${_this}__: .NOTMAIN
+
+.-include "local.autodep.mk"
+
+.if defined(SRCS)
+# it would be nice to be able to query .SUFFIXES
+OBJ_EXTENSIONS+= .o .po .lo .So
+
+# explicit dependencies help short-circuit .SUFFIX searches
+SRCS_DEP_FILTER+= N*.[hly]
+.for s in ${SRCS:${SRCS_DEP_FILTER:O:u:ts:}}
+.for e in ${OBJ_EXTENSIONS:O:u}
+.if !target(${s:T:R}$e)
+${s:T:R}$e: $s
+.endif
+.endfor
+.endfor
+.endif
+
+.if make(gendirdeps)
+# you are supposed to know what you are doing!
+UPDATE_DEPENDFILE = yes
+.elif !empty(.TARGETS) && !make(all)
+# do not update the *depend* files
+# unless we are building the entire directory or the default target.
+# NO means don't update .depend - or Makefile.depend*
+# no means update .depend but not Makefile.depend*
+UPDATE_DEPENDFILE = NO
+.elif ${.MAKEFLAGS:M-k} != ""
+# it is a bad idea to update anything
+UPDATE_DEPENDFILE = NO
+.endif
+
+_CURDIR ?= ${.CURDIR}
+_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
+
+.if ${.MAKE.LEVEL} == 0
+.if ${BUILD_AT_LEVEL0:Uyes:tl} == "no"
+UPDATE_DEPENDFILE = NO
+.endif
+.endif
+.if !exists(${_DEPENDFILE})
+_bootstrap_dirdeps = yes
+.endif
+_bootstrap_dirdeps ?= no
+UPDATE_DEPENDFILE ?= yes
+
+.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
+.info ${_DEPENDFILE:S,${SRCTOP}/,,} update=${UPDATE_DEPENDFILE}
+.endif
+
+.if !empty(XMAKE_META_FILE)
+.if exists(${.OBJDIR}/${XMAKE_META_FILE})
+# we cannot get accurate dependencies from an update build
+UPDATE_DEPENDFILE = NO
+.else
+META_XTRAS += ${XMAKE_META_FILE}
+.endif
+.endif
+
+.if ${_bootstrap_dirdeps} == "yes" || exists(${_DEPENDFILE})
+# if it isn't supposed to be touched by us the Makefile should have
+# UPDATE_DEPENDFILE = no
+WANT_UPDATE_DEPENDFILE ?= yes
+.endif
+
+.if ${WANT_UPDATE_DEPENDFILE:Uno:tl} != "no"
+.if ${.MAKE.MODE:Mmeta*} == "" || ${.MAKE.MODE:M*read*} != ""
+UPDATE_DEPENDFILE = no
+.endif
+
+.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
+.info ${_DEPENDFILE:S,${SRCTOP}/,,} update=${UPDATE_DEPENDFILE}
+.endif
+
+.if ${UPDATE_DEPENDFILE:tl} == "yes"
+# sometimes we want .meta files generated to aid debugging/error detection
+# but do not want to consider them for dependencies
+# for example the result of running configure
+# just make sure this is not empty
+META_FILE_FILTER ?= N.meta
+
+.if !empty(DPADD)
+# if we have any non-libs in DPADD,
+# they probably need to be paid attention to
+.if !empty(DPLIBS)
+FORCE_DPADD = ${DPADD:${DPLIBS:${M_ListToSkip}}:${DPADD_LAST:${M_ListToSkip}}}
+.else
+_nonlibs := ${DPADD:T:Nlib*:N*include}
+.if !empty(_nonlibs)
+FORCE_DPADD += ${_nonlibs:@x@${DPADD:M*/$x}@}
+.endif
+.endif
+.endif
+
+.if !make(gendirdeps)
+.END: gendirdeps
+.endif
+
+# if we don't have OBJS, then .depend isn't useful
+.if !target(.depend) && (!empty(OBJS) || ${.ALLTARGETS:M*.o} != "")
+# some makefiles and/or targets contain
+# circular dependencies if you dig too deep
+# (as meta mode is apt to do)
+# so we provide a means of supressing them.
+# the input to the loop below is target: dependency
+# with just one dependency per line.
+# Also some targets are not really local, or use random names.
+# Use local.autodep.mk to provide local additions!
+SUPPRESS_DEPEND += \
+ ${SB:S,/,_,g}* \
+ *:y.tab.c \
+ *.c:*.c \
+ *.h:*.h
+
+.NOPATH: .depend
+# we use ${.MAKE.META.CREATED} to trigger an update but
+# we process using ${.MAKE.META.FILES}
+# the double $$ defers initial evaluation
+# if necessary, we fake .po dependencies, just so the result
+# in Makefile.depend* is stable
+# The current objdir may be refered to in various ways
+OBJDIR_REFS += ${.OBJDIR} ${.OBJDIR:tA} ${_OBJDIR} ${RELOBJTOP}/${RELDIR}
+_depend = .depend
+# it would be nice to be able to get .SUFFIXES as ${.SUFFIXES}
+# we actually only care about the .SUFFIXES of files that might be
+# generated by tools like yacc.
+DEPEND_SUFFIXES += .c .h .cpp .hpp .cxx .hxx .cc .hh
+.depend: .NOMETA $${.MAKE.META.CREATED} ${_this}
+ @echo "Updating $@: ${.OODATE:T:[1..8]}"
+ @egrep -i '^R .*\.(${DEPEND_SUFFIXES:tl:O:u:S,^.,,:ts|})$$' /dev/null ${.MAKE.META.FILES:T:O:u:${META_FILE_FILTER:ts:}:M*o.meta} | \
+ sed -e 's, \./, ,${OBJDIR_REFS:O:u:@d@;s, $d/, ,@};/\//d' \
+ -e 's,^\([^/][^/]*\).meta...[0-9]* ,\1: ,' | \
+ sort -u | \
+ while read t d; do \
+ case "$$d:" in $$t) continue;; esac; \
+ case "$$t$$d" in ${SUPPRESS_DEPEND:U.:O:u:ts|}) continue;; esac; \
+ echo $$t $$d; \
+ done > $@.${.MAKE.PID}
+ @case "${.MAKE.META.FILES:T:M*.po.*}" in \
+ *.po.*) mv $@.${.MAKE.PID} $@;; \
+ *) { cat $@.${.MAKE.PID}; \
+ sed 's,\.So:,.o:,;s,\.o:,.po:,' $@.${.MAKE.PID}; } | sort -u > $@; \
+ rm -f $@.${.MAKE.PID};; \
+ esac
+.else
+# make sure this exists
+.depend:
+# do _not_ assume that .depend is in any fit state for us to use
+CAT_DEPEND = /dev/null
+.if ${.MAKE.LEVEL} > 0
+.export CAT_DEPEND
+.endif
+_depend =
+.endif
+
+.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
+.info ${_DEPENDFILE:S,${SRCTOP}/,,} _depend=${_depend}
+.endif
+
+gendirdeps: ${_DEPENDFILE}
+
+.if !target(${_DEPENDFILE})
+.if ${_bootstrap_dirdeps} == "yes"
+# We are boot-strapping a new directory
+# Use DPADD to seed DIRDEPS
+.if !empty(DPADD)
+# anything which matches ${_OBJROOT}* but not ${_OBJTOP}*
+# needs to be qualified in DIRDEPS
+# The pseudo machine "host" is used for HOST_TARGET
+DIRDEPS = \
+ ${DPADD:M${_OBJTOP}*:H:C,${_OBJTOP}[^/]*/,,:N.:O:u} \
+ ${DPADD:M${_OBJROOT}*:N${_OBJTOP}*:H:S,${_OBJROOT},,:C,^([^/]+)/(.*),\2.\1,:S,${HOST_TARGET}$,host,:N.*:O:u}
+
+.endif
+.endif
+
+_gendirdeps_mutex =
+.if defined(NEED_GENDIRDEPS_MUTEX)
+# If a src dir gets built with multiple object dirs,
+# we need a mutex. Obviously, this is best avoided.
+# Note if .MAKE.DEPENDFILE is common for all ${MACHINE}
+# you either need to mutex, or ensure only one machine builds at a time!
+# lockf is an example of a suitable tool
+LOCKF ?= /usr/bin/lockf
+.if exists(${LOCKF})
+GENDIRDEPS_MUTEXER ?= ${LOCKF} -k
+.endif
+.if empty(GENDIRDEPS_MUTEXER)
+.error NEED_GENDIRDEPS_MUTEX defined, but GENDIRDEPS_MUTEXER not set
+.else
+_gendirdeps_mutex = ${GENDIRDEPS_MUTEXER} ${GENDIRDEPS_MUTEX:U${_CURDIR}/Makefile}
+.endif
+.endif
+
+# If we have META_XTRAS we most likely did not create them
+# but we need to behave as if we did.
+# Avoid adding glob patterns to .MAKE.META.CREATED though.
+.MAKE.META.CREATED += ${META_XTRAS:N*\**:O:u}
+
+.if make(gendirdeps)
+META_FILES = *.meta
+.elif ${OPTIMIZE_OBJECT_META_FILES:Uno:tl} == "no"
+META_FILES = ${.MAKE.META.FILES:T:N.depend*:O:u}
+.else
+# if we have 1000's of .o.meta, .So.meta etc we need only look at one set
+# it is left as an exercise for the reader to work out what this does
+META_FILES = ${.MAKE.META.FILES:T:N.depend*:N*o.meta:O:u} \
+ ${.MAKE.META.FILES:T:M*.${.MAKE.META.FILES:M*o.meta:R:E:O:u:[1]}.meta:O:u}
+.endif
+
+.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != ""
+.info ${_DEPENDFILE:S,${SRCTOP}/,,}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} xtras=${META_XTRAS}
+.endif
+
+.if ${.MAKE.LEVEL} > 0 && !empty(GENDIRDEPS_FILTER)
+.export GENDIRDEPS_FILTER
+.endif
+
+# we might have .../ in MAKESYSPATH
+_makesyspath:= ${_PARSEDIR}
+${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.META.CREATED}
+ @echo Checking $@: ${.OODATE:T:[1..8]}
+ @(cd . && \
+ SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS:O:u}' \
+ DPADD='${FORCE_DPADD:O:u}' ${_gendirdeps_mutex} \
+ MAKESYSPATH=${_makesyspath} \
+ ${.MAKE} -f gendirdeps.mk RELDIR=${RELDIR} _DEPENDFILE=${_DEPENDFILE} \
+ META_FILES='${META_XTRAS:T:O:u} ${META_FILES:T:O:u:${META_FILE_FILTER:ts:}}')
+ @test -s $@ && touch $@; :
+.endif
+
+.endif
+.endif
+
+.if ${_bootstrap_dirdeps} == "yes"
+# make sure this is included at least once
+.include <dirdeps.mk>
+.else
+${_DEPENDFILE}: .PRECIOUS
+.endif
+
+CLEANFILES += *.meta filemon.* *.db
+.endif
diff --git a/contrib/bmake/mk/meta.stage.mk b/contrib/bmake/mk/meta.stage.mk
new file mode 100644
index 0000000..cf62db4
--- /dev/null
+++ b/contrib/bmake/mk/meta.stage.mk
@@ -0,0 +1,212 @@
+# $Id: meta.stage.mk,v 1.17 2013/01/24 01:02:23 sjg Exp $
+#
+# @(#) Copyright (c) 2011, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} != ""
+# this is generally safer anyway
+_dirdep = ${RELDIR}.${MACHINE}
+.else
+_dirdep = ${RELDIR}
+.endif
+
+# this allows us to trace dependencies back to their src dir
+.dirdep:
+ @echo '${_dirdep}' > $@
+
+.if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == ""
+_stage_file_basename = `basename $$f`
+_stage_target_dirname = `dirname $$t`
+.else
+_stage_file_basename = $${f\#\#*/}
+_stage_target_dirname = $${t%/*}
+.endif
+
+_objroot ?= ${_OBJROOT:tA}
+# make sure this is global
+_STAGED_DIRS ?=
+.export _STAGED_DIRS
+# add each dir we stage to to _STAGED_DIRS
+# and make sure we have absolute paths so that bmake
+# will match against .MAKE.META.BAILIWICK
+STAGE_DIR_FILTER = tA:@d@$${_STAGED_DIRS::+=$$d}$$d@
+# convert _STAGED_DIRS into suitable filters
+GENDIRDEPS_FILTER += Nnot-empty-is-important \
+ ${_STAGED_DIRS:O:u:M${OBJTOP}*:S,${OBJTOP}/,N,} \
+ ${_STAGED_DIRS:O:u:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,}
+
+# it is an error for more than one src dir to try and stage
+# the same file
+STAGE_DIRDEP_SCRIPT = StageDirdep() { \
+ t=$$1; \
+ if [ -s $$t.dirdep ]; then \
+ cmp -s .dirdep $$t.dirdep && return; \
+ echo "ERROR: $$t installed by `cat $$t.dirdep` not ${_dirdep}" >&2; \
+ exit 1; \
+ fi; \
+ ln .dirdep $$t.dirdep 2> /dev/null || \
+ cp .dirdep $$t.dirdep; }
+
+# common logic for staging files
+# this all relies on RELDIR being set to a subdir of SRCTOP
+# we use ln(1) if we can, else cp(1)
+STAGE_FILE_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageFiles() { \
+ case "$$1" in -m) mode=$$2; shift 2;; *) mode=;; esac; \
+ dest=$$1; shift; \
+ mkdir -p $$dest; \
+ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
+ for f in "$$@"; do \
+ case "$$f" in */*) t=$$dest/${_stage_file_basename};; *) t=$$dest/$$f;; esac; \
+ StageDirdep $$t; \
+ rm -f $$t; \
+ { ln $$f $$t 2> /dev/null || \
+ cp -p $$f $$t; }; \
+ $${mode:+chmod $$mode $$t}; \
+ done; :; }
+
+STAGE_LINKS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageLinks() { \
+ case "$$1" in --) shift;; -*) ldest= lnf=$$1; shift;; /*) ldest=$$1/;; esac; \
+ dest=$$1; shift; \
+ mkdir -p $$dest; \
+ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
+ while test $$\# -ge 2; do \
+ l=$$ldest$$1; shift; \
+ t=$$dest/$$1; \
+ case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \
+ shift; \
+ StageDirdep $$t; \
+ rm -f $$t 2>/dev/null; \
+ ln $$lnf $$l $$t; \
+ done; :; }
+
+STAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \
+ case "$$1" in -m) mode=$$2; shift 2;; *) mode=;; esac; \
+ dest=$$1; shift; \
+ mkdir -p $$dest; \
+ [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \
+ while test $$\# -ge 2; do \
+ s=$$1; shift; \
+ t=$$dest/$$1; \
+ case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \
+ shift; \
+ StageDirdep $$t; \
+ rm -f $$t; \
+ { ln $$s $$t 2> /dev/null || \
+ cp -p $$s $$t; }; \
+ $${mode:+chmod $$mode $$t}; \
+ done; :; }
+
+# this is simple, a list of the "staged" files depends on this,
+_STAGE_BASENAME_USE: .USE ${.TARGET:T}
+ @${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T}
+
+.if !empty(STAGE_INCSDIR)
+CLEANFILES += stage_incs
+
+STAGE_INCS ?= ${.ALLSRC:N.dirdep}
+
+stage_incs: .dirdep
+ @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_INCSDIR:${STAGE_DIR_FILTER}} ${STAGE_INCS}
+ @touch $@
+.endif
+
+.if !empty(STAGE_LIBDIR)
+CLEANFILES += stage_libs
+
+STAGE_LIBS ?= ${.ALLSRC:N.dirdep}
+
+stage_libs: .dirdep
+ @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${STAGE_LIBS}
+.if !empty(SHLIB_LINKS)
+ @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} \
+ ${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*} $t@}
+.elif !empty(SHLIB_LINK) && !empty(SHLIB_NAME)
+ @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK} ${SYMLINKS:T}
+.endif
+ @touch $@
+.endif
+
+.if !empty(STAGE_DIR)
+STAGE_SETS += _default
+STAGE_DIR._default = ${STAGE_DIR}
+STAGE_LINKS_DIR._default = ${STAGE_LINKS_DIR:U${STAGE_OBJTOP}}
+STAGE_SYMLINKS_DIR._default = ${STAGE_SYMLINKS_DIR:U${STAGE_OBJTOP}}
+STAGE_FILES._default = ${STAGE_FILES}
+STAGE_LINKS._default = ${STAGE_LINKS}
+STAGE_SYMLINKS._default = ${STAGE_SYMLINKS}
+STAGE_FILES ?= ${.ALLSRC:N.dirdep:Nstage_*}
+STAGE_SYMLINKS ?= ${.ALLSRC:T:N.dirdep:Nstage_*}
+.endif
+
+.if !empty(STAGE_SETS)
+
+CLEANFILES += ${STAGE_SETS:@s@stage*$s@}
+
+# some makefiles need to populate multiple directories
+.for s in ${STAGE_SETS:O:u}
+STAGE_FILES.$s ?= ${.ALLSRC:N.dirdep}
+STAGE_SYMLINKS.$s ?= ${.ALLSRC:N.dirdep}
+STAGE_LINKS_DIR.$s ?= ${STAGE_OBJTOP}
+STAGE_SYMLINKS_DIR.$s ?= ${STAGE_OBJTOP}
+
+.if $s != "_default"
+stage_files: stage_files.$s
+stage_files.$s: .dirdep
+.else
+stage_files: .dirdep
+.endif
+ @${STAGE_FILE_SCRIPT}; StageFiles ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_FILES.$s}
+ @touch $@
+
+.if $s != "_default"
+stage_links: stage_links.$s
+stage_links.$s: .dirdep
+.else
+stage_links: .dirdep
+.endif
+ @${STAGE_LINKS_SCRIPT}; StageLinks ${STAGE_LINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_LINKS.$s}
+ @touch $@
+
+.if $s != "_default"
+stage_symlinks: stage_symlinks.$s
+stage_symlinks.$s: .dirdep
+.else
+stage_symlinks: .dirdep
+.endif
+ @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_SYMLINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_SYMLINKS.$s}
+ @touch $@
+
+.endfor
+.endif
+
+.if !empty(STAGE_AS_SETS)
+CLEANFILES += ${STAGE_AS_SETS:@s@stage*$s@}
+
+# sometimes things need to be renamed as they are staged
+# each ${file} will be staged as ${STAGE_AS_${file:T}}
+# one could achieve the same with SYMLINKS
+.for s in ${STAGE_AS_SETS:O:u}
+STAGE_AS.$s ?= ${.ALLSRC:N.dirdep}
+
+stage_as: stage_as.$s
+stage_as.$s: .dirdep
+ @${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS.$s:@f@$f ${STAGE_AS_${f:T}:U${f:T}}@}
+ @touch $@
+
+.endfor
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/meta.subdir.mk b/contrib/bmake/mk/meta.subdir.mk
new file mode 100644
index 0000000..2b739ee
--- /dev/null
+++ b/contrib/bmake/mk/meta.subdir.mk
@@ -0,0 +1,79 @@
+# $Id: meta.subdir.mk,v 1.10 2012/07/03 05:26:46 sjg Exp $
+
+#
+# @(#) Copyright (c) 2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !defined(NO_SUBDIR) && !empty(SUBDIR)
+.if make(destroy*) || make(clean*)
+.MAKE.MODE = compat
+.if !commands(destroy)
+.-include <bsd.obj.mk>
+.endif
+.elif ${.MAKE.LEVEL} == 0
+
+.MAIN: all
+
+.if !exists(${.CURDIR}/${.MAKE.DEPENDFILE:T}) || make(gendirdeps)
+# start with this
+DIRDEPS = ${SUBDIR:N.WAIT:O:u:@d@${RELDIR}/$d@}
+
+.if make(gendirdeps)
+.include <meta.autodep.mk>
+.else
+# this is the cunning bit
+# actually it is probably a bit risky
+# since we may pickup subdirs which are not relevant
+# the alternative is a walk through the tree though
+# which is difficult without a sub-make.
+
+.if defined(BOOTSTRAP_DEPENDFILES)
+_find_name = ${.MAKE.MAKEFILE_PREFERENCE:@m@-o -name $m@:S,^-o,,1}
+DIRDEPS = ${_subdeps:H:O:u:@d@${RELDIR}/$d@}
+.elif ${.MAKE.DEPENDFILE:E} == ${MACHINE} && defined(ALL_MACHINES)
+# we want to find Makefile.depend.* ie for all machines
+# and turn the dirs into dir.<machine>
+_find_name = -name '${.MAKE.DEPENDFILE:T:R}*'
+DIRDEPS = ${_subdeps:O:u:${NIgnoreFiles}:@d@${RELDIR}/${d:H}.${d:E}@:S,.${MACHINE}$,,:S,.depend$,,}
+.else
+# much simpler
+_find_name = -name ${.MAKE.DEPENDFILE:T}
+.if ${.MAKE.DEPENDFILE:E} == ${MACHINE}
+_find_name += -o -name ${.MAKE.DEPENDFILE:T:R}
+.endif
+DIRDEPS = ${_subdeps:H:O:u:@d@${RELDIR}/$d@}
+.endif
+
+_subdeps != cd ${.CURDIR} && \
+ find ${SUBDIR:N.WAIT} -type f \( ${_find_name} \) -print -o \
+ -name .svn -prune 2> /dev/null; echo
+
+.if empty(_subdeps)
+DIRDEPS =
+.else
+# clean up if needed
+DIRDEPS := ${DIRDEPS:S,^./,,:S,/./,/,g:${SUBDIREPS_FILTER:Uu}}
+.endif
+# we just dealt with it, if we leave it defined,
+# dirdeps.mk will compute some interesting combinations.
+.undef ALL_MACHINES
+
+DEP_RELDIR = ${RELDIR}
+.include <dirdeps.mk>
+.endif
+.endif
+.else
+all: .PHONY
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/meta.sys.mk b/contrib/bmake/mk/meta.sys.mk
new file mode 100644
index 0000000..1707a66
--- /dev/null
+++ b/contrib/bmake/mk/meta.sys.mk
@@ -0,0 +1,139 @@
+# $Id: meta.sys.mk,v 1.16 2012/07/03 05:26:00 sjg Exp $
+
+#
+# @(#) Copyright (c) 2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# include this if you want to enable meta mode
+# for maximum benefit, requires filemon(4) driver.
+
+.if ${MAKE_VERSION:U0} > 20100901
+.if !target(.ERROR)
+
+
+META_MODE += meta verbose
+.MAKE.MODE ?= ${META_MODE}
+
+.if ${.MAKE.LEVEL} == 0
+_make_mode := ${.MAKE.MODE} ${META_MODE}
+.if ${_make_mode:M*read*} != "" || ${_make_mode:M*nofilemon*} != ""
+# tell everyone we are not updating Makefile.depend*
+UPDATE_DEPENDFILE = NO
+.export UPDATE_DEPENDFILE
+.endif
+.if ${UPDATE_DEPENDFILE:Uyes:tl} == "no" && !exists(/dev/filemon)
+# we should not get upset
+META_MODE += nofilemon
+.export META_MODE
+.endif
+.endif
+
+.if !defined(NO_SILENT)
+.if ${MAKE_VERSION} > 20110818
+# only be silent when we have a .meta file
+META_MODE += silent=yes
+.else
+.SILENT:
+.endif
+.endif
+
+# make defaults .MAKE.DEPENDFILE to .depend
+# that won't work for us.
+.if ${.MAKE.DEPENDFILE} == ".depend"
+.undef .MAKE.DEPENDFILE
+.endif
+
+# if you don't cross build for multiple MACHINEs concurrently, then
+# .MAKE.DEPENDFILE = Makefile.depend
+# probably makes sense - you can set that in local.sys.mk
+.MAKE.DEPENDFILE ?= Makefile.depend.${MACHINE}
+
+# we use the pseudo machine "host" for the build host.
+# this should be taken care of before we get here
+.if ${OBJTOP:Ua} == ${HOST_OBJTOP:Ub}
+MACHINE = host
+.endif
+
+.if ${.MAKE.LEVEL} == 0
+# it can be handy to know which MACHINE kicked off the build
+# for example, if using Makefild.depend for multiple machines,
+# allowing only MACHINE0 to update can keep things simple.
+MACHINE0 := ${MACHINE}
+
+.if defined(PYTHON) && exists(${PYTHON})
+# we prefer the python version of this - it is much faster
+META2DEPS ?= ${.PARSEDIR}/meta2deps.py
+.else
+META2DEPS ?= ${.PARSEDIR}/meta2deps.sh
+.endif
+META2DEPS := ${META2DEPS}
+.export META2DEPS
+.endif
+
+MAKE_PRINT_VAR_ON_ERROR += \
+ .ERROR_TARGET \
+ .ERROR_META_FILE \
+ .MAKE.LEVEL \
+ MAKEFILE \
+ .MAKE.MODE
+
+.if !defined(SB) && defined(SRCTOP)
+SB = ${SRCTOP:H}
+.endif
+ERROR_LOGDIR ?= ${SB}/error
+meta_error_log = ${ERROR_LOGDIR}/meta-${.MAKE.PID}.log
+
+# we are not interested in make telling us a failure happened elsewhere
+.ERROR: _metaError
+_metaError: .NOMETA .NOTMAIN
+ -@[ "${.ERROR_META_FILE}" ] && { \
+ grep -q 'failure has been detected in another branch' ${.ERROR_META_FILE} && exit 0; \
+ mkdir -p ${meta_error_log:H}; \
+ cp ${.ERROR_META_FILE} ${meta_error_log}; \
+ echo "ERROR: log ${meta_error_log}" >&2; }; :
+
+.endif
+
+# Are we, after all, in meta mode?
+.if ${.MAKE.MODE:Mmeta*} != ""
+MKDEP = meta.autodep
+
+.if ${.MAKE.LEVEL} == 0
+# make sure dirdeps target exists and do it first
+all: dirdeps .WAIT
+dirdeps:
+.NOPATH: dirdeps
+
+.if defined(ALL_MACHINES)
+# the first .MAIN: is what counts
+# by default dirdeps is all we want at level0
+.MAIN: dirdeps
+# tell dirdeps.mk what we want
+BUILD_AT_LEVEL0 = no
+.endif
+
+.if ${.MAKE.DEPENDFILE:E} == ${MACHINE}
+# it works best if we do everything via sub-makes
+BUILD_AT_LEVEL0 ?= no
+.endif
+BUILD_AT_LEVEL0 ?= yes
+.endif
+
+# if we think we are updating dependencies,
+# then filemon had better be present
+.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no" && !exists(/dev/filemon)
+.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded.
+.endif
+
+.endif
+.endif
diff --git a/contrib/bmake/mk/meta2deps.py b/contrib/bmake/mk/meta2deps.py
new file mode 100755
index 0000000..cb6d321
--- /dev/null
+++ b/contrib/bmake/mk/meta2deps.py
@@ -0,0 +1,614 @@
+#!/usr/bin/env python
+
+"""
+This script parses each "meta" file and extracts the
+information needed to deduce build and src dependencies.
+
+It works much the same as the original shell script, but is
+*much* more efficient.
+
+The parsing work is handled by the class MetaFile.
+We only pay attention to a subset of the information in the
+"meta" files. Specifically:
+
+'CWD' to initialize our notion.
+
+'C' to track chdir(2) on a per process basis
+
+'R' files read are what we really care about.
+ directories read, provide a clue to resolving
+ subsequent relative paths. That is if we cannot find
+ them relative to 'cwd', we check relative to the last
+ dir read.
+
+'W' files opened for write or read-write,
+ for filemon V3 and earlier.
+
+'E' files executed.
+
+'L' files linked
+
+'V' the filemon version, this record is used as a clue
+ that we have reached the interesting bit.
+
+"""
+
+"""
+RCSid:
+ $Id: meta2deps.py,v 1.7 2012/11/06 05:44:03 sjg Exp $
+
+ Copyright (c) 2011, Juniper Networks, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE 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
+ OWNER 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.
+
+"""
+
+import os, re, sys
+
+def getv(dict, key, d=None):
+ """Lookup key in dict and return value or the supplied default."""
+ if key in dict:
+ return dict[key]
+ return d
+
+def resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
+ """
+ Return an absolute path, resolving via cwd or last_dir if needed.
+ """
+ if path.endswith('/.'):
+ path = path[0:-2]
+ if path[0] == '/':
+ return path
+ if path == '.':
+ return cwd
+ if path.startswith('./'):
+ return cwd + path[1:]
+ if last_dir == cwd:
+ last_dir = None
+ for d in [last_dir, cwd]:
+ if not d:
+ continue
+ p = '/'.join([d,path])
+ if debug > 2:
+ print >> debug_out, "looking for:", p,
+ if not os.path.exists(p):
+ if debug > 2:
+ print >> debug_out, "nope"
+ p = None
+ continue
+ if debug > 2:
+ print >> debug_out, "found:", p
+ return p
+ return None
+
+def abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr):
+ """
+ Return an absolute path, resolving via cwd or last_dir if needed.
+ this gets called a lot, so we try to avoid calling realpath
+ until we know we have something.
+ """
+ path = resolve(path, cwd, last_dir, debug, debug_out)
+ if path and (path.find('./') > 0 or
+ path.endswith('/..') or
+ os.path.islink(path)):
+ return os.path.realpath(path)
+ return path
+
+def sort_unique(list, cmp=None, key=None, reverse=False):
+ list.sort(cmp, key, reverse)
+ nl = []
+ le = None
+ for e in list:
+ if e == le:
+ continue
+ nl.append(e)
+ return nl
+
+class MetaFile:
+ """class to parse meta files generated by bmake."""
+
+ conf = None
+ dirdep_re = None
+ host_target = None
+ srctops = []
+ objroots = []
+
+ seen = {}
+ obj_deps = []
+ src_deps = []
+ file_deps = []
+
+ def __init__(self, name, conf={}):
+ """if name is set we will parse it now.
+ conf can have the follwing keys:
+
+ SRCTOPS list of tops of the src tree(s).
+
+ CURDIR the src directory 'bmake' was run from.
+
+ RELDIR the relative path from SRCTOP to CURDIR
+
+ MACHINE the machine we built for.
+ set to 'none' if we are not cross-building.
+
+ HOST_TARGET
+ when we build for the psuedo machine 'host'
+ the object tree uses HOST_TARGET rather than MACHINE.
+
+ OBJROOTS a list of the common prefix for all obj dirs it might
+ end in '/' or '-'.
+
+ DPDEPS names an optional file to which per file dependencies
+ will be appended.
+ For example if 'some/path/foo.h' is read from SRCTOP
+ then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output.
+ This can allow 'bmake' to learn all the dirs within
+ the tree that depend on 'foo.h'
+
+ debug desired debug level
+
+ debug_out open file to send debug output to (sys.stderr)
+
+ """
+
+ self.name = name
+ self.debug = getv(conf, 'debug', 0)
+ self.debug_out = getv(conf, 'debug_out', sys.stderr)
+
+ if not self.conf:
+ # some of the steps below we want to do only once
+ self.conf = conf
+ self.host_target = getv(conf, 'HOST_TARGET')
+ for srctop in getv(conf, 'SRCTOPS', []):
+ if srctop[-1] != '/':
+ srctop += '/'
+ if not srctop in self.srctops:
+ self.srctops.append(srctop)
+ _srctop = os.path.realpath(srctop)
+ if _srctop[-1] != '/':
+ _srctop += '/'
+ if not _srctop in self.srctops:
+ self.srctops.append(_srctop)
+
+ for objroot in getv(conf, 'OBJROOTS', []):
+ if not objroot in self.objroots:
+ self.objroots.append(objroot)
+ _objroot = os.path.realpath(objroot)
+ if objroot[-1] == '/':
+ _objroot += '/'
+ if not _objroot in self.objroots:
+ self.objroots.append(_objroot)
+
+ if self.debug:
+ print >> self.debug_out, "host_target=", self.host_target
+ print >> self.debug_out, "srctops=", self.srctops
+ print >> self.debug_out, "objroots=", self.objroots
+
+ self.dirdep_re = re.compile(r'([^/]+)/(.+)')
+
+ self.curdir = getv(conf, 'CURDIR')
+ self.machine = getv(conf, 'MACHINE', '')
+ self.reldir = getv(conf, 'RELDIR')
+ self.dpdeps = getv(conf, 'DPDEPS')
+ if self.dpdeps and not self.reldir:
+ if self.debug:
+ print >> self.debug_out, "need reldir:",
+ if self.curdir:
+ srctop = self.find_top(self.curdir, self.srctops)
+ if srctop:
+ self.reldir = self.curdir.replace(srctop,'')
+ if self.debug:
+ print >> self.debug_out, self.reldir
+ if not self.reldir:
+ self.dpdeps = None # we cannot do it?
+
+ if name:
+ self.parse()
+
+ def reset(self):
+ """reset state if we are being passed meta files from multiple directories."""
+ self.seen = {}
+ self.obj_deps = []
+ self.src_deps = []
+ self.file_deps = []
+
+ def dirdeps(self, sep='\n'):
+ """return DIRDEPS"""
+ return sep.strip() + sep.join(self.obj_deps)
+
+ def src_dirdeps(self, sep='\n'):
+ """return SRC_DIRDEPS"""
+ return sep.strip() + sep.join(self.src_deps)
+
+ def file_depends(self, out=None):
+ """Append DPDEPS_${file} += ${RELDIR}
+ for each file we saw, to the output file."""
+ if not self.reldir:
+ return None
+ for f in sort_unique(self.file_deps):
+ print >> out, 'DPDEPS_%s += %s' % (f, self.reldir)
+
+ def seenit(self, dir):
+ """rememer that we have seen dir."""
+ self.seen[dir] = 1
+
+ def add(self, list, data, clue=''):
+ """add data to list if it isn't already there."""
+ if data not in list:
+ list.append(data)
+ if self.debug:
+ print >> self.debug_out, "%s: %sAdd: %s" % (self.name, clue, data)
+
+ def find_top(self, path, list):
+ """the logical tree may be split accross multiple trees"""
+ for top in list:
+ if path.startswith(top):
+ if self.debug > 2:
+ print >> self.debug_out, "found in", top
+ return top
+ return None
+
+ def find_obj(self, objroot, dir, path, input):
+ """return path within objroot, taking care of .dirdep files"""
+ ddep = None
+ for ddepf in [path + '.dirdep', dir + '/.dirdep']:
+ if not ddep and os.path.exists(ddepf):
+ ddep = open(ddepf, 'rb').readline().strip('# \n')
+ if self.debug > 1:
+ print >> self.debug_out, "found %s: %s\n" % (ddepf, ddep)
+ if ddep.endswith(self.machine):
+ ddep = ddep[0:-(1+len(self.machine))]
+
+ if not ddep:
+ # no .dirdeps, so remember that we've seen the raw input
+ self.seenit(input)
+ self.seenit(dir)
+ if self.machine == 'none':
+ if dir.startswith(objroot):
+ return dir.replace(objroot,'')
+ return None
+ m = self.dirdep_re.match(dir.replace(objroot,''))
+ if m:
+ ddep = m.group(2)
+ dmachine = m.group(1)
+ if dmachine != self.machine:
+ if not (self.machine == 'host' and
+ dmachine == self.host_target):
+ if self.debug > 2:
+ print >> self.debug_out, "adding .%s to %s" % (dmachine, ddep)
+ ddep += '.' + dmachine
+
+ return ddep
+
+ def parse(self, name=None, file=None):
+ """A meta file looks like:
+
+ # Meta data file "path"
+ CMD "command-line"
+ CWD "cwd"
+ TARGET "target"
+ -- command output --
+ -- filemon acquired metadata --
+ # buildmon version 3
+ V 3
+ C "pid" "cwd"
+ E "pid" "path"
+ F "pid" "child"
+ R "pid" "path"
+ W "pid" "path"
+ X "pid" "status"
+ D "pid" "path"
+ L "pid" "src" "target"
+ M "pid" "old" "new"
+ S "pid" "path"
+ # Bye bye
+
+ We go to some effort to avoid processing a dependency more than once.
+ Of the above record types only C,E,F,L,R,V and W are of interest.
+ """
+
+ version = 0 # unknown
+ if name:
+ self.name = name;
+ if file:
+ f = file
+ cwd = last_dir = self.cwd
+ else:
+ f = open(self.name, 'rb')
+ skip = True
+ pid_cwd = {}
+ pid_last_dir = {}
+ last_pid = 0
+
+ if self.curdir:
+ self.seenit(self.curdir) # we ignore this
+
+ interesting = 'CEFLRV'
+ for line in f:
+ # ignore anything we don't care about
+ if not line[0] in interesting:
+ continue
+ if self.debug > 2:
+ print >> self.debug_out, "input:", line,
+ w = line.split()
+
+ if skip:
+ if w[0] == 'V':
+ skip = False
+ version = int(w[1])
+ """
+ if version < 4:
+ # we cannot ignore 'W' records
+ # as they may be 'rw'
+ interesting += 'W'
+ """
+ elif w[0] == 'CWD':
+ self.cwd = cwd = last_dir = w[1]
+ self.seenit(cwd) # ignore this
+ if self.debug:
+ print >> self.debug_out, "%s: CWD=%s" % (self.name, cwd)
+ continue
+
+ pid = int(w[1])
+ if pid != last_pid:
+ if last_pid:
+ pid_cwd[last_pid] = cwd
+ pid_last_dir[last_pid] = last_dir
+ cwd = getv(pid_cwd, pid, self.cwd)
+ last_dir = getv(pid_last_dir, pid, self.cwd)
+ last_pid = pid
+
+ # process operations
+ if w[0] == 'F':
+ npid = int(w[2])
+ pid_cwd[npid] = cwd
+ pid_last_dir[npid] = cwd
+ last_pid = npid
+ continue
+ elif w[0] == 'C':
+ cwd = abspath(w[2], cwd, None, self.debug, self.debug_out)
+ if cwd.endswith('/.'):
+ cwd = cwd[0:-2]
+ last_dir = cwd
+ if self.debug > 1:
+ print >> self.debug_out, "cwd=", cwd
+ continue
+
+ if w[2] in self.seen:
+ if self.debug > 2:
+ print >> self.debug_out, "seen:", w[2]
+ continue
+ # file operations
+ if w[0] in 'ML':
+ path = w[2].strip("'")
+ else:
+ path = w[2]
+ # we are never interested in .dirdep files as dependencies
+ if path.endswith('.dirdep'):
+ continue
+ # we don't want to resolve the last component if it is
+ # a symlink
+ path = resolve(path, cwd, last_dir, self.debug, self.debug_out)
+ if not path:
+ continue
+ dir,base = os.path.split(path)
+ if dir in self.seen:
+ if self.debug > 2:
+ print >> self.debug_out, "seen:", dir
+ continue
+ # we can have a path in an objdir which is a link
+ # to the src dir, we may need to add dependencies for each
+ rdir = dir
+ dir = abspath(dir, cwd, last_dir, self.debug, self.debug_out)
+ if rdir == dir or rdir.find('./') > 0:
+ rdir = None
+ # now put path back together
+ path = '/'.join([dir,base])
+ if self.debug > 1:
+ print >> self.debug_out, "raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path)
+ if w[0] in 'SRWL':
+ if w[0] == 'W' and path.endswith('.dirdep'):
+ continue
+ if path in [last_dir, cwd, self.cwd, self.curdir]:
+ if self.debug > 1:
+ print >> self.debug_out, "skipping:", path
+ continue
+ if os.path.isdir(path):
+ if w[0] in 'RW':
+ last_dir = path;
+ if self.debug > 1:
+ print >> self.debug_out, "ldir=", last_dir
+ continue
+
+ if w[0] in 'REWML':
+ # finally, we get down to it
+ if dir == self.cwd or dir == self.curdir:
+ continue
+ srctop = self.find_top(path, self.srctops)
+ if srctop:
+ if self.dpdeps:
+ self.add(self.file_deps, path.replace(srctop,''), 'file')
+ self.add(self.src_deps, dir.replace(srctop,''), 'src')
+ self.seenit(w[2])
+ self.seenit(dir)
+ if rdir and not rdir.startswith(srctop):
+ dir = rdir # for below
+ rdir = None
+ else:
+ continue
+
+ objroot = None
+ for dir in [dir,rdir]:
+ if not dir:
+ continue
+ objroot = self.find_top(dir, self.objroots)
+ if objroot:
+ break
+ if objroot:
+ ddep = self.find_obj(objroot, dir, path, w[2])
+ if ddep:
+ self.add(self.obj_deps, ddep, 'obj')
+ else:
+ # don't waste time looking again
+ self.seenit(w[2])
+ self.seenit(dir)
+ if not file:
+ f.close()
+
+
+def main(argv, klass=MetaFile, xopts='', xoptf=None):
+ """Simple driver for class MetaFile.
+
+ Usage:
+ script [options] [key=value ...] "meta" ...
+
+ Options and key=value pairs contribute to the
+ dictionary passed to MetaFile.
+
+ -S "SRCTOP"
+ add "SRCTOP" to the "SRCTOPS" list.
+
+ -C "CURDIR"
+
+ -O "OBJROOT"
+ add "OBJROOT" to the "OBJROOTS" list.
+
+ -m "MACHINE"
+
+ -H "HOST_TARGET"
+
+ -D "DPDEPS"
+
+ -d bumps debug level
+
+ """
+ import getopt
+
+ # import Psyco if we can
+ # it can speed things up quite a bit
+ have_psyco = 0
+ try:
+ import psyco
+ psyco.full()
+ have_psyco = 1
+ except:
+ pass
+
+ conf = {
+ 'SRCTOPS': [],
+ 'OBJROOTS': [],
+ }
+
+ try:
+ machine = os.environ['MACHINE']
+ if machine:
+ conf['MACHINE'] = machine
+ srctop = os.environ['SB_SRC']
+ if srctop:
+ conf['SRCTOPS'].append(srctop)
+ objroot = os.environ['SB_OBJROOT']
+ if objroot:
+ conf['OBJROOTS'].append(objroot)
+ except:
+ pass
+
+ debug = 0
+ output = True
+
+ opts, args = getopt.getopt(argv[1:], 'dS:C:O:R:m:D:H:q' + xopts)
+ for o, a in opts:
+ if o == '-d':
+ debug += 1
+ elif o == '-q':
+ output = False
+ elif o == '-H':
+ conf['HOST_TARGET'] = a
+ elif o == '-S':
+ if a not in conf['SRCTOPS']:
+ conf['SRCTOPS'].append(a)
+ elif o == '-C':
+ conf['CURDIR'] = a
+ elif o == '-O':
+ if a not in conf['OBJROOTS']:
+ conf['OBJROOTS'].append(a)
+ elif o == '-R':
+ conf['RELDIR'] = a
+ elif o == '-D':
+ conf['DPDEPS'] = a
+ elif o == '-m':
+ conf['MACHINE'] = a
+ elif xoptf:
+ xoptf(o, a, conf)
+
+ conf['debug'] = debug
+
+ # get any var=val assignments
+ eaten = []
+ for a in args:
+ if a.find('=') > 0:
+ k,v = a.split('=')
+ if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']:
+ if k == 'SRCTOP':
+ k = 'SRCTOPS'
+ elif k == 'OBJROOT':
+ k = 'OBJROOTS'
+ if v not in conf[k]:
+ conf[k].append(v)
+ else:
+ conf[k] = v
+ eaten.append(a)
+ continue
+ break
+
+ for a in eaten:
+ args.remove(a)
+
+ debug_out = getv(conf, 'debug_out', sys.stderr)
+
+ if debug:
+ print >> debug_out, "config:"
+ print >> debug_out, "psyco=", have_psyco
+ for k,v in conf.items():
+ print >> debug_out, "%s=%s" % (k,v)
+
+ for a in args:
+ m = klass(a, conf)
+
+ if output:
+ print m.dirdeps()
+
+ print m.src_dirdeps('\nsrc:')
+
+ dpdeps = getv(conf, 'DPDEPS')
+ if dpdeps:
+ m.file_depends(open(dpdeps, 'wb'))
+
+ return m
+
+if __name__ == '__main__':
+ try:
+ main(sys.argv)
+ except:
+ # yes, this goes to stdout
+ print "ERROR: ", sys.exc_info()[1]
+ raise
+
diff --git a/contrib/bmake/mk/meta2deps.sh b/contrib/bmake/mk/meta2deps.sh
new file mode 100755
index 0000000..e7ddd82
--- /dev/null
+++ b/contrib/bmake/mk/meta2deps.sh
@@ -0,0 +1,307 @@
+#!/bin/sh
+
+# NAME:
+# meta2deps.sh - extract useful info from .meta files
+#
+# SYNOPSIS:
+# meta2deps.sh SB="SB" "meta" ...
+#
+# DESCRIPTION:
+# This script looks each "meta" file and extracts the
+# information needed to deduce build and src dependencies.
+#
+# To do this, we extract the 'CWD' record as well as all the
+# syscall traces which describe 'R'ead, 'C'hdir and 'E'xec
+# syscalls.
+#
+# The typical meta file looks like::
+#.nf
+#
+# # Meta data file "path"
+# CMD "command-line"
+# CWD "cwd"
+# TARGET "target"
+# -- command output --
+# -- filemon acquired metadata --
+# # buildmon version 2
+# V 2
+# E "pid" "path"
+# R "pid" "path"
+# C "pid" "cwd"
+# R "pid" "path"
+# X "pid" "status"
+#.fi
+#
+# The fact that all the syscall entry lines start with a single
+# character make these files quite easy to process using sed(1).
+#
+# To simplify the logic the 'CWD' line is made to look like a
+# normal 'C'hdir entry, and "cwd" is remembered so that it can
+# be prefixed to any "path" which is not absolute.
+#
+# If the "path" being read ends in '.srcrel' it is the content
+# of (actually the first line of) that file that we are
+# interested in.
+#
+# Any "path" which lies outside of the sandbox "SB" is generally
+# not of interest and is ignored.
+#
+# The output, is a set of absolute paths with "SB" like:
+#.nf
+#
+# $SB/obj-i386/junos/gnu/lib/csu
+# $SB/obj-i386/junos/gnu/lib/libgcc
+# $SB/obj-i386/bsd/include
+# $SB/obj-i386/bsd/lib/csu/i386-elf
+# $SB/obj-i386/bsd/lib/libc
+# $SB/src/bsd/include
+# $SB/src/bsd/sys/i386/include
+# $SB/src/bsd/sys/sys
+# $SB/src/pan-release/rtsock
+# $SB/src/pfe-shared/include/jnx
+#.fi
+#
+# Which can then be further processed by 'gendirdeps.mk'
+#
+# If we are passed 'DPDEPS='"dpdeps", then for each src file
+# outside of "CURDIR" we read, we output a line like:
+#.nf
+#
+# DPDEPS_$path += $RELDIR
+#.fi
+#
+# with "$path" geting turned into reldir's, so that we can end
+# up with a list of all the directories which depend on each src
+# file in another directory. This can allow for efficient yet
+# complete testing of changes.
+
+
+# RCSid:
+# $Id: meta2deps.sh,v 1.4 2012/11/07 06:55:21 sjg Exp $
+
+# Copyright (c) 2010, Juniper Networks, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE 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
+# OWNER 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.
+
+meta2src() {
+ cat /dev/null "$@" |
+ sed -n '/^R .*\.[chyl]$/s,^..[0-9]* ,,p' |
+ sort -u
+}
+
+meta2dirs() {
+ cat /dev/null "$@" |
+ sed -n '/^R .*\/.*\.[a-z0-9][^\/]*$/s,^..[0-9]* \(.*\)/[^/]*$,\1,p' |
+ sort -u
+}
+
+meta2deps() {
+ DPDEPS=
+ while :
+ do
+ case "$1" in
+ *=*) eval export "$1"; shift;;
+ *) break;;
+ esac
+ done
+
+ [ -z "$RELDIR" ] && unset DPDEPS
+ tf=/tmp/m2d$$-$USER
+ rm -f $tf.*
+ trap 'rm -f $tf.*; trap 0' 0
+
+ > $tf.dirdep
+ > $tf.qual
+ > $tf.srcdep
+ > $tf.srcrel
+ > $tf.dpdeps
+
+ seenit=
+ seensrc=
+ lpid=
+ cat /dev/null "$@" |
+ sed -e 's,^CWD,C C,;/^[CREFL] /!d' -e "s,',,g" |
+ while read op pid path junk
+ do
+ : op=$op pid=$pid path=$path
+ # we track cwd and ldir (of interest) per pid
+ # CWD is bmake's cwd
+ case "$lpid,$pid" in
+ ,C) CWD=$path cwd=$path ldir=$path
+ if [ -z "$SB" ]; then
+ SB=`echo $CWD | sed 's,/obj.*,,'`
+ fi
+ SRCTOP=${SRCTOP:-$SB/src}
+ continue
+ ;;
+ $pid,$pid) ;;
+ *)
+ case "$lpid" in
+ "") ;;
+ *) eval ldir_$lpid=$ldir cwd_$lpid=$cwd;;
+ esac
+ eval ldir=\${ldir_$pid:-$CWD} cwd=\${cwd_$pid:-$CWD}
+ lpid=$pid
+ ;;
+ esac
+
+ case "$op,$path" in
+ *.dirdep) continue;;
+ W,*srcrel) continue;;
+ C,*)
+ case "$path" in
+ /*) cwd=$path;;
+ *) cwd=`cd $cwd/$path 2> /dev/null && /bin/pwd`;;
+ esac
+ # watch out for temp dirs that no longer exist
+ test -d ${cwd:-/dev/null/no/such} || cwd=$CWD
+ continue
+ ;;
+ F,*) eval cwd_$path=$cwd ldir_$path=$ldir
+ continue
+ ;;
+ *) dir=${path%/*}
+ case "$path" in
+ $SB/*|${SB_BACKING_SB:-$SB}/*) ;;
+ $SB_OBJROOT*) ;;
+ /*/stage/*) ;;
+ /*) continue;;
+ *) for path in $ldir/$path $cwd/$path
+ do
+ test -e $path && break
+ done
+ dir=${path%/*}
+ ;;
+ esac
+ ;;
+ esac
+ # avoid repeating ourselves...
+ case "$DPDEPS,$seensrc," in
+ ,*)
+ case ",$seenit," in
+ *,$dir,*) continue;;
+ esac
+ ;;
+ *,$path,*) continue;;
+ esac
+ # canonicalize if needed
+ case "/$dir/" in
+ */../*|*/./*)
+ rdir=$dir
+ dir=`cd $dir 2> /dev/null && /bin/pwd`
+ seen="$rdir,$dir"
+ ;;
+ *) seen=$dir;;
+ esac
+ case "$dir" in
+ ${CURDIR:-.}|${CURDIR:-.}/*|"") continue;;
+ $SRCTOP/*|${SB_BACKING_SB:-$SB}/src/*)
+ # avoid repeating ourselves...
+ case "$DPDEPS,$seensrc," in
+ ,*)
+ case ",$seenit," in
+ *,$dir,*) continue;;
+ esac
+ ;;
+ esac
+ ;;
+ *)
+ case ",$seenit," in
+ *,$dir,*) continue;;
+ esac
+ ;;
+ esac
+ if [ -d $path ]; then
+ case "$path" in
+ */..) ldir=${dir%/*};;
+ *) ldir=$path;;
+ esac
+ continue
+ fi
+ [ -f $path ] || continue
+ case "$dir" in
+ $CWD) continue;; # ignore
+ $SRCTOP/*|${SB_BACKING_SB:-$SB}/src/*)
+ seenit="$seenit,$seen"
+ echo $dir >> $tf.srcdep
+ case "$DPDEPS,$reldir,$seensrc," in
+ ,*) ;;
+ *) seensrc="$seensrc,$path"
+ echo "DPDEPS_$dir/${path##*/} += $RELDIR" >> $tf.dpdeps
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ # if there is a .dirdep we cannot skip
+ # just because we've seen the dir before.
+ if [ -s $path.dirdep ]; then
+ # this file contains:
+ # '# ${RELDIR}.<machine>'
+ echo $path.dirdep >> $tf.qual
+ continue
+ elif [ -s $dir.dirdep ]; then
+ echo $dir.dirdep >> $tf.qual
+ seenit="$seenit,$seen"
+ continue
+ fi
+ seenit="$seenit,$seen"
+ case "$dir" in
+ $SB/*|${SB_OBJROOT:-$SB/}*|${SB_BACKING_SB:-$SB}/*)
+ echo $dir;;
+ esac
+ done > $tf.dirdep
+ _nl=echo
+ for f in $tf.dirdep $tf.qual $tf.srcdep
+ do
+ [ -s $f ] || continue
+ case $f in
+ *qual) # a list of .dirdep files
+ # we can prefix everthing with $OBJTOP to
+ # tell gendirdeps.mk that these are
+ # DIRDEP entries, since they are already
+ # qualified with .<machine> as needed.
+ # We strip .$MACHINE though
+ xargs cat < $f | sort -u |
+ sed "s,^# ,,;s,^,$OBJTOP/,;s,\.$MACHINE\$,,"
+ ;;
+ *) sort -u $f;;
+ esac
+ _nl=:
+ done
+ if [ -s $tf.dpdeps ]; then
+ case "$DPDEPS" in
+ */*) ;;
+ *) echo > $DPDEPS;; # the echo is needed!
+ esac
+ sort -u $tf.dpdeps |
+ sed "s,${SRCTOP}/,,;s,${SB_BACKING_SB:-$SB}/src/,," >> $DPDEPS
+ fi
+ # ensure we produce _something_ else egrep -v gets upset
+ $_nl
+}
+
+case /$0 in
+*/meta2dep*) meta2deps "$@";;
+*/meta2dirs*) meta2dirs "$@";;
+*/meta2src*) meta2src "$@";;
+esac
diff --git a/contrib/bmake/mk/mk-files.txt b/contrib/bmake/mk/mk-files.txt
new file mode 100644
index 0000000..7882641
--- /dev/null
+++ b/contrib/bmake/mk/mk-files.txt
@@ -0,0 +1,467 @@
+mk-files
+********
+
+The term ``mk-files`` refers to a collection of ``*.mk`` files.
+
+You need bmake_ or a *recent* NetBSD_ make.
+If in doubt use bmake_.
+
+Introduction
+============
+
+Many years ago, when building large software projects, I used GNU make
+(or my own patched version of it), and had developed a set of macros
+to simplify developing complex build trees.
+
+Since the early 90's my main development machines, run BSD
+(NetBSD_ to be precise), and the BSD source tree is good example of a
+large software project. It quickly became clear that
+``/usr/share/mk/*.mk`` were a great model, but were quite tightly
+linked to building the BSD tree.
+
+Much as I liked using NetBSD, my customers were more likely to be
+using SunOS, HP-UX etc, so I started on bmake_ and a portable collection
+of mk-files (mk.tar.gz_). NetBSD provided much of the original structure.
+
+Since then I've added a lot of features to NetBSD's make and hence to
+bmake which is kept closely in sync. The mk-files however have
+diverged quite a bit, though ideas are still picked up from NetBSD.
+
+Basics
+------
+
+The BSD build model is very simple. A directory produces one
+component, which is generally either a library or a program.
+Library makefiles include ``lib.mk`` and programs include ``prog.mk``
+and they *do the right thing*.
+
+A simple library makefile might look like::
+
+ LIB = sig
+
+ SRCS = \
+ sigaction.c \
+ sigcompat.c \
+ sighdl.c
+
+ .include <lib.mk>
+
+a simple program makefile::
+
+ PROG = cat
+
+ SRCS = cat.c
+
+ .include <prog.mk>
+
+in such cases even the ``SRCS`` line is unnecessary as ``prog.mk``
+will default it to ``${PROG}.c``.
+
+It is the sensible use of defaults and the plethora of macro modifiers
+provided by bmake_ that allow simple makefiles such as the above
+*just work* on many different systems.
+
+
+mk-files
+========
+
+This section provides a brief description of some of the ``*.mk``
+files.
+
+sys.mk
+------
+
+When bmake starts, it looks for ``sys.mk`` and reads it before doing
+anything else. Thus, this is the place to setup the environment for
+everyone else.
+
+In this distribution, sys.mk avoids doing anything platform dependent.
+It is quite short, and includes a number of other files (which may or
+may not exists)
+
+sys.env.mk
+ If it exists, is expected to do things like conditioning the
+ environment. Since it will only be included by the initial
+ instance of bmake, it should ``.export`` anything that
+ sub-makes might need.
+
+examples/sys.clean-env.mk
+ An example of how to clean the environment.
+ See the file for all the details::
+
+ .if ${MAKE_VERSION} >= 20100606 && ${.MAKE.LEVEL} == 0
+ # we save any env var that starts with these
+ MAKE_SAVE_ENV_PREFIX += SB MK MAKE MACHINE NEED_ CCACHE DISTCC USE_ SSH
+ MAKE_SAVE_ENV_VARS += \
+ PATH HOME USER LOGNAME \
+ SRCTOP OBJTOP OBJROOT \
+ ${_env_vars}
+
+ _env_vars != env | egrep '^(${MAKE_SAVE_ENV_PREFIX:ts|})' | sed 's,=.*,,'; echo
+ _export_list =
+ .for v in ${MAKE_SAVE_ENV_VARS:O:u}
+ .if !empty($v)
+ _export_list += $v
+ $v := ${$v}
+ .endif
+ .endfor
+ # now clobber the environment
+ .unexport-env
+
+ # list of vars that we handle specially below
+ _tricky_env_vars = MAKEOBJDIR
+ # export our selection - sans tricky ones
+ .export ${_export_list:${_tricky_env_vars:${M_ListToSkip}}}
+
+ # this next bit may need tweaking
+ .if defined(MAKEOBJDIR)
+ srctop := ${SRCTOP:U${SB_SRC:U${SB}/src}}
+ objroot := ${OBJROOT:U${SB_OBJROOT:U${SB}/${SB_OBJPREFIX}}}
+ # we'll take care of MACHINE below
+ objtop := ${OBJTOP:U${objroot}${MACHINE}}
+ .if !empty(objtop)
+ # we would normally want something like (/bin/sh):
+ # MAKEOBJDIR="\${.CURDIR:S,${SRCTOP},${OBJROOT}\${MACHINE},}"
+ # the $$ below is how we achieve the same result here.
+ # since everything saved from the environment above
+ # has run through := we need to compensate for ${MACHINE}
+ MAKEOBJDIR = $${.CURDIR:S,${srctop},${objtop:S,${MACHINE},\${MACHINE},},}
+
+ # export these as-is, and do not track...
+ .export-env ${_tricky_env_vars}
+ # now evaluate for ourselves
+ .for v in ${_tricky_env_vars}
+ $v := ${$v}
+ .endfor
+
+ .endif
+ .endif
+ .endif
+
+
+host-target.mk
+ Is used to set macros like ``HOST_TARGET``, ``HOST_OS`` and
+ ``host_os`` which are used to find the next step.
+
+sys/\*.mk
+ Platform specific additions, such as ``Darwin.mk`` or ``SunOS.mk``
+ set things like ``HOST_LIBEXT = .dylib`` for Darwin or
+ ``SHLIB_FULLVERSION = ${SHLIB_MAJOR}`` for SunOS 5.
+ If there is no OS specific file, ``sys/Generic.mk`` is used.
+
+local.sys.mk
+ Any ``local.*.mk`` file is not part of the distribution.
+ This provides a hook for sites to do extra setup without
+ having to edit the distributed files.
+
+
+The above arrangement makes it easy for the mk files to be part of a
+src tree on an NFS volume and to allow building on multiple platforms.
+
+lib.mk
+------
+
+This file is used to build a number of different libraries from the
+same SRCS.
+
+lib${LIB}.a
+ An archive lib of ``.o`` files, this is the default
+
+lib${LIB}_p.a
+ A profiled lib of ``.po`` files.
+ Still an archive lib, but all the objects are built with
+ profiling in mind - hence the different extension.
+ It is skipped if ``MKPROFILE`` is "no".
+
+lib${LIB}_pic.a
+ An archive of ``.so`` objects compiled for relocation.
+ On NetBSD this is the input to ``lib${LIB}.${LD_so}``, it is
+ skipped if ``MKPICLIB`` is "no".
+
+lib${LIB}.${LD_so}
+ A shared library. The value of ``LD_so`` is very platform
+ specific. For example::
+
+ # SunOS 5 and most other ELF systems
+ libsslfd.so.1
+
+ # Darwin
+ libsslfd.1.dylib
+
+ This library will only be built if ``SHLIB_MAJOR`` has
+ a value, and ``MKPIC`` is not set to "no".
+
+There is a lot of platform specific tweaking in ``lib.mk``, largely the
+result of the original distributions trying to avoid interfering with
+the system's ``sys.mk``.
+
+libnames.mk
+-----------
+
+This is included by both ``prog.mk`` and ``lib.mk`` and tries to
+include ``*.libnames.mk`` of which:
+
+local.libnames.mk
+ does not exist unless you create it. It is a handy way for you
+ to customize without touching the distributed files.
+ For example, on a test machine I needed to build openssl but
+ not install it, so put the following in ``local.libnames.mk``::
+
+ .if ${host_os} == "sunos"
+ LIBCRYPTO = ${OBJTOP}/openssl/lib/crypto/libcrypto${DLIBEXT}
+ LIBSSL = ${OBJTOP}/openssl/lib/ssl/libssl${DLIBEXT}
+ INCLUDES_libcrypto = -I${OBJ_libcrypto}
+ .endif
+
+ The makefile created an openssl dir in ``${OBJ_libcrypto}`` to
+ gather all the headers. dpadd.mk_ did the rest.
+
+sjg.libnames.mk
+ not part of the mk-files distribution.
+
+host.libnames.mk
+ contains logic to find any libs named in ``HOST_LIBS`` in
+ ``HOST_LIBDIRS``.
+
+Each file above gets an opportunity to define things like::
+
+ LIBSSLFD ?= ${OBJTOP}/ssl/lib/sslfd/libsslfd${DLIBEXT}
+ INCLUDES_libsslfd = -I${SRC_libsslfd}/h -I${OBJ_libslfd}
+
+these are used by dpadd.mk_ and will be explained below.
+
+dpadd.mk
+--------
+
+This file looks like line noise, and is best considered read-only.
+However it provides some very useful functionality, which simplifies the build.
+
+Makefiles can use the LIB* macros defined via libnames.mk_ or anywhere
+else in various ways::
+
+ # indicate that we need to include headers from LIBCRYPTO
+ # this would result in ${INCLUDES_libcrypto} being added to CFLAGS.
+ SRC_LIBS += ${LIBCRYPTO}
+
+ # indicate that libsslfd must be built already.
+ # it also has the same effect as SRC_LIBS
+ DPADD += ${LIBSSLFD}
+
+ # indicate that not only must libsslfd be built,
+ # but that we need to link with it.
+ # this is almost exactly equivalent to
+ # DPADD += ${LIBSSLFD}
+ # LDADD += -L${LIBSSLFD:H} -lsslfd
+ # and mostly serves to ensure that DPADD and LDADD are in sync.
+ DPLIBS += ${LIBSSLFD}
+
+Any library (referenced by its full path) in any of the above, is
+added to ``DPMAGIC_LIBS`` with the following results, for each lib *foo*.
+
+SRC_libfoo
+ Is set to indicate where the src for libfoo is.
+ By default it is derived from ``LIBFOO`` by replacing
+ ``${OBJTOP}`` with ``${SRCTOP}``.
+
+OBJ_libfoo
+ Not very exciting, is just the dir where libfoo lives.
+
+INCLUDES_libfoo
+ What to add to ``CFLAGS`` to find the public headers.
+ The default varies. If ``${SRC_libfoo}/h`` exists, it is assumed
+ to be the home of all public headers and thus the default is
+ ``-I${SRC_libfoo}/h``
+
+ Otherwise we make no assumptions and the default is
+ ``-I${SRC_libfoo} -I${OBJ_libfoo}``
+
+LDADD_libfoo
+ This only applies to libs reference via ``DPLIBS``.
+ The default is ``-lfoo``, ``LDADD_*`` provides a hook to
+ instantiate other linker flags at the appropriate point
+ without losing the benfits of ``DPLIBS``.
+
+prog.mk
+-------
+
+Compiles the specified SRCS and links them and the nominated libraries
+into a program. Prog makefiles usually need to list the libraries
+that need to be linked. We prefer use of ``DPLIBS`` but the more
+traditional ``DPADD`` and ``LDADD`` work just as well.
+That is::
+
+ DPLIBS += ${LIBCRYPTO}
+
+is equivalent to::
+
+ DPADD += ${LIBCRYPTO}
+ LDADD += -lcrypto
+
+obj.mk
+------
+
+One of the cool aspects of BSD make, is its support for separating
+object files from the src tree. This is also the source of much
+confusion to some.
+
+Traditionally one had to do a separate ``make obj`` pass through the
+tree. If ``MKOBJDIRS`` is "auto", we include auto.obj.mk_.
+
+auto.obj.mk
+-----------
+
+This leverages the ``.OBJDIR`` target introduced some years ago to
+NetBSD make, to automatically create the desired object dir.
+
+subdir.mk
+---------
+
+This is the traditional means of walking the tree. A makefile sets
+``SUBDIR`` to the list of sub-dirs to visit.
+
+If ``SUBDIR_MUST_EXIST`` is set, missing directories cause an error,
+otherwise a warning is issued. If you don't even want the warning,
+set ``MISSING_DIR=continue``.
+
+Traditionally, ``subdir.mk`` prints clue as it visits each subdir::
+
+ ===> ssl
+ ===> ssl/lib
+ ===> ssl/lib/sslfd
+
+you can suppress that - or enhance it by setting ``ECHO_DIR``::
+
+ # suppress subdir noise
+ ECHO_DIR=:
+ # print time stamps
+ ECHO_DIR=echo @ `date "+%s [%Y-%m-%d %T] "`
+
+links.mk
+--------
+
+Provides rules for processing lists of ``LINKS`` and ``SYMLINKS``.
+Each is expected to be a list of ``link`` and ``target`` pairs
+(``link`` -> ``target``).
+
+The logic is generally in a ``_*_SCRIPT`` which is referenced in a
+``_*_USE`` (``.USE``) target.
+
+The ``_BUILD_*`` forms are identical, but do not use ``${DESTDIR}``
+and so are useful for creating symlinks during the build phase.
+For example::
+
+ SYMLINKS += ${.CURDIR}/${MACHINE_ARCH}/include machine
+ header_links: _BUILD_SYMLINKS_USE
+
+ md.o: header_links
+
+would create a symlink called ``machine`` in ``${.OBJDIR}`` pointing to
+``${.CURDIR}/${MACHINE_ARCH}/include`` before compiling ``md.o``
+
+
+autoconf.mk
+-----------
+
+Deals with running (or generating) GNU autoconf ``configure`` scripts.
+
+dep.mk
+------
+
+Deals with collecting dependencies. Another useful feature of BSD
+make is the separation of this sort of information into a ``.depend``
+file. ``MKDEP`` needs to point to a suitable tool (like mkdeps.sh_)
+
+If ``USE_AUTODEP_MK`` is "yes" includes autodep.mk_
+
+autodep.mk
+----------
+
+Leverages the ``-MD`` feature of recent GCC to collect dependency
+information as a side effect of compilation. With this GCC puts
+dependency info into a ``.d`` file.
+
+Unfortunately GCC bases the name of the ``.d`` file on the name of the
+input rather than the output file, which causes problems when the same
+source is compiled different ways. The latest GCC supports ``-MF`` to
+name the ``.d`` file and ``-MT`` to control the name to put as the
+dependent.
+
+Recent bmake allows dependencies for the ``.END`` target (run at the
+end if everything was successful), and ``autodep.mk`` uses this to
+post process the ``.d`` files into ``.depend``.
+
+auto.dep.mk
+-----------
+
+A much simpler implementation than autodep.mk_ it uses
+``-MF ${.TARGET:T}.d``
+to avoid possible conflicts during parallel builds.
+This precludes the use of suffix rules to drive ``make depend``, so
+dep.mk_ handles that if specifically requested.
+
+own.mk
+------
+
+Normally included by ``init.mk`` (included by ``lib.mk`` and
+``prog.mk`` etc), sets macros for default ownership etc.
+
+It includes ``${MAKECONF}`` if it is defined and exists.
+
+man.mk
+------
+
+Deals with man pages.
+
+warnings.mk
+-----------
+
+This provides a means of fine grained control over warnings on a per
+``${MACHINE}`` or even file basis.
+
+A makefile sets ``WARNINGS_SET`` to name a list of warnings
+and individual ``W_*`` macros can be used to tweak them.
+For example::
+
+ WARNINGS_SET = HIGH
+ W_unused_sparc = -Wno-unused
+
+would add all the warnings in ``${HIGH_WARNINGS}`` to CFLAGS, but
+on sparc, ``-Wno-unused`` would replace ``-Wunused``.
+
+You should never need to edit ``warnings.mk``, it will include
+``warnings-sets.mk`` if it exists and you use that to make any local
+customizations.
+
+Meta mode
+=========
+
+The 20110505 and later versions of ``mk-files`` include a number of
+makefile contributed by Juniper Networks, Inc.
+These allow the latest version of bmake_ to run in `meta mode`_.
+
+.. _`meta mode`: bmake-meta-mode.htm
+
+Install
+=======
+
+You can use the content of mk.tar.gz_ without installing at all.
+
+The script ``install-mk`` takes care of copying ``*.mk`` into a
+destination directory, and unless told not to, create ``bsd.*.mk`` links
+for ``lib.mk`` etc.
+
+If you just want to create the ``bsd.*.mk`` links in the directory
+where you unpacked the tar file, you can::
+
+ ./mk/install-mk ./mk
+
+------
+
+.. _bmake: bmake.htm
+.. _NetBSD: http://www.netbsd.org/
+.. _mkdeps.sh: http://www.crufty.net/ftp/pub/sjg/mkdeps.sh
+.. _mk.tar.gz: http://www.crufty.net/ftp/pub/sjg/mk.tar.gz
+
+:Author: sjg@crufty.net
+:Revision: $Id: mk-files.txt,v 1.15 2011/06/08 07:06:18 sjg Exp $
+:Copyright: Crufty.NET
diff --git a/contrib/bmake/mk/nls.mk b/contrib/bmake/mk/nls.mk
new file mode 100644
index 0000000..e302c8d
--- /dev/null
+++ b/contrib/bmake/mk/nls.mk
@@ -0,0 +1,48 @@
+# $NetBSD: bsd.nls.mk,v 1.3 1996/10/18 02:34:45 thorpej Exp $
+
+.if !target(.MAIN)
+.if exists(${.CURDIR}/../Makefile.inc)
+.include "${.CURDIR}/../Makefile.inc"
+.endif
+
+.MAIN: all
+.endif
+
+.SUFFIXES: .cat .msg
+
+.msg.cat:
+ @rm -f ${.TARGET}
+ gencat ${.TARGET} ${.IMPSRC}
+
+.if defined(NLS) && !empty(NLS)
+NLSALL= ${NLS:.msg=.cat}
+.NOPATH: ${NLSALL}
+.endif
+
+.if !defined(NLSNAME)
+.if defined(PROG)
+NLSNAME=${PROG}
+.else
+NLSNAME=lib${LIB}
+.endif
+.endif
+
+nlsinstall:
+.if defined(NLSALL)
+ @for msg in ${NLSALL}; do \
+ NLSLANG=`basename $$msg .cat`; \
+ dir=${DESTDIR}${NLSDIR}/$${NLSLANG}; \
+ ${INSTALL} -d $$dir; \
+ ${INSTALL} ${COPY} -o ${NLSOWN} -g ${NLSGRP} -m ${NLSMODE} $$msg $$dir/${NLSNAME}.cat; \
+ done
+.endif
+
+.if defined(NLSALL)
+all: ${NLSALL}
+
+install: nlsinstall
+
+cleandir: cleannls
+cleannls:
+ rm -f ${NLSALL}
+.endif
diff --git a/contrib/bmake/mk/obj.mk b/contrib/bmake/mk/obj.mk
new file mode 100644
index 0000000..b936379
--- /dev/null
+++ b/contrib/bmake/mk/obj.mk
@@ -0,0 +1,113 @@
+# $Id: obj.mk,v 1.15 2012/11/11 22:37:02 sjg Exp $
+#
+# @(#) Copyright (c) 1999-2010, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !target(__${.PARSEFILE:S,bsd.,,}__)
+__${.PARSEFILE:S,bsd.,,}__:
+
+.include <init.mk>
+
+ECHO_TRACE ?= echo
+
+.if ${MK_OBJDIRS} == "no"
+obj:
+objlink:
+objwarn:
+.else
+
+# this has to match how make behaves
+.if defined(MAKEOBJDIRPREFIX) || defined(MAKEOBJDIR)
+.if defined(MAKEOBJDIRPREFIX)
+__objdir:= ${MAKEOBJDIRPREFIX}${.CURDIR}
+.else
+__objdir:= ${MAKEOBJDIR}
+.endif
+.else
+__objdir= ${__objlink}
+.endif
+
+.if defined(OBJMACHINE)
+__objlink= obj.${MACHINE}
+.else
+__objlink= obj
+.endif
+
+.if ${MK_AUTO_OBJ} == "yes"
+.-include "auto.obj.mk"
+.endif
+
+.NOPATH: ${__objdir}
+.PHONY: obj
+
+obj: _SUBDIRUSE
+ @if test ! -d ${__objdir}/.; then \
+ mkdir -p ${__objdir}; \
+ if test ! -d ${__objdir}; then \
+ mkdir ${__objdir}; exit 1; \
+ fi; \
+ ${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \
+ fi
+
+.if !target(_SUBDIRUSE)
+# this just allows us to be included by ourselves
+_SUBDIRUSE:
+.endif
+
+# so we can interact with freebsd makefiles
+.if !target(objwarn)
+objwarn:
+.if ${.OBJDIR} == ${.CURDIR}
+ @echo "Warning Object directory is ${.CURDIR}"
+.elif ${.OBJDIR} != ${__objdir}
+ @echo "Warning Object directory is ${.OBJDIR} vs. ${__objdir}"
+.endif
+.endif
+
+.if !target(objlink)
+objlink:
+.if ${__objdir:T} != ${__objlink}
+ @if test -d ${__objdir}/.; then \
+ ${RM} -f ${.CURDIR}/${__objlink}; \
+ ${LN} -s ${__objdir} ${.CURDIR}/${__objlink}; \
+ echo "${__objlink} -> ${__objdir}"; \
+ else \
+ echo "No ${__objdir} to link to - do a 'make obj'"; \
+ fi
+.endif
+.endif
+.endif
+
+_CURDIR?= ${.CURDIR}
+_OBJDIR?= ${.OBJDIR}
+
+.if !target(print-objdir)
+print-objdir:
+ @echo ${_OBJDIR}
+.endif
+
+.if !target(whereobj)
+whereobj:
+ @echo ${_OBJDIR}
+.endif
+
+.if !target(destroy)
+.if ${.CURDIR} != ${.OBJDIR}
+destroy:
+ (cd ${_CURDIR} && rm -rf ${_OBJDIR})
+.else
+destroy: clean
+.endif
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/options.mk b/contrib/bmake/mk/options.mk
new file mode 100644
index 0000000..7d1bf67
--- /dev/null
+++ b/contrib/bmake/mk/options.mk
@@ -0,0 +1,58 @@
+# $Id: options.mk,v 1.6 2013/01/28 19:28:52 sjg Exp $
+#
+# @(#) Copyright (c) 2012, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# Inspired by FreeBSD bsd.own.mk, but intentionally simpler.
+
+# Options are normally listed in either OPTIONS_DEFAULT_{YES,NO}
+# We convert these to ${OPTION}/{yes,no} in OPTIONS_DEFAULT_VALUES.
+# We add the OPTIONS_DEFAULT_NO first so they take precedence.
+# This allows override of an OPTIONS_DEFAULT_YES by adding it to
+# OPTIONS_DEFAULT_NO or adding ${OPTION}/no to OPTIONS_DEFAULT_VALUES.
+# An OPTIONS_DEFAULT_NO option can only be overridden by putting
+# ${OPTION}/yes in OPTIONS_DEFAULT_VALUES.
+# A makefile may set NO_* (or NO*) to indicate it cannot do something.
+# User sets WITH_* and WITHOUT_* to indicate what they want.
+# We set MK_* which is then all we need care about.
+OPTIONS_DEFAULT_VALUES += \
+ ${OPTIONS_DEFAULT_NO:O:u:S,$,/no,} \
+ ${OPTIONS_DEFAULT_YES:O:u:S,$,/yes,}
+
+.for o in ${OPTIONS_DEFAULT_VALUES:M*/*}
+.if ${o:T:tl} == "no"
+.if defined(WITH_${o:H}) && !defined(NO_${o:H}) && !defined(NO${o:H})
+MK_${o:H} ?= yes
+.else
+MK_${o:H} ?= no
+.endif
+.else
+.if defined(WITHOUT_${o:H}) || defined(NO_${o:H}) || defined(NO${o:H})
+MK_${o:H} ?= no
+.else
+MK_${o:H} ?= yes
+.endif
+.endif
+.endfor
+
+# OPTIONS_DEFAULT_DEPENDENT += FOO_UTILS/FOO
+# if neither WITH[OUT]_FOO_UTILS is set, use value of MK_FOO
+.for o in ${OPTIONS_DEFAULT_DEPENDENT:M*/*:O:u}
+.if defined(WITH_${o:H}) && !defined(NO_${o:H}) && !defined(NO${o:H})
+MK_${o:H} ?= yes
+.elif defined(WITHOUT_${o:H}) || defined(NO_${o:H}) || defined(NO${o:H})
+MK_${o:H} ?= no
+.else
+MK_${o:H} ?= ${MK_${o:T}}
+.endif
+.endfor
diff --git a/contrib/bmake/mk/own.mk b/contrib/bmake/mk/own.mk
new file mode 100644
index 0000000..85ea66b
--- /dev/null
+++ b/contrib/bmake/mk/own.mk
@@ -0,0 +1,244 @@
+# $Id: own.mk,v 1.26 2012/12/11 23:40:19 sjg Exp $
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+.if !target(__init.mk__)
+.include "init.mk"
+.endif
+
+.ifndef NOMAKECONF
+MAKECONF?= /etc/mk.conf
+.-include "${MAKECONF}"
+.endif
+
+.include <host-target.mk>
+
+TARGET_OSNAME?= ${_HOST_OSNAME}
+TARGET_OSREL?= ${_HOST_OSREL}
+TARGET_OSTYPE?= ${HOST_OSTYPE}
+TARGET_HOST?= ${HOST_TARGET}
+
+# these may or may not exist
+.-include "${TARGET_HOST}.mk"
+.-include "config.mk"
+
+RM?= rm
+LN?= ln
+INSTALL?= install
+
+prefix?= /usr
+.if exists(${prefix}/lib)
+libprefix?= ${prefix}
+.else
+libprefix?= /usr
+.endif
+
+# FreeBSD at least does not set this
+MACHINE_ARCH?=${MACHINE}
+# we need to make sure these are defined too in case sys.mk fails to.
+COMPILE.s?= ${CC} ${AFLAGS} -c
+LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp
+LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+CXXFLAGS?= ${CFLAGS}
+COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
+LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.f?= ${FC} ${FFLAGS} -c
+LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+LEX.l?= ${LEX} ${LFLAGS}
+COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+YACC.y?= ${YACC} ${YFLAGS}
+
+# for suffix rules
+IMPFLAGS?= ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} ${CPPFLAGS.${.IMPSRC:T}}
+.for s in .c .cc
+COMPILE.$s += ${IMPFLAGS}
+LINK.$s += ${IMPFLAGS}
+.endfor
+
+PRINT.VAR.MAKE = MAKESYSPATH=${MAKESYSPATH:U${.PARSEDIR}} ${.MAKE}
+.if empty(.MAKEFLAGS:M-V*)
+.if defined(MAKEOBJDIRPREFIX) || defined(MAKEOBJDIR)
+PRINTOBJDIR= ${PRINT.VAR.MAKE} -r -V .OBJDIR -f /dev/null xxx
+.else
+PRINTOBJDIR= ${PRINT.VAR.MAKE} -V .OBJDIR
+.endif
+.else
+PRINTOBJDIR= echo # prevent infinite recursion
+.endif
+
+# we really like to have SRCTOP and OBJTOP defined...
+.if !defined(SRCTOP) || !defined(OBJTOP)
+.-include "srctop.mk"
+.endif
+
+.if !defined(SRCTOP) || !defined(OBJTOP)
+# dpadd.mk is rather pointless without these
+OPTIONS_DEFAULT_NO+= DPADD_MK
+.endif
+
+# process options
+OPTIONS_DEFAULT_NO+= \
+ INSTALL_AS_USER \
+ LIBTOOL \
+ LINT \
+ META_MODE \
+
+OPTIONS_DEFAULT_YES+= \
+ ARCHIVE \
+ AUTODEP \
+ AUTO_OBJ \
+ CRYPTO \
+ DOC \
+ DPADD_MK \
+ GDB \
+ KERBEROS \
+ LINKLIB \
+ MAN \
+ NLS \
+ OBJ \
+ PIC \
+ SHARE \
+ SKEY \
+ YP \
+
+OPTIONS_DEFAULT_DEPENDENT+= \
+ CATPAGES/MAN \
+ OBJDIRS/OBJ \
+ PICINSTALL/LINKLIB \
+ PICLIB/PIC \
+ PROFILE/LINKLIB \
+
+.include <options.mk>
+
+.if ${MK_INSTALL_AS_USER} == "yes"
+# We ignore this if user is root.
+_uid!= id -u
+.if ${_uid} != 0
+.if !defined(USERGRP)
+USERGRP!= id -g
+.export USERGRP
+.endif
+.for x in BIN CONF DOC INFO KMOD LIB MAN NLS SHARE
+$xOWN= ${USER}
+$xGRP= ${USERGRP}
+.endfor
+.endif
+.endif
+
+# override this in sys.mk
+ROOT_GROUP?= wheel
+BINGRP?= ${ROOT_GROUP}
+BINOWN?= root
+BINMODE?= 555
+NONBINMODE?= 444
+
+# Define MANZ to have the man pages compressed (gzip)
+#MANZ= 1
+
+MANTARGET?= cat
+MANDIR?= ${prefix}/share/man/${MANTARGET}
+MANGRP?= ${BINGRP}
+MANOWN?= ${BINOWN}
+MANMODE?= ${NONBINMODE}
+
+LIBDIR?= ${libprefix}/lib
+SHLIBDIR?= ${libprefix}/lib
+.if ${USE_SHLIBDIR:Uno} == "yes"
+_LIBSODIR?= ${SHLIBDIR}
+.else
+_LIBSODIR?= ${LIBDIR}
+.endif
+# this is where ld.*so lives
+SHLINKDIR?= /usr/libexec
+LINTLIBDIR?= ${libprefix}/libdata/lint
+LIBGRP?= ${BINGRP}
+LIBOWN?= ${BINOWN}
+LIBMODE?= ${NONBINMODE}
+
+DOCDIR?= ${prefix}/share/doc
+DOCGRP?= ${BINGRP}
+DOCOWN?= ${BINOWN}
+DOCMODE?= ${NONBINMODE}
+
+NLSDIR?= ${prefix}/share/nls
+NLSGRP?= ${BINGRP}
+NLSOWN?= ${BINOWN}
+NLSMODE?= ${NONBINMODE}
+
+KMODDIR?= ${prefix}/lkm
+KMODGRP?= ${BINGRP}
+KMODOWN?= ${BINOWN}
+KMODMODE?= ${NONBINMODE}
+
+COPY?= -c
+STRIP_FLAG?= -s
+
+.if ${TARGET_OSNAME} == "NetBSD"
+.if exists(/usr/libexec/ld.elf_so)
+OBJECT_FMT=ELF
+.endif
+OBJECT_FMT?=a.out
+.endif
+# sys.mk should set something appropriate if need be.
+OBJECT_FMT?=ELF
+
+.if (${_HOST_OSNAME} == "FreeBSD")
+CFLAGS+= ${CPPFLAGS}
+.endif
+
+# allow for per target flags
+# apply the :T:R first, so the more specific :T can override if needed
+CPPFLAGS += ${CPPFLAGS_${.TARGET:T:R}} ${CPPFLAGS_${.TARGET:T}}
+CFLAGS += ${CFLAGS_${.TARGET:T:R}} ${CFLAGS_${.TARGET:T}}
+
+# Define SYS_INCLUDE to indicate whether you want symbolic links to the system
+# source (``symlinks''), or a separate copy (``copies''); (latter useful
+# in environments where it's not possible to keep /sys publicly readable)
+#SYS_INCLUDE= symlinks
+
+# don't try to generate PIC versions of libraries on machines
+# which don't support PIC.
+.if (${MACHINE_ARCH} == "vax") || \
+ ((${MACHINE_ARCH} == "mips") && defined(STATIC_TOOLCHAIN)) || \
+ ((${MACHINE_ARCH} == "alpha") && defined(ECOFF_TOOLCHAIN))
+MK_PIC=no
+.endif
+
+# No lint, for now.
+NOLINT=
+
+
+.if ${MK_LINKLIB} == "no"
+MK_PICINSTALL= no
+MK_PROFILE= no
+.endif
+
+.if ${MK_MAN} == "no"
+MK_CATPAGES= no
+.endif
+
+.if ${MK_OBJ} == "no"
+MK_OBJDIRS= no
+MK_AUTO_OBJ= no
+.endif
+
+.if ${MK_SHARE} == "no"
+MK_CATPAGES= no
+MK_DOC= no
+MK_INFO= no
+MK_MAN= no
+MK_NLS= no
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/prlist.mk b/contrib/bmake/mk/prlist.mk
new file mode 100644
index 0000000..09d7dfd
--- /dev/null
+++ b/contrib/bmake/mk/prlist.mk
@@ -0,0 +1,36 @@
+# $Id: prlist.mk,v 1.3 2008/07/17 16:24:57 sjg Exp $
+#
+# @(#) Copyright (c) 2006, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+# this needs to be included after all the lists it will process
+# are defined - which is why it is a separate file.
+# Usage looks like:
+# MAKEFLAGS= ${.MAKE} -f ${MAKEFILE} prlist.SOMETHING_HUGE | xargs whatever
+#
+.if make(prlist.*)
+.for t in ${.TARGETS:Mprlist.*:E}
+.if empty($t)
+prlist.$t:
+.else
+prlist.$t: ${$t:O:u:S,^,prlist-,}
+${$t:O:u:S,^,prlist-,}: .PHONY
+ @echo "${.TARGET:S,prlist-,,}"
+.endif
+.endfor
+.endif
+
+.endif
diff --git a/contrib/bmake/mk/prog.mk b/contrib/bmake/mk/prog.mk
new file mode 100644
index 0000000..99fd7e8
--- /dev/null
+++ b/contrib/bmake/mk/prog.mk
@@ -0,0 +1,219 @@
+# $Id: prog.mk,v 1.24 2012/12/13 23:04:14 sjg Exp $
+
+.if !target(__${.PARSEFILE}__)
+__${.PARSEFILE}__:
+
+.include <init.mk>
+
+# FreeBSD at least expects MAN8 etc.
+.if defined(MAN) && !empty(MAN)
+_sect:=${MAN:E}
+MAN${_sect}=${MAN}
+.endif
+
+.SUFFIXES: .out .o .c .cc .C .y .l .s .8 .7 .6 .5 .4 .3 .2 .1 .0
+
+CFLAGS+= ${COPTS}
+
+.if ${TARGET_OSNAME} == "NetBSD"
+.if ${MACHINE_ARCH} == "sparc64"
+CFLAGS+= -mcmodel=medlow
+.endif
+
+# ELF platforms depend on crtbegin.o and crtend.o
+.if ${OBJECT_FMT} == "ELF"
+.ifndef LIBCRTBEGIN
+LIBCRTBEGIN= ${DESTDIR}/usr/lib/crtbegin.o
+.MADE: ${LIBCRTBEGIN}
+.endif
+.ifndef LIBCRTEND
+LIBCRTEND= ${DESTDIR}/usr/lib/crtend.o
+.MADE: ${LIBCRTEND}
+.endif
+_SHLINKER= ${SHLINKDIR}/ld.elf_so
+.else
+LIBCRTBEGIN?=
+LIBCRTEND?=
+_SHLINKER= ${SHLINKDIR}/ld.so
+.endif
+
+.ifndef LIBCRT0
+LIBCRT0= ${DESTDIR}/usr/lib/crt0.o
+.MADE: ${LIBCRT0}
+.endif
+.endif # NetBSD
+
+# here is where you can define what LIB* are
+.-include <libnames.mk>
+.if ${MK_DPADD_MK} == "yes"
+# lots of cool magic, but might not suit everyone.
+.include <dpadd.mk>
+.endif
+
+.if defined(SHAREDSTRINGS)
+CLEANFILES+=strings
+.c.o:
+ ${CC} -E ${CFLAGS} ${.IMPSRC} | xstr -c -
+ @${CC} ${CFLAGS} -c x.c -o ${.TARGET}
+ @rm -f x.c
+
+.cc.o:
+ ${CXX} -E ${CXXFLAGS} ${.IMPSRC} | xstr -c -
+ @mv -f x.c x.cc
+ @${CXX} ${CXXFLAGS} -c x.cc -o ${.TARGET}
+ @rm -f x.cc
+
+.C.o:
+ ${CXX} -E ${CXXFLAGS} ${.IMPSRC} | xstr -c -
+ @mv -f x.c x.C
+ @${CXX} ${CXXFLAGS} -c x.C -o ${.TARGET}
+ @rm -f x.C
+.endif
+
+
+.if defined(PROG)
+SRCS?= ${PROG}.c
+.for s in ${SRCS:N*.h:N*.sh:M*/*}
+${.o .po .lo:L:@o@${s:T:R}$o@}: $s
+.endfor
+.if !empty(SRCS:N*.h:N*.sh)
+OBJS+= ${SRCS:T:N*.h:N*.sh:R:S/$/.o/g}
+LOBJS+= ${LSRCS:.c=.ln} ${SRCS:M*.c:.c=.ln}
+.endif
+
+.if defined(OBJS) && !empty(OBJS)
+.NOPATH: ${OBJS} ${PROG} ${SRCS:M*.[ly]:C/\..$/.c/} ${YHEADER:D${SRCS:M*.y:.y=.h}}
+
+# this is known to work for NetBSD 1.6 and FreeBSD 4.2
+.if ${TARGET_OSNAME} == "NetBSD" || ${TARGET_OSNAME} == "FreeBSD"
+_PROGLDOPTS=
+.if ${SHLINKDIR} != "/usr/libexec" # XXX: change or remove if ld.so moves
+_PROGLDOPTS+= -Wl,-dynamic-linker=${_SHLINKER}
+.endif
+.if defined(LIBDIR) && ${SHLIBDIR} != ${LIBDIR}
+_PROGLDOPTS+= -Wl,-rpath-link,${DESTDIR}${SHLIBDIR}:${DESTDIR}/usr/lib \
+ -L${DESTDIR}${SHLIBDIR}
+.endif
+_PROGLDOPTS+= -Wl,-rpath,${SHLIBDIR}:/usr/lib
+
+.if defined(PROG_CXX)
+_CCLINK= ${CXX}
+_SUPCXX= -lstdc++ -lm
+.endif
+.endif # NetBSD
+
+_CCLINK?= ${CC}
+
+.if defined(DESTDIR) && exists(${LIBCRT0}) && ${LIBCRT0} != "/dev/null"
+
+${PROG}: ${LIBCRT0} ${OBJS} ${LIBC} ${DPADD}
+ ${_CCLINK} ${LDFLAGS} ${LDSTATIC} -o ${.TARGET} -nostdlib ${_PROGLDOPTS} -L${DESTDIR}/usr/lib ${LIBCRT0} ${LIBCRTBEGIN} ${OBJS} ${LDADD} -L${DESTDIR}/usr/lib ${_SUPCXX} -lgcc -lc -lgcc ${LIBCRTEND}
+
+.else
+
+${PROG}: ${LIBCRT0} ${OBJS} ${LIBC} ${DPADD}
+ ${_CCLINK} ${LDFLAGS} ${LDSTATIC} -o ${.TARGET} ${_PROGLDOPTS} ${OBJS} ${LDADD}
+
+.endif # defined(DESTDIR)
+.endif # defined(OBJS) && !empty(OBJS)
+
+.if !defined(MAN)
+MAN= ${PROG}.1
+.endif # !defined(MAN)
+.endif # defined(PROG)
+
+.if !defined(_SKIP_BUILD)
+all: ${PROG}
+.endif
+all: _SUBDIRUSE
+
+.if !target(clean)
+cleanprog:
+ rm -f a.out [Ee]rrs mklog core *.core \
+ ${PROG} ${OBJS} ${LOBJS} ${CLEANFILES}
+
+clean: _SUBDIRUSE cleanprog
+cleandir: _SUBDIRUSE cleanprog
+.else
+cleandir: _SUBDIRUSE clean
+.endif
+
+.if defined(SRCS) && (!defined(MKDEP) || ${MKDEP} != autodep)
+afterdepend: .depend
+ @(TMP=/tmp/_depend$$$$; \
+ sed -e 's/^\([^\.]*\).o[ ]*:/\1.o \1.ln:/' \
+ < .depend > $$TMP; \
+ mv $$TMP .depend)
+.endif
+
+.if !target(install)
+.if !target(beforeinstall)
+beforeinstall:
+.endif
+.if !target(afterinstall)
+afterinstall:
+.endif
+
+.if !empty(BINOWN)
+PROG_INSTALL_OWN ?= -o ${BINOWN} -g ${BINGRP}
+.endif
+
+.if !target(realinstall)
+realinstall: proginstall
+.endif
+.if !target(proginstall)
+proginstall:
+.if defined(PROG)
+ [ -d ${DESTDIR}${BINDIR} ] || \
+ ${INSTALL} -d ${PROG_INSTALL_OWN} -m 775 ${DESTDIR}${BINDIR}
+ ${INSTALL} ${COPY} ${STRIP_FLAG} ${PROG_INSTALL_OWN} -m ${BINMODE} \
+ ${PROG} ${DESTDIR}${BINDIR}/${PROG_NAME}
+.endif
+.if defined(HIDEGAME)
+ (cd ${DESTDIR}/usr/games; rm -f ${PROG}; ln -s dm ${PROG})
+.endif
+.endif
+
+.include <links.mk>
+
+install: maninstall install_links _SUBDIRUSE
+
+install_links:
+.if !empty(SYMLINKS)
+ @set ${SYMLINKS}; ${_SYMLINKS_SCRIPT}
+.endif
+.if !empty(LINKS)
+ @set ${LINKS}; ${_LINKS_SCRIPT}
+.endif
+
+maninstall: afterinstall
+afterinstall: realinstall
+realinstall: beforeinstall
+.endif
+
+.if !target(lint)
+lint: ${LOBJS}
+.if defined(LOBJS) && !empty(LOBJS)
+ @${LINT} ${LINTFLAGS} ${LDFLAGS:M-L*} ${LOBJS} ${LDADD}
+.endif
+.endif
+
+.NOPATH: ${PROG}
+.if defined(OBJS) && !empty(OBJS)
+.NOPATH: ${OBJS}
+.endif
+
+.if ${MK_MAN} != "no"
+.include <man.mk>
+.endif
+
+.if ${MK_NLS} != "no"
+.include <nls.mk>
+.endif
+
+.include <obj.mk>
+.include <dep.mk>
+.include <subdir.mk>
+.include <final.mk>
+
+.endif
diff --git a/contrib/bmake/mk/progs.mk b/contrib/bmake/mk/progs.mk
new file mode 100644
index 0000000..0fd2312
--- /dev/null
+++ b/contrib/bmake/mk/progs.mk
@@ -0,0 +1,87 @@
+# $Id: progs.mk,v 1.11 2012/11/06 17:18:54 sjg Exp $
+#
+# @(#) Copyright (c) 2006, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.MAIN: all
+
+.if defined(PROGS)
+
+# In meta mode, we can capture dependenices for _one_ of the progs.
+# if makefile doesn't nominate one, we use the first.
+.ifndef UPDATE_DEPENDFILE_PROG
+UPDATE_DEPENDFILE_PROG = ${PROGS:[1]}
+.export UPDATE_DEPENDFILE_PROG
+.endif
+
+.ifndef PROG
+# They may have asked us to build just one
+.for t in ${PROGS}
+.if make($t)
+PROG ?= $t
+.endif
+.endfor
+.endif
+
+.if defined(PROG)
+# just one of many
+PROG_VARS += CFLAGS CPPFLAGS CXXFLAGS DPADD DPLIBS LDADD MAN SRCS
+.for v in ${PROG_VARS:O:u}
+$v += ${${v}_${PROG}:U${${v}.${PROG}}}
+.endfor
+
+# for meta mode, there can be only one!
+.if ${PROG} == ${UPDATE_DEPENDFILE_PROG:Uno}
+UPDATE_DEPENDFILE ?= yes
+.endif
+UPDATE_DEPENDFILE ?= NO
+
+# ensure that we don't clobber each other's dependencies
+DEPENDFILE?= .depend.${PROG}
+# prog.mk will do the rest
+.else
+all: ${PROGS}
+
+# We cannot capture dependencies for meta mode here
+UPDATE_DEPENDFILE = NO
+# nor can we safely run in parallel.
+.NOTPARALLEL:
+.endif
+.endif
+
+# handle being called [bsd.]progs.mk
+.include <${.PARSEFILE:S,progs,prog,}>
+
+.ifndef PROG
+PROGS_TARGETS += clean
+
+.for p in ${PROGS}
+.if defined(PROGS_CXX) && !empty(PROGS_CXX:M$p)
+# bsd.prog.mk may need to know this
+x.$p= PROG_CXX=$p
+.endif
+
+$p ${p}_p: .PHONY .MAKE
+ (cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} 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})
+.endfor
+.endfor
+
+.for t in ${PROGS_TARGETS:O:u}
+$t: ${PROGS:%=%.$t}
+.endfor
+
+.endif
diff --git a/contrib/bmake/mk/rst2htm.mk b/contrib/bmake/mk/rst2htm.mk
new file mode 100644
index 0000000..8bd66da
--- /dev/null
+++ b/contrib/bmake/mk/rst2htm.mk
@@ -0,0 +1,43 @@
+# $Id: rst2htm.mk,v 1.8 2011/04/03 21:39:25 sjg Exp $
+#
+# @(#) Copyright (c) 2009, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# convert reStructuredText to HTML, using rst2html.py from
+# docutils - http://docutils.sourceforge.net/
+
+.if empty(TXTSRCS)
+TXTSRCS != 'ls' -1t ${.CURDIR}/*.txt ${.CURDIR}/*.rst 2>/dev/null; echo
+.endif
+RSTSRCS ?= ${TXTSRCS}
+HTMFILES ?= ${RSTSRCS:R:T:O:u:%=%.htm}
+RST2HTML ?= rst2html.py
+RST2S5 ?= rst2s5.py
+# the following will run RST2S5 if the target name contains the word 'slides'
+# otherwise it uses RST2HTML
+RST2HTM = ${"${.TARGET:T:M*slides*}":?${RST2S5} ${RST2S5_FLAGS}:${RST2HTML} ${RST2HTML_FLAGS}}
+
+RST_SUFFIXES ?= .rst .txt
+
+CLEANFILES += ${HTMFILES}
+
+html: ${HTMFILES}
+
+.SUFFIXES: ${RST_SUFFIXES} .htm
+
+${RST_SUFFIXES:@s@$s.htm@}:
+ ${RST2HTM} ${.IMPSRC} ${.TARGET}
+
+.for s in ${RSTSRCS:O:u}
+${s:R:T}.htm: $s
+.endfor
diff --git a/contrib/bmake/mk/scripts.mk b/contrib/bmake/mk/scripts.mk
new file mode 100644
index 0000000..efd65f9
--- /dev/null
+++ b/contrib/bmake/mk/scripts.mk
@@ -0,0 +1,52 @@
+# $Id: scripts.mk,v 1.2 2006/11/09 01:55:18 sjg Exp $
+
+.include <init.mk>
+
+.if defined(SCRIPTS)
+
+all: ${SCRIPTS}
+
+.PHONY: scriptsinstall
+install: scriptsinstall
+
+.if !target(scriptsinstall)
+SCRIPTSDIR?= ${BINDIR}
+SCRIPTSOWN?= ${BINOWN}
+SCRIPTSGRP?= ${BINGRP}
+SCRIPTSMODE?= ${BINMODE}
+
+# how we get script name from src
+SCRIPTSNAME_MOD?=T:R
+
+script_targets= ${SCRIPTS:@s@${DESTDIR}${SCRIPTSDIR_$s:U${SCRIPTSDIR}}/${SCRIPTSNAME_$s:U${s:${SCRIPTSNAME_MOD}}}@}
+
+scriptsinstall:: ${script_targets}
+
+.PRECIOUS: ${script_targets}
+.if !defined(UPDATE)
+.PHONY: ${script_targets}
+.endif
+
+INSTALL_FLAGS?= ${RENAME} ${PRESERVE} ${COPY} ${INSTPRIV} \
+ -o ${OWN_${.TARGET:T}:U${SCRIPTSOWN}} \
+ -g ${GRP_${.TARGET:T}:U${SCRIPTSGRP}} \
+ -m ${MODE_${.TARGET:T}:U${SCRIPTSMODE}}
+
+__SCRIPTINSTALL_USE: .USE
+ ${INSTALL} ${INSTALL_FLAGS_${.TARGET:T}:U${INSTALL_FLAGS}} \
+ ${.ALLSRC} ${.TARGET}
+
+.for s in ${SCRIPTS}
+.if !defined(BUILD) && !make(all) && !make(${s})
+${DESTDIR}${SCRIPTSDIR_$s:U${SCRIPTSDIR}}/${SCRIPTSNAME_$s:U${s:${SCRIPTSNAME_MOD}}}: .MADE
+.endif
+${DESTDIR}${SCRIPTSDIR_$s:U${SCRIPTSDIR}}/${SCRIPTSNAME_$s:U${s:${SCRIPTSNAME_MOD}}}: ${s} __SCRIPTINSTALL_USE
+.endfor
+.endif
+
+.endif
+
+.if !target(scriptsinstall)
+scriptsinstall::
+.endif
+
diff --git a/contrib/bmake/mk/srctop.mk b/contrib/bmake/mk/srctop.mk
new file mode 100644
index 0000000..fab090c
--- /dev/null
+++ b/contrib/bmake/mk/srctop.mk
@@ -0,0 +1,66 @@
+# $Id: srctop.mk,v 1.3 2012/11/11 23:20:18 sjg Exp $
+#
+# @(#) Copyright (c) 2012, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.if !defined(SRCTOP)
+# if using mk(1) SB will be set.
+.ifdef SB
+.if ${.CURDIR:S,${SB},,} != ${.CURDIR}
+# we are actually within SB
+.ifdef SB_SRC
+SRCTOP:= ${SB_SRC}
+.elif exists(${SB}/src)
+SRCTOP:= ${SB}/src
+.else
+SRCTOP:= ${SB}
+.endif
+.endif
+.endif
+
+.if !defined(SRCTOP)
+.for rd in share/mk build/mk mk
+.if ${_this_mk_dir:M*${rd}} != ""
+.if ${.CURDIR:S,${_this_mk_dir:${rd:C,[^/]+,H,g:S,/, ,g:ts:}},,} != ${.CURDIR}
+SRCTOP:= ${_this_mk_dir:${rd:C,[^/]+,H,g:S,/, ,g:ts:}}
+.endif
+.endif
+.endfor
+.endif
+
+.if !defined(SRCTOP)
+_SRCTOP_TEST_?= [ -f ../.sandbox-env -o -d share/mk ]
+# Linux at least has a bug where attempting to check an automounter
+# directory will hang. So avoid looking above /a/b
+SRCTOP!= cd ${.CURDIR}; while :; do \
+ here=`pwd`; \
+ ${_SRCTOP_TEST_} && { echo $$here; break; }; \
+ case $$here in /*/*/*) cd ..;; *) echo ""; break;; esac; \
+ done
+.endif
+.if defined(SRCTOP) && exists(${SRCTOP}/.)
+.export SRCTOP
+.endif
+.endif
+
+.if !defined(OBJTOP) && !empty(SRCTOP)
+.if defined(MAKEOBJDIRPREFIX) && exists(${MAKEOBJDIRPREFIX}${SRCTOP})
+OBJTOP= ${MAKEOBJDIRPREFIX}${SRCTOP}
+.elif (exists(${SRCTOP}/Makefile) || exists(${SRCTOP}/makefile))
+OBJTOP!= cd ${SRCTOP} && ${PRINTOBJDIR}
+.endif
+.if empty(OBJTOP)
+OBJTOP= ${SRCTOP}
+.endif
+.export OBJTOP
+.endif
diff --git a/contrib/bmake/mk/subdir.mk b/contrib/bmake/mk/subdir.mk
new file mode 100644
index 0000000..313b7d7
--- /dev/null
+++ b/contrib/bmake/mk/subdir.mk
@@ -0,0 +1,99 @@
+# $Id: subdir.mk,v 1.14 2012/11/12 04:34:33 sjg Exp $
+# skip missing directories...
+
+# $NetBSD: bsd.subdir.mk,v 1.11 1996/04/04 02:05:06 jtc Exp $
+# @(#)bsd.subdir.mk 5.9 (Berkeley) 2/1/91
+
+.if ${.MAKE.LEVEL} == 0 && ${.MAKE.MODE:Uno:Mmeta*} != ""
+.include <meta.subdir.mk>
+# keep everyone happy
+_SUBDIRUSE:
+.elif !commands(_SUBDIRUSE) && !defined(NO_SUBDIR) && !defined(NOSUBDIR)
+.if exists(${.CURDIR}/Makefile.inc)
+.include "Makefile.inc"
+.endif
+.if !target(.MAIN)
+.MAIN: all
+.endif
+
+ECHO_DIR ?= echo
+.ifdef SUBDIR_MUST_EXIST
+MISSING_DIR=echo "Missing ===> ${.CURDIR}/$${entry}"; exit 1
+.else
+MISSING_DIR=echo "Skipping ===> ${.CURDIR}/$${entry}"; continue
+.endif
+
+_SUBDIRUSE: .USE
+.if defined(SUBDIR)
+ @Exists() { test -f $$1; }; \
+ for entry in ${SUBDIR}; do \
+ (set -e; \
+ if Exists ${.CURDIR}/$${entry}.${MACHINE}/[mM]akefile; then \
+ _newdir_="$${entry}.${MACHINE}"; \
+ elif Exists ${.CURDIR}/$${entry}/[mM]akefile; then \
+ _newdir_="$${entry}"; \
+ else \
+ ${MISSING_DIR}; \
+ fi; \
+ if test X"${_THISDIR_}" = X""; then \
+ _nextdir_="$${_newdir_}"; \
+ else \
+ _nextdir_="$${_THISDIR_}/$${_newdir_}"; \
+ fi; \
+ ${ECHO_DIR} "===> $${_nextdir_}"; \
+ cd ${.CURDIR}/$${_newdir_}; \
+ ${.MAKE} _THISDIR_="$${_nextdir_}" \
+ ${.TARGET:S/realinstall/install/:S/.depend/depend/}) || exit 1; \
+ done
+
+${SUBDIR}::
+ @set -e; if test -d ${.CURDIR}/${.TARGET}.${MACHINE}; then \
+ _newdir_=${.TARGET}.${MACHINE}; \
+ else \
+ _newdir_=${.TARGET}; \
+ fi; \
+ ${ECHO_DIR} "===> $${_newdir_}"; \
+ cd ${.CURDIR}/$${_newdir_}; \
+ ${.MAKE} _THISDIR_="$${_newdir_}" all
+.endif
+
+.if !target(install)
+.if !target(beforeinstall)
+beforeinstall:
+.endif
+.if !target(afterinstall)
+afterinstall:
+.endif
+install: maninstall
+maninstall: afterinstall
+afterinstall: realinstall
+realinstall: beforeinstall _SUBDIRUSE
+.endif
+
+.if defined(SRCS)
+etags: ${SRCS}
+ -cd ${.CURDIR}; etags `echo ${.ALLSRC:N*.h} | sed 's;${.CURDIR}/;;'`
+.endif
+
+SUBDIR_TARGETS += \
+ all \
+ clean \
+ cleandir \
+ includes \
+ depend \
+ lint \
+ obj \
+ tags \
+ etags
+
+.for t in ${SUBDIR_TARGETS:O:u}
+$t: _SUBDIRUSE
+.endfor
+
+.include <own.mk>
+.if make(destroy*)
+.include <obj.mk>
+.endif
+.endif
+# make sure this exists
+all:
diff --git a/contrib/bmake/mk/sys.clean-env.mk b/contrib/bmake/mk/sys.clean-env.mk
new file mode 100644
index 0000000..b1867c3
--- /dev/null
+++ b/contrib/bmake/mk/sys.clean-env.mk
@@ -0,0 +1,119 @@
+# $Id: sys.clean-env.mk,v 1.20 2012/11/12 06:56:04 sjg Exp $
+#
+# @(#) Copyright (c) 2009, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# This makefile would normally be included by sys.env.mk
+
+# The variables used by this makefile include:
+#
+# MAKE_ENV_SAVE_VAR_LIST
+# The actuall list of variables from the environment that will be
+# preserved.
+# MAKE_ENV_SAVE_PREFIX_LIST
+# A list of prefixes to match against the environment - the results
+# are added to MAKE_ENV_SAVE_VAR_LIST after being filtered by...
+# MAKE_ENV_SAVE_EXCLUDE_LIST
+# A list of words or patterns which is turned into a list of :N
+# modifiers.
+
+.if ${.MAKE.LEVEL} == 0 && ${MAKE_VERSION} >= 20100606
+# We save any env var that starts with the words in MAKE_ENV_SAVE_PREFIX_LIST.
+# This gets expanded to an egrep expression like '^(A|B|C...)'
+# and added to MAKE_ENV_SAVE_VAR_LIST below.
+# If any of these end up being too greedy, MAKE_ENV_SAVE_EXCLUDE_LIST
+# can be used to filter.
+MAKE_ENV_SAVE_PREFIX_LIST += \
+ CCACHE \
+ CVS \
+ DEBUG \
+ DISTCC \
+ HOST \
+ MACHINE \
+ MAKE \
+ MK \
+ NEED_ \
+ SB_ \
+ SSH \
+ SVN \
+ USE_ \
+ WITH_ \
+ WITHOUT_ \
+
+
+# This could be a list of vars or patterns to explicitly exclude.
+MAKE_ENV_SAVE_EXCLUDE_LIST ?= _
+
+# This is the actual list that we will save
+# HOME is probably something worth clobbering eg.
+# HOME=/var/empty
+MAKE_ENV_SAVE_VAR_LIST += \
+ HOME \
+ LOGNAME \
+ OBJROOT \
+ OBJTOP \
+ PATH \
+ SB \
+ SRCTOP \
+ USER \
+ ${_env_vars:${MAKE_ENV_SAVE_EXCLUDE_LIST:${M_ListToSkip}}}
+
+_env_vars != env | egrep '^(${MAKE_ENV_SAVE_PREFIX_LIST:ts|})' | sed 's,=.*,,'; echo
+
+_export_list =
+.for v in ${MAKE_ENV_SAVE_VAR_LIST:O:u}
+.if defined($v)
+_export_list += $v
+# Save current value
+$v := ${$v}
+.endif
+.endfor
+
+# Now, clobber the environment
+.unexport-env
+
+# This is a list of vars that we handle specially below
+_tricky_env_vars = MAKEOBJDIR OBJTOP
+# Export our selection - sans tricky ones
+.export ${_export_list:${_tricky_env_vars:${M_ListToSkip}}}
+
+# This next bit may need tweaking
+# if you don't happen to like the way I set it.
+.if defined(MAKEOBJDIR)
+# We are going to set this to the equivalent of the shell's
+# MAKEOBJDIR='${.CURDIR:S,${SRCTOP},${OBJTOP},}'
+_srctop := ${SRCTOP:U${SB_SRC:U${SB}/src}}
+_objroot := ${OBJROOT:U${SB_OBJROOT:U${SB}/${SB_OBJPREFIX}}}
+_objtop := ${OBJTOP:U${_objroot}${MACHINE}}
+# Take care of ${MACHINE}
+.if ${MACHINE} == "host" || ${OBJTOP} == ${HOST_OBJTOP:Uno}
+OBJTOP = ${_objtop:S,${HOST_TARGET}$,\${MACHINE},}
+.else
+OBJTOP = ${_objtop:S,${MACHINE}$,\${MACHINE},}
+.endif
+# Export like this
+MAKEOBJDIR = $${.CURDIR:S,${_srctop},$${OBJTOP},}
+#.info ${MAKE_SAVE_ENV_VARS _srctop _objroot _objtop OBJTOP MAKEOBJDIR:L:@v@${.newline}$v=${$v}@}
+
+# Export these as-is, and do not track...
+# otherwise the environment will be ruined when we evaluate them below.
+.export-env ${_tricky_env_vars}
+
+# Now evaluate for ourselves
+.for v in ${_tricky_env_vars}
+$v := ${$v}
+.endfor
+#.info ${_tricky_env_vars:@v@${.newline}$v=${$v}@}
+
+.endif # MAKEOBJDIR
+.endif # level 0
diff --git a/contrib/bmake/mk/sys.dependfile.mk b/contrib/bmake/mk/sys.dependfile.mk
new file mode 100644
index 0000000..752a46f
--- /dev/null
+++ b/contrib/bmake/mk/sys.dependfile.mk
@@ -0,0 +1,47 @@
+# $Id: sys.dependfile.mk,v 1.4 2012/11/08 18:31:42 sjg Exp $
+#
+# @(#) Copyright (c) 2012, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# This only makes sense in meta mode.
+# This allows a mixture of auto generated as well as manually edited
+# dependency files, which can be differentiated by their names.
+# As per dirdeps.mk we only require:
+# 1. a common prefix
+# 2. that machine specific files end in .${MACHINE}
+#
+# The .MAKE.DEPENDFILE_PREFERENCE below is an example.
+
+# All depend file names should start with this
+.MAKE.DEPENDFILE_PREFIX ?= Makefile.depend
+
+# The order of preference: we will use the first one of these we find
+# otherwise the 1st entry will be used by default.
+.MAKE.DEPENDFILE_PREFERENCE ?= \
+ ${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.${MACHINE} \
+ ${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}
+
+_e := ${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}
+.if !empty(_e)
+.MAKE.DEPENDFILE := ${_e:[1]}
+.elif ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}} != "" && ${.MAKE.DEPENDFILE_PREFERENCE:[1]:E} != ${MACHINE}
+# MACHINE specific depend files are supported, but *not* default.
+# If any already exist, we should follow suit.
+_aml = ${ALL_MACHINE_LIST:Uarm amd64 i386 powerpc:N${MACHINE}} ${MACHINE}
+# MACHINE must be the last entry in _aml ;-)
+_e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@}
+.if !empty(_e)
+.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}:[1]}
+.endif
+.endif
+.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:[1]}
diff --git a/contrib/bmake/mk/sys.mk b/contrib/bmake/mk/sys.mk
new file mode 100644
index 0000000..30eca9b
--- /dev/null
+++ b/contrib/bmake/mk/sys.mk
@@ -0,0 +1,199 @@
+# $Id: sys.mk,v 1.35 2012/11/12 06:27:51 sjg Exp $
+#
+# @(#) Copyright (c) 2003-2009, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# Avoid putting anything platform specific in here.
+
+# We use the following paradigm for preventing multiple inclusion.
+# It relies on the fact that conditionals and dependencies are resolved
+# at the time they are read.
+#
+# _this ?= ${.PARSEFILE}
+# .if !target(__${_this}__)
+# __${_this}__:
+#
+.if ${MAKE_VERSION:U0} > 20100408
+_this = ${.PARSEDIR:tA}/${.PARSEFILE}
+.else
+_this = ${.PARSEDIR}/${.PARSEFILE}
+.endif
+
+# Sometimes we want to turn on debugging in just one or two places
+# if .CURDIR is matched by any entry in DEBUG_MAKE_SYS_DIRS we
+# will apply DEBUG_MAKE_FLAGS now.
+# if an entry in DEBUG_MAKE_DIRS matches, we at the end of sys.mk
+# eg. DEBUG_MAKE_FLAGS=-dv DEBUG_MAKE_SYS_DIRS="*lib/sjg"
+# use DEBUG_MAKE_FLAGS0 to apply only to .MAKE.LEVEL 0
+#
+.if ${.MAKE.LEVEL:U1} == 0
+# we use indirection, to simplify the tests below, and incase
+# DEBUG_* were given on our command line.
+_DEBUG_MAKE_FLAGS = ${DEBUG_MAKE_FLAGS0}
+_DEBUG_MAKE_SYS_DIRS = ${DEBUG_MAKE_SYS_DIRS0:U${DEBUG_MAKE_SYS_DIRS}}
+_DEBUG_MAKE_DIRS = ${DEBUG_MAKE_DIRS0:U${DEBUG_MAKE_DIRS}}
+.else
+_DEBUG_MAKE_FLAGS = ${DEBUG_MAKE_FLAGS}
+_DEBUG_MAKE_SYS_DIRS = ${DEBUG_MAKE_SYS_DIRS}
+_DEBUG_MAKE_DIRS = ${DEBUG_MAKE_DIRS}
+.endif
+
+.if !empty(_DEBUG_MAKE_FLAGS)
+.if ${_DEBUG_MAKE_SYS_DIRS:Uno:@x@${.CURDIR:M$x}@} != ""
+.MAKEFLAGS: ${_DEBUG_MAKE_FLAGS}
+.endif
+.endif
+
+# if this is an ancient version of bmake
+MAKE_VERSION ?= 0
+.if ${MAKE_VERSION:M*make-*}
+# turn it into what we want - just the date
+MAKE_VERSION := ${MAKE_VERSION:[1]:C,.*-,,}
+.endif
+
+# some useful modifiers
+
+# A useful trick for testing multiple :M's against something
+# :L says to use the variable's name as its value - ie. literal
+# got = ${clean* destroy:${M_ListToMatch:S,V,.TARGETS,}}
+M_ListToMatch = L:@m@$${V:M$$m}@
+# match against our initial targets (see above)
+M_L_TARGETS = ${M_ListToMatch:S,V,_TARGETS,}
+
+# turn a list into a set of :N modifiers
+# NskipFoo = ${Foo:${M_ListToSkip}}
+M_ListToSkip= O:u:ts::S,:,:N,g:S,^,N,
+
+# type should be a builtin in any sh since about 1980,
+# AUTOCONF := ${autoconf:L:${M_whence}}
+M_type = @x@(type $$x 2> /dev/null); echo;@:sh:[0]:N* found*:[@]:C,[()],,g
+M_whence = ${M_type}:M/*
+
+# convert a path to a valid shell variable
+M_P2V = tu:C,[./-],_,g
+
+# convert path to absolute
+.if ${MAKE_VERSION:U0} > 20100408
+M_tA = tA
+.else
+M_tA = C,.*,('cd' & \&\& 'pwd') 2> /dev/null || echo &,:sh
+.endif
+
+# absoulte path to what we are reading.
+_PARSEDIR = ${.PARSEDIR:${M_tA}}
+
+# we expect a recent bmake
+.if !defined(_TARGETS)
+# some things we do only once
+_TARGETS := ${.TARGETS}
+.-include <sys.env.mk>
+.endif
+
+# we need HOST_TARGET etc below.
+.include <host-target.mk>
+
+# find the OS specifics
+.if defined(SYS_OS_MK)
+.include <${SYS_OS_MK}>
+.else
+_sys_mk =
+.for x in ${HOST_OSTYPE} ${HOST_TARGET} ${HOST_OS} ${MACHINE} Generic
+.if empty(_sys_mk)
+.-include <sys/$x.mk>
+_sys_mk := ${.MAKE.MAKEFILES:M*/$x.mk}
+.if !empty(_sys_mk)
+_sys_mk := sys/${_sys_mk:T}
+.endif
+.endif
+.if empty(_sys_mk)
+# might be an old style
+.-include <$x.sys.mk>
+_sys_mk := ${.MAKE.MAKEFILES:M*/$x.sys.mk:T}
+.endif
+.endfor
+
+SYS_OS_MK := ${_sys_mk}
+.export SYS_OS_MK
+.endif
+
+# allow customization without editing.
+.-include <local.sys.mk>
+
+# if you want objdirs make them automatic
+.if ${MKOBJDIRS:Uno} == "auto"
+.include <auto.obj.mk>
+.endif
+
+.if !empty(SRCTOP)
+.if ${.CURDIR} == ${SRCTOP}
+RELDIR = .
+.elif ${.CURDIR:M${SRCTOP}/*}
+RELDIR := ${.CURDIR:S,${SRCTOP}/,,}
+.endif
+.endif
+
+MACHINE_ARCH.host ?= ${_HOST_ARCH}
+MACHINE_ARCH.${MACHINE} ?= ${MACHINE}
+.if empty(MACHINE_ARCH)
+MACHINE_ARCH = ${MACHINE_ARCH.${MACHINE}}
+.endif
+
+.ifndef ROOT_GROUP
+ROOT_GROUP != sed -n /:0:/s/:.*//p /etc/group
+.export ROOT_GROUP
+.endif
+
+unix ?= We run ${_HOST_OSNAME}.
+
+# A race condition in mkdir, means that it can bail if another
+# process made a dir that mkdir expected to.
+# We repeat the mkdir -p a number of times to try and work around this.
+# We stop looping as soon as the dir exists.
+# If we get to the end of the loop, a plain mkdir will issue an error.
+Mkdirs= Mkdirs() { \
+ for d in $$*; do \
+ for i in 1 2 3 4 5 6; do \
+ mkdir -p $$d; \
+ test -d $$d && return 0; \
+ done; \
+ mkdir $$d || exit $$?; \
+ done; }
+
+# this often helps with debugging
+.SUFFIXES: .cpp-out
+
+.c.cpp-out:
+ @${COMPILE.c:N-c} -E ${.IMPSRC} | grep -v '^[ ]*$$'
+
+.cc.cpp-out:
+ @${COMPILE.cc:N-c} -E ${.IMPSRC} | grep -v '^[ ]*$$'
+
+# we don't include own.mk but user can expect -DWITH_META_MODE to work
+.if defined(WITHOUT_META_MODE)
+USE_META= no
+.elif defined(WITH_META_MODE)
+USE_META= yes
+.endif
+.if ${USE_META:Uno} == "yes"
+.-include <meta.sys.mk>
+.endif
+# make sure we have a harmless value
+.MAKE.MODE ?= normal
+
+# if .CURDIR is matched by any entry in DEBUG_MAKE_DIRS we
+# will apply DEBUG_MAKE_FLAGS, now.
+.if !empty(_DEBUG_MAKE_FLAGS)
+.if ${_DEBUG_MAKE_DIRS:Uno:@x@${.CURDIR:M$x}@} != ""
+.MAKEFLAGS: ${_DEBUG_MAKE_FLAGS}
+.endif
+.endif
diff --git a/contrib/bmake/mk/sys/AIX.mk b/contrib/bmake/mk/sys/AIX.mk
new file mode 100644
index 0000000..18adfa6
--- /dev/null
+++ b/contrib/bmake/mk/sys/AIX.mk
@@ -0,0 +1,197 @@
+# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $
+# @(#)sys.mk 5.11 (Berkeley) 3/13/91
+
+OS= AIX
+unix= We run ${OS}.
+ROOT_GROUP= system
+
+# This needs a lot of work yet...
+
+NOPIC=no # no shared libs?
+
+.SUFFIXES: .out .a .ln .o .c .cc .C .F .f .r .y .l .s .S .cl .p .h .sh .m4
+
+.LIBS: .a
+
+AR= ar
+ARFLAGS= rl
+RANLIB= ranlib
+
+AS= as
+AFLAGS=
+COMPILE.s= ${AS} ${AFLAGS}
+LINK.s= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S= ${CC} ${AFLAGS} ${CPPFLAGS} -c
+LINK.S= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+.if exists(/usr/local/bin/gcc)
+CC= gcc
+DBG= -O -g
+STATIC?= -static
+.else
+CC= cc
+DBG= -g
+STATIC=
+.endif
+CFLAGS= ${DBG}
+COMPILE.c= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX= g++
+CXXFLAGS= ${CFLAGS}
+COMPILE.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP= cpp
+.if defined(DESTDIR)
+CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include
+.endif
+
+MK_DEP= mkdeps.sh -N
+FC= f77
+FFLAGS= -O
+RFLAGS=
+COMPILE.f= ${FC} ${FFLAGS} -c
+LINK.f= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+LEX= lex
+LFLAGS=
+LEX.l= ${LEX} ${LFLAGS}
+
+LD= ld
+LDFLAGS=
+
+LINT= lint
+LINTFLAGS= -chapbx
+
+MAKE= bmake
+
+PC= pc
+PFLAGS=
+COMPILE.p= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL= sh
+
+YACC= yacc
+YFLAGS= -d
+YACC.y= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# C++
+.cc:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} -o ${.TARGET} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/Darwin.mk b/contrib/bmake/mk/sys/Darwin.mk
new file mode 100644
index 0000000..d05e32a
--- /dev/null
+++ b/contrib/bmake/mk/sys/Darwin.mk
@@ -0,0 +1,220 @@
+# $NetBSD: Darwin.sys.mk,v 1.3 2003/02/16 09:44:41 grant Exp $
+# @(#)sys.mk 8.2 (Berkeley) 3/21/94
+
+OS= Darwin
+unix?= We run ${OS}.
+
+.SUFFIXES: .out .a .ln .o .s .S .c .cc .cpp .cxx .C .F .f .r .y .l .cl .p .h
+.SUFFIXES: .sh .m4 .dylib
+
+.LIBS: .a .dylib
+
+SHLIBEXT = .dylib
+HOST_LIBEXT = .dylib
+DSHLIBEXT = .dylib
+
+AR?= ar
+ARFLAGS?= rl
+RANLIB =
+
+AS?= as
+AFLAGS?=
+COMPILE.s?= ${AS} ${AFLAGS}
+LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c
+LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+.if exists(/usr/bin/gcc)
+CC?= gcc -pipe
+.else
+CC?= cc -pipe
+.endif
+DBG?= -O2
+CFLAGS?= ${DBG}
+COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+.if exists(/usr/bin/g++)
+CXX?= g++
+.else
+CXX?= c++
+.endif
+CXXFLAGS?= ${CFLAGS}
+COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+OBJC?= ${CC}
+OBJCFLAGS?= ${CFLAGS}
+COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
+LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP?= cpp
+NOLINT= 1
+CPPFLAGS?=
+
+MK_DEP?= mkdeps.sh -N
+
+FC?= f77
+FFLAGS?= -O
+RFLAGS?=
+COMPILE.f?= ${FC} ${FFLAGS} -c
+LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+INSTALL?= install
+
+LEX?= lex
+LFLAGS?=
+LEX.l?= ${LEX} ${LFLAGS}
+
+LD?= ld
+LDFLAGS?=
+
+SHLIB_TEENY = 0
+SHLIB_MINOR = 0
+
+MKPICLIB = no
+LIBEXT = .dylib
+
+LINT?= lint
+LINTFLAGS?= -chapbx
+
+LORDER?= lorder
+
+MAKE?= bmake
+
+NM?= nm
+
+PC?= pc
+PFLAGS?=
+COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL?= sh
+
+SIZE?= size
+
+TSORT?= tsort -q
+
+YACC?= bison -y
+YFLAGS?= -d
+YACC.y?= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# C++
+.cc:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} -o ${.TARGET} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/Generic.mk b/contrib/bmake/mk/sys/Generic.mk
new file mode 100644
index 0000000..179da97
--- /dev/null
+++ b/contrib/bmake/mk/sys/Generic.mk
@@ -0,0 +1,208 @@
+# $Id: Generic.mk,v 1.11 2010/09/24 05:59:53 sjg Exp $
+#
+
+# some reasonable defaults
+.SUFFIXES: .out .a .ln .o .s .S .c .cc .cpp .cxx .C .F .f .r .y .l .cl .p .h
+.SUFFIXES: .sh .m4
+
+.LIBS: .a
+
+tools = \
+ ar \
+ lorder \
+ ranlib \
+ tsort
+
+.for t in ${tools}
+${t:tu} := ${t:${M_whence}}
+.endfor
+
+# need to make sure this is set
+MACHINE_ARCH.${MACHINE} ?= ${MACHINE}
+.if empty(MACHINE_ARCH)
+MACHINE_ARCH = ${MACHINE_ARCH.${MACHINE}}
+.endif
+
+.if !empty(TSORT)
+TSORT += -q
+.endif
+
+ARFLAGS?= rl
+
+AS?= as
+AFLAGS?=
+.if ${MACHINE_ARCH} == "sparc64"
+AFLAGS+= -Wa,-Av9a
+.endif
+COMPILE.s?= ${CC} ${AFLAGS} -c
+LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp
+LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CC?= cc
+DBG?= -O2
+CFLAGS?= ${DBG}
+COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX?= c++
+CXXFLAGS?= ${CFLAGS}
+COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+OBJC?= ${CC}
+OBJCFLAGS?= ${CFLAGS}
+COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
+LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP?= cpp
+CPPFLAGS?=
+
+FC?= f77
+FFLAGS?= -O
+RFLAGS?=
+COMPILE.f?= ${FC} ${FFLAGS} -c
+LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+INSTALL?= install
+
+LEX?= lex
+LFLAGS?=
+LEX.l?= ${LEX} ${LFLAGS}
+
+LD?= ld
+LDFLAGS?=
+
+LINT?= lint
+LINTFLAGS?= -chapbxzF
+
+MAKE?= ${.MAKE}
+
+NM?= nm
+
+PC?= pc
+PFLAGS?=
+COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL?= sh
+
+SIZE?= size
+
+YACC?= yacc
+YFLAGS?=
+YACC.y?= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.c.ln:
+ ${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC}
+
+# C++
+.cc .cpp .cxx .C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o .cpp.o .cxx.o .C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a .cpp.a .cxx.a .C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
+
diff --git a/contrib/bmake/mk/sys/HP-UX.mk b/contrib/bmake/mk/sys/HP-UX.mk
new file mode 100644
index 0000000..f6e3e2c
--- /dev/null
+++ b/contrib/bmake/mk/sys/HP-UX.mk
@@ -0,0 +1,237 @@
+# $Id: HP-UX.mk,v 1.9 2003/09/30 16:42:23 sjg Exp $
+# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $
+# @(#)sys.mk 5.11 (Berkeley) 3/13/91
+
+OS= HP-UX
+ROOT_GROUP= root
+unix?= We run ${OS}.
+
+# HP-UX's cc does not provide any clues as to wether this is 9.x or 10.x
+# nor does sys/param.h, so we'll use the existence of /hp-ux
+.if exists("/hp-ux")
+OSMAJOR?=9
+.endif
+OSMAJOR?=10
+__HPUX_VERSION?=${OSMAJOR}
+
+.SUFFIXES: .out .a .ln .o .c .cc .C .F .f .r .y .l .s .S .cl .p .h .sh .m4
+
+LIBMODE= 755
+LIBCRT0= /lib/crt0.o
+
+.LIBS: .a
+
+# +b<path> is needed to stop the binaries from insisting on having
+# the build tree available :-)
+# +s tells the dynamic loader to use SHLIB_PATH if set
+LD_bpath?=-Wl,+b/lib:/usr/lib:/usr/local/lib
+LD_spath?=-Wl,+s
+LDADD+= ${LD_bpath} ${LD_spath}
+
+.if exists(/usr/lib/end.o)
+LDADD+= /usr/lib/end.o
+.endif
+
+AR= ar
+ARFLAGS= rl
+RANLIB= :
+
+AFLAGS=
+COMPILE.s= ${AS} ${AFLAGS}
+LINK.s= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S= ${CC} ${AFLAGS} ${CPPFLAGS} -c
+LINK.S= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+.if exists(/usr/local/bin/gcc)
+PIPE?= -pipe
+CC?= gcc ${PIPE}
+AS= gas
+DBG?= -O -g
+STATIC?= -static
+.if defined(DESTDIR)
+CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include
+.endif
+.else
+# HP's bundled compiler knows not -g or -O
+AS= as
+CC= cc
+.if exists(/opt/ansic/bin/cc)
+CCMODE?=-Ae +ESlit
+PICFLAG?= +z
+LD_x=
+DBG?=-g -O
+.endif
+DBG?=
+STATIC?= -Wl,-a,archive
+.endif
+.if (${__HPUX_VERSION} == "10")
+CCSOURCE_FLAGS?= -D_HPUX_SOURCE
+.else
+CCSOURCE_FLAGS?= -D_HPUX_SOURCE -D_INCLUDE_POSIX_SOURCE -D_INCLUDE_XOPEN_SOURCE -D_INCLUDE_XOPEN_SOURCE_EXTENDED
+.endif
+CFLAGS= ${DBG}
+CFLAGS+= ${CCMODE} -D__hpux__ -D__HPUX_VERSION=${__HPUX_VERSION} ${CCSOURCE_FLAGS}
+COMPILE.c= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX= g++
+CXXFLAGS= ${CFLAGS}
+COMPILE.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP= cpp
+
+MK_DEP= mkdeps.sh -N
+FC= f77
+FFLAGS= -O
+RFLAGS=
+COMPILE.f= ${FC} ${FFLAGS} -c
+LINK.f= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+LEX= lex
+LFLAGS=
+LEX.l= ${LEX} ${LFLAGS}
+
+LD= ld
+LDFLAGS=
+
+LINT= lint
+LINTFLAGS= -chapbx
+
+MAKE= bmake
+
+PC= pc
+PFLAGS=
+COMPILE.p= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+# HP's sh sucks
+ENV=
+SHELL= /bin/ksh
+
+.if exists(/usr/local/bin/bison)
+YACC= bison -y
+.else
+YACC= yacc
+.endif
+YFLAGS= -d
+YACC.y= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# C++
+.cc:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} -o ${.TARGET} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/IRIX.mk b/contrib/bmake/mk/sys/IRIX.mk
new file mode 100644
index 0000000..783e405
--- /dev/null
+++ b/contrib/bmake/mk/sys/IRIX.mk
@@ -0,0 +1,199 @@
+# $NetBSD: IRIX.sys.mk,v 1.2 2002/12/24 23:03:27 jschauma Exp $
+# @(#)sys.mk 8.2 (Berkeley) 3/21/94
+
+.if ${.PARSEFILE} == "sys.mk"
+.ifndef ROOT_GROUP
+OS!= uname -s
+ROOT_GROUP!= sed -n /:0:/s/:.*//p /etc/group
+.MAKEOVERRIDES+= OS ROOT_GROUP
+.endif
+unix?= We run ${OS}.
+.endif
+
+.SUFFIXES: .out .a .ln .o .s .S .c .cc .cpp .cxx .C .F .f .r .y .l .cl .p .h
+.SUFFIXES: .sh .m4
+
+.LIBS: .a
+
+AR?= ar
+ARFLAGS?= rl
+RANLIB?= ranlib
+
+AS?= as
+AFLAGS?=
+COMPILE.s?= ${CC} ${AFLAGS} -c
+LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp
+LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CC?= cc
+NOGCCERROR?= # defined
+DBG?= -O2
+CFLAGS?= ${DBG}
+COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX?= CC
+CXXFLAGS?= ${CFLAGS}
+COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+OBJC?= ${CC}
+OBJCFLAGS?= ${CFLAGS}
+COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
+LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP?= CC
+CPPFLAGS?=
+
+FC?= f77
+FFLAGS?= -O
+RFLAGS?=
+COMPILE.f?= ${FC} ${FFLAGS} -c
+LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+INSTALL?= ${PREFIX}/bin/install-sh
+
+LEX?= lex
+LFLAGS?=
+LEX.l?= ${LEX} ${LFLAGS}
+
+LD?= ld
+LDFLAGS?=
+
+LINT?= lint
+LINTFLAGS?= -chapbxzF
+
+LORDER?= lorder
+
+MAKE?= make
+
+NM?= nm
+
+PC?= pc
+PFLAGS?=
+COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL?= sh
+
+SIZE?= size
+
+TSORT?= tsort -q
+
+YACC?= yacc
+YFLAGS?=
+YACC.y?= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.c.ln:
+ ${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC}
+
+# C++
+.cc .cpp .cxx .C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o .cpp.o .cxx.o .C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a .cpp.a .cxx.a .C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/Linux.mk b/contrib/bmake/mk/sys/Linux.mk
new file mode 100644
index 0000000..862cde6
--- /dev/null
+++ b/contrib/bmake/mk/sys/Linux.mk
@@ -0,0 +1,200 @@
+# $Id: Linux.mk,v 1.7 2011/03/02 05:05:21 sjg Exp $
+# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $
+# @(#)sys.mk 5.11 (Berkeley) 3/13/91
+
+OS?= Linux
+unix?= We run ${OS}.
+
+ROOT_GROUP= root
+
+# would be better to work out where it is...
+LIBCRT0= /dev/null
+
+NEED_SOLINKS=yes
+
+.SUFFIXES: .out .a .ln .o .c .cc .C .F .f .r .y .l .s .S .cl .p .h .sh .m4
+
+.LIBS: .a
+
+AR= ar
+ARFLAGS= rl
+RANLIB= ranlib
+
+AS= as
+AFLAGS=
+COMPILE.s= ${AS} ${AFLAGS}
+LINK.s= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S= ${CC} ${AFLAGS} ${CPPFLAGS} -c
+LINK.S= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+.if exists(/usr/local/bin/gcc)
+CC= gcc -pipe
+DBG= -O -g
+STATIC?= -static
+.else
+CC= cc -pipe
+DBG= -g
+STATIC= -Bstatic
+.endif
+CFLAGS= ${DBG}
+COMPILE.c= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX= g++
+CXXFLAGS= ${CFLAGS}
+COMPILE.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP= cpp
+.if defined(DESTDIR)
+CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include
+.endif
+
+MK_DEP= mkdeps.sh -N
+FC= f77
+FFLAGS= -O
+RFLAGS=
+COMPILE.f= ${FC} ${FFLAGS} -c
+LINK.f= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+LEX= lex
+LFLAGS=
+LEX.l= ${LEX} ${LFLAGS}
+
+LD= ld
+LDFLAGS=
+
+LINT= lint
+LINTFLAGS= -chapbx
+
+MAKE= bmake
+
+PC= pc
+PFLAGS=
+COMPILE.p= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL= sh
+
+YACC= yacc
+YFLAGS= -d
+YACC.y= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# C++
+.cc:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} -o ${.TARGET} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/NetBSD.mk b/contrib/bmake/mk/sys/NetBSD.mk
new file mode 100644
index 0000000..4bc7da1
--- /dev/null
+++ b/contrib/bmake/mk/sys/NetBSD.mk
@@ -0,0 +1,234 @@
+# $NetBSD: sys.mk,v 1.66.2.1 2002/06/05 03:31:01 lukem Exp $
+# @(#)sys.mk 8.2 (Berkeley) 3/21/94
+
+OS= NetBSD
+unix?= We run ${OS}.
+
+.if !defined(MAKE_VERSION)
+# we are running native make
+# which defined MAKE_VERSION between 20010609 and 20090324
+# so we can make a rough guess
+.if defined(.MAKE.LEVEL)
+MAKE_VERSION = 20090908
+.elif defined(.MAKE.MAKEFILES)
+# introduced 20071008
+MAKE_VERSION = 20090324
+.else
+# this just before when MAKE_VERSION was introduced
+MAKE_VERSION = 20010606
+.endif
+.endif
+
+.SUFFIXES: .out .a .ln .o .s .S .c .cc .cpp .cxx .C .F .f .r .y .l .cl .p .h
+.SUFFIXES: .sh .m4
+
+.LIBS: .a
+
+AR?= ar
+ARFLAGS?= rl
+RANLIB?= ranlib
+
+AS?= as
+AFLAGS?=
+COMPILE.s?= ${CC} ${AFLAGS} -c
+LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp
+LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CC?= cc
+
+# need to make sure this is set
+MACHINE_ARCH.${MACHINE} ?= ${MACHINE}
+.if empty(MACHINE_ARCH)
+MACHINE_ARCH = ${MACHINE_ARCH.${MACHINE}}
+.endif
+
+#
+# CPU model, derived from MACHINE_ARCH
+#
+MACHINE_CPU= ${MACHINE_ARCH:C/mipse[bl]/mips/:C/mips64e[bl]/mips/:C/sh3e[bl]/sh3/:S/m68000/m68k/:S/armeb/arm/}
+
+.if ${MACHINE_CPU} == "alpha" || \
+ ${MACHINE_CPU} == "arm" || \
+ ${MACHINE_CPU} == "i386" || \
+ ${MACHINE_CPU} == "m68k" || \
+ ${MACHINE_CPU} == "mips" || \
+ ${MACHINE_CPU} == "powerpc" || \
+ ${MACHINE_CPU} == "sparc" || \
+ ${MACHINE_CPU} == "vax"
+DBG?= -O2
+.elif ${MACHINE_ARCH} == "x86_64"
+DBG?=
+.elif ${MACHINE_ARCH} == "sparc64"
+DBG?= -O -ffixed-g4 #Hack for embedany memory model compatibility
+.else
+DBG?= -O
+.endif
+CFLAGS?= ${DBG}
+COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX?= c++
+CXXFLAGS?= ${CFLAGS}
+COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+OBJC?= ${CC}
+OBJCFLAGS?= ${CFLAGS}
+COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
+LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP?= cpp
+CPPFLAGS?=
+
+FC?= f77
+FFLAGS?= -O
+RFLAGS?=
+COMPILE.f?= ${FC} ${FFLAGS} -c
+LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+INSTALL?= install
+
+LEX?= lex
+LFLAGS?=
+LEX.l?= ${LEX} ${LFLAGS}
+
+LD?= ld
+LDFLAGS?=
+
+LINT?= lint
+LINTFLAGS?= -chapbxzF
+
+LORDER?= lorder
+
+MAKE?= make
+
+NM?= nm
+
+PC?= pc
+PFLAGS?=
+COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL?= sh
+
+SIZE?= size
+
+TSORT?= tsort -q
+
+YACC?= yacc
+YFLAGS?=
+YACC.y?= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.c.ln:
+ ${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC}
+
+# C++
+.cc .cpp .cxx .C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o .cpp.o .cxx.o .C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a .cpp.a .cxx.a .C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/OSF1.mk b/contrib/bmake/mk/sys/OSF1.mk
new file mode 100644
index 0000000..a8d729a
--- /dev/null
+++ b/contrib/bmake/mk/sys/OSF1.mk
@@ -0,0 +1,211 @@
+# $Id: OSF1.mk,v 1.6 2003/09/30 16:42:23 sjg Exp $
+# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $
+# @(#)sys.mk 5.11 (Berkeley) 3/13/91
+
+OS?= OSF1
+unix?= We run ${OS}.
+ROOT_GROUP= system
+
+# can't fine one anywhere, so just stop the dependency
+LIBCRT0= /dev/null
+
+PATH=/usr/sbin:/usr/bin:/usr/ucb:/opt/gnu/bin:/usr/ccs/bin
+
+.SUFFIXES: .out .a .ln .o .c .cc .C .F .f .r .y .l .s .S .cl .p .h .sh .m4
+
+.LIBS: .a
+
+# no -X
+LD_X=
+LD_x= -x
+LD_r= -r
+AR= ar
+ARFLAGS= rl
+RANLIB= ranlib
+
+AS= as
+AS_STDIN= -
+AFLAGS=
+COMPILE.s= ${AS} ${AFLAGS}
+LINK.s= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S= ${CC} ${AFLAGS} ${CPPFLAGS} -c
+LINK.S= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+.if exists(/opt/gnu/bin/gcc) || exists(/usr/local/bin/gcc)
+CC?= gcc
+.else
+CC?= cc -std
+.endif
+.if (${CC:T} == "gcc")
+DBG= -O -g
+STATIC= -static
+DBG= -g
+STATIC= -non_shared
+.endif
+
+CFLAGS= ${DBG}
+COMPILE.c= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX= g++
+CXXFLAGS= ${CFLAGS}
+COMPILE.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP= /usr/ccs/lib/cpp
+.if defined(DESTDIR)
+CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include
+.endif
+
+MK_DEP= mkdeps.sh -N
+FC= f77
+FFLAGS= -O
+RFLAGS=
+COMPILE.f= ${FC} ${FFLAGS} -c
+LINK.f= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+LEX= lex
+LFLAGS=
+LEX.l= ${LEX} ${LFLAGS}
+
+LD= ld
+LDFLAGS=
+
+LINT= lint
+LINTFLAGS= -chapbx
+
+MAKE= bmake
+
+PC= pc
+PFLAGS=
+COMPILE.p= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL= sh
+
+.if exists(/usr/local/bin/bison) || exists(/opt/gnu/bin/bison)
+YACC= bison -y
+.else
+YACC= yacc
+.endif
+YFLAGS= -d
+YACC.y= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# C++
+.cc:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/OpenBSD.mk b/contrib/bmake/mk/sys/OpenBSD.mk
new file mode 100644
index 0000000..ed496f1
--- /dev/null
+++ b/contrib/bmake/mk/sys/OpenBSD.mk
@@ -0,0 +1,209 @@
+# $NetBSD: OpenBSD.sys.mk,v 1.1 2002/11/17 09:18:00 cjep Exp $
+# @(#)sys.mk 8.2 (Berkeley) 3/21/94
+
+OS= OpenBSD
+unix?= We run ${OS}.
+
+.SUFFIXES: .out .a .ln .o .s .S .c .cc .cpp .cxx .C .F .f .r .y .l .cl .p .h
+.SUFFIXES: .sh .m4
+
+.LIBS: .a
+
+# need to make sure this is set
+MACHINE_ARCH.${MACHINE} ?= ${MACHINE}
+.if empty(MACHINE_ARCH)
+MACHINE_ARCH = ${MACHINE_ARCH.${MACHINE}}
+.endif
+
+AR?= ar
+ARFLAGS?= rl
+RANLIB?= ranlib
+
+AS?= as
+AFLAGS?=
+.if ${MACHINE_ARCH} == "sparc64"
+AFLAGS+= -Wa,-Av9a
+.endif
+COMPILE.s?= ${CC} ${AFLAGS} -c
+LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp
+LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CC?= cc
+.if ${MACHINE_ARCH} == "alpha" || \
+ ${MACHINE_ARCH} == "i386" || \
+ ${MACHINE_ARCH} == "m68k" || \
+ ${MACHINE_ARCH} == "sparc" || \
+ ${MACHINE_ARCH} == "vax"
+DBG?= -O2
+.else
+DBG?= -O
+.endif
+CFLAGS?= ${DBG}
+COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX?= c++
+CXXFLAGS?= ${CFLAGS}
+COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+OBJC?= ${CC}
+OBJCFLAGS?= ${CFLAGS}
+COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
+LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP?= cpp
+CPPFLAGS?=
+
+FC?= f77
+FFLAGS?= -O
+RFLAGS?=
+COMPILE.f?= ${FC} ${FFLAGS} -c
+LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+INSTALL?= install
+
+LEX?= lex
+LFLAGS?=
+LEX.l?= ${LEX} ${LFLAGS}
+
+LD?= ld
+LDFLAGS?=
+
+LINT?= lint
+LINTFLAGS?= -chapbxzF
+
+LORDER?= lorder
+
+MAKE?= make
+
+NM?= nm
+
+PC?= pc
+PFLAGS?=
+COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL?= sh
+
+SIZE?= size
+
+TSORT?= tsort -q
+
+YACC?= yacc
+YFLAGS?=
+YACC.y?= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.c.ln:
+ ${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC}
+
+# C++
+.cc .cpp .cxx .C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o .cpp.o .cxx.o .C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a .cpp.a .cxx.a .C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/SunOS.mk b/contrib/bmake/mk/sys/SunOS.mk
new file mode 100644
index 0000000..f164aa2
--- /dev/null
+++ b/contrib/bmake/mk/sys/SunOS.mk
@@ -0,0 +1,232 @@
+# $Id: SunOS.mk,v 1.5 2010/01/11 23:02:05 sjg Exp $
+
+.if ${.PARSEFILE} == "sys.mk"
+.include <host-target.mk>
+
+OS?= SunOS.${HOST_OSMAJOR}
+unix?= We run ${OS}.
+.endif
+
+.if ${HOST_OSMAJOR} > 4
+ROOT_GROUP= root
+
+SHLIB_FULLVERSION = ${SHLIB_MAJOR}
+
+# supress the dependency
+LIBCRT0= /dev/null
+
+.ifndef CC
+# the PATH below may find an ancient gcc
+CC := ${gcc:L:${M_whence}}
+.export CC
+.endif
+
+# the stuff in /usr/xpg4/bin is usually more sane.
+PATH=/usr/xpg4/bin:/usr/sbin:/usr/bin:/usr/ucb:/usr/sfw/bin:/opt/gnu/bin:/usr/ccs/bin:/usr/local/bin
+.export PATH
+
+DSHLIBEXT = .so
+HOST_LIBDIRS = /usr/lib /lib /usr/sfw/lib
+
+# no -X
+LD_X=
+LD_x=
+RANLIB= :
+CPP= /usr/ccs/lib/cpp
+.else
+ROOT_GROUP= wheel
+RANLIB= ranlib
+CPP= cpp
+.endif
+
+# the rest is common
+
+.SUFFIXES: .out .a .ln .o .c .cc .C .F .f .r .y .l .s .S .cl .p .h .sh .m4
+
+.LIBS: .a
+
+AR= ar
+ARFLAGS= rl
+
+AS= as
+AS_STDIN= -
+AFLAGS=
+COMPILE.s= ${AS} ${AFLAGS}
+LINK.s= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S= ${CC} ${AFLAGS} ${CPPFLAGS} -c
+LINK.S= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+.if exists(/opt/gnu/bin/gcc) || exists(/usr/local/bin/gcc)
+CC ?= gcc -pipe
+DBG= -O -g
+STATIC= -static
+.else
+CC ?= cc
+DBG= -g
+STATIC= -Bstatic
+.endif
+CFLAGS= ${DBG}
+COMPILE.c= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CXX= g++
+CXXFLAGS= ${CFLAGS}
+COMPILE.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+.if defined(DESTDIR)
+CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include
+.endif
+
+MK_DEP= mkdeps.sh -N
+FC= f77
+FFLAGS= -O
+RFLAGS=
+COMPILE.f= ${FC} ${FFLAGS} -c
+LINK.f= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+LEX= lex
+LFLAGS=
+LEX.l= ${LEX} ${LFLAGS}
+
+LD= ld
+LDFLAGS=
+
+LINT= lint
+LINTFLAGS= -chapbx
+
+MAKE= bmake
+
+PC= pc
+PFLAGS=
+COMPILE.p= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL= sh
+
+.if exists(/usr/local/bin/bison) || exists(/opt/gnu/bin/bison)
+YACC= bison -y
+.else
+YACC= yacc
+.endif
+YFLAGS= -d
+YACC.y= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# C++
+.cc:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/sys/UnixWare.mk b/contrib/bmake/mk/sys/UnixWare.mk
new file mode 100644
index 0000000..f21895b
--- /dev/null
+++ b/contrib/bmake/mk/sys/UnixWare.mk
@@ -0,0 +1,254 @@
+# $Id: UnixWare.mk,v 1.1 2005/10/09 22:56:40 sjg Exp $
+# based on "Id: SunOS.5.sys.mk,v 1.6 2003/09/30 16:42:23 sjg Exp "
+# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $
+# @(#)sys.mk 5.11 (Berkeley) 3/13/91
+
+OS?= UnixWare
+unix?= We run ${OS}.
+ROOT_GROUP= root
+
+# can't fine one anywhere, so just stop the dependency
+LIBCRT0= /dev/null
+
+PATH=/usr/sbin:/usr/bin:/usr/ccs/bin:/usr/ccs/lib:/usr/ucb:/usr/local/bin
+
+.SUFFIXES: .out .a .ln .o .c .cc .C .F .f .r .y .l .s .S .cl .p .h .sh .m4
+
+.LIBS: .a
+
+# no -X
+LD_X=
+LD_x=
+AR?= ar
+ARFLAGS?= rl
+RANLIB?= :
+
+AS?= as
+AS_STDIN?= -
+AFLAGS?=
+COMPILE.s?= ${AS} ${AFLAGS}
+LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS}
+COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c
+LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+# at least gcc 2.95 on UnixWare has no internal macro to identify the system
+.if exists(/usr/local/bin/gcc)
+CC?= gcc -pipe -DUNIXWARE
+DBG?= -O -g
+STATIC?= -static
+.else
+CC?= cc
+DBG?= -g
+STATIC?= -Bstatic # XXX: don't know about UDK compilers
+.endif
+CFLAGS?= ${DBG}
+COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c
+LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+.if exists(/usr/local/bin/g++)
+CXX?= g++ -DUNIXWARE
+.else
+CXX?= c++ # XXX: don't know about UDK compilers
+.endif
+CXXFLAGS?= ${CFLAGS}
+COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c
+LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+CPP?= /usr/ccs/lib/cpp
+.if defined(DESTDIR)
+CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include
+.endif
+
+MK_DEP?= mkdeps.sh -N
+.if exists(/usr/local/bin/g77)
+FC?= g77
+.else
+FC?= f77 # XXX: don't know about UDK compilers
+.endif
+FFLAGS?= -O
+RFLAGS?=
+COMPILE.f?= ${FC} ${FFLAGS} -c
+LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS}
+COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c
+LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
+COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c
+LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
+
+INSTALL?= /usr/ucb/install # BSD install
+
+LEX?= lex
+LFLAGS?=
+LEX.l?= ${LEX} ${LFLAGS}
+
+LD?= ld
+LDFLAGS?=
+
+LIBC?= ${DESTDIR}/usr/ccs/lib/libc.a
+LIBCOMPAT?=
+LIBCRYPT?= ${DESTDIR}/usr/lib/libcrypt.a
+LIBCURSES?= ${DESTDIR}/usr/ccs/lib/libcurses.a
+LIBDBM?=
+LIBDES?=
+LIBEDIT?=
+LIBGCC?=
+LIBKDB?=
+LIBKRB?=
+LIBKVM?=
+LIBL?= ${DESTDIR}/usr/ccs/lib/libl.a
+LIBM?= ${DESTDIR}/usr/ccs/lib/libm.a
+LIBMP?=
+LIBPC?=
+LIBPCAP?=
+LIBPLOT?=
+LIBRESOLV?=
+LIBRPCSVC?= ${DESTDIR}/usr/lib/librpcsvc.a
+LIBSKEY?= ${DESTDIR}/usr/lib/libskey.a
+LIBTERMCAP?= ${DESTDIR}/usr/ccs/lib/libtermcap.a
+LIBUTIL?=
+LIBWRAP?=
+LIBY?= ${DESTDIR}/usr/ccs/lib/liby.a
+LIBZ?=
+
+LINT?= lint
+LINTFLAGS?= -pF
+
+LORDER?= lorder
+
+MAKE?= bmake
+
+NM?= nm
+
+PC?= pc # XXX: UDK probably does not have pc
+PFLAGS?=
+COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c
+LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
+
+SHELL?= sh
+
+SIZE?= size
+
+TSORT?= tsort
+
+.if exists(/usr/local/bin/bison)
+YACC?= bison -y
+.else
+YACC?= yacc
+.endif
+YFLAGS?= -d
+YACC.y?= ${YACC} ${YFLAGS}
+
+# C
+.c:
+ ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.c.o:
+ ${COMPILE.c} ${.IMPSRC}
+.c.a:
+ ${COMPILE.c} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# C++
+.cc:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.cc.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.cc.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.C:
+ ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.C.o:
+ ${COMPILE.cc} ${.IMPSRC}
+.C.a:
+ ${COMPILE.cc} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Fortran/Ratfor
+.f:
+ ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.f.o:
+ ${COMPILE.f} ${.IMPSRC}
+.f.a:
+ ${COMPILE.f} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.F:
+ ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.F.o:
+ ${COMPILE.F} ${.IMPSRC}
+.F.a:
+ ${COMPILE.F} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+.r:
+ ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.r.o:
+ ${COMPILE.r} ${.IMPSRC}
+.r.a:
+ ${COMPILE.r} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Pascal
+.p:
+ ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.p.o:
+ ${COMPILE.p} ${.IMPSRC}
+.p.a:
+ ${COMPILE.p} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Assembly
+.s:
+ ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.s.o:
+ ${COMPILE.s} ${.IMPSRC}
+.s.a:
+ ${COMPILE.s} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+.S:
+ ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS}
+.S.o:
+ ${COMPILE.S} ${.IMPSRC}
+.S.a:
+ ${COMPILE.S} ${.IMPSRC}
+ ${AR} ${ARFLAGS} $@ $*.o
+ rm -f $*.o
+
+# Lex
+.l:
+ ${LEX.l} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll
+ rm -f lex.yy.c
+.l.c:
+ ${LEX.l} ${.IMPSRC}
+ mv lex.yy.c ${.TARGET}
+.l.o:
+ ${LEX.l} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} lex.yy.c
+ rm -f lex.yy.c
+
+# Yacc
+.y:
+ ${YACC.y} ${.IMPSRC}
+ ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS}
+ rm -f y.tab.c
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ mv y.tab.c ${.TARGET}
+.y.o:
+ ${YACC.y} ${.IMPSRC}
+ ${COMPILE.c} -o ${.TARGET} y.tab.c
+ rm -f y.tab.c
+
+# Shell
+.sh:
+ rm -f ${.TARGET}
+ cp ${.IMPSRC} ${.TARGET}
diff --git a/contrib/bmake/mk/target-flags.mk b/contrib/bmake/mk/target-flags.mk
new file mode 100644
index 0000000..f8932b2
--- /dev/null
+++ b/contrib/bmake/mk/target-flags.mk
@@ -0,0 +1,62 @@
+# NAME:
+# target-flags.mk - target specific flags
+#
+# DESCRIPTION:
+# Include this macro file after all others in a makefile and
+# follow it with any target specfic flag settings.
+# For each such variable v in TARGET_FLAG_VARS we set:
+#.nf
+#
+# _$v := ${$v}
+# $v = ${${v}_${.TARGET:T}:U${_$v}}
+#.fi
+#
+# This allows one to do things like:
+#.nf
+#
+# TARGET_FLAG_VARS= CFLAGS
+# .include <target-flags.mk>
+# CFLAGS_fu.o = ${_CFLAGS:N-Wall}
+#.fi
+#
+# To turn off -Wall for just the target fu.o
+# Actually CFLAGS is the default value for TARGET_FLAG_VARS.
+#
+# BUGS:
+# One must be careful to avoid creating circular references in
+# variables. The original version of this macro file did
+# elaborate things with CFLAGS. The current, simpler
+# implementation is ultimately more flexible.
+#
+# It is important that target-flags.mk is included after other
+# macro files and that target specific flags that may reference
+# _$v are set after that.
+#
+# Only works with a make(1) that does nested evaluation correctly.
+
+
+
+# RCSid:
+# $Id: target-flags.mk,v 1.8 2002/05/08 06:01:00 sjg Exp $
+#
+# @(#) Copyright (c) 1998-2002, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+TARGET_FLAG_VARS?= CFLAGS
+.for v in ${TARGET_FLAG_VARS}
+.ifndef _$v
+_$v := ${$v}
+$v = ${${v}_${.TARGET:T}:U${_$v}}
+.endif
+.endfor
+
diff --git a/contrib/bmake/mk/warnings.mk b/contrib/bmake/mk/warnings.mk
new file mode 100644
index 0000000..9143e42
--- /dev/null
+++ b/contrib/bmake/mk/warnings.mk
@@ -0,0 +1,148 @@
+# RCSid:
+# $Id: warnings.mk,v 1.7 2009/12/11 17:06:03 sjg Exp $
+#
+# @(#) Copyright (c) 2002, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+.ifndef _w_cflags
+
+# Any number of warnings sets can be added.
+.-include "warnings-sets.mk"
+
+# Modest defaults - put more elaborate sets in warnings-sets.mk
+# -Wunused etc are here so you can set
+# W_unused=-Wno-unused etc.
+MIN_WARNINGS?= -Wall \
+ -Wformat \
+ -Wimplicit \
+ -Wunused \
+ -Wuninitialized
+
+LOW_WARNINGS?= ${MIN_WARNINGS} -W -Wstrict-prototypes -Wmissing-prototypes
+
+MEDIUM_WARNINGS?= ${LOW_WARNINGS} -Werror
+
+HIGH_WARNINGS?= ${MEDIUM_WARNINGS} \
+ -Wcast-align \
+ -Wcast-qual \
+ -Wparentheses \
+ -Wpointer-arith \
+ -Wmissing-declarations \
+ -Wreturn-type \
+ -Wswitch \
+ -Wwrite-strings
+
+# The two step default makes it easier to test build with different defaults.
+DEFAULT_WARNINGS_SET?= MIN
+WARNINGS_SET?= ${DEFAULT_WARNINGS_SET}
+
+# If you add sets, besure to list them (you don't have to touch this list).
+ALL_WARNINGS_SETS+= MIN LOW MEDIUM HIGH
+
+.if empty(${WARNINGS_SET}_WARNINGS)
+.if ${MAKE_VERSION:U0:[1]:C/.*-//} >= 20050530
+.BEGIN: _empty_warnings
+_empty_warnings: .PHONY
+.else
+.BEGIN:
+.endif
+ @echo "ERROR: Invalid: WARNINGS_SET=${WARNINGS_SET}"
+ @echo "ERROR: Try one of: ${ALL_WARNINGS_SETS:O:u}"; exit 1
+
+.endif
+
+# Without -O or if we've set -O0 somewhere - to make debugging more effective,
+# we need to turn off -Wuninitialized as otherwise we get a warning that
+# -Werror turns into an error. To be safe, set W_uninitialized blank.
+_w_cflags:= ${CFLAGS} ${CPPFLAGS}
+.if ${_w_cflags:M-O*} == "" || ${_w_cflags:M-O0} != ""
+W_uninitialized=
+.endif
+
+.if ${MAKE_VERSION:U0:[1]:C/.*-//} <= 20040118
+# This version uses .for loops to avoid a double free bug in old bmake's
+# but the .for loops are sensitive to when this file is read.
+
+# first, make a list of all the warning flags - doesn't matter if
+# its redundant - we'll sort -u
+_all_sets= ${WARNINGS_SET_${MACHINE_ARCH}} ${WARNINGS_SET} ${ALL_WARNINGS_SETS}
+_all_warnings= ${WARNINGS} ${_all_sets:O:u:@s@${$s_WARNINGS}@}
+
+# we want to set W_* for each warning so they are easy to turn off.
+# :O:u does a sort -u
+# using :C allows us to handle -f* -w* etc as well as -W*
+.for w in ${_all_warnings:O:u}
+${w:C/-(.)/\1_/} ?= $w
+.endfor
+
+# Allow for per-target warnings
+# Warning: the WARNINGS+= line below,
+# may make your brain hurt - trust me; it works --sjg
+# the idea is that you can set WARNINGS_SET[_${MACHINE_ARCH}]=HIGH
+# and use one of
+# W_format_mips_foo.o=
+# W_format_foo.o=
+# to turn off -Wformat for foo.o (on mips only in the first case), or
+# W_format_foo.o=-Wformat=2
+# for stricter checking.
+#
+# NOTE: that we force the target extension to be .o
+#
+.for w in ${WARNINGS_SET_${MACHINE_ARCH}:U${WARNINGS_SET}:@s@${$s_WARNINGS}@:O:u}
+WARNINGS+= ${${w:C/-(.)/\1_/}_${MACHINE_ARCH}_${.TARGET:T:R}.o:U${${w:C/-(.)/\1_/}_${.TARGET:T:R}.o:U${${w:C/-(.)/\1_/}_${MACHINE_ARCH}:U${${w:C/-(.)/\1_/}}}}}
+.endfor
+
+.else
+
+# .for loops have the [dis]advantage of being evaluated when read,
+# so adding to WARNINGS_SET[_${MACHINE_ARCH}] after this file is
+# read has no effect.
+# Replacing the above .for loops with the WARNINGS+= below solves that
+# but tiggers a double free bug in bmake-20040118 and earlier.
+# Don't try and read this too fast!
+#
+# The first :@ "loop" handles multiple sets in WARNINGS_SET
+#
+# In the second :@ "loop", the ::?= noise sets W_foo?=-Wfoo etc
+# which makes it easy to turn off override individual flags
+# (see W_uninitialized above).
+#
+# The last bit expands to ${W_foo_${.TARGET:T}:U${W_foo}}
+# which is the bit we ultimately want. It allows W_* to be set on a
+# per target basis.
+#
+# NOTE: that we force the target extension to be .o
+#
+WARNINGS+= ${WARNINGS_SET_${MACHINE_ARCH}:U${WARNINGS_SET}:@s@${$s_WARNINGS}@:O:u:@w@${${w:C/-(.)/\1_/}::?=$w} ${${w:C/-(.)/\1_/}_${MACHINE_ARCH}_${.TARGET:T:R}.o:U${${w:C/-(.)/\1_/}_${.TARGET:T:R}.o:U${${w:C/-(.)/\1_/}_${MACHINE_ARCH}:U${${w:C/-(.)/\1_/}}}}}@}
+
+.endif
+
+.ifndef NO_CFLAGS_WARNINGS
+# Just ${WARNINGS} should do, but this is more flexible?
+CFLAGS+= ${WARNINGS_${.TARGET:T:R}.o:U${WARNINGS}}
+.endif
+
+# it is rather silly that g++ blows up on some warning flags
+NO_CXX_WARNINGS+= \
+ missing-declarations \
+ missing-prototypes \
+ nested-externs \
+ strict-prototypes
+
+.for s in ${SRCS:M*.cc}
+.for w in ${NO_CXX_WARNINGS}
+W_$w_${s:T:R}.o=
+.endfor
+.endfor
+
+.endif # _w_cflags
diff --git a/contrib/bmake/mk/yacc.mk b/contrib/bmake/mk/yacc.mk
new file mode 100644
index 0000000..910b004
--- /dev/null
+++ b/contrib/bmake/mk/yacc.mk
@@ -0,0 +1,57 @@
+# $Id: yacc.mk,v 1.6 2011/06/10 22:45:46 sjg Exp $
+
+#
+# @(#) Copyright (c) 1999-2011, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# this file contains rules to DTRT when SRCS contains foo.y or foo.c
+# when only a foo.y exists.
+
+YACC?= yacc
+YFLAGS?= -v -t
+RM?= rm
+
+YACC.y?= ${YACC} ${YFLAGS}
+
+.if ${YACC.y:M-d} == "" || defined(NO_RENAME_Y_TAB_H)
+
+.y.c:
+ ${YACC.y} ${.IMPSRC}
+ [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET}
+ ${RM} -f y.tab.[!h]
+
+.else
+
+# the touch of the .c is to ensure it is newer than .h (paranoia)
+.y.h:
+ ${YACC.y} ${.IMPSRC}
+ [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET:T:R}.c
+ [ ! -s y.tab.h ] || cmp -s y.tab.h ${.TARGET:T:R}.h \
+ || mv y.tab.h ${.TARGET:T:R}.h
+ touch ${.TARGET:T:R}.c
+ ${RM} -f y.tab.*
+
+# Normally the .y.h rule does the work - to avoid races.
+# If for any reason the .c is lost but the .h remains,
+# regenerate the .c
+.y.c: ${.TARGET:T:R}.h
+ [ -s ${.TARGET} ] || { \
+ ${YACC.y} ${.IMPSRC} && \
+ { [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET}; \
+ ${RM} y.tab.*; }; }
+.endif
+
+beforedepend: ${SRCS:T:M*.y:S/.y/.c/g}
+
+CLEANFILES+= ${SRCS:T:M*.y:S/.y/.[ch]/g}
+CLEANFILES+= y.tab.[ch]
diff --git a/contrib/bmake/realpath.c b/contrib/bmake/realpath.c
index 1ef2cd8..fbf0335 100644
--- a/contrib/bmake/realpath.c
+++ b/contrib/bmake/realpath.c
@@ -1,5 +1,5 @@
-/* $Id: realpath.c,v 1.2 2010/04/21 17:47:49 sjg Exp $ */
-/* from: $NetBSD: getcwd.c,v 1.45 2007/10/26 19:48:14 christos Exp $ */
+/* $Id: realpath.c,v 1.3 2013/01/25 17:06:09 sjg Exp $ */
+/* from: $NetBSD: getcwd.c,v 1.53 2012/06/21 23:29:23 enami Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1995
@@ -52,24 +52,40 @@
# include <unistd.h>
#endif
+#ifndef __restrict
+# define __restrict /* restrict */
+#endif
+
/*
- * char *realpath(const char *path, char resolved[MAXPATHLEN]);
+ * char *realpath(const char *path, char *resolved);
*
* Find the real name of path, by removing all ".", ".." and symlink
* components. Returns (resolved) on success, or (NULL) on failure,
* in which case the path which caused trouble is left in (resolved).
*/
char *
-realpath(const char *path, char *resolved)
+realpath(const char * __restrict path, char * __restrict resolved)
{
struct stat sb;
- int idx = 0, n, nlnk = 0;
+ int idx = 0, nlnk = 0;
const char *q;
- char *p, wbuf[2][MAXPATHLEN];
+ char *p, wbuf[2][MAXPATHLEN], *fres;
size_t len;
+ ssize_t n;
+
+ /* POSIX sez we must test for this */
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (resolved == NULL) {
+ fres = resolved = malloc(MAXPATHLEN);
+ if (resolved == NULL)
+ return NULL;
+ } else
+ fres = NULL;
- if (!path || !resolved || path == resolved)
- return (NULL);
/*
* Build real path one by one with paying an attention to .,
@@ -82,10 +98,10 @@ realpath(const char *path, char *resolved)
*/
p = resolved;
- if (*path == 0) {
- *p = 0;
+ if (*path == '\0') {
+ *p = '\0';
errno = ENOENT;
- return (NULL);
+ goto out;
}
/* If relative path, start from current working directory. */
@@ -93,8 +109,8 @@ realpath(const char *path, char *resolved)
/* check for resolved pointer to appease coverity */
if (resolved && getcwd(resolved, MAXPATHLEN) == NULL) {
p[0] = '.';
- p[1] = 0;
- return (NULL);
+ p[1] = '\0';
+ goto out;
}
len = strlen(resolved);
if (len > 1)
@@ -106,18 +122,18 @@ loop:
while (*path == '/')
path++;
- if (*path == 0) {
+ if (*path == '\0') {
if (p == resolved)
*p++ = '/';
- *p = 0;
- return (resolved);
+ *p = '\0';
+ return resolved;
}
/* Find the end of this component. */
q = path;
do
q++;
- while (*q != '/' && *q != 0);
+ while (*q != '/' && *q != '\0');
/* Test . or .. */
if (path[0] == '.') {
@@ -129,7 +145,7 @@ loop:
/* Trim the last component. */
if (p != resolved)
while (*--p != '/')
- ;
+ continue;
path = q;
goto loop;
}
@@ -140,39 +156,39 @@ loop:
errno = ENAMETOOLONG;
if (p == resolved)
*p++ = '/';
- *p = 0;
- return (NULL);
+ *p = '\0';
+ goto out;
}
p[0] = '/';
memcpy(&p[1], path,
/* LINTED We know q > path. */
q - path);
- p[1 + q - path] = 0;
+ p[1 + q - path] = '\0';
/*
* If this component is a symlink, toss it and prepend link
* target to unresolved path.
*/
- if (lstat(resolved, &sb) == -1) {
- return (NULL);
- }
+ if (lstat(resolved, &sb) == -1)
+ goto out;
+
if (S_ISLNK(sb.st_mode)) {
if (nlnk++ >= MAXSYMLINKS) {
errno = ELOOP;
- return (NULL);
+ goto out;
}
n = readlink(resolved, wbuf[idx], sizeof(wbuf[0]) - 1);
if (n < 0)
- return (NULL);
+ goto out;
if (n == 0) {
errno = ENOENT;
- return (NULL);
+ goto out;
}
/* Append unresolved path to link target and switch to it. */
if (n + (len = strlen(q)) + 1 > sizeof(wbuf[0])) {
errno = ENAMETOOLONG;
- return (NULL);
+ goto out;
}
memcpy(&wbuf[idx][n], q, len + 1);
path = wbuf[idx];
@@ -185,12 +201,15 @@ loop:
}
if (*q == '/' && !S_ISDIR(sb.st_mode)) {
errno = ENOTDIR;
- return (NULL);
+ goto out;
}
/* Advance both resolved and unresolved path. */
p += 1 + q - path;
path = q;
goto loop;
+out:
+ free(fres);
+ return NULL;
}
#endif
diff --git a/contrib/bmake/unit-tests/Makefile.in b/contrib/bmake/unit-tests/Makefile.in
index e5bf9b2..a64a074 100644
--- a/contrib/bmake/unit-tests/Makefile.in
+++ b/contrib/bmake/unit-tests/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.39 2012/11/09 19:16:10 sjg Exp $
+# $Id: Makefile.in,v 1.40 2012/12/28 21:28:19 sjg Exp $
#
# $NetBSD: Makefile,v 1.35 2012/11/09 19:08:28 sjg Exp $
#
@@ -64,7 +64,7 @@ ${SUBFILES}:
clean:
rm -f *.out *.fail *.core
-.-include <bsd.obj.mk>
+.-include <obj.mk>
TEST_MAKE?= ${.MAKE}
TOOL_SED?= sed
diff --git a/contrib/bmake/var.c b/contrib/bmake/var.c
index e958a36..2e73d5b 100644
--- a/contrib/bmake/var.c
+++ b/contrib/bmake/var.c
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.171 2012/06/12 19:21:51 joerg Exp $ */
+/* $NetBSD: var.c,v 1.172 2012/11/15 16:42:26 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.171 2012/06/12 19:21:51 joerg Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.172 2012/11/15 16:42:26 christos Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: var.c,v 1.171 2012/06/12 19:21:51 joerg Exp $");
+__RCSID("$NetBSD: var.c,v 1.172 2012/11/15 16:42:26 christos Exp $");
#endif
#endif /* not lint */
#endif
@@ -2567,7 +2567,8 @@ ApplyModifiers(char *nstr, const char *tstr,
}
apply_mods:
if (DEBUG(VAR)) {
- fprintf(debug_file, "Applying :%c to \"%s\"\n", *tstr, nstr);
+ fprintf(debug_file, "Applying[%s] :%c to \"%s\"\n", v->name,
+ *tstr, nstr);
}
newStr = var_Error;
switch ((modifier = *tstr)) {
@@ -3167,8 +3168,8 @@ ApplyModifiers(char *nstr, const char *tstr,
free(cp2);
}
if (DEBUG(VAR))
- fprintf(debug_file, "Pattern for [%s] is [%s]\n", nstr,
- pattern);
+ fprintf(debug_file, "Pattern[%s] for [%s] is [%s]\n",
+ v->name, nstr, pattern);
if (*tstr == 'M') {
newStr = VarModify(ctxt, &parsestate, nstr, VarMatch,
pattern);
@@ -3523,7 +3524,8 @@ ApplyModifiers(char *nstr, const char *tstr,
}
}
if (DEBUG(VAR)) {
- fprintf(debug_file, "Result of :%c is \"%s\"\n", modifier, newStr);
+ fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n",
+ v->name, modifier, newStr);
}
if (newStr != nstr) {
diff --git a/contrib/bsnmp/lib/tc.def b/contrib/bsnmp/lib/tc.def
index 65f6972..65f6972 100755..100644
--- a/contrib/bsnmp/lib/tc.def
+++ b/contrib/bsnmp/lib/tc.def
diff --git a/contrib/bsnmp/snmp_target/snmp_target.3 b/contrib/bsnmp/snmp_target/snmp_target.3
index 626bb78..626bb78 100755..100644
--- a/contrib/bsnmp/snmp_target/snmp_target.3
+++ b/contrib/bsnmp/snmp_target/snmp_target.3
diff --git a/contrib/bsnmp/snmp_target/target_snmp.c b/contrib/bsnmp/snmp_target/target_snmp.c
index c6f05de..c6f05de 100755..100644
--- a/contrib/bsnmp/snmp_target/target_snmp.c
+++ b/contrib/bsnmp/snmp_target/target_snmp.c
diff --git a/contrib/bsnmp/snmp_target/target_tree.def b/contrib/bsnmp/snmp_target/target_tree.def
index 990bfac..990bfac 100755..100644
--- a/contrib/bsnmp/snmp_target/target_tree.def
+++ b/contrib/bsnmp/snmp_target/target_tree.def
diff --git a/contrib/bsnmp/snmp_usm/snmp_usm.3 b/contrib/bsnmp/snmp_usm/snmp_usm.3
index ceb62e4..ceb62e4 100755..100644
--- a/contrib/bsnmp/snmp_usm/snmp_usm.3
+++ b/contrib/bsnmp/snmp_usm/snmp_usm.3
diff --git a/contrib/bsnmp/snmp_usm/usm_snmp.c b/contrib/bsnmp/snmp_usm/usm_snmp.c
index d5350bc..d5350bc 100755..100644
--- a/contrib/bsnmp/snmp_usm/usm_snmp.c
+++ b/contrib/bsnmp/snmp_usm/usm_snmp.c
diff --git a/contrib/bsnmp/snmp_usm/usm_tree.def b/contrib/bsnmp/snmp_usm/usm_tree.def
index 72c446e..72c446e 100755..100644
--- a/contrib/bsnmp/snmp_usm/usm_tree.def
+++ b/contrib/bsnmp/snmp_usm/usm_tree.def
diff --git a/contrib/bsnmp/snmp_vacm/snmp_vacm.3 b/contrib/bsnmp/snmp_vacm/snmp_vacm.3
index dd57f7f..dd57f7f 100755..100644
--- a/contrib/bsnmp/snmp_vacm/snmp_vacm.3
+++ b/contrib/bsnmp/snmp_vacm/snmp_vacm.3
diff --git a/contrib/bsnmp/snmp_vacm/vacm_snmp.c b/contrib/bsnmp/snmp_vacm/vacm_snmp.c
index cdec9f4..cdec9f4 100755..100644
--- a/contrib/bsnmp/snmp_vacm/vacm_snmp.c
+++ b/contrib/bsnmp/snmp_vacm/vacm_snmp.c
diff --git a/contrib/bsnmp/snmp_vacm/vacm_tree.def b/contrib/bsnmp/snmp_vacm/vacm_tree.def
index 45b3c33..45b3c33 100755..100644
--- a/contrib/bsnmp/snmp_vacm/vacm_tree.def
+++ b/contrib/bsnmp/snmp_vacm/vacm_tree.def
diff --git a/contrib/compiler-rt/LICENSE.TXT b/contrib/compiler-rt/LICENSE.TXT
index f717942..6aab1f6 100644
--- a/contrib/compiler-rt/LICENSE.TXT
+++ b/contrib/compiler-rt/LICENSE.TXT
@@ -14,7 +14,7 @@ Full text of the relevant licenses is included below.
University of Illinois/NCSA
Open Source License
-Copyright (c) 2009-2012 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
All rights reserved.
@@ -55,7 +55,7 @@ SOFTWARE.
==============================================================================
-Copyright (c) 2009-2012 by the contributors listed in CREDITS.TXT
+Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/contrib/compiler-rt/lib/arm/aeabi_uldivmod.S b/contrib/compiler-rt/lib/arm/aeabi_uldivmod.S
index 724049d..e061a6e 100644
--- a/contrib/compiler-rt/lib/arm/aeabi_uldivmod.S
+++ b/contrib/compiler-rt/lib/arm/aeabi_uldivmod.S
@@ -27,4 +27,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod)
ldr r2, [sp, #8]
ldr r3, [sp, #12]
add sp, sp, #16
- pop {r11, pc} \ No newline at end of file
+ pop {r11, pc}
+
diff --git a/contrib/compiler-rt/lib/arm/divsi3.S b/contrib/compiler-rt/lib/arm/divsi3.S
index 00e6181..e76fe31 100644
--- a/contrib/compiler-rt/lib/arm/divsi3.S
+++ b/contrib/compiler-rt/lib/arm/divsi3.S
@@ -25,7 +25,16 @@
// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3)
DEFINE_COMPILERRT_FUNCTION(__divsi3)
- ESTABLISH_FRAME
+#if __ARM_ARCH_7S__
+ tst r1,r1
+ beq LOCAL_LABEL(divzero)
+ sdiv r0, r0, r1
+ bx lr
+LOCAL_LABEL(divzero):
+ mov r0,#0
+ bx lr
+#else
+ESTABLISH_FRAME
// Set aside the sign of the quotient.
eor r4, r0, r1
// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
@@ -39,3 +48,4 @@ DEFINE_COMPILERRT_FUNCTION(__divsi3)
eor r0, r0, r4, asr #31
sub r0, r0, r4, asr #31
CLEAR_FRAME_AND_RETURN
+#endif
diff --git a/contrib/compiler-rt/lib/arm/udivsi3.S b/contrib/compiler-rt/lib/arm/udivsi3.S
index 6d89665..28979fe 100644
--- a/contrib/compiler-rt/lib/arm/udivsi3.S
+++ b/contrib/compiler-rt/lib/arm/udivsi3.S
@@ -33,6 +33,15 @@
// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_uidiv, __udivsi3)
DEFINE_COMPILERRT_FUNCTION(__udivsi3)
+#if __ARM_ARCH_7S__
+ tst r1,r1
+ beq LOCAL_LABEL(divzero)
+ udiv r0, r0, r1
+ bx lr
+ LOCAL_LABEL(divzero):
+ mov r0,#0
+ bx lr
+#else
// We use a simple digit by digit algorithm; before we get into the actual
// divide loop, we must calculate the left-shift amount necessary to align
// the MSB of the divisor with that of the dividend (If this shift is
@@ -78,3 +87,4 @@ LOCAL_LABEL(return):
// Move the quotient to r0 and return.
mov r0, q
CLEAR_FRAME_AND_RETURN
+#endif
diff --git a/contrib/compiler-rt/lib/cmpdi2.c b/contrib/compiler-rt/lib/cmpdi2.c
index c2b1f69..52634d9 100644
--- a/contrib/compiler-rt/lib/cmpdi2.c
+++ b/contrib/compiler-rt/lib/cmpdi2.c
@@ -36,3 +36,16 @@ __cmpdi2(di_int a, di_int b)
return 2;
return 1;
}
+
+#ifdef __ARM_EABI__
+/* Returns: if (a < b) returns -1
+* if (a == b) returns 0
+* if (a > b) returns 1
+*/
+COMPILER_RT_ABI si_int
+__aeabi_lcmp(di_int a, di_int b)
+{
+ return __cmpdi2(a, b) - 1;
+}
+#endif
+
diff --git a/contrib/compiler-rt/lib/fixsfdi.c b/contrib/compiler-rt/lib/fixsfdi.c
index 8a06690..4f6cfdd 100644
--- a/contrib/compiler-rt/lib/fixsfdi.c
+++ b/contrib/compiler-rt/lib/fixsfdi.c
@@ -23,7 +23,7 @@
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
-ARM_EABI_FNALIAS(d2lz, fixsfdi)
+ARM_EABI_FNALIAS(f2lz, fixsfdi)
COMPILER_RT_ABI di_int
__fixsfdi(float a)
diff --git a/contrib/compiler-rt/lib/int_endianness.h b/contrib/compiler-rt/lib/int_endianness.h
index 70bd1773..edb58c8 100644
--- a/contrib/compiler-rt/lib/int_endianness.h
+++ b/contrib/compiler-rt/lib/int_endianness.h
@@ -31,7 +31,7 @@
/* .. */
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__minix)
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__minix)
#include <sys/endian.h>
#if _BYTE_ORDER == _BIG_ENDIAN
@@ -44,6 +44,19 @@
#endif /* *BSD */
+#if defined(__OpenBSD__) || defined(__Bitrig__)
+#include <machine/endian.h>
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* _BYTE_ORDER */
+
+#endif /* OpenBSD and Bitrig. */
+
/* .. */
/* Mac OSX has __BIG_ENDIAN__ or __LITTLE_ENDIAN__ automatically set by the compiler (at least with GCC) */
diff --git a/contrib/compiler-rt/lib/int_lib.h b/contrib/compiler-rt/lib/int_lib.h
index 2328a1d..594e812 100644
--- a/contrib/compiler-rt/lib/int_lib.h
+++ b/contrib/compiler-rt/lib/int_lib.h
@@ -25,7 +25,15 @@
#if __ARM_EABI__
# define ARM_EABI_FNALIAS(aeabi_name, name) \
void __aeabi_##aeabi_name() __attribute__((alias("__" #name)));
-# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
+
+# if !defined(__clang__) && defined(__GNUC__) && \
+ (__GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ < 5)
+/* The pcs attribute was introduced in GCC 4.5.0 */
+# define COMPILER_RT_ABI
+# else
+# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
+# endif
+
#else
# define ARM_EABI_FNALIAS(aeabi_name, name)
# define COMPILER_RT_ABI
diff --git a/contrib/compiler-rt/lib/ucmpdi2.c b/contrib/compiler-rt/lib/ucmpdi2.c
index 3242bbf..40af236 100644
--- a/contrib/compiler-rt/lib/ucmpdi2.c
+++ b/contrib/compiler-rt/lib/ucmpdi2.c
@@ -36,3 +36,16 @@ __ucmpdi2(du_int a, du_int b)
return 2;
return 1;
}
+
+#ifdef __ARM_EABI__
+/* Returns: if (a < b) returns -1
+* if (a == b) returns 0
+* if (a > b) returns 1
+*/
+COMPILER_RT_ABI si_int
+__aeabi_ulcmp(di_int a, di_int b)
+{
+ return __ucmpdi2(a, b) - 1;
+}
+#endif
+
diff --git a/contrib/dialog/samples/copifuncs/common.funcs b/contrib/dialog/samples/copifuncs/common.funcs
index 04eca9a..04eca9a 100755..100644
--- a/contrib/dialog/samples/copifuncs/common.funcs
+++ b/contrib/dialog/samples/copifuncs/common.funcs
diff --git a/contrib/dialog/samples/copifuncs/copi.ifman1 b/contrib/dialog/samples/copifuncs/copi.ifman1
index 3e271a5..3e271a5 100755..100644
--- a/contrib/dialog/samples/copifuncs/copi.ifman1
+++ b/contrib/dialog/samples/copifuncs/copi.ifman1
diff --git a/contrib/dialog/samples/copifuncs/copi.ifman2 b/contrib/dialog/samples/copifuncs/copi.ifman2
index 0b6dbb7..0b6dbb7 100755..100644
--- a/contrib/dialog/samples/copifuncs/copi.ifman2
+++ b/contrib/dialog/samples/copifuncs/copi.ifman2
diff --git a/contrib/dialog/samples/copifuncs/copi.ifmcfg2 b/contrib/dialog/samples/copifuncs/copi.ifmcfg2
index c8a8c03..c8a8c03 100755..100644
--- a/contrib/dialog/samples/copifuncs/copi.ifmcfg2
+++ b/contrib/dialog/samples/copifuncs/copi.ifmcfg2
diff --git a/contrib/dialog/samples/copifuncs/copi.ifmcfg4 b/contrib/dialog/samples/copifuncs/copi.ifmcfg4
index 4cb7a75..4cb7a75 100755..100644
--- a/contrib/dialog/samples/copifuncs/copi.ifmcfg4
+++ b/contrib/dialog/samples/copifuncs/copi.ifmcfg4
diff --git a/contrib/dialog/samples/copifuncs/copi.ifmcfg5 b/contrib/dialog/samples/copifuncs/copi.ifmcfg5
index 8221c1c..8221c1c 100755..100644
--- a/contrib/dialog/samples/copifuncs/copi.ifmcfg5
+++ b/contrib/dialog/samples/copifuncs/copi.ifmcfg5
diff --git a/contrib/dialog/samples/copifuncs/copi.ifpoll2 b/contrib/dialog/samples/copifuncs/copi.ifpoll2
index 216bff0..216bff0 100755..100644
--- a/contrib/dialog/samples/copifuncs/copi.ifpoll2
+++ b/contrib/dialog/samples/copifuncs/copi.ifpoll2
diff --git a/contrib/dialog/samples/copifuncs/copi.ifreq2 b/contrib/dialog/samples/copifuncs/copi.ifreq2
index 9ee78ff..9ee78ff 100755..100644
--- a/contrib/dialog/samples/copifuncs/copi.ifreq2
+++ b/contrib/dialog/samples/copifuncs/copi.ifreq2
diff --git a/contrib/dialog/samples/copifuncs/copi.sendifm2 b/contrib/dialog/samples/copifuncs/copi.sendifm2
index 1a34a1f..1a34a1f 100755..100644
--- a/contrib/dialog/samples/copifuncs/copi.sendifm2
+++ b/contrib/dialog/samples/copifuncs/copi.sendifm2
diff --git a/contrib/ee/Makefile b/contrib/ee/Makefile
index a6525ea..a6525ea 100755..100644
--- a/contrib/ee/Makefile
+++ b/contrib/ee/Makefile
diff --git a/contrib/ee/ee.c b/contrib/ee/ee.c
index 70a4407..70a4407 100755..100644
--- a/contrib/ee/ee.c
+++ b/contrib/ee/ee.c
diff --git a/contrib/expat/doc/expat.png b/contrib/expat/doc/expat.png
index 5bc0726..5bc0726 100755..100644
--- a/contrib/expat/doc/expat.png
+++ b/contrib/expat/doc/expat.png
Binary files differ
diff --git a/contrib/expat/doc/valid-xhtml10.png b/contrib/expat/doc/valid-xhtml10.png
index 4c23f48..4c23f48 100755..100644
--- a/contrib/expat/doc/valid-xhtml10.png
+++ b/contrib/expat/doc/valid-xhtml10.png
Binary files differ
diff --git a/contrib/expat/lib/expat_external.h b/contrib/expat/lib/expat_external.h
index 2c03284..2c03284 100755..100644
--- a/contrib/expat/lib/expat_external.h
+++ b/contrib/expat/lib/expat_external.h
diff --git a/contrib/expat/tests/benchmark/README.txt b/contrib/expat/tests/benchmark/README.txt
index 7f9cca0..7f9cca0 100755..100644
--- a/contrib/expat/tests/benchmark/README.txt
+++ b/contrib/expat/tests/benchmark/README.txt
diff --git a/contrib/expat/tests/benchmark/benchmark.c b/contrib/expat/tests/benchmark/benchmark.c
index 0f0fd18c..0f0fd18c 100755..100644
--- a/contrib/expat/tests/benchmark/benchmark.c
+++ b/contrib/expat/tests/benchmark/benchmark.c
diff --git a/contrib/expat/tests/benchmark/benchmark.dsp b/contrib/expat/tests/benchmark/benchmark.dsp
index 6f310d0a..6f310d0a 100755..100644
--- a/contrib/expat/tests/benchmark/benchmark.dsp
+++ b/contrib/expat/tests/benchmark/benchmark.dsp
diff --git a/contrib/expat/tests/benchmark/benchmark.dsw b/contrib/expat/tests/benchmark/benchmark.dsw
index 3346a9a..3346a9a 100755..100644
--- a/contrib/expat/tests/benchmark/benchmark.dsw
+++ b/contrib/expat/tests/benchmark/benchmark.dsw
diff --git a/contrib/expat/tests/minicheck.c b/contrib/expat/tests/minicheck.c
index d2f4295..d2f4295 100755..100644
--- a/contrib/expat/tests/minicheck.c
+++ b/contrib/expat/tests/minicheck.c
diff --git a/contrib/expat/tests/minicheck.h b/contrib/expat/tests/minicheck.h
index f846bea..f846bea 100755..100644
--- a/contrib/expat/tests/minicheck.h
+++ b/contrib/expat/tests/minicheck.h
diff --git a/contrib/expat/tests/runtestspp.cpp b/contrib/expat/tests/runtestspp.cpp
index c35dc58..c35dc58 100755..100644
--- a/contrib/expat/tests/runtestspp.cpp
+++ b/contrib/expat/tests/runtestspp.cpp
diff --git a/contrib/expat/xmlwf/codepage.c b/contrib/expat/xmlwf/codepage.c
index 57e48ff..57e48ff 100755..100644
--- a/contrib/expat/xmlwf/codepage.c
+++ b/contrib/expat/xmlwf/codepage.c
diff --git a/contrib/expat/xmlwf/codepage.h b/contrib/expat/xmlwf/codepage.h
index 6a4df68..6a4df68 100755..100644
--- a/contrib/expat/xmlwf/codepage.h
+++ b/contrib/expat/xmlwf/codepage.h
diff --git a/contrib/expat/xmlwf/ct.c b/contrib/expat/xmlwf/ct.c
index 95903a3..95903a3 100755..100644
--- a/contrib/expat/xmlwf/ct.c
+++ b/contrib/expat/xmlwf/ct.c
diff --git a/contrib/expat/xmlwf/filemap.h b/contrib/expat/xmlwf/filemap.h
index 814edec..814edec 100755..100644
--- a/contrib/expat/xmlwf/filemap.h
+++ b/contrib/expat/xmlwf/filemap.h
diff --git a/contrib/expat/xmlwf/readfilemap.c b/contrib/expat/xmlwf/readfilemap.c
index 088dda5..088dda5 100755..100644
--- a/contrib/expat/xmlwf/readfilemap.c
+++ b/contrib/expat/xmlwf/readfilemap.c
diff --git a/contrib/expat/xmlwf/unixfilemap.c b/contrib/expat/xmlwf/unixfilemap.c
index 93adce3..93adce3 100755..100644
--- a/contrib/expat/xmlwf/unixfilemap.c
+++ b/contrib/expat/xmlwf/unixfilemap.c
diff --git a/contrib/expat/xmlwf/win32filemap.c b/contrib/expat/xmlwf/win32filemap.c
index 41dc35b..41dc35b 100755..100644
--- a/contrib/expat/xmlwf/win32filemap.c
+++ b/contrib/expat/xmlwf/win32filemap.c
diff --git a/contrib/expat/xmlwf/xmlfile.c b/contrib/expat/xmlwf/xmlfile.c
index 99eeeaa..99eeeaa 100755..100644
--- a/contrib/expat/xmlwf/xmlfile.c
+++ b/contrib/expat/xmlwf/xmlfile.c
diff --git a/contrib/expat/xmlwf/xmlfile.h b/contrib/expat/xmlwf/xmlfile.h
index d093ecc..d093ecc 100755..100644
--- a/contrib/expat/xmlwf/xmlfile.h
+++ b/contrib/expat/xmlwf/xmlfile.h
diff --git a/contrib/expat/xmlwf/xmlmime.c b/contrib/expat/xmlwf/xmlmime.c
index 56a0e7f..56a0e7f 100755..100644
--- a/contrib/expat/xmlwf/xmlmime.c
+++ b/contrib/expat/xmlwf/xmlmime.c
diff --git a/contrib/expat/xmlwf/xmlmime.h b/contrib/expat/xmlwf/xmlmime.h
index bf0356d..bf0356d 100755..100644
--- a/contrib/expat/xmlwf/xmlmime.h
+++ b/contrib/expat/xmlwf/xmlmime.h
diff --git a/contrib/expat/xmlwf/xmltchar.h b/contrib/expat/xmlwf/xmltchar.h
index 1088575..1088575 100755..100644
--- a/contrib/expat/xmlwf/xmltchar.h
+++ b/contrib/expat/xmlwf/xmltchar.h
diff --git a/contrib/expat/xmlwf/xmlurl.h b/contrib/expat/xmlwf/xmlurl.h
index d329913..d329913 100755..100644
--- a/contrib/expat/xmlwf/xmlurl.h
+++ b/contrib/expat/xmlwf/xmlurl.h
diff --git a/contrib/expat/xmlwf/xmlwf.c b/contrib/expat/xmlwf/xmlwf.c
index 41a433d..41a433d 100755..100644
--- a/contrib/expat/xmlwf/xmlwf.c
+++ b/contrib/expat/xmlwf/xmlwf.c
diff --git a/contrib/expat/xmlwf/xmlwin32url.cxx b/contrib/expat/xmlwf/xmlwin32url.cxx
index bbfcce2..bbfcce2 100755..100644
--- a/contrib/expat/xmlwf/xmlwin32url.cxx
+++ b/contrib/expat/xmlwf/xmlwin32url.cxx
diff --git a/contrib/file/Magdir/lua b/contrib/file/Magdir/lua
index 61e69a6..fbb9f09 100644
--- a/contrib/file/Magdir/lua
+++ b/contrib/file/Magdir/lua
@@ -19,3 +19,4 @@
0 string \033Lua Lua bytecode,
>4 byte 0x50 version 5.0
>4 byte 0x51 version 5.1
+>4 byte 0x52 version 5.2
diff --git a/contrib/gcc/config/arm/freebsd.h b/contrib/gcc/config/arm/freebsd.h
index da7ffab..04be692 100644
--- a/contrib/gcc/config/arm/freebsd.h
+++ b/contrib/gcc/config/arm/freebsd.h
@@ -29,8 +29,13 @@
{ "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER }
#undef SUBTARGET_EXTRA_ASM_SPEC
+#ifdef TARGET_ARM_EABI
+#define SUBTARGET_EXTRA_ASM_SPEC \
+ "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=4} %{fpic|fpie:-k} %{fPIC|fPIE:-k}"
+#else
#define SUBTARGET_EXTRA_ASM_SPEC \
"-matpcs %{fpic|fpie:-k} %{fPIC|fPIE:-k}"
+#endif
/* Default to full FPA if -mhard-float is specified. */
#undef SUBTARGET_ASM_FLOAT_SPEC
@@ -61,8 +66,25 @@
#define TARGET_ENDIAN_DEFAULT 0
#endif
+#ifdef TARGET_ARM_EABI
+/* We default to a soft-float ABI so that binaries can run on all
+ target hardware. */
+#undef TARGET_DEFAULT_FLOAT_ABI
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
+
+#undef ARM_DEFAULT_ABI
+#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ FBSD_TARGET_OS_CPP_BUILTINS(); \
+ TARGET_BPABI_CPP_BUILTINS(); \
+ } \
+ while (false)
+#else
/* Default it to use ATPCS with soft-VFP. */
-#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_APCS_FRAME \
| TARGET_ENDIAN_DEFAULT)
@@ -70,6 +92,10 @@
#undef ARM_DEFAULT_ABI
#define ARM_DEFAULT_ABI ARM_ABI_ATPCS
+#undef FPUTYPE_DEFAULT
+#define FPUTYPE_DEFAULT FPUTYPE_VFP
+#endif
+
/* Define the actual types of some ANSI-mandated types.
Needs to agree with <machine/ansi.h>. GCC defaults come from c-decl.c,
c-common.c, and config/<arch>/<arch>.h. */
@@ -97,7 +123,7 @@
#define TARGET_VERSION fprintf (stderr, " (FreeBSD/armv6 ELF)");
#else
#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_strongarm
+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm9
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)");
#endif
@@ -134,5 +160,3 @@ do \
} \
while (0)
-#undef FPUTYPE_DEFAULT
-#define FPUTYPE_DEFAULT FPUTYPE_VFP
diff --git a/contrib/gcc/config/i386/host-cygwin.c b/contrib/gcc/config/i386/host-cygwin.c
index 15bd273..15bd273 100755..100644
--- a/contrib/gcc/config/i386/host-cygwin.c
+++ b/contrib/gcc/config/i386/host-cygwin.c
diff --git a/contrib/gcc/config/i386/winnt-cxx.c b/contrib/gcc/config/i386/winnt-cxx.c
index 6123ebb..6123ebb 100755..100644
--- a/contrib/gcc/config/i386/winnt-cxx.c
+++ b/contrib/gcc/config/i386/winnt-cxx.c
diff --git a/contrib/gcc/config/i386/winnt-stubs.c b/contrib/gcc/config/i386/winnt-stubs.c
index c196f75..c196f75 100755..100644
--- a/contrib/gcc/config/i386/winnt-stubs.c
+++ b/contrib/gcc/config/i386/winnt-stubs.c
diff --git a/contrib/gcc/unwind-dw2.c b/contrib/gcc/unwind-dw2.c
index 62c9d09..3306e06 100644
--- a/contrib/gcc/unwind-dw2.c
+++ b/contrib/gcc/unwind-dw2.c
@@ -1438,6 +1438,17 @@ uw_init_context_1 (struct _Unwind_Context *context,
context->ra = __builtin_extract_return_addr (outer_ra);
}
+#if defined(__clang__) && defined(__amd64__)
+/* Some versions of clang don't save and restore all callee registers, if a
+ __builtin_eh_return() intrinsic is used in a function. This is particularly
+ bad on amd64. For now, use the following ugly hack to force it to assume
+ those registers are clobbered, when invoking __builtin_eh_return(), so it
+ will emit code to save and restore them. */
+#define CLOBBER_REGS_HACK \
+ __asm __volatile(" " : : : "r15", "r14", "r13", "r12", "rbx", "rdx", "rax");
+#else
+#define CLOBBER_REGS_HACK
+#endif /* __clang__ */
/* Install TARGET into CURRENT so that we can return to it. This is a
macro because __builtin_eh_return must be invoked in the context of
@@ -1448,6 +1459,7 @@ uw_init_context_1 (struct _Unwind_Context *context,
{ \
long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
+ CLOBBER_REGS_HACK \
__builtin_eh_return (offset, handler); \
} \
while (0)
diff --git a/contrib/gdb/gdb/config/i386/nm-nto.h b/contrib/gdb/gdb/config/i386/nm-nto.h
index 34d9903..34d9903 100755..100644
--- a/contrib/gdb/gdb/config/i386/nm-nto.h
+++ b/contrib/gdb/gdb/config/i386/nm-nto.h
diff --git a/contrib/gdb/gdb/config/i386/nto.mh b/contrib/gdb/gdb/config/i386/nto.mh
index f412579..f412579 100755..100644
--- a/contrib/gdb/gdb/config/i386/nto.mh
+++ b/contrib/gdb/gdb/config/i386/nto.mh
diff --git a/contrib/gdb/gdb/config/i386/nto.mt b/contrib/gdb/gdb/config/i386/nto.mt
index 6655f3e..6655f3e 100755..100644
--- a/contrib/gdb/gdb/config/i386/nto.mt
+++ b/contrib/gdb/gdb/config/i386/nto.mt
diff --git a/contrib/gdb/gdb/config/i386/tm-nto.h b/contrib/gdb/gdb/config/i386/tm-nto.h
index ff5eb78..ff5eb78 100755..100644
--- a/contrib/gdb/gdb/config/i386/tm-nto.h
+++ b/contrib/gdb/gdb/config/i386/tm-nto.h
diff --git a/contrib/gdb/gdb/config/tm-nto.h b/contrib/gdb/gdb/config/tm-nto.h
index 359ff06..359ff06 100755..100644
--- a/contrib/gdb/gdb/config/tm-nto.h
+++ b/contrib/gdb/gdb/config/tm-nto.h
diff --git a/contrib/gdb/gdb/i386-nto-tdep.c b/contrib/gdb/gdb/i386-nto-tdep.c
index 6d2f492..6d2f492 100755..100644
--- a/contrib/gdb/gdb/i386-nto-tdep.c
+++ b/contrib/gdb/gdb/i386-nto-tdep.c
diff --git a/contrib/gdb/gdb/nto-procfs.c b/contrib/gdb/gdb/nto-procfs.c
index 00b4096..00b4096 100755..100644
--- a/contrib/gdb/gdb/nto-procfs.c
+++ b/contrib/gdb/gdb/nto-procfs.c
diff --git a/contrib/gdb/gdb/nto-tdep.c b/contrib/gdb/gdb/nto-tdep.c
index 056b93f..056b93f 100755..100644
--- a/contrib/gdb/gdb/nto-tdep.c
+++ b/contrib/gdb/gdb/nto-tdep.c
diff --git a/contrib/gdb/gdb/nto-tdep.h b/contrib/gdb/gdb/nto-tdep.h
index e22e8fd..e22e8fd 100755..100644
--- a/contrib/gdb/gdb/nto-tdep.h
+++ b/contrib/gdb/gdb/nto-tdep.h
diff --git a/contrib/gdb/gdb/proc-api.c b/contrib/gdb/gdb/proc-api.c
index e6d30ea..e6d30ea 100755..100644
--- a/contrib/gdb/gdb/proc-api.c
+++ b/contrib/gdb/gdb/proc-api.c
diff --git a/contrib/gdb/gdb/proc-events.c b/contrib/gdb/gdb/proc-events.c
index 5365fef..5365fef 100755..100644
--- a/contrib/gdb/gdb/proc-events.c
+++ b/contrib/gdb/gdb/proc-events.c
diff --git a/contrib/gdb/gdb/proc-flags.c b/contrib/gdb/gdb/proc-flags.c
index 6e737d1..6e737d1 100755..100644
--- a/contrib/gdb/gdb/proc-flags.c
+++ b/contrib/gdb/gdb/proc-flags.c
diff --git a/contrib/gdb/gdb/proc-why.c b/contrib/gdb/gdb/proc-why.c
index 15af16c..15af16c 100755..100644
--- a/contrib/gdb/gdb/proc-why.c
+++ b/contrib/gdb/gdb/proc-why.c
diff --git a/contrib/gdb/gdb/uw-thread.c b/contrib/gdb/gdb/uw-thread.c
index cc6ed6d..cc6ed6d 100755..100644
--- a/contrib/gdb/gdb/uw-thread.c
+++ b/contrib/gdb/gdb/uw-thread.c
diff --git a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch
index c232b2c..c232b2c 100755..100644
--- a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch
+++ b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch
diff --git a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0 b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0
index 1495801..1495801 100755..100644
--- a/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0
+++ b/contrib/ipfilter/FreeBSD-4.0/ipv6-patch-4.0
diff --git a/contrib/ipfilter/ipsend/44arp.c b/contrib/ipfilter/ipsend/44arp.c
index 5c07fb6..3fbafcc 100644
--- a/contrib/ipfilter/ipsend/44arp.c
+++ b/contrib/ipfilter/ipsend/44arp.c
@@ -72,7 +72,7 @@ char *addr, *eaddr;
size_t needed;
char *lim, *buf, *next;
struct rt_msghdr *rtm;
- struct sockaddr_inarp *sin;
+ struct sockaddr_in *sin;
struct sockaddr_dl *sdl;
#ifdef IPSEND
@@ -113,7 +113,7 @@ char *addr, *eaddr;
for (next = buf; next < lim; next += rtm->rtm_msglen)
{
rtm = (struct rt_msghdr *)next;
- sin = (struct sockaddr_inarp *)(rtm + 1);
+ sin = (struct sockaddr_in *)(rtm + 1);
sdl = (struct sockaddr_dl *)(sin + 1);
if (!bcmp(addr, (char *)&sin->sin_addr,
sizeof(struct in_addr)))
diff --git a/contrib/jemalloc/COPYING b/contrib/jemalloc/COPYING
index e27fc4d..019e813 100644
--- a/contrib/jemalloc/COPYING
+++ b/contrib/jemalloc/COPYING
@@ -1,10 +1,10 @@
Unless otherwise specified, files in the jemalloc source distribution are
subject to the following license:
--------------------------------------------------------------------------------
-Copyright (C) 2002-2012 Jason Evans <jasone@canonware.com>.
+Copyright (C) 2002-2013 Jason Evans <jasone@canonware.com>.
All rights reserved.
Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved.
-Copyright (C) 2009-2012 Facebook, Inc. All rights reserved.
+Copyright (C) 2009-2013 Facebook, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
diff --git a/contrib/jemalloc/ChangeLog b/contrib/jemalloc/ChangeLog
index ab3476c..6578225 100644
--- a/contrib/jemalloc/ChangeLog
+++ b/contrib/jemalloc/ChangeLog
@@ -6,6 +6,23 @@ found in the git revision history:
http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git
git://canonware.com/jemalloc.git
+* 3.3.0 (January 23, 2013)
+
+ This version includes a few minor performance improvements in addition to the
+ listed new features and bug fixes.
+
+ New features:
+ - Add clipping support to lg_chunk option processing.
+ - Add the --enable-ivsalloc option.
+ - Add the --without-export option.
+ - Add the --disable-zone-allocator option.
+
+ Bug fixes:
+ - Fix "arenas.extend" mallctl to output the number of arenas.
+ - Fix chunk_recycyle() to unconditionally inform Valgrind that returned memory
+ is undefined.
+ - Fix build break on FreeBSD related to alloca.h.
+
* 3.2.0 (November 9, 2012)
In addition to a couple of bug fixes, this version modifies page run
diff --git a/contrib/jemalloc/FREEBSD-diffs b/contrib/jemalloc/FREEBSD-diffs
index 0372f91..de2549a 100644
--- a/contrib/jemalloc/FREEBSD-diffs
+++ b/contrib/jemalloc/FREEBSD-diffs
@@ -1,5 +1,5 @@
diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in
-index 54b8747..91c4a4e 100644
+index 0930580..d45fa3d 100644
--- a/doc/jemalloc.xml.in
+++ b/doc/jemalloc.xml.in
@@ -51,12 +51,23 @@
@@ -27,7 +27,7 @@ index 54b8747..91c4a4e 100644
<refsect2>
<title>Standard API</title>
<funcprototype>
-@@ -2170,4 +2181,16 @@ malloc_conf = "lg_chunk:24";]]></programlisting></para>
+@@ -2173,4 +2184,16 @@ malloc_conf = "lg_chunk:24";]]></programlisting></para>
<para>The <function>posix_memalign<parameter/></function> function conforms
to IEEE Std 1003.1-2001 (&ldquo;POSIX.1&rdquo;).</para>
</refsect1>
@@ -45,7 +45,7 @@ index 54b8747..91c4a4e 100644
+ </refsect1>
</refentry>
diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in
-index 475821a..73306ac 100644
+index c606c12..0d46d9d 100644
--- a/include/jemalloc/internal/jemalloc_internal.h.in
+++ b/include/jemalloc/internal/jemalloc_internal.h.in
@@ -1,5 +1,8 @@
@@ -97,10 +97,10 @@ index de44e14..564d604 100644
bool malloc_mutex_init(malloc_mutex_t *mutex);
diff --git a/include/jemalloc/internal/private_namespace.h b/include/jemalloc/internal/private_namespace.h
-index 06241cd..7b19906 100644
+index 903fb4d..d6638df 100644
--- a/include/jemalloc/internal/private_namespace.h
+++ b/include/jemalloc/internal/private_namespace.h
-@@ -204,7 +204,6 @@
+@@ -216,7 +216,6 @@
#define iralloc JEMALLOC_N(iralloc)
#define irallocx JEMALLOC_N(irallocx)
#define isalloc JEMALLOC_N(isalloc)
@@ -203,7 +203,7 @@ index 0000000..9c97a13
+#define pthread_mutex_lock _pthread_mutex_lock
+#define pthread_mutex_unlock _pthread_mutex_unlock
diff --git a/src/jemalloc.c b/src/jemalloc.c
-index 8a667b6..aaf5012 100644
+index c117685..665d98f 100644
--- a/src/jemalloc.c
+++ b/src/jemalloc.c
@@ -8,6 +8,10 @@ malloc_tsd_data(, arenas, arena_t *, NULL)
@@ -216,8 +216,8 @@ index 8a667b6..aaf5012 100644
+
/* Runtime configuration options. */
const char *je_malloc_conf;
- #ifdef JEMALLOC_DEBUG
-@@ -448,7 +452,8 @@ malloc_conf_init(void)
+ bool opt_abort =
+@@ -453,7 +457,8 @@ malloc_conf_init(void)
#endif
;
diff --git a/contrib/jemalloc/FREEBSD-upgrade b/contrib/jemalloc/FREEBSD-upgrade
index cd6ada4..eb702d8 100755
--- a/contrib/jemalloc/FREEBSD-upgrade
+++ b/contrib/jemalloc/FREEBSD-upgrade
@@ -9,6 +9,7 @@
# - devel/git
# - devel/gmake
# - textproc/docbook-xsl
+# - textproc/libxslt
#
# The normal workflow for importing a new release is:
#
diff --git a/contrib/jemalloc/VERSION b/contrib/jemalloc/VERSION
index 5e64fc9..43f96d9 100644
--- a/contrib/jemalloc/VERSION
+++ b/contrib/jemalloc/VERSION
@@ -1 +1 @@
-3.2.0-0-g87499f6748ebe4817571e817e9f680ccb5bf54a9
+3.3.0-0-g83789f45307379e096c4e8be81d9e9a51e3f5a4a
diff --git a/contrib/jemalloc/doc/jemalloc.3 b/contrib/jemalloc/doc/jemalloc.3
index eada516..b0122ee 100644
--- a/contrib/jemalloc/doc/jemalloc.3
+++ b/contrib/jemalloc/doc/jemalloc.3
@@ -2,12 +2,12 @@
.\" Title: JEMALLOC
.\" Author: Jason Evans
.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
-.\" Date: 11/09/2012
+.\" Date: 01/23/2013
.\" Manual: User Manual
-.\" Source: jemalloc 3.2.0-0-g87499f6748ebe4817571e817e9f680ccb5bf54a9
+.\" Source: jemalloc 3.3.0-0-g83789f45307379e096c4e8be81d9e9a51e3f5a4a
.\" Language: English
.\"
-.TH "JEMALLOC" "3" "11/09/2012" "jemalloc 3.2.0-0-g87499f6748eb" "User Manual"
+.TH "JEMALLOC" "3" "01/23/2013" "jemalloc 3.3.0-0-g83789f453073" "User Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -31,7 +31,7 @@
jemalloc \- general purpose memory allocation functions
.SH "LIBRARY"
.PP
-This manual describes jemalloc 3\&.2\&.0\-0\-g87499f6748ebe4817571e817e9f680ccb5bf54a9\&. More information can be found at the
+This manual describes jemalloc 3\&.3\&.0\-0\-g83789f45307379e096c4e8be81d9e9a51e3f5a4a\&. More information can be found at the
\m[blue]\fBjemalloc website\fR\m[]\&\s-2\u[1]\d\s+2\&.
.PP
The following configuration options are enabled in libc\*(Aqs built\-in jemalloc:
@@ -652,7 +652,7 @@ is specified during configuration, in which case it is enabled by default\&.
.PP
"opt\&.lg_chunk" (\fBsize_t\fR) r\-
.RS 4
-Virtual memory chunk size (log base 2)\&. The default chunk size is 4 MiB (2^22)\&.
+Virtual memory chunk size (log base 2)\&. If a chunk size outside the supported size range is specified, the size is silently clipped to the minimum/maximum supported size\&. The default chunk size is 4 MiB (2^22)\&.
.RE
.PP
"opt\&.dss" (\fBconst char *\fR) r\-
diff --git a/contrib/jemalloc/include/jemalloc/internal/arena.h b/contrib/jemalloc/include/jemalloc/internal/arena.h
index 561c9b6..8fdee93 100644
--- a/contrib/jemalloc/include/jemalloc/internal/arena.h
+++ b/contrib/jemalloc/include/jemalloc/internal/arena.h
@@ -400,7 +400,6 @@ extern arena_bin_info_t arena_bin_info[NBINS];
#define nlclasses (chunk_npages - map_bias)
void arena_purge_all(arena_t *arena);
-void arena_prof_accum(arena_t *arena, uint64_t accumbytes);
void arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin,
size_t binind, uint64_t prof_accumbytes);
void arena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info,
@@ -464,6 +463,9 @@ void arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind,
size_t runind, size_t binind, size_t flags);
void arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,
size_t unzeroed);
+void arena_prof_accum_impl(arena_t *arena, uint64_t accumbytes);
+void arena_prof_accum_locked(arena_t *arena, uint64_t accumbytes);
+void arena_prof_accum(arena_t *arena, uint64_t accumbytes);
size_t arena_ptr_small_binind_get(const void *ptr, size_t mapbits);
size_t arena_bin_index(arena_t *arena, arena_bin_t *bin);
unsigned arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info,
@@ -478,7 +480,7 @@ void arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr,
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ARENA_C_))
# ifdef JEMALLOC_ARENA_INLINE_A
-JEMALLOC_INLINE arena_chunk_map_t *
+JEMALLOC_ALWAYS_INLINE arena_chunk_map_t *
arena_mapp_get(arena_chunk_t *chunk, size_t pageind)
{
@@ -488,21 +490,21 @@ arena_mapp_get(arena_chunk_t *chunk, size_t pageind)
return (&chunk->map[pageind-map_bias]);
}
-JEMALLOC_INLINE size_t *
+JEMALLOC_ALWAYS_INLINE size_t *
arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind)
{
return (&arena_mapp_get(chunk, pageind)->bits);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_get(arena_chunk_t *chunk, size_t pageind)
{
return (*arena_mapbitsp_get(chunk, pageind));
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_unallocated_size_get(arena_chunk_t *chunk, size_t pageind)
{
size_t mapbits;
@@ -512,7 +514,7 @@ arena_mapbits_unallocated_size_get(arena_chunk_t *chunk, size_t pageind)
return (mapbits & ~PAGE_MASK);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind)
{
size_t mapbits;
@@ -523,7 +525,7 @@ arena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind)
return (mapbits & ~PAGE_MASK);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind)
{
size_t mapbits;
@@ -534,7 +536,7 @@ arena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind)
return (mapbits >> LG_PAGE);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind)
{
size_t mapbits;
@@ -546,7 +548,7 @@ arena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind)
return (binind);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind)
{
size_t mapbits;
@@ -555,7 +557,7 @@ arena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind)
return (mapbits & CHUNK_MAP_DIRTY);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind)
{
size_t mapbits;
@@ -564,7 +566,7 @@ arena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind)
return (mapbits & CHUNK_MAP_UNZEROED);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind)
{
size_t mapbits;
@@ -573,7 +575,7 @@ arena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind)
return (mapbits & CHUNK_MAP_LARGE);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind)
{
size_t mapbits;
@@ -582,7 +584,7 @@ arena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind)
return (mapbits & CHUNK_MAP_ALLOCATED);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
arena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, size_t size,
size_t flags)
{
@@ -595,7 +597,7 @@ arena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, size_t size,
*mapbitsp = size | CHUNK_MAP_BININD_INVALID | flags;
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
arena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,
size_t size)
{
@@ -607,7 +609,7 @@ arena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,
*mapbitsp = size | (*mapbitsp & PAGE_MASK);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
arena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, size_t size,
size_t flags)
{
@@ -622,7 +624,7 @@ arena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, size_t size,
CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED;
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
arena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,
size_t binind)
{
@@ -635,7 +637,7 @@ arena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,
CHUNK_MAP_BININD_SHIFT);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, size_t runind,
size_t binind, size_t flags)
{
@@ -651,7 +653,7 @@ arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, size_t runind,
flags | unzeroed | CHUNK_MAP_ALLOCATED;
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,
size_t unzeroed)
{
@@ -661,7 +663,45 @@ arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,
*mapbitsp = (*mapbitsp & ~CHUNK_MAP_UNZEROED) | unzeroed;
}
-JEMALLOC_INLINE size_t
+JEMALLOC_INLINE void
+arena_prof_accum_impl(arena_t *arena, uint64_t accumbytes)
+{
+
+ cassert(config_prof);
+ assert(prof_interval != 0);
+
+ arena->prof_accumbytes += accumbytes;
+ if (arena->prof_accumbytes >= prof_interval) {
+ prof_idump();
+ arena->prof_accumbytes -= prof_interval;
+ }
+}
+
+JEMALLOC_INLINE void
+arena_prof_accum_locked(arena_t *arena, uint64_t accumbytes)
+{
+
+ cassert(config_prof);
+
+ if (prof_interval == 0)
+ return;
+ arena_prof_accum_impl(arena, accumbytes);
+}
+
+JEMALLOC_INLINE void
+arena_prof_accum(arena_t *arena, uint64_t accumbytes)
+{
+
+ cassert(config_prof);
+
+ if (prof_interval == 0)
+ return;
+ malloc_mutex_lock(&arena->lock);
+ arena_prof_accum_impl(arena, accumbytes);
+ malloc_mutex_unlock(&arena->lock);
+}
+
+JEMALLOC_ALWAYS_INLINE size_t
arena_ptr_small_binind_get(const void *ptr, size_t mapbits)
{
size_t binind;
@@ -856,7 +896,7 @@ arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx)
arena_mapp_get(chunk, pageind)->prof_ctx = ctx;
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache)
{
tcache_t *tcache;
@@ -887,7 +927,7 @@ arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache)
}
/* Return the size of the allocation pointed to by ptr. */
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
arena_salloc(const void *ptr, bool demote)
{
size_t ret;
@@ -933,7 +973,7 @@ arena_salloc(const void *ptr, bool demote)
return (ret);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr, bool try_tcache)
{
size_t pageind, mapbits;
diff --git a/contrib/jemalloc/include/jemalloc/internal/ckh.h b/contrib/jemalloc/include/jemalloc/internal/ckh.h
index 05d1fc0..50c39ed 100644
--- a/contrib/jemalloc/include/jemalloc/internal/ckh.h
+++ b/contrib/jemalloc/include/jemalloc/internal/ckh.h
@@ -5,7 +5,7 @@ typedef struct ckh_s ckh_t;
typedef struct ckhc_s ckhc_t;
/* Typedefs to allow easy function pointer passing. */
-typedef void ckh_hash_t (const void *, unsigned, size_t *, size_t *);
+typedef void ckh_hash_t (const void *, size_t[2]);
typedef bool ckh_keycomp_t (const void *, const void *);
/* Maintain counters used to get an idea of performance. */
@@ -75,11 +75,9 @@ bool ckh_insert(ckh_t *ckh, const void *key, const void *data);
bool ckh_remove(ckh_t *ckh, const void *searchkey, void **key,
void **data);
bool ckh_search(ckh_t *ckh, const void *seachkey, void **key, void **data);
-void ckh_string_hash(const void *key, unsigned minbits, size_t *hash1,
- size_t *hash2);
+void ckh_string_hash(const void *key, size_t r_hash[2]);
bool ckh_string_keycomp(const void *k1, const void *k2);
-void ckh_pointer_hash(const void *key, unsigned minbits, size_t *hash1,
- size_t *hash2);
+void ckh_pointer_hash(const void *key, size_t r_hash[2]);
bool ckh_pointer_keycomp(const void *k1, const void *k2);
#endif /* JEMALLOC_H_EXTERNS */
diff --git a/contrib/jemalloc/include/jemalloc/internal/hash.h b/contrib/jemalloc/include/jemalloc/internal/hash.h
index 2f501f5..56ecc79 100644
--- a/contrib/jemalloc/include/jemalloc/internal/hash.h
+++ b/contrib/jemalloc/include/jemalloc/internal/hash.h
@@ -1,3 +1,8 @@
+/*
+ * The following hash function is based on MurmurHash3, placed into the public
+ * domain by Austin Appleby. See http://code.google.com/p/smhasher/ for
+ * details.
+ */
/******************************************************************************/
#ifdef JEMALLOC_H_TYPES
@@ -14,55 +19,311 @@
#ifdef JEMALLOC_H_INLINES
#ifndef JEMALLOC_ENABLE_INLINE
-uint64_t hash(const void *key, size_t len, uint64_t seed);
+void hash(const void *key, size_t len, const uint32_t seed,
+ size_t r_hash[2]);
#endif
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_HASH_C_))
-/*
- * The following hash function is based on MurmurHash64A(), placed into the
- * public domain by Austin Appleby. See http://murmurhash.googlepages.com/ for
- * details.
- */
+/******************************************************************************/
+/* Internal implementation. */
+JEMALLOC_INLINE uint32_t
+hash_rotl_32(uint32_t x, int8_t r)
+{
+
+ return (x << r) | (x >> (32 - r));
+}
+
+JEMALLOC_INLINE uint64_t
+hash_rotl_64(uint64_t x, int8_t r)
+{
+ return (x << r) | (x >> (64 - r));
+}
+
+JEMALLOC_INLINE uint32_t
+hash_get_block_32(const uint32_t *p, int i)
+{
+
+ return p[i];
+}
+
JEMALLOC_INLINE uint64_t
-hash(const void *key, size_t len, uint64_t seed)
+hash_get_block_64(const uint64_t *p, int i)
{
- const uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
- const int r = 47;
- uint64_t h = seed ^ (len * m);
- const uint64_t *data = (const uint64_t *)key;
- const uint64_t *end = data + (len/8);
- const unsigned char *data2;
- assert(((uintptr_t)key & 0x7) == 0);
+ return p[i];
+}
+
+JEMALLOC_INLINE uint32_t
+hash_fmix_32(uint32_t h)
+{
- while(data != end) {
- uint64_t k = *data++;
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
- k *= m;
- k ^= k >> r;
- k *= m;
+ return h;
+}
- h ^= k;
- h *= m;
+JEMALLOC_INLINE uint64_t
+hash_fmix_64(uint64_t k)
+{
+
+ k ^= k >> 33;
+ k *= QU(0xff51afd7ed558ccdLLU);
+ k ^= k >> 33;
+ k *= QU(0xc4ceb9fe1a85ec53LLU);
+ k ^= k >> 33;
+
+ return k;
+}
+
+JEMALLOC_INLINE uint32_t
+hash_x86_32(const void *key, int len, uint32_t seed)
+{
+ const uint8_t *data = (const uint8_t *) key;
+ const int nblocks = len / 4;
+
+ uint32_t h1 = seed;
+
+ const uint32_t c1 = 0xcc9e2d51;
+ const uint32_t c2 = 0x1b873593;
+
+ /* body */
+ {
+ const uint32_t *blocks = (const uint32_t *) (data + nblocks*4);
+ int i;
+
+ for (i = -nblocks; i; i++) {
+ uint32_t k1 = hash_get_block_32(blocks, i);
+
+ k1 *= c1;
+ k1 = hash_rotl_32(k1, 15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = hash_rotl_32(h1, 13);
+ h1 = h1*5 + 0xe6546b64;
+ }
}
- data2 = (const unsigned char *)data;
- switch(len & 7) {
- case 7: h ^= ((uint64_t)(data2[6])) << 48;
- case 6: h ^= ((uint64_t)(data2[5])) << 40;
- case 5: h ^= ((uint64_t)(data2[4])) << 32;
- case 4: h ^= ((uint64_t)(data2[3])) << 24;
- case 3: h ^= ((uint64_t)(data2[2])) << 16;
- case 2: h ^= ((uint64_t)(data2[1])) << 8;
- case 1: h ^= ((uint64_t)(data2[0]));
- h *= m;
+ /* tail */
+ {
+ const uint8_t *tail = (const uint8_t *) (data + nblocks*4);
+
+ uint32_t k1 = 0;
+
+ switch (len & 3) {
+ case 3: k1 ^= tail[2] << 16;
+ case 2: k1 ^= tail[1] << 8;
+ case 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15);
+ k1 *= c2; h1 ^= k1;
+ }
}
- h ^= h >> r;
- h *= m;
- h ^= h >> r;
+ /* finalization */
+ h1 ^= len;
+
+ h1 = hash_fmix_32(h1);
+
+ return h1;
+}
+
+UNUSED JEMALLOC_INLINE void
+hash_x86_128(const void *key, const int len, uint32_t seed,
+ uint64_t r_out[2])
+{
+ const uint8_t * data = (const uint8_t *) key;
+ const int nblocks = len / 16;
+
+ uint32_t h1 = seed;
+ uint32_t h2 = seed;
+ uint32_t h3 = seed;
+ uint32_t h4 = seed;
+
+ const uint32_t c1 = 0x239b961b;
+ const uint32_t c2 = 0xab0e9789;
+ const uint32_t c3 = 0x38b34ae5;
+ const uint32_t c4 = 0xa1e38b93;
+
+ /* body */
+ {
+ const uint32_t *blocks = (const uint32_t *) (data + nblocks*16);
+ int i;
+
+ for (i = -nblocks; i; i++) {
+ uint32_t k1 = hash_get_block_32(blocks, i*4 + 0);
+ uint32_t k2 = hash_get_block_32(blocks, i*4 + 1);
+ uint32_t k3 = hash_get_block_32(blocks, i*4 + 2);
+ uint32_t k4 = hash_get_block_32(blocks, i*4 + 3);
- return (h);
+ k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;
+
+ h1 = hash_rotl_32(h1, 19); h1 += h2;
+ h1 = h1*5 + 0x561ccd1b;
+
+ k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;
+
+ h2 = hash_rotl_32(h2, 17); h2 += h3;
+ h2 = h2*5 + 0x0bcaa747;
+
+ k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;
+
+ h3 = hash_rotl_32(h3, 15); h3 += h4;
+ h3 = h3*5 + 0x96cd1c35;
+
+ k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;
+
+ h4 = hash_rotl_32(h4, 13); h4 += h1;
+ h4 = h4*5 + 0x32ac3b17;
+ }
+ }
+
+ /* tail */
+ {
+ const uint8_t *tail = (const uint8_t *) (data + nblocks*16);
+ uint32_t k1 = 0;
+ uint32_t k2 = 0;
+ uint32_t k3 = 0;
+ uint32_t k4 = 0;
+
+ switch (len & 15) {
+ case 15: k4 ^= tail[14] << 16;
+ case 14: k4 ^= tail[13] << 8;
+ case 13: k4 ^= tail[12] << 0;
+ k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;
+
+ case 12: k3 ^= tail[11] << 24;
+ case 11: k3 ^= tail[10] << 16;
+ case 10: k3 ^= tail[ 9] << 8;
+ case 9: k3 ^= tail[ 8] << 0;
+ k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;
+
+ case 8: k2 ^= tail[ 7] << 24;
+ case 7: k2 ^= tail[ 6] << 16;
+ case 6: k2 ^= tail[ 5] << 8;
+ case 5: k2 ^= tail[ 4] << 0;
+ k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;
+
+ case 4: k1 ^= tail[ 3] << 24;
+ case 3: k1 ^= tail[ 2] << 16;
+ case 2: k1 ^= tail[ 1] << 8;
+ case 1: k1 ^= tail[ 0] << 0;
+ k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;
+ }
+ }
+
+ /* finalization */
+ h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
+
+ h1 += h2; h1 += h3; h1 += h4;
+ h2 += h1; h3 += h1; h4 += h1;
+
+ h1 = hash_fmix_32(h1);
+ h2 = hash_fmix_32(h2);
+ h3 = hash_fmix_32(h3);
+ h4 = hash_fmix_32(h4);
+
+ h1 += h2; h1 += h3; h1 += h4;
+ h2 += h1; h3 += h1; h4 += h1;
+
+ r_out[0] = (((uint64_t) h2) << 32) | h1;
+ r_out[1] = (((uint64_t) h4) << 32) | h3;
+}
+
+UNUSED JEMALLOC_INLINE void
+hash_x64_128(const void *key, const int len, const uint32_t seed,
+ uint64_t r_out[2])
+{
+ const uint8_t *data = (const uint8_t *) key;
+ const int nblocks = len / 16;
+
+ uint64_t h1 = seed;
+ uint64_t h2 = seed;
+
+ const uint64_t c1 = QU(0x87c37b91114253d5LLU);
+ const uint64_t c2 = QU(0x4cf5ad432745937fLLU);
+
+ /* body */
+ {
+ const uint64_t *blocks = (const uint64_t *) (data);
+ int i;
+
+ for (i = 0; i < nblocks; i++) {
+ uint64_t k1 = hash_get_block_64(blocks, i*2 + 0);
+ uint64_t k2 = hash_get_block_64(blocks, i*2 + 1);
+
+ k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;
+
+ h1 = hash_rotl_64(h1, 27); h1 += h2;
+ h1 = h1*5 + 0x52dce729;
+
+ k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;
+
+ h2 = hash_rotl_64(h2, 31); h2 += h1;
+ h2 = h2*5 + 0x38495ab5;
+ }
+ }
+
+ /* tail */
+ {
+ const uint8_t *tail = (const uint8_t*)(data + nblocks*16);
+ uint64_t k1 = 0;
+ uint64_t k2 = 0;
+
+ switch (len & 15) {
+ case 15: k2 ^= ((uint64_t)(tail[14])) << 48;
+ case 14: k2 ^= ((uint64_t)(tail[13])) << 40;
+ case 13: k2 ^= ((uint64_t)(tail[12])) << 32;
+ case 12: k2 ^= ((uint64_t)(tail[11])) << 24;
+ case 11: k2 ^= ((uint64_t)(tail[10])) << 16;
+ case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8;
+ case 9: k2 ^= ((uint64_t)(tail[ 8])) << 0;
+ k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;
+
+ case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56;
+ case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48;
+ case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40;
+ case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32;
+ case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24;
+ case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16;
+ case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8;
+ case 1: k1 ^= ((uint64_t)(tail[ 0])) << 0;
+ k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;
+ }
+ }
+
+ /* finalization */
+ h1 ^= len; h2 ^= len;
+
+ h1 += h2;
+ h2 += h1;
+
+ h1 = hash_fmix_64(h1);
+ h2 = hash_fmix_64(h2);
+
+ h1 += h2;
+ h2 += h1;
+
+ r_out[0] = h1;
+ r_out[1] = h2;
+}
+
+
+/******************************************************************************/
+/* API. */
+JEMALLOC_INLINE void
+hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2])
+{
+#if (LG_SIZEOF_PTR == 3)
+ hash_x64_128(key, len, seed, (uint64_t *)r_hash);
+#else
+ uint64_t hashes[2];
+ hash_x86_128(key, len, seed, hashes);
+ r_hash[0] = (size_t)hashes[0];
+ r_hash[1] = (size_t)hashes[1];
+#endif
}
#endif
diff --git a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h
index 4214c53..9647ffe 100644
--- a/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h
+++ b/contrib/jemalloc/include/jemalloc/internal/jemalloc_internal.h
@@ -226,6 +226,7 @@ static const bool config_ivsalloc =
#define ALLOCM_LG_ALIGN_MASK ((int)0x3f)
#define ZU(z) ((size_t)z)
+#define QU(q) ((uint64_t)q)
#ifndef __DECONST
# define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
@@ -233,10 +234,17 @@ static const bool config_ivsalloc =
#ifdef JEMALLOC_DEBUG
/* Disable inlining to make debugging easier. */
+# define JEMALLOC_ALWAYS_INLINE
# define JEMALLOC_INLINE
# define inline
#else
# define JEMALLOC_ENABLE_INLINE
+# ifdef JEMALLOC_HAVE_ATTR
+# define JEMALLOC_ALWAYS_INLINE \
+ static inline JEMALLOC_ATTR(unused) JEMALLOC_ATTR(always_inline)
+# else
+# define JEMALLOC_ALWAYS_INLINE static inline
+# endif
# define JEMALLOC_INLINE static inline
# ifdef _MSC_VER
# define inline _inline
@@ -359,7 +367,11 @@ static const bool config_ivsalloc =
# include <malloc.h>
# define alloca _alloca
# else
-# include <alloca.h>
+# ifdef JEMALLOC_HAS_ALLOCA_H
+# include <alloca.h>
+# else
+# include <stdlib.h>
+# endif
# endif
# define VARIABLE_ARRAY(type, name, count) \
type *name = alloca(sizeof(type) * count)
@@ -591,13 +603,14 @@ arena_t *choose_arena(arena_t *arena);
* for allocations.
*/
malloc_tsd_externs(arenas, arena_t *)
-malloc_tsd_funcs(JEMALLOC_INLINE, arenas, arena_t *, NULL, arenas_cleanup)
+malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, arenas, arena_t *, NULL,
+ arenas_cleanup)
/*
* Compute usable size that would result from allocating an object with the
* specified size.
*/
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
s2u(size_t size)
{
@@ -612,7 +625,7 @@ s2u(size_t size)
* Compute usable size that would result from allocating an object with the
* specified size and alignment.
*/
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
sa2u(size_t size, size_t alignment)
{
size_t usize;
@@ -757,7 +770,7 @@ malloc_tsd_protos(JEMALLOC_ATTR(unused), thread_allocated, thread_allocated_t)
#endif
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
imallocx(size_t size, bool try_tcache, arena_t *arena)
{
@@ -769,14 +782,14 @@ imallocx(size_t size, bool try_tcache, arena_t *arena)
return (huge_malloc(size, false));
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
imalloc(size_t size)
{
return (imallocx(size, true, NULL));
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
icallocx(size_t size, bool try_tcache, arena_t *arena)
{
@@ -786,14 +799,14 @@ icallocx(size_t size, bool try_tcache, arena_t *arena)
return (huge_malloc(size, true));
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
icalloc(size_t size)
{
return (icallocx(size, true, NULL));
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
ipallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,
arena_t *arena)
{
@@ -818,7 +831,7 @@ ipallocx(size_t usize, size_t alignment, bool zero, bool try_tcache,
return (ret);
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
ipalloc(size_t usize, size_t alignment, bool zero)
{
@@ -830,7 +843,7 @@ ipalloc(size_t usize, size_t alignment, bool zero)
* void *ptr = [...]
* size_t sz = isalloc(ptr, config_prof);
*/
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
isalloc(const void *ptr, bool demote)
{
size_t ret;
@@ -849,7 +862,7 @@ isalloc(const void *ptr, bool demote)
return (ret);
}
-JEMALLOC_INLINE size_t
+JEMALLOC_ALWAYS_INLINE size_t
ivsalloc(const void *ptr, bool demote)
{
@@ -882,7 +895,7 @@ p2rz(const void *ptr)
return (u2rz(usize));
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
idallocx(void *ptr, bool try_tcache)
{
arena_chunk_t *chunk;
@@ -896,14 +909,14 @@ idallocx(void *ptr, bool try_tcache)
huge_dalloc(ptr, true);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
idalloc(void *ptr)
{
idallocx(ptr, true);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
iqallocx(void *ptr, bool try_tcache)
{
@@ -913,14 +926,14 @@ iqallocx(void *ptr, bool try_tcache)
idallocx(ptr, try_tcache);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
iqalloc(void *ptr)
{
iqallocx(ptr, true);
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
irallocx(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
bool no_move, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena)
{
@@ -989,7 +1002,7 @@ irallocx(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
}
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
bool no_move)
{
@@ -999,7 +1012,7 @@ iralloc(void *ptr, size_t size, size_t extra, size_t alignment, bool zero,
}
malloc_tsd_externs(thread_allocated, thread_allocated_t)
-malloc_tsd_funcs(JEMALLOC_INLINE, thread_allocated, thread_allocated_t,
+malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, thread_allocated, thread_allocated_t,
THREAD_ALLOCATED_INITIALIZER, malloc_tsd_no_cleanup)
#endif
diff --git a/contrib/jemalloc/include/jemalloc/internal/private_namespace.h b/contrib/jemalloc/include/jemalloc/internal/private_namespace.h
index 7b19906..d6638df 100644
--- a/contrib/jemalloc/include/jemalloc/internal/private_namespace.h
+++ b/contrib/jemalloc/include/jemalloc/internal/private_namespace.h
@@ -41,6 +41,8 @@
#define arena_postfork_parent JEMALLOC_N(arena_postfork_parent)
#define arena_prefork JEMALLOC_N(arena_prefork)
#define arena_prof_accum JEMALLOC_N(arena_prof_accum)
+#define arena_prof_accum_impl JEMALLOC_N(arena_prof_accum_impl)
+#define arena_prof_accum_locked JEMALLOC_N(arena_prof_accum_locked)
#define arena_prof_ctx_get JEMALLOC_N(arena_prof_ctx_get)
#define arena_prof_ctx_set JEMALLOC_N(arena_prof_ctx_set)
#define arena_prof_promoted JEMALLOC_N(arena_prof_promoted)
@@ -63,6 +65,7 @@
#define arenas_tsd_boot JEMALLOC_N(arenas_tsd_boot)
#define arenas_tsd_cleanup_wrapper JEMALLOC_N(arenas_tsd_cleanup_wrapper)
#define arenas_tsd_get JEMALLOC_N(arenas_tsd_get)
+#define arenas_tsd_get_wrapper JEMALLOC_N(arenas_tsd_get_wrapper)
#define arenas_tsd_set JEMALLOC_N(arenas_tsd_set)
#define atomic_add_u JEMALLOC_N(atomic_add_u)
#define atomic_add_uint32 JEMALLOC_N(atomic_add_uint32)
@@ -174,6 +177,15 @@
#define extent_tree_szad_search JEMALLOC_N(extent_tree_szad_search)
#define get_errno JEMALLOC_N(get_errno)
#define hash JEMALLOC_N(hash)
+#define hash_fmix_32 JEMALLOC_N(hash_fmix_32)
+#define hash_fmix_64 JEMALLOC_N(hash_fmix_64)
+#define hash_get_block_32 JEMALLOC_N(hash_get_block_32)
+#define hash_get_block_64 JEMALLOC_N(hash_get_block_64)
+#define hash_rotl_32 JEMALLOC_N(hash_rotl_32)
+#define hash_rotl_64 JEMALLOC_N(hash_rotl_64)
+#define hash_x64_128 JEMALLOC_N(hash_x64_128)
+#define hash_x86_128 JEMALLOC_N(hash_x86_128)
+#define hash_x86_32 JEMALLOC_N(hash_x86_32)
#define huge_allocated JEMALLOC_N(huge_allocated)
#define huge_boot JEMALLOC_N(huge_boot)
#define huge_dalloc JEMALLOC_N(huge_dalloc)
@@ -290,12 +302,14 @@
#define prof_tdata_tsd_boot JEMALLOC_N(prof_tdata_tsd_boot)
#define prof_tdata_tsd_cleanup_wrapper JEMALLOC_N(prof_tdata_tsd_cleanup_wrapper)
#define prof_tdata_tsd_get JEMALLOC_N(prof_tdata_tsd_get)
+#define prof_tdata_tsd_get_wrapper JEMALLOC_N(prof_tdata_tsd_get_wrapper)
#define prof_tdata_tsd_set JEMALLOC_N(prof_tdata_tsd_set)
#define quarantine JEMALLOC_N(quarantine)
#define quarantine_boot JEMALLOC_N(quarantine_boot)
#define quarantine_tsd_boot JEMALLOC_N(quarantine_tsd_boot)
#define quarantine_tsd_cleanup_wrapper JEMALLOC_N(quarantine_tsd_cleanup_wrapper)
#define quarantine_tsd_get JEMALLOC_N(quarantine_tsd_get)
+#define quarantine_tsd_get_wrapper JEMALLOC_N(quarantine_tsd_get_wrapper)
#define quarantine_tsd_set JEMALLOC_N(quarantine_tsd_set)
#define register_zone JEMALLOC_N(register_zone)
#define rtree_get JEMALLOC_N(rtree_get)
@@ -339,6 +353,7 @@
#define tcache_enabled_tsd_boot JEMALLOC_N(tcache_enabled_tsd_boot)
#define tcache_enabled_tsd_cleanup_wrapper JEMALLOC_N(tcache_enabled_tsd_cleanup_wrapper)
#define tcache_enabled_tsd_get JEMALLOC_N(tcache_enabled_tsd_get)
+#define tcache_enabled_tsd_get_wrapper JEMALLOC_N(tcache_enabled_tsd_get_wrapper)
#define tcache_enabled_tsd_set JEMALLOC_N(tcache_enabled_tsd_set)
#define tcache_event JEMALLOC_N(tcache_event)
#define tcache_event_hard JEMALLOC_N(tcache_event_hard)
@@ -354,6 +369,7 @@
#define tcache_tsd_boot JEMALLOC_N(tcache_tsd_boot)
#define tcache_tsd_cleanup_wrapper JEMALLOC_N(tcache_tsd_cleanup_wrapper)
#define tcache_tsd_get JEMALLOC_N(tcache_tsd_get)
+#define tcache_tsd_get_wrapper JEMALLOC_N(tcache_tsd_get_wrapper)
#define tcache_tsd_set JEMALLOC_N(tcache_tsd_set)
#define thread_allocated_booted JEMALLOC_N(thread_allocated_booted)
#define thread_allocated_initialized JEMALLOC_N(thread_allocated_initialized)
@@ -362,5 +378,6 @@
#define thread_allocated_tsd_boot JEMALLOC_N(thread_allocated_tsd_boot)
#define thread_allocated_tsd_cleanup_wrapper JEMALLOC_N(thread_allocated_tsd_cleanup_wrapper)
#define thread_allocated_tsd_get JEMALLOC_N(thread_allocated_tsd_get)
+#define thread_allocated_tsd_get_wrapper JEMALLOC_N(thread_allocated_tsd_get_wrapper)
#define thread_allocated_tsd_set JEMALLOC_N(thread_allocated_tsd_set)
#define u2rz JEMALLOC_N(u2rz)
diff --git a/contrib/jemalloc/include/jemalloc/internal/tcache.h b/contrib/jemalloc/include/jemalloc/internal/tcache.h
index 38d735c..71900c2 100644
--- a/contrib/jemalloc/include/jemalloc/internal/tcache.h
+++ b/contrib/jemalloc/include/jemalloc/internal/tcache.h
@@ -140,11 +140,11 @@ void tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size);
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TCACHE_C_))
/* Map of thread-specific caches. */
malloc_tsd_externs(tcache, tcache_t *)
-malloc_tsd_funcs(JEMALLOC_INLINE, tcache, tcache_t *, NULL,
+malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache, tcache_t *, NULL,
tcache_thread_cleanup)
/* Per thread flag that allows thread caches to be disabled. */
malloc_tsd_externs(tcache_enabled, tcache_enabled_t)
-malloc_tsd_funcs(JEMALLOC_INLINE, tcache_enabled, tcache_enabled_t,
+malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache_enabled, tcache_enabled_t,
tcache_enabled_default, malloc_tsd_no_cleanup)
JEMALLOC_INLINE void
@@ -206,7 +206,7 @@ tcache_enabled_set(bool enabled)
}
}
-JEMALLOC_INLINE tcache_t *
+JEMALLOC_ALWAYS_INLINE tcache_t *
tcache_get(bool create)
{
tcache_t *tcache;
@@ -258,7 +258,7 @@ tcache_get(bool create)
return (tcache);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
tcache_event(tcache_t *tcache)
{
@@ -271,7 +271,7 @@ tcache_event(tcache_t *tcache)
tcache_event_hard(tcache);
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
tcache_alloc_easy(tcache_bin_t *tbin)
{
void *ret;
@@ -287,7 +287,7 @@ tcache_alloc_easy(tcache_bin_t *tbin)
return (ret);
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
tcache_alloc_small(tcache_t *tcache, size_t size, bool zero)
{
void *ret;
@@ -320,6 +320,7 @@ tcache_alloc_small(tcache_t *tcache, size_t size, bool zero)
}
VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
memset(ret, 0, size);
+ VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
}
if (config_stats)
@@ -330,7 +331,7 @@ tcache_alloc_small(tcache_t *tcache, size_t size, bool zero)
return (ret);
}
-JEMALLOC_INLINE void *
+JEMALLOC_ALWAYS_INLINE void *
tcache_alloc_large(tcache_t *tcache, size_t size, bool zero)
{
void *ret;
@@ -370,6 +371,7 @@ tcache_alloc_large(tcache_t *tcache, size_t size, bool zero)
} else {
VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
memset(ret, 0, size);
+ VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
}
if (config_stats)
@@ -382,7 +384,7 @@ tcache_alloc_large(tcache_t *tcache, size_t size, bool zero)
return (ret);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
tcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind)
{
tcache_bin_t *tbin;
@@ -406,7 +408,7 @@ tcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind)
tcache_event(tcache);
}
-JEMALLOC_INLINE void
+JEMALLOC_ALWAYS_INLINE void
tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size)
{
size_t binind;
diff --git a/contrib/jemalloc/include/jemalloc/jemalloc.h b/contrib/jemalloc/include/jemalloc/jemalloc.h
index 629dbb4..43c1a38 100644
--- a/contrib/jemalloc/include/jemalloc/jemalloc.h
+++ b/contrib/jemalloc/include/jemalloc/jemalloc.h
@@ -7,12 +7,12 @@ extern "C" {
#include <limits.h>
#include <strings.h>
-#define JEMALLOC_VERSION "3.2.0-0-g87499f6748ebe4817571e817e9f680ccb5bf54a9"
+#define JEMALLOC_VERSION "3.3.0-0-g83789f45307379e096c4e8be81d9e9a51e3f5a4a"
#define JEMALLOC_VERSION_MAJOR 3
-#define JEMALLOC_VERSION_MINOR 2
+#define JEMALLOC_VERSION_MINOR 3
#define JEMALLOC_VERSION_BUGFIX 0
#define JEMALLOC_VERSION_NREV 0
-#define JEMALLOC_VERSION_GID "87499f6748ebe4817571e817e9f680ccb5bf54a9"
+#define JEMALLOC_VERSION_GID "83789f45307379e096c4e8be81d9e9a51e3f5a4a"
#include "jemalloc_defs.h"
#include "jemalloc_FreeBSD.h"
diff --git a/contrib/jemalloc/include/jemalloc/jemalloc_defs.h b/contrib/jemalloc/include/jemalloc/jemalloc_defs.h
index 169078b..8e361d3 100644
--- a/contrib/jemalloc/include/jemalloc/jemalloc_defs.h
+++ b/contrib/jemalloc/include/jemalloc/jemalloc_defs.h
@@ -250,6 +250,11 @@
/* #undef JEMALLOC_PURGE_MADVISE_DONTNEED */
#define JEMALLOC_PURGE_MADVISE_FREE
+/*
+ * Define if operating system has alloca.h header.
+ */
+/* #undef JEMALLOC_HAS_ALLOCA_H */
+
/* sizeof(void *) == 2^LG_SIZEOF_PTR. */
#define LG_SIZEOF_PTR 3
diff --git a/contrib/jemalloc/src/arena.c b/contrib/jemalloc/src/arena.c
index 0c53b07..8d50f4d 100644
--- a/contrib/jemalloc/src/arena.c
+++ b/contrib/jemalloc/src/arena.c
@@ -359,13 +359,29 @@ arena_run_reg_dalloc(arena_run_t *run, void *ptr)
}
static inline void
-arena_chunk_validate_zeroed(arena_chunk_t *chunk, size_t run_ind)
+arena_run_zero(arena_chunk_t *chunk, size_t run_ind, size_t npages)
+{
+
+ VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind <<
+ LG_PAGE)), (npages << LG_PAGE));
+ memset((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), 0,
+ (npages << LG_PAGE));
+ VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind <<
+ LG_PAGE)), (npages << LG_PAGE));
+}
+
+static inline void
+arena_run_page_validate_zeroed(arena_chunk_t *chunk, size_t run_ind)
{
size_t i;
UNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE));
+ VALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind <<
+ LG_PAGE)), PAGE);
for (i = 0; i < PAGE / sizeof(size_t); i++)
assert(p[i] == 0);
+ VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind <<
+ LG_PAGE)), PAGE);
}
static void
@@ -441,19 +457,10 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
for (i = 0; i < need_pages; i++) {
if (arena_mapbits_unzeroed_get(chunk,
run_ind+i) != 0) {
- VALGRIND_MAKE_MEM_UNDEFINED(
- (void *)((uintptr_t)
- chunk + ((run_ind+i) <<
- LG_PAGE)), PAGE);
- memset((void *)((uintptr_t)
- chunk + ((run_ind+i) <<
- LG_PAGE)), 0, PAGE);
+ arena_run_zero(chunk, run_ind+i,
+ 1);
} else if (config_debug) {
- VALGRIND_MAKE_MEM_DEFINED(
- (void *)((uintptr_t)
- chunk + ((run_ind+i) <<
- LG_PAGE)), PAGE);
- arena_chunk_validate_zeroed(
+ arena_run_page_validate_zeroed(
chunk, run_ind+i);
}
}
@@ -462,11 +469,7 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
* The run is dirty, so all pages must be
* zeroed.
*/
- VALGRIND_MAKE_MEM_UNDEFINED((void
- *)((uintptr_t)chunk + (run_ind <<
- LG_PAGE)), (need_pages << LG_PAGE));
- memset((void *)((uintptr_t)chunk + (run_ind <<
- LG_PAGE)), 0, (need_pages << LG_PAGE));
+ arena_run_zero(chunk, run_ind, need_pages);
}
}
@@ -492,19 +495,21 @@ arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
*/
if (config_debug && flag_dirty == 0 &&
arena_mapbits_unzeroed_get(chunk, run_ind) == 0)
- arena_chunk_validate_zeroed(chunk, run_ind);
+ arena_run_page_validate_zeroed(chunk, run_ind);
for (i = 1; i < need_pages - 1; i++) {
arena_mapbits_small_set(chunk, run_ind+i, i, binind, 0);
if (config_debug && flag_dirty == 0 &&
- arena_mapbits_unzeroed_get(chunk, run_ind+i) == 0)
- arena_chunk_validate_zeroed(chunk, run_ind+i);
+ arena_mapbits_unzeroed_get(chunk, run_ind+i) == 0) {
+ arena_run_page_validate_zeroed(chunk,
+ run_ind+i);
+ }
}
arena_mapbits_small_set(chunk, run_ind+need_pages-1,
need_pages-1, binind, flag_dirty);
if (config_debug && flag_dirty == 0 &&
arena_mapbits_unzeroed_get(chunk, run_ind+need_pages-1) ==
0) {
- arena_chunk_validate_zeroed(chunk,
+ arena_run_page_validate_zeroed(chunk,
run_ind+need_pages-1);
}
}
@@ -1322,21 +1327,6 @@ arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
}
void
-arena_prof_accum(arena_t *arena, uint64_t accumbytes)
-{
-
- cassert(config_prof);
-
- if (config_prof && prof_interval != 0) {
- arena->prof_accumbytes += accumbytes;
- if (arena->prof_accumbytes >= prof_interval) {
- prof_idump();
- arena->prof_accumbytes -= prof_interval;
- }
- }
-}
-
-void
arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind,
uint64_t prof_accumbytes)
{
@@ -1347,11 +1337,8 @@ arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind,
assert(tbin->ncached == 0);
- if (config_prof) {
- malloc_mutex_lock(&arena->lock);
+ if (config_prof)
arena_prof_accum(arena, prof_accumbytes);
- malloc_mutex_unlock(&arena->lock);
- }
bin = &arena->bins[binind];
malloc_mutex_lock(&bin->lock);
for (i = 0, nfill = (tcache_bin_info[binind].ncached_max >>
@@ -1459,11 +1446,8 @@ arena_malloc_small(arena_t *arena, size_t size, bool zero)
bin->stats.nrequests++;
}
malloc_mutex_unlock(&bin->lock);
- if (config_prof && isthreaded == false) {
- malloc_mutex_lock(&arena->lock);
+ if (config_prof && isthreaded == false)
arena_prof_accum(arena, size);
- malloc_mutex_unlock(&arena->lock);
- }
if (zero == false) {
if (config_fill) {
@@ -1480,6 +1464,7 @@ arena_malloc_small(arena_t *arena, size_t size, bool zero)
}
VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
memset(ret, 0, size);
+ VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
}
return (ret);
@@ -1507,7 +1492,7 @@ arena_malloc_large(arena_t *arena, size_t size, bool zero)
arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++;
}
if (config_prof)
- arena_prof_accum(arena, size);
+ arena_prof_accum_locked(arena, size);
malloc_mutex_unlock(&arena->lock);
if (zero == false) {
diff --git a/contrib/jemalloc/src/chunk.c b/contrib/jemalloc/src/chunk.c
index 1a3bb4f6..46e387e 100644
--- a/contrib/jemalloc/src/chunk.c
+++ b/contrib/jemalloc/src/chunk.c
@@ -78,6 +78,9 @@ chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size,
assert(node->size >= leadsize + size);
trailsize = node->size - leadsize - size;
ret = (void *)((uintptr_t)node->addr + leadsize);
+ zeroed = node->zeroed;
+ if (zeroed)
+ *zero = true;
/* Remove node from the tree. */
extent_tree_szad_remove(chunks_szad, node);
extent_tree_ad_remove(chunks_ad, node);
@@ -114,17 +117,21 @@ chunk_recycle(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, size_t size,
}
malloc_mutex_unlock(&chunks_mtx);
- zeroed = false;
- if (node != NULL) {
- if (node->zeroed) {
- zeroed = true;
- *zero = true;
- }
+ if (node != NULL)
base_node_dealloc(node);
- }
- if (zeroed == false && *zero) {
- VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
- memset(ret, 0, size);
+ VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
+ if (*zero) {
+ if (zeroed == false)
+ memset(ret, 0, size);
+ else if (config_debug) {
+ size_t i;
+ size_t *p = (size_t *)(uintptr_t)ret;
+
+ VALGRIND_MAKE_MEM_DEFINED(ret, size);
+ for (i = 0; i < size / sizeof(size_t); i++)
+ assert(p[i] == 0);
+ VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
+ }
}
return (ret);
}
@@ -194,14 +201,6 @@ label_return:
if (config_prof && opt_prof && opt_prof_gdump && gdump)
prof_gdump();
}
- if (config_debug && *zero && ret != NULL) {
- size_t i;
- size_t *p = (size_t *)(uintptr_t)ret;
-
- VALGRIND_MAKE_MEM_DEFINED(ret, size);
- for (i = 0; i < size / sizeof(size_t); i++)
- assert(p[i] == 0);
- }
assert(CHUNK_ADDR2BASE(ret) == ret);
return (ret);
}
diff --git a/contrib/jemalloc/src/chunk_dss.c b/contrib/jemalloc/src/chunk_dss.c
index 24781cc..d1aea93 100644
--- a/contrib/jemalloc/src/chunk_dss.c
+++ b/contrib/jemalloc/src/chunk_dss.c
@@ -127,6 +127,7 @@ chunk_alloc_dss(size_t size, size_t alignment, bool *zero)
if (*zero) {
VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
memset(ret, 0, size);
+ VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
}
return (ret);
}
diff --git a/contrib/jemalloc/src/ckh.c b/contrib/jemalloc/src/ckh.c
index 742a950..2f38348 100644
--- a/contrib/jemalloc/src/ckh.c
+++ b/contrib/jemalloc/src/ckh.c
@@ -70,20 +70,20 @@ ckh_bucket_search(ckh_t *ckh, size_t bucket, const void *key)
JEMALLOC_INLINE size_t
ckh_isearch(ckh_t *ckh, const void *key)
{
- size_t hash1, hash2, bucket, cell;
+ size_t hashes[2], bucket, cell;
assert(ckh != NULL);
- ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2);
+ ckh->hash(key, hashes);
/* Search primary bucket. */
- bucket = hash1 & ((ZU(1) << ckh->lg_curbuckets) - 1);
+ bucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);
cell = ckh_bucket_search(ckh, bucket, key);
if (cell != SIZE_T_MAX)
return (cell);
/* Search secondary bucket. */
- bucket = hash2 & ((ZU(1) << ckh->lg_curbuckets) - 1);
+ bucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);
cell = ckh_bucket_search(ckh, bucket, key);
return (cell);
}
@@ -126,7 +126,7 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,
{
const void *key, *data, *tkey, *tdata;
ckhc_t *cell;
- size_t hash1, hash2, bucket, tbucket;
+ size_t hashes[2], bucket, tbucket;
unsigned i;
bucket = argbucket;
@@ -155,10 +155,11 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,
#endif
/* Find the alternate bucket for the evicted item. */
- ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2);
- tbucket = hash2 & ((ZU(1) << ckh->lg_curbuckets) - 1);
+ ckh->hash(key, hashes);
+ tbucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);
if (tbucket == bucket) {
- tbucket = hash1 & ((ZU(1) << ckh->lg_curbuckets) - 1);
+ tbucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets)
+ - 1);
/*
* It may be that (tbucket == bucket) still, if the
* item's hashes both indicate this bucket. However,
@@ -192,19 +193,19 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey,
JEMALLOC_INLINE bool
ckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata)
{
- size_t hash1, hash2, bucket;
+ size_t hashes[2], bucket;
const void *key = *argkey;
const void *data = *argdata;
- ckh->hash(key, ckh->lg_curbuckets, &hash1, &hash2);
+ ckh->hash(key, hashes);
/* Try to insert in primary bucket. */
- bucket = hash1 & ((ZU(1) << ckh->lg_curbuckets) - 1);
+ bucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1);
if (ckh_try_bucket_insert(ckh, bucket, key, data) == false)
return (false);
/* Try to insert in secondary bucket. */
- bucket = hash2 & ((ZU(1) << ckh->lg_curbuckets) - 1);
+ bucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1);
if (ckh_try_bucket_insert(ckh, bucket, key, data) == false)
return (false);
@@ -417,9 +418,8 @@ ckh_delete(ckh_t *ckh)
#endif
idalloc(ckh->tab);
-#ifdef JEMALLOC_DEBUG
- memset(ckh, 0x5a, sizeof(ckh_t));
-#endif
+ if (config_debug)
+ memset(ckh, 0x5a, sizeof(ckh_t));
}
size_t
@@ -526,31 +526,10 @@ ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data)
}
void
-ckh_string_hash(const void *key, unsigned minbits, size_t *hash1, size_t *hash2)
+ckh_string_hash(const void *key, size_t r_hash[2])
{
- size_t ret1, ret2;
- uint64_t h;
-
- assert(minbits <= 32 || (SIZEOF_PTR == 8 && minbits <= 64));
- assert(hash1 != NULL);
- assert(hash2 != NULL);
-
- h = hash(key, strlen((const char *)key), UINT64_C(0x94122f335b332aea));
- if (minbits <= 32) {
- /*
- * Avoid doing multiple hashes, since a single hash provides
- * enough bits.
- */
- ret1 = h & ZU(0xffffffffU);
- ret2 = h >> 32;
- } else {
- ret1 = h;
- ret2 = hash(key, strlen((const char *)key),
- UINT64_C(0x8432a476666bbc13));
- }
- *hash1 = ret1;
- *hash2 = ret2;
+ hash(key, strlen((const char *)key), 0x94122f33U, r_hash);
}
bool
@@ -564,41 +543,16 @@ ckh_string_keycomp(const void *k1, const void *k2)
}
void
-ckh_pointer_hash(const void *key, unsigned minbits, size_t *hash1,
- size_t *hash2)
+ckh_pointer_hash(const void *key, size_t r_hash[2])
{
- size_t ret1, ret2;
- uint64_t h;
union {
const void *v;
- uint64_t i;
+ size_t i;
} u;
- assert(minbits <= 32 || (SIZEOF_PTR == 8 && minbits <= 64));
- assert(hash1 != NULL);
- assert(hash2 != NULL);
-
assert(sizeof(u.v) == sizeof(u.i));
-#if (LG_SIZEOF_PTR != LG_SIZEOF_INT)
- u.i = 0;
-#endif
u.v = key;
- h = hash(&u.i, sizeof(u.i), UINT64_C(0xd983396e68886082));
- if (minbits <= 32) {
- /*
- * Avoid doing multiple hashes, since a single hash provides
- * enough bits.
- */
- ret1 = h & ZU(0xffffffffU);
- ret2 = h >> 32;
- } else {
- assert(SIZEOF_PTR == 8);
- ret1 = h;
- ret2 = hash(&u.i, sizeof(u.i), UINT64_C(0x5e2be9aff8709a5d));
- }
-
- *hash1 = ret1;
- *hash2 = ret2;
+ hash(&u.i, sizeof(u.i), 0xd983396eU, r_hash);
}
bool
diff --git a/contrib/jemalloc/src/ctl.c b/contrib/jemalloc/src/ctl.c
index 6e01b1e..f2ef4e6 100644
--- a/contrib/jemalloc/src/ctl.c
+++ b/contrib/jemalloc/src/ctl.c
@@ -960,11 +960,11 @@ ctl_postfork_child(void)
if (*oldlenp != sizeof(t)) { \
size_t copylen = (sizeof(t) <= *oldlenp) \
? sizeof(t) : *oldlenp; \
- memcpy(oldp, (void *)&v, copylen); \
+ memcpy(oldp, (void *)&(v), copylen); \
ret = EINVAL; \
goto label_return; \
} else \
- *(t *)oldp = v; \
+ *(t *)oldp = (v); \
} \
} while (0)
@@ -974,7 +974,7 @@ ctl_postfork_child(void)
ret = EINVAL; \
goto label_return; \
} \
- v = *(t *)newp; \
+ (v) = *(t *)newp; \
} \
} while (0)
@@ -995,7 +995,7 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
if (l) \
malloc_mutex_lock(&ctl_mtx); \
READONLY(); \
- oldval = v; \
+ oldval = (v); \
READ(oldval, t); \
\
ret = 0; \
@@ -1017,7 +1017,7 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
return (ENOENT); \
malloc_mutex_lock(&ctl_mtx); \
READONLY(); \
- oldval = v; \
+ oldval = (v); \
READ(oldval, t); \
\
ret = 0; \
@@ -1036,7 +1036,7 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
\
malloc_mutex_lock(&ctl_mtx); \
READONLY(); \
- oldval = v; \
+ oldval = (v); \
READ(oldval, t); \
\
ret = 0; \
@@ -1060,7 +1060,7 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
if ((c) == false) \
return (ENOENT); \
READONLY(); \
- oldval = v; \
+ oldval = (v); \
READ(oldval, t); \
\
ret = 0; \
@@ -1077,7 +1077,7 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
t oldval; \
\
READONLY(); \
- oldval = v; \
+ oldval = (v); \
READ(oldval, t); \
\
ret = 0; \
@@ -1492,6 +1492,7 @@ arenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
int ret;
+ unsigned narenas;
malloc_mutex_lock(&ctl_mtx);
READONLY();
@@ -1499,7 +1500,8 @@ arenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
ret = EAGAIN;
goto label_return;
}
- READ(ctl_stats.narenas - 1, unsigned);
+ narenas = ctl_stats.narenas - 1;
+ READ(narenas, unsigned);
ret = 0;
label_return:
diff --git a/contrib/jemalloc/src/jemalloc.c b/contrib/jemalloc/src/jemalloc.c
index aaf5012..665d98f 100644
--- a/contrib/jemalloc/src/jemalloc.c
+++ b/contrib/jemalloc/src/jemalloc.c
@@ -14,17 +14,20 @@ __sym_compat(_malloc_options, __malloc_options_1_0, FBSD_1.0);
/* Runtime configuration options. */
const char *je_malloc_conf;
+bool opt_abort =
#ifdef JEMALLOC_DEBUG
-bool opt_abort = true;
-# ifdef JEMALLOC_FILL
-bool opt_junk = true;
-# else
-bool opt_junk = false;
-# endif
+ true
+#else
+ false
+#endif
+ ;
+bool opt_junk =
+#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL))
+ true
#else
-bool opt_abort = false;
-bool opt_junk = false;
+ false
#endif
+ ;
size_t opt_quarantine = ZU(0);
bool opt_redzone = false;
bool opt_utrace = false;
@@ -87,11 +90,13 @@ typedef struct {
#ifdef JEMALLOC_UTRACE
# define UTRACE(a, b, c) do { \
if (opt_utrace) { \
+ int utrace_serrno = errno; \
malloc_utrace_t ut; \
ut.p = (a); \
ut.s = (b); \
ut.r = (c); \
utrace(&ut, sizeof(ut)); \
+ errno = utrace_serrno; \
} \
} while (0)
#else
@@ -281,7 +286,7 @@ arenas_cleanup(void *arg)
malloc_mutex_unlock(&arenas_lock);
}
-static inline bool
+static JEMALLOC_ATTR(always_inline) bool
malloc_init(void)
{
@@ -474,7 +479,7 @@ malloc_conf_init(void)
while (*opts != '\0' && malloc_conf_next(&opts, &k, &klen, &v,
&vlen) == false) {
-#define CONF_HANDLE_BOOL_HIT(o, n, hit) \
+#define CONF_HANDLE_BOOL(o, n) \
if (sizeof(n)-1 == klen && strncmp(n, k, \
klen) == 0) { \
if (strncmp("true", v, vlen) == 0 && \
@@ -488,16 +493,9 @@ malloc_conf_init(void)
"Invalid conf value", \
k, klen, v, vlen); \
} \
- hit = true; \
- } else \
- hit = false;
-#define CONF_HANDLE_BOOL(o, n) { \
- bool hit; \
- CONF_HANDLE_BOOL_HIT(o, n, hit); \
- if (hit) \
continue; \
-}
-#define CONF_HANDLE_SIZE_T(o, n, min, max) \
+ }
+#define CONF_HANDLE_SIZE_T(o, n, min, max, clip) \
if (sizeof(n)-1 == klen && strncmp(n, k, \
klen) == 0) { \
uintmax_t um; \
@@ -510,12 +508,22 @@ malloc_conf_init(void)
malloc_conf_error( \
"Invalid conf value", \
k, klen, v, vlen); \
- } else if (um < min || um > max) { \
- malloc_conf_error( \
- "Out-of-range conf value", \
- k, klen, v, vlen); \
- } else \
- o = um; \
+ } else if (clip) { \
+ if (um < min) \
+ o = min; \
+ else if (um > max) \
+ o = max; \
+ else \
+ o = um; \
+ } else { \
+ if (um < min || um > max) { \
+ malloc_conf_error( \
+ "Out-of-range " \
+ "conf value", \
+ k, klen, v, vlen); \
+ } else \
+ o = um; \
+ } \
continue; \
}
#define CONF_HANDLE_SSIZE_T(o, n, min, max) \
@@ -560,7 +568,8 @@ malloc_conf_init(void)
* config_fill.
*/
CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE +
- (config_fill ? 2 : 1), (sizeof(size_t) << 3) - 1)
+ (config_fill ? 2 : 1), (sizeof(size_t) << 3) - 1,
+ true)
if (strncmp("dss", k, klen) == 0) {
int i;
bool match = false;
@@ -586,14 +595,14 @@ malloc_conf_init(void)
continue;
}
CONF_HANDLE_SIZE_T(opt_narenas, "narenas", 1,
- SIZE_T_MAX)
+ SIZE_T_MAX, false)
CONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, "lg_dirty_mult",
-1, (sizeof(size_t) << 3) - 1)
CONF_HANDLE_BOOL(opt_stats_print, "stats_print")
if (config_fill) {
CONF_HANDLE_BOOL(opt_junk, "junk")
CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine",
- 0, SIZE_T_MAX)
+ 0, SIZE_T_MAX, false)
CONF_HANDLE_BOOL(opt_redzone, "redzone")
CONF_HANDLE_BOOL(opt_zero, "zero")
}
@@ -891,7 +900,7 @@ JEMALLOC_ATTR(nonnull(1))
* Avoid any uncertainty as to how many backtrace frames to ignore in
* PROF_ALLOC_PREP().
*/
-JEMALLOC_ATTR(noinline)
+JEMALLOC_NOINLINE
#endif
static int
imemalign(void **memptr, size_t alignment, size_t size,
@@ -1377,7 +1386,7 @@ je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
*/
#ifdef JEMALLOC_EXPERIMENTAL
-JEMALLOC_INLINE void *
+static JEMALLOC_ATTR(always_inline) void *
iallocm(size_t usize, size_t alignment, bool zero, bool try_tcache,
arena_t *arena)
{
diff --git a/contrib/jemalloc/src/prof.c b/contrib/jemalloc/src/prof.c
index 04964ef..b9f03a0 100644
--- a/contrib/jemalloc/src/prof.c
+++ b/contrib/jemalloc/src/prof.c
@@ -26,7 +26,7 @@ bool opt_prof_leak = false;
bool opt_prof_accum = false;
char opt_prof_prefix[PATH_MAX + 1];
-uint64_t prof_interval;
+uint64_t prof_interval = 0;
bool prof_promote;
/*
@@ -90,8 +90,7 @@ static bool prof_dump(bool propagate_err, const char *filename,
bool leakcheck);
static void prof_dump_filename(char *filename, char v, int64_t vseq);
static void prof_fdump(void);
-static void prof_bt_hash(const void *key, unsigned minbits, size_t *hash1,
- size_t *hash2);
+static void prof_bt_hash(const void *key, size_t r_hash[2]);
static bool prof_bt_keycomp(const void *k1, const void *k2);
static malloc_mutex_t *prof_ctx_mutex_choose(void);
@@ -1043,34 +1042,13 @@ prof_gdump(void)
}
static void
-prof_bt_hash(const void *key, unsigned minbits, size_t *hash1, size_t *hash2)
+prof_bt_hash(const void *key, size_t r_hash[2])
{
- size_t ret1, ret2;
- uint64_t h;
prof_bt_t *bt = (prof_bt_t *)key;
cassert(config_prof);
- assert(minbits <= 32 || (SIZEOF_PTR == 8 && minbits <= 64));
- assert(hash1 != NULL);
- assert(hash2 != NULL);
- h = hash(bt->vec, bt->len * sizeof(void *),
- UINT64_C(0x94122f335b332aea));
- if (minbits <= 32) {
- /*
- * Avoid doing multiple hashes, since a single hash provides
- * enough bits.
- */
- ret1 = h & ZU(0xffffffffU);
- ret2 = h >> 32;
- } else {
- ret1 = h;
- ret2 = hash(bt->vec, bt->len * sizeof(void *),
- UINT64_C(0x8432a476666bbc13));
- }
-
- *hash1 = ret1;
- *hash2 = ret2;
+ hash(bt->vec, bt->len * sizeof(void *), 0x94122f33U, r_hash);
}
static bool
@@ -1206,13 +1184,11 @@ prof_boot1(void)
*/
opt_prof = true;
opt_prof_gdump = false;
- prof_interval = 0;
} else if (opt_prof) {
if (opt_lg_prof_interval >= 0) {
prof_interval = (((uint64_t)1U) <<
opt_lg_prof_interval);
- } else
- prof_interval = 0;
+ }
}
prof_promote = (opt_prof && opt_lg_prof_sample > LG_PAGE);
diff --git a/contrib/jemalloc/src/tcache.c b/contrib/jemalloc/src/tcache.c
index 47e14f3..7befdc8 100644
--- a/contrib/jemalloc/src/tcache.c
+++ b/contrib/jemalloc/src/tcache.c
@@ -97,9 +97,7 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem,
arena_bin_t *bin = &arena->bins[binind];
if (config_prof && arena == tcache->arena) {
- malloc_mutex_lock(&arena->lock);
arena_prof_accum(arena, tcache->prof_accumbytes);
- malloc_mutex_unlock(&arena->lock);
tcache->prof_accumbytes = 0;
}
@@ -180,7 +178,7 @@ tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem,
malloc_mutex_lock(&arena->lock);
if ((config_prof || config_stats) && arena == tcache->arena) {
if (config_prof) {
- arena_prof_accum(arena,
+ arena_prof_accum_locked(arena,
tcache->prof_accumbytes);
tcache->prof_accumbytes = 0;
}
@@ -343,11 +341,8 @@ tcache_destroy(tcache_t *tcache)
}
}
- if (config_prof && tcache->prof_accumbytes > 0) {
- malloc_mutex_lock(&tcache->arena->lock);
+ if (config_prof && tcache->prof_accumbytes > 0)
arena_prof_accum(tcache->arena, tcache->prof_accumbytes);
- malloc_mutex_unlock(&tcache->arena->lock);
- }
tcache_size = arena_salloc(tcache, false);
if (tcache_size <= SMALL_MAXCLASS) {
diff --git a/contrib/libarchive/libarchive/archive_getdate.c b/contrib/libarchive/libarchive/archive_getdate.c
index f8b5a28..aaa9d6f 100644
--- a/contrib/libarchive/libarchive/archive_getdate.c
+++ b/contrib/libarchive/libarchive/archive_getdate.c
@@ -369,8 +369,8 @@ relunitphrase(struct gdstate *gds)
&& gds->tokenp[1].token == tSEC_UNIT) {
/* "1 day" */
gds->HaveRel++;
- gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value;
- gds->tokenp += 3;
+ gds->RelSeconds += gds->tokenp[0].value * gds->tokenp[1].value;
+ gds->tokenp += 2;
return 1;
}
if (gds->tokenp[0].token == '-'
@@ -403,7 +403,7 @@ relunitphrase(struct gdstate *gds)
/* "now", "tomorrow" */
gds->HaveRel++;
gds->RelSeconds += gds->tokenp[0].value;
- ++gds->tokenp;
+ gds->tokenp += 1;
return 1;
}
if (gds->tokenp[0].token == tMONTH_UNIT) {
@@ -1022,10 +1022,11 @@ int
main(int argc, char **argv)
{
time_t d;
+ time_t now = time(NULL);
while (*++argv != NULL) {
(void)printf("Input: %s\n", *argv);
- d = get_date(*argv);
+ d = get_date(now, *argv);
if (d == -1)
(void)printf("Bad format - couldn't convert.\n");
else
diff --git a/contrib/libarchive/libarchive/test/test_archive_getdate.c b/contrib/libarchive/libarchive/test/test_archive_getdate.c
index 4be359b..c56c39e 100644
--- a/contrib/libarchive/libarchive/test/test_archive_getdate.c
+++ b/contrib/libarchive/libarchive/test/test_archive_getdate.c
@@ -43,6 +43,8 @@ DEFINE_TEST(test_archive_getdate)
assertEqualInt(get_date(now, "2004/01/29 513 mest"), 1075345980);
assertEqualInt(get_date(now, "99/02/17 7pm utc"), 919278000);
assertEqualInt(get_date(now, "02/17/99 7:11am est"), 919253460);
+ assertEqualInt(get_date(now, "now - 2 hours"),
+ get_date(now, "2 hours ago"));
/* It's important that we handle ctime() format. */
assertEqualInt(get_date(now, "Sun Feb 22 17:38:26 PST 2009"),
1235353106);
@@ -77,5 +79,6 @@ DEFINE_TEST(test_archive_getdate)
/* "last tuesday" is one week before "tuesday" */
assertEqualInt(get_date(now, "last tuesday UTC"),
now - 6 * 24 * 60 * 60);
+
/* TODO: Lots more tests here. */
}
diff --git a/contrib/libcxxrt/atomic.h b/contrib/libcxxrt/atomic.h
new file mode 100644
index 0000000..53aa26f
--- /dev/null
+++ b/contrib/libcxxrt/atomic.h
@@ -0,0 +1,29 @@
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+/**
+ * Swap macro that enforces a happens-before relationship with a corresponding
+ * ATOMIC_LOAD.
+ */
+#if __has_feature(cxx_atomic)
+#define ATOMIC_SWAP(addr, val)\
+ __c11_atomic_exchange((_Atomic(__typeof__(val))*)addr, val, __ATOMIC_ACQ_REL)
+#elif __has_builtin(__sync_swap)
+#define ATOMIC_SWAP(addr, val)\
+ __sync_swap(addr, val)
+#else
+#define ATOMIC_SWAP(addr, val)\
+ __sync_lock_test_and_set(addr, val)
+#endif
+
+#if __has_feature(cxx_atomic)
+#define ATOMIC_LOAD(addr)\
+ __c11_atomic_load((_Atomic(__typeof__(*addr))*)addr, __ATOMIC_ACQUIRE)
+#else
+#define ATOMIC_LOAD(addr)\
+ (__sync_synchronize(), *addr)
+#endif
diff --git a/contrib/libcxxrt/exception.cc b/contrib/libcxxrt/exception.cc
index fe56297..4ccf38e 100644
--- a/contrib/libcxxrt/exception.cc
+++ b/contrib/libcxxrt/exception.cc
@@ -32,6 +32,7 @@
#include <pthread.h>
#include "typeinfo.h"
#include "dwarf_eh.h"
+#include "atomic.h"
#include "cxxabi.h"
#pragma weak pthread_key_create
@@ -155,6 +156,17 @@ struct __cxa_thread_info
*/
_Unwind_Exception *currentCleanup;
/**
+ * Our state with respect to foreign exceptions. Usually none, set to
+ * caught if we have just caught an exception and rethrown if we are
+ * rethrowing it.
+ */
+ enum
+ {
+ none,
+ caught,
+ rethrown
+ } foreign_exception_state;
+ /**
* The public part of this structure, accessible from outside of this
* module.
*/
@@ -308,7 +320,16 @@ static void thread_cleanup(void* thread_info)
__cxa_thread_info *info = (__cxa_thread_info*)thread_info;
if (info->globals.caughtExceptions)
{
- free_exception_list(info->globals.caughtExceptions);
+ // If this is a foreign exception, ask it to clean itself up.
+ if (info->foreign_exception_state != __cxa_thread_info::none)
+ {
+ _Unwind_Exception *e = (_Unwind_Exception*)info->globals.caughtExceptions;
+ e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e);
+ }
+ else
+ {
+ free_exception_list(info->globals.caughtExceptions);
+ }
}
free(thread_info);
}
@@ -780,7 +801,8 @@ extern "C" void __cxa_decrement_exception_refcount(void* thrown_exception)
*/
extern "C" void __cxa_rethrow()
{
- __cxa_eh_globals *globals = __cxa_get_globals();
+ __cxa_thread_info *ti = thread_info();
+ __cxa_eh_globals *globals = &ti->globals;
// Note: We don't remove this from the caught list here, because
// __cxa_end_catch will be called when we unwind out of the try block. We
// could probably make this faster by providing an alternative rethrow
@@ -795,6 +817,15 @@ extern "C" void __cxa_rethrow()
std::terminate();
}
+ if (ti->foreign_exception_state != __cxa_thread_info::none)
+ {
+ ti->foreign_exception_state = __cxa_thread_info::rethrown;
+ _Unwind_Exception *e = (_Unwind_Exception*)ex;
+ _Unwind_Reason_Code err = _Unwind_Resume_or_Rethrow(e);
+ report_failure(err, ex);
+ return;
+ }
+
assert(ex->handlerCount > 0 && "Rethrowing uncaught exception!");
// ex->handlerCount will be decremented in __cxa_end_catch in enclosing
@@ -848,9 +879,9 @@ static bool check_type_signature(__cxa_exception *ex,
void *&adjustedPtr)
{
void *exception_ptr = (void*)(ex+1);
- const std::type_info *ex_type = ex->exceptionType;
+ const std::type_info *ex_type = ex ? ex->exceptionType : 0;
- bool is_ptr = ex_type->__is_pointer_p();
+ bool is_ptr = ex ? ex_type->__is_pointer_p() : false;
if (is_ptr)
{
exception_ptr = *(void**)exception_ptr;
@@ -911,8 +942,8 @@ static handler_type check_action_record(_Unwind_Context *context,
action_record = displacement ?
action_record_offset_base + displacement : 0;
// We only check handler types for C++ exceptions - foreign exceptions
- // are only allowed for cleanup.
- if (filter > 0 && 0 != ex)
+ // are only allowed for cleanups and catchalls.
+ if (filter > 0)
{
std::type_info *handler_type = get_type_info_entry(context, lsda, filter);
if (check_type_signature(ex, handler_type, adjustedPtr))
@@ -1133,8 +1164,10 @@ extern "C" void *__cxa_begin_catch(void *e) throw()
extern "C" void *__cxa_begin_catch(void *e)
#endif
{
- // Decrement the uncaught exceptions count
- __cxa_eh_globals *globals = __cxa_get_globals();
+ // We can't call the fast version here, because if the first exception that
+ // we see is a foreign exception then we won't have called it yet.
+ __cxa_thread_info *ti = thread_info();
+ __cxa_eh_globals *globals = &ti->globals;
globals->uncaughtExceptions--;
_Unwind_Exception *exceptionObject = (_Unwind_Exception*)e;
@@ -1177,9 +1210,22 @@ extern "C" void *__cxa_begin_catch(void *e)
{
ex->handlerCount++;
}
+ ti->foreign_exception_state = __cxa_thread_info::none;
return ex->adjustedPtr;
}
+ else
+ {
+ // If this is a foreign exception, then we need to be able to
+ // store it. We can't chain foreign exceptions, so we give up
+ // if there are already some outstanding ones.
+ if (globals->caughtExceptions != 0)
+ {
+ std::terminate();
+ }
+ globals->caughtExceptions = (__cxa_exception*)exceptionObject;
+ ti->foreign_exception_state = __cxa_thread_info::caught;
+ }
// exceptionObject is the pointer to the _Unwind_Exception within the
// __cxa_exception. The throw object is after this
return ((char*)exceptionObject + sizeof(_Unwind_Exception));
@@ -1195,10 +1241,23 @@ extern "C" void __cxa_end_catch()
{
// We can call the fast version here because the slow version is called in
// __cxa_throw(), which must have been called before we end a catch block
- __cxa_eh_globals *globals = __cxa_get_globals_fast();
+ __cxa_thread_info *ti = thread_info_fast();
+ __cxa_eh_globals *globals = &ti->globals;
__cxa_exception *ex = globals->caughtExceptions;
assert(0 != ex && "Ending catch when no exception is on the stack!");
+
+ if (ti->foreign_exception_state != __cxa_thread_info::none)
+ {
+ globals->caughtExceptions = 0;
+ if (ti->foreign_exception_state != __cxa_thread_info::rethrown)
+ {
+ _Unwind_Exception *e = (_Unwind_Exception*)ti->globals.caughtExceptions;
+ e->exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, e);
+ }
+ ti->foreign_exception_state = __cxa_thread_info::none;
+ return;
+ }
bool deleteException = true;
@@ -1328,7 +1387,7 @@ namespace std
{
if (thread_local_handlers) { return pathscale::set_unexpected(f); }
- return __sync_lock_test_and_set(&unexpectedHandler, f);
+ return ATOMIC_SWAP(&terminateHandler, f);
}
/**
* Sets the function that is called to terminate the program.
@@ -1336,7 +1395,8 @@ namespace std
terminate_handler set_terminate(terminate_handler f) throw()
{
if (thread_local_handlers) { return pathscale::set_terminate(f); }
- return __sync_lock_test_and_set(&terminateHandler, f);
+
+ return ATOMIC_SWAP(&terminateHandler, f);
}
/**
* Terminates the program, calling a custom terminate implementation if
@@ -1390,7 +1450,7 @@ namespace std
{
return info->unexpectedHandler;
}
- return unexpectedHandler;
+ return ATOMIC_LOAD(&unexpectedHandler);
}
/**
* Returns the current terminate handler.
@@ -1402,7 +1462,7 @@ namespace std
{
return info->terminateHandler;
}
- return terminateHandler;
+ return ATOMIC_LOAD(&terminateHandler);
}
}
#ifdef __arm__
diff --git a/contrib/libcxxrt/memory.cc b/contrib/libcxxrt/memory.cc
index bd7fd22..cc879e0 100644
--- a/contrib/libcxxrt/memory.cc
+++ b/contrib/libcxxrt/memory.cc
@@ -36,14 +36,8 @@
#include <stddef.h>
#include <stdlib.h>
#include "stdexcept.h"
+#include "atomic.h"
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#if !__has_builtin(__sync_swap)
-#define __sync_swap __sync_lock_test_and_set
-#endif
namespace std
{
@@ -67,7 +61,12 @@ namespace std
__attribute__((weak))
new_handler set_new_handler(new_handler handler)
{
- return __sync_swap(&new_handl, handler);
+ return ATOMIC_SWAP(&new_handl, handler);
+ }
+ __attribute__((weak))
+ new_handler get_new_handler(void)
+ {
+ return ATOMIC_LOAD(&new_handl);
}
}
@@ -75,12 +74,17 @@ namespace std
__attribute__((weak))
void* operator new(size_t size)
{
+ if (0 == size)
+ {
+ size = 1;
+ }
void * mem = malloc(size);
while (0 == mem)
{
- if (0 != new_handl)
+ new_handler h = std::get_new_handler();
+ if (0 != h)
{
- new_handl();
+ h();
}
else
{
@@ -95,14 +99,19 @@ void* operator new(size_t size)
__attribute__((weak))
void* operator new(size_t size, const std::nothrow_t &) throw()
{
+ if (0 == size)
+ {
+ size = 1;
+ }
void *mem = malloc(size);
while (0 == mem)
{
- if (0 != new_handl)
+ new_handler h = std::get_new_handler();
+ if (0 != h)
{
try
{
- new_handl();
+ h();
}
catch (...)
{
diff --git a/contrib/libcxxrt/typeinfo.h b/contrib/libcxxrt/typeinfo.h
index 8223977..a8a1a98 100644
--- a/contrib/libcxxrt/typeinfo.h
+++ b/contrib/libcxxrt/typeinfo.h
@@ -70,6 +70,14 @@ namespace std
*/
public:
/**
+ * Returns true if this is some pointer type, false otherwise.
+ */
+ virtual bool __is_pointer_p() const { return false; }
+ /**
+ * Returns true if this is some function type, false otherwise.
+ */
+ virtual bool __is_function_p() const { return false; }
+ /**
* Catch function. Allows external libraries to implement
* their own basic types. This is used, for example, in the
* GNUstep Objective-C runtime to allow Objective-C types to be
@@ -95,14 +103,6 @@ namespace std
{
return false;
}
- /**
- * Returns true if this is some pointer type, false otherwise.
- */
- virtual bool __is_pointer_p() const { return false; }
- /**
- * Returns true if this is some function type, false otherwise.
- */
- virtual bool __is_function_p() const { return false; }
};
}
@@ -284,7 +284,6 @@ namespace ABI_NAMESPACE
/** Pointer is a pointer to a member of an incomplete class. */
__incomplete_class_mask = 0x10
};
- virtual bool __is_pointer_p() const { return true; }
virtual bool __do_catch(const type_info *thrown_type,
void **thrown_object,
unsigned outer) const;
@@ -296,6 +295,7 @@ namespace ABI_NAMESPACE
struct __pointer_type_info : public __pbase_type_info
{
virtual ~__pointer_type_info();
+ virtual bool __is_pointer_p() const { return true; }
};
/**
diff --git a/contrib/libpcap/configure.in b/contrib/libpcap/configure.in
index 8432d2a..8432d2a 100755..100644
--- a/contrib/libpcap/configure.in
+++ b/contrib/libpcap/configure.in
diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h b/contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
index bc2af63..bc2af63 100755..100644
--- a/contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
+++ b/contrib/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index b7a8476..d12b5d6 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -60,6 +60,8 @@ def warn_fe_cc_log_diagnostics_failure : Warning<
"unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">;
def err_fe_no_pch_in_dir : Error<
"no suitable precompiled header file found in directory '%0'">;
+def err_fe_action_not_available : Error<
+ "action %0 not compiled in">;
def warn_fe_serialized_diag_failure : Warning<
"unable to open file %0 for serializing diagnostics (%1)">,
diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index c7c55b0..60a264a 100644
--- a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -31,6 +31,7 @@ using namespace clang;
static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
using namespace clang::frontend;
+ StringRef Action("unknown");
switch (CI.getFrontendOpts().ProgramAction) {
case ASTDeclList: return new ASTDeclListAction();
@@ -42,12 +43,20 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
case DumpTokens: return new DumpTokensAction();
case EmitAssembly: return new EmitAssemblyAction();
case EmitBC: return new EmitBCAction();
+#ifdef CLANG_ENABLE_REWRITER
case EmitHTML: return new HTMLPrintAction();
+#else
+ case EmitHTML: Action = "EmitHTML"; break;
+#endif
case EmitLLVM: return new EmitLLVMAction();
case EmitLLVMOnly: return new EmitLLVMOnlyAction();
case EmitCodeGenOnly: return new EmitCodeGenOnlyAction();
case EmitObj: return new EmitObjAction();
+#ifdef CLANG_ENABLE_REWRITER
case FixIt: return new FixItAction();
+#else
+ case FixIt: Action = "FixIt"; break;
+#endif
case GenerateModule: return new GenerateModuleAction;
case GeneratePCH: return new GeneratePCHAction;
case GeneratePTH: return new GeneratePTHAction();
@@ -74,19 +83,46 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
case PrintDeclContext: return new DeclContextPrintAction();
case PrintPreamble: return new PrintPreambleAction();
case PrintPreprocessedInput: {
- if (CI.getPreprocessorOutputOpts().RewriteIncludes)
+ if (CI.getPreprocessorOutputOpts().RewriteIncludes) {
+#ifdef CLANG_ENABLE_REWRITER
return new RewriteIncludesAction();
+#else
+ Action = "RewriteIncludesAction";
+ break;
+#endif
+ }
return new PrintPreprocessedAction();
}
+#ifdef CLANG_ENABLE_REWRITER
case RewriteMacros: return new RewriteMacrosAction();
case RewriteObjC: return new RewriteObjCAction();
case RewriteTest: return new RewriteTestAction();
- case RunAnalysis: return new ento::AnalysisAction();
+#else
+ case RewriteMacros: Action = "RewriteMacros"; break;
+ case RewriteObjC: Action = "RewriteObjC"; break;
+ case RewriteTest: Action = "RewriteTest"; break;
+#endif
+#ifdef CLANG_ENABLE_ARCMT
case MigrateSource: return new arcmt::MigrateSourceAction();
+#else
+ case MigrateSource: Action = "MigrateSource"; break;
+#endif
+#ifdef CLANG_ENABLE_STATIC_ANALYZER
+ case RunAnalysis: return new ento::AnalysisAction();
+#else
+ case RunAnalysis: Action = "RunAnalysis"; break;
+#endif
case RunPreprocessorOnly: return new PreprocessOnlyAction();
}
+
+#if !defined(CLANG_ENABLE_ARCMT) || !defined(CLANG_ENABLE_STATIC_ANALYZER) \
+ || !defined(CLANG_ENABLE_REWRITER)
+ CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action;
+ return 0;
+#else
llvm_unreachable("Invalid program action!");
+#endif
}
static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
@@ -97,10 +133,13 @@ static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
const FrontendOptions &FEOpts = CI.getFrontendOpts();
+#ifdef CLANG_ENABLE_REWRITER
if (FEOpts.FixAndRecompile) {
Act = new FixItRecompile(Act);
}
+#endif
+#ifdef CLANG_ENABLE_ARCMT
// Potentially wrap the base FE action in an ARC Migrate Tool action.
switch (FEOpts.ARCMTAction) {
case FrontendOptions::ARCMT_None:
@@ -124,6 +163,7 @@ static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
FEOpts.ObjCMTAction & ~FrontendOptions::ObjCMT_Literals,
FEOpts.ObjCMTAction & ~FrontendOptions::ObjCMT_Subscripting);
}
+#endif
// If there are any AST files to merge, create a frontend action
// adaptor to perform the merge.
@@ -176,12 +216,14 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args);
}
+#ifdef CLANG_ENABLE_STATIC_ANALYZER
// Honor -analyzer-checker-help.
// This should happen AFTER plugins have been loaded!
if (Clang->getAnalyzerOpts()->ShowCheckerHelp) {
ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins);
return 0;
}
+#endif
// If there were errors in processing arguments, don't do anything else.
bool Success = false;
diff --git a/contrib/ntp/html/drivers/driver44.html b/contrib/ntp/html/drivers/driver44.html
index d2cddb9..d2cddb9 100755..100644
--- a/contrib/ntp/html/drivers/driver44.html
+++ b/contrib/ntp/html/drivers/driver44.html
diff --git a/contrib/ntp/include/icom.h b/contrib/ntp/include/icom.h
index aac62c8..aac62c8 100755..100644
--- a/contrib/ntp/include/icom.h
+++ b/contrib/ntp/include/icom.h
diff --git a/contrib/ntp/readme.y2kfixes b/contrib/ntp/readme.y2kfixes
index e9a63c1..e9a63c1 100755..100644
--- a/contrib/ntp/readme.y2kfixes
+++ b/contrib/ntp/readme.y2kfixes
Binary files differ
diff --git a/contrib/ntp/scripts/stats/clock.awk b/contrib/ntp/scripts/stats/clock.awk
index ef62da9..ef62da9 100755..100644
--- a/contrib/ntp/scripts/stats/clock.awk
+++ b/contrib/ntp/scripts/stats/clock.awk
diff --git a/contrib/ntp/scripts/stats/dupe.awk b/contrib/ntp/scripts/stats/dupe.awk
index 317c2a4..317c2a4 100755..100644
--- a/contrib/ntp/scripts/stats/dupe.awk
+++ b/contrib/ntp/scripts/stats/dupe.awk
diff --git a/contrib/ntp/scripts/stats/ensemble.S b/contrib/ntp/scripts/stats/ensemble.S
index 32a4dba..32a4dba 100755..100644
--- a/contrib/ntp/scripts/stats/ensemble.S
+++ b/contrib/ntp/scripts/stats/ensemble.S
diff --git a/contrib/ntp/scripts/stats/ensemble.awk b/contrib/ntp/scripts/stats/ensemble.awk
index 136b33d..136b33d 100755..100644
--- a/contrib/ntp/scripts/stats/ensemble.awk
+++ b/contrib/ntp/scripts/stats/ensemble.awk
diff --git a/contrib/ntp/scripts/stats/etf.S b/contrib/ntp/scripts/stats/etf.S
index 9b9c68b..9b9c68b 100755..100644
--- a/contrib/ntp/scripts/stats/etf.S
+++ b/contrib/ntp/scripts/stats/etf.S
diff --git a/contrib/ntp/scripts/stats/etf.awk b/contrib/ntp/scripts/stats/etf.awk
index 8e6e334..8e6e334 100755..100644
--- a/contrib/ntp/scripts/stats/etf.awk
+++ b/contrib/ntp/scripts/stats/etf.awk
diff --git a/contrib/ntp/scripts/stats/itf.S b/contrib/ntp/scripts/stats/itf.S
index 56c8c8d..56c8c8d 100755..100644
--- a/contrib/ntp/scripts/stats/itf.S
+++ b/contrib/ntp/scripts/stats/itf.S
diff --git a/contrib/ntp/scripts/stats/itf.awk b/contrib/ntp/scripts/stats/itf.awk
index 2b21c5b..2b21c5b 100755..100644
--- a/contrib/ntp/scripts/stats/itf.awk
+++ b/contrib/ntp/scripts/stats/itf.awk
diff --git a/contrib/ntp/scripts/stats/loop.S b/contrib/ntp/scripts/stats/loop.S
index 8e564b6..8e564b6 100755..100644
--- a/contrib/ntp/scripts/stats/loop.S
+++ b/contrib/ntp/scripts/stats/loop.S
diff --git a/contrib/ntp/scripts/stats/loop.awk b/contrib/ntp/scripts/stats/loop.awk
index bac90db..bac90db 100755..100644
--- a/contrib/ntp/scripts/stats/loop.awk
+++ b/contrib/ntp/scripts/stats/loop.awk
diff --git a/contrib/ntp/scripts/stats/loop_summary b/contrib/ntp/scripts/stats/loop_summary
index 35479ec..35479ec 100755..100644
--- a/contrib/ntp/scripts/stats/loop_summary
+++ b/contrib/ntp/scripts/stats/loop_summary
diff --git a/contrib/ntp/scripts/stats/peer.awk b/contrib/ntp/scripts/stats/peer.awk
index 5fe260e..5fe260e 100755..100644
--- a/contrib/ntp/scripts/stats/peer.awk
+++ b/contrib/ntp/scripts/stats/peer.awk
diff --git a/contrib/ntp/scripts/stats/psummary.awk b/contrib/ntp/scripts/stats/psummary.awk
index ec06b0c..ec06b0c 100755..100644
--- a/contrib/ntp/scripts/stats/psummary.awk
+++ b/contrib/ntp/scripts/stats/psummary.awk
diff --git a/contrib/ntp/scripts/stats/tdata.S b/contrib/ntp/scripts/stats/tdata.S
index f360a24..f360a24 100755..100644
--- a/contrib/ntp/scripts/stats/tdata.S
+++ b/contrib/ntp/scripts/stats/tdata.S
diff --git a/contrib/ntp/scripts/stats/tdata.awk b/contrib/ntp/scripts/stats/tdata.awk
index 5be9c04..5be9c04 100755..100644
--- a/contrib/ntp/scripts/stats/tdata.awk
+++ b/contrib/ntp/scripts/stats/tdata.awk
diff --git a/contrib/tcpdump/bgp.h b/contrib/tcpdump/bgp.h
index 5081596..5081596 100755..100644
--- a/contrib/tcpdump/bgp.h
+++ b/contrib/tcpdump/bgp.h
diff --git a/contrib/tcpdump/configure.in b/contrib/tcpdump/configure.in
index 8864238..8864238 100755..100644
--- a/contrib/tcpdump/configure.in
+++ b/contrib/tcpdump/configure.in
diff --git a/contrib/tcpdump/ipproto.c b/contrib/tcpdump/ipproto.c
index e5d328c..e5d328c 100755..100644
--- a/contrib/tcpdump/ipproto.c
+++ b/contrib/tcpdump/ipproto.c
diff --git a/contrib/tcpdump/l2vpn.c b/contrib/tcpdump/l2vpn.c
index 021e7f0..021e7f0 100755..100644
--- a/contrib/tcpdump/l2vpn.c
+++ b/contrib/tcpdump/l2vpn.c
diff --git a/contrib/tcpdump/l2vpn.h b/contrib/tcpdump/l2vpn.h
index 871eca0..871eca0 100755..100644
--- a/contrib/tcpdump/l2vpn.h
+++ b/contrib/tcpdump/l2vpn.h
diff --git a/contrib/tcpdump/nlpid.c b/contrib/tcpdump/nlpid.c
index 64a359b..64a359b 100755..100644
--- a/contrib/tcpdump/nlpid.c
+++ b/contrib/tcpdump/nlpid.c
diff --git a/contrib/tcpdump/print-syslog.c b/contrib/tcpdump/print-syslog.c
index 3685d62..3685d62 100755..100644
--- a/contrib/tcpdump/print-syslog.c
+++ b/contrib/tcpdump/print-syslog.c
diff --git a/crypto/heimdal/doc/vars.texi b/crypto/heimdal/doc/vars.texi
index cf0f58b..cf0f58b 100755..100644
--- a/crypto/heimdal/doc/vars.texi
+++ b/crypto/heimdal/doc/vars.texi
diff --git a/crypto/openssl/crypto/bn/asm/s390x.S b/crypto/openssl/crypto/bn/asm/s390x.S
index 43fcb79..43fcb79 100755..100644
--- a/crypto/openssl/crypto/bn/asm/s390x.S
+++ b/crypto/openssl/crypto/bn/asm/s390x.S
diff --git a/crypto/openssl/crypto/bn/bn_const.c b/crypto/openssl/crypto/bn/bn_const.c
index eb60a25..eb60a25 100755..100644
--- a/crypto/openssl/crypto/bn/bn_const.c
+++ b/crypto/openssl/crypto/bn/bn_const.c
diff --git a/crypto/openssl/crypto/ocsp/ocsp_cl.c b/crypto/openssl/crypto/ocsp/ocsp_cl.c
index 9c14d9d..9c14d9d 100755..100644
--- a/crypto/openssl/crypto/ocsp/ocsp_cl.c
+++ b/crypto/openssl/crypto/ocsp/ocsp_cl.c
diff --git a/crypto/openssl/crypto/ocsp/ocsp_ext.c b/crypto/openssl/crypto/ocsp/ocsp_ext.c
index ec884cb..ec884cb 100755..100644
--- a/crypto/openssl/crypto/ocsp/ocsp_ext.c
+++ b/crypto/openssl/crypto/ocsp/ocsp_ext.c
diff --git a/crypto/openssl/crypto/ocsp/ocsp_lib.c b/crypto/openssl/crypto/ocsp/ocsp_lib.c
index a94dc83..a94dc83 100755..100644
--- a/crypto/openssl/crypto/ocsp/ocsp_lib.c
+++ b/crypto/openssl/crypto/ocsp/ocsp_lib.c
diff --git a/crypto/openssl/crypto/ocsp/ocsp_srv.c b/crypto/openssl/crypto/ocsp/ocsp_srv.c
index 1c606dd..1c606dd 100755..100644
--- a/crypto/openssl/crypto/ocsp/ocsp_srv.c
+++ b/crypto/openssl/crypto/ocsp/ocsp_srv.c
diff --git a/crypto/openssl/crypto/rand/rand_lcl.h b/crypto/openssl/crypto/rand/rand_lcl.h
index 618a8ec..618a8ec 100755..100644
--- a/crypto/openssl/crypto/rand/rand_lcl.h
+++ b/crypto/openssl/crypto/rand/rand_lcl.h
diff --git a/crypto/openssl/crypto/vms_rms.h b/crypto/openssl/crypto/vms_rms.h
index 00a00d9..00a00d9 100755..100644
--- a/crypto/openssl/crypto/vms_rms.h
+++ b/crypto/openssl/crypto/vms_rms.h
diff --git a/crypto/openssl/util/libeay.num b/crypto/openssl/util/libeay.num
index 93f80ba..93f80ba 100755..100644
--- a/crypto/openssl/util/libeay.num
+++ b/crypto/openssl/util/libeay.num
diff --git a/crypto/openssl/util/ssleay.num b/crypto/openssl/util/ssleay.num
index 37655bc..37655bc 100755..100644
--- a/crypto/openssl/util/ssleay.num
+++ b/crypto/openssl/util/ssleay.num
diff --git a/etc/Makefile b/etc/Makefile
index c18908f..81ef45a 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -156,6 +156,9 @@ ETCMAIL=Makefile README mailer.conf access.sample virtusertable.sample \
# Special top level files for FreeBSD
FREEBSD=COPYRIGHT
+# Sanitize DESTDIR
+DESTDIR:= ${DESTDIR:C://*:/:g}
+
afterinstall:
.if ${MK_MAN} != "no"
${_+_}cd ${.CURDIR}/../share/man; ${MAKE} makedb
@@ -177,6 +180,10 @@ CAP_MKDB_ENDIAN?=
PWD_MKDB_ENDIAN?=
.endif
+.if defined(NO_ROOT)
+METALOG.add?= cat -l >> ${METALOG}
+.endif
+
distribution:
.if !defined(DESTDIR)
@echo "set DESTDIR before running \"make ${.TARGET}\""
@@ -198,6 +205,14 @@ distribution:
.endif
pwd_mkdb ${PWD_MKDB_ENDIAN} -i -p -d ${DESTDIR}/etc \
${DESTDIR}/etc/master.passwd
+.if defined(NO_ROOT)
+ ( \
+ echo "./etc/login.conf.db type=file mode=0644 uname=root gname=wheel"; \
+ echo "./etc/passwd type=file mode=0644 uname=root gname=wheel"; \
+ echo "./etc/pwd.db type=file mode=0644 uname=root gname=wheel"; \
+ echo "./etc/spwd.db type=file mode=0600 uname=root gname=wheel"; \
+ ) | ${METALOG.add}
+.endif
.if ${MK_ATF} != "no"
${_+_}cd ${.CURDIR}/atf; ${MAKE} install
.endif
@@ -291,52 +306,77 @@ distribution:
${DESTDIR}/etc/nsswitch.conf
.endif
-distrib-dirs:
- mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.root.dist -p ${DESTDIR}/
- mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.var.dist -p ${DESTDIR}/var
- mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.usr.dist -p ${DESTDIR}/usr
- mtree -eU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.include.dist \
- -p ${DESTDIR}/usr/include
+MTREE_CMD?= mtree
+
+MTREES= mtree/BSD.root.dist / \
+ mtree/BSD.var.dist /var \
+ mtree/BSD.usr.dist /usr \
+ mtree/BSD.include.dist /usr/include
.if ${MK_BIND_LIBS} != "no"
- mtree -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BIND.include.dist \
- -p ${DESTDIR}/usr/include
+MTREES+= mtree/BIND.include.dist /usr/include
.endif
.if ${MK_BIND_MTREE} != "no"
- mtree -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BIND.chroot.dist \
- -p ${DESTDIR}/var/named
+MTREES+= mtree/BIND.chroot.dist /var/named
.endif
.if ${MK_GROFF} != "no"
- mtree -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.groff.dist -p ${DESTDIR}/usr
+MTREES+= mtree/BSD.groff.dist /usr
.endif
.if ${MK_SENDMAIL} != "no"
- mtree -deU ${MTREE_FOLLOWS_SYMLINKS} -f ${.CURDIR}/mtree/BSD.sendmail.dist -p ${DESTDIR}/
+MTREES+= mtree/BSD.sendmail.dist /
.endif
- cd ${DESTDIR}/; rm -f ${DESTDIR}/sys; ln -s usr/src/sys sys
- cd ${DESTDIR}/usr/share/man/en.ISO8859-1; ln -sf ../man* .
- cd ${DESTDIR}/usr/share/man/en.UTF-8; ln -sf ../man* .
+.for mtree in ${LOCAL_MTREE}
+MTREES+= ../${mtree} /
+.endfor
+
+distrib-dirs:
+ @set ${MTREES}; \
+ while test $$# -ge 2; do \
+ m=${.CURDIR}/$$1; \
+ shift; \
+ d=${DESTDIR}$$1; \
+ shift; \
+ ${ECHO} ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} \
+ -f $$m -p $$d; \
+ ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} -f $$m -p $$d; \
+ done; true
+.if defined(NO_ROOT)
+ @set ${MTREES}; \
+ while test $$# -ge 2; do \
+ m=${.CURDIR}/$$1; \
+ shift; \
+ d=$$1; \
+ test "$$d" == "/" && d=""; \
+ d=${DISTBASE}$$d; \
+ shift; \
+ ${ECHO} "${MTREE_CMD:N-W} -C -f $$m -K uname,gname | " \
+ "sed s#^\.#.$$d# | ${METALOG.add}" ; \
+ ${MTREE_CMD:N-W} -C -f $$m -K uname,gname | sed s#^\.#.$$d# | \
+ ${METALOG.add} ; \
+ done; true
+.endif
+ ${INSTALL_SYMLINK} usr/src/sys ${DESTDIR}/sys
cd ${DESTDIR}/usr/share/man; \
- set - `grep "^[a-zA-Z]" ${.CURDIR}/man.alias`; \
- while [ $$# -gt 0 ] ; \
- do \
- rm -rf "$$1"; \
- ln -s "$$2" "$$1"; \
- shift; shift; \
+ for mandir in man*; do \
+ ${INSTALL_SYMLINK} ../$$mandir \
+ ${DESTDIR}/usr/share/man/en.ISO8859-1/; \
+ ${INSTALL_SYMLINK} ../$$mandir \
+ ${DESTDIR}/usr/share/man/en.UTF-8/; \
done
cd ${DESTDIR}/usr/share/openssl/man; \
+ for mandir in man*; do \
+ ${INSTALL_SYMLINK} ../$$mandir \
+ ${DESTDIR}/usr/share/openssl/man/en.ISO8859-1/; \
+ done
set - `grep "^[a-zA-Z]" ${.CURDIR}/man.alias`; \
- while [ $$# -gt 0 ] ; \
- do \
- rm -rf "$$1"; \
- ln -s "$$2" "$$1"; \
+ while [ $$# -gt 0 ] ; do \
+ ${INSTALL_SYMLINK} "$$2" "${DESTDIR}/usr/share/man/$$1"; \
+ ${INSTALL_SYMLINK} "$$2" \
+ "${DESTDIR}/usr/share/openssl/man/$$1"; \
shift; shift; \
done
- cd ${DESTDIR}/usr/share/openssl/man/en.ISO8859-1; ln -sf ../man* .
- cd ${DESTDIR}/usr/share/nls; \
set - `grep "^[a-zA-Z]" ${.CURDIR}/nls.alias`; \
- while [ $$# -gt 0 ] ; \
- do \
- rm -rf "$$1"; \
- ln -s "$$2" "$$1"; \
+ while [ $$# -gt 0 ] ; do \
+ ${INSTALL_SYMLINK} "$$2" "${DESTDIR}/usr/share/nls/$$1"; \
shift; shift; \
done
diff --git a/etc/login.conf b/etc/login.conf
index 92826c4..67509f9 100644
--- a/etc/login.conf
+++ b/etc/login.conf
@@ -59,7 +59,7 @@ xuser:\
staff:\
:tc=default:
daemon:\
- :memorylocked=64M:\
+ :memorylocked=128M:\
:tc=default:
news:\
:tc=default:
diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist
index 336d055..89ec940 100644
--- a/etc/mtree/BSD.usr.dist
+++ b/etc/mtree/BSD.usr.dist
@@ -756,8 +756,6 @@
/set uname=man
cat1
..
- cat1aout
- ..
cat2
..
cat3
@@ -795,8 +793,6 @@
en.ISO8859-1 uname=root
cat1
..
- cat1aout
- ..
cat2
..
cat3
@@ -835,8 +831,6 @@
en.UTF-8 uname=root
cat1
..
- cat1aout
- ..
cat2
..
cat3
@@ -913,8 +907,6 @@
..
man1
..
- man1aout
- ..
man2
..
man3
diff --git a/etc/rc.d/ip6addrctl b/etc/rc.d/ip6addrctl
index 801d7bb..914ca8c 100755
--- a/etc/rc.d/ip6addrctl
+++ b/etc/rc.d/ip6addrctl
@@ -29,11 +29,15 @@ ip6addrctl_prefer_ipv6()
afexists inet6 || return 0
ip6addrctl flush >/dev/null 2>&1
- ip6addrctl add ::1/128 50 0
- ip6addrctl add ::/0 40 1
- ip6addrctl add 2002::/16 30 2
- ip6addrctl add ::/96 20 3
- ip6addrctl add ::ffff:0:0/96 10 4
+ ip6addrctl add ::1/128 50 0
+ ip6addrctl add ::/0 40 1
+ ip6addrctl add ::ffff:0:0/96 35 4
+ ip6addrctl add 2002::/16 30 2
+ ip6addrctl add 2001::/32 5 5
+ ip6addrctl add fc00::/7 3 13
+ ip6addrctl add ::/96 1 3
+ ip6addrctl add fec0::/10 1 11
+ ip6addrctl add 3ffe::/16 1 12
checkyesno ip6addrctl_verbose && ip6addrctl
}
@@ -42,11 +46,15 @@ ip6addrctl_prefer_ipv4()
afexists inet6 || return 0
ip6addrctl flush >/dev/null 2>&1
- ip6addrctl add ::ffff:0:0/96 50 0
- ip6addrctl add ::1/128 40 1
- ip6addrctl add ::/0 30 2
- ip6addrctl add 2002::/16 20 3
- ip6addrctl add ::/96 10 4
+ ip6addrctl add ::1/128 50 0
+ ip6addrctl add ::/0 40 1
+ ip6addrctl add ::ffff:0:0/96 100 4
+ ip6addrctl add 2002::/16 30 2
+ ip6addrctl add 2001::/32 5 5
+ ip6addrctl add fc00::/7 3 13
+ ip6addrctl add ::/96 1 3
+ ip6addrctl add fec0::/10 1 11
+ ip6addrctl add 3ffe::/16 1 12
checkyesno ip6addrctl_verbose && ip6addrctl
}
diff --git a/etc/rc.d/jail b/etc/rc.d/jail
index ff2f312..f19983f 100755
--- a/etc/rc.d/jail
+++ b/etc/rc.d/jail
@@ -509,7 +509,7 @@ jail_handle_ips_option()
esac
case "${_type}" in
inet) ;;
- inet6) ;;
+ inet6) ipv6_address_count=$((ipv6_address_count + 1)) ;;
*) warn "Could not determine address family. Not going" \
"to ${_action} address '${_addr}' for ${_jail}."
continue
@@ -546,6 +546,7 @@ jail_ips()
esac
# Handle addresses.
+ ipv6_address_count=0
jail_handle_ips_option ${_action} "${_ip}"
# Handle jail_xxx_ip_multi<N>
alias=0
@@ -558,6 +559,12 @@ jail_ips()
;;
esac
done
+ case ${ipv6_address_count} in
+ 0) ;;
+ *) # Sleep 1 second to let DAD complete before starting services.
+ sleep 1
+ ;;
+ esac
}
jail_prestart()
diff --git a/etc/rc.subr b/etc/rc.subr
index 053f89a..9bff68b 100644
--- a/etc/rc.subr
+++ b/etc/rc.subr
@@ -290,7 +290,7 @@ _find_processes()
_interpbn=${1##*/}
_fp_args='_argv'
_fp_match='case "$_argv" in
- ${_interp}|"${_interp} "*|"${_interpbn}: ${_procname}"*)'
+ ${_interp}|"${_interp} "*|"[${_interpbn}]"|"${_interpbn}: ${_procname}"*)'
else # a normal daemon
_procnamebn=${_procname##*/}
_fp_args='_arg0 _argv'
diff --git a/gnu/lib/csu/Makefile b/gnu/lib/csu/Makefile
index a65be66..1efe865 100644
--- a/gnu/lib/csu/Makefile
+++ b/gnu/lib/csu/Makefile
@@ -24,6 +24,10 @@ CFLAGS+= -I${GCCLIB}/include -I${GCCDIR}/config -I${GCCDIR} -I. \
CRTS_CFLAGS= -DCRTSTUFFS_O -DSHARED ${PICFLAG}
MKDEP= -DCRT_BEGIN
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+CFLAGS+= -DTARGET_ARM_EABI
+.endif
+
.if ${MACHINE_CPUARCH} == "ia64"
BEGINSRC= crtbegin.asm
ENDSRC= crtend.asm
diff --git a/gnu/lib/libgcc/Makefile b/gnu/lib/libgcc/Makefile
index c07ae87..73d9213 100644
--- a/gnu/lib/libgcc/Makefile
+++ b/gnu/lib/libgcc/Makefile
@@ -15,6 +15,10 @@ MK_SSP= no
.include "${.CURDIR}/../../usr.bin/cc/Makefile.tgt"
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+CFLAGS+= -DTARGET_ARM_EABI
+.endif
+
.if ${TARGET_CPUARCH} == "mips"
LIB= gcc
.endif
@@ -55,10 +59,13 @@ LIB2FUNCS+= _fixuns${mode}si
.endfor
# Likewise double-word routines.
+.if ${TARGET_CPUARCH} != "arm" || ${MK_ARM_EABI} == "no"
+# These are implemented in an ARM specific file but will not be filtered out
.for mode in sf df xf tf
LIB2FUNCS+= _fix${mode}di _fixuns${mode}di
LIB2FUNCS+= _floatdi${mode} _floatundi${mode}
.endfor
+.endif
LIB2ADD = $(LIB2FUNCS_EXTRA)
LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
@@ -115,15 +122,14 @@ CFLAGS+= -fheinous-gnu-extensions
LIB1ASMSRC = lib1funcs.asm
LIB1ASMFUNCS = _dvmd_tls _bb_init_func
-LIB2FUNCS_EXTRA = floatunsidf.c floatunsisf.c
+.if ${MK_ARM_EABI} != "no"
+LIB1ASMFUNCS+= _addsubdf3 _addsubsf3 _cmpdf2 _cmpsf2 _fixdfsi _fixsfsi \
+ _fixunsdfsi _fixunsdfsi _muldivdf3 _muldivsf3 _udivsi3
-# Not now
-#LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func
-#LIB1ASMFUNCS+= _call_via_rX _interwork_call_via_rX \
-# _lshrdi3 _ashrdi3 _ashldi3 \
-# _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
-# _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
-# _fixsfsi _fixunssfsi _floatdidf _floatdisf
+LIB2ADDEH = unwind-arm.c libunwind.S pr-support.c unwind-c.c
+.else
+LIB2FUNCS_EXTRA = floatunsidf.c floatunsisf.c
+.endif
.endif
.if ${TARGET_CPUARCH} == mips
@@ -329,6 +335,9 @@ CLEANFILES += cs-*.h option*
SHLIB_MKMAP = ${GCCDIR}/mkmap-symver.awk
SHLIB_MKMAP_OPTS =
SHLIB_MAPFILES = ${GCCDIR}/libgcc-std.ver
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+SHLIB_MAPFILES += ${GCCDIR}/config/arm/libgcc-bpabi.ver
+.endif
VERSION_MAP = libgcc.map
libgcc.map: ${SHLIB_MKMAP} ${SHLIB_MAPFILES} ${SOBJS} ${OBJS:R:S/$/.So/}
diff --git a/gnu/lib/libgcov/Makefile b/gnu/lib/libgcov/Makefile
index 680cdbf..dbefca2 100644
--- a/gnu/lib/libgcov/Makefile
+++ b/gnu/lib/libgcov/Makefile
@@ -15,6 +15,11 @@ CFLAGS+= -DIN_GCC -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED
CFLAGS+= -D_PTHREADS -DGTHREAD_USE_WEAK
CFLAGS+= -I${.CURDIR}/../../usr.bin/cc/cc_tools \
-I${GCCLIB}/include -I${GCCDIR}/config -I${GCCDIR} -I.
+
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+CFLAGS+= -DTARGET_ARM_EABI
+.endif
+
#
# Library members defined in libgcov.c.
# Defined in libgcov.c, included only in gcov library
diff --git a/gnu/lib/libstdc++/Makefile b/gnu/lib/libstdc++/Makefile
index 1005b5d..da88e70 100644
--- a/gnu/lib/libstdc++/Makefile
+++ b/gnu/lib/libstdc++/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
GCCVER= 4.2
GCCDIR= ${.CURDIR}/../../../contrib/gcc
GCCLIB= ${.CURDIR}/../../../contrib/gcclibs
@@ -14,7 +16,7 @@ LIB= stdc++
SHLIB_MAJOR= 6
CFLAGS+= -DIN_GLIBCPP_V3 -DHAVE_CONFIG_H
-.if ${MACHINE_CPUARCH} == "arm"
+.if ${MACHINE_CPUARCH} == "arm" && ${MK_ARM_EABI} == "no"
CFLAGS+= -D_GLIBCXX_SJLJ_EXCEPTIONS=1
.endif
CFLAGS+= -I${.CURDIR} -I${SUPDIR} -I${GCCDIR} -I${SRCDIR}/include
@@ -594,7 +596,13 @@ gthr-default.h: ${GCCDIR}/gthr-posix.h
CLEANFILES+= ${THRHDRS}
+.if ${MACHINE_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+unwind.h: ${GCCDIR}/config/arm/unwind-arm.h
+.else
unwind.h: ${GCCDIR}/unwind-generic.h
+.endif
+
+unwind.h:
ln -sf ${.ALLSRC} ${.TARGET}
SRCS+= unwind.h
diff --git a/gnu/lib/libsupc++/Version.map b/gnu/lib/libsupc++/Version.map
index ec6303e..dbcf495 100644
--- a/gnu/lib/libsupc++/Version.map
+++ b/gnu/lib/libsupc++/Version.map
@@ -142,8 +142,37 @@ GLIBCXX_3.4 {
_ZdaPvRKSt9nothrow_t;
_ZdlPv;
_ZdlPvRKSt9nothrow_t;
+ extern "C++" {
+ std::set_new_handler*;
+ std::set_terminate*;
+ std::set_unexpected*;
+
+ std::bad_alloc;
+ std::bad_cast;
+ std::exception*;
+
+ "typeinfo for std::bad_alloc";
+ "typeinfo for std::bad_cast";
+ "typeinfo for std::exception";
+
+ "typeinfo name for std::bad_alloc";
+ "typeinfo name for std::bad_cast";
+ "typeinfo name for std::exception";
+
+ "vtable for std::bad_alloc";
+ "vtable for std::bad_cast";
+ "vtable for std::exception";
+ };
};
+GLIBCXX_3.4.9 {
+ extern "C++" {
+ "std::bad_alloc::what() const";
+ "std::bad_cast::what() const";
+ "std::bad_typeid::what() const";
+ };
+} GLIBCXX_3.4;
+
CXXABI_1.3.1 {
__cxa_get_exception_ptr;
diff --git a/gnu/usr.bin/Makefile b/gnu/usr.bin/Makefile
index 3a61327..386c957 100644
--- a/gnu/usr.bin/Makefile
+++ b/gnu/usr.bin/Makefile
@@ -30,7 +30,7 @@ _groff= groff
_cvs= cvs
.endif
-.if ${MK_FDT} != "no"
+.if ${MK_GPL_DTC} != "no"
_dtc= dtc
.endif
diff --git a/gnu/usr.bin/cc/Makefile.inc b/gnu/usr.bin/cc/Makefile.inc
index 7a5991e..0302617 100644
--- a/gnu/usr.bin/cc/Makefile.inc
+++ b/gnu/usr.bin/cc/Makefile.inc
@@ -26,6 +26,10 @@ CSTD?= gnu89
CFLAGS+= -DCROSS_COMPILE
.endif
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+CFLAGS+= -DTARGET_ARM_EABI
+.endif
+
.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
CFLAGS += -DTARGET_ENDIAN_DEFAULT=MASK_BIG_END
.endif
diff --git a/gnu/usr.bin/cc/c++/Makefile b/gnu/usr.bin/cc/c++/Makefile
index f434b34..98e1ea3 100644
--- a/gnu/usr.bin/cc/c++/Makefile
+++ b/gnu/usr.bin/cc/c++/Makefile
@@ -1,5 +1,6 @@
# $FreeBSD$
+NO_MAN=
.include <bsd.own.mk>
.include "../Makefile.inc"
@@ -9,13 +10,13 @@
PROG= g++
SRCS+= g++spec.c
+
+DPADD= ${LIBCPP} ${LIBIBERTY}
+LDADD= ${LIBCPP} ${LIBIBERTY}
+
.if ${MK_CLANG_IS_CC} == "no"
LINKS= ${BINDIR}/g++ ${BINDIR}/c++
LINKS+= ${BINDIR}/g++ ${BINDIR}/CC
.endif
-NO_MAN=
-
-DPADD= ${LIBCPP} ${LIBIBERTY}
-LDADD= ${LIBCPP} ${LIBIBERTY}
.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/c++filt/Makefile b/gnu/usr.bin/cc/c++filt/Makefile
index 03ad7c2..5379795 100644
--- a/gnu/usr.bin/cc/c++filt/Makefile
+++ b/gnu/usr.bin/cc/c++filt/Makefile
@@ -1,5 +1,8 @@
# $FreeBSD$
+NO_MAN=
+.include <bsd.own.mk>
+
.include "../Makefile.inc"
.include "../Makefile.fe"
@@ -7,7 +10,6 @@
PROG= c++filt
SRCS= cp-demangle.c
-NO_MAN=
CFLAGS+= -DSTANDALONE_DEMANGLER -DVERSION=\"$(GCC_VERSION)\"
diff --git a/gnu/usr.bin/cc/cc1/Makefile b/gnu/usr.bin/cc/cc1/Makefile
index 7b1e343..3c0d8fa 100644
--- a/gnu/usr.bin/cc/cc1/Makefile
+++ b/gnu/usr.bin/cc/cc1/Makefile
@@ -1,9 +1,10 @@
# $FreeBSD$
-.include "../Makefile.inc"
NO_MAN=
.include <bsd.own.mk>
+.include "../Makefile.inc"
+
.PATH: ${GCCDIR}
PROG= cc1
diff --git a/gnu/usr.bin/cc/cc1plus/Makefile b/gnu/usr.bin/cc/cc1plus/Makefile
index dd3d524..83b0abb 100644
--- a/gnu/usr.bin/cc/cc1plus/Makefile
+++ b/gnu/usr.bin/cc/cc1plus/Makefile
@@ -1,9 +1,10 @@
# $FreeBSD$
-.include "../Makefile.inc"
NO_MAN=
.include <bsd.own.mk>
+.include "../Makefile.inc"
+
.PATH: ${GCCDIR}/cp ${GCCDIR}
PROG= cc1plus
diff --git a/gnu/usr.bin/cc/cc_int/Makefile b/gnu/usr.bin/cc/cc_int/Makefile
index e6051e1..86c1791 100644
--- a/gnu/usr.bin/cc/cc_int/Makefile
+++ b/gnu/usr.bin/cc/cc_int/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
.include "../Makefile.inc"
.include "../Makefile.ver"
diff --git a/gnu/usr.bin/cc/cc_tools/Makefile b/gnu/usr.bin/cc/cc_tools/Makefile
index c697dd3..8f75f43 100644
--- a/gnu/usr.bin/cc/cc_tools/Makefile
+++ b/gnu/usr.bin/cc/cc_tools/Makefile
@@ -51,6 +51,9 @@ TARGET_INC+= ${GCC_CPU}/elf.h
.endif
.if ${TARGET_CPUARCH} == "arm"
TARGET_INC+= ${GCC_CPU}/aout.h
+.if ${MK_ARM_EABI} != "no"
+TARGET_INC+= ${GCC_CPU}/bpabi.h
+.endif
.endif
.if ${TARGET_ARCH} == "powerpc64"
TARGET_INC+= ${GCC_CPU}/biarch64.h
@@ -349,7 +352,13 @@ gthr-default.h: ${GCCDIR}/gthr-posix.h
GENSRCS+= gthr-default.h
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+unwind.h: ${GCCDIR}/config/arm/unwind-arm.h
+.else
unwind.h: ${GCCDIR}/unwind-generic.h
+.endif
+
+unwind.h:
ln -sf ${.ALLSRC} ${.TARGET}
GENSRCS+= unwind.h
diff --git a/gnu/usr.bin/cc/doc/Makefile b/gnu/usr.bin/cc/doc/Makefile
index 840b694..a56231b 100644
--- a/gnu/usr.bin/cc/doc/Makefile
+++ b/gnu/usr.bin/cc/doc/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
.include "../Makefile.inc"
.include "../Makefile.ver"
diff --git a/gnu/usr.bin/cc/gcov/Makefile b/gnu/usr.bin/cc/gcov/Makefile
index f48d177..9a87c02 100644
--- a/gnu/usr.bin/cc/gcov/Makefile
+++ b/gnu/usr.bin/cc/gcov/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
.include "../Makefile.inc"
.include "../Makefile.ver"
diff --git a/gnu/usr.bin/cc/include/Makefile b/gnu/usr.bin/cc/include/Makefile
index 1698262..357bac0 100644
--- a/gnu/usr.bin/cc/include/Makefile
+++ b/gnu/usr.bin/cc/include/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
.include "../Makefile.inc"
INCSDIR=${INCLUDEDIR}/gcc/${GCCVER}
diff --git a/gnu/usr.bin/cc/libcpp/Makefile b/gnu/usr.bin/cc/libcpp/Makefile
index 23bc26e..bfaea7d 100644
--- a/gnu/usr.bin/cc/libcpp/Makefile
+++ b/gnu/usr.bin/cc/libcpp/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
# Use our headers in preference to ones from ../cc_tools.
CFLAGS+= -I${.CURDIR} -I.
diff --git a/gnu/usr.bin/cc/libdecnumber/Makefile b/gnu/usr.bin/cc/libdecnumber/Makefile
index 82df5a9..2987c1c 100644
--- a/gnu/usr.bin/cc/libdecnumber/Makefile
+++ b/gnu/usr.bin/cc/libdecnumber/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
# Use our headers in preference to ones from ../cc_tools.
CFLAGS+= -I${.CURDIR} -I.
diff --git a/gnu/usr.bin/cc/libiberty/Makefile b/gnu/usr.bin/cc/libiberty/Makefile
index 7446793..adaa128 100644
--- a/gnu/usr.bin/cc/libiberty/Makefile
+++ b/gnu/usr.bin/cc/libiberty/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
#
# Make sure we will pick up our config.h file first, not the one from
# cc_tools.
diff --git a/gnu/usr.bin/gdb/kgdb/main.c b/gnu/usr.bin/gdb/kgdb/main.c
index 9293f36..45a3dc0 100644
--- a/gnu/usr.bin/gdb/kgdb/main.c
+++ b/gnu/usr.bin/gdb/kgdb/main.c
@@ -333,11 +333,24 @@ main(int argc, char *argv[])
args.argv = malloc(sizeof(char *));
args.argv[0] = argv[0];
- while ((ch = getopt(argc, argv, "ac:d:fn:qr:vw")) != -1) {
+ while ((ch = getopt(argc, argv, "ab:c:d:fn:qr:vw")) != -1) {
switch (ch) {
case 'a':
annotation_level++;
break;
+ case 'b':
+ {
+ int i;
+ char *p;
+
+ i = strtol (optarg, &p, 0);
+ if (i == 0 && p == optarg)
+ warnx("warning: could not set baud rate to `%s'.\n",
+ optarg);
+ else
+ baud_rate = i;
+ }
+ break;
case 'c': /* use given core file. */
if (vmcore != NULL) {
warnx("option %c: can only be specified once",
diff --git a/gnu/usr.bin/grep/grep.c b/gnu/usr.bin/grep/grep.c
index 1684a82..0cab4a1 100644
--- a/gnu/usr.bin/grep/grep.c
+++ b/gnu/usr.bin/grep/grep.c
@@ -304,7 +304,7 @@ reset (int fd, char const *file, struct stats *stats)
if (directories == SKIP_DIRECTORIES && S_ISDIR (stats->stat.st_mode))
return 0;
#ifndef DJGPP
- if (devices == SKIP_DEVICES && (S_ISCHR(stats->stat.st_mode) || S_ISBLK(stats->stat.st_mode) || S_ISSOCK(stats->stat.st_mode)))
+ if (devices == SKIP_DEVICES && (S_ISCHR(stats->stat.st_mode) || S_ISBLK(stats->stat.st_mode) || S_ISSOCK(stats->stat.st_mode) || S_ISFIFO(stats->stat.st_mode)))
#else
if (devices == SKIP_DEVICES && (S_ISCHR(stats->stat.st_mode) || S_ISBLK(stats->stat.st_mode)))
#endif
@@ -942,6 +942,7 @@ grepfile (char const *file, struct stats *stats)
int desc;
int count;
int status;
+ int flags;
if (! file)
{
@@ -950,7 +951,7 @@ grepfile (char const *file, struct stats *stats)
}
else
{
- while ((desc = open (file, O_RDONLY)) < 0 && errno == EINTR)
+ while ((desc = open (file, O_RDONLY | O_NONBLOCK)) < 0 && errno == EINTR)
continue;
if (desc < 0)
@@ -990,6 +991,9 @@ grepfile (char const *file, struct stats *stats)
return 1;
}
+ flags = fcntl(desc, F_GETFL);
+ flags &= ~O_NONBLOCK;
+ fcntl(desc, F_SETFL, flags);
filename = file;
}
diff --git a/gnu/usr.bin/patch/Makefile b/gnu/usr.bin/patch/Makefile
index 373efbb..76d28e8 100644
--- a/gnu/usr.bin/patch/Makefile
+++ b/gnu/usr.bin/patch/Makefile
@@ -1,6 +1,17 @@
# $FreeBSD$
-PROG= patch
+.include <bsd.own.mk>
+
+.if ${MK_BSD_PATCH} == "yes"
+PROG= gnupatch
+CLEANFILES+= gnupatch.1
+
+gnupatch.1: patch.1
+ cp ${.ALLSRC} ${.TARGET}
+.else
+PROG= patch
+.endif
+
SRCS= backupfile.c inp.c patch.c pch.c util.c version.c
CFLAGS+=-DHAVE_CONFIG_H
diff --git a/include/arpa/Makefile b/include/arpa/Makefile
index a480b31..8a7f63d 100644
--- a/include/arpa/Makefile
+++ b/include/arpa/Makefile
@@ -1,7 +1,12 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
NO_OBJ=
-INCS= ftp.h inet.h nameser.h nameser_compat.h telnet.h tftp.h
+INCS= ftp.h inet.h nameser.h nameser_compat.h tftp.h
+.if ${MK_TELNET} == "no"
+INCS+= telnet.h
+.endif
INCSDIR=${INCLUDEDIR}/arpa
.include <bsd.prog.mk>
diff --git a/include/stdio.h b/include/stdio.h
index 2fd9125..4fc78b8 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -343,6 +343,7 @@ char *tempnam(const char *, const char *);
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809
+FILE *fmemopen(void * __restrict, size_t, const char * __restrict);
ssize_t getdelim(char ** __restrict, size_t * __restrict, int,
FILE * __restrict);
int renameat(int, const char *, int, const char *);
diff --git a/include/time.h b/include/time.h
index 6c9e7a9..14d6044 100644
--- a/include/time.h
+++ b/include/time.h
@@ -112,6 +112,7 @@ typedef __pid_t pid_t;
#define CLOCK_MONOTONIC_FAST 12 /* FreeBSD-specific. */
#define CLOCK_SECOND 13 /* FreeBSD-specific. */
#define CLOCK_THREAD_CPUTIME_ID 14
+#define CLOCK_PROCESS_CPUTIME_ID 15
#endif /* !defined(CLOCK_REALTIME) && __POSIX_VISIBLE >= 200112 */
#if !defined(TIMER_ABSTIME) && __POSIX_VISIBLE >= 200112
diff --git a/kerberos5/lib/libkrb5/Makefile b/kerberos5/lib/libkrb5/Makefile
index fbd9930..4736857 100644
--- a/kerberos5/lib/libkrb5/Makefile
+++ b/kerberos5/lib/libkrb5/Makefile
@@ -82,8 +82,7 @@ MAN= krb5.3 \
krb5_timeofday.3 \
krb5_v4compat.3 \
krb5_verify_init_creds.3 \
- krb5_verify_user.3 \
- verify_krb5_conf.8
+ krb5_verify_user.3
MAN+= krb5.conf.5
MAN+= kerberos.8
@@ -107,7 +106,6 @@ MLINKS= krb5.3 krb5_add_et_list.3 \
krb5.3 krb5_data_realloc.3 \
krb5.3 krb5_data_zero.3 \
krb5.3 krb5_free_config_files.3 \
- krb5.3 krb5_free_context.3 \
krb5.3 krb5_free_cred_contents.3 \
krb5.3 krb5_free_creds.3 \
krb5.3 krb5_free_data.3 \
@@ -123,7 +121,6 @@ MLINKS= krb5.3 krb5_add_et_list.3 \
krb5.3 krb5_get_use_admin_kdc.3 \
krb5.3 krb5_init_ets.3 \
krb5.3 krb5_kerberos_enctypes.3 \
- krb5.3 krb5_krbhst_get_addrinfo.3 \
krb5.3 krb5_prepend_config_files_default.3 \
krb5.3 krb5_set_config_files.3 \
krb5.3 krb5_set_default_in_tkt_etypes.3 \
@@ -195,7 +192,6 @@ MLINKS= krb5.3 krb5_add_et_list.3 \
krb5_auth_context.3 krb5_auth_getcksumtype.3 \
krb5_auth_context.3 krb5_auth_getkeytype.3 \
krb5_auth_context.3 krb5_auth_getlocalseqnumber.3 \
- krb5_auth_context.3 krb5_auth_getremoteseqnumber.3 \
krb5_auth_context.3 krb5_auth_setcksumtype.3 \
krb5_auth_context.3 krb5_auth_setkeytype.3 \
krb5_auth_context.3 krb5_auth_setlocalseqnumber.3 \
@@ -383,11 +379,8 @@ MLINKS= krb5.3 krb5_add_et_list.3 \
krb5_principal.3 krb5_free_principal.3 \
krb5_principal.3 krb5_get_default_principal.3 \
krb5_principal.3 krb5_make_principal.3 \
- krb5_principal.3 krb5_parse_name.3 \
krb5_principal.3 krb5_parse_name_flags.3 \
krb5_principal.3 krb5_parse_nametype.3 \
- krb5_principal.3 krb5_princ_realm.3 \
- krb5_principal.3 krb5_princ_set_realm.3 \
krb5_principal.3 krb5_principal_compare.3 \
krb5_principal.3 krb5_principal_compare_any_realm.3 \
krb5_principal.3 krb5_principal_get_comp_string.3 \
@@ -486,7 +479,6 @@ MLINKS= krb5.3 krb5_add_et_list.3 \
krb5_support.3 krb5_config_vget_time_default.3 \
krb5_support.3 krb5_expand_hostname.3 \
krb5_support.3 krb5_expand_hostname_realms.3 \
- krb5_support.3 krb5_free_host_realm.3 \
krb5_support.3 krb5_kuserok.3 \
krb5_support.3 krb5_plugin_register.3 \
krb5_ticket.3 krb5_ticket_get_flags.3 \
diff --git a/lib/Makefile b/lib/Makefile
index 3dd274e..132302e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -115,6 +115,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_libusbhid} \
${_libusb} \
${_libvgl} \
+ ${_libvmmapi} \
libwrap \
liby \
libz \
@@ -198,6 +199,10 @@ _libproc= libproc
_librtld_db= librtld_db
.endif
+.if ${MACHINE_CPUARCH} == "amd64"
+_libvmmapi= libvmmapi
+.endif
+
.if ${MACHINE_CPUARCH} == "ia64"
_libefi= libefi
.endif
diff --git a/lib/clang/Makefile b/lib/clang/Makefile
index cfc1554..a77d241 100644
--- a/lib/clang/Makefile
+++ b/lib/clang/Makefile
@@ -3,8 +3,20 @@
.include <bsd.own.mk>
.if !make(install)
+.if !defined(EARLY_BUILD) && defined(MK_CLANG_FULL) && ${MK_CLANG_FULL} != "no"
+_libclangstaticanalyzer= \
+ libclangstaticanalyzercheckers \
+ libclangstaticanalyzercore \
+ libclangstaticanalyzerfrontend
+_libclangarcmigrate= \
+ libclangarcmigrate
+_libclangrewriter= \
+ libclangrewritecore \
+ libclangrewritefrontend
+.endif # !EARLY_BUILD && MK_CLANG_FULL
+
SUBDIR= libclanganalysis \
- libclangarcmigrate \
+ ${_libclangarcmigrate} \
libclangast \
libclangbasic \
libclangcodegen \
@@ -14,13 +26,10 @@ SUBDIR= libclanganalysis \
libclangfrontendtool \
libclanglex \
libclangparse \
- libclangrewritecore \
- libclangrewritefrontend \
+ ${_libclangrewriter} \
libclangsema \
libclangserialization \
- libclangstaticanalyzercheckers \
- libclangstaticanalyzercore \
- libclangstaticanalyzerfrontend \
+ ${_libclangstaticanalyzer} \
\
libllvmanalysis \
libllvmarchive \
@@ -78,8 +87,8 @@ SUBDIR+=libllvmdebuginfo \
libllvmmcdisassembler \
libllvmmcjit \
libllvmruntimedyld
-.endif
-.endif
+.endif # MK_CLANG_EXTRAS
+.endif # !make(install)
SUBDIR+= include
diff --git a/lib/clang/clang.build.mk b/lib/clang/clang.build.mk
index 298a2eb..0015e3d 100644
--- a/lib/clang/clang.build.mk
+++ b/lib/clang/clang.build.mk
@@ -8,6 +8,12 @@ CFLAGS+= -I${LLVM_SRCS}/include -I${CLANG_SRCS}/include \
-DLLVM_ON_UNIX -DLLVM_ON_FREEBSD \
-D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS #-DNDEBUG
+.if !defined(EARLY_BUILD) && defined(MK_CLANG_FULL) && ${MK_CLANG_FULL} != "no"
+CFLAGS+= -DCLANG_ENABLE_ARCMT \
+ -DCLANG_ENABLE_REWRITER \
+ -DCLANG_ENABLE_STATIC_ANALYZER
+.endif # !EARLY_BUILD && MK_CLANG_FULL
+
# LLVM is not strict aliasing safe as of 12/31/2011
CFLAGS+= -fno-strict-aliasing
diff --git a/lib/clang/libclanganalysis/Makefile b/lib/clang/libclanganalysis/Makefile
index 61c45be..76bf1e5 100644
--- a/lib/clang/libclanganalysis/Makefile
+++ b/lib/clang/libclanganalysis/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clanganalysis
SRCDIR= tools/clang/lib/Analysis
diff --git a/lib/clang/libclangarcmigrate/Makefile b/lib/clang/libclangarcmigrate/Makefile
index 6544805..7597e9c 100644
--- a/lib/clang/libclangarcmigrate/Makefile
+++ b/lib/clang/libclangarcmigrate/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangarcmigrate
SRCDIR= tools/clang/lib/ARCMigrate
diff --git a/lib/clang/libclangast/Makefile b/lib/clang/libclangast/Makefile
index 0b851e6..0ddeb53 100644
--- a/lib/clang/libclangast/Makefile
+++ b/lib/clang/libclangast/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangast
SRCDIR= tools/clang/lib/AST
diff --git a/lib/clang/libclangbasic/Makefile b/lib/clang/libclangbasic/Makefile
index f0efd74..eec941a 100644
--- a/lib/clang/libclangbasic/Makefile
+++ b/lib/clang/libclangbasic/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangbasic
SRCDIR= tools/clang/lib/Basic
diff --git a/lib/clang/libclangcodegen/Makefile b/lib/clang/libclangcodegen/Makefile
index 5252e7c..7aefa7c 100644
--- a/lib/clang/libclangcodegen/Makefile
+++ b/lib/clang/libclangcodegen/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangcodegen
SRCDIR= tools/clang/lib/CodeGen
diff --git a/lib/clang/libclangdriver/Makefile b/lib/clang/libclangdriver/Makefile
index 4950cfa..aae2a05 100644
--- a/lib/clang/libclangdriver/Makefile
+++ b/lib/clang/libclangdriver/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangdriver
SRCDIR= tools/clang/lib/Driver
diff --git a/lib/clang/libclangedit/Makefile b/lib/clang/libclangedit/Makefile
index a0e45a9..59b0b54 100644
--- a/lib/clang/libclangedit/Makefile
+++ b/lib/clang/libclangedit/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangedit
SRCDIR= tools/clang/lib/Edit
diff --git a/lib/clang/libclangfrontend/Makefile b/lib/clang/libclangfrontend/Makefile
index c2813b4..44ba2fb 100644
--- a/lib/clang/libclangfrontend/Makefile
+++ b/lib/clang/libclangfrontend/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangfrontend
SRCDIR= tools/clang/lib/Frontend
diff --git a/lib/clang/libclangfrontendtool/Makefile b/lib/clang/libclangfrontendtool/Makefile
index f37979f..f20aa35 100644
--- a/lib/clang/libclangfrontendtool/Makefile
+++ b/lib/clang/libclangfrontendtool/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangfrontendtool
SRCDIR= tools/clang/lib/FrontendTool
diff --git a/lib/clang/libclanglex/Makefile b/lib/clang/libclanglex/Makefile
index 3ad0e3f..768d43c 100644
--- a/lib/clang/libclanglex/Makefile
+++ b/lib/clang/libclanglex/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clanglex
SRCDIR= tools/clang/lib/Lex
diff --git a/lib/clang/libclangparse/Makefile b/lib/clang/libclangparse/Makefile
index 599a034..dbe9adb 100644
--- a/lib/clang/libclangparse/Makefile
+++ b/lib/clang/libclangparse/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangparse
SRCDIR= tools/clang/lib/Parse
diff --git a/lib/clang/libclangrewritecore/Makefile b/lib/clang/libclangrewritecore/Makefile
index 3a628d0..80115ee 100644
--- a/lib/clang/libclangrewritecore/Makefile
+++ b/lib/clang/libclangrewritecore/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangrewritecore
SRCDIR= tools/clang/lib/Rewrite/Core
diff --git a/lib/clang/libclangrewritefrontend/Makefile b/lib/clang/libclangrewritefrontend/Makefile
index 35de008..ffa11b4 100644
--- a/lib/clang/libclangrewritefrontend/Makefile
+++ b/lib/clang/libclangrewritefrontend/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangrewritefrontend
SRCDIR= tools/clang/lib/Rewrite/Frontend
diff --git a/lib/clang/libclangsema/Makefile b/lib/clang/libclangsema/Makefile
index 235fa13..9ced8b4 100644
--- a/lib/clang/libclangsema/Makefile
+++ b/lib/clang/libclangsema/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangsema
SRCDIR= tools/clang/lib/Sema
diff --git a/lib/clang/libclangserialization/Makefile b/lib/clang/libclangserialization/Makefile
index 75f68bf..962bbf0 100644
--- a/lib/clang/libclangserialization/Makefile
+++ b/lib/clang/libclangserialization/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangserialization
SRCDIR= tools/clang/lib/Serialization
diff --git a/lib/clang/libclangstaticanalyzercheckers/Makefile b/lib/clang/libclangstaticanalyzercheckers/Makefile
index 96274d9..9536151 100644
--- a/lib/clang/libclangstaticanalyzercheckers/Makefile
+++ b/lib/clang/libclangstaticanalyzercheckers/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangstaticanalyzercheckers
SRCDIR= tools/clang/lib/StaticAnalyzer/Checkers
diff --git a/lib/clang/libclangstaticanalyzercore/Makefile b/lib/clang/libclangstaticanalyzercore/Makefile
index 82ff5a3..9c263f0 100644
--- a/lib/clang/libclangstaticanalyzercore/Makefile
+++ b/lib/clang/libclangstaticanalyzercore/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangstaticanalyzercore
SRCDIR= tools/clang/lib/StaticAnalyzer/Core
diff --git a/lib/clang/libclangstaticanalyzerfrontend/Makefile b/lib/clang/libclangstaticanalyzerfrontend/Makefile
index 5c7cd41..9e19f92 100644
--- a/lib/clang/libclangstaticanalyzerfrontend/Makefile
+++ b/lib/clang/libclangstaticanalyzerfrontend/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= clangstaticanalyzerfrontend
SRCDIR= tools/clang/lib/StaticAnalyzer/Frontend
diff --git a/lib/clang/libllvmarchive/Makefile b/lib/clang/libllvmarchive/Makefile
index a28f2f5..d553405 100644
--- a/lib/clang/libllvmarchive/Makefile
+++ b/lib/clang/libllvmarchive/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmarchive
SRCDIR= lib/Archive
diff --git a/lib/clang/libllvmarmasmparser/Makefile b/lib/clang/libllvmarmasmparser/Makefile
index c3d0d89..05e6263 100644
--- a/lib/clang/libllvmarmasmparser/Makefile
+++ b/lib/clang/libllvmarmasmparser/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmarmasmparser
SRCDIR= lib/Target/ARM/AsmParser
diff --git a/lib/clang/libllvmarmcodegen/Makefile b/lib/clang/libllvmarmcodegen/Makefile
index 6ae9251..6a10eaf 100644
--- a/lib/clang/libllvmarmcodegen/Makefile
+++ b/lib/clang/libllvmarmcodegen/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmarmcodegen
SRCDIR= lib/Target/ARM
diff --git a/lib/clang/libllvmarmdesc/Makefile b/lib/clang/libllvmarmdesc/Makefile
index bd2e0cb..61679a6 100644
--- a/lib/clang/libllvmarmdesc/Makefile
+++ b/lib/clang/libllvmarmdesc/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmarmdesc
SRCDIR= lib/Target/ARM/MCTargetDesc
diff --git a/lib/clang/libllvmarmdisassembler/Makefile b/lib/clang/libllvmarmdisassembler/Makefile
index a3d16f7..eb46736 100644
--- a/lib/clang/libllvmarmdisassembler/Makefile
+++ b/lib/clang/libllvmarmdisassembler/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmarmdisassembler
SRCDIR= lib/Target/ARM/Disassembler
diff --git a/lib/clang/libllvmarminfo/Makefile b/lib/clang/libllvmarminfo/Makefile
index ec88367..1da434c 100644
--- a/lib/clang/libllvmarminfo/Makefile
+++ b/lib/clang/libllvmarminfo/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmarminfo
SRCDIR= lib/Target/ARM/TargetInfo
diff --git a/lib/clang/libllvmarminstprinter/Makefile b/lib/clang/libllvmarminstprinter/Makefile
index ca7e7d4..67b8fee 100644
--- a/lib/clang/libllvmarminstprinter/Makefile
+++ b/lib/clang/libllvmarminstprinter/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmarminstprinter
SRCDIR= lib/Target/ARM/InstPrinter
diff --git a/lib/clang/libllvmasmparser/Makefile b/lib/clang/libllvmasmparser/Makefile
index 8ceba69..bb8f0df 100644
--- a/lib/clang/libllvmasmparser/Makefile
+++ b/lib/clang/libllvmasmparser/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmasmparser
SRCDIR= lib/AsmParser
diff --git a/lib/clang/libllvmasmprinter/Makefile b/lib/clang/libllvmasmprinter/Makefile
index 36e626f..97bc73d3 100644
--- a/lib/clang/libllvmasmprinter/Makefile
+++ b/lib/clang/libllvmasmprinter/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmasmprinter
SRCDIR= lib/CodeGen/AsmPrinter
diff --git a/lib/clang/libllvmbitreader/Makefile b/lib/clang/libllvmbitreader/Makefile
index c426680..094e0e7 100644
--- a/lib/clang/libllvmbitreader/Makefile
+++ b/lib/clang/libllvmbitreader/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmbitreader
SRCDIR= lib/Bitcode/Reader
diff --git a/lib/clang/libllvmbitwriter/Makefile b/lib/clang/libllvmbitwriter/Makefile
index 3431b21..1cb9d41 100644
--- a/lib/clang/libllvmbitwriter/Makefile
+++ b/lib/clang/libllvmbitwriter/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmbitwriter
SRCDIR= lib/Bitcode/Writer
diff --git a/lib/clang/libllvmcodegen/Makefile b/lib/clang/libllvmcodegen/Makefile
index 8beb583..e65d19c 100644
--- a/lib/clang/libllvmcodegen/Makefile
+++ b/lib/clang/libllvmcodegen/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmcodegen
SRCDIR= lib/CodeGen
diff --git a/lib/clang/libllvmcore/Makefile b/lib/clang/libllvmcore/Makefile
index 5b597fe..d2010c0 100644
--- a/lib/clang/libllvmcore/Makefile
+++ b/lib/clang/libllvmcore/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmcore
SRCDIR= lib/VMCore
diff --git a/lib/clang/libllvmdebuginfo/Makefile b/lib/clang/libllvmdebuginfo/Makefile
index e12289b..757b909 100644
--- a/lib/clang/libllvmdebuginfo/Makefile
+++ b/lib/clang/libllvmdebuginfo/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmdebuginfo
SRCDIR= lib/DebugInfo
diff --git a/lib/clang/libllvmexecutionengine/Makefile b/lib/clang/libllvmexecutionengine/Makefile
index c0dde71..3ec39c7 100644
--- a/lib/clang/libllvmexecutionengine/Makefile
+++ b/lib/clang/libllvmexecutionengine/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmexecutionengine
SRCDIR= lib/ExecutionEngine
diff --git a/lib/clang/libllvminstcombine/Makefile b/lib/clang/libllvminstcombine/Makefile
index e989fa5..3752aef 100644
--- a/lib/clang/libllvminstcombine/Makefile
+++ b/lib/clang/libllvminstcombine/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvminstcombine
SRCDIR= lib/Transforms/InstCombine
diff --git a/lib/clang/libllvminstrumentation/Makefile b/lib/clang/libllvminstrumentation/Makefile
index ef09370..6d666e5 100644
--- a/lib/clang/libllvminstrumentation/Makefile
+++ b/lib/clang/libllvminstrumentation/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvminstrumentation
SRCDIR= lib/Transforms/Instrumentation
diff --git a/lib/clang/libllvminterpreter/Makefile b/lib/clang/libllvminterpreter/Makefile
index 6a1b453..06fcca4 100644
--- a/lib/clang/libllvminterpreter/Makefile
+++ b/lib/clang/libllvminterpreter/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvminterpreter
SRCDIR= lib/ExecutionEngine/Interpreter
diff --git a/lib/clang/libllvmjit/Makefile b/lib/clang/libllvmjit/Makefile
index ff852d5..682f704 100644
--- a/lib/clang/libllvmjit/Makefile
+++ b/lib/clang/libllvmjit/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmjit
SRCDIR= lib/ExecutionEngine/JIT
diff --git a/lib/clang/libllvmlinker/Makefile b/lib/clang/libllvmlinker/Makefile
index 73f153b..7275131 100644
--- a/lib/clang/libllvmlinker/Makefile
+++ b/lib/clang/libllvmlinker/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmlinker
SRCDIR= lib/Linker
diff --git a/lib/clang/libllvmmcdisassembler/Makefile b/lib/clang/libllvmmcdisassembler/Makefile
index dc5f294..94aff3e 100644
--- a/lib/clang/libllvmmcdisassembler/Makefile
+++ b/lib/clang/libllvmmcdisassembler/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmmcdisassembler
SRCDIR= lib/MC/MCDisassembler
diff --git a/lib/clang/libllvmmcparser/Makefile b/lib/clang/libllvmmcparser/Makefile
index 48deadf..b39926a 100644
--- a/lib/clang/libllvmmcparser/Makefile
+++ b/lib/clang/libllvmmcparser/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmmcparser
SRCDIR= lib/MC/MCParser
diff --git a/lib/clang/libllvmmipsasmparser/Makefile b/lib/clang/libllvmmipsasmparser/Makefile
index f5fb3c3..0572f8d 100644
--- a/lib/clang/libllvmmipsasmparser/Makefile
+++ b/lib/clang/libllvmmipsasmparser/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmmipsasmparser
SRCDIR= lib/Target/Mips/AsmParser
diff --git a/lib/clang/libllvmmipscodegen/Makefile b/lib/clang/libllvmmipscodegen/Makefile
index c33d954..7675a01 100644
--- a/lib/clang/libllvmmipscodegen/Makefile
+++ b/lib/clang/libllvmmipscodegen/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmmipscodegen
SRCDIR= lib/Target/Mips
diff --git a/lib/clang/libllvmmipsdesc/Makefile b/lib/clang/libllvmmipsdesc/Makefile
index 120b866..4ddb646 100644
--- a/lib/clang/libllvmmipsdesc/Makefile
+++ b/lib/clang/libllvmmipsdesc/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmmipsdesc
SRCDIR= lib/Target/Mips/MCTargetDesc
diff --git a/lib/clang/libllvmmipsdisassembler/Makefile b/lib/clang/libllvmmipsdisassembler/Makefile
index 7cdd982..1c0a4b6 100644
--- a/lib/clang/libllvmmipsdisassembler/Makefile
+++ b/lib/clang/libllvmmipsdisassembler/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmmipsdisassembler
SRCDIR= lib/Target/Mips/Disassembler
diff --git a/lib/clang/libllvmmipsinfo/Makefile b/lib/clang/libllvmmipsinfo/Makefile
index c5b96cd..c65c8c8 100644
--- a/lib/clang/libllvmmipsinfo/Makefile
+++ b/lib/clang/libllvmmipsinfo/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmmipsinfo
SRCDIR= lib/Target/Mips/TargetInfo
diff --git a/lib/clang/libllvmmipsinstprinter/Makefile b/lib/clang/libllvmmipsinstprinter/Makefile
index 36d3b04..39df7cc 100644
--- a/lib/clang/libllvmmipsinstprinter/Makefile
+++ b/lib/clang/libllvmmipsinstprinter/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmmipsinstprinter
SRCDIR= lib/Target/Mips/InstPrinter
diff --git a/lib/clang/libllvmobject/Makefile b/lib/clang/libllvmobject/Makefile
index d056dc7..c8c8068 100644
--- a/lib/clang/libllvmobject/Makefile
+++ b/lib/clang/libllvmobject/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmobject
SRCDIR= lib/Object
diff --git a/lib/clang/libllvmpowerpccodegen/Makefile b/lib/clang/libllvmpowerpccodegen/Makefile
index a97c352..a09da59 100644
--- a/lib/clang/libllvmpowerpccodegen/Makefile
+++ b/lib/clang/libllvmpowerpccodegen/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmpowerpccodegen
SRCDIR= lib/Target/PowerPC
diff --git a/lib/clang/libllvmpowerpcdesc/Makefile b/lib/clang/libllvmpowerpcdesc/Makefile
index 2a5ef6e..e48b484 100644
--- a/lib/clang/libllvmpowerpcdesc/Makefile
+++ b/lib/clang/libllvmpowerpcdesc/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmpowerpcdesc
SRCDIR= lib/Target/PowerPC/MCTargetDesc
diff --git a/lib/clang/libllvmpowerpcinfo/Makefile b/lib/clang/libllvmpowerpcinfo/Makefile
index 8310378..03bba0e 100644
--- a/lib/clang/libllvmpowerpcinfo/Makefile
+++ b/lib/clang/libllvmpowerpcinfo/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmpowerpcinfo
SRCDIR= lib/Target/PowerPC/TargetInfo
diff --git a/lib/clang/libllvmpowerpcinstprinter/Makefile b/lib/clang/libllvmpowerpcinstprinter/Makefile
index c1528ae..ac98321 100644
--- a/lib/clang/libllvmpowerpcinstprinter/Makefile
+++ b/lib/clang/libllvmpowerpcinstprinter/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmpowerpcinstprinter
SRCDIR= lib/Target/PowerPC/InstPrinter
diff --git a/lib/clang/libllvmruntimedyld/Makefile b/lib/clang/libllvmruntimedyld/Makefile
index d5d5447..02ca4bd 100644
--- a/lib/clang/libllvmruntimedyld/Makefile
+++ b/lib/clang/libllvmruntimedyld/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmruntimedyld
SRCDIR= lib/ExecutionEngine/RuntimeDyld
diff --git a/lib/clang/libllvmselectiondag/Makefile b/lib/clang/libllvmselectiondag/Makefile
index e6950127..7543102 100644
--- a/lib/clang/libllvmselectiondag/Makefile
+++ b/lib/clang/libllvmselectiondag/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmselectiondag
SRCDIR= lib/CodeGen/SelectionDAG
diff --git a/lib/clang/libllvmtablegen/Makefile b/lib/clang/libllvmtablegen/Makefile
index 8dffad0..069cec0 100644
--- a/lib/clang/libllvmtablegen/Makefile
+++ b/lib/clang/libllvmtablegen/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmtablegen
SRCDIR= lib/TableGen
diff --git a/lib/clang/libllvmtarget/Makefile b/lib/clang/libllvmtarget/Makefile
index b82377e..595d2cc 100644
--- a/lib/clang/libllvmtarget/Makefile
+++ b/lib/clang/libllvmtarget/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmtarget
SRCDIR= lib/Target
diff --git a/lib/clang/libllvmvectorize/Makefile b/lib/clang/libllvmvectorize/Makefile
index 444d672..d0f5b73 100644
--- a/lib/clang/libllvmvectorize/Makefile
+++ b/lib/clang/libllvmvectorize/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmvectorize
SRCDIR= lib/Transforms/Vectorize
diff --git a/lib/clang/libllvmx86asmparser/Makefile b/lib/clang/libllvmx86asmparser/Makefile
index c140268..252b2d0 100644
--- a/lib/clang/libllvmx86asmparser/Makefile
+++ b/lib/clang/libllvmx86asmparser/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmx86asmparser
SRCDIR= lib/Target/X86/AsmParser
diff --git a/lib/clang/libllvmx86codegen/Makefile b/lib/clang/libllvmx86codegen/Makefile
index bcc7aa0..939b257 100644
--- a/lib/clang/libllvmx86codegen/Makefile
+++ b/lib/clang/libllvmx86codegen/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmx86codegen
SRCDIR= lib/Target/X86
diff --git a/lib/clang/libllvmx86desc/Makefile b/lib/clang/libllvmx86desc/Makefile
index 3d2a9dd..a177129 100644
--- a/lib/clang/libllvmx86desc/Makefile
+++ b/lib/clang/libllvmx86desc/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmx86desc
SRCDIR= lib/Target/X86/MCTargetDesc
diff --git a/lib/clang/libllvmx86info/Makefile b/lib/clang/libllvmx86info/Makefile
index 85155a8..bc1a7d7 100644
--- a/lib/clang/libllvmx86info/Makefile
+++ b/lib/clang/libllvmx86info/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmx86info
SRCDIR= lib/Target/X86/TargetInfo
diff --git a/lib/clang/libllvmx86instprinter/Makefile b/lib/clang/libllvmx86instprinter/Makefile
index a44006c..308f91c 100644
--- a/lib/clang/libllvmx86instprinter/Makefile
+++ b/lib/clang/libllvmx86instprinter/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmx86instprinter
SRCDIR= lib/Target/X86/InstPrinter
diff --git a/lib/clang/libllvmx86utils/Makefile b/lib/clang/libllvmx86utils/Makefile
index bbed6b0..8355e7e 100644
--- a/lib/clang/libllvmx86utils/Makefile
+++ b/lib/clang/libllvmx86utils/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
LIB= llvmx86utils
SRCDIR= lib/Target/X86/Utils
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index 29508ad..73b3c22 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -231,9 +231,6 @@ MLINKS+= archive_entry_perms.3 archive_entry_set_fflags.3
MLINKS+= archive_entry_perms.3 archive_entry_set_gid.3
MLINKS+= archive_entry_perms.3 archive_entry_set_gname.3
MLINKS+= archive_entry_perms.3 archive_entry_perm.3
-MLINKS+= archive_entry_perms.3 archive_entry_set_fflags.3
-MLINKS+= archive_entry_perms.3 archive_entry_set_gid.3
-MLINKS+= archive_entry_perms.3 archive_entry_set_gname.3
MLINKS+= archive_entry_perms.3 archive_entry_set_perm.3
MLINKS+= archive_entry_perms.3 archive_entry_set_uid.3
MLINKS+= archive_entry_perms.3 archive_entry_set_uname.3
@@ -264,10 +261,6 @@ MLINKS+= archive_entry_stat.3 archive_entry_set_filetype.3
MLINKS+= archive_entry_stat.3 archive_entry_set_ino.3
MLINKS+= archive_entry_stat.3 archive_entry_set_ino64.3
MLINKS+= archive_entry_stat.3 archive_entry_set_mode.3
-MLINKS+= archive_entry_stat.3 archive_entry_set_rdev.3
-MLINKS+= archive_entry_stat.3 archive_entry_set_rdevmajor.3
-MLINKS+= archive_entry_stat.3 archive_entry_set_rdevminor.3
-MLINKS+= archive_entry_stat.3 archive_entry_set_size.3
MLINKS+= archive_entry_stat.3 archive_entry_set_nlink.3
MLINKS+= archive_entry_stat.3 archive_entry_set_rdev.3
MLINKS+= archive_entry_stat.3 archive_entry_set_rdevmajor.3
diff --git a/lib/libc/amd64/sys/__vdso_gettc.c b/lib/libc/amd64/sys/__vdso_gettc.c
index 091fe26..c6f2dfb 100644
--- a/lib/libc/amd64/sys/__vdso_gettc.c
+++ b/lib/libc/amd64/sys/__vdso_gettc.c
@@ -27,9 +27,11 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
+#include <sys/elf.h>
#include <sys/time.h>
#include <sys/vdso.h>
#include <machine/cpufunc.h>
+#include "libc_private.h"
static u_int
__vdso_gettc_low(const struct vdso_timehands *th)
@@ -41,9 +43,18 @@ __vdso_gettc_low(const struct vdso_timehands *th)
return (rv);
}
+#pragma weak __vdso_gettc
u_int
__vdso_gettc(const struct vdso_timehands *th)
{
return (th->th_x86_shift > 0 ? __vdso_gettc_low(th) : rdtsc32());
}
+
+#pragma weak __vdso_gettimekeep
+int
+__vdso_gettimekeep(struct vdso_timekeep **tk)
+{
+
+ return (_elf_aux_info(AT_TIMEKEEP, tk, sizeof(*tk)));
+}
diff --git a/lib/libc/arm/Makefile.inc b/lib/libc/arm/Makefile.inc
index 4c72e56..1ae1298 100644
--- a/lib/libc/arm/Makefile.inc
+++ b/lib/libc/arm/Makefile.inc
@@ -8,3 +8,11 @@ SOFTFLOAT_BITS=32
# Long double is just double precision.
MDSRCS+=machdep_ldisd.c
SYM_MAPS+=${.CURDIR}/arm/Symbol.map
+
+.if ${MK_ARM_EABI} == "no"
+# This contains the symbols that were removed when moving to the ARM EABI
+SYM_MAPS+=${.CURDIR}/arm/Symbol_oabi.map
+.else
+.include "${.CURDIR}/arm/aeabi/Makefile.inc"
+.endif
+
diff --git a/lib/libc/arm/SYS.h b/lib/libc/arm/SYS.h
index 584c151..ed1a045 100644
--- a/lib/libc/arm/SYS.h
+++ b/lib/libc/arm/SYS.h
@@ -39,7 +39,15 @@
#include <sys/syscall.h>
#include <machine/swi.h>
+#ifdef __ARM_EABI__
+#define SYSTRAP(x) \
+ mov ip, r7; \
+ ldr r7, =SYS_ ## x; \
+ swi 0; \
+ mov r7, ip
+#else
#define SYSTRAP(x) swi 0 | SYS_ ## x
+#endif
#define CERROR _C_LABEL(cerror)
#define CURBRK _C_LABEL(curbrk)
diff --git a/lib/libc/arm/Symbol.map b/lib/libc/arm/Symbol.map
index 48f6747..1c83b0a 100644
--- a/lib/libc/arm/Symbol.map
+++ b/lib/libc/arm/Symbol.map
@@ -46,10 +46,6 @@ FBSDprivate_1.0 {
_set_tp;
__aeabi_read_tp;
___longjmp;
- __umodsi3;
- __modsi3;
- __udivsi3;
- __divsi3;
__makecontext;
__longjmp;
signalcontext;
diff --git a/lib/libc/arm/Symbol_oabi.map b/lib/libc/arm/Symbol_oabi.map
new file mode 100644
index 0000000..0c22e4a
--- /dev/null
+++ b/lib/libc/arm/Symbol_oabi.map
@@ -0,0 +1,16 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...)
+ * and are not used in the ARM EABI.
+ */
+FBSDprivate_1.0 {
+ __umodsi3;
+ __modsi3;
+ __udivsi3;
+ __divsi3;
+};
diff --git a/lib/libc/arm/aeabi/Makefile.inc b/lib/libc/arm/aeabi/Makefile.inc
new file mode 100644
index 0000000..ac147c0
--- /dev/null
+++ b/lib/libc/arm/aeabi/Makefile.inc
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/arm/aeabi
+
+SRCS+= aeabi_atexit.c \
+ aeabi_double.c \
+ aeabi_float.c \
+ aeabi_unwind_cpp.c
+
+SYM_MAPS+=${.CURDIR}/arm/aeabi/Symbol.map
+
diff --git a/lib/libc/arm/aeabi/Symbol.map b/lib/libc/arm/aeabi/Symbol.map
new file mode 100644
index 0000000..9493427
--- /dev/null
+++ b/lib/libc/arm/aeabi/Symbol.map
@@ -0,0 +1,47 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain AEABI symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSDprivate_1.0 {
+ __aeabi_atexit;
+
+ __aeabi_dcmpeq;
+ __aeabi_dcmplt;
+ __aeabi_dcmple;
+ __aeabi_dcmpge;
+ __aeabi_dcmpgt;
+ __aeabi_dcmpun;
+
+ __aeabi_d2iz;
+ __aeabi_d2f;
+
+ __aeabi_dadd;
+ __aeabi_ddiv;
+ __aeabi_dmul;
+ __aeabi_dsub;
+
+
+ __aeabi_fcmpeq;
+ __aeabi_fcmplt;
+ __aeabi_fcmple;
+ __aeabi_fcmpge;
+ __aeabi_fcmpgt;
+ __aeabi_fcmpun;
+
+ __aeabi_f2iz;
+ __aeabi_f2d;
+
+ __aeabi_fadd;
+ __aeabi_fdiv;
+ __aeabi_fmul;
+ __aeabi_fsub;
+
+
+ __aeabi_i2d;
+ __aeabi_i2f;
+};
diff --git a/sys/arm/mv/kirkwood/sheevaplug.c b/lib/libc/arm/aeabi/aeabi_atexit.c
index 3463106..8502595 100644
--- a/sys/arm/mv/kirkwood/sheevaplug.c
+++ b/lib/libc/arm/aeabi/aeabi_atexit.c
@@ -1,10 +1,7 @@
-/*-
- * Copyright (c) 2010 The FreeBSD Foundation
+/*
+ * Copyright (C) 2012 Andrew Turner
* All rights reserved.
*
- * This software was developed by Semihalf 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:
@@ -17,7 +14,7 @@
* 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
+ * 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)
@@ -25,20 +22,17 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <dev/fdt/fdt_common.h>
-#include <dev/ofw/openfirm.h>
-
-#include <machine/fdt.h>
+int __cxa_atexit(void (*)(void *), void *, void *);
int
-fdt_pci_devmap(phandle_t node, struct pmap_devmap *devmap, vm_offset_t io_va,
- vm_offset_t mem_va)
+__aeabi_atexit(void *object, void (*func)(void*), void *dso)
{
-
- return (0);
+ return __cxa_atexit(func, object, dso);
}
+
diff --git a/lib/libc/arm/aeabi/aeabi_double.c b/lib/libc/arm/aeabi/aeabi_double.c
new file mode 100644
index 0000000..5f9065c
--- /dev/null
+++ b/lib/libc/arm/aeabi/aeabi_double.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+flag __unorddf2(float64, float64);
+
+int __aeabi_dcmpeq(float64 a, float64 b)
+{
+ return float64_eq(a, b);
+}
+
+int __aeabi_dcmplt(float64 a, float64 b)
+{
+ return float64_lt(a, b);
+}
+
+int __aeabi_dcmple(float64 a, float64 b)
+{
+ return float64_le(a, b);
+}
+
+int __aeabi_dcmpge(float64 a, float64 b)
+{
+ return float64_le(b, a);
+}
+
+int __aeabi_dcmpgt(float64 a, float64 b)
+{
+ return float64_lt(b, a);
+}
+
+int __aeabi_dcmpun(float64 a, float64 b)
+{
+ return __unorddf2(a, b);
+}
+
+int __aeabi_d2iz(float64 a)
+{
+ return float64_to_int32_round_to_zero(a);
+}
+
+float32 __aeabi_d2f(float64 a)
+{
+ return float64_to_float32(a);
+}
+
+float64 __aeabi_i2d(int a)
+{
+ return int32_to_float64(a);
+}
+
+float64 __aeabi_dadd(float64 a, float64 b)
+{
+ return float64_add(a, b);
+}
+
+float64 __aeabi_ddiv(float64 a, float64 b)
+{
+ return float64_div(a, b);
+}
+
+float64 __aeabi_dmul(float64 a, float64 b)
+{
+ return float64_mul(a, b);
+}
+
+float64 __aeabi_dsub(float64 a, float64 b)
+{
+ return float64_sub(a, b);
+}
+
diff --git a/lib/libc/arm/aeabi/aeabi_float.c b/lib/libc/arm/aeabi/aeabi_float.c
new file mode 100644
index 0000000..97751ad
--- /dev/null
+++ b/lib/libc/arm/aeabi/aeabi_float.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+flag __unordsf2(float32, float32);
+
+int __aeabi_fcmpeq(float32 a, float32 b)
+{
+ return float32_eq(a, b);
+}
+
+int __aeabi_fcmplt(float32 a, float32 b)
+{
+ return float32_lt(a, b);
+}
+
+int __aeabi_fcmple(float32 a, float32 b)
+{
+ return float32_le(a, b);
+}
+
+int __aeabi_fcmpge(float32 a, float32 b)
+{
+ return float32_le(b, a);
+}
+
+int __aeabi_fcmpgt(float32 a, float32 b)
+{
+ return float32_lt(b, a);
+}
+
+int __aeabi_fcmpun(float32 a, float32 b)
+{
+ return __unordsf2(a, b);
+}
+
+int __aeabi_f2iz(float32 a)
+{
+ return float32_to_int32_round_to_zero(a);
+}
+
+float32 __aeabi_f2d(float32 a)
+{
+ return float32_to_float64(a);
+}
+
+float32 __aeabi_i2f(int a)
+{
+ return int32_to_float32(a);
+}
+
+float32 __aeabi_fadd(float32 a, float32 b)
+{
+ return float32_add(a, b);
+}
+
+float32 __aeabi_fdiv(float32 a, float32 b)
+{
+ return float32_div(a, b);
+}
+
+float32 __aeabi_fmul(float32 a, float32 b)
+{
+ return float32_mul(a, b);
+}
+
+float32 __aeabi_fsub(float32 a, float32 b)
+{
+ return float32_sub(a, b);
+}
+
diff --git a/lib/libc/arm/aeabi/aeabi_unwind_cpp.c b/lib/libc/arm/aeabi/aeabi_unwind_cpp.c
new file mode 100644
index 0000000..c07cbbd
--- /dev/null
+++ b/lib/libc/arm/aeabi/aeabi_unwind_cpp.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Provide an implementation of __aeabi_unwind_cpp_pr{0,1,2}. These are
+ * required by libc but are implemented in libgcc_eh.a which we don't link
+ * against. The libgcc_eh.a version will be called so we call abort to
+ * check this.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+void __aeabi_unwind_cpp_pr0(void) __hidden;
+void __aeabi_unwind_cpp_pr1(void) __hidden;
+void __aeabi_unwind_cpp_pr2(void) __hidden;
+
+void
+__aeabi_unwind_cpp_pr0(void)
+{
+ abort();
+}
+
+void
+__aeabi_unwind_cpp_pr1(void)
+{
+ abort();
+}
+
+void
+__aeabi_unwind_cpp_pr2(void)
+{
+ abort();
+}
+
diff --git a/lib/libc/arm/gen/Makefile.inc b/lib/libc/arm/gen/Makefile.inc
index a78cbb9..ec36d45 100644
--- a/lib/libc/arm/gen/Makefile.inc
+++ b/lib/libc/arm/gen/Makefile.inc
@@ -3,4 +3,8 @@
SRCS+= _ctx_start.S _setjmp.S _set_tp.c alloca.S fabs.c \
getcontextx.c infinity.c ldexp.c makecontext.c \
- __aeabi_read_tp.S setjmp.S signalcontext.c sigsetjmp.S divsi3.S flt_rounds.c
+ __aeabi_read_tp.S setjmp.S signalcontext.c sigsetjmp.S flt_rounds.c
+
+.if ${MK_ARM_EABI} == "no"
+SRCS+= divsi3.S
+.endif
diff --git a/lib/libc/arm/sys/Makefile.inc b/lib/libc/arm/sys/Makefile.inc
index 1a58eae..fd251c8 100644
--- a/lib/libc/arm/sys/Makefile.inc
+++ b/lib/libc/arm/sys/Makefile.inc
@@ -1,5 +1,7 @@
# $FreeBSD$
+SRCS+= __vdso_gettc.c
+
MDASM= Ovfork.S brk.S cerror.S pipe.S ptrace.S sbrk.S shmat.S sigreturn.S syscall.S
# Don't generate default code for these syscalls:
diff --git a/lib/libc/arm/sys/__vdso_gettc.c b/lib/libc/arm/sys/__vdso_gettc.c
new file mode 100644
index 0000000..b99bbc4
--- /dev/null
+++ b/lib/libc/arm/sys/__vdso_gettc.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2013 Konstantin Belousov <kib@FreeBSD.org>
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/vdso.h>
+#include <errno.h>
+
+#pragma weak __vdso_gettc
+u_int
+__vdso_gettc(const struct vdso_timehands *th)
+{
+
+ return (0);
+}
+
+#pragma weak __vdso_gettimekeep
+int
+__vdso_gettimekeep(struct vdso_timekeep **tk)
+{
+
+ return (ENOSYS);
+}
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index abface8..0bbbb33 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -40,6 +40,7 @@ SRCS+= __getosreldate.c __xuname.c \
SRCS+= pwcache.c pwcache.h
.PATH: ${.CURDIR}/../../contrib/libc-vis
+CFLAGS+= -I${.CURDIR}/../../contrib/libc-vis
SRCS+= unvis.c vis.c
MISRCS+=modf.c
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 0c6f48e..4cbf07c 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -298,6 +298,8 @@ FBSD_1.0 {
ualarm;
ulimit;
uname;
+ strunvis;
+ strunvisx;
usleep;
utime;
valloc;
@@ -391,8 +393,6 @@ FBSD_1.3 {
snvis;
strnunvis;
strnunvisx;
- strunvis;
- strunvisx;
strnvis;
strnvisx;
strsnvis;
diff --git a/lib/libc/i386/sys/__vdso_gettc.c b/lib/libc/i386/sys/__vdso_gettc.c
index 4419141..c6f2dfb 100644
--- a/lib/libc/i386/sys/__vdso_gettc.c
+++ b/lib/libc/i386/sys/__vdso_gettc.c
@@ -27,9 +27,11 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
+#include <sys/elf.h>
#include <sys/time.h>
#include <sys/vdso.h>
#include <machine/cpufunc.h>
+#include "libc_private.h"
static u_int
__vdso_gettc_low(const struct vdso_timehands *th)
@@ -48,3 +50,11 @@ __vdso_gettc(const struct vdso_timehands *th)
return (th->th_x86_shift > 0 ? __vdso_gettc_low(th) : rdtsc32());
}
+
+#pragma weak __vdso_gettimekeep
+int
+__vdso_gettimekeep(struct vdso_timekeep **tk)
+{
+
+ return (_elf_aux_info(AT_TIMEKEEP, tk, sizeof(*tk)));
+}
diff --git a/lib/libc/ia64/sys/Makefile.inc b/lib/libc/ia64/sys/Makefile.inc
index 3876d3a..2846590 100644
--- a/lib/libc/ia64/sys/Makefile.inc
+++ b/lib/libc/ia64/sys/Makefile.inc
@@ -1,5 +1,7 @@
# $FreeBSD$
+SRCS+= __vdso_gettc.c
+
MDASM+= Ovfork.S brk.S cerror.S exect.S fork.S getcontext.S pipe.S ptrace.S \
sbrk.S setlogin.S sigreturn.S swapcontext.S
diff --git a/lib/libc/ia64/sys/__vdso_gettc.c b/lib/libc/ia64/sys/__vdso_gettc.c
new file mode 100644
index 0000000..b99bbc4
--- /dev/null
+++ b/lib/libc/ia64/sys/__vdso_gettc.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2013 Konstantin Belousov <kib@FreeBSD.org>
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/vdso.h>
+#include <errno.h>
+
+#pragma weak __vdso_gettc
+u_int
+__vdso_gettc(const struct vdso_timehands *th)
+{
+
+ return (0);
+}
+
+#pragma weak __vdso_gettimekeep
+int
+__vdso_gettimekeep(struct vdso_timekeep **tk)
+{
+
+ return (ENOSYS);
+}
diff --git a/lib/libc/mips/sys/Makefile.inc b/lib/libc/mips/sys/Makefile.inc
index 3601909..fc11349 100644
--- a/lib/libc/mips/sys/Makefile.inc
+++ b/lib/libc/mips/sys/Makefile.inc
@@ -1,5 +1,7 @@
# $FreeBSD$
+SRCS+= __vdso_gettc.c
+
MDASM= Ovfork.S brk.S cerror.S exect.S \
fork.S pipe.S ptrace.S sbrk.S syscall.S
diff --git a/lib/libc/mips/sys/__vdso_gettc.c b/lib/libc/mips/sys/__vdso_gettc.c
new file mode 100644
index 0000000..b99bbc4
--- /dev/null
+++ b/lib/libc/mips/sys/__vdso_gettc.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2013 Konstantin Belousov <kib@FreeBSD.org>
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/vdso.h>
+#include <errno.h>
+
+#pragma weak __vdso_gettc
+u_int
+__vdso_gettc(const struct vdso_timehands *th)
+{
+
+ return (0);
+}
+
+#pragma weak __vdso_gettimekeep
+int
+__vdso_gettimekeep(struct vdso_timekeep **tk)
+{
+
+ return (ENOSYS);
+}
diff --git a/lib/libc/net/name6.c b/lib/libc/net/name6.c
index 0031f46..f360162 100644
--- a/lib/libc/net/name6.c
+++ b/lib/libc/net/name6.c
@@ -200,6 +200,7 @@ static struct hostent *_hpmapv6(struct hostent *, int *);
#endif
static struct hostent *_hpsort(struct hostent *, res_state);
+#ifdef INET6
static struct hostent *_hpreorder(struct hostent *);
static int get_addrselectpolicy(struct policyhead *);
static void free_addrselectpolicy(struct policyhead *);
@@ -209,6 +210,7 @@ static void set_source(struct hp_order *, struct policyhead *);
static int matchlen(struct sockaddr *, struct sockaddr *);
static int comp_dst(const void *, const void *);
static int gai_addr2scopetype(struct sockaddr *);
+#endif
/*
* Functions defined in RFC2553
@@ -285,8 +287,10 @@ getipnodebyname(const char *name, int af, int flags, int *errp)
hp = gethostbyname2(name, af);
hp = _hpcopy(hp, errp);
-
#ifdef INET6
+ if (af == AF_INET6)
+ hp = _hpreorder(hp);
+
if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) &&
MAPADDRENABLED(flags)) {
struct hostent *hp2 = gethostbyname2(name, AF_INET);
@@ -309,7 +313,7 @@ getipnodebyname(const char *name, int af, int flags, int *errp)
*errp = statp->res_h_errno;
statp->options = options;
- return _hpreorder(_hpsort(hp, statp));
+ return _hpsort(hp, statp);
}
struct hostent *
@@ -632,6 +636,7 @@ _hpsort(struct hostent *hp, res_state statp)
return hp;
}
+#ifdef INET6
/*
* _hpreorder: sort address by default address selection
*/
@@ -1109,3 +1114,4 @@ gai_addr2scopetype(struct sockaddr *sa)
return(-1);
}
}
+#endif
diff --git a/lib/libc/powerpc/Makefile.inc b/lib/libc/powerpc/Makefile.inc
index 453726a..104f80c 100644
--- a/lib/libc/powerpc/Makefile.inc
+++ b/lib/libc/powerpc/Makefile.inc
@@ -1,5 +1,7 @@
# $FreeBSD$
+SRCS+= __vdso_gettc.c
+
# Long double is 64-bits
MDSRCS+=machdep_ldisd.c
SYM_MAPS+=${.CURDIR}/powerpc/Symbol.map
diff --git a/lib/libc/powerpc/sys/__vdso_gettc.c b/lib/libc/powerpc/sys/__vdso_gettc.c
new file mode 100644
index 0000000..b99bbc4
--- /dev/null
+++ b/lib/libc/powerpc/sys/__vdso_gettc.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2013 Konstantin Belousov <kib@FreeBSD.org>
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/vdso.h>
+#include <errno.h>
+
+#pragma weak __vdso_gettc
+u_int
+__vdso_gettc(const struct vdso_timehands *th)
+{
+
+ return (0);
+}
+
+#pragma weak __vdso_gettimekeep
+int
+__vdso_gettimekeep(struct vdso_timekeep **tk)
+{
+
+ return (ENOSYS);
+}
diff --git a/lib/libc/powerpc64/Makefile.inc b/lib/libc/powerpc64/Makefile.inc
index e4ccbb9..a30779d 100644
--- a/lib/libc/powerpc64/Makefile.inc
+++ b/lib/libc/powerpc64/Makefile.inc
@@ -1,5 +1,7 @@
# $FreeBSD$
+SRCS+= __vdso_gettc.c
+
# Long double is 64-bits
MDSRCS+=machdep_ldisd.c
SYM_MAPS+=${.CURDIR}/powerpc64/Symbol.map
diff --git a/lib/libc/powerpc64/sys/__vdso_gettc.c b/lib/libc/powerpc64/sys/__vdso_gettc.c
new file mode 100644
index 0000000..b99bbc4
--- /dev/null
+++ b/lib/libc/powerpc64/sys/__vdso_gettc.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2013 Konstantin Belousov <kib@FreeBSD.org>
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/vdso.h>
+#include <errno.h>
+
+#pragma weak __vdso_gettc
+u_int
+__vdso_gettc(const struct vdso_timehands *th)
+{
+
+ return (0);
+}
+
+#pragma weak __vdso_gettimekeep
+int
+__vdso_gettimekeep(struct vdso_timekeep **tk)
+{
+
+ return (ENOSYS);
+}
diff --git a/lib/libc/quad/Makefile.inc b/lib/libc/quad/Makefile.inc
index 016fa34..9cef22e 100644
--- a/lib/libc/quad/Makefile.inc
+++ b/lib/libc/quad/Makefile.inc
@@ -8,6 +8,10 @@
SRCS+= cmpdi2.c divdi3.c moddi3.c qdivrem.c ucmpdi2.c udivdi3.c umoddi3.c
+.elif ${LIBC_ARCH} == "arm" && ${MK_ARM_EABI} != "no"
+
+SRCS+= adddi3.c anddi3.c floatunsdidf.c iordi3.c lshldi3.c notdi2.c \
+ qdivrem.c subdi3.c xordi3.c
.else
SRCS+= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c fixdfdi.c \
diff --git a/lib/libc/sparc64/Makefile.inc b/lib/libc/sparc64/Makefile.inc
index 76cc8b9..84a0e06 100644
--- a/lib/libc/sparc64/Makefile.inc
+++ b/lib/libc/sparc64/Makefile.inc
@@ -5,6 +5,8 @@
.include "fpu/Makefile.inc"
+SRCS+= __vdso_gettc.c
+
# Long double is quad precision
GDTOASRCS+=strtorQ.c
MDSRCS+=machdep_ldisQ.c
diff --git a/lib/libc/sparc64/sys/__vdso_gettc.c b/lib/libc/sparc64/sys/__vdso_gettc.c
new file mode 100644
index 0000000..b99bbc4
--- /dev/null
+++ b/lib/libc/sparc64/sys/__vdso_gettc.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2013 Konstantin Belousov <kib@FreeBSD.org>
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/vdso.h>
+#include <errno.h>
+
+#pragma weak __vdso_gettc
+u_int
+__vdso_gettc(const struct vdso_timehands *th)
+{
+
+ return (0);
+}
+
+#pragma weak __vdso_gettimekeep
+int
+__vdso_gettimekeep(struct vdso_timekeep **tk)
+{
+
+ return (ENOSYS);
+}
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
index 6570051..bc3b9e5 100644
--- a/lib/libc/stdio/Makefile.inc
+++ b/lib/libc/stdio/Makefile.inc
@@ -8,7 +8,8 @@ SRCS+= _flock_stub.c asprintf.c clrerr.c dprintf.c \
fclose.c fcloseall.c fdopen.c \
feof.c ferror.c fflush.c fgetc.c fgetln.c fgetpos.c fgets.c fgetwc.c \
fgetwln.c fgetws.c \
- fileno.c findfp.c flags.c fopen.c fprintf.c fpurge.c fputc.c fputs.c \
+ fileno.c findfp.c flags.c fmemopen.c fopen.c fprintf.c fpurge.c \
+ fputc.c fputs.c \
fputwc.c fputws.c fread.c freopen.c fscanf.c fseek.c fsetpos.c \
ftell.c funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwscanf.c \
fwrite.c getc.c getchar.c getdelim.c getline.c \
@@ -48,7 +49,7 @@ MLINKS+=ferror.3 ferror_unlocked.3 \
MLINKS+=fflush.3 fpurge.3
MLINKS+=fgets.3 gets.3
MLINKS+=flockfile.3 ftrylockfile.3 flockfile.3 funlockfile.3
-MLINKS+=fopen.3 fdopen.3 fopen.3 freopen.3
+MLINKS+=fopen.3 fdopen.3 fopen.3 freopen.3 fopen.3 fmemopen.3
MLINKS+=fputs.3 puts.3
MLINKS+=fread.3 fwrite.3
MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko.3 fseek.3 fsetpos.3 fseek.3 ftell.3 \
diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map
index cafb0c6..b78de5a 100644
--- a/lib/libc/stdio/Symbol.map
+++ b/lib/libc/stdio/Symbol.map
@@ -155,6 +155,7 @@ FBSD_1.3 {
getwchar_l;
putwc_l;
putwchar_l;
+ fmemopen;
};
FBSDprivate_1.0 {
diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c
new file mode 100644
index 0000000..581a91e
--- /dev/null
+++ b/lib/libc/stdio/fmemopen.c
@@ -0,0 +1,258 @@
+/*-
+ * Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org>
+ *
+ * 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 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 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "local.h"
+
+struct fmemopen_cookie
+{
+ char *buf; /* pointer to the memory region */
+ bool own; /* did we allocate the buffer ourselves? */
+ char bin; /* is this a binary buffer? */
+ size_t size; /* buffer length in bytes */
+ size_t len; /* data length in bytes */
+ size_t off; /* current offset into the buffer */
+};
+
+static int fmemopen_read(void *cookie, char *buf, int nbytes);
+static int fmemopen_write(void *cookie, const char *buf, int nbytes);
+static fpos_t fmemopen_seek(void *cookie, fpos_t offset, int whence);
+static int fmemopen_close(void *cookie);
+
+FILE *
+fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
+{
+ struct fmemopen_cookie *ck;
+ FILE *f;
+ int flags, rc;
+
+ /*
+ * Retrieve the flags as used by open(2) from the mode argument, and
+ * validate them.
+ */
+ rc = __sflags(mode, &flags);
+ if (rc == 0) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * There's no point in requiring an automatically allocated buffer
+ * in write-only mode.
+ */
+ if (!(flags & O_RDWR) && buf == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ ck = malloc(sizeof(struct fmemopen_cookie));
+ if (ck == NULL) {
+ return (NULL);
+ }
+
+ ck->off = 0;
+ ck->size = size;
+
+ /* Check whether we have to allocate the buffer ourselves. */
+ ck->own = ((ck->buf = buf) == NULL);
+ if (ck->own) {
+ ck->buf = malloc(size);
+ if (ck->buf == NULL) {
+ free(ck);
+ return (NULL);
+ }
+ }
+
+ /*
+ * POSIX distinguishes between w+ and r+, in that w+ is supposed to
+ * truncate the buffer.
+ */
+ if (ck->own || mode[0] == 'w') {
+ ck->buf[0] = '\0';
+ }
+
+ /* Check for binary mode. */
+ ck->bin = strchr(mode, 'b') != NULL;
+
+ /*
+ * The size of the current buffer contents is set depending on the
+ * mode:
+ *
+ * for append (text-mode), the position of the first NULL byte, or the
+ * size of the buffer if none is found
+ *
+ * for append (binary-mode), the size of the buffer
+ *
+ * for read, the size of the buffer
+ *
+ * for write, 0
+ */
+ switch (mode[0]) {
+ case 'a':
+ if (ck->bin) {
+ /*
+ * This isn't useful, since the buffer isn't allowed
+ * to grow.
+ */
+ ck->off = ck->len = size;
+ } else
+ ck->off = ck->len = strnlen(ck->buf, ck->size);
+ break;
+ case 'r':
+ ck->len = size;
+ break;
+ case 'w':
+ ck->len = 0;
+ break;
+ }
+
+ f = funopen(ck,
+ flags & O_WRONLY ? NULL : fmemopen_read,
+ flags & O_RDONLY ? NULL : fmemopen_write,
+ fmemopen_seek, fmemopen_close);
+
+ if (f == NULL) {
+ if (ck->own)
+ free(ck->buf);
+ free(ck);
+ return (NULL);
+ }
+
+ /*
+ * Turn off buffering, so a write past the end of the buffer
+ * correctly returns a short object count.
+ */
+ setvbuf(f, NULL, _IONBF, 0);
+
+ return (f);
+}
+
+static int
+fmemopen_read(void *cookie, char *buf, int nbytes)
+{
+ struct fmemopen_cookie *ck = cookie;
+
+ if (nbytes > ck->len - ck->off)
+ nbytes = ck->len - ck->off;
+
+ if (nbytes == 0)
+ return (0);
+
+ memcpy(buf, ck->buf + ck->off, nbytes);
+
+ ck->off += nbytes;
+
+ return (nbytes);
+}
+
+static int
+fmemopen_write(void *cookie, const char *buf, int nbytes)
+{
+ struct fmemopen_cookie *ck = cookie;
+
+ if (nbytes > ck->size - ck->off)
+ nbytes = ck->size - ck->off;
+
+ if (nbytes == 0)
+ return (0);
+
+ memcpy(ck->buf + ck->off, buf, nbytes);
+
+ ck->off += nbytes;
+
+ if (ck->off > ck->len)
+ ck->len = ck->off;
+
+ /*
+ * We append a NULL byte if all these conditions are met:
+ * - the buffer is not binary
+ * - the buffer is not full
+ * - the data just written doesn't already end with a NULL byte
+ */
+ if (!ck->bin && ck->off < ck->size && ck->buf[ck->off - 1] != '\0')
+ ck->buf[ck->off] = '\0';
+
+ return (nbytes);
+}
+
+static fpos_t
+fmemopen_seek(void *cookie, fpos_t offset, int whence)
+{
+ struct fmemopen_cookie *ck = cookie;
+
+
+ switch (whence) {
+ case SEEK_SET:
+ if (offset > ck->size) {
+ errno = EINVAL;
+ return (-1);
+ }
+ ck->off = offset;
+ break;
+
+ case SEEK_CUR:
+ if (ck->off + offset > ck->size) {
+ errno = EINVAL;
+ return (-1);
+ }
+ ck->off += offset;
+ break;
+
+ case SEEK_END:
+ if (offset > 0 || -offset > ck->len) {
+ errno = EINVAL;
+ return (-1);
+ }
+ ck->off = ck->len + offset;
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (ck->off);
+}
+
+static int
+fmemopen_close(void *cookie)
+{
+ struct fmemopen_cookie *ck = cookie;
+
+ if (ck->own)
+ free(ck->buf);
+
+ free(ck);
+
+ return (0);
+}
diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3
index da89ed4..a07be38 100644
--- a/lib/libc/stdio/fopen.3
+++ b/lib/libc/stdio/fopen.3
@@ -32,13 +32,14 @@
.\" @(#)fopen.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd November 30, 2012
+.Dd January 30, 2013
.Dt FOPEN 3
.Os
.Sh NAME
.Nm fopen ,
.Nm fdopen ,
-.Nm freopen
+.Nm freopen ,
+.Nm fmemopen
.Nd stream open functions
.Sh LIBRARY
.Lb libc
@@ -50,6 +51,8 @@
.Fn fdopen "int fildes" "const char *mode"
.Ft FILE *
.Fn freopen "const char *path" "const char *mode" "FILE *stream"
+.Ft FILE *
+.Fn fmemopen "void *restrict *buf" "size_t size" "const char * restrict mode"
.Sh DESCRIPTION
The
.Fn fopen
@@ -115,7 +118,9 @@ after either the
or the first letter.
This is strictly for compatibility with
.St -isoC
-and has no effect; the ``b'' is ignored.
+and has effect only for
+.Fn fmemopen
+; otherwise the ``b'' is ignored.
.Pp
Any created files will have mode
.Do Dv S_IRUSR
@@ -202,6 +207,34 @@ standard text stream
.Dv ( stderr , stdin ,
or
.Dv stdout ) .
+.Pp
+The
+.Fn fmemopen
+function
+associates the buffer given by the
+.Fa buf
+and
+.Fa size
+arguments with a stream.
+The
+.Fa buf
+argument is either a null pointer or point to a buffer that
+is at least
+.Fa size
+bytes long.
+If a null pointer is specified as the
+.Fa buf
+argument,
+.Fn fmemopen
+allocates
+.Fa size
+bytes of memory. This buffer is automatically freed when the
+stream is closed. Buffers can be opened in text-mode (default) or binary-mode
+(if ``b'' is present in the second or third position of the
+.Fa mode
+argument). Buffers opened in text-mode make sure that writes are terminated with
+a NULL byte, if the last write hasn't filled up the whole buffer. Buffers
+opened in binary-mode never append a NULL byte.
.Sh RETURN VALUES
Upon successful completion
.Fn fopen ,
@@ -225,16 +258,18 @@ argument
to
.Fn fopen ,
.Fn fdopen ,
+.Fn freopen ,
or
-.Fn freopen
+.Fn fmemopen
was invalid.
.El
.Pp
The
.Fn fopen ,
-.Fn fdopen
-and
+.Fn fdopen ,
.Fn freopen
+and
+.Fn fmemopen
functions
may also fail and set
.Va errno
@@ -294,3 +329,10 @@ The
.Dq Li e
mode option does not conform to any standard
but is also supported by glibc.
+The
+.Fn fmemopen
+function
+conforms to
+.St -p1003.1-2008 .
+The ``b'' mode does not conform to any standard
+but is also supported by glibc.
diff --git a/lib/libc/sys/__vdso_gettimeofday.c b/lib/libc/sys/__vdso_gettimeofday.c
index 32abb69..a305173 100644
--- a/lib/libc/sys/__vdso_gettimeofday.c
+++ b/lib/libc/sys/__vdso_gettimeofday.c
@@ -79,6 +79,7 @@ binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs)
static struct vdso_timekeep *tk;
+#pragma weak __vdso_gettimeofday
int
__vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
{
@@ -88,7 +89,7 @@ __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
if (tz != NULL)
return (ENOSYS);
if (tk == NULL) {
- error = _elf_aux_info(AT_TIMEKEEP, &tk, sizeof(tk));
+ error = __vdso_gettimekeep(&tk);
if (error != 0 || tk == NULL)
return (ENOSYS);
}
@@ -101,6 +102,7 @@ __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
return (0);
}
+#pragma weak __vdso_clock_gettime
int
__vdso_clock_gettime(clockid_t clock_id, struct timespec *ts)
{
diff --git a/lib/libc/sys/chroot.2 b/lib/libc/sys/chroot.2
index 060d064..36d0364 100644
--- a/lib/libc/sys/chroot.2
+++ b/lib/libc/sys/chroot.2
@@ -92,12 +92,8 @@ system call.
Any other value for
.Ql kern.chroot_allow_open_directories
will bypass the check for open directories
-.Pp
-Upon successful completion, a value of 0 is returned.
-Otherwise,
-a value of -1 is returned and
-.Va errno
-is set to indicate an error.
+.Sh RETURN VALUES
+.Rv -std
.Sh ERRORS
The
.Fn chroot
diff --git a/lib/libc/sys/gettimeofday.c b/lib/libc/sys/gettimeofday.c
index 4cc87e1..5b12523 100644
--- a/lib/libc/sys/gettimeofday.c
+++ b/lib/libc/sys/gettimeofday.c
@@ -41,10 +41,7 @@ __gettimeofday(struct timeval *tv, struct timezone *tz)
{
int error;
- if (__vdso_gettimeofday != NULL && __vdso_gettc != NULL)
- error = __vdso_gettimeofday(tv, tz);
- else
- error = ENOSYS;
+ error = __vdso_gettimeofday(tv, tz);
if (error == ENOSYS)
error = __sys_gettimeofday(tv, tz);
return (error);
diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2
index 63a662f..6ae7914 100644
--- a/lib/libc/sys/kqueue.2
+++ b/lib/libc/sys/kqueue.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 15, 2012
+.Dd January 21, 2013
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -417,7 +417,9 @@ and
facilities, and has a lower precedence.
The filter will record
all attempts to deliver a signal to a process, even if the signal has
-been marked as SIG_IGN.
+been marked as SIG_IGN, except for the
+.Dv SIGCHLD
+signal, which, if ignored, won't be recorded by the filter.
Event notification happens after normal
signal delivery processing.
.Va data
diff --git a/lib/libc/sys/posix_fadvise.2 b/lib/libc/sys/posix_fadvise.2
index f303f42..7a9a648 100644
--- a/lib/libc/sys/posix_fadvise.2
+++ b/lib/libc/sys/posix_fadvise.2
@@ -134,4 +134,4 @@ interface conforms to
The
.Fn posix_fadvise
system call first appeared in
-.Fx 10.0 .
+.Fx 9.1 .
diff --git a/lib/libcompiler_rt/Makefile b/lib/libcompiler_rt/Makefile
index af1fcb6..26ce4f7a 100644
--- a/lib/libcompiler_rt/Makefile
+++ b/lib/libcompiler_rt/Makefile
@@ -136,18 +136,22 @@ SRCF+= adddf3 \
addsf3 \
divdf3 \
divsf3 \
- divsi3 \
extendsfdf2 \
fixdfsi \
fixsfsi \
floatsidf \
floatsisf \
- modsi3 \
muldf3 \
mulsf3 \
subdf3 \
subsf3 \
- truncdfsf2 \
+ truncdfsf2
+.endif
+
+.if ${MACHINE_CPUARCH} != "mips" && \
+ (${MACHINE_CPUARCH} != "arm" || ${MK_ARM_EABI} != "no")
+SRCF+= divsi3 \
+ modsi3 \
udivsi3 \
umodsi3
.endif
@@ -181,6 +185,13 @@ SRCS+= ${file}.c
. endif
.endfor
+.if ${MACHINE_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+SRCS+= aeabi_idivmod.S \
+ aeabi_ldivmod.S \
+ aeabi_uidivmod.S \
+ aeabi_uldivmod.S
+.endif
+
.if ${MACHINE_CPUARCH} != "mips"
. if ${MK_INSTALLLIB} != "no"
SYMLINKS+=libcompiler_rt.a ${LIBDIR}/libgcc.a
diff --git a/lib/libcxxrt/Version.map b/lib/libcxxrt/Version.map
index ca990a0..1fdda27 100644
--- a/lib/libcxxrt/Version.map
+++ b/lib/libcxxrt/Version.map
@@ -209,18 +209,7 @@ CXXABI_1.3 {
"std::type_info::type_info(std::type_info const&)";
"std::type_info::type_info(std::type_info const&)";
- "std::type_info::~type_info()";
- "std::type_info::~type_info()";
- "std::type_info::~type_info()";
"std::type_info::operator=(std::type_info const&)";
- "std::unexpected()";
- "std::get_terminate()";
- "std::set_terminate(void (*)())";
- "std::get_unexpected()";
- "std::set_unexpected(void (*)())";
- "std::set_new_handler(void (*)())";
- "std::uncaught_exception()";
- "std::terminate()";
# Extensions
@@ -243,67 +232,22 @@ CXXABI_1.3.1 {
CXXRT_1.0 {
extern "C++" {
- "std::bad_cast::what() const";
- "std::bad_typeid::what() const";
- "std::bad_alloc::what() const";
- "std::exception::what() const";
"std::type_info::name() const";
"std::type_info::before(std::type_info const&) const";
"std::type_info::operator==(std::type_info const&) const";
"std::type_info::operator!=(std::type_info const&) const";
- "std::bad_typeid::bad_typeid(std::bad_typeid const&)";
- "std::bad_typeid::bad_typeid()";
- "std::bad_typeid::bad_typeid(std::bad_typeid const&)";
- "std::bad_typeid::bad_typeid()";
- "std::bad_typeid::~bad_typeid()";
- "std::bad_typeid::~bad_typeid()";
- "std::bad_typeid::~bad_typeid()";
- "std::bad_typeid::operator=(std::bad_typeid const&)";
"std::bad_cast::bad_cast(std::bad_cast const&)";
"std::bad_cast::bad_cast()";
"std::bad_cast::bad_cast(std::bad_cast const&)";
"std::bad_cast::bad_cast()";
- "std::bad_cast::~bad_cast()";
- "std::bad_cast::~bad_cast()";
- "std::bad_cast::~bad_cast()";
"std::bad_cast::operator=(std::bad_cast const&)";
- "std::bad_alloc::bad_alloc(std::bad_alloc const&)";
- "std::bad_alloc::bad_alloc()";
- "std::bad_alloc::bad_alloc(std::bad_alloc const&)";
- "std::bad_alloc::bad_alloc()";
- "std::bad_alloc::~bad_alloc()";
- "std::bad_alloc::~bad_alloc()";
- "std::bad_alloc::~bad_alloc()";
- "std::bad_alloc::operator=(std::bad_alloc const&)";
"std::exception::exception(std::exception const&)";
"std::exception::exception()";
"std::exception::exception(std::exception const&)";
"std::exception::exception()";
- "std::exception::~exception()";
- "std::exception::~exception()";
- "std::exception::~exception()";
"std::exception::operator=(std::exception const&)";
- "vtable for std::bad_typeid";
- "vtable for std::bad_cast";
- "vtable for std::bad_alloc";
- "vtable for std::exception";
- "vtable for std::type_info";
- "typeinfo for std::bad_typeid";
- "typeinfo for std::bad_cast";
- "typeinfo for std::bad_alloc";
- "typeinfo for std::exception";
- "typeinfo for std::type_info";
- "typeinfo name for std::bad_typeid";
- "typeinfo name for std::bad_cast";
- "typeinfo name for std::bad_alloc";
- "typeinfo name for std::exception";
- "typeinfo name for std::type_info";
-
- "std::type_info::__is_function_p() const";
- "std::type_info::__do_upcast(__cxxabiv1::__class_type_info const*, void**) const";
- "std::type_info::__is_pointer_p() const";
@@ -317,6 +261,7 @@ CXXRT_1.0 {
} CXXABI_1.3.1;
+
GLIBCXX_3.4 {
extern "C++" {
"operator delete[](void*)";
@@ -327,5 +272,50 @@ GLIBCXX_3.4 {
"operator new[](unsigned long)";
"operator new(unsigned long)";
"operator new(unsigned long, std::nothrow_t const&)";
+
+ "std::unexpected()";
+ "std::get_terminate()";
+ "std::get_unexpected()";
+ "std::uncaught_exception()";
+ "std::terminate()";
+
+ "std::type_info::~type_info()";
+ "std::bad_cast::~bad_cast()";
+ "std::exception::~exception()";
+
+ std::set_new_handler*;
+ std::set_terminate*;
+ std::set_unexpected*;
+ std::exception*;
+ std::bad_alloc;
+ std::bad_typeid;
+ std::type_info*;
+
+ "vtable for std::bad_alloc";
+ "vtable for std::bad_cast";
+ "vtable for std::bad_typeid";
+ "vtable for std::exception";
+ "vtable for std::type_info";
+
+ "typeinfo for std::bad_alloc";
+ "typeinfo for std::bad_typeid";
+ "typeinfo for std::exception";
+ "typeinfo for std::bad_cast";
+ "typeinfo for std::exception";
+ "typeinfo for std::type_info";
+ "typeinfo name for std::bad_typeid";
+ "typeinfo name for std::bad_cast";
+ "typeinfo name for std::exception";
+ "typeinfo name for std::type_info";
+
};
};
+
+GLIBCXX_3.4.9 {
+ extern "C++" {
+ "std::bad_typeid::what() const";
+ "std::bad_cast::what() const";
+ "std::bad_alloc::what() const";
+ };
+} GLIBCXX_3.4;
+
diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3
index fe58321..33f7666 100644
--- a/lib/libedit/editline.3
+++ b/lib/libedit/editline.3
@@ -526,8 +526,6 @@ If
is
.Dv NULL ,
try
-.Pa $PWD/.editrc
-then
.Pa $HOME/.editrc .
Refer to
.Xr editrc 5
diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5
index f46b874..6e04ea1 100644
--- a/lib/libedit/editrc.5
+++ b/lib/libedit/editrc.5
@@ -473,6 +473,13 @@ Move down one line.
Editline extended command.
.El
.\" End of section automatically generated with makelist
+.Sh FILES
+.Bl -tag -width "~/.editrcXXX"
+.It Pa ~/.editrc
+User configuration file for the
+.Xr editline 3
+library.
+.El
.Sh SEE ALSO
.Xr editline 3 ,
.Xr regex 3 ,
diff --git a/lib/libpmc/Makefile b/lib/libpmc/Makefile
index f59dc2b..c15d38a 100644
--- a/lib/libpmc/Makefile
+++ b/lib/libpmc/Makefile
@@ -29,6 +29,7 @@ MAN+= pmc.core.3
MAN+= pmc.core2.3
MAN+= pmc.iaf.3
MAN+= pmc.ivybridge.3
+MAN+= pmc.ivybridgexeon.3
MAN+= pmc.ucf.3
MAN+= pmc.k7.3
MAN+= pmc.k8.3
diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c
index 4fb2572..1866e7f 100644
--- a/lib/libpmc/libpmc.c
+++ b/lib/libpmc/libpmc.c
@@ -188,6 +188,11 @@ static const struct pmc_event_descr ivybridge_event_table[] =
__PMC_EV_ALIAS_IVYBRIDGE()
};
+static const struct pmc_event_descr ivybridge_xeon_event_table[] =
+{
+ __PMC_EV_ALIAS_IVYBRIDGE_XEON()
+};
+
static const struct pmc_event_descr sandybridge_event_table[] =
{
__PMC_EV_ALIAS_SANDYBRIDGE()
@@ -233,6 +238,7 @@ PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC);
PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
PMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
+PMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
PMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
@@ -272,6 +278,7 @@ PMC_CLASS_TABLE_DESC(core, IAP, core, iap);
PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap);
PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap);
PMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap);
+PMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap);
PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap);
PMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap);
PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap);
@@ -577,6 +584,8 @@ static struct pmc_event_alias core2_aliases_without_iaf[] = {
#define corei7_aliases_without_iaf core2_aliases_without_iaf
#define ivybridge_aliases core2_aliases
#define ivybridge_aliases_without_iaf core2_aliases_without_iaf
+#define ivybridge_xeon_aliases core2_aliases
+#define ivybridge_xeon_aliases_without_iaf core2_aliases_without_iaf
#define sandybridge_aliases core2_aliases
#define sandybridge_aliases_without_iaf core2_aliases_without_iaf
#define sandybridge_xeon_aliases core2_aliases
@@ -807,7 +816,8 @@ iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
return (-1);
} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE ||
cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON ||
- cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE) {
+ cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE ||
+ cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) {
if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp);
} else
@@ -2684,6 +2694,10 @@ pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
ev = ivybridge_event_table;
count = PMC_EVENT_TABLE_SIZE(ivybridge);
break;
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
+ ev = ivybridge_xeon_event_table;
+ count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon);
+ break;
case PMC_CPU_INTEL_SANDYBRIDGE:
ev = sandybridge_event_table;
count = PMC_EVENT_TABLE_SIZE(sandybridge);
@@ -2983,6 +2997,9 @@ pmc_init(void)
case PMC_CPU_INTEL_IVYBRIDGE:
PMC_MDEP_INIT_INTEL_V2(ivybridge);
break;
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
+ PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon);
+ break;
case PMC_CPU_INTEL_SANDYBRIDGE:
pmc_class_table[n++] = &ucf_class_table_descr;
pmc_class_table[n++] = &sandybridgeuc_class_table_descr;
@@ -3125,6 +3142,10 @@ _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
ev = ivybridge_event_table;
evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge);
break;
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
+ ev = ivybridge_xeon_event_table;
+ evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon);
+ break;
case PMC_CPU_INTEL_SANDYBRIDGE:
ev = sandybridge_event_table;
evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge);
diff --git a/lib/libpmc/pmc.ivybridge.3 b/lib/libpmc/pmc.ivybridge.3
index 9a81da4..7d8bdca 100644
--- a/lib/libpmc/pmc.ivybridge.3
+++ b/lib/libpmc/pmc.ivybridge.3
@@ -853,6 +853,7 @@ Dirty L2 cache lines evicted by the MLC prefetcher.
.Xr pmc.p6 3 ,
.Xr pmc.corei7 3 ,
.Xr pmc.corei7uc 3 ,
+.Xr pmc.ivybridgexeon 3 ,
.Xr pmc.sandybridge 3 ,
.Xr pmc.sandybridgeuc 3 ,
.Xr pmc.sandybridgexeon 3 ,
diff --git a/lib/libpmc/pmc.ivybridgexeon.3 b/lib/libpmc/pmc.ivybridgexeon.3
new file mode 100644
index 0000000..76d5e60
--- /dev/null
+++ b/lib/libpmc/pmc.ivybridgexeon.3
@@ -0,0 +1,911 @@
+.\" Copyright (c) 2013 Hiren Panchasara <hiren.panchasara@gmail.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd Jan 25, 2013
+.Dt PMC.IVYBRIDGEXEON 3
+.Os
+.Sh NAME
+.Nm pmc.ivybridgexeon
+.Nd measurement events for
+.Tn Intel
+.Tn Ivy Bridge Xeon
+family CPUs
+.Sh LIBRARY
+.Lb libpmc
+.Sh SYNOPSIS
+.In pmc.h
+.Sh DESCRIPTION
+.Tn Intel
+.Tn "Ivy Bridge Xeon"
+CPUs contain PMCs conforming to version 2 of the
+.Tn Intel
+performance measurement architecture.
+These CPUs may contain up to three classes of PMCs:
+.Bl -tag -width "Li PMC_CLASS_IAP"
+.It Li PMC_CLASS_IAF
+Fixed-function counters that count only one hardware event per counter.
+.It Li PMC_CLASS_IAP
+Programmable counters that may be configured to count one of a defined
+set of hardware events.
+.El
+.Pp
+The number of PMCs available in each class and their widths need to be
+determined at run time by calling
+.Xr pmc_cpuinfo 3 .
+.Pp
+Intel Ivy Bridge Xeon PMCs are documented in
+.Rs
+.%B "Intel(R) 64 and IA-32 Architectures Software Developer's Manual"
+.%N "Order Number: 325462-045US"
+.%D January 2013
+.%Q "Intel Corporation"
+.Re
+.Ss IVYBRIDGE FIXED FUNCTION PMCS
+These PMCs and their supported events are documented in
+.Xr pmc.iaf 3 .
+.Ss IVYBRIDGE PROGRAMMABLE PMCS
+The programmable PMCs support the following capabilities:
+.Bl -column "PMC_CAP_INTERRUPT" "Support"
+.It Em Capability Ta Em Support
+.It PMC_CAP_CASCADE Ta \&No
+.It PMC_CAP_EDGE Ta Yes
+.It PMC_CAP_INTERRUPT Ta Yes
+.It PMC_CAP_INVERT Ta Yes
+.It PMC_CAP_READ Ta Yes
+.It PMC_CAP_PRECISE Ta \&No
+.It PMC_CAP_SYSTEM Ta Yes
+.It PMC_CAP_TAGGING Ta \&No
+.It PMC_CAP_THRESHOLD Ta Yes
+.It PMC_CAP_USER Ta Yes
+.It PMC_CAP_WRITE Ta Yes
+.El
+.Ss Event Qualifiers
+Event specifiers for these PMCs support the following common
+qualifiers:
+.Bl -tag -width indent
+.It Li rsp= Ns Ar value
+Configure the Off-core Response bits.
+.Bl -tag -width indent
+.It Li REQ_DMND_DATA_RD
+Counts the number of demand and DCU prefetch data reads of full and partial
+cachelines as well as demand data page table entry cacheline reads. Does not
+count L2 data read prefetches or instruction fetches.
+.It Li REQ_DMND_RFO
+Counts the number of demand and DCU prefetch reads for ownership (RFO)
+requests generated by a write to data cacheline. Does not count L2 RFO
+prefetches.
+.It Li REQ_DMND_IFETCH
+Counts the number of demand and DCU prefetch instruction cacheline reads.
+Does not count L2 code read prefetches.
+.It Li REQ_WB
+Counts the number of writeback (modified to exclusive) transactions.
+.It Li REQ_PF_DATA_RD
+Counts the number of data cacheline reads generated by L2 prefetchers.
+.It Li REQ_PF_RFO
+Counts the number of RFO requests generated by L2 prefetchers.
+.It Li REQ_PF_IFETCH
+Counts the number of code reads generated by L2 prefetchers.
+.It Li REQ_PF_LLC_DATA_RD
+L2 prefetcher to L3 for loads.
+.It Li REQ_PF_LLC_RFO
+RFO requests generated by L2 prefetcher
+.It Li REQ_PF_LLC_IFETCH
+L2 prefetcher to L3 for instruction fetches.
+.It Li REQ_BUS_LOCKS
+Bus lock and split lock requests.
+.It Li REQ_STRM_ST
+Streaming store requests.
+.It Li REQ_OTHER
+Any other request that crosses IDI, including I/O.
+.It Li RES_ANY
+Catch all value for any response types.
+.It Li RES_SUPPLIER_NO_SUPP
+No Supplier Information available.
+.It Li RES_SUPPLIER_LLC_HITM
+M-state initial lookup stat in L3.
+.It Li RES_SUPPLIER_LLC_HITE
+E-state.
+.It Li RES_SUPPLIER_LLC_HITS
+S-state.
+.It Li RES_SUPPLIER_LLC_HITF
+F-state.
+.It Li RES_SUPPLIER_LOCAL
+Local DRAM Controller.
+.It Li RES_SNOOP_SNP_NONE
+No details on snoop-related information.
+.It Li RES_SNOOP_SNP_NO_NEEDED
+No snoop was needed to satisfy the request.
+.It Li RES_SNOOP_SNP_MISS
+A snoop was needed and it missed all snooped caches:
+-For LLC Hit, ReslHitl was returned by all cores
+-For LLC Miss, Rspl was returned by all sockets and data was returned from
+DRAM.
+.It Li RES_SNOOP_HIT_NO_FWD
+A snoop was needed and it hits in at least one snooped cache. Hit denotes a
+cache-line was valid before snoop effect. This includes:
+-Snoop Hit w/ Invalidation (LLC Hit, RFO)
+-Snoop Hit, Left Shared (LLC Hit/Miss, IFetch/Data_RD)
+-Snoop Hit w/ Invalidation and No Forward (LLC Miss, RFO Hit S)
+In the LLC Miss case, data is returned from DRAM.
+.It Li RES_SNOOP_HIT_FWD
+A snoop was needed and data was forwarded from a remote socket.
+This includes:
+-Snoop Forward Clean, Left Shared (LLC Hit/Miss, IFetch/Data_RD/RFT).
+.It Li RES_SNOOP_HITM
+A snoop was needed and it HitM-ed in local or remote cache. HitM denotes a
+cache-line was in modified state before effect as a results of snoop. This
+includes:
+-Snoop HitM w/ WB (LLC miss, IFetch/Data_RD)
+-Snoop Forward Modified w/ Invalidation (LLC Hit/Miss, RFO)
+-Snoop MtoS (LLC Hit, IFetch/Data_RD).
+.It Li RES_NON_DRAM
+Target was non-DRAM system address. This includes MMIO transactions.
+.El
+.It Li cmask= Ns Ar value
+Configure the PMC to increment only if the number of configured
+events measured in a cycle is greater than or equal to
+.Ar value .
+.It Li edge
+Configure the PMC to count the number of de-asserted to asserted
+transitions of the conditions expressed by the other qualifiers.
+If specified, the counter will increment only once whenever a
+condition becomes true, irrespective of the number of clocks during
+which the condition remains true.
+.It Li inv
+Invert the sense of comparison when the
+.Dq Li cmask
+qualifier is present, making the counter increment when the number of
+events per cycle is less than the value specified by the
+.Dq Li cmask
+qualifier.
+.It Li os
+Configure the PMC to count events happening at processor privilege
+level 0.
+.It Li usr
+Configure the PMC to count events occurring at privilege levels 1, 2
+or 3.
+.El
+.Pp
+If neither of the
+.Dq Li os
+or
+.Dq Li usr
+qualifiers are specified, the default is to enable both.
+.Ss Event Specifiers (Programmable PMCs)
+Ivy Bridge programmable PMCs support the following events:
+.Bl -tag -width indent
+.It Li LD_BLOCKS.STORE_FORWARD
+.Pq Event 03H , Umask 02H
+loads blocked by overlapping with store buffer that cannot be forwarded .
+.It Li MISALIGN_MEM_REF.LOADS
+.Pq Event 05H , Umask 01H
+Speculative cache-line split load uops dispatched to L1D.
+.It Li MISALIGN_MEM_REF.STORES
+.Pq Event 05H , Umask 02H
+Speculative cache-line split Store- address uops dispatched to L1D.
+.It Li LD_BLOCKS_PARTIAL.ADDRESS_ALIAS
+.Pq Event 07H , Umask 01H
+False dependencies in MOB due to partial compare on address.
+.It Li DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK
+.Pq Event 08H , Umask 81H
+Misses in all TLB levels that cause a page walk of any page size from demand loads.
+.It Li DTLB_LOAD_MISSES.DEMAND_LD_WALK_COMPLETED
+.Pq Event 08H , Umask 82H
+Misses in all TLB levels that caused page walk completed of any size by demand loads.
+.It Li DTLB_LOAD_MISSES.DEMAND_LD_WALK_DURATION
+.Pq Event 08H , Umask 84H
+Cycle PMH is busy with a walk due to demand loads.
+.It Li UOPS_ISSUED.ANY
+.Pq Event 0EH , Umask 01H
+Increments each cycle the # of Uops issued by the RAT to RS.
+Set Cmask = 1, Inv = 1to count stalled cycles.
+Set Cmask = 1, Inv = 1, Any= 1to count stalled cycles of this core.
+.It Li UOPS_ISSUED.FLAGS_MERGE
+.Pq Event 0EH , Umask 10H
+Number of flags-merge uops allocated. Such uops adds delay.
+.It Li UOPS_ISSUED.SLOW_LEA
+.Pq Event 0EH , Umask 20H
+Number of slow LEA or similar uops allocated. Such uop has 3 sources (e.g. 2
+sources + immediate) regardless if as a result of LEA instruction or not.
+.It Li UOPS_ISSUED.SINGLE_MUL
+.Pq Event 0EH , Umask 40H
+Number of multiply packed/scalar single precision uops allocated.
+.It Li ARITH.FPU_DIV_ACTIVE
+.Pq Event 14H , Umask 01H
+Cycles that the divider is active, includes INT and FP. Set 'edge =1,
+cmask=1' to count the number of divides.
+.It Li L2_RQSTS.DEMAND_DATA_RD_HIT
+.Pq Event 24H , Umask 01H
+Demand Data Read requests that hit L2 cache.
+.It Li L2_RQSTS.ALL_DEMAND_DATA_RD
+.Pq Event 24H , Umask 03H
+Counts any demand and L1 HW prefetch data load requests to L2.
+.It Li L2_RQSTS.RFO_HITS
+.Pq Event 24H , Umask 04H
+Counts the number of store RFO requests that hit the L2 cache.
+.It Li L2_RQSTS.RFO_MISS
+.Pq Event 24H , Umask 08H
+Counts the number of store RFO requests that miss the L2 cache.
+.It Li L2_RQSTS.ALL_RFO
+.Pq Event 24H , Umask 0CH
+Counts all L2 store RFO requests.
+.It Li L2_RQSTS.CODE_RD_HIT
+.Pq Event 24H , Umask 10H
+Number of instruction fetches that hit the L2 cache.
+.It Li L2_RQSTS.CODE_RD_MISS
+.Pq Event 24H , Umask 20H
+Number of instruction fetches that missed the L2 cache.
+.It Li L2_RQSTS.ALL_CODE_RD
+.Pq Event 24H , Umask 30H
+Counts all L2 code requests.
+.It Li L2_RQSTS.PF_HIT
+.Pq Event 24H , Umask 40H
+Counts all L2 HW prefetcher requests that hit L2.
+.It Li L2_RQSTS.PF_MISS
+.Pq Event 24H , Umask 80H
+Counts all L2 HW prefetcher requests that missed L2.
+.It Li L2_RQSTS.ALL_PF
+.Pq Event 24H , Umask C0H
+Counts all L2 HW prefetcher requests.
+.It Li L2_STORE_LOCK_RQSTS.MISS
+.Pq Event 27H , Umask 01H
+RFOs that miss cache lines.
+.It Li L2_STORE_LOCK_RQSTS.HIT_M
+.Pq Event 27H , Umask 08H
+RFOs that hit cache lines in M state.
+.It Li L2_STORE_LOCK_RQSTS.ALL
+.Pq Event 27H , Umask 0FH
+RFOs that access cache lines in any state.
+.It Li L2_L1D_WB_RQSTS.MISS
+.Pq Event 28H , Umask 01H
+Not rejected writebacks that missed LLC.
+.It Li L2_L1D_WB_RQSTS.HIT_E
+.Pq Event 28H , Umask 04H
+Not rejected writebacks from L1D to L2 cache lines in E state.
+.It Li L2_L1D_WB_RQSTS.HIT_M
+.Pq Event 28H , Umask 08H
+Not rejected writebacks from L1D to L2 cache lines in M state.
+.It Li L2_L1D_WB_RQSTS.ALL
+.Pq Event 28H , Umask 0FH
+Not rejected writebacks from L1D to L2 cache lines in any state.
+.It Li LONGEST_LAT_CACHE.REFERENCE
+.Pq Event 2EH , Umask 4FH
+This event counts requests originating from the core that reference a cache
+line in the last level cache.
+.It Li LONGEST_LAT_CACHE.MISS
+.Pq Event 2EH , Umask 41H
+This event counts each cache miss condition for references to the last level
+cache.
+.It Li CPU_CLK_UNHALTED.THREAD_P
+.Pq Event 3CH , Umask 00H
+Counts the number of thread cycles while the thread is not in a halt state.
+The thread enters the halt state when it is running the HLT instruction. The
+core frequency may change from time to time due to power or thermal
+throttling.
+.It Li CPU_CLK_THREAD_UNHALTED.REF_XCLK
+.Pq Event 3CH , Umask 01H
+Increments at the frequency of XCLK (100 MHz) when not halted.
+.It Li L1D_PEND_MISS.PENDING
+.Pq Event 48H , Umask 01H
+Increments the number of outstanding L1D misses every cycle. Set Cmaks = 1
+and Edge =1 to count occurrences.
+Counter 2 only.
+Set Cmask = 1 to count cycles.
+.It Li DTLB_STORE_MISSES.MISS_CAUSES_A_WALK
+.Pq Event 49H , Umask 01H
+Miss in all TLB levels causes an page walk of any page size (4K/2M/4M/1G).
+.It Li DTLB_STORE_MISSES.WALK_COMPLETED
+.Pq Event 49H , Umask 02H
+Miss in all TLB levels causes a page walk that completes of any page size
+(4K/2M/4M/1G).
+.It Li DTLB_STORE_MISSES.WALK_DURATION
+.Pq Event 49H , Umask 04H
+Cycles PMH is busy with this walk.
+.It Li DTLB_STORE_MISSES.STLB_HIT
+.Pq Event 49H , Umask 10H
+Store operations that miss the first TLB level but hit the second and do not
+cause page walks.
+.It Li LOAD_HIT_PRE.SW_PF
+.Pq Event 4CH , Umask 01H
+Non-SW-prefetch load dispatches that hit fill buffer allocated for S/W prefetch.
+.It Li LOAD_HIT_PRE.HW_PF
+.Pq Event 4CH , Umask 02H
+Non-SW-prefetch load dispatches that hit fill buffer allocated for H/W prefetch.
+.It Li L1D.REPLACEMENT
+.Pq Event 51H , Umask 01H
+Counts the number of lines brought into the L1 data cache.
+.It Li MOVE_ELIMINATION.INT_NOT_ELIMINATED
+.Pq Event 58H , Umask 01H
+Number of integer Move Elimination candidate uops that were not eliminated.
+.It Li MOVE_ELIMINATION.SIMD_NOT_ELIMINATED
+.Pq Event 58H , Umask 02H
+Number of SIMD Move Elimination candidate uops that were not eliminated.
+.It Li MOVE_ELIMINATION.INT_ELIMINATED
+.Pq Event 58H , Umask 04H
+Number of integer Move Elimination candidate uops that were eliminated.
+.It Li MOVE_ELIMINATION.SIMD_ELIMINATED
+.Pq Event 58H , Umask 08H
+Number of SIMD Move Elimination candidate uops that were eliminated.
+.It Li CPL_CYCLES.RING0
+.Pq Event 5CH , Umask 01H
+Unhalted core cycles when the thread is in ring 0.
+Use Edge to count transition.
+.It Li CPL_CYCLES.RING123
+.Pq Event 5CH , Umask 02H
+Unhalted core cycles when the thread is not in ring 0.
+.It Li RS_EVENTS.EMPTY_CYCLES
+.Pq Event 5EH , Umask 01H
+Cycles the RS is empty for the thread.
+.It Li DTLB_LOAD_MISSES.STLB_HIT
+.Pq Event 5FH , Umask 04H
+Counts load operations that missed 1st level DTLB but hit the 2nd level.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD
+.Pq Event 60H , Umask 01H
+Offcore outstanding Demand Data Read transactions in SQ to uncore. Set
+Cmask=1 to count cycles.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD
+.Pq Event 60H , Umask 02H
+Offcore outstanding Demand Code Read transactions in SQ to uncore. Set
+Cmask=1 to count cycles.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO
+.Pq Event 60H , Umask 04H
+Offcore outstanding RFO store transactions in SQ to uncore. Set Cmask=1 to
+count cycles.
+.It Li OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD
+.Pq Event 60H , Umask 08H
+Offcore outstanding cacheable data read transactions in SQ to uncore. Set
+Cmask=1 to count cycles.
+.It Li LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION
+.Pq Event 63H , Umask 01H
+Cycles in which the L1D and L2 are locked, due to a UC lock or split lock.
+.It Li LOCK_CYCLES.CACHE_LOCK_DURATION
+.Pq Event 63H , Umask 02H
+Cycles in which the L1D is locked.
+.It Li IDQ.EMPTY
+.Pq Event 79H , Umask 02H
+Counts cycles the IDQ is empty.
+.It Li IDQ.MITE_UOPS
+.Pq Event 79H , Umask 04H
+Increment each cycle # of uops delivered to IDQ from MITE path.
+Can combine Umask 04H and 20H.
+Set Cmask = 1 to count cycles.
+.It Li IDQ.DSB_UOPS
+.Pq Event 79H , Umask 08H
+Increment each cycle. # of uops delivered to IDQ from DSB path.
+Can combine Umask 08H and 10H
+Set Cmask = 1 to count cycles.
+.It Li IDQ.MS_DSB_UOPS
+.Pq Event 79H , Umask 10H
+Increment each cycle # of uops delivered to IDQ when MS_busy by DSB. Set
+Cmask = 1 to count cycles. Add Edge=1 to count # of delivery.
+Can combine Umask 04H, 08H.
+.It Li IDQ.MS_MITE_UOPS
+.Pq Event 79H , Umask 20H
+Increment each cycle # of uops delivered to IDQ when MS_busy by MITE. Set
+Cmask = 1 to count cycles.
+Can combine Umask 04H, 08H.
+.It Li IDQ.MS_UOPS
+.Pq Event 79H , Umask 30H
+Increment each cycle # of uops delivered to IDQ from MS by either DSB or
+MITE. Set Cmask = 1 to count cycles.
+Can combine Umask 04H, 08H.
+.It Li IDQ.ALL_DSB_CYCLES_ANY_UOPS
+.Pq Event 79H , Umask 18H
+Counts cycles DSB is delivered at least one uops. Set Cmask = 1.
+.It Li IDQ.ALL_DSB_CYCLES_4_UOPS
+.Pq Event 79H , Umask 18H
+Counts cycles DSB is delivered four uops. Set Cmask = 4.
+.It Li IDQ.ALL_MITE_CYCLES_ANY_UOPS
+.Pq Event 79H , Umask 24H
+Counts cycles MITE is delivered at least one uops. Set Cmask = 1.
+.It Li IDQ.ALL_MITE_CYCLES_4_UOPS
+.Pq Event 79H , Umask 24H
+Counts cycles MITE is delivered four uops. Set Cmask = 4.
+.It Li IDQ.MITE_ALL_UOPS
+.Pq Event 79H , Umask 3CH
+# of uops delivered to IDQ from any path.
+.It Li ICACHE.MISSES
+.Pq Event 80H , Umask 02H
+Number of Instruction Cache, Streaming Buffer and Victim Cache Misses.
+Includes UC accesses.
+.It Li ITLB_MISSES.MISS_CAUSES_A_WALK
+.Pq Event 85H , Umask 01H
+Misses in all ITLB levels that cause page walks.
+.It Li ITLB_MISSES.WALK_COMPLETED
+.Pq Event 85H , Umask 02H
+Misses in all ITLB levels that cause completed page walks.
+.It Li ITLB_MISSES.WALK_DURATION
+.Pq Event 85H , Umask 04H
+Cycle PMH is busy with a walk.
+.It Li ITLB_MISSES.STLB_HIT
+.Pq Event 85H , Umask 10H
+Number of cache load STLB hits. No page walk.
+.It Li ILD_STALL.LCP
+.Pq Event 87H , Umask 01H
+Stalls caused by changing prefix length of the instruction.
+.It Li ILD_STALL.IQ_FULL
+.Pq Event 87H , Umask 04H
+Stall cycles due to IQ is full.
+.It Li BR_INST_EXEC.COND
+.Pq Event 88H , Umask 01H
+Qualify conditional near branch instructions executed, but not necessarily
+retired.
+Must combine with umask 40H, 80H.
+.It Li BR_INST_EXEC.DIRECT_JMP
+.Pq Event 88H , Umask 02H
+Qualify all unconditional near branch instructions excluding calls and
+indirect branches.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.INDIRECT_JMP_NON_CALL_RET
+.Pq Event 88H , Umask 04H
+Qualify executed indirect near branch instructions that are not calls nor
+returns.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.RETURN_NEAR
+.Pq Event 88H , Umask 08H
+Qualify indirect near branches that have a return mnemonic.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.DIRECT_NEAR_CALL
+.Pq Event 88H , Umask 10H
+Qualify unconditional near call branch instructions, excluding non call
+branch, executed.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.INDIRECT_NEAR_CALL
+.Pq Event 88H , Umask 20H
+Qualify indirect near calls, including both register and memory indirect,
+executed.
+Must combine with umask 80H.
+.It Li BR_INST_EXEC.NONTAKEN
+.Pq Event 88H , Umask 40H
+Qualify non-taken near branches executed.
+Applicable to umask 01H only.
+.It Li BR_INST_EXEC.TAKEN
+.Pq Event 88H , Umask 80H
+Qualify taken near branches executed. Must combine with 01H,02H, 04H, 08H,
+10H, 20H.
+.It Li BR_INST_EXEC.ALL_BRANCHES
+.Pq Event 88H , Umask FFH
+Counts all near executed branches (not necessarily retired).
+.It Li BR_MISP_EXEC.COND
+.Pq Event 89H , Umask 01H
+Qualify conditional near branch instructions mispredicted.
+Must combine with umask 40H, 80H.
+.It Li BR_MISP_EXEC.INDIRECT_JMP_NON_CALL_RET
+.Pq Event 89H , Umask 04H
+Qualify mispredicted indirect near branch instructions that are not calls
+nor returns.
+Must combine with umask 80H.
+.It Li BR_MISP_EXEC.RETURN_NEAR
+.Pq Event 89H , Umask 08H
+Qualify mispredicted indirect near branches that have a return mnemonic.
+Must combine with umask 80H.
+.It Li BR_MISP_EXEC.DIRECT_NEAR_CALL
+.Pq Event 89H , Umask 10H
+Qualify mispredicted unconditional near call branch instructions, excluding
+non call branch, executed.
+Must combine with umask 80H.
+.It Li BR_MISP_EXEC.INDIRECT_NEAR_CALL
+.Pq Event 89H , Umask 20H
+Qualify mispredicted indirect near calls, including both register and memory
+indirect, executed.
+Must combine with umask 80H.
+.It Li BR_MISP_EXEC.NONTAKEN
+.Pq Event 89H , Umask 40H
+Qualify mispredicted non-taken near branches executed.
+Applicable to umask 01H only.
+.It Li BR_MISP_EXEC.TAKEN
+.Pq Event 89H , Umask 80H
+Qualify mispredicted taken near branches executed. Must combine with
+01H,02H, 04H, 08H, 10H, 20H.
+.It Li BR_MISP_EXEC.ALL_BRANCHES
+.Pq Event 89H , Umask FFH
+Counts all near executed branches (not necessarily retired).
+.It Li IDQ_UOPS_NOT_DELIVERED.CORE
+.Pq Event 9CH , Umask 01H
+Count number of non-delivered uops to RAT per thread.
+Use Cmask to qualify uop b/w.
+.It Li UOPS_DISPATCHED_PORT.PORT_0
+.Pq Event A1H , Umask 01H
+Cycles which a Uop is dispatched on port 0.
+.It Li UOPS_DISPATCHED_PORT.PORT_1
+.Pq Event A1H , Umask 02H
+Cycles which a Uop is dispatched on port 1.
+.It Li UOPS_DISPATCHED_PORT.PORT_2_LD
+.Pq Event A1H , Umask 04H
+Cycles which a load uop is dispatched on port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_2_STA
+.Pq Event A1H , Umask 08H
+Cycles which a store address uop is dispatched on port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_2
+.Pq Event A1H , Umask 0CH
+Cycles which a Uop is dispatched on port 2.
+.It Li UOPS_DISPATCHED_PORT.PORT_3_LD
+.Pq Event A1H , Umask 10H
+Cycles which a load uop is dispatched on port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_3_STA
+.Pq Event A1H , Umask 20H
+Cycles which a store address uop is dispatched on port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_3
+.Pq Event A1H , Umask 30H
+Cycles which a Uop is dispatched on port 3.
+.It Li UOPS_DISPATCHED_PORT.PORT_4
+.Pq Event A1H , Umask 40H
+Cycles which a Uop is dispatched on port 4.
+.It Li UOPS_DISPATCHED_PORT.PORT_5
+.Pq Event A1H , Umask 80H
+Cycles which a Uop is dispatched on port 5.
+.It Li RESOURCE_STALLS.ANY
+.Pq Event A2H , Umask 01H
+Cycles Allocation is stalled due to Resource Related reason.
+.It Li RESOURCE_STALLS.RS
+.Pq Event A2H , Umask 04H
+Cycles stalled due to no eligible RS entry available.
+.It Li RESOURCE_STALLS.SB
+.Pq Event A2H , Umask 08H
+Cycles stalled due to no store buffers available. (not including draining
+form sync).
+.It Li RESOURCE_STALLS.ROB
+.Pq Event A2H , Umask 10H
+Cycles stalled due to re-order buffer full.
+.It Li CYCLE_ACTIVITY.CYCLES_L2_PENDING
+.Pq Event A3H , Umask 01H
+Cycles with pending L2 miss loads. Set AnyThread to count per core.
+.It Li CYCLE_ACTIVITY.CYCLES_LDM_PENDING
+.Pq Event A3H , Umask 02H
+Cycles with pending memory loads. Set AnyThread to count per core.
+.It Li CYCLE_ACTIVITY.CYCLES_NO_EXECUTE
+.Pq Event A3H , Umask 04H
+Cycles of dispatch stalls. Set AnyThread to count per core.
+.It Li CYCLE_ACTIVITY.CYCLES_L1D_PENDING
+.Pq Event A3H , Umask 08H
+Cycles with pending L1 cache miss loads. Set AnyThread to count per core.
+.It Li DSB2MITE_SWITCHES.COUNT
+.Pq Event ABH , Umask 01H
+Number of DSB to MITE switches.
+.It Li DSB2MITE_SWITCHES.PENALTY_CYCLES
+.Pq Event ABH , Umask 02H
+Cycles DSB to MITE switches caused delay.
+.It Li DSB_FILL.EXCEED_DSB_LINES
+.Pq Event ACH , Umask 08H
+DSB Fill encountered > 3 DSB lines.
+.It Li ITLB.ITLB_FLUSH
+.Pq Event AEH , Umask 01H
+Counts the number of ITLB flushes, includes 4k/2M/4M pages.
+.It Li OFFCORE_REQUESTS.DEMAND_DATA_RD
+.Pq Event B0H , Umask 01H
+Demand data read requests sent to uncore.
+.It Li OFFCORE_REQUESTS.DEMAND_CODE_RD
+.Pq Event B0H , Umask 02H
+Demand code read requests sent to uncore.
+.It Li OFFCORE_REQUESTS.DEMAND_RFO
+.Pq Event B0H , Umask 04H
+Demand RFO read requests sent to uncore, including regular RFOs, locks,
+ItoM.
+.It Li OFFCORE_REQUESTS.ALL_DATA_RD
+.Pq Event B0H , Umask 08H
+Data read requests sent to uncore (demand and prefetch).
+.It Li UOPS_EXECUTED.THREAD
+.Pq Event B1H , Umask 01H
+Counts total number of uops to be executed per-thread each cycle. Set Cmask
+= 1, INV =1 to count stall cycles.
+.It Li UOPS_EXECUTED.CORE
+.Pq Event B1H , Umask 02H
+Counts total number of uops to be executed per-core each cycle.
+Do not need to set ANY.
+.It Li OFF_CORE_RESPONSE_0
+.Pq Event B7H , Umask 01H
+Off-core Response Performance Monitoring.
+PMC0 only.
+Requires programming MSR 01A6H.
+.It Li OFF_CORE_RESPONSE_1
+.Pq Event BBH , Umask 01H
+Off-core Response Performance Monitoring.
+PMC3 only.
+Requires programming MSR 01A7H.
+.It Li TLB_FLUSH.DTLB_THREAD
+.Pq Event BDH , Umask 01H
+DTLB flush attempts of the thread- specific entries.
+.It Li TLB_FLUSH.STLB_ANY
+.Pq Event BDH , Umask 20H
+Count number of STLB flush attempts.
+.It Li INST_RETIRED.ANY_P
+.Pq Event C0H , Umask 00H
+Number of instructions at retirement.
+.It Li INST_RETIRED.ALL
+.Pq Event C0H , Umask 01H
+Precise instruction retired event with HW to reduce effect of PEBS shadow in
+IP distribution.
+PMC1 only.
+Must quiesce other PMCs.
+.It Li OTHER_ASSISTS.AVX_STORE
+.Pq Event C1H , Umask 08H
+Number of assists associated with 256-bit AVX store operations.
+.It Li OTHER_ASSISTS.AVX_TO_SSE
+.Pq Event C1H , Umask 10H
+Number of transitions from AVX- 256 to legacy SSE when penalty applicable.
+.It Li OTHER_ASSISTS.SSE_TO_AVX
+.Pq Event C1H , Umask 20H
+Number of transitions from SSE to AVX-256 when penalty applicable.
+.It Li UOPS_RETIRED.ALL
+.Pq Event C2H , Umask 01H
+Counts the number of micro-ops retired, Use cmask=1 and invert to count
+active cycles or stalled cycles.
+Supports PEBS, use Any=1 for core granular.
+.It Li UOPS_RETIRED.RETIRE_SLOTS
+.Pq Event C2H , Umask 02H
+Counts the number of retirement slots used each cycle.
+.It Li MACHINE_CLEARS.MEMORY_ORDERING
+.Pq Event C3H , Umask 02H
+Counts the number of machine clears due to memory order conflicts.
+.It Li MACHINE_CLEARS.SMC
+.Pq Event C3H , Umask 04H
+Number of self-modifying-code machine clears detected.
+.It Li MACHINE_CLEARS.MASKMOV
+.Pq Event C3H , Umask 20H
+Counts the number of executed AVX masked load operations that refer to an
+illegal address range with the mask bits set to 0.
+.It Li BR_INST_RETIRED.ALL_BRANCHES
+.Pq Event C4H , Umask 00H
+Branch instructions at retirement.
+.It Li BR_INST_RETIRED.CONDITIONAL
+.Pq Event C4H , Umask 01H
+Counts the number of conditional branch instructions retired.
+Supports PEBS.
+.It Li BR_INST_RETIRED.NEAR_CALL
+.Pq Event C4H , Umask 02H
+Direct and indirect near call instructions retired.
+.It Li BR_INST_RETIRED.ALL_BRANCHES
+.Pq Event C4H , Umask 04H
+Counts the number of branch instructions retired.
+.It Li BR_INST_RETIRED.NEAR_RETURN
+.Pq Event C4H , Umask 08H
+Counts the number of near return instructions retired.
+.It Li BR_INST_RETIRED.NOT_TAKEN
+.Pq Event C4H , Umask 10H
+Counts the number of not taken branch instructions retired.
+.It Li BR_INST_RETIRED.NEAR_TAKEN
+.Pq Event C4H , Umask 20H
+Number of near taken branches retired.
+.It Li BR_INST_RETIRED.FAR_BRANCH
+.Pq Event C4H , Umask 40H
+Number of far branches retired.
+.It Li BR_MISP_RETIRED.ALL_BRANCHES
+.Pq Event C5H , Umask 00H
+Mispredicted branch instructions at retirement.
+.It Li BR_MISP_RETIRED.CONDITIONAL
+.Pq Event C5H , Umask 01H
+Mispredicted conditional branch instructions retired.
+Supports PEBS.
+.It Li BR_MISP_RETIRED.NEAR_CALL
+.Pq Event C5H , Umask 02H
+Direct and indirect mispredicted near call instructions retired.
+.It Li BR_MISP_RETIRED.ALL_BRANCHES
+.Pq Event C5H , Umask 04H
+Mispredicted macro branch instructions retired.
+.It Li BR_MISP_RETIRED.NOT_TAKEN
+.Pq Event C5H , Umask 10H
+Mispredicted not taken branch instructions retired.
+.It Li BR_MISP_RETIRED.TAKEN
+.Pq Event C5H , Umask 20H
+Mispredicted taken branch instructions retired.
+.It Li FP_ASSIST.X87_OUTPUT
+.Pq Event CAH , Umask 02H
+Number of X87 FP assists due to Output values.
+.It Li FP_ASSIST.X87_INPUT
+.Pq Event CAH , Umask 04H
+Number of X87 FP assists due to input values.
+.It Li FP_ASSIST.SIMD_OUTPUT
+.Pq Event CAH , Umask 08H
+Number of SIMD FP assists due to Output values.
+.It Li FP_ASSIST.SIMD_INPUT
+.Pq Event CAH , Umask 10H
+Number of SIMD FP assists due to input values.
+.It Li FP_ASSIST.ANY
+.Pq Event CAH , Umask 1EH
+Cycles with any input/output SSE* or FP assists.
+.It Li ROB_MISC_EVENTS.LBR_INSERTS
+.Pq Event CCH , Umask 20H
+Count cases of saving new LBR records by hardware.
+.It Li MEM_TRANS_RETIRED.LOAD_LATENCY
+.Pq Event CDH , Umask 01H
+Sample loads with specified latency threshold.
+PMC3 only.
+Specify threshold in MSR 0x3F6.
+.It Li MEM_TRANS_RETIRED.PRECISE_STORE
+.Pq Event CDH , Umask 02H
+Sample stores and collect precise store operation via PEBS record.
+PMC3 only.
+.It Li MEM_UOP_RETIRED.LOADS
+.Pq Event D0H , Umask 01H
+Qualify retired memory uops that are loads. Combine with umask 10H, 20H,
+40H, 80H.
+Supports PEBS.
+.It Li MEM_UOP_RETIRED.STORES
+.Pq Event D0H , Umask 02H
+Qualify retired memory uops that are stores. Combine with umask 10H, 20H,
+40H, 80H.
+.It Li MEM_UOP_RETIRED.STLB_MISS
+.Pq Event D0H , Umask 10H
+Qualify retired memory uops with STLB miss. Must combine with umask 01H,
+02H, to produce counts.
+.It Li MEM_UOP_RETIRED.LOCK
+.Pq Event D0H , Umask 20H
+Qualify retired memory uops with lock. Must combine with umask 01H, 02H, to
+produce counts.
+.It Li MEM_UOP_RETIRED.SPLIT
+.Pq Event D0H , Umask 40H
+Qualify retired memory uops with line split. Must combine with umask 01H,
+02H, to produce counts.
+.It Li MEM_UOP_RETIRED.ALL
+.Pq Event D0H , Umask 80H
+Qualify any retired memory uops. Must combine with umask 01H, 02H, to
+produce counts.
+.It Li MEM_LOAD_UOPS_RETIRED.L1_HIT
+.Pq Event D1H , Umask 01H
+Retired load uops with L1 cache hits as data sources.
+Supports PEBS.
+.It Li MEM_LOAD_UOPS_RETIRED.L2_HIT
+.Pq Event D1H , Umask 02H
+Retired load uops with L2 cache hits as data sources.
+.It Li MEM_LOAD_UOPS_RETIRED.LLC_HIT
+.Pq Event D1H , Umask 04H
+Retired load uops whose data source was LLC hit with no snoop required.
+.It Li MEM_LOAD_UOPS_RETIRED.LLC_MISS
+.Pq Event D1H , Umask 20H
+Retired load uops whose data source is LLC miss.
+.It Li MEM_LOAD_UOPS_RETIRED.HIT_LFB
+.Pq Event D1H , Umask 40H
+Retired load uops which data sources were load uops missed L1 but hit FB due
+to preceding miss to the same cache line with data not ready.
+.It Li MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS
+.Pq Event D2H , Umask 01H
+Retired load uops which data sources were LLC hit and cross-core snoop
+missed in on-pkg core cache.
+Supports PEBS.
+.It Li MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT
+.Pq Event D2H , Umask 02H
+Retired load uops which data sources were LLC and cross-core snoop hits in
+on-pkg core cache.
+Supports PEBS.
+.It Li MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM
+.Pq Event D2H , Umask 04H
+Retired load uops which data sources were HitM responses from shared LLC.
+.It Li MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE
+.Pq Event D2H , Umask 08H
+Retired load uops which data sources were hits in LLC without snoops
+required.
+.It Li MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM
+.Pq Event D3H , Umask 01H
+Retired load uops which data sources missed LLC but serviced from local
+dram.
+Supports PEBS.
+.It Li MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_DRAM
+.Pq Event D3H , Umask 04H
+Retired load uops whose data source was remote DRAM.
+.It Li MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_HITM
+.Pq Event D3H , Umask 10H
+Retired load uops whose data source was remote HITM.
+.It Li MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_FWD
+.Pq Event D3H , Umask 20H
+Retired load uops whose data source was forwards from a remote cache.
+.It Li BACLEARS.ANY
+.Pq Event E6H , Umask 1FH
+Number of front end re-steers due to BPU misprediction.
+.It Li L2_TRANS.DEMAND_DATA_RD
+.Pq Event F0H , Umask 01H
+Demand Data Read requests that access L2 cache.
+.It Li L2_TRANS.RFO
+.Pq Event F0H , Umask 02H
+RFO requests that access L2 cache.
+.It Li L2_TRANS.CODE_RD
+.Pq Event F0H , Umask 04H
+L2 cache accesses when fetching instructions.
+.It Li L2_TRANS.ALL_PF
+.Pq Event F0H , Umask 08H
+Any MLC or LLC HW prefetch accessing L2, including rejects.
+.It Li L2_TRANS.L1D_WB
+.Pq Event F0H , Umask 10H
+L1D writebacks that access L2 cache.
+.It Li L2_TRANS.L2_FILL
+.Pq Event F0H , Umask 20H
+L2 fill requests that access L2 cache.
+.It Li L2_TRANS.L2_WB
+.Pq Event F0H , Umask 40H
+L2 writebacks that access L2 cache.
+.It Li L2_TRANS.ALL_REQUESTS
+.Pq Event F0H , Umask 80H
+Transactions accessing L2 pipe.
+.It Li L2_LINES_IN.I
+.Pq Event F1H , Umask 01H
+L2 cache lines in I state filling L2.
+Counting does not cover rejects.
+.It Li L2_LINES_IN.S
+.Pq Event F1H , Umask 02H
+L2 cache lines in S state filling L2.
+Counting does not cover rejects.
+.It Li L2_LINES_IN.E
+.Pq Event F1H , Umask 04H
+L2 cache lines in E state filling L2.
+Counting does not cover rejects.
+.It Li L2_LINES_IN.ALL
+.Pq Event F1H , Umask 07H
+L2 cache lines filling L2.
+Counting does not cover rejects.
+.It Li L2_LINES_OUT.DEMAND_CLEAN
+.Pq Event F2H , Umask 01H
+Clean L2 cache lines evicted by demand.
+.It Li L2_LINES_OUT.DEMAND_DIRTY
+.Pq Event F2H , Umask 02H
+Dirty L2 cache lines evicted by demand.
+.It Li L2_LINES_OUT.PF_CLEAN
+.Pq Event F2H , Umask 04H
+Clean L2 cache lines evicted by the MLC prefetcher.
+.It Li L2_LINES_OUT.PF_DIRTY
+.Pq Event F2H , Umask 08H
+Dirty L2 cache lines evicted by the MLC prefetcher.
+.It Li L2_LINES_OUT.DIRTY_ALL
+.Pq Event F2H , Umask 0AH
+Dirty L2 cache lines filling the L2.
+.El
+.Sh SEE ALSO
+.Xr pmc 3 ,
+.Xr pmc.atom 3 ,
+.Xr pmc.core 3 ,
+.Xr pmc.iaf 3 ,
+.Xr pmc.ucf 3 ,
+.Xr pmc.k7 3 ,
+.Xr pmc.k8 3 ,
+.Xr pmc.p4 3 ,
+.Xr pmc.p5 3 ,
+.Xr pmc.p6 3 ,
+.Xr pmc.corei7 3 ,
+.Xr pmc.corei7uc 3 ,
+.Xr pmc.ivybridge 3 ,
+.Xr pmc.sandybridge 3 ,
+.Xr pmc.sandybridgeuc 3 ,
+.Xr pmc.sandybridgexeon 3 ,
+.Xr pmc.westmere 3 ,
+.Xr pmc.westmereuc 3 ,
+.Xr pmc.soft 3 ,
+.Xr pmc.tsc 3 ,
+.Xr pmc_cpuinfo 3 ,
+.Xr pmclog 3 ,
+.Xr hwpmc 4
+.Sh HISTORY
+The
+.Nm pmc
+library first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+The
+.Lb libpmc
+library was written by
+.An "Joseph Koshy"
+.Aq jkoshy@FreeBSD.org .
+The support for the Ivy Bridge Xeon
+microarchitecture was written by
+.An "Hiren Panchasara"
+.Aq hiren.panchasara@gmail.com .
diff --git a/lib/libpmc/pmc.sandybridge.3 b/lib/libpmc/pmc.sandybridge.3
index 62f8f28..931bd9d 100644
--- a/lib/libpmc/pmc.sandybridge.3
+++ b/lib/libpmc/pmc.sandybridge.3
@@ -926,6 +926,8 @@ Split locks in SQ.
.Xr pmc.corei7 3 ,
.Xr pmc.corei7uc 3 ,
.Xr pmc.iaf 3 ,
+.Xr pmc.ivybridge 3 ,
+.Xr pmc.ivybridgexeon 3 ,
.Xr pmc.k7 3 ,
.Xr pmc.k8 3 ,
.Xr pmc.p4 3 ,
diff --git a/lib/libpmc/pmc.sandybridgexeon.3 b/lib/libpmc/pmc.sandybridgexeon.3
index c62a82b..0ddaeda 100644
--- a/lib/libpmc/pmc.sandybridgexeon.3
+++ b/lib/libpmc/pmc.sandybridgexeon.3
@@ -997,6 +997,7 @@ Split locks in SQ.
.Xr pmc.corei7 3 ,
.Xr pmc.corei7uc 3 ,
.Xr pmc.ivybridge 3 ,
+.Xr pmc.ivybridgexeon 3 ,
.Xr pmc.sandybridge 3 ,
.Xr pmc.sandybridgeuc 3 ,
.Xr pmc.westmere 3 ,
diff --git a/lib/libproc/proc_rtld.c b/lib/libproc/proc_rtld.c
index 2a9ed39..5259049 100644
--- a/lib/libproc/proc_rtld.c
+++ b/lib/libproc/proc_rtld.c
@@ -44,7 +44,8 @@ map_iter(const rd_loadobj_t *lop, void *arg)
if (phdl->nobjs >= phdl->rdobjsz) {
phdl->rdobjsz *= 2;
- phdl->rdobjs = realloc(phdl->rdobjs, phdl->rdobjsz);
+ phdl->rdobjs = reallocf(phdl->rdobjs, sizeof(*phdl->rdobjs) *
+ phdl->rdobjsz);
if (phdl->rdobjs == NULL)
return (-1);
}
diff --git a/lib/libradius/libradius.3 b/lib/libradius/libradius.3
index 253659c..f3ff700 100644
--- a/lib/libradius/libradius.3
+++ b/lib/libradius/libradius.3
@@ -38,7 +38,7 @@
.Ft int
.Fn rad_add_server "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries"
.Ft int
-.Fn rad_add_server_ex "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries" "int dead_time" "struct in_addr bindto"
+.Fn rad_add_server_ex "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries" "int dead_time" "struct in_addr *bindto"
.Ft "struct rad_handle *"
.Fn rad_auth_open "void"
.Ft void
diff --git a/lib/libstand/if_ether.h b/lib/libstand/if_ether.h
deleted file mode 100644
index 373f95a..0000000
--- a/lib/libstand/if_ether.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/* $NetBSD: if_ether.h,v 1.25 1997/01/17 17:06:06 mikel Exp $ */
-
-/*
- * Copyright (c) 1982, 1986, 1993
- * The Regents of the University of California. 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.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)if_ether.h 8.1 (Berkeley) 6/10/93
- *
- * $FreeBSD$
- */
-
-/*
- * Ethernet address - 6 octets
- * this is only used by the ethers(3) functions.
- */
-struct ether_addr {
- u_int8_t ether_addr_octet[6];
-};
-
-/*
- * Structure of a 10Mb/s Ethernet header.
- */
-#define ETHER_ADDR_LEN 6
-
-struct ether_header {
- u_int8_t ether_dhost[ETHER_ADDR_LEN];
- u_int8_t ether_shost[ETHER_ADDR_LEN];
- u_int16_t ether_type;
-};
-
-#define ETHERTYPE_PUP 0x0200 /* PUP protocol */
-#define ETHERTYPE_IP 0x0800 /* IP protocol */
-#define ETHERTYPE_ARP 0x0806 /* address resolution protocol */
-#define ETHERTYPE_REVARP 0x8035 /* reverse addr resolution protocol */
-
-/*
- * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
- * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
- * by an ETHER type (as given above) and then the (variable-length) header.
- */
-#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */
-#define ETHERTYPE_NTRAILER 16
-
-#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */
-
-#define ETHERMTU 1500
-#define ETHERMIN (60-14)
-
-#ifdef _KERNEL
-/*
- * Macro to map an IP multicast address to an Ethernet multicast address.
- * The high-order 25 bits of the Ethernet address are statically assigned,
- * and the low-order 23 bits are taken from the low end of the IP address.
- */
-#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \
- /* struct in_addr *ipaddr; */ \
- /* u_int8_t enaddr[ETHER_ADDR_LEN]; */ \
-{ \
- (enaddr)[0] = 0x01; \
- (enaddr)[1] = 0x00; \
- (enaddr)[2] = 0x5e; \
- (enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f; \
- (enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \
- (enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \
-}
-#endif
-
-/*
- * Ethernet Address Resolution Protocol.
- *
- * See RFC 826 for protocol description. Structure below is adapted
- * to resolving internet addresses. Field names used correspond to
- * RFC 826.
- */
-struct ether_arp {
- struct arphdr ea_hdr; /* fixed-size header */
- u_int8_t arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */
- u_int8_t arp_spa[4]; /* sender protocol address */
- u_int8_t arp_tha[ETHER_ADDR_LEN]; /* target hardware address */
- u_int8_t arp_tpa[4]; /* target protocol address */
-};
-#define arp_hrd ea_hdr.ar_hrd
-#define arp_pro ea_hdr.ar_pro
-#define arp_hln ea_hdr.ar_hln
-#define arp_pln ea_hdr.ar_pln
-#define arp_op ea_hdr.ar_op
-
-/*
- * Structure shared between the ethernet driver modules and
- * the address resolution code. For example, each ec_softc or il_softc
- * begins with this structure.
- */
-struct arpcom {
- struct ifnet ac_if; /* network-visible interface */
- u_int8_t ac_enaddr[ETHER_ADDR_LEN]; /* ethernet hardware address */
- char ac__pad[2]; /* be nice to m68k ports */
- LIST_HEAD(, ether_multi) ac_multiaddrs; /* list of ether multicast addrs */
- int ac_multicnt; /* length of ac_multiaddrs list */
-};
-
-struct llinfo_arp {
- LIST_ENTRY(llinfo_arp) la_list;
- struct rtentry *la_rt;
- struct mbuf *la_hold; /* last packet until resolved/timeout */
- long la_asked; /* last time we QUERIED for this addr */
-#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
-};
-
-struct sockaddr_inarp {
- u_int8_t sin_len;
- u_int8_t sin_family;
- u_int16_t sin_port;
- struct in_addr sin_addr;
- struct in_addr sin_srcaddr;
- u_int16_t sin_tos;
- u_int16_t sin_other;
-#define SIN_PROXY 1
-};
-
-/*
- * IP and ethernet specific routing flags
- */
-#define RTF_USETRAILERS RTF_PROTO1 /* use trailers */
-#define RTF_ANNOUNCE RTF_PROTO2 /* announce new arp entry */
-
-#ifdef _KERNEL
-u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN];
-u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN];
-u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN];
-struct ifqueue arpintrq;
-
-void arpwhohas(struct arpcom *, struct in_addr *);
-void arpintr(void);
-int arpresolve(struct arpcom *,
- struct rtentry *, struct mbuf *, struct sockaddr *, u_char *, struct llentry **);
-void arp_ifinit(struct arpcom *, struct ifaddr *);
-void arp_rtrequest(int, struct rtentry *, struct sockaddr *);
-
-int ether_addmulti(struct ifreq *, struct arpcom *);
-int ether_delmulti(struct ifreq *, struct arpcom *);
-#endif /* _KERNEL */
-
-/*
- * Ethernet multicast address structure. There is one of these for each
- * multicast address or range of multicast addresses that we are supposed
- * to listen to on a particular interface. They are kept in a linked list,
- * rooted in the interface's arpcom structure. (This really has nothing to
- * do with ARP, or with the Internet address family, but this appears to be
- * the minimally-disrupting place to put it.)
- */
-struct ether_multi {
- u_int8_t enm_addrlo[ETHER_ADDR_LEN]; /* low or only address of range */
- u_int8_t enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */
- struct arpcom *enm_ac; /* back pointer to arpcom */
- u_int enm_refcount; /* no. claims to this addr/range */
- LIST_ENTRY(ether_multi) enm_list;
-};
-
-/*
- * Structure used by macros below to remember position when stepping through
- * all of the ether_multi records.
- */
-struct ether_multistep {
- struct ether_multi *e_enm;
-};
-
-/*
- * Macro for looking up the ether_multi record for a given range of Ethernet
- * multicast addresses connected to a given arpcom structure. If no matching
- * record is found, "enm" returns NULL.
- */
-#define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm) \
- /* u_int8_t addrlo[ETHER_ADDR_LEN]; */ \
- /* u_int8_t addrhi[ETHER_ADDR_LEN]; */ \
- /* struct arpcom *ac; */ \
- /* struct ether_multi *enm; */ \
-{ \
- for ((enm) = (ac)->ac_multiaddrs.lh_first; \
- (enm) != NULL && \
- (bcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 || \
- bcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0); \
- (enm) = (enm)->enm_list.le_next); \
-}
-
-/*
- * Macro to step through all of the ether_multi records, one at a time.
- * The current position is remembered in "step", which the caller must
- * provide. ETHER_FIRST_MULTI(), below, must be called to initialize "step"
- * and get the first record. Both macros return a NULL "enm" when there
- * are no remaining records.
- */
-#define ETHER_NEXT_MULTI(step, enm) \
- /* struct ether_multistep step; */ \
- /* struct ether_multi *enm; */ \
-{ \
- if (((enm) = (step).e_enm) != NULL) \
- (step).e_enm = (enm)->enm_list.le_next; \
-}
-
-#define ETHER_FIRST_MULTI(step, ac, enm) \
- /* struct ether_multistep step; */ \
- /* struct arpcom *ac; */ \
- /* struct ether_multi *enm; */ \
-{ \
- (step).e_enm = (ac)->ac_multiaddrs.lh_first; \
- ETHER_NEXT_MULTI((step), (enm)); \
-}
-
-#ifdef _KERNEL
-void arp_rtrequest(int, struct rtentry *, struct sockaddr *);
-int arpresolve(struct arpcom *, struct rtentry *, struct mbuf *,
- struct sockaddr *, u_char *, struct llentry **);
-void arpintr(void);
-int arpioctl(u_long, caddr_t);
-void arp_ifinit(struct arpcom *, struct ifaddr *);
-void revarpinput(struct mbuf *);
-void in_revarpinput(struct mbuf *);
-void revarprequest(struct ifnet *);
-int revarpwhoarewe(struct ifnet *, struct in_addr *, struct in_addr *);
-int revarpwhoami(struct in_addr *, struct ifnet *);
-int db_show_arptab(void);
-#endif
-
-/*
- * Prototype ethers(3) functions.
- */
-#ifndef _KERNEL
-#include <sys/cdefs.h>
-__BEGIN_DECLS
-char * ether_ntoa(struct ether_addr *);
-struct ether_addr *
- ether_aton(char *);
-int ether_ntohost(char *, struct ether_addr *);
-int ether_hostton(char *, struct ether_addr *);
-int ether_line(char *, struct ether_addr *, char *);
-__END_DECLS
-#endif
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index c29e8c3..937d83f 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -363,6 +363,12 @@ _libpthread_init(struct pthread *curthread)
_thr_signal_init();
if (_thread_event_mask & TD_CREATE)
_thr_report_creation(curthread, curthread);
+ /*
+ * Always use our rtld lock implementation.
+ * It is faster because it postpones signal handlers
+ * instead of calling sigprocmask(2).
+ */
+ _thr_rtld_init();
}
}
diff --git a/lib/libthr/thread/thr_kern.c b/lib/libthr/thread/thr_kern.c
index 1e7cb51..b5a8358 100644
--- a/lib/libthr/thread/thr_kern.c
+++ b/lib/libthr/thread/thr_kern.c
@@ -57,11 +57,6 @@ _thr_setthreaded(int threaded)
return (0);
__isthreaded = threaded;
- if (threaded != 0) {
- _thr_rtld_init();
- } else {
- _thr_rtld_fini();
- }
return (0);
}
diff --git a/lib/libutil/gr_util.c b/lib/libutil/gr_util.c
index acb9767..3f7e199 100644
--- a/lib/libutil/gr_util.c
+++ b/lib/libutil/gr_util.c
@@ -50,8 +50,6 @@ static char group_file[PATH_MAX];
static char tempname[PATH_MAX];
static int initialized;
-static const char group_line_format[] = "%s:%s:%ju:";
-
/*
* Initialize statics
*/
@@ -318,7 +316,7 @@ gr_mkdb(void)
}
/*
- * Clean up. Preserver errno for the caller's convenience.
+ * Clean up. Preserves errno for the caller's convenience.
*/
void
gr_fini(void)
@@ -346,7 +344,6 @@ gr_equal(const struct group *gr1, const struct group *gr2)
{
int gr1_ndx;
int gr2_ndx;
- bool found;
/* Check that the non-member information is the same. */
if (gr1->gr_name == NULL || gr2->gr_name == NULL) {
@@ -367,17 +364,15 @@ gr_equal(const struct group *gr1, const struct group *gr2)
if (gr1->gr_mem != gr2->gr_mem)
return (false);
} else {
- for (found = false, gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL;
- gr1_ndx++) {
- for (gr2_ndx = 0; gr2->gr_mem[gr2_ndx] != NULL;
- gr2_ndx++)
+ for (gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL; gr1_ndx++) {
+ for (gr2_ndx = 0;; gr2_ndx++) {
+ if (gr2->gr_mem[gr2_ndx] == NULL)
+ return (false);
if (strcmp(gr1->gr_mem[gr1_ndx],
gr2->gr_mem[gr2_ndx]) == 0) {
- found = true;
break;
}
- if (!found)
- return (false);
+ }
}
/* Check that group2 does not have more members than group1. */
@@ -394,7 +389,10 @@ gr_equal(const struct group *gr1, const struct group *gr2)
char *
gr_make(const struct group *gr)
{
+ const char *group_line_format = "%s:%s:%ju:";
+ const char *sep;
char *line;
+ char *p;
size_t line_size;
int ndx;
@@ -409,16 +407,18 @@ gr_make(const struct group *gr)
}
/* Create the group line and fill it. */
- if ((line = malloc(line_size)) == NULL)
+ if ((line = p = malloc(line_size)) == NULL)
return (NULL);
- snprintf(line, line_size, group_line_format, gr->gr_name, gr->gr_passwd,
+ p += sprintf(p, group_line_format, gr->gr_name, gr->gr_passwd,
(uintmax_t)gr->gr_gid);
- if (gr->gr_mem != NULL)
+ if (gr->gr_mem != NULL) {
+ sep = "";
for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) {
- strcat(line, gr->gr_mem[ndx]);
- if (gr->gr_mem[ndx + 1] != NULL)
- strcat(line, ",");
+ p = stpcpy(p, sep);
+ p = stpcpy(p, gr->gr_mem[ndx]);
+ sep = ",";
}
+ }
return (line);
}
diff --git a/lib/libvmmapi/Makefile b/lib/libvmmapi/Makefile
new file mode 100644
index 0000000..93d3c85
--- /dev/null
+++ b/lib/libvmmapi/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+LIB= vmmapi
+SRCS= vmmapi.c vmmapi_freebsd.c
+INCS= vmmapi.h
+
+WARNS?= 2
+
+CFLAGS+= -I${.CURDIR}
+
+.include <bsd.lib.mk>
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c
new file mode 100644
index 0000000..cfb42d0
--- /dev/null
+++ b/lib/libvmmapi/vmmapi.c
@@ -0,0 +1,723 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <machine/specialreg.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+
+#include "vmmapi.h"
+
+struct vmctx {
+ int fd;
+ char *name;
+};
+
+#define CREATE(x) sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
+#define DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))
+
+static int
+vm_device_open(const char *name)
+{
+ int fd, len;
+ char *vmfile;
+
+ len = strlen("/dev/vmm/") + strlen(name) + 1;
+ vmfile = malloc(len);
+ assert(vmfile != NULL);
+ snprintf(vmfile, len, "/dev/vmm/%s", name);
+
+ /* Open the device file */
+ fd = open(vmfile, O_RDWR, 0);
+
+ free(vmfile);
+ return (fd);
+}
+
+int
+vm_create(const char *name)
+{
+
+ return (CREATE((char *)name));
+}
+
+struct vmctx *
+vm_open(const char *name)
+{
+ struct vmctx *vm;
+
+ vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
+ assert(vm != NULL);
+
+ vm->fd = -1;
+ vm->name = (char *)(vm + 1);
+ strcpy(vm->name, name);
+
+ if ((vm->fd = vm_device_open(vm->name)) < 0)
+ goto err;
+
+ return (vm);
+err:
+ vm_destroy(vm);
+ return (NULL);
+}
+
+void
+vm_destroy(struct vmctx *vm)
+{
+ assert(vm != NULL);
+
+ if (vm->fd >= 0)
+ close(vm->fd);
+ DESTROY(vm->name);
+
+ free(vm);
+}
+
+size_t
+vmm_get_mem_total(void)
+{
+ size_t mem_total = 0;
+ size_t oldlen = sizeof(mem_total);
+ int error;
+ error = sysctlbyname("hw.vmm.mem_total", &mem_total, &oldlen, NULL, 0);
+ if (error)
+ return -1;
+ return mem_total;
+}
+
+size_t
+vmm_get_mem_free(void)
+{
+ size_t mem_free = 0;
+ size_t oldlen = sizeof(mem_free);
+ int error;
+ error = sysctlbyname("hw.vmm.mem_free", &mem_free, &oldlen, NULL, 0);
+ if (error)
+ return -1;
+ return mem_free;
+}
+
+int
+vm_get_memory_seg(struct vmctx *ctx, vm_paddr_t gpa, size_t *ret_len)
+{
+ int error;
+ struct vm_memory_segment seg;
+
+ bzero(&seg, sizeof(seg));
+ seg.gpa = gpa;
+ error = ioctl(ctx->fd, VM_GET_MEMORY_SEG, &seg);
+ *ret_len = seg.len;
+ return (error);
+}
+
+int
+vm_setup_memory(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char **mapaddr)
+{
+ int error;
+ struct vm_memory_segment seg;
+
+ /*
+ * Create and optionally map 'len' bytes of memory at guest
+ * physical address 'gpa'
+ */
+ bzero(&seg, sizeof(seg));
+ seg.gpa = gpa;
+ seg.len = len;
+ error = ioctl(ctx->fd, VM_MAP_MEMORY, &seg);
+ if (error == 0 && mapaddr != NULL) {
+ *mapaddr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
+ ctx->fd, gpa);
+ }
+ return (error);
+}
+
+char *
+vm_map_memory(struct vmctx *ctx, vm_paddr_t gpa, size_t len)
+{
+
+ /* Map 'len' bytes of memory at guest physical address 'gpa' */
+ return ((char *)mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
+ ctx->fd, gpa));
+}
+
+int
+vm_set_desc(struct vmctx *ctx, int vcpu, int reg,
+ uint64_t base, uint32_t limit, uint32_t access)
+{
+ int error;
+ struct vm_seg_desc vmsegdesc;
+
+ bzero(&vmsegdesc, sizeof(vmsegdesc));
+ vmsegdesc.cpuid = vcpu;
+ vmsegdesc.regnum = reg;
+ vmsegdesc.desc.base = base;
+ vmsegdesc.desc.limit = limit;
+ vmsegdesc.desc.access = access;
+
+ error = ioctl(ctx->fd, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
+ return (error);
+}
+
+int
+vm_get_desc(struct vmctx *ctx, int vcpu, int reg,
+ uint64_t *base, uint32_t *limit, uint32_t *access)
+{
+ int error;
+ struct vm_seg_desc vmsegdesc;
+
+ bzero(&vmsegdesc, sizeof(vmsegdesc));
+ vmsegdesc.cpuid = vcpu;
+ vmsegdesc.regnum = reg;
+
+ error = ioctl(ctx->fd, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
+ if (error == 0) {
+ *base = vmsegdesc.desc.base;
+ *limit = vmsegdesc.desc.limit;
+ *access = vmsegdesc.desc.access;
+ }
+ return (error);
+}
+
+int
+vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val)
+{
+ int error;
+ struct vm_register vmreg;
+
+ bzero(&vmreg, sizeof(vmreg));
+ vmreg.cpuid = vcpu;
+ vmreg.regnum = reg;
+ vmreg.regval = val;
+
+ error = ioctl(ctx->fd, VM_SET_REGISTER, &vmreg);
+ return (error);
+}
+
+int
+vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
+{
+ int error;
+ struct vm_register vmreg;
+
+ bzero(&vmreg, sizeof(vmreg));
+ vmreg.cpuid = vcpu;
+ vmreg.regnum = reg;
+
+ error = ioctl(ctx->fd, VM_GET_REGISTER, &vmreg);
+ *ret_val = vmreg.regval;
+ return (error);
+}
+
+int
+vm_get_pinning(struct vmctx *ctx, int vcpu, int *host_cpuid)
+{
+ int error;
+ struct vm_pin vmpin;
+
+ bzero(&vmpin, sizeof(vmpin));
+ vmpin.vm_cpuid = vcpu;
+
+ error = ioctl(ctx->fd, VM_GET_PINNING, &vmpin);
+ *host_cpuid = vmpin.host_cpuid;
+ return (error);
+}
+
+int
+vm_set_pinning(struct vmctx *ctx, int vcpu, int host_cpuid)
+{
+ int error;
+ struct vm_pin vmpin;
+
+ bzero(&vmpin, sizeof(vmpin));
+ vmpin.vm_cpuid = vcpu;
+ vmpin.host_cpuid = host_cpuid;
+
+ error = ioctl(ctx->fd, VM_SET_PINNING, &vmpin);
+ return (error);
+}
+
+int
+vm_run(struct vmctx *ctx, int vcpu, uint64_t rip, struct vm_exit *vmexit)
+{
+ int error;
+ struct vm_run vmrun;
+
+ bzero(&vmrun, sizeof(vmrun));
+ vmrun.cpuid = vcpu;
+ vmrun.rip = rip;
+
+ error = ioctl(ctx->fd, VM_RUN, &vmrun);
+ bcopy(&vmrun.vm_exit, vmexit, sizeof(struct vm_exit));
+ return (error);
+}
+
+static int
+vm_inject_event_real(struct vmctx *ctx, int vcpu, enum vm_event_type type,
+ int vector, int error_code, int error_code_valid)
+{
+ struct vm_event ev;
+
+ bzero(&ev, sizeof(ev));
+ ev.cpuid = vcpu;
+ ev.type = type;
+ ev.vector = vector;
+ ev.error_code = error_code;
+ ev.error_code_valid = error_code_valid;
+
+ return (ioctl(ctx->fd, VM_INJECT_EVENT, &ev));
+}
+
+int
+vm_inject_event(struct vmctx *ctx, int vcpu, enum vm_event_type type,
+ int vector)
+{
+
+ return (vm_inject_event_real(ctx, vcpu, type, vector, 0, 0));
+}
+
+int
+vm_inject_event2(struct vmctx *ctx, int vcpu, enum vm_event_type type,
+ int vector, int error_code)
+{
+
+ return (vm_inject_event_real(ctx, vcpu, type, vector, error_code, 1));
+}
+
+int
+vm_apicid2vcpu(struct vmctx *ctx, int apicid)
+{
+ /*
+ * The apic id associated with the 'vcpu' has the same numerical value
+ * as the 'vcpu' itself.
+ */
+ return (apicid);
+}
+
+int
+vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector)
+{
+ struct vm_lapic_irq vmirq;
+
+ bzero(&vmirq, sizeof(vmirq));
+ vmirq.cpuid = vcpu;
+ vmirq.vector = vector;
+
+ return (ioctl(ctx->fd, VM_LAPIC_IRQ, &vmirq));
+}
+
+int
+vm_inject_nmi(struct vmctx *ctx, int vcpu)
+{
+ struct vm_nmi vmnmi;
+
+ bzero(&vmnmi, sizeof(vmnmi));
+ vmnmi.cpuid = vcpu;
+
+ return (ioctl(ctx->fd, VM_INJECT_NMI, &vmnmi));
+}
+
+static struct {
+ const char *name;
+ int type;
+} capstrmap[] = {
+ { "hlt_exit", VM_CAP_HALT_EXIT },
+ { "mtrap_exit", VM_CAP_MTRAP_EXIT },
+ { "pause_exit", VM_CAP_PAUSE_EXIT },
+ { "unrestricted_guest", VM_CAP_UNRESTRICTED_GUEST },
+ { 0 }
+};
+
+int
+vm_capability_name2type(const char *capname)
+{
+ int i;
+
+ for (i = 0; capstrmap[i].name != NULL && capname != NULL; i++) {
+ if (strcmp(capstrmap[i].name, capname) == 0)
+ return (capstrmap[i].type);
+ }
+
+ return (-1);
+}
+
+const char *
+vm_capability_type2name(int type)
+{
+ int i;
+
+ for (i = 0; capstrmap[i].name != NULL; i++) {
+ if (capstrmap[i].type == type)
+ return (capstrmap[i].name);
+ }
+
+ return (NULL);
+}
+
+int
+vm_get_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
+ int *retval)
+{
+ int error;
+ struct vm_capability vmcap;
+
+ bzero(&vmcap, sizeof(vmcap));
+ vmcap.cpuid = vcpu;
+ vmcap.captype = cap;
+
+ error = ioctl(ctx->fd, VM_GET_CAPABILITY, &vmcap);
+ *retval = vmcap.capval;
+ return (error);
+}
+
+int
+vm_set_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap, int val)
+{
+ struct vm_capability vmcap;
+
+ bzero(&vmcap, sizeof(vmcap));
+ vmcap.cpuid = vcpu;
+ vmcap.captype = cap;
+ vmcap.capval = val;
+
+ return (ioctl(ctx->fd, VM_SET_CAPABILITY, &vmcap));
+}
+
+int
+vm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
+{
+ struct vm_pptdev pptdev;
+
+ bzero(&pptdev, sizeof(pptdev));
+ pptdev.bus = bus;
+ pptdev.slot = slot;
+ pptdev.func = func;
+
+ return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
+}
+
+int
+vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
+{
+ struct vm_pptdev pptdev;
+
+ bzero(&pptdev, sizeof(pptdev));
+ pptdev.bus = bus;
+ pptdev.slot = slot;
+ pptdev.func = func;
+
+ return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
+}
+
+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)
+{
+ struct vm_pptdev_mmio pptmmio;
+
+ bzero(&pptmmio, sizeof(pptmmio));
+ pptmmio.bus = bus;
+ pptmmio.slot = slot;
+ pptmmio.func = func;
+ pptmmio.gpa = gpa;
+ pptmmio.len = len;
+ pptmmio.hpa = hpa;
+
+ return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
+}
+
+int
+vm_setup_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
+ int destcpu, int vector, int numvec)
+{
+ struct vm_pptdev_msi pptmsi;
+
+ bzero(&pptmsi, sizeof(pptmsi));
+ pptmsi.vcpu = vcpu;
+ pptmsi.bus = bus;
+ pptmsi.slot = slot;
+ pptmsi.func = func;
+ pptmsi.destcpu = destcpu;
+ pptmsi.vector = vector;
+ pptmsi.numvec = numvec;
+
+ return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
+}
+
+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)
+{
+ struct vm_pptdev_msix pptmsix;
+
+ bzero(&pptmsix, sizeof(pptmsix));
+ pptmsix.vcpu = vcpu;
+ pptmsix.bus = bus;
+ pptmsix.slot = slot;
+ pptmsix.func = func;
+ pptmsix.idx = idx;
+ pptmsix.msg = msg;
+ pptmsix.addr = addr;
+ pptmsix.vector_control = vector_control;
+
+ return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
+}
+
+uint64_t *
+vm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv,
+ int *ret_entries)
+{
+ int error;
+
+ static struct vm_stats vmstats;
+
+ vmstats.cpuid = vcpu;
+
+ error = ioctl(ctx->fd, VM_STATS, &vmstats);
+ if (error == 0) {
+ if (ret_entries)
+ *ret_entries = vmstats.num_entries;
+ if (ret_tv)
+ *ret_tv = vmstats.tv;
+ return (vmstats.statbuf);
+ } else
+ return (NULL);
+}
+
+const char *
+vm_get_stat_desc(struct vmctx *ctx, int index)
+{
+ static struct vm_stat_desc statdesc;
+
+ statdesc.index = index;
+ if (ioctl(ctx->fd, VM_STAT_DESC, &statdesc) == 0)
+ return (statdesc.desc);
+ else
+ return (NULL);
+}
+
+int
+vm_get_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state *state)
+{
+ int error;
+ struct vm_x2apic x2apic;
+
+ bzero(&x2apic, sizeof(x2apic));
+ x2apic.cpuid = vcpu;
+
+ error = ioctl(ctx->fd, VM_GET_X2APIC_STATE, &x2apic);
+ *state = x2apic.state;
+ return (error);
+}
+
+int
+vm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state state)
+{
+ int error;
+ struct vm_x2apic x2apic;
+
+ bzero(&x2apic, sizeof(x2apic));
+ x2apic.cpuid = vcpu;
+ x2apic.state = state;
+
+ error = ioctl(ctx->fd, VM_SET_X2APIC_STATE, &x2apic);
+
+ return (error);
+}
+
+/*
+ * From Intel Vol 3a:
+ * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
+ */
+int
+vcpu_reset(struct vmctx *vmctx, int vcpu)
+{
+ int error;
+ uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
+ uint32_t desc_access, desc_limit;
+ uint16_t sel;
+
+ zero = 0;
+
+ rflags = 0x2;
+ error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
+ if (error)
+ goto done;
+
+ rip = 0xfff0;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
+ goto done;
+
+ cr0 = CR0_NE;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
+ goto done;
+
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, zero)) != 0)
+ goto done;
+
+ cr4 = 0;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
+ goto done;
+
+ /*
+ * CS: present, r/w, accessed, 16-bit, byte granularity, usable
+ */
+ desc_base = 0xffff0000;
+ desc_limit = 0xffff;
+ desc_access = 0x0093;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ sel = 0xf000;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, sel)) != 0)
+ goto done;
+
+ /*
+ * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
+ */
+ desc_base = 0;
+ desc_limit = 0xffff;
+ desc_access = 0x0093;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ sel = 0;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, sel)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, sel)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, sel)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, sel)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, sel)) != 0)
+ goto done;
+
+ /* General purpose registers */
+ rdx = 0xf00;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RAX, zero)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBX, zero)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RCX, zero)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSI, zero)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDI, zero)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBP, zero)) != 0)
+ goto done;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, zero)) != 0)
+ goto done;
+
+ /* GDTR, IDTR */
+ desc_base = 0;
+ desc_limit = 0xffff;
+ desc_access = 0;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
+ desc_base, desc_limit, desc_access);
+ if (error != 0)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_IDTR,
+ desc_base, desc_limit, desc_access);
+ if (error != 0)
+ goto done;
+
+ /* TR */
+ desc_base = 0;
+ desc_limit = 0xffff;
+ desc_access = 0x0000008b;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
+ if (error)
+ goto done;
+
+ sel = 0;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, sel)) != 0)
+ goto done;
+
+ /* LDTR */
+ desc_base = 0;
+ desc_limit = 0xffff;
+ desc_access = 0x00000082;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, desc_base,
+ desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ sel = 0;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
+ goto done;
+
+ /* XXX cr2, debug registers */
+
+ error = 0;
+done:
+ return (error);
+}
diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h
new file mode 100644
index 0000000..de04252
--- /dev/null
+++ b/lib/libvmmapi/vmmapi.h
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMMAPI_H_
+#define _VMMAPI_H_
+
+struct vmctx;
+enum x2apic_state;
+
+int vm_create(const char *name);
+struct vmctx *vm_open(const char *name);
+void vm_destroy(struct vmctx *ctx);
+size_t vmm_get_mem_total(void);
+size_t vmm_get_mem_free(void);
+int vm_get_memory_seg(struct vmctx *ctx, vm_paddr_t gpa, size_t *ret_len);
+/*
+ * Create a memory segment of 'len' bytes in the guest physical address space
+ * at offset 'gpa'.
+ *
+ * If 'mapaddr' is not NULL then this region is mmap'ed into the address
+ * space of the calling process. If there is an mmap error then *mapaddr
+ * will be set to MAP_FAILED.
+ */
+
+int vm_setup_memory(struct vmctx *ctx, vm_paddr_t gpa, size_t len,
+ char **mapaddr);
+char * vm_map_memory(struct vmctx *ctx, vm_paddr_t gpa, size_t len);
+int vm_set_desc(struct vmctx *ctx, int vcpu, int reg,
+ uint64_t base, uint32_t limit, uint32_t access);
+int vm_get_desc(struct vmctx *ctx, int vcpu, int reg,
+ uint64_t *base, uint32_t *limit, uint32_t *access);
+int vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val);
+int vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *retval);
+int vm_get_pinning(struct vmctx *ctx, int vcpu, int *host_cpuid);
+int vm_set_pinning(struct vmctx *ctx, int vcpu, int host_cpuid);
+int vm_run(struct vmctx *ctx, int vcpu, uint64_t rip,
+ struct vm_exit *ret_vmexit);
+int vm_apicid2vcpu(struct vmctx *ctx, int apicid);
+int vm_inject_event(struct vmctx *ctx, int vcpu, enum vm_event_type type,
+ int vector);
+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_inject_nmi(struct vmctx *ctx, int vcpu);
+int vm_capability_name2type(const char *capname);
+const char *vm_capability_type2name(int type);
+int vm_get_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
+ int *retval);
+int vm_set_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
+ int val);
+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,
+ int dest, int vector, 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);
+
+/*
+ * Return a pointer to the statistics buffer. Note that this is not MT-safe.
+ */
+uint64_t *vm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv,
+ int *ret_entries);
+const char *vm_get_stat_desc(struct vmctx *ctx, int index);
+
+int vm_get_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state *s);
+int vm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state s);
+
+/* Reset vcpu register state */
+int vcpu_reset(struct vmctx *ctx, int vcpu);
+
+/*
+ * FreeBSD specific APIs
+ */
+int vm_setup_freebsd_registers(struct vmctx *ctx, int vcpu,
+ uint64_t rip, uint64_t cr3, uint64_t gdtbase,
+ uint64_t rsp);
+void vm_setup_freebsd_gdt(uint64_t *gdtr);
+#endif /* _VMMAPI_H_ */
diff --git a/lib/libvmmapi/vmmapi_freebsd.c b/lib/libvmmapi/vmmapi_freebsd.c
new file mode 100644
index 0000000..9bd2988
--- /dev/null
+++ b/lib/libvmmapi/vmmapi_freebsd.c
@@ -0,0 +1,183 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <machine/specialreg.h>
+#include <machine/segments.h>
+#include <machine/vmm.h>
+
+#include "vmmapi.h"
+
+#define DESC_UNUSABLE 0x00010000
+
+#define GUEST_NULL_SEL 0
+#define GUEST_CODE_SEL 1
+#define GUEST_DATA_SEL 2
+#define GUEST_GDTR_LIMIT (3 * 8 - 1)
+
+void
+vm_setup_freebsd_gdt(uint64_t *gdtr)
+{
+ gdtr[GUEST_NULL_SEL] = 0;
+ gdtr[GUEST_CODE_SEL] = 0x0020980000000000;
+ gdtr[GUEST_DATA_SEL] = 0x0000900000000000;
+}
+
+/*
+ * Setup the 'vcpu' register set such that it will begin execution at
+ * 'rip' in long mode.
+ */
+int
+vm_setup_freebsd_registers(struct vmctx *vmctx, int vcpu,
+ uint64_t rip, uint64_t cr3, uint64_t gdtbase,
+ uint64_t rsp)
+{
+ int error;
+ uint64_t cr0, cr4, efer, rflags, desc_base;
+ uint32_t desc_access, desc_limit;
+ uint16_t gsel;
+
+ cr0 = CR0_PE | CR0_PG | CR0_NE;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
+ goto done;
+
+ cr4 = CR4_PAE;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
+ goto done;
+
+ efer = EFER_LME | EFER_LMA;
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_EFER, efer)))
+ goto done;
+
+ rflags = 0x2;
+ error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
+ if (error)
+ goto done;
+
+ desc_base = 0;
+ desc_limit = 0;
+ desc_access = 0x0000209B;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ desc_access = 0x00000093;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
+ desc_base, desc_limit, desc_access);
+ if (error)
+ goto done;
+
+ /*
+ * XXX TR is pointing to null selector even though we set the
+ * TSS segment to be usable with a base address and limit of 0.
+ */
+ desc_access = 0x0000008b;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
+ if (error)
+ goto done;
+
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, 0, 0,
+ DESC_UNUSABLE);
+ if (error)
+ goto done;
+
+ gsel = GSEL(GUEST_CODE_SEL, SEL_KPL);
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, gsel)) != 0)
+ goto done;
+
+ gsel = GSEL(GUEST_DATA_SEL, SEL_KPL);
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, gsel)) != 0)
+ goto done;
+
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, gsel)) != 0)
+ goto done;
+
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, gsel)) != 0)
+ goto done;
+
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, gsel)) != 0)
+ goto done;
+
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, gsel)) != 0)
+ goto done;
+
+ /* XXX TR is pointing to the null selector */
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, 0)) != 0)
+ goto done;
+
+ /* LDTR is pointing to the null selector */
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
+ goto done;
+
+ /* entry point */
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
+ goto done;
+
+ /* page table base */
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, cr3)) != 0)
+ goto done;
+
+ desc_base = gdtbase;
+ desc_limit = GUEST_GDTR_LIMIT;
+ error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
+ desc_base, desc_limit, 0);
+ if (error != 0)
+ goto done;
+
+ if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, rsp)) != 0)
+ goto done;
+
+ error = 0;
+done:
+ return (error);
+}
diff --git a/lib/ncurses/form/Makefile b/lib/ncurses/form/Makefile
index fe89d45..d05cbfe 100644
--- a/lib/ncurses/form/Makefile
+++ b/lib/ncurses/form/Makefile
@@ -59,7 +59,6 @@ LDADD= -lncurses${LIB_SUFFIX}
.if defined(ENABLE_WIDEC)
INCS= form.h
-.endif
.PATH: ${NCURSES_DIR}/man
MAN= \
@@ -157,6 +156,9 @@ MLINKS= form_cursor.3 pos_form_cursor.3 \
form_win.3 scale_form.3 \
form_win.3 set_form_sub.3 \
form_win.3 set_form_win.3
+.else
+NO_MAN=
+.endif
.include <bsd.lib.mk>
diff --git a/lib/ncurses/menu/Makefile b/lib/ncurses/menu/Makefile
index a853d8c..19a1ff3 100644
--- a/lib/ncurses/menu/Makefile
+++ b/lib/ncurses/menu/Makefile
@@ -45,7 +45,6 @@ LDADD= -lncurses${LIB_SUFFIX}
.if defined(ENABLE_WIDEC)
INCS= menu.h eti.h
-.endif
.PATH: ${NCURSES_DIR}/man
MAN= \
@@ -130,6 +129,9 @@ MLINKS= menu_attributes.3 menu_back.3 \
mitem_value.3 item_value.3 \
mitem_value.3 set_item_value.3 \
mitem_visible.3 item_visible.3
+.else
+NO_MAN=
+.endif
.include <bsd.lib.mk>
diff --git a/lib/ncurses/ncurses/Makefile b/lib/ncurses/ncurses/Makefile
index bdac622..869fb2e 100644
--- a/lib/ncurses/ncurses/Makefile
+++ b/lib/ncurses/ncurses/Makefile
@@ -2,6 +2,10 @@
SHLIBDIR?= /lib
+.if !defined(ENABLE_WIDEC)
+NO_MAN=
+.endif
+
.include <bsd.own.mk>
.include "${.CURDIR}/../config.mk"
@@ -304,8 +308,10 @@ SYMLINKS+= libncurses${LIB_SUFFIX}_p.a ${LIBDIR}/libtermlib${LIB_SUFFIX}_p.a
SYMLINKS+= libncurses${LIB_SUFFIX}_p.a ${LIBDIR}/libtinfo${LIB_SUFFIX}_p.a
.endif
+.if defined(ENABLE_WIDEC)
DOCSDIR= ${SHAREDIR}/doc/ncurses
DOCS= ncurses-intro.html hackguide.html
+.endif
.if ${MK_HTML} != "no"
.PATH: ${NCURSES_DIR}/doc/html
@@ -457,6 +463,7 @@ terminfo.5: MKterminfo.sh terminfo.head Caps
CLEANFILES+= terminfo.5
+.if defined(ENABLE_WIDEC)
.PATH: ${NCURSES_DIR}/man
MAN= \
curs_addch.3 \
@@ -517,7 +524,6 @@ MAN= \
resizeterm.3 \
wresize.3
-.if defined(ENABLE_WIDEC)
MAN+= \
curs_add_wch.3 \
curs_add_wchstr.3 \
diff --git a/lib/ncurses/panel/Makefile b/lib/ncurses/panel/Makefile
index 12b8b06..689586d 100644
--- a/lib/ncurses/panel/Makefile
+++ b/lib/ncurses/panel/Makefile
@@ -34,7 +34,6 @@ LDADD= -lncurses${LIB_SUFFIX}
.if defined(ENABLE_WIDEC)
INCS= panel.h
-.endif
# generate MAN
.PATH: ${NCURSES_DIR}/man
@@ -58,6 +57,9 @@ MLINKS= panel.3 bottom_panel.3 \
panel.3 show_panel.3 \
panel.3 top_panel.3 \
panel.3 update_panels.3
+.else
+NO_MAN=
+.endif
.include <bsd.lib.mk>
diff --git a/libexec/bootpd/rtmsg.c b/libexec/bootpd/rtmsg.c
index 8b81dab..c075bc5 100644
--- a/libexec/bootpd/rtmsg.c
+++ b/libexec/bootpd/rtmsg.c
@@ -106,9 +106,9 @@ static void getsocket () {
}
static struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
-static struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
+static struct sockaddr_in blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
static struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
-static int expire_time, flags, export_only, doing_proxy;
+static int expire_time, flags, doing_proxy;
static struct {
struct rt_msghdr m_rtm;
char m_space[512];
@@ -122,7 +122,7 @@ int bsd_arp_set(ia, eaddr, len)
char *eaddr;
int len;
{
- register struct sockaddr_inarp *sin = &sin_m;
+ register struct sockaddr_in *sin = &sin_m;
register struct sockaddr_dl *sdl;
register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
u_char *ea;
@@ -137,7 +137,7 @@ int bsd_arp_set(ia, eaddr, len)
ea = (u_char *)LLADDR(&sdl_m);
bcopy(eaddr, ea, len);
sdl_m.sdl_alen = len;
- doing_proxy = flags = export_only = expire_time = 0;
+ doing_proxy = flags = expire_time = 0;
/* make arp entry temporary */
clock_gettime(CLOCK_MONOTONIC, &tp);
@@ -148,7 +148,7 @@ tryagain:
report(LOG_WARNING, "rtmget: %s", strerror(errno));
return (1);
}
- sin = (struct sockaddr_inarp *)(rtm + 1);
+ sin = (struct sockaddr_in *)(rtm + 1);
sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
if (sdl->sdl_family == AF_LINK &&
@@ -163,13 +163,6 @@ tryagain:
inet_ntoa(sin->sin_addr));
return (1);
}
- if (sin_m.sin_other & SIN_PROXY) {
- report(LOG_WARNING,
- "set: proxy entry exists for non 802 device\n");
- return(1);
- }
- sin_m.sin_other = SIN_PROXY;
- export_only = 1;
goto tryagain;
}
overwrite:
@@ -209,14 +202,9 @@ static int rtmsg(cmd)
rtm->rtm_rmx.rmx_expire = expire_time;
rtm->rtm_inits = RTV_EXPIRE;
rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA);
- sin_m.sin_other = 0;
if (doing_proxy) {
- if (export_only)
- sin_m.sin_other = SIN_PROXY;
- else {
- rtm->rtm_addrs |= RTA_NETMASK;
- rtm->rtm_flags &= ~RTF_HOST;
- }
+ rtm->rtm_addrs |= RTA_NETMASK;
+ rtm->rtm_flags &= ~RTF_HOST;
}
/* FALLTHROUGH */
case RTM_GET:
diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile
index e41477d..31cbfdd 100644
--- a/libexec/rtld-elf/Makefile
+++ b/libexec/rtld-elf/Makefile
@@ -42,6 +42,16 @@ LDFLAGS+= -shared -Wl,-Bsymbolic
DPADD= ${LIBC_PIC}
LDADD= -lc_pic
+.if ${MACHINE_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+# Some of the required math functions (div & mod) are implemented in libgcc
+# on ARM. The library also needs to be placed first to be correctly linked.
+# As some of the functions are used before we have shared libraries.
+DPADD+= ${LIBGCC}
+LDADD+= -lgcc
+.endif
+
+
+
.if ${MK_SYMVER} == "yes"
LIBCDIR= ${TOPSRCDIR}/lib/libc
VERSION_DEF= ${LIBCDIR}/Versions.def
diff --git a/libexec/tftpd/tftp-io.c b/libexec/tftpd/tftp-io.c
index 1d4f743..6dabf4f 100644
--- a/libexec/tftpd/tftp-io.c
+++ b/libexec/tftpd/tftp-io.c
@@ -106,13 +106,13 @@ send_packet(int peer, uint16_t block, char *pkt, int size)
for (i = 0; i < 12 ; i++) {
DROPPACKETn("send_packet", 0);
- if (sendto(peer, pkt, size, 0,
- (struct sockaddr *)&peer_sock, peer_sock.ss_len)
- == size) {
+ if (sendto(peer, pkt, size, 0, (struct sockaddr *)&peer_sock,
+ peer_sock.ss_len) == size) {
if (i)
tftp_log(LOG_ERR,
"%s block %d, attempt %d successful",
- block, i);
+ packettype(ntohs(((struct tftphdr *)
+ (pkt))->th_opcode)), block, i);
return (0);
}
tftp_log(LOG_ERR,
@@ -142,7 +142,7 @@ send_error(int peer, int error)
char buf[MAXPKTSIZE];
if (debug&DEBUG_PACKETS)
- tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error);
+ tftp_log(LOG_DEBUG, "Sending ERROR %d", error);
DROPPACKET("send_error");
diff --git a/libexec/tftpd/tftp-options.c b/libexec/tftpd/tftp-options.c
index d5b6386..f926f32 100644
--- a/libexec/tftpd/tftp-options.c
+++ b/libexec/tftpd/tftp-options.c
@@ -99,16 +99,17 @@ option_tsize(int peer __unused, struct tftphdr *tp __unused, int mode,
int
option_timeout(int peer)
{
+ int to;
if (options[OPT_TIMEOUT].o_request == NULL)
return (0);
- int to = atoi(options[OPT_TIMEOUT].o_request);
+ to = atoi(options[OPT_TIMEOUT].o_request);
if (to < TIMEOUT_MIN || to > TIMEOUT_MAX) {
tftp_log(acting_as_client ? LOG_ERR : LOG_WARNING,
"Received bad value for timeout. "
- "Should be between %d and %d, received %s",
- TIMEOUT_MIN, TIMEOUT_MAX);
+ "Should be between %d and %d, received %d",
+ TIMEOUT_MIN, TIMEOUT_MAX, to);
send_error(peer, EBADOP);
if (acting_as_client)
return (1);
@@ -195,14 +196,14 @@ option_blksize(int peer)
tftp_log(LOG_ERR,
"Invalid blocksize (%d bytes), "
"net.inet.udp.maxdgram sysctl limits it to "
- "%d bytes.\n", size, maxdgram);
+ "%ld bytes.\n", size, maxdgram);
send_error(peer, EBADOP);
return (1);
} else {
tftp_log(LOG_WARNING,
"Invalid blocksize (%d bytes), "
"net.inet.udp.maxdgram sysctl limits it to "
- "%d bytes.\n", size, maxdgram);
+ "%ld bytes.\n", size, maxdgram);
size = maxdgram;
/* No reason to return */
}
@@ -257,7 +258,7 @@ option_blksize2(int peer __unused)
}
tftp_log(LOG_INFO,
"Invalid blocksize2 (%d bytes), net.inet.udp.maxdgram "
- "sysctl limits it to %d bytes.\n", size, maxdgram);
+ "sysctl limits it to %ld bytes.\n", size, maxdgram);
size = sizes[i];
/* No need to return */
}
diff --git a/libexec/tftpd/tftp-utils.h b/libexec/tftpd/tftp-utils.h
index 0468612..c1becf3 100644
--- a/libexec/tftpd/tftp-utils.h
+++ b/libexec/tftpd/tftp-utils.h
@@ -106,7 +106,7 @@ const char *debug_show(int d);
extern int tftp_logtostdout;
void tftp_openlog(const char *ident, int logopt, int facility);
void tftp_closelog(void);
-void tftp_log(int priority, const char *message, ...);
+void tftp_log(int priority, const char *message, ...) __printflike(2, 3);
/*
* Performance figures
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index a0010b3..87f80f0 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <netdb.h>
#include <pwd.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -799,8 +800,8 @@ tftp_xmitfile(int peer, const char *mode)
tftp_send(peer, &block, &ts);
read_close();
if (debug&DEBUG_SIMPLE)
- tftp_log(LOG_INFO, "Sent %d bytes in %d seconds",
- ts.amount, time(NULL) - now);
+ tftp_log(LOG_INFO, "Sent %jd bytes in %jd seconds",
+ (intmax_t)ts.amount, (intmax_t)time(NULL) - now);
}
static void
@@ -832,8 +833,8 @@ tftp_recvfile(int peer, const char *mode)
f = now2.tv_sec - now1.tv_sec +
(now2.tv_usec - now1.tv_usec) / 100000.0;
tftp_log(LOG_INFO,
- "Download of %d bytes in %d blocks completed after %0.1f seconds\n",
- ts.amount, block, f);
+ "Download of %jd bytes in %d blocks completed after %0.1f seconds\n",
+ (intmax_t)ts.amount, block, f);
}
return;
diff --git a/release/Makefile b/release/Makefile
index 79a3e3f..830e4ea 100644
--- a/release/Makefile
+++ b/release/Makefile
@@ -34,6 +34,20 @@ TARGET_ARCH?= ${TARGET}
IMAKE= ${MAKE} TARGET_ARCH=${TARGET_ARCH} TARGET=${TARGET}
DISTDIR= dist
+# Define OSRELEASE by using newvars.sh
+.if !defined(OSRELEASE) || empty(OSRELEASE)
+.for _V in TYPE BRANCH REVISION
+${_V}!= eval $$(awk '/^${_V}=/{print}' ${.CURDIR}/../sys/conf/newvers.sh); echo $$${_V}
+.endfor
+.for _V in ${TARGET_ARCH}
+.if !empty(TARGET:M${_V})
+OSRELEASE= ${TYPE}-${REVISION}-${BRANCH}-${TARGET}
+.else
+OSRELEASE= ${TYPE}-${REVISION}-${BRANCH}-${TARGET}-${TARGET_ARCH}
+.endif
+.endfor
+.endif
+
.if !exists(${DOCDIR})
NODOC= true
.endif
@@ -117,7 +131,7 @@ system: packagesystem
cp reldoc/* release
.endif
# Set up installation environment
- ln -s /tmp/bsdinstall_etc/resolv.conf release/etc/resolv.conf
+ ln -fs /tmp/bsdinstall_etc/resolv.conf release/etc/resolv.conf
echo sendmail_enable=\"NONE\" > release/etc/rc.conf
echo hostid_enable=\"NO\" >> release/etc/rc.conf
cp ${.CURDIR}/rc.local release/etc
@@ -142,7 +156,7 @@ bootonly: packagesystem
cp reldoc/* bootonly
.endif
# Set up installation environment
- ln -s /tmp/bsdinstall_etc/resolv.conf bootonly/etc/resolv.conf
+ ln -fs /tmp/bsdinstall_etc/resolv.conf bootonly/etc/resolv.conf
echo sendmail_enable=\"NONE\" > bootonly/etc/rc.conf
echo hostid_enable=\"NO\" >> bootonly/etc/rc.conf
cp ${.CURDIR}/rc.local bootonly/etc
@@ -183,4 +197,9 @@ install:
.if defined(DESTDIR) && !empty(DESTDIR)
mkdir -p ${DESTDIR}
.endif
- cp -a ${IMAGES} ftp ${DESTDIR}/
+ cp -a ftp ${DESTDIR}/
+.for I in ${IMAGES}
+ cp -p ${I} ${DESTDIR}/${OSRELEASE}-${I}
+.endfor
+ cd ${DESTDIR} && sha256 ${OSRELEASE}* > ${DESTDIR}/CHECKSUM.SHA256
+ cd ${DESTDIR} && md5 ${OSRELEASE}* > ${DESTDIR}/CHECKSUM.MD5
diff --git a/release/amd64/mkisoimages.sh b/release/amd64/mkisoimages.sh
index 105a073..e4093d7 100644
--- a/release/amd64/mkisoimages.sh
+++ b/release/amd64/mkisoimages.sh
@@ -39,6 +39,7 @@ fi
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
NAME=$1; shift
+publisher="The FreeBSD Project. http://www.FreeBSD.org/"
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
-makefs -t cd9660 $bootable -o rockridge -o label=$LABEL $NAME $*
+makefs -t cd9660 $bootable -o rockridge -o label=$LABEL -o publisher="$publisher" $NAME $*
rm $1/etc/fstab
diff --git a/release/generate-release.sh b/release/generate-release.sh
index e0baff8..dbc8427 100755
--- a/release/generate-release.sh
+++ b/release/generate-release.sh
@@ -3,191 +3,98 @@
# generate-release.sh: check out source trees, and build release components with
# totally clean, fresh trees.
#
-# Usage: generate-release.sh [-r revision] [-d docrevision] \
-# [-p portsrevision] svn-branch scratch-dir
+# Usage: generate-release.sh svn-branch[@revision] scratch-dir
#
# Environment variables:
-# SVNROOT: SVN URL to FreeBSD source repository (by default,
-# svn://svn.freebsd.org/base)
-# MAKE_FLAGS: optional flags to pass to make (e.g. -j)
-# RELSTRING: optional base name for media images (e.g. FreeBSD-9.0-RC2-amd64)
-#
-# Note: Since this requires a chroot, release cross-builds will not work!
+# SVNROOTBASE: SVN base URL to FreeBSD repository (svn://svn.freebsd.org)
+# SVNROOTSRC: URL to FreeBSD src tree (${SVNROOTBASE}/base)
+# SVNROOTDOC: URL to FreeBSD doc tree (${SVNROOTBASE}/doc)
+# SVNROOTPORTS:URL to FreeBSD ports tree (${SVNROOTBASE}/ports)
+# BRANCHSRC: branch name of src (svn-branch[@revision])
+# BRANCHDOC: branch name of doc (head)
+# BRANCHPORTS: branch name of ports (head)
+# WORLD_FLAGS: optional flags to pass to buildworld (e.g. -j)
+# KERNEL_FLAGS: optional flags to pass to buildkernel (e.g. -j)
#
# $FreeBSD$
#
-unset B_ARCH
-unset ARCH
-unset MACHINE_ARCH
-
-HOST_ARCH=`uname -p`
-
usage()
{
- echo "Usage: $0 [-a arch] [-r revision] [-d docrevision] [-p portsrevision] svn-branch scratch-dir"
+ echo "Usage: $0 svn-branch[@revision] scratch-dir" 2>&1
exit 1
}
-arch_error ()
-{
- echo "Architecture ${OPTARG} cannot be built on host architecture ${HOST_ARCH}"
- exit 1
-}
-
-REVISION=
-DOCREVISION=
-PORTSREVISION=
-while getopts a:d:r:p: opt; do
- case $opt in
- a)
- case "${OPTARG}" in
- i386|amd64)
- if [ "${HOST_ARCH}" != "amd64" ]; then
- arch_error "${OPTARG}"
- fi
- ;;
- powerpc|powerpc64)
- if [ "${HOST_ARCH}" != "powerpc64" ]; then
- arch_error "${OPTARG}"
- fi
- ;;
- *)
- arch_error "${OPTARG}"
- ;;
- esac
- B_ARCH="$OPTARG"
- ;;
- d)
- DOCREVISION="-r $OPTARG"
- ;;
- r)
- REVISION="-r $OPTARG"
- ;;
- p)
- PORTSREVISION="-r $OPTARG"
- ;;
- \?)
- usage
- ;;
- esac
-done
-shift $(($OPTIND - 1))
-
-# If target architecture is not specified, use hw.machine_arch
-if [ "x${B_ARCH}" == "x" ]; then
- B_ARCH="${HOST_ARCH}"
-fi
-ARCH_FLAGS="ARCH=${B_ARCH} TARGET_ARCH=${B_ARCH}"
-
if [ $# -lt 2 ]; then
usage
fi
-if [ $(id -u) -ne 0 ]; then
- echo "Needs to be run as root."
+: ${SVNROOTBASE:=svn://svn.freebsd.org}
+: ${SVNROOTSRC:=${SVNROOTBASE}/base}
+: ${SVNROOTDOC:=${SVNROOTBASE}/doc}
+: ${SVNROOTPORTS:=${SVNROOTBASE}/ports}
+: ${SVNROOT:=${SVNROOTSRC}} # for backward compatibility
+: ${SVN_CMD:=/usr/local/bin/svn}
+BRANCHSRC=$1
+: ${BRANCHDOC:=head}
+: ${BRANCHPORTS:=head}
+: ${WORLD_FLAGS:=${MAKE_FLAGS}}
+: ${KERNEL_FLAGS:=${MAKE_FLAGS}}
+: ${CHROOTDIR:=$2}
+
+if [ ! -r "${CHROOTDIR}" ]; then
+ echo "${CHROOTDIR}: scratch dir not found."
exit 1
fi
-set -e # Everything must succeed
-
-case $MAKE_FLAGS in
- *-j*)
- ;;
- *)
- MAKE_FLAGS="$MAKE_FLAGS -j "$(sysctl -n hw.ncpu)
- ;;
+CHROOT_CMD="/usr/sbin/chroot ${CHROOTDIR}"
+case ${TARGET} in
+"") ;;
+*) SETENV_TARGET="TARGET=$TARGET" ;;
esac
+case ${TARGET_ARCH} in
+"") ;;
+*) SETENV_TARGET_ARCH="TARGET_ARCH=$TARGET_ARCH" ;;
+esac
+SETENV="env -i PATH=/bin:/usr/bin:/sbin:/usr/sbin"
+CROSSENV="${SETENV_TARGET} ${SETENV_TARGET_ARCH}"
+WMAKE="make -C /usr/src ${WORLD_FLAGS}"
+NWMAKE="${WMAKE} __MAKE_CONF=/dev/null SRCCONF=/dev/null"
+KMAKE="make -C /usr/src ${KERNEL_FLAGS}"
+RMAKE="make -C /usr/src/release"
-mkdir -p $2/usr/src
-
-svn co ${SVNROOT:-svn://svn.freebsd.org/base}/$1 $2/usr/src $REVISION
-svn co ${SVNROOT:-svn://svn.freebsd.org/doc}/head $2/usr/doc $DOCREVISION
-svn co ${SVNROOT:-svn://svn.freebsd.org/ports}/head $2/usr/ports $PORTSREVISION
-
-cd $2/usr/src
-make $MAKE_FLAGS ${ARCH_FLAGS} buildworld
-make $ARCH_FLAGS installworld distribution DESTDIR=$2
-mount -t devfs devfs $2/dev
-trap "umount $2/dev" EXIT # Clean up devfs mount on exit
-
-# Most commands below are run in chroot, so fake getosreldate(3) right now
-OSVERSION=$(grep '#define __FreeBSD_version' $2/usr/include/sys/param.h | awk '{print $3}')
-export OSVERSION
-BRANCH=$(grep '^BRANCH=' $2/usr/src/sys/conf/newvers.sh | awk -F\= '{print $2}')
-BRANCH=`echo ${BRANCH} | sed -e 's,",,g'`
-REVISION=$(grep '^REVISION=' $2/usr/src/sys/conf/newvers.sh | awk -F\= '{print $2}')
-REVISION=`echo ${REVISION} | sed -e 's,",,g'`
-OSRELEASE="${REVISION}-${BRANCH}"
-
-pkgng_install_docports ()
-{
- # Attempt to install docproj port from pkgng package.
- chroot ${CHROOTDIR} /bin/sh -c 'env ASSUME_ALWAYS_YES=1 /usr/sbin/pkg install -y docproj-nojadetex'
- # Check if docproj was installed, since pkg(8) returns '0' if unable
- # to install a package from the repository. If it is not installed,
- # fallback to installing using pkg_add(1).
- chroot ${CHROOTDIR} /bin/sh -c '/usr/sbin/pkg info -q docproj-nojadetex' || \
- pkgadd_install_docports
-}
+if [ $(id -u) -ne 0 ]; then
+ echo "Needs to be run as root."
+ exit 1
+fi
-build_compat9_port ()
-{
- chroot ${CHROOTDIR} /bin/sh -c 'make -C /usr/ports/misc/compat9x BATCH=yes install clean'
-}
+set -e # Everything must succeed
-pkgadd_install_docports ()
-{
- # Attempt to install docproj package with pkg_add(1).
- # If not successful, build the docproj port.
- if [ "${REVISION}" == "10.0" ]; then
- # Packages for 10-CURRENT are still located in the 9-CURRENT
- # directory. Override environment to use correct package
- # location if building for 10-CURRENT.
- PACKAGESITE="ftp://ftp.freebsd.org/pub/FreeBSD/ports/${B_ARCH}/packages-9-current/Latest/"
- export PACKAGESITE
- PACKAGEROOT="ftp://ftp.freebsd.org/pub/FreeBSD/ports/${B_ARCH}/packages-9-current/"
- export PACKAGEROOT
- PKG_PATH="ftp://ftp.freebsd.org/pub/FreeBSD/ports/${B_ARCH}/packages-9-current/All/"
- export PKG_PATH
- build_compat9_port
- fi
- chroot ${CHROOTDIR} /bin/sh -c '/usr/sbin/pkg_add -r docproj-nojadetex' || \
- build_docports
-}
+mkdir -p ${CHROOTDIR}/usr/src
+${SVN_CMD} co ${SVNROOT}/${BRANCHSRC} ${CHROOTDIR}/usr/src
+${SVN_CMD} co ${SVNROOTDOC}/${BRANCHDOC} ${CHROOTDIR}/usr/doc
+${SVN_CMD} co ${SVNROOTPORTS}/${BRANCHPORTS} ${CHROOTDIR}/usr/ports
-build_docports()
-{
- # Could not install textproc/docproj from pkg(8) or pkg_add(1). Build
- # the port as final fallback.
- chroot ${CHROOTDIR} /bin/sh -c 'make -C /usr/ports/textproc/docproj BATCH=yes WITH_JADETEX=no WITHOUT_X11=yes WITHOUT_PYTHON=yes install clean' || \
- { echo "*** Could not build the textproj/docproj port. Exiting."; exit 2; }
-}
+${SETENV} ${NWMAKE} -C ${CHROOTDIR}/usr/src ${WORLD_FLAGS} buildworld
+${SETENV} ${NWMAKE} -C ${CHROOTDIR}/usr/src installworld distribution DESTDIR=${CHROOTDIR}
+mount -t devfs devfs ${CHROOTDIR}/dev
+trap "umount ${CHROOTDIR}/dev" EXIT # Clean up devfs mount on exit
-if [ -d $2/usr/doc ]; then
- cp /etc/resolv.conf $2/etc/resolv.conf
+if [ -d ${CHROOTDIR}/usr/doc ]; then
+ cp /etc/resolv.conf ${CHROOTDIR}/etc/resolv.conf
# Install docproj to build release documentation
- CHROOTDIR="$2"
- set +e
- pkgng_install_docports "${CHROOTDIR}"
- set -e
+ ${CHROOT_CMD} /bin/sh -c \
+ 'make -C /usr/ports/textproc/docproj \
+ BATCH=yes \
+ WITHOUT_SVN=yes \
+ WITHOUT_JADETEX=yes \
+ WITHOUT_X11=yes \
+ WITHOUT_PYTHON=yes \
+ install'
fi
-chroot $2 make -C /usr/src $MAKE_FLAGS ${ARCH_FLAGS} buildworld buildkernel
-chroot $2 make -C /usr/src/release ${ARCH_FLAGS} release
-chroot $2 make -C /usr/src/release install DESTDIR=/R
-
-if [ "x${OSVERSION}" == "x" ]; then
- OSRELEASE=`chroot $2 uname -r`
-fi
-
-: ${RELSTRING=`chroot $2 uname -s`-${OSRELEASE}-${B_ARCH}}
-
-cd $2/R
-for i in release.iso bootonly.iso memstick; do
- mv $i $RELSTRING-$i
-done
-sha256 $RELSTRING-* > CHECKSUM.SHA256
-md5 $RELSTRING-* > CHECKSUM.MD5
-
+${CHROOT_CMD} ${SETENV} ${CROSSENV} ${WMAKE} buildworld
+${CHROOT_CMD} ${SETENV} ${CROSSENV} ${KMAKE} buildkernel
+${CHROOT_CMD} ${SETENV} ${CROSSENV} ${RMAKE} release
+${CHROOT_CMD} ${SETENV} ${CROSSENV} ${RMAKE} install DESTDIR=/R
diff --git a/release/i386/mkisoimages.sh b/release/i386/mkisoimages.sh
index 105a073..e4093d7 100644
--- a/release/i386/mkisoimages.sh
+++ b/release/i386/mkisoimages.sh
@@ -39,6 +39,7 @@ fi
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
NAME=$1; shift
+publisher="The FreeBSD Project. http://www.FreeBSD.org/"
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
-makefs -t cd9660 $bootable -o rockridge -o label=$LABEL $NAME $*
+makefs -t cd9660 $bootable -o rockridge -o label=$LABEL -o publisher="$publisher" $NAME $*
rm $1/etc/fstab
diff --git a/release/ia64/mkisoimages.sh b/release/ia64/mkisoimages.sh
index d4a0802..b5cec32 100644
--- a/release/ia64/mkisoimages.sh
+++ b/release/ia64/mkisoimages.sh
@@ -63,6 +63,7 @@ if [ $bootable = yes ]; then
if [ -s $BASE/boot/mfsroot.gz ]; then
cp $BASE/boot/mfsroot.gz $MNT/boot
fi
+ cp $BASE/boot/color.4th $MNT/boot
cp $BASE/boot/support.4th $MNT/boot
cp $BASE/boot/check-password.4th $MNT/boot
cp $BASE/boot/screen.4th $MNT/boot
@@ -74,8 +75,9 @@ else
BOOTOPTS=""
fi
+publisher="The FreeBSD Project. http://www.FreeBSD.org/"
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $BASE/etc/fstab
-makefs -t cd9660 $BOOTOPTS -o rockridge -o label=$LABEL $NAME $BASE $*
+makefs -t cd9660 $BOOTOPTS -o rockridge -o label=$LABEL -o publisher="$publisher" $NAME $BASE $*
rm $BASE/etc/fstab
rm -f $EFIPART
exit 0
diff --git a/release/pc98/mkisoimages.sh b/release/pc98/mkisoimages.sh
index 68f2196..5a19b4d 100644
--- a/release/pc98/mkisoimages.sh
+++ b/release/pc98/mkisoimages.sh
@@ -39,6 +39,7 @@ fi
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
NAME=$1; shift
+publisher="The FreeBSD Project. http://www.FreeBSD.org/"
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
-makefs -t cd9660 $bootable -o rockridge -o label=$LABEL $NAME $*
+makefs -t cd9660 $bootable -o rockridge -o label=$LABEL -o publisher="$publisher" $NAME $*
rm $1/etc/fstab
diff --git a/release/powerpc/mkisoimages.sh b/release/powerpc/mkisoimages.sh
index 6bd29a7..7ba4649 100644
--- a/release/powerpc/mkisoimages.sh
+++ b/release/powerpc/mkisoimages.sh
@@ -61,9 +61,9 @@ fi
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
NAME=$1; shift
+publisher="The FreeBSD Project. http://www.FreeBSD.org/"
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
-makefs -t cd9660 $bootable -o rockridge -o label=$LABEL $NAME $*
+makefs -t cd9660 $bootable -o rockridge -o label=$LABEL -o publisher="$publisher" $NAME $*
rm $1/etc/fstab
rm /tmp/hfs-boot-block
rm -rf $1/ppc
-
diff --git a/release/rc.local b/release/rc.local
index b1f9b19..f0f297f 100755
--- a/release/rc.local
+++ b/release/rc.local
@@ -45,6 +45,16 @@ else
fi
export TERM
+if [ -f /etc/installerconfig ]; then
+ if bsdinstall script /etc/installerconfig; then
+ dialog --backtitle "FreeBSD Installer" --title "Complete" --no-cancel --ok-label "Reboot" --pause "Installation of FreeBSD complete! Rebooting in 10 seconds" 10 30 10
+ reboot
+ else
+ dialog --backtitle "FreeBSD Installer" --title "Error" --textbox /tmp/bsdinstall_log 0 0
+ fi
+ exit
+fi
+
dialog --backtitle "FreeBSD Installer" --title "Welcome" --extra-button --extra-label "Shell" --ok-label "Install" --cancel-label "Live CD" --yesno "Welcome to FreeBSD! Would you like to begin an installation or use the live CD?" 0 0
case $? in
diff --git a/release/sparc64/mkisoimages.sh b/release/sparc64/mkisoimages.sh
index 9ae6dcf..82cadab 100644
--- a/release/sparc64/mkisoimages.sh
+++ b/release/sparc64/mkisoimages.sh
@@ -22,51 +22,61 @@
# resulting ISO image, base-bits-dir contains the image contents and
# extra-bits-dir, if provided, contains additional files to be merged
# into base-bits-dir as part of making the image.
-
-publisher="The FreeBSD Project. http://www.freebsd.org/"
-IMG=/tmp/bootfs
-MNT=/mnt
-
-if [ "x$1" = "x-b" ]; then
- dd if=/dev/zero of=${IMG} bs=512 count=1024
- MD=`mdconfig -a -t vnode -f ${IMG}`
- sunlabel -w -B -b $4/boot/boot1 ${MD} auto
- newfs -O1 -o space -m 0 /dev/${MD}
- mount /dev/${MD} ${MNT}
- mkdir ${MNT}/boot
- cp $4/boot/loader ${MNT}/boot
- umount ${MNT}
- mdconfig -d -u ${MD#md}
- bootable="-B ,,,,${IMG}"
- shift
-else
- bootable=""
-fi
-
if [ $# -lt 3 ]; then
- echo Usage: $0 '[-b] image-label image-name base-bits-dir [extra-bits-dir]'
- rm -f ${IMG}
+ echo Usage: $0 '[-b] image-label image-name base-bits-dir [extra-bits-dir]' > /dev/stderr
exit 1
fi
-type mkisofs 2>&1 | grep " is " >/dev/null
-if [ $? -ne 0 ]; then
- echo The cdrtools port is not installed. Trying to get it now.
- if [ -f /usr/ports/sysutils/cdrtools/Makefile ]; then
- cd /usr/ports/sysutils/cdrtools && make install BATCH=yes && make clean
- else
- if ! pkg_add -r cdrtools; then
- echo "Could not get it via pkg_add - please go install this"
- echo "from the ports collection and run this script again."
- exit 2
- fi
- fi
-fi
-
+case $1 in
+-b) BOPT=$1; shift ;;
+esac
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
NAME=$1; shift
+# Create an ISO image
+publisher="The FreeBSD Project. http://www.FreeBSD.org/"
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
-mkisofs $bootable -r -J -V $LABEL -publisher "$publisher" -o $NAME $*
+makefs -t cd9660 -B be -o rockridge -o label="$LABEL" -o publisher="$publisher" ${NAME}.tmp $*
rm $1/etc/fstab
-rm -f ${IMG}
+
+if [ "x$BOPT" != "x-b" ]; then
+ mv ${NAME}.tmp ${NAME}
+ exit 0
+fi
+TMPIMGDIR=`mktemp -d /tmp/bootfs.XXXXXXXX` || exit 1
+BOOTFSDIR="${TMPIMGDIR}/bootfs"
+BOOTFSIMG="${TMPIMGDIR}/bootfs.img"
+
+# Create a boot filesystem
+mkdir -p "${BOOTFSDIR}/boot"
+cp $4/boot/loader "${BOOTFSDIR}/boot"
+makefs -t ffs -B be -M 512k "${BOOTFSIMG}" "${BOOTFSDIR}"
+dd if=$4/boot/boot1 of="${BOOTFSIMG}" bs=512 conv=notrunc,sync
+
+# Create a boot ISO image
+: ${CYLSIZE:=640}
+ISOSIZE=$(stat -f %z ${NAME}.tmp)
+ISOBLKS=$(((${ISOSIZE} + 511) / 512))
+ISOCYLS=$(((${ISOBLKS} + (${CYLSIZE} - 1)) / ${CYLSIZE}))
+
+BOOTFSSIZE=$(stat -f %z "${BOOTFSIMG}")
+BOOTFSBLKS=$(((${BOOTFSSIZE} + 511) / 512))
+BOOTFSCYLS=$(((${BOOTFSBLKS} + (${CYLSIZE} - 1)) / ${CYLSIZE}))
+
+ENDCYL=$((${ISOCYLS} + ${BOOTFSCYLS}))
+NSECTS=$((${ENDCYL} * 1 * ${CYLSIZE}))
+
+dd if=${NAME}.tmp of=${NAME} bs=${CYLSIZE}b conv=notrunc,sync
+dd if=${BOOTFSIMG} of=${NAME} bs=${CYLSIZE}b seek=${ISOCYLS} conv=notrunc,sync
+# The number of alternative cylinders is always 2.
+dd if=/dev/zero of=${NAME} bs=${CYLSIZE}b seek=${ENDCYL} count=2 conv=notrunc,sync
+rm -rf ${NAME}.tmp ${TMPIMGDIR}
+
+# Write VTOC8 label to boot ISO image
+MD=`mdconfig -a -t vnode -S 512 -y 1 -x ${CYLSIZE} -f ${NAME}`
+gpart create -s VTOC8 ${MD}
+# !4: usr, for ISO image part
+gpart add -i 1 -s $((${ISOCYLS} * ${CYLSIZE} * 512))b -t \!4 ${MD}
+# !2: root, for bootfs part.
+gpart add -i 6 -s $((${BOOTFSCYLS} * ${CYLSIZE} * 512))b -t \!2 ${MD}
+mdconfig -d -u ${MD#md}
diff --git a/sbin/devd/devd.8 b/sbin/devd/devd.8
index 7377e25..bc5092c 100644
--- a/sbin/devd/devd.8
+++ b/sbin/devd/devd.8
@@ -35,6 +35,7 @@
.Nm
.Op Fl Ddn
.Op Fl f Ar file
+.Op Fl l Ar num
.Sh DESCRIPTION
The
.Nm
@@ -55,6 +56,12 @@ instead of the default
If option
.Fl f
is specified more than once, the last file specified is used.
+.It Fl l Ar num
+Limit concurrent
+.Pa /var/run/devd.pipe
+connections to
+.Ar num .
+The default connection limit is 10.
.It Fl n
Do not process all pending events before becoming a daemon.
Instead, call daemon right away.
diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc
index 576dcf6..46f3623 100644
--- a/sbin/devd/devd.cc
+++ b/sbin/devd/devd.cc
@@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <libutil.h>
#include <paths.h>
+#include <poll.h>
#include <regex.h>
#include <signal.h>
#include <stdlib.h>
@@ -136,7 +137,7 @@ config cfg;
event_proc::event_proc() : _prio(-1)
{
- // nothing
+ _epsvec.reserve(4);
}
event_proc::~event_proc()
@@ -240,25 +241,18 @@ my_system(const char *command)
bool
action::do_action(config &c)
{
- string s = c.expand_string(_cmd);
+ string s = c.expand_string(_cmd.c_str());
if (Dflag)
fprintf(stderr, "Executing '%s'\n", s.c_str());
my_system(s.c_str());
return (true);
}
-match::match(config &c, const char *var, const char *re)
- : _var(var), _re("^")
+match::match(config &c, const char *var, const char *re) :
+ _inv(re[0] == '!'),
+ _var(var),
+ _re(c.expand_string(_inv ? re + 1 : re, "^", "$"))
{
- if (!c.expand_string(string(re)).empty() &&
- c.expand_string(string(re)).at(0) == '!') {
- _re.append(c.expand_string(string(re)).substr(1));
- _inv = 1;
- } else {
- _re.append(c.expand_string(string(re)));
- _inv = 0;
- }
- _re.append("$");
regcomp(&_regex, _re.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE);
}
@@ -623,24 +617,37 @@ config::expand_one(const char *&src, string &dst)
do {
buffer.append(src++, 1);
} while (is_id_char(*src));
- buffer.append("", 1);
dst.append(get_variable(buffer.c_str()));
}
const string
-config::expand_string(const string &s)
+config::expand_string(const char *src, const char *prepend, const char *append)
{
- const char *src;
+ const char *var_at;
string dst;
- src = s.c_str();
- while (*src) {
- if (*src == '$')
- expand_one(src, dst);
- else
- dst.append(src++, 1);
+ /*
+ * 128 bytes is enough for 2427 of 2438 expansions that happen
+ * while parsing config files, as tested on 2013-01-30.
+ */
+ dst.reserve(128);
+
+ if (prepend != NULL)
+ dst = prepend;
+
+ for (;;) {
+ var_at = strchr(src, '$');
+ if (var_at == NULL) {
+ dst.append(src);
+ break;
+ }
+ dst.append(src, var_at - src);
+ src = var_at;
+ expand_one(src, dst);
}
- dst.append("", 1);
+
+ if (append != NULL)
+ dst.append(append);
return (dst);
}
@@ -814,23 +821,58 @@ create_socket(const char *name)
return (fd);
}
+unsigned int max_clients = 10; /* Default, can be overriden on cmdline. */
+unsigned int num_clients;
list<int> clients;
void
notify_clients(const char *data, int len)
{
- list<int> bad;
- list<int>::const_iterator i;
+ list<int>::iterator i;
- for (i = clients.begin(); i != clients.end(); ++i) {
- if (write(*i, data, len) <= 0) {
- bad.push_back(*i);
+ /*
+ * Deliver the data to all clients. Throw clients overboard at the
+ * first sign of trouble. This reaps clients who've died or closed
+ * their sockets, and also clients who are alive but failing to keep up
+ * (or who are maliciously not reading, to consume buffer space in
+ * kernel memory or tie up the limited number of available connections).
+ */
+ for (i = clients.begin(); i != clients.end(); ) {
+ if (write(*i, data, len) != len) {
+ --num_clients;
close(*i);
- }
+ i = clients.erase(i);
+ } else
+ ++i;
}
+}
- for (i = bad.begin(); i != bad.end(); ++i)
- clients.erase(find(clients.begin(), clients.end(), *i));
+void
+check_clients(void)
+{
+ int s;
+ struct pollfd pfd;
+ list<int>::iterator i;
+
+ /*
+ * Check all existing clients to see if any of them have disappeared.
+ * Normally we reap clients when we get an error trying to send them an
+ * event. This check eliminates the problem of an ever-growing list of
+ * zombie clients because we're never writing to them on a system
+ * without frequent device-change activity.
+ */
+ pfd.events = 0;
+ for (i = clients.begin(); i != clients.end(); ) {
+ pfd.fd = *i;
+ s = poll(&pfd, 1, 0);
+ if ((s < 0 && s != EINTR ) ||
+ (s > 0 && (pfd.revents & POLLHUP))) {
+ --num_clients;
+ close(*i);
+ i = clients.erase(i);
+ } else
+ ++i;
+ }
}
void
@@ -838,9 +880,18 @@ new_client(int fd)
{
int s;
+ /*
+ * First go reap any zombie clients, then accept the connection, and
+ * shut down the read side to stop clients from consuming kernel memory
+ * by sending large buffers full of data we'll never read.
+ */
+ check_clients();
s = accept(fd, NULL, NULL);
- if (s != -1)
+ if (s != -1) {
+ shutdown(s, SHUT_RD);
clients.push_back(s);
+ ++num_clients;
+ }
}
static void
@@ -851,6 +902,7 @@ event_loop(void)
char buffer[DEVCTL_MAXBUF];
int once = 0;
int server_fd, max_fd;
+ int accepting;
timeval tv;
fd_set fds;
@@ -858,6 +910,7 @@ event_loop(void)
if (fd == -1)
err(1, "Can't open devctl device %s", PATH_DEVCTL);
server_fd = create_socket(PIPE);
+ accepting = 1;
max_fd = max(fd, server_fd) + 1;
while (1) {
if (romeo_must_die)
@@ -880,15 +933,38 @@ event_loop(void)
once++;
}
}
+ /*
+ * When we've already got the max number of clients, stop
+ * accepting new connections (don't put server_fd in the set),
+ * shrink the accept() queue to reject connections quickly, and
+ * poll the existing clients more often, so that we notice more
+ * quickly when any of them disappear to free up client slots.
+ */
FD_ZERO(&fds);
FD_SET(fd, &fds);
- FD_SET(server_fd, &fds);
- rv = select(max_fd, &fds, NULL, NULL, NULL);
+ if (num_clients < max_clients) {
+ if (!accepting) {
+ listen(server_fd, max_clients);
+ accepting = 1;
+ }
+ FD_SET(server_fd, &fds);
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+ } else {
+ if (accepting) {
+ listen(server_fd, 0);
+ accepting = 0;
+ }
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+ }
+ rv = select(max_fd, &fds, NULL, NULL, &tv);
if (rv == -1) {
if (errno == EINTR)
continue;
err(1, "select");
- }
+ } else if (rv == 0)
+ check_clients();
if (FD_ISSET(fd, &fds)) {
rv = read(fd, buffer, sizeof(buffer) - 1);
if (rv > 0) {
@@ -1007,7 +1083,8 @@ gensighand(int)
static void
usage()
{
- fprintf(stderr, "usage: %s [-Ddn] [-f file]\n", getprogname());
+ fprintf(stderr, "usage: %s [-Ddn] [-l connlimit] [-f file]\n",
+ getprogname());
exit(1);
}
@@ -1036,7 +1113,7 @@ main(int argc, char **argv)
int ch;
check_devd_enabled();
- while ((ch = getopt(argc, argv, "Ddf:n")) != -1) {
+ while ((ch = getopt(argc, argv, "Ddf:l:n")) != -1) {
switch (ch) {
case 'D':
Dflag++;
@@ -1047,6 +1124,9 @@ main(int argc, char **argv)
case 'f':
configfile = optarg;
break;
+ case 'l':
+ max_clients = MAX(1, strtoul(optarg, NULL, 0));
+ break;
case 'n':
nflag++;
break;
diff --git a/sbin/devd/devd.hh b/sbin/devd/devd.hh
index 3613216..a48d07b 100644
--- a/sbin/devd/devd.hh
+++ b/sbin/devd/devd.hh
@@ -90,9 +90,9 @@ public:
virtual bool do_match(config &);
virtual bool do_action(config &) { return true; }
private:
+ bool _inv;
std::string _var;
std::string _re;
- bool _inv;
regex_t _regex;
};
@@ -162,7 +162,8 @@ public:
void pop_var_table();
void set_variable(const char *var, const char *val);
const std::string &get_variable(const std::string &var);
- const std::string expand_string(const std::string &var);
+ const std::string expand_string(const char * var,
+ const char * prepend = NULL, const char * append = NULL);
char *set_vars(char *);
void find_and_execute(char);
protected:
diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8
index 61f8275..8843e53 100644
--- a/sbin/geom/class/part/gpart.8
+++ b/sbin/geom/class/part/gpart.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 3, 2013
+.Dd January 25, 2013
.Dt GPART 8
.Os
.Sh NAME
@@ -807,34 +807,51 @@ Both types of bootstrap code are used to boot from the GUID Partition Table.
First, a protective MBR is embedded into the first disk sector from the
.Pa /boot/pmbr
image.
-It searches the GPT
+It searches through the GPT for a
.Cm freebsd-boot
partition (see the
.Sx "PARTITION TYPES"
-section) in the GPT and runs the next bootstrap stage from it.
+section) and runs the next bootstrap stage from it.
The
.Cm freebsd-boot
partition should be smaller than 545 KB.
+It can be located either before or after other
+.Fx
+partitions on the disk.
There are two variants of bootstrap code to write to this partition:
.Pa /boot/gptboot
and
.Pa /boot/gptzfsboot .
.Pa /boot/gptboot
is used to boot from UFS.
-It searches
+It searches through
+.Cm freebsd-ufs
+partitions in the GPT and boots from the first one with the
+.Cm bootonce
+attribute set.
+If that attribute is not found,
+.Pa /boot/gptboot
+boots from the first
.Cm freebsd-ufs
-GPT partitions and starts
+partition with the
+.Cm bootme
+attribute set.
+If neither attribute is found,
+.Pa /boot/gptboot
+boots from the first
+.Cm freebsd-ufs
+partition.
.Pa /boot/loader
.Pq the third bootstrap stage
-if found.
-The
+is loaded from the first partition that matches these conditions.
.Pa /boot/gptzfsboot
is used to boot from ZFS.
-It searches
+It searches through the GPT for
.Cm freebsd-zfs
-GPT partitions and starts
+partitions, trying to detect ZFS pools.
+After all pools are detected,
.Pa /boot/zfsloader
-if found.
+is started from the first one found.
.Pp
The VTOC8 scheme does not support embedding bootstrap code.
Instead, the 8 KBytes bootstrap code image
@@ -945,7 +962,7 @@ The GEOM PART class can detect the same partition table visible through
different GEOM providers, and some of them will be marked as corrupt.
Be careful when choosing a provider for recovery.
If you choose incorrectly you can destroy the metadata of another GEOM class,
-e.g.\& GEOM MIRROR or GEOM LABEL.
+e.g.,\& GEOM MIRROR or GEOM LABEL.
.Sh SYSCTL VARIABLES
The following
.Xr sysctl 8
diff --git a/sbin/geom/class/raid/graid.8 b/sbin/geom/class/raid/graid.8
index 630cd01..ed33e00 100644
--- a/sbin/geom/class/raid/graid.8
+++ b/sbin/geom/class/raid/graid.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 13, 2012
+.Dd January 16, 2013
.Dt GRAID 8
.Os
.Sh NAME
@@ -274,7 +274,6 @@ complete it there.
Do not run GEOM RAID class on migrating volumes under pain of possible data
corruption!
.Sh 2TiB BARRIERS
-Promise metadata format does not support disks above 2TiB.
NVIDIA metadata format does not support volumes above 2TiB.
.Sh SYSCTL VARIABLES
The following
diff --git a/sbin/geom/class/raid3/geom_raid3.c b/sbin/geom/class/raid3/geom_raid3.c
index 3f037cd..cd0aa65 100644
--- a/sbin/geom/class/raid3/geom_raid3.c
+++ b/sbin/geom/class/raid3/geom_raid3.c
@@ -76,7 +76,7 @@ struct g_command class_commands[] = {
{ "insert", G_FLAG_VERBOSE, NULL,
{
{ 'h', "hardcode", NULL, G_TYPE_BOOL },
- { 'n', "number", NULL, G_TYPE_NUMBER },
+ { 'n', "number", G_VAL_OPTIONAL, G_TYPE_NUMBER },
G_OPT_SENTINEL
},
"[-hv] <-n number> name prov"
diff --git a/sbin/geom/class/raid3/graid3.8 b/sbin/geom/class/raid3/graid3.8
index f396cc3..a82d388 100644
--- a/sbin/geom/class/raid3/graid3.8
+++ b/sbin/geom/class/raid3/graid3.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 5, 2010
+.Dd January 15, 2012
.Dt GRAID3 8
.Os
.Sh NAME
@@ -53,7 +53,7 @@
.Nm
.Cm insert
.Op Fl hv
-.Fl n Ar number
+.Op Fl n Ar number
.Ar name
.Ar prov
.Nm
@@ -171,6 +171,8 @@ Add the given component to the existing array, if one of the components was
removed previously with the
.Cm remove
command or if one component is missing and will not be connected again.
+If no number is given, new component will be added instead of first missed
+component.
.Pp
Additional options include:
.Bl -tag -width ".Fl h"
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index 5911a94..b4db0f1 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -473,6 +473,8 @@ static struct cmd inet6_cmds[] = {
DEF_CMD("-nud", -ND6_IFF_PERFORMNUD, setnd6flags),
DEF_CMD("auto_linklocal",ND6_IFF_AUTO_LINKLOCAL,setnd6flags),
DEF_CMD("-auto_linklocal",-ND6_IFF_AUTO_LINKLOCAL,setnd6flags),
+ DEF_CMD("no_prefer_iface",ND6_IFF_NO_PREFER_IFACE,setnd6flags),
+ DEF_CMD("-no_prefer_iface",-ND6_IFF_NO_PREFER_IFACE,setnd6flags),
DEF_CMD_ARG("pltime", setip6pltime),
DEF_CMD_ARG("vltime", setip6vltime),
DEF_CMD("eui64", 0, setip6eui64),
diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c
index 80065f6..5c46452 100644
--- a/sbin/ifconfig/af_nd6.c
+++ b/sbin/ifconfig/af_nd6.c
@@ -58,7 +58,7 @@ static const char rcsid[] =
#define MAX_SYSCTL_TRY 5
#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
"\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
- "\007NO_RADR\020DEFAULTIF"
+ "\007NO_RADR\010NO_PREFER_IFACE\020DEFAULTIF"
static int isnd6defif(int);
void setnd6flags(const char *, int, int, const struct afswtch *);
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index f4c6daa..9c74980 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -28,7 +28,7 @@
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
.\" $FreeBSD$
.\"
-.Dd November 7, 2012
+.Dd January 10, 2013
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -716,6 +716,13 @@ Set a flag to enable Neighbor Unreachability Detection.
.It Cm -nud
Clear a flag
.Cm nud .
+.It Cm no_prefer_iface
+Set a flag to not prefer address on the interface as candidates of the
+source address for outgoing packets, even when the interface is
+outgoing interface.
+.It Cm -no_prefer_iface
+Clear a flag
+.Cm no_prefer_iface .
.El
.Pp
The following parameters are specific to cloning
diff --git a/sbin/newfs_msdos/newfs_msdos.c b/sbin/newfs_msdos/newfs_msdos.c
index c2e9a35..fe1631a 100644
--- a/sbin/newfs_msdos/newfs_msdos.c
+++ b/sbin/newfs_msdos/newfs_msdos.c
@@ -808,7 +808,7 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
struct stat st;
if (fstat(fd, &st))
- err(1, "Cannot get disk size");
+ err(1, "cannot get disk size");
/* create a fake geometry for a file image */
ms = st.st_size;
dlp.d_secsize = 512;
@@ -832,18 +832,18 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
if (ioctl(fd, DIOCGDINFO, &dlp) == -1) {
if (bpb->bpbBytesPerSec == 0 && ioctl(fd, DIOCGSECTORSIZE,
&dlp.d_secsize) == -1)
- errx(1, "Cannot get sector size, %s", strerror(errno));
+ err(1, "cannot get sector size");
dlp.d_secperunit = ms / dlp.d_secsize;
if (bpb->bpbSecPerTrack == 0 && ioctl(fd, DIOCGFWSECTORS,
&dlp.d_nsectors) == -1) {
- warnx("Cannot get number of sectors per track, %s", strerror(errno));
+ warn("cannot get number of sectors per track");
dlp.d_nsectors = 63;
}
if (bpb->bpbHeads == 0 &&
ioctl(fd, DIOCGFWHEADS, &dlp.d_ntracks) == -1) {
- warnx("Cannot get number of heads, %s", strerror(errno));
+ warn("cannot get number of heads");
if (dlp.d_secperunit <= 63*1*1024)
dlp.d_ntracks = 1;
else if (dlp.d_secperunit <= 63*16*1024)
diff --git a/sbin/route/route.c b/sbin/route/route.c
index 4637ba4..48f90a7 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -86,7 +86,6 @@ union sockunion {
#endif
struct sockaddr_at sat;
struct sockaddr_dl sdl;
- struct sockaddr_inarp sinarp;
struct sockaddr_storage ss; /* added to avoid memory overrun */
} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;
@@ -923,10 +922,8 @@ newroute(int argc, char **argv)
flags |= RTF_HOST;
if ((nrflags & F_INTERFACE) == 0)
flags |= RTF_GATEWAY;
- if (nrflags & F_PROXY) {
- so_dst.sinarp.sin_other = SIN_PROXY;
+ if (nrflags & F_PROXY)
flags |= RTF_ANNOUNCE;
- }
if (dest == NULL)
dest = "";
if (gateway == NULL)
diff --git a/sbin/setkey/Makefile b/sbin/setkey/Makefile
index 03c2ea2..e2c93cc 100644
--- a/sbin/setkey/Makefile
+++ b/sbin/setkey/Makefile
@@ -61,7 +61,7 @@ CLEANFILES+= scriptdump y.tab.h
#SCRIPTS= scriptdump
-LOCALPREFIX= /usr
+LOCALPREFIX= /usr/local
scriptdump: scriptdump.pl
sed -e 's#@LOCALPREFIX@#${LOCALPREFIX}#' < $> > scriptdump
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index 8fad089..43592b3 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -266,7 +266,7 @@ parse(const char *string, int lineno)
if (!(kind & CTLFLAG_WR)) {
if (kind & CTLFLAG_TUN) {
- warnx("oid '%s' is a read only tunable%p", bufp, line);
+ warnx("oid '%s' is a read only tunable%s", bufp, line);
warnx("Tunable values are set in /boot/loader.conf");
} else
warnx("oid '%s' is read only%s", bufp, line);
diff --git a/secure/lib/libssh/Makefile b/secure/lib/libssh/Makefile
index 7224823..937fa24 100644
--- a/secure/lib/libssh/Makefile
+++ b/secure/lib/libssh/Makefile
@@ -38,6 +38,10 @@ DPADD+= ${LIBGSSAPI} ${LIBKRB5} ${LIBHX509} ${LIBASN1} ${LIBCOM_ERR} ${LIBMD} ${
LDADD+= -lgssapi -lkrb5 -lhx509 -lasn1 -lcom_err -lmd -lroken
.endif
+.if ${MK_OPENSSH_NONE_CIPHER} != "no"
+CFLAGS+= -DNONE_CIPHER_ENABLED
+.endif
+
NO_LINT=
DPADD+= ${LIBCRYPTO} ${LIBCRYPT}
diff --git a/secure/usr.bin/ssh/Makefile b/secure/usr.bin/ssh/Makefile
index 9304fd5..0bee10c 100644
--- a/secure/usr.bin/ssh/Makefile
+++ b/secure/usr.bin/ssh/Makefile
@@ -25,6 +25,10 @@ DPADD+= ${LIBGSSAPI}
LDADD+= -lgssapi
.endif
+.if ${MK_OPENSSH_NONE_CIPHER} != "no"
+CFLAGS+= -DNONE_CIPHER_ENABLED
+.endif
+
DPADD+= ${LIBCRYPT} ${LIBCRYPTO}
LDADD+= -lcrypt -lcrypto
diff --git a/secure/usr.sbin/sshd/Makefile b/secure/usr.sbin/sshd/Makefile
index cc914c4..3fb0708 100644
--- a/secure/usr.sbin/sshd/Makefile
+++ b/secure/usr.sbin/sshd/Makefile
@@ -40,6 +40,10 @@ DPADD+= ${LIBGSSAPI_KRB5} ${LIBGSSAPI} ${LIBKRB5} ${LIBASN1}
LDADD+= -lgssapi_krb5 -lgssapi -lkrb5 -lasn1
.endif
+.if ${MK_OPENSSH_NONE_CIPHER} != "no"
+CFLAGS+= -DNONE_CIPHER_ENABLED
+.endif
+
DPADD+= ${LIBCRYPTO} ${LIBCRYPT}
LDADD+= -lcrypto -lcrypt
diff --git a/share/info/Makefile b/share/info/Makefile
index 0110e02..6c09adb 100644
--- a/share/info/Makefile
+++ b/share/info/Makefile
@@ -17,6 +17,6 @@ beforeinstall:
@exit 3;
.endif
.if !exists(${DESTDIR}${INFODIR}/dir)
- ${INSTALL} -o ${INFOOWN} -g ${INFOGRP} -m ${INFOMODE} \
+ ${INSTALL} -o ${INFOOWN} -g ${INFOGRP} -m 644 \
dir-tmpl ${DESTDIR}${INFODIR}/dir
.endif
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 8894cfd..cdd7474 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -70,6 +70,7 @@ MAN= aac.4 \
bce.4 \
bfe.4 \
bge.4 \
+ ${_bhyve.4} \
bktr.4 \
blackhole.4 \
bpf.4 \
@@ -784,6 +785,7 @@ MLINKS+=lindev.4 full.4
.endif
.if ${MACHINE_CPUARCH} == "amd64"
+_bhyve.4= bhyve.4
_qlxgb.4= qlxgb.4
_sfxge.4= sfxge.4
diff --git a/share/man/man4/bhyve.4 b/share/man/man4/bhyve.4
new file mode 100644
index 0000000..cdfc1e2
--- /dev/null
+++ b/share/man/man4/bhyve.4
@@ -0,0 +1,68 @@
+.\"
+.\" Copyright (c) 2012 NetApp Inc
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 5, 2013
+.Dt BHYVE 4
+.Os
+.Sh NAME
+.Nm bhyve
+.Nd virtual machine monitor
+.Sh SYNOPSIS
+.Cd "/usr/sbin/bhyve"
+.Cd "/usr/sbin/bhyveload"
+.Cd "/usr/sbin/bhyvectl"
+.Cd "/boot/kernel/vmm.ko"
+.Sh DESCRIPTION
+.Nm
+is a virtual machine monitor that is hosted by FreeBSD. It is used to host
+unmodified guest operating systems on top of FreeBSD.
+.Pp
+.Nm
+relies heavily on hardware assist provided by the CPU and chipset to virtualize
+processor and memory resources.
+.Sh SEE ALSO
+.Xr bhyve 8 ,
+.Xr bhyveload 8 ,
+.Xr bhyvectl 8 ,
+.Xr vmm 4
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 10.0 ,
+and was developed at NetApp Inc.
+.Sh AUTHORS
+.Nm
+was developed by
+.An -nosplit
+.An "Peter Grehan" Aq grehan@FreeBSD.org
+and
+.An "Neel Natu" Aq neel@FreeBSD.org
+at NetApp Inc.
+.Sh BUGS
+.Nm
+is considered experimental in
+.Fx .
diff --git a/share/man/man4/mfi.4 b/share/man/man4/mfi.4
index 9313335..0deb92d 100644
--- a/share/man/man4/mfi.4
+++ b/share/man/man4/mfi.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 12, 2010
+.Dd January 24, 2013
.Dt MFI 4
.Os
.Sh NAME
@@ -85,16 +85,24 @@ LSI MegaRAID SAS 8408E
.It
LSI MegaRAID SAS 8480E
.It
+LSI MegaRAID SAS 9240
+.It
LSI MegaRAID SAS 9260
.It
Dell PERC5
.It
Dell PERC6
.It
+IBM ServeRAID M1015 SAS/SATA
+.It
+IBM ServeRAID M1115 SAS/SATA
+.It
IBM ServeRAID M5015 SAS/SATA
.It
IBM ServeRAID-MR10i
.It
+Intel RAID Controller SRCSAS18E
+.It
Intel RAID Controller SROMBSAS18E
.El
.Sh FILES
diff --git a/share/man/man4/rl.4 b/share/man/man4/rl.4
index 4cbf6e9..583274b 100644
--- a/share/man/man4/rl.4
+++ b/share/man/man4/rl.4
@@ -30,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 22, 2010
+.Dd January 16, 2013
.Dt RL 4
.Os
.Sh NAME
@@ -155,6 +155,8 @@ Corega FEther CB-TXD
.It
Corega FEtherII CB-TXD
.It
+D-Link DFE-520TX (rev. C1)
+.It
D-Link DFE-528TX
.It
D-Link DFE-530TX+
diff --git a/share/man/man4/stf.4 b/share/man/man4/stf.4
index 5e32763..5e210df 100644
--- a/share/man/man4/stf.4
+++ b/share/man/man4/stf.4
@@ -190,8 +190,8 @@ The default value is shown next to each variable.
.It Va net.link.stf.permit_rfc1918 : No 0
The RFC3056 requires the use of globally unique 32-bit IPv4
addresses. This sysctl variable controls the behaviour of this
-requirement. When it set to not 0,
-.Nm stf
+requirement. When it set to not 0,
+.Nm stf
allows the use of private IPv4 addresses described in the RFC1918.
This may be useful for an Intranet environment or when some mechanisms
of network address translation (NAT) are used.
diff --git a/share/man/man5/make.conf.5 b/share/man/man5/make.conf.5
index f9d0184..f7fad38 100644
--- a/share/man/man5/make.conf.5
+++ b/share/man/man5/make.conf.5
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 14, 2012
+.Dd January 21, 2013
.Dt MAKE.CONF 5
.Os
.Sh NAME
@@ -255,10 +255,6 @@ Set this to not update the doc tree during
.Pq Vt bool
Set this to not update the ports tree during
.Dq Li "make update" .
-.It Va NO_WWWUPDATE
-.Pq Vt bool
-Set this to not update the www tree during
-.Dq Li "make update" .
.It Va SUP
.Pq Vt str
The location of the
@@ -309,6 +305,11 @@ and
.Pa ports
trees with
.Dq Li "make update" .
+This option is deprecated.
+Please use
+.Va SVN_UPDATE
+or
+.Xr freebsd-update 8 .
.It Va SVN_UPDATE
.Pq Vt bool
Set this to use
diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5
index faa117f..f621307 100644
--- a/share/man/man5/src.conf.5
+++ b/share/man/man5/src.conf.5
@@ -1,7 +1,7 @@
.\" DO NOT EDIT-- this file is automatically generated.
.\" from FreeBSD: head/tools/build/options/makeman 236279 2012-05-30 02:37:20Z gjb
.\" $FreeBSD$
-.Dd November 5, 2012
+.Dd February 2, 2013
.Dt SRC.CONF 5
.Os
.Sh NAME
@@ -100,6 +100,9 @@ Set to not build
.Xr apm 8 ,
.Xr apmd 8
and related programs.
+.It Va WITH_ARM_EABI
+.\" from FreeBSD: head/tools/build/options/WITH_ARM_EABI 245539 2013-01-17 05:56:28Z andrew
+Set the ARM ABI to EABI.
.It Va WITHOUT_ASSERT_DEBUG
.\" from FreeBSD: head/tools/build/options/WITHOUT_ASSERT_DEBUG 162215 2006-09-11 13:55:27Z ru
Set to compile programs and libraries without the
@@ -242,6 +245,9 @@ Set to not build the BSD licensed version of cpio based on
.It Va WITH_BSD_GREP
.\" from FreeBSD: head/tools/build/options/WITH_BSD_GREP 222273 2011-05-25 01:04:12Z obrien
Install BSD-licensed grep as '[ef]grep' instead of GNU grep.
+.It Va WITH_BSD_PATCH
+.\" from FreeBSD: head/tools/build/options/WITH_BSD_PATCH 246074 2013-01-29 17:03:18Z gabor
+Install BSD-licensed patch as 'patch' instead of GNU patch.
.It Va WITHOUT_BSNMP
.\" from FreeBSD: head/tools/build/options/WITHOUT_BSNMP 183306 2008-09-23 16:15:42Z sam
Set to not build or install
@@ -292,6 +298,8 @@ When set, it also enforces the following options:
.It
.Va WITHOUT_CLANG_EXTRAS
.It
+.Va WITHOUT_CLANG_FULL
+.It
.Va WITHOUT_CLANG_IS_CC
.El
.It Va WITH_CLANG
@@ -303,6 +311,20 @@ amd64/amd64, i386/i386, pc98/i386, powerpc/powerpc and powerpc/powerpc64.
.It Va WITH_CLANG_EXTRAS
.\" from FreeBSD: head/tools/build/options/WITH_CLANG_EXTRAS 231057 2012-02-05 23:56:22Z dim
Set to build additional clang and llvm tools, such as bugpoint.
+.It Va WITHOUT_CLANG_FULL
+.\" from FreeBSD: head/tools/build/options/WITHOUT_CLANG_FULL 246259 2013-02-02 22:28:29Z dim
+Set to avoid building the ARCMigrate, Rewriter and StaticAnalyzer components of
+the Clang C/C++ compiler.
+.Pp
+It is a default setting on
+arm/arm, arm/armeb, arm/armv6, arm/armv6eb, ia64/ia64, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32 and sparc64/sparc64.
+.It Va WITH_CLANG_FULL
+.\" from FreeBSD: head/tools/build/options/WITH_CLANG_FULL 246259 2013-02-02 22:28:29Z dim
+Set to build the ARCMigrate, Rewriter and StaticAnalyzer components of the
+Clang C/C++ compiler.
+.Pp
+It is a default setting on
+amd64/amd64, i386/i386, pc98/i386, powerpc/powerpc and powerpc/powerpc64.
.It Va WITHOUT_CLANG_IS_CC
.\" from FreeBSD: head/tools/build/options/WITHOUT_CLANG_IS_CC 242629 2012-11-05 21:53:23Z brooks
Set to install the GCC compiler as
@@ -379,6 +401,10 @@ When set, it also enforces the following options:
.It
.Va WITHOUT_CLANG
.It
+.Va WITHOUT_CLANG_EXTRAS
+.It
+.Va WITHOUT_CLANG_FULL
+.It
.Va WITHOUT_CLANG_IS_CC
.It
.Va WITHOUT_GROFF
@@ -476,6 +502,10 @@ Set to not build GPIB bus support.
Set to not build
.Xr gpioctl 8
as part of the base system.
+.It Va WITH_GPL_DTC
+.\" from FreeBSD: head/tools/build/options/WITH_GPL_DTC 246262 2013-02-02 22:42:46Z dim
+Set to build the GPL'd version of the device tree compiler from elinux.org,
+instead of the BSD licensed one.
.It Va WITHOUT_GROFF
.\" from FreeBSD: head/tools/build/options/WITHOUT_GROFF 218941 2011-02-22 08:13:49Z uqs
Set to not build
@@ -640,9 +670,9 @@ and
On amd64, set to not build 32-bit library set and a
.Nm ld-elf32.so.1
runtime linker.
-.It Va WITH_LIBCPLUSPLUS
-.\" from FreeBSD: head/tools/build/options/WITH_LIBCPLUSPLUS 228082 2011-11-28 17:56:46Z dim
-Set to build libcxxrt and libc++.
+.It Va WITHOUT_LIBCPLUSPLUS
+.\" from FreeBSD: head/tools/build/options/WITHOUT_LIBCPLUSPLUS 246262 2013-02-02 22:42:46Z dim
+Set to avoid building libcxxrt and libc++.
.It Va WITHOUT_LIBPTHREAD
.\" from FreeBSD: head/tools/build/options/WITHOUT_LIBPTHREAD 188848 2009-02-20 11:09:55Z mtm
Set to not build the
@@ -804,6 +834,16 @@ Set to not build NLS catalogs.
.\" from FreeBSD: head/tools/build/options/WITHOUT_NLS_CATALOGS 156932 2006-03-21 07:50:50Z ru
Set to not build NLS catalog support for
.Xr csh 1 .
+.It Va WITH_NMTREE
+.\" from FreeBSD: head/tools/build/options/WITH_NMTREE 245435 2013-01-14 20:38:32Z brooks
+Set to install
+.Xr nmtree 8
+as
+.Xr mtree 8 .
+By default
+.Xr fmtree 8
+is installed as
+.Xr mtree 8 .
.It Va WITHOUT_NS_CACHING
.\" from FreeBSD: head/tools/build/options/WITHOUT_NS_CACHING 172803 2007-10-19 14:01:25Z ru
Set to disable name caching in the
@@ -825,6 +865,16 @@ Infiniband software stack.
.It Va WITHOUT_OPENSSH
.\" from FreeBSD: head/tools/build/options/WITHOUT_OPENSSH 156932 2006-03-21 07:50:50Z ru
Set to not build OpenSSH.
+.It Va WITH_OPENSSH_NONE_CIPHER
+.\" from FreeBSD: head/tools/build/options/WITH_OPENSSH_NONE_CIPHER 245527 2013-01-17 01:51:04Z bz
+Set to include the "None" cipher support in OpenSSH and its libraries.
+Additional adjustments may need to be done to system configuration
+files, such as
+.Xr sshd_config 5 ,
+to enable this cipher.
+Please see
+.Pa /usr/src/crypto/openssh/README.hpn
+for full details.
.It Va WITHOUT_OPENSSL
.\" from FreeBSD: head/tools/build/options/WITHOUT_OPENSSL 156932 2006-03-21 07:50:50Z ru
Set to not build OpenSSL.
@@ -865,6 +915,11 @@ Set to build some programs without PAM support, particularly
.Xr ftpd 8
and
.Xr ppp 8 .
+.It Va WITHOUT_PC_SYSINSTALL
+.\" from FreeBSD: head/tools/build/options/WITHOUT_PC_SYSINSTALL 245606 2013-01-18 15:57:09Z eadler
+Set to not build
+.Xr pc-sysinstall 8
+and related programs.
.It Va WITHOUT_PF
.\" from FreeBSD: head/tools/build/options/WITHOUT_PF 156932 2006-03-21 07:50:50Z ru
Set to not build PF firewall package.
@@ -1022,6 +1077,10 @@ When set, it also enforces the following options:
.It
.Va WITHOUT_CLANG
.It
+.Va WITHOUT_CLANG_EXTRAS
+.It
+.Va WITHOUT_CLANG_FULL
+.It
.Va WITHOUT_CLANG_IS_CC
.It
.Va WITHOUT_GCC
diff --git a/share/man/man7/release.7 b/share/man/man7/release.7
index ff6fec4..8216eef 100644
--- a/share/man/man7/release.7
+++ b/share/man/man7/release.7
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 16, 2012
+.Dd February 3, 2013
.Dt RELEASE 7
.Os
.Sh NAME
@@ -116,26 +116,40 @@ Note that because this uses a chroot, it cannot be used to cross-build
.Fx
release media.
.Pp
-Environment variables:
-.Bl -tag -width ".Cm MAKE_FLAGS"
-.It Ev MAKE_FLAGS
+Optional environment variables:
+.Bl -tag -width ".Cm WORLD_FLAGS"
+.It Ev WORLD_FLAGS
This environment variable can be set to pass flags (e.g. -j) to
.Xr make 1
-when invoked by the script.
-.It Ev SVNROOT
-The location of the FreeBSD SVN source, doc, and ports repositories.
+when invoked to build a world by the script.
+.It Ev KERNEL_FLAGS
+This environment variable can be set to pass flags (e.g. -j) to
+.Xr make 1
+when invoked to build a kernel by the script.
+.It Ev SVNROOTBASE
+The base part of URL of the FreeBSD SVN repositories.
Defaults to
-.Pa svn://svn.freebsd.org/base
-for the source tree,
-.Pa svn://svn.freebsd.org/ports/head
-for the Ports Collection, and
-.Pa svn://svn.freebsd.org/doc/head
-for the Documentation Project source.
-.It Ev RELSTRING
-Optional base name for generated media images (e.g. FreeBSD-9.0-RC2-amd64).
-Defaults to the output of
-.Ic `uname -s`-`uname -r`-`uname -p`
-within the chroot.
+.Pa svn://svn.freebsd.org .
+.It Ev SVNROOTSRC
+The URL of the FreeBSD SVN source repository.
+Defaults to
+.Pa ${SVNROOTBASE}/base .
+.It Ev SVNROOTDOC
+The URL of the FreeBSD SVN doc repository.
+Defaults to
+.Pa ${SVNROOTBASE}/doc .
+.It Ev SVNROOTPORTS
+The URL of the FreeBSD SVN ports repository.
+Defaults to
+.Pa ${SVNROOTBASE}/ports .
+.It Ev BRANCHDOC
+The branch name of the FreeBSD SVN doc repository.
+Defaults to
+.Pa head .
+.It Ev BRANCHPORTS
+The branch name of the FreeBSD SVN ports repository.
+Defaults to
+.Pa head .
.El
.Sh MAKEFILE TARGETS
The release makefile
@@ -155,15 +169,12 @@ platform.
Copy all produced release media to
.Pa ${DESTDIR} .
.It Cm cdrom
-Builds installation CD-ROM images. On some systems, this may require that
-.Xr mkisofs 8
-be installed
-.Pq Pa sysutils/cdrtools
-and possibly that the
+Builds installation CD-ROM images.
+This may require the
.Xr md 4
(memory disk) device driver be present in the kernel
-(either by being compiled in or available as a module). This target
-produces files called
+(either by being compiled in or available as a module).
+This target produces files called
.Pa release.iso
and
.Pa bootonly.iso
@@ -171,7 +182,8 @@ as its output.
.It Cm memstick
Builds an installation memory stick image named
.Pa memstick .
-Not applicable on all platforms. Requires that the
+Not applicable on all platforms.
+Requires that the
.Xr md 4
(memory disk) device driver be present in the kernel
(either by being compiled in or available as a module).
@@ -207,27 +219,32 @@ target invoked by
.El
.Sh ENVIRONMENT
Optional variables:
-.Bl -tag -width ".Va TARGET_ARCH"
-.It Va WORLDDIR
+.Bl -tag -width ".Ev TARGET_ARCH"
+.It Ev OSRELEASE
+Optional base name for generated media images (e.g. FreeBSD-9.0-RC2-amd64).
+Defaults to the output of
+.Ic `uname -s`-`uname -r`-`uname -p`
+within the chroot.
+.It Ev WORLDDIR
Location of a directory containing the src tree. By default, the directory
above the one containing the makefile
.Pq Pa src .
-.It Va PORTSDIR
+.It Ev PORTSDIR
Location of a directory containing the ports tree. By default,
.Pa /usr/ports .
If it is unset or cannot be found, ports will not be included in the release.
-.It Va DOCDIR
+.It Ev DOCDIR
Location of a directory containing the doc tree. By default,
.Pa /usr/doc .
If it is unset or cannot be found, most documentation will not be included in
the release; see
.Ev NODOC
below.
-.It Va NOPORTS
+.It Ev NOPORTS
If defined, the Ports Collection will be omitted from the release.
-.It Va NOSRC
+.It Ev NOSRC
If set, do not include system source code in the release.
-.It Va NODOC
+.It Ev NODOC
If defined, the XML-based documentation from the
.Fx
Documentation Project will not be built.
@@ -236,33 +253,33 @@ However, the
distribution will still be created with the minimal documentation set
provided in
.Pa src/share/doc .
-.It Va TARGET
+.It Ev TARGET
The target hardware platform.
This is analogous to the
.Dq Nm uname Fl m
output.
This is necessary to cross-build some target architectures.
For example, cross-building for PC98 machines requires
-.Va TARGET_ARCH Ns = Ns Li i386
+.Ev TARGET_ARCH Ns = Ns Li i386
and
-.Va TARGET Ns = Ns Li pc98 .
+.Ev TARGET Ns = Ns Li pc98 .
If not set,
-.Va TARGET
+.Ev TARGET
defaults to the current hardware platform.
-.It Va TARGET_ARCH
+.It Ev TARGET_ARCH
The target machine processor architecture.
This is analogous to the
.Dq Nm uname Fl p
output.
Set this to cross-build for a different architecture.
If not set,
-.Va TARGET_ARCH
+.Ev TARGET_ARCH
defaults to the current machine architecture, unless
-.Va TARGET
+.Ev TARGET
is also set, in which case it defaults to the appropriate
value for that platform.
Typically, one only needs to set
-.Va TARGET .
+.Ev TARGET .
.El
.Sh FILES
.Bl -tag -compact -width Pa
@@ -299,7 +316,6 @@ The following sequence of commands can be used to build a
in a clean environment, including ports and documentation:
.Bd -literal -offset indent
cd /usr/src/release
-export SVNROOT=svn://svn.freebsd.org/base
sh generate-release.sh head /local3/release
.Ed
.Pp
@@ -310,7 +326,7 @@ directory.
.Xr cc 1 ,
.Xr install 1 ,
.Xr make 1 ,
-.Xr svn 1 Pq Pa ports/devel/subversion-freebsd ,
+.Xr svn 1 Pq Pa ports/devel/subversion ,
.Xr uname 1 ,
.Xr md 4 ,
.Xr make.conf 5 ,
diff --git a/share/man/man9/VFS_SET.9 b/share/man/man9/VFS_SET.9
index f30f431..cc2e037 100644
--- a/share/man/man9/VFS_SET.9
+++ b/share/man/man9/VFS_SET.9
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 5, 2007
+.Dd January 28, 2013
.Dt VFS_SET 9
.Os
.Sh NAME
@@ -84,26 +84,18 @@ sysctl is set to
.Sh PSEUDOCODE
.Bd -literal
/*
- * fill in the ones we use, and use the vfs_std for the rest.
+ * Fill in the fields for which we have special methods.
+ * The others are initially null. This tells vfs to change them to
+ * pointers to vfs_std* functions during file system registration.
*/
static struct vfsops myfs_vfsops = {
- myfs_mount,
- vfs_stdstart,
- myfs_unmount,
- myfs_root,
- vfs_stdquotactl,
- myfs_statfs,
- vfs_stdsync,
- vfs_stdvget,
- vfs_stdfhtovp,
- vfs_stdcheckexp,
- vfs_stdvptofh,
- vfs_stdinit,
- vfs_stduninit,
- vfs_stdextattrctl,
+ .vfs_mount = myfs_mount,
+ .vfs_root = myfs_root,
+ .vfs_statfs = myfs_statfs,
+ .vfs_unmount = myfs_unmount,
};
-VFS_SET(myfs_vfsops, skelfs, 0);
+VFS_SET(myfs_vfsops, myfs, 0);
.Ed
.Sh SEE ALSO
.Xr jail 2 ,
diff --git a/share/man/man9/vm_map_insert.9 b/share/man/man9/vm_map_insert.9
index 3a6a51f..8f3b52e 100644
--- a/share/man/man9/vm_map_insert.9
+++ b/share/man/man9/vm_map_insert.9
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 19, 2003
+.Dd January 11, 2013
.Dt VM_MAP_INSERT 9
.Os
.Sh NAME
@@ -73,9 +73,6 @@ This function implicitly creates a new
.Vt vm_map_entry
by calling the internal function
.Fn vm_map_entry_create .
-This function may use the
-.Va Giant
-lock to ensure that only a single thread is present in the function.
.Sh RETURN VALUES
The
.Fn vm_map_insert
diff --git a/share/man/man9/vm_map_stack.9 b/share/man/man9/vm_map_stack.9
index dabe937..e237c06 100644
--- a/share/man/man9/vm_map_stack.9
+++ b/share/man/man9/vm_map_stack.9
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 19, 2003
+.Dd January 11, 2013
.Dt VM_MAP_STACK 9
.Os
.Sh NAME
@@ -81,11 +81,11 @@ function calls
to create its mappings.
.Pp
The
+.Fn vm_map_stack
+and
.Fn vm_map_growstack
-function acquires the
-.Va Giant
-lock, and the process lock on
-.Fa p ,
+functions acquire the process lock on
+.Fa p
for the duration of the call.
.Sh RETURN VALUES
The
diff --git a/share/misc/committers-doc.dot b/share/misc/committers-doc.dot
index 0d896b3..168dcd2 100644
--- a/share/misc/committers-doc.dot
+++ b/share/misc/committers-doc.dot
@@ -58,6 +58,7 @@ brueffer [label="Christian Brueffer\nbrueffer@FreeBSD.org\n2003/01/13"]
chinsan [label="Chinsan Huang\nchinsan@FreeBSD.org\n2006/09/20"]
danger [label="Daniel Gerzo\ndanger@FreeBSD.org\n2006/08/20"]
delphij [label="Xin Li\ndelphij@FreeBSD.org\n2004/09/14"]
+dru [label="Dru Lavigne\ndru@FreeBSD.org\n2013/01/22"]
eadler [label="Eitan Adler\neadler@FreeBSD.org\n2012/10/15"]
ebrandi [label="Edson Brandi\nebrandi@FreeBSD.org\n2012/09/13"]
gabor [label="Gabor Kovesdan\ngabor@FreeBSD.org\n2007/02/02"]
@@ -93,6 +94,7 @@ zeising [label="Niclas Zeising\nzeising@FreeBSD.org\n2012/07/03"]
bcr -> gavin
bcr -> wblock
bcr -> eadler
+bcr -> dru
blackend -> ale
@@ -116,8 +118,11 @@ gabor -> issyl0
gabor -> ebrandi
gjb -> wblock
+gjb -> rene
+gjb -> dru
hrs -> ryusuke
+hrs -> dru
jesusr -> jcamou
diff --git a/share/misc/committers-ports.dot b/share/misc/committers-ports.dot
index af20fc0..cf48d6a 100644
--- a/share/misc/committers-ports.dot
+++ b/share/misc/committers-ports.dot
@@ -77,6 +77,7 @@ culot [label="Frederic Culot\nculot@FreeBSD.org\n2010/10/16"]
daichi [label="Daichi Goto\ndaichi@FreeBSD.org\n2002/10/17"]
danfe [label="Alexey Dokuchaev\ndanfe@FreeBSD.org\n2004/08/20"]
db [label="Diane Bruce\ndb@FreeBSD.org\n2007/01/18"]
+dbn [label="David Naylor\ndbn@FreeBSD.org\n2013/01/14"]
decke [label="Bernhard Froehlich\ndecke@FreeBSD.org\n2010/03/21"]
delphij [label="Xin Li\ndelphij@FreeBSD.org\n2006/05/01"]
demon [label="Dmitry Sivachenko\ndemon@FreeBSD.org\n2000/11/13"]
@@ -233,6 +234,8 @@ asami -> obrien
avilla -> jhale
avilla -> rakuco
+bdrewery -> dbn
+
bapt -> bdrewery
bapt -> eadler
bapt -> jlaffaye
@@ -274,6 +277,7 @@ delphij -> rafan
demon -> mat
eadler -> ak
+eadler -> dbn
eadler -> bdrewery
eadler -> gjb
eadler -> tj
diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot
index f3756e8..a733a0e 100644
--- a/share/misc/committers-src.dot
+++ b/share/misc/committers-src.dot
@@ -117,6 +117,7 @@ bruno [label="Bruno Ducrot\nbruno@FreeBSD.org\n2005/07/18"]
bryanv [label="Bryan Venteicher\nbryanv@FreeBSD.org\n2012/11/03"]
bschmidt [label="Bernhard Schmidt\nbschmidt@FreeBSD.org\n2010/02/06"]
bz [label="Bjoern A. Zeeb\nbz@FreeBSD.org\n2004/07/27"]
+carl [label="Carl Delsey\ncarl@FreeBSD.org\n2013/01/14"]
cognet [label="Olivier Houchard\ncognet@FreeBSD.org\n2002/10/09"]
cokane [label="Coleman Kane\ncokane@FreeBSD.org\n2000/06/19"]
cperciva [label="Colin Percival\ncperciva@FreeBSD.org\n2004/01/20"]
@@ -159,6 +160,7 @@ grog [label="Greg Lehey\ngrog@FreeBSD.org\n1998/08/30"]
gshapiro [label="Gregory Shapiro\ngshapiro@FreeBSD.org\n2000/07/12"]
harti [label="Hartmut Brandt\nharti@FreeBSD.org\n2003/01/29"]
hmp [label="Hiten Pandya\nhmp@FreeBSD.org\n2004/03/23"]
+ian [label="Ian Lepore\nian@FreeBSD.org\n2013/01/07"]
iedowse [label="Ian Dowse\niedowse@FreeBSD.org\n2000/12/01"]
imp [label="Warner Losh\nimp@FreeBSD.org\n1996/09/20"]
ivoras [label="Ivan Voras\nivoras@FreeBSD.org\n2008/06/10"]
@@ -338,6 +340,7 @@ bz -> syrinx
cognet -> jceel
cognet -> kevlo
+cognet -> ian
cperciva -> eadler
cperciva -> flz
@@ -454,6 +457,8 @@ jhb -> peterj
jhb -> pfg
jhb -> rnoland
+jimharris -> carl
+
jkh -> grog
jkh -> imp
jkh -> jlemon
diff --git a/share/mk/Makefile b/share/mk/Makefile
index 81f943c..2110b26 100644
--- a/share/mk/Makefile
+++ b/share/mk/Makefile
@@ -6,7 +6,6 @@
FILES= \
bsd.README \
bsd.arch.inc.mk \
- bsd.compat.mk \
bsd.compiler.mk \
bsd.cpu.mk \
bsd.crunchgen.mk \
diff --git a/share/mk/bsd.README b/share/mk/bsd.README
index f09142e..a9adc1f 100644
--- a/share/mk/bsd.README
+++ b/share/mk/bsd.README
@@ -356,6 +356,8 @@ SHLIB_LDSCRIPT Template file to generate shared library linker script.
Unless used, a simple symlink is created to the real
shared object.
+LIBRARIES_ONLY Do not build or install files other than the library.
+
The include file <bsd.lib.mk> includes the file named "../Makefile.inc"
if it exists, as well as the include file <bsd.man.mk>.
diff --git a/share/mk/bsd.compat.mk b/share/mk/bsd.compat.mk
deleted file mode 100644
index 6a86871..0000000
--- a/share/mk/bsd.compat.mk
+++ /dev/null
@@ -1,41 +0,0 @@
-# $FreeBSD$
-
-.if !defined(BURN_BRIDGES)
-.for oldnew in \
- NOATM:NO_ATM \
- NOCLEANDIR:NO_CLEANDIR \
- NOCRYPT:NO_CRYPT \
- NODOCCOMPRESS:NO_DOCCOMPRESS \
- NOEXTRADEPEND:NO_EXTRADEPEND \
- NOFORTH:NO_FORTH \
- NOFSCHG:NO_FSCHG \
- NOGAMES:NO_GAMES \
- NOHTML:NO_HTML \
- NOINET6:NO_INET6 \
- NOINFO:NO_INFO \
- NOINFOCOMPRESS:NO_INFOCOMPRESS \
- NOINSTALLLIB:NO_INSTALLLIB \
- NOLIBPTHREAD:NO_LIBPTHREAD \
- NOLIBTHR:NO_LIBTHR \
- NOLINT:NO_LINT \
- NOMAN:NO_MAN \
- NOMANCOMPRESS:NO_MANCOMPRESS \
- NOMLINKS:NO_MLINKS \
- NOOBJ:NO_OBJ \
- NOPAM:NO_PAM \
- NOPIC:NO_PIC \
- NOPROFILE:NO_PROFILE \
- NO_RCMNDS:NO_RCMDS \
- NOSHARE:NO_SHARE \
- NOSHARED:NO_SHARED \
- NOTAGS:NO_TAGS
-.for old in ${oldnew:C/:.*//}
-.for new in ${oldnew:C/.*://}
-.if defined(${old}) && !defined(${new})
-.warning ${old} is deprecated in favour of ${new}
-${new}= ${${old}}
-.endif
-.endfor
-.endfor
-.endfor
-.endif
diff --git a/share/mk/bsd.incs.mk b/share/mk/bsd.incs.mk
index d51fb17..74c378b 100644
--- a/share/mk/bsd.incs.mk
+++ b/share/mk/bsd.incs.mk
@@ -73,7 +73,7 @@ installincludes:
t=${DESTDIR}$$1; \
shift; \
${ECHO} $$t -\> $$l; \
- ln -fs $$l $$t; \
+ ${INSTALL_SYMLINK} $$l $$t; \
done; true
.endif
.endif # !target(installincludes)
diff --git a/share/mk/bsd.info.mk b/share/mk/bsd.info.mk
index 9c3220d..c54b435 100644
--- a/share/mk/bsd.info.mk
+++ b/share/mk/bsd.info.mk
@@ -113,7 +113,7 @@ DVIPS2ASCII?= dvips2ascii
.info.html:
${INFO2HTML} ${.IMPSRC}
- ln -f ${.TARGET:R}.info.Top.html ${.TARGET}
+ ${INSTALL_LINK} ${.TARGET:R}.info.Top.html ${.TARGET}
.PATH: ${.CURDIR} ${SRCDIR}
diff --git a/share/mk/bsd.init.mk b/share/mk/bsd.init.mk
index 72a6de0..f5f4c66 100644
--- a/share/mk/bsd.init.mk
+++ b/share/mk/bsd.init.mk
@@ -9,7 +9,6 @@ __<bsd.init.mk>__:
.if exists(${.CURDIR}/../Makefile.inc)
.include "${.CURDIR}/../Makefile.inc"
.endif
-.include <bsd.compat.mk>
.include <bsd.own.mk>
.MAIN: all
.endif # !target(__<bsd.init.mk>__)
diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk
index 1335964..f406c23 100644
--- a/share/mk/bsd.lib.mk
+++ b/share/mk/bsd.lib.mk
@@ -184,7 +184,7 @@ ${SHLIB_NAME_FULL}: ${SOBJS}
@${ECHO} building shared library ${SHLIB_NAME}
@rm -f ${SHLIB_NAME} ${SHLIB_LINK}
.if defined(SHLIB_LINK)
- @ln -fs ${SHLIB_NAME} ${SHLIB_LINK}
+ @${INSTALL_SYMLINK} ${SHLIB_NAME} ${SHLIB_LINK}
.endif
.if !defined(NM)
@${CC} ${LDFLAGS} ${SSP_CFLAGS} ${SOLINKOPTS} \
@@ -309,9 +309,9 @@ _libinstall:
${_INSTALLFLAGS} lib${LIB}.ld ${DESTDIR}${LIBDIR}/${SHLIB_LINK}
.else
.if ${SHLIBDIR} == ${LIBDIR}
- ln -fs ${SHLIB_NAME} ${DESTDIR}${LIBDIR}/${SHLIB_LINK}
+ ${INSTALL_SYMLINK} ${SHLIB_NAME} ${DESTDIR}${LIBDIR}/${SHLIB_LINK}
.else
- ln -fs ${_SHLIBDIRPREFIX}${SHLIBDIR}/${SHLIB_NAME} \
+ ${INSTALL_SYMLINK} ${_SHLIBDIRPREFIX}${SHLIBDIR}/${SHLIB_NAME} \
${DESTDIR}${LIBDIR}/${SHLIB_LINK}
.if exists(${DESTDIR}${LIBDIR}/${SHLIB_NAME})
-chflags noschg ${DESTDIR}${LIBDIR}/${SHLIB_NAME}
@@ -331,12 +331,15 @@ _libinstall:
.endif
.endif # !defined(INTERNALLIB)
+.if !defined(LIBRARIES_ONLY)
.include <bsd.nls.mk>
.include <bsd.files.mk>
.include <bsd.incs.mk>
+.endif
+
.include <bsd.links.mk>
-.if ${MK_MAN} != "no"
+.if ${MK_MAN} != "no" && !defined(LIBRARIES_ONLY)
realinstall: _maninstall
.ORDER: beforeinstall _maninstall
.endif
@@ -348,7 +351,7 @@ lint: ${SRCS:M*.c}
${LINT} ${LINTFLAGS} ${CFLAGS:M-[DIU]*} ${.ALLSRC}
.endif
-.if ${MK_MAN} != "no"
+.if ${MK_MAN} != "no" && !defined(LIBRARIES_ONLY)
.include <bsd.man.mk>
.endif
diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk
index 4f8bedd..95f9064 100644
--- a/share/mk/bsd.libnames.mk
+++ b/share/mk/bsd.libnames.mk
@@ -162,6 +162,7 @@ LIBULOG?= ${DESTDIR}${LIBDIR}/libulog.a
LIBUTIL?= ${DESTDIR}${LIBDIR}/libutil.a
LIBUUTIL?= ${DESTDIR}${LIBDIR}/libuutil.a
LIBVGL?= ${DESTDIR}${LIBDIR}/libvgl.a
+LIBVMMAPI?= ${DESTDIR}${LIBDIR}/libvmmapi.a
LIBWIND?= ${DESTDIR}${LIBDIR}/libwind.a
LIBWRAP?= ${DESTDIR}${LIBDIR}/libwrap.a
LIBXPG4?= ${DESTDIR}${LIBDIR}/libxpg4.a
diff --git a/share/mk/bsd.links.mk b/share/mk/bsd.links.mk
index 49f557a..1e4d57e 100644
--- a/share/mk/bsd.links.mk
+++ b/share/mk/bsd.links.mk
@@ -15,7 +15,7 @@ _installlinks:
t=${DESTDIR}$$1; \
shift; \
${ECHO} $$t -\> $$l; \
- ln -f $$l $$t; \
+ ${INSTALL_LINK} $$l $$t; \
done; true
.endif
.if defined(SYMLINKS) && !empty(SYMLINKS)
@@ -26,6 +26,6 @@ _installlinks:
t=${DESTDIR}$$1; \
shift; \
${ECHO} $$t -\> $$l; \
- ln -fs $$l $$t; \
+ ${INSTALL_SYMLINK} $$l $$t; \
done; true
.endif
diff --git a/share/mk/bsd.man.mk b/share/mk/bsd.man.mk
index 8602b55..6445ba3 100644
--- a/share/mk/bsd.man.mk
+++ b/share/mk/bsd.man.mk
@@ -62,7 +62,7 @@ MROFF_CMD?= groff -Tascii -mtty-char -man -t
MCOMPRESS_CMD?= ${COMPRESS_CMD}
MCOMPRESS_EXT?= ${COMPRESS_EXT}
-SECTIONS= 1 1aout 2 3 4 5 6 7 8 9
+SECTIONS= 1 2 3 4 5 6 7 8 9
.SUFFIXES: ${SECTIONS:S/^/./g}
# Backwards compatibility.
@@ -216,7 +216,7 @@ _maninstall: ${MAN}
t=${DESTDIR}${MANDIR}$${sect}${MANSUBDIR}/$$name; \
${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \
rm -f $${t} $${t}${MCOMPRESS_EXT}; \
- ln $${l}${ZEXT} $${t}${ZEXT}; \
+ ${INSTALL_LINK} $${l}${ZEXT} $${t}${ZEXT}; \
done
.if defined(MANBUILDCAT) && !empty(MANBUILDCAT)
@set ${MLINKS:C/\.([^.]*)$/.\1 \1/}; \
@@ -231,7 +231,7 @@ _maninstall: ${MAN}
t=${DESTDIR}${CATDIR}$${sect}${MANSUBDIR}/$$name; \
${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \
rm -f $${t} $${t}${MCOMPRESS_EXT}; \
- ln $${l}${ZEXT} $${t}${ZEXT}; \
+ ${INSTALL_LINK} $${l}${ZEXT} $${t}${ZEXT}; \
done
.endif
.endif
diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk
index 78af8fb..aea33d3 100644
--- a/share/mk/bsd.own.mk
+++ b/share/mk/bsd.own.mk
@@ -181,6 +181,15 @@ NLSMODE?= ${NOBINMODE}
INCLUDEDIR?= /usr/include
+#
+# install(1) parameters.
+#
+HRDLINK?= -l h
+SYMLINK?= -l s
+
+INSTALL_LINK?= ${INSTALL} ${HRDLINK}
+INSTALL_SYMLINK?= ${INSTALL} ${SYMLINK}
+
# Common variables
.if !defined(DEBUG_FLAGS)
STRIP?= -s
@@ -216,80 +225,6 @@ WITHOUT_${var}=
.endfor
#
-# Compat NO_* options (same as above, except their use is deprecated).
-#
-.if !defined(BURN_BRIDGES)
-.for var in \
- ACPI \
- ATM \
- AUDIT \
- AUTHPF \
- BIND \
- BIND_DNSSEC \
- BIND_ETC \
- BIND_LIBS_LWRES \
- BIND_MTREE \
- BIND_NAMED \
- BIND_UTILS \
- BLUETOOTH \
- BOOT \
- CALENDAR \
- CPP \
- CRYPT \
- CVS \
- CXX \
- DICT \
- DYNAMICROOT \
- EXAMPLES \
- FORTH \
- FP_LIBC \
- GAMES \
- GCOV \
- GDB \
- GNU \
- GPIB \
- GROFF \
- HTML \
- INET6 \
- INFO \
- IPFILTER \
- IPX \
- KDUMP \
- KERBEROS \
- LIB32 \
- LIBPTHREAD \
- LIBTHR \
- LOCALES \
- LPR \
- MAILWRAPPER \
- NETCAT \
- NIS \
- NLS \
- NLS_CATALOGS \
- NS_CACHING \
- OPENSSH \
- OPENSSL \
- PAM \
- PF \
- RCMDS \
- RCS \
- RESCUE \
- SENDMAIL \
- SETUID_LOGIN \
- SHAREDOCS \
- SYSCONS \
- TCSH \
- TOOLCHAIN \
- USB \
- WPA_SUPPLICANT_EAPOL
-.if defined(NO_${var})
-#.warning NO_${var} is deprecated in favour of WITHOUT_${var}=
-WITHOUT_${var}=
-.endif
-.endfor
-.endif # !defined(BURN_BRIDGES)
-
-#
# Older-style variables that enabled behaviour when set.
#
.if defined(YES_HESIOD)
@@ -383,6 +318,7 @@ __DEFAULT_YES_OPTIONS = \
OPENSSH \
OPENSSL \
PAM \
+ PC_SYSINSTALL \
PF \
PKGBOOTSTRAP \
PKGTOOLS \
@@ -417,6 +353,8 @@ __DEFAULT_YES_OPTIONS = \
ZONEINFO
__DEFAULT_NO_OPTIONS = \
+ ARM_EABI \
+ BSD_PATCH \
BIND_IDN \
BIND_LARGE_FILE \
BIND_LIBS \
@@ -427,12 +365,15 @@ __DEFAULT_NO_OPTIONS = \
BSD_GREP \
CLANG_EXTRAS \
CTF \
+ GPL_DTC \
HESIOD \
ICONV \
IDEA \
INSTALL_AS_USER \
+ NMTREE \
NAND \
OFED \
+ OPENSSH_NONE_CIPHER \
SHARED_TOOLCHAIN
#
@@ -450,9 +391,9 @@ __T=${MACHINE_ARCH}
.endif
# Clang is only for x86 and powerpc right now, by default.
.if ${__T} == "amd64" || ${__T} == "i386" || ${__T:Mpowerpc*}
-__DEFAULT_YES_OPTIONS+=CLANG
+__DEFAULT_YES_OPTIONS+=CLANG CLANG_FULL
.else
-__DEFAULT_NO_OPTIONS+=CLANG
+__DEFAULT_NO_OPTIONS+=CLANG CLANG_FULL
.endif
# Clang the default system compiler only on x86.
.if ${__T} == "amd64" || ${__T} == "i386"
@@ -540,10 +481,6 @@ MK_ZFS:= no
MK_CTF:= no
.endif
-.if ${MK_CLANG} == "no"
-MK_CLANG_EXTRAS:= no
-.endif
-
.if ${MK_CRYPT} == "no"
MK_OPENSSL:= no
MK_OPENSSH:= no
@@ -586,6 +523,8 @@ MK_GDB:= no
.endif
.if ${MK_CLANG} == "no"
+MK_CLANG_EXTRAS:= no
+MK_CLANG_FULL:= no
MK_CLANG_IS_CC:= no
.endif
diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk
index cfa07a3..801f804 100644
--- a/share/mk/bsd.prog.mk
+++ b/share/mk/bsd.prog.mk
@@ -95,8 +95,7 @@ ${PROG}: ${OBJS}
.if ${MK_MAN} != "no" && !defined(MAN) && \
!defined(MAN1) && !defined(MAN2) && !defined(MAN3) && \
!defined(MAN4) && !defined(MAN5) && !defined(MAN6) && \
- !defined(MAN7) && !defined(MAN8) && !defined(MAN9) && \
- !defined(MAN1aout)
+ !defined(MAN7) && !defined(MAN8) && !defined(MAN9)
MAN= ${PROG}.1
MAN1= ${MAN}
.endif
diff --git a/share/mk/sys.mk b/share/mk/sys.mk
index 2f67903..8b8a5ce 100644
--- a/share/mk/sys.mk
+++ b/share/mk/sys.mk
@@ -346,5 +346,4 @@ OBJFORMAT?= elf
.endif
-.include <bsd.compat.mk>
.include <bsd.cpu.mk>
diff --git a/share/monetdef/Makefile b/share/monetdef/Makefile
index 972f149..4f0adcc 100644
--- a/share/monetdef/Makefile
+++ b/share/monetdef/Makefile
@@ -110,11 +110,11 @@ ISO8859-1_ISO8859-15= af_ZA ca_AD ca_ES ca_FR ca_IT da_DK de_AT de_CH de_DE \
fi_FI fr_BE fr_CA fr_CH fr_FR \
is_IS it_IT it_CH nl_BE nl_NL nb_NO nn_NO no_NO sv_SE
ISO8859-1_US-ASCII= en_AU en_CA en_GB en_NZ en_US
-ISO8859-1_UTF-8= af_ZA ca_AD ca_ES ca_FR ca_IT da_DK de_AT de_CH de_DE \
+ISO8859-1_UTF-8= af_ZA ca_ES da_DK de_AT de_CH de_DE \
en_AU en_CA en_NZ en_US es_ES \
fi_FI fr_BE fr_CA fr_FR is_IS it_IT nl_BE \
nl_NL nb_NO nn_NO no_NO pt_BR sv_SE
-ISO8859-2_UTF-8= hr_HR hu_HU ro_RO sk_SK sl_SI sr_YU
+ISO8859-2_UTF-8= hr_HR hu_HU ro_RO sk_SK sl_SI
ISO8859-7_UTF-8= el_GR
ISO8859-9_UTF-8= tr_TR
ISO8859-13_ISO8859-4= lt_LT
diff --git a/share/msgdef/Makefile b/share/msgdef/Makefile
index 069498f..59a5383 100644
--- a/share/msgdef/Makefile
+++ b/share/msgdef/Makefile
@@ -112,7 +112,7 @@ ISO8859-1_ISO8859-15= af_ZA ca_ES da_DK de_DE en_CA en_GB en_US es_ES \
${NL_LINKS} ${NO_LINKS}
ISO8859-1_US-ASCII= ${GB_LINKS} en_CA en_GB en_US
ISO8859-1_UTF-8= af_ZA ca_ES da_DK de_DE en_CA en_GB en_US es_ES eu_ES \
- fi_FI fr_BE fr_CH fr_FR is_IS it_IT nb_NO nl_NL nn_NO no_NO \
+ fi_FI fr_BE fr_CH fr_FR is_IS it_IT nl_NL no_NO \
pt_PT sv_SE
ISO8859-2_ISO8859-2= ${CZ_LINKS}
ISO8859-2_UTF-8= cs_CZ hr_HR hu_HU pl_PL ro_RO sl_SI
diff --git a/share/numericdef/Makefile b/share/numericdef/Makefile
index 2dc12f8..baf99de 100644
--- a/share/numericdef/Makefile
+++ b/share/numericdef/Makefile
@@ -93,7 +93,7 @@ eucJP_UTF-8= ja_JP
eucKR_CP949= ko_KR
eucKR_UTF-8= ko_KR
ISO8859-1_ISO8859-15= af_ZA ca_ES da_DK de_CH de_DE en_US es_ES eu_ES \
- fi_FI fr_BE fr_FR is_IS it_CH it_IT nl_NL no_NO pt_PT sv_SE \
+ fi_FI fr_BE fr_FR is_IS it_IT nl_NL no_NO pt_PT sv_SE \
${BE_LINKS} ${CA_LINKS} ${DE_LINKS} ${FR_LINKS} ${GB_LINKS} \
${IT_LINKS} ${NO_LINKS} ${US_LINKS}
ISO8859-1_ISO8859-1= ${BE_LINKS} ${CA_LINKS} ${DE_LINKS} ${FR_LINKS} \
diff --git a/share/zoneinfo/Makefile b/share/zoneinfo/Makefile
index 6de8ef5..bccea5e 100644
--- a/share/zoneinfo/Makefile
+++ b/share/zoneinfo/Makefile
@@ -29,6 +29,7 @@
#
CLEANFILES+= yearistype
+CLEANDIRS+= builddir
CONTRIBDIR= ${.CURDIR}/../../contrib/tzdata/
.PATH: ${CONTRIBDIR}
@@ -48,13 +49,39 @@ TZFILES+= backward systemv
TZFILES:= ${TZFILES:S/^/${CONTRIBDIR}/}
-all: yearistype
+TZBUILDDIR= ${.OBJDIR}/builddir
+TZBUILDSUBDIRS= \
+ Africa \
+ America/Argentina \
+ America/Indiana \
+ America/Kentucky \
+ America/North_Dakota \
+ Antarctica \
+ Arctic \
+ Asia \
+ Atlantic \
+ Australia \
+ Etc \
+ Europe \
+ Indian \
+ Pacific \
+ SystemV
-beforeinstall:
+all: zoneinfo
+
+.PHONY: zoneinfo
+zoneinfo: yearistype ${TDATA}
+ mkdir -p ${TZBUILDDIR}
+ cd ${TZBUILDDIR}; mkdir -p ${TZBUILDSUBDIRS}
umask 022; cd ${.CURDIR}; \
- zic -D -d ${DESTDIR}/usr/share/zoneinfo -p ${POSIXRULES} \
- -u ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \
+ zic -D -d ${TZBUILDDIR} -p ${POSIXRULES} -m ${NOBINMODE} \
${LEAPFILE} -y ${.OBJDIR}/yearistype ${TZFILES}
+
+beforeinstall:
+ cd ${TZBUILDDIR} && \
+ find . -type f -print -exec ${INSTALL} \
+ -o ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \
+ \{} ${DESTDIR}/usr/share/zoneinfo/\{} \;
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \
${CONTRIBDIR}/zone.tab ${DESTDIR}/usr/share/zoneinfo/
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index d2e4aad..31dbb3f 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -1431,11 +1431,11 @@ cpususpend_handler(void)
while (!CPU_ISSET(cpu, &started_cpus))
ia32_pause();
- CPU_CLR_ATOMIC(cpu, &started_cpus);
-
/* Resume MCA and local APIC */
mca_resume();
lapic_setup(0);
+
+ CPU_CLR_ATOMIC(cpu, &started_cpus);
}
/*
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index a7b1e2b..5436b6f 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -102,6 +102,7 @@ __FBSDID("$FreeBSD$");
#include "opt_vm.h"
#include <sys/param.h>
+#include <sys/bus.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
@@ -133,6 +134,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_reserv.h>
#include <vm/uma.h>
+#include <machine/intr_machdep.h>
+#include <machine/apicvar.h>
#include <machine/cpu.h>
#include <machine/cputypes.h>
#include <machine/md_var.h>
@@ -1151,6 +1154,15 @@ pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
eva - sva < PMAP_CLFLUSH_THRESHOLD) {
/*
+ * XXX: Some CPUs fault, hang, or trash the local APIC
+ * registers if we use CLFLUSH on the local APIC
+ * range. The local APIC is always uncached, so we
+ * don't need to flush for that range anyway.
+ */
+ if (pmap_kextract(sva) == lapic_paddr)
+ return;
+
+ /*
* Otherwise, do per-cache line flush. Use the mfence
* instruction to insure that previous stores are
* included in the write-back. The processor
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 48f41b3..5819a0d 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -197,7 +197,6 @@ device uart # Generic UART driver
device ppc
device ppbus # Parallel port bus (required)
device lpt # Printer
-device plip # TCP/IP over parallel
device ppi # Parallel port interface device
#device vpo # Requires scbus and da
@@ -332,3 +331,11 @@ device snd_via8233 # VIA VT8233x Audio
device mmc # MMC/SD bus
device mmcsd # MMC/SD memory card
device sdhci # Generic PCI SD Host Controller
+
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI device
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 6562981..a4371f7 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -440,6 +440,15 @@ device safe # SafeNet 1141
options SAFE_DEBUG # enable debugging support: hw.safe.debug
options SAFE_RNDTEST # enable rndtest support
+#
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI Interface
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
+
#####################################################################
#
diff --git a/sys/amd64/include/intr_machdep.h b/sys/amd64/include/intr_machdep.h
index 700e35f..8671605 100644
--- a/sys/amd64/include/intr_machdep.h
+++ b/sys/amd64/include/intr_machdep.h
@@ -94,7 +94,7 @@ struct pic {
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
int (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
- STAILQ_ENTRY(pic) pics;
+ TAILQ_ENTRY(pic) pics;
};
/* Flags for pic_disable_source() */
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
new file mode 100644
index 0000000..ec94083
--- /dev/null
+++ b/sys/amd64/include/vmm.h
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_H_
+#define _VMM_H_
+
+#ifdef _KERNEL
+
+#define VM_MAX_NAMELEN 32
+
+struct vm;
+struct vm_memory_segment;
+struct seg_desc;
+struct vm_exit;
+struct vm_run;
+struct vlapic;
+
+enum x2apic_state;
+
+typedef int (*vmm_init_func_t)(void);
+typedef int (*vmm_cleanup_func_t)(void);
+typedef void * (*vmi_init_func_t)(struct vm *vm); /* instance specific apis */
+typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip);
+typedef void (*vmi_cleanup_func_t)(void *vmi);
+typedef int (*vmi_mmap_set_func_t)(void *vmi, vm_paddr_t gpa,
+ vm_paddr_t hpa, size_t length,
+ vm_memattr_t attr, int prot,
+ boolean_t superpages_ok);
+typedef vm_paddr_t (*vmi_mmap_get_func_t)(void *vmi, vm_paddr_t gpa);
+typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num,
+ uint64_t *retval);
+typedef int (*vmi_set_register_t)(void *vmi, int vcpu, int num,
+ uint64_t val);
+typedef int (*vmi_get_desc_t)(void *vmi, int vcpu, int num,
+ struct seg_desc *desc);
+typedef int (*vmi_set_desc_t)(void *vmi, int vcpu, int num,
+ struct seg_desc *desc);
+typedef int (*vmi_inject_event_t)(void *vmi, int vcpu,
+ int type, int vector,
+ uint32_t code, int code_valid);
+typedef int (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval);
+typedef int (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val);
+
+struct vmm_ops {
+ vmm_init_func_t init; /* module wide initialization */
+ vmm_cleanup_func_t cleanup;
+
+ vmi_init_func_t vminit; /* vm-specific initialization */
+ vmi_run_func_t vmrun;
+ vmi_cleanup_func_t vmcleanup;
+ vmi_mmap_set_func_t vmmmap_set;
+ vmi_mmap_get_func_t vmmmap_get;
+ vmi_get_register_t vmgetreg;
+ vmi_set_register_t vmsetreg;
+ vmi_get_desc_t vmgetdesc;
+ vmi_set_desc_t vmsetdesc;
+ vmi_inject_event_t vminject;
+ vmi_get_cap_t vmgetcap;
+ vmi_set_cap_t vmsetcap;
+};
+
+extern struct vmm_ops vmm_ops_intel;
+extern struct vmm_ops vmm_ops_amd;
+
+struct vm *vm_create(const char *name);
+void vm_destroy(struct vm *vm);
+const char *vm_name(struct vm *vm);
+int vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len);
+int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
+int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len);
+vm_paddr_t vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t size);
+int vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase,
+ struct vm_memory_segment *seg);
+int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
+int vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val);
+int vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
+ struct seg_desc *ret_desc);
+int vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
+ struct seg_desc *desc);
+int vm_get_pinning(struct vm *vm, int vcpu, int *cpuid);
+int vm_set_pinning(struct vm *vm, int vcpu, int cpuid);
+int vm_run(struct vm *vm, struct vm_run *vmrun);
+int vm_inject_event(struct vm *vm, int vcpu, int type,
+ int vector, uint32_t error_code, int error_code_valid);
+int vm_inject_nmi(struct vm *vm, int vcpu);
+int vm_nmi_pending(struct vm *vm, int vcpuid);
+void vm_nmi_clear(struct vm *vm, int vcpuid);
+uint64_t *vm_guest_msrs(struct vm *vm, int cpu);
+struct vlapic *vm_lapic(struct vm *vm, int cpu);
+int vm_get_capability(struct vm *vm, int vcpu, int type, int *val);
+int vm_set_capability(struct vm *vm, int vcpu, int type, int val);
+int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
+int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
+void vm_activate_cpu(struct vm *vm, int vcpu);
+cpuset_t vm_active_cpus(struct vm *vm);
+struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
+
+/*
+ * Return 1 if device indicated by bus/slot/func is supposed to be a
+ * pci passthrough device.
+ *
+ * Return 0 otherwise.
+ */
+int vmm_is_pptdev(int bus, int slot, int func);
+
+void *vm_iommu_domain(struct vm *vm);
+
+enum vcpu_state {
+ VCPU_IDLE,
+ VCPU_RUNNING,
+ VCPU_CANNOT_RUN,
+};
+
+int vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state);
+enum vcpu_state vcpu_get_state(struct vm *vm, int vcpu);
+
+static int __inline
+vcpu_is_running(struct vm *vm, int vcpu)
+{
+ return (vcpu_get_state(vm, vcpu) == VCPU_RUNNING);
+}
+
+void *vcpu_stats(struct vm *vm, int vcpu);
+void vm_interrupt_hostcpu(struct vm *vm, int vcpu);
+
+#endif /* KERNEL */
+
+#include <machine/vmm_instruction_emul.h>
+
+#define VM_MAXCPU 8 /* maximum virtual cpus */
+
+/*
+ * Identifiers for events that can be injected into the VM
+ */
+enum vm_event_type {
+ VM_EVENT_NONE,
+ VM_HW_INTR,
+ VM_NMI,
+ VM_HW_EXCEPTION,
+ VM_SW_INTR,
+ VM_PRIV_SW_EXCEPTION,
+ VM_SW_EXCEPTION,
+ VM_EVENT_MAX
+};
+
+/*
+ * Identifiers for architecturally defined registers.
+ */
+enum vm_reg_name {
+ VM_REG_GUEST_RAX,
+ VM_REG_GUEST_RBX,
+ VM_REG_GUEST_RCX,
+ VM_REG_GUEST_RDX,
+ VM_REG_GUEST_RSI,
+ VM_REG_GUEST_RDI,
+ VM_REG_GUEST_RBP,
+ VM_REG_GUEST_R8,
+ VM_REG_GUEST_R9,
+ VM_REG_GUEST_R10,
+ VM_REG_GUEST_R11,
+ VM_REG_GUEST_R12,
+ VM_REG_GUEST_R13,
+ VM_REG_GUEST_R14,
+ VM_REG_GUEST_R15,
+ VM_REG_GUEST_CR0,
+ VM_REG_GUEST_CR3,
+ VM_REG_GUEST_CR4,
+ VM_REG_GUEST_DR7,
+ VM_REG_GUEST_RSP,
+ VM_REG_GUEST_RIP,
+ VM_REG_GUEST_RFLAGS,
+ VM_REG_GUEST_ES,
+ VM_REG_GUEST_CS,
+ VM_REG_GUEST_SS,
+ VM_REG_GUEST_DS,
+ VM_REG_GUEST_FS,
+ VM_REG_GUEST_GS,
+ VM_REG_GUEST_LDTR,
+ VM_REG_GUEST_TR,
+ VM_REG_GUEST_IDTR,
+ VM_REG_GUEST_GDTR,
+ VM_REG_GUEST_EFER,
+ VM_REG_LAST
+};
+
+/*
+ * Identifiers for optional vmm capabilities
+ */
+enum vm_cap_type {
+ VM_CAP_HALT_EXIT,
+ VM_CAP_MTRAP_EXIT,
+ VM_CAP_PAUSE_EXIT,
+ VM_CAP_UNRESTRICTED_GUEST,
+ VM_CAP_MAX
+};
+
+enum x2apic_state {
+ X2APIC_ENABLED,
+ X2APIC_AVAILABLE,
+ X2APIC_DISABLED,
+ X2APIC_STATE_LAST
+};
+
+/*
+ * The 'access' field has the format specified in Table 21-2 of the Intel
+ * Architecture Manual vol 3b.
+ *
+ * XXX The contents of the 'access' field are architecturally defined except
+ * bit 16 - Segment Unusable.
+ */
+struct seg_desc {
+ uint64_t base;
+ uint32_t limit;
+ uint32_t access;
+};
+
+enum vm_exitcode {
+ VM_EXITCODE_INOUT,
+ VM_EXITCODE_VMX,
+ VM_EXITCODE_BOGUS,
+ VM_EXITCODE_RDMSR,
+ VM_EXITCODE_WRMSR,
+ VM_EXITCODE_HLT,
+ VM_EXITCODE_MTRAP,
+ VM_EXITCODE_PAUSE,
+ VM_EXITCODE_PAGING,
+ VM_EXITCODE_SPINUP_AP,
+ VM_EXITCODE_MAX
+};
+
+struct vm_exit {
+ enum vm_exitcode exitcode;
+ int inst_length; /* 0 means unknown */
+ uint64_t rip;
+ union {
+ struct {
+ uint16_t bytes:3; /* 1 or 2 or 4 */
+ uint16_t in:1; /* out is 0, in is 1 */
+ uint16_t string:1;
+ uint16_t rep:1;
+ uint16_t port;
+ uint32_t eax; /* valid for out */
+ } inout;
+ struct {
+ uint64_t gpa;
+ struct vie vie;
+ } paging;
+ /*
+ * VMX specific payload. Used when there is no "better"
+ * exitcode to represent the VM-exit.
+ */
+ struct {
+ int error; /* vmx inst error */
+ uint32_t exit_reason;
+ uint64_t exit_qualification;
+ } vmx;
+ struct {
+ uint32_t code; /* ecx value */
+ uint64_t wval;
+ } msr;
+ struct {
+ int vcpu;
+ uint64_t rip;
+ } spinup_ap;
+ } u;
+};
+
+#endif /* _VMM_H_ */
diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h
new file mode 100644
index 0000000..2311673
--- /dev/null
+++ b/sys/amd64/include/vmm_dev.h
@@ -0,0 +1,215 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_DEV_H_
+#define _VMM_DEV_H_
+
+#ifdef _KERNEL
+void vmmdev_init(void);
+int vmmdev_cleanup(void);
+#endif
+
+struct vm_memory_segment {
+ vm_paddr_t gpa; /* in */
+ size_t len; /* in */
+};
+
+struct vm_register {
+ int cpuid;
+ int regnum; /* enum vm_reg_name */
+ uint64_t regval;
+};
+
+struct vm_seg_desc { /* data or code segment */
+ int cpuid;
+ int regnum; /* enum vm_reg_name */
+ struct seg_desc desc;
+};
+
+struct vm_pin {
+ int vm_cpuid;
+ int host_cpuid; /* -1 to unpin */
+};
+
+struct vm_run {
+ int cpuid;
+ uint64_t rip; /* start running here */
+ struct vm_exit vm_exit;
+};
+
+struct vm_event {
+ int cpuid;
+ enum vm_event_type type;
+ int vector;
+ uint32_t error_code;
+ int error_code_valid;
+};
+
+struct vm_lapic_irq {
+ int cpuid;
+ int vector;
+};
+
+struct vm_capability {
+ int cpuid;
+ enum vm_cap_type captype;
+ int capval;
+ int allcpus;
+};
+
+struct vm_pptdev {
+ int bus;
+ int slot;
+ int func;
+};
+
+struct vm_pptdev_mmio {
+ int bus;
+ int slot;
+ int func;
+ vm_paddr_t gpa;
+ vm_paddr_t hpa;
+ size_t len;
+};
+
+struct vm_pptdev_msi {
+ int vcpu;
+ int bus;
+ int slot;
+ int func;
+ int numvec; /* 0 means disabled */
+ int vector;
+ int destcpu;
+};
+
+struct vm_pptdev_msix {
+ int vcpu;
+ int bus;
+ int slot;
+ int func;
+ int idx;
+ uint32_t msg;
+ uint32_t vector_control;
+ uint64_t addr;
+};
+
+struct vm_nmi {
+ int cpuid;
+};
+
+#define MAX_VM_STATS 64
+struct vm_stats {
+ int cpuid; /* in */
+ int num_entries; /* out */
+ struct timeval tv;
+ uint64_t statbuf[MAX_VM_STATS];
+};
+
+struct vm_stat_desc {
+ int index; /* in */
+ char desc[128]; /* out */
+};
+
+struct vm_x2apic {
+ int cpuid;
+ enum x2apic_state state;
+};
+
+enum {
+ IOCNUM_RUN,
+ IOCNUM_SET_PINNING,
+ IOCNUM_GET_PINNING,
+ IOCNUM_MAP_MEMORY,
+ IOCNUM_GET_MEMORY_SEG,
+ IOCNUM_SET_REGISTER,
+ IOCNUM_GET_REGISTER,
+ IOCNUM_SET_SEGMENT_DESCRIPTOR,
+ IOCNUM_GET_SEGMENT_DESCRIPTOR,
+ IOCNUM_INJECT_EVENT,
+ IOCNUM_LAPIC_IRQ,
+ IOCNUM_SET_CAPABILITY,
+ IOCNUM_GET_CAPABILITY,
+ IOCNUM_BIND_PPTDEV,
+ IOCNUM_UNBIND_PPTDEV,
+ IOCNUM_MAP_PPTDEV_MMIO,
+ IOCNUM_PPTDEV_MSI,
+ IOCNUM_PPTDEV_MSIX,
+ IOCNUM_INJECT_NMI,
+ IOCNUM_VM_STATS,
+ IOCNUM_VM_STAT_DESC,
+ IOCNUM_SET_X2APIC_STATE,
+ IOCNUM_GET_X2APIC_STATE,
+};
+
+#define VM_RUN \
+ _IOWR('v', IOCNUM_RUN, struct vm_run)
+#define VM_SET_PINNING \
+ _IOW('v', IOCNUM_SET_PINNING, struct vm_pin)
+#define VM_GET_PINNING \
+ _IOWR('v', IOCNUM_GET_PINNING, struct vm_pin)
+#define VM_MAP_MEMORY \
+ _IOWR('v', IOCNUM_MAP_MEMORY, struct vm_memory_segment)
+#define VM_GET_MEMORY_SEG \
+ _IOWR('v', IOCNUM_GET_MEMORY_SEG, struct vm_memory_segment)
+#define VM_SET_REGISTER \
+ _IOW('v', IOCNUM_SET_REGISTER, struct vm_register)
+#define VM_GET_REGISTER \
+ _IOWR('v', IOCNUM_GET_REGISTER, struct vm_register)
+#define VM_SET_SEGMENT_DESCRIPTOR \
+ _IOW('v', IOCNUM_SET_SEGMENT_DESCRIPTOR, struct vm_seg_desc)
+#define VM_GET_SEGMENT_DESCRIPTOR \
+ _IOWR('v', IOCNUM_GET_SEGMENT_DESCRIPTOR, struct vm_seg_desc)
+#define VM_INJECT_EVENT \
+ _IOW('v', IOCNUM_INJECT_EVENT, struct vm_event)
+#define VM_LAPIC_IRQ \
+ _IOW('v', IOCNUM_LAPIC_IRQ, struct vm_lapic_irq)
+#define VM_SET_CAPABILITY \
+ _IOW('v', IOCNUM_SET_CAPABILITY, struct vm_capability)
+#define VM_GET_CAPABILITY \
+ _IOWR('v', IOCNUM_GET_CAPABILITY, struct vm_capability)
+#define VM_BIND_PPTDEV \
+ _IOW('v', IOCNUM_BIND_PPTDEV, struct vm_pptdev)
+#define VM_UNBIND_PPTDEV \
+ _IOW('v', IOCNUM_UNBIND_PPTDEV, struct vm_pptdev)
+#define VM_MAP_PPTDEV_MMIO \
+ _IOW('v', IOCNUM_MAP_PPTDEV_MMIO, struct vm_pptdev_mmio)
+#define VM_PPTDEV_MSI \
+ _IOW('v', IOCNUM_PPTDEV_MSI, struct vm_pptdev_msi)
+#define VM_PPTDEV_MSIX \
+ _IOW('v', IOCNUM_PPTDEV_MSIX, struct vm_pptdev_msix)
+#define VM_INJECT_NMI \
+ _IOW('v', IOCNUM_INJECT_NMI, struct vm_nmi)
+#define VM_STATS \
+ _IOWR('v', IOCNUM_VM_STATS, struct vm_stats)
+#define VM_STAT_DESC \
+ _IOWR('v', IOCNUM_VM_STAT_DESC, struct vm_stat_desc)
+#define VM_SET_X2APIC_STATE \
+ _IOW('v', IOCNUM_SET_X2APIC_STATE, struct vm_x2apic)
+#define VM_GET_X2APIC_STATE \
+ _IOWR('v', IOCNUM_GET_X2APIC_STATE, struct vm_x2apic)
+#endif
diff --git a/sys/amd64/include/vmm_instruction_emul.h b/sys/amd64/include/vmm_instruction_emul.h
new file mode 100644
index 0000000..4c7a346
--- /dev/null
+++ b/sys/amd64/include/vmm_instruction_emul.h
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_INSTRUCTION_EMUL_H_
+#define _VMM_INSTRUCTION_EMUL_H_
+
+/*
+ * The data structures 'vie' and 'vie_op' are meant to be opaque to the
+ * consumers of instruction decoding. The only reason why their contents
+ * need to be exposed is because they are part of the 'vm_exit' structure.
+ */
+struct vie_op {
+ uint8_t op_byte; /* actual opcode byte */
+ uint8_t op_type; /* type of operation (e.g. MOV) */
+ uint16_t op_flags;
+};
+
+#define VIE_INST_SIZE 15
+struct vie {
+ uint8_t inst[VIE_INST_SIZE]; /* instruction bytes */
+ uint8_t num_valid; /* size of the instruction */
+ uint8_t num_processed;
+
+ uint8_t rex_w:1, /* REX prefix */
+ rex_r:1,
+ rex_x:1,
+ rex_b:1,
+ rex_present:1;
+
+ uint8_t mod:2, /* ModRM byte */
+ reg:4,
+ rm:4;
+
+ uint8_t ss:2, /* SIB byte */
+ index:4,
+ base:4;
+
+ uint8_t disp_bytes;
+ uint8_t imm_bytes;
+
+ uint8_t scale;
+ int base_register; /* VM_REG_GUEST_xyz */
+ int index_register; /* VM_REG_GUEST_xyz */
+
+ int64_t displacement; /* optional addr displacement */
+ int64_t immediate; /* optional immediate operand */
+
+ uint8_t decoded; /* set to 1 if successfully decoded */
+
+ struct vie_op op; /* opcode description */
+};
+
+/*
+ * Callback functions to read and write memory regions.
+ */
+typedef int (*mem_region_read_t)(void *vm, int cpuid, uint64_t gpa,
+ uint64_t *rval, int rsize, void *arg);
+
+typedef int (*mem_region_write_t)(void *vm, int cpuid, uint64_t gpa,
+ uint64_t wval, int wsize, void *arg);
+
+/*
+ * Emulate the decoded 'vie' instruction.
+ *
+ * The callbacks 'mrr' and 'mrw' emulate reads and writes to the memory region
+ * containing 'gpa'. 'mrarg' is an opaque argument that is passed into the
+ * callback functions.
+ *
+ * 'void *vm' should be 'struct vm *' when called from kernel context and
+ * 'struct vmctx *' when called from user context.
+ * s
+ */
+int vmm_emulate_instruction(void *vm, int cpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t mrr, mem_region_write_t mrw,
+ void *mrarg);
+
+#ifdef _KERNEL
+/*
+ * APIs to fetch and decode the instruction from nested page fault handler.
+ */
+int vmm_fetch_instruction(struct vm *vm, int cpuid,
+ uint64_t rip, int inst_length, uint64_t cr3,
+ struct vie *vie);
+
+int vmm_decode_instruction(struct vm *vm, int cpuid,
+ uint64_t gla, struct vie *vie);
+#endif /* _KERNEL */
+
+#endif /* _VMM_INSTRUCTION_EMUL_H_ */
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index 2c269d3..7b52a64 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -107,11 +107,6 @@ typedef struct {
/*
* Miscellaneous
*/
-#define LINUX_NAME_MAX 255
-#define LINUX_MAX_UTSNAME 65
-
-#define LINUX_CTL_MAXNAME 10
-
#define LINUX_AT_COUNT 16 /* Count of used aux entry types.
* Keep this synchronized with
* elf_linux_fixup() code.
@@ -127,11 +122,6 @@ struct l___sysctl_args
l_ulong __spare[4];
} __packed;
-/* Scheduling policies */
-#define LINUX_SCHED_OTHER 0
-#define LINUX_SCHED_FIFO 1
-#define LINUX_SCHED_RR 2
-
/* Resource limits */
#define LINUX_RLIMIT_CPU 0
#define LINUX_RLIMIT_FSIZE 1
@@ -265,15 +255,6 @@ struct l_statfs64 {
l_int f_spare[6];
} __packed;
-struct l_new_utsname {
- char sysname[LINUX_MAX_UTSNAME];
- char nodename[LINUX_MAX_UTSNAME];
- char release[LINUX_MAX_UTSNAME];
- char version[LINUX_MAX_UTSNAME];
- char machine[LINUX_MAX_UTSNAME];
- char domainname[LINUX_MAX_UTSNAME];
-} __packed;
-
/*
* Signalling
*/
@@ -535,27 +516,9 @@ struct l_rt_sigframe {
l_handler_t sf_handler;
} __packed;
-extern int bsd_to_linux_signal[];
-extern int linux_to_bsd_signal[];
extern struct sysentvec elf_linux_sysvec;
/*
- * Pluggable ioctl handlers
- */
-struct linux_ioctl_args;
-struct thread;
-
-typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *);
-
-struct linux_ioctl_handler {
- linux_ioctl_function_t *func;
- int low, high;
-};
-
-int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
-int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
-
-/*
* open/fcntl flags
*/
#define LINUX_O_RDONLY 00000000
@@ -597,65 +560,6 @@ int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
#define LINUX_F_WRLCK 1
#define LINUX_F_UNLCK 2
-/*
- * posix_fadvise advice
- */
-#define LINUX_POSIX_FADV_NORMAL 0
-#define LINUX_POSIX_FADV_RANDOM 1
-#define LINUX_POSIX_FADV_SEQUENTIAL 2
-#define LINUX_POSIX_FADV_WILLNEED 3
-#define LINUX_POSIX_FADV_DONTNEED 4
-#define LINUX_POSIX_FADV_NOREUSE 5
-
-/*
- * mount flags
- */
-#define LINUX_MS_RDONLY 0x0001
-#define LINUX_MS_NOSUID 0x0002
-#define LINUX_MS_NODEV 0x0004
-#define LINUX_MS_NOEXEC 0x0008
-#define LINUX_MS_REMOUNT 0x0020
-
-/*
- * SystemV IPC defines
- */
-#define LINUX_SEMOP 1
-#define LINUX_SEMGET 2
-#define LINUX_SEMCTL 3
-#define LINUX_MSGSND 11
-#define LINUX_MSGRCV 12
-#define LINUX_MSGGET 13
-#define LINUX_MSGCTL 14
-#define LINUX_SHMAT 21
-#define LINUX_SHMDT 22
-#define LINUX_SHMGET 23
-#define LINUX_SHMCTL 24
-
-#define LINUX_IPC_RMID 0
-#define LINUX_IPC_SET 1
-#define LINUX_IPC_STAT 2
-#define LINUX_IPC_INFO 3
-
-#define LINUX_SHM_LOCK 11
-#define LINUX_SHM_UNLOCK 12
-#define LINUX_SHM_STAT 13
-#define LINUX_SHM_INFO 14
-
-#define LINUX_SHM_RDONLY 0x1000
-#define LINUX_SHM_RND 0x2000
-#define LINUX_SHM_REMAP 0x4000
-
-/* semctl commands */
-#define LINUX_GETPID 11
-#define LINUX_GETVAL 12
-#define LINUX_GETALL 13
-#define LINUX_GETNCNT 14
-#define LINUX_GETZCNT 15
-#define LINUX_SETVAL 16
-#define LINUX_SETALL 17
-#define LINUX_SEM_STAT 18
-#define LINUX_SEM_INFO 19
-
union l_semun {
l_int val;
l_uintptr_t buf;
@@ -667,25 +571,6 @@ union l_semun {
/*
* Socket defines
*/
-#define LINUX_SOCKET 1
-#define LINUX_BIND 2
-#define LINUX_CONNECT 3
-#define LINUX_LISTEN 4
-#define LINUX_ACCEPT 5
-#define LINUX_GETSOCKNAME 6
-#define LINUX_GETPEERNAME 7
-#define LINUX_SOCKETPAIR 8
-#define LINUX_SEND 9
-#define LINUX_RECV 10
-#define LINUX_SENDTO 11
-#define LINUX_RECVFROM 12
-#define LINUX_SHUTDOWN 13
-#define LINUX_SETSOCKOPT 14
-#define LINUX_GETSOCKOPT 15
-#define LINUX_SENDMSG 16
-#define LINUX_RECVMSG 17
-#define LINUX_ACCEPT4 18
-
#define LINUX_SOL_SOCKET 1
#define LINUX_SOL_IP 0
#define LINUX_SOL_IPX 256
@@ -714,17 +599,6 @@ union l_semun {
#define LINUX_SO_TIMESTAMP 29
#define LINUX_SO_ACCEPTCONN 30
-#define LINUX_IP_TOS 1
-#define LINUX_IP_TTL 2
-#define LINUX_IP_HDRINCL 3
-#define LINUX_IP_OPTIONS 4
-
-#define LINUX_IP_MULTICAST_IF 32
-#define LINUX_IP_MULTICAST_TTL 33
-#define LINUX_IP_MULTICAST_LOOP 34
-#define LINUX_IP_ADD_MEMBERSHIP 35
-#define LINUX_IP_DROP_MEMBERSHIP 36
-
struct l_sockaddr {
l_ushort sa_family;
char sa_data[14];
@@ -890,30 +764,6 @@ struct l_user_desc {
#define LINUX_GET_USEABLE(desc) \
(((desc)->b >> LINUX_ENTRY_B_USEABLE) & 1)
-#define LINUX_CLOCK_REALTIME 0
-#define LINUX_CLOCK_MONOTONIC 1
-#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
-#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
-#define LINUX_CLOCK_REALTIME_HR 4
-#define LINUX_CLOCK_MONOTONIC_HR 5
-
-#define LINUX_CLONE_VM 0x00000100
-#define LINUX_CLONE_FS 0x00000200
-#define LINUX_CLONE_FILES 0x00000400
-#define LINUX_CLONE_SIGHAND 0x00000800
-#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
-#define LINUX_CLONE_VFORK 0x00004000
-#define LINUX_CLONE_PARENT 0x00008000
-#define LINUX_CLONE_THREAD 0x00010000
-#define LINUX_CLONE_SETTLS 0x00080000
-#define LINUX_CLONE_PARENT_SETTID 0x00100000
-#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
-#define LINUX_CLONE_CHILD_SETTID 0x01000000
-
-#define LINUX_THREADING_FLAGS \
- (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
- LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
-
struct iovec;
struct l_iovec32 {
@@ -935,7 +785,4 @@ struct linux_robust_list_head {
l_uintptr_t pending_list;
};
-int linux_set_upcall_kse(struct thread *td, register_t stack);
-int linux_set_cloned_tls(struct thread *td, void *desc);
-
#endif /* !_AMD64_LINUX_H_ */
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 5afc9ce..42500da 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <amd64/linux32/linux32_proto.h>
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_signal.h>
diff --git a/sys/amd64/vmm/amd/amdv.c b/sys/amd64/vmm/amd/amdv.c
new file mode 100644
index 0000000..dc071d3
--- /dev/null
+++ b/sys/amd64/vmm/amd/amdv.c
@@ -0,0 +1,265 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/smp.h>
+
+#include <machine/vmm.h>
+#include "io/iommu.h"
+
+static int
+amdv_init(void)
+{
+
+ printf("amdv_init: not implemented\n");
+ return (ENXIO);
+}
+
+static int
+amdv_cleanup(void)
+{
+
+ printf("amdv_cleanup: not implemented\n");
+ return (ENXIO);
+}
+
+static void *
+amdv_vminit(struct vm *vm)
+{
+
+ printf("amdv_vminit: not implemented\n");
+ return (NULL);
+}
+
+static int
+amdv_vmrun(void *arg, int vcpu, register_t rip)
+{
+
+ printf("amdv_vmrun: not implemented\n");
+ return (ENXIO);
+}
+
+static void
+amdv_vmcleanup(void *arg)
+{
+
+ printf("amdv_vmcleanup: not implemented\n");
+ return;
+}
+
+static int
+amdv_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t length,
+ vm_memattr_t attr, int prot, boolean_t spok)
+{
+
+ printf("amdv_vmmmap_set: not implemented\n");
+ return (EINVAL);
+}
+
+static vm_paddr_t
+amdv_vmmmap_get(void *arg, vm_paddr_t gpa)
+{
+
+ printf("amdv_vmmmap_get: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_getreg(void *arg, int vcpu, int regnum, uint64_t *retval)
+{
+
+ printf("amdv_getreg: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_setreg(void *arg, int vcpu, int regnum, uint64_t val)
+{
+
+ printf("amdv_setreg: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_getdesc(void *vmi, int vcpu, int num, struct seg_desc *desc)
+{
+
+ printf("amdv_get_desc: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_setdesc(void *vmi, int vcpu, int num, struct seg_desc *desc)
+{
+
+ printf("amdv_get_desc: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_inject_event(void *vmi, int vcpu, int type, int vector,
+ uint32_t error_code, int error_code_valid)
+{
+
+ printf("amdv_inject_event: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_getcap(void *arg, int vcpu, int type, int *retval)
+{
+
+ printf("amdv_getcap: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_setcap(void *arg, int vcpu, int type, int val)
+{
+
+ printf("amdv_setcap: not implemented\n");
+ return (EINVAL);
+}
+
+struct vmm_ops vmm_ops_amd = {
+ amdv_init,
+ amdv_cleanup,
+ amdv_vminit,
+ amdv_vmrun,
+ amdv_vmcleanup,
+ amdv_vmmmap_set,
+ amdv_vmmmap_get,
+ amdv_getreg,
+ amdv_setreg,
+ amdv_getdesc,
+ amdv_setdesc,
+ amdv_inject_event,
+ amdv_getcap,
+ amdv_setcap
+};
+
+static int
+amd_iommu_init(void)
+{
+
+ printf("amd_iommu_init: not implemented\n");
+ return (ENXIO);
+}
+
+static void
+amd_iommu_cleanup(void)
+{
+
+ printf("amd_iommu_cleanup: not implemented\n");
+}
+
+static void
+amd_iommu_enable(void)
+{
+
+ printf("amd_iommu_enable: not implemented\n");
+}
+
+static void
+amd_iommu_disable(void)
+{
+
+ printf("amd_iommu_disable: not implemented\n");
+}
+
+static void *
+amd_iommu_create_domain(vm_paddr_t maxaddr)
+{
+
+ printf("amd_iommu_create_domain: not implemented\n");
+ return (NULL);
+}
+
+static void
+amd_iommu_destroy_domain(void *domain)
+{
+
+ printf("amd_iommu_destroy_domain: not implemented\n");
+}
+
+static uint64_t
+amd_iommu_create_mapping(void *domain, vm_paddr_t gpa, vm_paddr_t hpa,
+ uint64_t len)
+{
+
+ printf("amd_iommu_create_mapping: not implemented\n");
+ return (0);
+}
+
+static uint64_t
+amd_iommu_remove_mapping(void *domain, vm_paddr_t gpa, uint64_t len)
+{
+
+ printf("amd_iommu_remove_mapping: not implemented\n");
+ return (0);
+}
+
+static void
+amd_iommu_add_device(void *domain, int bus, int slot, int func)
+{
+
+ printf("amd_iommu_add_device: not implemented\n");
+}
+
+static void
+amd_iommu_remove_device(void *domain, int bus, int slot, int func)
+{
+
+ printf("amd_iommu_remove_device: not implemented\n");
+}
+
+static void
+amd_iommu_invalidate_tlb(void *domain)
+{
+
+ printf("amd_iommu_invalidate_tlb: not implemented\n");
+}
+
+struct iommu_ops iommu_ops_amd = {
+ amd_iommu_init,
+ amd_iommu_cleanup,
+ amd_iommu_enable,
+ amd_iommu_disable,
+ amd_iommu_create_domain,
+ amd_iommu_destroy_domain,
+ amd_iommu_create_mapping,
+ amd_iommu_remove_mapping,
+ amd_iommu_add_device,
+ amd_iommu_remove_device,
+ amd_iommu_invalidate_tlb,
+};
diff --git a/sys/amd64/vmm/intel/ept.c b/sys/amd64/vmm/intel/ept.c
new file mode 100644
index 0000000..4f91601
--- /dev/null
+++ b/sys/amd64/vmm/intel/ept.c
@@ -0,0 +1,392 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/param.h>
+#include <machine/cpufunc.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+
+#include <machine/vmm.h>
+#include "vmx_cpufunc.h"
+#include "vmx_msr.h"
+#include "vmx.h"
+#include "ept.h"
+
+#define EPT_PWL4(cap) ((cap) & (1UL << 6))
+#define EPT_MEMORY_TYPE_WB(cap) ((cap) & (1UL << 14))
+#define EPT_PDE_SUPERPAGE(cap) ((cap) & (1UL << 16)) /* 2MB pages */
+#define EPT_PDPTE_SUPERPAGE(cap) ((cap) & (1UL << 17)) /* 1GB pages */
+#define INVVPID_SUPPORTED(cap) ((cap) & (1UL << 32))
+#define INVEPT_SUPPORTED(cap) ((cap) & (1UL << 20))
+
+#define INVVPID_ALL_TYPES_MASK 0xF0000000000UL
+#define INVVPID_ALL_TYPES_SUPPORTED(cap) \
+ (((cap) & INVVPID_ALL_TYPES_MASK) == INVVPID_ALL_TYPES_MASK)
+
+#define INVEPT_ALL_TYPES_MASK 0x6000000UL
+#define INVEPT_ALL_TYPES_SUPPORTED(cap) \
+ (((cap) & INVEPT_ALL_TYPES_MASK) == INVEPT_ALL_TYPES_MASK)
+
+#define EPT_PG_RD (1 << 0)
+#define EPT_PG_WR (1 << 1)
+#define EPT_PG_EX (1 << 2)
+#define EPT_PG_MEMORY_TYPE(x) ((x) << 3)
+#define EPT_PG_IGNORE_PAT (1 << 6)
+#define EPT_PG_SUPERPAGE (1 << 7)
+
+#define EPT_ADDR_MASK ((uint64_t)-1 << 12)
+
+MALLOC_DECLARE(M_VMX);
+
+static uint64_t page_sizes_mask;
+
+int
+ept_init(void)
+{
+ int page_shift;
+ uint64_t cap;
+
+ cap = rdmsr(MSR_VMX_EPT_VPID_CAP);
+
+ /*
+ * Verify that:
+ * - page walk length is 4 steps
+ * - extended page tables can be laid out in write-back memory
+ * - invvpid instruction with all possible types is supported
+ * - invept instruction with all possible types is supported
+ */
+ if (!EPT_PWL4(cap) ||
+ !EPT_MEMORY_TYPE_WB(cap) ||
+ !INVVPID_SUPPORTED(cap) ||
+ !INVVPID_ALL_TYPES_SUPPORTED(cap) ||
+ !INVEPT_SUPPORTED(cap) ||
+ !INVEPT_ALL_TYPES_SUPPORTED(cap))
+ return (EINVAL);
+
+ /* Set bits in 'page_sizes_mask' for each valid page size */
+ page_shift = PAGE_SHIFT;
+ page_sizes_mask = 1UL << page_shift; /* 4KB page */
+
+ page_shift += 9;
+ if (EPT_PDE_SUPERPAGE(cap))
+ page_sizes_mask |= 1UL << page_shift; /* 2MB superpage */
+
+ page_shift += 9;
+ if (EPT_PDPTE_SUPERPAGE(cap))
+ page_sizes_mask |= 1UL << page_shift; /* 1GB superpage */
+
+ return (0);
+}
+
+#if 0
+static void
+ept_dump(uint64_t *ptp, int nlevels)
+{
+ int i, t, tabs;
+ uint64_t *ptpnext, ptpval;
+
+ if (--nlevels < 0)
+ return;
+
+ tabs = 3 - nlevels;
+ for (t = 0; t < tabs; t++)
+ printf("\t");
+ printf("PTP = %p\n", ptp);
+
+ for (i = 0; i < 512; i++) {
+ ptpval = ptp[i];
+
+ if (ptpval == 0)
+ continue;
+
+ for (t = 0; t < tabs; t++)
+ printf("\t");
+ printf("%3d 0x%016lx\n", i, ptpval);
+
+ if (nlevels != 0 && (ptpval & EPT_PG_SUPERPAGE) == 0) {
+ ptpnext = (uint64_t *)
+ PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK);
+ ept_dump(ptpnext, nlevels);
+ }
+ }
+}
+#endif
+
+static size_t
+ept_create_mapping(uint64_t *ptp, vm_paddr_t gpa, vm_paddr_t hpa, size_t length,
+ vm_memattr_t attr, vm_prot_t prot, boolean_t spok)
+{
+ int spshift, ptpshift, ptpindex, nlevels;
+
+ /*
+ * Compute the size of the mapping that we can accomodate.
+ *
+ * This is based on three factors:
+ * - super page sizes supported by the processor
+ * - alignment of the region starting at 'gpa' and 'hpa'
+ * - length of the region 'len'
+ */
+ spshift = PAGE_SHIFT;
+ if (spok)
+ spshift += (EPT_PWLEVELS - 1) * 9;
+ while (spshift >= PAGE_SHIFT) {
+ uint64_t spsize = 1UL << spshift;
+ if ((page_sizes_mask & spsize) != 0 &&
+ (gpa & (spsize - 1)) == 0 &&
+ (hpa & (spsize - 1)) == 0 &&
+ length >= spsize) {
+ break;
+ }
+ spshift -= 9;
+ }
+
+ if (spshift < PAGE_SHIFT) {
+ panic("Invalid spshift for gpa 0x%016lx, hpa 0x%016lx, "
+ "length 0x%016lx, page_sizes_mask 0x%016lx",
+ gpa, hpa, length, page_sizes_mask);
+ }
+
+ nlevels = EPT_PWLEVELS;
+ while (--nlevels >= 0) {
+ ptpshift = PAGE_SHIFT + nlevels * 9;
+ ptpindex = (gpa >> ptpshift) & 0x1FF;
+
+ /* We have reached the leaf mapping */
+ if (spshift >= ptpshift)
+ break;
+
+ /*
+ * We are working on a non-leaf page table page.
+ *
+ * Create the next level page table page if necessary and point
+ * to it from the current page table.
+ */
+ if (ptp[ptpindex] == 0) {
+ void *nlp = malloc(PAGE_SIZE, M_VMX, M_WAITOK | M_ZERO);
+ ptp[ptpindex] = vtophys(nlp);
+ ptp[ptpindex] |= EPT_PG_RD | EPT_PG_WR | EPT_PG_EX;
+ }
+
+ /* Work our way down to the next level page table page */
+ ptp = (uint64_t *)PHYS_TO_DMAP(ptp[ptpindex] & EPT_ADDR_MASK);
+ }
+
+ if ((gpa & ((1UL << ptpshift) - 1)) != 0) {
+ panic("ept_create_mapping: gpa 0x%016lx and ptpshift %d "
+ "mismatch\n", gpa, ptpshift);
+ }
+
+ if (prot != VM_PROT_NONE) {
+ /* Do the mapping */
+ ptp[ptpindex] = hpa;
+
+ /* Apply the access controls */
+ if (prot & VM_PROT_READ)
+ ptp[ptpindex] |= EPT_PG_RD;
+ if (prot & VM_PROT_WRITE)
+ ptp[ptpindex] |= EPT_PG_WR;
+ if (prot & VM_PROT_EXECUTE)
+ ptp[ptpindex] |= EPT_PG_EX;
+
+ /*
+ * XXX should we enforce this memory type by setting the
+ * ignore PAT bit to 1.
+ */
+ ptp[ptpindex] |= EPT_PG_MEMORY_TYPE(attr);
+
+ if (nlevels > 0)
+ ptp[ptpindex] |= EPT_PG_SUPERPAGE;
+ } else {
+ /* Remove the mapping */
+ ptp[ptpindex] = 0;
+ }
+
+ return (1UL << ptpshift);
+}
+
+static vm_paddr_t
+ept_lookup_mapping(uint64_t *ptp, vm_paddr_t gpa)
+{
+ int nlevels, ptpshift, ptpindex;
+ uint64_t ptpval, hpabase, pgmask;
+
+ nlevels = EPT_PWLEVELS;
+ while (--nlevels >= 0) {
+ ptpshift = PAGE_SHIFT + nlevels * 9;
+ ptpindex = (gpa >> ptpshift) & 0x1FF;
+
+ ptpval = ptp[ptpindex];
+
+ /* Cannot make progress beyond this point */
+ if ((ptpval & (EPT_PG_RD | EPT_PG_WR | EPT_PG_EX)) == 0)
+ break;
+
+ if (nlevels == 0 || (ptpval & EPT_PG_SUPERPAGE)) {
+ pgmask = (1UL << ptpshift) - 1;
+ hpabase = ptpval & ~pgmask;
+ return (hpabase | (gpa & pgmask));
+ }
+
+ /* Work our way down to the next level page table page */
+ ptp = (uint64_t *)PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK);
+ }
+
+ return ((vm_paddr_t)-1);
+}
+
+static void
+ept_free_pt_entry(pt_entry_t pte)
+{
+ if (pte == 0)
+ return;
+
+ /* sanity check */
+ if ((pte & EPT_PG_SUPERPAGE) != 0)
+ panic("ept_free_pt_entry: pte cannot have superpage bit");
+
+ return;
+}
+
+static void
+ept_free_pd_entry(pd_entry_t pde)
+{
+ pt_entry_t *pt;
+ int i;
+
+ if (pde == 0)
+ return;
+
+ if ((pde & EPT_PG_SUPERPAGE) == 0) {
+ pt = (pt_entry_t *)PHYS_TO_DMAP(pde & EPT_ADDR_MASK);
+ for (i = 0; i < NPTEPG; i++)
+ ept_free_pt_entry(pt[i]);
+ free(pt, M_VMX); /* free the page table page */
+ }
+}
+
+static void
+ept_free_pdp_entry(pdp_entry_t pdpe)
+{
+ pd_entry_t *pd;
+ int i;
+
+ if (pdpe == 0)
+ return;
+
+ if ((pdpe & EPT_PG_SUPERPAGE) == 0) {
+ pd = (pd_entry_t *)PHYS_TO_DMAP(pdpe & EPT_ADDR_MASK);
+ for (i = 0; i < NPDEPG; i++)
+ ept_free_pd_entry(pd[i]);
+ free(pd, M_VMX); /* free the page directory page */
+ }
+}
+
+static void
+ept_free_pml4_entry(pml4_entry_t pml4e)
+{
+ pdp_entry_t *pdp;
+ int i;
+
+ if (pml4e == 0)
+ return;
+
+ if ((pml4e & EPT_PG_SUPERPAGE) == 0) {
+ pdp = (pdp_entry_t *)PHYS_TO_DMAP(pml4e & EPT_ADDR_MASK);
+ for (i = 0; i < NPDPEPG; i++)
+ ept_free_pdp_entry(pdp[i]);
+ free(pdp, M_VMX); /* free the page directory ptr page */
+ }
+}
+
+void
+ept_vmcleanup(struct vmx *vmx)
+{
+ int i;
+
+ for (i = 0; i < NPML4EPG; i++)
+ ept_free_pml4_entry(vmx->pml4ept[i]);
+}
+
+int
+ept_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t len,
+ vm_memattr_t attr, int prot, boolean_t spok)
+{
+ size_t n;
+ struct vmx *vmx = arg;
+
+ while (len > 0) {
+ n = ept_create_mapping(vmx->pml4ept, gpa, hpa, len, attr,
+ prot, spok);
+ len -= n;
+ gpa += n;
+ hpa += n;
+ }
+
+ return (0);
+}
+
+vm_paddr_t
+ept_vmmmap_get(void *arg, vm_paddr_t gpa)
+{
+ vm_paddr_t hpa;
+ struct vmx *vmx;
+
+ vmx = arg;
+ hpa = ept_lookup_mapping(vmx->pml4ept, gpa);
+ return (hpa);
+}
+
+static void
+invept_single_context(void *arg)
+{
+ struct invept_desc desc = *(struct invept_desc *)arg;
+
+ invept(INVEPT_TYPE_SINGLE_CONTEXT, desc);
+}
+
+void
+ept_invalidate_mappings(u_long pml4ept)
+{
+ struct invept_desc invept_desc = { 0 };
+
+ invept_desc.eptp = EPTP(pml4ept);
+
+ smp_rendezvous(NULL, invept_single_context, NULL, &invept_desc);
+}
diff --git a/sys/amd64/vmm/intel/ept.h b/sys/amd64/vmm/intel/ept.h
new file mode 100644
index 0000000..2d7258d
--- /dev/null
+++ b/sys/amd64/vmm/intel/ept.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _EPT_H_
+#define _EPT_H_
+
+struct vmx;
+
+#define EPT_PWLEVELS 4 /* page walk levels */
+#define EPTP(pml4) ((pml4) | (EPT_PWLEVELS - 1) << 3 | PAT_WRITE_BACK)
+
+int ept_init(void);
+int ept_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t length,
+ vm_memattr_t attr, int prot, boolean_t allow_superpage_mappings);
+vm_paddr_t ept_vmmmap_get(void *arg, vm_paddr_t gpa);
+void ept_invalidate_mappings(u_long ept_pml4);
+void ept_vmcleanup(struct vmx *vmx);
+#endif
diff --git a/sys/amd64/vmm/intel/vmcs.c b/sys/amd64/vmm/intel/vmcs.c
new file mode 100644
index 0000000..a5784dd
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmcs.c
@@ -0,0 +1,551 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_ddb.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/pcpu.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/segments.h>
+#include <machine/pmap.h>
+
+#include <machine/vmm.h>
+#include "vmm_host.h"
+#include "vmcs.h"
+#include "vmx_cpufunc.h"
+#include "ept.h"
+#include "vmx.h"
+
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
+
+static uint64_t
+vmcs_fix_regval(uint32_t encoding, uint64_t val)
+{
+
+ switch (encoding) {
+ case VMCS_GUEST_CR0:
+ val = vmx_fix_cr0(val);
+ break;
+ case VMCS_GUEST_CR4:
+ val = vmx_fix_cr4(val);
+ break;
+ default:
+ break;
+ }
+ return (val);
+}
+
+static uint32_t
+vmcs_field_encoding(int ident)
+{
+ switch (ident) {
+ case VM_REG_GUEST_CR0:
+ return (VMCS_GUEST_CR0);
+ case VM_REG_GUEST_CR3:
+ return (VMCS_GUEST_CR3);
+ case VM_REG_GUEST_CR4:
+ return (VMCS_GUEST_CR4);
+ case VM_REG_GUEST_DR7:
+ return (VMCS_GUEST_DR7);
+ case VM_REG_GUEST_RSP:
+ return (VMCS_GUEST_RSP);
+ case VM_REG_GUEST_RIP:
+ return (VMCS_GUEST_RIP);
+ case VM_REG_GUEST_RFLAGS:
+ return (VMCS_GUEST_RFLAGS);
+ case VM_REG_GUEST_ES:
+ return (VMCS_GUEST_ES_SELECTOR);
+ case VM_REG_GUEST_CS:
+ return (VMCS_GUEST_CS_SELECTOR);
+ case VM_REG_GUEST_SS:
+ return (VMCS_GUEST_SS_SELECTOR);
+ case VM_REG_GUEST_DS:
+ return (VMCS_GUEST_DS_SELECTOR);
+ case VM_REG_GUEST_FS:
+ return (VMCS_GUEST_FS_SELECTOR);
+ case VM_REG_GUEST_GS:
+ return (VMCS_GUEST_GS_SELECTOR);
+ case VM_REG_GUEST_TR:
+ return (VMCS_GUEST_TR_SELECTOR);
+ case VM_REG_GUEST_LDTR:
+ return (VMCS_GUEST_LDTR_SELECTOR);
+ case VM_REG_GUEST_EFER:
+ return (VMCS_GUEST_IA32_EFER);
+ default:
+ return (-1);
+ }
+
+}
+
+static int
+vmcs_seg_desc_encoding(int seg, uint32_t *base, uint32_t *lim, uint32_t *acc)
+{
+
+ switch (seg) {
+ case VM_REG_GUEST_ES:
+ *base = VMCS_GUEST_ES_BASE;
+ *lim = VMCS_GUEST_ES_LIMIT;
+ *acc = VMCS_GUEST_ES_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_CS:
+ *base = VMCS_GUEST_CS_BASE;
+ *lim = VMCS_GUEST_CS_LIMIT;
+ *acc = VMCS_GUEST_CS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_SS:
+ *base = VMCS_GUEST_SS_BASE;
+ *lim = VMCS_GUEST_SS_LIMIT;
+ *acc = VMCS_GUEST_SS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_DS:
+ *base = VMCS_GUEST_DS_BASE;
+ *lim = VMCS_GUEST_DS_LIMIT;
+ *acc = VMCS_GUEST_DS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_FS:
+ *base = VMCS_GUEST_FS_BASE;
+ *lim = VMCS_GUEST_FS_LIMIT;
+ *acc = VMCS_GUEST_FS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_GS:
+ *base = VMCS_GUEST_GS_BASE;
+ *lim = VMCS_GUEST_GS_LIMIT;
+ *acc = VMCS_GUEST_GS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_TR:
+ *base = VMCS_GUEST_TR_BASE;
+ *lim = VMCS_GUEST_TR_LIMIT;
+ *acc = VMCS_GUEST_TR_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_LDTR:
+ *base = VMCS_GUEST_LDTR_BASE;
+ *lim = VMCS_GUEST_LDTR_LIMIT;
+ *acc = VMCS_GUEST_LDTR_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_IDTR:
+ *base = VMCS_GUEST_IDTR_BASE;
+ *lim = VMCS_GUEST_IDTR_LIMIT;
+ *acc = VMCS_INVALID_ENCODING;
+ break;
+ case VM_REG_GUEST_GDTR:
+ *base = VMCS_GUEST_GDTR_BASE;
+ *lim = VMCS_GUEST_GDTR_LIMIT;
+ *acc = VMCS_INVALID_ENCODING;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+int
+vmcs_getreg(struct vmcs *vmcs, int ident, uint64_t *retval)
+{
+ int error;
+ uint32_t encoding;
+
+ /*
+ * If we need to get at vmx-specific state in the VMCS we can bypass
+ * the translation of 'ident' to 'encoding' by simply setting the
+ * sign bit. As it so happens the upper 16 bits are reserved (i.e
+ * set to 0) in the encodings for the VMCS so we are free to use the
+ * sign bit.
+ */
+ if (ident < 0)
+ encoding = ident & 0x7fffffff;
+ else
+ encoding = vmcs_field_encoding(ident);
+
+ if (encoding == (uint32_t)-1)
+ return (EINVAL);
+
+ VMPTRLD(vmcs);
+ error = vmread(encoding, retval);
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_setreg(struct vmcs *vmcs, int ident, uint64_t val)
+{
+ int error;
+ uint32_t encoding;
+
+ if (ident < 0)
+ encoding = ident & 0x7fffffff;
+ else
+ encoding = vmcs_field_encoding(ident);
+
+ if (encoding == (uint32_t)-1)
+ return (EINVAL);
+
+ val = vmcs_fix_regval(encoding, val);
+
+ VMPTRLD(vmcs);
+ error = vmwrite(encoding, val);
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_setdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
+{
+ int error;
+ uint32_t base, limit, access;
+
+ error = vmcs_seg_desc_encoding(seg, &base, &limit, &access);
+ if (error != 0)
+ panic("vmcs_setdesc: invalid segment register %d", seg);
+
+ VMPTRLD(vmcs);
+ if ((error = vmwrite(base, desc->base)) != 0)
+ goto done;
+
+ if ((error = vmwrite(limit, desc->limit)) != 0)
+ goto done;
+
+ if (access != VMCS_INVALID_ENCODING) {
+ if ((error = vmwrite(access, desc->access)) != 0)
+ goto done;
+ }
+done:
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_getdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
+{
+ int error;
+ uint32_t base, limit, access;
+ uint64_t u64;
+
+ error = vmcs_seg_desc_encoding(seg, &base, &limit, &access);
+ if (error != 0)
+ panic("vmcs_getdesc: invalid segment register %d", seg);
+
+ VMPTRLD(vmcs);
+ if ((error = vmread(base, &u64)) != 0)
+ goto done;
+ desc->base = u64;
+
+ if ((error = vmread(limit, &u64)) != 0)
+ goto done;
+ desc->limit = u64;
+
+ if (access != VMCS_INVALID_ENCODING) {
+ if ((error = vmread(access, &u64)) != 0)
+ goto done;
+ desc->access = u64;
+ }
+done:
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count)
+{
+ int error;
+
+ VMPTRLD(vmcs);
+
+ /*
+ * Guest MSRs are saved in the VM-exit MSR-store area.
+ * Guest MSRs are loaded from the VM-entry MSR-load area.
+ * Both areas point to the same location in memory.
+ */
+ if ((error = vmwrite(VMCS_EXIT_MSR_STORE, g_area)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_EXIT_MSR_STORE_COUNT, g_count)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD, g_area)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, g_count)) != 0)
+ goto done;
+
+ error = 0;
+done:
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_set_defaults(struct vmcs *vmcs,
+ u_long host_rip, u_long host_rsp, u_long ept_pml4,
+ uint32_t pinbased_ctls, uint32_t procbased_ctls,
+ uint32_t procbased_ctls2, uint32_t exit_ctls,
+ uint32_t entry_ctls, u_long msr_bitmap, uint16_t vpid)
+{
+ int error, codesel, datasel, tsssel;
+ u_long cr0, cr4, efer;
+ uint64_t eptp, pat, fsbase, idtrbase;
+ uint32_t exc_bitmap;
+
+ codesel = vmm_get_host_codesel();
+ datasel = vmm_get_host_datasel();
+ tsssel = vmm_get_host_tsssel();
+
+ /*
+ * Make sure we have a "current" VMCS to work with.
+ */
+ VMPTRLD(vmcs);
+
+ /*
+ * Load the VMX controls
+ */
+ if ((error = vmwrite(VMCS_PIN_BASED_CTLS, pinbased_ctls)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, procbased_ctls)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_SEC_PROC_BASED_CTLS, procbased_ctls2)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_EXIT_CTLS, exit_ctls)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_ENTRY_CTLS, entry_ctls)) != 0)
+ goto done;
+
+ /* Guest state */
+
+ /* Initialize guest IA32_PAT MSR with the default value */
+ pat = PAT_VALUE(0, PAT_WRITE_BACK) |
+ PAT_VALUE(1, PAT_WRITE_THROUGH) |
+ PAT_VALUE(2, PAT_UNCACHED) |
+ PAT_VALUE(3, PAT_UNCACHEABLE) |
+ PAT_VALUE(4, PAT_WRITE_BACK) |
+ PAT_VALUE(5, PAT_WRITE_THROUGH) |
+ PAT_VALUE(6, PAT_UNCACHED) |
+ PAT_VALUE(7, PAT_UNCACHEABLE);
+ if ((error = vmwrite(VMCS_GUEST_IA32_PAT, pat)) != 0)
+ goto done;
+
+ /* Host state */
+
+ /* Initialize host IA32_PAT MSR */
+ pat = vmm_get_host_pat();
+ if ((error = vmwrite(VMCS_HOST_IA32_PAT, pat)) != 0)
+ goto done;
+
+ /* Load the IA32_EFER MSR */
+ efer = vmm_get_host_efer();
+ if ((error = vmwrite(VMCS_HOST_IA32_EFER, efer)) != 0)
+ goto done;
+
+ /* Load the control registers */
+
+ cr0 = vmm_get_host_cr0();
+ if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0)
+ goto done;
+
+ cr4 = vmm_get_host_cr4() | CR4_VMXE;
+ if ((error = vmwrite(VMCS_HOST_CR4, cr4)) != 0)
+ goto done;
+
+ /* Load the segment selectors */
+ if ((error = vmwrite(VMCS_HOST_ES_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_CS_SELECTOR, codesel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_SS_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_DS_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_FS_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_GS_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_TR_SELECTOR, tsssel)) != 0)
+ goto done;
+
+ /*
+ * Load the Base-Address for %fs and idtr.
+ *
+ * Note that we exclude %gs, tss and gdtr here because their base
+ * address is pcpu specific.
+ */
+ fsbase = vmm_get_host_fsbase();
+ if ((error = vmwrite(VMCS_HOST_FS_BASE, fsbase)) != 0)
+ goto done;
+
+ idtrbase = vmm_get_host_idtrbase();
+ if ((error = vmwrite(VMCS_HOST_IDTR_BASE, idtrbase)) != 0)
+ goto done;
+
+ /* instruction pointer */
+ if ((error = vmwrite(VMCS_HOST_RIP, host_rip)) != 0)
+ goto done;
+
+ /* stack pointer */
+ if ((error = vmwrite(VMCS_HOST_RSP, host_rsp)) != 0)
+ goto done;
+
+ /* eptp */
+ eptp = EPTP(ept_pml4);
+ if ((error = vmwrite(VMCS_EPTP, eptp)) != 0)
+ goto done;
+
+ /* vpid */
+ if ((error = vmwrite(VMCS_VPID, vpid)) != 0)
+ goto done;
+
+ /* msr bitmap */
+ if ((error = vmwrite(VMCS_MSR_BITMAP, msr_bitmap)) != 0)
+ goto done;
+
+ /* exception bitmap */
+ exc_bitmap = 1 << IDT_MC;
+ if ((error = vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap)) != 0)
+ goto done;
+
+ /* link pointer */
+ if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0)
+ goto done;
+done:
+ VMCLEAR(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[];
+
+DB_SHOW_COMMAND(vmcs, db_show_vmcs)
+{
+ uint64_t cur_vmcs, val;
+ uint32_t exit;
+
+ if (!vmxon_enabled[curcpu]) {
+ db_printf("VMX not enabled\n");
+ return;
+ }
+
+ if (have_addr) {
+ db_printf("Only current VMCS supported\n");
+ return;
+ }
+
+ vmptrst(&cur_vmcs);
+ if (cur_vmcs == VMCS_INITIAL) {
+ db_printf("No current VM context\n");
+ return;
+ }
+ db_printf("VMCS: %jx\n", cur_vmcs);
+ db_printf("VPID: %lu\n", vmcs_read(VMCS_VPID));
+ db_printf("Activity: ");
+ val = vmcs_read(VMCS_GUEST_ACTIVITY);
+ switch (val) {
+ case 0:
+ db_printf("Active");
+ break;
+ case 1:
+ db_printf("HLT");
+ break;
+ case 2:
+ db_printf("Shutdown");
+ break;
+ case 3:
+ db_printf("Wait for SIPI");
+ break;
+ default:
+ db_printf("Unknown: %#lx", val);
+ }
+ db_printf("\n");
+ exit = vmcs_read(VMCS_EXIT_REASON);
+ if (exit & 0x80000000)
+ db_printf("Entry Failure Reason: %u\n", exit & 0xffff);
+ else
+ db_printf("Exit Reason: %u\n", exit & 0xffff);
+ db_printf("Qualification: %#lx\n", vmcs_exit_qualification());
+ db_printf("Guest Linear Address: %#lx\n",
+ vmcs_read(VMCS_GUEST_LINEAR_ADDRESS));
+ switch (exit & 0x8000ffff) {
+ case EXIT_REASON_EXCEPTION:
+ case EXIT_REASON_EXT_INTR:
+ val = vmcs_read(VMCS_EXIT_INTERRUPTION_INFO);
+ db_printf("Interrupt Type: ");
+ switch (val >> 8 & 0x7) {
+ case 0:
+ db_printf("external");
+ break;
+ case 2:
+ db_printf("NMI");
+ break;
+ case 3:
+ db_printf("HW exception");
+ break;
+ case 4:
+ db_printf("SW exception");
+ break;
+ default:
+ db_printf("?? %lu", val >> 8 & 0x7);
+ break;
+ }
+ db_printf(" Vector: %lu", val & 0xff);
+ if (val & 0x800)
+ db_printf(" Error Code: %lx",
+ vmcs_read(VMCS_EXIT_INTERRUPTION_ERROR));
+ db_printf("\n");
+ break;
+ case EXIT_REASON_EPT_FAULT:
+ case EXIT_REASON_EPT_MISCONFIG:
+ db_printf("Guest Physical Address: %#lx\n",
+ vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS));
+ break;
+ }
+ db_printf("VM-instruction error: %#lx\n", vmcs_instruction_error());
+}
+#endif
diff --git a/sys/amd64/vmm/intel/vmcs.h b/sys/amd64/vmm/intel/vmcs.h
new file mode 100644
index 0000000..f39eed2
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmcs.h
@@ -0,0 +1,338 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMCS_H_
+#define _VMCS_H_
+
+#ifdef _KERNEL
+struct vmcs {
+ uint32_t identifier;
+ uint32_t abort_code;
+ char _impl_specific[PAGE_SIZE - sizeof(uint32_t) * 2];
+};
+CTASSERT(sizeof(struct vmcs) == PAGE_SIZE);
+
+/* MSR save region is composed of an array of 'struct msr_entry' */
+struct msr_entry {
+ uint32_t index;
+ uint32_t reserved;
+ uint64_t val;
+
+};
+
+int vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count);
+int vmcs_set_defaults(struct vmcs *vmcs, u_long host_rip, u_long host_rsp,
+ u_long ept_pml4,
+ uint32_t pinbased_ctls, uint32_t procbased_ctls,
+ uint32_t procbased_ctls2, uint32_t exit_ctls,
+ uint32_t entry_ctls, u_long msr_bitmap,
+ uint16_t vpid);
+int vmcs_getreg(struct vmcs *vmcs, int ident, uint64_t *retval);
+int vmcs_setreg(struct vmcs *vmcs, int ident, uint64_t val);
+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);
+
+#define vmexit_instruction_length() vmcs_read(VMCS_EXIT_INSTRUCTION_LENGTH)
+#define vmcs_guest_rip() vmcs_read(VMCS_GUEST_RIP)
+#define vmcs_instruction_error() vmcs_read(VMCS_INSTRUCTION_ERROR)
+#define vmcs_exit_reason() (vmcs_read(VMCS_EXIT_REASON) & 0xffff)
+#define vmcs_exit_qualification() vmcs_read(VMCS_EXIT_QUALIFICATION)
+#define vmcs_guest_cr3() vmcs_read(VMCS_GUEST_CR3)
+#define vmcs_gpa() vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)
+#define vmcs_gla() vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)
+
+#endif /* _KERNEL */
+
+#define VMCS_INITIAL 0xffffffffffffffff
+
+#define VMCS_IDENT(encoding) ((encoding) | 0x80000000)
+/*
+ * VMCS field encodings from Appendix H, Intel Architecture Manual Vol3B.
+ */
+#define VMCS_INVALID_ENCODING 0xffffffff
+
+/* 16-bit control fields */
+#define VMCS_VPID 0x00000000
+
+/* 16-bit guest-state fields */
+#define VMCS_GUEST_ES_SELECTOR 0x00000800
+#define VMCS_GUEST_CS_SELECTOR 0x00000802
+#define VMCS_GUEST_SS_SELECTOR 0x00000804
+#define VMCS_GUEST_DS_SELECTOR 0x00000806
+#define VMCS_GUEST_FS_SELECTOR 0x00000808
+#define VMCS_GUEST_GS_SELECTOR 0x0000080A
+#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C
+#define VMCS_GUEST_TR_SELECTOR 0x0000080E
+
+/* 16-bit host-state fields */
+#define VMCS_HOST_ES_SELECTOR 0x00000C00
+#define VMCS_HOST_CS_SELECTOR 0x00000C02
+#define VMCS_HOST_SS_SELECTOR 0x00000C04
+#define VMCS_HOST_DS_SELECTOR 0x00000C06
+#define VMCS_HOST_FS_SELECTOR 0x00000C08
+#define VMCS_HOST_GS_SELECTOR 0x00000C0A
+#define VMCS_HOST_TR_SELECTOR 0x00000C0C
+
+/* 64-bit control fields */
+#define VMCS_IO_BITMAP_A 0x00002000
+#define VMCS_IO_BITMAP_B 0x00002002
+#define VMCS_MSR_BITMAP 0x00002004
+#define VMCS_EXIT_MSR_STORE 0x00002006
+#define VMCS_EXIT_MSR_LOAD 0x00002008
+#define VMCS_ENTRY_MSR_LOAD 0x0000200A
+#define VMCS_EXECUTIVE_VMCS 0x0000200C
+#define VMCS_TSC_OFFSET 0x00002010
+#define VMCS_VIRTUAL_APIC 0x00002012
+#define VMCS_APIC_ACCESS 0x00002014
+#define VMCS_EPTP 0x0000201A
+
+/* 64-bit read-only fields */
+#define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400
+
+/* 64-bit guest-state fields */
+#define VMCS_LINK_POINTER 0x00002800
+#define VMCS_GUEST_IA32_DEBUGCTL 0x00002802
+#define VMCS_GUEST_IA32_PAT 0x00002804
+#define VMCS_GUEST_IA32_EFER 0x00002806
+#define VMCS_GUEST_IA32_PERF_GLOBAL_CTRL 0x00002808
+#define VMCS_GUEST_PDPTE0 0x0000280A
+#define VMCS_GUEST_PDPTE1 0x0000280C
+#define VMCS_GUEST_PDPTE2 0x0000280E
+#define VMCS_GUEST_PDPTE3 0x00002810
+
+/* 64-bit host-state fields */
+#define VMCS_HOST_IA32_PAT 0x00002C00
+#define VMCS_HOST_IA32_EFER 0x00002C02
+#define VMCS_HOST_IA32_PERF_GLOBAL_CTRL 0x00002C04
+
+/* 32-bit control fields */
+#define VMCS_PIN_BASED_CTLS 0x00004000
+#define VMCS_PRI_PROC_BASED_CTLS 0x00004002
+#define VMCS_EXCEPTION_BITMAP 0x00004004
+#define VMCS_PF_ERROR_MASK 0x00004006
+#define VMCS_PF_ERROR_MATCH 0x00004008
+#define VMCS_CR3_TARGET_COUNT 0x0000400A
+#define VMCS_EXIT_CTLS 0x0000400C
+#define VMCS_EXIT_MSR_STORE_COUNT 0x0000400E
+#define VMCS_EXIT_MSR_LOAD_COUNT 0x00004010
+#define VMCS_ENTRY_CTLS 0x00004012
+#define VMCS_ENTRY_MSR_LOAD_COUNT 0x00004014
+#define VMCS_ENTRY_INTR_INFO 0x00004016
+#define VMCS_ENTRY_EXCEPTION_ERROR 0x00004018
+#define VMCS_ENTRY_INST_LENGTH 0x0000401A
+#define VMCS_TPR_THRESHOLD 0x0000401C
+#define VMCS_SEC_PROC_BASED_CTLS 0x0000401E
+#define VMCS_PLE_GAP 0x00004020
+#define VMCS_PLE_WINDOW 0x00004022
+
+/* 32-bit read-only data fields */
+#define VMCS_INSTRUCTION_ERROR 0x00004400
+#define VMCS_EXIT_REASON 0x00004402
+#define VMCS_EXIT_INTERRUPTION_INFO 0x00004404
+#define VMCS_EXIT_INTERRUPTION_ERROR 0x00004406
+#define VMCS_IDT_VECTORING_INFO 0x00004408
+#define VMCS_IDT_VECTORING_ERROR 0x0000440A
+#define VMCS_EXIT_INSTRUCTION_LENGTH 0x0000440C
+#define VMCS_EXIT_INSTRUCTION_INFO 0x0000440E
+
+/* 32-bit guest-state fields */
+#define VMCS_GUEST_ES_LIMIT 0x00004800
+#define VMCS_GUEST_CS_LIMIT 0x00004802
+#define VMCS_GUEST_SS_LIMIT 0x00004804
+#define VMCS_GUEST_DS_LIMIT 0x00004806
+#define VMCS_GUEST_FS_LIMIT 0x00004808
+#define VMCS_GUEST_GS_LIMIT 0x0000480A
+#define VMCS_GUEST_LDTR_LIMIT 0x0000480C
+#define VMCS_GUEST_TR_LIMIT 0x0000480E
+#define VMCS_GUEST_GDTR_LIMIT 0x00004810
+#define VMCS_GUEST_IDTR_LIMIT 0x00004812
+#define VMCS_GUEST_ES_ACCESS_RIGHTS 0x00004814
+#define VMCS_GUEST_CS_ACCESS_RIGHTS 0x00004816
+#define VMCS_GUEST_SS_ACCESS_RIGHTS 0x00004818
+#define VMCS_GUEST_DS_ACCESS_RIGHTS 0x0000481A
+#define VMCS_GUEST_FS_ACCESS_RIGHTS 0x0000481C
+#define VMCS_GUEST_GS_ACCESS_RIGHTS 0x0000481E
+#define VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x00004820
+#define VMCS_GUEST_TR_ACCESS_RIGHTS 0x00004822
+#define VMCS_GUEST_INTERRUPTIBILITY 0x00004824
+#define VMCS_GUEST_ACTIVITY 0x00004826
+#define VMCS_GUEST_SMBASE 0x00004828
+#define VMCS_GUEST_IA32_SYSENTER_CS 0x0000482A
+#define VMCS_PREEMPTION_TIMER_VALUE 0x0000482E
+
+/* 32-bit host state fields */
+#define VMCS_HOST_IA32_SYSENTER_CS 0x00004C00
+
+/* Natural Width control fields */
+#define VMCS_CR0_MASK 0x00006000
+#define VMCS_CR4_MASK 0x00006002
+#define VMCS_CR0_SHADOW 0x00006004
+#define VMCS_CR4_SHADOW 0x00006006
+#define VMCS_CR3_TARGET0 0x00006008
+#define VMCS_CR3_TARGET1 0x0000600A
+#define VMCS_CR3_TARGET2 0x0000600C
+#define VMCS_CR3_TARGET3 0x0000600E
+
+/* Natural Width read-only fields */
+#define VMCS_EXIT_QUALIFICATION 0x00006400
+#define VMCS_IO_RCX 0x00006402
+#define VMCS_IO_RSI 0x00006404
+#define VMCS_IO_RDI 0x00006406
+#define VMCS_IO_RIP 0x00006408
+#define VMCS_GUEST_LINEAR_ADDRESS 0x0000640A
+
+/* Natural Width guest-state fields */
+#define VMCS_GUEST_CR0 0x00006800
+#define VMCS_GUEST_CR3 0x00006802
+#define VMCS_GUEST_CR4 0x00006804
+#define VMCS_GUEST_ES_BASE 0x00006806
+#define VMCS_GUEST_CS_BASE 0x00006808
+#define VMCS_GUEST_SS_BASE 0x0000680A
+#define VMCS_GUEST_DS_BASE 0x0000680C
+#define VMCS_GUEST_FS_BASE 0x0000680E
+#define VMCS_GUEST_GS_BASE 0x00006810
+#define VMCS_GUEST_LDTR_BASE 0x00006812
+#define VMCS_GUEST_TR_BASE 0x00006814
+#define VMCS_GUEST_GDTR_BASE 0x00006816
+#define VMCS_GUEST_IDTR_BASE 0x00006818
+#define VMCS_GUEST_DR7 0x0000681A
+#define VMCS_GUEST_RSP 0x0000681C
+#define VMCS_GUEST_RIP 0x0000681E
+#define VMCS_GUEST_RFLAGS 0x00006820
+#define VMCS_GUEST_PENDING_DBG_EXCEPTIONS 0x00006822
+#define VMCS_GUEST_IA32_SYSENTER_ESP 0x00006824
+#define VMCS_GUEST_IA32_SYSENTER_EIP 0x00006826
+
+/* Natural Width host-state fields */
+#define VMCS_HOST_CR0 0x00006C00
+#define VMCS_HOST_CR3 0x00006C02
+#define VMCS_HOST_CR4 0x00006C04
+#define VMCS_HOST_FS_BASE 0x00006C06
+#define VMCS_HOST_GS_BASE 0x00006C08
+#define VMCS_HOST_TR_BASE 0x00006C0A
+#define VMCS_HOST_GDTR_BASE 0x00006C0C
+#define VMCS_HOST_IDTR_BASE 0x00006C0E
+#define VMCS_HOST_IA32_SYSENTER_ESP 0x00006C10
+#define VMCS_HOST_IA32_SYSENTER_EIP 0x00006C12
+#define VMCS_HOST_RSP 0x00006C14
+#define VMCS_HOST_RIP 0x00006c16
+
+/*
+ * VM instruction error numbers
+ */
+#define VMRESUME_WITH_NON_LAUNCHED_VMCS 5
+
+/*
+ * VMCS exit reasons
+ */
+#define EXIT_REASON_EXCEPTION 0
+#define EXIT_REASON_EXT_INTR 1
+#define EXIT_REASON_TRIPLE_FAULT 2
+#define EXIT_REASON_INIT 3
+#define EXIT_REASON_SIPI 4
+#define EXIT_REASON_IO_SMI 5
+#define EXIT_REASON_SMI 6
+#define EXIT_REASON_INTR_WINDOW 7
+#define EXIT_REASON_NMI_WINDOW 8
+#define EXIT_REASON_TASK_SWITCH 9
+#define EXIT_REASON_CPUID 10
+#define EXIT_REASON_GETSEC 11
+#define EXIT_REASON_HLT 12
+#define EXIT_REASON_INVD 13
+#define EXIT_REASON_INVLPG 14
+#define EXIT_REASON_RDPMC 15
+#define EXIT_REASON_RDTSC 16
+#define EXIT_REASON_RSM 17
+#define EXIT_REASON_VMCALL 18
+#define EXIT_REASON_VMCLEAR 19
+#define EXIT_REASON_VMLAUNCH 20
+#define EXIT_REASON_VMPTRLD 21
+#define EXIT_REASON_VMPTRST 22
+#define EXIT_REASON_VMREAD 23
+#define EXIT_REASON_VMRESUME 24
+#define EXIT_REASON_VMWRITE 25
+#define EXIT_REASON_VMXOFF 26
+#define EXIT_REASON_VMXON 27
+#define EXIT_REASON_CR_ACCESS 28
+#define EXIT_REASON_DR_ACCESS 29
+#define EXIT_REASON_INOUT 30
+#define EXIT_REASON_RDMSR 31
+#define EXIT_REASON_WRMSR 32
+#define EXIT_REASON_INVAL_VMCS 33
+#define EXIT_REASON_INVAL_MSR 34
+#define EXIT_REASON_MWAIT 36
+#define EXIT_REASON_MTF 37
+#define EXIT_REASON_MONITOR 39
+#define EXIT_REASON_PAUSE 40
+#define EXIT_REASON_MCE 41
+#define EXIT_REASON_TPR 43
+#define EXIT_REASON_APIC 44
+#define EXIT_REASON_GDTR_IDTR 46
+#define EXIT_REASON_LDTR_TR 47
+#define EXIT_REASON_EPT_FAULT 48
+#define EXIT_REASON_EPT_MISCONFIG 49
+#define EXIT_REASON_INVEPT 50
+#define EXIT_REASON_RDTSCP 51
+#define EXIT_REASON_VMX_PREEMPT 52
+#define EXIT_REASON_INVVPID 53
+#define EXIT_REASON_WBINVD 54
+#define EXIT_REASON_XSETBV 55
+
+/*
+ * VMCS interrupt information fields
+ */
+#define VMCS_INTERRUPTION_INFO_VALID (1U << 31)
+#define VMCS_INTERRUPTION_INFO_HW_INTR (0 << 8)
+#define VMCS_INTERRUPTION_INFO_NMI (2 << 8)
+
+/*
+ * VMCS Guest interruptibility field
+ */
+#define VMCS_INTERRUPTIBILITY_STI_BLOCKING (1 << 0)
+#define VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING (1 << 1)
+#define VMCS_INTERRUPTIBILITY_SMI_BLOCKING (1 << 2)
+#define VMCS_INTERRUPTIBILITY_NMI_BLOCKING (1 << 3)
+
+/*
+ * Exit qualification for EXIT_REASON_INVAL_VMCS
+ */
+#define EXIT_QUAL_NMI_WHILE_STI_BLOCKING 3
+
+/*
+ * Exit qualification for EPT violation
+ */
+#define EPT_VIOLATION_DATA_READ (1UL << 0)
+#define EPT_VIOLATION_DATA_WRITE (1UL << 1)
+#define EPT_VIOLATION_INST_FETCH (1UL << 2)
+#define EPT_VIOLATION_GLA_VALID (1UL << 7)
+#define EPT_VIOLATION_XLAT_VALID (1UL << 8)
+
+#endif
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
new file mode 100644
index 0000000..287ac8c
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -0,0 +1,1852 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/psl.h>
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+#include <machine/pmap.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
+#include <machine/vmparam.h>
+
+#include <x86/apicreg.h>
+
+#include <machine/vmm.h>
+#include "vmm_host.h"
+#include "vmm_lapic.h"
+#include "vmm_msr.h"
+#include "vmm_ktr.h"
+#include "vmm_stat.h"
+
+#include "vmx_msr.h"
+#include "ept.h"
+#include "vmx_cpufunc.h"
+#include "vmx.h"
+#include "x86.h"
+#include "vmx_controls.h"
+
+#define PINBASED_CTLS_ONE_SETTING \
+ (PINBASED_EXTINT_EXITING | \
+ PINBASED_NMI_EXITING | \
+ PINBASED_VIRTUAL_NMI)
+#define PINBASED_CTLS_ZERO_SETTING 0
+
+#define PROCBASED_CTLS_WINDOW_SETTING \
+ (PROCBASED_INT_WINDOW_EXITING | \
+ PROCBASED_NMI_WINDOW_EXITING)
+
+#define PROCBASED_CTLS_ONE_SETTING \
+ (PROCBASED_SECONDARY_CONTROLS | \
+ PROCBASED_IO_EXITING | \
+ PROCBASED_MSR_BITMAPS | \
+ PROCBASED_CTLS_WINDOW_SETTING)
+#define PROCBASED_CTLS_ZERO_SETTING \
+ (PROCBASED_CR3_LOAD_EXITING | \
+ PROCBASED_CR3_STORE_EXITING | \
+ PROCBASED_IO_BITMAPS)
+
+#define PROCBASED_CTLS2_ONE_SETTING PROCBASED2_ENABLE_EPT
+#define PROCBASED_CTLS2_ZERO_SETTING 0
+
+#define VM_EXIT_CTLS_ONE_SETTING_NO_PAT \
+ (VM_EXIT_HOST_LMA | \
+ VM_EXIT_SAVE_EFER | \
+ VM_EXIT_LOAD_EFER)
+
+#define VM_EXIT_CTLS_ONE_SETTING \
+ (VM_EXIT_CTLS_ONE_SETTING_NO_PAT | \
+ VM_EXIT_SAVE_PAT | \
+ VM_EXIT_LOAD_PAT)
+#define VM_EXIT_CTLS_ZERO_SETTING VM_EXIT_SAVE_DEBUG_CONTROLS
+
+#define VM_ENTRY_CTLS_ONE_SETTING_NO_PAT VM_ENTRY_LOAD_EFER
+
+#define VM_ENTRY_CTLS_ONE_SETTING \
+ (VM_ENTRY_CTLS_ONE_SETTING_NO_PAT | \
+ VM_ENTRY_LOAD_PAT)
+#define VM_ENTRY_CTLS_ZERO_SETTING \
+ (VM_ENTRY_LOAD_DEBUG_CONTROLS | \
+ VM_ENTRY_INTO_SMM | \
+ VM_ENTRY_DEACTIVATE_DUAL_MONITOR)
+
+#define guest_msr_rw(vmx, msr) \
+ msr_bitmap_change_access((vmx)->msr_bitmap, (msr), MSR_BITMAP_ACCESS_RW)
+
+#define HANDLED 1
+#define UNHANDLED 0
+
+MALLOC_DEFINE(M_VMX, "vmx", "vmx");
+
+int vmxon_enabled[MAXCPU];
+static char vmxon_region[MAXCPU][PAGE_SIZE] __aligned(PAGE_SIZE);
+
+static uint32_t pinbased_ctls, procbased_ctls, procbased_ctls2;
+static uint32_t exit_ctls, entry_ctls;
+
+static uint64_t cr0_ones_mask, cr0_zeros_mask;
+static uint64_t cr4_ones_mask, cr4_zeros_mask;
+
+static volatile u_int nextvpid;
+
+static int vmx_no_patmsr;
+
+/*
+ * Virtual NMI blocking conditions.
+ *
+ * Some processor implementations also require NMI to be blocked if
+ * the STI_BLOCKING bit is set. It is possible to detect this at runtime
+ * based on the (exit_reason,exit_qual) tuple being set to
+ * (EXIT_REASON_INVAL_VMCS, EXIT_QUAL_NMI_WHILE_STI_BLOCKING).
+ *
+ * We take the easy way out and also include STI_BLOCKING as one of the
+ * gating items for vNMI injection.
+ */
+static uint64_t nmi_blocking_bits = VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING |
+ VMCS_INTERRUPTIBILITY_NMI_BLOCKING |
+ VMCS_INTERRUPTIBILITY_STI_BLOCKING;
+
+/*
+ * Optional capabilities
+ */
+static int cap_halt_exit;
+static int cap_pause_exit;
+static int cap_unrestricted_guest;
+static int cap_monitor_trap;
+
+/* statistics */
+static VMM_STAT_DEFINE(VCPU_MIGRATIONS, "vcpu migration across host cpus");
+static VMM_STAT_DEFINE(VMEXIT_EXTINT, "vm exits due to external interrupt");
+static VMM_STAT_DEFINE(VMEXIT_HLT_IGNORED, "number of times hlt was ignored");
+static VMM_STAT_DEFINE(VMEXIT_HLT, "number of times hlt was intercepted");
+
+#ifdef KTR
+static const char *
+exit_reason_to_str(int reason)
+{
+ static char reasonbuf[32];
+
+ switch (reason) {
+ case EXIT_REASON_EXCEPTION:
+ return "exception";
+ case EXIT_REASON_EXT_INTR:
+ return "extint";
+ case EXIT_REASON_TRIPLE_FAULT:
+ return "triplefault";
+ case EXIT_REASON_INIT:
+ return "init";
+ case EXIT_REASON_SIPI:
+ return "sipi";
+ case EXIT_REASON_IO_SMI:
+ return "iosmi";
+ case EXIT_REASON_SMI:
+ return "smi";
+ case EXIT_REASON_INTR_WINDOW:
+ return "intrwindow";
+ case EXIT_REASON_NMI_WINDOW:
+ return "nmiwindow";
+ case EXIT_REASON_TASK_SWITCH:
+ return "taskswitch";
+ case EXIT_REASON_CPUID:
+ return "cpuid";
+ case EXIT_REASON_GETSEC:
+ return "getsec";
+ case EXIT_REASON_HLT:
+ return "hlt";
+ case EXIT_REASON_INVD:
+ return "invd";
+ case EXIT_REASON_INVLPG:
+ return "invlpg";
+ case EXIT_REASON_RDPMC:
+ return "rdpmc";
+ case EXIT_REASON_RDTSC:
+ return "rdtsc";
+ case EXIT_REASON_RSM:
+ return "rsm";
+ case EXIT_REASON_VMCALL:
+ return "vmcall";
+ case EXIT_REASON_VMCLEAR:
+ return "vmclear";
+ case EXIT_REASON_VMLAUNCH:
+ return "vmlaunch";
+ case EXIT_REASON_VMPTRLD:
+ return "vmptrld";
+ case EXIT_REASON_VMPTRST:
+ return "vmptrst";
+ case EXIT_REASON_VMREAD:
+ return "vmread";
+ case EXIT_REASON_VMRESUME:
+ return "vmresume";
+ case EXIT_REASON_VMWRITE:
+ return "vmwrite";
+ case EXIT_REASON_VMXOFF:
+ return "vmxoff";
+ case EXIT_REASON_VMXON:
+ return "vmxon";
+ case EXIT_REASON_CR_ACCESS:
+ return "craccess";
+ case EXIT_REASON_DR_ACCESS:
+ return "draccess";
+ case EXIT_REASON_INOUT:
+ return "inout";
+ case EXIT_REASON_RDMSR:
+ return "rdmsr";
+ case EXIT_REASON_WRMSR:
+ return "wrmsr";
+ case EXIT_REASON_INVAL_VMCS:
+ return "invalvmcs";
+ case EXIT_REASON_INVAL_MSR:
+ return "invalmsr";
+ case EXIT_REASON_MWAIT:
+ return "mwait";
+ case EXIT_REASON_MTF:
+ return "mtf";
+ case EXIT_REASON_MONITOR:
+ return "monitor";
+ case EXIT_REASON_PAUSE:
+ return "pause";
+ case EXIT_REASON_MCE:
+ return "mce";
+ case EXIT_REASON_TPR:
+ return "tpr";
+ case EXIT_REASON_APIC:
+ return "apic";
+ case EXIT_REASON_GDTR_IDTR:
+ return "gdtridtr";
+ case EXIT_REASON_LDTR_TR:
+ return "ldtrtr";
+ case EXIT_REASON_EPT_FAULT:
+ return "eptfault";
+ case EXIT_REASON_EPT_MISCONFIG:
+ return "eptmisconfig";
+ case EXIT_REASON_INVEPT:
+ return "invept";
+ case EXIT_REASON_RDTSCP:
+ return "rdtscp";
+ case EXIT_REASON_VMX_PREEMPT:
+ return "vmxpreempt";
+ case EXIT_REASON_INVVPID:
+ return "invvpid";
+ case EXIT_REASON_WBINVD:
+ return "wbinvd";
+ case EXIT_REASON_XSETBV:
+ return "xsetbv";
+ default:
+ snprintf(reasonbuf, sizeof(reasonbuf), "%d", reason);
+ return (reasonbuf);
+ }
+}
+
+#ifdef SETJMP_TRACE
+static const char *
+vmx_setjmp_rc2str(int rc)
+{
+ switch (rc) {
+ case VMX_RETURN_DIRECT:
+ return "direct";
+ case VMX_RETURN_LONGJMP:
+ return "longjmp";
+ case VMX_RETURN_VMRESUME:
+ return "vmresume";
+ case VMX_RETURN_VMLAUNCH:
+ return "vmlaunch";
+ case VMX_RETURN_AST:
+ return "ast";
+ default:
+ return "unknown";
+ }
+}
+
+#define SETJMP_TRACE(vmx, vcpu, vmxctx, regname) \
+ VMM_CTR1((vmx)->vm, (vcpu), "setjmp trace " #regname " 0x%016lx", \
+ (vmxctx)->regname)
+
+static void
+vmx_setjmp_trace(struct vmx *vmx, int vcpu, struct vmxctx *vmxctx, int rc)
+{
+ uint64_t host_rip, host_rsp;
+
+ if (vmxctx != &vmx->ctx[vcpu])
+ panic("vmx_setjmp_trace: invalid vmxctx %p; should be %p",
+ vmxctx, &vmx->ctx[vcpu]);
+
+ VMM_CTR1((vmx)->vm, (vcpu), "vmxctx = %p", vmxctx);
+ VMM_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);
+ VMM_CTR2((vmx)->vm, (vcpu), "vmcs host_rip 0x%016lx, host_rsp 0x%016lx",
+ host_rip, host_rsp);
+
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_r15);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_r14);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_r13);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_r12);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_rbp);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_rsp);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_rbx);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_rip);
+
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rdi);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rsi);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rdx);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rcx);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r8);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r9);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rax);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rbx);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rbp);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r10);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r11);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r12);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r13);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r14);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r15);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_cr2);
+}
+#endif
+#else
+static void __inline
+vmx_setjmp_trace(struct vmx *vmx, int vcpu, struct vmxctx *vmxctx, int rc)
+{
+ return;
+}
+#endif /* KTR */
+
+u_long
+vmx_fix_cr0(u_long cr0)
+{
+
+ return ((cr0 | cr0_ones_mask) & ~cr0_zeros_mask);
+}
+
+u_long
+vmx_fix_cr4(u_long cr4)
+{
+
+ return ((cr4 | cr4_ones_mask) & ~cr4_zeros_mask);
+}
+
+static void
+msr_save_area_init(struct msr_entry *g_area, int *g_count)
+{
+ int cnt;
+
+ static struct msr_entry guest_msrs[] = {
+ { MSR_KGSBASE, 0, 0 },
+ };
+
+ cnt = sizeof(guest_msrs) / sizeof(guest_msrs[0]);
+ if (cnt > GUEST_MSR_MAX_ENTRIES)
+ panic("guest msr save area overrun");
+ bcopy(guest_msrs, g_area, sizeof(guest_msrs));
+ *g_count = cnt;
+}
+
+static void
+vmx_disable(void *arg __unused)
+{
+ struct invvpid_desc invvpid_desc = { 0 };
+ struct invept_desc invept_desc = { 0 };
+
+ if (vmxon_enabled[curcpu]) {
+ /*
+ * See sections 25.3.3.3 and 25.3.3.4 in Intel Vol 3b.
+ *
+ * VMXON or VMXOFF are not required to invalidate any TLB
+ * caching structures. This prevents potential retention of
+ * cached information in the TLB between distinct VMX episodes.
+ */
+ invvpid(INVVPID_TYPE_ALL_CONTEXTS, invvpid_desc);
+ invept(INVEPT_TYPE_ALL_CONTEXTS, invept_desc);
+ vmxoff();
+ }
+ load_cr4(rcr4() & ~CR4_VMXE);
+}
+
+static int
+vmx_cleanup(void)
+{
+
+ smp_rendezvous(NULL, vmx_disable, NULL, NULL);
+
+ return (0);
+}
+
+static void
+vmx_enable(void *arg __unused)
+{
+ int error;
+
+ load_cr4(rcr4() | CR4_VMXE);
+
+ *(uint32_t *)vmxon_region[curcpu] = vmx_revision();
+ error = vmxon(vmxon_region[curcpu]);
+ if (error == 0)
+ vmxon_enabled[curcpu] = 1;
+}
+
+static int
+vmx_init(void)
+{
+ int error;
+ uint64_t fixed0, fixed1, feature_control;
+ uint32_t tmp;
+
+ /* CPUID.1:ECX[bit 5] must be 1 for processor to support VMX */
+ if (!(cpu_feature2 & CPUID2_VMX)) {
+ printf("vmx_init: processor does not support VMX operation\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits
+ * are set (bits 0 and 2 respectively).
+ */
+ feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
+ if ((feature_control & 0x5) != 0x5) {
+ printf("vmx_init: VMX operation disabled by BIOS\n");
+ return (ENXIO);
+ }
+
+ /* Check support for primary processor-based VM-execution controls */
+ error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_TRUE_PROCBASED_CTLS,
+ PROCBASED_CTLS_ONE_SETTING,
+ PROCBASED_CTLS_ZERO_SETTING, &procbased_ctls);
+ if (error) {
+ printf("vmx_init: processor does not support desired primary "
+ "processor-based controls\n");
+ return (error);
+ }
+
+ /* Clear the processor-based ctl bits that are set on demand */
+ procbased_ctls &= ~PROCBASED_CTLS_WINDOW_SETTING;
+
+ /* Check support for secondary processor-based VM-execution controls */
+ error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2,
+ MSR_VMX_PROCBASED_CTLS2,
+ PROCBASED_CTLS2_ONE_SETTING,
+ PROCBASED_CTLS2_ZERO_SETTING, &procbased_ctls2);
+ if (error) {
+ printf("vmx_init: processor does not support desired secondary "
+ "processor-based controls\n");
+ return (error);
+ }
+
+ /* Check support for VPID */
+ error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, MSR_VMX_PROCBASED_CTLS2,
+ PROCBASED2_ENABLE_VPID, 0, &tmp);
+ if (error == 0)
+ procbased_ctls2 |= PROCBASED2_ENABLE_VPID;
+
+ /* Check support for pin-based VM-execution controls */
+ error = vmx_set_ctlreg(MSR_VMX_PINBASED_CTLS,
+ MSR_VMX_TRUE_PINBASED_CTLS,
+ PINBASED_CTLS_ONE_SETTING,
+ PINBASED_CTLS_ZERO_SETTING, &pinbased_ctls);
+ if (error) {
+ printf("vmx_init: processor does not support desired "
+ "pin-based controls\n");
+ return (error);
+ }
+
+ /* Check support for VM-exit controls */
+ error = vmx_set_ctlreg(MSR_VMX_EXIT_CTLS, MSR_VMX_TRUE_EXIT_CTLS,
+ VM_EXIT_CTLS_ONE_SETTING,
+ VM_EXIT_CTLS_ZERO_SETTING,
+ &exit_ctls);
+ if (error) {
+ /* Try again without the PAT MSR bits */
+ error = vmx_set_ctlreg(MSR_VMX_EXIT_CTLS,
+ MSR_VMX_TRUE_EXIT_CTLS,
+ VM_EXIT_CTLS_ONE_SETTING_NO_PAT,
+ VM_EXIT_CTLS_ZERO_SETTING,
+ &exit_ctls);
+ if (error) {
+ printf("vmx_init: processor does not support desired "
+ "exit controls\n");
+ return (error);
+ } else {
+ if (bootverbose)
+ printf("vmm: PAT MSR access not supported\n");
+ guest_msr_valid(MSR_PAT);
+ vmx_no_patmsr = 1;
+ }
+ }
+
+ /* Check support for VM-entry controls */
+ if (!vmx_no_patmsr) {
+ error = vmx_set_ctlreg(MSR_VMX_ENTRY_CTLS,
+ MSR_VMX_TRUE_ENTRY_CTLS,
+ VM_ENTRY_CTLS_ONE_SETTING,
+ VM_ENTRY_CTLS_ZERO_SETTING,
+ &entry_ctls);
+ } else {
+ error = vmx_set_ctlreg(MSR_VMX_ENTRY_CTLS,
+ MSR_VMX_TRUE_ENTRY_CTLS,
+ VM_ENTRY_CTLS_ONE_SETTING_NO_PAT,
+ VM_ENTRY_CTLS_ZERO_SETTING,
+ &entry_ctls);
+ }
+
+ if (error) {
+ printf("vmx_init: processor does not support desired "
+ "entry controls\n");
+ return (error);
+ }
+
+ /*
+ * Check support for optional features by testing them
+ * as individual bits
+ */
+ cap_halt_exit = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_TRUE_PROCBASED_CTLS,
+ PROCBASED_HLT_EXITING, 0,
+ &tmp) == 0);
+
+ cap_monitor_trap = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_PROCBASED_CTLS,
+ PROCBASED_MTF, 0,
+ &tmp) == 0);
+
+ cap_pause_exit = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_TRUE_PROCBASED_CTLS,
+ PROCBASED_PAUSE_EXITING, 0,
+ &tmp) == 0);
+
+ cap_unrestricted_guest = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2,
+ MSR_VMX_PROCBASED_CTLS2,
+ PROCBASED2_UNRESTRICTED_GUEST, 0,
+ &tmp) == 0);
+
+ /* Initialize EPT */
+ error = ept_init();
+ if (error) {
+ printf("vmx_init: ept initialization failed (%d)\n", error);
+ return (error);
+ }
+
+ /*
+ * Stash the cr0 and cr4 bits that must be fixed to 0 or 1
+ */
+ fixed0 = rdmsr(MSR_VMX_CR0_FIXED0);
+ fixed1 = rdmsr(MSR_VMX_CR0_FIXED1);
+ cr0_ones_mask = fixed0 & fixed1;
+ cr0_zeros_mask = ~fixed0 & ~fixed1;
+
+ /*
+ * CR0_PE and CR0_PG can be set to zero in VMX non-root operation
+ * if unrestricted guest execution is allowed.
+ */
+ if (cap_unrestricted_guest)
+ cr0_ones_mask &= ~(CR0_PG | CR0_PE);
+
+ /*
+ * Do not allow the guest to set CR0_NW or CR0_CD.
+ */
+ cr0_zeros_mask |= (CR0_NW | CR0_CD);
+
+ fixed0 = rdmsr(MSR_VMX_CR4_FIXED0);
+ fixed1 = rdmsr(MSR_VMX_CR4_FIXED1);
+ cr4_ones_mask = fixed0 & fixed1;
+ cr4_zeros_mask = ~fixed0 & ~fixed1;
+
+ /* enable VMX operation */
+ smp_rendezvous(NULL, vmx_enable, NULL, NULL);
+
+ return (0);
+}
+
+/*
+ * If this processor does not support VPIDs then simply return 0.
+ *
+ * Otherwise generate the next value of VPID to use. Any value is alright
+ * as long as it is non-zero.
+ *
+ * We always execute in VMX non-root context with EPT enabled. Thus all
+ * combined mappings are tagged with the (EP4TA, VPID, PCID) tuple. This
+ * in turn means that multiple VMs can share the same VPID as long as
+ * they have distinct EPT page tables.
+ *
+ * XXX
+ * We should optimize this so that it returns VPIDs that are not in
+ * use. Then we will not unnecessarily invalidate mappings in
+ * vmx_set_pcpu_defaults() just because two or more vcpus happen to
+ * use the same 'vpid'.
+ */
+static uint16_t
+vmx_vpid(void)
+{
+ uint16_t vpid = 0;
+
+ if ((procbased_ctls2 & PROCBASED2_ENABLE_VPID) != 0) {
+ do {
+ vpid = atomic_fetchadd_int(&nextvpid, 1);
+ } while (vpid == 0);
+ }
+
+ return (vpid);
+}
+
+static int
+vmx_setup_cr_shadow(int which, struct vmcs *vmcs)
+{
+ int error, mask_ident, shadow_ident;
+ uint64_t mask_value, shadow_value;
+
+ if (which != 0 && which != 4)
+ panic("vmx_setup_cr_shadow: unknown cr%d", which);
+
+ if (which == 0) {
+ mask_ident = VMCS_CR0_MASK;
+ mask_value = cr0_ones_mask | cr0_zeros_mask;
+ shadow_ident = VMCS_CR0_SHADOW;
+ shadow_value = cr0_ones_mask;
+ } else {
+ mask_ident = VMCS_CR4_MASK;
+ mask_value = cr4_ones_mask | cr4_zeros_mask;
+ shadow_ident = VMCS_CR4_SHADOW;
+ shadow_value = cr4_ones_mask;
+ }
+
+ error = vmcs_setreg(vmcs, VMCS_IDENT(mask_ident), mask_value);
+ if (error)
+ return (error);
+
+ error = vmcs_setreg(vmcs, VMCS_IDENT(shadow_ident), shadow_value);
+ if (error)
+ return (error);
+
+ return (0);
+}
+#define vmx_setup_cr0_shadow(vmcs) vmx_setup_cr_shadow(0, (vmcs))
+#define vmx_setup_cr4_shadow(vmcs) vmx_setup_cr_shadow(4, (vmcs))
+
+static void *
+vmx_vminit(struct vm *vm)
+{
+ uint16_t vpid;
+ int i, error, guest_msr_count;
+ struct vmx *vmx;
+
+ vmx = malloc(sizeof(struct vmx), M_VMX, M_WAITOK | M_ZERO);
+ if ((uintptr_t)vmx & PAGE_MASK) {
+ panic("malloc of struct vmx not aligned on %d byte boundary",
+ PAGE_SIZE);
+ }
+ vmx->vm = vm;
+
+ /*
+ * Clean up EPTP-tagged guest physical and combined mappings
+ *
+ * VMX transitions are not required to invalidate any guest physical
+ * mappings. So, it may be possible for stale guest physical mappings
+ * to be present in the processor TLBs.
+ *
+ * Combined mappings for this EP4TA are also invalidated for all VPIDs.
+ */
+ ept_invalidate_mappings(vtophys(vmx->pml4ept));
+
+ msr_bitmap_initialize(vmx->msr_bitmap);
+
+ /*
+ * It is safe to allow direct access to MSR_GSBASE and MSR_FSBASE.
+ * The guest FSBASE and GSBASE are saved and restored during
+ * vm-exit and vm-entry respectively. The host FSBASE and GSBASE are
+ * always restored from the vmcs host state area on vm-exit.
+ *
+ * The SYSENTER_CS/ESP/EIP MSRs are identical to FS/GSBASE in
+ * how they are saved/restored so can be directly accessed by the
+ * guest.
+ *
+ * Guest KGSBASE is saved and restored in the guest MSR save area.
+ * Host KGSBASE is restored before returning to userland from the pcb.
+ * There will be a window of time when we are executing in the host
+ * kernel context with a value of KGSBASE from the guest. This is ok
+ * because the value of KGSBASE is inconsequential in kernel context.
+ *
+ * MSR_EFER is saved and restored in the guest VMCS area on a
+ * VM exit and entry respectively. It is also restored from the
+ * host VMCS area on a VM exit.
+ */
+ if (guest_msr_rw(vmx, MSR_GSBASE) ||
+ guest_msr_rw(vmx, MSR_FSBASE) ||
+ guest_msr_rw(vmx, MSR_SYSENTER_CS_MSR) ||
+ guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) ||
+ guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) ||
+ guest_msr_rw(vmx, MSR_KGSBASE) ||
+ guest_msr_rw(vmx, MSR_EFER))
+ panic("vmx_vminit: error setting guest msr access");
+
+ /*
+ * MSR_PAT is saved and restored in the guest VMCS are on a VM exit
+ * and entry respectively. It is also restored from the host VMCS
+ * area on a VM exit. However, if running on a system with no
+ * MSR_PAT save/restore support, leave access disabled so accesses
+ * will be trapped.
+ */
+ if (!vmx_no_patmsr && guest_msr_rw(vmx, MSR_PAT))
+ panic("vmx_vminit: error setting guest pat msr access");
+
+ for (i = 0; i < VM_MAXCPU; i++) {
+ vmx->vmcs[i].identifier = vmx_revision();
+ error = vmclear(&vmx->vmcs[i]);
+ if (error != 0) {
+ panic("vmx_vminit: vmclear error %d on vcpu %d\n",
+ error, i);
+ }
+
+ vpid = vmx_vpid();
+
+ error = vmcs_set_defaults(&vmx->vmcs[i],
+ (u_long)vmx_longjmp,
+ (u_long)&vmx->ctx[i],
+ vtophys(vmx->pml4ept),
+ pinbased_ctls,
+ procbased_ctls,
+ procbased_ctls2,
+ exit_ctls, entry_ctls,
+ vtophys(vmx->msr_bitmap),
+ vpid);
+
+ if (error != 0)
+ panic("vmx_vminit: vmcs_set_defaults error %d", error);
+
+ vmx->cap[i].set = 0;
+ vmx->cap[i].proc_ctls = procbased_ctls;
+
+ vmx->state[i].lastcpu = -1;
+ vmx->state[i].vpid = vpid;
+
+ msr_save_area_init(vmx->guest_msrs[i], &guest_msr_count);
+
+ error = vmcs_set_msr_save(&vmx->vmcs[i],
+ vtophys(vmx->guest_msrs[i]),
+ guest_msr_count);
+ if (error != 0)
+ panic("vmcs_set_msr_save error %d", error);
+
+ error = vmx_setup_cr0_shadow(&vmx->vmcs[i]);
+ if (error != 0)
+ panic("vmx_setup_cr0_shadow %d", error);
+
+ error = vmx_setup_cr4_shadow(&vmx->vmcs[i]);
+ if (error != 0)
+ panic("vmx_setup_cr4_shadow %d", error);
+ }
+
+ return (vmx);
+}
+
+static int
+vmx_handle_cpuid(struct vm *vm, int vcpu, struct vmxctx *vmxctx)
+{
+ int handled, func;
+
+ func = vmxctx->guest_rax;
+
+ handled = x86_emulate_cpuid(vm, vcpu,
+ (uint32_t*)(&vmxctx->guest_rax),
+ (uint32_t*)(&vmxctx->guest_rbx),
+ (uint32_t*)(&vmxctx->guest_rcx),
+ (uint32_t*)(&vmxctx->guest_rdx));
+ return (handled);
+}
+
+static __inline void
+vmx_run_trace(struct vmx *vmx, int vcpu)
+{
+#ifdef KTR
+ VMM_CTR1(vmx->vm, vcpu, "Resume execution at 0x%0lx", vmcs_guest_rip());
+#endif
+}
+
+static __inline void
+vmx_exit_trace(struct vmx *vmx, int vcpu, uint64_t rip, uint32_t exit_reason,
+ int handled)
+{
+#ifdef KTR
+ VMM_CTR3(vmx->vm, vcpu, "%s %s vmexit at 0x%0lx",
+ handled ? "handled" : "unhandled",
+ exit_reason_to_str(exit_reason), rip);
+#endif
+}
+
+static __inline void
+vmx_astpending_trace(struct vmx *vmx, int vcpu, uint64_t rip)
+{
+#ifdef KTR
+ VMM_CTR1(vmx->vm, vcpu, "astpending vmexit at 0x%0lx", rip);
+#endif
+}
+
+static int
+vmx_set_pcpu_defaults(struct vmx *vmx, int vcpu)
+{
+ int error, lastcpu;
+ struct vmxstate *vmxstate;
+ struct invvpid_desc invvpid_desc = { 0 };
+
+ vmxstate = &vmx->state[vcpu];
+ lastcpu = vmxstate->lastcpu;
+ vmxstate->lastcpu = curcpu;
+
+ if (lastcpu == curcpu) {
+ error = 0;
+ goto done;
+ }
+
+ 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;
+
+ /*
+ * If we are using VPIDs then invalidate all mappings tagged with 'vpid'
+ *
+ * We do this because this vcpu was executing on a different host
+ * cpu when it last ran. We do not track whether it invalidated
+ * mappings associated with its 'vpid' during that run. So we must
+ * assume that the mappings associated with 'vpid' on 'curcpu' are
+ * stale and invalidate them.
+ *
+ * Note that we incur this penalty only when the scheduler chooses to
+ * move the thread associated with this vcpu between host cpus.
+ *
+ * Note also that this will invalidate mappings tagged with 'vpid'
+ * for "all" EP4TAs.
+ */
+ if (vmxstate->vpid != 0) {
+ 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);
+}
+
+/*
+ * We depend on 'procbased_ctls' to have the Interrupt Window Exiting bit set.
+ */
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+ }
+ if (interruptibility & nmi_blocking_bits)
+ goto nmiblocked;
+
+ /*
+ * Inject the virtual NMI. The vector must be the NMI IDT entry
+ * or the VMCS entry check will fail.
+ */
+ 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);
+
+ VMM_CTR0(vmx->vm, vcpu, "Injecting vNMI");
+
+ /* Clear the request */
+ vm_nmi_clear(vmx->vm, vcpu);
+ return (1);
+
+nmiblocked:
+ /*
+ * Set the NMI Window Exiting execution control so we can inject
+ * the virtual NMI as soon as blocking condition goes away.
+ */
+ vmx_set_nmi_window_exiting(vmx, vcpu);
+
+ VMM_CTR0(vmx->vm, vcpu, "Enabling NMI window exiting");
+ return (1);
+}
+
+static void
+vmx_inject_interrupts(struct vmx *vmx, int vcpu)
+{
+ int error, vector;
+ uint64_t info, rflags, interruptibility;
+
+ const int HWINTR_BLOCKED = VMCS_INTERRUPTIBILITY_STI_BLOCKING |
+ VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING;
+
+ /*
+ * If there is already an interrupt pending then just return.
+ *
+ * This could happen if an interrupt was injected on a prior
+ * 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);
+ if (info & VMCS_INTERRUPTION_INFO_VALID)
+ return;
+
+ /*
+ * NMI injection has priority so deal with those first
+ */
+ if (vmx_inject_nmi(vmx, vcpu))
+ return;
+
+ /* Ask the local apic for a vector to inject */
+ vector = lapic_pending_intr(vmx->vm, vcpu);
+ if (vector < 0)
+ return;
+
+ if (vector < 32 || vector > 255)
+ 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);
+
+ if ((rflags & PSL_I) == 0)
+ goto cantinject;
+
+ error = vmread(VMCS_GUEST_INTERRUPTIBILITY, &interruptibility);
+ if (error) {
+ panic("vmx_inject_interrupts: vmread(interruptibility) %d",
+ error);
+ }
+ 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);
+
+ /* Update the Local APIC ISR */
+ lapic_intr_accepted(vmx->vm, vcpu, vector);
+
+ VMM_CTR1(vmx->vm, vcpu, "Injecting hwintr at vector %d", vector);
+
+ return;
+
+cantinject:
+ /*
+ * Set the Interrupt Window Exiting execution control so we can inject
+ * the interrupt as soon as blocking condition goes away.
+ */
+ vmx_set_int_window_exiting(vmx, vcpu);
+
+ VMM_CTR0(vmx->vm, vcpu, "Enabling interrupt window exiting");
+}
+
+static int
+vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual)
+{
+ int error, cr, vmcs_guest_cr;
+ uint64_t regval, ones_mask, zeros_mask;
+ const struct vmxctx *vmxctx;
+
+ /* We only handle mov to %cr0 or %cr4 at this time */
+ if ((exitqual & 0xf0) != 0x00)
+ return (UNHANDLED);
+
+ cr = exitqual & 0xf;
+ if (cr != 0 && cr != 4)
+ return (UNHANDLED);
+
+ vmxctx = &vmx->ctx[vcpu];
+
+ /*
+ * We must use vmwrite() directly here because vmcs_setreg() will
+ * call vmclear(vmcs) as a side-effect which we certainly don't want.
+ */
+ switch ((exitqual >> 8) & 0xf) {
+ case 0:
+ regval = vmxctx->guest_rax;
+ break;
+ case 1:
+ regval = vmxctx->guest_rcx;
+ break;
+ case 2:
+ regval = vmxctx->guest_rdx;
+ break;
+ case 3:
+ regval = vmxctx->guest_rbx;
+ break;
+ case 4:
+ error = vmread(VMCS_GUEST_RSP, &regval);
+ if (error) {
+ panic("vmx_emulate_cr_access: "
+ "error %d reading guest rsp", error);
+ }
+ break;
+ case 5:
+ regval = vmxctx->guest_rbp;
+ break;
+ case 6:
+ regval = vmxctx->guest_rsi;
+ break;
+ case 7:
+ regval = vmxctx->guest_rdi;
+ break;
+ case 8:
+ regval = vmxctx->guest_r8;
+ break;
+ case 9:
+ regval = vmxctx->guest_r9;
+ break;
+ case 10:
+ regval = vmxctx->guest_r10;
+ break;
+ case 11:
+ regval = vmxctx->guest_r11;
+ break;
+ case 12:
+ regval = vmxctx->guest_r12;
+ break;
+ case 13:
+ regval = vmxctx->guest_r13;
+ break;
+ case 14:
+ regval = vmxctx->guest_r14;
+ break;
+ case 15:
+ regval = vmxctx->guest_r15;
+ break;
+ }
+
+ if (cr == 0) {
+ ones_mask = cr0_ones_mask;
+ zeros_mask = cr0_zeros_mask;
+ vmcs_guest_cr = VMCS_GUEST_CR0;
+ } else {
+ ones_mask = cr4_ones_mask;
+ zeros_mask = cr4_zeros_mask;
+ vmcs_guest_cr = VMCS_GUEST_CR4;
+ }
+ regval |= ones_mask;
+ regval &= ~zeros_mask;
+ error = vmwrite(vmcs_guest_cr, regval);
+ if (error) {
+ panic("vmx_emulate_cr_access: error %d writing cr%d",
+ error, cr);
+ }
+
+ return (HANDLED);
+}
+
+static int
+vmx_ept_fault(struct vm *vm, int cpu,
+ uint64_t gla, uint64_t gpa, uint64_t rip, int inst_length,
+ uint64_t cr3, uint64_t ept_qual, struct vie *vie)
+{
+ int read, write, error;
+
+ /* EPT violation on an instruction fetch doesn't make sense here */
+ if (ept_qual & EPT_VIOLATION_INST_FETCH)
+ return (UNHANDLED);
+
+ /* EPT violation must be a read fault or a write fault */
+ read = ept_qual & EPT_VIOLATION_DATA_READ ? 1 : 0;
+ write = ept_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0;
+ if ((read | write) == 0)
+ return (UNHANDLED);
+
+ /*
+ * The EPT violation must have been caused by accessing a
+ * guest-physical address that is a translation of a guest-linear
+ * address.
+ */
+ if ((ept_qual & EPT_VIOLATION_GLA_VALID) == 0 ||
+ (ept_qual & EPT_VIOLATION_XLAT_VALID) == 0) {
+ return (UNHANDLED);
+ }
+
+ /* Fetch, decode and emulate the faulting instruction */
+ if (vmm_fetch_instruction(vm, cpu, rip, inst_length, cr3, vie) != 0)
+ return (UNHANDLED);
+
+ if (vmm_decode_instruction(vm, cpu, gla, vie) != 0)
+ return (UNHANDLED);
+
+ /*
+ * Check if this is a local apic access
+ */
+ if (gpa < DEFAULT_APIC_BASE || gpa >= DEFAULT_APIC_BASE + PAGE_SIZE)
+ return (UNHANDLED);
+
+ error = vmm_emulate_instruction(vm, cpu, gpa, vie,
+ lapic_mmio_read, lapic_mmio_write, 0);
+
+ return (error ? UNHANDLED : HANDLED);
+}
+
+static int
+vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
+{
+ int error, handled;
+ struct vmcs *vmcs;
+ struct vmxctx *vmxctx;
+ uint32_t eax, ecx, edx;
+ uint64_t qual, gla, gpa, cr3, intr_info;
+
+ handled = 0;
+ vmcs = &vmx->vmcs[vcpu];
+ vmxctx = &vmx->ctx[vcpu];
+ qual = vmexit->u.vmx.exit_qualification;
+ vmexit->exitcode = VM_EXITCODE_BOGUS;
+
+ switch (vmexit->u.vmx.exit_reason) {
+ case EXIT_REASON_CR_ACCESS:
+ handled = vmx_emulate_cr_access(vmx, vcpu, qual);
+ break;
+ case EXIT_REASON_RDMSR:
+ ecx = vmxctx->guest_rcx;
+ error = emulate_rdmsr(vmx->vm, vcpu, ecx);
+ if (error) {
+ vmexit->exitcode = VM_EXITCODE_RDMSR;
+ vmexit->u.msr.code = ecx;
+ } else
+ handled = 1;
+ break;
+ case EXIT_REASON_WRMSR:
+ eax = vmxctx->guest_rax;
+ ecx = vmxctx->guest_rcx;
+ edx = vmxctx->guest_rdx;
+ error = emulate_wrmsr(vmx->vm, vcpu, ecx,
+ (uint64_t)edx << 32 | eax);
+ if (error) {
+ vmexit->exitcode = VM_EXITCODE_WRMSR;
+ vmexit->u.msr.code = ecx;
+ vmexit->u.msr.wval = (uint64_t)edx << 32 | eax;
+ } else
+ handled = 1;
+ break;
+ case EXIT_REASON_HLT:
+ vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT, 1);
+ /*
+ * If there is an event waiting to be injected then there is
+ * no need to 'hlt'.
+ */
+ error = vmread(VMCS_ENTRY_INTR_INFO, &intr_info);
+ if (error)
+ panic("vmx_exit_process: vmread(intrinfo) %d", error);
+
+ if (intr_info & VMCS_INTERRUPTION_INFO_VALID) {
+ handled = 1;
+ vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT_IGNORED, 1);
+ } else
+ vmexit->exitcode = VM_EXITCODE_HLT;
+ break;
+ case EXIT_REASON_MTF:
+ vmexit->exitcode = VM_EXITCODE_MTRAP;
+ break;
+ case EXIT_REASON_PAUSE:
+ vmexit->exitcode = VM_EXITCODE_PAUSE;
+ break;
+ case EXIT_REASON_INTR_WINDOW:
+ vmx_clear_int_window_exiting(vmx, vcpu);
+ VMM_CTR0(vmx->vm, vcpu, "Disabling interrupt window exiting");
+ /* FALLTHRU */
+ case EXIT_REASON_EXT_INTR:
+ /*
+ * External interrupts serve only to cause VM exits and allow
+ * the host interrupt handler to run.
+ *
+ * If this external interrupt triggers a virtual interrupt
+ * to a VM, then that state will be recorded by the
+ * host interrupt handler in the VM's softc. We will inject
+ * this virtual interrupt during the subsequent VM enter.
+ */
+
+ /*
+ * This is special. We want to treat this as an 'handled'
+ * VM-exit but not increment the instruction pointer.
+ */
+ vmm_stat_incr(vmx->vm, vcpu, VMEXIT_EXTINT, 1);
+ return (1);
+ case EXIT_REASON_NMI_WINDOW:
+ /* Exit to allow the pending virtual NMI to be injected */
+ vmx_clear_nmi_window_exiting(vmx, vcpu);
+ VMM_CTR0(vmx->vm, vcpu, "Disabling NMI window exiting");
+ return (1);
+ case EXIT_REASON_INOUT:
+ vmexit->exitcode = VM_EXITCODE_INOUT;
+ vmexit->u.inout.bytes = (qual & 0x7) + 1;
+ vmexit->u.inout.in = (qual & 0x8) ? 1 : 0;
+ vmexit->u.inout.string = (qual & 0x10) ? 1 : 0;
+ vmexit->u.inout.rep = (qual & 0x20) ? 1 : 0;
+ vmexit->u.inout.port = (uint16_t)(qual >> 16);
+ vmexit->u.inout.eax = (uint32_t)(vmxctx->guest_rax);
+ break;
+ case EXIT_REASON_CPUID:
+ handled = vmx_handle_cpuid(vmx->vm, vcpu, vmxctx);
+ break;
+ case EXIT_REASON_EPT_FAULT:
+ gla = vmcs_gla();
+ gpa = vmcs_gpa();
+ cr3 = vmcs_guest_cr3();
+ handled = vmx_ept_fault(vmx->vm, vcpu, gla, gpa,
+ vmexit->rip, vmexit->inst_length,
+ cr3, qual, &vmexit->u.paging.vie);
+ if (!handled) {
+ vmexit->exitcode = VM_EXITCODE_PAGING;
+ vmexit->u.paging.gpa = gpa;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (handled) {
+ /*
+ * It is possible that control is returned to userland
+ * even though we were able to handle the VM exit in the
+ * kernel.
+ *
+ * In such a case we want to make sure that the userland
+ * restarts guest execution at the instruction *after*
+ * 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;
+
+ /*
+ * Special case for spinning up an AP - exit to userspace to
+ * give the controlling process a chance to intercept and
+ * spin up a thread for the AP.
+ */
+ if (vmexit->exitcode == VM_EXITCODE_SPINUP_AP)
+ handled = 0;
+ } else {
+ if (vmexit->exitcode == VM_EXITCODE_BOGUS) {
+ /*
+ * If this VM exit was not claimed by anybody then
+ * treat it as a generic VMX exit.
+ */
+ vmexit->exitcode = VM_EXITCODE_VMX;
+ vmexit->u.vmx.error = 0;
+ } else {
+ /*
+ * The exitcode and collateral have been populated.
+ * The VM exit will be processed further in userland.
+ */
+ }
+ }
+ return (handled);
+}
+
+static int
+vmx_run(void *arg, int vcpu, register_t rip)
+{
+ int error, vie, rc, handled, astpending;
+ uint32_t exit_reason;
+ struct vmx *vmx;
+ struct vmxctx *vmxctx;
+ struct vmcs *vmcs;
+ struct vm_exit *vmexit;
+
+ vmx = arg;
+ vmcs = &vmx->vmcs[vcpu];
+ vmxctx = &vmx->ctx[vcpu];
+ vmxctx->launched = 0;
+
+ astpending = 0;
+ vmexit = vm_exitinfo(vmx->vm, vcpu);
+
+ /*
+ * XXX Can we avoid doing this every time we do a vm run?
+ */
+ VMPTRLD(vmcs);
+
+ /*
+ * XXX
+ * We do this every time because we may setup the virtual machine
+ * from a different process than the one that actually runs it.
+ *
+ * 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);
+
+ do {
+ lapic_timer_tick(vmx->vm, vcpu);
+ vmx_inject_interrupts(vmx, vcpu);
+ vmx_run_trace(vmx, vcpu);
+ rc = vmx_setjmp(vmxctx);
+#ifdef SETJMP_TRACE
+ vmx_setjmp_trace(vmx, vcpu, vmxctx, rc);
+#endif
+ switch (rc) {
+ case VMX_RETURN_DIRECT:
+ if (vmxctx->launched == 0) {
+ vmxctx->launched = 1;
+ vmx_launch(vmxctx);
+ } else
+ vmx_resume(vmxctx);
+ panic("vmx_launch/resume should not return");
+ break;
+ case VMX_RETURN_LONGJMP:
+ break; /* vm exit */
+ case VMX_RETURN_AST:
+ astpending = 1;
+ break;
+ case VMX_RETURN_VMRESUME:
+ vie = vmcs_instruction_error();
+ if (vmxctx->launch_error == VM_FAIL_INVALID ||
+ vie != VMRESUME_WITH_NON_LAUNCHED_VMCS) {
+ printf("vmresume error %d vmcs inst error %d\n",
+ vmxctx->launch_error, vie);
+ goto err_exit;
+ }
+ vmx_launch(vmxctx); /* try to launch the guest */
+ panic("vmx_launch should not return");
+ break;
+ case VMX_RETURN_VMLAUNCH:
+ vie = vmcs_instruction_error();
+#if 1
+ printf("vmlaunch error %d vmcs inst error %d\n",
+ vmxctx->launch_error, vie);
+#endif
+ goto err_exit;
+ default:
+ panic("vmx_setjmp returned %d", rc);
+ }
+
+ /* enable interrupts */
+ enable_intr();
+
+ /* collect some basic information for VM exit processing */
+ vmexit->rip = rip = vmcs_guest_rip();
+ vmexit->inst_length = vmexit_instruction_length();
+ vmexit->u.vmx.exit_reason = exit_reason = vmcs_exit_reason();
+ vmexit->u.vmx.exit_qualification = vmcs_exit_qualification();
+
+ if (astpending) {
+ handled = 1;
+ vmexit->inst_length = 0;
+ vmexit->exitcode = VM_EXITCODE_BOGUS;
+ vmx_astpending_trace(vmx, vcpu, rip);
+ break;
+ }
+
+ handled = vmx_exit_process(vmx, vcpu, vmexit);
+ vmx_exit_trace(vmx, vcpu, rip, exit_reason, handled);
+
+ } while (handled);
+
+ /*
+ * If a VM exit has been handled then the exitcode must be BOGUS
+ * If a VM exit is not handled then the exitcode must not be BOGUS
+ */
+ if ((handled && vmexit->exitcode != VM_EXITCODE_BOGUS) ||
+ (!handled && vmexit->exitcode == VM_EXITCODE_BOGUS)) {
+ panic("Mismatch between handled (%d) and exitcode (%d)",
+ handled, vmexit->exitcode);
+ }
+
+ VMM_CTR1(vmx->vm, vcpu, "goto userland: exitcode %d",vmexit->exitcode);
+
+ /*
+ * XXX
+ * We need to do this to ensure that any VMCS state cached by the
+ * processor is flushed to memory. We need to do this in case the
+ * VM moves to a different cpu the next time it runs.
+ *
+ * Can we avoid doing this?
+ */
+ VMCLEAR(vmcs);
+ return (0);
+
+err_exit:
+ vmexit->exitcode = VM_EXITCODE_VMX;
+ vmexit->u.vmx.exit_reason = (uint32_t)-1;
+ vmexit->u.vmx.exit_qualification = (uint32_t)-1;
+ vmexit->u.vmx.error = vie;
+ VMCLEAR(vmcs);
+ return (ENOEXEC);
+}
+
+static void
+vmx_vmcleanup(void *arg)
+{
+ int error;
+ struct vmx *vmx = arg;
+
+ /*
+ * XXXSMP we also need to clear the VMCS active on the other vcpus.
+ */
+ error = vmclear(&vmx->vmcs[0]);
+ if (error != 0)
+ panic("vmx_vmcleanup: vmclear error %d on vcpu 0", error);
+
+ ept_vmcleanup(vmx);
+ free(vmx, M_VMX);
+
+ return;
+}
+
+static register_t *
+vmxctx_regptr(struct vmxctx *vmxctx, int reg)
+{
+
+ switch (reg) {
+ case VM_REG_GUEST_RAX:
+ return (&vmxctx->guest_rax);
+ case VM_REG_GUEST_RBX:
+ return (&vmxctx->guest_rbx);
+ case VM_REG_GUEST_RCX:
+ return (&vmxctx->guest_rcx);
+ case VM_REG_GUEST_RDX:
+ return (&vmxctx->guest_rdx);
+ case VM_REG_GUEST_RSI:
+ return (&vmxctx->guest_rsi);
+ case VM_REG_GUEST_RDI:
+ return (&vmxctx->guest_rdi);
+ case VM_REG_GUEST_RBP:
+ return (&vmxctx->guest_rbp);
+ case VM_REG_GUEST_R8:
+ return (&vmxctx->guest_r8);
+ case VM_REG_GUEST_R9:
+ return (&vmxctx->guest_r9);
+ case VM_REG_GUEST_R10:
+ return (&vmxctx->guest_r10);
+ case VM_REG_GUEST_R11:
+ return (&vmxctx->guest_r11);
+ case VM_REG_GUEST_R12:
+ return (&vmxctx->guest_r12);
+ case VM_REG_GUEST_R13:
+ return (&vmxctx->guest_r13);
+ case VM_REG_GUEST_R14:
+ return (&vmxctx->guest_r14);
+ case VM_REG_GUEST_R15:
+ return (&vmxctx->guest_r15);
+ default:
+ break;
+ }
+ return (NULL);
+}
+
+static int
+vmxctx_getreg(struct vmxctx *vmxctx, int reg, uint64_t *retval)
+{
+ register_t *regp;
+
+ if ((regp = vmxctx_regptr(vmxctx, reg)) != NULL) {
+ *retval = *regp;
+ return (0);
+ } else
+ return (EINVAL);
+}
+
+static int
+vmxctx_setreg(struct vmxctx *vmxctx, int reg, uint64_t val)
+{
+ register_t *regp;
+
+ if ((regp = vmxctx_regptr(vmxctx, reg)) != NULL) {
+ *regp = val;
+ return (0);
+ } else
+ return (EINVAL);
+}
+
+static int
+vmx_getreg(void *arg, int vcpu, int reg, uint64_t *retval)
+{
+ struct vmx *vmx = arg;
+
+ if (vmxctx_getreg(&vmx->ctx[vcpu], reg, retval) == 0)
+ return (0);
+
+ /*
+ * If the vcpu is running then don't mess with the VMCS.
+ *
+ * vmcs_getreg will VMCLEAR the vmcs when it is done which will cause
+ * the subsequent vmlaunch/vmresume to fail.
+ */
+ if (vcpu_is_running(vmx->vm, vcpu))
+ panic("vmx_getreg: %s%d is running", vm_name(vmx->vm), vcpu);
+
+ return (vmcs_getreg(&vmx->vmcs[vcpu], reg, retval));
+}
+
+static int
+vmx_setreg(void *arg, int vcpu, int reg, uint64_t val)
+{
+ int error;
+ uint64_t ctls;
+ struct vmx *vmx = arg;
+
+ /*
+ * XXX Allow caller to set contents of the guest registers saved in
+ * the 'vmxctx' even though the vcpu might be running. We need this
+ * specifically to support the rdmsr emulation that will set the
+ * %eax and %edx registers during vm exit processing.
+ */
+ if (vmxctx_setreg(&vmx->ctx[vcpu], reg, val) == 0)
+ return (0);
+
+ /*
+ * If the vcpu is running then don't mess with the VMCS.
+ *
+ * vmcs_setreg will VMCLEAR the vmcs when it is done which will cause
+ * the subsequent vmlaunch/vmresume to fail.
+ */
+ if (vcpu_is_running(vmx->vm, vcpu))
+ panic("vmx_setreg: %s%d is running", vm_name(vmx->vm), vcpu);
+
+ error = vmcs_setreg(&vmx->vmcs[vcpu], reg, val);
+
+ if (error == 0) {
+ /*
+ * If the "load EFER" VM-entry control is 1 then the
+ * value of EFER.LMA must be identical to "IA-32e mode guest"
+ * bit in the VM-entry control.
+ */
+ if ((entry_ctls & VM_ENTRY_LOAD_EFER) != 0 &&
+ (reg == VM_REG_GUEST_EFER)) {
+ vmcs_getreg(&vmx->vmcs[vcpu],
+ VMCS_IDENT(VMCS_ENTRY_CTLS), &ctls);
+ if (val & EFER_LMA)
+ ctls |= VM_ENTRY_GUEST_LMA;
+ else
+ ctls &= ~VM_ENTRY_GUEST_LMA;
+ vmcs_setreg(&vmx->vmcs[vcpu],
+ VMCS_IDENT(VMCS_ENTRY_CTLS), ctls);
+ }
+ }
+
+ return (error);
+}
+
+static int
+vmx_getdesc(void *arg, int vcpu, int reg, struct seg_desc *desc)
+{
+ struct vmx *vmx = arg;
+
+ return (vmcs_getdesc(&vmx->vmcs[vcpu], reg, desc));
+}
+
+static int
+vmx_setdesc(void *arg, int vcpu, int reg, struct seg_desc *desc)
+{
+ struct vmx *vmx = arg;
+
+ return (vmcs_setdesc(&vmx->vmcs[vcpu], reg, desc));
+}
+
+static int
+vmx_inject(void *arg, int vcpu, int type, int vector, uint32_t code,
+ int code_valid)
+{
+ int error;
+ uint64_t info;
+ struct vmx *vmx = arg;
+ struct vmcs *vmcs = &vmx->vmcs[vcpu];
+
+ static uint32_t type_map[VM_EVENT_MAX] = {
+ 0x1, /* VM_EVENT_NONE */
+ 0x0, /* VM_HW_INTR */
+ 0x2, /* VM_NMI */
+ 0x3, /* VM_HW_EXCEPTION */
+ 0x4, /* VM_SW_INTR */
+ 0x5, /* VM_PRIV_SW_EXCEPTION */
+ 0x6, /* VM_SW_EXCEPTION */
+ };
+
+ /*
+ * If there is already an exception pending to be delivered to the
+ * vcpu then just return.
+ */
+ error = vmcs_getreg(vmcs, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), &info);
+ if (error)
+ return (error);
+
+ if (info & VMCS_INTERRUPTION_INFO_VALID)
+ return (EAGAIN);
+
+ info = vector | (type_map[type] << 8) | (code_valid ? 1 << 11 : 0);
+ info |= VMCS_INTERRUPTION_INFO_VALID;
+ error = vmcs_setreg(vmcs, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), info);
+ if (error != 0)
+ return (error);
+
+ if (code_valid) {
+ error = vmcs_setreg(vmcs,
+ VMCS_IDENT(VMCS_ENTRY_EXCEPTION_ERROR),
+ code);
+ }
+ return (error);
+}
+
+static int
+vmx_getcap(void *arg, int vcpu, int type, int *retval)
+{
+ struct vmx *vmx = arg;
+ int vcap;
+ int ret;
+
+ ret = ENOENT;
+
+ vcap = vmx->cap[vcpu].set;
+
+ switch (type) {
+ case VM_CAP_HALT_EXIT:
+ if (cap_halt_exit)
+ ret = 0;
+ break;
+ case VM_CAP_PAUSE_EXIT:
+ if (cap_pause_exit)
+ ret = 0;
+ break;
+ case VM_CAP_MTRAP_EXIT:
+ if (cap_monitor_trap)
+ ret = 0;
+ break;
+ case VM_CAP_UNRESTRICTED_GUEST:
+ if (cap_unrestricted_guest)
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (ret == 0)
+ *retval = (vcap & (1 << type)) ? 1 : 0;
+
+ return (ret);
+}
+
+static int
+vmx_setcap(void *arg, int vcpu, int type, int val)
+{
+ struct vmx *vmx = arg;
+ struct vmcs *vmcs = &vmx->vmcs[vcpu];
+ uint32_t baseval;
+ uint32_t *pptr;
+ int error;
+ int flag;
+ int reg;
+ int retval;
+
+ retval = ENOENT;
+ pptr = NULL;
+
+ switch (type) {
+ case VM_CAP_HALT_EXIT:
+ if (cap_halt_exit) {
+ retval = 0;
+ pptr = &vmx->cap[vcpu].proc_ctls;
+ baseval = *pptr;
+ flag = PROCBASED_HLT_EXITING;
+ reg = VMCS_PRI_PROC_BASED_CTLS;
+ }
+ break;
+ case VM_CAP_MTRAP_EXIT:
+ if (cap_monitor_trap) {
+ retval = 0;
+ pptr = &vmx->cap[vcpu].proc_ctls;
+ baseval = *pptr;
+ flag = PROCBASED_MTF;
+ reg = VMCS_PRI_PROC_BASED_CTLS;
+ }
+ break;
+ case VM_CAP_PAUSE_EXIT:
+ if (cap_pause_exit) {
+ retval = 0;
+ pptr = &vmx->cap[vcpu].proc_ctls;
+ baseval = *pptr;
+ flag = PROCBASED_PAUSE_EXITING;
+ reg = VMCS_PRI_PROC_BASED_CTLS;
+ }
+ break;
+ case VM_CAP_UNRESTRICTED_GUEST:
+ if (cap_unrestricted_guest) {
+ retval = 0;
+ baseval = procbased_ctls2;
+ flag = PROCBASED2_UNRESTRICTED_GUEST;
+ reg = VMCS_SEC_PROC_BASED_CTLS;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (retval == 0) {
+ if (val) {
+ baseval |= flag;
+ } else {
+ baseval &= ~flag;
+ }
+ VMPTRLD(vmcs);
+ error = vmwrite(reg, baseval);
+ VMCLEAR(vmcs);
+
+ if (error) {
+ retval = error;
+ } else {
+ /*
+ * Update optional stored flags, and record
+ * setting
+ */
+ if (pptr != NULL) {
+ *pptr = baseval;
+ }
+
+ if (val) {
+ vmx->cap[vcpu].set |= (1 << type);
+ } else {
+ vmx->cap[vcpu].set &= ~(1 << type);
+ }
+ }
+ }
+
+ return (retval);
+}
+
+struct vmm_ops vmm_ops_intel = {
+ vmx_init,
+ vmx_cleanup,
+ vmx_vminit,
+ vmx_run,
+ vmx_vmcleanup,
+ ept_vmmmap_set,
+ ept_vmmmap_get,
+ vmx_getreg,
+ vmx_setreg,
+ vmx_getdesc,
+ vmx_setdesc,
+ vmx_inject,
+ vmx_getcap,
+ vmx_setcap
+};
diff --git a/sys/amd64/vmm/intel/vmx.h b/sys/amd64/vmm/intel/vmx.h
new file mode 100644
index 0000000..c7cd567
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx.h
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMX_H_
+#define _VMX_H_
+
+#include "vmcs.h"
+
+#define GUEST_MSR_MAX_ENTRIES 64 /* arbitrary */
+
+struct vmxctx {
+ register_t tmpstk[32]; /* vmx_return() stack */
+ register_t tmpstktop;
+
+ register_t guest_rdi; /* Guest state */
+ register_t guest_rsi;
+ register_t guest_rdx;
+ register_t guest_rcx;
+ register_t guest_r8;
+ register_t guest_r9;
+ register_t guest_rax;
+ register_t guest_rbx;
+ register_t guest_rbp;
+ register_t guest_r10;
+ register_t guest_r11;
+ register_t guest_r12;
+ register_t guest_r13;
+ register_t guest_r14;
+ register_t guest_r15;
+ register_t guest_cr2;
+
+ register_t host_r15; /* Host state */
+ register_t host_r14;
+ register_t host_r13;
+ register_t host_r12;
+ register_t host_rbp;
+ register_t host_rsp;
+ register_t host_rbx;
+ register_t host_rip;
+ /*
+ * XXX todo debug registers and fpu state
+ */
+
+ int launched; /* vmcs launch state */
+ int launch_error;
+};
+
+struct vmxcap {
+ int set;
+ uint32_t proc_ctls;
+};
+
+struct vmxstate {
+ int lastcpu; /* host cpu that this 'vcpu' last ran on */
+ uint16_t vpid;
+};
+
+/* virtual machine softc */
+struct vmx {
+ pml4_entry_t pml4ept[NPML4EPG];
+ struct vmcs vmcs[VM_MAXCPU]; /* one vmcs per virtual cpu */
+ char msr_bitmap[PAGE_SIZE];
+ struct msr_entry guest_msrs[VM_MAXCPU][GUEST_MSR_MAX_ENTRIES];
+ struct vmxctx ctx[VM_MAXCPU];
+ struct vmxcap cap[VM_MAXCPU];
+ struct vmxstate state[VM_MAXCPU];
+ struct vm *vm;
+};
+CTASSERT((offsetof(struct vmx, pml4ept) & PAGE_MASK) == 0);
+CTASSERT((offsetof(struct vmx, vmcs) & PAGE_MASK) == 0);
+CTASSERT((offsetof(struct vmx, msr_bitmap) & PAGE_MASK) == 0);
+CTASSERT((offsetof(struct vmx, guest_msrs) & 15) == 0);
+
+#define VMX_RETURN_DIRECT 0
+#define VMX_RETURN_LONGJMP 1
+#define VMX_RETURN_VMRESUME 2
+#define VMX_RETURN_VMLAUNCH 3
+#define VMX_RETURN_AST 4
+/*
+ * vmx_setjmp() returns:
+ * - 0 when it returns directly
+ * - 1 when it returns from vmx_longjmp
+ * - 2 when it returns from vmx_resume (which would only be in the error case)
+ * - 3 when it returns from vmx_launch (which would only be in the error case)
+ * - 4 when it returns from vmx_resume or vmx_launch because of AST pending
+ */
+int vmx_setjmp(struct vmxctx *ctx);
+void vmx_longjmp(void); /* returns via vmx_setjmp */
+void vmx_launch(struct vmxctx *ctx) __dead2; /* may return via vmx_setjmp */
+void vmx_resume(struct vmxctx *ctx) __dead2; /* may return via vmx_setjmp */
+
+u_long vmx_fix_cr0(u_long cr0);
+u_long vmx_fix_cr4(u_long cr4);
+
+#endif
diff --git a/sys/amd64/vmm/intel/vmx_controls.h b/sys/amd64/vmm/intel/vmx_controls.h
new file mode 100644
index 0000000..31f29f8
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_controls.h
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMX_CONTROLS_H_
+#define _VMX_CONTROLS_H_
+
+/* Pin-Based VM-Execution Controls */
+#define PINBASED_EXTINT_EXITING (1 << 0)
+#define PINBASED_NMI_EXITING (1 << 3)
+#define PINBASED_VIRTUAL_NMI (1 << 5)
+#define PINBASED_PREMPTION_TIMER (1 << 6)
+
+/* Primary Processor-Based VM-Execution Controls */
+#define PROCBASED_INT_WINDOW_EXITING (1 << 2)
+#define PROCBASED_TSC_OFFSET (1 << 3)
+#define PROCBASED_HLT_EXITING (1 << 7)
+#define PROCBASED_INVLPG_EXITING (1 << 9)
+#define PROCBASED_MWAIT_EXITING (1 << 10)
+#define PROCBASED_RDPMC_EXITING (1 << 11)
+#define PROCBASED_RDTSC_EXITING (1 << 12)
+#define PROCBASED_CR3_LOAD_EXITING (1 << 15)
+#define PROCBASED_CR3_STORE_EXITING (1 << 16)
+#define PROCBASED_CR8_LOAD_EXITING (1 << 19)
+#define PROCBASED_CR8_STORE_EXITING (1 << 20)
+#define PROCBASED_USE_TPR_SHADOW (1 << 21)
+#define PROCBASED_NMI_WINDOW_EXITING (1 << 22)
+#define PROCBASED_MOV_DR_EXITING (1 << 23)
+#define PROCBASED_IO_EXITING (1 << 24)
+#define PROCBASED_IO_BITMAPS (1 << 25)
+#define PROCBASED_MTF (1 << 27)
+#define PROCBASED_MSR_BITMAPS (1 << 28)
+#define PROCBASED_MONITOR_EXITING (1 << 29)
+#define PROCBASED_PAUSE_EXITING (1 << 30)
+#define PROCBASED_SECONDARY_CONTROLS (1 << 31)
+
+/* Secondary Processor-Based VM-Execution Controls */
+#define PROCBASED2_VIRTUALIZE_APIC (1 << 0)
+#define PROCBASED2_ENABLE_EPT (1 << 1)
+#define PROCBASED2_DESC_TABLE_EXITING (1 << 2)
+#define PROCBASED2_ENABLE_RDTSCP (1 << 3)
+#define PROCBASED2_VIRTUALIZE_X2APIC (1 << 4)
+#define PROCBASED2_ENABLE_VPID (1 << 5)
+#define PROCBASED2_WBINVD_EXITING (1 << 6)
+#define PROCBASED2_UNRESTRICTED_GUEST (1 << 7)
+#define PROCBASED2_PAUSE_LOOP_EXITING (1 << 10)
+
+/* VM Exit Controls */
+#define VM_EXIT_SAVE_DEBUG_CONTROLS (1 << 2)
+#define VM_EXIT_HOST_LMA (1 << 9)
+#define VM_EXIT_LOAD_PERF_GLOBAL_CTRL (1 << 12)
+#define VM_EXIT_ACKNOWLEDGE_INTERRUPT (1 << 15)
+#define VM_EXIT_SAVE_PAT (1 << 18)
+#define VM_EXIT_LOAD_PAT (1 << 19)
+#define VM_EXIT_SAVE_EFER (1 << 20)
+#define VM_EXIT_LOAD_EFER (1 << 21)
+#define VM_EXIT_SAVE_PREEMPTION_TIMER (1 << 22)
+
+/* VM Entry Controls */
+#define VM_ENTRY_LOAD_DEBUG_CONTROLS (1 << 2)
+#define VM_ENTRY_GUEST_LMA (1 << 9)
+#define VM_ENTRY_INTO_SMM (1 << 10)
+#define VM_ENTRY_DEACTIVATE_DUAL_MONITOR (1 << 11)
+#define VM_ENTRY_LOAD_PERF_GLOBAL_CTRL (1 << 13)
+#define VM_ENTRY_LOAD_PAT (1 << 14)
+#define VM_ENTRY_LOAD_EFER (1 << 15)
+
+#endif
diff --git a/sys/amd64/vmm/intel/vmx_cpufunc.h b/sys/amd64/vmm/intel/vmx_cpufunc.h
new file mode 100644
index 0000000..2e66443
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_cpufunc.h
@@ -0,0 +1,218 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMX_CPUFUNC_H_
+#define _VMX_CPUFUNC_H_
+
+struct vmcs;
+
+/*
+ * Section 5.2 "Conventions" from Intel Architecture Manual 2B.
+ *
+ * error
+ * VMsucceed 0
+ * VMFailInvalid 1
+ * VMFailValid 2 see also VMCS VM-Instruction Error Field
+ */
+#define VM_SUCCESS 0
+#define VM_FAIL_INVALID 1
+#define VM_FAIL_VALID 2
+#define VMX_SET_ERROR_CODE \
+ " jnc 1f;" \
+ " mov $1, %[error];" /* CF: error = 1 */ \
+ " jmp 3f;" \
+ "1: jnz 2f;" \
+ " mov $2, %[error];" /* ZF: error = 2 */ \
+ " jmp 3f;" \
+ "2: mov $0, %[error];" \
+ "3:"
+
+/* returns 0 on success and non-zero on failure */
+static __inline int
+vmxon(char *region)
+{
+ int error;
+ uint64_t addr;
+
+ addr = vtophys(region);
+ __asm __volatile("vmxon %[addr];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [addr] "m" (*(uint64_t *)&addr)
+ : "memory");
+
+ return (error);
+}
+
+/* returns 0 on success and non-zero on failure */
+static __inline int
+vmclear(struct vmcs *vmcs)
+{
+ int error;
+ uint64_t addr;
+
+ addr = vtophys(vmcs);
+ __asm __volatile("vmclear %[addr];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [addr] "m" (*(uint64_t *)&addr)
+ : "memory");
+ return (error);
+}
+
+static __inline void
+vmxoff(void)
+{
+
+ __asm __volatile("vmxoff");
+}
+
+static __inline void
+vmptrst(uint64_t *addr)
+{
+
+ __asm __volatile("vmptrst %[addr]" :: [addr]"m" (*addr) : "memory");
+}
+
+static __inline int
+vmptrld(struct vmcs *vmcs)
+{
+ int error;
+ uint64_t addr;
+
+ addr = vtophys(vmcs);
+ __asm __volatile("vmptrld %[addr];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [addr] "m" (*(uint64_t *)&addr)
+ : "memory");
+ return (error);
+}
+
+static __inline int
+vmwrite(uint64_t reg, uint64_t val)
+{
+ int error;
+
+ __asm __volatile("vmwrite %[val], %[reg];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [val] "r" (val), [reg] "r" (reg)
+ : "memory");
+
+ return (error);
+}
+
+static __inline int
+vmread(uint64_t r, uint64_t *addr)
+{
+ int error;
+
+ __asm __volatile("vmread %[r], %[addr];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [r] "r" (r), [addr] "m" (*addr)
+ : "memory");
+
+ return (error);
+}
+
+static void __inline
+VMCLEAR(struct vmcs *vmcs)
+{
+ int err;
+
+ err = vmclear(vmcs);
+ if (err != 0)
+ panic("%s: vmclear(%p) error %d", __func__, vmcs, err);
+
+ critical_exit();
+}
+
+static void __inline
+VMPTRLD(struct vmcs *vmcs)
+{
+ int err;
+
+ critical_enter();
+
+ err = vmptrld(vmcs);
+ if (err != 0)
+ panic("%s: vmptrld(%p) error %d", __func__, vmcs, err);
+}
+
+#define INVVPID_TYPE_ADDRESS 0UL
+#define INVVPID_TYPE_SINGLE_CONTEXT 1UL
+#define INVVPID_TYPE_ALL_CONTEXTS 2UL
+
+struct invvpid_desc {
+ uint16_t vpid;
+ uint16_t _res1;
+ uint32_t _res2;
+ uint64_t linear_addr;
+};
+CTASSERT(sizeof(struct invvpid_desc) == 16);
+
+static void __inline
+invvpid(uint64_t type, struct invvpid_desc desc)
+{
+ int error;
+
+ __asm __volatile("invvpid %[desc], %[type];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [desc] "m" (desc), [type] "r" (type)
+ : "memory");
+
+ if (error)
+ panic("invvpid error %d", error);
+}
+
+#define INVEPT_TYPE_SINGLE_CONTEXT 1UL
+#define INVEPT_TYPE_ALL_CONTEXTS 2UL
+struct invept_desc {
+ uint64_t eptp;
+ uint64_t _res;
+};
+CTASSERT(sizeof(struct invept_desc) == 16);
+
+static void __inline
+invept(uint64_t type, struct invept_desc desc)
+{
+ int error;
+
+ __asm __volatile("invept %[desc], %[type];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [desc] "m" (desc), [type] "r" (type)
+ : "memory");
+
+ if (error)
+ panic("invept error %d", error);
+}
+#endif
diff --git a/sys/amd64/vmm/intel/vmx_genassym.c b/sys/amd64/vmm/intel/vmx_genassym.c
new file mode 100644
index 0000000..823a05d
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_genassym.c
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/assym.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h>
+
+#include <machine/vmm.h>
+#include "vmx.h"
+#include "vmx_cpufunc.h"
+
+ASSYM(VMXCTX_TMPSTKTOP, offsetof(struct vmxctx, tmpstktop));
+ASSYM(VMXCTX_GUEST_RDI, offsetof(struct vmxctx, guest_rdi));
+ASSYM(VMXCTX_GUEST_RSI, offsetof(struct vmxctx, guest_rsi));
+ASSYM(VMXCTX_GUEST_RDX, offsetof(struct vmxctx, guest_rdx));
+ASSYM(VMXCTX_GUEST_RCX, offsetof(struct vmxctx, guest_rcx));
+ASSYM(VMXCTX_GUEST_R8, offsetof(struct vmxctx, guest_r8));
+ASSYM(VMXCTX_GUEST_R9, offsetof(struct vmxctx, guest_r9));
+ASSYM(VMXCTX_GUEST_RAX, offsetof(struct vmxctx, guest_rax));
+ASSYM(VMXCTX_GUEST_RBX, offsetof(struct vmxctx, guest_rbx));
+ASSYM(VMXCTX_GUEST_RBP, offsetof(struct vmxctx, guest_rbp));
+ASSYM(VMXCTX_GUEST_R10, offsetof(struct vmxctx, guest_r10));
+ASSYM(VMXCTX_GUEST_R11, offsetof(struct vmxctx, guest_r11));
+ASSYM(VMXCTX_GUEST_R12, offsetof(struct vmxctx, guest_r12));
+ASSYM(VMXCTX_GUEST_R13, offsetof(struct vmxctx, guest_r13));
+ASSYM(VMXCTX_GUEST_R14, offsetof(struct vmxctx, guest_r14));
+ASSYM(VMXCTX_GUEST_R15, offsetof(struct vmxctx, guest_r15));
+ASSYM(VMXCTX_GUEST_CR2, offsetof(struct vmxctx, guest_cr2));
+
+ASSYM(VMXCTX_HOST_R15, offsetof(struct vmxctx, host_r15));
+ASSYM(VMXCTX_HOST_R14, offsetof(struct vmxctx, host_r14));
+ASSYM(VMXCTX_HOST_R13, offsetof(struct vmxctx, host_r13));
+ASSYM(VMXCTX_HOST_R12, offsetof(struct vmxctx, host_r12));
+ASSYM(VMXCTX_HOST_RBP, offsetof(struct vmxctx, host_rbp));
+ASSYM(VMXCTX_HOST_RSP, offsetof(struct vmxctx, host_rsp));
+ASSYM(VMXCTX_HOST_RBX, offsetof(struct vmxctx, host_rbx));
+ASSYM(VMXCTX_HOST_RIP, offsetof(struct vmxctx, host_rip));
+
+ASSYM(VMXCTX_LAUNCH_ERROR, offsetof(struct vmxctx, launch_error));
+
+ASSYM(VM_SUCCESS, VM_SUCCESS);
+ASSYM(VM_FAIL_INVALID, VM_FAIL_INVALID);
+ASSYM(VM_FAIL_VALID, VM_FAIL_VALID);
+
+ASSYM(VMX_RETURN_DIRECT, VMX_RETURN_DIRECT);
+ASSYM(VMX_RETURN_LONGJMP, VMX_RETURN_LONGJMP);
+ASSYM(VMX_RETURN_VMRESUME, VMX_RETURN_VMRESUME);
+ASSYM(VMX_RETURN_VMLAUNCH, VMX_RETURN_VMLAUNCH);
+ASSYM(VMX_RETURN_AST, VMX_RETURN_AST);
+
+ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
+ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
diff --git a/sys/amd64/vmm/intel/vmx_msr.c b/sys/amd64/vmm/intel/vmx_msr.c
new file mode 100644
index 0000000..2aba63c
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_msr.c
@@ -0,0 +1,172 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/cpufunc.h>
+
+#include "vmx_msr.h"
+
+static boolean_t
+vmx_ctl_allows_one_setting(uint64_t msr_val, int bitpos)
+{
+
+ if (msr_val & (1UL << (bitpos + 32)))
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+static boolean_t
+vmx_ctl_allows_zero_setting(uint64_t msr_val, int bitpos)
+{
+
+ if ((msr_val & (1UL << bitpos)) == 0)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+uint32_t
+vmx_revision(void)
+{
+
+ return (rdmsr(MSR_VMX_BASIC) & 0xffffffff);
+}
+
+/*
+ * Generate a bitmask to be used for the VMCS execution control fields.
+ *
+ * The caller specifies what bits should be set to one in 'ones_mask'
+ * and what bits should be set to zero in 'zeros_mask'. The don't-care
+ * bits are set to the default value. The default values are obtained
+ * based on "Algorithm 3" in Section 27.5.1 "Algorithms for Determining
+ * VMX Capabilities".
+ *
+ * Returns zero on success and non-zero on error.
+ */
+int
+vmx_set_ctlreg(int ctl_reg, int true_ctl_reg, uint32_t ones_mask,
+ uint32_t zeros_mask, uint32_t *retval)
+{
+ int i;
+ uint64_t val, trueval;
+ boolean_t true_ctls_avail, one_allowed, zero_allowed;
+
+ /* We cannot ask the same bit to be set to both '1' and '0' */
+ if ((ones_mask ^ zeros_mask) != (ones_mask | zeros_mask))
+ return (EINVAL);
+
+ if (rdmsr(MSR_VMX_BASIC) & (1UL << 55))
+ true_ctls_avail = TRUE;
+ else
+ true_ctls_avail = FALSE;
+
+ val = rdmsr(ctl_reg);
+ if (true_ctls_avail)
+ trueval = rdmsr(true_ctl_reg); /* step c */
+ else
+ trueval = val; /* step a */
+
+ for (i = 0; i < 32; i++) {
+ one_allowed = vmx_ctl_allows_one_setting(trueval, i);
+ zero_allowed = vmx_ctl_allows_zero_setting(trueval, i);
+
+ KASSERT(one_allowed || zero_allowed,
+ ("invalid zero/one setting for bit %d of ctl 0x%0x, "
+ "truectl 0x%0x\n", i, ctl_reg, true_ctl_reg));
+
+ if (zero_allowed && !one_allowed) { /* b(i),c(i) */
+ if (ones_mask & (1 << i))
+ return (EINVAL);
+ *retval &= ~(1 << i);
+ } else if (one_allowed && !zero_allowed) { /* b(i),c(i) */
+ if (zeros_mask & (1 << i))
+ return (EINVAL);
+ *retval |= 1 << i;
+ } else {
+ if (zeros_mask & (1 << i)) /* b(ii),c(ii) */
+ *retval &= ~(1 << i);
+ else if (ones_mask & (1 << i)) /* b(ii), c(ii) */
+ *retval |= 1 << i;
+ else if (!true_ctls_avail)
+ *retval &= ~(1 << i); /* b(iii) */
+ else if (vmx_ctl_allows_zero_setting(val, i))/* c(iii)*/
+ *retval &= ~(1 << i);
+ else if (vmx_ctl_allows_one_setting(val, i)) /* c(iv) */
+ *retval |= 1 << i;
+ else {
+ panic("vmx_set_ctlreg: unable to determine "
+ "correct value of ctl bit %d for msr "
+ "0x%0x and true msr 0x%0x", i, ctl_reg,
+ true_ctl_reg);
+ }
+ }
+ }
+
+ return (0);
+}
+
+void
+msr_bitmap_initialize(char *bitmap)
+{
+
+ memset(bitmap, 0xff, PAGE_SIZE);
+}
+
+int
+msr_bitmap_change_access(char *bitmap, u_int msr, int access)
+{
+ int byte, bit;
+
+ if (msr <= 0x00001FFF)
+ byte = msr / 8;
+ else if (msr >= 0xC0000000 && msr <= 0xC0001FFF)
+ byte = 1024 + (msr - 0xC0000000) / 8;
+ else
+ return (EINVAL);
+
+ bit = msr & 0x7;
+
+ if (access & MSR_BITMAP_ACCESS_READ)
+ bitmap[byte] &= ~(1 << bit);
+ else
+ bitmap[byte] |= 1 << bit;
+
+ byte += 2048;
+ if (access & MSR_BITMAP_ACCESS_WRITE)
+ bitmap[byte] &= ~(1 << bit);
+ else
+ bitmap[byte] |= 1 << bit;
+
+ return (0);
+}
diff --git a/sys/amd64/vmm/intel/vmx_msr.h b/sys/amd64/vmm/intel/vmx_msr.h
new file mode 100644
index 0000000..e6379a9
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_msr.h
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMX_MSR_H_
+#define _VMX_MSR_H_
+
+#define MSR_VMX_BASIC 0x480
+#define MSR_VMX_EPT_VPID_CAP 0x48C
+
+#define MSR_VMX_PROCBASED_CTLS 0x482
+#define MSR_VMX_TRUE_PROCBASED_CTLS 0x48E
+
+#define MSR_VMX_PINBASED_CTLS 0x481
+#define MSR_VMX_TRUE_PINBASED_CTLS 0x48D
+
+#define MSR_VMX_PROCBASED_CTLS2 0x48B
+
+#define MSR_VMX_EXIT_CTLS 0x483
+#define MSR_VMX_TRUE_EXIT_CTLS 0x48f
+
+#define MSR_VMX_ENTRY_CTLS 0x484
+#define MSR_VMX_TRUE_ENTRY_CTLS 0x490
+
+#define MSR_VMX_CR0_FIXED0 0x486
+#define MSR_VMX_CR0_FIXED1 0x487
+
+#define MSR_VMX_CR4_FIXED0 0x488
+#define MSR_VMX_CR4_FIXED1 0x489
+
+uint32_t vmx_revision(void);
+
+int vmx_set_ctlreg(int ctl_reg, int true_ctl_reg, uint32_t ones_mask,
+ uint32_t zeros_mask, uint32_t *retval);
+
+/*
+ * According to Section 21.10.4 "Software Access to Related Structures",
+ * changes to data structures pointed to by the VMCS must be made only when
+ * there is no logical processor with a current VMCS that points to the
+ * data structure.
+ *
+ * This pretty much limits us to configuring the MSR bitmap before VMCS
+ * initialization for SMP VMs. Unless of course we do it the hard way - which
+ * would involve some form of synchronization between the vcpus to vmclear
+ * all VMCSs' that point to the bitmap.
+ */
+#define MSR_BITMAP_ACCESS_NONE 0x0
+#define MSR_BITMAP_ACCESS_READ 0x1
+#define MSR_BITMAP_ACCESS_WRITE 0x2
+#define MSR_BITMAP_ACCESS_RW (MSR_BITMAP_ACCESS_READ|MSR_BITMAP_ACCESS_WRITE)
+void msr_bitmap_initialize(char *bitmap);
+int msr_bitmap_change_access(char *bitmap, u_int msr, int access);
+
+#endif
diff --git a/sys/amd64/vmm/intel/vmx_support.S b/sys/amd64/vmm/intel/vmx_support.S
new file mode 100644
index 0000000..4ba582a
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_support.S
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asmacros.h>
+
+#include "vmx_assym.s"
+
+/*
+ * Disable interrupts before updating %rsp in VMX_CHECK_AST or
+ * VMX_GUEST_RESTORE.
+ *
+ * The location that %rsp points to is a 'vmxctx' and not a
+ * real stack so we don't want an interrupt handler to trash it
+ */
+#define VMX_DISABLE_INTERRUPTS cli
+
+/*
+ * If the thread hosting the vcpu has an ast pending then take care of it
+ * by returning from vmx_setjmp() with a return value of VMX_RETURN_AST.
+ *
+ * Assumes that %rdi holds a pointer to the 'vmxctx' and that interrupts
+ * are disabled.
+ */
+#define VMX_CHECK_AST \
+ movq PCPU(CURTHREAD),%rax; \
+ testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax); \
+ je 9f; \
+ movq $VMX_RETURN_AST,%rsi; \
+ movq %rdi,%rsp; \
+ addq $VMXCTX_TMPSTKTOP,%rsp; \
+ callq vmx_return; \
+9:
+
+/*
+ * Assumes that %rdi holds a pointer to the 'vmxctx'.
+ *
+ * On "return" all registers are updated to reflect guest state. The two
+ * exceptions are %rip and %rsp. These registers are atomically switched
+ * by hardware from the guest area of the vmcs.
+ *
+ * We modify %rsp to point to the 'vmxctx' so we can use it to restore
+ * host context in case of an error with 'vmlaunch' or 'vmresume'.
+ */
+#define VMX_GUEST_RESTORE \
+ movq %rdi,%rsp; \
+ movq VMXCTX_GUEST_CR2(%rdi),%rsi; \
+ movq %rsi,%cr2; \
+ movq VMXCTX_GUEST_RSI(%rdi),%rsi; \
+ movq VMXCTX_GUEST_RDX(%rdi),%rdx; \
+ movq VMXCTX_GUEST_RCX(%rdi),%rcx; \
+ movq VMXCTX_GUEST_R8(%rdi),%r8; \
+ movq VMXCTX_GUEST_R9(%rdi),%r9; \
+ movq VMXCTX_GUEST_RAX(%rdi),%rax; \
+ movq VMXCTX_GUEST_RBX(%rdi),%rbx; \
+ movq VMXCTX_GUEST_RBP(%rdi),%rbp; \
+ movq VMXCTX_GUEST_R10(%rdi),%r10; \
+ movq VMXCTX_GUEST_R11(%rdi),%r11; \
+ movq VMXCTX_GUEST_R12(%rdi),%r12; \
+ movq VMXCTX_GUEST_R13(%rdi),%r13; \
+ movq VMXCTX_GUEST_R14(%rdi),%r14; \
+ movq VMXCTX_GUEST_R15(%rdi),%r15; \
+ movq VMXCTX_GUEST_RDI(%rdi),%rdi; /* restore rdi the last */
+
+#define VM_INSTRUCTION_ERROR(reg) \
+ jnc 1f; \
+ movl $VM_FAIL_INVALID,reg; /* CF is set */ \
+ jmp 3f; \
+1: jnz 2f; \
+ movl $VM_FAIL_VALID,reg; /* ZF is set */ \
+ jmp 3f; \
+2: movl $VM_SUCCESS,reg; \
+3: movl reg,VMXCTX_LAUNCH_ERROR(%rsp)
+
+ .text
+/*
+ * int vmx_setjmp(ctxp)
+ * %rdi = ctxp
+ *
+ * Return value is '0' when it returns directly from here.
+ * Return value is '1' when it returns after a vm exit through vmx_longjmp.
+ */
+ENTRY(vmx_setjmp)
+ movq (%rsp),%rax /* return address */
+ movq %r15,VMXCTX_HOST_R15(%rdi)
+ movq %r14,VMXCTX_HOST_R14(%rdi)
+ movq %r13,VMXCTX_HOST_R13(%rdi)
+ movq %r12,VMXCTX_HOST_R12(%rdi)
+ movq %rbp,VMXCTX_HOST_RBP(%rdi)
+ movq %rsp,VMXCTX_HOST_RSP(%rdi)
+ movq %rbx,VMXCTX_HOST_RBX(%rdi)
+ movq %rax,VMXCTX_HOST_RIP(%rdi)
+
+ /*
+ * XXX save host debug registers
+ */
+ movl $VMX_RETURN_DIRECT,%eax
+ ret
+END(vmx_setjmp)
+
+/*
+ * void vmx_return(struct vmxctx *ctxp, int retval)
+ * %rdi = ctxp
+ * %rsi = retval
+ * Return to vmm context through vmx_setjmp() with a value of 'retval'.
+ */
+ENTRY(vmx_return)
+ /* Restore host context. */
+ movq VMXCTX_HOST_R15(%rdi),%r15
+ movq VMXCTX_HOST_R14(%rdi),%r14
+ movq VMXCTX_HOST_R13(%rdi),%r13
+ movq VMXCTX_HOST_R12(%rdi),%r12
+ movq VMXCTX_HOST_RBP(%rdi),%rbp
+ movq VMXCTX_HOST_RSP(%rdi),%rsp
+ movq VMXCTX_HOST_RBX(%rdi),%rbx
+ movq VMXCTX_HOST_RIP(%rdi),%rax
+ movq %rax,(%rsp) /* return address */
+
+ /*
+ * XXX restore host debug registers
+ */
+ movl %esi,%eax
+ ret
+END(vmx_return)
+
+/*
+ * void vmx_longjmp(void)
+ * %rsp points to the struct vmxctx
+ */
+ENTRY(vmx_longjmp)
+ /*
+ * Save guest state that is not automatically saved in the vmcs.
+ */
+ movq %rdi,VMXCTX_GUEST_RDI(%rsp)
+ movq %rsi,VMXCTX_GUEST_RSI(%rsp)
+ movq %rdx,VMXCTX_GUEST_RDX(%rsp)
+ movq %rcx,VMXCTX_GUEST_RCX(%rsp)
+ movq %r8,VMXCTX_GUEST_R8(%rsp)
+ movq %r9,VMXCTX_GUEST_R9(%rsp)
+ movq %rax,VMXCTX_GUEST_RAX(%rsp)
+ movq %rbx,VMXCTX_GUEST_RBX(%rsp)
+ movq %rbp,VMXCTX_GUEST_RBP(%rsp)
+ movq %r10,VMXCTX_GUEST_R10(%rsp)
+ movq %r11,VMXCTX_GUEST_R11(%rsp)
+ movq %r12,VMXCTX_GUEST_R12(%rsp)
+ movq %r13,VMXCTX_GUEST_R13(%rsp)
+ movq %r14,VMXCTX_GUEST_R14(%rsp)
+ movq %r15,VMXCTX_GUEST_R15(%rsp)
+
+ movq %cr2,%rdi
+ movq %rdi,VMXCTX_GUEST_CR2(%rsp)
+
+ movq %rsp,%rdi
+ movq $VMX_RETURN_LONGJMP,%rsi
+
+ addq $VMXCTX_TMPSTKTOP,%rsp
+ callq vmx_return
+END(vmx_longjmp)
+
+/*
+ * void vmx_resume(struct vmxctx *ctxp)
+ * %rdi = ctxp
+ *
+ * Although the return type is a 'void' this function may return indirectly
+ * through vmx_setjmp() with a return value of 2.
+ */
+ENTRY(vmx_resume)
+ VMX_DISABLE_INTERRUPTS
+
+ VMX_CHECK_AST
+
+ /*
+ * Restore guest state that is not automatically loaded from the vmcs.
+ */
+ VMX_GUEST_RESTORE
+
+ vmresume
+
+ /*
+ * Capture the reason why vmresume failed.
+ */
+ VM_INSTRUCTION_ERROR(%eax)
+
+ /* Return via vmx_setjmp with return value of VMX_RETURN_VMRESUME */
+ movq %rsp,%rdi
+ movq $VMX_RETURN_VMRESUME,%rsi
+
+ addq $VMXCTX_TMPSTKTOP,%rsp
+ callq vmx_return
+END(vmx_resume)
+
+/*
+ * void vmx_launch(struct vmxctx *ctxp)
+ * %rdi = ctxp
+ *
+ * Although the return type is a 'void' this function may return indirectly
+ * through vmx_setjmp() with a return value of 3.
+ */
+ENTRY(vmx_launch)
+ VMX_DISABLE_INTERRUPTS
+
+ VMX_CHECK_AST
+
+ /*
+ * Restore guest state that is not automatically loaded from the vmcs.
+ */
+ VMX_GUEST_RESTORE
+
+ vmlaunch
+
+ /*
+ * Capture the reason why vmlaunch failed.
+ */
+ VM_INSTRUCTION_ERROR(%eax)
+
+ /* Return via vmx_setjmp with return value of VMX_RETURN_VMLAUNCH */
+ movq %rsp,%rdi
+ movq $VMX_RETURN_VMLAUNCH,%rsi
+
+ addq $VMXCTX_TMPSTKTOP,%rsp
+ callq vmx_return
+END(vmx_launch)
diff --git a/sys/amd64/vmm/intel/vtd.c b/sys/amd64/vmm/intel/vtd.c
new file mode 100644
index 0000000..ef0e9bc
--- /dev/null
+++ b/sys/amd64/vmm/intel/vtd.c
@@ -0,0 +1,677 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/pci/pcireg.h>
+
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/pci_cfgreg.h>
+
+#include "io/iommu.h"
+
+/*
+ * Documented in the "Intel Virtualization Technology for Directed I/O",
+ * Architecture Spec, September 2008.
+ */
+
+/* Section 10.4 "Register Descriptions" */
+struct vtdmap {
+ volatile uint32_t version;
+ volatile uint32_t res0;
+ volatile uint64_t cap;
+ volatile uint64_t ext_cap;
+ volatile uint32_t gcr;
+ volatile uint32_t gsr;
+ volatile uint64_t rta;
+ volatile uint64_t ccr;
+};
+
+#define VTD_CAP_SAGAW(cap) (((cap) >> 8) & 0x1F)
+#define VTD_CAP_ND(cap) ((cap) & 0x7)
+#define VTD_CAP_CM(cap) (((cap) >> 7) & 0x1)
+#define VTD_CAP_SPS(cap) (((cap) >> 34) & 0xF)
+#define VTD_CAP_RWBF(cap) (((cap) >> 4) & 0x1)
+
+#define VTD_ECAP_DI(ecap) (((ecap) >> 2) & 0x1)
+#define VTD_ECAP_COHERENCY(ecap) ((ecap) & 0x1)
+#define VTD_ECAP_IRO(ecap) (((ecap) >> 8) & 0x3FF)
+
+#define VTD_GCR_WBF (1 << 27)
+#define VTD_GCR_SRTP (1 << 30)
+#define VTD_GCR_TE (1 << 31)
+
+#define VTD_GSR_WBFS (1 << 27)
+#define VTD_GSR_RTPS (1 << 30)
+#define VTD_GSR_TES (1 << 31)
+
+#define VTD_CCR_ICC (1UL << 63) /* invalidate context cache */
+#define VTD_CCR_CIRG_GLOBAL (1UL << 61) /* global invalidation */
+
+#define VTD_IIR_IVT (1UL << 63) /* invalidation IOTLB */
+#define VTD_IIR_IIRG_GLOBAL (1ULL << 60) /* global IOTLB invalidation */
+#define VTD_IIR_IIRG_DOMAIN (2ULL << 60) /* domain IOTLB invalidation */
+#define VTD_IIR_IIRG_PAGE (3ULL << 60) /* page IOTLB invalidation */
+#define VTD_IIR_DRAIN_READS (1ULL << 49) /* drain pending DMA reads */
+#define VTD_IIR_DRAIN_WRITES (1ULL << 48) /* drain pending DMA writes */
+#define VTD_IIR_DOMAIN_P 32
+
+#define VTD_ROOT_PRESENT 0x1
+#define VTD_CTX_PRESENT 0x1
+#define VTD_CTX_TT_ALL (1UL << 2)
+
+#define VTD_PTE_RD (1UL << 0)
+#define VTD_PTE_WR (1UL << 1)
+#define VTD_PTE_SUPERPAGE (1UL << 7)
+#define VTD_PTE_ADDR_M (0x000FFFFFFFFFF000UL)
+
+struct domain {
+ uint64_t *ptp; /* first level page table page */
+ int pt_levels; /* number of page table levels */
+ int addrwidth; /* 'AW' field in context entry */
+ int spsmask; /* supported super page sizes */
+ u_int id; /* domain id */
+ vm_paddr_t maxaddr; /* highest address to be mapped */
+ SLIST_ENTRY(domain) next;
+};
+
+static SLIST_HEAD(, domain) domhead;
+
+#define DRHD_MAX_UNITS 8
+static int drhd_num;
+static struct vtdmap *vtdmaps[DRHD_MAX_UNITS];
+static int max_domains;
+typedef int (*drhd_ident_func_t)(void);
+
+static uint64_t root_table[PAGE_SIZE / sizeof(uint64_t)] __aligned(4096);
+static uint64_t ctx_tables[256][PAGE_SIZE / sizeof(uint64_t)] __aligned(4096);
+
+static MALLOC_DEFINE(M_VTD, "vtd", "vtd");
+
+/*
+ * Config space register definitions from the "Intel 5520 and 5500" datasheet.
+ */
+static int
+tylersburg_vtd_ident(void)
+{
+ int units, nlbus;
+ uint16_t did, vid;
+ uint32_t miscsts, vtbar;
+
+ const int bus = 0;
+ const int slot = 20;
+ const int func = 0;
+
+ units = 0;
+
+ vid = pci_cfgregread(bus, slot, func, PCIR_VENDOR, 2);
+ did = pci_cfgregread(bus, slot, func, PCIR_DEVICE, 2);
+ if (vid != 0x8086 || did != 0x342E)
+ goto done;
+
+ /*
+ * Check if this is a dual IOH configuration.
+ */
+ miscsts = pci_cfgregread(bus, slot, func, 0x9C, 4);
+ if (miscsts & (1 << 25))
+ nlbus = pci_cfgregread(bus, slot, func, 0x160, 1);
+ else
+ nlbus = -1;
+
+ vtbar = pci_cfgregread(bus, slot, func, 0x180, 4);
+ if (vtbar & 0x1) {
+ vtdmaps[units++] = (struct vtdmap *)
+ PHYS_TO_DMAP(vtbar & 0xffffe000);
+ } else if (bootverbose)
+ printf("VT-d unit in legacy IOH is disabled!\n");
+
+ if (nlbus != -1) {
+ vtbar = pci_cfgregread(nlbus, slot, func, 0x180, 4);
+ if (vtbar & 0x1) {
+ vtdmaps[units++] = (struct vtdmap *)
+ PHYS_TO_DMAP(vtbar & 0xffffe000);
+ } else if (bootverbose)
+ printf("VT-d unit in non-legacy IOH is disabled!\n");
+ }
+done:
+ return (units);
+}
+
+static drhd_ident_func_t drhd_ident_funcs[] = {
+ tylersburg_vtd_ident,
+ NULL
+};
+
+static int
+vtd_max_domains(struct vtdmap *vtdmap)
+{
+ int nd;
+
+ nd = VTD_CAP_ND(vtdmap->cap);
+
+ switch (nd) {
+ case 0:
+ return (16);
+ case 1:
+ return (64);
+ case 2:
+ return (256);
+ case 3:
+ return (1024);
+ case 4:
+ return (4 * 1024);
+ case 5:
+ return (16 * 1024);
+ case 6:
+ return (64 * 1024);
+ default:
+ panic("vtd_max_domains: invalid value of nd (0x%0x)", nd);
+ }
+}
+
+static u_int
+domain_id(void)
+{
+ u_int id;
+ struct domain *dom;
+
+ /* Skip domain id 0 - it is reserved when Caching Mode field is set */
+ for (id = 1; id < max_domains; id++) {
+ SLIST_FOREACH(dom, &domhead, next) {
+ if (dom->id == id)
+ break;
+ }
+ if (dom == NULL)
+ break; /* found it */
+ }
+
+ if (id >= max_domains)
+ panic("domain ids exhausted");
+
+ return (id);
+}
+
+static void
+vtd_wbflush(struct vtdmap *vtdmap)
+{
+
+ if (VTD_ECAP_COHERENCY(vtdmap->ext_cap) == 0)
+ pmap_invalidate_cache();
+
+ if (VTD_CAP_RWBF(vtdmap->cap)) {
+ vtdmap->gcr = VTD_GCR_WBF;
+ while ((vtdmap->gsr & VTD_GSR_WBFS) != 0)
+ ;
+ }
+}
+
+static void
+vtd_ctx_global_invalidate(struct vtdmap *vtdmap)
+{
+
+ vtdmap->ccr = VTD_CCR_ICC | VTD_CCR_CIRG_GLOBAL;
+ while ((vtdmap->ccr & VTD_CCR_ICC) != 0)
+ ;
+}
+
+static void
+vtd_iotlb_global_invalidate(struct vtdmap *vtdmap)
+{
+ int offset;
+ volatile uint64_t *iotlb_reg, val;
+
+ vtd_wbflush(vtdmap);
+
+ offset = VTD_ECAP_IRO(vtdmap->ext_cap) * 16;
+ iotlb_reg = (volatile uint64_t *)((caddr_t)vtdmap + offset + 8);
+
+ *iotlb_reg = VTD_IIR_IVT | VTD_IIR_IIRG_GLOBAL |
+ VTD_IIR_DRAIN_READS | VTD_IIR_DRAIN_WRITES;
+
+ while (1) {
+ val = *iotlb_reg;
+ if ((val & VTD_IIR_IVT) == 0)
+ break;
+ }
+}
+
+static void
+vtd_translation_enable(struct vtdmap *vtdmap)
+{
+
+ vtdmap->gcr = VTD_GCR_TE;
+ while ((vtdmap->gsr & VTD_GSR_TES) == 0)
+ ;
+}
+
+static void
+vtd_translation_disable(struct vtdmap *vtdmap)
+{
+
+ vtdmap->gcr = 0;
+ while ((vtdmap->gsr & VTD_GSR_TES) != 0)
+ ;
+}
+
+static int
+vtd_init(void)
+{
+ int i, units;
+ struct vtdmap *vtdmap;
+ vm_paddr_t ctx_paddr;
+
+ for (i = 0; drhd_ident_funcs[i] != NULL; i++) {
+ units = (*drhd_ident_funcs[i])();
+ if (units > 0)
+ break;
+ }
+
+ if (units <= 0)
+ return (ENXIO);
+
+ drhd_num = units;
+ vtdmap = vtdmaps[0];
+
+ if (VTD_CAP_CM(vtdmap->cap) != 0)
+ panic("vtd_init: invalid caching mode");
+
+ max_domains = vtd_max_domains(vtdmap);
+
+ /*
+ * Set up the root-table to point to the context-entry tables
+ */
+ for (i = 0; i < 256; i++) {
+ ctx_paddr = vtophys(ctx_tables[i]);
+ if (ctx_paddr & PAGE_MASK)
+ panic("ctx table (0x%0lx) not page aligned", ctx_paddr);
+
+ root_table[i * 2] = ctx_paddr | VTD_ROOT_PRESENT;
+ }
+
+ return (0);
+}
+
+static void
+vtd_cleanup(void)
+{
+}
+
+static void
+vtd_enable(void)
+{
+ int i;
+ struct vtdmap *vtdmap;
+
+ for (i = 0; i < drhd_num; i++) {
+ vtdmap = vtdmaps[i];
+ vtd_wbflush(vtdmap);
+
+ /* Update the root table address */
+ vtdmap->rta = vtophys(root_table);
+ vtdmap->gcr = VTD_GCR_SRTP;
+ while ((vtdmap->gsr & VTD_GSR_RTPS) == 0)
+ ;
+
+ vtd_ctx_global_invalidate(vtdmap);
+ vtd_iotlb_global_invalidate(vtdmap);
+
+ vtd_translation_enable(vtdmap);
+ }
+}
+
+static void
+vtd_disable(void)
+{
+ int i;
+ struct vtdmap *vtdmap;
+
+ for (i = 0; i < drhd_num; i++) {
+ vtdmap = vtdmaps[i];
+ vtd_translation_disable(vtdmap);
+ }
+}
+
+static void
+vtd_add_device(void *arg, int bus, int slot, int func)
+{
+ int idx;
+ uint64_t *ctxp;
+ struct domain *dom = arg;
+ vm_paddr_t pt_paddr;
+ struct vtdmap *vtdmap;
+
+ if (bus < 0 || bus > PCI_BUSMAX ||
+ slot < 0 || slot > PCI_SLOTMAX ||
+ func < 0 || func > PCI_FUNCMAX)
+ panic("vtd_add_device: invalid bsf %d/%d/%d", bus, slot, func);
+
+ vtdmap = vtdmaps[0];
+ ctxp = ctx_tables[bus];
+ pt_paddr = vtophys(dom->ptp);
+ idx = (slot << 3 | func) * 2;
+
+ if (ctxp[idx] & VTD_CTX_PRESENT) {
+ panic("vtd_add_device: device %d/%d/%d is already owned by "
+ "domain %d", bus, slot, func,
+ (uint16_t)(ctxp[idx + 1] >> 8));
+ }
+
+ /*
+ * Order is important. The 'present' bit is set only after all fields
+ * of the context pointer are initialized.
+ */
+ ctxp[idx + 1] = dom->addrwidth | (dom->id << 8);
+
+ if (VTD_ECAP_DI(vtdmap->ext_cap))
+ ctxp[idx] = VTD_CTX_TT_ALL;
+ else
+ ctxp[idx] = 0;
+
+ ctxp[idx] |= pt_paddr | VTD_CTX_PRESENT;
+
+ /*
+ * 'Not Present' entries are not cached in either the Context Cache
+ * or in the IOTLB, so there is no need to invalidate either of them.
+ */
+}
+
+static void
+vtd_remove_device(void *arg, int bus, int slot, int func)
+{
+ int i, idx;
+ uint64_t *ctxp;
+ struct vtdmap *vtdmap;
+
+ if (bus < 0 || bus > PCI_BUSMAX ||
+ slot < 0 || slot > PCI_SLOTMAX ||
+ func < 0 || func > PCI_FUNCMAX)
+ panic("vtd_add_device: invalid bsf %d/%d/%d", bus, slot, func);
+
+ ctxp = ctx_tables[bus];
+ idx = (slot << 3 | func) * 2;
+
+ /*
+ * Order is important. The 'present' bit is must be cleared first.
+ */
+ ctxp[idx] = 0;
+ ctxp[idx + 1] = 0;
+
+ /*
+ * Invalidate the Context Cache and the IOTLB.
+ *
+ * XXX use device-selective invalidation for Context Cache
+ * XXX use domain-selective invalidation for IOTLB
+ */
+ for (i = 0; i < drhd_num; i++) {
+ vtdmap = vtdmaps[i];
+ vtd_ctx_global_invalidate(vtdmap);
+ vtd_iotlb_global_invalidate(vtdmap);
+ }
+}
+
+#define CREATE_MAPPING 0
+#define REMOVE_MAPPING 1
+
+static uint64_t
+vtd_update_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len,
+ int remove)
+{
+ struct domain *dom;
+ int i, spshift, ptpshift, ptpindex, nlevels;
+ uint64_t spsize, *ptp;
+
+ dom = arg;
+ ptpindex = 0;
+ ptpshift = 0;
+
+ if (gpa & PAGE_MASK)
+ panic("vtd_create_mapping: unaligned gpa 0x%0lx", gpa);
+
+ if (hpa & PAGE_MASK)
+ panic("vtd_create_mapping: unaligned hpa 0x%0lx", hpa);
+
+ if (len & PAGE_MASK)
+ panic("vtd_create_mapping: unaligned len 0x%0lx", len);
+
+ /*
+ * Compute the size of the mapping that we can accomodate.
+ *
+ * This is based on three factors:
+ * - supported super page size
+ * - alignment of the region starting at 'gpa' and 'hpa'
+ * - length of the region 'len'
+ */
+ spshift = 48;
+ for (i = 3; i >= 0; i--) {
+ spsize = 1UL << spshift;
+ if ((dom->spsmask & (1 << i)) != 0 &&
+ (gpa & (spsize - 1)) == 0 &&
+ (hpa & (spsize - 1)) == 0 &&
+ (len >= spsize)) {
+ break;
+ }
+ spshift -= 9;
+ }
+
+ ptp = dom->ptp;
+ nlevels = dom->pt_levels;
+ while (--nlevels >= 0) {
+ ptpshift = 12 + nlevels * 9;
+ ptpindex = (gpa >> ptpshift) & 0x1FF;
+
+ /* We have reached the leaf mapping */
+ if (spshift >= ptpshift) {
+ break;
+ }
+
+ /*
+ * We are working on a non-leaf page table page.
+ *
+ * Create a downstream page table page if necessary and point
+ * to it from the current page table.
+ */
+ if (ptp[ptpindex] == 0) {
+ void *nlp = malloc(PAGE_SIZE, M_VTD, M_WAITOK | M_ZERO);
+ ptp[ptpindex] = vtophys(nlp)| VTD_PTE_RD | VTD_PTE_WR;
+ }
+
+ ptp = (uint64_t *)PHYS_TO_DMAP(ptp[ptpindex] & VTD_PTE_ADDR_M);
+ }
+
+ if ((gpa & ((1UL << ptpshift) - 1)) != 0)
+ panic("gpa 0x%lx and ptpshift %d mismatch", gpa, ptpshift);
+
+ /*
+ * Update the 'gpa' -> 'hpa' mapping
+ */
+ if (remove) {
+ ptp[ptpindex] = 0;
+ } else {
+ ptp[ptpindex] = hpa | VTD_PTE_RD | VTD_PTE_WR;
+
+ if (nlevels > 0)
+ ptp[ptpindex] |= VTD_PTE_SUPERPAGE;
+ }
+
+ return (1UL << ptpshift);
+}
+
+static uint64_t
+vtd_create_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len)
+{
+
+ return (vtd_update_mapping(arg, gpa, hpa, len, CREATE_MAPPING));
+}
+
+static uint64_t
+vtd_remove_mapping(void *arg, vm_paddr_t gpa, uint64_t len)
+{
+
+ return (vtd_update_mapping(arg, gpa, 0, len, REMOVE_MAPPING));
+}
+
+static void
+vtd_invalidate_tlb(void *dom)
+{
+ int i;
+ struct vtdmap *vtdmap;
+
+ /*
+ * Invalidate the IOTLB.
+ * XXX use domain-selective invalidation for IOTLB
+ */
+ for (i = 0; i < drhd_num; i++) {
+ vtdmap = vtdmaps[i];
+ vtd_iotlb_global_invalidate(vtdmap);
+ }
+}
+
+static void *
+vtd_create_domain(vm_paddr_t maxaddr)
+{
+ struct domain *dom;
+ vm_paddr_t addr;
+ int tmp, i, gaw, agaw, sagaw, res, pt_levels, addrwidth;
+ struct vtdmap *vtdmap;
+
+ if (drhd_num <= 0)
+ panic("vtd_create_domain: no dma remapping hardware available");
+
+ vtdmap = vtdmaps[0];
+
+ /*
+ * Calculate AGAW.
+ * Section 3.4.2 "Adjusted Guest Address Width", Architecture Spec.
+ */
+ addr = 0;
+ for (gaw = 0; addr < maxaddr; gaw++)
+ addr = 1ULL << gaw;
+
+ res = (gaw - 12) % 9;
+ if (res == 0)
+ agaw = gaw;
+ else
+ agaw = gaw + 9 - res;
+
+ if (agaw > 64)
+ agaw = 64;
+
+ /*
+ * Select the smallest Supported AGAW and the corresponding number
+ * of page table levels.
+ */
+ pt_levels = 2;
+ sagaw = 30;
+ addrwidth = 0;
+ tmp = VTD_CAP_SAGAW(vtdmap->cap);
+ for (i = 0; i < 5; i++) {
+ if ((tmp & (1 << i)) != 0 && sagaw >= agaw)
+ break;
+ pt_levels++;
+ addrwidth++;
+ sagaw += 9;
+ if (sagaw > 64)
+ sagaw = 64;
+ }
+
+ if (i >= 5) {
+ panic("vtd_create_domain: SAGAW 0x%lx does not support AGAW %d",
+ VTD_CAP_SAGAW(vtdmap->cap), agaw);
+ }
+
+ dom = malloc(sizeof(struct domain), M_VTD, M_ZERO | M_WAITOK);
+ dom->pt_levels = pt_levels;
+ dom->addrwidth = addrwidth;
+ dom->spsmask = VTD_CAP_SPS(vtdmap->cap);
+ dom->id = domain_id();
+ dom->maxaddr = maxaddr;
+ dom->ptp = malloc(PAGE_SIZE, M_VTD, M_ZERO | M_WAITOK);
+ if ((uintptr_t)dom->ptp & PAGE_MASK)
+ panic("vtd_create_domain: ptp (%p) not page aligned", dom->ptp);
+
+ SLIST_INSERT_HEAD(&domhead, dom, next);
+
+ return (dom);
+}
+
+static void
+vtd_free_ptp(uint64_t *ptp, int level)
+{
+ int i;
+ uint64_t *nlp;
+
+ if (level > 1) {
+ for (i = 0; i < 512; i++) {
+ if ((ptp[i] & (VTD_PTE_RD | VTD_PTE_WR)) == 0)
+ continue;
+ if ((ptp[i] & VTD_PTE_SUPERPAGE) != 0)
+ continue;
+ nlp = (uint64_t *)PHYS_TO_DMAP(ptp[i] & VTD_PTE_ADDR_M);
+ vtd_free_ptp(nlp, level - 1);
+ }
+ }
+
+ bzero(ptp, PAGE_SIZE);
+ free(ptp, M_VTD);
+}
+
+static void
+vtd_destroy_domain(void *arg)
+{
+ struct domain *dom;
+
+ dom = arg;
+
+ SLIST_REMOVE(&domhead, dom, domain, next);
+ vtd_free_ptp(dom->ptp, dom->pt_levels);
+ free(dom, M_VTD);
+}
+
+struct iommu_ops iommu_ops_intel = {
+ vtd_init,
+ vtd_cleanup,
+ vtd_enable,
+ vtd_disable,
+ vtd_create_domain,
+ vtd_destroy_domain,
+ vtd_create_mapping,
+ vtd_remove_mapping,
+ vtd_add_device,
+ vtd_remove_device,
+ vtd_invalidate_tlb,
+};
diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c
new file mode 100644
index 0000000..c8447cc
--- /dev/null
+++ b/sys/amd64/vmm/io/iommu.c
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/md_var.h>
+
+#include "vmm_util.h"
+#include "vmm_mem.h"
+#include "iommu.h"
+
+static boolean_t iommu_avail;
+static struct iommu_ops *ops;
+static void *host_domain;
+
+static __inline int
+IOMMU_INIT(void)
+{
+ if (ops != NULL)
+ return ((*ops->init)());
+ else
+ return (ENXIO);
+}
+
+static __inline void
+IOMMU_CLEANUP(void)
+{
+ if (ops != NULL && iommu_avail)
+ (*ops->cleanup)();
+}
+
+static __inline void *
+IOMMU_CREATE_DOMAIN(vm_paddr_t maxaddr)
+{
+
+ if (ops != NULL && iommu_avail)
+ return ((*ops->create_domain)(maxaddr));
+ else
+ return (NULL);
+}
+
+static __inline void
+IOMMU_DESTROY_DOMAIN(void *dom)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->destroy_domain)(dom);
+}
+
+static __inline uint64_t
+IOMMU_CREATE_MAPPING(void *domain, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len)
+{
+
+ if (ops != NULL && iommu_avail)
+ return ((*ops->create_mapping)(domain, gpa, hpa, len));
+ else
+ return (len); /* XXX */
+}
+
+static __inline uint64_t
+IOMMU_REMOVE_MAPPING(void *domain, vm_paddr_t gpa, uint64_t len)
+{
+
+ if (ops != NULL && iommu_avail)
+ return ((*ops->remove_mapping)(domain, gpa, len));
+ else
+ return (len); /* XXX */
+}
+
+static __inline void
+IOMMU_ADD_DEVICE(void *domain, int bus, int slot, int func)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->add_device)(domain, bus, slot, func);
+}
+
+static __inline void
+IOMMU_REMOVE_DEVICE(void *domain, int bus, int slot, int func)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->remove_device)(domain, bus, slot, func);
+}
+
+static __inline void
+IOMMU_INVALIDATE_TLB(void *domain)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->invalidate_tlb)(domain);
+}
+
+static __inline void
+IOMMU_ENABLE(void)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->enable)();
+}
+
+static __inline void
+IOMMU_DISABLE(void)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->disable)();
+}
+
+void
+iommu_init(void)
+{
+ int error, bus, slot, func;
+ vm_paddr_t maxaddr;
+ const char *name;
+ device_t dev;
+
+ if (vmm_is_intel())
+ ops = &iommu_ops_intel;
+ else if (vmm_is_amd())
+ ops = &iommu_ops_amd;
+ else
+ ops = NULL;
+
+ error = IOMMU_INIT();
+ if (error)
+ return;
+
+ iommu_avail = TRUE;
+
+ /*
+ * Create a domain for the devices owned by the host
+ */
+ maxaddr = vmm_mem_maxaddr();
+ host_domain = IOMMU_CREATE_DOMAIN(maxaddr);
+ if (host_domain == NULL)
+ panic("iommu_init: unable to create a host domain");
+
+ /*
+ * Create 1:1 mappings from '0' to 'maxaddr' for devices assigned to
+ * the host
+ */
+ iommu_create_mapping(host_domain, 0, 0, maxaddr);
+
+ for (bus = 0; bus <= PCI_BUSMAX; bus++) {
+ for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
+ for (func = 0; func <= PCI_FUNCMAX; func++) {
+ dev = pci_find_dbsf(0, bus, slot, func);
+ if (dev == NULL)
+ continue;
+
+ /* skip passthrough devices */
+ name = device_get_name(dev);
+ if (name != NULL && strcmp(name, "ppt") == 0)
+ continue;
+
+ /* everything else belongs to the host domain */
+ iommu_add_device(host_domain, bus, slot, func);
+ }
+ }
+ }
+ IOMMU_ENABLE();
+
+}
+
+void
+iommu_cleanup(void)
+{
+ IOMMU_DISABLE();
+ IOMMU_DESTROY_DOMAIN(host_domain);
+ IOMMU_CLEANUP();
+}
+
+void *
+iommu_create_domain(vm_paddr_t maxaddr)
+{
+
+ return (IOMMU_CREATE_DOMAIN(maxaddr));
+}
+
+void
+iommu_destroy_domain(void *dom)
+{
+
+ IOMMU_DESTROY_DOMAIN(dom);
+}
+
+void
+iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa, size_t len)
+{
+ uint64_t mapped, remaining;
+
+ remaining = len;
+
+ while (remaining > 0) {
+ mapped = IOMMU_CREATE_MAPPING(dom, gpa, hpa, remaining);
+ gpa += mapped;
+ hpa += mapped;
+ remaining -= mapped;
+ }
+}
+
+void
+iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len)
+{
+ uint64_t unmapped, remaining;
+
+ remaining = len;
+
+ while (remaining > 0) {
+ unmapped = IOMMU_REMOVE_MAPPING(dom, gpa, remaining);
+ gpa += unmapped;
+ remaining -= unmapped;
+ }
+}
+
+void *
+iommu_host_domain(void)
+{
+
+ return (host_domain);
+}
+
+void
+iommu_add_device(void *dom, int bus, int slot, int func)
+{
+
+ IOMMU_ADD_DEVICE(dom, bus, slot, func);
+}
+
+void
+iommu_remove_device(void *dom, int bus, int slot, int func)
+{
+
+ IOMMU_REMOVE_DEVICE(dom, bus, slot, func);
+}
+
+void
+iommu_invalidate_tlb(void *domain)
+{
+
+ IOMMU_INVALIDATE_TLB(domain);
+}
diff --git a/sys/amd64/vmm/io/iommu.h b/sys/amd64/vmm/io/iommu.h
new file mode 100644
index 0000000..d5c1d6e
--- /dev/null
+++ b/sys/amd64/vmm/io/iommu.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IO_IOMMU_H_
+#define _IO_IOMMU_H_
+
+typedef int (*iommu_init_func_t)(void);
+typedef void (*iommu_cleanup_func_t)(void);
+typedef void (*iommu_enable_func_t)(void);
+typedef void (*iommu_disable_func_t)(void);
+typedef void *(*iommu_create_domain_t)(vm_paddr_t maxaddr);
+typedef void (*iommu_destroy_domain_t)(void *domain);
+typedef uint64_t (*iommu_create_mapping_t)(void *domain, vm_paddr_t gpa,
+ vm_paddr_t hpa, uint64_t len);
+typedef uint64_t (*iommu_remove_mapping_t)(void *domain, vm_paddr_t gpa,
+ uint64_t len);
+typedef void (*iommu_add_device_t)(void *domain, int bus, int slot, int func);
+typedef void (*iommu_remove_device_t)(void *dom, int bus, int slot, int func);
+typedef void (*iommu_invalidate_tlb_t)(void *dom);
+
+struct iommu_ops {
+ iommu_init_func_t init; /* module wide */
+ iommu_cleanup_func_t cleanup;
+ iommu_enable_func_t enable;
+ iommu_disable_func_t disable;
+
+ iommu_create_domain_t create_domain; /* domain-specific */
+ iommu_destroy_domain_t destroy_domain;
+ iommu_create_mapping_t create_mapping;
+ iommu_remove_mapping_t remove_mapping;
+ iommu_add_device_t add_device;
+ iommu_remove_device_t remove_device;
+ iommu_invalidate_tlb_t invalidate_tlb;
+};
+
+extern struct iommu_ops iommu_ops_intel;
+extern struct iommu_ops iommu_ops_amd;
+
+void iommu_init(void);
+void iommu_cleanup(void);
+void *iommu_host_domain(void);
+void *iommu_create_domain(vm_paddr_t maxaddr);
+void iommu_destroy_domain(void *dom);
+void iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa,
+ size_t len);
+void iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len);
+void iommu_add_device(void *dom, int bus, int slot, int func);
+void iommu_remove_device(void *dom, int bus, int slot, int func);
+void iommu_invalidate_tlb(void *domain);
+#endif
diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c
new file mode 100644
index 0000000..4a05985
--- /dev/null
+++ b/sys/amd64/vmm/io/ppt.c
@@ -0,0 +1,619 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/pciio.h>
+#include <sys/rman.h>
+#include <sys/smp.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/resource.h>
+
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+
+#include "vmm_lapic.h"
+#include "vmm_ktr.h"
+
+#include "iommu.h"
+#include "ppt.h"
+
+/* XXX locking */
+
+#define MAX_PPTDEVS (sizeof(pptdevs) / sizeof(pptdevs[0]))
+#define MAX_MSIMSGS 32
+
+/*
+ * If the MSI-X table is located in the middle of a BAR then that MMIO
+ * region gets split into two segments - one segment above the MSI-X table
+ * and the other segment below the MSI-X table - with a hole in place of
+ * the MSI-X table so accesses to it can be trapped and emulated.
+ *
+ * So, allocate a MMIO segment for each BAR register + 1 additional segment.
+ */
+#define MAX_MMIOSEGS ((PCIR_MAX_BAR_0 + 1) + 1)
+
+MALLOC_DEFINE(M_PPTMSIX, "pptmsix", "Passthru MSI-X resources");
+
+struct pptintr_arg { /* pptintr(pptintr_arg) */
+ struct pptdev *pptdev;
+ int vec;
+ int vcpu;
+};
+
+static struct pptdev {
+ device_t dev;
+ struct vm *vm; /* owner of this device */
+ struct vm_memory_segment mmio[MAX_MMIOSEGS];
+ struct {
+ int num_msgs; /* guest state */
+
+ int startrid; /* host state */
+ struct resource *res[MAX_MSIMSGS];
+ void *cookie[MAX_MSIMSGS];
+ struct pptintr_arg arg[MAX_MSIMSGS];
+ } msi;
+
+ struct {
+ int num_msgs;
+ int startrid;
+ int msix_table_rid;
+ struct resource *msix_table_res;
+ struct resource **res;
+ void **cookie;
+ struct pptintr_arg *arg;
+ } msix;
+} pptdevs[64];
+
+static int num_pptdevs;
+
+static int
+ppt_probe(device_t dev)
+{
+ int bus, slot, func;
+ struct pci_devinfo *dinfo;
+
+ dinfo = (struct pci_devinfo *)device_get_ivars(dev);
+
+ bus = pci_get_bus(dev);
+ slot = pci_get_slot(dev);
+ func = pci_get_function(dev);
+
+ /*
+ * To qualify as a pci passthrough device a device must:
+ * - be allowed by administrator to be used in this role
+ * - be an endpoint device
+ */
+ if (vmm_is_pptdev(bus, slot, func) &&
+ (dinfo->cfg.hdrtype & PCIM_HDRTYPE) == PCIM_HDRTYPE_NORMAL)
+ return (0);
+ else
+ return (ENXIO);
+}
+
+static int
+ppt_attach(device_t dev)
+{
+ int n;
+
+ if (num_pptdevs >= MAX_PPTDEVS) {
+ printf("ppt_attach: maximum number of pci passthrough devices "
+ "exceeded\n");
+ return (ENXIO);
+ }
+
+ n = num_pptdevs++;
+ pptdevs[n].dev = dev;
+
+ if (bootverbose)
+ device_printf(dev, "attached\n");
+
+ return (0);
+}
+
+static int
+ppt_detach(device_t dev)
+{
+ /*
+ * XXX check whether there are any pci passthrough devices assigned
+ * to guests before we allow this driver to detach.
+ */
+
+ return (0);
+}
+
+static device_method_t ppt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ppt_probe),
+ DEVMETHOD(device_attach, ppt_attach),
+ DEVMETHOD(device_detach, ppt_detach),
+ {0, 0}
+};
+
+static devclass_t ppt_devclass;
+DEFINE_CLASS_0(ppt, ppt_driver, ppt_methods, 0);
+DRIVER_MODULE(ppt, pci, ppt_driver, ppt_devclass, NULL, NULL);
+
+static struct pptdev *
+ppt_find(int bus, int slot, int func)
+{
+ device_t dev;
+ int i, b, s, f;
+
+ for (i = 0; i < num_pptdevs; i++) {
+ dev = pptdevs[i].dev;
+ b = pci_get_bus(dev);
+ s = pci_get_slot(dev);
+ f = pci_get_function(dev);
+ if (bus == b && slot == s && func == f)
+ return (&pptdevs[i]);
+ }
+ return (NULL);
+}
+
+static void
+ppt_unmap_mmio(struct vm *vm, struct pptdev *ppt)
+{
+ int i;
+ struct vm_memory_segment *seg;
+
+ for (i = 0; i < MAX_MMIOSEGS; i++) {
+ seg = &ppt->mmio[i];
+ if (seg->len == 0)
+ continue;
+ (void)vm_unmap_mmio(vm, seg->gpa, seg->len);
+ bzero(seg, sizeof(struct vm_memory_segment));
+ }
+}
+
+static void
+ppt_teardown_msi(struct pptdev *ppt)
+{
+ int i, rid;
+ void *cookie;
+ struct resource *res;
+
+ if (ppt->msi.num_msgs == 0)
+ return;
+
+ for (i = 0; i < ppt->msi.num_msgs; i++) {
+ rid = ppt->msi.startrid + i;
+ res = ppt->msi.res[i];
+ cookie = ppt->msi.cookie[i];
+
+ if (cookie != NULL)
+ bus_teardown_intr(ppt->dev, res, cookie);
+
+ if (res != NULL)
+ bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, res);
+
+ ppt->msi.res[i] = NULL;
+ ppt->msi.cookie[i] = NULL;
+ }
+
+ if (ppt->msi.startrid == 1)
+ pci_release_msi(ppt->dev);
+
+ ppt->msi.num_msgs = 0;
+}
+
+static void
+ppt_teardown_msix_intr(struct pptdev *ppt, int idx)
+{
+ int rid;
+ struct resource *res;
+ void *cookie;
+
+ rid = ppt->msix.startrid + idx;
+ res = ppt->msix.res[idx];
+ cookie = ppt->msix.cookie[idx];
+
+ if (cookie != NULL)
+ bus_teardown_intr(ppt->dev, res, cookie);
+
+ if (res != NULL)
+ bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, res);
+
+ ppt->msix.res[idx] = NULL;
+ ppt->msix.cookie[idx] = NULL;
+}
+
+static void
+ppt_teardown_msix(struct pptdev *ppt)
+{
+ int i;
+
+ if (ppt->msix.num_msgs == 0)
+ return;
+
+ for (i = 0; i < ppt->msix.num_msgs; i++)
+ ppt_teardown_msix_intr(ppt, i);
+
+ if (ppt->msix.msix_table_res) {
+ bus_release_resource(ppt->dev, SYS_RES_MEMORY,
+ ppt->msix.msix_table_rid,
+ ppt->msix.msix_table_res);
+ ppt->msix.msix_table_res = NULL;
+ ppt->msix.msix_table_rid = 0;
+ }
+
+ free(ppt->msix.res, M_PPTMSIX);
+ free(ppt->msix.cookie, M_PPTMSIX);
+ free(ppt->msix.arg, M_PPTMSIX);
+
+ pci_release_msi(ppt->dev);
+
+ ppt->msix.num_msgs = 0;
+}
+
+int
+ppt_assign_device(struct vm *vm, int bus, int slot, int func)
+{
+ struct pptdev *ppt;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt != NULL) {
+ /*
+ * If this device is owned by a different VM then we
+ * cannot change its owner.
+ */
+ if (ppt->vm != NULL && ppt->vm != vm)
+ return (EBUSY);
+
+ ppt->vm = vm;
+ iommu_add_device(vm_iommu_domain(vm), bus, slot, func);
+ return (0);
+ }
+ return (ENOENT);
+}
+
+int
+ppt_unassign_device(struct vm *vm, int bus, int slot, int func)
+{
+ struct pptdev *ppt;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt != NULL) {
+ /*
+ * If this device is not owned by this 'vm' then bail out.
+ */
+ if (ppt->vm != vm)
+ return (EBUSY);
+ ppt_unmap_mmio(vm, ppt);
+ ppt_teardown_msi(ppt);
+ ppt_teardown_msix(ppt);
+ iommu_remove_device(vm_iommu_domain(vm), bus, slot, func);
+ ppt->vm = NULL;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+int
+ppt_unassign_all(struct vm *vm)
+{
+ int i, bus, slot, func;
+ device_t dev;
+
+ for (i = 0; i < num_pptdevs; i++) {
+ if (pptdevs[i].vm == vm) {
+ dev = pptdevs[i].dev;
+ bus = pci_get_bus(dev);
+ slot = pci_get_slot(dev);
+ func = pci_get_function(dev);
+ ppt_unassign_device(vm, bus, slot, func);
+ }
+ }
+
+ return (0);
+}
+
+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 i, error;
+ struct vm_memory_segment *seg;
+ struct pptdev *ppt;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt != NULL) {
+ if (ppt->vm != vm)
+ return (EBUSY);
+
+ for (i = 0; i < MAX_MMIOSEGS; i++) {
+ seg = &ppt->mmio[i];
+ if (seg->len == 0) {
+ error = vm_map_mmio(vm, gpa, len, hpa);
+ if (error == 0) {
+ seg->gpa = gpa;
+ seg->len = len;
+ }
+ return (error);
+ }
+ }
+ return (ENOSPC);
+ }
+ return (ENOENT);
+}
+
+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)
+ (void) lapic_set_intr(ppt->vm, pptarg->vcpu, vec);
+ else {
+ /*
+ * XXX
+ * This is not expected to happen - panic?
+ */
+ }
+
+ /*
+ * For legacy interrupts give other filters a chance in case
+ * the interrupt was not generated by the passthrough device.
+ */
+ if (ppt->msi.startrid == 0)
+ return (FILTER_STRAY);
+ else
+ return (FILTER_HANDLED);
+}
+
+/*
+ * XXX
+ * When we try to free the MSI resource the kernel will bind the thread to
+ * the host cpu was originally handling the MSI. The function freeing the
+ * MSI vector (apic_free_vector()) will panic the kernel if the thread
+ * is already bound to a cpu.
+ *
+ * So, we temporarily unbind the vcpu thread before freeing the MSI resource.
+ */
+static void
+PPT_TEARDOWN_MSI(struct vm *vm, int vcpu, struct pptdev *ppt)
+{
+ int pincpu = -1;
+
+ vm_get_pinning(vm, vcpu, &pincpu);
+
+ if (pincpu >= 0)
+ vm_set_pinning(vm, vcpu, -1);
+
+ ppt_teardown_msi(ppt);
+
+ if (pincpu >= 0)
+ vm_set_pinning(vm, vcpu, pincpu);
+}
+
+int
+ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func,
+ int destcpu, int vector, 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))
+ return (EINVAL);
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt == NULL)
+ return (ENOENT);
+ if (ppt->vm != vm) /* Make sure we own this device */
+ return (EBUSY);
+
+ /* Free any allocated resources */
+ PPT_TEARDOWN_MSI(vm, vcpu, ppt);
+
+ if (numvec == 0) /* nothing more to do */
+ return (0);
+
+ flags = RF_ACTIVE;
+ msi_count = pci_msi_count(ppt->dev);
+ if (msi_count == 0) {
+ startrid = 0; /* legacy interrupt */
+ msi_count = 1;
+ flags |= RF_SHAREABLE;
+ } else
+ startrid = 1; /* MSI */
+
+ /*
+ * The device must be capable of supporting the number of vectors
+ * the guest wants to allocate.
+ */
+ if (numvec > msi_count)
+ return (EINVAL);
+
+ /*
+ * Make sure that we can allocate all the MSI vectors that are needed
+ * by the guest.
+ */
+ if (startrid == 1) {
+ tmp = numvec;
+ error = pci_alloc_msi(ppt->dev, &tmp);
+ if (error)
+ return (error);
+ else if (tmp != numvec) {
+ pci_release_msi(ppt->dev);
+ return (ENOSPC);
+ } else {
+ /* success */
+ }
+ }
+
+ ppt->msi.startrid = startrid;
+
+ /*
+ * Allocate the irq resource and attach it to the interrupt handler.
+ */
+ for (i = 0; i < numvec; i++) {
+ ppt->msi.num_msgs = i + 1;
+ ppt->msi.cookie[i] = NULL;
+
+ rid = startrid + i;
+ ppt->msi.res[i] = bus_alloc_resource_any(ppt->dev, SYS_RES_IRQ,
+ &rid, flags);
+ if (ppt->msi.res[i] == NULL)
+ break;
+
+ ppt->msi.arg[i].pptdev = ppt;
+ ppt->msi.arg[i].vec = vector + i;
+ ppt->msi.arg[i].vcpu = destcpu;
+
+ error = bus_setup_intr(ppt->dev, ppt->msi.res[i],
+ INTR_TYPE_NET | INTR_MPSAFE,
+ pptintr, NULL, &ppt->msi.arg[i],
+ &ppt->msi.cookie[i]);
+ if (error != 0)
+ break;
+ }
+
+ if (i < numvec) {
+ PPT_TEARDOWN_MSI(vm, vcpu, ppt);
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+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)
+{
+ struct pptdev *ppt;
+ struct pci_devinfo *dinfo;
+ int numvec, alloced, rid, error;
+ size_t res_size, cookie_size, arg_size;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt == NULL)
+ return (ENOENT);
+ if (ppt->vm != vm) /* Make sure we own this device */
+ return (EBUSY);
+
+ dinfo = device_get_ivars(ppt->dev);
+ if (!dinfo)
+ return (ENXIO);
+
+ /*
+ * First-time configuration:
+ * Allocate the MSI-X table
+ * Allocate the IRQ resources
+ * Set up some variables in ppt->msix
+ */
+ if (ppt->msix.num_msgs == 0) {
+ numvec = pci_msix_count(ppt->dev);
+ if (numvec <= 0)
+ return (EINVAL);
+
+ ppt->msix.startrid = 1;
+ ppt->msix.num_msgs = numvec;
+
+ res_size = numvec * sizeof(ppt->msix.res[0]);
+ cookie_size = numvec * sizeof(ppt->msix.cookie[0]);
+ arg_size = numvec * sizeof(ppt->msix.arg[0]);
+
+ ppt->msix.res = malloc(res_size, M_PPTMSIX, M_WAITOK | M_ZERO);
+ ppt->msix.cookie = malloc(cookie_size, M_PPTMSIX,
+ M_WAITOK | M_ZERO);
+ ppt->msix.arg = malloc(arg_size, M_PPTMSIX, M_WAITOK | M_ZERO);
+
+ rid = dinfo->cfg.msix.msix_table_bar;
+ ppt->msix.msix_table_res = bus_alloc_resource_any(ppt->dev,
+ SYS_RES_MEMORY, &rid, RF_ACTIVE);
+
+ if (ppt->msix.msix_table_res == NULL) {
+ ppt_teardown_msix(ppt);
+ return (ENOSPC);
+ }
+ ppt->msix.msix_table_rid = rid;
+
+ alloced = numvec;
+ error = pci_alloc_msix(ppt->dev, &alloced);
+ if (error || alloced != numvec) {
+ ppt_teardown_msix(ppt);
+ return (error == 0 ? ENOSPC: error);
+ }
+ }
+
+ if ((vector_control & PCIM_MSIX_VCTRL_MASK) == 0) {
+ /* Tear down the IRQ if it's already set up */
+ ppt_teardown_msix_intr(ppt, idx);
+
+ /* Allocate the IRQ resource */
+ ppt->msix.cookie[idx] = NULL;
+ rid = ppt->msix.startrid + idx;
+ ppt->msix.res[idx] = bus_alloc_resource_any(ppt->dev, SYS_RES_IRQ,
+ &rid, RF_ACTIVE);
+ if (ppt->msix.res[idx] == NULL)
+ return (ENXIO);
+
+ ppt->msix.arg[idx].pptdev = ppt;
+ ppt->msix.arg[idx].vec = msg;
+ ppt->msix.arg[idx].vcpu = (addr >> 12) & 0xFF;
+
+ /* Setup the MSI-X interrupt */
+ error = bus_setup_intr(ppt->dev, ppt->msix.res[idx],
+ INTR_TYPE_NET | INTR_MPSAFE,
+ pptintr, NULL, &ppt->msix.arg[idx],
+ &ppt->msix.cookie[idx]);
+
+ if (error != 0) {
+ bus_teardown_intr(ppt->dev, ppt->msix.res[idx], ppt->msix.cookie[idx]);
+ bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, ppt->msix.res[idx]);
+ ppt->msix.cookie[idx] = NULL;
+ ppt->msix.res[idx] = NULL;
+ return (ENXIO);
+ }
+ } else {
+ /* Masked, tear it down if it's already been set up */
+ ppt_teardown_msix_intr(ppt, idx);
+ }
+
+ return (0);
+}
+
diff --git a/sys/amd64/vmm/io/ppt.h b/sys/amd64/vmm/io/ppt.h
new file mode 100644
index 0000000..63c8228
--- /dev/null
+++ b/sys/amd64/vmm/io/ppt.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IO_PPT_H_
+#define _IO_PPT_H_
+
+int ppt_assign_device(struct vm *vm, int bus, int slot, int func);
+int ppt_unassign_device(struct vm *vm, int bus, int slot, int func);
+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);
+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);
+#endif
diff --git a/sys/amd64/vmm/io/vdev.c b/sys/amd64/vmm/io/vdev.c
new file mode 100644
index 0000000..cd6c5d1
--- /dev/null
+++ b/sys/amd64/vmm/io/vdev.c
@@ -0,0 +1,270 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include "vdev.h"
+
+struct vdev {
+ SLIST_ENTRY(vdev) entry;
+ struct vdev_ops *ops;
+ void *dev;
+};
+static SLIST_HEAD(, vdev) vdev_head;
+static int vdev_count;
+
+struct vdev_region {
+ SLIST_ENTRY(vdev_region) entry;
+ struct vdev_ops *ops;
+ void *dev;
+ struct io_region *io;
+};
+static SLIST_HEAD(, vdev_region) region_head;
+static int region_count;
+
+static MALLOC_DEFINE(M_VDEV, "vdev", "vdev");
+
+#define VDEV_INIT (0)
+#define VDEV_RESET (1)
+#define VDEV_HALT (2)
+
+// static const char* vdev_event_str[] = {"VDEV_INIT", "VDEV_RESET", "VDEV_HALT"};
+
+static int
+vdev_system_event(int event)
+{
+ struct vdev *vd;
+ int rc;
+
+ // TODO: locking
+ SLIST_FOREACH(vd, &vdev_head, entry) {
+ // printf("%s : %s Device %s\n", __func__, vdev_event_str[event], vd->ops->name);
+ switch (event) {
+ case VDEV_INIT:
+ rc = vd->ops->init(vd->dev);
+ break;
+ case VDEV_RESET:
+ rc = vd->ops->reset(vd->dev);
+ break;
+ case VDEV_HALT:
+ rc = vd->ops->halt(vd->dev);
+ break;
+ default:
+ break;
+ }
+ if (rc) {
+ printf("vdev %s init failed rc=%d\n",
+ vd->ops->name, rc);
+ return rc;
+ }
+ }
+ return 0;
+}
+
+int
+vdev_init(void)
+{
+ return vdev_system_event(VDEV_INIT);
+}
+
+int
+vdev_reset(void)
+{
+ return vdev_system_event(VDEV_RESET);
+}
+
+int
+vdev_halt(void)
+{
+ return vdev_system_event(VDEV_HALT);
+}
+
+void
+vdev_vm_init(void)
+{
+ SLIST_INIT(&vdev_head);
+ vdev_count = 0;
+
+ SLIST_INIT(&region_head);
+ region_count = 0;
+}
+void
+vdev_vm_cleanup(void)
+{
+ struct vdev *vd;
+
+ // TODO: locking
+ while (!SLIST_EMPTY(&vdev_head)) {
+ vd = SLIST_FIRST(&vdev_head);
+ SLIST_REMOVE_HEAD(&vdev_head, entry);
+ free(vd, M_VDEV);
+ vdev_count--;
+ }
+}
+
+int
+vdev_register(struct vdev_ops *ops, void *dev)
+{
+ struct vdev *vd;
+ vd = malloc(sizeof(*vd), M_VDEV, M_WAITOK | M_ZERO);
+ vd->ops = ops;
+ vd->dev = dev;
+
+ // TODO: locking
+ SLIST_INSERT_HEAD(&vdev_head, vd, entry);
+ vdev_count++;
+ return 0;
+}
+
+void
+vdev_unregister(void *dev)
+{
+ struct vdev *vd, *found;
+
+ found = NULL;
+ // TODO: locking
+ SLIST_FOREACH(vd, &vdev_head, entry) {
+ if (vd->dev == dev) {
+ found = vd;
+ }
+ }
+
+ if (found) {
+ SLIST_REMOVE(&vdev_head, found, vdev, entry);
+ free(found, M_VDEV);
+ }
+}
+
+#define IN_RANGE(val, start, end) \
+ (((val) >= (start)) && ((val) < (end)))
+
+static struct vdev_region*
+vdev_find_region(struct io_region *io, void *dev)
+{
+ struct vdev_region *region, *found;
+ uint64_t region_base;
+ uint64_t region_end;
+
+ found = NULL;
+
+ // TODO: locking
+ // FIXME: we should verify we are in the context the current
+ // vcpu here as well.
+ SLIST_FOREACH(region, &region_head, entry) {
+ region_base = region->io->base;
+ region_end = region_base + region->io->len;
+ if (IN_RANGE(io->base, region_base, region_end) &&
+ IN_RANGE(io->base+io->len, region_base, region_end+1) &&
+ (dev && dev == region->dev)) {
+ found = region;
+ break;
+ }
+ }
+ return found;
+}
+
+int
+vdev_register_region(struct vdev_ops *ops, void *dev, struct io_region *io)
+{
+ struct vdev_region *region;
+
+ region = vdev_find_region(io, dev);
+ if (region) {
+ return -EEXIST;
+ }
+
+ region = malloc(sizeof(*region), M_VDEV, M_WAITOK | M_ZERO);
+ region->io = io;
+ region->ops = ops;
+ region->dev = dev;
+
+ // TODO: locking
+ SLIST_INSERT_HEAD(&region_head, region, entry);
+ region_count++;
+
+ return 0;
+}
+
+void
+vdev_unregister_region(void *dev, struct io_region *io)
+{
+ struct vdev_region *region;
+
+ region = vdev_find_region(io, dev);
+
+ if (region) {
+ SLIST_REMOVE(&region_head, region, vdev_region, entry);
+ free(region, M_VDEV);
+ region_count--;
+ }
+}
+
+static int
+vdev_memrw(uint64_t gpa, opsize_t size, uint64_t *data, int read)
+{
+ struct vdev_region *region;
+ struct io_region io;
+ region_attr_t attr;
+ int rc;
+
+ io.base = gpa;
+ io.len = size;
+
+ region = vdev_find_region(&io, NULL);
+ if (!region)
+ return -EINVAL;
+
+ attr = (read) ? MMIO_READ : MMIO_WRITE;
+ if (!(region->io->attr & attr))
+ return -EPERM;
+
+ if (read)
+ rc = region->ops->memread(region->dev, gpa, size, data);
+ else
+ rc = region->ops->memwrite(region->dev, gpa, size, *data);
+
+ return rc;
+}
+
+int
+vdev_memread(uint64_t gpa, opsize_t size, uint64_t *data)
+{
+ return vdev_memrw(gpa, size, data, 1);
+}
+
+int
+vdev_memwrite(uint64_t gpa, opsize_t size, uint64_t data)
+{
+ return vdev_memrw(gpa, size, &data, 0);
+}
diff --git a/sys/amd64/vmm/io/vdev.h b/sys/amd64/vmm/io/vdev.h
new file mode 100644
index 0000000..6feeba8
--- /dev/null
+++ b/sys/amd64/vmm/io/vdev.h
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VDEV_H_
+#define _VDEV_H_
+
+typedef enum {
+ BYTE = 1,
+ WORD = 2,
+ DWORD = 4,
+ QWORD = 8,
+} opsize_t;
+
+typedef enum {
+ MMIO_READ = 1,
+ MMIO_WRITE = 2,
+} region_attr_t;
+
+struct io_region {
+ uint64_t base;
+ uint64_t len;
+ region_attr_t attr;
+ int vcpu;
+};
+
+typedef int (*vdev_init_t)(void* dev);
+typedef int (*vdev_reset_t)(void* dev);
+typedef int (*vdev_halt_t)(void* dev);
+typedef int (*vdev_memread_t)(void* dev, uint64_t gpa, opsize_t size, uint64_t *data);
+typedef int (*vdev_memwrite_t)(void* dev, uint64_t gpa, opsize_t size, uint64_t data);
+
+
+struct vdev_ops {
+ const char *name;
+ vdev_init_t init;
+ vdev_reset_t reset;
+ vdev_halt_t halt;
+ vdev_memread_t memread;
+ vdev_memwrite_t memwrite;
+};
+
+
+void vdev_vm_init(void);
+void vdev_vm_cleanup(void);
+
+int vdev_register(struct vdev_ops *ops, void *dev);
+void vdev_unregister(void *dev);
+
+int vdev_register_region(struct vdev_ops *ops, void *dev, struct io_region *io);
+void vdev_unregister_region(void *dev, struct io_region *io);
+
+int vdev_init(void);
+int vdev_reset(void);
+int vdev_halt(void);
+int vdev_memread(uint64_t gpa, opsize_t size, uint64_t *data);
+int vdev_memwrite(uint64_t gpa, opsize_t size, uint64_t data);
+
+#endif /* _VDEV_H_ */
+
diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
new file mode 100644
index 0000000..15fc6c2
--- /dev/null
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -0,0 +1,901 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+
+#include <machine/clock.h>
+#include <x86/specialreg.h>
+#include <x86/apicreg.h>
+
+#include <machine/vmm.h>
+
+#include "vmm_lapic.h"
+#include "vmm_ktr.h"
+#include "vdev.h"
+#include "vlapic.h"
+
+#define VLAPIC_CTR0(vlapic, format) \
+ VMM_CTR0((vlapic)->vm, (vlapic)->vcpuid, format)
+
+#define VLAPIC_CTR1(vlapic, format, p1) \
+ VMM_CTR1((vlapic)->vm, (vlapic)->vcpuid, format, p1)
+
+#define VLAPIC_CTR_IRR(vlapic, msg) \
+do { \
+ uint32_t *irrptr = &(vlapic)->apic.irr0; \
+ irrptr[0] = irrptr[0]; /* silence compiler */ \
+ VLAPIC_CTR1((vlapic), msg " irr0 0x%08x", irrptr[0 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr1 0x%08x", irrptr[1 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr2 0x%08x", irrptr[2 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr3 0x%08x", irrptr[3 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr4 0x%08x", irrptr[4 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr5 0x%08x", irrptr[5 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr6 0x%08x", irrptr[6 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr7 0x%08x", irrptr[7 << 2]); \
+} while (0)
+
+#define VLAPIC_CTR_ISR(vlapic, msg) \
+do { \
+ uint32_t *isrptr = &(vlapic)->apic.isr0; \
+ isrptr[0] = isrptr[0]; /* silence compiler */ \
+ VLAPIC_CTR1((vlapic), msg " isr0 0x%08x", isrptr[0 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr1 0x%08x", isrptr[1 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr2 0x%08x", isrptr[2 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr3 0x%08x", isrptr[3 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr4 0x%08x", isrptr[4 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr5 0x%08x", isrptr[5 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr6 0x%08x", isrptr[6 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr7 0x%08x", isrptr[7 << 2]); \
+} while (0)
+
+static MALLOC_DEFINE(M_VLAPIC, "vlapic", "vlapic");
+
+#define PRIO(x) ((x) >> 4)
+
+#define VLAPIC_VERSION (16)
+#define VLAPIC_MAXLVT_ENTRIES (5)
+
+#define x2apic(vlapic) (((vlapic)->msr_apicbase & APICBASE_X2APIC) ? 1 : 0)
+
+enum boot_state {
+ BS_INIT,
+ BS_SIPI,
+ BS_RUNNING
+};
+
+struct vlapic {
+ struct vm *vm;
+ int vcpuid;
+
+ struct io_region *mmio;
+ struct vdev_ops *ops;
+ struct LAPIC apic;
+
+ int esr_update;
+
+ int divisor;
+ int ccr_ticks;
+
+ /*
+ * The 'isrvec_stk' is a stack of vectors injected by the local apic.
+ * A vector is popped from the stack when the processor does an EOI.
+ * The vector on the top of the stack is used to compute the
+ * Processor Priority in conjunction with the TPR.
+ */
+ uint8_t isrvec_stk[ISRVEC_STK_SIZE];
+ int isrvec_stk_top;
+
+ uint64_t msr_apicbase;
+ enum boot_state boot_state;
+};
+
+#define VLAPIC_BUS_FREQ tsc_freq
+
+static int
+vlapic_timer_divisor(uint32_t dcr)
+{
+ switch (dcr & 0xB) {
+ case APIC_TDCR_2:
+ return (2);
+ case APIC_TDCR_4:
+ return (4);
+ case APIC_TDCR_8:
+ return (8);
+ case APIC_TDCR_16:
+ return (16);
+ case APIC_TDCR_32:
+ return (32);
+ case APIC_TDCR_64:
+ return (64);
+ case APIC_TDCR_128:
+ return (128);
+ default:
+ panic("vlapic_timer_divisor: invalid dcr 0x%08x", dcr);
+ }
+}
+
+static void
+vlapic_mask_lvts(uint32_t *lvts, int num_lvt)
+{
+ int i;
+ for (i = 0; i < num_lvt; i++) {
+ *lvts |= APIC_LVT_M;
+ lvts += 4;
+ }
+}
+
+#if 0
+static inline void
+vlapic_dump_lvt(uint32_t offset, uint32_t *lvt)
+{
+ printf("Offset %x: lvt %08x (V:%02x DS:%x M:%x)\n", offset,
+ *lvt, *lvt & APIC_LVTT_VECTOR, *lvt & APIC_LVTT_DS,
+ *lvt & APIC_LVTT_M);
+}
+#endif
+
+static uint64_t
+vlapic_get_ccr(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ return lapic->ccr_timer;
+}
+
+static void
+vlapic_update_errors(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ lapic->esr = 0; // XXX
+}
+
+static void
+vlapic_init_ipi(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ lapic->version = VLAPIC_VERSION;
+ lapic->version |= (VLAPIC_MAXLVT_ENTRIES < MAXLVTSHIFT);
+ lapic->dfr = 0xffffffff;
+ lapic->svr = APIC_SVR_VECTOR;
+ vlapic_mask_lvts(&lapic->lvt_timer, VLAPIC_MAXLVT_ENTRIES+1);
+}
+
+static int
+vlapic_op_reset(void* dev)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ struct LAPIC *lapic = &vlapic->apic;
+
+ memset(lapic, 0, sizeof(*lapic));
+ lapic->apr = vlapic->vcpuid;
+ vlapic_init_ipi(vlapic);
+ vlapic->divisor = vlapic_timer_divisor(lapic->dcr_timer);
+
+ if (vlapic->vcpuid == 0)
+ vlapic->boot_state = BS_RUNNING; /* BSP */
+ else
+ vlapic->boot_state = BS_INIT; /* AP */
+
+ return 0;
+
+}
+
+static int
+vlapic_op_init(void* dev)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ vdev_register_region(vlapic->ops, vlapic, vlapic->mmio);
+ return vlapic_op_reset(dev);
+}
+
+static int
+vlapic_op_halt(void* dev)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ vdev_unregister_region(vlapic, vlapic->mmio);
+ return 0;
+
+}
+
+void
+vlapic_set_intr_ready(struct vlapic *vlapic, int vector)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ uint32_t *irrptr;
+ int idx;
+
+ if (vector < 0 || vector >= 256)
+ panic("vlapic_set_intr_ready: invalid vector %d\n", vector);
+
+ idx = (vector / 32) * 4;
+ irrptr = &lapic->irr0;
+ atomic_set_int(&irrptr[idx], 1 << (vector % 32));
+ VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
+}
+
+static void
+vlapic_start_timer(struct vlapic *vlapic, uint32_t elapsed)
+{
+ uint32_t icr_timer;
+
+ icr_timer = vlapic->apic.icr_timer;
+
+ vlapic->ccr_ticks = ticks;
+ if (elapsed < icr_timer)
+ vlapic->apic.ccr_timer = icr_timer - elapsed;
+ else {
+ /*
+ * This can happen when the guest is trying to run its local
+ * apic timer higher that the setting of 'hz' in the host.
+ *
+ * We deal with this by running the guest local apic timer
+ * at the rate of the host's 'hz' setting.
+ */
+ vlapic->apic.ccr_timer = 0;
+ }
+}
+
+static __inline uint32_t *
+vlapic_get_lvt(struct vlapic *vlapic, uint32_t offset)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ int i;
+
+ if (offset < APIC_OFFSET_TIMER_LVT || offset > APIC_OFFSET_ERROR_LVT) {
+ panic("vlapic_get_lvt: invalid LVT\n");
+ }
+ i = (offset - APIC_OFFSET_TIMER_LVT) >> 2;
+ return ((&lapic->lvt_timer) + i);;
+}
+
+#if 1
+static void
+dump_isrvec_stk(struct vlapic *vlapic)
+{
+ int i;
+ uint32_t *isrptr;
+
+ isrptr = &vlapic->apic.isr0;
+ for (i = 0; i < 8; i++)
+ printf("ISR%d 0x%08x\n", i, isrptr[i * 4]);
+
+ for (i = 0; i <= vlapic->isrvec_stk_top; i++)
+ printf("isrvec_stk[%d] = %d\n", i, vlapic->isrvec_stk[i]);
+}
+#endif
+
+/*
+ * Algorithm adopted from section "Interrupt, Task and Processor Priority"
+ * in Intel Architecture Manual Vol 3a.
+ */
+static void
+vlapic_update_ppr(struct vlapic *vlapic)
+{
+ int isrvec, tpr, ppr;
+
+ /*
+ * Note that the value on the stack at index 0 is always 0.
+ *
+ * This is a placeholder for the value of ISRV when none of the
+ * bits is set in the ISRx registers.
+ */
+ isrvec = vlapic->isrvec_stk[vlapic->isrvec_stk_top];
+ tpr = vlapic->apic.tpr;
+
+#if 1
+ {
+ int i, lastprio, curprio, vector, idx;
+ uint32_t *isrptr;
+
+ if (vlapic->isrvec_stk_top == 0 && isrvec != 0)
+ panic("isrvec_stk is corrupted: %d", isrvec);
+
+ /*
+ * Make sure that the priority of the nested interrupts is
+ * always increasing.
+ */
+ lastprio = -1;
+ for (i = 1; i <= vlapic->isrvec_stk_top; i++) {
+ curprio = PRIO(vlapic->isrvec_stk[i]);
+ if (curprio <= lastprio) {
+ dump_isrvec_stk(vlapic);
+ panic("isrvec_stk does not satisfy invariant");
+ }
+ lastprio = curprio;
+ }
+
+ /*
+ * Make sure that each bit set in the ISRx registers has a
+ * corresponding entry on the isrvec stack.
+ */
+ i = 1;
+ isrptr = &vlapic->apic.isr0;
+ for (vector = 0; vector < 256; vector++) {
+ idx = (vector / 32) * 4;
+ if (isrptr[idx] & (1 << (vector % 32))) {
+ if (i > vlapic->isrvec_stk_top ||
+ vlapic->isrvec_stk[i] != vector) {
+ dump_isrvec_stk(vlapic);
+ panic("ISR and isrvec_stk out of sync");
+ }
+ i++;
+ }
+ }
+ }
+#endif
+
+ if (PRIO(tpr) >= PRIO(isrvec))
+ ppr = tpr;
+ else
+ ppr = isrvec & 0xf0;
+
+ vlapic->apic.ppr = ppr;
+ VLAPIC_CTR1(vlapic, "vlapic_update_ppr 0x%02x", ppr);
+}
+
+static void
+vlapic_process_eoi(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ uint32_t *isrptr;
+ int i, idx, bitpos;
+
+ isrptr = &lapic->isr0;
+
+ /*
+ * The x86 architecture reserves the the first 32 vectors for use
+ * by the processor.
+ */
+ for (i = 7; i > 0; i--) {
+ idx = i * 4;
+ bitpos = fls(isrptr[idx]);
+ if (bitpos != 0) {
+ if (vlapic->isrvec_stk_top <= 0) {
+ panic("invalid vlapic isrvec_stk_top %d",
+ vlapic->isrvec_stk_top);
+ }
+ isrptr[idx] &= ~(1 << (bitpos - 1));
+ VLAPIC_CTR_ISR(vlapic, "vlapic_process_eoi");
+ vlapic->isrvec_stk_top--;
+ vlapic_update_ppr(vlapic);
+ return;
+ }
+ }
+}
+
+static __inline int
+vlapic_get_lvt_field(uint32_t *lvt, uint32_t mask)
+{
+ return (*lvt & mask);
+}
+
+static __inline int
+vlapic_periodic_timer(struct vlapic *vlapic)
+{
+ uint32_t *lvt;
+
+ lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_TIMER_LVT);
+
+ return (vlapic_get_lvt_field(lvt, APIC_LVTT_TM_PERIODIC));
+}
+
+static void
+vlapic_fire_timer(struct vlapic *vlapic)
+{
+ int vector;
+ uint32_t *lvt;
+
+ lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_TIMER_LVT);
+
+ if (!vlapic_get_lvt_field(lvt, APIC_LVTT_M)) {
+ vector = vlapic_get_lvt_field(lvt,APIC_LVTT_VECTOR);
+ vlapic_set_intr_ready(vlapic, vector);
+ }
+}
+
+static int
+lapic_process_icr(struct vlapic *vlapic, uint64_t icrval)
+{
+ int i;
+ cpuset_t dmask;
+ uint32_t dest, vec, mode;
+ struct vlapic *vlapic2;
+ struct vm_exit *vmexit;
+
+ if (x2apic(vlapic))
+ dest = icrval >> 32;
+ else
+ dest = icrval >> (32 + 24);
+ vec = icrval & APIC_VECTOR_MASK;
+ mode = icrval & APIC_DELMODE_MASK;
+
+ if (mode == APIC_DELMODE_FIXED || mode == APIC_DELMODE_NMI) {
+ switch (icrval & APIC_DEST_MASK) {
+ case APIC_DEST_DESTFLD:
+ CPU_SETOF(dest, &dmask);
+ break;
+ case APIC_DEST_SELF:
+ CPU_SETOF(vlapic->vcpuid, &dmask);
+ break;
+ case APIC_DEST_ALLISELF:
+ dmask = vm_active_cpus(vlapic->vm);
+ break;
+ case APIC_DEST_ALLESELF:
+ dmask = vm_active_cpus(vlapic->vm);
+ CPU_CLR(vlapic->vcpuid, &dmask);
+ break;
+ }
+
+ while ((i = cpusetobj_ffs(&dmask)) != 0) {
+ i--;
+ CPU_CLR(i, &dmask);
+ if (mode == APIC_DELMODE_FIXED)
+ lapic_set_intr(vlapic->vm, i, vec);
+ else
+ vm_inject_nmi(vlapic->vm, i);
+ }
+
+ return (0); /* handled completely in the kernel */
+ }
+
+ if (mode == APIC_DELMODE_INIT) {
+ if ((icrval & APIC_LEVEL_MASK) == APIC_LEVEL_DEASSERT)
+ return (0);
+
+ if (vlapic->vcpuid == 0 && dest != 0 && dest < VM_MAXCPU) {
+ vlapic2 = vm_lapic(vlapic->vm, dest);
+
+ /* move from INIT to waiting-for-SIPI state */
+ if (vlapic2->boot_state == BS_INIT) {
+ vlapic2->boot_state = BS_SIPI;
+ }
+
+ return (0);
+ }
+ }
+
+ if (mode == APIC_DELMODE_STARTUP) {
+ if (vlapic->vcpuid == 0 && dest != 0 && dest < VM_MAXCPU) {
+ vlapic2 = vm_lapic(vlapic->vm, dest);
+
+ /*
+ * Ignore SIPIs in any state other than wait-for-SIPI
+ */
+ if (vlapic2->boot_state != BS_SIPI)
+ return (0);
+
+ vmexit = vm_exitinfo(vlapic->vm, vlapic->vcpuid);
+ vmexit->exitcode = VM_EXITCODE_SPINUP_AP;
+ vmexit->u.spinup_ap.vcpu = dest;
+ vmexit->u.spinup_ap.rip = vec << PAGE_SHIFT;
+
+ /*
+ * XXX this assumes that the startup IPI always succeeds
+ */
+ vlapic2->boot_state = BS_RUNNING;
+ vm_activate_cpu(vlapic2->vm, dest);
+
+ return (0);
+ }
+ }
+
+ /*
+ * This will cause a return to userland.
+ */
+ return (1);
+}
+
+int
+vlapic_pending_intr(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ int idx, i, bitpos, vector;
+ uint32_t *irrptr, val;
+
+ irrptr = &lapic->irr0;
+
+ /*
+ * The x86 architecture reserves the the first 32 vectors for use
+ * by the processor.
+ */
+ for (i = 7; i > 0; i--) {
+ idx = i * 4;
+ val = atomic_load_acq_int(&irrptr[idx]);
+ bitpos = fls(val);
+ if (bitpos != 0) {
+ vector = i * 32 + (bitpos - 1);
+ if (PRIO(vector) > PRIO(lapic->ppr)) {
+ VLAPIC_CTR1(vlapic, "pending intr %d", vector);
+ return (vector);
+ } else
+ break;
+ }
+ }
+ VLAPIC_CTR0(vlapic, "no pending intr");
+ return (-1);
+}
+
+void
+vlapic_intr_accepted(struct vlapic *vlapic, int vector)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ uint32_t *irrptr, *isrptr;
+ int idx, stk_top;
+
+ /*
+ * clear the ready bit for vector being accepted in irr
+ * and set the vector as in service in isr.
+ */
+ idx = (vector / 32) * 4;
+
+ irrptr = &lapic->irr0;
+ atomic_clear_int(&irrptr[idx], 1 << (vector % 32));
+ VLAPIC_CTR_IRR(vlapic, "vlapic_intr_accepted");
+
+ isrptr = &lapic->isr0;
+ isrptr[idx] |= 1 << (vector % 32);
+ VLAPIC_CTR_ISR(vlapic, "vlapic_intr_accepted");
+
+ /*
+ * Update the PPR
+ */
+ vlapic->isrvec_stk_top++;
+
+ stk_top = vlapic->isrvec_stk_top;
+ if (stk_top >= ISRVEC_STK_SIZE)
+ panic("isrvec_stk_top overflow %d", stk_top);
+
+ vlapic->isrvec_stk[stk_top] = vector;
+ vlapic_update_ppr(vlapic);
+}
+
+int
+vlapic_op_mem_read(void* dev, uint64_t gpa, opsize_t size, uint64_t *data)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ struct LAPIC *lapic = &vlapic->apic;
+ uint64_t offset = gpa & ~(PAGE_SIZE);
+ uint32_t *reg;
+ int i;
+
+ if (offset > sizeof(*lapic)) {
+ *data = 0;
+ return 0;
+ }
+
+ offset &= ~3;
+ switch(offset)
+ {
+ case APIC_OFFSET_ID:
+ if (x2apic(vlapic))
+ *data = vlapic->vcpuid;
+ else
+ *data = vlapic->vcpuid << 24;
+ break;
+ case APIC_OFFSET_VER:
+ *data = lapic->version;
+ break;
+ case APIC_OFFSET_TPR:
+ *data = lapic->tpr;
+ break;
+ case APIC_OFFSET_APR:
+ *data = lapic->apr;
+ break;
+ case APIC_OFFSET_PPR:
+ *data = lapic->ppr;
+ break;
+ case APIC_OFFSET_EOI:
+ *data = lapic->eoi;
+ break;
+ case APIC_OFFSET_LDR:
+ *data = lapic->ldr;
+ break;
+ case APIC_OFFSET_DFR:
+ *data = lapic->dfr;
+ break;
+ case APIC_OFFSET_SVR:
+ *data = lapic->svr;
+ break;
+ case APIC_OFFSET_ISR0 ... APIC_OFFSET_ISR7:
+ i = (offset - APIC_OFFSET_ISR0) >> 2;
+ reg = &lapic->isr0;
+ *data = *(reg + i);
+ break;
+ case APIC_OFFSET_TMR0 ... APIC_OFFSET_TMR7:
+ i = (offset - APIC_OFFSET_TMR0) >> 2;
+ reg = &lapic->tmr0;
+ *data = *(reg + i);
+ break;
+ case APIC_OFFSET_IRR0 ... APIC_OFFSET_IRR7:
+ i = (offset - APIC_OFFSET_IRR0) >> 2;
+ reg = &lapic->irr0;
+ *data = atomic_load_acq_int(reg + i);
+ break;
+ case APIC_OFFSET_ESR:
+ *data = lapic->esr;
+ break;
+ case APIC_OFFSET_ICR_LOW:
+ *data = lapic->icr_lo;
+ break;
+ case APIC_OFFSET_ICR_HI:
+ *data = lapic->icr_hi;
+ break;
+ case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
+ reg = vlapic_get_lvt(vlapic, offset);
+ *data = *(reg);
+ break;
+ case APIC_OFFSET_ICR:
+ *data = lapic->icr_timer;
+ break;
+ case APIC_OFFSET_CCR:
+ *data = vlapic_get_ccr(vlapic);
+ break;
+ case APIC_OFFSET_DCR:
+ *data = lapic->dcr_timer;
+ break;
+ case APIC_OFFSET_RRR:
+ default:
+ *data = 0;
+ break;
+ }
+ return 0;
+}
+
+int
+vlapic_op_mem_write(void* dev, uint64_t gpa, opsize_t size, uint64_t data)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ struct LAPIC *lapic = &vlapic->apic;
+ uint64_t offset = gpa & ~(PAGE_SIZE);
+ uint32_t *reg;
+ int retval;
+
+ if (offset > sizeof(*lapic)) {
+ return 0;
+ }
+
+ retval = 0;
+ offset &= ~3;
+ switch(offset)
+ {
+ case APIC_OFFSET_ID:
+ break;
+ case APIC_OFFSET_TPR:
+ lapic->tpr = data & 0xff;
+ vlapic_update_ppr(vlapic);
+ break;
+ case APIC_OFFSET_EOI:
+ vlapic_process_eoi(vlapic);
+ break;
+ case APIC_OFFSET_LDR:
+ break;
+ case APIC_OFFSET_DFR:
+ break;
+ case APIC_OFFSET_SVR:
+ lapic->svr = data;
+ break;
+ case APIC_OFFSET_ICR_LOW:
+ if (!x2apic(vlapic)) {
+ data &= 0xffffffff;
+ data |= (uint64_t)lapic->icr_hi << 32;
+ }
+ retval = lapic_process_icr(vlapic, data);
+ break;
+ case APIC_OFFSET_ICR_HI:
+ if (!x2apic(vlapic)) {
+ retval = 0;
+ lapic->icr_hi = data;
+ }
+ break;
+ case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
+ reg = vlapic_get_lvt(vlapic, offset);
+ if (!(lapic->svr & APIC_SVR_ENABLE)) {
+ data |= APIC_LVT_M;
+ }
+ *reg = data;
+ // vlapic_dump_lvt(offset, reg);
+ break;
+ case APIC_OFFSET_ICR:
+ lapic->icr_timer = data;
+ vlapic_start_timer(vlapic, 0);
+ break;
+
+ case APIC_OFFSET_DCR:
+ lapic->dcr_timer = data;
+ vlapic->divisor = vlapic_timer_divisor(data);
+ break;
+
+ case APIC_OFFSET_ESR:
+ vlapic_update_errors(vlapic);
+ break;
+ case APIC_OFFSET_VER:
+ case APIC_OFFSET_APR:
+ case APIC_OFFSET_PPR:
+ case APIC_OFFSET_RRR:
+ case APIC_OFFSET_ISR0 ... APIC_OFFSET_ISR7:
+ case APIC_OFFSET_TMR0 ... APIC_OFFSET_TMR7:
+ case APIC_OFFSET_IRR0 ... APIC_OFFSET_IRR7:
+ case APIC_OFFSET_CCR:
+ default:
+ // Read only.
+ break;
+ }
+
+ return (retval);
+}
+
+int
+vlapic_timer_tick(struct vlapic *vlapic)
+{
+ int curticks, delta, periodic, fired;
+ uint32_t ccr;
+ uint32_t decrement, leftover;
+
+restart:
+ curticks = ticks;
+ delta = curticks - vlapic->ccr_ticks;
+
+ /* Local APIC timer is disabled */
+ if (vlapic->apic.icr_timer == 0)
+ return (-1);
+
+ /* One-shot mode and timer has already counted down to zero */
+ periodic = vlapic_periodic_timer(vlapic);
+ if (!periodic && vlapic->apic.ccr_timer == 0)
+ return (-1);
+ /*
+ * The 'curticks' and 'ccr_ticks' are out of sync by more than
+ * 2^31 ticks. We deal with this by restarting the timer.
+ */
+ if (delta < 0) {
+ vlapic_start_timer(vlapic, 0);
+ goto restart;
+ }
+
+ fired = 0;
+ decrement = (VLAPIC_BUS_FREQ / vlapic->divisor) / hz;
+
+ vlapic->ccr_ticks = curticks;
+ ccr = vlapic->apic.ccr_timer;
+
+ while (delta-- > 0) {
+ if (ccr > decrement) {
+ ccr -= decrement;
+ continue;
+ }
+
+ /* Trigger the local apic timer interrupt */
+ vlapic_fire_timer(vlapic);
+ if (periodic) {
+ leftover = decrement - ccr;
+ vlapic_start_timer(vlapic, leftover);
+ ccr = vlapic->apic.ccr_timer;
+ } else {
+ /*
+ * One-shot timer has counted down to zero.
+ */
+ ccr = 0;
+ }
+ fired = 1;
+ break;
+ }
+
+ vlapic->apic.ccr_timer = ccr;
+
+ if (!fired)
+ return ((ccr / decrement) + 1);
+ else
+ return (0);
+}
+
+struct vdev_ops vlapic_dev_ops = {
+ .name = "vlapic",
+ .init = vlapic_op_init,
+ .reset = vlapic_op_reset,
+ .halt = vlapic_op_halt,
+ .memread = vlapic_op_mem_read,
+ .memwrite = vlapic_op_mem_write,
+};
+static struct io_region vlapic_mmio[VM_MAXCPU];
+
+struct vlapic *
+vlapic_init(struct vm *vm, int vcpuid)
+{
+ struct vlapic *vlapic;
+
+ vlapic = malloc(sizeof(struct vlapic), M_VLAPIC, M_WAITOK | M_ZERO);
+ vlapic->vm = vm;
+ vlapic->vcpuid = vcpuid;
+
+ vlapic->msr_apicbase = DEFAULT_APIC_BASE | APICBASE_ENABLED;
+
+ if (vcpuid == 0)
+ vlapic->msr_apicbase |= APICBASE_BSP;
+
+ vlapic->ops = &vlapic_dev_ops;
+
+ vlapic->mmio = vlapic_mmio + vcpuid;
+ vlapic->mmio->base = DEFAULT_APIC_BASE;
+ vlapic->mmio->len = PAGE_SIZE;
+ vlapic->mmio->attr = MMIO_READ|MMIO_WRITE;
+ vlapic->mmio->vcpu = vcpuid;
+
+ vdev_register(&vlapic_dev_ops, vlapic);
+
+ vlapic_op_init(vlapic);
+
+ return (vlapic);
+}
+
+void
+vlapic_cleanup(struct vlapic *vlapic)
+{
+ vlapic_op_halt(vlapic);
+ vdev_unregister(vlapic);
+ free(vlapic, M_VLAPIC);
+}
+
+uint64_t
+vlapic_get_apicbase(struct vlapic *vlapic)
+{
+
+ return (vlapic->msr_apicbase);
+}
+
+void
+vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val)
+{
+ int err;
+ enum x2apic_state state;
+
+ err = vm_get_x2apic_state(vlapic->vm, vlapic->vcpuid, &state);
+ if (err)
+ panic("vlapic_set_apicbase: err %d fetching x2apic state", err);
+
+ if (state == X2APIC_DISABLED)
+ val &= ~APICBASE_X2APIC;
+
+ vlapic->msr_apicbase = val;
+}
+
+void
+vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state)
+{
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, vcpuid);
+
+ if (state == X2APIC_DISABLED)
+ vlapic->msr_apicbase &= ~APICBASE_X2APIC;
+}
diff --git a/sys/amd64/vmm/io/vlapic.h b/sys/amd64/vmm/io/vlapic.h
new file mode 100644
index 0000000..00de019
--- /dev/null
+++ b/sys/amd64/vmm/io/vlapic.h
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VLAPIC_H_
+#define _VLAPIC_H_
+
+#include "vdev.h"
+
+struct vm;
+
+/*
+ * Map of APIC Registers: Offset Description Access
+ */
+#define APIC_OFFSET_ID 0x20 // Local APIC ID R/W
+#define APIC_OFFSET_VER 0x30 // Local APIC Version R
+#define APIC_OFFSET_TPR 0x80 // Task Priority Register R/W
+#define APIC_OFFSET_APR 0x90 // Arbitration Priority Register R
+#define APIC_OFFSET_PPR 0xA0 // Processor Priority Register R
+#define APIC_OFFSET_EOI 0xB0 // EOI Register W
+#define APIC_OFFSET_RRR 0xC0 // Remote read R
+#define APIC_OFFSET_LDR 0xD0 // Logical Destination R/W
+#define APIC_OFFSET_DFR 0xE0 // Destination Format Register 0..27 R; 28..31 R/W
+#define APIC_OFFSET_SVR 0xF0 // Spurious Interrupt Vector Reg. 0..3 R; 4..9 R/W
+#define APIC_OFFSET_ISR0 0x100 // ISR 000-031 R
+#define APIC_OFFSET_ISR1 0x110 // ISR 032-063 R
+#define APIC_OFFSET_ISR2 0x120 // ISR 064-095 R
+#define APIC_OFFSET_ISR3 0x130 // ISR 095-128 R
+#define APIC_OFFSET_ISR4 0x140 // ISR 128-159 R
+#define APIC_OFFSET_ISR5 0x150 // ISR 160-191 R
+#define APIC_OFFSET_ISR6 0x160 // ISR 192-223 R
+#define APIC_OFFSET_ISR7 0x170 // ISR 224-255 R
+#define APIC_OFFSET_TMR0 0x180 // TMR 000-031 R
+#define APIC_OFFSET_TMR1 0x190 // TMR 032-063 R
+#define APIC_OFFSET_TMR2 0x1A0 // TMR 064-095 R
+#define APIC_OFFSET_TMR3 0x1B0 // TMR 095-128 R
+#define APIC_OFFSET_TMR4 0x1C0 // TMR 128-159 R
+#define APIC_OFFSET_TMR5 0x1D0 // TMR 160-191 R
+#define APIC_OFFSET_TMR6 0x1E0 // TMR 192-223 R
+#define APIC_OFFSET_TMR7 0x1F0 // TMR 224-255 R
+#define APIC_OFFSET_IRR0 0x200 // IRR 000-031 R
+#define APIC_OFFSET_IRR1 0x210 // IRR 032-063 R
+#define APIC_OFFSET_IRR2 0x220 // IRR 064-095 R
+#define APIC_OFFSET_IRR3 0x230 // IRR 095-128 R
+#define APIC_OFFSET_IRR4 0x240 // IRR 128-159 R
+#define APIC_OFFSET_IRR5 0x250 // IRR 160-191 R
+#define APIC_OFFSET_IRR6 0x260 // IRR 192-223 R
+#define APIC_OFFSET_IRR7 0x270 // IRR 224-255 R
+#define APIC_OFFSET_ESR 0x280 // Error Status Register R
+#define APIC_OFFSET_ICR_LOW 0x300 // Interrupt Command Reg. (0-31) R/W
+#define APIC_OFFSET_ICR_HI 0x310 // Interrupt Command Reg. (32-63) R/W
+#define APIC_OFFSET_TIMER_LVT 0x320 // Local Vector Table (Timer) R/W
+#define APIC_OFFSET_THERM_LVT 0x330 // Local Vector Table (Thermal) R/W (PIV+)
+#define APIC_OFFSET_PERF_LVT 0x340 // Local Vector Table (Performance) R/W (P6+)
+#define APIC_OFFSET_LINT0_LVT 0x350 // Local Vector Table (LINT0) R/W
+#define APIC_OFFSET_LINT1_LVT 0x360 // Local Vector Table (LINT1) R/W
+#define APIC_OFFSET_ERROR_LVT 0x370 // Local Vector Table (ERROR) R/W
+#define APIC_OFFSET_ICR 0x380 // Initial Count Reg. for Timer R/W
+#define APIC_OFFSET_CCR 0x390 // Current Count of Timer R
+#define APIC_OFFSET_DCR 0x3E0 // Timer Divide Configuration Reg. R/W
+
+/*
+ * 16 priority levels with at most one vector injected per level.
+ */
+#define ISRVEC_STK_SIZE (16 + 1)
+
+enum x2apic_state;
+
+struct vlapic *vlapic_init(struct vm *vm, int vcpuid);
+void vlapic_cleanup(struct vlapic *vlapic);
+
+int vlapic_op_mem_write(void* dev, uint64_t gpa,
+ opsize_t size, uint64_t data);
+
+int vlapic_op_mem_read(void* dev, uint64_t gpa,
+ opsize_t size, uint64_t *data);
+
+int vlapic_pending_intr(struct vlapic *vlapic);
+void vlapic_intr_accepted(struct vlapic *vlapic, int vector);
+void vlapic_set_intr_ready(struct vlapic *vlapic, int vector);
+int vlapic_timer_tick(struct vlapic *vlapic);
+
+uint64_t vlapic_get_apicbase(struct vlapic *vlapic);
+void vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val);
+void vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state s);
+
+#endif /* _VLAPIC_H_ */
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
new file mode 100644
index 0000000..82d4baa
--- /dev/null
+++ b/sys/amd64/vmm/vmm.c
@@ -0,0 +1,1038 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <sys/pcpu.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+
+#include <machine/vm.h>
+#include <machine/pcb.h>
+#include <machine/smp.h>
+#include <x86/apicreg.h>
+
+#include <machine/vmm.h>
+#include "vmm_host.h"
+#include "vmm_mem.h"
+#include "vmm_util.h"
+#include <machine/vmm_dev.h>
+#include "vlapic.h"
+#include "vmm_msr.h"
+#include "vmm_ipi.h"
+#include "vmm_stat.h"
+#include "vmm_lapic.h"
+
+#include "io/ppt.h"
+#include "io/iommu.h"
+
+struct vlapic;
+
+struct vcpu {
+ int flags;
+ enum vcpu_state state;
+ struct mtx mtx;
+ int pincpu; /* host cpuid this vcpu is bound to */
+ int hostcpu; /* host cpuid this vcpu last ran on */
+ uint64_t guest_msrs[VMM_MSR_NUM];
+ struct vlapic *vlapic;
+ int vcpuid;
+ struct savefpu *guestfpu; /* guest fpu state */
+ void *stats;
+ struct vm_exit exitinfo;
+ enum x2apic_state x2apic_state;
+ int nmi_pending;
+};
+#define VCPU_F_PINNED 0x0001
+
+#define VCPU_PINCPU(vm, vcpuid) \
+ ((vm->vcpu[vcpuid].flags & VCPU_F_PINNED) ? vm->vcpu[vcpuid].pincpu : -1)
+
+#define VCPU_UNPIN(vm, vcpuid) (vm->vcpu[vcpuid].flags &= ~VCPU_F_PINNED)
+
+#define VCPU_PIN(vm, vcpuid, host_cpuid) \
+do { \
+ vm->vcpu[vcpuid].flags |= VCPU_F_PINNED; \
+ vm->vcpu[vcpuid].pincpu = host_cpuid; \
+} while(0)
+
+#define vcpu_lock_init(v) mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN)
+#define vcpu_lock(v) mtx_lock_spin(&((v)->mtx))
+#define vcpu_unlock(v) mtx_unlock_spin(&((v)->mtx))
+
+#define VM_MAX_MEMORY_SEGMENTS 2
+
+struct vm {
+ void *cookie; /* processor-specific data */
+ void *iommu; /* iommu-specific data */
+ struct vcpu vcpu[VM_MAXCPU];
+ int num_mem_segs;
+ struct vm_memory_segment mem_segs[VM_MAX_MEMORY_SEGMENTS];
+ char name[VM_MAX_NAMELEN];
+
+ /*
+ * Set of active vcpus.
+ * An active vcpu is one that has been started implicitly (BSP) or
+ * explicitly (AP) by sending it a startup ipi.
+ */
+ cpuset_t active_cpus;
+};
+
+static struct vmm_ops *ops;
+#define VMM_INIT() (ops != NULL ? (*ops->init)() : 0)
+#define VMM_CLEANUP() (ops != NULL ? (*ops->cleanup)() : 0)
+
+#define VMINIT(vm) (ops != NULL ? (*ops->vminit)(vm): NULL)
+#define VMRUN(vmi, vcpu, rip) \
+ (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip) : ENXIO)
+#define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL)
+#define VMMMAP_SET(vmi, gpa, hpa, len, attr, prot, spm) \
+ (ops != NULL ? \
+ (*ops->vmmmap_set)(vmi, gpa, hpa, len, attr, prot, spm) : \
+ ENXIO)
+#define VMMMAP_GET(vmi, gpa) \
+ (ops != NULL ? (*ops->vmmmap_get)(vmi, gpa) : ENXIO)
+#define VMGETREG(vmi, vcpu, num, retval) \
+ (ops != NULL ? (*ops->vmgetreg)(vmi, vcpu, num, retval) : ENXIO)
+#define VMSETREG(vmi, vcpu, num, val) \
+ (ops != NULL ? (*ops->vmsetreg)(vmi, vcpu, num, val) : ENXIO)
+#define VMGETDESC(vmi, vcpu, num, desc) \
+ (ops != NULL ? (*ops->vmgetdesc)(vmi, vcpu, num, desc) : ENXIO)
+#define VMSETDESC(vmi, vcpu, num, desc) \
+ (ops != NULL ? (*ops->vmsetdesc)(vmi, vcpu, num, desc) : ENXIO)
+#define VMINJECT(vmi, vcpu, type, vec, ec, ecv) \
+ (ops != NULL ? (*ops->vminject)(vmi, vcpu, type, vec, ec, ecv) : ENXIO)
+#define VMGETCAP(vmi, vcpu, num, retval) \
+ (ops != NULL ? (*ops->vmgetcap)(vmi, vcpu, num, retval) : ENXIO)
+#define VMSETCAP(vmi, vcpu, num, val) \
+ (ops != NULL ? (*ops->vmsetcap)(vmi, vcpu, num, val) : ENXIO)
+
+#define fpu_start_emulating() load_cr0(rcr0() | CR0_TS)
+#define fpu_stop_emulating() clts()
+
+static MALLOC_DEFINE(M_VM, "vm", "vm");
+CTASSERT(VMM_MSR_NUM <= 64); /* msr_mask can keep track of up to 64 msrs */
+
+/* statistics */
+static VMM_STAT_DEFINE(VCPU_TOTAL_RUNTIME, "vcpu total runtime");
+
+static void
+vcpu_cleanup(struct vcpu *vcpu)
+{
+ vlapic_cleanup(vcpu->vlapic);
+ vmm_stat_free(vcpu->stats);
+ fpu_save_area_free(vcpu->guestfpu);
+}
+
+static void
+vcpu_init(struct vm *vm, uint32_t vcpu_id)
+{
+ struct vcpu *vcpu;
+
+ vcpu = &vm->vcpu[vcpu_id];
+
+ vcpu_lock_init(vcpu);
+ vcpu->hostcpu = NOCPU;
+ vcpu->vcpuid = vcpu_id;
+ vcpu->vlapic = vlapic_init(vm, vcpu_id);
+ vm_set_x2apic_state(vm, vcpu_id, X2APIC_ENABLED);
+ vcpu->guestfpu = fpu_save_area_alloc();
+ fpu_save_area_reset(vcpu->guestfpu);
+ vcpu->stats = vmm_stat_alloc();
+}
+
+struct vm_exit *
+vm_exitinfo(struct vm *vm, int cpuid)
+{
+ struct vcpu *vcpu;
+
+ if (cpuid < 0 || cpuid >= VM_MAXCPU)
+ panic("vm_exitinfo: invalid cpuid %d", cpuid);
+
+ vcpu = &vm->vcpu[cpuid];
+
+ return (&vcpu->exitinfo);
+}
+
+static int
+vmm_init(void)
+{
+ int error;
+
+ vmm_host_state_init();
+ vmm_ipi_init();
+
+ error = vmm_mem_init();
+ if (error)
+ return (error);
+
+ if (vmm_is_intel())
+ ops = &vmm_ops_intel;
+ else if (vmm_is_amd())
+ ops = &vmm_ops_amd;
+ else
+ return (ENXIO);
+
+ vmm_msr_init();
+
+ return (VMM_INIT());
+}
+
+static int
+vmm_handler(module_t mod, int what, void *arg)
+{
+ int error;
+
+ switch (what) {
+ case MOD_LOAD:
+ vmmdev_init();
+ iommu_init();
+ error = vmm_init();
+ break;
+ case MOD_UNLOAD:
+ error = vmmdev_cleanup();
+ if (error == 0) {
+ iommu_cleanup();
+ vmm_ipi_cleanup();
+ error = VMM_CLEANUP();
+ }
+ break;
+ default:
+ error = 0;
+ break;
+ }
+ return (error);
+}
+
+static moduledata_t vmm_kmod = {
+ "vmm",
+ vmm_handler,
+ NULL
+};
+
+/*
+ * vmm initialization has the following dependencies:
+ *
+ * - iommu initialization must happen after the pci passthru driver has had
+ * a chance to attach to any passthru devices (after SI_SUB_CONFIGURE).
+ *
+ * - VT-x initialization requires smp_rendezvous() and therefore must happen
+ * after SMP is fully functional (after SI_SUB_SMP).
+ */
+DECLARE_MODULE(vmm, vmm_kmod, SI_SUB_SMP + 1, SI_ORDER_ANY);
+MODULE_VERSION(vmm, 1);
+
+SYSCTL_NODE(_hw, OID_AUTO, vmm, CTLFLAG_RW, NULL, NULL);
+
+struct vm *
+vm_create(const char *name)
+{
+ int i;
+ struct vm *vm;
+ vm_paddr_t maxaddr;
+
+ const int BSP = 0;
+
+ if (name == NULL || strlen(name) >= VM_MAX_NAMELEN)
+ return (NULL);
+
+ vm = malloc(sizeof(struct vm), M_VM, M_WAITOK | M_ZERO);
+ strcpy(vm->name, name);
+ vm->cookie = VMINIT(vm);
+
+ for (i = 0; i < VM_MAXCPU; i++) {
+ vcpu_init(vm, i);
+ guest_msrs_init(vm, i);
+ }
+
+ maxaddr = vmm_mem_maxaddr();
+ vm->iommu = iommu_create_domain(maxaddr);
+ vm_activate_cpu(vm, BSP);
+
+ return (vm);
+}
+
+static void
+vm_free_mem_seg(struct vm *vm, struct vm_memory_segment *seg)
+{
+ size_t len;
+ vm_paddr_t hpa;
+ void *host_domain;
+
+ host_domain = iommu_host_domain();
+
+ len = 0;
+ while (len < seg->len) {
+ hpa = vm_gpa2hpa(vm, seg->gpa + len, PAGE_SIZE);
+ if (hpa == (vm_paddr_t)-1) {
+ panic("vm_free_mem_segs: cannot free hpa "
+ "associated with gpa 0x%016lx", seg->gpa + len);
+ }
+
+ /*
+ * Remove the 'gpa' to 'hpa' mapping in VMs domain.
+ * And resurrect the 1:1 mapping for 'hpa' in 'host_domain'.
+ */
+ iommu_remove_mapping(vm->iommu, seg->gpa + len, PAGE_SIZE);
+ iommu_create_mapping(host_domain, hpa, hpa, PAGE_SIZE);
+
+ vmm_mem_free(hpa, PAGE_SIZE);
+
+ len += PAGE_SIZE;
+ }
+
+ /*
+ * Invalidate cached translations associated with 'vm->iommu' since
+ * we have now moved some pages from it.
+ */
+ iommu_invalidate_tlb(vm->iommu);
+
+ bzero(seg, sizeof(struct vm_memory_segment));
+}
+
+void
+vm_destroy(struct vm *vm)
+{
+ int i;
+
+ ppt_unassign_all(vm);
+
+ for (i = 0; i < vm->num_mem_segs; i++)
+ vm_free_mem_seg(vm, &vm->mem_segs[i]);
+
+ vm->num_mem_segs = 0;
+
+ for (i = 0; i < VM_MAXCPU; i++)
+ vcpu_cleanup(&vm->vcpu[i]);
+
+ iommu_destroy_domain(vm->iommu);
+
+ VMCLEANUP(vm->cookie);
+
+ free(vm, M_VM);
+}
+
+const char *
+vm_name(struct vm *vm)
+{
+ return (vm->name);
+}
+
+int
+vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
+{
+ const boolean_t spok = TRUE; /* superpage mappings are ok */
+
+ return (VMMMAP_SET(vm->cookie, gpa, hpa, len, VM_MEMATTR_UNCACHEABLE,
+ VM_PROT_RW, spok));
+}
+
+int
+vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len)
+{
+ const boolean_t spok = TRUE; /* superpage mappings are ok */
+
+ return (VMMMAP_SET(vm->cookie, gpa, 0, len, 0,
+ VM_PROT_NONE, spok));
+}
+
+/*
+ * Returns TRUE if 'gpa' is available for allocation and FALSE otherwise
+ */
+static boolean_t
+vm_gpa_available(struct vm *vm, vm_paddr_t gpa)
+{
+ int i;
+ vm_paddr_t gpabase, gpalimit;
+
+ if (gpa & PAGE_MASK)
+ panic("vm_gpa_available: gpa (0x%016lx) not page aligned", gpa);
+
+ for (i = 0; i < vm->num_mem_segs; i++) {
+ gpabase = vm->mem_segs[i].gpa;
+ gpalimit = gpabase + vm->mem_segs[i].len;
+ if (gpa >= gpabase && gpa < gpalimit)
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+int
+vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len)
+{
+ int error, available, allocated;
+ struct vm_memory_segment *seg;
+ vm_paddr_t g, hpa;
+ void *host_domain;
+
+ const boolean_t spok = TRUE; /* superpage mappings are ok */
+
+ if ((gpa & PAGE_MASK) || (len & PAGE_MASK) || len == 0)
+ return (EINVAL);
+
+ available = allocated = 0;
+ g = gpa;
+ while (g < gpa + len) {
+ if (vm_gpa_available(vm, g))
+ available++;
+ else
+ allocated++;
+
+ g += PAGE_SIZE;
+ }
+
+ /*
+ * If there are some allocated and some available pages in the address
+ * range then it is an error.
+ */
+ if (allocated && available)
+ return (EINVAL);
+
+ /*
+ * If the entire address range being requested has already been
+ * allocated then there isn't anything more to do.
+ */
+ if (allocated && available == 0)
+ return (0);
+
+ if (vm->num_mem_segs >= VM_MAX_MEMORY_SEGMENTS)
+ return (E2BIG);
+
+ host_domain = iommu_host_domain();
+
+ seg = &vm->mem_segs[vm->num_mem_segs];
+
+ error = 0;
+ seg->gpa = gpa;
+ seg->len = 0;
+ while (seg->len < len) {
+ hpa = vmm_mem_alloc(PAGE_SIZE);
+ if (hpa == 0) {
+ error = ENOMEM;
+ break;
+ }
+
+ error = VMMMAP_SET(vm->cookie, gpa + seg->len, hpa, PAGE_SIZE,
+ VM_MEMATTR_WRITE_BACK, VM_PROT_ALL, spok);
+ if (error)
+ break;
+
+ /*
+ * Remove the 1:1 mapping for 'hpa' from the 'host_domain'.
+ * Add mapping for 'gpa + seg->len' to 'hpa' in the VMs domain.
+ */
+ iommu_remove_mapping(host_domain, hpa, PAGE_SIZE);
+ iommu_create_mapping(vm->iommu, gpa + seg->len, hpa, PAGE_SIZE);
+
+ seg->len += PAGE_SIZE;
+ }
+
+ if (error) {
+ vm_free_mem_seg(vm, seg);
+ return (error);
+ }
+
+ /*
+ * Invalidate cached translations associated with 'host_domain' since
+ * we have now moved some pages from it.
+ */
+ iommu_invalidate_tlb(host_domain);
+
+ vm->num_mem_segs++;
+
+ return (0);
+}
+
+vm_paddr_t
+vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t len)
+{
+ vm_paddr_t nextpage;
+
+ nextpage = rounddown(gpa + PAGE_SIZE, PAGE_SIZE);
+ if (len > nextpage - gpa)
+ panic("vm_gpa2hpa: invalid gpa/len: 0x%016lx/%lu", gpa, len);
+
+ return (VMMMAP_GET(vm->cookie, gpa));
+}
+
+int
+vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase,
+ struct vm_memory_segment *seg)
+{
+ int i;
+
+ for (i = 0; i < vm->num_mem_segs; i++) {
+ if (gpabase == vm->mem_segs[i].gpa) {
+ *seg = vm->mem_segs[i];
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+int
+vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval)
+{
+
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (reg >= VM_REG_LAST)
+ return (EINVAL);
+
+ return (VMGETREG(vm->cookie, vcpu, reg, retval));
+}
+
+int
+vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val)
+{
+
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (reg >= VM_REG_LAST)
+ return (EINVAL);
+
+ return (VMSETREG(vm->cookie, vcpu, reg, val));
+}
+
+static boolean_t
+is_descriptor_table(int reg)
+{
+
+ switch (reg) {
+ case VM_REG_GUEST_IDTR:
+ case VM_REG_GUEST_GDTR:
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+}
+
+static boolean_t
+is_segment_register(int reg)
+{
+
+ switch (reg) {
+ case VM_REG_GUEST_ES:
+ case VM_REG_GUEST_CS:
+ case VM_REG_GUEST_SS:
+ case VM_REG_GUEST_DS:
+ case VM_REG_GUEST_FS:
+ case VM_REG_GUEST_GS:
+ case VM_REG_GUEST_TR:
+ case VM_REG_GUEST_LDTR:
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+}
+
+int
+vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
+ struct seg_desc *desc)
+{
+
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (!is_segment_register(reg) && !is_descriptor_table(reg))
+ return (EINVAL);
+
+ return (VMGETDESC(vm->cookie, vcpu, reg, desc));
+}
+
+int
+vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
+ struct seg_desc *desc)
+{
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (!is_segment_register(reg) && !is_descriptor_table(reg))
+ return (EINVAL);
+
+ return (VMSETDESC(vm->cookie, vcpu, reg, desc));
+}
+
+int
+vm_get_pinning(struct vm *vm, int vcpuid, int *cpuid)
+{
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ *cpuid = VCPU_PINCPU(vm, vcpuid);
+
+ return (0);
+}
+
+int
+vm_set_pinning(struct vm *vm, int vcpuid, int host_cpuid)
+{
+ struct thread *td;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ td = curthread; /* XXXSMP only safe when muxing vcpus */
+
+ /* unpin */
+ if (host_cpuid < 0) {
+ VCPU_UNPIN(vm, vcpuid);
+ thread_lock(td);
+ sched_unbind(td);
+ thread_unlock(td);
+ return (0);
+ }
+
+ if (CPU_ABSENT(host_cpuid))
+ return (EINVAL);
+
+ /*
+ * XXX we should check that 'host_cpuid' has not already been pinned
+ * by another vm.
+ */
+ thread_lock(td);
+ sched_bind(td, host_cpuid);
+ thread_unlock(td);
+ VCPU_PIN(vm, vcpuid, host_cpuid);
+
+ return (0);
+}
+
+static void
+restore_guest_fpustate(struct vcpu *vcpu)
+{
+
+ /* flush host state to the pcb */
+ fpuexit(curthread);
+
+ /* restore guest FPU state */
+ fpu_stop_emulating();
+ fpurestore(vcpu->guestfpu);
+
+ /*
+ * The FPU is now "dirty" with the guest's state so turn on emulation
+ * to trap any access to the FPU by the host.
+ */
+ fpu_start_emulating();
+}
+
+static void
+save_guest_fpustate(struct vcpu *vcpu)
+{
+
+ if ((rcr0() & CR0_TS) == 0)
+ panic("fpu emulation not enabled in host!");
+
+ /* save guest FPU state */
+ fpu_stop_emulating();
+ fpusave(vcpu->guestfpu);
+ fpu_start_emulating();
+}
+
+static VMM_STAT_DEFINE(VCPU_IDLE_TICKS, "number of ticks vcpu was idle");
+
+int
+vm_run(struct vm *vm, struct vm_run *vmrun)
+{
+ int error, vcpuid, sleepticks, t;
+ struct vcpu *vcpu;
+ struct pcb *pcb;
+ uint64_t tscval, rip;
+ struct vm_exit *vme;
+
+ vcpuid = vmrun->cpuid;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ vcpu = &vm->vcpu[vcpuid];
+ vme = &vmrun->vm_exit;
+ rip = vmrun->rip;
+restart:
+ critical_enter();
+
+ tscval = rdtsc();
+
+ pcb = PCPU_GET(curpcb);
+ set_pcb_flags(pcb, PCB_FULL_IRET);
+
+ restore_guest_msrs(vm, vcpuid);
+ restore_guest_fpustate(vcpu);
+
+ vcpu->hostcpu = curcpu;
+ error = VMRUN(vm->cookie, vcpuid, rip);
+ vcpu->hostcpu = NOCPU;
+
+ save_guest_fpustate(vcpu);
+ restore_host_msrs(vm, vcpuid);
+
+ vmm_stat_incr(vm, vcpuid, VCPU_TOTAL_RUNTIME, rdtsc() - tscval);
+
+ /* copy the exit information */
+ bcopy(&vcpu->exitinfo, vme, sizeof(struct vm_exit));
+
+ critical_exit();
+
+ /*
+ * Oblige the guest's desire to 'hlt' by sleeping until the vcpu
+ * is ready to run.
+ */
+ if (error == 0 && vme->exitcode == VM_EXITCODE_HLT) {
+ vcpu_lock(vcpu);
+
+ /*
+ * Figure out the number of host ticks until the next apic
+ * timer interrupt in the guest.
+ */
+ sleepticks = lapic_timer_tick(vm, vcpuid);
+
+ /*
+ * If the guest local apic timer is disabled then sleep for
+ * a long time but not forever.
+ */
+ if (sleepticks < 0)
+ sleepticks = hz;
+
+ /*
+ * Do a final check for pending NMI or interrupts before
+ * really putting this thread to sleep.
+ *
+ * These interrupts could have happened any time after we
+ * returned from VMRUN() and before we grabbed the vcpu lock.
+ */
+ if (!vm_nmi_pending(vm, vcpuid) &&
+ lapic_pending_intr(vm, vcpuid) < 0) {
+ if (sleepticks <= 0)
+ panic("invalid sleepticks %d", sleepticks);
+ t = ticks;
+ msleep_spin(vcpu, &vcpu->mtx, "vmidle", sleepticks);
+ vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t);
+ }
+
+ vcpu_unlock(vcpu);
+
+ rip = vme->rip + vme->inst_length;
+ goto restart;
+ }
+
+ return (error);
+}
+
+int
+vm_inject_event(struct vm *vm, int vcpuid, int type,
+ int vector, uint32_t code, int code_valid)
+{
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ if ((type > VM_EVENT_NONE && type < VM_EVENT_MAX) == 0)
+ return (EINVAL);
+
+ if (vector < 0 || vector > 255)
+ return (EINVAL);
+
+ return (VMINJECT(vm->cookie, vcpuid, type, vector, code, code_valid));
+}
+
+static VMM_STAT_DEFINE(VCPU_NMI_COUNT, "number of NMIs delivered to vcpu");
+
+int
+vm_inject_nmi(struct vm *vm, int vcpuid)
+{
+ struct vcpu *vcpu;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ vcpu->nmi_pending = 1;
+ vm_interrupt_hostcpu(vm, vcpuid);
+ return (0);
+}
+
+int
+vm_nmi_pending(struct vm *vm, int vcpuid)
+{
+ struct vcpu *vcpu;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ panic("vm_nmi_pending: invalid vcpuid %d", vcpuid);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ return (vcpu->nmi_pending);
+}
+
+void
+vm_nmi_clear(struct vm *vm, int vcpuid)
+{
+ struct vcpu *vcpu;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ panic("vm_nmi_pending: invalid vcpuid %d", vcpuid);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ if (vcpu->nmi_pending == 0)
+ panic("vm_nmi_clear: inconsistent nmi_pending state");
+
+ vcpu->nmi_pending = 0;
+ vmm_stat_incr(vm, vcpuid, VCPU_NMI_COUNT, 1);
+}
+
+int
+vm_get_capability(struct vm *vm, int vcpu, int type, int *retval)
+{
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (type < 0 || type >= VM_CAP_MAX)
+ return (EINVAL);
+
+ return (VMGETCAP(vm->cookie, vcpu, type, retval));
+}
+
+int
+vm_set_capability(struct vm *vm, int vcpu, int type, int val)
+{
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (type < 0 || type >= VM_CAP_MAX)
+ return (EINVAL);
+
+ return (VMSETCAP(vm->cookie, vcpu, type, val));
+}
+
+uint64_t *
+vm_guest_msrs(struct vm *vm, int cpu)
+{
+ return (vm->vcpu[cpu].guest_msrs);
+}
+
+struct vlapic *
+vm_lapic(struct vm *vm, int cpu)
+{
+ return (vm->vcpu[cpu].vlapic);
+}
+
+boolean_t
+vmm_is_pptdev(int bus, int slot, int func)
+{
+ int found, i, n;
+ int b, s, f;
+ char *val, *cp, *cp2;
+
+ /*
+ * XXX
+ * The length of an environment variable is limited to 128 bytes which
+ * puts an upper limit on the number of passthru devices that may be
+ * specified using a single environment variable.
+ *
+ * Work around this by scanning multiple environment variable
+ * names instead of a single one - yuck!
+ */
+ const char *names[] = { "pptdevs", "pptdevs2", "pptdevs3", NULL };
+
+ /* set pptdevs="1/2/3 4/5/6 7/8/9 10/11/12" */
+ found = 0;
+ for (i = 0; names[i] != NULL && !found; i++) {
+ cp = val = getenv(names[i]);
+ while (cp != NULL && *cp != '\0') {
+ if ((cp2 = strchr(cp, ' ')) != NULL)
+ *cp2 = '\0';
+
+ n = sscanf(cp, "%d/%d/%d", &b, &s, &f);
+ if (n == 3 && bus == b && slot == s && func == f) {
+ found = 1;
+ break;
+ }
+
+ if (cp2 != NULL)
+ *cp2++ = ' ';
+
+ cp = cp2;
+ }
+ freeenv(val);
+ }
+ return (found);
+}
+
+void *
+vm_iommu_domain(struct vm *vm)
+{
+
+ return (vm->iommu);
+}
+
+int
+vcpu_set_state(struct vm *vm, int vcpuid, enum vcpu_state state)
+{
+ int error;
+ struct vcpu *vcpu;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ panic("vm_set_run_state: invalid vcpuid %d", vcpuid);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ vcpu_lock(vcpu);
+
+ /*
+ * The following state transitions are allowed:
+ * IDLE -> RUNNING -> IDLE
+ * IDLE -> CANNOT_RUN -> IDLE
+ */
+ if ((vcpu->state == VCPU_IDLE && state != VCPU_IDLE) ||
+ (vcpu->state != VCPU_IDLE && state == VCPU_IDLE)) {
+ error = 0;
+ vcpu->state = state;
+ } else {
+ error = EBUSY;
+ }
+
+ vcpu_unlock(vcpu);
+
+ return (error);
+}
+
+enum vcpu_state
+vcpu_get_state(struct vm *vm, int vcpuid)
+{
+ struct vcpu *vcpu;
+ enum vcpu_state state;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ panic("vm_get_run_state: invalid vcpuid %d", vcpuid);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ vcpu_lock(vcpu);
+ state = vcpu->state;
+ vcpu_unlock(vcpu);
+
+ return (state);
+}
+
+void
+vm_activate_cpu(struct vm *vm, int vcpuid)
+{
+
+ if (vcpuid >= 0 && vcpuid < VM_MAXCPU)
+ CPU_SET(vcpuid, &vm->active_cpus);
+}
+
+cpuset_t
+vm_active_cpus(struct vm *vm)
+{
+
+ return (vm->active_cpus);
+}
+
+void *
+vcpu_stats(struct vm *vm, int vcpuid)
+{
+
+ return (vm->vcpu[vcpuid].stats);
+}
+
+int
+vm_get_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state *state)
+{
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ *state = vm->vcpu[vcpuid].x2apic_state;
+
+ return (0);
+}
+
+int
+vm_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state)
+{
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (state < 0 || state >= X2APIC_STATE_LAST)
+ return (EINVAL);
+
+ vm->vcpu[vcpuid].x2apic_state = state;
+
+ vlapic_set_x2apic_state(vm, vcpuid, state);
+
+ return (0);
+}
+
+void
+vm_interrupt_hostcpu(struct vm *vm, int vcpuid)
+{
+ int hostcpu;
+ struct vcpu *vcpu;
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ vcpu_lock(vcpu);
+ hostcpu = vcpu->hostcpu;
+ if (hostcpu == NOCPU) {
+ /*
+ * If the vcpu is 'RUNNING' but without a valid 'hostcpu' then
+ * the host thread must be sleeping waiting for an event to
+ * kick the vcpu out of 'hlt'.
+ *
+ * XXX this is racy because the condition exists right before
+ * and after calling VMRUN() in vm_run(). The wakeup() is
+ * benign in this case.
+ */
+ if (vcpu->state == VCPU_RUNNING)
+ wakeup_one(vcpu);
+ } else {
+ if (vcpu->state != VCPU_RUNNING)
+ panic("invalid vcpu state %d", vcpu->state);
+ if (hostcpu != curcpu)
+ ipi_cpu(hostcpu, vmm_ipinum);
+ }
+ vcpu_unlock(vcpu);
+}
diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c
new file mode 100644
index 0000000..0150ebd
--- /dev/null
+++ b/sys/amd64/vmm/vmm_dev.c
@@ -0,0 +1,538 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+#include <sys/conf.h>
+#include <sys/sysctl.h>
+#include <sys/libkern.h>
+#include <sys/ioccom.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+
+#include <machine/vmm.h>
+#include "vmm_lapic.h"
+#include "vmm_stat.h"
+#include "vmm_mem.h"
+#include "io/ppt.h"
+#include <machine/vmm_dev.h>
+
+struct vmmdev_softc {
+ struct vm *vm; /* vm instance cookie */
+ struct cdev *cdev;
+ SLIST_ENTRY(vmmdev_softc) link;
+};
+static SLIST_HEAD(, vmmdev_softc) head;
+
+static struct mtx vmmdev_mtx;
+
+static MALLOC_DEFINE(M_VMMDEV, "vmmdev", "vmmdev");
+
+SYSCTL_DECL(_hw_vmm);
+
+static struct vmmdev_softc *
+vmmdev_lookup(const char *name)
+{
+ struct vmmdev_softc *sc;
+
+#ifdef notyet /* XXX kernel is not compiled with invariants */
+ mtx_assert(&vmmdev_mtx, MA_OWNED);
+#endif
+
+ SLIST_FOREACH(sc, &head, link) {
+ if (strcmp(name, vm_name(sc->vm)) == 0)
+ break;
+ }
+
+ return (sc);
+}
+
+static struct vmmdev_softc *
+vmmdev_lookup2(struct cdev *cdev)
+{
+
+ return (cdev->si_drv1);
+}
+
+static int
+vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags)
+{
+ int error, off, c;
+ vm_paddr_t hpa, gpa;
+ struct vmmdev_softc *sc;
+
+ static char zerobuf[PAGE_SIZE];
+
+ error = 0;
+ mtx_lock(&vmmdev_mtx);
+ sc = vmmdev_lookup2(cdev);
+ if (sc == NULL)
+ error = ENXIO;
+
+ while (uio->uio_resid > 0 && error == 0) {
+ gpa = uio->uio_offset;
+ off = gpa & PAGE_MASK;
+ c = min(uio->uio_resid, PAGE_SIZE - off);
+
+ /*
+ * The VM has a hole in its physical memory map. If we want to
+ * use 'dd' to inspect memory beyond the hole we need to
+ * provide bogus data for memory that lies in the hole.
+ *
+ * Since this device does not support lseek(2), dd(1) will
+ * read(2) blocks of data to simulate the lseek(2).
+ */
+ hpa = vm_gpa2hpa(sc->vm, gpa, c);
+ if (hpa == (vm_paddr_t)-1) {
+ if (uio->uio_rw == UIO_READ)
+ error = uiomove(zerobuf, c, uio);
+ else
+ error = EFAULT;
+ } else
+ error = uiomove((void *)PHYS_TO_DMAP(hpa), c, uio);
+ }
+
+ mtx_unlock(&vmmdev_mtx);
+ return (error);
+}
+
+static int
+vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
+ struct thread *td)
+{
+ int error, vcpu, state_changed;
+ enum vcpu_state new_state;
+ struct vmmdev_softc *sc;
+ struct vm_memory_segment *seg;
+ struct vm_register *vmreg;
+ struct vm_seg_desc* vmsegdesc;
+ struct vm_pin *vmpin;
+ struct vm_run *vmrun;
+ struct vm_event *vmevent;
+ struct vm_lapic_irq *vmirq;
+ struct vm_capability *vmcap;
+ struct vm_pptdev *pptdev;
+ struct vm_pptdev_mmio *pptmmio;
+ struct vm_pptdev_msi *pptmsi;
+ struct vm_pptdev_msix *pptmsix;
+ struct vm_nmi *vmnmi;
+ struct vm_stats *vmstats;
+ struct vm_stat_desc *statdesc;
+ struct vm_x2apic *x2apic;
+
+ sc = vmmdev_lookup2(cdev);
+ if (sc == NULL)
+ return (ENXIO);
+
+ vcpu = -1;
+ state_changed = 0;
+
+ /*
+ * Some VMM ioctls can operate only on vcpus that are not running.
+ */
+ switch (cmd) {
+ case VM_RUN:
+ case VM_SET_PINNING:
+ case VM_GET_REGISTER:
+ case VM_SET_REGISTER:
+ case VM_GET_SEGMENT_DESCRIPTOR:
+ case VM_SET_SEGMENT_DESCRIPTOR:
+ case VM_INJECT_EVENT:
+ case VM_GET_CAPABILITY:
+ case VM_SET_CAPABILITY:
+ case VM_PPTDEV_MSI:
+ case VM_PPTDEV_MSIX:
+ case VM_SET_X2APIC_STATE:
+ /*
+ * XXX fragile, handle with care
+ * Assumes that the first field of the ioctl data is the vcpu.
+ */
+ vcpu = *(int *)data;
+ if (vcpu < 0 || vcpu >= VM_MAXCPU) {
+ error = EINVAL;
+ goto done;
+ }
+
+ if (cmd == VM_RUN)
+ new_state = VCPU_RUNNING;
+ else
+ new_state = VCPU_CANNOT_RUN;
+
+ error = vcpu_set_state(sc->vm, vcpu, new_state);
+ if (error)
+ goto done;
+
+ state_changed = 1;
+ break;
+
+ case VM_MAP_PPTDEV_MMIO:
+ case VM_BIND_PPTDEV:
+ case VM_UNBIND_PPTDEV:
+ case VM_MAP_MEMORY:
+ /*
+ * ioctls that operate on the entire virtual machine must
+ * prevent all vcpus from running.
+ */
+ error = 0;
+ for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++) {
+ error = vcpu_set_state(sc->vm, vcpu, VCPU_CANNOT_RUN);
+ if (error)
+ break;
+ }
+
+ if (error) {
+ while (--vcpu >= 0)
+ vcpu_set_state(sc->vm, vcpu, VCPU_IDLE);
+ goto done;
+ }
+
+ state_changed = 2;
+ break;
+
+ default:
+ break;
+ }
+
+ switch(cmd) {
+ case VM_RUN:
+ vmrun = (struct vm_run *)data;
+ error = vm_run(sc->vm, vmrun);
+ break;
+ case VM_STAT_DESC: {
+ const char *desc;
+ statdesc = (struct vm_stat_desc *)data;
+ desc = vmm_stat_desc(statdesc->index);
+ if (desc != NULL) {
+ error = 0;
+ strlcpy(statdesc->desc, desc, sizeof(statdesc->desc));
+ } else
+ error = EINVAL;
+ break;
+ }
+ case VM_STATS: {
+ CTASSERT(MAX_VM_STATS >= MAX_VMM_STAT_TYPES);
+ vmstats = (struct vm_stats *)data;
+ getmicrotime(&vmstats->tv);
+ error = vmm_stat_copy(sc->vm, vmstats->cpuid,
+ &vmstats->num_entries, vmstats->statbuf);
+ break;
+ }
+ case VM_PPTDEV_MSI:
+ 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->numvec);
+ break;
+ case VM_PPTDEV_MSIX:
+ pptmsix = (struct vm_pptdev_msix *)data;
+ error = ppt_setup_msix(sc->vm, pptmsix->vcpu,
+ pptmsix->bus, pptmsix->slot,
+ pptmsix->func, pptmsix->idx,
+ pptmsix->msg, pptmsix->vector_control,
+ pptmsix->addr);
+ break;
+ case VM_MAP_PPTDEV_MMIO:
+ pptmmio = (struct vm_pptdev_mmio *)data;
+ error = ppt_map_mmio(sc->vm, pptmmio->bus, pptmmio->slot,
+ pptmmio->func, pptmmio->gpa, pptmmio->len,
+ pptmmio->hpa);
+ break;
+ case VM_BIND_PPTDEV:
+ pptdev = (struct vm_pptdev *)data;
+ error = ppt_assign_device(sc->vm, pptdev->bus, pptdev->slot,
+ pptdev->func);
+ break;
+ case VM_UNBIND_PPTDEV:
+ pptdev = (struct vm_pptdev *)data;
+ error = ppt_unassign_device(sc->vm, pptdev->bus, pptdev->slot,
+ pptdev->func);
+ break;
+ case VM_INJECT_EVENT:
+ vmevent = (struct vm_event *)data;
+ error = vm_inject_event(sc->vm, vmevent->cpuid, vmevent->type,
+ vmevent->vector,
+ vmevent->error_code,
+ vmevent->error_code_valid);
+ break;
+ case VM_INJECT_NMI:
+ vmnmi = (struct vm_nmi *)data;
+ error = vm_inject_nmi(sc->vm, vmnmi->cpuid);
+ break;
+ case VM_LAPIC_IRQ:
+ vmirq = (struct vm_lapic_irq *)data;
+ error = lapic_set_intr(sc->vm, vmirq->cpuid, vmirq->vector);
+ break;
+ case VM_SET_PINNING:
+ vmpin = (struct vm_pin *)data;
+ error = vm_set_pinning(sc->vm, vmpin->vm_cpuid,
+ vmpin->host_cpuid);
+ break;
+ case VM_GET_PINNING:
+ vmpin = (struct vm_pin *)data;
+ error = vm_get_pinning(sc->vm, vmpin->vm_cpuid,
+ &vmpin->host_cpuid);
+ break;
+ case VM_MAP_MEMORY:
+ seg = (struct vm_memory_segment *)data;
+ error = vm_malloc(sc->vm, seg->gpa, seg->len);
+ break;
+ case VM_GET_MEMORY_SEG:
+ seg = (struct vm_memory_segment *)data;
+ seg->len = 0;
+ (void)vm_gpabase2memseg(sc->vm, seg->gpa, seg);
+ error = 0;
+ break;
+ case VM_GET_REGISTER:
+ vmreg = (struct vm_register *)data;
+ error = vm_get_register(sc->vm, vmreg->cpuid, vmreg->regnum,
+ &vmreg->regval);
+ break;
+ case VM_SET_REGISTER:
+ vmreg = (struct vm_register *)data;
+ error = vm_set_register(sc->vm, vmreg->cpuid, vmreg->regnum,
+ vmreg->regval);
+ break;
+ case VM_SET_SEGMENT_DESCRIPTOR:
+ vmsegdesc = (struct vm_seg_desc *)data;
+ error = vm_set_seg_desc(sc->vm, vmsegdesc->cpuid,
+ vmsegdesc->regnum,
+ &vmsegdesc->desc);
+ break;
+ case VM_GET_SEGMENT_DESCRIPTOR:
+ vmsegdesc = (struct vm_seg_desc *)data;
+ error = vm_get_seg_desc(sc->vm, vmsegdesc->cpuid,
+ vmsegdesc->regnum,
+ &vmsegdesc->desc);
+ break;
+ case VM_GET_CAPABILITY:
+ vmcap = (struct vm_capability *)data;
+ error = vm_get_capability(sc->vm, vmcap->cpuid,
+ vmcap->captype,
+ &vmcap->capval);
+ break;
+ case VM_SET_CAPABILITY:
+ vmcap = (struct vm_capability *)data;
+ error = vm_set_capability(sc->vm, vmcap->cpuid,
+ vmcap->captype,
+ vmcap->capval);
+ break;
+ case VM_SET_X2APIC_STATE:
+ x2apic = (struct vm_x2apic *)data;
+ error = vm_set_x2apic_state(sc->vm,
+ x2apic->cpuid, x2apic->state);
+ break;
+ case VM_GET_X2APIC_STATE:
+ x2apic = (struct vm_x2apic *)data;
+ error = vm_get_x2apic_state(sc->vm,
+ x2apic->cpuid, &x2apic->state);
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+
+ if (state_changed == 1) {
+ vcpu_set_state(sc->vm, vcpu, VCPU_IDLE);
+ } else if (state_changed == 2) {
+ for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++)
+ vcpu_set_state(sc->vm, vcpu, VCPU_IDLE);
+ }
+
+done:
+ return (error);
+}
+
+static int
+vmmdev_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int nprot, vm_memattr_t *memattr)
+{
+ int error;
+ struct vmmdev_softc *sc;
+
+ error = -1;
+ mtx_lock(&vmmdev_mtx);
+
+ sc = vmmdev_lookup2(cdev);
+ if (sc != NULL && (nprot & PROT_EXEC) == 0) {
+ *paddr = vm_gpa2hpa(sc->vm, (vm_paddr_t)offset, PAGE_SIZE);
+ if (*paddr != (vm_paddr_t)-1)
+ error = 0;
+ }
+
+ mtx_unlock(&vmmdev_mtx);
+
+ return (error);
+}
+
+static void
+vmmdev_destroy(struct vmmdev_softc *sc, boolean_t unlink)
+{
+
+ /*
+ * XXX must stop virtual machine instances that may be still
+ * running and cleanup their state.
+ */
+ if (sc->cdev)
+ destroy_dev(sc->cdev);
+
+ if (sc->vm)
+ vm_destroy(sc->vm);
+
+ if (unlink) {
+ mtx_lock(&vmmdev_mtx);
+ SLIST_REMOVE(&head, sc, vmmdev_softc, link);
+ mtx_unlock(&vmmdev_mtx);
+ }
+
+ free(sc, M_VMMDEV);
+}
+
+static int
+sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ char buf[VM_MAX_NAMELEN];
+ struct vmmdev_softc *sc;
+
+ strlcpy(buf, "beavis", sizeof(buf));
+ error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ /*
+ * XXX TODO if any process has this device open then fail
+ */
+
+ mtx_lock(&vmmdev_mtx);
+ sc = vmmdev_lookup(buf);
+ if (sc == NULL) {
+ mtx_unlock(&vmmdev_mtx);
+ return (EINVAL);
+ }
+
+ sc->cdev->si_drv1 = NULL;
+ mtx_unlock(&vmmdev_mtx);
+
+ vmmdev_destroy(sc, TRUE);
+
+ return (0);
+}
+SYSCTL_PROC(_hw_vmm, OID_AUTO, destroy, CTLTYPE_STRING | CTLFLAG_RW,
+ NULL, 0, sysctl_vmm_destroy, "A", NULL);
+
+static struct cdevsw vmmdevsw = {
+ .d_name = "vmmdev",
+ .d_version = D_VERSION,
+ .d_ioctl = vmmdev_ioctl,
+ .d_mmap = vmmdev_mmap,
+ .d_read = vmmdev_rw,
+ .d_write = vmmdev_rw,
+};
+
+static int
+sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct vm *vm;
+ struct vmmdev_softc *sc, *sc2;
+ char buf[VM_MAX_NAMELEN];
+
+ strlcpy(buf, "beavis", sizeof(buf));
+ error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ mtx_lock(&vmmdev_mtx);
+ sc = vmmdev_lookup(buf);
+ mtx_unlock(&vmmdev_mtx);
+ if (sc != NULL)
+ return (EEXIST);
+
+ vm = vm_create(buf);
+ if (vm == NULL)
+ return (EINVAL);
+
+ sc = malloc(sizeof(struct vmmdev_softc), M_VMMDEV, M_WAITOK | M_ZERO);
+ sc->vm = vm;
+
+ /*
+ * Lookup the name again just in case somebody sneaked in when we
+ * dropped the lock.
+ */
+ mtx_lock(&vmmdev_mtx);
+ sc2 = vmmdev_lookup(buf);
+ if (sc2 == NULL)
+ SLIST_INSERT_HEAD(&head, sc, link);
+ mtx_unlock(&vmmdev_mtx);
+
+ if (sc2 != NULL) {
+ vmmdev_destroy(sc, FALSE);
+ return (EEXIST);
+ }
+
+ sc->cdev = make_dev(&vmmdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
+ "vmm/%s", buf);
+ sc->cdev->si_drv1 = sc;
+
+ return (0);
+}
+SYSCTL_PROC(_hw_vmm, OID_AUTO, create, CTLTYPE_STRING | CTLFLAG_RW,
+ NULL, 0, sysctl_vmm_create, "A", NULL);
+
+void
+vmmdev_init(void)
+{
+ mtx_init(&vmmdev_mtx, "vmm device mutex", NULL, MTX_DEF);
+}
+
+int
+vmmdev_cleanup(void)
+{
+ int error;
+
+ if (SLIST_EMPTY(&head))
+ error = 0;
+ else
+ error = EBUSY;
+
+ return (error);
+}
diff --git a/sys/amd64/vmm/vmm_host.c b/sys/amd64/vmm/vmm_host.c
new file mode 100644
index 0000000..8dfef73
--- /dev/null
+++ b/sys/amd64/vmm/vmm_host.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/pcpu.h>
+
+#include <machine/cpufunc.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
+
+#include "vmm_host.h"
+
+static uint64_t vmm_host_efer, vmm_host_pat, vmm_host_cr0, vmm_host_cr4;
+
+void
+vmm_host_state_init(void)
+{
+
+ vmm_host_efer = rdmsr(MSR_EFER);
+ vmm_host_pat = rdmsr(MSR_PAT);
+
+ /*
+ * We always want CR0.TS to be set when the processor does a VM exit.
+ *
+ * With emulation turned on unconditionally after a VM exit, we are
+ * able to trap inadvertent use of the FPU until the guest FPU state
+ * has been safely squirreled away.
+ */
+ vmm_host_cr0 = rcr0() | CR0_TS;
+
+ vmm_host_cr4 = rcr4();
+}
+
+uint64_t
+vmm_get_host_pat(void)
+{
+
+ return (vmm_host_pat);
+}
+
+uint64_t
+vmm_get_host_efer(void)
+{
+
+ return (vmm_host_efer);
+}
+
+uint64_t
+vmm_get_host_cr0(void)
+{
+
+ return (vmm_host_cr0);
+}
+
+uint64_t
+vmm_get_host_cr4(void)
+{
+
+ return (vmm_host_cr4);
+}
+
+uint64_t
+vmm_get_host_datasel(void)
+{
+
+ return (GSEL(GDATA_SEL, SEL_KPL));
+
+}
+
+uint64_t
+vmm_get_host_codesel(void)
+{
+
+ return (GSEL(GCODE_SEL, SEL_KPL));
+}
+
+uint64_t
+vmm_get_host_tsssel(void)
+{
+
+ return (GSEL(GPROC0_SEL, SEL_KPL));
+}
+
+uint64_t
+vmm_get_host_fsbase(void)
+{
+
+ return (0);
+}
+
+uint64_t
+vmm_get_host_idtrbase(void)
+{
+
+ return (r_idt.rd_base);
+}
diff --git a/sys/amd64/vmm/vmm_host.h b/sys/amd64/vmm/vmm_host.h
new file mode 100644
index 0000000..839f54a
--- /dev/null
+++ b/sys/amd64/vmm/vmm_host.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_HOST_H_
+#define _VMM_HOST_H_
+
+#ifndef _KERNEL
+#error "no user-servicable parts inside"
+#endif
+
+void vmm_host_state_init(void);
+
+uint64_t vmm_get_host_pat(void);
+uint64_t vmm_get_host_efer(void);
+uint64_t vmm_get_host_cr0(void);
+uint64_t vmm_get_host_cr4(void);
+uint64_t vmm_get_host_datasel(void);
+uint64_t vmm_get_host_codesel(void);
+uint64_t vmm_get_host_tsssel(void);
+uint64_t vmm_get_host_fsbase(void);
+uint64_t vmm_get_host_idtrbase(void);
+
+/*
+ * Inline access to host state that is used on every VM entry
+ */
+static __inline uint64_t
+vmm_get_host_trbase(void)
+{
+
+ return ((uint64_t)PCPU_GET(tssp));
+}
+
+static __inline uint64_t
+vmm_get_host_gdtrbase(void)
+{
+
+ return ((uint64_t)&gdt[NGDT * curcpu]);
+}
+
+struct pcpu;
+extern struct pcpu __pcpu[];
+
+static __inline uint64_t
+vmm_get_host_gsbase(void)
+{
+
+ return ((uint64_t)&__pcpu[curcpu]);
+}
+
+#endif
diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c
new file mode 100644
index 0000000..40748ea
--- /dev/null
+++ b/sys/amd64/vmm/vmm_instruction_emul.c
@@ -0,0 +1,868 @@
+/*-
+ * Copyright (c) 2012 Sandvine, Inc.
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef _KERNEL
+#include <sys/param.h>
+#include <sys/pcpu.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/vmm.h>
+#else /* !_KERNEL */
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <machine/vmm.h>
+
+#include <vmmapi.h>
+#endif /* _KERNEL */
+
+
+
+/* struct vie_op.op_type */
+enum {
+ VIE_OP_TYPE_NONE = 0,
+ VIE_OP_TYPE_MOV,
+ VIE_OP_TYPE_AND,
+ VIE_OP_TYPE_LAST
+};
+
+/* struct vie_op.op_flags */
+#define VIE_OP_F_IMM (1 << 0) /* immediate operand present */
+#define VIE_OP_F_IMM8 (1 << 1) /* 8-bit immediate operand */
+
+static const struct vie_op one_byte_opcodes[256] = {
+ [0x88] = {
+ .op_byte = 0x88,
+ .op_type = VIE_OP_TYPE_MOV,
+ },
+ [0x89] = {
+ .op_byte = 0x89,
+ .op_type = VIE_OP_TYPE_MOV,
+ },
+ [0x8B] = {
+ .op_byte = 0x8B,
+ .op_type = VIE_OP_TYPE_MOV,
+ },
+ [0xC7] = {
+ .op_byte = 0xC7,
+ .op_type = VIE_OP_TYPE_MOV,
+ .op_flags = VIE_OP_F_IMM,
+ },
+ [0x23] = {
+ .op_byte = 0x23,
+ .op_type = VIE_OP_TYPE_AND,
+ },
+ [0x81] = {
+ /* XXX Group 1 extended opcode - not just AND */
+ .op_byte = 0x81,
+ .op_type = VIE_OP_TYPE_AND,
+ .op_flags = VIE_OP_F_IMM,
+ }
+};
+
+/* struct vie.mod */
+#define VIE_MOD_INDIRECT 0
+#define VIE_MOD_INDIRECT_DISP8 1
+#define VIE_MOD_INDIRECT_DISP32 2
+#define VIE_MOD_DIRECT 3
+
+/* struct vie.rm */
+#define VIE_RM_SIB 4
+#define VIE_RM_DISP32 5
+
+#define GB (1024 * 1024 * 1024)
+
+static enum vm_reg_name gpr_map[16] = {
+ VM_REG_GUEST_RAX,
+ VM_REG_GUEST_RCX,
+ VM_REG_GUEST_RDX,
+ VM_REG_GUEST_RBX,
+ VM_REG_GUEST_RSP,
+ VM_REG_GUEST_RBP,
+ VM_REG_GUEST_RSI,
+ VM_REG_GUEST_RDI,
+ VM_REG_GUEST_R8,
+ VM_REG_GUEST_R9,
+ VM_REG_GUEST_R10,
+ VM_REG_GUEST_R11,
+ VM_REG_GUEST_R12,
+ VM_REG_GUEST_R13,
+ VM_REG_GUEST_R14,
+ VM_REG_GUEST_R15
+};
+
+static uint64_t size2mask[] = {
+ [1] = 0xff,
+ [2] = 0xffff,
+ [4] = 0xffffffff,
+ [8] = 0xffffffffffffffff,
+};
+
+static int
+vie_valid_register(enum vm_reg_name reg)
+{
+#ifdef _KERNEL
+ /*
+ * XXX
+ * The operand register in which we store the result of the
+ * read must be a GPR that we can modify even if the vcpu
+ * is "running". All the GPRs qualify except for %rsp.
+ *
+ * This is a limitation of the vm_set_register() API
+ * and can be fixed if necessary.
+ */
+ if (reg == VM_REG_GUEST_RSP)
+ return (0);
+#endif
+ return (1);
+}
+
+static int
+vie_read_register(void *vm, int vcpuid, enum vm_reg_name reg, uint64_t *rval)
+{
+ int error;
+
+ if (!vie_valid_register(reg))
+ return (EINVAL);
+
+ error = vm_get_register(vm, vcpuid, reg, rval);
+
+ return (error);
+}
+
+static int
+vie_read_bytereg(void *vm, int vcpuid, struct vie *vie, uint8_t *rval)
+{
+ uint64_t val;
+ int error, rshift;
+ enum vm_reg_name reg;
+
+ rshift = 0;
+ reg = gpr_map[vie->reg];
+
+ /*
+ * 64-bit mode imposes limitations on accessing legacy byte registers.
+ *
+ * The legacy high-byte registers cannot be addressed if the REX
+ * prefix is present. In this case the values 4, 5, 6 and 7 of the
+ * 'ModRM:reg' field address %spl, %bpl, %sil and %dil respectively.
+ *
+ * If the REX prefix is not present then the values 4, 5, 6 and 7
+ * of the 'ModRM:reg' field address the legacy high-byte registers,
+ * %ah, %ch, %dh and %bh respectively.
+ */
+ if (!vie->rex_present) {
+ if (vie->reg & 0x4) {
+ /*
+ * Obtain the value of %ah by reading %rax and shifting
+ * right by 8 bits (same for %bh, %ch and %dh).
+ */
+ rshift = 8;
+ reg = gpr_map[vie->reg & 0x3];
+ }
+ }
+
+ if (!vie_valid_register(reg))
+ return (EINVAL);
+
+ error = vm_get_register(vm, vcpuid, reg, &val);
+ *rval = val >> rshift;
+ return (error);
+}
+
+static int
+vie_update_register(void *vm, int vcpuid, enum vm_reg_name reg,
+ uint64_t val, int size)
+{
+ int error;
+ uint64_t origval;
+
+ if (!vie_valid_register(reg))
+ return (EINVAL);
+
+ switch (size) {
+ case 1:
+ case 2:
+ error = vie_read_register(vm, vcpuid, reg, &origval);
+ if (error)
+ return (error);
+ val &= size2mask[size];
+ val |= origval & ~size2mask[size];
+ break;
+ case 4:
+ val &= 0xffffffffUL;
+ break;
+ case 8:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ error = vm_set_register(vm, vcpuid, reg, val);
+ return (error);
+}
+
+/*
+ * The following simplifying assumptions are made during emulation:
+ *
+ * - guest is in 64-bit mode
+ * - default address size is 64-bits
+ * - default operand size is 32-bits
+ *
+ * - operand size override is not supported
+ *
+ * - address size override is not supported
+ */
+static int
+emulate_mov(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
+{
+ int error, size;
+ enum vm_reg_name reg;
+ uint8_t byte;
+ uint64_t val;
+
+ size = 4;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0x88:
+ /*
+ * MOV byte from reg (ModRM:reg) to mem (ModRM:r/m)
+ * 88/r: mov r/m8, r8
+ * REX + 88/r: mov r/m8, r8 (%ah, %ch, %dh, %bh not available)
+ */
+ size = 1;
+ error = vie_read_bytereg(vm, vcpuid, vie, &byte);
+ if (error == 0)
+ error = memwrite(vm, vcpuid, gpa, byte, size, arg);
+ break;
+ case 0x89:
+ /*
+ * MOV from reg (ModRM:reg) to mem (ModRM:r/m)
+ * 89/r: mov r/m32, r32
+ * REX.W + 89/r mov r/m64, r64
+ */
+ if (vie->rex_w)
+ size = 8;
+ reg = gpr_map[vie->reg];
+ error = vie_read_register(vm, vcpuid, reg, &val);
+ if (error == 0) {
+ val &= size2mask[size];
+ error = memwrite(vm, vcpuid, gpa, val, size, arg);
+ }
+ break;
+ case 0x8B:
+ /*
+ * MOV from mem (ModRM:r/m) to reg (ModRM:reg)
+ * 8B/r: mov r32, r/m32
+ * REX.W 8B/r: mov r64, r/m64
+ */
+ if (vie->rex_w)
+ size = 8;
+ error = memread(vm, vcpuid, gpa, &val, size, arg);
+ if (error == 0) {
+ reg = gpr_map[vie->reg];
+ error = vie_update_register(vm, vcpuid, reg, val, size);
+ }
+ break;
+ case 0xC7:
+ /*
+ * MOV from imm32 to mem (ModRM:r/m)
+ * C7/0 mov r/m32, imm32
+ * REX.W + C7/0 mov r/m64, imm32 (sign-extended to 64-bits)
+ */
+ val = vie->immediate; /* already sign-extended */
+
+ if (vie->rex_w)
+ size = 8;
+
+ if (size != 8)
+ val &= size2mask[size];
+
+ error = memwrite(vm, vcpuid, gpa, val, size, arg);
+ break;
+ default:
+ break;
+ }
+
+ return (error);
+}
+
+static int
+emulate_and(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
+{
+ int error, size;
+ enum vm_reg_name reg;
+ uint64_t val1, val2;
+
+ size = 4;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0x23:
+ /*
+ * AND reg (ModRM:reg) and mem (ModRM:r/m) and store the
+ * result in reg.
+ *
+ * 23/r and r32, r/m32
+ * REX.W + 23/r and r64, r/m64
+ */
+ if (vie->rex_w)
+ size = 8;
+
+ /* get the first operand */
+ reg = gpr_map[vie->reg];
+ error = vie_read_register(vm, vcpuid, reg, &val1);
+ if (error)
+ break;
+
+ /* get the second operand */
+ error = memread(vm, vcpuid, gpa, &val2, size, arg);
+ if (error)
+ break;
+
+ /* perform the operation and write the result */
+ val1 &= val2;
+ error = vie_update_register(vm, vcpuid, reg, val1, size);
+ break;
+ case 0x81:
+ /*
+ * AND reg (ModRM:reg) with immediate and store the
+ * result in reg
+ *
+ * 81/ and r/m32, imm32
+ * REX.W + 81/ and r/m64, imm32 sign-extended to 64
+ *
+ * Currently, only the AND operation of the 0x81 opcode
+ * is implemented (ModRM:reg = b100).
+ */
+ if ((vie->reg & 7) != 4)
+ break;
+
+ if (vie->rex_w)
+ size = 8;
+
+ /* get the first operand */
+ error = memread(vm, vcpuid, gpa, &val1, size, arg);
+ if (error)
+ break;
+
+ /*
+ * perform the operation with the pre-fetched immediate
+ * operand and write the result
+ */
+ val1 &= vie->immediate;
+ error = memwrite(vm, vcpuid, gpa, val1, size, arg);
+ break;
+ default:
+ break;
+ }
+ return (error);
+}
+
+int
+vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite,
+ void *memarg)
+{
+ int error;
+
+ if (!vie->decoded)
+ return (EINVAL);
+
+ switch (vie->op.op_type) {
+ case VIE_OP_TYPE_MOV:
+ error = emulate_mov(vm, vcpuid, gpa, vie,
+ memread, memwrite, memarg);
+ break;
+ case VIE_OP_TYPE_AND:
+ error = emulate_and(vm, vcpuid, gpa, vie,
+ memread, memwrite, memarg);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+#ifdef _KERNEL
+static void
+vie_init(struct vie *vie)
+{
+
+ bzero(vie, sizeof(struct vie));
+
+ vie->base_register = VM_REG_LAST;
+ vie->index_register = VM_REG_LAST;
+}
+
+static int
+gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys,
+ uint64_t *gpa, uint64_t *gpaend)
+{
+ vm_paddr_t hpa;
+ int nlevels, ptpshift, ptpindex;
+ uint64_t *ptpbase, pte, pgsize;
+
+ /*
+ * XXX assumes 64-bit guest with 4 page walk levels
+ */
+ nlevels = 4;
+ while (--nlevels >= 0) {
+ /* Zero out the lower 12 bits and the upper 12 bits */
+ ptpphys >>= 12; ptpphys <<= 24; ptpphys >>= 12;
+
+ hpa = vm_gpa2hpa(vm, ptpphys, PAGE_SIZE);
+ if (hpa == -1)
+ goto error;
+
+ ptpbase = (uint64_t *)PHYS_TO_DMAP(hpa);
+
+ ptpshift = PAGE_SHIFT + nlevels * 9;
+ ptpindex = (gla >> ptpshift) & 0x1FF;
+ pgsize = 1UL << ptpshift;
+
+ pte = ptpbase[ptpindex];
+
+ if ((pte & PG_V) == 0)
+ goto error;
+
+ if (pte & PG_PS) {
+ if (pgsize > 1 * GB)
+ goto error;
+ else
+ break;
+ }
+
+ ptpphys = pte;
+ }
+
+ /* Zero out the lower 'ptpshift' bits and the upper 12 bits */
+ pte >>= ptpshift; pte <<= (ptpshift + 12); pte >>= 12;
+ *gpa = pte | (gla & (pgsize - 1));
+ *gpaend = pte + pgsize;
+ return (0);
+
+error:
+ return (-1);
+}
+
+int
+vmm_fetch_instruction(struct vm *vm, int cpuid, uint64_t rip, int inst_length,
+ uint64_t cr3, struct vie *vie)
+{
+ int n, err;
+ uint64_t hpa, gpa, gpaend, off;
+
+ /*
+ * XXX cache previously fetched instructions using 'rip' as the tag
+ */
+
+ if (inst_length > VIE_INST_SIZE)
+ panic("vmm_fetch_instruction: invalid length %d", inst_length);
+
+ vie_init(vie);
+
+ /* Copy the instruction into 'vie' */
+ while (vie->num_valid < inst_length) {
+ err = gla2gpa(vm, rip, cr3, &gpa, &gpaend);
+ if (err)
+ break;
+
+ off = gpa & PAGE_MASK;
+ n = min(inst_length - vie->num_valid, PAGE_SIZE - off);
+
+ hpa = vm_gpa2hpa(vm, gpa, n);
+ if (hpa == -1)
+ break;
+
+ bcopy((void *)PHYS_TO_DMAP(hpa), &vie->inst[vie->num_valid], n);
+
+ rip += n;
+ vie->num_valid += n;
+ }
+
+ if (vie->num_valid == inst_length)
+ return (0);
+ else
+ return (-1);
+}
+
+static int
+vie_peek(struct vie *vie, uint8_t *x)
+{
+
+ if (vie->num_processed < vie->num_valid) {
+ *x = vie->inst[vie->num_processed];
+ return (0);
+ } else
+ return (-1);
+}
+
+static void
+vie_advance(struct vie *vie)
+{
+
+ vie->num_processed++;
+}
+
+static int
+decode_rex(struct vie *vie)
+{
+ uint8_t x;
+
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ if (x >= 0x40 && x <= 0x4F) {
+ vie->rex_present = 1;
+
+ vie->rex_w = x & 0x8 ? 1 : 0;
+ vie->rex_r = x & 0x4 ? 1 : 0;
+ vie->rex_x = x & 0x2 ? 1 : 0;
+ vie->rex_b = x & 0x1 ? 1 : 0;
+
+ vie_advance(vie);
+ }
+
+ return (0);
+}
+
+static int
+decode_opcode(struct vie *vie)
+{
+ uint8_t x;
+
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ vie->op = one_byte_opcodes[x];
+
+ if (vie->op.op_type == VIE_OP_TYPE_NONE)
+ return (-1);
+
+ vie_advance(vie);
+ return (0);
+}
+
+/*
+ * XXX assuming 32-bit or 64-bit guest
+ */
+static int
+decode_modrm(struct vie *vie)
+{
+ uint8_t x;
+
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ vie->mod = (x >> 6) & 0x3;
+ vie->rm = (x >> 0) & 0x7;
+ vie->reg = (x >> 3) & 0x7;
+
+ /*
+ * A direct addressing mode makes no sense in the context of an EPT
+ * fault. There has to be a memory access involved to cause the
+ * EPT fault.
+ */
+ if (vie->mod == VIE_MOD_DIRECT)
+ return (-1);
+
+ if ((vie->mod == VIE_MOD_INDIRECT && vie->rm == VIE_RM_DISP32) ||
+ (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)) {
+ /*
+ * Table 2-5: Special Cases of REX Encodings
+ *
+ * mod=0, r/m=5 is used in the compatibility mode to
+ * indicate a disp32 without a base register.
+ *
+ * mod!=3, r/m=4 is used in the compatibility mode to
+ * indicate that the SIB byte is present.
+ *
+ * The 'b' bit in the REX prefix is don't care in
+ * this case.
+ */
+ } else {
+ vie->rm |= (vie->rex_b << 3);
+ }
+
+ vie->reg |= (vie->rex_r << 3);
+
+ /* SIB */
+ if (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)
+ goto done;
+
+ vie->base_register = gpr_map[vie->rm];
+
+ switch (vie->mod) {
+ case VIE_MOD_INDIRECT_DISP8:
+ vie->disp_bytes = 1;
+ break;
+ case VIE_MOD_INDIRECT_DISP32:
+ vie->disp_bytes = 4;
+ break;
+ case VIE_MOD_INDIRECT:
+ if (vie->rm == VIE_RM_DISP32) {
+ vie->disp_bytes = 4;
+ vie->base_register = VM_REG_LAST; /* no base */
+ }
+ break;
+ }
+
+ /* Figure out immediate operand size (if any) */
+ if (vie->op.op_flags & VIE_OP_F_IMM)
+ vie->imm_bytes = 4;
+ else if (vie->op.op_flags & VIE_OP_F_IMM8)
+ vie->imm_bytes = 1;
+
+done:
+ vie_advance(vie);
+
+ return (0);
+}
+
+static int
+decode_sib(struct vie *vie)
+{
+ uint8_t x;
+
+ /* Proceed only if SIB byte is present */
+ if (vie->mod == VIE_MOD_DIRECT || vie->rm != VIE_RM_SIB)
+ return (0);
+
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ /* De-construct the SIB byte */
+ vie->ss = (x >> 6) & 0x3;
+ vie->index = (x >> 3) & 0x7;
+ vie->base = (x >> 0) & 0x7;
+
+ /* Apply the REX prefix modifiers */
+ vie->index |= vie->rex_x << 3;
+ vie->base |= vie->rex_b << 3;
+
+ switch (vie->mod) {
+ case VIE_MOD_INDIRECT_DISP8:
+ vie->disp_bytes = 1;
+ break;
+ case VIE_MOD_INDIRECT_DISP32:
+ vie->disp_bytes = 4;
+ break;
+ }
+
+ if (vie->mod == VIE_MOD_INDIRECT &&
+ (vie->base == 5 || vie->base == 13)) {
+ /*
+ * Special case when base register is unused if mod = 0
+ * and base = %rbp or %r13.
+ *
+ * Documented in:
+ * Table 2-3: 32-bit Addressing Forms with the SIB Byte
+ * Table 2-5: Special Cases of REX Encodings
+ */
+ vie->disp_bytes = 4;
+ } else {
+ vie->base_register = gpr_map[vie->base];
+ }
+
+ /*
+ * All encodings of 'index' are valid except for %rsp (4).
+ *
+ * Documented in:
+ * Table 2-3: 32-bit Addressing Forms with the SIB Byte
+ * Table 2-5: Special Cases of REX Encodings
+ */
+ if (vie->index != 4)
+ vie->index_register = gpr_map[vie->index];
+
+ /* 'scale' makes sense only in the context of an index register */
+ if (vie->index_register < VM_REG_LAST)
+ vie->scale = 1 << vie->ss;
+
+ vie_advance(vie);
+
+ return (0);
+}
+
+static int
+decode_displacement(struct vie *vie)
+{
+ int n, i;
+ uint8_t x;
+
+ union {
+ char buf[4];
+ int8_t signed8;
+ int32_t signed32;
+ } u;
+
+ if ((n = vie->disp_bytes) == 0)
+ return (0);
+
+ if (n != 1 && n != 4)
+ panic("decode_displacement: invalid disp_bytes %d", n);
+
+ for (i = 0; i < n; i++) {
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ u.buf[i] = x;
+ vie_advance(vie);
+ }
+
+ if (n == 1)
+ vie->displacement = u.signed8; /* sign-extended */
+ else
+ vie->displacement = u.signed32; /* sign-extended */
+
+ return (0);
+}
+
+static int
+decode_immediate(struct vie *vie)
+{
+ int i, n;
+ uint8_t x;
+ union {
+ char buf[4];
+ int8_t signed8;
+ int32_t signed32;
+ } u;
+
+ if ((n = vie->imm_bytes) == 0)
+ return (0);
+
+ if (n != 1 && n != 4)
+ panic("decode_immediate: invalid imm_bytes %d", n);
+
+ for (i = 0; i < n; i++) {
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ u.buf[i] = x;
+ vie_advance(vie);
+ }
+
+ if (n == 1)
+ vie->immediate = u.signed8; /* sign-extended */
+ else
+ vie->immediate = u.signed32; /* sign-extended */
+
+ return (0);
+}
+
+#define VERIFY_GLA
+/*
+ * Verify that the 'guest linear address' provided as collateral of the nested
+ * page table fault matches with our instruction decoding.
+ */
+#ifdef VERIFY_GLA
+static int
+verify_gla(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie)
+{
+ int error;
+ uint64_t base, idx;
+
+ base = 0;
+ if (vie->base_register != VM_REG_LAST) {
+ error = vm_get_register(vm, cpuid, vie->base_register, &base);
+ if (error) {
+ printf("verify_gla: error %d getting base reg %d\n",
+ error, vie->base_register);
+ return (-1);
+ }
+ }
+
+ idx = 0;
+ if (vie->index_register != VM_REG_LAST) {
+ error = vm_get_register(vm, cpuid, vie->index_register, &idx);
+ if (error) {
+ printf("verify_gla: error %d getting index reg %d\n",
+ error, vie->index_register);
+ return (-1);
+ }
+ }
+
+ if (base + vie->scale * idx + vie->displacement != gla) {
+ printf("verify_gla mismatch: "
+ "base(0x%0lx), scale(%d), index(0x%0lx), "
+ "disp(0x%0lx), gla(0x%0lx)\n",
+ base, vie->scale, idx, vie->displacement, gla);
+ return (-1);
+ }
+
+ return (0);
+}
+#endif /* VERIFY_GLA */
+
+int
+vmm_decode_instruction(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie)
+{
+
+ if (decode_rex(vie))
+ return (-1);
+
+ if (decode_opcode(vie))
+ return (-1);
+
+ if (decode_modrm(vie))
+ return (-1);
+
+ if (decode_sib(vie))
+ return (-1);
+
+ if (decode_displacement(vie))
+ return (-1);
+
+ if (decode_immediate(vie))
+ return (-1);
+
+#ifdef VERIFY_GLA
+ if (verify_gla(vm, cpuid, gla, vie))
+ return (-1);
+#endif
+
+ vie->decoded = 1; /* success */
+
+ return (0);
+}
+#endif /* _KERNEL */
diff --git a/sys/amd64/vmm/vmm_ipi.c b/sys/amd64/vmm/vmm_ipi.c
new file mode 100644
index 0000000..643d326
--- /dev/null
+++ b/sys/amd64/vmm/vmm_ipi.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/bus.h>
+
+#include <machine/intr_machdep.h>
+#include <machine/apicvar.h>
+#include <machine/segments.h>
+#include <machine/md_var.h>
+
+#include <machine/vmm.h>
+#include "vmm_ipi.h"
+
+extern inthand_t IDTVEC(rsvd), IDTVEC(justreturn);
+
+/*
+ * The default is to use the IPI_AST to interrupt a vcpu.
+ */
+int vmm_ipinum = IPI_AST;
+
+CTASSERT(APIC_SPURIOUS_INT == 255);
+
+void
+vmm_ipi_init(void)
+{
+ int idx;
+ uintptr_t func;
+ struct gate_descriptor *ip;
+
+ /*
+ * Search backwards from the highest IDT vector available for use
+ * as our IPI vector. We install the 'justreturn' handler at that
+ * vector and use it to interrupt the vcpus.
+ *
+ * We do this because the IPI_AST is heavyweight and saves all
+ * registers in the trapframe. This is overkill for our use case
+ * which is simply to EOI the interrupt and return.
+ */
+ idx = APIC_SPURIOUS_INT;
+ while (--idx >= APIC_IPI_INTS) {
+ ip = &idt[idx];
+ func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
+ if (func == (uintptr_t)&IDTVEC(rsvd)) {
+ vmm_ipinum = idx;
+ setidt(vmm_ipinum, IDTVEC(justreturn), SDT_SYSIGT,
+ SEL_KPL, 0);
+ break;
+ }
+ }
+
+ if (vmm_ipinum != IPI_AST && bootverbose) {
+ printf("vmm_ipi_init: installing ipi handler to interrupt "
+ "vcpus at vector %d\n", vmm_ipinum);
+ }
+}
+
+void
+vmm_ipi_cleanup(void)
+{
+ if (vmm_ipinum != IPI_AST)
+ setidt(vmm_ipinum, IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
+}
diff --git a/sys/amd64/vmm/vmm_ipi.h b/sys/amd64/vmm/vmm_ipi.h
new file mode 100644
index 0000000..91552e3
--- /dev/null
+++ b/sys/amd64/vmm/vmm_ipi.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_IPI_H_
+#define _VMM_IPI_H_
+
+struct vm;
+
+extern int vmm_ipinum;
+
+void vmm_ipi_init(void);
+void vmm_ipi_cleanup(void);
+
+#endif
diff --git a/sys/amd64/vmm/vmm_ktr.h b/sys/amd64/vmm/vmm_ktr.h
new file mode 100644
index 0000000..e691c61
--- /dev/null
+++ b/sys/amd64/vmm/vmm_ktr.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_KTR_H_
+#define _VMM_KTR_H_
+
+#include <sys/ktr.h>
+#include <sys/pcpu.h>
+
+#define KTR_VMM KTR_GEN
+
+#define VMM_CTR0(vm, vcpuid, format) \
+CTR3(KTR_VMM, "vm %s-%d(%d): " format, vm_name((vm)), (vcpuid), curcpu)
+
+#define VMM_CTR1(vm, vcpuid, format, p1) \
+CTR4(KTR_VMM, "vm %s-%d(%d): " format, vm_name((vm)), (vcpuid), curcpu, \
+ (p1))
+
+#define VMM_CTR2(vm, vcpuid, format, p1, p2) \
+CTR5(KTR_VMM, "vm %s-%d(%d): " format, vm_name((vm)), (vcpuid), curcpu, \
+ (p1), (p2))
+
+#define VMM_CTR3(vm, vcpuid, format, p1, p2, p3) \
+CTR6(KTR_VMM, "vm %s-%d(%d): " format, vm_name((vm)), (vcpuid), curcpu, \
+ (p1), (p2), (p3))
+#endif
diff --git a/sys/amd64/vmm/vmm_lapic.c b/sys/amd64/vmm/vmm_lapic.c
new file mode 100644
index 0000000..d024b71
--- /dev/null
+++ b/sys/amd64/vmm/vmm_lapic.c
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+
+#include <x86/specialreg.h>
+#include <x86/apicreg.h>
+
+#include <machine/vmm.h>
+#include "vmm_ipi.h"
+#include "vmm_lapic.h"
+#include "vlapic.h"
+
+int
+lapic_pending_intr(struct vm *vm, int cpu)
+{
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ return (vlapic_pending_intr(vlapic));
+}
+
+void
+lapic_intr_accepted(struct vm *vm, int cpu, int vector)
+{
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ vlapic_intr_accepted(vlapic, vector);
+}
+
+int
+lapic_set_intr(struct vm *vm, int cpu, int vector)
+{
+ struct vlapic *vlapic;
+
+ if (cpu < 0 || cpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (vector < 32 || vector > 255)
+ return (EINVAL);
+
+ vlapic = vm_lapic(vm, cpu);
+ vlapic_set_intr_ready(vlapic, vector);
+
+ vm_interrupt_hostcpu(vm, cpu);
+
+ return (0);
+}
+
+int
+lapic_timer_tick(struct vm *vm, int cpu)
+{
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ return (vlapic_timer_tick(vlapic));
+}
+
+static boolean_t
+x2apic_msr(u_int msr)
+{
+ if (msr >= 0x800 && msr <= 0xBFF)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+static u_int
+x2apic_msr_to_regoff(u_int msr)
+{
+
+ return ((msr - 0x800) << 4);
+}
+
+boolean_t
+lapic_msr(u_int msr)
+{
+
+ if (x2apic_msr(msr) || (msr == MSR_APICBASE))
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+int
+lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval)
+{
+ int error;
+ u_int offset;
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ if (msr == MSR_APICBASE) {
+ *rval = vlapic_get_apicbase(vlapic);
+ error = 0;
+ } else {
+ offset = x2apic_msr_to_regoff(msr);
+ error = vlapic_op_mem_read(vlapic, offset, DWORD, rval);
+ }
+
+ return (error);
+}
+
+int
+lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t val)
+{
+ int error;
+ u_int offset;
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ if (msr == MSR_APICBASE) {
+ vlapic_set_apicbase(vlapic, val);
+ error = 0;
+ } else {
+ offset = x2apic_msr_to_regoff(msr);
+ error = vlapic_op_mem_write(vlapic, offset, DWORD, val);
+ }
+
+ return (error);
+}
+
+int
+lapic_mmio_write(void *vm, int cpu, uint64_t gpa, uint64_t wval, int size,
+ void *arg)
+{
+ int error;
+ uint64_t off;
+ struct vlapic *vlapic;
+
+ off = gpa - DEFAULT_APIC_BASE;
+
+ /*
+ * Memory mapped local apic accesses must be 4 bytes wide and
+ * aligned on a 16-byte boundary.
+ */
+ if (size != 4 || off & 0xf)
+ return (EINVAL);
+
+ vlapic = vm_lapic(vm, cpu);
+ error = vlapic_op_mem_write(vlapic, off, DWORD, wval);
+ return (error);
+}
+
+int
+lapic_mmio_read(void *vm, int cpu, uint64_t gpa, uint64_t *rval, int size,
+ void *arg)
+{
+ int error;
+ uint64_t off;
+ struct vlapic *vlapic;
+
+ off = gpa - DEFAULT_APIC_BASE;
+
+ /*
+ * Memory mapped local apic accesses must be 4 bytes wide and
+ * aligned on a 16-byte boundary.
+ */
+ if (size != 4 || off & 0xf)
+ return (EINVAL);
+
+ vlapic = vm_lapic(vm, cpu);
+ error = vlapic_op_mem_read(vlapic, off, DWORD, rval);
+ return (error);
+}
diff --git a/sys/amd64/vmm/vmm_lapic.h b/sys/amd64/vmm/vmm_lapic.h
new file mode 100644
index 0000000..a79912e
--- /dev/null
+++ b/sys/amd64/vmm/vmm_lapic.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_LAPIC_H_
+#define _VMM_LAPIC_H_
+
+struct vm;
+
+boolean_t lapic_msr(u_int num);
+int lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval);
+int lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t wval);
+
+int lapic_mmio_read(void *vm, int cpu, uint64_t gpa,
+ uint64_t *rval, int size, void *arg);
+int lapic_mmio_write(void *vm, int cpu, uint64_t gpa,
+ uint64_t wval, int size, void *arg);
+
+int lapic_timer_tick(struct vm *vm, int cpu);
+
+/*
+ * Returns a vector between 32 and 255 if an interrupt is pending in the
+ * IRR that can be delivered based on the current state of ISR and TPR.
+ *
+ * Note that the vector does not automatically transition to the ISR as a
+ * result of calling this function.
+ *
+ * Returns -1 if there is no eligible vector that can be delivered to the
+ * guest at this time.
+ */
+int lapic_pending_intr(struct vm *vm, int cpu);
+
+/*
+ * Transition 'vector' from IRR to ISR. This function is called with the
+ * vector returned by 'lapic_pending_intr()' when the guest is able to
+ * accept this interrupt (i.e. RFLAGS.IF = 1 and no conditions exist that
+ * block interrupt delivery).
+ */
+void lapic_intr_accepted(struct vm *vm, int cpu, int vector);
+
+/*
+ * Signals to the LAPIC that an interrupt at 'vector' needs to be generated
+ * to the 'cpu', the state is recorded in IRR.
+ */
+int lapic_set_intr(struct vm *vm, int cpu, int vector);
+
+#endif
diff --git a/sys/amd64/vmm/vmm_mem.c b/sys/amd64/vmm/vmm_mem.c
new file mode 100644
index 0000000..04f99b1
--- /dev/null
+++ b/sys/amd64/vmm/vmm_mem.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/linker.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+
+#include <machine/md_var.h>
+#include <machine/metadata.h>
+#include <machine/pc/bios.h>
+#include <machine/vmparam.h>
+#include <machine/pmap.h>
+
+#include "vmm_util.h"
+#include "vmm_mem.h"
+
+SYSCTL_DECL(_hw_vmm);
+
+static u_long pages_allocated;
+SYSCTL_ULONG(_hw_vmm, OID_AUTO, pages_allocated, CTLFLAG_RD,
+ &pages_allocated, 0, "4KB pages allocated");
+
+static void
+update_pages_allocated(int howmany)
+{
+ pages_allocated += howmany; /* XXX locking? */
+}
+
+int
+vmm_mem_init(void)
+{
+
+ return (0);
+}
+
+vm_paddr_t
+vmm_mem_alloc(size_t size)
+{
+ int flags;
+ vm_page_t m;
+ vm_paddr_t pa;
+
+ if (size != PAGE_SIZE)
+ panic("vmm_mem_alloc: invalid allocation size %lu", size);
+
+ flags = VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
+ VM_ALLOC_ZERO;
+
+ while (1) {
+ /*
+ * XXX need policy to determine when to back off the allocation
+ */
+ m = vm_page_alloc(NULL, 0, flags);
+ if (m == NULL)
+ VM_WAIT;
+ else
+ break;
+ }
+
+ pa = VM_PAGE_TO_PHYS(m);
+
+ if ((m->flags & PG_ZERO) == 0)
+ pagezero((void *)PHYS_TO_DMAP(pa));
+ m->valid = VM_PAGE_BITS_ALL;
+
+ update_pages_allocated(1);
+
+ return (pa);
+}
+
+void
+vmm_mem_free(vm_paddr_t base, size_t length)
+{
+ vm_page_t m;
+
+ if (base & PAGE_MASK) {
+ panic("vmm_mem_free: base 0x%0lx must be aligned on a "
+ "0x%0x boundary\n", base, PAGE_SIZE);
+ }
+
+ if (length != PAGE_SIZE)
+ panic("vmm_mem_free: invalid length %lu", length);
+
+ m = PHYS_TO_VM_PAGE(base);
+ m->wire_count--;
+ vm_page_free(m);
+ atomic_subtract_int(&cnt.v_wire_count, 1);
+
+ update_pages_allocated(-1);
+}
+
+vm_paddr_t
+vmm_mem_maxaddr(void)
+{
+
+ return (ptoa(Maxmem));
+}
diff --git a/sys/amd64/vmm/vmm_mem.h b/sys/amd64/vmm/vmm_mem.h
new file mode 100644
index 0000000..7d45c74
--- /dev/null
+++ b/sys/amd64/vmm/vmm_mem.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_MEM_H_
+#define _VMM_MEM_H_
+
+int vmm_mem_init(void);
+vm_paddr_t vmm_mem_alloc(size_t size);
+void vmm_mem_free(vm_paddr_t start, size_t size);
+vm_paddr_t vmm_mem_maxaddr(void);
+
+#endif
diff --git a/sys/amd64/vmm/vmm_msr.c b/sys/amd64/vmm/vmm_msr.c
new file mode 100644
index 0000000..d97c819
--- /dev/null
+++ b/sys/amd64/vmm/vmm_msr.c
@@ -0,0 +1,254 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+
+#include <machine/specialreg.h>
+
+#include <machine/vmm.h>
+#include "vmm_lapic.h"
+#include "vmm_msr.h"
+
+#define VMM_MSR_F_EMULATE 0x01
+#define VMM_MSR_F_READONLY 0x02
+#define VMM_MSR_F_INVALID 0x04 /* guest_msr_valid() can override this */
+
+struct vmm_msr {
+ int num;
+ int flags;
+ uint64_t hostval;
+};
+
+static struct vmm_msr vmm_msr[] = {
+ { MSR_LSTAR, 0 },
+ { MSR_CSTAR, 0 },
+ { MSR_STAR, 0 },
+ { MSR_SF_MASK, 0 },
+ { MSR_PAT, VMM_MSR_F_EMULATE | VMM_MSR_F_INVALID },
+ { MSR_BIOS_SIGN,VMM_MSR_F_EMULATE },
+ { MSR_MCG_CAP, VMM_MSR_F_EMULATE | VMM_MSR_F_READONLY },
+};
+
+#define vmm_msr_num (sizeof(vmm_msr) / sizeof(vmm_msr[0]))
+CTASSERT(VMM_MSR_NUM >= vmm_msr_num);
+
+#define readonly_msr(idx) \
+ ((vmm_msr[(idx)].flags & VMM_MSR_F_READONLY) != 0)
+
+#define emulated_msr(idx) \
+ ((vmm_msr[(idx)].flags & VMM_MSR_F_EMULATE) != 0)
+
+#define invalid_msr(idx) \
+ ((vmm_msr[(idx)].flags & VMM_MSR_F_INVALID) != 0)
+
+void
+vmm_msr_init(void)
+{
+ int i;
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ if (emulated_msr(i))
+ continue;
+ /*
+ * XXX this assumes that the value of the host msr does not
+ * change after we have cached it.
+ */
+ vmm_msr[i].hostval = rdmsr(vmm_msr[i].num);
+ }
+}
+
+void
+guest_msrs_init(struct vm *vm, int cpu)
+{
+ int i;
+ uint64_t *guest_msrs;
+
+ guest_msrs = vm_guest_msrs(vm, cpu);
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ switch (vmm_msr[i].num) {
+ case MSR_LSTAR:
+ case MSR_CSTAR:
+ case MSR_STAR:
+ case MSR_SF_MASK:
+ case MSR_BIOS_SIGN:
+ case MSR_MCG_CAP:
+ guest_msrs[i] = 0;
+ break;
+ case MSR_PAT:
+ guest_msrs[i] = PAT_VALUE(0, PAT_WRITE_BACK) |
+ PAT_VALUE(1, PAT_WRITE_THROUGH) |
+ PAT_VALUE(2, PAT_UNCACHED) |
+ PAT_VALUE(3, PAT_UNCACHEABLE) |
+ PAT_VALUE(4, PAT_WRITE_BACK) |
+ PAT_VALUE(5, PAT_WRITE_THROUGH) |
+ PAT_VALUE(6, PAT_UNCACHED) |
+ PAT_VALUE(7, PAT_UNCACHEABLE);
+ break;
+ default:
+ panic("guest_msrs_init: missing initialization for msr "
+ "0x%0x", vmm_msr[i].num);
+ }
+ }
+}
+
+static int
+msr_num_to_idx(u_int num)
+{
+ int i;
+
+ for (i = 0; i < vmm_msr_num; i++)
+ if (vmm_msr[i].num == num)
+ return (i);
+
+ return (-1);
+}
+
+int
+emulate_wrmsr(struct vm *vm, int cpu, u_int num, uint64_t val)
+{
+ int idx;
+ uint64_t *guest_msrs;
+
+ if (lapic_msr(num))
+ return (lapic_wrmsr(vm, cpu, num, val));
+
+ idx = msr_num_to_idx(num);
+ if (idx < 0 || invalid_msr(idx))
+ return (EINVAL);
+
+ if (!readonly_msr(idx)) {
+ guest_msrs = vm_guest_msrs(vm, cpu);
+
+ /* Stash the value */
+ guest_msrs[idx] = val;
+
+ /* Update processor state for non-emulated MSRs */
+ if (!emulated_msr(idx))
+ wrmsr(vmm_msr[idx].num, val);
+ }
+
+ return (0);
+}
+
+int
+emulate_rdmsr(struct vm *vm, int cpu, u_int num)
+{
+ int error, idx;
+ uint32_t eax, edx;
+ uint64_t result, *guest_msrs;
+
+ if (lapic_msr(num)) {
+ error = lapic_rdmsr(vm, cpu, num, &result);
+ goto done;
+ }
+
+ idx = msr_num_to_idx(num);
+ if (idx < 0 || invalid_msr(idx)) {
+ error = EINVAL;
+ goto done;
+ }
+
+ guest_msrs = vm_guest_msrs(vm, cpu);
+ result = guest_msrs[idx];
+
+ /*
+ * If this is not an emulated msr register make sure that the processor
+ * state matches our cached state.
+ */
+ if (!emulated_msr(idx) && (rdmsr(num) != result)) {
+ panic("emulate_rdmsr: msr 0x%0x has inconsistent cached "
+ "(0x%016lx) and actual (0x%016lx) values", num,
+ result, rdmsr(num));
+ }
+
+ error = 0;
+
+done:
+ if (error == 0) {
+ eax = result;
+ edx = result >> 32;
+ error = vm_set_register(vm, cpu, VM_REG_GUEST_RAX, eax);
+ if (error)
+ panic("vm_set_register(rax) error %d", error);
+ error = vm_set_register(vm, cpu, VM_REG_GUEST_RDX, edx);
+ if (error)
+ panic("vm_set_register(rdx) error %d", error);
+ }
+ return (error);
+}
+
+void
+restore_guest_msrs(struct vm *vm, int cpu)
+{
+ int i;
+ uint64_t *guest_msrs;
+
+ guest_msrs = vm_guest_msrs(vm, cpu);
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ if (emulated_msr(i))
+ continue;
+ else
+ wrmsr(vmm_msr[i].num, guest_msrs[i]);
+ }
+}
+
+void
+restore_host_msrs(struct vm *vm, int cpu)
+{
+ int i;
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ if (emulated_msr(i))
+ continue;
+ else
+ wrmsr(vmm_msr[i].num, vmm_msr[i].hostval);
+ }
+}
+
+/*
+ * Must be called by the CPU-specific code before any guests are
+ * created
+ */
+void
+guest_msr_valid(int msr)
+{
+ int i;
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ if (vmm_msr[i].num == msr && invalid_msr(i)) {
+ vmm_msr[i].flags &= ~VMM_MSR_F_INVALID;
+ }
+ }
+}
diff --git a/sys/amd64/vmm/vmm_msr.h b/sys/amd64/vmm/vmm_msr.h
new file mode 100644
index 0000000..8a1fda3
--- /dev/null
+++ b/sys/amd64/vmm/vmm_msr.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_MSR_H_
+#define _VMM_MSR_H_
+
+#define VMM_MSR_NUM 16
+struct vm;
+
+void vmm_msr_init(void);
+int emulate_wrmsr(struct vm *vm, int vcpu, u_int msr, uint64_t val);
+int emulate_rdmsr(struct vm *vm, int vcpu, u_int msr);
+void guest_msrs_init(struct vm *vm, int cpu);
+void guest_msr_valid(int msr);
+void restore_host_msrs(struct vm *vm, int cpu);
+void restore_guest_msrs(struct vm *vm, int cpu);
+
+#endif
diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c
new file mode 100644
index 0000000..ae60979
--- /dev/null
+++ b/sys/amd64/vmm/vmm_stat.c
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/smp.h>
+
+#include <machine/vmm.h>
+#include "vmm_stat.h"
+
+static int vstnum;
+static struct vmm_stat_type *vsttab[MAX_VMM_STAT_TYPES];
+
+static MALLOC_DEFINE(M_VMM_STAT, "vmm stat", "vmm stat");
+
+void
+vmm_stat_init(void *arg)
+{
+ struct vmm_stat_type *vst = arg;
+
+ /* We require all stats to identify themselves with a description */
+ if (vst->desc == NULL)
+ return;
+
+ if (vstnum >= MAX_VMM_STAT_TYPES) {
+ printf("Cannot accomodate vmm stat type \"%s\"!\n", vst->desc);
+ return;
+ }
+
+ vst->index = vstnum;
+ vsttab[vstnum++] = vst;
+}
+
+int
+vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf)
+{
+ int i;
+ uint64_t *stats;
+
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ stats = vcpu_stats(vm, vcpu);
+ for (i = 0; i < vstnum; i++)
+ buf[i] = stats[i];
+ *num_stats = vstnum;
+ return (0);
+}
+
+void *
+vmm_stat_alloc(void)
+{
+ u_long size;
+
+ size = vstnum * sizeof(uint64_t);
+
+ return (malloc(size, M_VMM_STAT, M_ZERO | M_WAITOK));
+}
+
+void
+vmm_stat_free(void *vp)
+{
+ free(vp, M_VMM_STAT);
+}
+
+const char *
+vmm_stat_desc(int index)
+{
+
+ if (index >= 0 && index < vstnum)
+ return (vsttab[index]->desc);
+ else
+ return (NULL);
+}
diff --git a/sys/amd64/vmm/vmm_stat.h b/sys/amd64/vmm/vmm_stat.h
new file mode 100644
index 0000000..7c075a6
--- /dev/null
+++ b/sys/amd64/vmm/vmm_stat.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_STAT_H_
+#define _VMM_STAT_H_
+
+struct vm;
+
+#define MAX_VMM_STAT_TYPES 64 /* arbitrary */
+
+struct vmm_stat_type {
+ const char *desc; /* description of statistic */
+ int index; /* position in the stats buffer */
+};
+
+void vmm_stat_init(void *arg);
+
+#define VMM_STAT_DEFINE(type, desc) \
+ struct vmm_stat_type type[1] = { \
+ { desc, -1 } \
+ }; \
+ SYSINIT(type##_stat, SI_SUB_KLD, SI_ORDER_ANY, vmm_stat_init, type)
+
+void *vmm_stat_alloc(void);
+void vmm_stat_free(void *vp);
+
+/*
+ * 'buf' should be at least fit 'MAX_VMM_STAT_TYPES' entries
+ */
+int vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf);
+const char *vmm_stat_desc(int index);
+
+static void __inline
+vmm_stat_incr(struct vm *vm, int vcpu, struct vmm_stat_type *vst, uint64_t x)
+{
+#ifdef VMM_KEEP_STATS
+ uint64_t *stats = vcpu_stats(vm, vcpu);
+ if (vst->index >= 0)
+ stats[vst->index] += x;
+#endif
+}
+
+#endif
diff --git a/sys/amd64/vmm/vmm_support.S b/sys/amd64/vmm/vmm_support.S
new file mode 100644
index 0000000..2afc608
--- /dev/null
+++ b/sys/amd64/vmm/vmm_support.S
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define LOCORE
+
+#include <machine/asmacros.h>
+
+#define LA_EOI 0xB0
+
+ .text
+ SUPERALIGN_TEXT
+IDTVEC(justreturn)
+ pushq %rax
+ movq lapic, %rax
+ movl $0, LA_EOI(%rax)
+ popq %rax
+ iretq
diff --git a/sys/amd64/vmm/vmm_util.c b/sys/amd64/vmm/vmm_util.c
new file mode 100644
index 0000000..f245f92
--- /dev/null
+++ b/sys/amd64/vmm/vmm_util.c
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/libkern.h>
+
+#include <machine/md_var.h>
+
+#include "vmm_util.h"
+
+boolean_t
+vmm_is_intel(void)
+{
+
+ if (strcmp(cpu_vendor, "GenuineIntel") == 0)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+boolean_t
+vmm_is_amd(void)
+{
+ if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+boolean_t
+vmm_supports_1G_pages(void)
+{
+ unsigned int regs[4];
+
+ /*
+ * CPUID.80000001:EDX[bit 26] = 1 indicates support for 1GB pages
+ *
+ * Both Intel and AMD support this bit.
+ */
+ if (cpu_exthigh >= 0x80000001) {
+ do_cpuid(0x80000001, regs);
+ if (regs[3] & (1 << 26))
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+#include <sys/proc.h>
+#include <machine/frame.h>
+#define DUMP_REG(x) printf(#x "\t\t0x%016lx\n", (long)(tf->tf_ ## x))
+#define DUMP_SEG(x) printf(#x "\t\t0x%04x\n", (unsigned)(tf->tf_ ## x))
+void
+dump_trapframe(struct trapframe *tf)
+{
+ DUMP_REG(rdi);
+ DUMP_REG(rsi);
+ DUMP_REG(rdx);
+ DUMP_REG(rcx);
+ DUMP_REG(r8);
+ DUMP_REG(r9);
+ DUMP_REG(rax);
+ DUMP_REG(rbx);
+ DUMP_REG(rbp);
+ DUMP_REG(r10);
+ DUMP_REG(r11);
+ DUMP_REG(r12);
+ DUMP_REG(r13);
+ DUMP_REG(r14);
+ DUMP_REG(r15);
+ DUMP_REG(trapno);
+ DUMP_REG(addr);
+ DUMP_REG(flags);
+ DUMP_REG(err);
+ DUMP_REG(rip);
+ DUMP_REG(rflags);
+ DUMP_REG(rsp);
+ DUMP_SEG(cs);
+ DUMP_SEG(ss);
+ DUMP_SEG(fs);
+ DUMP_SEG(gs);
+ DUMP_SEG(es);
+ DUMP_SEG(ds);
+}
diff --git a/sys/amd64/vmm/vmm_util.h b/sys/amd64/vmm/vmm_util.h
new file mode 100644
index 0000000..7f82332
--- /dev/null
+++ b/sys/amd64/vmm/vmm_util.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_UTIL_H_
+#define _VMM_UTIL_H_
+
+struct trapframe;
+
+boolean_t vmm_is_intel(void);
+boolean_t vmm_is_amd(void);
+boolean_t vmm_supports_1G_pages(void);
+
+void dump_trapframe(struct trapframe *tf);
+
+#endif
diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c
new file mode 100644
index 0000000..94abe09
--- /dev/null
+++ b/sys/amd64/vmm/x86.c
@@ -0,0 +1,202 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/cpuset.h>
+
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+#include <machine/vmm.h>
+
+#include "x86.h"
+
+#define CPUID_VM_HIGH 0x40000000
+
+static const char bhyve_id[12] = "BHyVE BHyVE ";
+
+int
+x86_emulate_cpuid(struct vm *vm, int vcpu_id,
+ uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+ int error;
+ unsigned int func, regs[4];
+ enum x2apic_state x2apic_state;
+
+ func = *eax;
+
+ /*
+ * Requests for invalid CPUID levels should map to the highest
+ * available level instead.
+ */
+ if (cpu_exthigh != 0 && *eax >= 0x80000000) {
+ if (*eax > cpu_exthigh)
+ *eax = cpu_exthigh;
+ } else if (*eax >= 0x40000000) {
+ if (*eax > CPUID_VM_HIGH)
+ *eax = CPUID_VM_HIGH;
+ } else if (*eax > cpu_high) {
+ *eax = cpu_high;
+ }
+
+ /*
+ * In general the approach used for CPU topology is to
+ * advertise a flat topology where all CPUs are packages with
+ * no multi-core or SMT.
+ */
+ switch (func) {
+ case CPUID_0000_0000:
+ case CPUID_0000_0002:
+ case CPUID_0000_0003:
+ case CPUID_0000_000A:
+ cpuid_count(*eax, *ecx, regs);
+ break;
+
+ case CPUID_8000_0000:
+ case CPUID_8000_0001:
+ case CPUID_8000_0002:
+ case CPUID_8000_0003:
+ case CPUID_8000_0004:
+ case CPUID_8000_0006:
+ case CPUID_8000_0007:
+ case CPUID_8000_0008:
+ cpuid_count(*eax, *ecx, regs);
+ break;
+
+ case CPUID_0000_0001:
+ do_cpuid(1, regs);
+
+ error = vm_get_x2apic_state(vm, vcpu_id, &x2apic_state);
+ if (error) {
+ panic("x86_emulate_cpuid: error %d "
+ "fetching x2apic state", error);
+ }
+
+ /*
+ * Override the APIC ID only in ebx
+ */
+ regs[1] &= ~(CPUID_LOCAL_APIC_ID);
+ regs[1] |= (vcpu_id << CPUID_0000_0001_APICID_SHIFT);
+
+ /*
+ * Don't expose VMX, SpeedStep or TME capability.
+ * Advertise x2APIC capability and Hypervisor guest.
+ */
+ regs[2] &= ~(CPUID2_VMX | CPUID2_EST | CPUID2_TM2);
+
+ regs[2] |= CPUID2_HV;
+
+ if (x2apic_state != X2APIC_DISABLED)
+ regs[2] |= CPUID2_X2APIC;
+
+ /*
+ * Hide xsave/osxsave/avx until the FPU save/restore
+ * issues are resolved
+ */
+ regs[2] &= ~(CPUID2_XSAVE | CPUID2_OSXSAVE |
+ CPUID2_AVX);
+
+ /*
+ * Hide monitor/mwait until we know how to deal with
+ * these instructions.
+ */
+ regs[2] &= ~CPUID2_MON;
+
+ /*
+ * Hide thermal monitoring
+ */
+ regs[3] &= ~(CPUID_ACPI | CPUID_TM);
+
+ /*
+ * Machine check handling is done in the host.
+ * Hide MTRR capability.
+ */
+ regs[3] &= ~(CPUID_MCA | CPUID_MCE | CPUID_MTRR);
+
+ /*
+ * Disable multi-core.
+ */
+ regs[1] &= ~CPUID_HTT_CORES;
+ regs[3] &= ~CPUID_HTT;
+ break;
+
+ case CPUID_0000_0004:
+ do_cpuid(4, regs);
+
+ /*
+ * Do not expose topology.
+ */
+ regs[0] &= 0xffff8000;
+ regs[0] |= 0x04008000;
+ break;
+
+ case CPUID_0000_0006:
+ case CPUID_0000_0007:
+ /*
+ * Handle the access, but report 0 for
+ * all options
+ */
+ regs[0] = 0;
+ regs[1] = 0;
+ regs[2] = 0;
+ regs[3] = 0;
+ break;
+
+ case CPUID_0000_000B:
+ /*
+ * Processor topology enumeration
+ */
+ regs[0] = 0;
+ regs[1] = 0;
+ regs[2] = *ecx & 0xff;
+ regs[3] = vcpu_id;
+ break;
+
+ case 0x40000000:
+ regs[0] = CPUID_VM_HIGH;
+ bcopy(bhyve_id, &regs[1], 4);
+ bcopy(bhyve_id, &regs[2], 4);
+ bcopy(bhyve_id, &regs[3], 4);
+ break;
+ default:
+ /* XXX: Leaf 5? */
+ return (0);
+ }
+
+ *eax = regs[0];
+ *ebx = regs[1];
+ *ecx = regs[2];
+ *edx = regs[3];
+ return (1);
+}
diff --git a/sys/amd64/vmm/x86.h b/sys/amd64/vmm/x86.h
new file mode 100644
index 0000000..368e967
--- /dev/null
+++ b/sys/amd64/vmm/x86.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _X86_H_
+#define _X86_H_
+
+#define CPUID_0000_0000 (0x0)
+#define CPUID_0000_0001 (0x1)
+#define CPUID_0000_0002 (0x2)
+#define CPUID_0000_0003 (0x3)
+#define CPUID_0000_0004 (0x4)
+#define CPUID_0000_0006 (0x6)
+#define CPUID_0000_0007 (0x7)
+#define CPUID_0000_000A (0xA)
+#define CPUID_0000_000B (0xB)
+#define CPUID_8000_0000 (0x80000000)
+#define CPUID_8000_0001 (0x80000001)
+#define CPUID_8000_0002 (0x80000002)
+#define CPUID_8000_0003 (0x80000003)
+#define CPUID_8000_0004 (0x80000004)
+#define CPUID_8000_0006 (0x80000006)
+#define CPUID_8000_0007 (0x80000007)
+#define CPUID_8000_0008 (0x80000008)
+
+/*
+ * CPUID instruction Fn0000_0001:
+ */
+#define CPUID_0000_0001_APICID_MASK (0xff<<24)
+#define CPUID_0000_0001_APICID_SHIFT 24
+
+/*
+ * CPUID instruction Fn0000_0001 ECX
+ */
+#define CPUID_0000_0001_FEAT0_VMX (1<<5)
+
+int x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx);
+
+#endif
diff --git a/sys/arm/allwinner/a10_clk.c b/sys/arm/allwinner/a10_clk.c
new file mode 100644
index 0000000..2d7699e
--- /dev/null
+++ b/sys/arm/allwinner/a10_clk.c
@@ -0,0 +1,171 @@
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * 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.
+ */
+
+/* Simple clock driver for Allwinner A10 */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include "a10_clk.h"
+
+struct a10_ccm_softc {
+ struct resource *res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct a10_ccm_softc *a10_ccm_sc = NULL;
+
+#define ccm_read_4(reg) \
+ bus_space_read_4(a10_ccm_sc->bst, a10_ccm_sc->bsh, reg)
+#define ccm_write_4(reg, val) \
+ bus_space_write_4(a10_ccm_sc->bst, a10_ccm_sc->bsh, reg, val)
+
+static int
+a10_ccm_probe(device_t dev)
+{
+ if (ofw_bus_is_compatible(dev, "allwinner,sun4i-ccm")) {
+ device_set_desc(dev, "Allwinner Clock Control Module");
+ return(BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+a10_ccm_attach(device_t dev)
+{
+ struct a10_ccm_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ if (a10_ccm_sc)
+ return (ENXIO);
+
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res);
+ sc->bsh = rman_get_bushandle(sc->res);
+
+ a10_ccm_sc = sc;
+
+ return (0);
+}
+
+static device_method_t a10_ccm_methods[] = {
+ DEVMETHOD(device_probe, a10_ccm_probe),
+ DEVMETHOD(device_attach, a10_ccm_attach),
+ { 0, 0 }
+};
+
+static driver_t a10_ccm_driver = {
+ "a10_ccm",
+ a10_ccm_methods,
+ sizeof(struct a10_ccm_softc),
+};
+
+static devclass_t a10_ccm_devclass;
+
+DRIVER_MODULE(a10_ccm, simplebus, a10_ccm_driver, a10_ccm_devclass, 0, 0);
+
+int
+a10_clk_usb_activate(void)
+{
+ struct a10_ccm_softc *sc = a10_ccm_sc;
+ uint32_t reg_value = 0;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ /* Gating AHB clock for USB */
+ reg_value = ccm_read_4(CCM_AHB_GATING0);
+ reg_value |= CCM_AHB_GATING_USB0; /* AHB clock gate usb0 */
+ reg_value |= CCM_AHB_GATING_EHCI1; /* AHB clock gate ehci1 */
+ ccm_write_4(CCM_AHB_GATING0, reg_value);
+
+ /* Enable clock for USB */
+ reg_value = ccm_read_4(CCM_USB_CLK);
+ reg_value |= CCM_USB_PHY; /* USBPHY */
+ reg_value |= CCM_USB0_RESET; /* disable reset for USB0 */
+ reg_value |= CCM_USB1_RESET; /* disable reset for USB1 */
+ reg_value |= CCM_USB2_RESET; /* disable reset for USB2 */
+ ccm_write_4(CCM_USB_CLK, reg_value);
+
+ return (0);
+}
+
+int
+a10_clk_usb_deactivate(void)
+{
+ struct a10_ccm_softc *sc = a10_ccm_sc;
+ uint32_t reg_value = 0;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ /* Disable clock for USB */
+ reg_value = ccm_read_4(CCM_USB_CLK);
+ reg_value &= ~CCM_USB_PHY; /* USBPHY */
+ reg_value &= ~CCM_USB0_RESET; /* reset for USB0 */
+ reg_value &= ~CCM_USB1_RESET; /* reset for USB1 */
+ reg_value &= ~CCM_USB2_RESET; /* reset for USB2 */
+ ccm_write_4(CCM_USB_CLK, reg_value);
+
+ /* Disable gating AHB clock for USB */
+ reg_value = ccm_read_4(CCM_AHB_GATING0);
+ reg_value &= ~CCM_AHB_GATING_USB0; /* disable AHB clock gate usb0 */
+ reg_value &= ~CCM_AHB_GATING_EHCI1; /* disable AHB clock gate ehci1 */
+ ccm_write_4(CCM_AHB_GATING0, reg_value);
+
+ return (0);
+}
+
diff --git a/sys/arm/allwinner/a10_clk.h b/sys/arm/allwinner/a10_clk.h
new file mode 100644
index 0000000..7316a22
--- /dev/null
+++ b/sys/arm/allwinner/a10_clk.h
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * 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 _A10_CLK_H_
+#define _A10_CLK_H_
+
+#define CCMU_BASE 0xe1c20000
+
+#define CCM_PLL1_CFG 0x0000
+#define CCM_PLL1_TUN 0x0004
+#define CCM_PLL2_CFG 0x0008
+#define CCM_PLL2_TUN 0x000c
+#define CCM_PLL3_CFG 0x0010
+#define CCM_PLL3_TUN 0x0014
+#define CCM_PLL4_CFG 0x0018
+#define CCM_PLL4_TUN 0x001c
+#define CCM_PLL5_CFG 0x0020
+#define CCM_PLL5_TUN 0x0024
+#define CCM_PLL6_CFG 0x0028
+#define CCM_PLL6_TUN 0x002c
+#define CCM_PLL7_CFG 0x0030
+#define CCM_PLL7_TUN 0x0034
+#define CCM_PLL1_TUN2 0x0038
+#define CCM_PLL5_TUN2 0x003c
+#define CCM_PLL_LOCK_DBG 0x004c
+#define CCM_OSC24M_CFG 0x0050
+#define CCM_CPU_AHB_APB0_CFG 0x0054
+#define CCM_APB1_CLK_DIV 0x0058
+#define CCM_AXI_GATING 0x005c
+#define CCM_AHB_GATING0 0x0060
+#define CCM_AHB_GATING1 0x0064
+#define CCM_APB0_GATING 0x0068
+#define CCM_APB1_GATING 0x006c
+#define CCM_NAND_SCLK_CFG 0x0080
+#define CCM_MS_SCLK_CFG 0x0084
+#define CCM_MMC0_SCLK_CFG 0x0088
+#define CCM_MMC1_SCLK_CFG 0x008c
+#define CCM_MMC2_SCLK_CFG 0x0090
+#define CCM_MMC3_SCLK_CFG 0x0094
+#define CCM_TS_CLK 0x0098
+#define CCM_SS_CLK 0x009c
+#define CCM_SPI0_CLK 0x00a0
+#define CCM_SPI1_CLK 0x00a4
+#define CCM_SPI2_CLK 0x00a8
+#define CCM_PATA_CLK 0x00ac
+#define CCM_IR0_CLK 0x00b0
+#define CCM_IR1_CLK 0x00b4
+#define CCM_IIS_CLK 0x00b8
+#define CCM_AC97_CLK 0x00bc
+#define CCM_SPDIF_CLK 0x00c0
+#define CCM_KEYPAD_CLK 0x00c4
+#define CCM_SATA_CLK 0x00c8
+#define CCM_USB_CLK 0x00cc
+#define CCM_GPS_CLK 0x00d0
+#define CCM_SPI3_CLK 0x00d4
+#define CCM_DRAM_CLK 0x0100
+#define CCM_BE0_SCLK 0x0104
+#define CCM_BE1_SCLK 0x0108
+#define CCM_FE0_CLK 0x010c
+#define CCM_FE1_CLK 0x0110
+#define CCM_MP_CLK 0x0114
+#define CCM_LCD0_CH0_CLK 0x0118
+#define CCM_LCD1_CH0_CLK 0x011c
+#define CCM_CSI_ISP_CLK 0x0120
+#define CCM_TVD_CLK 0x0128
+#define CCM_LCD0_CH1_CLK 0x012c
+#define CCM_LCD1_CH1_CLK 0x0130
+#define CCM_CS0_CLK 0x0134
+#define CCM_CS1_CLK 0x0138
+#define CCM_VE_CLK 0x013c
+#define CCM_AUDIO_CODEC_CLK 0x0140
+#define CCM_AVS_CLK 0x0144
+#define CCM_ACE_CLK 0x0148
+#define CCM_LVDS_CLK 0x014c
+#define CCM_HDMI_CLK 0x0150
+#define CCM_MALI400_CLK 0x0154
+
+#define CCM_AHB_GATING_USB0 (1 << 0)
+#define CCM_AHB_GATING_EHCI1 (1 << 3)
+
+#define CCM_USB_PHY (1 << 8)
+#define CCM_USB0_RESET (1 << 0)
+#define CCM_USB1_RESET (1 << 1)
+#define CCM_USB2_RESET (1 << 2)
+
+int a10_clk_usb_activate(void);
+int a10_clk_usb_deactivate(void);
+
+#endif /* _A10_CLK_H_ */
diff --git a/sys/arm/allwinner/a10_ehci.c b/sys/arm/allwinner/a10_ehci.c
new file mode 100644
index 0000000..d3a90d0
--- /dev/null
+++ b/sys/arm/allwinner/a10_ehci.c
@@ -0,0 +1,279 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * 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.
+ */
+
+/*
+ * Allwinner A10 attachment driver for the USB Enhanced Host Controller.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include "a10_clk.h"
+
+#define EHCI_HC_DEVSTR "Allwinner Integrated USB 2.0 controller"
+
+#define SW_USB_PMU_IRQ_ENABLE 0x800
+
+#define SW_SDRAM_REG_HPCR_USB1 (0x250 + ((1 << 2) * 4))
+#define SW_SDRAM_REG_HPCR_USB2 (0x250 + ((1 << 2) * 5))
+#define SW_SDRAM_BP_HPCR_ACCESS (1 << 0)
+
+#define SW_ULPI_BYPASS (1 << 0)
+#define SW_AHB_INCRX_ALIGN (1 << 8)
+#define SW_AHB_INCR4 (1 << 9)
+#define SW_AHB_INCR8 (1 << 10)
+
+#define A10_READ_4(sc, reg) \
+ bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
+
+#define A10_WRITE_4(sc, reg, data) \
+ bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
+
+static device_attach_t a10_ehci_attach;
+static device_detach_t a10_ehci_detach;
+
+bs_r_1_proto(reversed);
+bs_w_1_proto(reversed);
+
+static int
+a10_ehci_probe(device_t self)
+{
+ if (!ofw_bus_is_compatible(self, "allwinner,usb-ehci"))
+ return (ENXIO);
+
+ device_set_desc(self, EHCI_HC_DEVSTR);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_ehci_attach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ bus_space_handle_t bsh;
+ int err;
+ int rid;
+ uint32_t reg_value = 0;
+
+ /* initialise some bus fields */
+ sc->sc_bus.parent = self;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus,
+ USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
+ return (ENOMEM);
+ }
+
+ sc->sc_bus.usbrev = USB_REV_2_0;
+
+ rid = 0;
+ sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->sc_io_res) {
+ device_printf(self, "Could not map memory\n");
+ goto error;
+ }
+
+ sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+ sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+ bsh = rman_get_bushandle(sc->sc_io_res);
+
+ sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+ if (bus_space_subregion(sc->sc_io_tag, bsh, 0x00,
+ sc->sc_io_size, &sc->sc_io_hdl) != 0)
+ panic("%s: unable to subregion USB host registers",
+ device_get_name(self));
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(self, "Could not allocate irq\n");
+ goto error;
+ }
+ sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(self, "Could not add USB device\n");
+ goto error;
+ }
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+ device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);
+
+ sprintf(sc->sc_vendor, "Allwinner");
+
+ err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+ if (err) {
+ device_printf(self, "Could not setup irq, %d\n", err);
+ sc->sc_intr_hdl = NULL;
+ goto error;
+ }
+
+ sc->sc_flags |= EHCI_SCFLG_DONTRESET;
+
+ /* Enable clock for USB */
+ a10_clk_usb_activate();
+
+ /* Enable passby */
+ reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE);
+ reg_value |= SW_AHB_INCR8; /* AHB INCR8 enable */
+ reg_value |= SW_AHB_INCR4; /* AHB burst type INCR4 enable */
+ reg_value |= SW_AHB_INCRX_ALIGN; /* AHB INCRX align enable */
+ reg_value |= SW_ULPI_BYPASS; /* ULPI bypass enable */
+ A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);
+
+ /* Configure port */
+ reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2);
+ reg_value |= SW_SDRAM_BP_HPCR_ACCESS;
+ A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value);
+
+ err = ehci_init(sc);
+ if (!err) {
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ }
+ if (err) {
+ device_printf(self, "USB init failed err=%d\n", err);
+ goto error;
+ }
+ return (0);
+
+error:
+ a10_ehci_detach(self);
+ return (ENXIO);
+}
+
+static int
+a10_ehci_detach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ device_t bdev;
+ int err;
+ uint32_t reg_value = 0;
+
+ if (sc->sc_bus.bdev) {
+ bdev = sc->sc_bus.bdev;
+ device_detach(bdev);
+ device_delete_child(self, bdev);
+ }
+ /* during module unload there are lots of children leftover */
+ device_delete_children(self);
+
+ if (sc->sc_irq_res && sc->sc_intr_hdl) {
+ /*
+ * only call ehci_detach() after ehci_init()
+ */
+ ehci_detach(sc);
+
+ err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
+
+ if (err)
+ /* XXX or should we panic? */
+ device_printf(self, "Could not tear down irq, %d\n",
+ err);
+ sc->sc_intr_hdl = NULL;
+ }
+
+ if (sc->sc_irq_res) {
+ bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+ if (sc->sc_io_res) {
+ bus_release_resource(self, SYS_RES_MEMORY, 0,
+ sc->sc_io_res);
+ sc->sc_io_res = NULL;
+ }
+ usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
+
+ /* Disable configure port */
+ reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2);
+ reg_value &= ~SW_SDRAM_BP_HPCR_ACCESS;
+ A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value);
+
+ /* Disable passby */
+ reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE);
+ reg_value &= ~SW_AHB_INCR8; /* AHB INCR8 disable */
+ reg_value &= ~SW_AHB_INCR4; /* AHB burst type INCR4 disable */
+ reg_value &= ~SW_AHB_INCRX_ALIGN; /* AHB INCRX align disable */
+ reg_value &= ~SW_ULPI_BYPASS; /* ULPI bypass disable */
+ A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);
+
+ /* Disable clock for USB */
+ a10_clk_usb_deactivate();
+
+ return (0);
+}
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, a10_ehci_probe),
+ DEVMETHOD(device_attach, a10_ehci_attach),
+ DEVMETHOD(device_detach, a10_ehci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD_END
+};
+
+static driver_t ehci_driver = {
+ .name = "ehci",
+ .methods = ehci_methods,
+ .size = sizeof(ehci_softc_t),
+};
+
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
+MODULE_DEPEND(ehci, usb, 1, 1, 1);
diff --git a/sys/arm/allwinner/a10_machdep.c b/sys/arm/allwinner/a10_machdep.c
new file mode 100644
index 0000000..1ad9ea1
--- /dev/null
+++ b/sys/arm/allwinner/a10_machdep.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/ti/ti_machdep.c
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/frame.h> /* For trapframe_t, used in <machine/machdep.h> */
+#include <machine/machdep.h>
+#include <machine/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+
+/* Start of address space used for bootstrap map */
+#define DEVMAP_BOOTSTRAP_MAP_START 0xE0000000
+
+void (*a10_cpu_reset)(void);
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ a10_cpu_reset = NULL;
+ return (DEVMAP_BOOTSTRAP_MAP_START - ARM_NOCACHE_KVA_SIZE);
+}
+
+void
+initarm_gpio_init(void)
+{
+}
+
+void
+initarm_late_init(void)
+{
+}
+
+#define FDT_DEVMAP_MAX (1 + 2 + 1 + 1)
+static struct pmap_devmap fdt_devmap[FDT_DEVMAP_MAX] = {
+ { 0, 0, 0, 0, 0, }
+};
+
+/*
+ * Construct pmap_devmap[] with DT-derived config data.
+ */
+int
+platform_devmap_init(void)
+{
+ int i = 0;
+
+ fdt_devmap[i].pd_va = 0xE1C00000;
+ fdt_devmap[i].pd_pa = 0x01C00000;
+ fdt_devmap[i].pd_size = 0x00400000; /* 4 MB */
+ fdt_devmap[i].pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ fdt_devmap[i].pd_cache = PTE_DEVICE;
+
+ i++;
+
+ pmap_devmap_bootstrap_table = &fdt_devmap[0];
+
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+ return (0);
+}
+
+void
+cpu_reset()
+{
+ if (a10_cpu_reset)
+ (*a10_cpu_reset)();
+ else
+ printf("no cpu_reset implementation\n");
+ printf("Reset failed!\n");
+ while (1);
+}
diff --git a/sys/arm/allwinner/aintc.c b/sys/arm/allwinner/aintc.c
new file mode 100644
index 0000000..bfa35f5
--- /dev/null
+++ b/sys/arm/allwinner/aintc.c
@@ -0,0 +1,211 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/**
+ * Interrupt controller registers
+ *
+ */
+#define SW_INT_VECTOR_REG 0x00
+#define SW_INT_BASE_ADR_REG 0x04
+#define SW_INT_PROTECTION_REG 0x08
+#define SW_INT_NMI_CTRL_REG 0x0c
+
+#define SW_INT_IRQ_PENDING_REG0 0x10
+#define SW_INT_IRQ_PENDING_REG1 0x14
+#define SW_INT_IRQ_PENDING_REG2 0x18
+
+#define SW_INT_FIQ_PENDING_REG0 0x20
+#define SW_INT_FIQ_PENDING_REG1 0x24
+#define SW_INT_FIQ_PENDING_REG2 0x28
+
+#define SW_INT_SELECT_REG0 0x30
+#define SW_INT_SELECT_REG1 0x34
+#define SW_INT_SELECT_REG2 0x38
+
+#define SW_INT_ENABLE_REG0 0x40
+#define SW_INT_ENABLE_REG1 0x44
+#define SW_INT_ENABLE_REG2 0x48
+
+#define SW_INT_MASK_REG0 0x50
+#define SW_INT_MASK_REG1 0x54
+#define SW_INT_MASK_REG2 0x58
+
+#define SW_INT_IRQNO_ENMI 0
+
+#define SW_INT_IRQ_PENDING_REG(_b) (0x10 + ((_b) * 4))
+#define SW_INT_FIQ_PENDING_REG(_b) (0x20 + ((_b) * 4))
+#define SW_INT_SELECT_REG(_b) (0x30 + ((_b) * 4))
+#define SW_INT_ENABLE_REG(_b) (0x40 + ((_b) * 4))
+#define SW_INT_MASK_REG(_b) (0x50 + ((_b) * 4))
+
+struct a10_aintc_softc {
+ device_t sc_dev;
+ struct resource * aintc_res;
+ bus_space_tag_t aintc_bst;
+ bus_space_handle_t aintc_bsh;
+ uint8_t ver;
+};
+
+static struct a10_aintc_softc *a10_aintc_sc = NULL;
+
+#define aintc_read_4(reg) \
+ bus_space_read_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg)
+#define aintc_write_4(reg, val) \
+ bus_space_write_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg, val)
+
+static int
+a10_aintc_probe(device_t dev)
+{
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-ic"))
+ return (ENXIO);
+ device_set_desc(dev, "A10 AINTC Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_aintc_attach(device_t dev)
+{
+ struct a10_aintc_softc *sc = device_get_softc(dev);
+ int rid = 0;
+ int i;
+
+ sc->sc_dev = dev;
+
+ if (a10_aintc_sc)
+ return (ENXIO);
+
+ sc->aintc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->aintc_res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->aintc_bst = rman_get_bustag(sc->aintc_res);
+ sc->aintc_bsh = rman_get_bushandle(sc->aintc_res);
+
+ a10_aintc_sc = sc;
+
+ /* Disable & clear all interrupts */
+ for (i = 0; i < 3; i++) {
+ aintc_write_4(SW_INT_ENABLE_REG(i), 0);
+ aintc_write_4(SW_INT_MASK_REG(i), 0xffffffff);
+ }
+ /* enable protection mode*/
+ aintc_write_4(SW_INT_PROTECTION_REG, 0x01);
+
+ /* config the external interrupt source type*/
+ aintc_write_4(SW_INT_NMI_CTRL_REG, 0x00);
+
+ return (0);
+}
+
+static device_method_t a10_aintc_methods[] = {
+ DEVMETHOD(device_probe, a10_aintc_probe),
+ DEVMETHOD(device_attach, a10_aintc_attach),
+ { 0, 0 }
+};
+
+static driver_t a10_aintc_driver = {
+ "aintc",
+ a10_aintc_methods,
+ sizeof(struct a10_aintc_softc),
+};
+
+static devclass_t a10_aintc_devclass;
+
+DRIVER_MODULE(aintc, simplebus, a10_aintc_driver, a10_aintc_devclass, 0, 0);
+
+int
+arm_get_next_irq(int last_irq)
+{
+ uint32_t value;
+ int i, b;
+
+ for (i = 0; i < 3; i++) {
+ value = aintc_read_4(SW_INT_IRQ_PENDING_REG(i));
+ for (b = 0; b < 32; b++)
+ if (value & (1 << b)) {
+ return (i * 32 + b);
+ }
+ }
+
+ return (-1);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ uint32_t bit, block, value;
+
+ bit = (nb % 32);
+ block = (nb / 32);
+
+ value = aintc_read_4(SW_INT_ENABLE_REG(block));
+ value &= ~(1 << bit);
+ aintc_write_4(SW_INT_ENABLE_REG(block), value);
+
+ value = aintc_read_4(SW_INT_MASK_REG(block));
+ value |= (1 << bit);
+ aintc_write_4(SW_INT_MASK_REG(block), value);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ uint32_t bit, block, value;
+
+ bit = (nb % 32);
+ block = (nb / 32);
+
+ value = aintc_read_4(SW_INT_ENABLE_REG(block));
+ value |= (1 << bit);
+ aintc_write_4(SW_INT_ENABLE_REG(block), value);
+
+ value = aintc_read_4(SW_INT_MASK_REG(block));
+ value &= ~(1 << bit);
+ aintc_write_4(SW_INT_MASK_REG(block), value);
+
+ if(nb == SW_INT_IRQNO_ENMI) /* must clear pending bit when enabled */
+ aintc_write_4(SW_INT_IRQ_PENDING_REG(0), (1 << SW_INT_IRQNO_ENMI));
+}
diff --git a/sys/arm/allwinner/bus_space.c b/sys/arm/allwinner/bus_space.c
new file mode 100644
index 0000000..4cce820
--- /dev/null
+++ b/sys/arm/allwinner/bus_space.c
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (C) 2012 FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(generic);
+bs_protos(generic_armv4);
+
+struct bus_space _base_tag = {
+ /* cookie */
+ .bs_cookie = (void *) 0,
+
+ /* mapping/unmapping */
+ .bs_map = generic_bs_map,
+ .bs_unmap = generic_bs_unmap,
+ .bs_subregion = generic_bs_subregion,
+
+ /* allocation/deallocation */
+ .bs_alloc = generic_bs_alloc,
+ .bs_free = generic_bs_free,
+
+ /* barrier */
+ .bs_barrier = generic_bs_barrier,
+
+ /* read (single) */
+ .bs_r_1 = generic_bs_r_1,
+ .bs_r_2 = generic_armv4_bs_r_2,
+ .bs_r_4 = generic_bs_r_4,
+ .bs_r_8 = NULL,
+
+ /* read multiple */
+ .bs_rm_1 = generic_bs_rm_1,
+ .bs_rm_2 = generic_armv4_bs_rm_2,
+ .bs_rm_4 = generic_bs_rm_4,
+ .bs_rm_8 = NULL,
+
+ /* read region */
+ .bs_rr_1 = generic_bs_rr_1,
+ .bs_rr_2 = generic_armv4_bs_rr_2,
+ .bs_rr_4 = generic_bs_rr_4,
+ .bs_rr_8 = NULL,
+
+ /* write (single) */
+ .bs_w_1 = generic_bs_w_1,
+ .bs_w_2 = generic_armv4_bs_w_2,
+ .bs_w_4 = generic_bs_w_4,
+ .bs_w_8 = NULL,
+
+ /* write multiple */
+ .bs_wm_1 = generic_bs_wm_1,
+ .bs_wm_2 = generic_armv4_bs_wm_2,
+ .bs_wm_4 = generic_bs_wm_4,
+ .bs_wm_8 = NULL,
+
+ /* write region */
+ .bs_wr_1 = generic_bs_wr_1,
+ .bs_wr_2 = generic_armv4_bs_wr_2,
+ .bs_wr_4 = generic_bs_wr_4,
+ .bs_wr_8 = NULL,
+
+ /* set multiple */
+ /* XXX not implemented */
+
+ /* set region */
+ .bs_sr_1 = NULL,
+ .bs_sr_2 = generic_armv4_bs_sr_2,
+ .bs_sr_4 = generic_bs_sr_4,
+ .bs_sr_8 = NULL,
+
+ /* copy */
+ .bs_c_1 = NULL,
+ .bs_c_2 = generic_armv4_bs_c_2,
+ .bs_c_4 = NULL,
+ .bs_c_8 = NULL,
+};
+
+bus_space_tag_t fdtbus_bs_tag = &_base_tag;
diff --git a/sys/arm/allwinner/common.c b/sys/arm/allwinner/common.c
new file mode 100644
index 0000000..eb49479
--- /dev/null
+++ b/sys/arm/allwinner/common.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+ if (!fdt_is_compatible(node, "allwinner,sun4i-ic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_aintc_decode_ic,
+ NULL
+};
diff --git a/sys/arm/allwinner/console.c b/sys/arm/allwinner/console.c
new file mode 100644
index 0000000..52d7376
--- /dev/null
+++ b/sys/arm/allwinner/console.c
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * 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.
+ */
+
+/* Simple UART console driver for Allwinner A10 */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cons.h>
+#include <sys/consio.h>
+#include <sys/kernel.h>
+
+#ifndef A10_UART_BASE
+#define A10_UART_BASE 0xe1c28000 /* UART0 */
+#endif
+
+#define REG_SHIFT 2
+
+#define UART_DLL 0 /* Out: Divisor Latch Low */
+#define UART_DLM 1 /* Out: Divisor Latch High */
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+
+static uint32_t
+uart_getreg(uint32_t *bas)
+{
+ return *((volatile uint32_t *)(bas)) & 0xff;
+}
+
+static void
+uart_setreg(uint32_t *bas, uint32_t val)
+{
+ *((volatile uint32_t *)(bas)) = val;
+}
+
+static int
+ub_getc(void)
+{
+ while ((uart_getreg((uint32_t *)(A10_UART_BASE +
+ (UART_LSR << REG_SHIFT))) & UART_LSR_DR) == 0);
+ __asm __volatile("nop");
+
+ return (uart_getreg((uint32_t *)A10_UART_BASE) & 0xff);
+}
+
+static void
+ub_putc(unsigned char c)
+{
+ if (c == '\n')
+ ub_putc('\r');
+
+ while ((uart_getreg((uint32_t *)(A10_UART_BASE +
+ (UART_LSR << REG_SHIFT))) & UART_LSR_THRE) == 0)
+ __asm __volatile("nop");
+
+ uart_setreg((uint32_t *)A10_UART_BASE, c);
+}
+
+static cn_probe_t uart_cnprobe;
+static cn_init_t uart_cninit;
+static cn_term_t uart_cnterm;
+static cn_getc_t uart_cngetc;
+static cn_putc_t uart_cnputc;
+static cn_grab_t uart_cngrab;
+static cn_ungrab_t uart_cnungrab;
+
+static void
+uart_cngrab(struct consdev *cp)
+{
+}
+
+static void
+uart_cnungrab(struct consdev *cp)
+{
+}
+
+
+static void
+uart_cnprobe(struct consdev *cp)
+{
+ sprintf(cp->cn_name, "uart");
+ cp->cn_pri = CN_NORMAL;
+}
+
+static void
+uart_cninit(struct consdev *cp)
+{
+ uart_setreg((uint32_t *)(A10_UART_BASE +
+ (UART_FCR << REG_SHIFT)), 0x06);
+}
+
+void
+uart_cnputc(struct consdev *cp, int c)
+{
+ ub_putc(c);
+}
+
+int
+uart_cngetc(struct consdev * cp)
+{
+ return ub_getc();
+}
+
+static void
+uart_cnterm(struct consdev * cp)
+{
+}
+
+CONSOLE_DRIVER(uart);
+
diff --git a/sys/arm/allwinner/files.a10 b/sys/arm/allwinner/files.a10
new file mode 100644
index 0000000..9d056fc
--- /dev/null
+++ b/sys/arm/allwinner/files.a10
@@ -0,0 +1,19 @@
+# $FreeBSD$
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+arm/arm/irq_dispatch.S standard
+
+arm/allwinner/a10_clk.c standard
+arm/allwinner/a10_ehci.c optional ehci
+arm/allwinner/timer.c standard
+arm/allwinner/aintc.c standard
+arm/allwinner/bus_space.c standard
+arm/allwinner/common.c standard
+arm/allwinner/console.c standard
+arm/allwinner/a10_machdep.c standard
diff --git a/sys/arm/allwinner/std.a10 b/sys/arm/allwinner/std.a10
new file mode 100644
index 0000000..f698b34
--- /dev/null
+++ b/sys/arm/allwinner/std.a10
@@ -0,0 +1,21 @@
+# Allwinner A10 common options
+#$FreeBSD$
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoption ARM_LITTLE_ENDIAN
+
+# Physical memory starts at 0x40200000. We assume images are loaded at
+# 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel'
+#
+#
+options PHYSADDR=0x40000000
+
+makeoptions KERNPHYSADDR=0x40200000
+options KERNPHYSADDR=0x40200000
+makeoptions KERNVIRTADDR=0xc0200000
+options KERNVIRTADDR=0xc0200000
+
+options STARTUP_PAGETABLE_ADDR=0x48000000
+
+files "../allwinner/files.a10"
diff --git a/sys/arm/allwinner/timer.c b/sys/arm/allwinner/timer.c
new file mode 100644
index 0000000..4da3517
--- /dev/null
+++ b/sys/arm/allwinner/timer.c
@@ -0,0 +1,379 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <sys/kdb.h>
+
+/**
+ * Timer registers addr
+ *
+ */
+#define SW_TIMER_IRQ_EN_REG 0x00
+#define SW_TIMER_IRQ_STA_REG 0x04
+#define SW_TIMER0_CTRL_REG 0x10
+#define SW_TIMER0_INT_VALUE_REG 0x14
+#define SW_TIMER0_CUR_VALUE_REG 0x18
+
+#define SW_COUNTER64LO_REG 0xa4
+#define SW_COUNTER64HI_REG 0xa8
+#define CNT64_CTRL_REG 0xa0
+
+#define CNT64_RL_EN 0x02 /* read latch enable */
+
+#define TIMER_ENABLE (1<<0)
+#define TIMER_AUTORELOAD (1<<1)
+#define TIMER_OSC24M (1<<2) /* oscillator = 24mhz */
+#define TIMER_PRESCALAR (4<<4) /* prescalar = 16 */
+
+#define SYS_TIMER_CLKSRC 24000000 /* clock source */
+
+struct a10_timer_softc {
+ device_t sc_dev;
+ struct resource *res[2];
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ void *sc_ih; /* interrupt handler */
+ uint32_t sc_period;
+ uint32_t timer0_freq;
+ struct eventtimer et;
+};
+
+int a10_timer_get_timerfreq(struct a10_timer_softc *);
+
+#define timer_read_4(sc, reg) \
+ bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg)
+#define timer_write_4(sc, reg, val) \
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val)
+
+static u_int a10_timer_get_timecount(struct timecounter *);
+static int a10_timer_timer_start(struct eventtimer *,
+ struct bintime *, struct bintime *);
+static int a10_timer_timer_stop(struct eventtimer *);
+
+static uint64_t timer_read_counter64(void);
+
+static int a10_timer_initialized = 0;
+static int a10_timer_hardclock(void *);
+static int a10_timer_probe(device_t);
+static int a10_timer_attach(device_t);
+
+static struct timecounter a10_timer_timecounter = {
+ .tc_name = "a10_timer timer0",
+ .tc_get_timecount = a10_timer_get_timecount,
+ .tc_counter_mask = ~0u,
+ .tc_frequency = 0,
+ .tc_quality = 1000,
+};
+
+struct a10_timer_softc *a10_timer_sc = NULL;
+
+static struct resource_spec a10_timer_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static uint64_t
+timer_read_counter64(void)
+{
+ uint32_t lo, hi;
+
+ /* Latch counter, wait for it to be ready to read. */
+ timer_write_4(a10_timer_sc, CNT64_CTRL_REG, CNT64_RL_EN);
+ while (timer_read_4(a10_timer_sc, CNT64_CTRL_REG) & CNT64_RL_EN)
+ continue;
+
+ hi = timer_read_4(a10_timer_sc, SW_COUNTER64HI_REG);
+ lo = timer_read_4(a10_timer_sc, SW_COUNTER64LO_REG);
+
+ return (((uint64_t)hi << 32) | lo);
+}
+
+static int
+a10_timer_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-timer"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Allwinner A10 timer");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_timer_attach(device_t dev)
+{
+ struct a10_timer_softc *sc;
+ int err;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, a10_timer_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->sc_dev = dev;
+ sc->sc_bst = rman_get_bustag(sc->res[0]);
+ sc->sc_bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Setup and enable the timer interrupt */
+ err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, a10_timer_hardclock,
+ NULL, sc, &sc->sc_ih);
+ if (err != 0) {
+ bus_release_resources(dev, a10_timer_spec, sc->res);
+ device_printf(dev, "Unable to setup the clock irq handler, "
+ "err = %d\n", err);
+ return (ENXIO);
+ }
+
+ /* Set clock source to OSC24M, 16 pre-division */
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ val |= TIMER_PRESCALAR | TIMER_OSC24M;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ /* Enable timer0 */
+ val = timer_read_4(sc, SW_TIMER_IRQ_EN_REG);
+ val |= TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER_IRQ_EN_REG, val);
+
+ sc->timer0_freq = SYS_TIMER_CLKSRC;
+
+ /* Set desired frequency in event timer and timecounter */
+ sc->et.et_frequency = sc->timer0_freq;
+ sc->et.et_name = "a10_timer Eventtimer";
+ sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
+ sc->et.et_quality = 1000;
+ sc->et.et_min_period.sec = 0;
+ sc->et.et_min_period.frac =
+ ((0x00000005LLU << 32) / sc->et.et_frequency) << 32;
+ sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
+ sc->et.et_max_period.frac =
+ ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
+ sc->et.et_start = a10_timer_timer_start;
+ sc->et.et_stop = a10_timer_timer_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ if (device_get_unit(dev) == 0)
+ a10_timer_sc = sc;
+
+ a10_timer_timecounter.tc_frequency = sc->timer0_freq;
+ tc_init(&a10_timer_timecounter);
+
+ if (bootverbose) {
+ device_printf(sc->sc_dev, "clock: hz=%d stathz = %d\n", hz, stathz);
+
+ device_printf(sc->sc_dev, "event timer clock frequency %u\n",
+ sc->timer0_freq);
+ device_printf(sc->sc_dev, "timecounter clock frequency %lld\n",
+ a10_timer_timecounter.tc_frequency);
+ }
+
+ a10_timer_initialized = 1;
+
+ return (0);
+}
+
+static int
+a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
+ struct bintime *period)
+{
+ struct a10_timer_softc *sc;
+ uint32_t count;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)et->et_priv;
+
+ sc->sc_period = 0;
+
+ if (period != NULL) {
+ sc->sc_period = (sc->et.et_frequency * (period->frac >> 32)) >> 32;
+ sc->sc_period += sc->et.et_frequency * period->sec;
+ }
+ if (first == NULL)
+ count = sc->sc_period;
+ else {
+ count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
+ if (first->sec != 0)
+ count += sc->et.et_frequency * first->sec;
+ }
+
+ /* Update timer values */
+ timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, sc->sc_period);
+ timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, count);
+
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ if (first == NULL) {
+ /* periodic */
+ val |= TIMER_AUTORELOAD;
+ } else {
+ /* oneshot */
+ val &= ~TIMER_AUTORELOAD;
+ }
+ /* Enable timer0 */
+ val |= TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ return (0);
+}
+
+static int
+a10_timer_timer_stop(struct eventtimer *et)
+{
+ struct a10_timer_softc *sc;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)et->et_priv;
+
+ /* Disable timer0 */
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ val &= ~TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ sc->sc_period = 0;
+
+ return (0);
+}
+
+int
+a10_timer_get_timerfreq(struct a10_timer_softc *sc)
+{
+ return (sc->timer0_freq);
+}
+
+void
+cpu_initclocks(void)
+{
+ cpu_initclocks_bsp();
+}
+
+static int
+a10_timer_hardclock(void *arg)
+{
+ struct a10_timer_softc *sc;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)arg;
+
+ /* Clear interrupt pending bit. */
+ timer_write_4(sc, SW_TIMER_IRQ_STA_REG, 0x1);
+
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ /*
+ * Disabled autoreload and sc_period > 0 means
+ * timer_start was called with non NULL first value.
+ * Now we will set periodic timer with the given period
+ * value.
+ */
+ if ((val & (1<<1)) == 0 && sc->sc_period > 0) {
+ /* Update timer */
+ timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, sc->sc_period);
+
+ /* Make periodic and enable */
+ val |= TIMER_AUTORELOAD | TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+ }
+
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+
+ return (FILTER_HANDLED);
+}
+
+u_int
+a10_timer_get_timecount(struct timecounter *tc)
+{
+
+ if (a10_timer_sc == NULL)
+ return (0);
+
+ return ((u_int)timer_read_counter64());
+}
+
+static device_method_t a10_timer_methods[] = {
+ DEVMETHOD(device_probe, a10_timer_probe),
+ DEVMETHOD(device_attach, a10_timer_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t a10_timer_driver = {
+ "a10_timer",
+ a10_timer_methods,
+ sizeof(struct a10_timer_softc),
+};
+
+static devclass_t a10_timer_devclass;
+
+DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0);
+
+void
+DELAY(int usec)
+{
+ uint32_t counter;
+ uint64_t end, now;
+
+ if (!a10_timer_initialized) {
+ for (; usec > 0; usec--)
+ for (counter = 50; counter > 0; counter--)
+ cpufunc_nullop();
+ return;
+ }
+
+ now = timer_read_counter64();
+ end = now + (a10_timer_sc->timer0_freq / 1000000) * (usec + 1);
+
+ while (now < end)
+ now = timer_read_counter64();
+}
+
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index 42566e8..fa7afd4 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -849,9 +849,6 @@ bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs,
vm_offset_t vaddr = (vm_offset_t)buf;
int seg;
int error = 0;
- pd_entry_t *pde;
- pt_entry_t pte;
- pt_entry_t *ptep;
lastaddr = *lastaddrp;
bmask = ~(dmat->boundary - 1);
@@ -868,34 +865,9 @@ bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs,
for (seg = *segp; buflen > 0 ; ) {
/*
* Get the physical address for this segment.
- *
- * XXX Don't support checking for coherent mappings
- * XXX in user address space.
*/
if (__predict_true(pmap == pmap_kernel())) {
- if (pmap_get_pde_pte(pmap, vaddr, &pde, &ptep) == FALSE)
- return (EFAULT);
-
- if (__predict_false(pmap_pde_section(pde))) {
- if (*pde & L1_S_SUPERSEC)
- curaddr = (*pde & L1_SUP_FRAME) |
- (vaddr & L1_SUP_OFFSET);
- else
- curaddr = (*pde & L1_S_FRAME) |
- (vaddr & L1_S_OFFSET);
- } else {
- pte = *ptep;
- KASSERT((pte & L2_TYPE_MASK) != L2_TYPE_INV,
- ("INV type"));
- if (__predict_false((pte & L2_TYPE_MASK)
- == L2_TYPE_L)) {
- curaddr = (pte & L2_L_FRAME) |
- (vaddr & L2_L_OFFSET);
- } else {
- curaddr = (pte & L2_S_FRAME) |
- (vaddr & L2_S_OFFSET);
- }
- }
+ curaddr = pmap_kextract(vaddr);
} else {
curaddr = pmap_extract(pmap, vaddr);
map->flags &= ~DMAMAP_COHERENT;
diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c
index 5dc2679..1d15e27 100644
--- a/sys/arm/arm/cpufunc.c
+++ b/sys/arm/arm/cpufunc.c
@@ -1146,7 +1146,7 @@ struct cpu_functions cortexa_cpufuncs = {
/* Other functions */
cpufunc_nullop, /* flush_prefetchbuf */
- arm11_drain_writebuf, /* drain_writebuf */
+ armv7_drain_writebuf, /* drain_writebuf */
cpufunc_nullop, /* flush_brnchtgt_C */
(void *)cpufunc_nullop, /* flush_brnchtgt_E */
@@ -1157,7 +1157,7 @@ struct cpu_functions cortexa_cpufuncs = {
cpufunc_null_fixup, /* dataabt_fixup */
cpufunc_null_fixup, /* prefetchabt_fixup */
- arm11_context_switch, /* context_switch */
+ armv7_context_switch, /* context_switch */
cortexa_setup /* cpu setup */
};
diff --git a/sys/arm/arm/cpufunc_asm_arm10.S b/sys/arm/arm/cpufunc_asm_arm10.S
index 22da6aa..2ef999c 100644
--- a/sys/arm/arm/cpufunc_asm_arm10.S
+++ b/sys/arm/arm/cpufunc_asm_arm10.S
@@ -87,7 +87,7 @@ ENTRY_NP(arm10_icache_sync_range)
mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_sync_next
+ bhi .Larm10_sync_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -108,12 +108,10 @@ ENTRY_NP(arm10_icache_sync_all)
orr ip, s_max, i_max
.Lnext_index:
mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
- sub ip, ip, i_inc
- tst ip, i_max /* Index 0 is last one */
- bne .Lnext_index /* Next index */
- mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index /* Next index */
subs s_max, s_max, s_inc
- bpl .Lnext_set /* Next set */
+ bhs .Lnext_set /* Next set */
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -133,7 +131,7 @@ ENTRY(arm10_dcache_wb_range)
mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_wb_next
+ bhi .Larm10_wb_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -150,7 +148,7 @@ ENTRY(arm10_dcache_wbinv_range)
mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_wbinv_next
+ bhi .Larm10_wbinv_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -171,7 +169,7 @@ ENTRY(arm10_dcache_inv_range)
mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_inv_next
+ bhi .Larm10_inv_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -189,7 +187,7 @@ ENTRY(arm10_idcache_wbinv_range)
mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_id_wbinv_next
+ bhi .Larm10_id_wbinv_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -211,12 +209,10 @@ ENTRY(arm10_dcache_wbinv_all)
orr ip, s_max, i_max
.Lnext_index_inv:
mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
- sub ip, ip, i_inc
- tst ip, i_max /* Index 0 is last one */
- bne .Lnext_index_inv /* Next index */
- mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index_inv /* Next index */
subs s_max, s_max, s_inc
- bpl .Lnext_set_inv /* Next set */
+ bhs .Lnext_set_inv /* Next set */
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
diff --git a/sys/arm/arm/cpufunc_asm_arm9.S b/sys/arm/arm/cpufunc_asm_arm9.S
index 291d3f7..ae9fe00 100644
--- a/sys/arm/arm/cpufunc_asm_arm9.S
+++ b/sys/arm/arm/cpufunc_asm_arm9.S
@@ -81,7 +81,7 @@ ENTRY_NP(arm9_icache_sync_range)
mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_sync_next
+ bhi .Larm9_sync_next
mov pc, lr
ENTRY_NP(arm9_icache_sync_all)
@@ -101,12 +101,10 @@ ENTRY_NP(arm9_icache_sync_all)
orr ip, s_max, i_max
.Lnext_index:
mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
- sub ip, ip, i_inc
- tst ip, i_max /* Index 0 is last one */
- bne .Lnext_index /* Next index */
- mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index /* Next index */
subs s_max, s_max, s_inc
- bpl .Lnext_set /* Next set */
+ bhs .Lnext_set /* Next set */
mov pc, lr
.Larm9_line_size:
@@ -125,7 +123,7 @@ ENTRY(arm9_dcache_wb_range)
mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_wb_next
+ bhi .Larm9_wb_next
mov pc, lr
ENTRY(arm9_dcache_wbinv_range)
@@ -141,7 +139,7 @@ ENTRY(arm9_dcache_wbinv_range)
mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_wbinv_next
+ bhi .Larm9_wbinv_next
mov pc, lr
/*
@@ -161,7 +159,7 @@ ENTRY(arm9_dcache_inv_range)
mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_inv_next
+ bhi .Larm9_inv_next
mov pc, lr
ENTRY(arm9_idcache_wbinv_range)
@@ -178,7 +176,7 @@ ENTRY(arm9_idcache_wbinv_range)
mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_id_wbinv_next
+ bhi .Larm9_id_wbinv_next
mov pc, lr
ENTRY_NP(arm9_idcache_wbinv_all)
@@ -199,12 +197,10 @@ ENTRY(arm9_dcache_wbinv_all)
orr ip, s_max, i_max
.Lnext_index_inv:
mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
- sub ip, ip, i_inc
- tst ip, i_max /* Index 0 is last one */
- bne .Lnext_index_inv /* Next index */
- mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index_inv /* Next index */
subs s_max, s_max, s_inc
- bpl .Lnext_set_inv /* Next set */
+ bhs .Lnext_set_inv /* Next set */
mov pc, lr
.Larm9_cache_data:
diff --git a/sys/arm/arm/db_trace.c b/sys/arm/arm/db_trace.c
index d6e1c3a..89ec507 100644
--- a/sys/arm/arm/db_trace.c
+++ b/sys/arm/arm/db_trace.c
@@ -50,6 +50,395 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_sym.h>
#include <ddb/db_output.h>
+#ifdef __ARM_EABI__
+/*
+ * Definitions for the instruction interpreter.
+ *
+ * The ARM EABI specifies how to perform the frame unwinding in the
+ * Exception Handling ABI for the ARM Architecture document. To perform
+ * the unwind we need to know the initial frame pointer, stack pointer,
+ * link register and program counter. We then find the entry within the
+ * index table that points to the function the program counter is within.
+ * This gives us either a list of three instructions to process, a 31-bit
+ * relative offset to a table of instructions, or a value telling us
+ * we can't unwind any further.
+ *
+ * When we have the instructions to process we need to decode them
+ * following table 4 in section 9.3. This describes a collection of bit
+ * patterns to encode that steps to take to update the stack pointer and
+ * link register to the correct values at the start of the function.
+ */
+
+/* A special case when we are unable to unwind past this function */
+#define EXIDX_CANTUNWIND 1
+
+/* The register names */
+#define FP 11
+#define SP 13
+#define LR 14
+#define PC 15
+
+/*
+ * These are set in the linker script. Their addresses will be
+ * either the start or end of the exception table or index.
+ */
+extern int extab_start, extab_end, exidx_start, exidx_end;
+
+/*
+ * Entry types.
+ * These are the only entry types that have been seen in the kernel.
+ */
+#define ENTRY_MASK 0xff000000
+#define ENTRY_ARM_SU16 0x80000000
+#define ENTRY_ARM_LU16 0x81000000
+
+/* Instruction masks. */
+#define INSN_VSP_MASK 0xc0
+#define INSN_VSP_SIZE_MASK 0x3f
+#define INSN_STD_MASK 0xf0
+#define INSN_STD_DATA_MASK 0x0f
+#define INSN_POP_TYPE_MASK 0x08
+#define INSN_POP_COUNT_MASK 0x07
+#define INSN_VSP_LARGE_INC_MASK 0xff
+
+/* Instruction definitions */
+#define INSN_VSP_INC 0x00
+#define INSN_VSP_DEC 0x40
+#define INSN_POP_MASKED 0x80
+#define INSN_VSP_REG 0x90
+#define INSN_POP_COUNT 0xa0
+#define INSN_FINISH 0xb0
+#define INSN_VSP_LARGE_INC 0xb2
+
+/* An item in the exception index table */
+struct unwind_idx {
+ uint32_t offset;
+ uint32_t insn;
+};
+
+/* The state of the unwind process */
+struct unwind_state {
+ uint32_t registers[16];
+ uint32_t start_pc;
+ uint32_t *insn;
+ u_int entries;
+ u_int byte;
+ uint16_t update_mask;
+};
+
+/* We need to provide these but never use them */
+void __aeabi_unwind_cpp_pr0(void);
+void __aeabi_unwind_cpp_pr1(void);
+void __aeabi_unwind_cpp_pr2(void);
+
+void
+__aeabi_unwind_cpp_pr0(void)
+{
+ panic("__aeabi_unwind_cpp_pr0");
+}
+
+void
+__aeabi_unwind_cpp_pr1(void)
+{
+ panic("__aeabi_unwind_cpp_pr1");
+}
+
+void
+__aeabi_unwind_cpp_pr2(void)
+{
+ panic("__aeabi_unwind_cpp_pr2");
+}
+
+/* Expand a 31-bit signed value to a 32-bit signed value */
+static __inline int32_t
+db_expand_prel31(uint32_t prel31)
+{
+
+ return ((int32_t)(prel31 & 0x7fffffffu) << 1) / 2;
+}
+
+/*
+ * Perform a binary search of the index table to find the function
+ * with the largest address that doesn't exceed addr.
+ */
+static struct unwind_idx *
+db_find_index(uint32_t addr)
+{
+ unsigned int min, mid, max;
+ struct unwind_idx *start;
+ struct unwind_idx *item;
+ int32_t prel31_addr;
+ uint32_t func_addr;
+
+ start = (struct unwind_idx *)&exidx_start;
+
+ min = 0;
+ max = (&exidx_end - &exidx_start) / 2;
+
+ while (min != max) {
+ mid = min + (max - min + 1) / 2;
+
+ item = &start[mid];
+
+ prel31_addr = db_expand_prel31(item->offset);
+ func_addr = (uint32_t)&item->offset + prel31_addr;
+
+ if (func_addr <= addr) {
+ min = mid;
+ } else {
+ max = mid - 1;
+ }
+ }
+
+ return &start[min];
+}
+
+/* Reads the next byte from the instruction list */
+static uint8_t
+db_unwind_exec_read_byte(struct unwind_state *state)
+{
+ uint8_t insn;
+
+ /* Read the unwind instruction */
+ insn = (*state->insn) >> (state->byte * 8);
+
+ /* Update the location of the next instruction */
+ if (state->byte == 0) {
+ state->byte = 3;
+ state->insn++;
+ state->entries--;
+ } else
+ state->byte--;
+
+ return insn;
+}
+
+/* Executes the next instruction on the list */
+static int
+db_unwind_exec_insn(struct unwind_state *state)
+{
+ unsigned int insn;
+ uint32_t *vsp = (uint32_t *)state->registers[SP];
+ int update_vsp = 0;
+
+ /* This should never happen */
+ if (state->entries == 0)
+ return 1;
+
+ /* Read the next instruction */
+ insn = db_unwind_exec_read_byte(state);
+
+ if ((insn & INSN_VSP_MASK) == INSN_VSP_INC) {
+ state->registers[SP] += ((insn & INSN_VSP_SIZE_MASK) << 2) + 4;
+
+ } else if ((insn & INSN_VSP_MASK) == INSN_VSP_DEC) {
+ state->registers[SP] -= ((insn & INSN_VSP_SIZE_MASK) << 2) + 4;
+
+ } else if ((insn & INSN_STD_MASK) == INSN_POP_MASKED) {
+ unsigned int mask, reg;
+
+ /* Load the mask */
+ mask = db_unwind_exec_read_byte(state);
+ mask |= (insn & INSN_STD_DATA_MASK) << 8;
+
+ /* We have a refuse to unwind instruction */
+ if (mask == 0)
+ return 1;
+
+ /* Update SP */
+ update_vsp = 1;
+
+ /* Load the registers */
+ for (reg = 4; mask && reg < 16; mask >>= 1, reg++) {
+ if (mask & 1) {
+ state->registers[reg] = *vsp++;
+ state->update_mask |= 1 << reg;
+
+ /* If we have updated SP kep its value */
+ if (reg == SP)
+ update_vsp = 0;
+ }
+ }
+
+ } else if ((insn & INSN_STD_MASK) == INSN_VSP_REG &&
+ ((insn & INSN_STD_DATA_MASK) != 13) &&
+ ((insn & INSN_STD_DATA_MASK) != 15)) {
+ /* sp = register */
+ state->registers[SP] =
+ state->registers[insn & INSN_STD_DATA_MASK];
+
+ } else if ((insn & INSN_STD_MASK) == INSN_POP_COUNT) {
+ unsigned int count, reg;
+
+ /* Read how many registers to load */
+ count = insn & INSN_POP_COUNT_MASK;
+
+ /* Update sp */
+ update_vsp = 1;
+
+ /* Pop the registers */
+ for (reg = 4; reg <= 4 + count; reg++) {
+ state->registers[reg] = *vsp++;
+ state->update_mask |= 1 << reg;
+ }
+
+ /* Check if we are in the pop r14 version */
+ if ((insn & INSN_POP_TYPE_MASK) != 0) {
+ state->registers[14] = *vsp++;
+ }
+
+ } else if (insn == INSN_FINISH) {
+ /* Stop processing */
+ state->entries = 0;
+
+ } else if ((insn & INSN_VSP_LARGE_INC_MASK) == INSN_VSP_LARGE_INC) {
+ unsigned int uleb128;
+
+ /* Read the increment value */
+ uleb128 = db_unwind_exec_read_byte(state);
+
+ state->registers[SP] += 0x204 + (uleb128 << 2);
+
+ } else {
+ /* We hit a new instruction that needs to be implemented */
+ db_printf("Unhandled instruction %.2x\n", insn);
+ return 1;
+ }
+
+ if (update_vsp) {
+ state->registers[SP] = (uint32_t)vsp;
+ }
+
+#if 0
+ db_printf("fp = %08x, sp = %08x, lr = %08x, pc = %08x\n",
+ state->registers[FP], state->registers[SP], state->registers[LR],
+ state->registers[PC]);
+#endif
+
+ return 0;
+}
+
+/* Performs the unwind of a function */
+static int
+db_unwind_tab(struct unwind_state *state)
+{
+ uint32_t entry;
+
+ /* Set PC to a known value */
+ state->registers[PC] = 0;
+
+ /* Read the personality */
+ entry = *state->insn & ENTRY_MASK;
+
+ if (entry == ENTRY_ARM_SU16) {
+ state->byte = 2;
+ state->entries = 1;
+ } else if (entry == ENTRY_ARM_LU16) {
+ state->byte = 1;
+ state->entries = ((*state->insn >> 16) & 0xFF) + 1;
+ } else {
+ db_printf("Unknown entry: %x\n", entry);
+ return 1;
+ }
+
+ while (state->entries > 0) {
+ if (db_unwind_exec_insn(state) != 0)
+ return 1;
+ }
+
+ /*
+ * The program counter was not updated, load it from the link register.
+ */
+ if (state->registers[PC] == 0)
+ state->registers[PC] = state->registers[LR];
+
+ return 0;
+}
+
+static void
+db_stack_trace_cmd(struct unwind_state *state)
+{
+ struct unwind_idx *index;
+ const char *name;
+ db_expr_t value;
+ db_expr_t offset;
+ c_db_sym_t sym;
+ u_int reg, i;
+ char *sep;
+
+ while (1) {
+ /* Reset the mask of updated registers */
+ state->update_mask = 0;
+
+ /* The pc value is correct and will be overwritten, save it */
+ state->start_pc = state->registers[PC];
+
+ /* Find the item to run */
+ index = db_find_index(state->start_pc);
+
+ if (index->insn == EXIDX_CANTUNWIND) {
+ printf("Unable to unwind\n");
+ break;
+ } else if (index->insn & (1 << 31)) {
+ /* The data is within the instruction */
+ state->insn = &index->insn;
+ } else {
+ /* We have a prel31 offset to the unwind table */
+ uint32_t prel31_tbl = db_expand_prel31(index->insn);
+
+ state->insn = (uint32_t *)((uintptr_t)&index->insn +
+ prel31_tbl);
+ }
+
+ /* Run the unwind function */
+ if (db_unwind_tab(state) != 0)
+ break;
+
+ /* This is not a kernel address, stop processing */
+ if (state->registers[PC] < VM_MIN_KERNEL_ADDRESS)
+ break;
+
+ /* Print the frame details */
+ sym = db_search_symbol(state->start_pc, DB_STGY_ANY, &offset);
+ if (sym == C_DB_SYM_NULL) {
+ value = 0;
+ name = "(null)";
+ } else
+ db_symbol_values(sym, &name, &value);
+ db_printf("%s() at ", name);
+ db_printsym(state->start_pc, DB_STGY_PROC);
+ db_printf("\n");
+ db_printf("\t pc = 0x%08x lr = 0x%08x (", state->start_pc,
+ state->registers[LR]);
+ db_printsym(state->registers[LR], DB_STGY_PROC);
+ db_printf(")\n");
+ db_printf("\t sp = 0x%08x fp = 0x%08x",
+ state->registers[SP], state->registers[FP]);
+
+ /* Don't print the registers we have already printed */
+ state->update_mask &= ~((1 << SP) | (1 << FP) | (1 << LR) |
+ (1 << PC));
+ sep = "\n\t";
+ for (i = 0, reg = 0; state->update_mask != 0;
+ state->update_mask >>= 1, reg++) {
+ if ((state->update_mask & 1) != 0) {
+ db_printf("%s%sr%d = 0x%08x", sep,
+ (reg < 10) ? " " : "", reg,
+ state->registers[reg]);
+ i++;
+ if (i == 2) {
+ sep = "\n\t";
+ i = 0;
+ } else
+ sep = " ";
+
+ }
+ }
+ db_printf("\n");
+ }
+}
+#endif
+
/*
* APCS stack frames are awkward beasts, so I don't think even trying to use
* a structure to represent them is a good idea.
@@ -78,6 +467,7 @@ __FBSDID("$FreeBSD$");
* fields are actually present.
*/
+#ifndef __ARM_EABI__ /* The frame format is differend in AAPCS */
static void
db_stack_trace_cmd(db_expr_t addr, db_expr_t count, boolean_t kernel_only)
{
@@ -171,6 +561,7 @@ db_stack_trace_cmd(db_expr_t addr, db_expr_t count, boolean_t kernel_only)
}
}
}
+#endif
/* XXX stubs */
void
@@ -193,11 +584,24 @@ db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
int
db_trace_thread(struct thread *thr, int count)
{
+#ifdef __ARM_EABI__
+ struct unwind_state state;
+#endif
struct pcb *ctx;
if (thr != curthread) {
ctx = kdb_thr_ctx(thr);
+
+#ifdef __ARM_EABI__
+ state.registers[FP] = ctx->un_32.pcb32_r11;
+ state.registers[SP] = ctx->un_32.pcb32_sp;
+ state.registers[LR] = ctx->un_32.pcb32_lr;
+ state.registers[PC] = ctx->un_32.pcb32_pc;
+
+ db_stack_trace_cmd(&state);
+#else
db_stack_trace_cmd(ctx->un_32.pcb32_r11, -1, TRUE);
+#endif
} else
db_trace_self();
return (0);
@@ -206,8 +610,20 @@ db_trace_thread(struct thread *thr, int count)
void
db_trace_self(void)
{
+#ifdef __ARM_EABI__
+ struct unwind_state state;
+ register uint32_t sp __asm__ ("sp");
+
+ state.registers[FP] = (uint32_t)__builtin_frame_address(0);
+ state.registers[SP] = (uint32_t)sp;
+ state.registers[LR] = (uint32_t)__builtin_return_address(0);
+ state.registers[PC] = (uint32_t)db_trace_self;
+
+ db_stack_trace_cmd(&state);
+#else
db_addr_t addr;
addr = (db_addr_t)__builtin_frame_address(0);
db_stack_trace_cmd(addr, -1, FALSE);
+#endif
}
diff --git a/sys/arm/arm/intr.c b/sys/arm/arm/intr.c
index e79e44c..062b10a 100644
--- a/sys/arm/arm/intr.c
+++ b/sys/arm/arm/intr.c
@@ -50,17 +50,34 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/cpu.h>
+#define INTRNAME_LEN (MAXCOMLEN + 1)
+
typedef void (*mask_fn)(void *);
static struct intr_event *intr_events[NIRQ];
-static int intrcnt_tab[NIRQ];
-static int intrcnt_index = 0;
-static int last_printed = 0;
void arm_handler_execute(struct trapframe *, int);
void (*arm_post_filter)(void *) = NULL;
+/*
+ * Pre-format intrnames into an array of fixed-size strings containing spaces.
+ * This allows us to avoid the need for an intermediate table of indices into
+ * the names and counts arrays, while still meeting the requirements and
+ * assumptions of vmstat(8) and the kdb "show intrcnt" command, the two
+ * consumers of this data.
+ */
+void
+arm_intrnames_init(void)
+{
+ int i;
+
+ for (i = 0; i < NIRQ; ++i) {
+ snprintf(&intrnames[i * INTRNAME_LEN], INTRNAME_LEN, "%-*s",
+ INTRNAME_LEN - 1, "");
+ }
+}
+
void
arm_setup_irqhandler(const char *name, driver_filter_t *filt,
void (*hand)(void*), void *arg, int irq, int flags, void **cookiep)
@@ -78,14 +95,8 @@ arm_setup_irqhandler(const char *name, driver_filter_t *filt,
if (error)
return;
intr_events[irq] = event;
- last_printed +=
- snprintf(intrnames + last_printed,
- MAXCOMLEN + 1,
- "irq%d: %s", irq, name);
- last_printed++;
- intrcnt_tab[irq] = intrcnt_index;
- intrcnt_index++;
-
+ snprintf(&intrnames[irq * INTRNAME_LEN], INTRNAME_LEN,
+ "irq%d: %-*s", irq, INTRNAME_LEN - 1, name);
}
intr_event_add_handler(event, name, filt, hand, arg,
intr_priority(flags), flags, cookiep);
@@ -122,7 +133,7 @@ arm_handler_execute(struct trapframe *frame, int irqnb)
PCPU_INC(cnt.v_intr);
i = -1;
while ((i = arm_get_next_irq(i)) != -1) {
- intrcnt[intrcnt_tab[i]]++;
+ intrcnt[i]++;
event = intr_events[i];
if (intr_event_handle(event, frame) != 0) {
/* XXX: Log stray IRQs */
diff --git a/sys/arm/arm/locore.S b/sys/arm/arm/locore.S
index ed7af25..00a61e7 100644
--- a/sys/arm/arm/locore.S
+++ b/sys/arm/arm/locore.S
@@ -484,12 +484,29 @@ ENTRY_NP(abort)
ENTRY_NP(sigcode)
mov r0, sp
+
+ /*
+ * Call the sigreturn system call.
+ *
+ * We have to load r7 manually rather than using
+ * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
+ * correct. Using the alternative places esigcode at the address
+ * of the data rather than the address one past the data.
+ */
+
+ ldr r7, [pc, #12] /* Load SYS_sigreturn */
swi SYS_sigreturn
/* Well if that failed we better exit quick ! */
+ ldr r7, [pc, #8] /* Load SYS_exit */
swi SYS_exit
- b . - 8
+
+ /* Branch back to retry SYS_sigreturn */
+ b . - 16
+
+ .word SYS_sigreturn
+ .word SYS_exit
.align 0
.global _C_LABEL(esigcode)
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index a1b5a8f..5c4d92c 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -1474,6 +1474,7 @@ initarm(struct arm_boot_params *abp)
init_proc0(kernelstack.pv_va);
+ arm_intrnames_init();
arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
arm_dump_avail_init(memsize, sizeof(dump_avail) / sizeof(dump_avail[0]));
pmap_bootstrap(freemempos, pmap_bootstrap_lastaddr, &kernel_l1pt);
diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S
index e93b948..4c422e8 100644
--- a/sys/arm/arm/swtch.S
+++ b/sys/arm/arm/swtch.S
@@ -79,6 +79,7 @@
*/
#include "assym.s"
+#include "opt_sched.h"
#include <machine/asm.h>
#include <machine/asmacros.h>
@@ -428,6 +429,7 @@ ENTRY(cpu_switch)
/* Release the old thread */
str r6, [r4, #TD_LOCK]
+#if defined(SCHED_ULE) && defined(SMP)
ldr r6, .Lblocked_lock
GET_CURTHREAD_PTR(r3)
@@ -435,6 +437,7 @@ ENTRY(cpu_switch)
ldr r4, [r3, #TD_LOCK]
cmp r4, r6
beq 1b
+#endif
/* XXXSCW: Safe to re-enable FIQs here */
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index e737dc8..bdc4ccc 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -866,7 +866,11 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
register_t *ap;
int error;
+#ifdef __ARM_EABI__
+ sa->code = td->td_frame->tf_r7;
+#else
sa->code = sa->insn & 0x000fffff;
+#endif
ap = &td->td_frame->tf_r0;
if (sa->code == SYS_syscall) {
sa->code = *ap++;
@@ -905,16 +909,18 @@ syscall(struct thread *td, trapframe_t *frame)
struct syscall_args sa;
int error;
+#ifndef __ARM_EABI__
sa.insn = *(uint32_t *)(frame->tf_pc - INSN_SIZE);
switch (sa.insn & SWI_OS_MASK) {
case 0: /* XXX: we need our own one. */
- sa.nap = 4;
break;
default:
call_trapsignal(td, SIGILL, 0);
userret(td, frame);
return;
}
+#endif
+ sa.nap = 4;
error = syscallenter(td, &sa);
KASSERT(error != 0 || td->td_ar == NULL,
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index cc87bbe..22a209b 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -398,6 +398,12 @@ cpu_thread_alloc(struct thread *td)
PAGE_SIZE) - 1;
td->td_frame = (struct trapframe *)
((u_int)td->td_kstack + USPACE_SVC_STACK_TOP - sizeof(struct pcb)) - 1;
+ /*
+ * Ensure td_frame is aligned to an 8 byte boundary as it will be
+ * placed into the stack pointer which must be 8 byte aligned in
+ * the ARM EABI.
+ */
+ td->td_frame = (struct trapframe *)((u_int)td->td_frame & ~7);
#ifdef __XSCALE__
#ifndef CPU_XSCALE_CORE3
pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE);
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
index 35343c8..0f1e81c 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
@@ -136,6 +136,7 @@ struct video_adapter_softc {
int console;
intptr_t fb_addr;
+ intptr_t fb_paddr;
unsigned int fb_size;
unsigned int height;
@@ -222,6 +223,7 @@ bcm_fb_init(void *arg)
fb_config->screen_size);
va_sc->fb_addr = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size);
+ va_sc->fb_paddr = fb_config->base;
va_sc->fb_size = fb_config->screen_size;
va_sc->depth = fb_config->bpp;
va_sc->stride = fb_config->pitch;
@@ -795,7 +797,7 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
* framebuffer, since it shouldn't be touched
*/
if (offset < sc->stride*sc->height) {
- *paddr = sc->fb_addr + offset;
+ *paddr = sc->fb_paddr + offset;
return (0);
}
@@ -805,6 +807,27 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
static int
bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
{
+ struct video_adapter_softc *sc;
+ struct fbtype *fb;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ switch (cmd) {
+ case FBIOGTYPE:
+ fb = (struct fbtype *)data;
+ fb->fb_type = FBTYPE_PCIMISC;
+ fb->fb_height = sc->height;
+ fb->fb_width = sc->width;
+ fb->fb_depth = sc->depth;
+ if (sc->depth <= 1 || sc->depth > 8)
+ fb->fb_cmsize = 0;
+ else
+ fb->fb_cmsize = 1 << sc->depth;
+ fb->fb_size = sc->fb_size;
+ break;
+ default:
+ return (fb_commonioctl(adp, cmd, data));
+ }
return (0);
}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
index 7308c0f..7eff61c 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
@@ -82,11 +82,6 @@ initarm_late_init(void)
pcell_t cells[2];
int len;
- /*
- * It seems there is no way to let syscons framework know
- * that framebuffer resolution has changed. So just try
- * to fetch data from FDT and go with defaults if failed
- */
system = OF_finddevice("/system");
if (system != 0) {
len = OF_getprop(system, "linux,serial", &cells, sizeof(cells));
diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE
index 1481d92..6336c0c 100644
--- a/sys/arm/conf/BEAGLEBONE
+++ b/sys/arm/conf/BEAGLEBONE
@@ -37,6 +37,7 @@ options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
options PROCFS #Process filesystem (requires PSEUDOFS)
options PSEUDOFS #Pseudo-filesystem framework
+options TMPFS #Efficient memory filesystem
options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI
options KTRACE #ktrace(1) support
@@ -61,9 +62,9 @@ options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
#options DIAGNOSTIC
# NFS support
-#options NFSCL
+options NFSCL
#options NFSD
-#options NFSLOCKD
+options NFSLOCKD
# Uncomment this for NFS root
#options NFS_ROOT #NFS usable as /, requires NFSCL
@@ -124,4 +125,3 @@ device axe # ASIX Electronics USB Ethernet
options FDT
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=beaglebone.dts
-
diff --git a/sys/arm/conf/CUBIEBOARD b/sys/arm/conf/CUBIEBOARD
new file mode 100644
index 0000000..82f484b
--- /dev/null
+++ b/sys/arm/conf/CUBIEBOARD
@@ -0,0 +1,134 @@
+# CUBIEBOARD -- Custom configuration for the CUBIEBOARD ARM development
+# platform, check out http://www.cubieboard.org
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+ident CUBIEBOARD
+
+include "../allwinner/std.a10"
+
+makeoptions MODULES_OVERRIDE=""
+makeoptions WITHOUT_MODULES="ahc"
+
+options HZ=100
+options SCHED_4BSD #4BSD scheduler
+options INET #InterNETworking
+options INET6 #IPv6 communications protocols
+options FFS #Berkeley Fast Filesystem
+options SOFTUPDATES #Enable FFS soft updates support
+options UFS_ACL #Support for access control lists
+options UFS_DIRHASH #Improve performance on big directories
+options MSDOSFS #MSDOS Filesystem
+options CD9660 #ISO 9660 Filesystem
+options PROCFS #Process filesystem (requires PSEUDOFS)
+options PSEUDOFS #Pseudo-filesystem framework
+options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI
+options KTRACE #ktrace(1) support
+options SYSVSHM #SYSV-style shared memory
+options SYSVMSG #SYSV-style message queues
+options SYSVSEM #SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options PREEMPTION
+options FREEBSD_BOOT_LOADER
+
+# Debugging
+makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT #Enable verbose sysinit messages
+options KDB
+options DDB #Enable the kernel debugger
+options INVARIANTS #Enable calls of extra sanity checking
+options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
+options WITNESS #Enable checks to detect deadlocks and cycles
+options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS support
+#options NFSCL
+#options NFSSERVER #Network Filesystem Server
+#options NFSCLIENT #Network Filesystem Client
+
+# Uncomment this for NFS root
+#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=cpsw0
+
+# MMC/SD/SDIO card slot support
+#device mmc # mmc/sd bus
+#device mmcsd # mmc/sd flash cards
+
+# Boot device is 2nd slice on MMC/SD card
+options ROOTDEVNAME=\"ufs:/dev/da0s2\"
+
+# ATA controllers
+#device ahci # AHCI-compatible SATA controllers
+#device ata # Legacy ATA/SATA controllers
+#options ATA_CAM # Handle legacy controllers with CAM
+#options ATA_STATIC_ID # Static device numbering
+
+# Console and misc
+#device uart
+#device uart_ns8250
+device pty
+device snp
+device md
+device random # Entropy device
+
+# I2C support
+#device iicbus
+#device iic
+
+# GPIO
+#device gpio
+
+device scbus # SCSI bus (required for SCSI)
+device da # Direct Access (disks)
+device pass
+
+# USB support
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+#device uhci
+#device ohci
+device ehci
+
+device umass
+
+# Ethernet
+device loop
+device ether
+device mii
+device smscphy
+#device cpsw
+device bpf
+
+# USB ethernet support, requires miibus
+device miibus
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=cubieboard.dts
+
diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR
index 3dd83fc..25c0121 100644
--- a/sys/arm/conf/DOCKSTAR
+++ b/sys/arm/conf/DOCKSTAR
@@ -5,7 +5,7 @@
#
ident DOCKSTAR
-include "../mv/kirkwood/std.sheevaplug"
+include "../mv/kirkwood/std.db88f6xxx"
options SOC_MV_KIRKWOOD
makeoptions MODULES_OVERRIDE=""
diff --git a/sys/arm/conf/DREAMPLUG-1001 b/sys/arm/conf/DREAMPLUG-1001
new file mode 100644
index 0000000..442cde0
--- /dev/null
+++ b/sys/arm/conf/DREAMPLUG-1001
@@ -0,0 +1,183 @@
+# Kernel config for GlobalScale Technologies DreamPlug version 1001.
+#
+# This is for units that are version 10, revision 01, with NOR SPI flash.
+# These units are identified with the number "1001" on the S/N label.
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+#
+
+ident DREAMPLUG-1001
+
+include "../mv/kirkwood/std.db88f6xxx"
+
+makeoptions FDT_DTS_FILE=dreamplug-1001.dts
+
+makeoptions MODULES_OVERRIDE=""
+
+options SOC_MV_KIRKWOOD
+
+options SCHED_4BSD #4BSD scheduler
+options INET #InterNETworking
+options INET6 #IPv6 communications protocols
+options SOFTUPDATES
+options CD9660 #ISO 9660 filesystem
+options FFS #Berkeley Fast Filesystem
+options MSDOSFS #MS DOS File System (FAT, FAT32)
+options NULLFS #NULL filesystem
+options TMPFS #Efficient memory filesystem
+options SYSVSHM #SYSV-style shared memory
+options SYSVMSG #SYSV-style message queues
+options SYSVSEM #SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options GEOM_ELI # Disk encryption.
+options GEOM_LABEL # Providers labelization.
+options GEOM_PART_GPT # GPT partitioning
+
+# Flattened Device Tree
+device fdt
+options FDT
+options FDT_DTB_STATIC
+
+# Misc pseudo devices
+device bpf #Required for DHCP
+device faith #IPv6-to-IPv4 relaying (translation)
+device firmware #firmware(9) required for USB wlan
+device gif #IPv6 and IPv4 tunneling
+device loop #Network loopback
+device md #Memory/malloc disk
+device pty #BSD-style compatibility pseudo ttys
+device random #Entropy device
+device tun #Packet tunnel.
+device ether #Required for all ethernet devices
+device vlan #802.1Q VLAN support
+device wlan #802.11 WLAN support
+
+# cam support for umass and ahci
+device scbus
+device pass
+device da
+device cd
+
+# Serial ports
+device uart
+
+# Networking
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+
+# USB
+options USB_HOST_ALIGN=32 # Align DMA to cacheline
+#options USB_DEBUG # Compile in USB debug support
+device usb # Basic usb support
+device ehci # USB host controller
+device umass # Mass storage
+device uhid # Human-interface devices
+device rum # Ralink Technology RT2501USB wireless NICs
+device uath # Atheros AR5523 wireless NICs
+device ural # Ralink Technology RT2500USB wireless NICs
+device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device urtw # Realtek RTL8187B/L USB
+device upgt # Conexant/Intersil PrismGT SoftMAC USB
+device u3g # USB-based 3G modems (Option, Huawei, Sierra)
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+# SATA
+device mvs
+device ahci
+
+# Sound
+device sound
+device snd_uaudio
+
+#crypto
+device cesa # Marvell security engine
+device crypto
+device cryptodev
+
+# IPSec
+device enc
+options IPSEC
+options IPSEC_NAT_T
+options TCP_SIGNATURE #include support for RFC 2385
+
+# IPFW
+options IPFIREWALL
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+options IPFIREWALL_VERBOSE
+options IPFIREWALL_VERBOSE_LIMIT=100
+options IPFIREWALL_NAT
+options LIBALIAS
+options DUMMYNET
+options IPDIVERT
+
+#PF
+device pf
+device pflog
+device pfsync
+
+# ALTQ, required for PF
+options ALTQ # Basic ALTQ support
+options ALTQ_CBQ # Class Based Queueing
+options ALTQ_RED # Random Early Detection
+options ALTQ_RIO # RED In/Out
+options ALTQ_HFSC # Hierarchical Packet Scheduler
+options ALTQ_CDNR # Traffic conditioner
+options ALTQ_PRIQ # Priority Queueing
+options ALTQ_NOPCC # Required if the TSC is unusable
+#options ALTQ_DEBUG
+
+# Debugging
+makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+options KDB
+options DIAGNOSTIC
+options INVARIANTS #Enable calls of extra sanity checking
+options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS #Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+
+# Enable these options for nfs root configured via BOOTP.
+options NFSCL #Network Filesystem Client
+options NFSLOCKD #Network Lock Manager
+#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=mge0
+
+# If not using BOOTP, use something like one of these...
+#options ROOTDEVNAME=\"ufs:/dev/da1a\"
+options ROOTDEVNAME=\"ufs:/dev/da1s1a\"
+#options ROOTDEVNAME=\"ufs:/dev/da1p10\"
+#options ROOTDEVNAME=\"nfs:192.168.0.254/dreamplug\"
+
+# To use this configuration with the (rare) model 1001N (nand flash),
+# create a kernel config file that looks like this:
+#
+# include DREAMPLUG-1001
+# nomakeoptions FDT_DTS_FILE
+# makeoptions FDT_DTS_FILE=dreamplug-1001N.dts
+# device nand
+
diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES
index 1d4f897..fa36275 100644
--- a/sys/arm/conf/NOTES
+++ b/sys/arm/conf/NOTES
@@ -19,7 +19,6 @@ files "../econa/files.econa"
files "../mv/files.mv"
files "../mv/discovery/files.db78xxx"
files "../mv/kirkwood/files.kirkwood"
-files "../mv/kirkwood/files.sheevaplug"
files "../mv/orion/files.db88f5xxx"
files "../mv/orion/files.ts7800"
files "../s3c2xx0/files.s3c2xx0"
diff --git a/sys/arm/conf/SHEEVAPLUG b/sys/arm/conf/SHEEVAPLUG
index b7de8f6..c6bd901 100644
--- a/sys/arm/conf/SHEEVAPLUG
+++ b/sys/arm/conf/SHEEVAPLUG
@@ -5,7 +5,7 @@
#
ident SHEEVAPLUG
-include "../mv/kirkwood/std.sheevaplug"
+include "../mv/kirkwood/std.db88f6xxx"
options SOC_MV_KIRKWOOD
makeoptions MODULES_OVERRIDE=""
diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h
index 4862453..82b7d1b 100644
--- a/sys/arm/include/atomic.h
+++ b/sys/arm/include/atomic.h
@@ -677,6 +677,17 @@ atomic_readandclear_32(volatile u_int32_t *p)
#define atomic_store_rel_long atomic_store_long
#define atomic_load_acq_32 atomic_load_32
#define atomic_load_acq_long atomic_load_long
+#define atomic_add_acq_long atomic_add_long
+#define atomic_add_rel_long atomic_add_long
+#define atomic_subtract_acq_long atomic_subtract_long
+#define atomic_subtract_rel_long atomic_subtract_long
+#define atomic_clear_acq_long atomic_clear_long
+#define atomic_clear_rel_long atomic_clear_long
+#define atomic_set_acq_long atomic_set_long
+#define atomic_set_rel_long atomic_set_long
+#define atomic_cmpset_acq_long atomic_cmpset_long
+#define atomic_cmpset_rel_long atomic_cmpset_long
+#define atomic_load_acq_long atomic_load_long
#undef __with_interrupts_disabled
static __inline void
@@ -758,25 +769,13 @@ atomic_store_long(volatile u_long *dst, u_long src)
*dst = src;
}
-#define atomic_add_acq_long atomic_add_long
-#define atomic_add_rel_long atomic_add_long
-#define atomic_subtract_acq_long atomic_subtract_long
-#define atomic_subtract_rel_long atomic_subtract_long
-#define atomic_clear_acq_long atomic_clear_long
-#define atomic_clear_rel_long atomic_clear_long
-#define atomic_set_acq_long atomic_set_long
-#define atomic_set_rel_long atomic_set_long
-#define atomic_cmpset_acq_long atomic_cmpset_long
-#define atomic_cmpset_rel_long atomic_cmpset_long
-#define atomic_load_acq_long atomic_load_long
-
#define atomic_clear_ptr atomic_clear_32
#define atomic_set_ptr atomic_set_32
#define atomic_cmpset_ptr atomic_cmpset_32
#define atomic_cmpset_rel_ptr atomic_cmpset_rel_32
#define atomic_cmpset_acq_ptr atomic_cmpset_acq_32
#define atomic_store_ptr atomic_store_32
-#define atomic_store_rel_ptr atomic_store_ptr
+#define atomic_store_rel_ptr atomic_store_rel_32
#define atomic_add_int atomic_add_32
#define atomic_add_acq_int atomic_add_acq_32
diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h
index 45e36e9..9392969 100644
--- a/sys/arm/include/intr.h
+++ b/sys/arm/include/intr.h
@@ -70,6 +70,7 @@
int arm_get_next_irq(int);
void arm_mask_irq(uintptr_t);
void arm_unmask_irq(uintptr_t);
+void arm_intrnames_init(void);
void arm_setup_irqhandler(const char *, int (*)(void*), void (*)(void*),
void *, int, int, void **);
int arm_remove_irqhandler(int, void *);
diff --git a/sys/arm/include/proc.h b/sys/arm/include/proc.h
index c1bce00..597a5ad 100644
--- a/sys/arm/include/proc.h
+++ b/sys/arm/include/proc.h
@@ -60,7 +60,11 @@ struct mdproc {
void *md_sigtramp;
};
+#ifdef __ARM_EABI__
+#define KINFO_PROC_SIZE 816
+#else
#define KINFO_PROC_SIZE 792
+#endif
#define MAXARGS 8
struct syscall_args {
@@ -69,7 +73,9 @@ struct syscall_args {
register_t args[MAXARGS];
int narg;
u_int nap;
+#ifndef __ARM_EABI__
u_int32_t insn;
+#endif
};
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
index eac46cc..267ba6e 100644
--- a/sys/arm/include/vmparam.h
+++ b/sys/arm/include/vmparam.h
@@ -134,12 +134,15 @@
#endif
#define VM_MAX_KERNEL_ADDRESS 0xffffffff
+
/*
* Virtual size (bytes) for various kernel submaps.
*/
-
#ifndef VM_KMEM_SIZE
-#define VM_KMEM_SIZE (12*1024*1024)
+#define VM_KMEM_SIZE (12*1024*1024)
+#endif
+#ifndef VM_KMEM_SIZE_SCALE
+#define VM_KMEM_SIZE_SCALE (2)
#endif
#define MAXTSIZ (16*1024*1024)
diff --git a/sys/arm/mv/kirkwood/files.sheevaplug b/sys/arm/mv/kirkwood/files.sheevaplug
deleted file mode 100644
index f56c2ab..0000000
--- a/sys/arm/mv/kirkwood/files.sheevaplug
+++ /dev/null
@@ -1,4 +0,0 @@
-# $FreeBSD$
-
-include "arm/mv/kirkwood/files.kirkwood"
-arm/mv/kirkwood/sheevaplug.c standard
diff --git a/sys/arm/mv/kirkwood/std.sheevaplug b/sys/arm/mv/kirkwood/std.sheevaplug
deleted file mode 100644
index 44c977e..0000000
--- a/sys/arm/mv/kirkwood/std.sheevaplug
+++ /dev/null
@@ -1,5 +0,0 @@
-# $FreeBSD$
-
-include "../mv/std.mv"
-include "../mv/kirkwood/std.kirkwood"
-files "../mv/kirkwood/files.sheevaplug"
diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c
index ae74fa3..fba222d 100644
--- a/sys/arm/mv/mv_machdep.c
+++ b/sys/arm/mv/mv_machdep.c
@@ -279,6 +279,25 @@ out:
}
/*
+ * Supply a default do-nothing implementation of fdt_pci_devmap() via a weak
+ * alias. Many Marvell platforms don't support a PCI interface, but to support
+ * those that do, we end up with a reference to this function below, in
+ * platform_devmap_init(). If "device pci" appears in the kernel config, the
+ * real implementation of this function in dev/fdt/fdt_pci.c overrides the weak
+ * alias defined here.
+ */
+int mv_default_fdt_pci_devmap(phandle_t node, struct pmap_devmap *devmap,
+ vm_offset_t io_va, vm_offset_t mem_va);
+int
+mv_default_fdt_pci_devmap(phandle_t node, struct pmap_devmap *devmap,
+ vm_offset_t io_va, vm_offset_t mem_va)
+{
+
+ return (0);
+}
+__weak_reference(mv_default_fdt_pci_devmap, fdt_pci_devmap);
+
+/*
* XXX: When device entry in devmap has pd_size smaller than section size,
* system will freeze during initialization
*/
diff --git a/sys/arm/ti/am335x/am335x_scm_padconf.c b/sys/arm/ti/am335x/am335x_scm_padconf.c
index 4ed63a3..6bb89f5 100644
--- a/sys/arm/ti/am335x/am335x_scm_padconf.c
+++ b/sys/arm/ti/am335x/am335x_scm_padconf.c
@@ -86,127 +86,117 @@ const struct ti_scm_padstate ti_padstate_devmap[] = {
};
const struct ti_scm_padconf ti_padconf_devmap[] = {
- _PIN(0x800, "GPMC_AD0", 32, 7,"gpmc_ad0", "mmc1_dat0", NULL, NULL, NULL, NULL, NULL, "gpio1_0"),
- _PIN(0x804, "GPMC_AD1", 33, 7,"gpmc_ad1", "mmc1_dat1", NULL, NULL, NULL, NULL, NULL, "gpio1_1"),
- _PIN(0x808, "GPMC_AD2", 34, 7,"gpmc_ad2", "mmc1_dat2", NULL, NULL, NULL, NULL, NULL, "gpio1_2"),
- _PIN(0x80C, "GPMC_AD3", 35, 7,"gpmc_ad3", "mmc1_dat3", NULL, NULL, NULL, NULL, NULL, "gpio1_3"),
- _PIN(0x810, "GPMC_AD4", 36, 7,"gpmc_ad4", "mmc1_dat4", NULL, NULL, NULL, NULL, NULL, "gpio1_4"),
- _PIN(0x814, "GPMC_AD5", 37, 7,"gpmc_ad5", "mmc1_dat5", NULL, NULL, NULL, NULL, NULL, "gpio1_5"),
- _PIN(0x818, "GPMC_AD6", 38, 7,"gpmc_ad6", "mmc1_dat6", NULL, NULL, NULL, NULL, NULL, "gpio1_6"),
- _PIN(0x81C, "GPMC_AD7", 39, 7,"gpmc_ad7", "mmc1_dat7", NULL, NULL, NULL, NULL, NULL, "gpio1_7"),
-#if 0 /* Incomplete Entries - fill with data from table 2-7 in datasheet */
- _PIN(0x820, "gpmc_ad8", 0, 0, "gpmc_ad8", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x824, "gpmc_ad9", 0, 0, "gpmc_ad9", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x828, "gpmc_ad10", 0, 0, "gpmc_ad10", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x82C, "gpmc_ad11", 0, 0, "gpmc_ad11", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x830, "gpmc_ad12", 0, 0, "gpmc_ad12", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x834, "gpmc_ad13", 0, 0, "gpmc_ad13", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x838, "gpmc_ad14", 0, 0, "gpmc_ad14", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x83C, "gpmc_ad15", 0, 0, "gpmc_ad15", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x840, "gpmc_a0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x844, "gpmc_a1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x848, "gpmc_a2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x84C, "gpmc_a3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x850, "gpmc_a4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
- _PIN(0x854, "GPMC_A5", 53, 7, "gpmc_a5", "gmii2_txd0", "rgmii2_td0", "rmii2_txd0", "gpmc_a21", "pr1_mii1_rxd3", "eQEP1B_in", "gpio1_21"),
- _PIN(0x858, "GPMC_A6", 54, 7, "gpmc_a6", "gmii2_txclk", "rgmii2_tclk", "mmc2_dat4", "gpmc_a22", "pr1_mii1_rxd2", "eQEP1_index", "gpio1_22"),
- _PIN(0x85C, "GPMC_A7", 55, 7, "gpmc_a7", "gmii2_rxclk", "rgmii2_rclk", "mmc2_dat5", "gpmc_a23", "pr1_mii1_rxd1", "eQEP1_strobe", "gpio1_23"),
- _PIN(0x860, "GPMC_A8", 56, 7, "gpmc_a8", "gmii2_rxd3", "rgmii2_rd3", "mmc2_dat6", "gpmc_a24", "pr1_mii1_rxd0", "mcasp0_aclkx", "gpio1_24"),
-#if 0
- _PIN(0x864, "gpmc_a9", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x868, "gpmc_a10", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x86C, "gpmc_a11", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x870, "gpmc_wait0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x874, "gpmc_wpn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x878, "gpmc_be1n", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x87c, "gpmc_csn0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x880, "gpmc_csn1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x884, "gpmc_csn2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x888, "gpmc_csn3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x88c, "gpmc_clk", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x890, "gpmc_advn_ale", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x894, "gpmc_oen_ren", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x898, "gpmc_wen", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x89c, "gpmc_be0n_cle", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8a0, "lcd_data0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8a4, "lcd_data1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8a8, "lcd_data2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8ac, "lcd_data3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8b0, "lcd_data4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8b4, "lcd_data5", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8b8, "lcd_data6", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8bc, "lcd_data7", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8c0, "lcd_data8", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8c4, "lcd_data9", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8c8, "lcd_data10", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8cc, "lcd_data11", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8d0, "lcd_data12", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8d4, "lcd_data13", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8d8, "lcd_data14", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8dc, "lcd_data15", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8e0, "lcd_vsync", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8e4, "lcd_hsync", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8e8, "lcd_pclk", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8ec, "lcd_ac_bias_en", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
- _PIN(0x8f0, "MMC0_DAT3", 90, 7, "mmc0_dat3", "gpmc_a20", "uart4_ctsn", "timer5", "uart1_dcdn", "pr1_pru0_pru_r30_8", "pr1_pru0_pru_r31_8", "gpio2_26"),
- _PIN(0x8f4, "MMC0_DAT2", 91, 7, "mmc0_dat2", "gpmc_a21", "uart4_rtsn", "timer6", "uart1_dsrn", "pr1_pru0_pru_r30_9", "pr1_pru0_pru_r31_9", "gpio2_27"),
- _PIN(0x8f8, "MMC0_DAT1", 92, 7, "mmc0_dat1", "gpmc_a22", "uart5_ctsn", "uart3_rxd", "uart1_dtrn", "pr1_pru0_pru_r30_10", "pr1_pru0_pru_r31_10", "gpio2_28"),
- _PIN(0x8fc, "MMC0_DAT0", 93, 7, "mmc0_dat0", "gpmc_a23", "uart5_rtsn", "uart3_txd", "uart1_rin", "pr1_pru0_pru_r30_11", "pr1_pru0_pru_r31_11", "gpio2_29"),
- _PIN(0x900, "MMC0_CLK", 94, 7, "mmc0_clk", "gpmc_a24", "uart3_ctsn", "uart2_rxd", "dcan1_tx", "pr1_pru0_pru_r30_12", "pr1_pru0_pru_r31_12", "gpio2_30"),
- _PIN(0x904, "MMC0_CMD", 95, 7, "mmc0_cmd", "gpmc_a25", "uart3_rtsn", "uart2_txd", "dcan1_rx", "pr1_pru0_pru_r30_13", "pr1_pru0_pru_r31_13", "gpio2_31"),
- _PIN(0x908, "MII1_COL", 96, 7, "gmii1_col", "rmii2_refclk", "spi1_sclk", "uart5_rxd", "mcasp1_axr2", "mmc2_dat3", "mcasp0_axr2", "gpio3_0"),
- _PIN(0x90c, "MII1_CRS", 97, 7, "gmii1_crs", "rmii1_crs_dv", "spi1_d0", "I2C1_SDA", "mcasp1_aclkx", "uart5_ctsn", "uart2_rxd", "gpio3_1"),
- _PIN(0x910, "MII1_RX_ER", 98, 7, "gmii1_rxerr", "rmii1_rxerr", "spi1_d1", "I2C1_SCL", "mcasp1_fsx", "uart5_rtsn", "uart2_txd", "gpio3_2"),
- _PIN(0x914, "MII1_TX_EN", 99, 7, "gmii1_txen", "rmii1_txen", "rgmii1_tctl", "timer4", "mcasp1_axr0", "eQEP0_index", "mmc2_cmd", "gpio3_3"),
+ _PIN(0x800, "GPMC_AD0", 32, 7,"gpmc_ad0", "mmc1_dat0", NULL, NULL, NULL, NULL, NULL, "gpio1_0"),
+ _PIN(0x804, "GPMC_AD1", 33, 7,"gpmc_ad1", "mmc1_dat1", NULL, NULL, NULL, NULL, NULL, "gpio1_1"),
+ _PIN(0x808, "GPMC_AD2", 34, 7,"gpmc_ad2", "mmc1_dat2", NULL, NULL, NULL, NULL, NULL, "gpio1_2"),
+ _PIN(0x80C, "GPMC_AD3", 35, 7,"gpmc_ad3", "mmc1_dat3", NULL, NULL, NULL, NULL, NULL, "gpio1_3"),
+ _PIN(0x810, "GPMC_AD4", 36, 7,"gpmc_ad4", "mmc1_dat4", NULL, NULL, NULL, NULL, NULL, "gpio1_4"),
+ _PIN(0x814, "GPMC_AD5", 37, 7,"gpmc_ad5", "mmc1_dat5", NULL, NULL, NULL, NULL, NULL, "gpio1_5"),
+ _PIN(0x818, "GPMC_AD6", 38, 7,"gpmc_ad6", "mmc1_dat6", NULL, NULL, NULL, NULL, NULL, "gpio1_6"),
+ _PIN(0x81C, "GPMC_AD7", 39, 7,"gpmc_ad7", "mmc1_dat7", NULL, NULL, NULL, NULL, NULL, "gpio1_7"),
+ _PIN(0x820, "GPMC_AD8", 22, 7, "gpmc_ad8", "lcd_data23", "mmc1_dat0", "mmc2_dat4", "ehrpwm2A", NULL, NULL, "gpio0_22"),
+ _PIN(0x824, "GPMC_AD9", 23, 7, "gpmc_ad9", "lcd_data22", "mmc1_dat1", "mmc2_dat5", "ehrpwm2B", NULL, NULL, "gpio0_23"),
+ _PIN(0x828, "GPMC_AD10", 26, 7, "gpmc_ad10", "lcd_data21", "mmc1_dat2", "mmc2_dat6", "ehrpwm2_tripzone_in", NULL, NULL, "gpio0_26"),
+ _PIN(0x82C, "GPMC_AD11", 27, 7, "gpmc_ad11", "lcd_data20", "mmc1_dat3", "mmc2_dat7", "ehrpwm0_synco", NULL, NULL, "gpio0_27"),
+ _PIN(0x830, "GPMC_AD12", 44, 7, "gpmc_ad12", "lcd_data19", "mmc1_dat4", "mmc2_dat0", "eQEP2A_in", "pr1_mii0_txd2", "pr1_pru0_pru_r30_14", "gpio1_12"),
+ _PIN(0x834, "GPMC_AD13", 45, 7, "gpmc_ad13", "lcd_data18", "mmc1_dat5", "mmc2_dat1", "eQEP2B_in", "pr1_mii0_txd1", "pr1_pru0_pru_r30_15", "gpio1_13"),
+ _PIN(0x838, "GPMC_AD14", 46, 7, "gpmc_ad14", "lcd_data17", "mmc1_dat6", "mmc2_dat2", "eQEP2_index", "pr1_mii0_txd0", "pr1_pru0_pru_r31_14", "gpio1_14"),
+ _PIN(0x83C, "GPMC_AD15", 47, 7, "gpmc_ad15", "lcd_data16", "mmc1_dat7", "mmc2_dat3", "eQEP2_strobe", "pr1_ecap0_ecap_capin_apwm_o", "pr1_pru0_pru_r31_15", "gpio1_15"),
+ _PIN(0x840, "GPMC_A0", 48, 7, "gpmc_a0", "gmii2_txen", "rgmii2_tctl", "rmii2_txen", "gpmc_a16", "pr1_mii_mt1_clk", "ehrpwm1_tripzone_input", "gpio1_16"),
+ _PIN(0x844, "GPMC_A1", 49, 7, "gpmc_a1", "gmii2_rxdv", "rgmii2_rctl", "mmc2_dat0", "gpmc_a17", "pr1_mii1_txd3", "ehrpwm0_synco", "gpio1_17"),
+ _PIN(0x848, "GPMC_A2", 50, 7, "gpmc_a2", "gmii2_txd3", "rgmii2_td3", "mmc2_dat1", "gpmc_a18", "pr1_mii1_txd2", "ehrpwm1A", "gpio1_18"),
+ _PIN(0x84C, "GPMC_A3", 51, 7, "gpmc_a3", "gmii2_txd2", "rgmii2_td2", "mmc2_dat2", "gpmc_a19", "pr1_mii1_txd1", "ehrpwm1B", "gpio1_19"),
+ _PIN(0x850, "GPMC_A4", 52, 7, "gpmc_a4", "gmii2_txd1", "rgmii2_td1", "rmii2_tdx1", "gpmc_a20", "pr1_mii1_txd0", "eQEP1A_in", "gpio1_20"),
+ _PIN(0x854, "GPMC_A5", 53, 7, "gpmc_a5", "gmii2_txd0", "rgmii2_td0", "rmii2_txd0", "gpmc_a21", "pr1_mii1_rxd3", "eQEP1B_in", "gpio1_21"),
+ _PIN(0x858, "GPMC_A6", 54, 7, "gpmc_a6", "gmii2_txclk", "rgmii2_tclk", "mmc2_dat4", "gpmc_a22", "pr1_mii1_rxd2", "eQEP1_index", "gpio1_22"),
+ _PIN(0x85C, "GPMC_A7", 55, 7, "gpmc_a7", "gmii2_rxclk", "rgmii2_rclk", "mmc2_dat5", "gpmc_a23", "pr1_mii1_rxd1", "eQEP1_strobe", "gpio1_23"),
+ _PIN(0x860, "GPMC_A8", 56, 7, "gpmc_a8", "gmii2_rxd3", "rgmii2_rd3", "mmc2_dat6", "gpmc_a24", "pr1_mii1_rxd0", "mcasp0_aclkx", "gpio1_24"),
+ _PIN(0x864, "GPMC_A9", 57, 7, "gmpc_a9", "gmii2_rxd2", "rgmii2_rd2", "mmc2_dat7 / rmii2_crs_dv", "gpmc_a25", "pr1_mii_mr1_clk", "mcasp0_fsx", "gpio1_25"),
+ _PIN(0x868, "GPMC_A10", 58, 7, "gmpc_a10", "gmii2_rxd1", "rgmii2_rd1", "rmii2_rxd1", "gpmc_a26", "pr1_mii1_rxdv", "mcasp0_arx0", "gpio1_26"),
+ _PIN(0x86C, "GPMC_A11", 59, 7, "gmpc_a11", "gmii2_rxd0", "rgmii2_rd0", "rmii2_rxd0", "gpmc_a27", "pr1_mii1_rxer", "mcasp0_axr1", "gpio1_27"),
+ _PIN(0x870, "GPMC_WAIT0", 30, 7, "gpmc_wait0", "gmii2_crs", "gpmc_csn4", "rmii2_crs_dv", "mmc1_sdcd", "pr1_mii1_col", "uart4_rxd", "gpio0_30"),
+ _PIN(0x874, "GPMC_WPn", 31, 7, "gpmc_wpn", "gmii2_rxerr", "gpmc_csn5", "rmii2_rxerr", "mmc2_sdcd", "pr1_mii1_txen", "uart4_txd", "gpio0_31"),
+ _PIN(0x878, "GPMC_BEn1", 60, 7, "gpmc_be1n", "gmii2_col", "gmpc_csn6","mmc2_dat3", "gpmc_dir", "pr1_mii1_rxlink", "mcasp0_aclkr", "gpio1_28"),
+ _PIN(0x87c, "GPMC_CSn0", 61, 7, "gpmc_csn0", NULL, NULL, NULL, NULL, NULL, NULL, "gpio1_29"),
+ _PIN(0x880, "GPMC_CSn1", 62, 7, "gpmc_csn1", "gpmc_clk", "mmc1_clk", "pr1_edio_data_in6", "pr1_edio_data_out6", "pr1_pru1_pru_r30_12", "pr1_pru1_pru_r31_12", "gpio1_30"),
+ _PIN(0x884, "GPMC_CSn2", 63, 7, "gpmc_csn2", "gpmc_be1n", "mmc1_cmd", "pr1_edio_data_in7", "pr1_edio_data_out7", "pr1_pru1_pru_r30_13", "pr1_pru1_pru_r31_13", "gpio1_31"),
+ _PIN(0x888, "GPMC_CSn3", 64, 7, "gpmc_csn3", "gpmc_a3", "rmii2_crs_dv", "mmc2_cmd", "pr1_mii0_crs", "pr1_mdio_data", "EMU4", "gpio2_0"),
+ _PIN(0x88c, "GPMC_CLK", 65, 7, "gpmc_clk", "lcd_memory_clk", "gpmc_wait1", "mmc2_clk", "pr1_mii1_crs", "pr1_mdio_mdclk", "mcasp0_fsr", "gpio2_1"),
+ _PIN(0x890, "GPMC_ADVn_ALE", 66, 7, "gpmc_advn_ale", NULL, "timer4", NULL, NULL, NULL, NULL, "gpio2_2"),
+ _PIN(0x894, "GPMC_OEn_REn", 67, 7, "gpmc_oen_ren", NULL, "timer7", NULL, NULL, NULL, NULL, "gpio2_3"),
+ _PIN(0x898, "GPMC_WEn", 68, 7, "gpmc_wen", NULL, "timer6", NULL, NULL, NULL, NULL, "gpio2_4"),
+ _PIN(0x89c, "GPMC_BEn0_CLE", 67, 7, "gpmc_ben0_cle", NULL, "timer5", NULL, NULL, NULL, NULL, "gpio2_5"),
+ _PIN(0x8a0, "LCD_DATA0", 68, 7, "lcd_data0", "gpmc_a0", "pr1_mii_mt0_clk", "ehrpwm2A", NULL, "pr1_pru1_pru_r30_0", "pr1_pru1_pru_r31_0", "gpio2_6"),
+ _PIN(0x8a4, "LCD_DATA1", 69, 7, "lcd_data1", "gpmc_a1", "pr1_mii0_txen", "ehrpwm2B", NULL, "pr1_pru1_pru_r30_1", "pr1_pru1_pru_r31_1", "gpio2_7"),
+ _PIN(0x8a8, "LCD_DATA2", 70, 7, "lcd_data2", "gpmc_a2", "pr1_mii0_txd3", "ehrpwm2_tripzone_input", NULL, "pr1_pru1_pru_r30_2", "pr1_pru1_pru_r31_2", "gpio2_8"),
+ _PIN(0x8ac, "LCD_DATA3", 71, 7, "lcd_data3", "gpmc_a3", "pr1_mii0_txd2", "ehrpwm0_synco", NULL, "pr1_pru1_pru_r30_3", "pr1_pru1_pru_r31_3", "gpio2_9"),
+ _PIN(0x8b0, "LCD_DATA4", 72, 7, "lcd_data4", "gpmc_a4", "pr1_mii0_txd1", "eQEP2A_in", NULL, "pr1_pru1_pru_r30_4", "pr1_pru1_pru_r31_4", "gpio2_10"),
+ _PIN(0x8b4, "LCD_DATA5", 73, 7, "lcd_data5", "gpmc_a5", "pr1_mii0_txd0", "eQEP2B_in", NULL, "pr1_pru1_pru_r30_5", "pr1_pru1_pru_r31_5", "gpio2_11"),
+ _PIN(0x8b8, "LCD_DATA6", 74, 7, "lcd_data6", "gpmc_a6", "pr1_edio_data_in6", "eQEP2_index", "pr1_edio_data_out6", "pr1_pru1_pru_r30_6", "pr1_pru1_pru_r31_6", "gpio2_12"),
+ _PIN(0x8bc, "LCD_DATA7", 75, 7, "lcd_data7", "gpmc_a7", "pr1_edio_data_in7", "eQEP2_strobe", "pr1_edio_data_out7", "pr1_pru1_pru_r30_7", "pr1_pru1_pru_r31_7", "gpio2_13"),
+ _PIN(0x8c0, "LCD_DATA8", 76, 7, "lcd_data8", "gpmc_a12", "ehrpwm1_tripzone_input", "mcasp0_aclkx", "uart5_txd", "pr1_mii0_rxd3", "uart2_ctsn", "gpio2_14"),
+ _PIN(0x8c4, "LCD_DATA9", 76, 7, "lcd_data9", "gpmc_a13", "ehrpwm0_synco", "mcasp0_fsx", "uart5_rxd", "pr1_mii0_rxd2", "uart2_rtsn", "gpio2_15"),
+ _PIN(0x8c8, "LCD_DATA10", 77, 7, "lcd_data10", "gpmc_a14", "ehrpwm1A", "mcasp0_axr0", NULL, "pr1_mii0_rxd1", "uart3_ctsn", "gpio2_16"),
+ _PIN(0x8cc, "LCD_DATA11", 78, 7, "lcd_data11", "gpmc_a15", "ehrpwm1B", "mcasp0_ahclkr", "mcasp0_axr2", "pr1_mii0_rxd0", "uart3_rtsn", "gpio2_17"),
+ _PIN(0x8d0, "LCD_DATA12", 8, 7, "lcd_data12", "gpmc_a16", "eQEP1A_in", "mcasp0_aclkr", "mcasp0_axr2", "pr1_mii0_rxlink", "uart4_ctsn", "gpio0_8"),
+ _PIN(0x8d4, "LCD_DATA13", 9, 7, "lcd_data13", "gpmc_a17", "eQEP1B_in", "mcasp0_fsr", "mcasp0_axr3", "pr1_mii0_rxer", "uart4_rtsn", "gpio0_9"),
+ _PIN(0x8d8, "LCD_DATA14", 10, 7, "lcd_data14", "gpmc_a18", "eQEP1_index", "mcasp0_axr1", "uart5_rxd", "pr1_mii_mr0_clk", "uart5_ctsn", "gpio0_10"),
+ _PIN(0x8dc, "LCD_DATA15", 11, 7, "lcd_data15", "gpmc_a19", "eQEP1_strobe", "mcasp0_ahclkx", "mcasp0_axr3", "pr1_mii0_rxdv", "uart5_rtsn", "gpio0_11"),
+ _PIN(0x8e0, "LCD_VSYNC", 86, 7, "lcd_vsync", "gpmc_a8", "gpmc_a1", "pr1_edio_data_in2", "pr1_edio_data_out2", "pr1_pru1_pru_r30_8", "pr1_pru1_pru_r31_8", "gpio2_22"),
+ _PIN(0x8e4, "LCD_HSYNC", 87, 7, "lcd_hsync", "gmpc_a9", "gpmc_a2", "pr1_edio_data_in3", "pr1_edio_data_out3", "pr1_pru1_pru_r30_9", "pr1_pru1_pru_r31_9", "gpio2_23"),
+ _PIN(0x8e8, "LCD_PCLK", 88, 7, "lcd_pclk", "gpmc_a10", "pr1_mii0_crs", "pr1_edio_data_in4", "pr1_edio_data_out4", "pr1_pru1_pru_r30_10", "pr1_pru1_pru_r31_10", "gpio2_24"),
+ _PIN(0x8ec, "LCD_AC_BIAS_EN", 89, 7, "lcd_ac_bias_en", "gpmc_a11", "pr1_mii1_crs", "pr1_edio_data_in5", "pr1_edio_data_out5", "pr1_pru1_pru_r30_11", "pr1_pru1_pru_r31_11", "gpio2_25"),
+ _PIN(0x8f0, "MMC0_DAT3", 90, 7, "mmc0_dat3", "gpmc_a20", "uart4_ctsn", "timer5", "uart1_dcdn", "pr1_pru0_pru_r30_8", "pr1_pru0_pru_r31_8", "gpio2_26"),
+ _PIN(0x8f4, "MMC0_DAT2", 91, 7, "mmc0_dat2", "gpmc_a21", "uart4_rtsn", "timer6", "uart1_dsrn", "pr1_pru0_pru_r30_9", "pr1_pru0_pru_r31_9", "gpio2_27"),
+ _PIN(0x8f8, "MMC0_DAT1", 92, 7, "mmc0_dat1", "gpmc_a22", "uart5_ctsn", "uart3_rxd", "uart1_dtrn", "pr1_pru0_pru_r30_10", "pr1_pru0_pru_r31_10", "gpio2_28"),
+ _PIN(0x8fc, "MMC0_DAT0", 93, 7, "mmc0_dat0", "gpmc_a23", "uart5_rtsn", "uart3_txd", "uart1_rin", "pr1_pru0_pru_r30_11", "pr1_pru0_pru_r31_11", "gpio2_29"),
+ _PIN(0x900, "MMC0_CLK", 94, 7, "mmc0_clk", "gpmc_a24", "uart3_ctsn", "uart2_rxd", "dcan1_tx", "pr1_pru0_pru_r30_12", "pr1_pru0_pru_r31_12", "gpio2_30"),
+ _PIN(0x904, "MMC0_CMD", 95, 7, "mmc0_cmd", "gpmc_a25", "uart3_rtsn", "uart2_txd", "dcan1_rx", "pr1_pru0_pru_r30_13", "pr1_pru0_pru_r31_13", "gpio2_31"),
+ _PIN(0x908, "MII1_COL", 96, 7, "gmii1_col", "rmii2_refclk", "spi1_sclk", "uart5_rxd", "mcasp1_axr2", "mmc2_dat3", "mcasp0_axr2", "gpio3_0"),
+ _PIN(0x90c, "MII1_CRS", 97, 7, "gmii1_crs", "rmii1_crs_dv", "spi1_d0", "I2C1_SDA", "mcasp1_aclkx", "uart5_ctsn", "uart2_rxd", "gpio3_1"),
+ _PIN(0x910, "MII1_RX_ER", 98, 7, "gmii1_rxerr", "rmii1_rxerr", "spi1_d1", "I2C1_SCL", "mcasp1_fsx", "uart5_rtsn", "uart2_txd", "gpio3_2"),
+ _PIN(0x914, "MII1_TX_EN", 99, 7, "gmii1_txen", "rmii1_txen", "rgmii1_tctl", "timer4", "mcasp1_axr0", "eQEP0_index", "mmc2_cmd", "gpio3_3"),
_PIN(0x918, "MII1_RX_DV", 100, 7, "gmii1_rxdv", "cd_memory_clk", "rgmii1_rctl", "uart5_txd", "mcasp1_aclkx", "mmc2_dat0", "mcasp0_aclkr", "gpio3_4"),
- _PIN(0x91c, "MII1_TXD3", 16, 7, "gmii1_txd3", "dcan0_tx", "rgmii1_td3", "uart4_rxd", "mcasp1_fsx", "mmc2_dat1", "mcasp0_fsr", "gpio0_16"),
- _PIN(0x920, "MII1_TXD2", 17, 7, "gmii1_txd2", "dcan0_rx", "rgmii1_td2", "uart4_txd", "mcasp1_axr0", "mmc2_dat2", "mcasp0_ahclkx", "gpio0_17"),
- _PIN(0x924, "MII1_TXD1", 21, 7, "gmii1_txd1", "rmii1_txd1", "rgmii1_td1", "mcasp1_fsr", "mcasp1_axr1", "eQEP0A_in", "mmc1_cmd", "gpio0_21"),
- _PIN(0x928, "MII1_TXD0", 28, 7, "gmii1_txd0", "rmii1_txd0", "rgmii1_td0", "mcasp1_axr2", "mcasp1_aclkr", "eQEP0B_in", "mmc1_clk", "gpio0_28"),
+ _PIN(0x91c, "MII1_TXD3", 16, 7, "gmii1_txd3", "dcan0_tx", "rgmii1_td3", "uart4_rxd", "mcasp1_fsx", "mmc2_dat1", "mcasp0_fsr", "gpio0_16"),
+ _PIN(0x920, "MII1_TXD2", 17, 7, "gmii1_txd2", "dcan0_rx", "rgmii1_td2", "uart4_txd", "mcasp1_axr0", "mmc2_dat2", "mcasp0_ahclkx", "gpio0_17"),
+ _PIN(0x924, "MII1_TXD1", 21, 7, "gmii1_txd1", "rmii1_txd1", "rgmii1_td1", "mcasp1_fsr", "mcasp1_axr1", "eQEP0A_in", "mmc1_cmd", "gpio0_21"),
+ _PIN(0x928, "MII1_TXD0", 28, 7, "gmii1_txd0", "rmii1_txd0", "rgmii1_td0", "mcasp1_axr2", "mcasp1_aclkr", "eQEP0B_in", "mmc1_clk", "gpio0_28"),
_PIN(0x92c, "MII1_TX_CLK", 105, 7, "gmii1_txclk", "uart2_rxd", "rgmii1_tclk", "mmc0_dat7", "mmc1_dat0", "uart1_dcdn", "mcasp0_aclkx", "gpio3_9"),
_PIN(0x930, "MII1_RX_CLK", 106, 7, "gmii1_rxclk", "uart2_txd", "rgmii1_rclk", "mmc0_dat6", "mmc1_dat1", "uart1_dsrn", "mcasp0_fsx", "gpio3_10"),
- _PIN(0x934, "MII1_RXD3", 82, 7, "gmii1_rxd3", "uart3_rxd", "rgmii1_rd3", "mmc0_dat5", "mmc1_dat2", "uart1_dtrn", "mcasp0_axr0", "gpio2_18"),
- _PIN(0x938, "MII1_RXD2", 83, 7, "gmii1_rxd2", "uart3_txd", "rgmii1_rd2", "mmc0_dat4", "mmc1_dat3", "uart1_rin", "mcasp0_axr1", "gpio2_19"),
- _PIN(0x93c, "MII1_RXD1", 84, 7, "gmii1_rxd1", "rmii1_rxd1", "rgmii1_rd1", "mcasp1_axr3", "mcasp1_fsr", "eQEP0_strobe", "mmc2_clk", "gpio2_20"),
- _PIN(0x940, "MII1_RXD0", 85, 7, "gmii1_rxd0", "rmii1_rxd0", "rgmii1_rd0", "mcasp1_ahclkx", "mcasp1_ahclkr", "mcasp1_aclkr", "mcasp0_axr3", "gpio2_21"),
- _PIN(0x944, "RMII1_REF_CLK", 29, 7, "rmii1_refclk", "xdma_event_intr2", "spi1_cs0", "uart5_txd", "mcasp1_axr3", "mmc0_pow", "mcasp1_ahclkx", "gpio0_29"),
- _PIN(0x948, "MDIO", 0, 7, "mdio_data", "timer6", "uart5_rxd", "uart3_ctsn", "mmc0_sdcd","mmc1_cmd", "mmc2_cmd","gpio0_0"),
- _PIN(0x94c, "MDC", 1, 7, "mdio_clk", "timer5", "uart5_txd", "uart3_rtsn", "mmc0_sdwp", "mmc1_clk", "mmc2_clk", "gpio0_1"),
-#if 0 /* Incomplete Entries - fill with data from table 2-7 in datasheet */
- _PIN(0x950, "spi0_sclk", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x954, "spi0_d0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
- _PIN(0x958, "spi0_d1", 4, 7, "spi0_d1", "mmc1_sdwp", "I2C1_SDA", "ehrpwm0_tripzone_input", "pr1_uart0_rxd", "pr1_edio_data_in0", "pr1_edio_data_out0", "gpio0_4"),
- _PIN(0x95c, "spi0_cs0", 5, 7, "spi0_cs0", "mmc2_sdwp", "I2C1_SCL", "ehrpwm0_synci", "pr1_uart0_txd", "pr1_edio_data_in1", "pr1_edio_data_out1", "gpio0_5"),
-#if 0
- _PIN(0x960, "spi0_cs1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x964, "ecap0_in_pwm0_out",0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x968, "uart0_ctsn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x96c, "uart0_rtsn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x970, "uart0_rxd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x974, "uart0_txd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
- _PIN(0x978, "uart1_ctsn", 12, 7, "uart1_ctsn", "timer6_mux1", "dcan0_tx", "I2C2_SDA", "spi1_cs0", "pr1_uart0_cts_n", "pr1_edc_latch0_in", "gpio0_12"),
- _PIN(0x97c, "uart1_rtsn", 13, 7, "uart1_rtsn", "timer5_mux1", "dcan0_rx", "I2C2_SCL", "spi1_cs1", "pr1_uart0_rts_n ", "pr1_edc_latch1_in", "gpio0_13"),
-#if 0
- _PIN(0x980, "uart1_rxd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x984, "uart1_txd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
+ _PIN(0x934, "MII1_RXD3", 82, 7, "gmii1_rxd3", "uart3_rxd", "rgmii1_rd3", "mmc0_dat5", "mmc1_dat2", "uart1_dtrn", "mcasp0_axr0", "gpio2_18"),
+ _PIN(0x938, "MII1_RXD2", 83, 7, "gmii1_rxd2", "uart3_txd", "rgmii1_rd2", "mmc0_dat4", "mmc1_dat3", "uart1_rin", "mcasp0_axr1", "gpio2_19"),
+ _PIN(0x93c, "MII1_RXD1", 84, 7, "gmii1_rxd1", "rmii1_rxd1", "rgmii1_rd1", "mcasp1_axr3", "mcasp1_fsr", "eQEP0_strobe", "mmc2_clk", "gpio2_20"),
+ _PIN(0x940, "MII1_RXD0", 85, 7, "gmii1_rxd0", "rmii1_rxd0", "rgmii1_rd0", "mcasp1_ahclkx", "mcasp1_ahclkr", "mcasp1_aclkr", "mcasp0_axr3", "gpio2_21"),
+ _PIN(0x944, "RMII1_REF_CLK", 29, 7, "rmii1_refclk", "xdma_event_intr2", "spi1_cs0", "uart5_txd", "mcasp1_axr3", "mmc0_pow", "mcasp1_ahclkx", "gpio0_29"),
+ _PIN(0x948, "MDIO", 0, 7, "mdio_data", "timer6", "uart5_rxd", "uart3_ctsn", "mmc0_sdcd","mmc1_cmd", "mmc2_cmd","gpio0_0"),
+ _PIN(0x94c, "MDC", 1, 7, "mdio_clk", "timer5", "uart5_txd", "uart3_rtsn", "mmc0_sdwp", "mmc1_clk", "mmc2_clk", "gpio0_1"),
+ _PIN(0x950, "SPI0_SCLK", 2, 7, "spi0_sclk", "uart2_rxd", "I2C2_SDA", "ehrpwm0A", "pr1_uart0_cts_n", "pr1_edio_sof", "EMU2", "gpio0_2"),
+ _PIN(0x954, "SPI0_D0", 3, 7, "spi0_d0", "uart2_txd", "i2C2_SCL", "ehrpwm0B", "pr1_uart0_rts_n", "pr1_edio_latch_in", "EMU3", "gpio0_3"),
+ _PIN(0x958, "SPIO_D1", 4, 7, "spi0_d1", "mmc1_sdwp", "I2C1_SDA", "ehrpwm0_tripzone_input", "pr1_uart0_rxd", "pr1_edio_data_in0", "pr1_edio_data_out0", "gpio0_4"),
+ _PIN(0x95c, "SPI0_CS0", 5, 7, "spi0_cs0", "mmc2_sdwp", "I2C1_SCL", "ehrpwm0_synci", "pr1_uart0_txd", "pr1_edio_data_in1", "pr1_edio_data_out1", "gpio0_5"),
+ _PIN(0x960, "SPI0_CS1", 6, 7, "spi0_cs1", "uart3_rxd", "eCAP1_in_PWM1_out", "mcc0_pow", "xdm_event_intr2", "mmc0_sdcd", "EMU4", "gpio0_6"),
+ _PIN(0x964, "ECAP0_IN_PWM0_OUT",7, 7, "eCAP0_in_PWM0_out", "uart3_txd", "spi1_cs1", "pr1_ecap0_ecap_capin_apwm_o", "spi1_sclk", "mmc0_sdwp", "xdma_event_intr2", "gpio0_7"),
+ _PIN(0x968, "UART0_CTSn", 40, 7, "uart0_ctsn", "uart4_rxd", "dcan1_tx", "I2C1_SDA", "spi1_d0", "timer7", "pr1_edc_sync0_out", "gpio1_8"),
+ _PIN(0x96c, "UART0_RTSn", 41, 7, "uart0_rtsn", "uart4_txd", "dcan1_rx", "I2C1_SCL", "spi1_d1", "spi1_cs0", "pr1_edc_sync1_out", "gpio1_9"),
+ _PIN(0x970, "UART0_rxd", 42, 7, "uart0_rxd", "spi1_cs0", "dcan0_tx", "I2C2_SDA", "eCAP2_in_PWM2_out", "pr1_pru1_pru_r30_14", "pr1_pru1_pru_r31_14", "gpio1_10"),
+ _PIN(0x974, "UART0_txd", 43, 7, "uart0_txd", "spi1_cs1", "dcan0_rx", "I2C2_SCL", "eCAP1_in_PWM1_out", "pr1_pru1_pru_r30_15", "pr1_pru1_pru_r31_15", "gpio1_11"),
+ _PIN(0x978, "UART1_CTSn", 12, 7, "uart1_ctsn", "timer6_mux1", "dcan0_tx", "I2C2_SDA", "spi1_cs0", "pr1_uart0_cts_n", "pr1_edc_latch0_in", "gpio0_12"),
+ _PIN(0x97c, "UART1_RTSn", 13, 7, "uart1_rtsn", "timer5_mux1", "dcan0_rx", "I2C2_SCL", "spi1_cs1", "pr1_uart0_rts_n ", "pr1_edc_latch1_in", "gpio0_13"),
+ _PIN(0x980, "UART1_RXD", 14, 7, "uart1_rxd", "mmc1_sdwp", "dcan1_tx", "I2C1_SDA", NULL, "pr1_uart0_rxd", "pr1_pru1_pru_r31_16", "gpio0_14"),
+ _PIN(0x984, "UART1_TXD", 15, 7, "uart1_txd", "mmc2_sdwp", "dcan1_rx", "I2C1_SCL", NULL, "pr1_uart0_txd", "pr1_pru0_pru_r31_16", "gpio0_15"),
_PIN(0x988, "I2C0_SDA", 101, 7, "I2C0_SDA", "timer4", "uart2_ctsn", "eCAP2_in_PWM2_out", NULL, NULL, NULL, "gpio3_5"),
_PIN(0x98c, "I2C0_SCL", 102, 7, "I2C0_SCL", "timer7", "uart2_rtsn", "eCAP1_in_PWM1_out", NULL, NULL, NULL, "gpio3_6"),
+ _PIN(0x990, "MCASP0_ACLKX", 110, 7, "mcasp0_aclkx", "ehrpwm0A", NULL, "spi1_sclk", "mmc0_sdcd", "pr1_pru0_pru_r30_0", "pr1_pru0_pru_r31_0", "gpio3_14"),
+ _PIN(0x994, "MCASP0_FSX", 111, 7, "mcasp0_fsx", "ehrpwm0B", NULL, "spi1_d0", "mmc1_sdcd", "pr1_pru0_pru_r30_1", "pr1_pru0_pru_r31_1", "gpio3_15"),
+ _PIN(0x998, "MCASP0_AXR0", 112, 7, "mcasp0_axr0", "ehrpwm0_tripzone_input", NULL, "spi1_d1", "mmc2_sdcd", "pr1_pru0_pru_r30_2", "pr1_pru0_pru_r31_2", "gpio3_16"),
+ _PIN(0x99c, "MCASP0_AHCLKR", 113, 7, "mcasp0_ahclkr", "ehrpwm0_synci", "mcasp0_axr2", "spi1_cs0", "eCAP2_in_PWM2_out", "pr1_pru0_pru_r30_3", "pr1_pru0_pru_r31_3", "gpio3_17"),
+ _PIN(0x9a0, "MCASP0_ACLKR", 114, 7, "mcasp0_aclkr", "eQEP0A_in", "mcasp0_axr2", "mcasp1_aclkx", "mmc0_sdwp", "pr1_pru0_pru_r30_4", "pr1_pru0_pru_r31_4", "gpio3_18"),
+ _PIN(0x9a4, "MCASP0_FSR", 115, 7, "mcasp0_fsr", "eQEP0B_in", "mcasp0_axr3", "mcasp1_fsx", "EMU2", "pr1_pru0_pru_r30_5", "pr1_pru0_pru_r31_5", "gpio3_19"),
+ _PIN(0x9a8, "MCASP0_AXR1", 116, 7, "mcasp0_axr1", "eQEP0_index", NULL, "mcasp1_axr0", "EMU3", "pr1_pru0_pru_r30_6", "pr1_pru0_pru_r31_6", "gpio3_20"),
+ _PIN(0x9ac, "MCASP0_AHCLKX", 117, 7, "mcasp0_ahclkx", "eQEP0_strobe", "mcasp0_axr3", "mcasp1_axr1", "EMU4", "pr1_pru0_pru_r30_7", "pr1_pru0_pru_r31_7", "gpio3_21"),
+ _PIN(0x9b0, "XDMA_EVENT_INTR0", 19, 7, "xdma_event_intr0", NULL, "timer4", "clkout1", "spi1_cs1", "pr1_pru1_pru_r31_16", "EMU2", "gpio0_19"),
+ _PIN(0x9b4, "XDMA_EVENT_INTR1", 20, 7, "xdma_event_intr1", NULL, "tclkin", "clkout2", "timer7", "pr1_pru0_pru_r31_16", "EMU3", "gpio0_20"),
#if 0
- _PIN(0x990, "mcasp0_aclkx", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x994, "mcasp0_fsx", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x998, "mcasp0_axr0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x99c, "mcasp0_ahclkr", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9a0, "mcasp0_aclkr", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9a4, "mcasp0_fsr", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9a8, "mcasp0_axr1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9ac, "mcasp0_ahclkx", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9b0, "xdma_event_intr0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9b4, "xdma_event_intr1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9b8, "nresetin_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9bc, "porz", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9c0, "nnmi", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
@@ -218,8 +208,10 @@ const struct ti_scm_padconf ti_padconf_devmap[] = {
_PIN(0x9d8, "tdo", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9dc, "tck", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9e0, "ntrst", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9e4, "emu0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9e8, "emu1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+#endif
+ _PIN(0x9e4, "EMU0", 103, 7, "EMU0", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_7"),
+ _PIN(0x9e8, "EMU1", 104, 0, "EMU1", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_8"),
+#if 0
_PIN(0x9ec, "osc1_in", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9f0, "osc1_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9f4, "osc1_vss", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
@@ -228,17 +220,17 @@ const struct ti_scm_padconf ti_padconf_devmap[] = {
_PIN(0xa00, "ext_wakeup", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0xa04, "enz_kaldo_1p8v", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
#endif
- _PIN(0xa08, "USB0_DM", 0, 0, "USB0_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa0c, "USB0_DP", 0, 0, "USB0_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa10, "USB0_CE", 0, 0, "USB0_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa14, "USB0_ID", 0, 0, "USB0_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa18, "USB0_VBUS", 0, 0, "USB0_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa1c, "USB0_DRVVBUS", 18, 7, "USB0_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio0_18"),
- _PIN(0xa20, "USB1_DM", 0, 0, "USB1_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa24, "USB1_DP", 0, 0, "USB1_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa28, "USB1_CE", 0, 0, "USB1_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa2c, "USB1_ID", 0, 0, "USB1_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa30, "USB1_VBUS", 0, 0, "USB1_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa08, "USB0_DM", 0, 0, "USB0_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa0c, "USB0_DP", 0, 0, "USB0_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa10, "USB0_CE", 0, 0, "USB0_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa14, "USB0_ID", 0, 0, "USB0_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa18, "USB0_VBUS", 0, 0, "USB0_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa1c, "USB0_DRVVBUS", 18, 7, "USB0_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio0_18"),
+ _PIN(0xa20, "USB1_DM", 0, 0, "USB1_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa24, "USB1_DP", 0, 0, "USB1_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa28, "USB1_CE", 0, 0, "USB1_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa2c, "USB1_ID", 0, 0, "USB1_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa30, "USB1_VBUS", 0, 0, "USB1_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0xa34, "USB1_DRVVBUS", 109, 7, "USB1_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_13"),
#if 0
_PIN(0xa38, "ddr_resetn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
diff --git a/sys/arm/ti/cpsw/if_cpsw.c b/sys/arm/ti/cpsw/if_cpsw.c
index a47c131..93702df 100644
--- a/sys/arm/ti/cpsw/if_cpsw.c
+++ b/sys/arm/ti/cpsw/if_cpsw.c
@@ -25,8 +25,22 @@
*/
/*
- * TI 3 Port Switch Ethernet (CPSW) Driver
- * Found in TI8148, AM335x SoCs
+ * TI Common Platform Ethernet Switch (CPSW) Driver
+ * Found in TI8148 "DaVinci" and AM335x "Sitara" SoCs.
+ *
+ * This controller is documented in the AM335x Technical Reference
+ * Manual, in the TMS320DM814x DaVinci Digital Video Processors TRM
+ * and in the TMS320C6452 3 Port Switch Ethernet Subsystem TRM.
+ *
+ * It is basically a single Ethernet port (port 0) wired internally to
+ * a 3-port store-and-forward switch connected to two independent
+ * "sliver" controllers (port 1 and port 2). You can operate the
+ * controller in a variety of different ways by suitably configuring
+ * the slivers and the Address Lookup Engine (ALE) that routes packets
+ * between the ports.
+ *
+ * This code was developed and tested on a BeagleBone with
+ * an AM335x SoC.
*/
#include <sys/cdefs.h>
@@ -76,44 +90,82 @@ __FBSDID("$FreeBSD$");
#include "miibus_if.h"
-static int cpsw_probe(device_t dev);
-static int cpsw_attach(device_t dev);
-static int cpsw_detach(device_t dev);
-static int cpsw_shutdown(device_t dev);
-static int cpsw_suspend(device_t dev);
-static int cpsw_resume(device_t dev);
-
-static int cpsw_miibus_readreg(device_t dev, int phy, int reg);
-static int cpsw_miibus_writereg(device_t dev, int phy, int reg, int value);
-
-static int cpsw_ifmedia_upd(struct ifnet *ifp);
-static void cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
-
-static void cpsw_init(void *arg);
-static void cpsw_init_locked(void *arg);
-static void cpsw_start(struct ifnet *ifp);
-static void cpsw_start_locked(struct ifnet *ifp);
-static void cpsw_stop_locked(struct cpsw_softc *sc);
-static int cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data);
-static int cpsw_init_slot_lists(struct cpsw_softc *sc);
-static void cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot);
-static void cpsw_fill_rx_queue_locked(struct cpsw_softc *sc);
-static void cpsw_tx_watchdog(struct cpsw_softc *sc);
-
-static void cpsw_intr_rx_thresh(void *arg);
+/* Device probe/attach/detach. */
+static int cpsw_probe(device_t);
+static void cpsw_init_slots(struct cpsw_softc *);
+static int cpsw_attach(device_t);
+static void cpsw_free_slot(struct cpsw_softc *, struct cpsw_slot *);
+static int cpsw_detach(device_t);
+
+/* Device Init/shutdown. */
+static void cpsw_init(void *);
+static void cpsw_init_locked(void *);
+static int cpsw_shutdown(device_t);
+static void cpsw_shutdown_locked(struct cpsw_softc *);
+
+/* Device Suspend/Resume. */
+static int cpsw_suspend(device_t);
+static int cpsw_resume(device_t);
+
+/* Ioctl. */
+static int cpsw_ioctl(struct ifnet *, u_long command, caddr_t data);
+
+static int cpsw_miibus_readreg(device_t, int phy, int reg);
+static int cpsw_miibus_writereg(device_t, int phy, int reg, int value);
+
+/* Send/Receive packets. */
static void cpsw_intr_rx(void *arg);
-static void cpsw_intr_rx_locked(void *arg);
-static void cpsw_intr_tx(void *arg);
-static void cpsw_intr_tx_locked(void *arg);
-static void cpsw_intr_misc(void *arg);
-
-static void cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry);
-static void cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry);
-static int cpsw_ale_uc_entry_set(struct cpsw_softc *sc, uint8_t port, uint8_t *mac);
-static int cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac);
-#ifdef CPSW_DEBUG
-static void cpsw_ale_dump_table(struct cpsw_softc *sc);
-#endif
+static struct mbuf *cpsw_rx_dequeue(struct cpsw_softc *);
+static void cpsw_rx_enqueue(struct cpsw_softc *);
+static void cpsw_start(struct ifnet *);
+static void cpsw_tx_enqueue(struct cpsw_softc *);
+static int cpsw_tx_dequeue(struct cpsw_softc *);
+
+/* Misc interrupts and watchdog. */
+static void cpsw_intr_rx_thresh(void *);
+static void cpsw_intr_misc(void *);
+static void cpsw_tick(void *);
+static void cpsw_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int cpsw_ifmedia_upd(struct ifnet *);
+static void cpsw_tx_watchdog(struct cpsw_softc *);
+
+/* ALE support */
+static void cpsw_ale_read_entry(struct cpsw_softc *, uint16_t idx, uint32_t *ale_entry);
+static void cpsw_ale_write_entry(struct cpsw_softc *, uint16_t idx, uint32_t *ale_entry);
+static int cpsw_ale_mc_entry_set(struct cpsw_softc *, uint8_t portmap, uint8_t *mac);
+static int cpsw_ale_update_addresses(struct cpsw_softc *, int purge);
+static void cpsw_ale_dump_table(struct cpsw_softc *);
+
+/* Statistics and sysctls. */
+static void cpsw_add_sysctls(struct cpsw_softc *);
+static void cpsw_stats_collect(struct cpsw_softc *);
+static int cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS);
+
+/*
+ * Arbitrary limit on number of segments in an mbuf to be transmitted.
+ * Packets with more segments than this will be defragmented before
+ * they are queued.
+ */
+#define CPSW_TXFRAGS 8
+
+
+/*
+ * TODO: The CPSW subsystem (CPSW_SS) can drive two independent PHYs
+ * as separate Ethernet ports. To properly support this, we should
+ * break this into two separate devices: a CPSW_SS device that owns
+ * the interrupts and actually talks to the CPSW hardware, and a
+ * separate CPSW Ethernet child device for each Ethernet port. The RX
+ * interrupt, for example, would be part of CPSW_SS; it would receive
+ * a packet, note the input port, and then dispatch it to the child
+ * device's interface queue. Similarly for transmit.
+ *
+ * It's not clear to me whether the device tree should be restructured
+ * with a cpsw_ss node and two child nodes. That would allow specifying
+ * MAC addresses for each port, for example, but might be overkill.
+ *
+ * Unfortunately, I don't have hardware right now that supports two
+ * Ethernet ports via CPSW.
+ */
static device_method_t cpsw_methods[] = {
/* Device interface */
@@ -137,7 +189,6 @@ static driver_t cpsw_driver = {
static devclass_t cpsw_devclass;
-
DRIVER_MODULE(cpsw, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
DRIVER_MODULE(miibus, cpsw, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(cpsw, ether, 1, 1, 1);
@@ -152,40 +203,109 @@ static struct resource_spec res_spec[] = {
{ -1, 0 }
};
-static struct {
- driver_intr_t *handler;
- char * description;
-} cpsw_intrs[CPSW_INTR_COUNT + 1] = {
- { cpsw_intr_rx_thresh, "CPSW RX threshold interrupt" },
- { cpsw_intr_rx, "CPSW RX interrupt" },
- { cpsw_intr_tx, "CPSW TX interrupt" },
- { cpsw_intr_misc, "CPSW misc interrupt" },
+/* Number of entries here must match size of stats
+ * array in struct cpsw_softc. */
+static struct cpsw_stat {
+ int reg;
+ char *oid;
+} cpsw_stat_sysctls[CPSW_SYSCTL_COUNT] = {
+ {0x00, "GoodRxFrames"},
+ {0x04, "BroadcastRxFrames"},
+ {0x08, "MulticastRxFrames"},
+ {0x0C, "PauseRxFrames"},
+ {0x10, "RxCrcErrors"},
+ {0x14, "RxAlignErrors"},
+ {0x18, "OversizeRxFrames"},
+ {0x1c, "RxJabbers"},
+ {0x20, "ShortRxFrames"},
+ {0x24, "RxFragments"},
+ {0x30, "RxOctets"},
+ {0x34, "GoodTxFrames"},
+ {0x38, "BroadcastTxFrames"},
+ {0x3c, "MulticastTxFrames"},
+ {0x40, "PauseTxFrames"},
+ {0x44, "DeferredTxFrames"},
+ {0x48, "CollisionsTxFrames"},
+ {0x4c, "SingleCollisionTxFrames"},
+ {0x50, "MultipleCollisionTxFrames"},
+ {0x54, "ExcessiveCollisions"},
+ {0x58, "LateCollisions"},
+ {0x5c, "TxUnderrun"},
+ {0x60, "CarrierSenseErrors"},
+ {0x64, "TxOctets"},
+ {0x68, "RxTx64OctetFrames"},
+ {0x6c, "RxTx65to127OctetFrames"},
+ {0x70, "RxTx128to255OctetFrames"},
+ {0x74, "RxTx256to511OctetFrames"},
+ {0x78, "RxTx512to1024OctetFrames"},
+ {0x7c, "RxTx1024upOctetFrames"},
+ {0x80, "NetOctets"},
+ {0x84, "RxStartOfFrameOverruns"},
+ {0x88, "RxMiddleOfFrameOverruns"},
+ {0x8c, "RxDmaOverruns"}
};
-/* Locking macros */
+/*
+ * Basic debug support.
+ */
+
+#define IF_DEBUG(sc) if (sc->cpsw_if_flags & IFF_DEBUG)
+
+static void
+cpsw_debugf_head(const char *funcname)
+{
+ int t = (int)(time_second % (24 * 60 * 60));
+
+ printf("%02d:%02d:%02d %s ", t / (60 * 60), (t / 60) % 60, t % 60, funcname);
+}
+
+#include <machine/stdarg.h>
+static void
+cpsw_debugf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ printf("\n");
+
+}
+
+#define CPSW_DEBUGF(a) do { \
+ IF_DEBUG(sc) { \
+ cpsw_debugf_head(__func__); \
+ cpsw_debugf a; \
+ } \
+} while (0)
+
+
+/*
+ * Locking macros
+ */
#define CPSW_TX_LOCK(sc) do { \
- mtx_assert(&(sc)->rx_lock, MA_NOTOWNED); \
- mtx_lock(&(sc)->tx_lock); \
+ mtx_assert(&(sc)->rx.lock, MA_NOTOWNED); \
+ mtx_lock(&(sc)->tx.lock); \
} while (0)
-#define CPSW_TX_UNLOCK(sc) mtx_unlock(&(sc)->tx_lock)
-#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx_lock, MA_OWNED)
+#define CPSW_TX_UNLOCK(sc) mtx_unlock(&(sc)->tx.lock)
+#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx.lock, MA_OWNED)
#define CPSW_RX_LOCK(sc) do { \
- mtx_assert(&(sc)->tx_lock, MA_NOTOWNED); \
- mtx_lock(&(sc)->rx_lock); \
+ mtx_assert(&(sc)->tx.lock, MA_NOTOWNED); \
+ mtx_lock(&(sc)->rx.lock); \
} while (0)
-#define CPSW_RX_UNLOCK(sc) mtx_unlock(&(sc)->rx_lock)
-#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx_lock, MA_OWNED)
+#define CPSW_RX_UNLOCK(sc) mtx_unlock(&(sc)->rx.lock)
+#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx.lock, MA_OWNED)
#define CPSW_GLOBAL_LOCK(sc) do { \
- if ((mtx_owned(&(sc)->tx_lock) ? 1 : 0) != \
- (mtx_owned(&(sc)->rx_lock) ? 1 : 0)) { \
+ if ((mtx_owned(&(sc)->tx.lock) ? 1 : 0) != \
+ (mtx_owned(&(sc)->rx.lock) ? 1 : 0)) { \
panic("cpsw deadlock possibility detection!"); \
} \
- mtx_lock(&(sc)->tx_lock); \
- mtx_lock(&(sc)->rx_lock); \
+ mtx_lock(&(sc)->tx.lock); \
+ mtx_lock(&(sc)->rx.lock); \
} while (0)
#define CPSW_GLOBAL_UNLOCK(sc) do { \
@@ -198,35 +318,128 @@ static struct {
CPSW_RX_LOCK_ASSERT(sc); \
} while (0)
-
-#include <machine/stdarg.h>
+/*
+ * Read/Write macros
+ */
+#define cpsw_read_4(sc, reg) bus_read_4(sc->res[0], reg)
+#define cpsw_write_4(sc, reg, val) bus_write_4(sc->res[0], reg, val)
+
+#define cpsw_cpdma_bd_offset(i) (CPSW_CPPI_RAM_OFFSET + ((i)*16))
+
+#define cpsw_cpdma_bd_paddr(sc, slot) \
+ (slot->bd_offset + vtophys(rman_get_start(sc->res[0])))
+#define cpsw_cpdma_read_bd(sc, slot, val) \
+ bus_read_region_4(sc->res[0], slot->bd_offset, (uint32_t *) val, 4)
+#define cpsw_cpdma_write_bd(sc, slot, val) \
+ bus_write_region_4(sc->res[0], slot->bd_offset, (uint32_t *) val, 4)
+#define cpsw_cpdma_write_bd_next(sc, slot, next_slot) \
+ cpsw_write_4(sc, slot->bd_offset, cpsw_cpdma_bd_paddr(sc, next_slot))
+#define cpsw_cpdma_read_bd_flags(sc, slot) \
+ bus_read_2(sc->res[0], slot->bd_offset + 14)
+#define cpsw_write_hdp_slot(sc, queue, slot) \
+ cpsw_write_4(sc, (queue)->hdp_offset, cpsw_cpdma_bd_paddr(sc, slot))
+#define CP_OFFSET (CPSW_CPDMA_TX_CP(0) - CPSW_CPDMA_TX_HDP(0))
+#define cpsw_read_cp(sc, queue) \
+ cpsw_read_4(sc, (queue)->hdp_offset + CP_OFFSET)
+#define cpsw_write_cp(sc, queue, val) \
+ cpsw_write_4(sc, (queue)->hdp_offset + CP_OFFSET, (val))
+#define cpsw_write_cp_slot(sc, queue, slot) \
+ cpsw_write_cp(sc, queue, cpsw_cpdma_bd_paddr(sc, slot))
+
+#if 0
+/* XXX temporary function versions for debugging. */
static void
-cpsw_debugf_head(const char *funcname)
+cpsw_write_hdp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
{
- int t = (int)(time_second % (24 * 60 * 60));
+ uint32_t reg = queue->hdp_offset;
+ uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
+ CPSW_DEBUGF(("HDP <=== 0x%08x (was 0x%08x)", v, cpsw_read_4(sc, reg)));
+ cpsw_write_4(sc, reg, v);
+}
- printf("%02d:%02d:%02d %s ", t / (60 * 60), (t / 60) % 60, t % 60, funcname);
+static void
+cpsw_write_cp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
+{
+ uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
+ CPSW_DEBUGF(("CP <=== 0x%08x (expecting 0x%08x)", v, cpsw_read_cp(sc, queue)));
+ cpsw_write_cp(sc, queue, v);
}
+#endif
+/*
+ * Expanded dump routines for verbose debugging.
+ */
static void
-cpsw_debugf(const char *fmt, ...)
+cpsw_dump_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
{
- va_list ap;
+ static const char *flags[] = {"SOP", "EOP", "Owner", "EOQ",
+ "TDownCmplt", "PassCRC", "Long", "Short", "MacCtl", "Overrun",
+ "PktErr1", "PortEn/PktErr0", "RxVlanEncap", "Port2", "Port1",
+ "Port0"};
+ struct cpsw_cpdma_bd bd;
+ const char *sep;
+ int i;
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
+ cpsw_cpdma_read_bd(sc, slot, &bd);
+ printf("BD Addr: 0x%08x Next: 0x%08x\n", cpsw_cpdma_bd_paddr(sc, slot), bd.next);
+ printf(" BufPtr: 0x%08x BufLen: 0x%08x\n", bd.bufptr, bd.buflen);
+ printf(" BufOff: 0x%08x PktLen: 0x%08x\n", bd.bufoff, bd.pktlen);
+ printf(" Flags: ");
+ sep = "";
+ for (i = 0; i < 16; ++i) {
+ if (bd.flags & (1 << (15 - i))) {
+ printf("%s%s", sep, flags[i]);
+ sep = ",";
+ }
+ }
printf("\n");
+ if (slot->mbuf) {
+ printf(" Ether: %14D\n",
+ (char *)(slot->mbuf->m_hdr.mh_data), " ");
+ printf(" Packet: %16D\n",
+ (char *)(slot->mbuf->m_hdr.mh_data) + 14, " ");
+ }
+}
+#define CPSW_DUMP_SLOT(cs, slot) do { \
+ IF_DEBUG(sc) { \
+ cpsw_dump_slot(sc, slot); \
+ } \
+} while (0)
+
+
+static void
+cpsw_dump_queue(struct cpsw_softc *sc, struct cpsw_slots *q)
+{
+ struct cpsw_slot *slot;
+ int i = 0;
+ int others = 0;
+
+ STAILQ_FOREACH(slot, q, next) {
+ if (i > 4)
+ ++others;
+ else
+ cpsw_dump_slot(sc, slot);
+ ++i;
+ }
+ if (others)
+ printf(" ... and %d more.\n", others);
+ printf("\n");
}
-#define CPSW_DEBUGF(a) do { \
- if (sc->cpsw_if_flags & IFF_DEBUG) { \
- cpsw_debugf_head(__func__); \
- cpsw_debugf a; \
- } \
+#define CPSW_DUMP_QUEUE(sc, q) do { \
+ IF_DEBUG(sc) { \
+ cpsw_dump_queue(sc, q); \
+ } \
} while (0)
+
+/*
+ *
+ * Device Probe, Attach, Detach.
+ *
+ */
+
static int
cpsw_probe(device_t dev)
{
@@ -238,18 +451,107 @@ cpsw_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
+
+static void
+cpsw_init_slots(struct cpsw_softc *sc)
+{
+ struct cpsw_slot *slot;
+ int i;
+
+ STAILQ_INIT(&sc->avail);
+
+ /* Put the slot descriptors onto the global avail list. */
+ for (i = 0; i < sizeof(sc->_slots) / sizeof(sc->_slots[0]); i++) {
+ slot = &sc->_slots[i];
+ slot->bd_offset = cpsw_cpdma_bd_offset(i);
+ STAILQ_INSERT_TAIL(&sc->avail, slot, next);
+ }
+}
+
+/*
+ * bind an interrupt, add the relevant info to sc->interrupts
+ */
+static int
+cpsw_attach_interrupt(struct cpsw_softc *sc, struct resource *res, driver_intr_t *handler, const char *description)
+{
+ void **pcookie;
+ int error;
+
+ sc->interrupts[sc->interrupt_count].res = res;
+ sc->interrupts[sc->interrupt_count].description = description;
+ pcookie = &sc->interrupts[sc->interrupt_count].ih_cookie;
+
+ error = bus_setup_intr(sc->dev, res, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, *handler, sc, pcookie);
+ if (error)
+ device_printf(sc->dev,
+ "could not setup %s\n", description);
+ else
+ ++sc->interrupt_count;
+ return (error);
+}
+
+/*
+ * teardown everything in sc->interrupts.
+ */
+static void
+cpsw_detach_interrupts(struct cpsw_softc *sc)
+{
+ int error;
+ int i;
+
+ for (i = 0; i < sizeof(sc->interrupts) / sizeof(sc->interrupts[0]); ++i) {
+ if (!sc->interrupts[i].ih_cookie)
+ continue;
+ error = bus_teardown_intr(sc->dev,
+ sc->interrupts[i].res, sc->interrupts[i].ih_cookie);
+ if (error)
+ device_printf(sc->dev, "could not release %s\n",
+ sc->interrupts[i].description);
+ sc->interrupts[i].ih_cookie = NULL;
+ }
+}
+
+static int
+cpsw_add_slots(struct cpsw_softc *sc, struct cpsw_queue *queue, int requested)
+{
+ const int max_slots = sizeof(sc->_slots) / sizeof(sc->_slots[0]);
+ struct cpsw_slot *slot;
+ int i;
+
+ if (requested < 0)
+ requested = max_slots;
+
+ for (i = 0; i < requested; ++i) {
+ slot = STAILQ_FIRST(&sc->avail);
+ if (slot == NULL)
+ return (0);
+ if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
+ if_printf(sc->ifp, "failed to create dmamap\n");
+ return (ENOMEM);
+ }
+ STAILQ_REMOVE_HEAD(&sc->avail, next);
+ STAILQ_INSERT_TAIL(&queue->avail, slot, next);
+ ++queue->avail_queue_len;
+ ++queue->queue_slots;
+ }
+ return (0);
+}
+
static int
cpsw_attach(device_t dev)
{
+ bus_dma_segment_t segs[1];
struct cpsw_softc *sc = device_get_softc(dev);
struct mii_softc *miisc;
struct ifnet *ifp;
void *phy_sc;
- int i, error, phy;
+ int error, phy, nsegs;
uint32_t reg;
CPSW_DEBUGF((""));
+ getbinuptime(&sc->attach_uptime);
sc->dev = dev;
sc->node = ofw_bus_get_node(dev);
@@ -259,10 +561,10 @@ cpsw_attach(device_t dev)
return (ENXIO);
}
/* Initialize mutexes */
- mtx_init(&sc->tx_lock, device_get_nameunit(dev),
- "cpsw TX lock", MTX_DEF);
- mtx_init(&sc->rx_lock, device_get_nameunit(dev),
- "cpsw RX lock", MTX_DEF);
+ mtx_init(&sc->tx.lock, device_get_nameunit(dev),
+ "cpsw TX lock", MTX_DEF);
+ mtx_init(&sc->rx.lock, device_get_nameunit(dev),
+ "cpsw RX lock", MTX_DEF);
/* Allocate IO and IRQ resources */
error = bus_alloc_resources(dev, res_spec, sc->res);
@@ -272,11 +574,11 @@ cpsw_attach(device_t dev)
return (ENXIO);
}
- reg = cpsw_read_4(CPSW_SS_IDVER);
- device_printf(dev, "Version %d.%d (%d)\n", (reg >> 8 & 0x7),
+ reg = cpsw_read_4(sc, CPSW_SS_IDVER);
+ device_printf(dev, "CPSW SS Version %d.%d (%d)\n", (reg >> 8 & 0x7),
reg & 0xFF, (reg >> 11) & 0x1F);
- //cpsw_add_sysctls(sc); TODO
+ cpsw_add_sysctls(sc);
/* Allocate a busdma tag and DMA safe memory for mbufs. */
error = bus_dma_tag_create(
@@ -285,22 +587,14 @@ cpsw_attach(device_t dev)
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filtfunc, filtfuncarg */
- MCLBYTES, 1, /* maxsize, nsegments */
+ MCLBYTES, CPSW_TXFRAGS, /* maxsize, nsegments */
MCLBYTES, 0, /* maxsegsz, flags */
NULL, NULL, /* lockfunc, lockfuncarg */
&sc->mbuf_dtag); /* dmatag */
if (error) {
device_printf(dev, "bus_dma_tag_create failed\n");
cpsw_detach(dev);
- return (ENOMEM);
- }
-
- /* Initialize the tx_avail and rx_avail lists. */
- error = cpsw_init_slot_lists(sc);
- if (error) {
- device_printf(dev, "failed to allocate dmamaps\n");
- cpsw_detach(dev);
- return (ENOMEM);
+ return (error);
}
/* Allocate network interface */
@@ -311,6 +605,16 @@ cpsw_attach(device_t dev)
return (ENOMEM);
}
+ /* Allocate the null mbuf and pre-sync it. */
+ sc->null_mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ memset(sc->null_mbuf->m_hdr.mh_data, 0, sc->null_mbuf->m_ext.ext_size);
+ bus_dmamap_create(sc->mbuf_dtag, 0, &sc->null_mbuf_dmamap);
+ bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, sc->null_mbuf_dmamap,
+ sc->null_mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
+ bus_dmamap_sync(sc->mbuf_dtag, sc->null_mbuf_dmamap,
+ BUS_DMASYNC_PREWRITE);
+ sc->null_mbuf_paddr = segs[0].ds_addr;
+
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_softc = sc;
ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
@@ -321,11 +625,32 @@ cpsw_attach(device_t dev)
ifp->if_start = cpsw_start;
ifp->if_ioctl = cpsw_ioctl;
- ifp->if_snd.ifq_drv_maxlen = CPSW_MAX_TX_BUFFERS - 1;
+ cpsw_init_slots(sc);
+
+ /* Allocate slots to TX and RX queues. */
+ STAILQ_INIT(&sc->rx.avail);
+ STAILQ_INIT(&sc->rx.active);
+ STAILQ_INIT(&sc->tx.avail);
+ STAILQ_INIT(&sc->tx.active);
+ // For now: 128 slots to TX, rest to RX.
+ // XXX TODO: start with 32/64 and grow dynamically based on demand.
+ if (cpsw_add_slots(sc, &sc->tx, 128) || cpsw_add_slots(sc, &sc->rx, -1)) {
+ device_printf(dev, "failed to allocate dmamaps\n");
+ cpsw_detach(dev);
+ return (ENOMEM);
+ }
+ device_printf(dev, "Initial queue size TX=%d RX=%d\n",
+ sc->tx.queue_slots, sc->rx.queue_slots);
+
+ ifp->if_snd.ifq_drv_maxlen = sc->tx.queue_slots;
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
IFQ_SET_READY(&ifp->if_snd);
+ sc->tx.hdp_offset = CPSW_CPDMA_TX_HDP(0);
+ sc->rx.hdp_offset = CPSW_CPDMA_RX_HDP(0);
+
/* Get high part of MAC address from control module (mac_id0_hi) */
+ /* TODO: Get MAC ID1 as well as MAC ID0. */
ti_scm_reg_read_4(0x634, &reg);
sc->mac_addr[0] = reg & 0xFF;
sc->mac_addr[1] = (reg >> 8) & 0xFF;
@@ -338,11 +663,14 @@ cpsw_attach(device_t dev)
sc->mac_addr[5] = (reg >> 8) & 0xFF;
ether_ifattach(ifp, sc->mac_addr);
- callout_init(&sc->wd_callout, 0);
+ callout_init(&sc->watchdog.callout, 0);
/* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
/* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
- cpsw_write_4(MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+ cpsw_write_4(sc, MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+
+ /* Clear ALE */
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, 1 << 30);
/* Attach PHY(s) */
error = mii_attach(dev, &sc->miibus, ifp, cpsw_ifmedia_upd,
@@ -358,25 +686,38 @@ cpsw_attach(device_t dev)
miisc = LIST_FIRST(&sc->mii->mii_phys);
/* Select PHY and enable interrupts */
- cpsw_write_4(MDIOUSERPHYSEL0, 1 << 6 | (miisc->mii_phy & 0x1F));
-
- /* Attach interrupt handlers */
- for (i = 1; i <= CPSW_INTR_COUNT; ++i) {
- error = bus_setup_intr(dev, sc->res[i],
- INTR_TYPE_NET | INTR_MPSAFE,
- NULL, *cpsw_intrs[i - 1].handler,
- sc, &sc->ih_cookie[i - 1]);
- if (error) {
- device_printf(dev, "could not setup %s\n",
- cpsw_intrs[i].description);
- cpsw_detach(dev);
- return (error);
- }
+ cpsw_write_4(sc, MDIOUSERPHYSEL0, 1 << 6 | (miisc->mii_phy & 0x1F));
+
+ /* Note: We don't use sc->res[3] (TX interrupt) */
+ if (cpsw_attach_interrupt(sc, sc->res[1],
+ cpsw_intr_rx_thresh, "CPSW RX threshold interrupt") ||
+ cpsw_attach_interrupt(sc, sc->res[2],
+ cpsw_intr_rx, "CPSW RX interrupt") ||
+ cpsw_attach_interrupt(sc, sc->res[4],
+ cpsw_intr_misc, "CPSW misc interrupt")) {
+ cpsw_detach(dev);
+ return (ENXIO);
}
return (0);
}
+static void
+cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
+{
+ int error;
+
+ if (slot->dmamap) {
+ error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
+ KASSERT(error == 0, ("Mapping still active"));
+ slot->dmamap = NULL;
+ }
+ if (slot->mbuf) {
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ }
+}
+
static int
cpsw_detach(device_t dev)
{
@@ -389,31 +730,20 @@ cpsw_detach(device_t dev)
if (device_is_attached(dev)) {
ether_ifdetach(sc->ifp);
CPSW_GLOBAL_LOCK(sc);
- cpsw_stop_locked(sc);
+ cpsw_shutdown_locked(sc);
CPSW_GLOBAL_UNLOCK(sc);
- callout_drain(&sc->wd_callout);
+ callout_drain(&sc->watchdog.callout);
}
bus_generic_detach(dev);
device_delete_child(dev, sc->miibus);
/* Stop and release all interrupts */
- for (i = 0; i < CPSW_INTR_COUNT; ++i) {
- if (!sc->ih_cookie[i])
- continue;
-
- error = bus_teardown_intr(dev, sc->res[1 + i], sc->ih_cookie[i]);
- if (error)
- device_printf(dev, "could not release %s\n",
- cpsw_intrs[i + 1].description);
- }
+ cpsw_detach_interrupts(sc);
/* Free dmamaps and mbufs */
- for (i = 0; i < CPSW_MAX_TX_BUFFERS; i++) {
- cpsw_free_slot(sc, &sc->_tx_slots[i]);
- }
- for (i = 0; i < CPSW_MAX_RX_BUFFERS; i++) {
- cpsw_free_slot(sc, &sc->_rx_slots[i]);
+ for (i = 0; i < sizeof(sc->_slots) / sizeof(sc->_slots[0]); ++i) {
+ cpsw_free_slot(sc, &sc->_slots[i]);
}
/* Free DMA tag */
@@ -424,409 +754,323 @@ cpsw_detach(device_t dev)
bus_release_resources(dev, res_spec, sc->res);
/* Destroy mutexes */
- mtx_destroy(&sc->rx_lock);
- mtx_destroy(&sc->tx_lock);
+ mtx_destroy(&sc->rx.lock);
+ mtx_destroy(&sc->tx.lock);
return (0);
}
-static int
-cpsw_suspend(device_t dev)
+/*
+ *
+ * Init/Shutdown.
+ *
+ */
+
+static void
+cpsw_reset(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ int i;
- CPSW_DEBUGF((""));
- CPSW_GLOBAL_LOCK(sc);
- cpsw_stop_locked(sc);
- CPSW_GLOBAL_UNLOCK(sc);
- return (0);
-}
+ /* Reset RMII/RGMII wrapper. */
+ cpsw_write_4(sc, CPSW_WR_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_WR_SOFT_RESET) & 1)
+ ;
-static int
-cpsw_resume(device_t dev)
-{
- /* XXX TODO XXX */
- device_printf(dev, "%s\n", __FUNCTION__);
- return (0);
+ /* Disable TX and RX interrupts for all cores. */
+ for (i = 0; i < 3; ++i) {
+ cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_TX_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_RX_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_MISC_EN(i), 0x00);
+ }
+
+ /* Reset CPSW subsystem. */
+ cpsw_write_4(sc, CPSW_SS_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_SS_SOFT_RESET) & 1)
+ ;
+
+ /* Reset Sliver port 1 and 2 */
+ for (i = 0; i < 2; i++) {
+ /* Reset */
+ cpsw_write_4(sc, CPSW_SL_SOFT_RESET(i), 1);
+ while (cpsw_read_4(sc, CPSW_SL_SOFT_RESET(i)) & 1)
+ ;
+ }
+
+ /* Reset DMA controller. */
+ cpsw_write_4(sc, CPSW_CPDMA_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_CPDMA_SOFT_RESET) & 1)
+ ;
+
+ /* Disable TX & RX DMA */
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 0);
+
+ /* Clear all queues. */
+ for (i = 0; i < 8; i++) {
+ cpsw_write_4(sc, CPSW_CPDMA_TX_HDP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_HDP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CP(i), 0);
+ }
+
+ /* Clear all interrupt Masks */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
+ cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
}
-static int
-cpsw_shutdown(device_t dev)
+static void
+cpsw_init(void *arg)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ struct cpsw_softc *sc = arg;
CPSW_DEBUGF((""));
CPSW_GLOBAL_LOCK(sc);
- cpsw_stop_locked(sc);
+ cpsw_init_locked(arg);
CPSW_GLOBAL_UNLOCK(sc);
- return (0);
}
-static int
-cpsw_miibus_ready(struct cpsw_softc *sc)
+static void
+cpsw_init_locked(void *arg)
{
- uint32_t r, retries = CPSW_MIIBUS_RETRIES;
+ struct ifnet *ifp;
+ struct cpsw_softc *sc = arg;
+ struct cpsw_slot *slot;
+ uint32_t i;
- while (--retries) {
- r = cpsw_read_4(MDIOUSERACCESS0);
- if ((r & 1 << 31) == 0)
- return 1;
- DELAY(CPSW_MIIBUS_DELAY);
- }
- return 0;
-}
+ CPSW_DEBUGF((""));
+ ifp = sc->ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
-static int
-cpsw_miibus_readreg(device_t dev, int phy, int reg)
-{
- struct cpsw_softc *sc = device_get_softc(dev);
- uint32_t cmd, r;
+ getbinuptime(&sc->init_uptime);
- if (!cpsw_miibus_ready(sc)) {
- device_printf(dev, "MDIO not ready to read\n");
- return 0;
- }
+ /* Reset the controller. */
+ cpsw_reset(sc);
- /* Set GO, reg, phy */
- cmd = 1 << 31 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
- cpsw_write_4(MDIOUSERACCESS0, cmd);
+ /* Enable ALE */
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, 1 << 31 | 1 << 4);
- if (!cpsw_miibus_ready(sc)) {
- device_printf(dev, "MDIO timed out during read\n");
- return 0;
- }
-
- r = cpsw_read_4(MDIOUSERACCESS0);
- if((r & 1 << 29) == 0) {
- device_printf(dev, "Failed to read from PHY.\n");
- r = 0;
+ /* Init Sliver port 1 and 2 */
+ for (i = 0; i < 2; i++) {
+ /* Set Slave Mapping */
+ cpsw_write_4(sc, CPSW_SL_RX_PRI_MAP(i), 0x76543210);
+ cpsw_write_4(sc, CPSW_PORT_P_TX_PRI_MAP(i + 1), 0x33221100);
+ cpsw_write_4(sc, CPSW_SL_RX_MAXLEN(i), 0x5f2);
+ /* Set MACCONTROL for ports 0,1: IFCTL_B(16), IFCTL_A(15),
+ GMII_EN(5), FULLDUPLEX(1) */
+ /* TODO: Docs claim that IFCTL_B and IFCTL_A do the same thing? */
+ /* Huh? Docs call bit 0 "Loopback" some places, "FullDuplex" others. */
+ cpsw_write_4(sc, CPSW_SL_MACCONTROL(i), 1 << 15 | 1 << 5 | 1);
}
- return (r & 0xFFFF);
-}
-
-static int
-cpsw_miibus_writereg(device_t dev, int phy, int reg, int value)
-{
- struct cpsw_softc *sc = device_get_softc(dev);
- uint32_t cmd;
- if (!cpsw_miibus_ready(sc)) {
- device_printf(dev, "MDIO not ready to write\n");
- return 0;
- }
+ /* Set Host Port Mapping */
+ cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
+ cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
- /* Set GO, WRITE, reg, phy, and value */
- cmd = 3 << 30 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16
- | (value & 0xFFFF);
- cpsw_write_4(MDIOUSERACCESS0, cmd);
+ /* Initialize ALE: all ports set to forwarding(3), initialize addrs */
+ for (i = 0; i < 3; i++)
+ cpsw_write_4(sc, CPSW_ALE_PORTCTL(i), 3);
+ cpsw_ale_update_addresses(sc, 1);
- if (!cpsw_miibus_ready(sc)) {
- device_printf(dev, "MDIO timed out during write\n");
- return 0;
- }
+ cpsw_write_4(sc, CPSW_SS_PTYPE, 0);
- if((cpsw_read_4(MDIOUSERACCESS0) & (1 << 29)) == 0)
- device_printf(dev, "Failed to write to PHY.\n");
+ /* Enable statistics for ports 0, 1 and 2 */
+ cpsw_write_4(sc, CPSW_SS_STAT_PORT_EN, 7);
- return 0;
-}
+ /* Experiment: Turn off flow control */
+ /* This seems to fix the watchdog resets that have plagued
+ earlier versions of this driver; I'm not yet sure if there
+ are negative effects yet. */
+ cpsw_write_4(sc, CPSW_SS_FLOW_CONTROL, 0);
-static int
-cpsw_init_slot_lists(struct cpsw_softc *sc)
-{
- int i;
+ /* Make IP hdr aligned with 4 */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
- STAILQ_INIT(&sc->rx_active);
- STAILQ_INIT(&sc->rx_avail);
- STAILQ_INIT(&sc->tx_active);
- STAILQ_INIT(&sc->tx_avail);
-
- /* Put the slot descriptors onto the avail lists. */
- for (i = 0; i < CPSW_MAX_TX_BUFFERS; i++) {
- struct cpsw_slot *slot = &sc->_tx_slots[i];
- slot->index = i;
- /* XXX TODO: Remove this from here; allocate dmamaps lazily
- in the encap routine to reduce memory usage. */
- if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
- if_printf(sc->ifp, "failed to create dmamap for tx mbuf\n");
- return (ENOMEM);
- }
- STAILQ_INSERT_TAIL(&sc->tx_avail, slot, next);
- }
+ /* Initialize RX Buffer Descriptors */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), 0);
- for (i = 0; i < CPSW_MAX_RX_BUFFERS; i++) {
- struct cpsw_slot *slot = &sc->_rx_slots[i];
- slot->index = i;
- if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
- if_printf(sc->ifp, "failed to create dmamap for rx mbuf\n");
- return (ENOMEM);
- }
- STAILQ_INSERT_TAIL(&sc->rx_avail, slot, next);
- }
+ /* Enable TX & RX DMA */
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 1);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 1);
- return (0);
-}
+ /* Enable Interrupts for core 0 */
+ cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(0), 0xFF);
+ cpsw_write_4(sc, CPSW_WR_C_RX_EN(0), 0xFF);
+ cpsw_write_4(sc, CPSW_WR_C_MISC_EN(0), 0x3F);
-static void
-cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
-{
- int error;
+ /* Enable host Error Interrupt */
+ cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_SET, 3);
- if (slot->dmamap) {
- error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
- KASSERT(error == 0, ("Mapping still active"));
- slot->dmamap = NULL;
- }
- if (slot->mbuf) {
- m_freem(slot->mbuf);
- slot->mbuf = NULL;
- }
-}
+ /* Enable interrupts for RX Channel 0 */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_SET, 1);
-/*
- * Pad the packet to the minimum length for Ethernet.
- * (CPSW hardware doesn't do this for us.)
- */
-static int
-cpsw_pad(struct mbuf *m)
-{
- int padlen = ETHER_MIN_LEN - m->m_pkthdr.len;
- struct mbuf *last, *n;
+ /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
+ /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
+ cpsw_write_4(sc, MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
- if (padlen <= 0)
- return (0);
+ /* Select MII in GMII_SEL, Internal Delay mode */
+ //ti_scm_reg_write_4(0x650, 0);
- /* If there's only the packet-header and we can pad there, use it. */
- if (m->m_pkthdr.len == m->m_len && M_WRITABLE(m) &&
- M_TRAILINGSPACE(m) >= padlen) {
- last = m;
- } else {
- /*
- * Walk packet chain to find last mbuf. We will either
- * pad there, or append a new mbuf and pad it.
- */
- for (last = m; last->m_next != NULL; last = last->m_next)
- ;
- if (!(M_WRITABLE(last) && M_TRAILINGSPACE(last) >= padlen)) {
- /* Allocate new empty mbuf, pad it. Compact later. */
- MGET(n, M_NOWAIT, MT_DATA);
- if (n == NULL)
- return (ENOBUFS);
- n->m_len = 0;
- last->m_next = n;
- last = n;
- }
- }
+ /* Initialize active queues. */
+ slot = STAILQ_FIRST(&sc->tx.active);
+ if (slot != NULL)
+ cpsw_write_hdp_slot(sc, &sc->tx, slot);
+ slot = STAILQ_FIRST(&sc->rx.active);
+ if (slot != NULL)
+ cpsw_write_hdp_slot(sc, &sc->rx, slot);
+ cpsw_rx_enqueue(sc);
- /* Now zero the pad area. */
- memset(mtod(last, caddr_t) + last->m_len, 0, padlen);
- last->m_len += padlen;
- m->m_pkthdr.len += padlen;
+ /* Activate network interface */
+ sc->rx.running = 1;
+ sc->tx.running = 1;
+ sc->watchdog.timer = 0;
+ callout_reset(&sc->watchdog.callout, hz, cpsw_tick, sc);
+ sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- return (0);
}
-static void
-cpsw_start(struct ifnet *ifp)
+static int
+cpsw_shutdown(device_t dev)
{
- struct cpsw_softc *sc = ifp->if_softc;
+ struct cpsw_softc *sc = device_get_softc(dev);
- CPSW_TX_LOCK(sc);
- cpsw_start_locked(ifp);
- CPSW_TX_UNLOCK(sc);
+ CPSW_DEBUGF((""));
+ CPSW_GLOBAL_LOCK(sc);
+ cpsw_shutdown_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ return (0);
}
static void
-cpsw_start_locked(struct ifnet *ifp)
+cpsw_rx_teardown_locked(struct cpsw_softc *sc)
{
- bus_dma_segment_t seg[1];
- struct cpsw_cpdma_bd bd;
- struct cpsw_softc *sc = ifp->if_softc;
- struct cpsw_queue newslots = STAILQ_HEAD_INITIALIZER(newslots);
- struct cpsw_slot *slot, *prev_slot = NULL, *first_new_slot;
- struct mbuf *m0, *mtmp;
- int error, nsegs, enqueued = 0;
-
- CPSW_TX_LOCK_ASSERT(sc);
-
- if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING)
- return;
+ struct mbuf *received, *next;
+ int i = 0;
- /* Pull pending packets from IF queue and prep them for DMA. */
+ CPSW_DEBUGF(("starting RX teardown"));
+ cpsw_write_4(sc, CPSW_CPDMA_RX_TEARDOWN, 0);
for (;;) {
- slot = STAILQ_FIRST(&sc->tx_avail);
- if (slot == NULL) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
+ received = cpsw_rx_dequeue(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ while (received != NULL) {
+ next = received->m_nextpkt;
+ received->m_nextpkt = NULL;
+ (*sc->ifp->if_input)(sc->ifp, received);
+ received = next;
}
-
- IF_DEQUEUE(&ifp->if_snd, m0);
- if (m0 == NULL)
- break;
-
- if ((error = cpsw_pad(m0))) {
- if_printf(ifp,
- "%s: Dropping packet; could not pad\n", __func__);
- m_freem(m0);
- continue;
+ CPSW_GLOBAL_LOCK(sc);
+ if (!sc->rx.running) {
+ CPSW_DEBUGF(("finished RX teardown (%d retries)", i));
+ return;
}
-
- /* TODO: don't defragment here, queue each
- packet fragment as a separate entry. */
- mtmp = m_defrag(m0, M_NOWAIT);
- if (mtmp)
- m0 = mtmp;
-
- slot->mbuf = m0;
- /* Create mapping in DMA memory */
- error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
- m0, seg, &nsegs, BUS_DMA_NOWAIT);
- KASSERT(nsegs == 1, ("More than one segment (nsegs=%d)", nsegs));
- KASSERT(error == 0, ("DMA error (error=%d)", error));
- if (error != 0 || nsegs != 1) {
- if_printf(ifp,
- "%s: Can't load packet for DMA (nsegs=%d, error=%d), dropping packet\n",
- __func__, nsegs, error);
- bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
- m_freem(m0);
- break;
+ if (++i > 10) {
+ if_printf(sc->ifp, "Unable to cleanly shutdown receiver\n");
+ return;
}
- bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap,
- BUS_DMASYNC_PREWRITE);
-
- if (prev_slot != NULL)
- cpsw_cpdma_write_txbd_next(prev_slot->index,
- cpsw_cpdma_txbd_paddr(slot->index));
- bd.next = 0;
- bd.bufptr = seg->ds_addr;
- bd.bufoff = 0;
- bd.buflen = seg->ds_len;
- bd.pktlen = seg->ds_len;
- bd.flags = 7 << 13; /* Set OWNERSHIP, SOP, EOP */
- cpsw_cpdma_write_txbd(slot->index, &bd);
- ++enqueued;
-
- prev_slot = slot;
- STAILQ_REMOVE_HEAD(&sc->tx_avail, next);
- STAILQ_INSERT_TAIL(&newslots, slot, next);
- BPF_MTAP(ifp, m0);
+ DELAY(10);
}
+}
- if (STAILQ_EMPTY(&newslots))
- return;
+static void
+cpsw_tx_teardown_locked(struct cpsw_softc *sc)
+{
+ int i = 0;
- /* Attach the list of new buffers to the hardware TX queue. */
- prev_slot = STAILQ_LAST(&sc->tx_active, cpsw_slot, next);
- first_new_slot = STAILQ_FIRST(&newslots);
- STAILQ_CONCAT(&sc->tx_active, &newslots);
- if (prev_slot == NULL) {
- /* Start the TX queue fresh. */
- cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
- cpsw_cpdma_txbd_paddr(first_new_slot->index));
- } else {
- /* Add buffers to end of current queue. */
- cpsw_cpdma_write_txbd_next(prev_slot->index,
- cpsw_cpdma_txbd_paddr(first_new_slot->index));
- /* If underrun, restart queue. */
- if (cpsw_cpdma_read_txbd_flags(prev_slot->index) & CPDMA_BD_EOQ)
- cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
- cpsw_cpdma_txbd_paddr(first_new_slot->index));
- }
- sc->tx_enqueues += enqueued;
- sc->tx_queued += enqueued;
- if (sc->tx_queued > sc->tx_max_queued) {
- sc->tx_max_queued = sc->tx_queued;
- CPSW_DEBUGF(("New TX high water mark %d", sc->tx_queued));
+ CPSW_DEBUGF(("starting TX teardown"));
+ cpsw_write_4(sc, CPSW_CPDMA_TX_TEARDOWN, 0);
+ cpsw_tx_dequeue(sc);
+ while (sc->tx.running && ++i < 10) {
+ DELAY(10);
+ cpsw_tx_dequeue(sc);
}
+ if (sc->tx.running)
+ if_printf(sc->ifp, "Unable to cleanly shutdown transmitter\n");
+ CPSW_DEBUGF(("finished TX teardown (%d retries, %d idle buffers)",
+ i, sc->tx.active_queue_len));
}
static void
-cpsw_stop_locked(struct cpsw_softc *sc)
+cpsw_shutdown_locked(struct cpsw_softc *sc)
{
struct ifnet *ifp;
- int i;
CPSW_DEBUGF((""));
-
CPSW_GLOBAL_LOCK_ASSERT(sc);
-
ifp = sc->ifp;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
/* Disable interface */
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
- /* Stop tick engine */
- callout_stop(&sc->wd_callout);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- /* Wait for hardware to clear pending ops. */
- CPSW_GLOBAL_UNLOCK(sc);
- CPSW_DEBUGF(("starting RX and TX teardown"));
- cpsw_write_4(CPSW_CPDMA_RX_TEARDOWN, 0);
- cpsw_write_4(CPSW_CPDMA_TX_TEARDOWN, 0);
- i = 0;
- cpsw_intr_rx(sc); // Try clearing without delay.
- cpsw_intr_tx(sc);
- while (sc->rx_running || sc->tx_running) {
- DELAY(10);
- cpsw_intr_rx(sc);
- cpsw_intr_tx(sc);
- ++i;
- }
- CPSW_DEBUGF(("finished RX and TX teardown (%d tries)", i));
- CPSW_GLOBAL_LOCK(sc);
+ /* Stop ticker */
+ callout_stop(&sc->watchdog.callout);
- /* All slots are now available */
- STAILQ_CONCAT(&sc->rx_avail, &sc->rx_active);
- STAILQ_CONCAT(&sc->tx_avail, &sc->tx_active);
- CPSW_DEBUGF(("%d buffers dropped at TX reset", sc->tx_queued));
- sc->tx_queued = 0;
+ /* Tear down the RX/TX queues. */
+ cpsw_rx_teardown_locked(sc);
+ cpsw_tx_teardown_locked(sc);
- /* Reset writer */
- cpsw_write_4(CPSW_WR_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_WR_SOFT_RESET) & 1)
- ;
+ /* Capture stats before we reset controller. */
+ cpsw_stats_collect(sc);
- /* Reset SS */
- cpsw_write_4(CPSW_SS_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_SS_SOFT_RESET) & 1)
- ;
+ cpsw_reset(sc);
+}
- /* Reset Sliver port 1 and 2 */
- for (i = 0; i < 2; i++) {
- /* Reset */
- cpsw_write_4(CPSW_SL_SOFT_RESET(i), 1);
- while (cpsw_read_4(CPSW_SL_SOFT_RESET(i)) & 1)
- ;
- }
+/*
+ * Suspend/Resume.
+ */
- /* Reset CPDMA */
- cpsw_write_4(CPSW_CPDMA_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_CPDMA_SOFT_RESET) & 1)
- ;
+static int
+cpsw_suspend(device_t dev)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
- /* Disable TX & RX DMA */
- cpsw_write_4(CPSW_CPDMA_TX_CONTROL, 0);
- cpsw_write_4(CPSW_CPDMA_RX_CONTROL, 0);
+ CPSW_DEBUGF((""));
+ CPSW_GLOBAL_LOCK(sc);
+ cpsw_shutdown_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ return (0);
+}
- /* Disable TX and RX interrupts for all cores. */
- for (i = 0; i < 3; ++i) {
- cpsw_write_4(CPSW_WR_C_TX_EN(i), 0x00);
- cpsw_write_4(CPSW_WR_C_RX_EN(i), 0x00);
- cpsw_write_4(CPSW_WR_C_MISC_EN(i), 0x00);
- }
+static int
+cpsw_resume(device_t dev)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
- /* Clear all interrupt Masks */
- cpsw_write_4(CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
- cpsw_write_4(CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
+ CPSW_DEBUGF(("UNIMPLEMENTED"));
+ return (0);
}
+/*
+ *
+ * IOCTL
+ *
+ */
+
static void
cpsw_set_promisc(struct cpsw_softc *sc, int set)
{
+ /*
+ * Enabling promiscuous mode requires two bits of work: First,
+ * ALE_BYPASS needs to be enabled. That disables the ALE
+ * forwarding logic and causes every packet to be sent to the
+ * host port. That makes us promiscuous wrt received packets.
+ *
+ * With ALE forwarding disabled, the transmitter needs to set
+ * an explicit output port on every packet to route it to the
+ * correct egress. This should be doable for systems such as
+ * BeagleBone where only one egress port is actually wired to
+ * a PHY. If you have both egress ports wired up, life gets a
+ * lot more interesting.
+ *
+ * Hmmm.... NetBSD driver uses ALE_BYPASS always and doesn't
+ * seem to set explicit egress ports. Does that mean they
+ * are always promiscuous?
+ */
if (set) {
printf("Promiscuous mode unimplemented\n");
}
@@ -848,7 +1092,6 @@ cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
int error;
uint32_t changed;
- CPSW_DEBUGF(("command=0x%lx", command));
error = 0;
switch (command) {
@@ -865,118 +1108,175 @@ cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
cpsw_set_allmulti(sc,
ifp->if_flags & IFF_ALLMULTI);
} else {
- CPSW_DEBUGF(("SIOCSIFFLAGS: UP but not RUNNING"));
+ CPSW_DEBUGF(("SIOCSIFFLAGS: UP but not RUNNING; starting up"));
cpsw_init_locked(sc);
}
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- CPSW_DEBUGF(("SIOCSIFFLAGS: not UP but RUNNING"));
- cpsw_stop_locked(sc);
+ CPSW_DEBUGF(("SIOCSIFFLAGS: not UP but RUNNING; shutting down"));
+ cpsw_shutdown_locked(sc);
}
sc->cpsw_if_flags = ifp->if_flags;
CPSW_GLOBAL_UNLOCK(sc);
break;
case SIOCADDMULTI:
- CPSW_DEBUGF(("SIOCADDMULTI unimplemented"));
+ cpsw_ale_update_addresses(sc, 0);
break;
case SIOCDELMULTI:
- CPSW_DEBUGF(("SIOCDELMULTI unimplemented"));
+ /* Ugh. DELMULTI doesn't provide the specific address
+ being removed, so the best we can do is remove
+ everything and rebuild it all. */
+ cpsw_ale_update_addresses(sc, 1);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command);
break;
default:
- CPSW_DEBUGF(("ether ioctl"));
error = ether_ioctl(ifp, command, data);
}
return (error);
}
-static void
-cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+/*
+ *
+ * MIIBUS
+ *
+ */
+static int
+cpsw_miibus_ready(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = ifp->if_softc;
- struct mii_data *mii;
+ uint32_t r, retries = CPSW_MIIBUS_RETRIES;
- CPSW_DEBUGF((""));
- CPSW_TX_LOCK(sc);
+ while (--retries) {
+ r = cpsw_read_4(sc, MDIOUSERACCESS0);
+ if ((r & 1 << 31) == 0)
+ return 1;
+ DELAY(CPSW_MIIBUS_DELAY);
+ }
+ return 0;
+}
- mii = sc->mii;
- mii_pollstat(mii);
+static int
+cpsw_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
+ uint32_t cmd, r;
- ifmr->ifm_active = mii->mii_media_active;
- ifmr->ifm_status = mii->mii_media_status;
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO not ready to read\n");
+ return 0;
+ }
- CPSW_TX_UNLOCK(sc);
-}
+ /* Set GO, reg, phy */
+ cmd = 1 << 31 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
+ cpsw_write_4(sc, MDIOUSERACCESS0, cmd);
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO timed out during read\n");
+ return 0;
+ }
+
+ r = cpsw_read_4(sc, MDIOUSERACCESS0);
+ if((r & 1 << 29) == 0) {
+ device_printf(dev, "Failed to read from PHY.\n");
+ r = 0;
+ }
+ return (r & 0xFFFF);
+}
static int
-cpsw_ifmedia_upd(struct ifnet *ifp)
+cpsw_miibus_writereg(device_t dev, int phy, int reg, int value)
{
- struct cpsw_softc *sc = ifp->if_softc;
+ struct cpsw_softc *sc = device_get_softc(dev);
+ uint32_t cmd;
- CPSW_DEBUGF((""));
- if (ifp->if_flags & IFF_UP) {
- CPSW_GLOBAL_LOCK(sc);
- sc->cpsw_media_status = sc->mii->mii_media.ifm_media;
- mii_mediachg(sc->mii);
- cpsw_init_locked(sc);
- CPSW_GLOBAL_UNLOCK(sc);
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO not ready to write\n");
+ return 0;
}
- return (0);
-}
+ /* Set GO, WRITE, reg, phy, and value */
+ cmd = 3 << 30 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16
+ | (value & 0xFFFF);
+ cpsw_write_4(sc, MDIOUSERACCESS0, cmd);
-static void
-cpsw_intr_rx_thresh(void *arg)
-{
- struct cpsw_softc *sc = arg;
- CPSW_DEBUGF((""));
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO timed out during write\n");
+ return 0;
+ }
+
+ if((cpsw_read_4(sc, MDIOUSERACCESS0) & (1 << 29)) == 0)
+ device_printf(dev, "Failed to write to PHY.\n");
+
+ return 0;
}
+/*
+ *
+ * Transmit/Receive Packets.
+ *
+ */
+
+
static void
cpsw_intr_rx(void *arg)
{
struct cpsw_softc *sc = arg;
+ struct mbuf *received, *next;
CPSW_RX_LOCK(sc);
- cpsw_intr_rx_locked(arg);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
+ received = cpsw_rx_dequeue(sc);
+ cpsw_rx_enqueue(sc);
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
CPSW_RX_UNLOCK(sc);
+
+ while (received != NULL) {
+ next = received->m_nextpkt;
+ received->m_nextpkt = NULL;
+ (*sc->ifp->if_input)(sc->ifp, received);
+ received = next;
+ }
}
-static void
-cpsw_intr_rx_locked(void *arg)
+static struct mbuf *
+cpsw_rx_dequeue(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = arg;
struct cpsw_cpdma_bd bd;
- struct cpsw_slot *slot, *last_slot = NULL;
+ struct cpsw_slot *slot;
struct ifnet *ifp;
+ struct mbuf *mb_head, *mb_tail;
+ int removed = 0;
ifp = sc->ifp;
- if (!sc->rx_running)
- return;
+ mb_head = mb_tail = NULL;
/* Pull completed packets off hardware RX queue. */
- slot = STAILQ_FIRST(&sc->rx_active);
- while (slot != NULL) {
- cpsw_cpdma_read_rxbd(slot->index, &bd);
+ while ((slot = STAILQ_FIRST(&sc->rx.active)) != NULL) {
+ cpsw_cpdma_read_bd(sc, slot, &bd);
if (bd.flags & CPDMA_BD_OWNER)
break; /* Still in use by hardware */
+ CPSW_DEBUGF(("Removing received packet from RX queue"));
+ ++removed;
+ STAILQ_REMOVE_HEAD(&sc->rx.active, next);
+ STAILQ_INSERT_TAIL(&sc->rx.avail, slot, next);
+
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+
if (bd.flags & CPDMA_BD_TDOWNCMPLT) {
CPSW_DEBUGF(("RX teardown in progress"));
- cpsw_write_4(CPSW_CPDMA_RX_CP(0), 0xfffffffc);
- sc->rx_running = 0;
- return;
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ cpsw_write_cp(sc, &sc->rx, 0xfffffffc);
+ sc->rx.running = 0;
+ break;
}
- bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ cpsw_write_cp_slot(sc, &sc->rx, slot);
- /* Fill mbuf */
+ /* Set up mbuf */
/* TODO: track SOP/EOP bits to assemble a full mbuf
out of received fragments. */
slot->mbuf->m_hdr.mh_data += bd.bufoff;
@@ -984,6 +1284,7 @@ cpsw_intr_rx_locked(void *arg)
slot->mbuf->m_pkthdr.len = bd.pktlen - 4;
slot->mbuf->m_flags |= M_PKTHDR;
slot->mbuf->m_pkthdr.rcvif = ifp;
+ slot->mbuf->m_nextpkt = NULL;
if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
/* check for valid CRC by looking into pkt_err[5:4] */
@@ -994,64 +1295,60 @@ cpsw_intr_rx_locked(void *arg)
}
}
- /* Handover packet */
- CPSW_RX_UNLOCK(sc);
- (*ifp->if_input)(ifp, slot->mbuf);
+ /* Add mbuf to packet list to be returned. */
+ if (mb_tail) {
+ mb_tail->m_nextpkt = slot->mbuf;
+ } else {
+ mb_head = slot->mbuf;
+ }
+ mb_tail = slot->mbuf;
slot->mbuf = NULL;
- CPSW_RX_LOCK(sc);
-
- last_slot = slot;
- STAILQ_REMOVE_HEAD(&sc->rx_active, next);
- STAILQ_INSERT_TAIL(&sc->rx_avail, slot, next);
- slot = STAILQ_FIRST(&sc->rx_active);
}
- /* Tell hardware last slot we processed. */
- if (last_slot)
- cpsw_write_4(CPSW_CPDMA_RX_CP(0),
- cpsw_cpdma_rxbd_paddr(last_slot->index));
-
- /* Repopulate hardware RX queue. */
- cpsw_fill_rx_queue_locked(sc);
+ if (removed != 0) {
+ sc->rx.queue_removes += removed;
+ sc->rx.active_queue_len -= removed;
+ sc->rx.avail_queue_len += removed;
+ if (sc->rx.avail_queue_len > sc->rx.max_avail_queue_len)
+ sc->rx.max_avail_queue_len = sc->rx.avail_queue_len;
+ }
+ return (mb_head);
}
static void
-cpsw_fill_rx_queue_locked(struct cpsw_softc *sc)
+cpsw_rx_enqueue(struct cpsw_softc *sc)
{
bus_dma_segment_t seg[1];
- struct cpsw_queue tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
struct cpsw_cpdma_bd bd;
- struct cpsw_slot *slot, *prev_slot, *next_slot;
- int error, nsegs;
+ struct ifnet *ifp = sc->ifp;
+ struct cpsw_slots tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
+ struct cpsw_slot *slot, *prev_slot = NULL;
+ struct cpsw_slot *last_old_slot, *first_new_slot;
+ int error, nsegs, added = 0;
- /* Try to allocate new mbufs. */
- STAILQ_FOREACH(slot, &sc->rx_avail, next) {
- if (slot->mbuf != NULL)
- continue;
- slot->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ /* Register new mbufs with hardware. */
+ while ((slot = STAILQ_FIRST(&sc->rx.avail)) != NULL) {
if (slot->mbuf == NULL) {
- if_printf(sc->ifp, "Unable to fill RX queue\n");
- break;
+ slot->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (slot->mbuf == NULL) {
+ if_printf(sc->ifp, "Unable to fill RX queue\n");
+ break;
+ }
+ slot->mbuf->m_len =
+ slot->mbuf->m_pkthdr.len =
+ slot->mbuf->m_ext.ext_size;
}
- slot->mbuf->m_len = slot->mbuf->m_pkthdr.len = slot->mbuf->m_ext.ext_size;
- }
-
- /* Register new mbufs with hardware. */
- prev_slot = NULL;
- while (!STAILQ_EMPTY(&sc->rx_avail)) {
- slot = STAILQ_FIRST(&sc->rx_avail);
- if (slot->mbuf == NULL)
- break;
error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
slot->mbuf, seg, &nsegs, BUS_DMA_NOWAIT);
KASSERT(nsegs == 1, ("More than one segment (nsegs=%d)", nsegs));
KASSERT(error == 0, ("DMA error (error=%d)", error));
- if (nsegs != 1 || error) {
- if_printf(sc->ifp,
+ if (error != 0 || nsegs != 1) {
+ if_printf(ifp,
"%s: Can't prep RX buf for DMA (nsegs=%d, error=%d)\n",
__func__, nsegs, error);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
m_freem(slot->mbuf);
slot->mbuf = NULL;
break;
@@ -1062,410 +1359,563 @@ cpsw_fill_rx_queue_locked(struct cpsw_softc *sc)
/* Create and submit new rx descriptor*/
bd.next = 0;
bd.bufptr = seg->ds_addr;
- bd.buflen = MCLBYTES-1;
- bd.bufoff = 2; /* make IP hdr aligned with 4 */
- bd.pktlen = 0;
+ bd.bufoff = 0;
+ bd.buflen = MCLBYTES - 1;
+ bd.pktlen = bd.buflen;
bd.flags = CPDMA_BD_OWNER;
- cpsw_cpdma_write_rxbd(slot->index, &bd);
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ ++added;
- if (prev_slot) {
- cpsw_cpdma_write_rxbd_next(prev_slot->index,
- cpsw_cpdma_rxbd_paddr(slot->index));
- }
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
prev_slot = slot;
- STAILQ_REMOVE_HEAD(&sc->rx_avail, next);
+ STAILQ_REMOVE_HEAD(&sc->rx.avail, next);
+ sc->rx.avail_queue_len--;
STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
}
+ if (added == 0)
+ return;
+
+ CPSW_DEBUGF(("Adding %d buffers to RX queue", added));
+
/* Link new entries to hardware RX queue. */
- prev_slot = STAILQ_LAST(&sc->rx_active, cpsw_slot, next);
- next_slot = STAILQ_FIRST(&tmpqueue);
- if (next_slot == NULL) {
+ last_old_slot = STAILQ_LAST(&sc->rx.active, cpsw_slot, next);
+ first_new_slot = STAILQ_FIRST(&tmpqueue);
+ STAILQ_CONCAT(&sc->rx.active, &tmpqueue);
+ if (first_new_slot == NULL) {
return;
- } else if (prev_slot == NULL) {
- /* Start a fresh RX queue. */
- cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
- cpsw_cpdma_rxbd_paddr(next_slot->index));
+ } else if (last_old_slot == NULL) {
+ /* Start a fresh queue. */
+ cpsw_write_hdp_slot(sc, &sc->rx, first_new_slot);
} else {
/* Add buffers to end of current queue. */
- cpsw_cpdma_write_rxbd_next(prev_slot->index,
- cpsw_cpdma_rxbd_paddr(next_slot->index));
+ cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
/* If underrun, restart queue. */
- if (cpsw_cpdma_read_rxbd_flags(prev_slot->index) & CPDMA_BD_EOQ) {
- cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
- cpsw_cpdma_rxbd_paddr(next_slot->index));
+ if (cpsw_cpdma_read_bd_flags(sc, last_old_slot) & CPDMA_BD_EOQ) {
+ cpsw_write_hdp_slot(sc, &sc->rx, first_new_slot);
}
}
- STAILQ_CONCAT(&sc->rx_active, &tmpqueue);
+ sc->rx.queue_adds += added;
+ sc->rx.active_queue_len += added;
+ if (sc->rx.active_queue_len > sc->rx.max_active_queue_len) {
+ sc->rx.max_active_queue_len = sc->rx.active_queue_len;
+ }
}
static void
-cpsw_intr_tx(void *arg)
+cpsw_start(struct ifnet *ifp)
{
- struct cpsw_softc *sc = arg;
+ struct cpsw_softc *sc = ifp->if_softc;
+
CPSW_TX_LOCK(sc);
- cpsw_intr_tx_locked(arg);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 2);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && sc->tx.running) {
+ cpsw_tx_enqueue(sc);
+ cpsw_tx_dequeue(sc);
+ }
CPSW_TX_UNLOCK(sc);
}
static void
-cpsw_intr_tx_locked(void *arg)
+cpsw_tx_enqueue(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = arg;
- struct cpsw_slot *slot, *last_slot = NULL;
- uint32_t flags, last_flags = 0, retires = 0;
+ bus_dma_segment_t segs[CPSW_TXFRAGS];
+ struct cpsw_cpdma_bd bd;
+ struct cpsw_slots tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
+ struct cpsw_slot *slot, *prev_slot = NULL;
+ struct cpsw_slot *last_old_slot, *first_new_slot;
+ struct mbuf *m0;
+ int error, nsegs, seg, added = 0, padlen;
+
+ /* Pull pending packets from IF queue and prep them for DMA. */
+ while ((slot = STAILQ_FIRST(&sc->tx.avail)) != NULL) {
+ IF_DEQUEUE(&sc->ifp->if_snd, m0);
+ if (m0 == NULL)
+ break;
+
+ slot->mbuf = m0;
+ padlen = ETHER_MIN_LEN - slot->mbuf->m_pkthdr.len;
+ if (padlen < 0)
+ padlen = 0;
+
+ /* Create mapping in DMA memory */
+ error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
+ slot->mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
+ /* If the packet is too fragmented, try to simplify. */
+ if (error == EFBIG ||
+ (error == 0 &&
+ nsegs + (padlen > 0 ? 1 : 0) > sc->tx.avail_queue_len)) {
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ if (padlen > 0) /* May as well add padding. */
+ m_append(slot->mbuf, padlen,
+ sc->null_mbuf->m_hdr.mh_data);
+ m0 = m_defrag(slot->mbuf, M_NOWAIT);
+ if (m0 == NULL) {
+ if_printf(sc->ifp,
+ "Can't defragment packet; dropping\n");
+ m_freem(slot->mbuf);
+ } else {
+ CPSW_DEBUGF(("Requeueing defragmented packet"));
+ IF_PREPEND(&sc->ifp->if_snd, m0);
+ }
+ slot->mbuf = NULL;
+ continue;
+ }
+ if (error != 0) {
+ if_printf(sc->ifp,
+ "%s: Can't setup DMA (error=%d), dropping packet\n",
+ __func__, error);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ break;
+ }
+
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap,
+ BUS_DMASYNC_PREWRITE);
+
+
+ CPSW_DEBUGF(("Queueing TX packet: %d segments + %d pad bytes",
+ nsegs, padlen));
+
+ /* If there is only one segment, the for() loop
+ * gets skipped and the single buffer gets set up
+ * as both SOP and EOP. */
+ /* Start by setting up the first buffer */
+ bd.next = 0;
+ bd.bufptr = segs[0].ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = segs[0].ds_len;
+ bd.pktlen = m_length(slot->mbuf, NULL) + padlen;
+ bd.flags = CPDMA_BD_SOP | CPDMA_BD_OWNER;
+ for (seg = 1; seg < nsegs; ++seg) {
+ /* Save the previous buffer (which isn't EOP) */
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+ slot = STAILQ_FIRST(&sc->tx.avail);
+
+ /* Setup next buffer (which isn't SOP) */
+ bd.next = 0;
+ bd.bufptr = segs[seg].ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = segs[seg].ds_len;
+ bd.pktlen = 0;
+ bd.flags = CPDMA_BD_OWNER;
+ }
+ /* Save the final buffer. */
+ if (padlen <= 0)
+ bd.flags |= CPDMA_BD_EOP;
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+
+ if (padlen > 0) {
+ slot = STAILQ_FIRST(&sc->tx.avail);
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+
+ /* Setup buffer of null pad bytes (definitely EOP) */
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ bd.next = 0;
+ bd.bufptr = sc->null_mbuf_paddr;
+ bd.bufoff = 0;
+ bd.buflen = padlen;
+ bd.pktlen = 0;
+ bd.flags = CPDMA_BD_EOP | CPDMA_BD_OWNER;
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ ++nsegs;
+ }
- if (!sc->tx_running)
+ if (nsegs > sc->tx.longest_chain)
+ sc->tx.longest_chain = nsegs;
+
+ // TODO: Should we defer the BPF tap until
+ // after all packets are queued?
+ BPF_MTAP(sc->ifp, m0);
+ }
+
+ /* Attach the list of new buffers to the hardware TX queue. */
+ last_old_slot = STAILQ_LAST(&sc->tx.active, cpsw_slot, next);
+ first_new_slot = STAILQ_FIRST(&tmpqueue);
+ STAILQ_CONCAT(&sc->tx.active, &tmpqueue);
+ if (first_new_slot == NULL) {
return;
+ } else if (last_old_slot == NULL) {
+ /* Start a fresh queue. */
+ cpsw_write_hdp_slot(sc, &sc->tx, first_new_slot);
+ } else {
+ /* Add buffers to end of current queue. */
+ cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
+ /* If underrun, restart queue. */
+ if (cpsw_cpdma_read_bd_flags(sc, last_old_slot) & CPDMA_BD_EOQ) {
+ cpsw_write_hdp_slot(sc, &sc->tx, first_new_slot);
+ }
+ }
+ sc->tx.queue_adds += added;
+ sc->tx.active_queue_len += added;
+ if (sc->tx.active_queue_len > sc->tx.max_active_queue_len) {
+ sc->tx.max_active_queue_len = sc->tx.active_queue_len;
+ }
+}
+
+static int
+cpsw_tx_dequeue(struct cpsw_softc *sc)
+{
+ struct cpsw_slot *slot, *last_removed_slot = NULL;
+ uint32_t flags, removed = 0;
- slot = STAILQ_FIRST(&sc->tx_active);
- if (slot == NULL &&
- cpsw_read_4(CPSW_CPDMA_TX_CP(0)) == 0xfffffffc) {
+ slot = STAILQ_FIRST(&sc->tx.active);
+ if (slot == NULL && cpsw_read_cp(sc, &sc->tx) == 0xfffffffc) {
CPSW_DEBUGF(("TX teardown of an empty queue"));
- cpsw_write_4(CPSW_CPDMA_TX_CP(0), 0xfffffffc);
- sc->tx_running = 0;
- return;
+ cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
+ sc->tx.running = 0;
+ return (0);
}
- /* Pull completed segments off the hardware TX queue. */
+ /* Pull completed buffers off the hardware TX queue. */
while (slot != NULL) {
- flags = cpsw_cpdma_read_txbd_flags(slot->index);
+ flags = cpsw_cpdma_read_bd_flags(sc, slot);
if (flags & CPDMA_BD_OWNER)
- break; /* Hardware is still using this. */
-
- if (flags & CPDMA_BD_TDOWNCMPLT) {
- CPSW_DEBUGF(("TX teardown in progress"));
- cpsw_write_4(CPSW_CPDMA_TX_CP(0), 0xfffffffc);
- sc->tx_running = 0;
- return;
- }
+ break; /* Hardware is still using this packet. */
- /* Release dmamap, free mbuf. */
- bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap,
- BUS_DMASYNC_POSTWRITE);
+ CPSW_DEBUGF(("TX removing completed packet"));
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
m_freem(slot->mbuf);
slot->mbuf = NULL;
- STAILQ_REMOVE_HEAD(&sc->tx_active, next);
- STAILQ_INSERT_TAIL(&sc->tx_avail, slot, next);
- sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ /* Dequeue any additional buffers used by this packet. */
+ while (slot != NULL && slot->mbuf == NULL) {
+ STAILQ_REMOVE_HEAD(&sc->tx.active, next);
+ STAILQ_INSERT_TAIL(&sc->tx.avail, slot, next);
+ ++removed;
+ last_removed_slot = slot;
+ slot = STAILQ_FIRST(&sc->tx.active);
+ }
- last_slot = slot;
- last_flags = flags;
- ++retires;
- slot = STAILQ_FIRST(&sc->tx_active);
+ /* TearDown complete is only marked on the SOP for the packet. */
+ if (flags & CPDMA_BD_TDOWNCMPLT) {
+ CPSW_DEBUGF(("TX teardown in progress"));
+ cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
+ // TODO: Increment a count of dropped TX packets
+ sc->tx.running = 0;
+ break;
+ }
}
- if (retires != 0) {
- /* Tell hardware the last item we dequeued. */
- cpsw_write_4(CPSW_CPDMA_TX_CP(0),
- cpsw_cpdma_txbd_paddr(last_slot->index));
- sc->tx_retires += retires;
- sc->tx_queued -= retires;
+ if (removed != 0) {
+ cpsw_write_cp_slot(sc, &sc->tx, last_removed_slot);
+ sc->tx.queue_removes += removed;
+ sc->tx.active_queue_len -= removed;
+ sc->tx.avail_queue_len += removed;
+ if (sc->tx.avail_queue_len > sc->tx.max_avail_queue_len)
+ sc->tx.max_avail_queue_len = sc->tx.avail_queue_len;
}
+ return (removed);
}
+/*
+ *
+ * Miscellaneous interrupts.
+ *
+ */
+
static void
-cpsw_intr_misc(void *arg)
+cpsw_intr_rx_thresh(void *arg)
{
struct cpsw_softc *sc = arg;
- uint32_t stat = cpsw_read_4(CPSW_WR_C_MISC_STAT(0));
+ uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_RX_THRESH_STAT(0));
CPSW_DEBUGF(("stat=%x", stat));
- /* EOI_RX_PULSE */
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 0);
}
static void
-cpsw_tick(void *msc)
+cpsw_intr_misc_host_error(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = msc;
+ uint32_t intstat;
+ uint32_t dmastat;
+ int txerr, rxerr, txchan, rxchan;
+
+ printf("\n\n");
+ device_printf(sc->dev,
+ "HOST ERROR: PROGRAMMING ERROR DETECTED BY HARDWARE\n");
+ printf("\n\n");
+ intstat = cpsw_read_4(sc, CPSW_CPDMA_DMA_INTSTAT_MASKED);
+ device_printf(sc->dev, "CPSW_CPDMA_DMA_INTSTAT_MASKED=0x%x\n", intstat);
+ dmastat = cpsw_read_4(sc, CPSW_CPDMA_DMASTATUS);
+ device_printf(sc->dev, "CPSW_CPDMA_DMASTATUS=0x%x\n", dmastat);
+
+ txerr = (dmastat >> 20) & 15;
+ txchan = (dmastat >> 16) & 7;
+ rxerr = (dmastat >> 12) & 15;
+ rxchan = (dmastat >> 8) & 7;
+
+ switch (txerr) {
+ case 0: break;
+ case 1: printf("SOP error on TX channel %d\n", txchan);
+ break;
+ case 2: printf("Ownership bit not set on SOP buffer on TX channel %d\n", txchan);
+ break;
+ case 3: printf("Zero Next Buffer but not EOP on TX channel %d\n", txchan);
+ break;
+ case 4: printf("Zero Buffer Pointer on TX channel %d\n", txchan);
+ break;
+ case 5: printf("Zero Buffer Length on TX channel %d\n", txchan);
+ break;
+ case 6: printf("Packet length error on TX channel %d\n", txchan);
+ break;
+ default: printf("Unknown error on TX channel %d\n", txchan);
+ break;
+ }
- /* Check for TX timeout */
- cpsw_tx_watchdog(sc);
+ if (txerr != 0) {
+ printf("CPSW_CPDMA_TX%d_HDP=0x%x\n",
+ txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_HDP(txchan)));
+ printf("CPSW_CPDMA_TX%d_CP=0x%x\n",
+ txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_CP(txchan)));
+ cpsw_dump_queue(sc, &sc->tx.active);
+ }
- mii_tick(sc->mii);
+ switch (rxerr) {
+ case 0: break;
+ case 2: printf("Ownership bit not set on RX channel %d\n", rxchan);
+ break;
+ case 4: printf("Zero Buffer Pointer on RX channel %d\n", rxchan);
+ break;
+ case 5: printf("Zero Buffer Length on RX channel %d\n", rxchan);
+ break;
+ case 6: printf("Buffer offset too big on RX channel %d\n", rxchan);
+ break;
+ default: printf("Unknown RX error on RX channel %d\n", rxchan);
+ break;
+ }
- /* Check for media type change */
- if(sc->cpsw_media_status != sc->mii->mii_media.ifm_media) {
- printf("%s: media type changed (ifm_media=%x)\n", __func__,
- sc->mii->mii_media.ifm_media);
- cpsw_ifmedia_upd(sc->ifp);
+ if (rxerr != 0) {
+ printf("CPSW_CPDMA_RX%d_HDP=0x%x\n",
+ rxchan, cpsw_read_4(sc,CPSW_CPDMA_RX_HDP(rxchan)));
+ printf("CPSW_CPDMA_RX%d_CP=0x%x\n",
+ rxchan, cpsw_read_4(sc, CPSW_CPDMA_RX_CP(rxchan)));
+ cpsw_dump_queue(sc, &sc->rx.active);
}
- /* Schedule another timeout one second from now */
- callout_reset(&sc->wd_callout, hz, cpsw_tick, sc);
-}
+ printf("\nALE Table\n");
+ cpsw_ale_dump_table(sc);
-static void
-cpsw_tx_watchdog(struct cpsw_softc *sc)
-{
- struct ifnet *ifp = sc->ifp;
+ // XXX do something useful here??
+ panic("CPSW HOST ERROR INTERRUPT");
- CPSW_GLOBAL_LOCK(sc);
- if (sc->tx_retires > sc->tx_retires_at_last_tick) {
- sc->tx_wd_timer = 0; /* Stuff got sent. */
- } else if (sc->tx_queued == 0) {
- sc->tx_wd_timer = 0; /* Nothing to send. */
- } else {
- /* There was something to send but we didn't. */
- ++sc->tx_wd_timer;
- if (sc->tx_wd_timer > 3) {
- sc->tx_wd_timer = 0;
- ifp->if_oerrors++;
- if_printf(ifp, "watchdog timeout\n");
- cpsw_stop_locked(sc);
- cpsw_init_locked(sc);
- CPSW_DEBUGF(("watchdog reset completed\n"));
- }
- }
- sc->tx_retires_at_last_tick = sc->tx_retires;
- CPSW_GLOBAL_UNLOCK(sc);
+ // Suppress this interrupt in the future.
+ cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_CLEAR, intstat);
+ printf("XXX HOST ERROR INTERRUPT SUPPRESSED\n");
+ // The watchdog will probably reset the controller
+ // in a little while. It will probably fail again.
}
static void
-cpsw_init(void *arg)
+cpsw_intr_misc(void *arg)
{
struct cpsw_softc *sc = arg;
-
- CPSW_DEBUGF((""));
- CPSW_GLOBAL_LOCK(sc);
- cpsw_init_locked(arg);
- CPSW_GLOBAL_UNLOCK(sc);
+ uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_MISC_STAT(0));
+
+ if (stat & 16)
+ CPSW_DEBUGF(("Time sync event interrupt unimplemented"));
+ if (stat & 8)
+ cpsw_stats_collect(sc);
+ if (stat & 4)
+ cpsw_intr_misc_host_error(sc);
+ if (stat & 2)
+ CPSW_DEBUGF(("MDIO link change interrupt unimplemented"));
+ if (stat & 1)
+ CPSW_DEBUGF(("MDIO operation completed interrupt unimplemented"));
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
}
-int once = 1;
+/*
+ *
+ * Periodic Checks and Watchdog.
+ *
+ */
static void
-cpsw_init_locked(void *arg)
+cpsw_tick(void *msc)
{
- struct ifnet *ifp;
- struct cpsw_softc *sc = arg;
- uint8_t broadcast_address[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- uint32_t i;
-
- CPSW_DEBUGF((""));
- ifp = sc->ifp;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
- return;
-
- /* Reset writer */
- cpsw_write_4(CPSW_WR_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_WR_SOFT_RESET) & 1)
- ;
-
- /* Reset SS */
- cpsw_write_4(CPSW_SS_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_SS_SOFT_RESET) & 1)
- ;
+ struct cpsw_softc *sc = msc;
- /* Clear table (30) and enable ALE(31) */
- if (once)
- cpsw_write_4(CPSW_ALE_CONTROL, 3 << 30);
- else
- cpsw_write_4(CPSW_ALE_CONTROL, 1 << 31);
- once = 0; // FIXME
+ /* Check for TX timeout */
+ cpsw_tx_watchdog(sc);
- /* Reset and init Sliver port 1 and 2 */
- for (i = 0; i < 2; i++) {
- /* Reset */
- cpsw_write_4(CPSW_SL_SOFT_RESET(i), 1);
- while (cpsw_read_4(CPSW_SL_SOFT_RESET(i)) & 1)
- ;
- /* Set Slave Mapping */
- cpsw_write_4(CPSW_SL_RX_PRI_MAP(i), 0x76543210);
- cpsw_write_4(CPSW_PORT_P_TX_PRI_MAP(i + 1), 0x33221100);
- cpsw_write_4(CPSW_SL_RX_MAXLEN(i), 0x5f2);
- /* Set MAC Address */
- cpsw_write_4(CPSW_PORT_P_SA_HI(i + 1),
- sc->mac_addr[3] << 24 |
- sc->mac_addr[2] << 16 |
- sc->mac_addr[1] << 8 |
- sc->mac_addr[0]);
- cpsw_write_4(CPSW_PORT_P_SA_LO(i+1),
- sc->mac_addr[5] << 8 |
- sc->mac_addr[4]);
-
- /* Set MACCONTROL for ports 0,1: FULLDUPLEX(1), GMII_EN(5),
- IFCTL_A(15), IFCTL_B(16) FIXME */
- cpsw_write_4(CPSW_SL_MACCONTROL(i), 1 << 15 | 1 << 5 | 1);
-
- /* Set ALE port to forwarding(3) */
- cpsw_write_4(CPSW_ALE_PORTCTL(i + 1), 3);
+ /* Check for media type change */
+ mii_tick(sc->mii);
+ if(sc->cpsw_media_status != sc->mii->mii_media.ifm_media) {
+ printf("%s: media type changed (ifm_media=%x)\n", __func__,
+ sc->mii->mii_media.ifm_media);
+ cpsw_ifmedia_upd(sc->ifp);
}
- /* Set Host Port Mapping */
- cpsw_write_4(CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
- cpsw_write_4(CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
-
- /* Set ALE port to forwarding(3)*/
- cpsw_write_4(CPSW_ALE_PORTCTL(0), 3);
-
- /* Add own MAC address and broadcast to ALE */
- cpsw_ale_uc_entry_set(sc, 0, sc->mac_addr);
- cpsw_ale_mc_entry_set(sc, 7, broadcast_address);
-
- cpsw_write_4(CPSW_SS_PTYPE, 0);
- /* Enable statistics for ports 0, 1 and 2 */
- cpsw_write_4(CPSW_SS_STAT_PORT_EN, 7);
-
- /* Reset CPDMA */
- cpsw_write_4(CPSW_CPDMA_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_CPDMA_SOFT_RESET) & 1)
- ;
-
- /* Make IP hdr aligned with 4 */
- cpsw_write_4(CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
+ /* Schedule another timeout one second from now */
+ callout_reset(&sc->watchdog.callout, hz, cpsw_tick, sc);
+}
- for (i = 0; i < 8; i++) {
- cpsw_write_4(CPSW_CPDMA_TX_HDP(i), 0);
- cpsw_write_4(CPSW_CPDMA_RX_HDP(i), 0);
- cpsw_write_4(CPSW_CPDMA_TX_CP(i), 0);
- cpsw_write_4(CPSW_CPDMA_RX_CP(i), 0);
- }
+static void
+cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
- /* Initialize RX Buffer Descriptors */
- cpsw_write_4(CPSW_CPDMA_RX_FREEBUFFER(0), 0);
- cpsw_fill_rx_queue_locked(sc);
+ CPSW_DEBUGF((""));
+ CPSW_TX_LOCK(sc);
- /* Clear all interrupt Masks */
- cpsw_write_4(CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
- cpsw_write_4(CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
+ mii = sc->mii;
+ mii_pollstat(mii);
- /* Enable TX & RX DMA */
- cpsw_write_4(CPSW_CPDMA_TX_CONTROL, 1);
- cpsw_write_4(CPSW_CPDMA_RX_CONTROL, 1);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
- /* Enable TX and RX interrupt receive for core 0 */
- cpsw_write_4(CPSW_WR_C_TX_EN(0), 0xFF);
- cpsw_write_4(CPSW_WR_C_RX_EN(0), 0xFF);
- //cpsw_write_4(CPSW_WR_C_MISC_EN(0), 0x3F);
+ CPSW_TX_UNLOCK(sc);
+}
- /* Enable host Error Interrupt */
- cpsw_write_4(CPSW_CPDMA_DMA_INTMASK_SET, 1);
+static int
+cpsw_ifmedia_upd(struct ifnet *ifp)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
- /* Enable interrupts for TX and RX Channel 0 */
- cpsw_write_4(CPSW_CPDMA_TX_INTMASK_SET, 1);
- cpsw_write_4(CPSW_CPDMA_RX_INTMASK_SET, 1);
+ CPSW_DEBUGF((""));
+ if (ifp->if_flags & IFF_UP) {
+ CPSW_GLOBAL_LOCK(sc);
+ sc->cpsw_media_status = sc->mii->mii_media.ifm_media;
+ mii_mediachg(sc->mii);
+ cpsw_init_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ }
- /* Ack stalled irqs */
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 0);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 2);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
+ return (0);
+}
- /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
- /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
- cpsw_write_4(MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+static void
+cpsw_tx_watchdog_full_reset(struct cpsw_softc *sc)
+{
+ cpsw_debugf_head("CPSW watchdog");
+ if_printf(sc->ifp, "watchdog timeout\n");
+ cpsw_shutdown_locked(sc);
+ cpsw_init_locked(sc);
+}
- /* Select MII in GMII_SEL, Internal Delay mode */
- //ti_scm_reg_write_4(0x650, 0);
+static void
+cpsw_tx_watchdog(struct cpsw_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
- /* Activate network interface */
- sc->rx_running = 1;
- sc->tx_running = 1;
- sc->tx_wd_timer = 0;
- callout_reset(&sc->wd_callout, hz, cpsw_tick, sc);
- sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
- sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ CPSW_GLOBAL_LOCK(sc);
+ if (sc->tx.active_queue_len == 0 || (ifp->if_flags & IFF_UP) == 0 ||
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || !sc->tx.running) {
+ sc->watchdog.timer = 0; /* Nothing to do. */
+ } else if (sc->tx.queue_removes > sc->tx.queue_removes_at_last_tick) {
+ sc->watchdog.timer = 0; /* Stuff done while we weren't looking. */
+ } else if (cpsw_tx_dequeue(sc) > 0) {
+ sc->watchdog.timer = 0; /* We just did something. */
+ } else {
+ /* There was something to do but it didn't get done. */
+ ++sc->watchdog.timer;
+ if (sc->watchdog.timer > 2) {
+ sc->watchdog.timer = 0;
+ ++ifp->if_oerrors;
+ ++sc->watchdog.resets;
+ cpsw_tx_watchdog_full_reset(sc);
+ }
+ }
+ sc->tx.queue_removes_at_last_tick = sc->tx.queue_removes;
+ CPSW_GLOBAL_UNLOCK(sc);
}
+/*
+ *
+ * ALE support routines.
+ *
+ */
+
static void
cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
{
- cpsw_write_4(CPSW_ALE_TBLCTL, idx & 1023);
- ale_entry[0] = cpsw_read_4(CPSW_ALE_TBLW0);
- ale_entry[1] = cpsw_read_4(CPSW_ALE_TBLW1);
- ale_entry[2] = cpsw_read_4(CPSW_ALE_TBLW2);
+ cpsw_write_4(sc, CPSW_ALE_TBLCTL, idx & 1023);
+ ale_entry[0] = cpsw_read_4(sc, CPSW_ALE_TBLW0);
+ ale_entry[1] = cpsw_read_4(sc, CPSW_ALE_TBLW1);
+ ale_entry[2] = cpsw_read_4(sc, CPSW_ALE_TBLW2);
}
static void
cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
{
- cpsw_write_4(CPSW_ALE_TBLW0, ale_entry[0]);
- cpsw_write_4(CPSW_ALE_TBLW1, ale_entry[1]);
- cpsw_write_4(CPSW_ALE_TBLW2, ale_entry[2]);
- cpsw_write_4(CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023));
+ cpsw_write_4(sc, CPSW_ALE_TBLW0, ale_entry[0]);
+ cpsw_write_4(sc, CPSW_ALE_TBLW1, ale_entry[1]);
+ cpsw_write_4(sc, CPSW_ALE_TBLW2, ale_entry[2]);
+ cpsw_write_4(sc, CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023));
}
static int
-cpsw_ale_find_entry_by_mac(struct cpsw_softc *sc, uint8_t *mac)
+cpsw_ale_remove_all_mc_entries(struct cpsw_softc *sc)
{
int i;
uint32_t ale_entry[3];
- for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
+
+ /* First two entries are link address and broadcast. */
+ for (i = 2; i < CPSW_MAX_ALE_ENTRIES; i++) {
cpsw_ale_read_entry(sc, i, ale_entry);
- if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) &&
- (((ale_entry[1] >> 0) & 0xFF) == mac[1]) &&
- (((ale_entry[0] >>24) & 0xFF) == mac[2]) &&
- (((ale_entry[0] >>16) & 0xFF) == mac[3]) &&
- (((ale_entry[0] >> 8) & 0xFF) == mac[4]) &&
- (((ale_entry[0] >> 0) & 0xFF) == mac[5])) {
- return (i);
+ if (((ale_entry[1] >> 28) & 3) == 1 && /* Address entry */
+ ((ale_entry[1] >> 8) & 1) == 1) { /* MCast link addr */
+ ale_entry[0] = ale_entry[1] = ale_entry[2] = 0;
+ cpsw_ale_write_entry(sc, i, ale_entry);
}
}
return CPSW_MAX_ALE_ENTRIES;
}
static int
-cpsw_ale_find_free_entry(struct cpsw_softc *sc)
+cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
{
- int i;
+ int free_index = -1, matching_index = -1, i;
uint32_t ale_entry[3];
+
+ /* Find a matching entry or a free entry. */
for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
cpsw_ale_read_entry(sc, i, ale_entry);
+
/* Entry Type[61:60] is 0 for free entry */
- if (((ale_entry[1] >> 28) & 3) == 0) {
- return i;
+ if (free_index < 0 && ((ale_entry[1] >> 28) & 3) == 0) {
+ free_index = i;
}
- }
- return CPSW_MAX_ALE_ENTRIES;
-}
-
-
-static int
-cpsw_ale_uc_entry_set(struct cpsw_softc *sc, uint8_t port, uint8_t *mac)
-{
- int i;
- uint32_t ale_entry[3];
- if ((i = cpsw_ale_find_entry_by_mac(sc, mac)) == CPSW_MAX_ALE_ENTRIES) {
- i = cpsw_ale_find_free_entry(sc);
+ if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) &&
+ (((ale_entry[1] >> 0) & 0xFF) == mac[1]) &&
+ (((ale_entry[0] >>24) & 0xFF) == mac[2]) &&
+ (((ale_entry[0] >>16) & 0xFF) == mac[3]) &&
+ (((ale_entry[0] >> 8) & 0xFF) == mac[4]) &&
+ (((ale_entry[0] >> 0) & 0xFF) == mac[5])) {
+ matching_index = i;
+ break;
+ }
}
- if (i == CPSW_MAX_ALE_ENTRIES)
- return (ENOMEM);
-
- /* Set MAC address */
- ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
- ale_entry[1] = mac[0] << 8 | mac[1];
-
- /* Entry type[61:60] is addr entry(1) */
- ale_entry[1] |= 0x10 << 24;
-
- /* Set portmask [67:66] */
- ale_entry[2] = (port & 3) << 2;
-
- cpsw_ale_write_entry(sc, i, ale_entry);
-
- return 0;
-}
-
-static int
-cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
-{
- int i;
- uint32_t ale_entry[3];
-
- if ((i = cpsw_ale_find_entry_by_mac(sc, mac)) == CPSW_MAX_ALE_ENTRIES) {
- i = cpsw_ale_find_free_entry(sc);
+ if (matching_index < 0) {
+ if (free_index < 0)
+ return (ENOMEM);
+ i = free_index;
}
- if (i == CPSW_MAX_ALE_ENTRIES)
- return (ENOMEM);
-
/* Set MAC address */
ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
ale_entry[1] = mac[0] << 8 | mac[1];
@@ -1481,7 +1931,6 @@ cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
return 0;
}
-#ifdef CPSW_DEBUG
static void
cpsw_ale_dump_table(struct cpsw_softc *sc) {
int i;
@@ -1504,5 +1953,232 @@ cpsw_ale_dump_table(struct cpsw_softc *sc) {
printf("\n");
}
}
+ printf("\n");
+}
+
+static int
+cpsw_ale_update_addresses(struct cpsw_softc *sc, int purge)
+{
+ uint8_t *mac;
+ uint32_t ale_entry[3];
+ struct ifnet *ifp = sc->ifp;
+ struct ifmultiaddr *ifma;
+ int i;
+
+ /* Route incoming packets for our MAC address to Port 0 (host). */
+ /* For simplicity, keep this entry at table index 0 in the ALE. */
+ if_addr_rlock(ifp);
+ mac = LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr);
+ ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+ ale_entry[1] = 0x10 << 24 | mac[0] << 8 | mac[1]; /* addr entry + mac */
+ ale_entry[2] = 0; /* port = 0 */
+ cpsw_ale_write_entry(sc, 0, ale_entry);
+
+ /* Set outgoing MAC Address for Ports 1 and 2. */
+ for (i = 1; i < 3; ++i) {
+ cpsw_write_4(sc, CPSW_PORT_P_SA_HI(i),
+ mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]);
+ cpsw_write_4(sc, CPSW_PORT_P_SA_LO(i),
+ mac[5] << 8 | mac[4]);
+ }
+ if_addr_runlock(ifp);
+
+ /* Keep the broadcast address at table entry 1. */
+ ale_entry[0] = 0xffffffff; /* Lower 32 bits of MAC */
+ ale_entry[1] = 0xd000ffff; /* FW (3 << 30), Addr entry (1 << 24), upper 16 bits of Mac */
+ ale_entry[2] = 0x0000001c; /* Forward to all ports */
+ cpsw_ale_write_entry(sc, 1, ale_entry);
+
+ /* SIOCDELMULTI doesn't specify the particular address
+ being removed, so we have to remove all and rebuild. */
+ if (purge)
+ cpsw_ale_remove_all_mc_entries(sc);
+
+ /* Set other multicast addrs desired. */
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ cpsw_ale_mc_entry_set(sc, 7,
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ }
+ if_maddr_runlock(ifp);
+
+ return (0);
+}
+
+/*
+ *
+ * Statistics and Sysctls.
+ *
+ */
+
+#if 0
+static void
+cpsw_stats_dump(struct cpsw_softc *sc)
+{
+ int i;
+ uint32_t r;
+
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
+ cpsw_stat_sysctls[i].reg);
+ CPSW_DEBUGF(("%s: %ju + %u = %ju", cpsw_stat_sysctls[i].oid,
+ (intmax_t)sc->shadow_stats[i], r,
+ (intmax_t)sc->shadow_stats[i] + r));
+ }
}
#endif
+
+static void
+cpsw_stats_collect(struct cpsw_softc *sc)
+{
+ int i;
+ uint32_t r;
+
+ CPSW_DEBUGF(("Controller shadow statistics updated."));
+
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
+ cpsw_stat_sysctls[i].reg);
+ sc->shadow_stats[i] += r;
+ cpsw_write_4(sc, CPSW_STATS_OFFSET + cpsw_stat_sysctls[i].reg, r);
+ }
+}
+
+static int
+cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct cpsw_stat *stat;
+ uint64_t result;
+
+ sc = (struct cpsw_softc *)arg1;
+ stat = &cpsw_stat_sysctls[oidp->oid_number];
+ result = sc->shadow_stats[oidp->oid_number];
+ result += cpsw_read_4(sc, CPSW_STATS_OFFSET + stat->reg);
+ return (sysctl_handle_64(oidp, &result, 0, req));
+}
+
+static int
+cpsw_stat_attached(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct bintime t;
+ unsigned result;
+
+ sc = (struct cpsw_softc *)arg1;
+ getbinuptime(&t);
+ bintime_sub(&t, &sc->attach_uptime);
+ result = t.sec;
+ return (sysctl_handle_int(oidp, &result, 0, req));
+}
+
+static int
+cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct bintime t;
+ unsigned result;
+
+ sc = (struct cpsw_softc *)arg1;
+ if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ getbinuptime(&t);
+ bintime_sub(&t, &sc->init_uptime);
+ result = t.sec;
+ } else
+ result = 0;
+ return (sysctl_handle_int(oidp, &result, 0, req));
+}
+
+static void
+cpsw_add_queue_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, struct cpsw_queue *queue)
+{
+ struct sysctl_oid_list *parent;
+
+ parent = SYSCTL_CHILDREN(node);
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "totalBuffers",
+ CTLFLAG_RD, &queue->queue_slots, 0,
+ "Total buffers currently assigned to this queue");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "activeBuffers",
+ CTLFLAG_RD, &queue->active_queue_len, 0,
+ "Buffers currently registered with hardware controller");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxActiveBuffers",
+ CTLFLAG_RD, &queue->max_active_queue_len, 0,
+ "Max value of activeBuffers since last driver reset");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "availBuffers",
+ CTLFLAG_RD, &queue->avail_queue_len, 0,
+ "Buffers allocated to this queue but not currently "
+ "registered with hardware controller");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxAvailBuffers",
+ CTLFLAG_RD, &queue->max_avail_queue_len, 0,
+ "Max value of availBuffers since last driver reset");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalEnqueued",
+ CTLFLAG_RD, &queue->queue_adds, 0,
+ "Total buffers added to queue");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalDequeued",
+ CTLFLAG_RD, &queue->queue_removes, 0,
+ "Total buffers removed from queue");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "longestChain",
+ CTLFLAG_RD, &queue->longest_chain, 0,
+ "Max buffers used for a single packet");
+}
+
+static void
+cpsw_add_watchdog_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, struct cpsw_softc *sc)
+{
+ struct sysctl_oid_list *parent;
+
+ parent = SYSCTL_CHILDREN(node);
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "resets",
+ CTLFLAG_RD, &sc->watchdog.resets, 0,
+ "Total number of watchdog resets");
+}
+
+static void
+cpsw_add_sysctls(struct cpsw_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *stats_node, *queue_node, *node;
+ struct sysctl_oid_list *parent, *stats_parent, *queue_parent;
+ int i;
+
+ ctx = device_get_sysctl_ctx(sc->dev);
+ parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
+
+ SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "attachedSecs",
+ CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_attached, "IU",
+ "Time since driver attach");
+
+ SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "uptime",
+ CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_uptime, "IU",
+ "Seconds since driver init");
+
+ stats_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats",
+ CTLFLAG_RD, NULL, "CPSW Statistics");
+ stats_parent = SYSCTL_CHILDREN(stats_node);
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ SYSCTL_ADD_PROC(ctx, stats_parent, i,
+ cpsw_stat_sysctls[i].oid,
+ CTLTYPE_U64 | CTLFLAG_RD, sc, 0,
+ cpsw_stats_sysctl, "IU",
+ cpsw_stat_sysctls[i].oid);
+ }
+
+ queue_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "queue",
+ CTLFLAG_RD, NULL, "CPSW Queue Statistics");
+ queue_parent = SYSCTL_CHILDREN(queue_node);
+
+ node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "tx",
+ CTLFLAG_RD, NULL, "TX Queue Statistics");
+ cpsw_add_queue_sysctls(ctx, node, &sc->tx);
+
+ node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "rx",
+ CTLFLAG_RD, NULL, "RX Queue Statistics");
+ cpsw_add_queue_sysctls(ctx, node, &sc->rx);
+
+ node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "watchdog",
+ CTLFLAG_RD, NULL, "Watchdog Statistics");
+ cpsw_add_watchdog_sysctls(ctx, node, sc);
+}
+
diff --git a/sys/arm/ti/cpsw/if_cpswreg.h b/sys/arm/ti/cpsw/if_cpswreg.h
index dab4f36..46f8417 100644
--- a/sys/arm/ti/cpsw/if_cpswreg.h
+++ b/sys/arm/ti/cpsw/if_cpswreg.h
@@ -34,8 +34,11 @@
#define CPSW_SS_SOFT_RESET (CPSW_SS_OFFSET + 0x08)
#define CPSW_SS_STAT_PORT_EN (CPSW_SS_OFFSET + 0x0C)
#define CPSW_SS_PTYPE (CPSW_SS_OFFSET + 0x10)
+#define CPSW_SS_FLOW_CONTROL (CPSW_SS_OFFSET + 0x24)
#define CPSW_PORT_OFFSET 0x0100
+#define CPSW_PORT_P_MAX_BLKS(p) (CPSW_PORT_OFFSET + 0x08 + ((p) * 0x100))
+#define CPSW_PORT_P_BLK_CNT(p) (CPSW_PORT_OFFSET + 0x0C + ((p) * 0x100))
#define CPSW_PORT_P_TX_PRI_MAP(p) (CPSW_PORT_OFFSET + 0x118 + ((p-1) * 0x100))
#define CPSW_PORT_P0_CPDMA_TX_PRI_MAP (CPSW_PORT_OFFSET + 0x01C)
#define CPSW_PORT_P0_CPDMA_RX_CH_MAP (CPSW_PORT_OFFSET + 0x020)
@@ -84,10 +87,14 @@
#define CPSW_ALE_TBLW0 (CPSW_ALE_OFFSET + 0x3C)
#define CPSW_ALE_PORTCTL(p) (CPSW_ALE_OFFSET + 0x40 + ((p) * 0x04))
+/* SL1 is at 0x0D80, SL2 is at 0x0DC0 */
#define CPSW_SL_OFFSET 0x0D80
#define CPSW_SL_MACCONTROL(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x04)
+#define CPSW_SL_MACSTATUS(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x08)
#define CPSW_SL_SOFT_RESET(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x0C)
#define CPSW_SL_RX_MAXLEN(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x10)
+#define CPSW_SL_RX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x18)
+#define CPSW_SL_TX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x1C)
#define CPSW_SL_RX_PRI_MAP(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x24)
#define MDIO_OFFSET 0x1000
@@ -109,5 +116,22 @@
#define CPSW_WR_C_MISC_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x4C)
#define CPSW_CPPI_RAM_OFFSET 0x2000
+#define CPSW_CPPI_RAM_SIZE 0x2000
+
+#define CPDMA_BD_SOP (1<<15)
+#define CPDMA_BD_EOP (1<<14)
+#define CPDMA_BD_OWNER (1<<13)
+#define CPDMA_BD_EOQ (1<<12)
+#define CPDMA_BD_TDOWNCMPLT (1<<11)
+#define CPDMA_BD_PKT_ERR_MASK (3<< 4)
+
+struct cpsw_cpdma_bd {
+ volatile uint32_t next;
+ volatile uint32_t bufptr;
+ volatile uint16_t buflen;
+ volatile uint16_t bufoff;
+ volatile uint16_t pktlen;
+ volatile uint16_t flags;
+};
#endif /*_IF_CPSWREG_H */
diff --git a/sys/arm/ti/cpsw/if_cpswvar.h b/sys/arm/ti/cpsw/if_cpswvar.h
index 35024c6..2aebb0f 100644
--- a/sys/arm/ti/cpsw/if_cpswvar.h
+++ b/sys/arm/ti/cpsw/if_cpswvar.h
@@ -35,105 +35,90 @@
#define CPSW_MIIBUS_RETRIES 5
#define CPSW_MIIBUS_DELAY 1000
-#define CPSW_MAX_TX_BUFFERS 128
-#define CPSW_MAX_RX_BUFFERS 128
#define CPSW_MAX_ALE_ENTRIES 1024
+#define CPSW_SYSCTL_COUNT 34
+
struct cpsw_slot {
+ uint32_t bd_offset; /* Offset of corresponding BD within CPPI RAM. */
bus_dmamap_t dmamap;
struct mbuf *mbuf;
- int index;
STAILQ_ENTRY(cpsw_slot) next;
};
-STAILQ_HEAD(cpsw_queue, cpsw_slot);
+STAILQ_HEAD(cpsw_slots, cpsw_slot);
+
+struct cpsw_queue {
+ struct mtx lock;
+ int running;
+ struct cpsw_slots active;
+ struct cpsw_slots avail;
+ uint32_t queue_adds; /* total bufs added */
+ uint32_t queue_removes; /* total bufs removed */
+ uint32_t queue_removes_at_last_tick; /* Used by watchdog */
+ int queue_slots;
+ int active_queue_len;
+ int max_active_queue_len;
+ int avail_queue_len;
+ int max_avail_queue_len;
+ int longest_chain; /* Largest # segments in a single packet. */
+ int hdp_offset;
+};
struct cpsw_softc {
struct ifnet *ifp;
phandle_t node;
device_t dev;
+ struct bintime attach_uptime; /* system uptime when attach happened. */
+ struct bintime init_uptime; /* system uptime when init happened. */
+
+ /* TODO: We should set up a child structure for each port;
+ store mac, phy information, etc, in that structure. */
uint8_t mac_addr[ETHER_ADDR_LEN];
+
device_t miibus;
struct mii_data *mii;
- struct mtx tx_lock; /* transmitter lock */
- struct mtx rx_lock; /* receiver lock */
- struct resource *res[1 + CPSW_INTR_COUNT]; /* resources */
- void *ih_cookie[CPSW_INTR_COUNT]; /* interrupt handlers cookies */
+ /* We expect 1 memory resource and 4 interrupts from the device tree. */
+ struct resource *res[1 + CPSW_INTR_COUNT];
+
+ /* Interrupts get recorded here as we initialize them. */
+ /* Interrupt teardown just walks this list. */
+ struct {
+ struct resource *res;
+ void *ih_cookie;
+ const char *description;
+ } interrupts[CPSW_INTR_COUNT];
+ int interrupt_count;
uint32_t cpsw_if_flags;
int cpsw_media_status;
- struct callout wd_callout;
- int tx_wd_timer;
+ struct {
+ int resets;
+ int timer;
+ struct callout callout;
+ } watchdog;
bus_dma_tag_t mbuf_dtag;
- /* RX buffer tracking */
- int rx_running;
- struct cpsw_queue rx_active;
- struct cpsw_queue rx_avail;
- struct cpsw_slot _rx_slots[CPSW_MAX_RX_BUFFERS];
-
- /* TX buffer tracking. */
- int tx_running;
- struct cpsw_queue tx_active;
- struct cpsw_queue tx_avail;
- struct cpsw_slot _tx_slots[CPSW_MAX_TX_BUFFERS];
-
- /* Statistics */
- uint32_t tx_enqueues; /* total TX bufs added to queue */
- uint32_t tx_retires; /* total TX bufs removed from queue */
- uint32_t tx_retires_at_last_tick; /* used for watchdog */
- /* Note: tx_queued != tx_enqueues - tx_retires
- At driver reset, packets can be discarded
- from TX queue without being retired. */
- int tx_queued; /* Current bufs in TX queue */
- int tx_max_queued;
+ /* An mbuf full of nulls for TX padding. */
+ bus_dmamap_t null_mbuf_dmamap;
+ struct mbuf *null_mbuf;
+ bus_addr_t null_mbuf_paddr;
+
+ /* RX and TX buffer tracking */
+ struct cpsw_queue rx, tx;
+
+ /* 64-bit versions of 32-bit hardware statistics counters */
+ uint64_t shadow_stats[CPSW_SYSCTL_COUNT];
+
+ /* CPPI STATERAM has 512 slots for building TX/RX queues. */
+ /* TODO: Size here supposedly varies with different versions
+ of the controller. Check DaVinci specs and find a good
+ way to adjust this. One option is to have a separate
+ Device Tree parameter for number slots; another option
+ is to calculate it from the memory size in the device tree. */
+ struct cpsw_slot _slots[CPSW_CPPI_RAM_SIZE / sizeof(struct cpsw_cpdma_bd)];
+ struct cpsw_slots avail;
};
-#define CPDMA_BD_SOP (1<<15)
-#define CPDMA_BD_EOP (1<<14)
-#define CPDMA_BD_OWNER (1<<13)
-#define CPDMA_BD_EOQ (1<<12)
-#define CPDMA_BD_TDOWNCMPLT (1<<11)
-#define CPDMA_BD_PKT_ERR_MASK (3<< 4)
-
-struct cpsw_cpdma_bd {
- volatile uint32_t next;
- volatile uint32_t bufptr;
- volatile uint16_t buflen;
- volatile uint16_t bufoff;
- volatile uint16_t pktlen;
- volatile uint16_t flags;
-};
-
-/* Read/Write macros */
-#define cpsw_read_4(reg) bus_read_4(sc->res[0], reg)
-#define cpsw_write_4(reg, val) bus_write_4(sc->res[0], reg, val)
-
-#define cpsw_cpdma_txbd_offset(i) \
- (CPSW_CPPI_RAM_OFFSET + ((i)*16))
-#define cpsw_cpdma_txbd_paddr(i) (cpsw_cpdma_txbd_offset(i) + \
- vtophys(rman_get_start(sc->res[0])))
-#define cpsw_cpdma_read_txbd(i, val) \
- bus_read_region_4(sc->res[0], cpsw_cpdma_txbd_offset(i), (uint32_t *) val, 4)
-#define cpsw_cpdma_write_txbd(i, val) \
- bus_write_region_4(sc->res[0], cpsw_cpdma_txbd_offset(i), (uint32_t *) val, 4)
-#define cpsw_cpdma_write_txbd_next(i, val) \
- bus_write_4(sc->res[0], cpsw_cpdma_txbd_offset(i), val)
-#define cpsw_cpdma_read_txbd_flags(i) \
- bus_read_2(sc->res[0], cpsw_cpdma_txbd_offset(i)+14)
-
-#define cpsw_cpdma_rxbd_offset(i) \
- (CPSW_CPPI_RAM_OFFSET + ((CPSW_MAX_TX_BUFFERS + (i))*16))
-#define cpsw_cpdma_rxbd_paddr(i) (cpsw_cpdma_rxbd_offset(i) + \
- vtophys(rman_get_start(sc->res[0])))
-#define cpsw_cpdma_read_rxbd(i, val) \
- bus_read_region_4(sc->res[0], cpsw_cpdma_rxbd_offset(i), (uint32_t *) val, 4)
-#define cpsw_cpdma_write_rxbd(i, val) \
- bus_write_region_4(sc->res[0], cpsw_cpdma_rxbd_offset(i), (uint32_t *) val, 4)
-#define cpsw_cpdma_write_rxbd_next(i, val) \
- bus_write_4(sc->res[0], cpsw_cpdma_rxbd_offset(i), val)
-#define cpsw_cpdma_read_rxbd_flags(i) \
- bus_read_2(sc->res[0], cpsw_cpdma_rxbd_offset(i)+14)
-
#endif /*_IF_CPSWVAR_H */
diff --git a/sys/arm/ti/ti_scm.c b/sys/arm/ti/ti_scm.c
index ce31f6e..58849c2 100644
--- a/sys/arm/ti/ti_scm.c
+++ b/sys/arm/ti/ti_scm.c
@@ -155,8 +155,10 @@ ti_scm_padconf_set_internal(struct ti_scm_softc *sc,
}
/* couldn't find the mux mode */
- if (mode >= 8)
+ if (mode >= 8) {
+ printf("Invalid mode \"%s\"\n", muxmode);
return (EINVAL);
+ }
/* set the mux mode */
reg_val |= (uint16_t)(mode & ti_scm_dev.padconf_muxmode_mask);
@@ -391,13 +393,16 @@ ti_scm_padconf_init_from_fdt(struct ti_scm_softc *sc)
while (padstates->state != NULL) {
if (strcmp(padstates->state, padstate) == 0) {
err = ti_scm_padconf_set_internal(sc,
- padconf, muxname, padstates->reg);
+ padconf, muxname, padstates->reg);
}
padstates++;
}
if (err)
- device_printf(sc->sc_dev, "err: failed to configure"
- "pin \"%s\"\n", padconf->ballname);
+ device_printf(sc->sc_dev,
+ "err: failed to configure "
+ "pin \"%s\" as \"%s\"\n",
+ padconf->ballname,
+ muxname);
}
padconf++;
}
diff --git a/sys/boot/arm/uboot/Makefile b/sys/boot/arm/uboot/Makefile
index 1974218..c3c4bd8 100644
--- a/sys/boot/arm/uboot/Makefile
+++ b/sys/boot/arm/uboot/Makefile
@@ -112,8 +112,8 @@ CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
# clang doesn't understand %D as a specifier to printf
NO_WERROR.clang=
-DPADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBSTAND}
-LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} -lstand
+DPADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBSTAND} ${LIBGCC}
+LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} -lstand -lgcc
vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
diff --git a/sys/boot/fdt/dts/beaglebone.dts b/sys/boot/fdt/dts/beaglebone.dts
index 2c68021..3e2dc80 100644
--- a/sys/boot/fdt/dts/beaglebone.dts
+++ b/sys/boot/fdt/dts/beaglebone.dts
@@ -91,7 +91,58 @@
"MMC0_DAT0", "mmc0_dat0", "input_pullup",
"MMC0_DAT1", "mmc0_dat1", "input_pullup",
"MMC0_DAT2", "mmc0_dat2", "input_pullup",
- "MMC0_DAT3", "mmc0_dat3", "input_pullup";
+ "MMC0_DAT3", "mmc0_dat3", "input_pullup",
+ /* GPIO */
+ "ECAP0_IN_PWM0_OUT", "gpio0_7", "input_pulldown",
+ "GPMC_AD10", "gpio0_26", "input_pulldown",
+ "GPMC_AD11", "gpio0_27", "input_pulldown",
+ "GPMC_AD0", "gpio1_0", "input_pulldown",
+ "GPMC_AD1", "gpio1_1", "input_pulldown",
+ "GPMC_AD2", "gpio1_2", "input_pulldown",
+ "GPMC_AD3", "gpio1_3", "input_pulldown",
+ "GPMC_AD4", "gpio1_4", "input_pulldown",
+ "GPMC_AD5", "gpio1_5", "input_pulldown",
+ "GPMC_AD6", "gpio1_6", "input_pulldown",
+ "GPMC_AD7", "gpio1_7", "input_pulldown",
+ "GPMC_AD12", "gpio1_12", "input_pulldown",
+ "GPMC_AD13", "gpio1_13", "input_pulldown",
+ "GPMC_AD14", "gpio1_14", "input_pulldown",
+ "GPMC_AD15", "gpio1_15", "input_pulldown",
+ "GPMC_A0", "gpio1_16", "input_pulldown",
+ "GPMC_A1", "gpio1_17", "input_pulldown",
+ "GPMC_A5", "gpio1_21", "output", /* User LED 1 */
+ "GPMC_A6", "gpio1_22", "output", /* User LED 2 */
+ "GPMC_A7", "gpio1_23", "output", /* User LED 3 */
+ "GPMC_A8", "gpio1_24", "output", /* User LED 4 */
+ "GPMC_BEn1", "gpio1_28", "input_pulldown",
+ "GPMC_CSn0", "gpio1_29", "input_pulldown",
+ "GPMC_CSn1", "gpio1_30", "input_pulldown",
+ "GPMC_CSn2", "gpio1_31", "input_pulldown",
+ "GPMC_CLK", "gpio2_1", "input_pulldown",
+ "LCD_DATA0", "gpio2_6", "input_pulldown",
+ "LCD_DATA1", "gpio2_7", "input_pulldown",
+ "LCD_DATA2", "gpio2_8", "input_pulldown",
+ "LCD_DATA3", "gpio2_9", "input_pulldown",
+ "LCD_DATA4", "gpio2_10", "input_pulldown",
+ "LCD_DATA5", "gpio2_11", "input_pulldown",
+ "LCD_DATA6", "gpio2_12", "input_pulldown",
+ "LCD_DATA7", "gpio2_13", "input_pulldown",
+ "LCD_VSYNC", "gpio2_22", "input_pulldown",
+ "LCD_HSYNC", "gpio2_23", "input_pulldown",
+ "LCD_PCLK", "gpio2_24", "input_pulldown",
+ "LCD_AC_BIAS_EN", "gpio2_25", "input_pulldown",
+ "MCASP0_FSR", "gpio3_19", "input_pulldown",
+ "MCASP0_AHCLKX", "gpio3_21", "input_pulldown",
+ /* TIMERs */
+ "GPMC_ADVn_ALE", "timer4", "output",
+ "GPMC_BEn0_CLE", "timer5", "output",
+ "GPMC_WEn", "timer6", "output",
+ "GPMC_OEn_REn", "timer7", "output",
+ /* PWM */
+ "GPMC_A2", "ehrpwm1A", "output",
+ "GPMC_A3", "ehrpwm1B", "output",
+ "GPMC_AD8", "ehrpwm2A", "output",
+ "GPMC_AD9", "ehrpwm2B", "output";
};
prcm@44E00000 {
@@ -125,7 +176,7 @@
0x4804C000 0x1000
0x481AC000 0x1000
0x481AE000 0x1000 >;
- interrupts = < 17 19 21 23 >;
+ interrupts = < 96 97 98 99 32 33 62 63 >;
interrupt-parent = <&AINTC>;
};
@@ -161,7 +212,7 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "ti,cpsw";
- reg = <0x4A100000 0x3000>;
+ reg = <0x4A100000 0x4000>;
interrupts = <40 41 42 43>;
interrupt-parent = <&AINTC>;
phy-handle = <&phy0>;
diff --git a/sys/boot/fdt/dts/cubieboard.dts b/sys/boot/fdt/dts/cubieboard.dts
new file mode 100644
index 0000000..c4dd2a8
--- /dev/null
+++ b/sys/boot/fdt/dts/cubieboard.dts
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * 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$
+ */
+
+/dts-v1/;
+
+/ {
+ model = "Cubietech Cubieboard";
+ compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&AINTC>;
+
+ memory {
+ device_type = "memory";
+ reg = < 0x40000000 0x20000000 >; /* 512MB RAM */
+ };
+
+ aliases {
+ soc = &SOC;
+ UART0 = &UART0;
+ };
+
+ SOC: a10 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+ bus-frequency = <0>;
+
+ AINTC: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = < 0x01c20400 0x400 >;
+ };
+
+ ccm@01c20000 {
+ compatible = "allwinner,sun4i-ccm";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = < 0x01c20000 0x400 >;
+ };
+
+ timer@01c20c00 {
+ compatible = "allwinner,sun4i-timer";
+ reg = <0x01c20c00 0x90>;
+ interrupts = < 22 >;
+ interrupt-parent = <&AINTC>;
+ clock-frequency = < 24000000 >;
+ };
+
+ usb1: usb@01c1c000 {
+ compatible = "allwinner,usb-ehci", "usb-ehci";
+ reg = <0x01c1c000 0x1000>;
+ interrupts = < 40 >;
+ interrupt-parent = <&AINTC>;
+ };
+
+ sata@01c18000 {
+ compatible = "allwinner,ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <56>;
+ interrupt-parent = <&AINTC>;
+ };
+
+ UART0: serial@01c28000 {
+ status = "okay";
+ compatible = "ns16550";
+ reg = <0x01c28000 0x400>;
+ reg-shift = <2>;
+ interrupts = <1>;
+ interrupt-parent = <&AINTC>;
+ current-speed = <115200>;
+ clock-frequency = < 24000000 >;
+ };
+ };
+
+ chosen {
+ bootargs = "-v";
+ stdin = "UART0";
+ stdout = "UART0";
+ };
+};
+
diff --git a/sys/boot/fdt/dts/dreamplug-1001.dts b/sys/boot/fdt/dts/dreamplug-1001.dts
new file mode 100644
index 0000000..92ca1b0
--- /dev/null
+++ b/sys/boot/fdt/dts/dreamplug-1001.dts
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2013 Ian Lepore
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software substantially based on work developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, 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.
+ *
+ * GlobalScale Technologies DreamPlug Device Tree Source.
+ *
+ * This source is for version 10 revision 01 units with NOR SPI flash.
+ * These units are marked "1001" on the serial number label.
+ *
+ * $FreeBSD$
+ */
+
+/dts-v1/;
+
+/ {
+ model = "GlobalScale Technologies Dreamplug v1001";
+ compatible = "globalscale,dreamplug-003-ds2001", "globalscale,dreamplug", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ mpp = &MPP;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ soc = &SOC;
+ sram = &SRAM;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "ARM,88FR131";
+ reg = <0x0>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <0x4000>; // L1, 16K
+ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
+
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x20000000>; // 512M at 0x0
+ };
+
+ localbus@0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "mrvl,lbc";
+ bank-count = <1>;
+
+ /* This reflects CPU decode windows setup. */
+ ranges = <0x0 0x1e 0xfa000000 0x00100000>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x00100000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+ };
+
+ SOC: soc88f6281@f1000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0xf1000000 0x00100000>;
+ bus-frequency = <0>;
+
+ PIC: pic@20200 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x20200 0x3c>;
+ compatible = "mrvl,pic";
+ };
+
+ timer@20300 {
+ compatible = "mrvl,timer";
+ reg = <0x20300 0x30>;
+ interrupts = <1>;
+ interrupt-parent = <&PIC>;
+ mrvl,has-wdt;
+ };
+
+ MPP: mpp@10000 {
+ #pin-cells = <2>;
+ compatible = "mrvl,mpp";
+ reg = <0x10000 0x34>;
+ pin-count = <50>;
+ pin-map = <
+ 0 2 /* MPP[ 0]: SPI_SCn */
+ 1 2 /* MPP[ 1]: SPI_MOSI */
+ 2 2 /* MPP[ 2]: SPI_SCK */
+ 3 2 /* MPP[ 3]: SPI_MISO */
+ 4 1 /* MPP[ 4]: NF_IO[6] */
+ 5 1 /* MPP[ 5]: NF_IO[7] */
+ 6 1 /* MPP[ 6]: SYSRST_OUTn */
+ 7 0 /* MPP[ 7]: GPO[7] */
+ 8 1 /* MPP[ 8]: TW_SDA */
+ 9 1 /* MPP[ 9]: TW_SCK */
+ 10 3 /* MPP[10]: UA0_TXD */
+ 11 3 /* MPP[11]: US0_RXD */
+ 12 1 /* MPP[12]: SD_CLK */
+ 13 1 /* MPP[13]: SD_CMD */
+ 14 1 /* MPP[14]: SD_D[0] */
+ 15 1 /* MPP[15]: SD_D[1] */
+ 16 1 /* MPP[16]: SD_D[2] */
+ 17 1 /* MPP[17]: SD_D[3] */
+ 18 1 /* MPP[18]: NF_IO[0] */
+ 19 1 /* MPP[19]: NF_IO[1] */
+ 20 3 /* MPP[20]: GE1[ 0] */
+ 21 3 /* MPP[21]: GE1[ 1] */
+ 22 3 /* MPP[22]: GE1[ 2] */
+ 23 3 /* MPP[23]: GE1[ 3] */
+ 24 3 /* MPP[24]: GE1[ 4] */
+ 25 3 /* MPP[25]: GE1[ 5] */
+ 26 3 /* MPP[26]: GE1[ 6] */
+ 27 3 /* MPP[27]: GE1[ 7] */
+ 28 3 /* MPP[28]: GE1[ 8] */
+ 29 3 /* MPP[29]: GE1[ 9] */
+ 30 3 /* MPP[30]: GE1[10] */
+ 31 3 /* MPP[31]: GE1[11] */
+ 32 3 /* MPP[32]: GE1[12] */
+ 33 3 /* MPP[33]: GE1[13] */
+ 34 3 /* MPP[34]: GE1[14] */
+ 35 3 /* MPP[35]: GE1[15] */
+ 36 0 /* MPP[36]: GPIO[36] */
+ 37 0 /* MPP[37]: GPIO[37] */
+ 38 0 /* MPP[38]: GPIO[38] */
+ 39 0 /* MPP[39]: GPIO[39] */
+ 40 2 /* MPP[40]: TDM_SPI_SCK */
+ 41 2 /* MPP[41]: TDM_SPI_MISO */
+ 42 2 /* MPP[42]: TDM_SPI_MOSI */
+ 43 0 /* MPP[43]: GPIO[43] */
+ 44 0 /* MPP[44]: GPIO[44] */
+ 45 0 /* MPP[45]: GPIO[45] */
+ 46 0 /* MPP[46]: GPIO[46] */
+ 47 0 /* MPP[47]: GPIO[47] */
+ 48 0 /* MPP[48]: GPIO[48] */
+ 49 0 /* MPP[49]: GPIO[49] */
+ >;
+ };
+
+ GPIO: gpio@10100 {
+ #gpio-cells = <3>;
+ compatible = "mrvl,gpio";
+ reg = <0x10100 0x20>;
+ gpio-controller;
+ interrupts = <35 36 37 38 39 40 41>;
+ interrupt-parent = <&PIC>;
+ pin-count = <50>;
+ };
+
+ gpioled@0 {
+ compatible = "mrvl,gpioled";
+
+ gpios = <&GPIO 47 2 0 /* GPIO[47] BT LED: OUT */
+ &GPIO 48 2 0 /* GPIO[48] WLAN LED: OUT */
+ &GPIO 49 2 0>; /* GPIO[49] WLAN AP LED: OUT */
+ };
+
+ rtc@10300 {
+ compatible = "mrvl,rtc";
+ reg = <0x10300 0x08>;
+ };
+
+ twsi@11000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,twsi";
+ reg = <0x11000 0x20>;
+ interrupts = <43>;
+ interrupt-parent = <&PIC>;
+ };
+
+ enet0: ethernet@72000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x72000 0x2000>;
+ ranges = <0x0 0x72000 0x2000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <12 13 14 11 46>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&phy0>;
+
+ mdio@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,mdio";
+
+ phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ };
+ };
+ };
+
+ enet1: ethernet@76000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x76000 0x02000>;
+ ranges = <0x0 0x76000 0x2000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <16 17 18 15 47>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&phy1>;
+ };
+
+ serial0: serial@12000 {
+ compatible = "ns16550";
+ reg = <0x12000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <33>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial1: serial@12100 {
+ compatible = "ns16550";
+ reg = <0x12100 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <34>;
+ interrupt-parent = <&PIC>;
+ };
+
+ crypto@30000 {
+ compatible = "mrvl,cesa";
+ reg = <0x30000 0x10000>;
+ interrupts = <22>;
+ interrupt-parent = <&PIC>;
+
+ sram-handle = <&SRAM>;
+ };
+
+ usb@50000 {
+ compatible = "mrvl,usb-ehci", "usb-ehci";
+ reg = <0x50000 0x1000>;
+ interrupts = <48 19>;
+ interrupt-parent = <&PIC>;
+ };
+
+ xor@60000 {
+ compatible = "mrvl,xor";
+ reg = <0x60000 0x1000>;
+ interrupts = <5 6 7 8>;
+ interrupt-parent = <&PIC>;
+ };
+
+ sata@80000 {
+ compatible = "mrvl,sata";
+ reg = <0x80000 0x6000>;
+ interrupts = <21>;
+ interrupt-parent = <&PIC>;
+ };
+
+ sdio@90000 {
+ compatible = "mrvl,sdio";
+ reg = <0x90000 0x134>;
+ interrupts = <28>;
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ SRAM: sram@fd000000 {
+ compatible = "mrvl,cesa-sram";
+ reg = <0xfd000000 0x00100000>;
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
+
+};
diff --git a/sys/boot/fdt/dts/dreamplug-1001N.dts b/sys/boot/fdt/dts/dreamplug-1001N.dts
new file mode 100644
index 0000000..230a65f
--- /dev/null
+++ b/sys/boot/fdt/dts/dreamplug-1001N.dts
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2013 Ian Lepore
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software substantially based on work developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, 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.
+ *
+ * GlobalScale Technologies DreamPlug Device Tree Source.
+ *
+ * This source is for version 10 revision 01 units with NAND flash.
+ * These units are marked "1001N" on the serial number label.
+ *
+ * $FreeBSD$
+ */
+
+/dts-v1/;
+
+/ {
+ model = "GlobalScale Technologies Dreamplug v1001N";
+ compatible = "globalscale,dreamplug-003-ds2001", "globalscale,dreamplug", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ mpp = &MPP;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ soc = &SOC;
+ sram = &SRAM;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "ARM,88FR131";
+ reg = <0x0>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <0x4000>; // L1, 16K
+ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
+
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x20000000>; // 512M at 0x0
+ };
+
+ localbus@0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "mrvl,lbc";
+ bank-count = <1>;
+
+ /* This reflects CPU decode windows setup. */
+ ranges = <0x0 0x2f 0xf9300000 0x00100000>;
+
+ nand@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mrvl,nfc";
+ reg = <0x0 0x0 0x00100000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ // Slice info reported by builtin linux when it boots...
+ //[ 11.161328] 0x00000000-0x00100000 : "u-boot"
+ //[ 11.167431] 0x00100000-0x00500000 : "uImage"
+ //[ 11.173471] 0x00500000-0x20000000 : "root"
+
+ slice@0 {
+ reg = <0x0 0x100000>;
+ label = "u-boot";
+ read-only;
+ };
+
+ slice@200000 {
+ reg = <0x100000 0x40000>;
+ label = "uImage";
+ };
+
+ slice@500000 {
+ reg = <0x500000 0x1FB00000>;
+ label = "root";
+ };
+ };
+ };
+
+ SOC: soc88f6281@f1000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0xf1000000 0x00100000>;
+ bus-frequency = <0>;
+
+ PIC: pic@20200 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x20200 0x3c>;
+ compatible = "mrvl,pic";
+ };
+
+ timer@20300 {
+ compatible = "mrvl,timer";
+ reg = <0x20300 0x30>;
+ interrupts = <1>;
+ interrupt-parent = <&PIC>;
+ mrvl,has-wdt;
+ };
+
+ MPP: mpp@10000 {
+ #pin-cells = <2>;
+ compatible = "mrvl,mpp";
+ reg = <0x10000 0x34>;
+ pin-count = <50>;
+ pin-map = <
+ 0 1 /* MPP[ 0]: NF_IO[2] */
+ 1 1 /* MPP[ 1]: NF_IO[3] */
+ 2 1 /* MPP[ 2]: NF_IO[4] */
+ 3 1 /* MPP[ 3]: NF_IO[5] */
+ 4 1 /* MPP[ 4]: NF_IO[6] */
+ 5 1 /* MPP[ 5]: NF_IO[7] */
+ 6 1 /* MPP[ 6]: SYSRST_OUTn */
+ 7 0 /* MPP[ 7]: GPO[7] */
+ 8 1 /* MPP[ 8]: TW_SDA */
+ 9 1 /* MPP[ 9]: TW_SCK */
+ 10 3 /* MPP[10]: UA0_TXD */
+ 11 3 /* MPP[11]: US0_RXD */
+ 12 1 /* MPP[12]: SD_CLK */
+ 13 1 /* MPP[13]: SD_CMD */
+ 14 1 /* MPP[14]: SD_D[0] */
+ 15 1 /* MPP[15]: SD_D[1] */
+ 16 1 /* MPP[16]: SD_D[2] */
+ 17 1 /* MPP[17]: SD_D[3] */
+ 18 1 /* MPP[18]: NF_IO[0] */
+ 19 1 /* MPP[19]: NF_IO[1] */
+ 20 3 /* MPP[20]: GE1[ 0] */
+ 21 3 /* MPP[21]: GE1[ 1] */
+ 22 3 /* MPP[22]: GE1[ 2] */
+ 23 3 /* MPP[23]: GE1[ 3] */
+ 24 3 /* MPP[24]: GE1[ 4] */
+ 25 3 /* MPP[25]: GE1[ 5] */
+ 26 3 /* MPP[26]: GE1[ 6] */
+ 27 3 /* MPP[27]: GE1[ 7] */
+ 28 3 /* MPP[28]: GE1[ 8] */
+ 29 3 /* MPP[29]: GE1[ 9] */
+ 30 3 /* MPP[30]: GE1[10] */
+ 31 3 /* MPP[31]: GE1[11] */
+ 32 3 /* MPP[32]: GE1[12] */
+ 33 3 /* MPP[33]: GE1[13] */
+ 34 3 /* MPP[34]: GE1[14] */
+ 35 3 /* MPP[35]: GE1[15] */
+ 36 0 /* MPP[36]: GPIO[36] */
+ 37 0 /* MPP[37]: GPIO[37] */
+ 38 0 /* MPP[38]: GPIO[38] */
+ 39 0 /* MPP[39]: GPIO[39] */
+ 40 2 /* MPP[40]: TDM_SPI_SCK */
+ 41 2 /* MPP[41]: TDM_SPI_MISO */
+ 42 2 /* MPP[42]: TDM_SPI_MOSI */
+ 43 0 /* MPP[43]: GPIO[43] */
+ 44 0 /* MPP[44]: GPIO[44] */
+ 45 0 /* MPP[45]: GPIO[45] */
+ 46 0 /* MPP[46]: GPIO[46] */
+ 47 0 /* MPP[47]: GPIO[47] */
+ 48 0 /* MPP[48]: GPIO[48] */
+ 49 0 /* MPP[49]: GPIO[49] */
+ >;
+ };
+
+ GPIO: gpio@10100 {
+ #gpio-cells = <3>;
+ compatible = "mrvl,gpio";
+ reg = <0x10100 0x20>;
+ gpio-controller;
+ interrupts = <35 36 37 38 39 40 41>;
+ interrupt-parent = <&PIC>;
+ pin-count = <50>;
+ };
+
+ gpioled@0 {
+ compatible = "mrvl,gpioled";
+
+ gpios = <&GPIO 47 2 0 /* GPIO[47] BT LED: OUT */
+ &GPIO 48 2 0 /* GPIO[48] WLAN LED: OUT */
+ &GPIO 49 2 0>; /* GPIO[49] WLAN AP LED: OUT */
+ };
+
+ rtc@10300 {
+ compatible = "mrvl,rtc";
+ reg = <0x10300 0x08>;
+ };
+
+ twsi@11000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,twsi";
+ reg = <0x11000 0x20>;
+ interrupts = <43>;
+ interrupt-parent = <&PIC>;
+ };
+
+ enet0: ethernet@72000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x72000 0x2000>;
+ ranges = <0x0 0x72000 0x2000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <12 13 14 11 46>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&phy0>;
+
+ mdio@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,mdio";
+
+ phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ };
+ };
+ };
+
+ enet1: ethernet@76000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x76000 0x02000>;
+ ranges = <0x0 0x76000 0x2000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <16 17 18 15 47>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&phy1>;
+ };
+
+ serial0: serial@12000 {
+ compatible = "ns16550";
+ reg = <0x12000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <33>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial1: serial@12100 {
+ compatible = "ns16550";
+ reg = <0x12100 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <34>;
+ interrupt-parent = <&PIC>;
+ };
+
+ crypto@30000 {
+ compatible = "mrvl,cesa";
+ reg = <0x30000 0x10000>;
+ interrupts = <22>;
+ interrupt-parent = <&PIC>;
+
+ sram-handle = <&SRAM>;
+ };
+
+ usb@50000 {
+ compatible = "mrvl,usb-ehci", "usb-ehci";
+ reg = <0x50000 0x1000>;
+ interrupts = <48 19>;
+ interrupt-parent = <&PIC>;
+ };
+
+ xor@60000 {
+ compatible = "mrvl,xor";
+ reg = <0x60000 0x1000>;
+ interrupts = <5 6 7 8>;
+ interrupt-parent = <&PIC>;
+ };
+
+ sata@80000 {
+ compatible = "mrvl,sata";
+ reg = <0x80000 0x6000>;
+ interrupts = <21>;
+ interrupt-parent = <&PIC>;
+ };
+
+ sdio@90000 {
+ compatible = "mrvl,sdio";
+ reg = <0x90000 0x134>;
+ interrupts = <28>;
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ SRAM: sram@fd000000 {
+ compatible = "mrvl,cesa-sram";
+ reg = <0xfd000000 0x00100000>;
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
+
+};
diff --git a/sys/boot/i386/efi/Makefile b/sys/boot/i386/efi/Makefile
index 95c219d..25df59b 100644
--- a/sys/boot/i386/efi/Makefile
+++ b/sys/boot/i386/efi/Makefile
@@ -36,7 +36,7 @@ FILES= loader.efi
FILESMODE_loader.efi= ${BINMODE}
LDSCRIPT= ${.CURDIR}/ldscript.i386
-LDFLAGS= -Wl,-T${LDSCRIPT} -shared -symbolic
+LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared
${PROG}: ${LDSCRIPT}
diff --git a/sys/boot/i386/libi386/bootinfo64.c b/sys/boot/i386/libi386/bootinfo64.c
index 0c6d077..617414e 100644
--- a/sys/boot/i386/libi386/bootinfo64.c
+++ b/sys/boot/i386/libi386/bootinfo64.c
@@ -134,7 +134,8 @@ bi_checkcpu(void)
{
char *cpu_vendor;
int vendor[3];
- int eflags, regs[4];
+ int eflags;
+ unsigned int regs[4];
/* Check for presence of "cpuid". */
eflags = read_eflags();
diff --git a/sys/boot/i386/libi386/comconsole.c b/sys/boot/i386/libi386/comconsole.c
index 3822597..e2710c1 100644
--- a/sys/boot/i386/libi386/comconsole.c
+++ b/sys/boot/i386/libi386/comconsole.c
@@ -50,7 +50,6 @@ static int comc_init(int arg);
static void comc_putchar(int c);
static int comc_getchar(void);
static int comc_getspeed(void);
-static void set_hw_console_hint(void);
static int comc_ischar(void);
static int comc_parseint(const char *string);
static uint32_t comc_parse_pcidev(const char *string);
@@ -202,27 +201,14 @@ comc_port_set(struct env_var *ev, int flags, const void *value)
}
if ((comconsole.c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) != 0 &&
- comc_port != port) {
+ comc_port != port)
comc_setup(comc_curspeed, port);
- set_hw_console_hint();
- }
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
return (CMD_OK);
}
-static void
-set_hw_console_hint(void)
-{
- char intbuf[64];
-
- unsetenv("hw.uart.console");
- sprintf(intbuf, "io:%d,br:%d", comc_port, comc_curspeed);
- env_setenv("hw.uart.console", EV_VOLATILE, intbuf,
- env_noset, env_nounset);
-}
-
/*
* Input: bus:dev:func[:bar]. If bar is not specified, it is 0x10.
* Output: bar[24:16] bus[15:8] dev[7:3] func[2:0]
@@ -288,7 +274,6 @@ comc_pcidev_handle(uint32_t locator)
comc_port_set, env_nounset);
comc_setup(comc_curspeed, port);
- set_hw_console_hint();
comc_locator = locator;
return (CMD_OK);
@@ -318,8 +303,10 @@ static void
comc_setup(int speed, int port)
{
static int TRY_COUNT = 1000000;
+ char intbuf[64];
int tries;
+ unsetenv("hw.uart.console");
comc_curspeed = speed;
comc_port = port;
@@ -334,9 +321,11 @@ comc_setup(int speed, int port)
inb(comc_port + com_data);
while (inb(comc_port + com_lsr) & LSR_RXRDY && ++tries < TRY_COUNT);
- if (tries < TRY_COUNT)
+ if (tries < TRY_COUNT) {
comconsole.c_flags |= (C_PRESENTIN | C_PRESENTOUT);
- else
+ sprintf(intbuf, "io:%d,br:%d", comc_port, comc_curspeed);
+ env_setenv("hw.uart.console", EV_VOLATILE, intbuf, NULL, NULL);
+ } else
comconsole.c_flags &= ~(C_PRESENTIN | C_PRESENTOUT);
}
diff --git a/sys/boot/i386/libi386/devicename.c b/sys/boot/i386/libi386/devicename.c
index 15889d3..c7705d7 100644
--- a/sys/boot/i386/libi386/devicename.c
+++ b/sys/boot/i386/libi386/devicename.c
@@ -128,7 +128,7 @@ i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path)
goto fail;
}
} else {
- cp = np;
+ cp = (char *)np;
}
if (*cp && (*cp != ':')) {
err = EINVAL;
diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c
index e4ec5c0..49814dd 100644
--- a/sys/boot/i386/libi386/pxe.c
+++ b/sys/boot/i386/libi386/pxe.c
@@ -88,6 +88,12 @@ static int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len,
static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len);
static void pxe_netif_end(struct netif *nif);
+#ifdef OLD_NFSV2
+int nfs_getrootfh(struct iodesc*, char*, u_char*);
+#else
+int nfs_getrootfh(struct iodesc*, char*, uint32_t*, u_char*);
+#endif
+
extern struct netif_stats pxe_st[];
extern u_int16_t __bangpxeseg;
extern u_int16_t __bangpxeoff;
diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c
index fa9d068..5a0badf 100644
--- a/sys/boot/sparc64/loader/main.c
+++ b/sys/boot/sparc64/loader/main.c
@@ -142,6 +142,10 @@ static vm_offset_t heapva;
static char bootpath[64];
static phandle_t root;
+#ifdef LOADER_ZFS_SUPPORT
+static struct zfs_devdesc zfs_currdev;
+#endif
+
/*
* Machine dependent structures that the machine independent
* loader part uses.
@@ -732,7 +736,6 @@ static void
sparc64_zfs_probe(void)
{
struct vtoc8 vtoc;
- struct zfs_devdesc zfs_currdev;
char alias[64], devname[sizeof(alias) + sizeof(":x") - 1];
char type[sizeof("device_type")];
char *bdev, *dev, *odev;
@@ -805,9 +808,6 @@ sparc64_zfs_probe(void)
zfs_currdev.root_guid = 0;
zfs_currdev.d_dev = &zfs_dev;
zfs_currdev.d_type = zfs_currdev.d_dev->dv_type;
- (void)strncpy(bootpath, zfs_fmtdev(&zfs_currdev),
- sizeof(bootpath) - 1);
- bootpath[sizeof(bootpath) - 1] = '\0';
}
}
#endif /* LOADER_ZFS_SUPPORT */
@@ -878,10 +878,14 @@ main(int (*openfirm)(void *))
if ((*dp)->dv_init != 0)
(*dp)->dv_init();
- /*
- * Now that sparc64_zfs_probe() might have altered bootpath,
- * export it.
- */
+#ifdef LOADER_ZFS_SUPPORT
+ if (zfs_currdev.pool_guid != 0) {
+ (void)strncpy(bootpath, zfs_fmtdev(&zfs_currdev),
+ sizeof(bootpath) - 1);
+ bootpath[sizeof(bootpath) - 1] = '\0';
+ }
+#endif
+
env_setenv("currdev", EV_VOLATILE, bootpath,
ofw_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, bootpath,
diff --git a/sys/boot/uboot/common/metadata.c b/sys/boot/uboot/common/metadata.c
index 74497a9..bbc1893 100644
--- a/sys/boot/uboot/common/metadata.c
+++ b/sys/boot/uboot/common/metadata.c
@@ -369,12 +369,15 @@ md_load(char *args, vm_offset_t *modulep)
/* Convert addresses to the final VA */
*modulep -= __elfN(relocation_offset);
- for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) {
- md = file_findmetadata(kfp, mdt[i]);
- if (md) {
- bcopy(md->md_data, &vaddr, sizeof vaddr);
- vaddr -= __elfN(relocation_offset);
- bcopy(&vaddr, md->md_data, sizeof vaddr);
+ /* Do relocation fixup on metadata of each module. */
+ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+ for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) {
+ md = file_findmetadata(xp, mdt[i]);
+ if (md) {
+ bcopy(md->md_data, &vaddr, sizeof vaddr);
+ vaddr -= __elfN(relocation_offset);
+ bcopy(&vaddr, md->md_data, sizeof vaddr);
+ }
}
}
diff --git a/sys/boot/usb/Makefile b/sys/boot/usb/Makefile
new file mode 100644
index 0000000..b71b10d
--- /dev/null
+++ b/sys/boot/usb/Makefile
@@ -0,0 +1,150 @@
+#
+# $FreeBSD$
+#
+# Copyright (c) 2013 Hans Petter Selasky. 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.
+#
+
+T=${.CURDIR}/tools
+S=${.CURDIR}/../..
+
+.PATH: \
+ ${.CURDIR} \
+ ${S}/dev/usb \
+ ${S}/dev/usb/controller \
+ ${S}/dev/usb/serial \
+ ${S}/dev/usb/storage \
+ ${S}/dev/usb/template
+
+LIB= usbboot
+INTERNALLIB=
+OBJCOPY?= objcopy
+SYSCC?= cc
+
+CFLAGS+= -DBOOTPROG=\"usbloader\"
+CFLAGS+= -DUSB_GLOBAL_INCLUDE_FILE="\"bsd_global.h\""
+CFLAGS+= -ffunction-sections -fdata-sections
+CFLAGS+= -ffreestanding
+CFLAGS+= -Wformat -Wall
+CFLAGS+= -I ${S}
+CFLAGS+= -I ${T}
+CFLAGS+= -I ${.CURDIR}
+CFLAGS+= -g
+
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -march=i386
+CFLAGS+= -mpreferred-stack-boundary=2
+.endif
+.if ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -m32
+.endif
+
+#
+# Single threaded BSD kernel
+#
+SRCS+= bsd_kernel.c
+
+#
+# BUSSPACE implementation
+#
+SRCS+= bsd_busspace.c
+
+#
+# BUSDMA implementation
+#
+SRCS+= usb_busdma_loader.c
+
+#
+# USB controller drivers
+#
+SRCS+= at91dci.c
+SRCS+= atmegadci.c
+SRCS+= avr32dci.c
+SRCS+= dwc_otg.c
+SRCS+= ehci.c
+SRCS+= musb_otg.c
+SRCS+= ohci.c
+SRCS+= uhci.c
+SRCS+= uss820dci.c
+SRCS+= xhci.c
+SRCS+= usb_controller.c
+
+CFLAGS += -DUSB_PROBE_LIST="\"xhci\", \"ehci\", \"uhci\", \"ohci\""
+
+#
+# USB core and templates
+#
+SRCS+= usb_core.c
+SRCS+= usb_debug.c
+SRCS+= usb_device.c
+SRCS+= usb_dynamic.c
+SRCS+= usb_error.c
+SRCS+= usb_handle_request.c
+SRCS+= usb_hid.c
+SRCS+= usb_hub.c
+SRCS+= usb_lookup.c
+SRCS+= usb_msctest.c
+SRCS+= usb_parse.c
+SRCS+= usb_request.c
+SRCS+= usb_transfer.c
+SRCS+= usb_util.c
+SRCS+= usb_template.c
+SRCS+= usb_template_cdce.c
+SRCS+= usb_template_msc.c
+SRCS+= usb_template_mtp.c
+SRCS+= usb_template_modem.c
+SRCS+= usb_template_mouse.c
+SRCS+= usb_template_kbd.c
+SRCS+= usb_template_audio.c
+SRCS+= sysinit_data.c
+SRCS+= sysuninit_data.c
+
+CLEANFILES+= sysinit
+CLEANFILES+= sysinit.bin
+CLEANFILES+= sysinit_data.c
+CLEANFILES+= sysuninit_data.c
+
+CLEANFILES+= ${SRCS:C/\.c/.osys/g}
+
+.include <bsd.lib.mk>
+
+#
+# SYSINIT() and SYSUNINIT() handling
+#
+sysinit: ${T}/sysinit.c
+ ${SYSCC} -Wall -o ${.TARGET} ${.ALLSRC}
+
+sysinit_data.c: sysinit.bin sysinit
+ ${.OBJDIR}/sysinit -i sysinit.bin -o ${.TARGET} -k sysinit -s sysinit_data
+
+sysuninit_data.c: sysinit.bin sysinit
+ ${.OBJDIR}/sysinit -i sysinit.bin -o ${.TARGET} -R -k sysuninit -s sysuninit_data
+
+.for F in ${OBJS}
+${F}sys: ${F}
+ ${OBJCOPY} -j ".debug.sysinit" -O binary ${F} ${.TARGET}
+ [ -f ${.TARGET} ] || touch ${.TARGET}
+.endfor
+
+sysinit.bin: ${OBJS:C/\.o/.osys/g:C/sysinit_data.osys//g:C/sysuninit_data.osys//g}
+ cat ${.ALLSRC} > sysinit.bin
diff --git a/sys/boot/usb/Makefile.test b/sys/boot/usb/Makefile.test
new file mode 100644
index 0000000..a366d36
--- /dev/null
+++ b/sys/boot/usb/Makefile.test
@@ -0,0 +1,61 @@
+#
+# $FreeBSD$
+#
+# Copyright (c) 2013 Hans Petter Selasky. 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.
+#
+
+#
+# USB test application
+#
+
+.PATH: ${.CURDIR}
+
+PROG= usbloader
+MAN=
+SRCS=
+
+CFLAGS+= -Wall
+CFLAGS+= -g
+
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -march=i386
+CFLAGS+= -mpreferred-stack-boundary=2
+.endif
+.if ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -m32
+.endif
+
+LDFLAGS+= -Wl,--gc-sections
+
+SRCS+= bsd_usbloader_test.c
+
+LDADD+= libusbboot.a
+DPADD+= libusbboot.a
+
+all: libusbboot.a
+
+.include <bsd.prog.mk>
+
+libusbboot.a:
+ make -f Makefile
diff --git a/sys/boot/usb/bsd_busspace.c b/sys/boot/usb/bsd_busspace.c
new file mode 100644
index 0000000..c9ba09f
--- /dev/null
+++ b/sys/boot/usb/bsd_busspace.c
@@ -0,0 +1,207 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. 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 <bsd_kernel.h>
+
+struct burst {
+ uint32_t dw0;
+ uint32_t dw1;
+ uint32_t dw2;
+ uint32_t dw3;
+ uint32_t dw4;
+ uint32_t dw5;
+ uint32_t dw6;
+ uint32_t dw7;
+};
+
+void
+bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t *datap, bus_size_t count)
+{
+ while (count--) {
+ *datap++ = bus_space_read_1(t, h, offset);
+ }
+}
+
+void
+bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint16_t *datap, bus_size_t count)
+{
+ while (count--) {
+ *datap++ = bus_space_read_2(t, h, offset);
+ }
+}
+
+void
+bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t *datap, bus_size_t count)
+{
+ h += offset;
+
+ while (count--) {
+ *datap++ = *((volatile uint32_t *)h);
+ }
+}
+
+void
+bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t *datap, bus_size_t count)
+{
+ while (count--) {
+ uint8_t temp = *datap++;
+
+ bus_space_write_1(t, h, offset, temp);
+ }
+}
+
+void
+bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint16_t *datap, bus_size_t count)
+{
+ while (count--) {
+ uint16_t temp = *datap++;
+
+ bus_space_write_2(t, h, offset, temp);
+ }
+}
+
+void
+bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t *datap, bus_size_t count)
+{
+ h += offset;
+
+ while (count--) {
+ *((volatile uint32_t *)h) = *datap++;
+ }
+}
+
+void
+bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t data)
+{
+ *((volatile uint8_t *)(h + offset)) = data;
+}
+
+void
+bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint16_t data)
+{
+ *((volatile uint16_t *)(h + offset)) = data;
+}
+
+void
+bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t data)
+{
+ *((volatile uint32_t *)(h + offset)) = data;
+}
+
+uint8_t
+bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
+{
+ return (*((volatile uint8_t *)(h + offset)));
+}
+
+uint16_t
+bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
+{
+ return (*((volatile uint16_t *)(h + offset)));
+}
+
+uint32_t
+bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
+{
+ return (*((volatile uint32_t *)(h + offset)));
+}
+
+void
+bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t *datap, bus_size_t count)
+{
+ h += offset;
+
+ while (count--) {
+ *datap++ = *((volatile uint8_t *)h);
+ h += 1;
+ }
+}
+
+void
+bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t *datap, bus_size_t count)
+{
+ h += offset;
+
+ while (count--) {
+ *((volatile uint8_t *)h) = *datap++;
+ h += 1;
+ }
+}
+
+void
+bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t *datap, bus_size_t count)
+{
+ enum { BURST = sizeof(struct burst) / 4 };
+
+ h += offset;
+
+ while (count >= BURST) {
+ *(struct burst *)datap = *((/* volatile */ struct burst *)h);
+
+ h += BURST * 4;
+ datap += BURST;
+ count -= BURST;
+ }
+
+ while (count--) {
+ *datap++ = *((volatile uint32_t *)h);
+ h += 4;
+ }
+}
+
+void
+bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t *datap, bus_size_t count)
+{
+ enum { BURST = sizeof(struct burst) / 4 };
+
+ h += offset;
+
+ while (count >= BURST) {
+ *((/* volatile */ struct burst *)h) = *(struct burst *)datap;
+
+ h += BURST * 4;
+ datap += BURST;
+ count -= BURST;
+ }
+
+ while (count--) {
+ *((volatile uint32_t *)h) = *datap++;
+ h += 4;
+ }
+}
diff --git a/sys/boot/usb/bsd_global.h b/sys/boot/usb/bsd_global.h
new file mode 100644
index 0000000..9fe1c8c
--- /dev/null
+++ b/sys/boot/usb/bsd_global.h
@@ -0,0 +1,63 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. 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.
+ */
+
+#ifndef _BSD_GLOBAL_H_
+#define _BSD_GLOBAL_H_
+
+#include <bsd_kernel.h>
+
+#define USB_DEBUG_VAR usb_debug
+#include <dev/usb/usb_freebsd_loader.h>
+#include <dev/usb/usb_endian.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_dynamic.h>
+#include <dev/usb/usb_device.h>
+#include <dev/usb/usb_hub.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_cdc.h>
+#include <dev/usb/usb_dev.h>
+#include <dev/usb/usb_mbuf.h>
+#include <dev/usb/usb_msctest.h>
+#include <dev/usb/usb_pci.h>
+#include <dev/usb/usb_pf.h>
+#include <dev/usb/usb_request.h>
+#include <dev/usb/usb_util.h>
+#include <dev/usb/usb_transfer.h>
+#include <dev/usb/usb_compat_linux.h>
+#include <dev/usb/usbhid.h>
+#include <dev/usb/usb_ioctl.h>
+#include <dev/usb/usb_generic.h>
+#include <dev/usb/quirk/usb_quirk.h>
+#include <dev/usb/template/usb_template.h>
+
+#endif /* _BSD_GLOBAL_H_ */
diff --git a/sys/boot/usb/bsd_kernel.c b/sys/boot/usb/bsd_kernel.c
new file mode 100644
index 0000000..5f24c2d
--- /dev/null
+++ b/sys/boot/usb/bsd_kernel.c
@@ -0,0 +1,1269 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. 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 <bsd_global.h>
+
+static struct usb_process usb_process[USB_PROC_MAX];
+static device_t usb_pci_root;
+
+/*------------------------------------------------------------------------*
+ * Implementation of mutex API
+ *------------------------------------------------------------------------*/
+
+struct mtx Giant;
+
+static void
+mtx_system_init(void *arg)
+{
+ mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE);
+}
+SYSINIT(mtx_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, mtx_system_init, NULL);
+
+void
+mtx_init(struct mtx *mtx, const char *name, const char *type, int opt)
+{
+ mtx->owned = 0;
+ mtx->parent = mtx;
+}
+
+void
+mtx_lock(struct mtx *mtx)
+{
+ mtx = mtx->parent;
+ mtx->owned++;
+}
+
+void
+mtx_unlock(struct mtx *mtx)
+{
+ mtx = mtx->parent;
+ mtx->owned--;
+}
+
+int
+mtx_owned(struct mtx *mtx)
+{
+ mtx = mtx->parent;
+ return (mtx->owned != 0);
+}
+
+void
+mtx_destroy(struct mtx *mtx)
+{
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * Implementation of shared/exclusive mutex API
+ *------------------------------------------------------------------------*/
+
+void
+sx_init_flags(struct sx *sx, const char *name, int flags)
+{
+ sx->owned = 0;
+}
+
+void
+sx_destroy(struct sx *sx)
+{
+ /* NOP */
+}
+
+void
+sx_xlock(struct sx *sx)
+{
+ sx->owned++;
+}
+
+void
+sx_xunlock(struct sx *sx)
+{
+ sx->owned--;
+}
+
+int
+sx_xlocked(struct sx *sx)
+{
+ return (sx->owned != 0);
+}
+
+/*------------------------------------------------------------------------*
+ * Implementaiton of condition variable API
+ *------------------------------------------------------------------------*/
+
+void
+cv_init(struct cv *cv, const char *desc)
+{
+ cv->sleeping = 0;
+}
+
+void
+cv_destroy(struct cv *cv)
+{
+ /* NOP */
+}
+
+void
+cv_wait(struct cv *cv, struct mtx *mtx)
+{
+ cv_timedwait(cv, mtx, -1);
+}
+
+int
+cv_timedwait(struct cv *cv, struct mtx *mtx, int timo)
+{
+ int start = ticks;
+ int delta;
+
+ if (cv->sleeping)
+ return (EWOULDBLOCK); /* not allowed */
+
+ cv->sleeping = 1;
+
+ while (cv->sleeping) {
+ if (timo >= 0) {
+ delta = ticks - start;
+ if (delta >= timo || delta < 0)
+ break;
+ }
+ mtx_unlock(mtx);
+
+ usb_idle();
+
+ mtx_lock(mtx);
+ }
+
+ if (cv->sleeping) {
+ cv->sleeping = 0;
+ return (EWOULDBLOCK); /* not allowed */
+ }
+ return (0);
+}
+
+void
+cv_signal(struct cv *cv)
+{
+ cv->sleeping = 0;
+}
+
+void
+cv_broadcast(struct cv *cv)
+{
+ cv->sleeping = 0;
+}
+
+/*------------------------------------------------------------------------*
+ * Implementation of callout API
+ *------------------------------------------------------------------------*/
+
+static void callout_proc_msg(struct usb_proc_msg *);
+
+volatile int ticks = 0;
+
+static LIST_HEAD(, callout) head_callout = LIST_HEAD_INITIALIZER(&head_callout);
+
+static struct mtx mtx_callout;
+static struct usb_proc_msg callout_msg[2];
+
+static void
+callout_system_init(void *arg)
+{
+ mtx_init(&mtx_callout, "callout-mtx", NULL, MTX_DEF | MTX_RECURSE);
+
+ callout_msg[0].pm_callback = &callout_proc_msg;
+ callout_msg[1].pm_callback = &callout_proc_msg;
+}
+SYSINIT(callout_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, callout_system_init, NULL);
+
+static void
+callout_callback(struct callout *c)
+{
+ mtx_lock(c->mtx);
+
+ mtx_lock(&mtx_callout);
+ if (c->entry.le_prev != NULL) {
+ LIST_REMOVE(c, entry);
+ c->entry.le_prev = NULL;
+ }
+ mtx_unlock(&mtx_callout);
+
+ if (c->func)
+ (c->func) (c->arg);
+
+ if (!(c->flags & CALLOUT_RETURNUNLOCKED))
+ mtx_unlock(c->mtx);
+}
+
+void
+callout_process(int timeout)
+{
+ ticks += timeout;
+ usb_proc_msignal(usb_process + 2, &callout_msg[0], &callout_msg[1]);
+}
+
+static void
+callout_proc_msg(struct usb_proc_msg *pmsg)
+{
+ struct callout *c;
+ int delta;
+
+repeat:
+ mtx_lock(&mtx_callout);
+
+ LIST_FOREACH(c, &head_callout, entry) {
+
+ delta = c->timeout - ticks;
+ if (delta < 0) {
+ mtx_unlock(&mtx_callout);
+
+ callout_callback(c);
+
+ goto repeat;
+ }
+ }
+ mtx_unlock(&mtx_callout);
+}
+
+void
+callout_init_mtx(struct callout *c, struct mtx *mtx, int flags)
+{
+ memset(c, 0, sizeof(*c));
+
+ if (mtx == NULL)
+ mtx = &Giant;
+
+ c->mtx = mtx;
+ c->flags = (flags & CALLOUT_RETURNUNLOCKED);
+}
+
+void
+callout_reset(struct callout *c, int to_ticks,
+ void (*func) (void *), void *arg)
+{
+ callout_stop(c);
+
+ c->func = func;
+ c->arg = arg;
+ c->timeout = ticks + to_ticks;
+
+ mtx_lock(&mtx_callout);
+ LIST_INSERT_HEAD(&head_callout, c, entry);
+ mtx_unlock(&mtx_callout);
+}
+
+void
+callout_stop(struct callout *c)
+{
+ mtx_lock(&mtx_callout);
+
+ if (c->entry.le_prev != NULL) {
+ LIST_REMOVE(c, entry);
+ c->entry.le_prev = NULL;
+ }
+ mtx_unlock(&mtx_callout);
+
+ c->func = NULL;
+ c->arg = NULL;
+}
+
+void
+callout_drain(struct callout *c)
+{
+ if (c->mtx == NULL)
+ return; /* not initialised */
+
+ mtx_lock(c->mtx);
+ callout_stop(c);
+ mtx_unlock(c->mtx);
+}
+
+int
+callout_pending(struct callout *c)
+{
+ int retval;
+
+ mtx_lock(&mtx_callout);
+ retval = (c->entry.le_prev != NULL);
+ mtx_unlock(&mtx_callout);
+
+ return (retval);
+}
+
+/*------------------------------------------------------------------------*
+ * Implementation of device API
+ *------------------------------------------------------------------------*/
+
+static const char unknown_string[] = { "unknown" };
+
+static TAILQ_HEAD(, module_data) module_head =
+ TAILQ_HEAD_INITIALIZER(module_head);
+
+static uint8_t
+devclass_equal(const char *a, const char *b)
+{
+ char ta, tb;
+
+ if (a == b)
+ return (1);
+
+ while (1) {
+ ta = *a;
+ tb = *b;
+ if (ta != tb)
+ return (0);
+ if (ta == 0)
+ break;
+ a++;
+ b++;
+ }
+ return (1);
+}
+
+int
+bus_generic_resume(device_t dev)
+{
+ return (0);
+}
+
+int
+bus_generic_shutdown(device_t dev)
+{
+ return (0);
+}
+
+int
+bus_generic_suspend(device_t dev)
+{
+ return (0);
+}
+
+int
+bus_generic_print_child(device_t dev, device_t child)
+{
+ return (0);
+}
+
+void
+bus_generic_driver_added(device_t dev, driver_t *driver)
+{
+ return;
+}
+
+device_t
+device_get_parent(device_t dev)
+{
+ return (dev ? dev->dev_parent : NULL);
+}
+
+void
+device_set_interrupt(device_t dev, intr_fn_t *fn, void *arg)
+{
+ dev->dev_irq_fn = fn;
+ dev->dev_irq_arg = arg;
+}
+
+void
+device_run_interrupts(device_t parent)
+{
+ device_t child;
+
+ if (parent == NULL)
+ return;
+
+ TAILQ_FOREACH(child, &parent->dev_children, dev_link) {
+ if (child->dev_irq_fn != NULL)
+ (child->dev_irq_fn) (child->dev_irq_arg);
+ }
+}
+
+void
+device_set_ivars(device_t dev, void *ivars)
+{
+ dev->dev_aux = ivars;
+}
+
+void *
+device_get_ivars(device_t dev)
+{
+ return (dev ? dev->dev_aux : NULL);
+}
+
+int
+device_get_unit(device_t dev)
+{
+ return (dev ? dev->dev_unit : 0);
+}
+
+int
+bus_generic_detach(device_t dev)
+{
+ device_t child;
+ int error;
+
+ if (!dev->dev_attached)
+ return (EBUSY);
+
+ TAILQ_FOREACH(child, &dev->dev_children, dev_link) {
+ if ((error = device_detach(child)) != 0)
+ return (error);
+ }
+ return (0);
+}
+
+const char *
+device_get_nameunit(device_t dev)
+{
+ if (dev && dev->dev_nameunit[0])
+ return (dev->dev_nameunit);
+
+ return (unknown_string);
+}
+
+static uint8_t
+devclass_create(devclass_t *dc_pp)
+{
+ if (dc_pp == NULL) {
+ return (1);
+ }
+ if (dc_pp[0] == NULL) {
+ dc_pp[0] = malloc(sizeof(**(dc_pp)),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+ if (dc_pp[0] == NULL) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static const struct module_data *
+devclass_find_create(const char *classname)
+{
+ const struct module_data *mod;
+
+ TAILQ_FOREACH(mod, &module_head, entry) {
+ if (devclass_equal(mod->mod_name, classname)) {
+ if (devclass_create(mod->devclass_pp)) {
+ continue;
+ }
+ return (mod);
+ }
+ }
+ return (NULL);
+}
+
+static uint8_t
+devclass_add_device(const struct module_data *mod, device_t dev)
+{
+ device_t *pp_dev;
+ device_t *end;
+ uint8_t unit;
+
+ pp_dev = mod->devclass_pp[0]->dev_list;
+ end = pp_dev + DEVCLASS_MAXUNIT;
+ unit = 0;
+
+ while (pp_dev != end) {
+ if (*pp_dev == NULL) {
+ *pp_dev = dev;
+ dev->dev_unit = unit;
+ dev->dev_module = mod;
+ snprintf(dev->dev_nameunit,
+ sizeof(dev->dev_nameunit),
+ "%s%d", device_get_name(dev), unit);
+ return (0);
+ }
+ pp_dev++;
+ unit++;
+ }
+ DPRINTF("Could not add device to devclass.\n");
+ return (1);
+}
+
+static void
+devclass_delete_device(const struct module_data *mod, device_t dev)
+{
+ if (mod == NULL) {
+ return;
+ }
+ mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL;
+ dev->dev_module = NULL;
+}
+
+static device_t
+make_device(device_t parent, const char *name)
+{
+ device_t dev = NULL;
+ const struct module_data *mod = NULL;
+
+ if (name) {
+
+ mod = devclass_find_create(name);
+
+ if (!mod) {
+
+ DPRINTF("%s:%d:%s: can't find device "
+ "class %s\n", __FILE__, __LINE__,
+ __FUNCTION__, name);
+
+ goto done;
+ }
+ }
+ dev = malloc(sizeof(*dev),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+ if (dev == NULL)
+ goto done;
+
+ dev->dev_parent = parent;
+ TAILQ_INIT(&dev->dev_children);
+
+ if (name) {
+ dev->dev_fixed_class = 1;
+ if (devclass_add_device(mod, dev)) {
+ goto error;
+ }
+ }
+done:
+ return (dev);
+
+error:
+ if (dev) {
+ free(dev, M_DEVBUF);
+ }
+ return (NULL);
+}
+
+device_t
+device_add_child(device_t dev, const char *name, int unit)
+{
+ device_t child;
+
+ if (unit != -1) {
+ device_printf(dev, "Unit is not -1\n");
+ }
+ child = make_device(dev, name);
+ if (child == NULL) {
+ device_printf(dev, "Could not add child '%s'\n", name);
+ goto done;
+ }
+ if (dev == NULL) {
+ /* no parent */
+ goto done;
+ }
+ TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link);
+done:
+ return (child);
+}
+
+int
+device_delete_child(device_t dev, device_t child)
+{
+ int error = 0;
+ device_t grandchild;
+
+ /* remove children first */
+
+ while ((grandchild = TAILQ_FIRST(&child->dev_children))) {
+ error = device_delete_child(child, grandchild);
+ if (error) {
+ device_printf(dev, "Error deleting child!\n");
+ goto done;
+ }
+ }
+
+ error = device_detach(child);
+
+ if (error)
+ goto done;
+
+ devclass_delete_device(child->dev_module, child);
+
+ if (dev != NULL) {
+ /* remove child from parent */
+ TAILQ_REMOVE(&dev->dev_children, child, dev_link);
+ }
+ free(child, M_DEVBUF);
+
+done:
+ return (error);
+}
+
+int
+device_delete_children(device_t dev)
+{
+ device_t child;
+ int error = 0;
+
+ while ((child = TAILQ_FIRST(&dev->dev_children))) {
+ error = device_delete_child(dev, child);
+ if (error) {
+ device_printf(dev, "Error deleting child!\n");
+ break;
+ }
+ }
+ return (error);
+}
+
+void
+device_quiet(device_t dev)
+{
+ dev->dev_quiet = 1;
+}
+
+const char *
+device_get_desc(device_t dev)
+{
+ if (dev)
+ return &(dev->dev_desc[0]);
+ return (unknown_string);
+}
+
+static int
+default_method(void)
+{
+ /* do nothing */
+ DPRINTF("Default method called\n");
+ return (0);
+}
+
+void *
+device_get_method(device_t dev, const char *what)
+{
+ const struct device_method *mtod;
+
+ mtod = dev->dev_module->driver->methods;
+ while (mtod->func != NULL) {
+ if (devclass_equal(mtod->desc, what)) {
+ return (mtod->func);
+ }
+ mtod++;
+ }
+ return ((void *)&default_method);
+}
+
+const char *
+device_get_name(device_t dev)
+{
+ if (dev == NULL)
+ return (unknown_string);
+
+ return (dev->dev_module->driver->name);
+}
+
+static int
+device_allocate_softc(device_t dev)
+{
+ const struct module_data *mod;
+
+ mod = dev->dev_module;
+
+ if ((dev->dev_softc_alloc == 0) &&
+ (mod->driver->size != 0)) {
+ dev->dev_sc = malloc(mod->driver->size,
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+ if (dev->dev_sc == NULL)
+ return (ENOMEM);
+
+ dev->dev_softc_alloc = 1;
+ }
+ return (0);
+}
+
+int
+device_probe_and_attach(device_t dev)
+{
+ const struct module_data *mod;
+ const char *bus_name_parent;
+
+ bus_name_parent = device_get_name(device_get_parent(dev));
+
+ if (dev->dev_attached)
+ return (0); /* fail-safe */
+
+ if (dev->dev_fixed_class) {
+
+ mod = dev->dev_module;
+
+ if (DEVICE_PROBE(dev) <= 0) {
+
+ if (device_allocate_softc(dev) == 0) {
+
+ if (DEVICE_ATTACH(dev) == 0) {
+ /* success */
+ dev->dev_attached = 1;
+ return (0);
+ }
+ }
+ }
+ device_detach(dev);
+
+ goto error;
+ }
+ /*
+ * Else find a module for our device, if any
+ */
+
+ TAILQ_FOREACH(mod, &module_head, entry) {
+ if (devclass_equal(mod->bus_name, bus_name_parent)) {
+ if (devclass_create(mod->devclass_pp)) {
+ continue;
+ }
+ if (devclass_add_device(mod, dev)) {
+ continue;
+ }
+ if (DEVICE_PROBE(dev) <= 0) {
+
+ if (device_allocate_softc(dev) == 0) {
+
+ if (DEVICE_ATTACH(dev) == 0) {
+ /* success */
+ dev->dev_attached = 1;
+ return (0);
+ }
+ }
+ }
+ /* else try next driver */
+
+ device_detach(dev);
+ }
+ }
+
+error:
+ return (ENODEV);
+}
+
+int
+device_detach(device_t dev)
+{
+ const struct module_data *mod = dev->dev_module;
+ int error;
+
+ if (dev->dev_attached) {
+
+ error = DEVICE_DETACH(dev);
+ if (error) {
+ return error;
+ }
+ dev->dev_attached = 0;
+ }
+ device_set_softc(dev, NULL);
+
+ if (dev->dev_fixed_class == 0)
+ devclass_delete_device(mod, dev);
+
+ return (0);
+}
+
+void
+device_set_softc(device_t dev, void *softc)
+{
+ if (dev->dev_softc_alloc) {
+ free(dev->dev_sc, M_DEVBUF);
+ dev->dev_sc = NULL;
+ }
+ dev->dev_sc = softc;
+ dev->dev_softc_alloc = 0;
+}
+
+void *
+device_get_softc(device_t dev)
+{
+ if (dev == NULL)
+ return (NULL);
+
+ return (dev->dev_sc);
+}
+
+int
+device_is_attached(device_t dev)
+{
+ return (dev->dev_attached);
+}
+
+void
+device_set_desc(device_t dev, const char *desc)
+{
+ snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc);
+}
+
+void
+device_set_desc_copy(device_t dev, const char *desc)
+{
+ device_set_desc(dev, desc);
+}
+
+void *
+devclass_get_softc(devclass_t dc, int unit)
+{
+ return (device_get_softc(devclass_get_device(dc, unit)));
+}
+
+int
+devclass_get_maxunit(devclass_t dc)
+{
+ int max_unit = 0;
+
+ if (dc) {
+ max_unit = DEVCLASS_MAXUNIT;
+ while (max_unit--) {
+ if (dc->dev_list[max_unit]) {
+ break;
+ }
+ }
+ max_unit++;
+ }
+ return (max_unit);
+}
+
+device_t
+devclass_get_device(devclass_t dc, int unit)
+{
+ return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ?
+ NULL : dc->dev_list[unit]);
+}
+
+devclass_t
+devclass_find(const char *classname)
+{
+ const struct module_data *mod;
+
+ TAILQ_FOREACH(mod, &module_head, entry) {
+ if (devclass_equal(mod->mod_name, classname))
+ return (mod->devclass_pp[0]);
+ }
+ return (NULL);
+}
+
+void
+module_register(void *data)
+{
+ struct module_data *mdata = data;
+
+ TAILQ_INSERT_TAIL(&module_head, mdata, entry);
+}
+
+/*------------------------------------------------------------------------*
+ * System startup
+ *------------------------------------------------------------------------*/
+
+static void
+sysinit_run(const void **ppdata)
+{
+ const struct sysinit *psys;
+
+ while ((psys = *ppdata) != NULL) {
+ (psys->func) (psys->data);
+ ppdata++;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * USB process API
+ *------------------------------------------------------------------------*/
+
+static int usb_do_process(struct usb_process *);
+static int usb_proc_level = -1;
+static struct mtx usb_proc_mtx;
+
+void
+usb_idle(void)
+{
+ int old_level = usb_proc_level;
+ int old_giant = Giant.owned;
+ int worked;
+
+ device_run_interrupts(usb_pci_root);
+
+ do {
+ worked = 0;
+ Giant.owned = 0;
+
+ while (++usb_proc_level < USB_PROC_MAX)
+ worked |= usb_do_process(usb_process + usb_proc_level);
+
+ usb_proc_level = old_level;
+ Giant.owned = old_giant;
+
+ } while (worked);
+}
+
+void
+usb_init(void)
+{
+ sysinit_run(sysinit_data);
+}
+
+void
+usb_uninit(void)
+{
+ sysinit_run(sysuninit_data);
+}
+
+static void
+usb_process_init_sub(struct usb_process *up)
+{
+ TAILQ_INIT(&up->up_qhead);
+
+ cv_init(&up->up_cv, "-");
+ cv_init(&up->up_drain, "usbdrain");
+
+ up->up_mtx = &usb_proc_mtx;
+}
+
+static void
+usb_process_init(void *arg)
+{
+ uint8_t x;
+
+ mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE);
+
+ for (x = 0; x != USB_PROC_MAX; x++)
+ usb_process_init_sub(&usb_process[x]);
+
+}
+SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL);
+
+static int
+usb_do_process(struct usb_process *up)
+{
+ struct usb_proc_msg *pm;
+ int worked = 0;
+
+ mtx_lock(&usb_proc_mtx);
+
+repeat:
+ pm = TAILQ_FIRST(&up->up_qhead);
+
+ if (pm != NULL) {
+
+ worked = 1;
+
+ (pm->pm_callback) (pm);
+
+ if (pm == TAILQ_FIRST(&up->up_qhead)) {
+ /* nothing changed */
+ TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry);
+ pm->pm_qentry.tqe_prev = NULL;
+ }
+ goto repeat;
+ }
+ mtx_unlock(&usb_proc_mtx);
+
+ return (worked);
+}
+
+int
+usb_proc_create(struct usb_process *up, struct mtx *p_mtx,
+ const char *pmesg, uint8_t prio)
+{
+#define USB_PROC_OFFSET(a,b) \
+ ((int)(((long)&((struct usb_bus *)0)->a) - \
+ ((long)&((struct usb_bus *)0)->b)))
+
+ /* figure out which process we are creating */
+ switch ((int)((long)up - (long)p_mtx)) {
+ case USB_PROC_OFFSET(giant_callback_proc, bus_mtx):
+ up->up_ptr = (void *)(usb_process + 2);
+ break;
+ case USB_PROC_OFFSET(non_giant_callback_proc, bus_mtx):
+ up->up_ptr = (void *)(usb_process + 2);
+ break;
+ case USB_PROC_OFFSET(explore_proc, bus_mtx):
+ up->up_ptr = (void *)(usb_process + 0);
+ break;
+ case USB_PROC_OFFSET(control_xfer_proc, bus_mtx):
+ up->up_ptr = (void *)(usb_process + 1);
+ break;
+ default:
+ up->up_ptr = (void *)(usb_process + 1);
+ break;
+ }
+ return (0); /* success */
+}
+
+void
+usb_proc_free(struct usb_process *up)
+{
+ /* NOP */
+}
+
+void *
+usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1)
+{
+ struct usb_proc_msg *pm0 = _pm0;
+ struct usb_proc_msg *pm1 = _pm1;
+ struct usb_proc_msg *pm2;
+ usb_size_t d;
+ uint8_t t;
+
+ /* find the correct parent */
+ while (up->up_ptr != NULL)
+ up = (struct usb_process *)up->up_ptr;
+
+ t = 0;
+
+ if (pm0->pm_qentry.tqe_prev) {
+ t |= 1;
+ }
+ if (pm1->pm_qentry.tqe_prev) {
+ t |= 2;
+ }
+ if (t == 0) {
+ /*
+ * No entries are queued. Queue "pm0" and use the existing
+ * message number.
+ */
+ pm2 = pm0;
+ } else if (t == 1) {
+ /* Check if we need to increment the message number. */
+ if (pm0->pm_num == up->up_msg_num) {
+ up->up_msg_num++;
+ }
+ pm2 = pm1;
+ } else if (t == 2) {
+ /* Check if we need to increment the message number. */
+ if (pm1->pm_num == up->up_msg_num) {
+ up->up_msg_num++;
+ }
+ pm2 = pm0;
+ } else if (t == 3) {
+ /*
+ * Both entries are queued. Re-queue the entry closest to
+ * the end.
+ */
+ d = (pm1->pm_num - pm0->pm_num);
+
+ /* Check sign after subtraction */
+ if (d & 0x80000000) {
+ pm2 = pm0;
+ } else {
+ pm2 = pm1;
+ }
+
+ TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
+ } else {
+ pm2 = NULL; /* panic - should not happen */
+ }
+
+ /* Put message last on queue */
+
+ pm2->pm_num = up->up_msg_num;
+ TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
+
+ return (pm2);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_proc_is_gone
+ *
+ * Return values:
+ * 0: USB process is running
+ * Else: USB process is tearing down
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_proc_is_gone(struct usb_process *up)
+{
+ return (0);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_proc_mwait
+ *
+ * This function will return when the USB process message pointed to
+ * by "pm" is no longer on a queue. This function must be called
+ * having "usb_proc_mtx" locked.
+ *------------------------------------------------------------------------*/
+void
+usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
+{
+ struct usb_proc_msg *pm0 = _pm0;
+ struct usb_proc_msg *pm1 = _pm1;
+
+ /* find the correct parent */
+ while (up->up_ptr != NULL)
+ up = (struct usb_process *)up->up_ptr;
+
+ /* Just remove the messages from the queue. */
+ if (pm0->pm_qentry.tqe_prev) {
+ TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
+ pm0->pm_qentry.tqe_prev = NULL;
+ }
+ if (pm1->pm_qentry.tqe_prev) {
+ TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
+ pm1->pm_qentry.tqe_prev = NULL;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * SYSTEM attach
+ *------------------------------------------------------------------------*/
+
+static device_method_t pci_methods[] = {
+ DEVMETHOD_END
+};
+
+static driver_t pci_driver = {
+ .name = "pci",
+ .methods = pci_methods,
+};
+
+static devclass_t pci_devclass;
+
+DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0);
+
+static const char *usb_pci_devices[] = {
+#ifdef USB_PROBE_LIST
+ USB_PROBE_LIST
+#endif
+};
+
+#define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *))
+
+static device_t usb_pci_dev[USB_PCI_USB_MAX];
+
+static void
+usb_pci_mod_load(void *arg)
+{
+ uint32_t x;
+
+ usb_pci_root = device_add_child(NULL, "pci", -1);
+ if (usb_pci_root == NULL)
+ return;
+
+ for (x = 0; x != USB_PCI_USB_MAX; x++) {
+ usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1);
+ if (usb_pci_dev[x] == NULL)
+ continue;
+ if (device_probe_and_attach(usb_pci_dev[x])) {
+ device_printf(usb_pci_dev[x],
+ "WARNING: Probe and attach failed!\n");
+ }
+ }
+}
+SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0);
+
+static void
+usb_pci_mod_unload(void *arg)
+{
+ uint32_t x;
+
+ for (x = 0; x != USB_PCI_USB_MAX; x++) {
+ if (usb_pci_dev[x]) {
+ device_detach(usb_pci_dev[x]);
+ device_delete_child(usb_pci_root, usb_pci_dev[x]);
+ }
+ }
+ if (usb_pci_root)
+ device_delete_child(NULL, usb_pci_root);
+}
+SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0);
+
+/*------------------------------------------------------------------------*
+ * MALLOC API
+ *------------------------------------------------------------------------*/
+
+#define USB_POOL_ALIGN 8
+
+static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN);
+static uint32_t usb_pool_rem = USB_POOL_SIZE;
+static uint32_t usb_pool_entries;
+
+struct malloc_hdr {
+ TAILQ_ENTRY(malloc_hdr) entry;
+ uint32_t size;
+} __aligned(USB_POOL_ALIGN);
+
+static TAILQ_HEAD(, malloc_hdr) malloc_head =
+ TAILQ_HEAD_INITIALIZER(malloc_head);
+
+void *
+usb_malloc(unsigned long size)
+{
+ struct malloc_hdr *hdr;
+
+ size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1);
+ size += sizeof(struct malloc_hdr);
+
+ TAILQ_FOREACH(hdr, &malloc_head, entry) {
+ if (hdr->size == size)
+ break;
+ }
+
+ if (hdr) {
+ printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
+ (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
+
+ TAILQ_REMOVE(&malloc_head, hdr, entry);
+ memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
+ return (hdr + 1);
+ }
+ if (usb_pool_rem >= size) {
+ hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem);
+ hdr->size = size;
+
+ usb_pool_rem -= size;
+ usb_pool_entries++;
+
+ printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
+ (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
+
+ memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
+ return (hdr + 1);
+ }
+ return (NULL);
+}
+
+void
+usb_free(void *arg)
+{
+ struct malloc_hdr *hdr;
+
+ if (arg == NULL)
+ return;
+
+ hdr = arg;
+ hdr--;
+
+ TAILQ_INSERT_TAIL(&malloc_head, hdr, entry);
+}
+
+char *
+usb_strdup(const char *str)
+{
+ char *tmp;
+ int len;
+
+ len = 1 + strlen(str);
+
+ tmp = usb_malloc(len);
+ if (tmp == NULL)
+ return (NULL);
+
+ memcpy(tmp, str, len);
+ return (tmp);
+}
diff --git a/sys/boot/usb/bsd_kernel.h b/sys/boot/usb/bsd_kernel.h
new file mode 100644
index 0000000..4c94721
--- /dev/null
+++ b/sys/boot/usb/bsd_kernel.h
@@ -0,0 +1,458 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2011 Hans Petter Selasky. 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.
+ */
+
+#ifndef _BSD_KERNEL_H_
+#define _BSD_KERNEL_H_
+
+#define _KERNEL
+#define __FreeBSD_version 1000000
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+#include <sys/errno.h>
+
+#define isalpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
+#define isdigit(x) ((x) >= '0' && (x) <= '9')
+#define panic(...) do { printf("USB PANIC: " __VA_ARGS__); while (1) ; } while (0)
+#define M_USB 0
+#define M_USBDEV 0
+#define USB_PROC_MAX 3
+#define SYSCTL_DECL(...)
+#define SYSCTL_NODE(name,...) struct { } name __used
+#define SYSCTL_INT(...)
+#define TUNABLE_INT(...)
+#define MALLOC_DECLARE(...)
+#define MALLOC_DEFINE(...)
+#define EVENTHANDLER_DECLARE(...)
+#define EVENTHANDLER_INVOKE(...)
+#define KASSERT(...)
+#define SCHEDULER_STOPPED(x) (0)
+#define PI_SWI(...) (0)
+#define UNIQ_NAME(x) x
+#define UNIQ_NAME_STR(x) #x
+#define DEVCLASS_MAXUNIT 32
+#define MOD_LOAD 1
+#define MOD_UNLOAD 2
+#define DEVMETHOD(what,func) { #what, (void *)&func }
+#define DEVMETHOD_END {0,0}
+#define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \
+ static struct module_data bsd_##name##_##busname##_driver_mod = { \
+ evh, arg, #busname, #name, #busname "/" #name, \
+ &driver, &devclass, { 0, 0 } }; \
+SYSINIT(bsd_##name##_##busname##_driver_mod, SI_SUB_DRIVERS, \
+ SI_ORDER_MIDDLE, module_register, \
+ &bsd_##name##_##busname##_driver_mod)
+#define SYSINIT(uniq, subs, order, _func, _data) \
+const struct sysinit UNIQ_NAME(sysinit_##uniq) = { \
+ .func = (_func), \
+ .data = __DECONST(void *, _data) \
+}; \
+SYSINIT_ENTRY(uniq##_entry, "sysinit", (subs), \
+ (order), "const struct sysinit", \
+ UNIQ_NAME_STR(sysinit_##uniq), "SYSINIT")
+
+#define SYSUNINIT(uniq, subs, order, _func, _data) \
+const struct sysinit UNIQ_NAME(sysuninit_##uniq) = { \
+ .func = (_func), \
+ .data = __DECONST(void *, _data) \
+}; \
+SYSINIT_ENTRY(uniq##_entry, "sysuninit", (subs), \
+ (order), "const struct sysuninit", \
+ UNIQ_NAME_STR(sysuninit_##uniq), "SYSUNINIT")
+#define MODULE_DEPEND(...)
+#define MODULE_VERSION(...)
+#define NULL ((void *)0)
+#define BUS_SPACE_BARRIER_READ 0x01
+#define BUS_SPACE_BARRIER_WRITE 0x02
+#define hz 1000
+#define PAGE_SIZE 4096
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define MTX_DEF 0
+#define MTX_RECURSE 0
+#define SX_DUPOK 0
+#define SX_NOWITNESS 0
+#define WITNESS_WARN(...)
+#define cold 0
+#define BUS_PROBE_GENERIC 0
+#define CALLOUT_RETURNUNLOCKED 0x1
+#define va_list __builtin_va_list
+#define va_size(type) __builtin_va_size(type)
+#define va_start(ap, last) __builtin_va_start(ap, last)
+#define va_end(ap) __builtin_va_end(ap)
+#define va_arg(ap, type) __builtin_va_arg((ap), type)
+#define DEVICE_ATTACH(dev, ...) \
+ (((device_attach_t *)(device_get_method(dev, "device_attach")))(dev,## __VA_ARGS__))
+#define DEVICE_DETACH(dev, ...) \
+ (((device_detach_t *)(device_get_method(dev, "device_detach")))(dev,## __VA_ARGS__))
+#define DEVICE_PROBE(dev, ...) \
+ (((device_probe_t *)(device_get_method(dev, "device_probe")))(dev,## __VA_ARGS__))
+#define DEVICE_RESUME(dev, ...) \
+ (((device_resume_t *)(device_get_method(dev, "device_resume")))(dev,## __VA_ARGS__))
+#define DEVICE_SHUTDOWN(dev, ...) \
+ (((device_shutdown_t *)(device_get_method(dev, "device_shutdown")))(dev,## __VA_ARGS__))
+#define DEVICE_SUSPEND(dev, ...) \
+ (((device_suspend_t *)(device_get_method(dev, "device_suspend")))(dev,## __VA_ARGS__))
+#define USB_HANDLE_REQUEST(dev, ...) \
+ (((usb_handle_request_t *)(device_get_method(dev, "usb_handle_request")))(dev,## __VA_ARGS__))
+#define USB_TAKE_CONTROLLER(dev, ...) \
+ (((usb_take_controller_t *)(device_get_method(dev, "usb_take_controller")))(dev,## __VA_ARGS__))
+
+enum {
+ SI_SUB_DUMMY = 0x0000000,
+ SI_SUB_LOCK = 0x1B00000,
+ SI_SUB_KLD = 0x2000000,
+ SI_SUB_DRIVERS = 0x3100000,
+ SI_SUB_PSEUDO = 0x7000000,
+ SI_SUB_KICK_SCHEDULER = 0xa000000,
+ SI_SUB_RUN_SCHEDULER = 0xfffffff
+};
+
+enum {
+ SI_ORDER_FIRST = 0x0000000,
+ SI_ORDER_SECOND = 0x0000001,
+ SI_ORDER_THIRD = 0x0000002,
+ SI_ORDER_FOURTH = 0x0000003,
+ SI_ORDER_MIDDLE = 0x1000000,
+ SI_ORDER_ANY = 0xfffffff /* last */
+};
+
+struct uio;
+struct thread;
+struct malloc_type;
+struct usb_process;
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+
+typedef unsigned long long uint64_t;
+typedef signed long long int64_t;
+
+typedef unsigned long bus_addr_t;
+typedef unsigned long bus_size_t;
+
+typedef unsigned long size_t;
+typedef unsigned long u_long;
+
+typedef void *bus_dmamap_t;
+typedef void *bus_dma_tag_t;
+
+typedef void *bus_space_tag_t;
+typedef uint8_t *bus_space_handle_t;
+
+typedef uint16_t uid_t;
+typedef uint16_t gid_t;
+typedef uint16_t mode_t;
+
+typedef uint8_t *caddr_t;
+typedef unsigned long __uintptr_t;
+typedef unsigned long uintptr_t;
+
+/* SYSINIT API */
+
+#include <sysinit.h>
+
+struct sysinit {
+ void (*func) (void *arg);
+ void *data;
+};
+
+/* MUTEX API */
+
+struct mtx {
+ int owned;
+ struct mtx *parent;
+};
+
+#define mtx_assert(...) do { } while (0)
+void mtx_init(struct mtx *, const char *, const char *, int);
+void mtx_lock(struct mtx *);
+void mtx_unlock(struct mtx *);
+int mtx_owned(struct mtx *);
+void mtx_destroy(struct mtx *);
+
+extern struct mtx Giant;
+
+/* SX API */
+
+struct sx {
+ int owned;
+};
+
+#define sx_assert(...) do { } while (0)
+#define sx_init(...) sx_init_flags(__VA_ARGS__, 0)
+void sx_init_flags(struct sx *, const char *, int);
+void sx_destroy(struct sx *);
+void sx_xlock(struct sx *);
+void sx_xunlock(struct sx *);
+int sx_xlocked(struct sx *);
+
+/* CONDVAR API */
+
+struct cv {
+ int sleeping;
+};
+
+void cv_init(struct cv *, const char *desc);
+void cv_destroy(struct cv *);
+void cv_wait(struct cv *, struct mtx *);
+int cv_timedwait(struct cv *, struct mtx *, int);
+void cv_signal(struct cv *);
+void cv_broadcast(struct cv *);
+
+/* CALLOUT API */
+
+typedef void callout_fn_t (void *);
+
+extern volatile int ticks;
+
+struct callout {
+ LIST_ENTRY(callout) entry;
+ callout_fn_t *func;
+ void *arg;
+ struct mtx *mtx;
+ int flags;
+ int timeout;
+};
+
+void callout_init_mtx(struct callout *, struct mtx *, int);
+void callout_reset(struct callout *, int, callout_fn_t *, void *);
+void callout_stop(struct callout *);
+void callout_drain(struct callout *);
+int callout_pending(struct callout *);
+void callout_process(int timeout);
+
+/* DEVICE API */
+
+struct driver;
+struct devclass;
+struct device;
+struct module;
+struct module_data;
+
+typedef struct driver driver_t;
+typedef struct devclass *devclass_t;
+typedef struct device *device_t;
+typedef void (intr_fn_t)(void *arg);
+
+typedef int device_attach_t (device_t dev);
+typedef int device_detach_t (device_t dev);
+typedef int device_resume_t (device_t dev);
+typedef int device_shutdown_t (device_t dev);
+typedef int device_probe_t (device_t dev);
+typedef int device_suspend_t (device_t dev);
+
+typedef int bus_child_location_str_t (device_t parent, device_t child, char *buf, size_t buflen);
+typedef int bus_child_pnpinfo_str_t (device_t parent, device_t child, char *buf, size_t buflen);
+typedef void bus_driver_added_t (device_t dev, driver_t *driver);
+
+struct device_method {
+ const char *desc;
+ void *const func;
+};
+
+typedef struct device_method device_method_t;
+
+struct device {
+ TAILQ_HEAD(device_list, device) dev_children;
+ TAILQ_ENTRY(device) dev_link;
+
+ struct device *dev_parent;
+ const struct module_data *dev_module;
+ void *dev_sc;
+ void *dev_aux;
+ intr_fn_t *dev_irq_fn;
+ void *dev_irq_arg;
+
+ uint16_t dev_unit;
+
+ char dev_nameunit[64];
+ char dev_desc[64];
+
+ uint8_t dev_res_alloc:1;
+ uint8_t dev_quiet:1;
+ uint8_t dev_softc_set:1;
+ uint8_t dev_softc_alloc:1;
+ uint8_t dev_attached:1;
+ uint8_t dev_fixed_class:1;
+ uint8_t dev_unit_manual:1;
+};
+
+struct devclass {
+ device_t dev_list[DEVCLASS_MAXUNIT];
+};
+
+struct driver {
+ const char *name;
+ const struct device_method *methods;
+ uint32_t size;
+};
+
+struct module_data {
+ int (*callback) (struct module *, int, void *arg);
+ void *arg;
+ const char *bus_name;
+ const char *mod_name;
+ const char *long_name;
+ const struct driver *driver;
+ struct devclass **devclass_pp;
+ TAILQ_ENTRY(module_data) entry;
+};
+
+device_t device_get_parent(device_t dev);
+void *device_get_method(device_t dev, const char *what);
+const char *device_get_name(device_t dev);
+const char *device_get_nameunit(device_t dev);
+
+#define device_printf(dev, fmt,...) \
+ printf("%s: " fmt, device_get_nameunit(dev),## __VA_ARGS__)
+device_t device_add_child(device_t dev, const char *name, int unit);
+void device_quiet(device_t dev);
+void device_set_interrupt(device_t dev, intr_fn_t *fn, void *arg);
+void device_run_interrupts(device_t parent);
+void device_set_ivars(device_t dev, void *ivars);
+void *device_get_ivars(device_t dev);
+const char *device_get_desc(device_t dev);
+int device_probe_and_attach(device_t dev);
+int device_detach(device_t dev);
+void *device_get_softc(device_t dev);
+void device_set_softc(device_t dev, void *softc);
+int device_delete_child(device_t dev, device_t child);
+int device_delete_children(device_t dev);
+int device_is_attached(device_t dev);
+void device_set_desc(device_t dev, const char *desc);
+void device_set_desc_copy(device_t dev, const char *desc);
+int device_get_unit(device_t dev);
+void *devclass_get_softc(devclass_t dc, int unit);
+int devclass_get_maxunit(devclass_t dc);
+device_t devclass_get_device(devclass_t dc, int unit);
+devclass_t devclass_find(const char *classname);
+
+#define bus_get_dma_tag(...) (NULL)
+int bus_generic_detach(device_t dev);
+int bus_generic_resume(device_t dev);
+int bus_generic_shutdown(device_t dev);
+int bus_generic_suspend(device_t dev);
+int bus_generic_print_child(device_t dev, device_t child);
+void bus_generic_driver_added(device_t dev, driver_t *driver);
+
+/* BUS SPACE API */
+
+void bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t data);
+void bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t data);
+void bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t data);
+
+uint8_t bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
+uint16_t bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
+uint32_t bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
+
+void bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t *datap, bus_size_t count);
+void bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t *datap, bus_size_t count);
+void bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t *datap, bus_size_t count);
+
+void bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t *datap, bus_size_t count);
+void bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t *datap, bus_size_t count);
+void bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t *datap, bus_size_t count);
+
+void bus_space_read_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t *datap, bus_size_t count);
+void bus_space_write_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t *datap, bus_size_t count);
+void bus_space_read_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t *datap, bus_size_t count);
+void bus_space_write_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t *datap, bus_size_t count);
+
+void bus_space_barrier(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, bus_size_t length, int flags);
+
+void module_register(void *);
+
+/* LIB-C */
+
+void *memset(void *, int, size_t len);
+void *memcpy(void *, const void *, size_t len);
+int printf(const char *,...) __printflike(1, 2);
+int snprintf(char *restrict str, size_t size, const char *restrict format,...) __printflike(3, 4);
+size_t strlen(const char *s);
+
+/* MALLOC API */
+
+#define malloc(s,x,f) usb_malloc(s)
+void *usb_malloc(size_t);
+
+#define free(p,x) usb_free(p)
+void usb_free(void *);
+
+#define strdup(p,x) usb_strdup(p)
+char *usb_strdup(const char *str);
+
+/* ENDIANNESS */
+
+/* Assume little endian */
+
+#define htole64(x) ((uint64_t)(x))
+#define le64toh(x) ((uint64_t)(x))
+
+#define htole32(x) ((uint32_t)(x))
+#define le32toh(x) ((uint32_t)(x))
+
+#define htole16(x) ((uint16_t)(x))
+#define le16toh(x) ((uint16_t)(x))
+
+#define be32toh(x) ((uint32_t)(x))
+#define htobe32(x) ((uint32_t)(x))
+
+/* USB */
+
+typedef int usb_handle_request_t (device_t dev, const void *req, void **pptr, uint16_t *plen, uint16_t offset, uint8_t *pstate);
+typedef int usb_take_controller_t (device_t dev);
+
+void usb_idle(void);
+void usb_init(void);
+void usb_uninit(void);
+
+/* set some defaults */
+
+#ifndef USB_POOL_SIZE
+#define USB_POOL_SIZE (1024*1024) /* 1 MByte */
+#endif
+
+int pause(const char *, int);
+void DELAY(unsigned int);
+
+/* OTHER */
+
+struct selinfo {
+};
+
+/* SYSTEM STARTUP API */
+
+extern const void *sysinit_data[];
+extern const void *sysuninit_data[];
+
+#endif /* _BSD_KERNEL_H_ */
diff --git a/sys/boot/usb/bsd_usbloader_test.c b/sys/boot/usb/bsd_usbloader_test.c
new file mode 100644
index 0000000..929e2e9
--- /dev/null
+++ b/sys/boot/usb/bsd_usbloader_test.c
@@ -0,0 +1,80 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. 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 <stdio.h>
+#include <stdint.h>
+#include <time.h>
+
+extern int usleep(int);
+extern void callout_process(int);
+extern void usb_idle(void);
+extern void usb_init(void);
+extern void usb_uninit(void);
+
+#define hz 1000
+
+void
+DELAY(unsigned int delay)
+{
+ usleep(delay);
+}
+
+int
+pause(const char *what, int timeout)
+{
+ if (timeout == 0)
+ timeout = 1;
+
+ usleep((1000000 / hz) * timeout);
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ uint32_t time;
+
+ usb_init();
+
+ time = 0;
+
+ while (1) {
+
+ usb_idle();
+
+ usleep(1000);
+
+ if (++time >= (1000 / hz)) {
+ time = 0;
+ callout_process(1);
+ }
+ }
+
+ usb_uninit();
+
+ return (0);
+}
diff --git a/sys/boot/usb/tools/sysinit.c b/sys/boot/usb/tools/sysinit.c
new file mode 100644
index 0000000..b968fe0
--- /dev/null
+++ b/sys/boot/usb/tools/sysinit.c
@@ -0,0 +1,331 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. 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 utility sorts sysinit structure entries in binary format and
+ * prints out the result in C-format.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <err.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sysexits.h>
+#include "sysinit.h"
+
+static int opt_R;
+static const char *input_f;
+static const char *output_f;
+static const char *struct_name;
+static const char *keyword;
+static struct sysinit_data **start;
+static struct sysinit_data **stop;
+
+static int input_file = -1;
+static int output_file = -1;
+
+static uint8_t *input_ptr;
+static uint32_t input_len;
+
+static uint32_t endian32;
+
+static char scratch_buf[4096];
+
+static int success;
+
+static void do_sysinit(void);
+
+/* the following function converts the numbers into host endian format */
+
+static uint32_t
+read32(uint32_t val)
+{
+ uint32_t temp;
+ uint32_t endian;
+
+ endian = endian32;
+ temp = 0;
+
+ while (val) {
+ temp |= (val & 0xF) << ((endian & 0xF) * 4);
+ endian >>= 4;
+ val >>= 4;
+ }
+ return (temp);
+}
+
+static void
+do_write(int fd, const char *buf)
+{
+ int len = strlen(buf);
+
+ if (write(fd, buf, len) != len)
+ err(EX_SOFTWARE, "Could not write to output file");
+}
+
+static void *
+do_malloc(int size)
+{
+ void *ptr;
+
+ ptr = malloc(size);
+ if (ptr == NULL)
+ errx(EX_SOFTWARE, "Could not allocate memory");
+ return (ptr);
+}
+
+static void
+usage(void)
+{
+ errx(EX_USAGE, "sysinit -i sysinit.bin -o sysinit_data.c \\\n"
+ "\t" "-k sysinit -s sysinit_data [ -R (reverse)]");
+}
+
+static void
+cleanup(void)
+{
+ if (output_file >= 0)
+ close(output_file);
+ if (input_file >= 0)
+ close(input_file);
+ if (success == 0) {
+ if (output_f)
+ unlink(output_f);
+ }
+}
+
+static int
+compare(const void *_pa, const void *_pb)
+{
+ const struct sysinit_data * const *pa = _pa;
+ const struct sysinit_data * const *pb = _pb;
+
+ if ((*pa)->dw_msb_value > (*pb)->dw_msb_value)
+ return (1);
+
+ if ((*pa)->dw_msb_value < (*pb)->dw_msb_value)
+ return (-1);
+
+ if ((*pa)->dw_lsb_value > (*pb)->dw_lsb_value)
+ return (1);
+
+ if ((*pa)->dw_lsb_value < (*pb)->dw_lsb_value)
+ return (-1);
+
+ return (0); /* equal */
+}
+
+static int
+compare_R(const void *_pa, const void *_pb)
+{
+ const struct sysinit_data * const *pa = _pa;
+ const struct sysinit_data * const *pb = _pb;
+
+ if ((*pa)->dw_msb_value > (*pb)->dw_msb_value)
+ return (-1);
+
+ if ((*pa)->dw_msb_value < (*pb)->dw_msb_value)
+ return (1);
+
+ if ((*pa)->dw_lsb_value > (*pb)->dw_lsb_value)
+ return (-1);
+
+ if ((*pa)->dw_lsb_value < (*pb)->dw_lsb_value)
+ return (1);
+
+ return (0); /* equal */
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sysinit_data **sipp;
+ int c;
+ int entries;
+ off_t off;
+
+ while ((c = getopt(argc, argv, "k:s:i:o:Rh")) != -1) {
+ switch (c) {
+ case 'i':
+ input_f = optarg;
+ break;
+ case 'o':
+ output_f = optarg;
+ break;
+ case 'R':
+ opt_R = 1;
+ break;
+ case 'k':
+ keyword = optarg;
+ break;
+ case 's':
+ struct_name = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (input_f == NULL || output_f == NULL ||
+ struct_name == NULL || keyword == NULL)
+ usage();
+
+ atexit(&cleanup);
+
+ cleanup();
+
+ input_file = open(input_f, O_RDONLY);
+ if (input_file < 0)
+ err(EX_SOFTWARE, "Could not open input file: %s", input_f);
+
+ output_file = open(output_f, O_TRUNC | O_CREAT | O_RDWR, 0600);
+ if (output_file < 0)
+ err(EX_SOFTWARE, "Could not open output file: %s", output_f);
+
+ off = lseek(input_file, 0, SEEK_END);
+
+ input_ptr = do_malloc(off);
+ input_len = off;
+
+ if (input_len % (uint32_t)sizeof(struct sysinit_data)) {
+ errx(EX_SOFTWARE, "Input file size is not divisible by %u",
+ (unsigned int)sizeof(struct sysinit_data));
+ }
+ off = lseek(input_file, 0, SEEK_SET);
+ if (off < 0)
+ err(EX_SOFTWARE, "Could not seek to start of input file");
+
+ if (read(input_file, input_ptr, input_len) != input_len)
+ err(EX_SOFTWARE, "Could not read input file");
+
+ entries = input_len / (uint32_t)sizeof(struct sysinit_data);
+
+ start = do_malloc(sizeof(void *) * entries);
+ stop = start + entries;
+
+ for (c = 0; c != entries; c++)
+ start[c] = &((struct sysinit_data *)input_ptr)[c];
+
+ if (start != stop)
+ endian32 = (*start)->dw_endian32;
+
+ /* switch all fields to host endian order */
+ for (sipp = start; sipp < stop; sipp++) {
+ (*sipp)->dw_lsb_value = read32((*sipp)->dw_lsb_value);
+ (*sipp)->dw_msb_value = read32((*sipp)->dw_msb_value);
+ (*sipp)->dw_file_line = read32((*sipp)->dw_file_line);
+ }
+
+ if (opt_R == 0) {
+ /* sort entries, rising numerical order */
+ qsort(start, entries, sizeof(void *), &compare);
+ } else {
+ /* sort entries, falling numerical order */
+ qsort(start, entries, sizeof(void *), &compare_R);
+ }
+
+ /* safe all strings */
+ for (sipp = start; sipp < stop; sipp++) {
+ (*sipp)->b_keyword_name[sizeof((*sipp)->b_keyword_name) - 1] = 0;
+ (*sipp)->b_global_type[sizeof((*sipp)->b_global_type) - 1] = 0;
+ (*sipp)->b_global_name[sizeof((*sipp)->b_global_name) - 1] = 0;
+ (*sipp)->b_file_name[sizeof((*sipp)->b_file_name) - 1] = 0;
+ (*sipp)->b_debug_info[sizeof((*sipp)->b_debug_info) - 1] = 0;
+ }
+
+ if (strcmp(keyword, "sysinit") == 0)
+ do_sysinit();
+ else if (strcmp(keyword, "sysuninit") == 0)
+ do_sysinit();
+ else
+ errx(EX_USAGE, "Unknown keyword '%s'", keyword);
+
+ success = 1;
+
+ return (0);
+}
+
+static void
+do_sysinit(void)
+{
+ struct sysinit_data **sipp;
+ int c;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "/*\n"
+ " * This file was automatically generated.\n"
+ " * Please do not edit.\n"
+ " */\n\n");
+
+ /* write out externals */
+ for (c = 0, sipp = start; sipp < stop; c++, sipp++) {
+ if (strcmp((const char *)(*sipp)->b_keyword_name, keyword))
+ continue;
+ if ((*sipp)->dw_msb_value == 0)
+ continue;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "/* #%04u: %s entry at %s:%u */\n",
+ c, (*sipp)->b_debug_info, (*sipp)->b_file_name,
+ (unsigned int)(*sipp)->dw_file_line);
+
+ do_write(output_file, scratch_buf);
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "extern %s %s;\n\n", (*sipp)->b_global_type,
+ (*sipp)->b_global_name);
+
+ do_write(output_file, scratch_buf);
+ }
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "const void *%s[] = {\n", struct_name);
+
+ do_write(output_file, scratch_buf);
+
+ /* write out actual table */
+ for (c = 0, sipp = start; sipp < stop; c++, sipp++) {
+ if (strcmp((const char *)(*sipp)->b_keyword_name, keyword))
+ continue;
+ if ((*sipp)->dw_msb_value == 0)
+ continue;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "\t&%s, /* #%04u */\n",
+ (*sipp)->b_global_name, (unsigned int)c);
+
+ do_write(output_file, scratch_buf);
+ }
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "\t(const void *)0\n"
+ "};\n");
+
+ do_write(output_file, scratch_buf);
+}
diff --git a/sys/boot/usb/tools/sysinit.h b/sys/boot/usb/tools/sysinit.h
new file mode 100644
index 0000000..a7a450e
--- /dev/null
+++ b/sys/boot/usb/tools/sysinit.h
@@ -0,0 +1,57 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. 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.
+ */
+
+#ifndef _SYSINIT_H_
+#define _SYSINIT_H_
+
+struct sysinit_data {
+ uint8_t b_keyword_name[64];
+ uint8_t b_debug_info[128];
+ uint8_t b_global_type[128];
+ uint8_t b_global_name[128];
+ uint8_t b_file_name[256];
+ uint32_t dw_endian32;
+ uint32_t dw_msb_value; /* must be non-zero, else entry is skipped */
+ uint32_t dw_lsb_value;
+ uint32_t dw_file_line;
+} __attribute__((__packed__));
+
+#define SYSINIT_ENTRY(uniq, keyword, msb, lsb, g_type, g_name, debug) \
+ static const struct sysinit_data sysinit_##uniq \
+ __attribute__((__section__(".debug.sysinit"), \
+ __used__, __aligned__(1))) = { \
+ .b_keyword_name = { keyword }, \
+ .b_debug_info = { debug }, \
+ .b_global_type = { g_type }, \
+ .b_global_name = { g_name }, \
+ .b_file_name = { __FILE__ }, \
+ .dw_endian32 = 0x76543210U, \
+ .dw_msb_value = (msb), \
+ .dw_lsb_value = (lsb), \
+ .dw_file_line = __LINE__ \
+}
+
+#endif /* _SYSINIT_H_ */
diff --git a/sys/boot/usb/usb_busdma_loader.c b/sys/boot/usb/usb_busdma_loader.c
new file mode 100644
index 0000000..c7d1ecb
--- /dev/null
+++ b/sys/boot/usb/usb_busdma_loader.c
@@ -0,0 +1,619 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. 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 <bsd_global.h>
+
+#if USB_HAVE_BUSDMA
+static void usb_pc_common_mem_cb(struct usb_page_cache *pc,
+ void *vaddr, uint32_t length);
+#endif
+
+/*------------------------------------------------------------------------*
+ * usbd_get_page - lookup DMA-able memory for the given offset
+ *
+ * NOTE: Only call this function when the "page_cache" structure has
+ * been properly initialized !
+ *------------------------------------------------------------------------*/
+void
+usbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
+ struct usb_page_search *res)
+{
+#if USB_HAVE_BUSDMA
+ struct usb_page *page;
+
+ if (pc->page_start) {
+
+ /* Case 1 - something has been loaded into DMA */
+
+ if (pc->buffer) {
+
+ /* Case 1a - Kernel Virtual Address */
+
+ res->buffer = USB_ADD_BYTES(pc->buffer, offset);
+ }
+ offset += pc->page_offset_buf;
+
+ /* compute destination page */
+
+ page = pc->page_start;
+
+ if (pc->ismultiseg) {
+
+ page += (offset / USB_PAGE_SIZE);
+
+ offset %= USB_PAGE_SIZE;
+
+ res->length = USB_PAGE_SIZE - offset;
+ res->physaddr = page->physaddr + offset;
+ } else {
+ res->length = (usb_size_t)-1;
+ res->physaddr = page->physaddr + offset;
+ }
+ if (!pc->buffer) {
+
+ /* Case 1b - Non Kernel Virtual Address */
+
+ res->buffer = USB_ADD_BYTES(page->buffer, offset);
+ }
+ return;
+ }
+#endif
+ /* Case 2 - Plain PIO */
+
+ res->buffer = USB_ADD_BYTES(pc->buffer, offset);
+ res->length = (usb_size_t)-1;
+#if USB_HAVE_BUSDMA
+ res->physaddr = 0;
+#endif
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_copy_in - copy directly to DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
+ const void *ptr, usb_frlength_t len)
+{
+ struct usb_page_search buf_res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &buf_res);
+
+ if (buf_res.length > len) {
+ buf_res.length = len;
+ }
+ memcpy(buf_res.buffer, ptr, buf_res.length);
+
+ offset += buf_res.length;
+ len -= buf_res.length;
+ ptr = USB_ADD_BYTES(ptr, buf_res.length);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_copy_out - copy directly from DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset,
+ void *ptr, usb_frlength_t len)
+{
+ struct usb_page_search res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &res);
+
+ if (res.length > len) {
+ res.length = len;
+ }
+ memcpy(ptr, res.buffer, res.length);
+
+ offset += res.length;
+ len -= res.length;
+ ptr = USB_ADD_BYTES(ptr, res.length);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_frame_zero - zero DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
+ usb_frlength_t len)
+{
+ struct usb_page_search res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &res);
+
+ if (res.length > len) {
+ res.length = len;
+ }
+ memset(res.buffer, 0, res.length);
+
+ offset += res.length;
+ len -= res.length;
+ }
+}
+
+#if USB_HAVE_BUSDMA
+
+/*------------------------------------------------------------------------*
+ * usb_pc_common_mem_cb - BUS-DMA callback function
+ *------------------------------------------------------------------------*/
+static void
+usb_pc_common_mem_cb(struct usb_page_cache *pc,
+ void *vaddr, uint32_t length)
+{
+ struct usb_page *pg;
+ usb_size_t rem;
+ bus_size_t off;
+ bus_addr_t phys = (uintptr_t)vaddr; /* XXX */
+ uint32_t nseg;
+
+ if (length == 0)
+ nseg = 1;
+ else
+ nseg = ((length + USB_PAGE_SIZE - 1) / USB_PAGE_SIZE);
+
+ pg = pc->page_start;
+ pg->physaddr = phys & ~(USB_PAGE_SIZE - 1);
+ rem = phys & (USB_PAGE_SIZE - 1);
+ pc->page_offset_buf = rem;
+ pc->page_offset_end += rem;
+ length += rem;
+
+ for (off = USB_PAGE_SIZE; off < length; off += USB_PAGE_SIZE) {
+ pg++;
+ pg->physaddr = (phys + off) & ~(USB_PAGE_SIZE - 1);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_alloc_mem - allocate DMA'able memory
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
+ usb_size_t size, usb_size_t align)
+{
+ void *ptr;
+ uint32_t rem;
+
+ /* allocate zeroed memory */
+
+ if (align != 1) {
+ ptr = usb_malloc(size + align);
+ if (ptr == NULL)
+ goto error;
+
+ rem = (-((uintptr_t)ptr)) & (align - 1);
+ } else {
+ ptr = usb_malloc(size);
+ if (ptr == NULL)
+ goto error;
+ rem = 0;
+ }
+
+ /* setup page cache */
+ pc->buffer = ((uint8_t *)ptr) + rem;
+ pc->page_start = pg;
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = size;
+ pc->map = NULL;
+ pc->tag = ptr;
+ pc->ismultiseg = (align == 1);
+
+ /* compute physical address */
+ usb_pc_common_mem_cb(pc, ptr, size);
+
+ usb_pc_cpu_flush(pc);
+ return (0);
+
+error:
+ /* reset most of the page cache */
+ pc->buffer = NULL;
+ pc->page_start = NULL;
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = 0;
+ pc->map = NULL;
+ pc->tag = NULL;
+ return (1);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_free_mem - free DMA memory
+ *
+ * This function is NULL safe.
+ *------------------------------------------------------------------------*/
+void
+usb_pc_free_mem(struct usb_page_cache *pc)
+{
+ if (pc != NULL && pc->buffer != NULL) {
+ usb_free(pc->tag);
+ pc->buffer = NULL;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_load_mem - load virtual memory into DMA
+ *
+ * Return values:
+ * 0: Success
+ * Else: Error
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, uint8_t sync)
+{
+ /* setup page cache */
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = size;
+ pc->ismultiseg = 1;
+
+ mtx_assert(pc->tag_parent->mtx, MA_OWNED);
+
+ if (size > 0) {
+ /* compute physical address */
+ usb_pc_common_mem_cb(pc, pc->buffer, size);
+ }
+ if (sync == 0) {
+ /*
+ * Call callback so that refcount is decremented
+ * properly:
+ */
+ pc->tag_parent->dma_error = 0;
+ (pc->tag_parent->func) (pc->tag_parent);
+ }
+ return (0);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_cpu_invalidate - invalidate CPU cache
+ *------------------------------------------------------------------------*/
+void
+usb_pc_cpu_invalidate(struct usb_page_cache *pc)
+{
+ if (pc->page_offset_end == pc->page_offset_buf) {
+ /* nothing has been loaded into this page cache! */
+ return;
+ }
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_cpu_flush - flush CPU cache
+ *------------------------------------------------------------------------*/
+void
+usb_pc_cpu_flush(struct usb_page_cache *pc)
+{
+ if (pc->page_offset_end == pc->page_offset_buf) {
+ /* nothing has been loaded into this page cache! */
+ return;
+ }
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_dmamap_create - create a DMA map
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size)
+{
+ return (0); /* NOP, success */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_dmamap_destroy
+ *
+ * This function is NULL safe.
+ *------------------------------------------------------------------------*/
+void
+usb_pc_dmamap_destroy(struct usb_page_cache *pc)
+{
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_dma_tag_setup - initialise USB DMA tags
+ *------------------------------------------------------------------------*/
+void
+usb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
+ struct usb_dma_tag *udt, bus_dma_tag_t dmat,
+ struct mtx *mtx, usb_dma_callback_t *func,
+ uint8_t ndmabits, uint8_t nudt)
+{
+ memset(udpt, 0, sizeof(*udpt));
+
+ /* sanity checking */
+ if ((nudt == 0) ||
+ (ndmabits == 0) ||
+ (mtx == NULL)) {
+ /* something is corrupt */
+ return;
+ }
+ /* initialise condition variable */
+ cv_init(udpt->cv, "USB DMA CV");
+
+ /* store some information */
+ udpt->mtx = mtx;
+ udpt->func = func;
+ udpt->tag = dmat;
+ udpt->utag_first = udt;
+ udpt->utag_max = nudt;
+ udpt->dma_bits = ndmabits;
+
+ while (nudt--) {
+ memset(udt, 0, sizeof(*udt));
+ udt->tag_parent = udpt;
+ udt++;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bus_tag_unsetup - factored out code
+ *------------------------------------------------------------------------*/
+void
+usb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt)
+{
+ struct usb_dma_tag *udt;
+ uint8_t nudt;
+
+ udt = udpt->utag_first;
+ nudt = udpt->utag_max;
+
+ while (nudt--) {
+ udt->align = 0;
+ udt++;
+ }
+
+ if (udpt->utag_max) {
+ /* destroy the condition variable */
+ cv_destroy(udpt->cv);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_work_loop
+ *
+ * This function handles loading of virtual buffers into DMA and is
+ * only called when "dma_refcount" is zero.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_work_loop(struct usb_xfer_queue *pq)
+{
+ struct usb_xfer_root *info;
+ struct usb_xfer *xfer;
+ usb_frcount_t nframes;
+
+ xfer = pq->curr;
+ info = xfer->xroot;
+
+ mtx_assert(info->xfer_mtx, MA_OWNED);
+
+ if (xfer->error) {
+ /* some error happened */
+ USB_BUS_LOCK(info->bus);
+ usbd_transfer_done(xfer, 0);
+ USB_BUS_UNLOCK(info->bus);
+ return;
+ }
+ if (!xfer->flags_int.bdma_setup) {
+ struct usb_page *pg;
+ usb_frlength_t frlength_0;
+ uint8_t isread;
+
+ xfer->flags_int.bdma_setup = 1;
+
+ /* reset BUS-DMA load state */
+
+ info->dma_error = 0;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ frlength_0 = xfer->sumlen;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ frlength_0 = xfer->frlengths[0];
+ }
+
+ /*
+ * Set DMA direction first. This is needed to
+ * select the correct cache invalidate and cache
+ * flush operations.
+ */
+ isread = USB_GET_DATA_ISREAD(xfer);
+ pg = xfer->dma_page_ptr;
+
+ if (xfer->flags_int.control_xfr &&
+ xfer->flags_int.control_hdr) {
+ /* special case */
+ if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
+ /* The device controller writes to memory */
+ xfer->frbuffers[0].isread = 1;
+ } else {
+ /* The host controller reads from memory */
+ xfer->frbuffers[0].isread = 0;
+ }
+ } else {
+ /* default case */
+ xfer->frbuffers[0].isread = isread;
+ }
+
+ /*
+ * Setup the "page_start" pointer which points to an array of
+ * USB pages where information about the physical address of a
+ * page will be stored. Also initialise the "isread" field of
+ * the USB page caches.
+ */
+ xfer->frbuffers[0].page_start = pg;
+
+ info->dma_nframes = nframes;
+ info->dma_currframe = 0;
+ info->dma_frlength_0 = frlength_0;
+
+ pg += (frlength_0 / USB_PAGE_SIZE);
+ pg += 2;
+
+ while (--nframes > 0) {
+ xfer->frbuffers[nframes].isread = isread;
+ xfer->frbuffers[nframes].page_start = pg;
+
+ pg += (xfer->frlengths[nframes] / USB_PAGE_SIZE);
+ pg += 2;
+ }
+
+ }
+ if (info->dma_error) {
+ USB_BUS_LOCK(info->bus);
+ usbd_transfer_done(xfer, USB_ERR_DMA_LOAD_FAILED);
+ USB_BUS_UNLOCK(info->bus);
+ return;
+ }
+ if (info->dma_currframe != info->dma_nframes) {
+
+ if (info->dma_currframe == 0) {
+ /* special case */
+ usb_pc_load_mem(xfer->frbuffers,
+ info->dma_frlength_0, 0);
+ } else {
+ /* default case */
+ nframes = info->dma_currframe;
+ usb_pc_load_mem(xfer->frbuffers + nframes,
+ xfer->frlengths[nframes], 0);
+ }
+
+ /* advance frame index */
+ info->dma_currframe++;
+
+ return;
+ }
+ /* go ahead */
+ usb_bdma_pre_sync(xfer);
+
+ /* start loading next USB transfer, if any */
+ usb_command_wrapper(pq, NULL);
+
+ /* finally start the hardware */
+ usbd_pipe_enter(xfer);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_done_event
+ *
+ * This function is called when the BUS-DMA has loaded virtual memory
+ * into DMA, if any.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_done_event(struct usb_dma_parent_tag *udpt)
+{
+ struct usb_xfer_root *info;
+
+ info = USB_DMATAG_TO_XROOT(udpt);
+
+ mtx_assert(info->xfer_mtx, MA_OWNED);
+
+ /* copy error */
+ info->dma_error = udpt->dma_error;
+
+ /* enter workloop again */
+ usb_command_wrapper(&info->dma_q,
+ info->dma_q.curr);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_pre_sync
+ *
+ * This function handles DMA synchronisation that must be done before
+ * an USB transfer is started.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_pre_sync(struct usb_xfer *xfer)
+{
+ struct usb_page_cache *pc;
+ usb_frcount_t nframes;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ }
+
+ pc = xfer->frbuffers;
+
+ while (nframes--) {
+
+ if (pc->isread) {
+ usb_pc_cpu_invalidate(pc);
+ } else {
+ usb_pc_cpu_flush(pc);
+ }
+ pc++;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_post_sync
+ *
+ * This function handles DMA synchronisation that must be done after
+ * an USB transfer is complete.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_post_sync(struct usb_xfer *xfer)
+{
+ struct usb_page_cache *pc;
+ usb_frcount_t nframes;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ }
+
+ pc = xfer->frbuffers;
+
+ while (nframes--) {
+ if (pc->isread) {
+ usb_pc_cpu_invalidate(pc);
+ }
+ pc++;
+ }
+}
+#endif
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index ac5eba7..768332e 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -2257,11 +2257,31 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
*/
mtx_unlock(&softc->ctl_lock);
- if (cmd == CTL_ENABLE_PORT)
+ if (cmd == CTL_ENABLE_PORT) {
+ struct ctl_lun *lun;
+
+ STAILQ_FOREACH(lun, &softc->lun_list,
+ links) {
+ fe->lun_enable(fe->targ_lun_arg,
+ lun->target,
+ lun->lun);
+ }
+
ctl_frontend_online(fe);
- else if (cmd == CTL_DISABLE_PORT)
+ } else if (cmd == CTL_DISABLE_PORT) {
+ struct ctl_lun *lun;
+
ctl_frontend_offline(fe);
+ STAILQ_FOREACH(lun, &softc->lun_list,
+ links) {
+ fe->lun_disable(
+ fe->targ_lun_arg,
+ lun->target,
+ lun->lun);
+ }
+ }
+
mtx_lock(&softc->ctl_lock);
if (cmd == CTL_SET_PORT_WWNS)
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 59357123..5dc20e5 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <cam/ctl/ctl_error.h>
typedef enum {
+ CTLFE_CCB_DEFAULT = 0x00,
CTLFE_CCB_WAITING = 0x01
} ctlfe_ccb_types;
@@ -304,10 +305,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
case AC_PATH_REGISTERED: {
struct ctl_frontend *fe;
struct ctlfe_softc *bus_softc;
- struct ctlfe_lun_softc *lun_softc;
- struct cam_path *path;
struct ccb_pathinq *cpi;
- cam_status status;
int retval;
cpi = (struct ccb_pathinq *)arg;
@@ -330,7 +328,6 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
M_NOWAIT | M_ZERO);
if (ccb == NULL) {
printf("%s: unable to malloc CCB!\n", __func__);
- xpt_free_path(path);
return;
}
xpt_setup_ccb(&ccb->ccb_h, cpi->ccb_h.path,
@@ -448,44 +445,31 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
mtx_unlock(&ctlfe_list_mtx);
}
- status = xpt_create_path(&path, /*periph*/ NULL,
- bus_softc->path_id,CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD);
- if (status != CAM_REQ_CMP) {
- printf("%s: unable to create path for wildcard "
- "periph\n", __func__);
- break;
- }
- lun_softc = malloc(sizeof(*lun_softc), M_CTLFE,
- M_NOWAIT | M_ZERO);
- if (lun_softc == NULL) {
- xpt_print(path, "%s: unable to allocate softc for "
- "wildcard periph\n", __func__);
- xpt_free_path(path);
- break;
+ break;
+ }
+ case AC_PATH_DEREGISTERED: {
+ struct ctlfe_softc *softc = NULL;
+
+ mtx_lock(&ctlfe_list_mtx);
+ STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
+ if (softc->path_id == xpt_path_path_id(path)) {
+ STAILQ_REMOVE(&ctlfe_softc_list, softc,
+ ctlfe_softc, links);
+ break;
+ }
}
+ mtx_unlock(&ctlfe_list_mtx);
- lun_softc->parent_softc = bus_softc;
- lun_softc->flags |= CTLFE_LUN_WILDCARD;
-
- status = cam_periph_alloc(ctlferegister,
- ctlfeoninvalidate,
- ctlfecleanup,
- ctlfestart,
- "ctl",
- CAM_PERIPH_BIO,
- path,
- ctlfeasync,
- 0,
- lun_softc);
-
- xpt_free_path(path);
-
+ if (softc != NULL) {
+ /*
+ * XXX KDM are we certain at this point that there
+ * are no outstanding commands for this frontend?
+ */
+ ctl_frontend_deregister(&softc->fe);
+ free(softc, M_CTLFE);
+ }
break;
}
- case AC_PATH_DEREGISTERED:
- /* ctl_frontend_deregister() */
- break;
case AC_CONTRACT: {
struct ac_contract *ac;
@@ -699,11 +683,14 @@ ctlfecleanup(struct cam_periph *periph)
softc = (struct ctlfe_lun_softc *)periph->softc;
bus_softc = softc->parent_softc;
- STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc,links);
+ STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
/*
* XXX KDM is there anything else that needs to be done here?
*/
+
+ callout_stop(&softc->dma_callout);
+
free(softc, M_CTLFE);
}
@@ -717,6 +704,8 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
softc->ccbs_alloced++;
+ start_ccb->ccb_h.ccb_type = CTLFE_CCB_DEFAULT;
+
ccb_h = TAILQ_FIRST(&softc->work_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
panic("shouldn't get to the CCB waiting case!");
@@ -857,8 +846,6 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
/*
* Datamove call, we need to setup the S/G list.
- * If we pass in a S/G list, the isp(4) driver at
- * least expects physical/bus addresses.
*/
cmd_info = (struct ctlfe_lun_cmd_info *)
@@ -933,12 +920,13 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
int *ti;
/*
- * XXX KDM this is a temporary hack. The
- * isp(4) driver can't deal with S/G lists
- * with virtual pointers, so we need to
- * go through and send down one virtual
- * pointer at a time.
+ * If we have more S/G list pointers than
+ * will fit in the available storage in the
+ * cmd_info structure inside the ctl_io header,
+ * then we need to send down the pointers
+ * one element at a time.
*/
+
sglist = (struct ctl_sg_entry *)
io->scsiio.kern_data_ptr;
ti = &cmd_info->cur_transfer_index;
@@ -1405,13 +1393,15 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
break;
default:
/*
- * XXX KDM the isp(4) driver doesn't really
- * seem to send errors back for data
- * transfers that I can tell. There is one
- * case where it'll send CAM_REQ_CMP_ERR,
- * but probably not that many more cases.
- * So set a generic data phase error here,
- * like the SXP driver sets.
+ * XXX KDM we probably need to figure out a
+ * standard set of errors that the SIM
+ * drivers should return in the event of a
+ * data transfer failure. A data phase
+ * error will at least point the user to a
+ * data transfer error of some sort.
+ * Hopefully the SIM printed out some
+ * additional information to give the user
+ * a clue what happened.
*/
io->io_hdr.port_status = 0xbad1;
ctl_set_data_phase_error(&io->scsiio);
@@ -1689,20 +1679,22 @@ ctlfe_onoffline(void *arg, int online)
sim = bus_softc->sim;
- CAM_SIM_LOCK(sim);
+ mtx_assert(sim->mtx, MA_OWNED);
+
status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP) {
printf("%s: unable to create path!\n", __func__);
- CAM_SIM_UNLOCK(sim);
return;
}
- CAM_SIM_UNLOCK(sim);
-
- ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_WAITOK | M_ZERO);
+ ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_NOWAIT | M_ZERO);
+ if (ccb == NULL) {
+ printf("%s: unable to malloc CCB!\n", __func__);
+ xpt_free_path(path);
+ return;
+ }
xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
-
/*
* Copan WWN format:
*
@@ -1720,11 +1712,9 @@ ctlfe_onoffline(void *arg, int online)
ccb->ccb_h.func_code = XPT_GET_SIM_KNOB;
- CAM_SIM_LOCK(sim);
xpt_action(ccb);
- CAM_SIM_UNLOCK(sim);
if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){
#ifdef RANDOM_WWNN
@@ -1822,9 +1812,6 @@ ctlfe_onoffline(void *arg, int online)
else
ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE;
-
- CAM_SIM_LOCK(sim);
-
xpt_action(ccb);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
@@ -1841,8 +1828,6 @@ ctlfe_onoffline(void *arg, int online)
xpt_free_path(path);
- CAM_SIM_UNLOCK(sim);
-
free(ccb, M_TEMP);
return;
@@ -1851,13 +1836,111 @@ ctlfe_onoffline(void *arg, int online)
static void
ctlfe_online(void *arg)
{
+ struct ctlfe_softc *bus_softc;
+ struct cam_path *path;
+ cam_status status;
+ struct ctlfe_lun_softc *lun_softc;
+ struct cam_sim *sim;
+
+ bus_softc = (struct ctlfe_softc *)arg;
+ sim = bus_softc->sim;
+
+ CAM_SIM_LOCK(sim);
+
+ /*
+ * Create the wildcard LUN before bringing the port online.
+ */
+ status = xpt_create_path(&path, /*periph*/ NULL,
+ bus_softc->path_id, CAM_TARGET_WILDCARD,
+ CAM_LUN_WILDCARD);
+ if (status != CAM_REQ_CMP) {
+ printf("%s: unable to create path for wildcard periph\n",
+ __func__);
+ CAM_SIM_UNLOCK(sim);
+ return;
+ }
+
+ lun_softc = malloc(sizeof(*lun_softc), M_CTLFE,
+ M_NOWAIT | M_ZERO);
+ if (lun_softc == NULL) {
+ xpt_print(path, "%s: unable to allocate softc for "
+ "wildcard periph\n", __func__);
+ xpt_free_path(path);
+ CAM_SIM_UNLOCK(sim);
+ return;
+ }
+
+ lun_softc->parent_softc = bus_softc;
+ lun_softc->flags |= CTLFE_LUN_WILDCARD;
+
+ STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, lun_softc, links);
+
+
+ status = cam_periph_alloc(ctlferegister,
+ ctlfeoninvalidate,
+ ctlfecleanup,
+ ctlfestart,
+ "ctl",
+ CAM_PERIPH_BIO,
+ path,
+ ctlfeasync,
+ 0,
+ lun_softc);
+
+ if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ const struct cam_status_entry *entry;
+
+ entry = cam_fetch_status_entry(status);
+
+ printf("%s: CAM error %s (%#x) returned from "
+ "cam_periph_alloc()\n", __func__, (entry != NULL) ?
+ entry->status_text : "Unknown", status);
+ }
+
+ xpt_free_path(path);
+
ctlfe_onoffline(arg, /*online*/ 1);
+
+ CAM_SIM_UNLOCK(sim);
}
static void
ctlfe_offline(void *arg)
{
+ struct ctlfe_softc *bus_softc;
+ struct cam_path *path;
+ cam_status status;
+ struct cam_periph *periph;
+ struct cam_sim *sim;
+
+ bus_softc = (struct ctlfe_softc *)arg;
+ sim = bus_softc->sim;
+
+ CAM_SIM_LOCK(sim);
+
ctlfe_onoffline(arg, /*online*/ 0);
+
+ /*
+ * Disable the wildcard LUN for this port now that we have taken
+ * the port offline.
+ */
+ status = xpt_create_path(&path, /*periph*/ NULL,
+ bus_softc->path_id, CAM_TARGET_WILDCARD,
+ CAM_LUN_WILDCARD);
+ if (status != CAM_REQ_CMP) {
+ CAM_SIM_UNLOCK(sim);
+ printf("%s: unable to create path for wildcard periph\n",
+ __func__);
+ return;
+ }
+
+
+ if ((periph = cam_periph_find(path, "ctl")) != NULL)
+ cam_periph_invalidate(periph);
+
+ xpt_free_path(path);
+
+ CAM_SIM_UNLOCK(sim);
}
static int
@@ -1890,21 +1973,17 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
bus_softc = (struct ctlfe_softc *)arg;
sim = bus_softc->sim;
- CAM_SIM_LOCK(sim);
-
- status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
- targ_id.id, lun_id);
+ status = xpt_create_path_unlocked(&path, /*periph*/ NULL,
+ bus_softc->path_id,
+ targ_id.id, lun_id);
/* XXX KDM need some way to return status to CTL here? */
if (status != CAM_REQ_CMP) {
printf("%s: could not create path, status %#x\n", __func__,
status);
- CAM_SIM_UNLOCK(sim);
return (1);
}
- CAM_SIM_UNLOCK(sim);
softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
-
CAM_SIM_LOCK(sim);
periph = cam_periph_find(path, "ctl");
if (periph != NULL) {
@@ -1937,23 +2016,20 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
}
/*
- * XXX KDM we disable LUN removal here. The problem is that the isp(4)
- * driver doesn't currently handle LUN removal properly. We need to keep
- * enough state here at the peripheral level even after LUNs have been
- * removed inside CTL.
- *
- * Once the isp(4) driver is fixed, this can be re-enabled.
+ * This will get called when the user removes a LUN to disable that LUN
+ * on every bus that is attached to CTL.
*/
static int
ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
{
-#ifdef NOTYET
struct ctlfe_softc *softc;
struct ctlfe_lun_softc *lun_softc;
+ struct cam_sim *sim;
softc = (struct ctlfe_softc *)arg;
+ sim = softc->sim;
- mtx_lock(softc->sim->mtx);
+ CAM_SIM_LOCK(sim);
STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
struct cam_path *path;
@@ -1965,7 +2041,7 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
}
}
if (lun_softc == NULL) {
- mtx_unlock(softc->sim->mtx);
+ CAM_SIM_UNLOCK(sim);
printf("%s: can't find target %d lun %d\n", __func__,
targ_id.id, lun_id);
return (1);
@@ -1973,8 +2049,7 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
cam_periph_invalidate(lun_softc->periph);
- mtx_unlock(softc->sim->mtx);
-#endif
+ CAM_SIM_UNLOCK(sim);
return (0);
}
@@ -2139,7 +2214,7 @@ ctlfe_datamove_done(union ctl_io *io)
sim = xpt_path_sim(ccb->ccb_h.path);
- mtx_lock(sim->mtx);
+ CAM_SIM_LOCK(sim);
periph = xpt_path_periph(ccb->ccb_h.path);
@@ -2186,7 +2261,7 @@ ctlfe_datamove_done(union ctl_io *io)
xpt_schedule(periph, /*priority*/ 1);
}
- mtx_unlock(sim->mtx);
+ CAM_SIM_UNLOCK(sim);
}
static void
diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index a37ae19..9dac9c0 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -3071,16 +3071,15 @@ scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
SSQ_PRINT_SENSE;
}
}
- if ((action & SS_MASK) >= SS_START &&
- (sense_flags & SF_NO_RECOVERY)) {
- action &= ~SS_MASK;
- action |= SS_FAIL;
- } else if ((action & SS_MASK) == SS_RETRY &&
- (sense_flags & SF_NO_RETRY)) {
- action &= ~SS_MASK;
- action |= SS_FAIL;
- }
-
+ }
+ if ((action & SS_MASK) >= SS_START &&
+ (sense_flags & SF_NO_RECOVERY)) {
+ action &= ~SS_MASK;
+ action |= SS_FAIL;
+ } else if ((action & SS_MASK) == SS_RETRY &&
+ (sense_flags & SF_NO_RETRY)) {
+ action &= ~SS_MASK;
+ action |= SS_FAIL;
}
if ((sense_flags & SF_PRINT_ALWAYS) != 0)
action |= SSQ_PRINT_SENSE;
@@ -3140,7 +3139,7 @@ scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
*cdb_string = '\0';
for (i = 0; i < cdb_len; i++)
snprintf(cdb_string + strlen(cdb_string),
- len - strlen(cdb_string), "%x ", cdb_ptr[i]);
+ len - strlen(cdb_string), "%02hhx ", cdb_ptr[i]);
return(cdb_string);
}
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index d5d7156..a7c4c5b 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -581,7 +581,7 @@ cdasync(void *callback_arg, u_int32_t code,
if (softc->state == CD_STATE_NORMAL && !softc->tur) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
- xpt_schedule(periph, CAM_PRIORITY_DEV);
+ xpt_schedule(periph, CAM_PRIORITY_NORMAL);
}
}
/* FALLTHROUGH */
@@ -1612,9 +1612,11 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
xpt_action(start_ccb);
}
- if (bp != NULL || softc->tur) {
+ if (bp != NULL || softc->tur ||
+ periph->immediate_priority != CAM_PRIORITY_NONE) {
/* Have more work to do, so ensure we stay scheduled */
- xpt_schedule(periph, CAM_PRIORITY_NORMAL);
+ xpt_schedule(periph, min(CAM_PRIORITY_NORMAL,
+ periph->immediate_priority));
}
break;
}
@@ -3293,10 +3295,11 @@ cdmediapoll(void *arg)
if (softc->flags & CD_FLAG_CHANGER)
return;
- if (softc->state == CD_STATE_NORMAL && !softc->tur) {
+ if (softc->state == CD_STATE_NORMAL && !softc->tur &&
+ softc->outstanding_cmds == 0) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
- xpt_schedule(periph, CAM_PRIORITY_DEV);
+ xpt_schedule(periph, CAM_PRIORITY_NORMAL);
}
}
/* Queue us up again */
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index adda9c9..7854215 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -863,6 +863,8 @@ static void daasync(void *callback_arg, u_int32_t code,
static void dasysctlinit(void *context, int pending);
static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS);
+static int dadeletemethodset(struct da_softc *softc,
+ da_delete_methods delete_method);
static periph_ctor_t daregister;
static periph_dtor_t dacleanup;
static periph_start_t dastart;
@@ -1079,6 +1081,9 @@ daschedule(struct cam_periph *periph)
struct da_softc *softc = (struct da_softc *)periph->softc;
uint32_t prio;
+ if (softc->state != DA_STATE_NORMAL)
+ return;
+
/* Check if cam_periph_getccb() was called. */
prio = periph->immediate_priority;
@@ -1423,10 +1428,10 @@ daasync(void *callback_arg, u_int32_t code,
}
case AC_SCSI_AEN:
softc = (struct da_softc *)periph->softc;
- if (softc->state == DA_STATE_NORMAL && !softc->tur) {
+ if (!softc->tur) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
- xpt_schedule(periph, CAM_PRIORITY_DEV);
+ daschedule(periph);
}
}
/* FALLTHROUGH */
@@ -1489,7 +1494,7 @@ dasysctlinit(void *context, int pending)
*/
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RW,
- &softc->delete_method, 0, dadeletemethodsysctl, "A",
+ softc, 0, dadeletemethodsysctl, "A",
"BIO_DELETE execution method");
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
@@ -1566,14 +1571,33 @@ dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
}
static int
+dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method)
+{
+
+ if (delete_method < 0 || delete_method > DA_DELETE_MAX)
+ return (EINVAL);
+
+ softc->delete_method = delete_method;
+
+ if (softc->delete_method > DA_DELETE_DISABLE)
+ softc->disk->d_flags |= DISKFLAG_CANDELETE;
+ else
+ softc->disk->d_flags &= ~DISKFLAG_CANDELETE;
+
+ return (0);
+}
+
+static int
dadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
{
char buf[16];
- int error;
const char *p;
- int i, value;
+ struct da_softc *softc;
+ int i, error, value;
- value = *(int *)arg1;
+ softc = (struct da_softc *)arg1;
+
+ value = softc->delete_method;
if (value < 0 || value > DA_DELETE_MAX)
p = "UNKNOWN";
else
@@ -1585,8 +1609,7 @@ dadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
for (i = 0; i <= DA_DELETE_MAX; i++) {
if (strcmp(buf, da_delete_method_names[i]) != 0)
continue;
- *(int *)arg1 = i;
- return (0);
+ return dadeletemethodset(softc, i);
}
return (EINVAL);
}
@@ -2014,7 +2037,6 @@ out:
}
case DA_STATE_PROBE:
{
- struct ccb_scsiio *csio;
struct scsi_read_capacity_data *rcap;
rcap = (struct scsi_read_capacity_data *)
@@ -2024,9 +2046,8 @@ out:
/* da_free_periph??? */
break;
}
- csio = &start_ccb->csio;
- scsi_read_capacity(csio,
- /*retries*/4,
+ scsi_read_capacity(&start_ccb->csio,
+ /*retries*/da_retry_count,
dadone,
MSG_SIMPLE_Q_TAG,
rcap,
@@ -2039,7 +2060,6 @@ out:
}
case DA_STATE_PROBE2:
{
- struct ccb_scsiio *csio;
struct scsi_read_capacity_data_long *rcaplong;
rcaplong = (struct scsi_read_capacity_data_long *)
@@ -2049,9 +2069,8 @@ out:
/* da_free_periph??? */
break;
}
- csio = &start_ccb->csio;
- scsi_read_capacity_16(csio,
- /*retries*/ 4,
+ scsi_read_capacity_16(&start_ccb->csio,
+ /*retries*/ da_retry_count,
/*cbfcnp*/ dadone,
/*tag_action*/ MSG_SIMPLE_Q_TAG,
/*lba*/ 0,
@@ -2060,7 +2079,7 @@ out:
/*rcap_buf*/ (uint8_t *)rcaplong,
/*rcap_buf_len*/ sizeof(*rcaplong),
/*sense_len*/ SSD_FULL_SIZE,
- /*timeout*/ 60000);
+ /*timeout*/ da_default_timeout * 1000);
start_ccb->ccb_h.ccb_bp = NULL;
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE2;
xpt_action(start_ccb);
@@ -2086,24 +2105,24 @@ cmd6workaround(union ccb *ccb)
if (softc->delete_method == DA_DELETE_UNMAP) {
xpt_print(ccb->ccb_h.path, "UNMAP is not supported, "
"switching to WRITE SAME(16) with UNMAP.\n");
- softc->delete_method = DA_DELETE_WS16;
+ dadeletemethodset(softc, DA_DELETE_WS16);
} else if (softc->delete_method == DA_DELETE_WS16) {
xpt_print(ccb->ccb_h.path,
"WRITE SAME(16) with UNMAP is not supported, "
"disabling BIO_DELETE.\n");
- softc->delete_method = DA_DELETE_DISABLE;
+ dadeletemethodset(softc, DA_DELETE_DISABLE);
} else if (softc->delete_method == DA_DELETE_WS10) {
xpt_print(ccb->ccb_h.path,
"WRITE SAME(10) with UNMAP is not supported, "
"disabling BIO_DELETE.\n");
- softc->delete_method = DA_DELETE_DISABLE;
+ dadeletemethodset(softc, DA_DELETE_DISABLE);
} else if (softc->delete_method == DA_DELETE_ZERO) {
xpt_print(ccb->ccb_h.path,
"WRITE SAME(10) is not supported, "
"disabling BIO_DELETE.\n");
- softc->delete_method = DA_DELETE_DISABLE;
+ dadeletemethodset(softc, DA_DELETE_DISABLE);
} else
- softc->delete_method = DA_DELETE_DISABLE;
+ dadeletemethodset(softc, DA_DELETE_DISABLE);
while ((bp = bioq_takefirst(&softc->delete_run_queue))
!= NULL)
bioq_disksort(&softc->delete_queue, bp);
@@ -2152,6 +2171,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
struct da_softc *softc;
struct ccb_scsiio *csio;
u_int32_t priority;
+ da_ccb_state state;
softc = (struct da_softc *)periph->softc;
priority = done_ccb->ccb_h.pinfo.priority;
@@ -2159,7 +2179,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
csio = &done_ccb->csio;
- switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
+ state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
+ switch (state) {
case DA_CCB_BUFFER_IO:
case DA_CCB_DELETE:
{
@@ -2257,8 +2278,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
softc->outstanding_cmds);
}
- if ((csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) ==
- DA_CCB_DELETE) {
+ if (state == DA_CCB_DELETE) {
while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
!= NULL) {
bp1->bio_resid = bp->bio_resid;
@@ -2284,7 +2304,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
rdcap = NULL;
rcaplong = NULL;
- if (softc->state == DA_STATE_PROBE)
+ if (state == DA_CCB_PROBE)
rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
else
rcaplong = (struct scsi_read_capacity_data_long *)
@@ -2297,7 +2317,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
u_int lbppbe; /* LB per physical block exponent. */
u_int lalba; /* Lowest aligned LBA. */
- if (softc->state == DA_STATE_PROBE) {
+ if (state == DA_CCB_PROBE) {
block_size = scsi_4btoul(rdcap->length);
maxsector = scsi_4btoul(rdcap->addr);
lbppbe = 0;
@@ -2349,7 +2369,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
rcaplong, sizeof(*rcaplong));
if ((lalba & SRC16_LBPME_A)
&& softc->delete_method == DA_DELETE_NONE)
- softc->delete_method = DA_DELETE_UNMAP;
+ dadeletemethodset(softc, DA_DELETE_UNMAP);
dp = &softc->params;
snprintf(announce_buf, sizeof(announce_buf),
"%juMB (%ju %u byte sectors: %dH %dS/T "
@@ -2410,7 +2430,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* If we tried READ CAPACITY(16) and failed,
* fallback to READ CAPACITY(10).
*/
- if ((softc->state == DA_STATE_PROBE2) &&
+ if ((state == DA_CCB_PROBE2) &&
(softc->flags & DA_FLAG_CAN_RC16) &&
(((csio->ccb_h.status & CAM_STATUS_MASK) ==
CAM_REQ_INVALID) ||
@@ -2490,7 +2510,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* operation.
*/
xpt_release_ccb(done_ccb);
- softc->state = DA_STATE_NORMAL;
+ softc->state = DA_STATE_NORMAL;
+ daschedule(periph);
wakeup(&softc->disk->d_mediasize);
if ((softc->flags & DA_FLAG_PROBED) == 0) {
softc->flags |= DA_FLAG_PROBED;
@@ -2615,7 +2636,7 @@ damediapoll(void *arg)
struct cam_periph *periph = arg;
struct da_softc *softc = periph->softc;
- if (softc->state == DA_STATE_NORMAL && !softc->tur) {
+ if (!softc->tur && softc->outstanding_cmds == 0) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
daschedule(periph);
diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c
index 79e96db..c4a8c49 100644
--- a/sys/cam/scsi/scsi_enc_ses.c
+++ b/sys/cam/scsi/scsi_enc_ses.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/ctype.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@@ -1053,10 +1054,11 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
{
struct ccb_dev_advinfo cdai;
ses_setphyspath_callback_args_t args;
- int ret;
+ int i, ret;
struct sbuf sb;
uint8_t *devid, *elmaddr;
ses_element_t *elmpriv;
+ const char *c;
ret = EIO;
devid = NULL;
@@ -1099,7 +1101,13 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
elmpriv = elm->elm_private;
if (elmpriv->descr != NULL && elmpriv->descr_len > 0) {
sbuf_cat(&sb, "/elmdesc@");
- sbuf_bcat(&sb, elmpriv->descr, elmpriv->descr_len);
+ for (i = 0, c = elmpriv->descr; i < elmpriv->descr_len;
+ i++, c++) {
+ if (!isprint(*c) || isspace(*c) || *c == '/')
+ sbuf_putc(&sb, '_');
+ else
+ sbuf_putc(&sb, *c);
+ }
}
sbuf_finish(&sb);
diff --git a/sys/cddl/compat/opensolaris/sys/kmem.h b/sys/cddl/compat/opensolaris/sys/kmem.h
index 428badf..ba8b42d 100644
--- a/sys/cddl/compat/opensolaris/sys/kmem.h
+++ b/sys/cddl/compat/opensolaris/sys/kmem.h
@@ -45,7 +45,6 @@ MALLOC_DECLARE(M_SOLARIS);
#define KM_SLEEP M_WAITOK
#define KM_PUSHPAGE M_WAITOK
#define KM_NOSLEEP M_NOWAIT
-#define KM_ZERO M_ZERO
#define KM_NODEBUG M_NODUMP
#define KMC_NODEBUG UMA_ZONE_NODUMP
#define KMC_NOTOUCH 0
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
index ef3d0f4..885af95 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
@@ -89,12 +89,13 @@ ddt_object_destroy(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
spa_t *spa = ddt->ddt_spa;
objset_t *os = ddt->ddt_os;
uint64_t *objectp = &ddt->ddt_object[type][class];
+ uint64_t count;
char name[DDT_NAMELEN];
ddt_object_name(ddt, type, class, name);
ASSERT(*objectp != 0);
- ASSERT(ddt_object_count(ddt, type, class) == 0);
+ VERIFY(ddt_object_count(ddt, type, class, &count) == 0 && count == 0);
ASSERT(ddt_histogram_empty(&ddt->ddt_histogram[type][class]));
VERIFY(zap_remove(os, DMU_POOL_DIRECTORY_OBJECT, name, tx) == 0);
VERIFY(zap_remove(os, spa->spa_ddt_stat_object, name, tx) == 0);
@@ -109,6 +110,7 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
{
ddt_object_t *ddo = &ddt->ddt_object_stats[type][class];
dmu_object_info_t doi;
+ uint64_t count;
char name[DDT_NAMELEN];
int error;
@@ -129,7 +131,11 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
*/
VERIFY(ddt_object_info(ddt, type, class, &doi) == 0);
- ddo->ddo_count = ddt_object_count(ddt, type, class);
+ error = ddt_object_count(ddt, type, class, &count);
+ if (error)
+ return error;
+
+ ddo->ddo_count = count;
ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9;
ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size;
@@ -143,6 +149,7 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
{
ddt_object_t *ddo = &ddt->ddt_object_stats[type][class];
dmu_object_info_t doi;
+ uint64_t count;
char name[DDT_NAMELEN];
ddt_object_name(ddt, type, class, name);
@@ -155,8 +162,9 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
* Cache DDT statistics; this is the only time they'll change.
*/
VERIFY(ddt_object_info(ddt, type, class, &doi) == 0);
+ VERIFY(ddt_object_count(ddt, type, class, &count) == 0);
- ddo->ddo_count = ddt_object_count(ddt, type, class);
+ ddo->ddo_count = count;
ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9;
ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size;
}
@@ -213,13 +221,13 @@ ddt_object_walk(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
ddt->ddt_object[type][class], dde, walk));
}
-uint64_t
-ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
+int
+ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class, uint64_t *count)
{
ASSERT(ddt_object_exists(ddt, type, class));
return (ddt_ops[type]->ddt_op_count(ddt->ddt_os,
- ddt->ddt_object[type][class]));
+ ddt->ddt_object[type][class], count));
}
int
@@ -1079,11 +1087,13 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, uint64_t txg)
}
for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- uint64_t count = 0;
+ uint64_t add, count = 0;
for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
if (ddt_object_exists(ddt, type, class)) {
ddt_object_sync(ddt, type, class, tx);
- count += ddt_object_count(ddt, type, class);
+ VERIFY(ddt_object_count(ddt, type, class,
+ &add) == 0);
+ count += add;
}
}
for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
index 6812aa3..f42b4dd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
@@ -133,14 +133,11 @@ ddt_zap_walk(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk)
return (error);
}
-static uint64_t
-ddt_zap_count(objset_t *os, uint64_t object)
+static int
+ddt_zap_count(objset_t *os, uint64_t object, uint64_t *count)
{
- uint64_t count = 0;
-
- VERIFY(zap_count(os, object, &count) == 0);
- return (count);
+ return (zap_count(os, object, count));
}
const ddt_ops_t ddt_zap_ops = {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
index 4392ea8..8da3f0e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
@@ -3792,9 +3792,8 @@ spa_generate_rootconf(const char *name)
/*
* Multi-vdev root pool configuration discovery is not supported yet.
*/
- nchildren = 0;
- VERIFY(nvlist_lookup_uint64(best_cfg, ZPOOL_CONFIG_VDEV_CHILDREN,
- &nchildren) == 0);
+ nchildren = 1;
+ nvlist_lookup_uint64(best_cfg, ZPOOL_CONFIG_VDEV_CHILDREN, &nchildren);
holes = NULL;
nvlist_lookup_uint64_array(best_cfg, ZPOOL_CONFIG_HOLE_ARRAY,
&holes, &nholes);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
index 405622b..5d9747b 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
@@ -163,7 +163,7 @@ typedef struct ddt_ops {
dmu_tx_t *tx);
int (*ddt_op_walk)(objset_t *os, uint64_t object, ddt_entry_t *dde,
uint64_t *walk);
- uint64_t (*ddt_op_count)(objset_t *os, uint64_t object);
+ int (*ddt_op_count)(objset_t *os, uint64_t object, uint64_t *count);
} ddt_ops_t;
#define DDT_NAMELEN 80
@@ -172,8 +172,8 @@ extern void ddt_object_name(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, char *name);
extern int ddt_object_walk(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, uint64_t *walk, ddt_entry_t *dde);
-extern uint64_t ddt_object_count(ddt_t *ddt, enum ddt_type type,
- enum ddt_class cls);
+extern int ddt_object_count(ddt_t *ddt, enum ddt_type type,
+ enum ddt_class class, uint64_t *count);
extern int ddt_object_info(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, dmu_object_info_t *);
extern boolean_t ddt_object_exists(ddt_t *ddt, enum ddt_type type,
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
index dac619b..ce0579c 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <sys/zfs_context.h>
@@ -33,7 +33,76 @@
#include <sys/callb.h>
/*
- * Pool-wide transaction groups.
+ * ZFS Transaction Groups
+ * ----------------------
+ *
+ * ZFS transaction groups are, as the name implies, groups of transactions
+ * that act on persistent state. ZFS asserts consistency at the granularity of
+ * these transaction groups. Each successive transaction group (txg) is
+ * assigned a 64-bit consecutive identifier. There are three active
+ * transaction group states: open, quiescing, or syncing. At any given time,
+ * there may be an active txg associated with each state; each active txg may
+ * either be processing, or blocked waiting to enter the next state. There may
+ * be up to three active txgs, and there is always a txg in the open state
+ * (though it may be blocked waiting to enter the quiescing state). In broad
+ * strokes, transactions — operations that change in-memory structures — are
+ * accepted into the txg in the open state, and are completed while the txg is
+ * in the open or quiescing states. The accumulated changes are written to
+ * disk in the syncing state.
+ *
+ * Open
+ *
+ * When a new txg becomes active, it first enters the open state. New
+ * transactions — updates to in-memory structures — are assigned to the
+ * currently open txg. There is always a txg in the open state so that ZFS can
+ * accept new changes (though the txg may refuse new changes if it has hit
+ * some limit). ZFS advances the open txg to the next state for a variety of
+ * reasons such as it hitting a time or size threshold, or the execution of an
+ * administrative action that must be completed in the syncing state.
+ *
+ * Quiescing
+ *
+ * After a txg exits the open state, it enters the quiescing state. The
+ * quiescing state is intended to provide a buffer between accepting new
+ * transactions in the open state and writing them out to stable storage in
+ * the syncing state. While quiescing, transactions can continue their
+ * operation without delaying either of the other states. Typically, a txg is
+ * in the quiescing state very briefly since the operations are bounded by
+ * software latencies rather than, say, slower I/O latencies. After all
+ * transactions complete, the txg is ready to enter the next state.
+ *
+ * Syncing
+ *
+ * In the syncing state, the in-memory state built up during the open and (to
+ * a lesser degree) the quiescing states is written to stable storage. The
+ * process of writing out modified data can, in turn modify more data. For
+ * example when we write new blocks, we need to allocate space for them; those
+ * allocations modify metadata (space maps)... which themselves must be
+ * written to stable storage. During the sync state, ZFS iterates, writing out
+ * data until it converges and all in-memory changes have been written out.
+ * The first such pass is the largest as it encompasses all the modified user
+ * data (as opposed to filesystem metadata). Subsequent passes typically have
+ * far less data to write as they consist exclusively of filesystem metadata.
+ *
+ * To ensure convergence, after a certain number of passes ZFS begins
+ * overwriting locations on stable storage that had been allocated earlier in
+ * the syncing state (and subsequently freed). ZFS usually allocates new
+ * blocks to optimize for large, continuous, writes. For the syncing state to
+ * converge however it must complete a pass where no new blocks are allocated
+ * since each allocation requires a modification of persistent metadata.
+ * Further, to hasten convergence, after a prescribed number of passes, ZFS
+ * also defers frees, and stops compressing.
+ *
+ * In addition to writing out user data, we must also execute synctasks during
+ * the syncing context. A synctask is the mechanism by which some
+ * administrative activities work such as creating and destroying snapshots or
+ * datasets. Note that when a synctask is initiated it enters the open txg,
+ * and ZFS then pushes that txg as quickly as possible to completion of the
+ * syncing state in order to reduce the latency of the administrative
+ * activity. To complete the syncing state, ZFS writes out a new uberblock,
+ * the root of the tree of blocks that comprise all state stored on the ZFS
+ * pool. Finally, if there is a quiesced txg waiting, we signal that it can
+ * now transition to the syncing state.
*/
static void txg_sync_thread(void *arg);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index e4157df..6fa9cea 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -5536,6 +5536,7 @@ static moduledata_t zfs_mod = {
0
};
DECLARE_MODULE(zfsctrl, zfs_mod, SI_SUB_VFS, SI_ORDER_ANY);
+MODULE_VERSION(zfsctrl, 1);
MODULE_DEPEND(zfsctrl, opensolaris, 1, 1, 1);
MODULE_DEPEND(zfsctrl, krpc, 1, 1, 1);
MODULE_DEPEND(zfsctrl, acl_nfs4, 1, 1, 1);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
index 72c22dc..7f3f7a1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -2025,6 +2025,8 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
err = zfs_vnode_lock(*vpp, flags);
if (err != 0)
*vpp = NULL;
+ else
+ (*vpp)->v_hash = ino;
return (err);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index 354deaa..9438266 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -323,7 +323,7 @@ zfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred,
}
static vm_page_t
-page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
+page_busy(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
{
vm_object_t obj;
vm_page_t pp;
@@ -332,32 +332,30 @@ page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
VM_OBJECT_LOCK_ASSERT(obj, MA_OWNED);
for (;;) {
- pp = vm_radix_lookup(&obj->rtree, OFF_TO_IDX(start),
- VM_RADIX_ANY);
- if (pp != NULL) {
- if (vm_page_is_valid(pp, (vm_offset_t)off, nbytes)) {
- if ((pp->oflags & VPO_BUSY) != 0) {
- /*
- * Reference the page before unlocking
- * and sleeping so that the page
- * daemon is less likely to reclaim it.
- */
- vm_page_reference(pp);
- vm_page_sleep(pp, "zfsmwb");
- continue;
- }
- vm_page_busy(pp);
- vm_page_undirty(pp);
- } else {
- if (obj->cached_page_count != 0 &&
- (pp->flags & PG_CACHED) != 0) {
- mtx_lock(&vm_page_queue_free_mtx);
- if (pp->object == obj)
- vm_page_cache_free(pp);
- mtx_unlock(&vm_page_queue_free_mtx);
- }
- pp = NULL;
+ if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
+ pp->valid) {
+ if ((pp->oflags & VPO_BUSY) != 0) {
+ /*
+ * Reference the page before unlocking and
+ * sleeping so that the page daemon is less
+ * likely to reclaim it.
+ */
+ vm_page_reference(pp);
+ vm_page_sleep(pp, "zfsmwb");
+ continue;
}
+ } else {
+ pp = vm_page_alloc(obj, OFF_TO_IDX(start),
+ VM_ALLOC_SYSTEM | VM_ALLOC_IFCACHED |
+ VM_ALLOC_NOBUSY);
+ }
+
+ if (pp != NULL) {
+ ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL);
+ vm_object_pip_add(obj, 1);
+ vm_page_io_start(pp);
+ pmap_remove_write(pp);
+ vm_page_clear_dirty(pp, off, nbytes);
}
break;
}
@@ -365,10 +363,55 @@ page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
}
static void
-page_unlock(vm_page_t pp)
+page_unbusy(vm_page_t pp)
{
- vm_page_wakeup(pp);
+ vm_page_io_finish(pp);
+ vm_object_pip_subtract(pp->object, 1);
+}
+
+static vm_page_t
+page_hold(vnode_t *vp, int64_t start)
+{
+ vm_object_t obj;
+ vm_page_t pp;
+
+ obj = vp->v_object;
+ VM_OBJECT_LOCK_ASSERT(obj, MA_OWNED);
+
+ for (;;) {
+ if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
+ pp->valid) {
+ if ((pp->oflags & VPO_BUSY) != 0) {
+ /*
+ * Reference the page before unlocking and
+ * sleeping so that the page daemon is less
+ * likely to reclaim it.
+ */
+ vm_page_reference(pp);
+ vm_page_sleep(pp, "zfsmwb");
+ continue;
+ }
+
+ ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL);
+ vm_page_lock(pp);
+ vm_page_hold(pp);
+ vm_page_unlock(pp);
+
+ } else
+ pp = NULL;
+ break;
+ }
+ return (pp);
+}
+
+static void
+page_unhold(vm_page_t pp)
+{
+
+ vm_page_lock(pp);
+ vm_page_unhold(pp);
+ vm_page_unlock(pp);
}
static caddr_t
@@ -399,6 +442,7 @@ update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid,
{
vm_object_t obj;
struct sf_buf *sf;
+ caddr_t va;
int off;
ASSERT(vp->v_mount != NULL);
@@ -409,27 +453,44 @@ update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid,
VM_OBJECT_LOCK(obj);
for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
vm_page_t pp;
- int nbytes = MIN(PAGESIZE - off, len);
+ int nbytes = imin(PAGESIZE - off, len);
+
+ if (segflg == UIO_NOCOPY) {
+ pp = vm_page_lookup(obj, OFF_TO_IDX(start));
+ KASSERT(pp != NULL,
+ ("zfs update_pages: NULL page in putpages case"));
+ KASSERT(off == 0,
+ ("zfs update_pages: unaligned data in putpages case"));
+ KASSERT(pp->valid == VM_PAGE_BITS_ALL,
+ ("zfs update_pages: invalid page in putpages case"));
+ KASSERT(pp->busy > 0,
+ ("zfs update_pages: unbusy page in putpages case"));
+ KASSERT(!pmap_page_is_write_mapped(pp),
+ ("zfs update_pages: writable page in putpages case"));
+ VM_OBJECT_UNLOCK(obj);
- if ((pp = page_lookup(vp, start, off, nbytes)) != NULL) {
- caddr_t va;
+ va = zfs_map_page(pp, &sf);
+ (void) dmu_write(os, oid, start, nbytes, va, tx);
+ zfs_unmap_page(sf);
+ VM_OBJECT_LOCK(obj);
+ vm_page_undirty(pp);
+ } else if ((pp = page_busy(vp, start, off, nbytes)) != NULL) {
VM_OBJECT_UNLOCK(obj);
+
va = zfs_map_page(pp, &sf);
- if (segflg == UIO_NOCOPY) {
- (void) dmu_write(os, oid, start+off, nbytes,
- va+off, tx);
- } else {
- (void) dmu_read(os, oid, start+off, nbytes,
- va+off, DMU_READ_PREFETCH);
- }
+ (void) dmu_read(os, oid, start+off, nbytes,
+ va+off, DMU_READ_PREFETCH);;
zfs_unmap_page(sf);
+
VM_OBJECT_LOCK(obj);
- page_unlock(pp);
+ page_unbusy(pp);
}
len -= nbytes;
off = 0;
}
+ if (segflg != UIO_NOCOPY)
+ vm_object_pip_wakeupn(obj, 0);
VM_OBJECT_UNLOCK(obj);
}
@@ -531,7 +592,7 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio)
vm_page_t pp;
uint64_t bytes = MIN(PAGESIZE - off, len);
- if (pp = page_lookup(vp, start, off, bytes)) {
+ if (pp = page_hold(vp, start)) {
struct sf_buf *sf;
caddr_t va;
@@ -540,7 +601,7 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio)
error = uiomove(va + off, bytes, UIO_READ, uio);
zfs_unmap_page(sf);
VM_OBJECT_LOCK(obj);
- page_unlock(pp);
+ page_unhold(pp);
} else {
VM_OBJECT_UNLOCK(obj);
error = dmu_read_uio(os, zp->z_id, uio, bytes);
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
index 9ff83db..8537e3c 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
@@ -19,6 +19,8 @@
*
* CDDL HEADER END
*
+ * Portions Copyright 2012,2013 Justin Hibbits <jhibbits@freebsd.org>
+ *
* $FreeBSD$
*/
/*
@@ -114,48 +116,6 @@ ASENTRY_NOPROF(dtrace_fulword)
END(dtrace_fulword)
/*
-uint8_t
-dtrace_fuword8_nocheck(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fuword8_nocheck)
- lbz %r3,0(%r3)
- blr
-END(dtrace_fuword8_nocheck)
-
-/*
-uint16_t
-dtrace_fuword16_nocheck(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fuword16_nocheck)
- lhz %r3,0(%r3)
- blr
-END(dtrace_fuword16_nocheck)
-
-/*
-uint32_t
-dtrace_fuword32_nocheck(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fuword32_nocheck)
- lwz %r3,0(%r3)
- blr
-END(dtrace_fuword32_nocheck)
-
-/*
-uint64_t
-dtrace_fuword64_nocheck(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fuword64_nocheck)
-#if defined(__powerpc64__)
- ld %r3,0(%r3)
-#else
- lwz %r5,0(%r3)
- lwz %r4,4(%r3)
- mr %r3,%r5
-#endif
- blr
-END(dtrace_fuword64_nocheck)
-
-/*
XXX: unoptimized
void
dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
index a697816..efbca6f 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
@@ -19,6 +19,8 @@
*
* CDDL HEADER END
*
+ * Portions Copyright 2012,2013 Justin Hibbits <jhibbits@freebsd.org>
+ *
* $FreeBSD$
*/
/*
@@ -45,11 +47,6 @@
#include "regset.h"
-uint8_t dtrace_fuword8_nocheck(void *);
-uint16_t dtrace_fuword16_nocheck(void *);
-uint32_t dtrace_fuword32_nocheck(void *);
-uint64_t dtrace_fuword64_nocheck(void *);
-
/* Offset to the LR Save word (ppc32) */
#define RETURN_OFFSET 4
#define RETURN_OFFSET64 8
@@ -462,31 +459,63 @@ dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
volatile uint16_t *flags)
{
if (dtrace_copycheck(uaddr, kaddr, size))
- dtrace_copy(uaddr, kaddr, size);
+ if (copyin((const void *)uaddr, (void *)kaddr, size)) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
}
void
dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
volatile uint16_t *flags)
{
- if (dtrace_copycheck(uaddr, kaddr, size))
- dtrace_copy(kaddr, uaddr, size);
+ if (dtrace_copycheck(uaddr, kaddr, size)) {
+ if (copyout((const void *)kaddr, (void *)uaddr, size)) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
+ }
}
void
dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
volatile uint16_t *flags)
{
- if (dtrace_copycheck(uaddr, kaddr, size))
- dtrace_copystr(uaddr, kaddr, size, flags);
+ size_t actual;
+ int error;
+
+ if (dtrace_copycheck(uaddr, kaddr, size)) {
+ error = copyinstr((const void *)uaddr, (void *)kaddr,
+ size, &actual);
+
+ /* ENAMETOOLONG is not a fault condition. */
+ if (error && error != ENAMETOOLONG) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
+ }
}
+/*
+ * The bulk of this function could be replaced to match dtrace_copyinstr()
+ * if we ever implement a copyoutstr().
+ */
void
dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
volatile uint16_t *flags)
{
- if (dtrace_copycheck(uaddr, kaddr, size))
- dtrace_copystr(kaddr, uaddr, size, flags);
+ size_t len;
+
+ if (dtrace_copycheck(uaddr, kaddr, size)) {
+ len = strlen((const char *)kaddr);
+ if (len > size)
+ len = size;
+
+ if (copyout((const void *)kaddr, (void *)uaddr, len)) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
+ }
}
uint8_t
@@ -497,18 +526,21 @@ dtrace_fuword8(void *uaddr)
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
return (0);
}
- return (dtrace_fuword8_nocheck(uaddr));
+ return (fubyte(uaddr));
}
uint16_t
dtrace_fuword16(void *uaddr)
{
- if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
- DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
- cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
- return (0);
+ uint16_t ret = 0;
+
+ if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
+ if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
}
- return (dtrace_fuword16_nocheck(uaddr));
+ return ret;
}
uint32_t
@@ -519,16 +551,19 @@ dtrace_fuword32(void *uaddr)
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
return (0);
}
- return (dtrace_fuword32_nocheck(uaddr));
+ return (fuword32(uaddr));
}
uint64_t
dtrace_fuword64(void *uaddr)
{
- if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
- DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
- cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
- return (0);
+ uint64_t ret = 0;
+
+ if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
+ if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
}
- return (dtrace_fuword64_nocheck(uaddr));
+ return ret;
}
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 31cda7d..d86da04 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -101,13 +101,9 @@ __FBSDID("$FreeBSD$");
#include <compat/freebsd32/freebsd32_util.h>
#endif
-#ifdef COMPAT_LINUX32 /* XXX */
-#include <machine/../linux32/linux.h>
-#else
-#include <machine/../linux/linux.h>
-#endif
#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_util.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h>
diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c
index 6a1098d..61156ba 100644
--- a/sys/compat/linux/linux_emul.c
+++ b/sys/compat/linux/linux_emul.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <compat/linux/linux_dtrace.h>
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_misc.h>
/**
* Special DTrace provider for the linuxulator.
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index df13277..0318a5c 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
#endif
+#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_util.h>
#include <compat/linux/linux_file.h>
diff --git a/sys/compat/linux/linux_file.h b/sys/compat/linux/linux_file.h
index d0d95ac..2d3106f 100644
--- a/sys/compat/linux/linux_file.h
+++ b/sys/compat/linux/linux_file.h
@@ -35,4 +35,23 @@
#define LINUX_AT_REMOVEDIR 0x200
#define LINUX_AT_SYMLINK_FOLLOW 0x400
+/*
+ * posix_fadvise advice
+ */
+#define LINUX_POSIX_FADV_NORMAL 0
+#define LINUX_POSIX_FADV_RANDOM 1
+#define LINUX_POSIX_FADV_SEQUENTIAL 2
+#define LINUX_POSIX_FADV_WILLNEED 3
+#define LINUX_POSIX_FADV_DONTNEED 4
+#define LINUX_POSIX_FADV_NOREUSE 5
+
+/*
+ * mount flags
+ */
+#define LINUX_MS_RDONLY 0x0001
+#define LINUX_MS_NOSUID 0x0002
+#define LINUX_MS_NODEV 0x0004
+#define LINUX_MS_NOEXEC 0x0008
+#define LINUX_MS_REMOUNT 0x0020
+
#endif /* !_LINUX_FILE_H_ */
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
index f71063c..2103636 100644
--- a/sys/compat/linux/linux_fork.c
+++ b/sys/compat/linux/linux_fork.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <compat/linux/linux_dtrace.h>
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_misc.h>
/* DTrace init */
LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
index c87fd00..c1531d0 100644
--- a/sys/compat/linux/linux_futex.c
+++ b/sys/compat/linux/linux_futex.c
@@ -1203,7 +1203,7 @@ release_futexes(struct proc *p)
if (entry != pending)
if (handle_futex_death(p,
- (uint32_t *)entry + futex_offset, pi)) {
+ (uint32_t *)((caddr_t)entry + futex_offset), pi)) {
LIN_SDT_PROBE0(futex, release_futexes, return);
return;
}
@@ -1222,7 +1222,7 @@ release_futexes(struct proc *p)
}
if (pending)
- handle_futex_death(p, (uint32_t *)pending + futex_offset, pip);
+ handle_futex_death(p, (uint32_t *)((caddr_t)pending + futex_offset), pip);
LIN_SDT_PROBE0(futex, release_futexes, return);
}
diff --git a/sys/compat/linux/linux_ioctl.h b/sys/compat/linux/linux_ioctl.h
index c075231..aa7650b 100644
--- a/sys/compat/linux/linux_ioctl.h
+++ b/sys/compat/linux/linux_ioctl.h
@@ -748,4 +748,20 @@ int linux_ifname(struct ifnet *, char *, size_t);
#define FBSD_LUSB_MAX 0xffff
#define FBSD_LUSB_MIN 0xffe0
+/*
+ * Pluggable ioctl handlers
+ */
+struct linux_ioctl_args;
+struct thread;
+
+typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *);
+
+struct linux_ioctl_handler {
+ linux_ioctl_function_t *func;
+ int low, high;
+};
+
+int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
+int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
+
#endif /* !_LINUX_IOCTL_H_ */
diff --git a/sys/compat/linux/linux_ipc.h b/sys/compat/linux/linux_ipc.h
index 4c01342..f1531ba 100644
--- a/sys/compat/linux/linux_ipc.h
+++ b/sys/compat/linux/linux_ipc.h
@@ -32,6 +32,48 @@
#define _LINUX_IPC_H_
/*
+ * SystemV IPC defines
+ */
+#define LINUX_SEMOP 1
+#define LINUX_SEMGET 2
+#define LINUX_SEMCTL 3
+#define LINUX_MSGSND 11
+#define LINUX_MSGRCV 12
+#define LINUX_MSGGET 13
+#define LINUX_MSGCTL 14
+#define LINUX_SHMAT 21
+#define LINUX_SHMDT 22
+#define LINUX_SHMGET 23
+#define LINUX_SHMCTL 24
+
+#define LINUX_IPC_RMID 0
+#define LINUX_IPC_SET 1
+#define LINUX_IPC_STAT 2
+#define LINUX_IPC_INFO 3
+
+#define LINUX_MSG_INFO 12
+
+#define LINUX_SHM_LOCK 11
+#define LINUX_SHM_UNLOCK 12
+#define LINUX_SHM_STAT 13
+#define LINUX_SHM_INFO 14
+
+#define LINUX_SHM_RDONLY 0x1000
+#define LINUX_SHM_RND 0x2000
+#define LINUX_SHM_REMAP 0x4000
+
+/* semctl commands */
+#define LINUX_GETPID 11
+#define LINUX_GETVAL 12
+#define LINUX_GETALL 13
+#define LINUX_GETNCNT 14
+#define LINUX_GETZCNT 15
+#define LINUX_SETVAL 16
+#define LINUX_SETALL 17
+#define LINUX_SEM_STAT 18
+#define LINUX_SEM_INFO 19
+
+/*
* Version flags for semctl, msgctl, and shmctl commands
* These are passed as bitflags or-ed with the actual command
*/
@@ -135,8 +177,6 @@ int linux_shmctl(struct thread *, struct linux_shmctl_args *);
int linux_shmdt(struct thread *, struct linux_shmdt_args *);
int linux_shmget(struct thread *, struct linux_shmget_args *);
-#define LINUX_MSG_INFO 12
-
#endif /* __i386__ || __amd64__ */
#endif /* _LINUX_IPC_H_ */
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
index 0856662..323a38f 100644
--- a/sys/compat/linux/linux_mib.c
+++ b/sys/compat/linux/linux_mib.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <compat/linux/linux_dtrace.h>
#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
/* DTrace init */
LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h
index b771825..154d78f 100644
--- a/sys/compat/linux/linux_misc.h
+++ b/sys/compat/linux/linux_misc.h
@@ -31,6 +31,14 @@
#ifndef _LINUX_MISC_H_
#define _LINUX_MISC_H_
+/*
+ * Miscellaneous
+ */
+#define LINUX_NAME_MAX 255
+#define LINUX_MAX_UTSNAME 65
+
+#define LINUX_CTL_MAXNAME 10
+
/* defines for prctl */
#define LINUX_PR_SET_PDEATHSIG 1 /* Second arg is a signal. */
#define LINUX_PR_GET_PDEATHSIG 2 /*
@@ -67,11 +75,51 @@ extern const char *linux_platform;
#define __LINUX_NPXCW__ 0x37f
#endif
+#define LINUX_CLONE_VM 0x00000100
+#define LINUX_CLONE_FS 0x00000200
+#define LINUX_CLONE_FILES 0x00000400
+#define LINUX_CLONE_SIGHAND 0x00000800
+#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
+#define LINUX_CLONE_VFORK 0x00004000
+#define LINUX_CLONE_PARENT 0x00008000
+#define LINUX_CLONE_THREAD 0x00010000
+#define LINUX_CLONE_SETTLS 0x00080000
+#define LINUX_CLONE_PARENT_SETTID 0x00100000
+#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
+#define LINUX_CLONE_CHILD_SETTID 0x01000000
+
+#define LINUX_THREADING_FLAGS \
+ (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
+ LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
+
+/* Scheduling policies */
+#define LINUX_SCHED_OTHER 0
+#define LINUX_SCHED_FIFO 1
+#define LINUX_SCHED_RR 2
+
+struct l_new_utsname {
+ char sysname[LINUX_MAX_UTSNAME];
+ char nodename[LINUX_MAX_UTSNAME];
+ char release[LINUX_MAX_UTSNAME];
+ char version[LINUX_MAX_UTSNAME];
+ char machine[LINUX_MAX_UTSNAME];
+ char domainname[LINUX_MAX_UTSNAME];
+};
+
+#define LINUX_CLOCK_REALTIME 0
+#define LINUX_CLOCK_MONOTONIC 1
+#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
+#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
+#define LINUX_CLOCK_REALTIME_HR 4
+#define LINUX_CLOCK_MONOTONIC_HR 5
+
extern int stclohz;
#define __WCLONE 0x80000000
int linux_common_wait(struct thread *td, int pid, int *status,
int options, struct rusage *ru);
+int linux_set_upcall_kse(struct thread *td, register_t stack);
+int linux_set_cloned_tls(struct thread *td, void *desc);
#endif /* _LINUX_MISC_H_ */
diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h
index 939009f..426cf43 100644
--- a/sys/compat/linux/linux_signal.h
+++ b/sys/compat/linux/linux_signal.h
@@ -33,6 +33,9 @@
#define LINUX_SI_TKILL -6;
+extern int bsd_to_linux_signal[];
+extern int linux_to_bsd_signal[];
+
void linux_to_bsd_sigset(l_sigset_t *, sigset_t *);
void bsd_to_linux_sigset(sigset_t *, l_sigset_t *);
int linux_do_sigaction(struct thread *, int, l_sigaction_t *, l_sigaction_t *);
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 7271a18..cd288f8 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <netinet/tcp.h>
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
@@ -326,6 +327,27 @@ linux_to_bsd_so_sockopt(int opt)
}
static int
+linux_to_bsd_tcp_sockopt(int opt)
+{
+
+ switch (opt) {
+ case LINUX_TCP_NODELAY:
+ return (TCP_NODELAY);
+ case LINUX_TCP_MAXSEG:
+ return (TCP_MAXSEG);
+ case LINUX_TCP_KEEPIDLE:
+ return (TCP_KEEPIDLE);
+ case LINUX_TCP_KEEPINTVL:
+ return (TCP_KEEPINTVL);
+ case LINUX_TCP_KEEPCNT:
+ return (TCP_KEEPCNT);
+ case LINUX_TCP_MD5SIG:
+ return (TCP_MD5SIG);
+ }
+ return (-1);
+}
+
+static int
linux_to_bsd_msg_flags(int flags)
{
int ret_flags = 0;
@@ -1496,8 +1518,7 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
name = linux_to_bsd_ip_sockopt(args->optname);
break;
case IPPROTO_TCP:
- /* Linux TCP option values match BSD's */
- name = args->optname;
+ name = linux_to_bsd_tcp_sockopt(args->optname);
break;
default:
name = -1;
@@ -1591,8 +1612,7 @@ linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
name = linux_to_bsd_ip_sockopt(args->optname);
break;
case IPPROTO_TCP:
- /* Linux TCP option values match BSD's */
- name = args->optname;
+ name = linux_to_bsd_tcp_sockopt(args->optname);
break;
default:
name = -1;
diff --git a/sys/compat/linux/linux_socket.h b/sys/compat/linux/linux_socket.h
index 1fe53ed..e6efadb 100644
--- a/sys/compat/linux/linux_socket.h
+++ b/sys/compat/linux/linux_socket.h
@@ -116,4 +116,44 @@ struct l_ucred {
uint32_t gid;
};
+/* Operations for socketcall */
+
+#define LINUX_SOCKET 1
+#define LINUX_BIND 2
+#define LINUX_CONNECT 3
+#define LINUX_LISTEN 4
+#define LINUX_ACCEPT 5
+#define LINUX_GETSOCKNAME 6
+#define LINUX_GETPEERNAME 7
+#define LINUX_SOCKETPAIR 8
+#define LINUX_SEND 9
+#define LINUX_RECV 10
+#define LINUX_SENDTO 11
+#define LINUX_RECVFROM 12
+#define LINUX_SHUTDOWN 13
+#define LINUX_SETSOCKOPT 14
+#define LINUX_GETSOCKOPT 15
+#define LINUX_SENDMSG 16
+#define LINUX_RECVMSG 17
+#define LINUX_ACCEPT4 18
+
+/* Socket options */
+#define LINUX_IP_TOS 1
+#define LINUX_IP_TTL 2
+#define LINUX_IP_HDRINCL 3
+#define LINUX_IP_OPTIONS 4
+
+#define LINUX_IP_MULTICAST_IF 32
+#define LINUX_IP_MULTICAST_TTL 33
+#define LINUX_IP_MULTICAST_LOOP 34
+#define LINUX_IP_ADD_MEMBERSHIP 35
+#define LINUX_IP_DROP_MEMBERSHIP 36
+
+#define LINUX_TCP_NODELAY 1
+#define LINUX_TCP_MAXSEG 2
+#define LINUX_TCP_KEEPIDLE 4
+#define LINUX_TCP_KEEPINTVL 5
+#define LINUX_TCP_KEEPCNT 6
+#define LINUX_TCP_MD5SIG 14
+
#endif /* _LINUX_SOCKET_H_ */
diff --git a/sys/compat/linux/linux_sysctl.c b/sys/compat/linux/linux_sysctl.c
index b2c10e1..decd8f8 100644
--- a/sys/compat/linux/linux_sysctl.c
+++ b/sys/compat/linux/linux_sysctl.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_util.h>
#define LINUX_CTL_KERN 1
diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c
index 1359025..e03af00 100644
--- a/sys/compat/linux/linux_time.c
+++ b/sys/compat/linux/linux_time.c
@@ -60,6 +60,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp
#endif
#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_misc.h>
/* DTrace init */
LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
diff --git a/sys/conf/Makefile.arm b/sys/conf/Makefile.arm
index 4145d60..63b451d 100644
--- a/sys/conf/Makefile.arm
+++ b/sys/conf/Makefile.arm
@@ -39,8 +39,12 @@ SYSTEM_DEP:= ${SYSTEM_DEP:$S/conf/ldscript.$M=ldscript.$M}
STRIP_FLAGS = -S
.endif
+CFLAGS += -mno-thumb-interwork
+
.if empty(DDB_ENABLED)
CFLAGS += -mno-apcs-frame
+.elif defined(WITH_ARM_EABI)
+CFLAGS += -funwind-tables
.endif
SYSTEM_LD_ = ${LD} -Bdynamic -T ldscript.$M.noheader ${LDFLAGS} \
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 216d2f5..ff245ed 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -446,6 +446,8 @@ options KTRACE_REQUEST_POOL=101
# KTR is a kernel tracing facility imported from BSD/OS. It is
# enabled with the KTR option. KTR_ENTRIES defines the number of
# entries in the circular trace buffer; it may be an arbitrary number.
+# KTR_BOOT_ENTRIES defines the number of entries during the early boot,
+# before malloc(9) is functional.
# KTR_COMPILE defines the mask of events to compile into the kernel as
# defined by the KTR_* constants in <sys/ktr.h>. KTR_MASK defines the
# initial value of the ktr_mask variable which determines at runtime
@@ -459,7 +461,8 @@ options KTRACE_REQUEST_POOL=101
# if KTR_VERBOSE is not defined. See ktr(4) and ktrdump(8) for details.
#
options KTR
-options KTR_ENTRIES=1024
+options KTR_BOOT_ENTRIES=1024
+options KTR_ENTRIES=(128 * 1024)
options KTR_COMPILE=(KTR_INTR|KTR_PROC)
options KTR_MASK=KTR_INTR
options KTR_CPUMASK=0x3
diff --git a/sys/conf/files b/sys/conf/files
index 04718e8..2a3db4f 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -283,6 +283,7 @@ contrib/altq/altq/altq_rio.c optional altq
contrib/altq/altq/altq_rmclass.c optional altq
contrib/altq/altq/altq_subr.c optional altq
contrib/dev/acpica/components/debugger/dbcmds.c optional acpi acpi_debug
+contrib/dev/acpica/components/debugger/dbconvert.c optional acpi acpi_debug
contrib/dev/acpica/components/debugger/dbdisply.c optional acpi acpi_debug
contrib/dev/acpica/components/debugger/dbexec.c optional acpi acpi_debug
contrib/dev/acpica/components/debugger/dbfileio.c optional acpi acpi_debug
@@ -324,6 +325,7 @@ contrib/dev/acpica/components/events/evgpe.c optional acpi
contrib/dev/acpica/components/events/evgpeblk.c optional acpi
contrib/dev/acpica/components/events/evgpeinit.c optional acpi
contrib/dev/acpica/components/events/evgpeutil.c optional acpi
+contrib/dev/acpica/components/events/evhandler.c optional acpi
contrib/dev/acpica/components/events/evmisc.c optional acpi
contrib/dev/acpica/components/events/evregion.c optional acpi
contrib/dev/acpica/components/events/evrgnini.c optional acpi
@@ -376,6 +378,7 @@ contrib/dev/acpica/components/namespace/nsnames.c optional acpi
contrib/dev/acpica/components/namespace/nsobject.c optional acpi
contrib/dev/acpica/components/namespace/nsparse.c optional acpi
contrib/dev/acpica/components/namespace/nspredef.c optional acpi
+contrib/dev/acpica/components/namespace/nsprepkg.c optional acpi
contrib/dev/acpica/components/namespace/nsrepair.c optional acpi
contrib/dev/acpica/components/namespace/nsrepair2.c optional acpi
contrib/dev/acpica/components/namespace/nssearch.c optional acpi
@@ -386,7 +389,9 @@ contrib/dev/acpica/components/namespace/nsxfname.c optional acpi
contrib/dev/acpica/components/namespace/nsxfobj.c optional acpi
contrib/dev/acpica/components/parser/psargs.c optional acpi
contrib/dev/acpica/components/parser/psloop.c optional acpi
+contrib/dev/acpica/components/parser/psobject.c optional acpi
contrib/dev/acpica/components/parser/psopcode.c optional acpi
+contrib/dev/acpica/components/parser/psopinfo.c optional acpi
contrib/dev/acpica/components/parser/psparse.c optional acpi
contrib/dev/acpica/components/parser/psscope.c optional acpi
contrib/dev/acpica/components/parser/pstree.c optional acpi
@@ -397,6 +402,7 @@ contrib/dev/acpica/components/resources/rsaddr.c optional acpi
contrib/dev/acpica/components/resources/rscalc.c optional acpi
contrib/dev/acpica/components/resources/rscreate.c optional acpi
contrib/dev/acpica/components/resources/rsdump.c optional acpi
+contrib/dev/acpica/components/resources/rsdumpinfo.c optional acpi
contrib/dev/acpica/components/resources/rsinfo.c optional acpi
contrib/dev/acpica/components/resources/rsio.c optional acpi
contrib/dev/acpica/components/resources/rsirq.c optional acpi
@@ -431,8 +437,10 @@ contrib/dev/acpica/components/utilities/utmisc.c optional acpi
contrib/dev/acpica/components/utilities/utmutex.c optional acpi
contrib/dev/acpica/components/utilities/utobject.c optional acpi
contrib/dev/acpica/components/utilities/utosi.c optional acpi
+contrib/dev/acpica/components/utilities/utownerid.c optional acpi
contrib/dev/acpica/components/utilities/utresrc.c optional acpi
contrib/dev/acpica/components/utilities/utstate.c optional acpi
+contrib/dev/acpica/components/utilities/utstring.c optional acpi
contrib/dev/acpica/components/utilities/utxface.c optional acpi
contrib/dev/acpica/components/utilities/utxferror.c optional acpi
contrib/dev/acpica/components/utilities/utxfinit.c optional acpi
@@ -638,9 +646,12 @@ dev/aic7xxx/aic7xxx_pci.c optional ahc pci
dev/alc/if_alc.c optional alc pci
dev/ale/if_ale.c optional ale pci
dev/altera/avgen/altera_avgen.c optional altera_avgen
+dev/altera/avgen/altera_avgen_fdt.c optional altera_avgen fdt
+dev/altera/avgen/altera_avgen_nexus.c optional altera_avgen
dev/altera/sdcard/altera_sdcard.c optional altera_sdcard
dev/altera/sdcard/altera_sdcard_disk.c optional altera_sdcard
dev/altera/sdcard/altera_sdcard_io.c optional altera_sdcard
+dev/altera/sdcard/altera_sdcard_fdt.c optional altera_sdcard fdt
dev/altera/sdcard/altera_sdcard_nexus.c optional altera_sdcard
dev/amr/amr.c optional amr
dev/amr/amr_cam.c optional amrp amr
@@ -1415,6 +1426,7 @@ dev/iscsi/initiator/isc_soc.c optional iscsi_initiator scbus
dev/iscsi/initiator/isc_sm.c optional iscsi_initiator scbus
dev/iscsi/initiator/isc_subr.c optional iscsi_initiator scbus
dev/isf/isf.c optional isf
+dev/isf/isf_fdt.c optional isf fdt
dev/isf/isf_nexus.c optional isf
dev/isp/isp.c optional isp
dev/isp/isp_freebsd.c optional isp
@@ -2276,15 +2288,6 @@ dev/utopia/idtphy.c optional utopia
dev/utopia/suni.c optional utopia
dev/utopia/utopia.c optional utopia
dev/vge/if_vge.c optional vge
-#
-# virtio support
-#
-dev/virtio/pci/virtio_pci.c optional vtnet
-dev/virtio/virtio.c optional vtnet
-dev/virtio/virtqueue.c optional vtnet
-dev/virtio/network/if_vtnet.c optional vtnet
-dev/virtio/virtio_bus_if.m optional vtnet
-dev/virtio/virtio_if.m optional vtnet
dev/vkbd/vkbd.c optional vkbd
dev/vr/if_vr.c optional vr pci
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index b6a474e..131a1e7 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -190,8 +190,7 @@ dev/fdc/fdc_acpi.c optional fdc
dev/fdc/fdc_isa.c optional fdc isa
dev/fdc/fdc_pccard.c optional fdc pccard
dev/hpt27xx/os_bsd.c optional hpt27xx
-dev/hpt27xx/osm_bsd.c optional hpt27xx \
- compile-with "${NORMAL_C} ${NO_WFORMAT_SECURITY}"
+dev/hpt27xx/osm_bsd.c optional hpt27xx
dev/hpt27xx/hpt27xx_config.c optional hpt27xx
dev/hptmv/entry.c optional hptmv
dev/hptmv/mv.c optional hptmv
@@ -390,6 +389,15 @@ dev/isci/scil/scif_sas_task_request.c optional isci
dev/isci/scil/scif_sas_task_request_state_handlers.c optional isci
dev/isci/scil/scif_sas_task_request_states.c optional isci
dev/isci/scil/scif_sas_timer.c optional isci
+dev/virtio/virtio.c optional virtio
+dev/virtio/virtqueue.c optional virtio
+dev/virtio/virtio_bus_if.m optional virtio
+dev/virtio/virtio_if.m optional virtio
+dev/virtio/pci/virtio_pci.c optional virtio_pci virtio pci
+dev/virtio/network/if_vtnet.c optional vtnet virtio
+dev/virtio/block/virtio_blk.c optional virtio_blk virtio
+dev/virtio/balloon/virtio_balloon.c optional virtio_balloon virtio
+dev/virtio/scsi/virtio_scsi.c optional virtio_scsi virtio scbus
isa/syscons_isa.c optional sc
isa/vga_isa.c optional vga
kern/kern_clocksource.c standard
@@ -455,6 +463,11 @@ libkern/memset.c standard
compat/x86bios/x86bios.c optional x86bios | atkbd | dpms | vesa
contrib/x86emu/x86emu.c optional x86bios | atkbd | dpms | vesa
#
+# bvm console
+#
+dev/bvm/bvm_console.c optional bvmconsole
+dev/bvm/bvm_dbg.c optional bvmdebug
+#
# x86 shared code between IA32, AMD64 and PC98 architectures
#
x86/acpica/OsdEnvironment.c optional acpi
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index 428757a..14d6c4b 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -74,6 +74,8 @@ kern/subr_busdma_bufalloc.c standard
kern/subr_dummy_vdso_tc.c standard
libkern/arm/divsi3.S standard
libkern/arm/ffs.S standard
+libkern/arm/ldivmod.S standard
+libkern/arm/ldivmod_helper.c standard
libkern/arm/muldi3.c standard
libkern/ashldi3.c standard
libkern/ashrdi3.c standard
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index d4df01d..fd536af 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -181,8 +181,7 @@ dev/glxiic/glxiic.c optional glxiic
dev/glxsb/glxsb.c optional glxsb
dev/glxsb/glxsb_hash.c optional glxsb
dev/hpt27xx/os_bsd.c optional hpt27xx
-dev/hpt27xx/osm_bsd.c optional hpt27xx \
- compile-with "${NORMAL_C} ${NO_WFORMAT_SECURITY}"
+dev/hpt27xx/osm_bsd.c optional hpt27xx
dev/hpt27xx/hpt27xx_config.c optional hpt27xx
dev/hptmv/entry.c optional hptmv
dev/hptmv/mv.c optional hptmv
@@ -371,6 +370,15 @@ dev/isci/scil/scif_sas_task_request.c optional isci
dev/isci/scil/scif_sas_task_request_state_handlers.c optional isci
dev/isci/scil/scif_sas_task_request_states.c optional isci
dev/isci/scil/scif_sas_timer.c optional isci
+dev/virtio/virtio.c optional virtio
+dev/virtio/virtqueue.c optional virtio
+dev/virtio/virtio_bus_if.m optional virtio
+dev/virtio/virtio_if.m optional virtio
+dev/virtio/pci/virtio_pci.c optional virtio_pci virtio pci
+dev/virtio/network/if_vtnet.c optional vtnet virtio
+dev/virtio/block/virtio_blk.c optional virtio_blk virtio
+dev/virtio/balloon/virtio_balloon.c optional virtio_balloon virtio
+dev/virtio/scsi/virtio_scsi.c optional virtio_scsi virtio scbus
i386/acpica/acpi_machdep.c optional acpi
acpi_wakecode.o optional acpi \
dependency "$S/i386/acpica/acpi_wakecode.S assym.s" \
diff --git a/sys/conf/files.mips b/sys/conf/files.mips
index 8c7a530..2dfc5dd 100644
--- a/sys/conf/files.mips
+++ b/sys/conf/files.mips
@@ -7,6 +7,7 @@
# Arch dependent files
mips/mips/autoconf.c standard
mips/mips/bus_space_generic.c standard
+mips/mips/bus_space_fdt.c optional fdt
mips/mips/busdma_machdep.c standard
mips/mips/cache.c standard
mips/mips/cache_mipsNN.c standard
diff --git a/sys/conf/ldscript.arm b/sys/conf/ldscript.arm
index 3b8422c..d681c87 100644
--- a/sys/conf/ldscript.arm
+++ b/sys/conf/ldscript.arm
@@ -56,6 +56,18 @@ SECTIONS
.init : { *(.init) } =0x9090
.plt : { *(.plt) }
+ _extab_start = .;
+ PROVIDE(extab_start = .);
+ .ARM.extab : { *(.ARM.extab) }
+ _extab.end = .;
+ PROVIDE(extab_end = .);
+
+ _exidx_start = .;
+ PROVIDE(exidx_start = .);
+ .ARM.exidx : { *(.ARM.exidx) }
+ _exidx_end = .;
+ PROVIDE(exidx_end = .);
+
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(0x1000) + (. & (0x1000 - 1)) ;
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 3cb211b..1e5e24b 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -86,6 +86,7 @@ fi
touch version
v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`} t=`date`
i=`${MAKE:-make} -V KERN_IDENT`
+compiler_v=$($(${MAKE:-make} -V CC) -v 2>&1 | grep 'version')
for dir in /bin /usr/bin /usr/local/bin; do
if [ -x "${dir}/svnversion" ] && [ -z ${svnversion} ] ; then
@@ -159,6 +160,7 @@ $COPYRIGHT
char sccs[sizeof(SCCSSTR) > 128 ? sizeof(SCCSSTR) : 128] = SCCSSTR;
char version[sizeof(VERSTR) > 256 ? sizeof(VERSTR) : 256] = VERSTR;
+char compiler_version[] = "${compiler_v}";
char ostype[] = "${TYPE}";
char osrelease[sizeof(RELSTR) > 32 ? sizeof(RELSTR) : 32] = RELSTR;
int osreldate = ${RELDATE};
diff --git a/sys/conf/options b/sys/conf/options
index 1fb3a2a..5722ac4 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -669,6 +669,7 @@ KTR_ALQ opt_ktr.h
KTR_MASK opt_ktr.h
KTR_CPUMASK opt_ktr.h
KTR_COMPILE opt_global.h
+KTR_BOOT_ENTRIES opt_global.h
KTR_ENTRIES opt_global.h
KTR_VERBOSE opt_ktr.h
WITNESS opt_global.h
@@ -775,6 +776,8 @@ ATH_ENABLE_11N opt_ath.h
ATH_ENABLE_DFS opt_ath.h
ATH_EEPROM_FIRMWARE opt_ath.h
ATH_ENABLE_RADIOTAP_VENDOR_EXT opt_ath.h
+ATH_DEBUG_ALQ opt_ath.h
+ATH_KTR_INTR_DEBUG opt_ath.h
# options for the Atheros hal
AH_SUPPORT_AR5416 opt_ah.h
@@ -794,7 +797,7 @@ AH_NEED_DESC_SWAP opt_ah.h
AH_USE_INIPDGAIN opt_ah.h
AH_MAXCHAN opt_ah.h
AH_RXCFG_SDMAMW_4BYTES opt_ah.h
-
+AH_INTERRUPT_DEBUGGING opt_ah.h
# AR5416 and later interrupt mitigation
# XXX do not use this for AR9130
AH_AR5416_INTERRUPT_MITIGATION opt_ah.h
diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt
index 6374788..5848335 100644
--- a/sys/contrib/dev/acpica/changes.txt
+++ b/sys/contrib/dev/acpica/changes.txt
@@ -1,8 +1,154 @@
----------------------------------------
-14 November 2012. Summary of changes for version 20121114:
+17 January 2013. Summary of changes for version 20130117:
+
+
+1) ACPICA Kernel-resident Subsystem:
+
+Updated the AcpiGetSleepTypeData interface: Allow the \_Sx methods to
+return either 1 or 2 integers. Although the ACPI spec defines the \_Sx
+objects to return a package containing one integer, most BIOS code returns
+two integers and the previous code reflects that. However, we also need to
+support BIOS code that actually implements to the ACPI spec, and this
+change reflects this.
+
+Fixed two issues with the ACPI_DEBUG_PRINT macros:
+1) Added the ACPI_DO_WHILE macro to the main DEBUG_PRINT helper macro for
+C compilers that require this support.
+2) Renamed the internal ACPI_DEBUG macro to ACPI_DO_DEBUG_PRINT since
+ACPI_DEBUG is already used by many of the various hosts.
+
+Updated all ACPICA copyrights and signons to 2013. Added the 2013
+copyright to all module headers and signons, including the standard Linux
+header. This affects virtually every file in the ACPICA core subsystem,
+iASL compiler, all ACPICA utilities, and the test suites.
-This release is available at https://www.acpica.org/downloads
-The ACPI 5.0 specification is available at www.acpi.info
+Example Code and Data Size: These are the sizes for the OS-independent
+acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The
+debug version of the code includes the debug output trace mechanism and
+has a much larger code and data size.
+
+ Previous Release:
+ Non-Debug Version: 94.5K Code, 25.5K Data, 120.0K Total
+ Debug Version: 182.2K Code, 74.9K Data, 257.1K Total
+ Current Release:
+ Non-Debug Version: 94.5K Code, 25.4K Data, 119.9K Total
+ Debug Version: 182.3K Code, 75.0K Data, 257.3K Total
+
+
+2) iASL Compiler/Disassembler and Tools:
+
+Generic Unix OSL: Use a buffer to eliminate multiple vfprintf()s and
+prevent a possible fault on some hosts. Some C libraries modify the arg
+pointer parameter to vfprintf making it difficult to call it twice in the
+AcpiOsVprintf function. Use a local buffer to workaround this issue. This
+does not affect the Windows OSL since the Win C library does not modify
+the arg pointer. Chao Guan, Bob Moore.
+
+iASL: Fixed a possible infinite loop when the maximum error count is
+reached. If an output file other than the .AML file is specified (such as
+a listing file), and the maximum number of errors is reached, do not
+attempt to flush data to the output file(s) as the compiler is aborting.
+This can cause an infinite loop as the max error count code essentially
+keeps calling itself.
+
+iASL/Disassembler: Added an option (-in) to ignore NOOP opcodes/operators.
+Implemented for both the compiler and the disassembler. Often, the NOOP
+opcode is used as padding for packages that are changed dynamically by the
+BIOS. When disassembled and recompiled, these NOOPs will cause syntax
+errors. This option causes the disassembler to ignore all NOOP opcodes
+(0xA3), and it also causes the compiler to ignore all ASL source code NOOP
+statements as well.
+
+Debugger: Enhanced the Sleep command to execute all sleep states. This
+change allows Sleep to be invoked with no arguments and causes the
+debugger to execute all of the sleep states, 0-5, automatically.
+
+----------------------------------------
+20 December 2012. Summary of changes for version 20121220:
+
+1) ACPICA Kernel-resident Subsystem:
+
+Implemented a new interface, AcpiWalkResourceBuffer. This interface is an
+alternate entry point for AcpiWalkResources and improves the usability of
+the resource manager by accepting as input a buffer containing the output
+of either a _CRS, _PRS, or _AEI method. The key functionality is that the
+input buffer is not deleted by this interface so that it can be used by
+the host later. See the ACPICA reference for details.
+
+Interpreter: Add a warning if a 64-bit constant appears in a 32-bit table
+(DSDT version < 2). The constant will be truncated and this warning
+reflects that behavior.
+
+Resource Manager: Add support for the new ACPI 5.0 wake bit in the IRQ,
+ExtendedInterrupt, and GpioInt descriptors. This change adds support to
+both get and set the new wake bit in these descriptors, separately from
+the existing share bit. Reported by Aaron Lu.
+
+Interpreter: Fix Store() when an implicit conversion is not possible. For
+example, in the cases such as a store of a string to an existing package
+object, implement the store as a CopyObject(). This is a small departure
+from the ACPI specification which states that the control method should be
+aborted in this case. However, the ASLTS suite depends on this behavior.
+
+Performance improvement for the various FUNCTION_TRACE and DEBUG_PRINT
+macros: check if debug output is currently enabled as soon as possible to
+minimize performance impact if debug is in fact not enabled.
+
+Source code restructuring: Cleanup to improve modularity. The following
+new files have been added: dbconvert.c, evhandler.c, nsprepkg.c,
+psopinfo.c, psobject.c, rsdumpinfo.c, utstring.c, and utownerid.c.
+Associated makefiles and project files have been updated.
+
+Changed an exception code for LoadTable operator. For the case where one
+of the input strings is too long, change the returned exception code from
+AE_BAD_PARAMETER to AE_AML_STRING_LIMIT.
+
+Fixed a possible memory leak in dispatcher error path. On error, delete
+the mutex object created during method mutex creation. Reported by
+tim.gardner@canonical.com.
+
+Example Code and Data Size: These are the sizes for the OS-independent
+acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The
+debug version of the code includes the debug output trace mechanism and
+has a much larger code and data size.
+
+ Previous Release:
+ Non-Debug Version: 94.3K Code, 25.3K Data, 119.6K Total
+ Debug Version: 175.5K Code, 74.5K Data, 250.0K Total
+ Current Release:
+ Non-Debug Version: 94.5K Code, 25.5K Data, 120.0K Total
+ Debug Version: 182.2K Code, 74.9K Data, 257.1K Total
+
+
+2) iASL Compiler/Disassembler and Tools:
+
+iASL: Disallow a method call as argument to the ObjectType ASL operator.
+This change tracks an errata to the ACPI 5.0 document. The AML grammar
+will not allow the interpreter to differentiate between a method and a
+method invocation when these are used as an argument to the ObjectType
+operator. The ACPI specification change is to disallow a method invocation
+(UserTerm) for the ObjectType operator.
+
+Finish support for the TPM2 and CSRT tables in the headers, table
+compiler, and disassembler.
+
+Unix user-space OSL: Fix a problem with WaitSemaphore where the timeout
+always expires immediately if the semaphore is not available. The original
+code was using a relative-time timeout, but sem_timedwait requires the use
+of an absolute time.
+
+iASL: Added a remark if the Timer() operator is used within a 32-bit
+table. This operator returns a 64-bit time value that will be truncated
+within a 32-bit table.
+
+iASL Source code restructuring: Cleanup to improve modularity. The
+following new files have been added: aslhex.c, aslxref.c, aslnamesp.c,
+aslmethod.c, and aslfileio.c. Associated makefiles and project files have
+been updated.
+
+
+----------------------------------------
+14 November 2012. Summary of changes for version 20121114:
1) ACPICA Kernel-resident Subsystem:
diff --git a/sys/contrib/dev/acpica/common/adfile.c b/sys/contrib/dev/acpica/common/adfile.c
index 67d7b79..5cde806 100644
--- a/sys/contrib/dev/acpica/common/adfile.c
+++ b/sys/contrib/dev/acpica/common/adfile.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/common/adisasm.c b/sys/contrib/dev/acpica/common/adisasm.c
index c63d9b5..42befa8 100644
--- a/sys/contrib/dev/acpica/common/adisasm.c
+++ b/sys/contrib/dev/acpica/common/adisasm.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -69,11 +69,11 @@ extern int AslCompilerdebug;
#endif
ACPI_STATUS
-LsDisplayNamespace (
+NsDisplayNamespace (
void);
void
-LsSetupNsList (
+NsSetupNamespaceListing (
void *Handle);
@@ -429,8 +429,8 @@ AdAmlDisassemble (
{
AcpiOsPrintf ("/**** Before second load\n");
- LsSetupNsList (File);
- LsDisplayNamespace ();
+ NsSetupNamespaceListing (File);
+ NsDisplayNamespace ();
AcpiOsPrintf ("*****/\n");
}
@@ -498,8 +498,8 @@ AdAmlDisassemble (
if (AslCompilerdebug)
{
AcpiOsPrintf ("/**** After second load and resource conversion\n");
- LsSetupNsList (File);
- LsDisplayNamespace ();
+ NsSetupNamespaceListing (File);
+ NsDisplayNamespace ();
AcpiOsPrintf ("*****/\n");
AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
@@ -549,8 +549,8 @@ Cleanup:
{
if (AslCompilerdebug) /* Display final namespace, with transforms */
{
- LsSetupNsList (File);
- LsDisplayNamespace ();
+ NsSetupNamespaceListing (File);
+ NsDisplayNamespace ();
}
fclose (File);
diff --git a/sys/contrib/dev/acpica/common/adwalk.c b/sys/contrib/dev/acpica/common/adwalk.c
index af86c91..f801f10 100644
--- a/sys/contrib/dev/acpica/common/adwalk.c
+++ b/sys/contrib/dev/acpica/common/adwalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/common/ahpredef.c b/sys/contrib/dev/acpica/common/ahpredef.c
index 858a714..4583b58 100644
--- a/sys/contrib/dev/acpica/common/ahpredef.c
+++ b/sys/contrib/dev/acpica/common/ahpredef.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/common/dmextern.c b/sys/contrib/dev/acpica/common/dmextern.c
index f5d676d..67f13f7 100644
--- a/sys/contrib/dev/acpica/common/dmextern.c
+++ b/sys/contrib/dev/acpica/common/dmextern.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/common/dmrestag.c b/sys/contrib/dev/acpica/common/dmrestag.c
index 1e9bd88..54f4282 100644
--- a/sys/contrib/dev/acpica/common/dmrestag.c
+++ b/sys/contrib/dev/acpica/common/dmrestag.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -89,7 +89,7 @@ AcpiDmAddResourceToNamespace (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context);
+ void **Context);
static void
AcpiDmAddResourcesToNamespace (
@@ -993,7 +993,7 @@ AcpiDmAddResourcesToNamespace (
*/
AcpiUtWalkAmlResources (NULL, (UINT8 *) NextOp->Named.Data,
(ACPI_SIZE) NextOp->Common.Value.Integer,
- AcpiDmAddResourceToNamespace, BufferNode);
+ AcpiDmAddResourceToNamespace, (void **) BufferNode);
}
@@ -1019,7 +1019,7 @@ AcpiDmAddResourceToNamespace (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context)
+ void **Context)
{
ACPI_STATUS Status;
ACPI_GENERIC_STATE ScopeInfo;
diff --git a/sys/contrib/dev/acpica/common/dmtable.c b/sys/contrib/dev/acpica/common/dmtable.c
index 5d2717c..e569b63 100644
--- a/sys/contrib/dev/acpica/common/dmtable.c
+++ b/sys/contrib/dev/acpica/common/dmtable.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -281,7 +281,7 @@ ACPI_DMTABLE_DATA AcpiDmTableData[] =
{ACPI_SIG_BGRT, AcpiDmTableInfoBgrt, NULL, NULL, TemplateBgrt, "Boot Graphics Resource Table"},
{ACPI_SIG_BOOT, AcpiDmTableInfoBoot, NULL, NULL, TemplateBoot, "Simple Boot Flag Table"},
{ACPI_SIG_CPEP, NULL, AcpiDmDumpCpep, DtCompileCpep, TemplateCpep, "Corrected Platform Error Polling table"},
- {ACPI_SIG_CSRT, NULL, AcpiDmDumpCsrt, NULL, NULL, "Core System Resource Table"},
+ {ACPI_SIG_CSRT, NULL, AcpiDmDumpCsrt, DtCompileCsrt, TemplateCsrt, "Core System Resource Table"},
{ACPI_SIG_DBG2, NULL, AcpiDmDumpDbg2, NULL, NULL, "Debug Port table type 2"},
{ACPI_SIG_DBGP, AcpiDmTableInfoDbgp, NULL, NULL, TemplateDbgp, "Debug Port table"},
{ACPI_SIG_DMAR, NULL, AcpiDmDumpDmar, DtCompileDmar, TemplateDmar, "DMA Remapping table"},
@@ -310,6 +310,7 @@ ACPI_DMTABLE_DATA AcpiDmTableData[] =
{ACPI_SIG_SPMI, AcpiDmTableInfoSpmi, NULL, NULL, TemplateSpmi, "Server Platform Management Interface table"},
{ACPI_SIG_SRAT, NULL, AcpiDmDumpSrat, DtCompileSrat, TemplateSrat, "System Resource Affinity Table"},
{ACPI_SIG_TCPA, AcpiDmTableInfoTcpa, NULL, NULL, TemplateTcpa, "Trusted Computing Platform Alliance table"},
+ {ACPI_SIG_TPM2, AcpiDmTableInfoTpm2, NULL, NULL, TemplateTpm2, "Trusted Platform Module hardware interface table"},
{ACPI_SIG_UEFI, AcpiDmTableInfoUefi, NULL, DtCompileUefi, TemplateUefi, "UEFI Boot Optimization Table"},
{ACPI_SIG_WAET, AcpiDmTableInfoWaet, NULL, NULL, TemplateWaet, "Windows ACPI Emulated Devices Table"},
{ACPI_SIG_WDAT, NULL, AcpiDmDumpWdat, DtCompileWdat, TemplateWdat, "Watchdog Action Table"},
diff --git a/sys/contrib/dev/acpica/common/dmtbdump.c b/sys/contrib/dev/acpica/common/dmtbdump.c
index 2a79b25..ac5ee90 100644
--- a/sys/contrib/dev/acpica/common/dmtbdump.c
+++ b/sys/contrib/dev/acpica/common/dmtbdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -614,6 +614,7 @@ AcpiDmDumpCsrt (
{
ACPI_STATUS Status;
ACPI_CSRT_GROUP *SubTable;
+ ACPI_CSRT_SHARED_INFO *SharedInfoTable;
ACPI_CSRT_DESCRIPTOR *SubSubTable;
UINT32 Length = Table->Length;
UINT32 Offset = sizeof (ACPI_TABLE_CSRT);
@@ -629,6 +630,8 @@ AcpiDmDumpCsrt (
SubTable = ACPI_ADD_PTR (ACPI_CSRT_GROUP, Table, Offset);
while (Offset < Table->Length)
{
+ /* Resource group subtable */
+
AcpiOsPrintf ("\n");
Status = AcpiDmDumpTable (Length, Offset, SubTable,
SubTable->Length, AcpiDmTableInfoCsrt0);
@@ -637,15 +640,23 @@ AcpiDmDumpCsrt (
return;
}
+ /* Shared info subtable (One per resource group) */
+
SubOffset = sizeof (ACPI_CSRT_GROUP);
+ SharedInfoTable = ACPI_ADD_PTR (ACPI_CSRT_SHARED_INFO, Table,
+ Offset + SubOffset);
- /* Shared resource group info buffer */
+ AcpiOsPrintf ("\n");
+ Status = AcpiDmDumpTable (Length, Offset + SubOffset, SharedInfoTable,
+ sizeof (ACPI_CSRT_SHARED_INFO), AcpiDmTableInfoCsrt1);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
- AcpiDmDumpBuffer (SubTable, SubOffset, SubTable->InfoLength,
- Offset+SubOffset, "Shared Data");
- SubOffset += SubTable->InfoLength;
+ SubOffset += SubTable->SharedInfoLength;
- /* Sub-Sub-tables (Resource Descriptors) */
+ /* Sub-Subtables (Resource Descriptors) */
SubSubTable = ACPI_ADD_PTR (ACPI_CSRT_DESCRIPTOR, Table,
Offset + SubOffset);
@@ -655,7 +666,7 @@ AcpiDmDumpCsrt (
{
AcpiOsPrintf ("\n");
Status = AcpiDmDumpTable (Length, Offset + SubOffset, SubSubTable,
- SubSubTable->Length, AcpiDmTableInfoCsrt1);
+ SubSubTable->Length, AcpiDmTableInfoCsrt2);
if (ACPI_FAILURE (Status))
{
return;
@@ -671,7 +682,7 @@ AcpiDmDumpCsrt (
Offset + SubOffset + SubSubOffset, "ResourceInfo");
SubSubOffset += InfoLength;
- /* Point to next sub-sub-table */
+ /* Point to next sub-subtable */
SubOffset += SubSubTable->Length;
SubSubTable = ACPI_ADD_PTR (ACPI_CSRT_DESCRIPTOR, SubSubTable,
diff --git a/sys/contrib/dev/acpica/common/dmtbinfo.c b/sys/contrib/dev/acpica/common/dmtbinfo.c
index 21fddec..54bd5c2 100644
--- a/sys/contrib/dev/acpica/common/dmtbinfo.c
+++ b/sys/contrib/dev/acpica/common/dmtbinfo.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -111,6 +111,7 @@
#define ACPI_SPMI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SPMI,f)
#define ACPI_SRAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SRAT,f)
#define ACPI_TCPA_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA,f)
+#define ACPI_TPM2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TPM2,f)
#define ACPI_UEFI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_UEFI,f)
#define ACPI_WAET_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WAET,f)
#define ACPI_WDAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WDAT,f)
@@ -128,7 +129,8 @@
#define ACPI_ASF4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_ADDRESS,f)
#define ACPI_CPEP0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CPEP_POLLING,f)
#define ACPI_CSRT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_GROUP,f)
-#define ACPI_CSRT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_DESCRIPTOR,f)
+#define ACPI_CSRT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_SHARED_INFO,f)
+#define ACPI_CSRT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_DESCRIPTOR,f)
#define ACPI_DBG20_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DBG2_DEVICE,f)
#define ACPI_DMARS_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_DEVICE_SCOPE,f)
#define ACPI_DMAR0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_HARDWARE_UNIT,f)
@@ -662,18 +664,38 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt0[] =
{ACPI_DMT_UINT16, ACPI_CSRT0_OFFSET (SubdeviceId), "Subdevice ID", 0},
{ACPI_DMT_UINT16, ACPI_CSRT0_OFFSET (Revision), "Revision", 0},
{ACPI_DMT_UINT16, ACPI_CSRT0_OFFSET (Reserved), "Reserved", 0},
- {ACPI_DMT_UINT32, ACPI_CSRT0_OFFSET (InfoLength), "InfoLength", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT0_OFFSET (SharedInfoLength), "Shared Info Length", 0},
ACPI_DMT_TERMINATOR
};
-/* Resource Descriptor subtable */
+/* Shared Info subtable */
ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt1[] =
{
- {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (Length), "Length", 0},
- {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (Type), "Type", 0},
- {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (Subtype), "Subtype", 0},
- {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (Uid), "UID", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (MajorVersion), "Major Version", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (MinorVersion), "Minor Version", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (MmioBaseLow), "MMIO Base Address Low", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (MmioBaseHigh), "MMIO Base Address High", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (GsiInterrupt), "GSI Interrupt", 0},
+ {ACPI_DMT_UINT8, ACPI_CSRT1_OFFSET (InterruptPolarity), "Interrupt Polarity", 0},
+ {ACPI_DMT_UINT8, ACPI_CSRT1_OFFSET (InterruptMode), "Interrupt Mode", 0},
+ {ACPI_DMT_UINT8, ACPI_CSRT1_OFFSET (NumChannels), "Num Channels", 0},
+ {ACPI_DMT_UINT8, ACPI_CSRT1_OFFSET (DmaAddressWidth), "DMA Address Width", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (BaseRequestLine), "Base Request Line", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (NumHandshakeSignals), "Num Handshake Signals", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (MaxBlockSize), "Max Block Size", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+
+/* Resource Descriptor subtable */
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt2[] =
+{
+ {ACPI_DMT_UINT32, ACPI_CSRT2_OFFSET (Length), "Length", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT2_OFFSET (Type), "Type", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT2_OFFSET (Subtype), "Subtype", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT2_OFFSET (Uid), "UID", 0},
ACPI_DMT_TERMINATOR
};
@@ -1984,6 +2006,21 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[] =
/*******************************************************************************
*
+ * TPM2 - Trusted Platform Module (TPM) 2.0 Hardware Interface Table
+ *
+ ******************************************************************************/
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2[] =
+{
+ {ACPI_DMT_UINT32, ACPI_TPM2_OFFSET (Flags), "Flags", 0},
+ {ACPI_DMT_UINT64, ACPI_TPM2_OFFSET (ControlAddress), "Control Address", 0},
+ {ACPI_DMT_UINT32, ACPI_TPM2_OFFSET (StartMethod), "Start Method", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+
+/*******************************************************************************
+ *
* UEFI - UEFI Boot optimization Table
*
******************************************************************************/
diff --git a/sys/contrib/dev/acpica/common/getopt.c b/sys/contrib/dev/acpica/common/getopt.c
index 3855fa5..6bedff6 100644
--- a/sys/contrib/dev/acpica/common/getopt.c
+++ b/sys/contrib/dev/acpica/common/getopt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslanalyze.c b/sys/contrib/dev/acpica/compiler/aslanalyze.c
index ea4ee35..a42526c 100644
--- a/sys/contrib/dev/acpica/compiler/aslanalyze.c
+++ b/sys/contrib/dev/acpica/compiler/aslanalyze.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslbtypes.c b/sys/contrib/dev/acpica/compiler/aslbtypes.c
index d7140d2..aac3870 100644
--- a/sys/contrib/dev/acpica/compiler/aslbtypes.c
+++ b/sys/contrib/dev/acpica/compiler/aslbtypes.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslcodegen.c b/sys/contrib/dev/acpica/compiler/aslcodegen.c
index 571e5dd..13ba665 100644
--- a/sys/contrib/dev/acpica/compiler/aslcodegen.c
+++ b/sys/contrib/dev/acpica/compiler/aslcodegen.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslcompile.c b/sys/contrib/dev/acpica/compiler/aslcompile.c
index 4ca98f6..6d4c466 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompile.c
+++ b/sys/contrib/dev/acpica/compiler/aslcompile.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -617,7 +617,7 @@ CmDoCompile (
/* Namespace cross-reference */
AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace");
- Status = LkCrossReferenceNamespace ();
+ Status = XfCrossReferenceNamespace ();
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
@@ -639,8 +639,8 @@ CmDoCompile (
DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n");
TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE,
- AnMethodAnalysisWalkBegin,
- AnMethodAnalysisWalkEnd, &AnalysisWalkInfo);
+ MtMethodAnalysisWalkBegin,
+ MtMethodAnalysisWalkEnd, &AnalysisWalkInfo);
UtEndEvent (Event);
/* Semantic error checking part two - typing of method returns */
@@ -719,11 +719,11 @@ CmDoOutputFiles (
/* Create listings and hex files */
LsDoListings ();
- LsDoHexOutput ();
+ HxDoHexOutput ();
/* Dump the namespace to the .nsp file if requested */
- (void) LsDisplayNamespace ();
+ (void) NsDisplayNamespace ();
}
@@ -766,12 +766,12 @@ CmDumpAllEvents (
Delta = (UINT32) (Event->EndTime - Event->StartTime);
- USec = Delta / 10;
- MSec = Delta / 10000;
+ USec = Delta / ACPI_100NSEC_PER_USEC;
+ MSec = Delta / ACPI_100NSEC_PER_MSEC;
/* Round milliseconds up */
- if ((USec - (MSec * 1000)) >= 500)
+ if ((USec - (MSec * ACPI_USEC_PER_MSEC)) >= 500)
{
MSec++;
}
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.h b/sys/contrib/dev/acpica/compiler/aslcompiler.h
index 72c21ab..d772e8f 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.h
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -188,19 +188,23 @@ AnOperandTypecheckWalkEnd (
void *Context);
ACPI_STATUS
-AnMethodAnalysisWalkBegin (
+AnMethodTypingWalkEnd (
ACPI_PARSE_OBJECT *Op,
UINT32 Level,
void *Context);
+
+/*
+ * aslmethod - Control method analysis walk
+ */
ACPI_STATUS
-AnMethodAnalysisWalkEnd (
+MtMethodAnalysisWalkBegin (
ACPI_PARSE_OBJECT *Op,
UINT32 Level,
void *Context);
ACPI_STATUS
-AnMethodTypingWalkEnd (
+MtMethodAnalysisWalkEnd (
ACPI_PARSE_OBJECT *Op,
UINT32 Level,
void *Context);
@@ -342,6 +346,12 @@ LsDoListings (
void);
void
+LsDumpAsciiInComment (
+ UINT32 FileId,
+ UINT32 Count,
+ UINT8 *Buffer);
+
+void
LsWriteNodeToAsmListing (
ACPI_PARSE_OBJECT *Op);
@@ -351,13 +361,18 @@ LsWriteNode (
UINT32 FileId);
void
-LsDoHexOutput (
+LsDumpParseTree (
void);
+
+/*
+ * aslhex - generate all "hex" output files (C, ASM, ASL)
+ */
void
-LsDumpParseTree (
+HxDoHexOutput (
void);
+
/*
* aslfold - constant folding
*/
@@ -689,26 +704,34 @@ LdLoadNamespace (
/*
- * asllookup - namespace cross reference
+ * asllookup - namespace lookup functions
*/
-ACPI_STATUS
-LkCrossReferenceNamespace (
- void);
-
void
LkFindUnreferencedObjects (
void);
+
+/*
+ * aslnamesp - namespace output file generation
+ */
ACPI_STATUS
-LsDisplayNamespace (
+NsDisplayNamespace (
void);
void
-LsSetupNsList (
+NsSetupNamespaceListing (
void *Handle);
/*
+ * aslxref - namespace cross reference
+ */
+ACPI_STATUS
+XfCrossReferenceNamespace (
+ void);
+
+
+/*
* aslutils - common compiler utilites
*/
void
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.l b/sys/contrib/dev/acpica/compiler/aslcompiler.l
index 5b9ff12..5b2d9ce 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.l
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.l
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -201,7 +201,7 @@ NamePathTail [.]{NameSeg}
"Mutex" { count (2); return (PARSEOP_MUTEX); }
"Name" { count (2); return (PARSEOP_NAME); }
"NAnd" { count (3); return (PARSEOP_NAND); }
-"Noop" { count (3); return (PARSEOP_NOOP); }
+"Noop" { if (!AcpiGbl_IgnoreNoopOperator) {count (3); return (PARSEOP_NOOP);} }
"NOr" { count (3); return (PARSEOP_NOR); }
"Not" { count (3); return (PARSEOP_NOT); }
"Notify" { count (3); return (PARSEOP_NOTIFY); }
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.y b/sys/contrib/dev/acpica/compiler/aslcompiler.y
index b6453ac..42ff850 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.y
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.y
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -661,6 +661,7 @@ void * AslLocalAllocate (unsigned int Size);
/* Types */
%type <n> SuperName
+%type <n> ObjectTypeName
%type <n> ArgTerm
%type <n> LocalTerm
%type <n> DebugTerm
@@ -1991,7 +1992,7 @@ NotTerm
ObjectTypeTerm
: PARSEOP_OBJECTTYPE '(' {$<n>$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE);}
- SuperName
+ ObjectTypeName
')' {$$ = TrLinkChildren ($<n>3,1,$4);}
| PARSEOP_OBJECTTYPE '('
error ')' {$$ = AslDoError(); yyclearin;}
@@ -2439,6 +2440,18 @@ SuperName
| LocalTerm {}
| DebugTerm {}
| Type6Opcode {}
+
+/* For ObjectType: SuperName except for UserTerm (method invocation) */
+
+ObjectTypeName
+ : NameString {}
+ | ArgTerm {}
+ | LocalTerm {}
+ | DebugTerm {}
+ | RefOfTerm {}
+ | DerefOfTerm {}
+ | IndexTerm {}
+
/* | UserTerm {} */ /* Caused reduce/reduce with Type6Opcode->UserTerm */
;
diff --git a/sys/contrib/dev/acpica/compiler/asldefine.h b/sys/contrib/dev/acpica/compiler/asldefine.h
index 0ee3c69..7c8bd66 100644
--- a/sys/contrib/dev/acpica/compiler/asldefine.h
+++ b/sys/contrib/dev/acpica/compiler/asldefine.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslerror.c b/sys/contrib/dev/acpica/compiler/aslerror.c
index 41ae967..f362589 100644
--- a/sys/contrib/dev/acpica/compiler/aslerror.c
+++ b/sys/contrib/dev/acpica/compiler/aslerror.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -660,7 +660,6 @@ AslCommonError (
Gbl_SourceLine = 0;
Gbl_NextError = Gbl_ErrorLog;
- CmDoOutputFiles ();
CmCleanupAndExit ();
exit(1);
}
diff --git a/sys/contrib/dev/acpica/compiler/aslfileio.c b/sys/contrib/dev/acpica/compiler/aslfileio.c
new file mode 100644
index 0000000..660b82f
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslfileio.c
@@ -0,0 +1,393 @@
+/******************************************************************************
+ *
+ * Module Name: aslfileio - File I/O support
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslfileio")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AslAbort
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
+ * I/O errors.
+ *
+ ******************************************************************************/
+
+void
+AslAbort (
+ void)
+{
+
+ AePrintErrorLog (ASL_FILE_STDERR);
+ if (Gbl_DebugFlag)
+ {
+ /* Print error summary to stdout also */
+
+ AePrintErrorLog (ASL_FILE_STDOUT);
+ }
+
+ exit (1);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlFileError
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * ErrorId - Index into error message array
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Decode errno to an error message and add the entire error
+ * to the error log.
+ *
+ ******************************************************************************/
+
+void
+FlFileError (
+ UINT32 FileId,
+ UINT8 ErrorId)
+{
+
+ sprintf (MsgBuffer, "\"%s\" (%s)", Gbl_Files[FileId].Filename,
+ strerror (errno));
+ AslCommonError (ASL_ERROR, ErrorId, 0, 0, 0, 0, NULL, MsgBuffer);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlOpenFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Filename - file pathname to open
+ * Mode - Open mode for fopen
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Open a file.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+void
+FlOpenFile (
+ UINT32 FileId,
+ char *Filename,
+ char *Mode)
+{
+ FILE *File;
+
+
+ File = fopen (Filename, Mode);
+ if (!File)
+ {
+ FlFileError (FileId, ASL_MSG_OPEN);
+ AslAbort ();
+ }
+
+ Gbl_Files[FileId].Filename = Filename;
+ Gbl_Files[FileId].Handle = File;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlGetFileSize
+ *
+ * PARAMETERS: FileId - Index into file info array
+ *
+ * RETURN: File Size
+ *
+ * DESCRIPTION: Get current file size. Uses seek-to-EOF. File must be open.
+ *
+ ******************************************************************************/
+
+UINT32
+FlGetFileSize (
+ UINT32 FileId)
+{
+ FILE *fp;
+ UINT32 FileSize;
+ long Offset;
+
+
+ fp = Gbl_Files[FileId].Handle;
+ Offset = ftell (fp);
+
+ fseek (fp, 0, SEEK_END);
+ FileSize = (UINT32) ftell (fp);
+
+ /* Restore file pointer */
+
+ fseek (fp, Offset, SEEK_SET);
+ return (FileSize);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlReadFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Buffer - Where to place the data
+ * Length - Amount to read
+ *
+ * RETURN: Status. AE_ERROR indicates EOF.
+ *
+ * DESCRIPTION: Read data from an open file.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+FlReadFile (
+ UINT32 FileId,
+ void *Buffer,
+ UINT32 Length)
+{
+ UINT32 Actual;
+
+
+ /* Read and check for error */
+
+ Actual = fread (Buffer, 1, Length, Gbl_Files[FileId].Handle);
+ if (Actual < Length)
+ {
+ if (feof (Gbl_Files[FileId].Handle))
+ {
+ /* End-of-file, just return error */
+
+ return (AE_ERROR);
+ }
+
+ FlFileError (FileId, ASL_MSG_READ);
+ AslAbort ();
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlWriteFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Buffer - Data to write
+ * Length - Amount of data to write
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Write data to an open file.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+void
+FlWriteFile (
+ UINT32 FileId,
+ void *Buffer,
+ UINT32 Length)
+{
+ UINT32 Actual;
+
+
+ /* Write and check for error */
+
+ Actual = fwrite ((char *) Buffer, 1, Length, Gbl_Files[FileId].Handle);
+ if (Actual != Length)
+ {
+ FlFileError (FileId, ASL_MSG_WRITE);
+ AslAbort ();
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlPrintFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Format - Printf format string
+ * ... - Printf arguments
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Formatted write to an open file.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+void
+FlPrintFile (
+ UINT32 FileId,
+ char *Format,
+ ...)
+{
+ INT32 Actual;
+ va_list Args;
+
+
+ va_start (Args, Format);
+
+ Actual = vfprintf (Gbl_Files[FileId].Handle, Format, Args);
+ va_end (Args);
+
+ if (Actual == -1)
+ {
+ FlFileError (FileId, ASL_MSG_WRITE);
+ AslAbort ();
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlSeekFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Offset - Absolute byte offset in file
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Seek to absolute offset.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+void
+FlSeekFile (
+ UINT32 FileId,
+ long Offset)
+{
+ int Error;
+
+
+ Error = fseek (Gbl_Files[FileId].Handle, Offset, SEEK_SET);
+ if (Error)
+ {
+ FlFileError (FileId, ASL_MSG_SEEK);
+ AslAbort ();
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlCloseFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Close an open file. Aborts compiler on error
+ *
+ ******************************************************************************/
+
+void
+FlCloseFile (
+ UINT32 FileId)
+{
+ int Error;
+
+
+ if (!Gbl_Files[FileId].Handle)
+ {
+ return;
+ }
+
+ Error = fclose (Gbl_Files[FileId].Handle);
+ if (Error)
+ {
+ FlFileError (FileId, ASL_MSG_CLOSE);
+ AslAbort ();
+ }
+
+ Gbl_Files[FileId].Handle = NULL;
+ return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlDeleteFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Delete a file.
+ *
+ ******************************************************************************/
+
+void
+FlDeleteFile (
+ UINT32 FileId)
+{
+ ASL_FILE_INFO *Info = &Gbl_Files[FileId];
+
+
+ if (!Info->Filename)
+ {
+ return;
+ }
+
+ if (remove (Info->Filename))
+ {
+ printf ("%s (%s file) ",
+ Info->Filename, Info->Description);
+ perror ("Could not delete");
+ }
+
+ Info->Filename = NULL;
+ return;
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslfiles.c b/sys/contrib/dev/acpica/compiler/aslfiles.c
index 39f64b7..a525fc2 100644
--- a/sys/contrib/dev/acpica/compiler/aslfiles.c
+++ b/sys/contrib/dev/acpica/compiler/aslfiles.c
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Module Name: aslfiles - file I/O suppoert
+ * Module Name: aslfiles - File support functions
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -64,352 +64,6 @@ FlParseInputPathname (
/*******************************************************************************
*
- * FUNCTION: AslAbort
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
- * I/O errors
- *
- ******************************************************************************/
-
-void
-AslAbort (
- void)
-{
-
- AePrintErrorLog (ASL_FILE_STDERR);
- if (Gbl_DebugFlag)
- {
- /* Print error summary to stdout also */
-
- AePrintErrorLog (ASL_FILE_STDOUT);
- }
-
- exit (1);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlFileError
- *
- * PARAMETERS: FileId - Index into file info array
- * ErrorId - Index into error message array
- *
- * RETURN: None
- *
- * DESCRIPTION: Decode errno to an error message and add the entire error
- * to the error log.
- *
- ******************************************************************************/
-
-void
-FlFileError (
- UINT32 FileId,
- UINT8 ErrorId)
-{
-
- sprintf (MsgBuffer, "\"%s\" (%s)", Gbl_Files[FileId].Filename,
- strerror (errno));
- AslCommonError (ASL_ERROR, ErrorId, 0, 0, 0, 0, NULL, MsgBuffer);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlOpenFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Filename - file pathname to open
- * Mode - Open mode for fopen
- *
- * RETURN: None
- *
- * DESCRIPTION: Open a file.
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-void
-FlOpenFile (
- UINT32 FileId,
- char *Filename,
- char *Mode)
-{
- FILE *File;
-
-
- File = fopen (Filename, Mode);
- if (!File)
- {
- FlFileError (FileId, ASL_MSG_OPEN);
- AslAbort ();
- }
-
- Gbl_Files[FileId].Filename = Filename;
- Gbl_Files[FileId].Handle = File;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlGetFileSize
- *
- * PARAMETERS: FileId - Index into file info array
- *
- * RETURN: File Size
- *
- * DESCRIPTION: Get current file size. Uses seek-to-EOF. File must be open.
- *
- ******************************************************************************/
-
-UINT32
-FlGetFileSize (
- UINT32 FileId)
-{
- FILE *fp;
- UINT32 FileSize;
- long Offset;
-
-
- fp = Gbl_Files[FileId].Handle;
- Offset = ftell (fp);
-
- fseek (fp, 0, SEEK_END);
- FileSize = (UINT32) ftell (fp);
-
- /* Restore file pointer */
-
- fseek (fp, Offset, SEEK_SET);
- return (FileSize);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlReadFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Buffer - Where to place the data
- * Length - Amount to read
- *
- * RETURN: Status. AE_ERROR indicates EOF.
- *
- * DESCRIPTION: Read data from an open file.
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-FlReadFile (
- UINT32 FileId,
- void *Buffer,
- UINT32 Length)
-{
- UINT32 Actual;
-
-
- /* Read and check for error */
-
- Actual = fread (Buffer, 1, Length, Gbl_Files[FileId].Handle);
- if (Actual < Length)
- {
- if (feof (Gbl_Files[FileId].Handle))
- {
- /* End-of-file, just return error */
-
- return (AE_ERROR);
- }
-
- FlFileError (FileId, ASL_MSG_READ);
- AslAbort ();
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlWriteFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Buffer - Data to write
- * Length - Amount of data to write
- *
- * RETURN: None
- *
- * DESCRIPTION: Write data to an open file.
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-void
-FlWriteFile (
- UINT32 FileId,
- void *Buffer,
- UINT32 Length)
-{
- UINT32 Actual;
-
-
- /* Write and check for error */
-
- Actual = fwrite ((char *) Buffer, 1, Length, Gbl_Files[FileId].Handle);
- if (Actual != Length)
- {
- FlFileError (FileId, ASL_MSG_WRITE);
- AslAbort ();
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlPrintFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Format - Printf format string
- * ... - Printf arguments
- *
- * RETURN: None
- *
- * DESCRIPTION: Formatted write to an open file.
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-void
-FlPrintFile (
- UINT32 FileId,
- char *Format,
- ...)
-{
- INT32 Actual;
- va_list Args;
-
-
- va_start (Args, Format);
-
- Actual = vfprintf (Gbl_Files[FileId].Handle, Format, Args);
- va_end (Args);
-
- if (Actual == -1)
- {
- FlFileError (FileId, ASL_MSG_WRITE);
- AslAbort ();
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlSeekFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Offset - Absolute byte offset in file
- *
- * RETURN: None
- *
- * DESCRIPTION: Seek to absolute offset
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-void
-FlSeekFile (
- UINT32 FileId,
- long Offset)
-{
- int Error;
-
-
- Error = fseek (Gbl_Files[FileId].Handle, Offset, SEEK_SET);
- if (Error)
- {
- FlFileError (FileId, ASL_MSG_SEEK);
- AslAbort ();
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlCloseFile
- *
- * PARAMETERS: FileId - Index into file info array
- *
- * RETURN: None
- *
- * DESCRIPTION: Close an open file. Aborts compiler on error
- *
- ******************************************************************************/
-
-void
-FlCloseFile (
- UINT32 FileId)
-{
- int Error;
-
-
- if (!Gbl_Files[FileId].Handle)
- {
- return;
- }
-
- Error = fclose (Gbl_Files[FileId].Handle);
- if (Error)
- {
- FlFileError (FileId, ASL_MSG_CLOSE);
- AslAbort ();
- }
-
- Gbl_Files[FileId].Handle = NULL;
- return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlDeleteFile
- *
- * PARAMETERS: FileId - Index into file info array
- *
- * RETURN: None
- *
- * DESCRIPTION: Delete a file.
- *
- ******************************************************************************/
-
-void
-FlDeleteFile (
- UINT32 FileId)
-{
- ASL_FILE_INFO *Info = &Gbl_Files[FileId];
-
-
- if (!Info->Filename)
- {
- return;
- }
-
- if (remove (Info->Filename))
- {
- printf ("%s (%s file) ",
- Info->Filename, Info->Description);
- perror ("Could not delete");
- }
-
- Info->Filename = NULL;
- return;
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: FlSetLineNumber
*
* PARAMETERS: Op - Parse node for the LINE asl statement
diff --git a/sys/contrib/dev/acpica/compiler/aslfold.c b/sys/contrib/dev/acpica/compiler/aslfold.c
index e5b6520..c01bce4 100644
--- a/sys/contrib/dev/acpica/compiler/aslfold.c
+++ b/sys/contrib/dev/acpica/compiler/aslfold.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslglobal.h b/sys/contrib/dev/acpica/compiler/aslglobal.h
index 101b23d..1b1f67c 100644
--- a/sys/contrib/dev/acpica/compiler/aslglobal.h
+++ b/sys/contrib/dev/acpica/compiler/aslglobal.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslhex.c b/sys/contrib/dev/acpica/compiler/aslhex.c
new file mode 100644
index 0000000..c6b310e
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslhex.c
@@ -0,0 +1,401 @@
+/******************************************************************************
+ *
+ * Module Name: aslhex - ASCII hex output file generation (C, ASM, and ASL)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("ashex")
+
+/*
+ * This module emits ASCII hex output files in either C, ASM, or ASL format
+ */
+
+
+/* Local prototypes */
+
+static void
+HxDoHexOutputC (
+ void);
+
+static void
+HxDoHexOutputAsl (
+ void);
+
+static void
+HxDoHexOutputAsm (
+ void);
+
+static UINT32
+HxReadAmlOutputFile (
+ UINT8 *Buffer);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxDoHexOutput
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Create the hex output file. Note: data is obtained by reading
+ * the entire AML output file that was previously generated.
+ *
+ ******************************************************************************/
+
+void
+HxDoHexOutput (
+ void)
+{
+
+ switch (Gbl_HexOutputFlag)
+ {
+ case HEX_OUTPUT_C:
+
+ HxDoHexOutputC ();
+ break;
+
+ case HEX_OUTPUT_ASM:
+
+ HxDoHexOutputAsm ();
+ break;
+
+ case HEX_OUTPUT_ASL:
+
+ HxDoHexOutputAsl ();
+ break;
+
+ default:
+ /* No other output types supported */
+ break;
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxReadAmlOutputFile
+ *
+ * PARAMETERS: Buffer - Where to return data
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Read a line of the AML output prior to formatting the data
+ *
+ ******************************************************************************/
+
+static UINT32
+HxReadAmlOutputFile (
+ UINT8 *Buffer)
+{
+ UINT32 Actual;
+
+
+ Actual = fread (Buffer, 1, HEX_TABLE_LINE_SIZE,
+ Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
+
+ if (ferror (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle))
+ {
+ FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
+ AslAbort ();
+ }
+
+ return (Actual);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxDoHexOutputC
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Create the hex output file. This is the same data as the AML
+ * output file, but formatted into hex/ascii bytes suitable for
+ * inclusion into a C source file.
+ *
+ ******************************************************************************/
+
+static void
+HxDoHexOutputC (
+ void)
+{
+ UINT8 FileData[HEX_TABLE_LINE_SIZE];
+ UINT32 LineLength;
+ UINT32 Offset = 0;
+ UINT32 AmlFileSize;
+ UINT32 i;
+
+
+ /* Get AML size, seek back to start */
+
+ AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
+ FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n");
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
+ AmlFileSize);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char AmlCode[] =\n{\n");
+
+ while (Offset < AmlFileSize)
+ {
+ /* Read enough bytes needed for one output line */
+
+ LineLength = HxReadAmlOutputFile (FileData);
+ if (!LineLength)
+ {
+ break;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+
+ for (i = 0; i < LineLength; i++)
+ {
+ /*
+ * Print each hex byte.
+ * Add a comma until the very last byte of the AML file
+ * (Some C compilers complain about a trailing comma)
+ */
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
+ if ((Offset + i + 1) < AmlFileSize)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
+ }
+ else
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+ }
+ }
+
+ /* Add fill spaces if needed for last line */
+
+ if (LineLength < HEX_TABLE_LINE_SIZE)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
+ 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
+ }
+
+ /* Emit the offset and ascii dump for the entire line */
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset);
+ LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
+ HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
+
+ Offset += LineLength;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "};\n");
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxDoHexOutputAsl
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Create the hex output file. This is the same data as the AML
+ * output file, but formatted into hex/ascii bytes suitable for
+ * inclusion into a C source file.
+ *
+ ******************************************************************************/
+
+static void
+HxDoHexOutputAsl (
+ void)
+{
+ UINT8 FileData[HEX_TABLE_LINE_SIZE];
+ UINT32 LineLength;
+ UINT32 Offset = 0;
+ UINT32 AmlFileSize;
+ UINT32 i;
+
+
+ /* Get AML size, seek back to start */
+
+ AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
+ FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " * ASL source code output\n");
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
+ AmlFileSize);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " Name (BUF1, Buffer()\n {\n");
+
+ while (Offset < AmlFileSize)
+ {
+ /* Read enough bytes needed for one output line */
+
+ LineLength = HxReadAmlOutputFile (FileData);
+ if (!LineLength)
+ {
+ break;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+
+ for (i = 0; i < LineLength; i++)
+ {
+ /*
+ * Print each hex byte.
+ * Add a comma until the very last byte of the AML file
+ * (Some C compilers complain about a trailing comma)
+ */
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
+ if ((Offset + i + 1) < AmlFileSize)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
+ }
+ else
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+ }
+ }
+
+ /* Add fill spaces if needed for last line */
+
+ if (LineLength < HEX_TABLE_LINE_SIZE)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
+ 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
+ }
+
+ /* Emit the offset and ascii dump for the entire line */
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset);
+ LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
+ HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
+
+ Offset += LineLength;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " })\n");
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxDoHexOutputAsm
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Create the hex output file. This is the same data as the AML
+ * output file, but formatted into hex/ascii bytes suitable for
+ * inclusion into a ASM source file.
+ *
+ ******************************************************************************/
+
+static void
+HxDoHexOutputAsm (
+ void)
+{
+ UINT8 FileData[HEX_TABLE_LINE_SIZE];
+ UINT32 LineLength;
+ UINT32 Offset = 0;
+ UINT32 AmlFileSize;
+ UINT32 i;
+
+
+ /* Get AML size, seek back to start */
+
+ AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
+ FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n");
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "; AML code block contains 0x%X bytes\n;\n",
+ AmlFileSize);
+
+ while (Offset < AmlFileSize)
+ {
+ /* Read enough bytes needed for one output line */
+
+ LineLength = HxReadAmlOutputFile (FileData);
+ if (!LineLength)
+ {
+ break;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " db ");
+
+ for (i = 0; i < LineLength; i++)
+ {
+ /*
+ * Print each hex byte.
+ * Add a comma until the last byte of the line
+ */
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "0%2.2Xh", FileData[i]);
+ if ((i + 1) < LineLength)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
+ }
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+
+ /* Add fill spaces if needed for last line */
+
+ if (LineLength < HEX_TABLE_LINE_SIZE)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
+ 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
+ }
+
+ /* Emit the offset and ascii dump for the entire line */
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ; %8.8X", Offset);
+ LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
+
+ Offset += LineLength;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
+}
diff --git a/sys/contrib/dev/acpica/compiler/asllength.c b/sys/contrib/dev/acpica/compiler/asllength.c
index ef113f9..57835a6 100644
--- a/sys/contrib/dev/acpica/compiler/asllength.c
+++ b/sys/contrib/dev/acpica/compiler/asllength.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asllisting.c b/sys/contrib/dev/acpica/compiler/asllisting.c
index 9a85fd7..49c43fb 100644
--- a/sys/contrib/dev/acpica/compiler/asllisting.c
+++ b/sys/contrib/dev/acpica/compiler/asllisting.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,12 +59,6 @@ LsDumpAscii (
UINT32 Count,
UINT8 *Buffer);
-static void
-LsDumpAsciiInComment (
- UINT32 FileId,
- UINT32 Count,
- UINT8 *Buffer);
-
static ACPI_STATUS
LsAmlListingWalk (
ACPI_PARSE_OBJECT *Op,
@@ -117,27 +111,57 @@ LsWriteNodeToListing (
ACPI_PARSE_OBJECT *Op,
UINT32 FileId);
-static void
-LsDoHexOutputC (
- void);
-
-static void
-LsDoHexOutputAsm (
- void);
-
-static void
-LsDoHexOutputAsl (
- void);
-
static ACPI_STATUS
LsTreeWriteWalk (
ACPI_PARSE_OBJECT *Op,
UINT32 Level,
void *Context);
-static UINT32
-LsReadAmlOutputFile (
- UINT8 *Buffer);
+#define ASL_LISTING_LINE_PREFIX ": "
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: LsDoListings
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Generate all requested listing files.
+ *
+ ******************************************************************************/
+
+void
+LsDoListings (
+ void)
+{
+
+ if (Gbl_C_OutputFlag)
+ {
+ LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
+ }
+
+ if (Gbl_ListingFlag)
+ {
+ LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
+ }
+
+ if (Gbl_AsmOutputFlag)
+ {
+ LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
+ }
+
+ if (Gbl_C_IncludeOutputFlag)
+ {
+ LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
+ }
+
+ if (Gbl_AsmIncludeOutputFlag)
+ {
+ LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
+ }
+}
/*******************************************************************************
@@ -147,7 +171,7 @@ LsReadAmlOutputFile (
* PARAMETERS: ASL_WALK_CALLBACK
*
*
- * RETURN: None.
+ * RETURN: None
*
* DESCRIPTION: Dump entire parse tree, for compiler debug only
*
@@ -196,7 +220,7 @@ LsDumpParseTree (
* Count - Number of bytes to convert
* Buffer - Buffer of bytes to convert
*
- * RETURN: None.
+ * RETURN: None
*
* DESCRIPTION: Convert hex bytes to ascii
*
@@ -239,13 +263,13 @@ LsDumpAscii (
* Count - Number of bytes to convert
* Buffer - Buffer of bytes to convert
*
- * RETURN: None.
+ * RETURN: None
*
* DESCRIPTION: Convert hex bytes to ascii
*
******************************************************************************/
-static void
+void
LsDumpAsciiInComment (
UINT32 FileId,
UINT32 Count,
@@ -374,50 +398,6 @@ LsGenerateListing (
/*******************************************************************************
*
- * FUNCTION: LsDoListings
- *
- * PARAMETERS: None.
- *
- * RETURN: None
- *
- * DESCRIPTION: Generate all requested listing files.
- *
- ******************************************************************************/
-
-void
-LsDoListings (
- void)
-{
-
- if (Gbl_C_OutputFlag)
- {
- LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
- }
-
- if (Gbl_ListingFlag)
- {
- LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
- }
-
- if (Gbl_AsmOutputFlag)
- {
- LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
- }
-
- if (Gbl_C_IncludeOutputFlag)
- {
- LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
- }
-
- if (Gbl_AsmIncludeOutputFlag)
- {
- LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
- }
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: LsPushNode
*
* PARAMETERS: Filename - Pointer to the include filename
@@ -687,7 +667,8 @@ LsWriteListingHexBytes (
{
case ASL_FILE_LISTING_OUTPUT:
- FlPrintFile (FileId, "%8.8X....", Gbl_CurrentAmlOffset);
+ FlPrintFile (FileId, "%8.8X%s", Gbl_CurrentAmlOffset,
+ ASL_LISTING_LINE_PREFIX);
break;
case ASL_FILE_ASM_SOURCE_OUTPUT:
@@ -747,6 +728,24 @@ LsWriteOneSourceLine (
Gbl_SourceLine++;
Gbl_ListingNode->LineNumber++;
+ /* Ignore lines that are completely blank (but count the line above) */
+
+ if (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) != AE_OK)
+ {
+ return (0);
+ }
+ if (FileByte == '\n')
+ {
+ return (1);
+ }
+
+ /*
+ * This is a non-empty line, we will print the entire line with
+ * the line number and possibly other prefixes and transforms.
+ */
+
+ /* Line prefixes for special files, C and ASM output */
+
if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
{
FlPrintFile (FileId, " *");
@@ -762,19 +761,21 @@ LsWriteOneSourceLine (
* This file contains "include" statements, print the current
* filename and line number within the current file
*/
- FlPrintFile (FileId, "%12s %5d....",
- Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber);
+ FlPrintFile (FileId, "%12s %5d%s",
+ Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber,
+ ASL_LISTING_LINE_PREFIX);
}
else
{
/* No include files, just print the line number */
- FlPrintFile (FileId, "%8d....", Gbl_SourceLine);
+ FlPrintFile (FileId, "%8u%s", Gbl_SourceLine,
+ ASL_LISTING_LINE_PREFIX);
}
- /* Read one line (up to a newline or EOF) */
+ /* Read the rest of this line (up to a newline or EOF) */
- while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK)
+ do
{
if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
{
@@ -788,13 +789,15 @@ LsWriteOneSourceLine (
if (FileByte == '\n')
{
/*
+ * This line has been completed.
* Check if an error occurred on this source line during the compile.
* If so, we print the error message after the source line.
*/
LsCheckException (Gbl_SourceLine, FileId);
return (1);
}
- }
+
+ } while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK);
/* EOF on the input file was reached */
@@ -1241,332 +1244,3 @@ LsWriteNodeToListing (
break;
}
}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoHexOutput
- *
- * PARAMETERS: None
- *
- * RETURN: None.
- *
- * DESCRIPTION: Create the hex output file.
- *
- ******************************************************************************/
-
-void
-LsDoHexOutput (
- void)
-{
-
- switch (Gbl_HexOutputFlag)
- {
- case HEX_OUTPUT_C:
-
- LsDoHexOutputC ();
- break;
-
- case HEX_OUTPUT_ASM:
-
- LsDoHexOutputAsm ();
- break;
-
- case HEX_OUTPUT_ASL:
-
- LsDoHexOutputAsl ();
- break;
-
- default:
- /* No other output types supported */
- break;
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsReadAmlOutputFile
- *
- * PARAMETERS: Buffer - Where to return data
- *
- * RETURN: None.
- *
- * DESCRIPTION: Read a line of the AML output prior to formatting the data
- *
- ******************************************************************************/
-
-static UINT32
-LsReadAmlOutputFile (
- UINT8 *Buffer)
-{
- UINT32 Actual;
-
-
- Actual = fread (Buffer, 1, HEX_TABLE_LINE_SIZE,
- Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
-
- if (ferror (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle))
- {
- FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
- AslAbort ();
- }
-
- return (Actual);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoHexOutputC
- *
- * PARAMETERS: None
- *
- * RETURN: None.
- *
- * DESCRIPTION: Create the hex output file. This is the same data as the AML
- * output file, but formatted into hex/ascii bytes suitable for
- * inclusion into a C source file.
- *
- ******************************************************************************/
-
-static void
-LsDoHexOutputC (
- void)
-{
- UINT8 FileData[HEX_TABLE_LINE_SIZE];
- UINT32 LineLength;
- UINT32 Offset = 0;
- UINT32 AmlFileSize;
- UINT32 i;
-
-
- /* Get AML size, seek back to start */
-
- AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
- FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n");
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
- AmlFileSize);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char AmlCode[] =\n{\n");
-
- while (Offset < AmlFileSize)
- {
- /* Read enough bytes needed for one output line */
-
- LineLength = LsReadAmlOutputFile (FileData);
- if (!LineLength)
- {
- break;
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
-
- for (i = 0; i < LineLength; i++)
- {
- /*
- * Print each hex byte.
- * Add a comma until the very last byte of the AML file
- * (Some C compilers complain about a trailing comma)
- */
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
- if ((Offset + i + 1) < AmlFileSize)
- {
- FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
- }
- else
- {
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
- }
- }
-
- /* Add fill spaces if needed for last line */
-
- if (LineLength < HEX_TABLE_LINE_SIZE)
- {
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
- 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
- }
-
- /* Emit the offset and ascii dump for the entire line */
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset);
- LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
- HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
-
- Offset += LineLength;
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "};\n");
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoHexOutputAsl
- *
- * PARAMETERS: None
- *
- * RETURN: None.
- *
- * DESCRIPTION: Create the hex output file. This is the same data as the AML
- * output file, but formatted into hex/ascii bytes suitable for
- * inclusion into a C source file.
- *
- ******************************************************************************/
-
-static void
-LsDoHexOutputAsl (
- void)
-{
- UINT8 FileData[HEX_TABLE_LINE_SIZE];
- UINT32 LineLength;
- UINT32 Offset = 0;
- UINT32 AmlFileSize;
- UINT32 i;
-
-
- /* Get AML size, seek back to start */
-
- AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
- FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " * ASL source code output\n");
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
- AmlFileSize);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " Name (BUF1, Buffer()\n {\n");
-
- while (Offset < AmlFileSize)
- {
- /* Read enough bytes needed for one output line */
-
- LineLength = LsReadAmlOutputFile (FileData);
- if (!LineLength)
- {
- break;
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
-
- for (i = 0; i < LineLength; i++)
- {
- /*
- * Print each hex byte.
- * Add a comma until the very last byte of the AML file
- * (Some C compilers complain about a trailing comma)
- */
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
- if ((Offset + i + 1) < AmlFileSize)
- {
- FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
- }
- else
- {
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
- }
- }
-
- /* Add fill spaces if needed for last line */
-
- if (LineLength < HEX_TABLE_LINE_SIZE)
- {
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
- 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
- }
-
- /* Emit the offset and ascii dump for the entire line */
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset);
- LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
- HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
-
- Offset += LineLength;
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " })\n");
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoHexOutputAsm
- *
- * PARAMETERS: None
- *
- * RETURN: None.
- *
- * DESCRIPTION: Create the hex output file. This is the same data as the AML
- * output file, but formatted into hex/ascii bytes suitable for
- * inclusion into a ASM source file.
- *
- ******************************************************************************/
-
-static void
-LsDoHexOutputAsm (
- void)
-{
- UINT8 FileData[HEX_TABLE_LINE_SIZE];
- UINT32 LineLength;
- UINT32 Offset = 0;
- UINT32 AmlFileSize;
- UINT32 i;
-
-
- /* Get AML size, seek back to start */
-
- AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
- FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n");
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "; AML code block contains 0x%X bytes\n;\n",
- AmlFileSize);
-
- while (Offset < AmlFileSize)
- {
- /* Read enough bytes needed for one output line */
-
- LineLength = LsReadAmlOutputFile (FileData);
- if (!LineLength)
- {
- break;
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " db ");
-
- for (i = 0; i < LineLength; i++)
- {
- /*
- * Print each hex byte.
- * Add a comma until the last byte of the line
- */
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "0%2.2Xh", FileData[i]);
- if ((i + 1) < LineLength)
- {
- FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
- }
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
-
- /* Add fill spaces if needed for last line */
-
- if (LineLength < HEX_TABLE_LINE_SIZE)
- {
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
- 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
- }
-
- /* Emit the offset and ascii dump for the entire line */
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " ; %8.8X", Offset);
- LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
-
- Offset += LineLength;
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
-}
diff --git a/sys/contrib/dev/acpica/compiler/aslload.c b/sys/contrib/dev/acpica/compiler/aslload.c
index 907dc14..813e603 100644
--- a/sys/contrib/dev/acpica/compiler/aslload.c
+++ b/sys/contrib/dev/acpica/compiler/aslload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asllookup.c b/sys/contrib/dev/acpica/compiler/asllookup.c
index 9af193b..67952a6 100644
--- a/sys/contrib/dev/acpica/compiler/asllookup.c
+++ b/sys/contrib/dev/acpica/compiler/asllookup.c
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Module Name: asllookup- Namespace lookup
+ * Module Name: asllookup- Namespace lookup functions
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,6 @@
#include <contrib/dev/acpica/compiler/aslcompiler.h>
#include "aslcompiler.y.h"
-
#include <contrib/dev/acpica/include/acparser.h>
#include <contrib/dev/acpica/include/amlcode.h>
#include <contrib/dev/acpica/include/acnamesp.h>
@@ -57,57 +56,12 @@
/* Local prototypes */
static ACPI_STATUS
-LsCompareOneNamespaceObject (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue);
-
-static ACPI_STATUS
-LsDoOneNamespaceObject (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue);
-
-static BOOLEAN
-LkObjectExists (
- char *Name);
-
-static void
-LkCheckFieldRange (
- ACPI_PARSE_OBJECT *Op,
- UINT32 RegionBitLength,
- UINT32 FieldBitOffset,
- UINT32 FieldBitLength,
- UINT32 AccessBitWidth);
-
-static ACPI_STATUS
-LkNamespaceLocateBegin (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context);
-
-static ACPI_STATUS
-LkNamespaceLocateEnd (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context);
-
-static ACPI_STATUS
LkIsObjectUsed (
ACPI_HANDLE ObjHandle,
UINT32 Level,
void *Context,
void **ReturnValue);
-static ACPI_STATUS
-LsDoOnePathname (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue);
-
static ACPI_PARSE_OBJECT *
LkGetNameOp (
ACPI_PARSE_OBJECT *Op);
@@ -115,480 +69,28 @@ LkGetNameOp (
/*******************************************************************************
*
- * FUNCTION: LsDoOneNamespaceObject
- *
- * PARAMETERS: ACPI_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Dump a namespace object to the namespace output file.
- * Called during the walk of the namespace to dump all objects.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-LsDoOneNamespaceObject (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue)
-{
- ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
- ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_PARSE_OBJECT *Op;
-
-
- Gbl_NumNamespaceObjects++;
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%5u [%u] %*s %4.4s - %s",
- Gbl_NumNamespaceObjects, Level, (Level * 3), " ",
- &Node->Name,
- AcpiUtGetTypeName (Node->Type));
-
- Op = Node->Op;
- ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node->Object);
-
- if (!Op)
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
- return (AE_OK);
- }
-
-
- if ((ObjDesc) &&
- (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND))
- {
- switch (Node->Type)
- {
- case ACPI_TYPE_INTEGER:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Value 0x%8.8X%8.8X]",
- ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
- break;
-
-
- case ACPI_TYPE_STRING:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Value \"%s\"]",
- ObjDesc->String.Pointer);
- break;
-
- default:
- /* Nothing to do for other types */
- break;
- }
-
- }
- else
- {
- switch (Node->Type)
- {
- case ACPI_TYPE_INTEGER:
-
- if (Op->Asl.ParseOpcode == PARSEOP_NAME)
- {
- Op = Op->Asl.Child;
- }
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Next;
- }
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Value 0x%8.8X%8.8X]",
- ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
- break;
-
-
- case ACPI_TYPE_STRING:
-
- if (Op->Asl.ParseOpcode == PARSEOP_NAME)
- {
- Op = Op->Asl.Child;
- }
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Next;
- }
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Value \"%s\"]",
- Op->Asl.Value.String);
- break;
-
-
- case ACPI_TYPE_LOCAL_REGION_FIELD:
-
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Child;
- }
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Offset 0x%04X Length 0x%04X bits]",
- Op->Asl.Parent->Asl.ExtraValue, (UINT32) Op->Asl.Value.Integer);
- break;
-
-
- case ACPI_TYPE_BUFFER_FIELD:
-
- switch (Op->Asl.ParseOpcode)
- {
- case PARSEOP_CREATEBYTEFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BYTE ( 8 bit)]");
- break;
-
- case PARSEOP_CREATEDWORDFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [DWORD (32 bit)]");
- break;
-
- case PARSEOP_CREATEQWORDFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [QWORD (64 bit)]");
- break;
-
- case PARSEOP_CREATEWORDFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [WORD (16 bit)]");
- break;
-
- case PARSEOP_CREATEBITFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BIT ( 1 bit)]");
- break;
-
- case PARSEOP_CREATEFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [Arbitrary Bit Field]");
- break;
-
- default:
- break;
-
- }
- break;
-
-
- case ACPI_TYPE_PACKAGE:
-
- if (Op->Asl.ParseOpcode == PARSEOP_NAME)
- {
- Op = Op->Asl.Child;
- }
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Next;
- }
- Op = Op->Asl.Child;
-
- if ((Op->Asl.ParseOpcode == PARSEOP_BYTECONST) ||
- (Op->Asl.ParseOpcode == PARSEOP_RAW_DATA))
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Length 0x%.2X elements]",
- Op->Asl.Value.Integer);
- }
- break;
-
-
- case ACPI_TYPE_BUFFER:
-
- if (Op->Asl.ParseOpcode == PARSEOP_NAME)
- {
- Op = Op->Asl.Child;
- }
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Next;
- }
- Op = Op->Asl.Child;
-
- if (Op && (Op->Asl.ParseOpcode == PARSEOP_INTEGER))
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Length 0x%.2X bytes]",
- Op->Asl.Value.Integer);
- }
- break;
-
-
- case ACPI_TYPE_METHOD:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Code Length 0x%.4X bytes]",
- Op->Asl.AmlSubtreeLength);
- break;
-
-
- case ACPI_TYPE_LOCAL_RESOURCE:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Desc Offset 0x%.4X Bytes]", Node->Value);
- break;
-
-
- case ACPI_TYPE_LOCAL_RESOURCE_FIELD:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Field Offset 0x%.4X Bits 0x%.4X Bytes] ",
- Node->Value, Node->Value / 8);
-
- if (Node->Flags & ANOBJ_IS_REFERENCED)
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- "Referenced");
- }
- else
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- "Name not referenced");
- }
- break;
-
-
- default:
- /* Nothing to do for other types */
- break;
- }
- }
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsSetupNsList
+ * FUNCTION: LkFindUnreferencedObjects
*
- * PARAMETERS: Handle - local file handle
+ * PARAMETERS: None
*
* RETURN: None
*
- * DESCRIPTION: Set the namespace output file to the input handle
+ * DESCRIPTION: Namespace walk to find objects that are not referenced in any
+ * way. Must be called after the namespace has been cross
+ * referenced.
*
******************************************************************************/
void
-LsSetupNsList (
- void *Handle)
-{
-
- Gbl_NsOutputFlag = TRUE;
- Gbl_Files[ASL_FILE_NAMESPACE_OUTPUT].Handle = Handle;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoOnePathname
- *
- * PARAMETERS: ACPI_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Print the full pathname for a namespace node.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-LsDoOnePathname (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue)
-{
- ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
- ACPI_STATUS Status;
- ACPI_BUFFER TargetPath;
-
-
- TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- Status = AcpiNsHandleToPathname (Node, &TargetPath);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%s\n", TargetPath.Pointer);
- ACPI_FREE (TargetPath.Pointer);
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDisplayNamespace
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Walk the namespace an display information about each node
- * in the tree. Information is written to the optional
- * namespace output file.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-LsDisplayNamespace (
+LkFindUnreferencedObjects (
void)
{
- ACPI_STATUS Status;
-
-
- if (!Gbl_NsOutputFlag)
- {
- return (AE_OK);
- }
-
- Gbl_NumNamespaceObjects = 0;
-
- /* File header */
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Contents of ACPI Namespace\n\n");
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Count Depth Name - Type\n\n");
-
- /* Walk entire namespace from the root */
-
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, FALSE, LsDoOneNamespaceObject, NULL,
- NULL, NULL);
-
- /* Print the full pathname for each namespace node */
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\nNamespace pathnames\n\n");
-
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, FALSE, LsDoOnePathname, NULL,
- NULL, NULL);
-
- return (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsCompareOneNamespaceObject
- *
- * PARAMETERS: ACPI_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Compare name of one object.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-LsCompareOneNamespaceObject (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue)
-{
- ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
-
-
- /* Simply check the name */
-
- if (*((UINT32 *) (Context)) == Node->Name.Integer)
- {
- /* Abort walk if we found one instance */
-
- return (AE_CTRL_TRUE);
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkObjectExists
- *
- * PARAMETERS: Name - 4 char ACPI name
- *
- * RETURN: TRUE if name exists in namespace
- *
- * DESCRIPTION: Walk the namespace to find an object
- *
- ******************************************************************************/
-
-static BOOLEAN
-LkObjectExists (
- char *Name)
-{
- ACPI_STATUS Status;
-
/* Walk entire namespace from the supplied root */
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, FALSE, LsCompareOneNamespaceObject, NULL,
- Name, NULL);
- if (Status == AE_CTRL_TRUE)
- {
- /* At least one instance of the name was found */
-
- return (TRUE);
- }
-
- return (FALSE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkGetNameOp
- *
- * PARAMETERS: Op - Current Op
- *
- * RETURN: NameOp associated with the input op
- *
- * DESCRIPTION: Find the name declaration op associated with the operator
- *
- ******************************************************************************/
-
-static ACPI_PARSE_OBJECT *
-LkGetNameOp (
- ACPI_PARSE_OBJECT *Op)
-{
- const ACPI_OPCODE_INFO *OpInfo;
- ACPI_PARSE_OBJECT *NameOp = Op;
-
-
- OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
-
-
- /* Get the NamePath from the appropriate place */
-
- if (OpInfo->Flags & AML_NAMED)
- {
- /* For nearly all NAMED operators, the name reference is the first child */
-
- NameOp = Op->Asl.Child;
- if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
- {
- /*
- * ALIAS is the only oddball opcode, the name declaration
- * (alias name) is the second operand
- */
- NameOp = Op->Asl.Child->Asl.Next;
- }
- }
- else if (OpInfo->Flags & AML_CREATE)
- {
- /* Name must appear as the last parameter */
-
- NameOp = Op->Asl.Child;
- while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
- {
- NameOp = NameOp->Asl.Next;
- }
- }
-
- return (NameOp);
+ (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, LkIsObjectUsed, NULL,
+ NULL, NULL);
}
@@ -660,232 +162,26 @@ LkIsObjectUsed (
/*******************************************************************************
*
- * FUNCTION: LkFindUnreferencedObjects
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Namespace walk to find objects that are not referenced in any
- * way. Must be called after the namespace has been cross
- * referenced.
- *
- ******************************************************************************/
-
-void
-LkFindUnreferencedObjects (
- void)
-{
-
- /* Walk entire namespace from the supplied root */
-
- (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, FALSE, LkIsObjectUsed, NULL,
- NULL, NULL);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkCrossReferenceNamespace
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Perform a cross reference check of the parse tree against the
- * namespace. Every named referenced within the parse tree
- * should be get resolved with a namespace lookup. If not, the
- * original reference in the ASL code is invalid -- i.e., refers
- * to a non-existent object.
- *
- * NOTE: The ASL "External" operator causes the name to be inserted into the
- * namespace so that references to the external name will be resolved
- * correctly here.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-LkCrossReferenceNamespace (
- void)
-{
- ACPI_WALK_STATE *WalkState;
-
-
- DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n");
-
- /*
- * Create a new walk state for use when looking up names
- * within the namespace (Passed as context to the callbacks)
- */
- WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
- if (!WalkState)
- {
- return (AE_NO_MEMORY);
- }
-
- /* Walk the entire parse tree */
-
- TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, LkNamespaceLocateBegin,
- LkNamespaceLocateEnd, WalkState);
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkCheckFieldRange
- *
- * PARAMETERS: RegionBitLength - Length of entire parent region
- * FieldBitOffset - Start of the field unit (within region)
- * FieldBitLength - Entire length of field unit
- * AccessBitWidth - Access width of the field unit
- *
- * RETURN: None
- *
- * DESCRIPTION: Check one field unit to make sure it fits in the parent
- * op region.
- *
- * Note: AccessBitWidth must be either 8,16,32, or 64
- *
- ******************************************************************************/
-
-static void
-LkCheckFieldRange (
- ACPI_PARSE_OBJECT *Op,
- UINT32 RegionBitLength,
- UINT32 FieldBitOffset,
- UINT32 FieldBitLength,
- UINT32 AccessBitWidth)
-{
- UINT32 FieldEndBitOffset;
-
-
- /*
- * Check each field unit against the region size. The entire
- * field unit (start offset plus length) must fit within the
- * region.
- */
- FieldEndBitOffset = FieldBitOffset + FieldBitLength;
-
- if (FieldEndBitOffset > RegionBitLength)
- {
- /* Field definition itself is beyond the end-of-region */
-
- AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
- return;
- }
-
- /*
- * Now check that the field plus AccessWidth doesn't go beyond
- * the end-of-region. Assumes AccessBitWidth is a power of 2
- */
- FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
-
- if (FieldEndBitOffset > RegionBitLength)
- {
- /* Field definition combined with the access is beyond EOR */
-
- AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
- }
-}
-
-/*******************************************************************************
- *
- * FUNCTION: LkNamespaceLocateBegin
- *
- * PARAMETERS: ASL_WALK_CALLBACK
+ * FUNCTION: LkGetNameOp
*
- * RETURN: Status
+ * PARAMETERS: Op - Current Op
*
- * DESCRIPTION: Descending callback used during cross-reference. For named
- * object references, attempt to locate the name in the
- * namespace.
+ * RETURN: NameOp associated with the input op
*
- * NOTE: ASL references to named fields within resource descriptors are
- * resolved to integer values here. Therefore, this step is an
- * important part of the code generation. We don't know that the
- * name refers to a resource descriptor until now.
+ * DESCRIPTION: Find the name declaration op associated with the operator
*
******************************************************************************/
-static ACPI_STATUS
-LkNamespaceLocateBegin (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context)
+static ACPI_PARSE_OBJECT *
+LkGetNameOp (
+ ACPI_PARSE_OBJECT *Op)
{
- ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
- ACPI_NAMESPACE_NODE *Node;
- ACPI_STATUS Status;
- ACPI_OBJECT_TYPE ObjectType;
- char *Path;
- UINT8 PassedArgs;
- ACPI_PARSE_OBJECT *NextOp;
- ACPI_PARSE_OBJECT *OwningOp;
- ACPI_PARSE_OBJECT *SpaceIdOp;
- UINT32 MinimumLength;
- UINT32 Offset;
- UINT32 FieldBitLength;
- UINT32 TagBitLength;
- UINT8 Message = 0;
const ACPI_OPCODE_INFO *OpInfo;
- UINT32 Flags;
-
-
- ACPI_FUNCTION_TRACE_PTR (LkNamespaceLocateBegin, Op);
-
- /*
- * If this node is the actual declaration of a name
- * [such as the XXXX name in "Method (XXXX)"],
- * we are not interested in it here. We only care about names that are
- * references to other objects within the namespace and the parent objects
- * of name declarations
- */
- if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
- {
- return (AE_OK);
- }
+ ACPI_PARSE_OBJECT *NameOp = Op;
- /* We are only interested in opcodes that have an associated name */
OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
- if ((!(OpInfo->Flags & AML_NAMED)) &&
- (!(OpInfo->Flags & AML_CREATE)) &&
- (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
- (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
- (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
- {
- return (AE_OK);
- }
-
- /*
- * One special case: CondRefOf operator - we don't care if the name exists
- * or not at this point, just ignore it, the point of the operator is to
- * determine if the name exists at runtime.
- */
- if ((Op->Asl.Parent) &&
- (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
- {
- return (AE_OK);
- }
-
- /*
- * We must enable the "search-to-root" for single NameSegs, but
- * we have to be very careful about opening up scopes
- */
- Flags = ACPI_NS_SEARCH_PARENT;
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
- {
- /*
- * These are name references, do not push the scope stack
- * for them.
- */
- Flags |= ACPI_NS_DONT_OPEN_SCOPE;
- }
/* Get the NamePath from the appropriate place */
@@ -893,510 +189,26 @@ LkNamespaceLocateBegin (
{
/* For nearly all NAMED operators, the name reference is the first child */
- Path = Op->Asl.Child->Asl.Value.String;
+ NameOp = Op->Asl.Child;
if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
{
/*
* ALIAS is the only oddball opcode, the name declaration
* (alias name) is the second operand
*/
- Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
+ NameOp = Op->Asl.Child->Asl.Next;
}
}
else if (OpInfo->Flags & AML_CREATE)
{
/* Name must appear as the last parameter */
- NextOp = Op->Asl.Child;
- while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
- {
- NextOp = NextOp->Asl.Next;
- }
- Path = NextOp->Asl.Value.String;
- }
- else
- {
- Path = Op->Asl.Value.String;
- }
-
- ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
-
- /*
- * Lookup the name in the namespace. Name must exist at this point, or it
- * is an invalid reference.
- *
- * The namespace is also used as a lookup table for references to resource
- * descriptors and the fields within them.
- */
- Gbl_NsLookupCount++;
-
- Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
- ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
- if (ACPI_FAILURE (Status))
- {
- if (Status == AE_NOT_FOUND)
- {
- /*
- * We didn't find the name reference by path -- we can qualify this
- * a little better before we print an error message
- */
- if (strlen (Path) == ACPI_NAME_SIZE)
- {
- /* A simple, one-segment ACPI name */
-
- if (LkObjectExists (Path))
- {
- /*
- * There exists such a name, but we couldn't get to it
- * from this scope
- */
- AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
- Op->Asl.ExternalName);
- }
- else
- {
- /* The name doesn't exist, period */
-
- AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
- Op, Op->Asl.ExternalName);
- }
- }
- else
- {
- /* Check for a fully qualified path */
-
- if (Path[0] == AML_ROOT_PREFIX)
- {
- /* Gave full path, the object does not exist */
-
- AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
- Op->Asl.ExternalName);
- }
- else
- {
- /*
- * We can't tell whether it doesn't exist or just
- * can't be reached.
- */
- AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
- Op->Asl.ExternalName);
- }
- }
-
- Status = AE_OK;
- }
- return (Status);
- }
-
- /* Check for a reference vs. name declaration */
-
- if (!(OpInfo->Flags & AML_NAMED) &&
- !(OpInfo->Flags & AML_CREATE))
- {
- /* This node has been referenced, mark it for reference check */
-
- Node->Flags |= ANOBJ_IS_REFERENCED;
- }
-
- /* Attempt to optimize the NamePath */
-
- OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
-
- /*
- * 1) Dereference an alias (A name reference that is an alias)
- * Aliases are not nested, the alias always points to the final object
- */
- if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
- (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
- {
- /* This node points back to the original PARSEOP_ALIAS */
-
- NextOp = Node->Op;
-
- /* The first child is the alias target op */
-
- NextOp = NextOp->Asl.Child;
-
- /* That in turn points back to original target alias node */
-
- if (NextOp->Asl.Node)
- {
- Node = NextOp->Asl.Node;
- }
-
- /* Else - forward reference to alias, will be resolved later */
- }
-
- /* 2) Check for a reference to a resource descriptor */
-
- if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
- (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
- {
- /*
- * This was a reference to a field within a resource descriptor.
- * Extract the associated field offset (either a bit or byte
- * offset depending on the field type) and change the named
- * reference into an integer for AML code generation
- */
- Offset = Node->Value;
- TagBitLength = Node->Length;
-
- /*
- * If a field is being created, generate the length (in bits) of
- * the field. Note: Opcodes other than CreateXxxField and Index
- * can come through here. For other opcodes, we just need to
- * convert the resource tag reference to an integer offset.
- */
- switch (Op->Asl.Parent->Asl.AmlOpcode)
- {
- case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
- /*
- * We know the length operand is an integer constant because
- * we know that it contains a reference to a resource
- * descriptor tag.
- */
- FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
- break;
-
- case AML_CREATE_BIT_FIELD_OP:
- FieldBitLength = 1;
- break;
-
- case AML_CREATE_BYTE_FIELD_OP:
- case AML_INDEX_OP:
- FieldBitLength = 8;
- break;
-
- case AML_CREATE_WORD_FIELD_OP:
- FieldBitLength = 16;
- break;
-
- case AML_CREATE_DWORD_FIELD_OP:
- FieldBitLength = 32;
- break;
-
- case AML_CREATE_QWORD_FIELD_OP:
- FieldBitLength = 64;
- break;
-
- default:
- FieldBitLength = 0;
- break;
- }
-
- /* Check the field length against the length of the resource tag */
-
- if (FieldBitLength)
- {
- if (TagBitLength < FieldBitLength)
- {
- Message = ASL_MSG_TAG_SMALLER;
- }
- else if (TagBitLength > FieldBitLength)
- {
- Message = ASL_MSG_TAG_LARGER;
- }
-
- if (Message)
- {
- sprintf (MsgBuffer, "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
- TagBitLength, (TagBitLength > 1) ? "s" : "",
- FieldBitLength, (FieldBitLength > 1) ? "s" : "");
-
- AslError (ASL_WARNING, Message, Op, MsgBuffer);
- }
- }
-
- /* Convert the BitOffset to a ByteOffset for certain opcodes */
-
- switch (Op->Asl.Parent->Asl.AmlOpcode)
- {
- case AML_CREATE_BYTE_FIELD_OP:
- case AML_CREATE_WORD_FIELD_OP:
- case AML_CREATE_DWORD_FIELD_OP:
- case AML_CREATE_QWORD_FIELD_OP:
- case AML_INDEX_OP:
-
- Offset = ACPI_DIV_8 (Offset);
- break;
-
- default:
- break;
- }
-
- /* Now convert this node to an integer whose value is the field offset */
-
- Op->Asl.AmlLength = 0;
- Op->Asl.ParseOpcode = PARSEOP_INTEGER;
- Op->Asl.Value.Integer = (UINT64) Offset;
- Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
-
- OpcGenerateAmlOpcode (Op);
- }
-
- /* 3) Check for a method invocation */
-
- else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
- (Node->Type == ACPI_TYPE_METHOD) &&
- (Op->Asl.Parent) &&
- (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) ||
-
- (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
- {
-
- /*
- * A reference to a method within one of these opcodes is not an
- * invocation of the method, it is simply a reference to the method.
- */
- if ((Op->Asl.Parent) &&
- ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) ||
- (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) ||
- (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
- {
- return (AE_OK);
- }
- /*
- * There are two types of method invocation:
- * 1) Invocation with arguments -- the parser recognizes this
- * as a METHODCALL.
- * 2) Invocation with no arguments --the parser cannot determine that
- * this is a method invocation, therefore we have to figure it out
- * here.
- */
- if (Node->Type != ACPI_TYPE_METHOD)
- {
- sprintf (MsgBuffer, "%s is a %s",
- Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
-
- AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
- return (AE_OK);
- }
-
- /* Save the method node in the caller's op */
-
- Op->Asl.Node = Node;
- if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
- {
- return (AE_OK);
- }
-
- /*
- * This is a method invocation, with or without arguments.
- * Count the number of arguments, each appears as a child
- * under the parent node
- */
- Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
- UtSetParseOpName (Op);
-
- PassedArgs = 0;
- NextOp = Op->Asl.Child;
-
- while (NextOp)
- {
- PassedArgs++;
- NextOp = NextOp->Asl.Next;
- }
-
- if (Node->Value != ASL_EXTERNAL_METHOD)
- {
- /*
- * Check the parsed arguments with the number expected by the
- * method declaration itself
- */
- if (PassedArgs != Node->Value)
- {
- sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName,
- Node->Value);
-
- if (PassedArgs < Node->Value)
- {
- AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
- }
- else
- {
- AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
- }
- }
- }
- }
-
- /* 4) Check for an ASL Field definition */
-
- else if ((Op->Asl.Parent) &&
- ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) ||
- (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
- {
- /*
- * Offset checking for fields. If the parent operation region has a
- * constant length (known at compile time), we can check fields
- * defined in that region against the region length. This will catch
- * fields and field units that cannot possibly fit within the region.
- *
- * Note: Index fields do not directly reference an operation region,
- * thus they are not included in this check.
- */
- if (Op == Op->Asl.Parent->Asl.Child)
- {
- /*
- * This is the first child of the field node, which is
- * the name of the region. Get the parse node for the
- * region -- which contains the length of the region.
- */
- OwningOp = Node->Op;
- Op->Asl.Parent->Asl.ExtraValue =
- ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
-
- /* Examine the field access width */
-
- switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
- {
- case AML_FIELD_ACCESS_ANY:
- case AML_FIELD_ACCESS_BYTE:
- case AML_FIELD_ACCESS_BUFFER:
- default:
- MinimumLength = 1;
- break;
-
- case AML_FIELD_ACCESS_WORD:
- MinimumLength = 2;
- break;
-
- case AML_FIELD_ACCESS_DWORD:
- MinimumLength = 4;
- break;
-
- case AML_FIELD_ACCESS_QWORD:
- MinimumLength = 8;
- break;
- }
-
- /*
- * Is the region at least as big as the access width?
- * Note: DataTableRegions have 0 length
- */
- if (((UINT32) OwningOp->Asl.Value.Integer) &&
- ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
- {
- AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
- }
-
- /*
- * Check EC/CMOS/SMBUS fields to make sure that the correct
- * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
- */
- SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
- switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
- {
- case ACPI_ADR_SPACE_EC:
- case ACPI_ADR_SPACE_CMOS:
- case ACPI_ADR_SPACE_GPIO:
-
- if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
- {
- AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
- }
- break;
-
- case ACPI_ADR_SPACE_SMBUS:
- case ACPI_ADR_SPACE_IPMI:
- case ACPI_ADR_SPACE_GSBUS:
-
- if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
- {
- AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
- }
- break;
-
- default:
-
- /* Nothing to do for other address spaces */
- break;
- }
- }
- else
+ NameOp = Op->Asl.Child;
+ while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
{
- /*
- * This is one element of the field list. Check to make sure
- * that it does not go beyond the end of the parent operation region.
- *
- * In the code below:
- * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits)
- * Op->Asl.ExtraValue - Field start offset (bits)
- * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits)
- * Op->Asl.Child->Asl.ExtraValue - Field access width (bits)
- */
- if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
- {
- LkCheckFieldRange (Op,
- Op->Asl.Parent->Asl.ExtraValue,
- Op->Asl.ExtraValue,
- (UINT32) Op->Asl.Child->Asl.Value.Integer,
- Op->Asl.Child->Asl.ExtraValue);
- }
+ NameOp = NameOp->Asl.Next;
}
}
- Op->Asl.Node = Node;
- return (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkNamespaceLocateEnd
- *
- * PARAMETERS: ASL_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Ascending callback used during cross reference. We only
- * need to worry about scope management here.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-LkNamespaceLocateEnd (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context)
-{
- ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
- const ACPI_OPCODE_INFO *OpInfo;
-
-
- ACPI_FUNCTION_TRACE (LkNamespaceLocateEnd);
-
-
- /* We are only interested in opcodes that have an associated name */
-
- OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
- if (!(OpInfo->Flags & AML_NAMED))
- {
- return (AE_OK);
- }
-
- /* Not interested in name references, we did not open a scope for them */
-
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
- {
- return (AE_OK);
- }
-
- /* Pop the scope stack if necessary */
-
- if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
- {
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%s: Popping scope for Op %p\n",
- AcpiUtGetTypeName (OpInfo->ObjectType), Op));
-
- (void) AcpiDsScopeStackPop (WalkState);
- }
-
- return (AE_OK);
+ return (NameOp);
}
diff --git a/sys/contrib/dev/acpica/compiler/aslmain.c b/sys/contrib/dev/acpica/compiler/aslmain.c
index 3b6d45b..1a05b9f 100644
--- a/sys/contrib/dev/acpica/compiler/aslmain.c
+++ b/sys/contrib/dev/acpica/compiler/aslmain.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -153,6 +153,7 @@ Options (
ACPI_OPTION ("-oi", "Disable integer optimization to Zero/One/Ones");
ACPI_OPTION ("-on", "Disable named reference string optimization");
ACPI_OPTION ("-cr", "Disable Resource Descriptor error checking");
+ ACPI_OPTION ("-in", "Ignore NoOp operators");
ACPI_OPTION ("-r <revision>", "Override table header Revision (1-255)");
printf ("\nASL Listing Files:\n");
@@ -172,6 +173,7 @@ Options (
ACPI_OPTION ("", "(Obtain DSDT from current system if no input file)");
ACPI_OPTION ("-e [f1,f2]", "Include ACPI table(s) for external symbol resolution");
ACPI_OPTION ("-g", "Get ACPI tables and write to files (*.dat)");
+ ACPI_OPTION ("-in", "Ignore NoOp opcodes");
ACPI_OPTION ("-vt", "Dump binary table data in hex format within output file");
printf ("\nHelp:\n");
@@ -622,6 +624,13 @@ AslDoOptions (
Gbl_C_IncludeOutputFlag = TRUE;
break;
+ case 'n':
+
+ /* Compiler/Disassembler: Ignore the NOOP operator */
+
+ AcpiGbl_IgnoreNoopOperator = TRUE;
+ break;
+
default:
printf ("Unknown option: -i%s\n", AcpiGbl_Optarg);
return (-1);
diff --git a/sys/contrib/dev/acpica/compiler/aslmap.c b/sys/contrib/dev/acpica/compiler/aslmap.c
index d9f3325..0d2e636 100644
--- a/sys/contrib/dev/acpica/compiler/aslmap.c
+++ b/sys/contrib/dev/acpica/compiler/aslmap.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslmessages.h b/sys/contrib/dev/acpica/compiler/aslmessages.h
index 07758ef..be7a3f9 100644
--- a/sys/contrib/dev/acpica/compiler/aslmessages.h
+++ b/sys/contrib/dev/acpica/compiler/aslmessages.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -190,6 +190,7 @@ typedef enum
ASL_MSG_TAG_SMALLER,
ASL_MSG_TIMEOUT,
ASL_MSG_TOO_MANY_TEMPS,
+ ASL_MSG_TRUNCATION,
ASL_MSG_UNKNOWN_RESERVED_NAME,
ASL_MSG_UNREACHABLE_CODE,
ASL_MSG_UNSUPPORTED,
@@ -274,7 +275,7 @@ char *AslMessages [] = {
/* ASL_MSG_HID_SUFFIX */ "_HID suffix must be all hex digits",
/* ASL_MSG_INCLUDE_FILE_OPEN */ "Could not open include file",
/* ASL_MSG_INPUT_FILE_OPEN */ "Could not open input file",
-/* ASL_MSG_INTEGER_LENGTH */ "64-bit integer in 32-bit table, truncating",
+/* ASL_MSG_INTEGER_LENGTH */ "64-bit integer in 32-bit table, truncating (DSDT version < 2)",
/* ASL_MSG_INTEGER_OPTIMIZATION */ "Integer optimized to single-byte AML opcode",
/* ASL_MSG_INTERRUPT_LIST */ "Too many interrupts (16 max)",
/* ASL_MSG_INTERRUPT_NUMBER */ "Invalid interrupt number (must be 0-15)",
@@ -366,6 +367,7 @@ char *AslMessages [] = {
/* ASL_MSG_TAG_SMALLER */ "ResourceTag smaller than Field",
/* ASL_MSG_TIMEOUT */ "Result is not used, possible operator timeout will be missed",
/* ASL_MSG_TOO_MANY_TEMPS */ "Method requires too many temporary variables (_T_x)",
+/* ASL_MSG_TRUNCATION */ "64-bit return value will be truncated to 32 bits (DSDT version < 2)",
/* ASL_MSG_UNKNOWN_RESERVED_NAME */ "Unknown reserved name",
/* ASL_MSG_UNREACHABLE_CODE */ "Statement is unreachable",
/* ASL_MSG_UNSUPPORTED */ "Unsupported feature",
diff --git a/sys/contrib/dev/acpica/compiler/aslmethod.c b/sys/contrib/dev/acpica/compiler/aslmethod.c
new file mode 100644
index 0000000..f104d44
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslmethod.c
@@ -0,0 +1,619 @@
+/******************************************************************************
+ *
+ * Module Name: aslmethod.c - Control method analysis walk
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslmethod")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: MtMethodAnalysisWalkBegin
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
+ * 1) Initialized local variables
+ * 2) Valid arguments
+ * 3) Return types
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+MtMethodAnalysisWalkBegin (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
+ ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
+ ACPI_PARSE_OBJECT *Next;
+ UINT32 RegisterNumber;
+ UINT32 i;
+ char LocalName[] = "Local0";
+ char ArgName[] = "Arg0";
+ ACPI_PARSE_OBJECT *ArgNode;
+ ACPI_PARSE_OBJECT *NextType;
+ ACPI_PARSE_OBJECT *NextParamType;
+ UINT8 ActualArgs = 0;
+
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_METHOD:
+
+ TotalMethods++;
+
+ /* Create and init method info */
+
+ MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
+ MethodInfo->Next = WalkInfo->MethodStack;
+ MethodInfo->Op = Op;
+
+ WalkInfo->MethodStack = MethodInfo;
+
+ /* Get the name node, ignored here */
+
+ Next = Op->Asl.Child;
+
+ /* Get the NumArguments node */
+
+ Next = Next->Asl.Next;
+ MethodInfo->NumArguments = (UINT8)
+ (((UINT8) Next->Asl.Value.Integer) & 0x07);
+
+ /* Get the SerializeRule and SyncLevel nodes, ignored here */
+
+ Next = Next->Asl.Next;
+ Next = Next->Asl.Next;
+ ArgNode = Next;
+
+ /* Get the ReturnType node */
+
+ Next = Next->Asl.Next;
+
+ NextType = Next->Asl.Child;
+ while (NextType)
+ {
+ /* Get and map each of the ReturnTypes */
+
+ MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
+ NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
+ NextType = NextType->Asl.Next;
+ }
+
+ /* Get the ParameterType node */
+
+ Next = Next->Asl.Next;
+
+ NextType = Next->Asl.Child;
+ while (NextType)
+ {
+ if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
+ {
+ NextParamType = NextType->Asl.Child;
+ while (NextParamType)
+ {
+ MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
+ NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
+ NextParamType = NextParamType->Asl.Next;
+ }
+ }
+ else
+ {
+ MethodInfo->ValidArgTypes[ActualArgs] =
+ AnMapObjTypeToBtype (NextType);
+ NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
+ ActualArgs++;
+ }
+
+ NextType = NextType->Asl.Next;
+ }
+
+ if ((MethodInfo->NumArguments) &&
+ (MethodInfo->NumArguments != ActualArgs))
+ {
+ /* error: Param list did not match number of args */
+ }
+
+ /* Allow numarguments == 0 for Function() */
+
+ if ((!MethodInfo->NumArguments) && (ActualArgs))
+ {
+ MethodInfo->NumArguments = ActualArgs;
+ ArgNode->Asl.Value.Integer |= ActualArgs;
+ }
+
+ /*
+ * Actual arguments are initialized at method entry.
+ * All other ArgX "registers" can be used as locals, so we
+ * track their initialization.
+ */
+ for (i = 0; i < MethodInfo->NumArguments; i++)
+ {
+ MethodInfo->ArgInitialized[i] = TRUE;
+ }
+ break;
+
+
+ case PARSEOP_METHODCALL:
+
+ if (MethodInfo &&
+ (Op->Asl.Node == MethodInfo->Op->Asl.Node))
+ {
+ AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
+ }
+ break;
+
+
+ case PARSEOP_LOCAL0:
+ case PARSEOP_LOCAL1:
+ case PARSEOP_LOCAL2:
+ case PARSEOP_LOCAL3:
+ case PARSEOP_LOCAL4:
+ case PARSEOP_LOCAL5:
+ case PARSEOP_LOCAL6:
+ case PARSEOP_LOCAL7:
+
+ if (!MethodInfo)
+ {
+ /*
+ * Local was used outside a control method, or there was an error
+ * in the method declaration.
+ */
+ AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
+ return (AE_ERROR);
+ }
+
+ RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
+
+ /*
+ * If the local is being used as a target, mark the local
+ * initialized
+ */
+ if (Op->Asl.CompileFlags & NODE_IS_TARGET)
+ {
+ MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
+ }
+
+ /*
+ * Otherwise, this is a reference, check if the local
+ * has been previously initialized.
+ *
+ * The only operator that accepts an uninitialized value is ObjectType()
+ */
+ else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
+ (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
+ {
+ LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
+ AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
+ }
+ break;
+
+
+ case PARSEOP_ARG0:
+ case PARSEOP_ARG1:
+ case PARSEOP_ARG2:
+ case PARSEOP_ARG3:
+ case PARSEOP_ARG4:
+ case PARSEOP_ARG5:
+ case PARSEOP_ARG6:
+
+ if (!MethodInfo)
+ {
+ /*
+ * Arg was used outside a control method, or there was an error
+ * in the method declaration.
+ */
+ AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
+ return (AE_ERROR);
+ }
+
+ RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
+ ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
+
+ /*
+ * If the Arg is being used as a target, mark the local
+ * initialized
+ */
+ if (Op->Asl.CompileFlags & NODE_IS_TARGET)
+ {
+ MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
+ }
+
+ /*
+ * Otherwise, this is a reference, check if the Arg
+ * has been previously initialized.
+ *
+ * The only operator that accepts an uninitialized value is ObjectType()
+ */
+ else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
+ (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
+ {
+ AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
+ }
+
+ /* Flag this arg if it is not a "real" argument to the method */
+
+ if (RegisterNumber >= MethodInfo->NumArguments)
+ {
+ AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
+ }
+ break;
+
+
+ case PARSEOP_RETURN:
+
+ if (!MethodInfo)
+ {
+ /*
+ * Probably was an error in the method declaration,
+ * no additional error here
+ */
+ ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
+ return (AE_ERROR);
+ }
+
+ /*
+ * A child indicates a possible return value. A simple Return or
+ * Return() is marked with NODE_IS_NULL_RETURN by the parser so
+ * that it is not counted as a "real" return-with-value, although
+ * the AML code that is actually emitted is Return(0). The AML
+ * definition of Return has a required parameter, so we are
+ * forced to convert a null return to Return(0).
+ */
+ if ((Op->Asl.Child) &&
+ (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
+ {
+ MethodInfo->NumReturnWithValue++;
+ }
+ else
+ {
+ MethodInfo->NumReturnNoValue++;
+ }
+ break;
+
+
+ case PARSEOP_BREAK:
+ case PARSEOP_CONTINUE:
+
+ Next = Op->Asl.Parent;
+ while (Next)
+ {
+ if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
+ {
+ break;
+ }
+ Next = Next->Asl.Parent;
+ }
+
+ if (!Next)
+ {
+ AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
+ }
+ break;
+
+
+ case PARSEOP_STALL:
+
+ /* We can range check if the argument is an integer */
+
+ if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
+ (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
+ }
+ break;
+
+
+ case PARSEOP_DEVICE:
+ case PARSEOP_EVENT:
+ case PARSEOP_MUTEX:
+ case PARSEOP_OPERATIONREGION:
+ case PARSEOP_POWERRESOURCE:
+ case PARSEOP_PROCESSOR:
+ case PARSEOP_THERMALZONE:
+
+ /*
+ * The first operand is a name to be created in the namespace.
+ * Check against the reserved list.
+ */
+ i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
+ if (i < ACPI_VALID_RESERVED_NAME_MAX)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
+ }
+ break;
+
+
+ case PARSEOP_NAME:
+
+ /* Typecheck any predefined names statically defined with Name() */
+
+ ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
+
+ /* Special typechecking for _HID */
+
+ if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
+ {
+ Next = Op->Asl.Child->Asl.Next;
+ AnCheckId (Next, ASL_TYPE_HID);
+ }
+
+ /* Special typechecking for _CID */
+
+ else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
+ {
+ Next = Op->Asl.Child->Asl.Next;
+
+ if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
+ (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
+ {
+ Next = Next->Asl.Child;
+ while (Next)
+ {
+ AnCheckId (Next, ASL_TYPE_CID);
+ Next = Next->Asl.Next;
+ }
+ }
+ else
+ {
+ AnCheckId (Next, ASL_TYPE_CID);
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: MtMethodAnalysisWalkEnd
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback for analysis walk. Complete method
+ * return analysis.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+MtMethodAnalysisWalkEnd (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
+ ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
+
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_METHOD:
+ case PARSEOP_RETURN:
+ if (!MethodInfo)
+ {
+ printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
+ AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
+ "No method info for this method");
+
+ CmCleanupAndExit ();
+ return (AE_AML_INTERNAL);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_METHOD:
+
+ WalkInfo->MethodStack = MethodInfo->Next;
+
+ /*
+ * Check if there is no return statement at the end of the
+ * method AND we can actually get there -- i.e., the execution
+ * of the method can possibly terminate without a return statement.
+ */
+ if ((!AnLastStatementIsReturn (Op)) &&
+ (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
+ {
+ /*
+ * No return statement, and execution can possibly exit
+ * via this path. This is equivalent to Return ()
+ */
+ MethodInfo->NumReturnNoValue++;
+ }
+
+ /*
+ * Check for case where some return statements have a return value
+ * and some do not. Exit without a return statement is a return with
+ * no value
+ */
+ if (MethodInfo->NumReturnNoValue &&
+ MethodInfo->NumReturnWithValue)
+ {
+ AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
+ Op->Asl.ExternalName);
+ }
+
+ /*
+ * If there are any RETURN() statements with no value, or there is a
+ * control path that allows the method to exit without a return value,
+ * we mark the method as a method that does not return a value. This
+ * knowledge can be used to check method invocations that expect a
+ * returned value.
+ */
+ if (MethodInfo->NumReturnNoValue)
+ {
+ if (MethodInfo->NumReturnWithValue)
+ {
+ Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
+ }
+ else
+ {
+ Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
+ }
+ }
+
+ /*
+ * Check predefined method names for correct return behavior
+ * and correct number of arguments. Also, some special checks
+ * For GPE and _REG methods.
+ */
+ if (ApCheckForPredefinedMethod (Op, MethodInfo))
+ {
+ /* Special check for two names like _L01 and _E01 in same scope */
+
+ ApCheckForGpeNameConflict (Op);
+
+ /*
+ * Special check for _REG: Must have an operation region definition
+ * within the same scope!
+ */
+ ApCheckRegMethod (Op);
+ }
+
+ ACPI_FREE (MethodInfo);
+ break;
+
+
+ case PARSEOP_NAME:
+
+ /* Special check for two names like _L01 and _E01 in same scope */
+
+ ApCheckForGpeNameConflict (Op);
+ break;
+
+
+ case PARSEOP_RETURN:
+
+ /*
+ * If the parent is a predefined method name, attempt to typecheck
+ * the return value. Only static types can be validated.
+ */
+ ApCheckPredefinedReturnValue (Op, MethodInfo);
+
+ /*
+ * The parent block does not "exit" and continue execution -- the
+ * method is terminated here with the Return() statement.
+ */
+ Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
+
+ /* Used in the "typing" pass later */
+
+ Op->Asl.ParentMethod = MethodInfo->Op;
+
+ /*
+ * If there is a peer node after the return statement, then this
+ * node is unreachable code -- i.e., it won't be executed because of
+ * the preceding Return() statement.
+ */
+ if (Op->Asl.Next)
+ {
+ AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
+ }
+ break;
+
+
+ case PARSEOP_IF:
+
+ if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
+ (Op->Asl.Next) &&
+ (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
+ {
+ /*
+ * This IF has a corresponding ELSE. The IF block has no exit,
+ * (it contains an unconditional Return)
+ * mark the ELSE block to remember this fact.
+ */
+ Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
+ }
+ break;
+
+
+ case PARSEOP_ELSE:
+
+ if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
+ (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
+ {
+ /*
+ * This ELSE block has no exit and the corresponding IF block
+ * has no exit either. Therefore, the parent node has no exit.
+ */
+ Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
+ }
+ break;
+
+
+ default:
+
+ if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
+ (Op->Asl.Parent))
+ {
+ /* If this node has no exit, then the parent has no exit either */
+
+ Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
+ }
+ break;
+ }
+
+ return (AE_OK);
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslnamesp.c b/sys/contrib/dev/acpica/compiler/aslnamesp.c
new file mode 100644
index 0000000..5eb3b64
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslnamesp.c
@@ -0,0 +1,422 @@
+/******************************************************************************
+ *
+ * Module Name: aslnamesp - Namespace output file generation
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+#include <contrib/dev/acpica/include/acnamesp.h>
+
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslnamesp")
+
+/* Local prototypes */
+
+static ACPI_STATUS
+NsDoOneNamespaceObject (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+static ACPI_STATUS
+NsDoOnePathname (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: NsSetupNamespaceListing
+ *
+ * PARAMETERS: Handle - local file handle
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set the namespace output file to the input handle
+ *
+ ******************************************************************************/
+
+void
+NsSetupNamespaceListing (
+ void *Handle)
+{
+
+ Gbl_NsOutputFlag = TRUE;
+ Gbl_Files[ASL_FILE_NAMESPACE_OUTPUT].Handle = Handle;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: NsDisplayNamespace
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Walk the namespace an display information about each node
+ * in the tree. Information is written to the optional
+ * namespace output file.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+NsDisplayNamespace (
+ void)
+{
+ ACPI_STATUS Status;
+
+
+ if (!Gbl_NsOutputFlag)
+ {
+ return (AE_OK);
+ }
+
+ Gbl_NumNamespaceObjects = 0;
+
+ /* File header */
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Contents of ACPI Namespace\n\n");
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Count Depth Name - Type\n\n");
+
+ /* Walk entire namespace from the root */
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, NsDoOneNamespaceObject, NULL,
+ NULL, NULL);
+
+ /* Print the full pathname for each namespace node */
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\nNamespace pathnames\n\n");
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, NsDoOnePathname, NULL,
+ NULL, NULL);
+
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: NsDoOneNamespaceObject
+ *
+ * PARAMETERS: ACPI_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Dump a namespace object to the namespace output file.
+ * Called during the walk of the namespace to dump all objects.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+NsDoOneNamespaceObject (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_PARSE_OBJECT *Op;
+
+
+ Gbl_NumNamespaceObjects++;
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%5u [%u] %*s %4.4s - %s",
+ Gbl_NumNamespaceObjects, Level, (Level * 3), " ",
+ &Node->Name,
+ AcpiUtGetTypeName (Node->Type));
+
+ Op = Node->Op;
+ ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node->Object);
+
+ if (!Op)
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
+ return (AE_OK);
+ }
+
+
+ if ((ObjDesc) &&
+ (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND))
+ {
+ switch (Node->Type)
+ {
+ case ACPI_TYPE_INTEGER:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Value 0x%8.8X%8.8X]",
+ ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Value \"%s\"]",
+ ObjDesc->String.Pointer);
+ break;
+
+ default:
+ /* Nothing to do for other types */
+ break;
+ }
+
+ }
+ else
+ {
+ switch (Node->Type)
+ {
+ case ACPI_TYPE_INTEGER:
+
+ if (Op->Asl.ParseOpcode == PARSEOP_NAME)
+ {
+ Op = Op->Asl.Child;
+ }
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Next;
+ }
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Value 0x%8.8X%8.8X]",
+ ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ if (Op->Asl.ParseOpcode == PARSEOP_NAME)
+ {
+ Op = Op->Asl.Child;
+ }
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Next;
+ }
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Value \"%s\"]",
+ Op->Asl.Value.String);
+ break;
+
+
+ case ACPI_TYPE_LOCAL_REGION_FIELD:
+
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Child;
+ }
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Offset 0x%04X Length 0x%04X bits]",
+ Op->Asl.Parent->Asl.ExtraValue, (UINT32) Op->Asl.Value.Integer);
+ break;
+
+
+ case ACPI_TYPE_BUFFER_FIELD:
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_CREATEBYTEFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BYTE ( 8 bit)]");
+ break;
+
+ case PARSEOP_CREATEDWORDFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [DWORD (32 bit)]");
+ break;
+
+ case PARSEOP_CREATEQWORDFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [QWORD (64 bit)]");
+ break;
+
+ case PARSEOP_CREATEWORDFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [WORD (16 bit)]");
+ break;
+
+ case PARSEOP_CREATEBITFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BIT ( 1 bit)]");
+ break;
+
+ case PARSEOP_CREATEFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [Arbitrary Bit Field]");
+ break;
+
+ default:
+ break;
+
+ }
+ break;
+
+
+ case ACPI_TYPE_PACKAGE:
+
+ if (Op->Asl.ParseOpcode == PARSEOP_NAME)
+ {
+ Op = Op->Asl.Child;
+ }
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Next;
+ }
+ Op = Op->Asl.Child;
+
+ if ((Op->Asl.ParseOpcode == PARSEOP_BYTECONST) ||
+ (Op->Asl.ParseOpcode == PARSEOP_RAW_DATA))
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Length 0x%.2X elements]",
+ Op->Asl.Value.Integer);
+ }
+ break;
+
+
+ case ACPI_TYPE_BUFFER:
+
+ if (Op->Asl.ParseOpcode == PARSEOP_NAME)
+ {
+ Op = Op->Asl.Child;
+ }
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Next;
+ }
+ Op = Op->Asl.Child;
+
+ if (Op && (Op->Asl.ParseOpcode == PARSEOP_INTEGER))
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Length 0x%.2X bytes]",
+ Op->Asl.Value.Integer);
+ }
+ break;
+
+
+ case ACPI_TYPE_METHOD:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Code Length 0x%.4X bytes]",
+ Op->Asl.AmlSubtreeLength);
+ break;
+
+
+ case ACPI_TYPE_LOCAL_RESOURCE:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Desc Offset 0x%.4X Bytes]", Node->Value);
+ break;
+
+
+ case ACPI_TYPE_LOCAL_RESOURCE_FIELD:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Field Offset 0x%.4X Bits 0x%.4X Bytes] ",
+ Node->Value, Node->Value / 8);
+
+ if (Node->Flags & ANOBJ_IS_REFERENCED)
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ "Referenced");
+ }
+ else
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ "Name not referenced");
+ }
+ break;
+
+
+ default:
+ /* Nothing to do for other types */
+ break;
+ }
+ }
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: NsDoOnePathname
+ *
+ * PARAMETERS: ACPI_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Print the full pathname for a namespace node.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+NsDoOnePathname (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
+ ACPI_STATUS Status;
+ ACPI_BUFFER TargetPath;
+
+
+ TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ Status = AcpiNsHandleToPathname (Node, &TargetPath);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%s\n", TargetPath.Pointer);
+ ACPI_FREE (TargetPath.Pointer);
+
+ return (AE_OK);
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslopcodes.c b/sys/contrib/dev/acpica/compiler/aslopcodes.c
index 9f4ab42..ca358dc 100644
--- a/sys/contrib/dev/acpica/compiler/aslopcodes.c
+++ b/sys/contrib/dev/acpica/compiler/aslopcodes.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -802,6 +802,14 @@ OpcGenerateAmlOpcode (
Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
break;
+ case PARSEOP_TIMER:
+
+ if (AcpiGbl_IntegerBitWidth == 32)
+ {
+ AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
+ }
+ break;
+
default:
/* Nothing to do for other opcodes */
break;
diff --git a/sys/contrib/dev/acpica/compiler/asloperands.c b/sys/contrib/dev/acpica/compiler/asloperands.c
index 2427265..f773f6f 100644
--- a/sys/contrib/dev/acpica/compiler/asloperands.c
+++ b/sys/contrib/dev/acpica/compiler/asloperands.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslopt.c b/sys/contrib/dev/acpica/compiler/aslopt.c
index 244e46c..3471006 100644
--- a/sys/contrib/dev/acpica/compiler/aslopt.c
+++ b/sys/contrib/dev/acpica/compiler/aslopt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -305,7 +305,7 @@ OptBuildShortestPath (
for (i = 0; i < NumCarats; i++)
{
- NewPathExternal[i] = '^';
+ NewPathExternal[i] = AML_PARENT_PREFIX;
}
/*
@@ -329,7 +329,7 @@ OptBuildShortestPath (
if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
{
- NewPathExternal[i] = '^';
+ NewPathExternal[i] = AML_PARENT_PREFIX;
i++;
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
}
@@ -448,7 +448,7 @@ OptOptimizeNameDeclaration (
if (((CurrentNode == AcpiGbl_RootNode) ||
(Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) &&
- (AmlNameString[0] == '\\'))
+ (ACPI_IS_ROOT_PREFIX (AmlNameString[0])))
{
/*
* The current scope is the root, and the namepath has a root prefix
diff --git a/sys/contrib/dev/acpica/compiler/aslpredef.c b/sys/contrib/dev/acpica/compiler/aslpredef.c
index a5ebb83..dea0c83 100644
--- a/sys/contrib/dev/acpica/compiler/aslpredef.c
+++ b/sys/contrib/dev/acpica/compiler/aslpredef.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,6 +66,7 @@ ApCheckForSpecialName (
static void
ApCheckObjectType (
+ const char *PredefinedName,
ACPI_PARSE_OBJECT *Op,
UINT32 ExpectedBtypes);
@@ -383,7 +384,8 @@ ApCheckPredefinedReturnValue (
/* Static data return object - check against expected type */
- ApCheckObjectType (ReturnValueOp,
+ ApCheckObjectType (PredefinedNames[Index].Info.Name,
+ ReturnValueOp,
PredefinedNames[Index].Info.ExpectedBtypes);
break;
@@ -482,7 +484,8 @@ ApCheckForPredefinedObject (
/* Typecheck the actual object, it is the next argument */
- ApCheckObjectType (Op->Asl.Child->Asl.Next,
+ ApCheckObjectType (PredefinedNames[Index].Info.Name,
+ Op->Asl.Child->Asl.Next,
PredefinedNames[Index].Info.ExpectedBtypes);
return;
}
@@ -640,7 +643,8 @@ ApCheckForSpecialName (
*
* FUNCTION: ApCheckObjectType
*
- * PARAMETERS: Op - Current parse node
+ * PARAMETERS: PredefinedName - Name of the predefined object we are checking
+ * Op - Current parse node
* ExpectedBtypes - Bitmap of expected return type(s)
*
* RETURN: None
@@ -653,6 +657,7 @@ ApCheckForSpecialName (
static void
ApCheckObjectType (
+ const char *PredefinedName,
ACPI_PARSE_OBJECT *Op,
UINT32 ExpectedBtypes)
{
@@ -701,8 +706,8 @@ TypeErrorExit:
ApGetExpectedTypes (StringBuffer, ExpectedBtypes);
- sprintf (MsgBuffer, "found %s, requires %s",
- UtGetOpName (Op->Asl.ParseOpcode), StringBuffer);
+ sprintf (MsgBuffer, "%s: found %s, requires %s",
+ PredefinedName, UtGetOpName (Op->Asl.ParseOpcode), StringBuffer);
AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op,
MsgBuffer);
diff --git a/sys/contrib/dev/acpica/compiler/aslresource.c b/sys/contrib/dev/acpica/compiler/aslresource.c
index e0e582a..d809b73 100644
--- a/sys/contrib/dev/acpica/compiler/aslresource.c
+++ b/sys/contrib/dev/acpica/compiler/aslresource.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype1.c b/sys/contrib/dev/acpica/compiler/aslrestype1.c
index 3de2421..21a8705 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype1.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype1.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype1i.c b/sys/contrib/dev/acpica/compiler/aslrestype1i.c
index 77bdd91..3ec92aa 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype1i.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype1i.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2.c b/sys/contrib/dev/acpica/compiler/aslrestype2.c
index 4784f86..942d45e 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2d.c b/sys/contrib/dev/acpica/compiler/aslrestype2d.c
index 7836461..035b6ec 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2d.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2d.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2e.c b/sys/contrib/dev/acpica/compiler/aslrestype2e.c
index fe2f0d8..5621762 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2e.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2e.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2q.c b/sys/contrib/dev/acpica/compiler/aslrestype2q.c
index 70cfbd5..3a002a4 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2q.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2q.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2s.c b/sys/contrib/dev/acpica/compiler/aslrestype2s.c
index fa30b58..42d51a9 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2s.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2s.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2w.c b/sys/contrib/dev/acpica/compiler/aslrestype2w.c
index 613b7b3..be388b7 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2w.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2w.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslstartup.c b/sys/contrib/dev/acpica/compiler/aslstartup.c
index 3d50a21..8deb894 100644
--- a/sys/contrib/dev/acpica/compiler/aslstartup.c
+++ b/sys/contrib/dev/acpica/compiler/aslstartup.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -341,7 +341,7 @@ AslDoOneFile (
/* TBD: Handle additional output files for disassembler */
Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix);
- LsDisplayNamespace ();
+ NsDisplayNamespace ();
#endif
/* Shutdown compiler and ACPICA subsystem */
diff --git a/sys/contrib/dev/acpica/compiler/aslstubs.c b/sys/contrib/dev/acpica/compiler/aslstubs.c
index 8711441..9ac9698 100644
--- a/sys/contrib/dev/acpica/compiler/aslstubs.c
+++ b/sys/contrib/dev/acpica/compiler/aslstubs.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslsupport.l b/sys/contrib/dev/acpica/compiler/aslsupport.l
index daab402..90af049 100644
--- a/sys/contrib/dev/acpica/compiler/aslsupport.l
+++ b/sys/contrib/dev/acpica/compiler/aslsupport.l
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asltransform.c b/sys/contrib/dev/acpica/compiler/asltransform.c
index 7c8bfcd..7a29446 100644
--- a/sys/contrib/dev/acpica/compiler/asltransform.c
+++ b/sys/contrib/dev/acpica/compiler/asltransform.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asltree.c b/sys/contrib/dev/acpica/compiler/asltree.c
index 86e7f2d..8fa532b 100644
--- a/sys/contrib/dev/acpica/compiler/asltree.c
+++ b/sys/contrib/dev/acpica/compiler/asltree.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asltypes.h b/sys/contrib/dev/acpica/compiler/asltypes.h
index 0e3b16a..538911f 100644
--- a/sys/contrib/dev/acpica/compiler/asltypes.h
+++ b/sys/contrib/dev/acpica/compiler/asltypes.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslutils.c b/sys/contrib/dev/acpica/compiler/aslutils.c
index 32ab1c9..1a4a27d 100644
--- a/sys/contrib/dev/acpica/compiler/aslutils.c
+++ b/sys/contrib/dev/acpica/compiler/aslutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -826,7 +826,8 @@ UtAttachNameseg (
/* No dots in the namepath, there is only a single nameseg. */
/* Handle prefixes */
- while ((*Name == '\\') || (*Name == '^'))
+ while (ACPI_IS_ROOT_PREFIX (*Name) ||
+ ACPI_IS_PARENT_PREFIX (*Name))
{
Name++;
}
diff --git a/sys/contrib/dev/acpica/compiler/asluuid.c b/sys/contrib/dev/acpica/compiler/asluuid.c
index 485db6b..ed884dc 100644
--- a/sys/contrib/dev/acpica/compiler/asluuid.c
+++ b/sys/contrib/dev/acpica/compiler/asluuid.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslwalks.c b/sys/contrib/dev/acpica/compiler/aslwalks.c
index 77bff82..6613cac 100644
--- a/sys/contrib/dev/acpica/compiler/aslwalks.c
+++ b/sys/contrib/dev/acpica/compiler/aslwalks.c
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Module Name: aslwalks.c - major analytical parse tree walks
+ * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,575 +54,6 @@
/*******************************************************************************
*
- * FUNCTION: AnMethodAnalysisWalkBegin
- *
- * PARAMETERS: ASL_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
- * 1) Initialized local variables
- * 2) Valid arguments
- * 3) Return types
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AnMethodAnalysisWalkBegin (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context)
-{
- ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
- ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
- ACPI_PARSE_OBJECT *Next;
- UINT32 RegisterNumber;
- UINT32 i;
- char LocalName[] = "Local0";
- char ArgName[] = "Arg0";
- ACPI_PARSE_OBJECT *ArgNode;
- ACPI_PARSE_OBJECT *NextType;
- ACPI_PARSE_OBJECT *NextParamType;
- UINT8 ActualArgs = 0;
-
-
- switch (Op->Asl.ParseOpcode)
- {
- case PARSEOP_METHOD:
-
- TotalMethods++;
-
- /* Create and init method info */
-
- MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
- MethodInfo->Next = WalkInfo->MethodStack;
- MethodInfo->Op = Op;
-
- WalkInfo->MethodStack = MethodInfo;
-
- /* Get the name node, ignored here */
-
- Next = Op->Asl.Child;
-
- /* Get the NumArguments node */
-
- Next = Next->Asl.Next;
- MethodInfo->NumArguments = (UINT8)
- (((UINT8) Next->Asl.Value.Integer) & 0x07);
-
- /* Get the SerializeRule and SyncLevel nodes, ignored here */
-
- Next = Next->Asl.Next;
- Next = Next->Asl.Next;
- ArgNode = Next;
-
- /* Get the ReturnType node */
-
- Next = Next->Asl.Next;
-
- NextType = Next->Asl.Child;
- while (NextType)
- {
- /* Get and map each of the ReturnTypes */
-
- MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
- NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
- NextType = NextType->Asl.Next;
- }
-
- /* Get the ParameterType node */
-
- Next = Next->Asl.Next;
-
- NextType = Next->Asl.Child;
- while (NextType)
- {
- if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
- {
- NextParamType = NextType->Asl.Child;
- while (NextParamType)
- {
- MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
- NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
- NextParamType = NextParamType->Asl.Next;
- }
- }
- else
- {
- MethodInfo->ValidArgTypes[ActualArgs] =
- AnMapObjTypeToBtype (NextType);
- NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
- ActualArgs++;
- }
-
- NextType = NextType->Asl.Next;
- }
-
- if ((MethodInfo->NumArguments) &&
- (MethodInfo->NumArguments != ActualArgs))
- {
- /* error: Param list did not match number of args */
- }
-
- /* Allow numarguments == 0 for Function() */
-
- if ((!MethodInfo->NumArguments) && (ActualArgs))
- {
- MethodInfo->NumArguments = ActualArgs;
- ArgNode->Asl.Value.Integer |= ActualArgs;
- }
-
- /*
- * Actual arguments are initialized at method entry.
- * All other ArgX "registers" can be used as locals, so we
- * track their initialization.
- */
- for (i = 0; i < MethodInfo->NumArguments; i++)
- {
- MethodInfo->ArgInitialized[i] = TRUE;
- }
- break;
-
-
- case PARSEOP_METHODCALL:
-
- if (MethodInfo &&
- (Op->Asl.Node == MethodInfo->Op->Asl.Node))
- {
- AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
- }
- break;
-
-
- case PARSEOP_LOCAL0:
- case PARSEOP_LOCAL1:
- case PARSEOP_LOCAL2:
- case PARSEOP_LOCAL3:
- case PARSEOP_LOCAL4:
- case PARSEOP_LOCAL5:
- case PARSEOP_LOCAL6:
- case PARSEOP_LOCAL7:
-
- if (!MethodInfo)
- {
- /*
- * Local was used outside a control method, or there was an error
- * in the method declaration.
- */
- AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
- return (AE_ERROR);
- }
-
- RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
-
- /*
- * If the local is being used as a target, mark the local
- * initialized
- */
- if (Op->Asl.CompileFlags & NODE_IS_TARGET)
- {
- MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
- }
-
- /*
- * Otherwise, this is a reference, check if the local
- * has been previously initialized.
- *
- * The only operator that accepts an uninitialized value is ObjectType()
- */
- else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
- (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
- {
- LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
- AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
- }
- break;
-
-
- case PARSEOP_ARG0:
- case PARSEOP_ARG1:
- case PARSEOP_ARG2:
- case PARSEOP_ARG3:
- case PARSEOP_ARG4:
- case PARSEOP_ARG5:
- case PARSEOP_ARG6:
-
- if (!MethodInfo)
- {
- /*
- * Arg was used outside a control method, or there was an error
- * in the method declaration.
- */
- AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
- return (AE_ERROR);
- }
-
- RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
- ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
-
- /*
- * If the Arg is being used as a target, mark the local
- * initialized
- */
- if (Op->Asl.CompileFlags & NODE_IS_TARGET)
- {
- MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
- }
-
- /*
- * Otherwise, this is a reference, check if the Arg
- * has been previously initialized.
- *
- * The only operator that accepts an uninitialized value is ObjectType()
- */
- else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
- (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
- {
- AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
- }
-
- /* Flag this arg if it is not a "real" argument to the method */
-
- if (RegisterNumber >= MethodInfo->NumArguments)
- {
- AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
- }
- break;
-
-
- case PARSEOP_RETURN:
-
- if (!MethodInfo)
- {
- /*
- * Probably was an error in the method declaration,
- * no additional error here
- */
- ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
- return (AE_ERROR);
- }
-
- /*
- * A child indicates a possible return value. A simple Return or
- * Return() is marked with NODE_IS_NULL_RETURN by the parser so
- * that it is not counted as a "real" return-with-value, although
- * the AML code that is actually emitted is Return(0). The AML
- * definition of Return has a required parameter, so we are
- * forced to convert a null return to Return(0).
- */
- if ((Op->Asl.Child) &&
- (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
- {
- MethodInfo->NumReturnWithValue++;
- }
- else
- {
- MethodInfo->NumReturnNoValue++;
- }
- break;
-
-
- case PARSEOP_BREAK:
- case PARSEOP_CONTINUE:
-
- Next = Op->Asl.Parent;
- while (Next)
- {
- if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
- {
- break;
- }
- Next = Next->Asl.Parent;
- }
-
- if (!Next)
- {
- AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
- }
- break;
-
-
- case PARSEOP_STALL:
-
- /* We can range check if the argument is an integer */
-
- if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
- (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
- {
- AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
- }
- break;
-
-
- case PARSEOP_DEVICE:
- case PARSEOP_EVENT:
- case PARSEOP_MUTEX:
- case PARSEOP_OPERATIONREGION:
- case PARSEOP_POWERRESOURCE:
- case PARSEOP_PROCESSOR:
- case PARSEOP_THERMALZONE:
-
- /*
- * The first operand is a name to be created in the namespace.
- * Check against the reserved list.
- */
- i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
- if (i < ACPI_VALID_RESERVED_NAME_MAX)
- {
- AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
- }
- break;
-
-
- case PARSEOP_NAME:
-
- /* Typecheck any predefined names statically defined with Name() */
-
- ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
-
- /* Special typechecking for _HID */
-
- if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
- {
- Next = Op->Asl.Child->Asl.Next;
- AnCheckId (Next, ASL_TYPE_HID);
- }
-
- /* Special typechecking for _CID */
-
- else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
- {
- Next = Op->Asl.Child->Asl.Next;
-
- if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
- (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
- {
- Next = Next->Asl.Child;
- while (Next)
- {
- AnCheckId (Next, ASL_TYPE_CID);
- Next = Next->Asl.Next;
- }
- }
- else
- {
- AnCheckId (Next, ASL_TYPE_CID);
- }
- }
- break;
-
-
- default:
- break;
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AnMethodAnalysisWalkEnd
- *
- * PARAMETERS: ASL_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Ascending callback for analysis walk. Complete method
- * return analysis.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AnMethodAnalysisWalkEnd (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context)
-{
- ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
- ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
-
-
- switch (Op->Asl.ParseOpcode)
- {
- case PARSEOP_METHOD:
- case PARSEOP_RETURN:
- if (!MethodInfo)
- {
- printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
- AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
- "No method info for this method");
-
- CmCleanupAndExit ();
- return (AE_AML_INTERNAL);
- }
- break;
-
- default:
- break;
- }
-
- switch (Op->Asl.ParseOpcode)
- {
- case PARSEOP_METHOD:
-
- WalkInfo->MethodStack = MethodInfo->Next;
-
- /*
- * Check if there is no return statement at the end of the
- * method AND we can actually get there -- i.e., the execution
- * of the method can possibly terminate without a return statement.
- */
- if ((!AnLastStatementIsReturn (Op)) &&
- (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
- {
- /*
- * No return statement, and execution can possibly exit
- * via this path. This is equivalent to Return ()
- */
- MethodInfo->NumReturnNoValue++;
- }
-
- /*
- * Check for case where some return statements have a return value
- * and some do not. Exit without a return statement is a return with
- * no value
- */
- if (MethodInfo->NumReturnNoValue &&
- MethodInfo->NumReturnWithValue)
- {
- AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
- Op->Asl.ExternalName);
- }
-
- /*
- * If there are any RETURN() statements with no value, or there is a
- * control path that allows the method to exit without a return value,
- * we mark the method as a method that does not return a value. This
- * knowledge can be used to check method invocations that expect a
- * returned value.
- */
- if (MethodInfo->NumReturnNoValue)
- {
- if (MethodInfo->NumReturnWithValue)
- {
- Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
- }
- else
- {
- Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
- }
- }
-
- /*
- * Check predefined method names for correct return behavior
- * and correct number of arguments. Also, some special checks
- * For GPE and _REG methods.
- */
- if (ApCheckForPredefinedMethod (Op, MethodInfo))
- {
- /* Special check for two names like _L01 and _E01 in same scope */
-
- ApCheckForGpeNameConflict (Op);
-
- /*
- * Special check for _REG: Must have an operation region definition
- * within the same scope!
- */
- ApCheckRegMethod (Op);
- }
-
- ACPI_FREE (MethodInfo);
- break;
-
-
- case PARSEOP_NAME:
-
- /* Special check for two names like _L01 and _E01 in same scope */
-
- ApCheckForGpeNameConflict (Op);
- break;
-
-
- case PARSEOP_RETURN:
-
- /*
- * If the parent is a predefined method name, attempt to typecheck
- * the return value. Only static types can be validated.
- */
- ApCheckPredefinedReturnValue (Op, MethodInfo);
-
- /*
- * The parent block does not "exit" and continue execution -- the
- * method is terminated here with the Return() statement.
- */
- Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
-
- /* Used in the "typing" pass later */
-
- Op->Asl.ParentMethod = MethodInfo->Op;
-
- /*
- * If there is a peer node after the return statement, then this
- * node is unreachable code -- i.e., it won't be executed because of
- * the preceding Return() statement.
- */
- if (Op->Asl.Next)
- {
- AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
- }
- break;
-
-
- case PARSEOP_IF:
-
- if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
- (Op->Asl.Next) &&
- (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
- {
- /*
- * This IF has a corresponding ELSE. The IF block has no exit,
- * (it contains an unconditional Return)
- * mark the ELSE block to remember this fact.
- */
- Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
- }
- break;
-
-
- case PARSEOP_ELSE:
-
- if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
- (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
- {
- /*
- * This ELSE block has no exit and the corresponding IF block
- * has no exit either. Therefore, the parent node has no exit.
- */
- Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
- }
- break;
-
-
- default:
-
- if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
- (Op->Asl.Parent))
- {
- /* If this node has no exit, then the parent has no exit either */
-
- Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
- }
- break;
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AnMethodTypingWalkEnd
*
* PARAMETERS: ASL_WALK_CALLBACK
diff --git a/sys/contrib/dev/acpica/compiler/aslxref.c b/sys/contrib/dev/acpica/compiler/aslxref.c
new file mode 100644
index 0000000..188c214
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslxref.c
@@ -0,0 +1,874 @@
+/******************************************************************************
+ *
+ * Module Name: aslxref - Namespace cross-reference
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+#include <contrib/dev/acpica/include/acparser.h>
+#include <contrib/dev/acpica/include/amlcode.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+#include <contrib/dev/acpica/include/acdispat.h>
+
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslxref")
+
+/* Local prototypes */
+
+static ACPI_STATUS
+XfNamespaceLocateBegin (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context);
+
+static ACPI_STATUS
+XfNamespaceLocateEnd (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context);
+
+static BOOLEAN
+XfObjectExists (
+ char *Name);
+
+static ACPI_STATUS
+XfCompareOneNamespaceObject (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+static void
+XfCheckFieldRange (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 RegionBitLength,
+ UINT32 FieldBitOffset,
+ UINT32 FieldBitLength,
+ UINT32 AccessBitWidth);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfCrossReferenceNamespace
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform a cross reference check of the parse tree against the
+ * namespace. Every named referenced within the parse tree
+ * should be get resolved with a namespace lookup. If not, the
+ * original reference in the ASL code is invalid -- i.e., refers
+ * to a non-existent object.
+ *
+ * NOTE: The ASL "External" operator causes the name to be inserted into the
+ * namespace so that references to the external name will be resolved
+ * correctly here.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+XfCrossReferenceNamespace (
+ void)
+{
+ ACPI_WALK_STATE *WalkState;
+
+
+ DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n");
+
+ /*
+ * Create a new walk state for use when looking up names
+ * within the namespace (Passed as context to the callbacks)
+ */
+ WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
+ if (!WalkState)
+ {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Walk the entire parse tree */
+
+ TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, XfNamespaceLocateBegin,
+ XfNamespaceLocateEnd, WalkState);
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfObjectExists
+ *
+ * PARAMETERS: Name - 4 char ACPI name
+ *
+ * RETURN: TRUE if name exists in namespace
+ *
+ * DESCRIPTION: Walk the namespace to find an object
+ *
+ ******************************************************************************/
+
+static BOOLEAN
+XfObjectExists (
+ char *Name)
+{
+ ACPI_STATUS Status;
+
+
+ /* Walk entire namespace from the supplied root */
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL,
+ Name, NULL);
+ if (Status == AE_CTRL_TRUE)
+ {
+ /* At least one instance of the name was found */
+
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfCompareOneNamespaceObject
+ *
+ * PARAMETERS: ACPI_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Compare name of one object.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+XfCompareOneNamespaceObject (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
+
+
+ /* Simply check the name */
+
+ if (*((UINT32 *) (Context)) == Node->Name.Integer)
+ {
+ /* Abort walk if we found one instance */
+
+ return (AE_CTRL_TRUE);
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfCheckFieldRange
+ *
+ * PARAMETERS: RegionBitLength - Length of entire parent region
+ * FieldBitOffset - Start of the field unit (within region)
+ * FieldBitLength - Entire length of field unit
+ * AccessBitWidth - Access width of the field unit
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Check one field unit to make sure it fits in the parent
+ * op region.
+ *
+ * Note: AccessBitWidth must be either 8,16,32, or 64
+ *
+ ******************************************************************************/
+
+static void
+XfCheckFieldRange (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 RegionBitLength,
+ UINT32 FieldBitOffset,
+ UINT32 FieldBitLength,
+ UINT32 AccessBitWidth)
+{
+ UINT32 FieldEndBitOffset;
+
+
+ /*
+ * Check each field unit against the region size. The entire
+ * field unit (start offset plus length) must fit within the
+ * region.
+ */
+ FieldEndBitOffset = FieldBitOffset + FieldBitLength;
+
+ if (FieldEndBitOffset > RegionBitLength)
+ {
+ /* Field definition itself is beyond the end-of-region */
+
+ AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
+ return;
+ }
+
+ /*
+ * Now check that the field plus AccessWidth doesn't go beyond
+ * the end-of-region. Assumes AccessBitWidth is a power of 2
+ */
+ FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
+
+ if (FieldEndBitOffset > RegionBitLength)
+ {
+ /* Field definition combined with the access is beyond EOR */
+
+ AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfNamespaceLocateBegin
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback used during cross-reference. For named
+ * object references, attempt to locate the name in the
+ * namespace.
+ *
+ * NOTE: ASL references to named fields within resource descriptors are
+ * resolved to integer values here. Therefore, this step is an
+ * important part of the code generation. We don't know that the
+ * name refers to a resource descriptor until now.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+XfNamespaceLocateBegin (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
+ ACPI_NAMESPACE_NODE *Node;
+ ACPI_STATUS Status;
+ ACPI_OBJECT_TYPE ObjectType;
+ char *Path;
+ UINT8 PassedArgs;
+ ACPI_PARSE_OBJECT *NextOp;
+ ACPI_PARSE_OBJECT *OwningOp;
+ ACPI_PARSE_OBJECT *SpaceIdOp;
+ UINT32 MinimumLength;
+ UINT32 Offset;
+ UINT32 FieldBitLength;
+ UINT32 TagBitLength;
+ UINT8 Message = 0;
+ const ACPI_OPCODE_INFO *OpInfo;
+ UINT32 Flags;
+
+
+ ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);
+
+ /*
+ * If this node is the actual declaration of a name
+ * [such as the XXXX name in "Method (XXXX)"],
+ * we are not interested in it here. We only care about names that are
+ * references to other objects within the namespace and the parent objects
+ * of name declarations
+ */
+ if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
+ {
+ return (AE_OK);
+ }
+
+ /* We are only interested in opcodes that have an associated name */
+
+ OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
+
+ if ((!(OpInfo->Flags & AML_NAMED)) &&
+ (!(OpInfo->Flags & AML_CREATE)) &&
+ (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
+ (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
+ (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * One special case: CondRefOf operator - we don't care if the name exists
+ * or not at this point, just ignore it, the point of the operator is to
+ * determine if the name exists at runtime.
+ */
+ if ((Op->Asl.Parent) &&
+ (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * We must enable the "search-to-root" for single NameSegs, but
+ * we have to be very careful about opening up scopes
+ */
+ Flags = ACPI_NS_SEARCH_PARENT;
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
+ {
+ /*
+ * These are name references, do not push the scope stack
+ * for them.
+ */
+ Flags |= ACPI_NS_DONT_OPEN_SCOPE;
+ }
+
+ /* Get the NamePath from the appropriate place */
+
+ if (OpInfo->Flags & AML_NAMED)
+ {
+ /* For nearly all NAMED operators, the name reference is the first child */
+
+ Path = Op->Asl.Child->Asl.Value.String;
+ if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
+ {
+ /*
+ * ALIAS is the only oddball opcode, the name declaration
+ * (alias name) is the second operand
+ */
+ Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
+ }
+ }
+ else if (OpInfo->Flags & AML_CREATE)
+ {
+ /* Name must appear as the last parameter */
+
+ NextOp = Op->Asl.Child;
+ while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
+ {
+ NextOp = NextOp->Asl.Next;
+ }
+ Path = NextOp->Asl.Value.String;
+ }
+ else
+ {
+ Path = Op->Asl.Value.String;
+ }
+
+ ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
+
+ /*
+ * Lookup the name in the namespace. Name must exist at this point, or it
+ * is an invalid reference.
+ *
+ * The namespace is also used as a lookup table for references to resource
+ * descriptors and the fields within them.
+ */
+ Gbl_NsLookupCount++;
+
+ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
+ ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
+ if (ACPI_FAILURE (Status))
+ {
+ if (Status == AE_NOT_FOUND)
+ {
+ /*
+ * We didn't find the name reference by path -- we can qualify this
+ * a little better before we print an error message
+ */
+ if (strlen (Path) == ACPI_NAME_SIZE)
+ {
+ /* A simple, one-segment ACPI name */
+
+ if (XfObjectExists (Path))
+ {
+ /*
+ * There exists such a name, but we couldn't get to it
+ * from this scope
+ */
+ AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
+ Op->Asl.ExternalName);
+ }
+ else
+ {
+ /* The name doesn't exist, period */
+
+ AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
+ Op, Op->Asl.ExternalName);
+ }
+ }
+ else
+ {
+ /* Check for a fully qualified path */
+
+ if (Path[0] == AML_ROOT_PREFIX)
+ {
+ /* Gave full path, the object does not exist */
+
+ AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
+ Op->Asl.ExternalName);
+ }
+ else
+ {
+ /*
+ * We can't tell whether it doesn't exist or just
+ * can't be reached.
+ */
+ AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
+ Op->Asl.ExternalName);
+ }
+ }
+
+ Status = AE_OK;
+ }
+ return (Status);
+ }
+
+ /* Check for a reference vs. name declaration */
+
+ if (!(OpInfo->Flags & AML_NAMED) &&
+ !(OpInfo->Flags & AML_CREATE))
+ {
+ /* This node has been referenced, mark it for reference check */
+
+ Node->Flags |= ANOBJ_IS_REFERENCED;
+ }
+
+ /* Attempt to optimize the NamePath */
+
+ OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
+
+ /*
+ * 1) Dereference an alias (A name reference that is an alias)
+ * Aliases are not nested, the alias always points to the final object
+ */
+ if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
+ (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
+ {
+ /* This node points back to the original PARSEOP_ALIAS */
+
+ NextOp = Node->Op;
+
+ /* The first child is the alias target op */
+
+ NextOp = NextOp->Asl.Child;
+
+ /* That in turn points back to original target alias node */
+
+ if (NextOp->Asl.Node)
+ {
+ Node = NextOp->Asl.Node;
+ }
+
+ /* Else - forward reference to alias, will be resolved later */
+ }
+
+ /* 2) Check for a reference to a resource descriptor */
+
+ if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
+ (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
+ {
+ /*
+ * This was a reference to a field within a resource descriptor.
+ * Extract the associated field offset (either a bit or byte
+ * offset depending on the field type) and change the named
+ * reference into an integer for AML code generation
+ */
+ Offset = Node->Value;
+ TagBitLength = Node->Length;
+
+ /*
+ * If a field is being created, generate the length (in bits) of
+ * the field. Note: Opcodes other than CreateXxxField and Index
+ * can come through here. For other opcodes, we just need to
+ * convert the resource tag reference to an integer offset.
+ */
+ switch (Op->Asl.Parent->Asl.AmlOpcode)
+ {
+ case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
+ /*
+ * We know the length operand is an integer constant because
+ * we know that it contains a reference to a resource
+ * descriptor tag.
+ */
+ FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
+ break;
+
+ case AML_CREATE_BIT_FIELD_OP:
+ FieldBitLength = 1;
+ break;
+
+ case AML_CREATE_BYTE_FIELD_OP:
+ case AML_INDEX_OP:
+ FieldBitLength = 8;
+ break;
+
+ case AML_CREATE_WORD_FIELD_OP:
+ FieldBitLength = 16;
+ break;
+
+ case AML_CREATE_DWORD_FIELD_OP:
+ FieldBitLength = 32;
+ break;
+
+ case AML_CREATE_QWORD_FIELD_OP:
+ FieldBitLength = 64;
+ break;
+
+ default:
+ FieldBitLength = 0;
+ break;
+ }
+
+ /* Check the field length against the length of the resource tag */
+
+ if (FieldBitLength)
+ {
+ if (TagBitLength < FieldBitLength)
+ {
+ Message = ASL_MSG_TAG_SMALLER;
+ }
+ else if (TagBitLength > FieldBitLength)
+ {
+ Message = ASL_MSG_TAG_LARGER;
+ }
+
+ if (Message)
+ {
+ sprintf (MsgBuffer, "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
+ TagBitLength, (TagBitLength > 1) ? "s" : "",
+ FieldBitLength, (FieldBitLength > 1) ? "s" : "");
+
+ AslError (ASL_WARNING, Message, Op, MsgBuffer);
+ }
+ }
+
+ /* Convert the BitOffset to a ByteOffset for certain opcodes */
+
+ switch (Op->Asl.Parent->Asl.AmlOpcode)
+ {
+ case AML_CREATE_BYTE_FIELD_OP:
+ case AML_CREATE_WORD_FIELD_OP:
+ case AML_CREATE_DWORD_FIELD_OP:
+ case AML_CREATE_QWORD_FIELD_OP:
+ case AML_INDEX_OP:
+
+ Offset = ACPI_DIV_8 (Offset);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Now convert this node to an integer whose value is the field offset */
+
+ Op->Asl.AmlLength = 0;
+ Op->Asl.ParseOpcode = PARSEOP_INTEGER;
+ Op->Asl.Value.Integer = (UINT64) Offset;
+ Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
+
+ OpcGenerateAmlOpcode (Op);
+ }
+
+ /* 3) Check for a method invocation */
+
+ else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
+ (Node->Type == ACPI_TYPE_METHOD) &&
+ (Op->Asl.Parent) &&
+ (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) ||
+
+ (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
+ {
+
+ /*
+ * A reference to a method within one of these opcodes is not an
+ * invocation of the method, it is simply a reference to the method.
+ */
+ if ((Op->Asl.Parent) &&
+ ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) ||
+ (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) ||
+ (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
+ {
+ return (AE_OK);
+ }
+ /*
+ * There are two types of method invocation:
+ * 1) Invocation with arguments -- the parser recognizes this
+ * as a METHODCALL.
+ * 2) Invocation with no arguments --the parser cannot determine that
+ * this is a method invocation, therefore we have to figure it out
+ * here.
+ */
+ if (Node->Type != ACPI_TYPE_METHOD)
+ {
+ sprintf (MsgBuffer, "%s is a %s",
+ Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
+
+ AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
+ return (AE_OK);
+ }
+
+ /* Save the method node in the caller's op */
+
+ Op->Asl.Node = Node;
+ if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * This is a method invocation, with or without arguments.
+ * Count the number of arguments, each appears as a child
+ * under the parent node
+ */
+ Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
+ UtSetParseOpName (Op);
+
+ PassedArgs = 0;
+ NextOp = Op->Asl.Child;
+
+ while (NextOp)
+ {
+ PassedArgs++;
+ NextOp = NextOp->Asl.Next;
+ }
+
+ if (Node->Value != ASL_EXTERNAL_METHOD)
+ {
+ /*
+ * Check the parsed arguments with the number expected by the
+ * method declaration itself
+ */
+ if (PassedArgs != Node->Value)
+ {
+ sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName,
+ Node->Value);
+
+ if (PassedArgs < Node->Value)
+ {
+ AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
+ }
+ else
+ {
+ AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
+ }
+ }
+ }
+ }
+
+ /* 4) Check for an ASL Field definition */
+
+ else if ((Op->Asl.Parent) &&
+ ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) ||
+ (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
+ {
+ /*
+ * Offset checking for fields. If the parent operation region has a
+ * constant length (known at compile time), we can check fields
+ * defined in that region against the region length. This will catch
+ * fields and field units that cannot possibly fit within the region.
+ *
+ * Note: Index fields do not directly reference an operation region,
+ * thus they are not included in this check.
+ */
+ if (Op == Op->Asl.Parent->Asl.Child)
+ {
+ /*
+ * This is the first child of the field node, which is
+ * the name of the region. Get the parse node for the
+ * region -- which contains the length of the region.
+ */
+ OwningOp = Node->Op;
+ Op->Asl.Parent->Asl.ExtraValue =
+ ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
+
+ /* Examine the field access width */
+
+ switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
+ {
+ case AML_FIELD_ACCESS_ANY:
+ case AML_FIELD_ACCESS_BYTE:
+ case AML_FIELD_ACCESS_BUFFER:
+ default:
+ MinimumLength = 1;
+ break;
+
+ case AML_FIELD_ACCESS_WORD:
+ MinimumLength = 2;
+ break;
+
+ case AML_FIELD_ACCESS_DWORD:
+ MinimumLength = 4;
+ break;
+
+ case AML_FIELD_ACCESS_QWORD:
+ MinimumLength = 8;
+ break;
+ }
+
+ /*
+ * Is the region at least as big as the access width?
+ * Note: DataTableRegions have 0 length
+ */
+ if (((UINT32) OwningOp->Asl.Value.Integer) &&
+ ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
+ {
+ AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
+ }
+
+ /*
+ * Check EC/CMOS/SMBUS fields to make sure that the correct
+ * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
+ */
+ SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
+ switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
+ {
+ case ACPI_ADR_SPACE_EC:
+ case ACPI_ADR_SPACE_CMOS:
+ case ACPI_ADR_SPACE_GPIO:
+
+ if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
+ {
+ AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
+ }
+ break;
+
+ case ACPI_ADR_SPACE_SMBUS:
+ case ACPI_ADR_SPACE_IPMI:
+ case ACPI_ADR_SPACE_GSBUS:
+
+ if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
+ {
+ AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
+ }
+ break;
+
+ default:
+
+ /* Nothing to do for other address spaces */
+ break;
+ }
+ }
+ else
+ {
+ /*
+ * This is one element of the field list. Check to make sure
+ * that it does not go beyond the end of the parent operation region.
+ *
+ * In the code below:
+ * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits)
+ * Op->Asl.ExtraValue - Field start offset (bits)
+ * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits)
+ * Op->Asl.Child->Asl.ExtraValue - Field access width (bits)
+ */
+ if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
+ {
+ XfCheckFieldRange (Op,
+ Op->Asl.Parent->Asl.ExtraValue,
+ Op->Asl.ExtraValue,
+ (UINT32) Op->Asl.Child->Asl.Value.Integer,
+ Op->Asl.Child->Asl.ExtraValue);
+ }
+ }
+ }
+
+ Op->Asl.Node = Node;
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfNamespaceLocateEnd
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback used during cross reference. We only
+ * need to worry about scope management here.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+XfNamespaceLocateEnd (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
+ const ACPI_OPCODE_INFO *OpInfo;
+
+
+ ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);
+
+
+ /* We are only interested in opcodes that have an associated name */
+
+ OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
+ if (!(OpInfo->Flags & AML_NAMED))
+ {
+ return (AE_OK);
+ }
+
+ /* Not interested in name references, we did not open a scope for them */
+
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
+ {
+ return (AE_OK);
+ }
+
+ /* Pop the scope stack if necessary */
+
+ if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
+ {
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "%s: Popping scope for Op %p\n",
+ AcpiUtGetTypeName (OpInfo->ObjectType), Op));
+
+ (void) AcpiDsScopeStackPop (WalkState);
+ }
+
+ return (AE_OK);
+}
diff --git a/sys/contrib/dev/acpica/compiler/dtcompile.c b/sys/contrib/dev/acpica/compiler/dtcompile.c
index 210b70c..1b24af26 100644
--- a/sys/contrib/dev/acpica/compiler/dtcompile.c
+++ b/sys/contrib/dev/acpica/compiler/dtcompile.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -165,7 +165,7 @@ DtDoCompile (
/* Write the binary, then the optional hex file */
DtOutputBinary (Gbl_RootTable);
- LsDoHexOutput ();
+ HxDoHexOutput ();
DtWriteTableToListing ();
CleanupAndExit:
@@ -284,6 +284,7 @@ DtCompileDataTable (
char *Signature;
ACPI_TABLE_HEADER *AcpiTableHeader;
ACPI_STATUS Status;
+ DT_FIELD *RootField = *FieldList;
/* Verify that we at least have a table signature and save it */
@@ -354,7 +355,7 @@ DtCompileDataTable (
if (!TableData || Gbl_CompileGeneric)
{
DtCompileGeneric ((void **) FieldList);
- goto Out;
+ goto FinishHeader;
}
/* Dispatch to per-table compile */
@@ -391,7 +392,8 @@ DtCompileDataTable (
return (AE_ERROR);
}
-Out:
+FinishHeader:
+
/* Set the final table length and then the checksum */
DtSetTableLength ();
@@ -399,6 +401,8 @@ Out:
ACPI_TABLE_HEADER, Gbl_RootTable->Buffer);
DtSetTableChecksum (&AcpiTableHeader->Checksum);
+ DtDumpFieldList (RootField);
+ DtDumpSubtableList ();
return (AE_OK);
}
diff --git a/sys/contrib/dev/acpica/compiler/dtcompiler.h b/sys/contrib/dev/acpica/compiler/dtcompiler.h
index 22d1805..e9bdf05 100644
--- a/sys/contrib/dev/acpica/compiler/dtcompiler.h
+++ b/sys/contrib/dev/acpica/compiler/dtcompiler.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -113,6 +113,7 @@ typedef struct dt_subtable
UINT32 Length;
UINT32 TotalLength;
UINT32 SizeOfLengthField;
+ UINT16 Depth;
UINT8 Flags;
} DT_SUBTABLE;
@@ -168,6 +169,14 @@ DtOutputBinary (
DT_SUBTABLE *RootTable);
void
+DtDumpSubtableList (
+ void);
+
+void
+DtDumpFieldList (
+ DT_FIELD *Field);
+
+void
DtWriteFieldToListing (
UINT8 *Buffer,
DT_FIELD *Field,
@@ -387,6 +396,10 @@ DtCompileCpep (
void **PFieldList);
ACPI_STATUS
+DtCompileCsrt (
+ void **PFieldList);
+
+ACPI_STATUS
DtCompileDmar (
void **PFieldList);
@@ -481,6 +494,7 @@ extern const unsigned char TemplateBoot[];
extern const unsigned char TemplateBert[];
extern const unsigned char TemplateBgrt[];
extern const unsigned char TemplateCpep[];
+extern const unsigned char TemplateCsrt[];
extern const unsigned char TemplateDbgp[];
extern const unsigned char TemplateDmar[];
extern const unsigned char TemplateEcdt[];
@@ -507,6 +521,7 @@ extern const unsigned char TemplateSpcr[];
extern const unsigned char TemplateSpmi[];
extern const unsigned char TemplateSrat[];
extern const unsigned char TemplateTcpa[];
+extern const unsigned char TemplateTpm2[];
extern const unsigned char TemplateUefi[];
extern const unsigned char TemplateWaet[];
extern const unsigned char TemplateWdat[];
diff --git a/sys/contrib/dev/acpica/compiler/dtexpress.c b/sys/contrib/dev/acpica/compiler/dtexpress.c
index f0a1c8e..1c6ed3f 100644
--- a/sys/contrib/dev/acpica/compiler/dtexpress.c
+++ b/sys/contrib/dev/acpica/compiler/dtexpress.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dtfield.c b/sys/contrib/dev/acpica/compiler/dtfield.c
index 6bfa649..11e443e 100644
--- a/sys/contrib/dev/acpica/compiler/dtfield.c
+++ b/sys/contrib/dev/acpica/compiler/dtfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dtio.c b/sys/contrib/dev/acpica/compiler/dtio.c
index 5f70a19..f3d5359 100644
--- a/sys/contrib/dev/acpica/compiler/dtio.c
+++ b/sys/contrib/dev/acpica/compiler/dtio.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -79,6 +79,18 @@ DtDumpBuffer (
UINT32 Offset,
UINT32 Length);
+static void
+DtDumpSubtableInfo (
+ DT_SUBTABLE *Subtable,
+ void *Context,
+ void *ReturnValue);
+
+static void
+DtDumpSubtableTree (
+ DT_SUBTABLE *Subtable,
+ void *Context,
+ void *ReturnValue);
+
/* States for DtGetNextLine */
@@ -708,7 +720,6 @@ DtScanFile (
{
ACPI_STATUS Status;
UINT32 Offset;
- DT_FIELD *Next;
ACPI_FUNCTION_NAME (DtScanFile);
@@ -738,28 +749,7 @@ DtScanFile (
/* Dump the parse tree if debug enabled */
- if (Gbl_DebugFlag)
- {
- Next = Gbl_FieldList;
- DbgPrint (ASL_DEBUG_OUTPUT, "Tree: %32s %32s %8s %8s %8s %8s %8s %8s\n\n",
- "Name", "Value", "Line", "ByteOff", "NameCol", "Column", "TableOff", "Flags");
-
- while (Next)
- {
- DbgPrint (ASL_DEBUG_OUTPUT, "Field: %32.32s %32.32s %.8X %.8X %.8X %.8X %.8X %.8X\n",
- Next->Name,
- Next->Value,
- Next->Line,
- Next->ByteOffset,
- Next->NameColumn,
- Next->Column,
- Next->TableOffset,
- Next->Flags);
-
- Next = Next->Next;
- }
- }
-
+ DtDumpFieldList (Gbl_FieldList);
return (Gbl_FieldList);
}
@@ -913,6 +903,123 @@ DtDumpBuffer (
/******************************************************************************
*
+ * FUNCTION: DtDumpFieldList
+ *
+ * PARAMETERS: Field - Root field
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump the entire field list
+ *
+ *****************************************************************************/
+
+void
+DtDumpFieldList (
+ DT_FIELD *Field)
+{
+
+ if (!Gbl_DebugFlag || !Field)
+ {
+ return;
+ }
+
+ DbgPrint (ASL_DEBUG_OUTPUT, "\nField List:\n"
+ "LineNo ByteOff NameCol Column TableOff "
+ "Flags %32s : %s\n\n", "Name", "Value");
+ while (Field)
+ {
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "%.08X %.08X %.08X %.08X %.08X %.08X %32s : %s\n",
+ Field->Line, Field->ByteOffset, Field->NameColumn,
+ Field->Column, Field->TableOffset, Field->Flags,
+ Field->Name, Field->Value);
+
+ Field = Field->Next;
+ }
+
+ DbgPrint (ASL_DEBUG_OUTPUT, "\n\n");
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: DtDumpSubtableInfo, DtDumpSubtableTree
+ *
+ * PARAMETERS: DT_WALK_CALLBACK
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Info - dump a subtable tree entry with extra information.
+ * Tree - dump a subtable tree formatted by depth indentation.
+ *
+ *****************************************************************************/
+
+static void
+DtDumpSubtableInfo (
+ DT_SUBTABLE *Subtable,
+ void *Context,
+ void *ReturnValue)
+{
+
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "[%.04X] %.08X %.08X %.08X %.08X %.08X %p %p %p\n",
+ Subtable->Depth, Subtable->Length, Subtable->TotalLength,
+ Subtable->SizeOfLengthField, Subtable->Flags, Subtable,
+ Subtable->Parent, Subtable->Child, Subtable->Peer);
+}
+
+static void
+DtDumpSubtableTree (
+ DT_SUBTABLE *Subtable,
+ void *Context,
+ void *ReturnValue)
+{
+
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "[%.04X] %*s%08X (%.02X) - (%.02X)\n",
+ Subtable->Depth, (4 * Subtable->Depth), " ",
+ Subtable, Subtable->Length, Subtable->TotalLength);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: DtDumpSubtableList
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump the raw list of subtables with information, and also
+ * dump the subtable list in formatted tree format. Assists with
+ * the development of new table code.
+ *
+ *****************************************************************************/
+
+void
+DtDumpSubtableList (
+ void)
+{
+
+ if (!Gbl_DebugFlag || !Gbl_RootTable)
+ {
+ return;
+ }
+
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "Subtable Info:\n"
+ "Depth Length TotalLen LenSize Flags "
+ "This Parent Child Peer\n\n");
+ DtWalkTableTree (Gbl_RootTable, DtDumpSubtableInfo, NULL, NULL);
+
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "\nSubtable Tree: (Depth, Subtable, Length, TotalLength)\n\n");
+ DtWalkTableTree (Gbl_RootTable, DtDumpSubtableTree, NULL, NULL);
+}
+
+
+/******************************************************************************
+ *
* FUNCTION: DtWriteFieldToListing
*
* PARAMETERS: Buffer - Contains the compiled data
diff --git a/sys/contrib/dev/acpica/compiler/dtparser.l b/sys/contrib/dev/acpica/compiler/dtparser.l
index b6fd6ff..b0f6d6c 100644
--- a/sys/contrib/dev/acpica/compiler/dtparser.l
+++ b/sys/contrib/dev/acpica/compiler/dtparser.l
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dtparser.y b/sys/contrib/dev/acpica/compiler/dtparser.y
index cf9fb98..47e74bd 100644
--- a/sys/contrib/dev/acpica/compiler/dtparser.y
+++ b/sys/contrib/dev/acpica/compiler/dtparser.y
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dtsubtable.c b/sys/contrib/dev/acpica/compiler/dtsubtable.c
index 9eebe83..df22710 100644
--- a/sys/contrib/dev/acpica/compiler/dtsubtable.c
+++ b/sys/contrib/dev/acpica/compiler/dtsubtable.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,7 @@ DtInsertSubtable (
Subtable->Peer = NULL;
Subtable->Parent = ParentTable;
+ Subtable->Depth = ParentTable->Depth + 1;
/* Link the new entry into the child list */
diff --git a/sys/contrib/dev/acpica/compiler/dttable.c b/sys/contrib/dev/acpica/compiler/dttable.c
index 8b58b76..1a8fd81 100644
--- a/sys/contrib/dev/acpica/compiler/dttable.c
+++ b/sys/contrib/dev/acpica/compiler/dttable.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -420,6 +420,94 @@ DtCompileCpep (
/******************************************************************************
*
+ * FUNCTION: DtCompileCsrt
+ *
+ * PARAMETERS: List - Current field list pointer
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Compile CSRT.
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+DtCompileCsrt (
+ void **List)
+{
+ ACPI_STATUS Status = AE_OK;
+ DT_SUBTABLE *Subtable;
+ DT_SUBTABLE *ParentTable;
+ DT_FIELD **PFieldList = (DT_FIELD **) List;
+ UINT32 DescriptorCount;
+ UINT32 GroupLength;
+
+
+ /* Sub-tables (Resource Groups) */
+
+ while (*PFieldList)
+ {
+ /* Resource group subtable */
+
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
+ &Subtable, TRUE);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Compute the number of resource descriptors */
+
+ GroupLength =
+ (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
+ Subtable->Buffer))->Length -
+ (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
+ Subtable->Buffer))->SharedInfoLength -
+ sizeof (ACPI_CSRT_GROUP);
+
+ DescriptorCount = (GroupLength /
+ sizeof (ACPI_CSRT_DESCRIPTOR));
+
+ ParentTable = DtPeekSubtable ();
+ DtInsertSubtable (ParentTable, Subtable);
+ DtPushSubtable (Subtable);
+
+ /* Shared info subtable (One per resource group) */
+
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
+ &Subtable, TRUE);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ ParentTable = DtPeekSubtable ();
+ DtInsertSubtable (ParentTable, Subtable);
+
+ /* Sub-Subtables (Resource Descriptors) */
+
+ while (*PFieldList && DescriptorCount)
+ {
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
+ &Subtable, TRUE);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ ParentTable = DtPeekSubtable ();
+ DtInsertSubtable (ParentTable, Subtable);
+ DescriptorCount--;
+ }
+
+ DtPopSubtable ();
+ }
+
+ return (Status);
+}
+
+
+/******************************************************************************
+ *
* FUNCTION: DtCompileDmar
*
* PARAMETERS: List - Current field list pointer
diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.c b/sys/contrib/dev/acpica/compiler/dttemplate.c
index fda712b..c0ff98b 100644
--- a/sys/contrib/dev/acpica/compiler/dttemplate.c
+++ b/sys/contrib/dev/acpica/compiler/dttemplate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.h b/sys/contrib/dev/acpica/compiler/dttemplate.h
index 1a817cd..07d1f91 100644
--- a/sys/contrib/dev/acpica/compiler/dttemplate.h
+++ b/sys/contrib/dev/acpica/compiler/dttemplate.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -128,6 +128,52 @@ const unsigned char TemplateCpep[] =
0x00,0x00,0x00,0x00 /* 00000030 "...." */
};
+const unsigned char TemplateCsrt[] =
+{
+ 0x43,0x53,0x52,0x54,0x4C,0x01,0x00,0x00, /* 00000000 "CSRTL..." */
+ 0x01,0x0D,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */
+ 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */
+ 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
+ 0x14,0x11,0x12,0x20,0x88,0x00,0x00,0x00, /* 00000020 "... ...." */
+ 0x49,0x4E,0x54,0x4C,0x00,0x00,0x00,0x00, /* 00000028 "INTL...." */
+ 0x60,0x9C,0x00,0x00,0x02,0x00,0x00,0x00, /* 00000030 "`......." */
+ 0x1C,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000038 "........" */
+ 0x00,0x00,0xA0,0xB3,0x00,0x00,0x00,0x00, /* 00000040 "........" */
+ 0x2A,0x00,0x00,0x00,0x02,0x00,0x06,0x20, /* 00000048 "*...... " */
+ 0x00,0x00,0x10,0x00,0xFF,0x0F,0x00,0x00, /* 00000050 "........" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x01,0x00, /* 00000058 "........" */
+ 0x53,0x50,0x49,0x20,0x0C,0x00,0x00,0x00, /* 00000060 "SPI ...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x30, /* 00000068 "....CHA0" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000070 "........" */
+ 0x43,0x48,0x41,0x31,0x0C,0x00,0x00,0x00, /* 00000078 "CHA1...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x32, /* 00000080 "....CHA2" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000088 "........" */
+ 0x43,0x48,0x41,0x33,0x0C,0x00,0x00,0x00, /* 00000090 "CHA3...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x34, /* 00000098 "....CHA4" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 000000A0 "........" */
+ 0x43,0x48,0x41,0x35,0xA0,0x00,0x00,0x00, /* 000000A8 "CHA5...." */
+ 0x49,0x4E,0x54,0x4C,0x00,0x00,0x00,0x00, /* 000000B0 "INTL...." */
+ 0x60,0x9C,0x00,0x00,0x03,0x00,0x00,0x00, /* 000000B8 "`......." */
+ 0x1C,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 000000C0 "........" */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C8 "........" */
+ 0x2B,0x00,0x00,0x00,0x02,0x00,0x08,0x20, /* 000000D0 "+...... " */
+ 0x10,0x00,0x10,0x00,0xFF,0x0F,0x00,0x00, /* 000000D8 "........" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x01,0x00, /* 000000E0 "........" */
+ 0x49,0x32,0x43,0x20,0x0C,0x00,0x00,0x00, /* 000000E8 "I2C ...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x30, /* 000000F0 "....CHA0" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 000000F8 "........" */
+ 0x43,0x48,0x41,0x31,0x0C,0x00,0x00,0x00, /* 00000100 "CHA1...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x32, /* 00000108 "....CHA2" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000110 "........" */
+ 0x43,0x48,0x41,0x33,0x0C,0x00,0x00,0x00, /* 00000118 "CHA3...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x34, /* 00000120 "....CHA4" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000128 "........" */
+ 0x43,0x48,0x41,0x35,0x0C,0x00,0x00,0x00, /* 00000130 "CHA5...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x36, /* 00000138 "....CHA6" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000140 "........" */
+ 0x43,0x48,0x41,0x37 /* 00000148 "CHA7" */
+};
+
const unsigned char TemplateDbgp[] =
{
0x44,0x42,0x47,0x50,0x34,0x00,0x00,0x00, /* 00000000 "DBGP4..." */
@@ -825,6 +871,17 @@ const unsigned char TemplateTcpa[] =
0x00,0x00 /* 00000030 ".." */
};
+const unsigned char TemplateTpm2[] =
+{
+ 0x54,0x50,0x4D,0x32,0x34,0x00,0x00,0x00, /* 00000000 "TPM24..." */
+ 0x03,0x42,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".BINTEL " */
+ 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */
+ 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
+ 0x14,0x11,0x12,0x20,0x00,0x00,0x00,0x00, /* 00000020 "... ...." */
+ 0x77,0x66,0x55,0x44,0x33,0x22,0x11,0x00, /* 00000028 "wfUD3".." */
+ 0x01,0x00,0x00,0x00 /* 00000030 "...." */
+};
+
const unsigned char TemplateUefi[] =
{
0x55,0x45,0x46,0x49,0x36,0x00,0x00,0x00, /* 00000000 "UEFI6..." */
diff --git a/sys/contrib/dev/acpica/compiler/dtutils.c b/sys/contrib/dev/acpica/compiler/dtutils.c
index f87fa20..80b0e44 100644
--- a/sys/contrib/dev/acpica/compiler/dtutils.c
+++ b/sys/contrib/dev/acpica/compiler/dtutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/preprocess.h b/sys/contrib/dev/acpica/compiler/preprocess.h
index f97434f..6decc00 100644
--- a/sys/contrib/dev/acpica/compiler/preprocess.h
+++ b/sys/contrib/dev/acpica/compiler/preprocess.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prexpress.c b/sys/contrib/dev/acpica/compiler/prexpress.c
index c0dccd9..c0aa565 100644
--- a/sys/contrib/dev/acpica/compiler/prexpress.c
+++ b/sys/contrib/dev/acpica/compiler/prexpress.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prmacros.c b/sys/contrib/dev/acpica/compiler/prmacros.c
index 82663a5..d76de8b 100644
--- a/sys/contrib/dev/acpica/compiler/prmacros.c
+++ b/sys/contrib/dev/acpica/compiler/prmacros.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prparser.l b/sys/contrib/dev/acpica/compiler/prparser.l
index 34daa48..b580d57 100644
--- a/sys/contrib/dev/acpica/compiler/prparser.l
+++ b/sys/contrib/dev/acpica/compiler/prparser.l
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prparser.y b/sys/contrib/dev/acpica/compiler/prparser.y
index 81cede3..391ad3f 100644
--- a/sys/contrib/dev/acpica/compiler/prparser.y
+++ b/sys/contrib/dev/acpica/compiler/prparser.y
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prscan.c b/sys/contrib/dev/acpica/compiler/prscan.c
index 233e45a..0d44d6a 100644
--- a/sys/contrib/dev/acpica/compiler/prscan.c
+++ b/sys/contrib/dev/acpica/compiler/prscan.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prutils.c b/sys/contrib/dev/acpica/compiler/prutils.c
index c8faeb6..0dbf307 100644
--- a/sys/contrib/dev/acpica/compiler/prutils.c
+++ b/sys/contrib/dev/acpica/compiler/prutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbcmds.c b/sys/contrib/dev/acpica/components/debugger/dbcmds.c
index 5120fcb..64c299c 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbcmds.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbcmds.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,17 +82,21 @@ AcpiDbDeviceResources (
void *Context,
void **ReturnValue);
+static void
+AcpiDbDoOneSleepState (
+ UINT8 SleepState);
+
/*******************************************************************************
*
* FUNCTION: AcpiDbConvertToNode
*
- * PARAMETERS: InString - String to convert
+ * PARAMETERS: InString - String to convert
*
* RETURN: Pointer to a NS node
*
* DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or
- * alpha strings.
+ * alphanumeric strings.
*
******************************************************************************/
@@ -126,9 +130,9 @@ AcpiDbConvertToNode (
}
else
{
- /* Alpha argument */
- /* The parameter is a name string that must be resolved to a
- * Named obj
+ /*
+ * Alpha argument: The parameter is a name string that must be
+ * resolved to a Namespace object.
*/
Node = AcpiDbLocalNsLookup (InString);
if (!Node)
@@ -145,11 +149,12 @@ AcpiDbConvertToNode (
*
* FUNCTION: AcpiDbSleep
*
- * PARAMETERS: ObjectArg - Desired sleep state (0-5)
+ * PARAMETERS: ObjectArg - Desired sleep state (0-5). NULL means
+ * invoke all possible sleep states.
*
* RETURN: Status
*
- * DESCRIPTION: Simulate a sleep/wake sequence
+ * DESCRIPTION: Simulate sleep/wake sequences
*
******************************************************************************/
@@ -157,50 +162,124 @@ ACPI_STATUS
AcpiDbSleep (
char *ObjectArg)
{
- ACPI_STATUS Status;
UINT8 SleepState;
+ UINT32 i;
ACPI_FUNCTION_TRACE (AcpiDbSleep);
+ /* Null input (no arguments) means to invoke all sleep states */
+
+ if (!ObjectArg)
+ {
+ AcpiOsPrintf ("Invoking all possible sleep states, 0-%d\n",
+ ACPI_S_STATES_MAX);
+
+ for (i = 0; i <= ACPI_S_STATES_MAX; i++)
+ {
+ AcpiDbDoOneSleepState ((UINT8) i);
+ }
+
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Convert argument to binary and invoke the sleep state */
+
SleepState = (UINT8) ACPI_STRTOUL (ObjectArg, NULL, 0);
+ AcpiDbDoOneSleepState (SleepState);
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbDoOneSleepState
+ *
+ * PARAMETERS: SleepState - Desired sleep state (0-5)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Simulate a sleep/wake sequence
+ *
+ ******************************************************************************/
+
+static void
+AcpiDbDoOneSleepState (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+ UINT8 SleepTypeA;
+ UINT8 SleepTypeB;
+
+
+ /* Validate parameter */
+
+ if (SleepState > ACPI_S_STATES_MAX)
+ {
+ AcpiOsPrintf ("Sleep state %d out of range (%d max)\n",
+ SleepState, ACPI_S_STATES_MAX);
+ return;
+ }
+
+ AcpiOsPrintf ("\n---- Invoking sleep state S%d (%s):\n",
+ SleepState, AcpiGbl_SleepStateNames[SleepState]);
+
+ /* Get the values for the sleep type registers (for display only) */
+
+ Status = AcpiGetSleepTypeData (SleepState, &SleepTypeA, &SleepTypeB);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiOsPrintf ("Could not evaluate [%s] method, %s\n",
+ AcpiGbl_SleepStateNames[SleepState],
+ AcpiFormatException (Status));
+ return;
+ }
- AcpiOsPrintf ("**** Prepare to sleep ****\n");
+ AcpiOsPrintf (
+ "Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n",
+ SleepState, SleepTypeA, SleepTypeB);
+
+ /* Invoke the various sleep/wake interfaces */
+
+ AcpiOsPrintf ("**** Sleep: Prepare to sleep (S%d) ****\n",
+ SleepState);
Status = AcpiEnterSleepStatePrep (SleepState);
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
}
- AcpiOsPrintf ("**** Going to sleep ****\n");
+ AcpiOsPrintf ("**** Sleep: Going to sleep (S%d) ****\n",
+ SleepState);
Status = AcpiEnterSleepState (SleepState);
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
}
- AcpiOsPrintf ("**** Prepare to return from sleep ****\n");
+ AcpiOsPrintf ("**** Wake: Prepare to return from sleep (S%d) ****\n",
+ SleepState);
Status = AcpiLeaveSleepStatePrep (SleepState);
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
}
- AcpiOsPrintf ("**** Returning from sleep ****\n");
+ AcpiOsPrintf ("**** Wake: Return from sleep (S%d) ****\n",
+ SleepState);
Status = AcpiLeaveSleepState (SleepState);
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
}
- return_ACPI_STATUS (Status);
+ return;
ErrorExit:
-
- ACPI_EXCEPTION ((AE_INFO, Status, "During sleep test"));
- return_ACPI_STATUS (Status);
+ ACPI_EXCEPTION ((AE_INFO, Status, "During invocation of sleep state S%d",
+ SleepState));
}
@@ -236,7 +315,7 @@ AcpiDbDisplayLocks (
*
* FUNCTION: AcpiDbDisplayTableInfo
*
- * PARAMETERS: TableArg - String with name of table to be displayed
+ * PARAMETERS: TableArg - Name of table to be displayed
*
* RETURN: None
*
@@ -377,8 +456,8 @@ AcpiDbUnloadAcpiTable (
*
* FUNCTION: AcpiDbSendNotify
*
- * PARAMETERS: Name - Name of ACPI object to send the notify to
- * Value - Value of the notify to send.
+ * PARAMETERS: Name - Name of ACPI object where to send notify
+ * Value - Value of the notify to send.
*
* RETURN: None
*
@@ -416,7 +495,8 @@ AcpiDbSendNotify (
}
else
{
- AcpiOsPrintf ("Named object [%4.4s] Type %s, must be Device/Thermal/Processor type\n",
+ AcpiOsPrintf (
+ "Named object [%4.4s] Type %s, must be Device/Thermal/Processor type\n",
AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type));
}
}
@@ -453,7 +533,6 @@ AcpiDbDisplayInterfaces (
ACPI_WAIT_FOREVER);
NextInterface = AcpiGbl_SupportedInterfaces;
-
while (NextInterface)
{
if (!(NextInterface->Flags & ACPI_OSI_INVALID))
@@ -518,7 +597,7 @@ AcpiDbDisplayInterfaces (
*
* FUNCTION: AcpiDbDisplayTemplate
*
- * PARAMETERS: BufferArg - Buffer name or addrss
+ * PARAMETERS: BufferArg - Buffer name or address
*
* RETURN: None
*
@@ -532,7 +611,7 @@ AcpiDbDisplayTemplate (
{
ACPI_NAMESPACE_NODE *Node;
ACPI_STATUS Status;
- ACPI_BUFFER ReturnObj;
+ ACPI_BUFFER ReturnBuffer;
/* Translate BufferArg to an Named object */
@@ -553,12 +632,12 @@ AcpiDbDisplayTemplate (
return;
}
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
/* Attempt to convert the raw buffer to a resource list */
- Status = AcpiRsCreateResourceList (Node->Object, &ReturnObj);
+ Status = AcpiRsCreateResourceList (Node->Object, &ReturnBuffer);
AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
AcpiDbgLevel |= ACPI_LV_RESOURCES;
@@ -573,7 +652,7 @@ AcpiDbDisplayTemplate (
/* Now we can dump the resource list */
AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE,
- ReturnObj.Pointer));
+ ReturnBuffer.Pointer));
DumpBuffer:
AcpiOsPrintf ("\nRaw data buffer:\n");
@@ -666,7 +745,8 @@ AcpiDmCompareAmlResources (
{
if (Aml1[i] != Aml2[i])
{
- AcpiOsPrintf ("Mismatch at byte offset %.2X: is %2.2X, should be %2.2X\n",
+ AcpiOsPrintf (
+ "Mismatch at byte offset %.2X: is %2.2X, should be %2.2X\n",
i, Aml2[i], Aml1[i]);
}
}
@@ -693,8 +773,8 @@ AcpiDmCompareAmlResources (
*
* FUNCTION: AcpiDmTestResourceConversion
*
- * PARAMETERS: Node - Parent device node
- * Name - resource method name (_CRS)
+ * PARAMETERS: Node - Parent device node
+ * Name - resource method name (_CRS)
*
* RETURN: Status
*
@@ -709,8 +789,8 @@ AcpiDmTestResourceConversion (
char *Name)
{
ACPI_STATUS Status;
- ACPI_BUFFER ReturnObj;
- ACPI_BUFFER ResourceObj;
+ ACPI_BUFFER ReturnBuffer;
+ ACPI_BUFFER ResourceBuffer;
ACPI_BUFFER NewAml;
ACPI_OBJECT *OriginalAml;
@@ -718,12 +798,12 @@ AcpiDmTestResourceConversion (
AcpiOsPrintf ("Resource Conversion Comparison:\n");
NewAml.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- ReturnObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- ResourceObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ ResourceBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
/* Get the original _CRS AML resource template */
- Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not obtain %s: %s\n",
@@ -733,7 +813,7 @@ AcpiDmTestResourceConversion (
/* Get the AML resource template, converted to internal resource structs */
- Status = AcpiGetCurrentResources (Node, &ResourceObj);
+ Status = AcpiGetCurrentResources (Node, &ResourceBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
@@ -743,7 +823,7 @@ AcpiDmTestResourceConversion (
/* Convert internal resource list to external AML resource template */
- Status = AcpiRsCreateAmlResources (ResourceObj.Pointer, &NewAml);
+ Status = AcpiRsCreateAmlResources (ResourceBuffer.Pointer, &NewAml);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiRsCreateAmlResources failed: %s\n",
@@ -753,7 +833,7 @@ AcpiDmTestResourceConversion (
/* Compare original AML to the newly created AML resource list */
- OriginalAml = ReturnObj.Pointer;
+ OriginalAml = ReturnBuffer.Pointer;
AcpiDmCompareAmlResources (
OriginalAml->Buffer.Pointer, (ACPI_RSDESC_SIZE) OriginalAml->Buffer.Length,
@@ -763,9 +843,9 @@ AcpiDmTestResourceConversion (
ACPI_FREE (NewAml.Pointer);
Exit2:
- ACPI_FREE (ResourceObj.Pointer);
+ ACPI_FREE (ResourceBuffer.Pointer);
Exit1:
- ACPI_FREE (ReturnObj.Pointer);
+ ACPI_FREE (ReturnBuffer.Pointer);
return (Status);
}
@@ -778,7 +858,8 @@ Exit1:
*
* RETURN: Status
*
- * DESCRIPTION: Simple callback to exercise AcpiWalkResources
+ * DESCRIPTION: Simple callback to exercise AcpiWalkResources and
+ * AcpiWalkResourceBuffer.
*
******************************************************************************/
@@ -817,7 +898,7 @@ AcpiDbDeviceResources (
ACPI_NAMESPACE_NODE *PrsNode = NULL;
ACPI_NAMESPACE_NODE *AeiNode = NULL;
char *ParentPath;
- ACPI_BUFFER ReturnObj;
+ ACPI_BUFFER ReturnBuffer;
ACPI_STATUS Status;
@@ -843,8 +924,8 @@ AcpiDbDeviceResources (
/* Prepare for a return object of arbitrary size */
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
/* _PRT */
@@ -853,7 +934,7 @@ AcpiDbDeviceResources (
{
AcpiOsPrintf ("Evaluating _PRT\n");
- Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not evaluate _PRT: %s\n",
@@ -861,10 +942,10 @@ AcpiDbDeviceResources (
goto GetCrs;
}
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiGetIrqRoutingTable (Node, &ReturnObj);
+ Status = AcpiGetIrqRoutingTable (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n",
@@ -883,10 +964,10 @@ GetCrs:
{
AcpiOsPrintf ("Evaluating _CRS\n");
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not evaluate _CRS: %s\n",
@@ -894,7 +975,7 @@ GetCrs:
goto GetPrs;
}
- /* This code is here to exercise the AcpiWalkResources interface */
+ /* This code exercises the AcpiWalkResources interface */
Status = AcpiWalkResources (Node, METHOD_NAME__CRS,
AcpiDbResourceCallback, NULL);
@@ -905,12 +986,12 @@ GetCrs:
goto GetPrs;
}
- /* Get the _CRS resource list */
+ /* Get the _CRS resource list (test ALLOCATE buffer) */
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = NULL;
+ ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- Status = AcpiGetCurrentResources (Node, &ReturnObj);
+ Status = AcpiGetCurrentResources (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
@@ -918,26 +999,41 @@ GetCrs:
goto GetPrs;
}
+ /* This code exercises the AcpiWalkResourceBuffer interface */
+
+ Status = AcpiWalkResourceBuffer (&ReturnBuffer,
+ AcpiDbResourceCallback, NULL);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiOsPrintf ("AcpiWalkResourceBuffer failed: %s\n",
+ AcpiFormatException (Status));
+ goto EndCrs;
+ }
+
/* Dump the _CRS resource list */
AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE,
- ReturnObj.Pointer));
+ ReturnBuffer.Pointer));
/*
- * Perform comparison of original AML to newly created AML. This tests both
- * the AML->Resource conversion and the Resource->Aml conversion.
+ * Perform comparison of original AML to newly created AML. This
+ * tests both the AML->Resource conversion and the Resource->AML
+ * conversion.
*/
- Status = AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS);
+ (void) AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS);
/* Execute _SRS with the resource list */
- Status = AcpiSetCurrentResources (Node, &ReturnObj);
+ Status = AcpiSetCurrentResources (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n",
AcpiFormatException (Status));
- goto GetPrs;
+ goto EndCrs;
}
+
+EndCrs:
+ ACPI_FREE_BUFFER (ReturnBuffer);
}
@@ -948,10 +1044,10 @@ GetPrs:
{
AcpiOsPrintf ("Evaluating _PRS\n");
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not evaluate _PRS: %s\n",
@@ -959,10 +1055,10 @@ GetPrs:
goto GetAei;
}
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiGetPossibleResources (Node, &ReturnObj);
+ Status = AcpiGetPossibleResources (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n",
@@ -981,10 +1077,10 @@ GetAei:
{
AcpiOsPrintf ("Evaluating _AEI\n");
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not evaluate _AEI: %s\n",
@@ -992,10 +1088,10 @@ GetAei:
goto Cleanup;
}
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiGetEventResources (Node, &ReturnObj);
+ Status = AcpiGetEventResources (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiGetEventResources failed: %s\n",
@@ -1017,8 +1113,9 @@ Cleanup:
*
* FUNCTION: AcpiDbDisplayResources
*
- * PARAMETERS: ObjectArg - String object name or object pointer.
- * "*" means "display resources for all devices"
+ * PARAMETERS: ObjectArg - String object name or object pointer.
+ * "*" means "display resources for all
+ * devices"
*
* RETURN: None
*
@@ -1071,13 +1168,13 @@ AcpiDbDisplayResources (
*
* FUNCTION: AcpiDbGenerateGpe
*
- * PARAMETERS: GpeArg - Raw GPE number, ascii string
- * BlockArg - GPE block number, ascii string
- * 0 or 1 for FADT GPE blocks
+ * PARAMETERS: GpeArg - Raw GPE number, ascii string
+ * BlockArg - GPE block number, ascii string
+ * 0 or 1 for FADT GPE blocks
*
* RETURN: None
*
- * DESCRIPTION: Generate a GPE
+ * DESCRIPTION: Simulate firing of a GPE
*
******************************************************************************/
diff --git a/sys/contrib/dev/acpica/components/debugger/dbconvert.c b/sys/contrib/dev/acpica/components/debugger/dbconvert.c
new file mode 100644
index 0000000..f781f29
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/debugger/dbconvert.c
@@ -0,0 +1,525 @@
+/*******************************************************************************
+ *
+ * Module Name: dbconvert - debugger miscellaneous conversion routines
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acdebug.h>
+
+#ifdef ACPI_DEBUGGER
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ ACPI_MODULE_NAME ("dbconvert")
+
+
+#define DB_DEFAULT_PKG_ELEMENTS 33
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbHexCharToValue
+ *
+ * PARAMETERS: HexChar - Ascii Hex digit, 0-9|a-f|A-F
+ * ReturnValue - Where the converted value is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiDbHexCharToValue (
+ int HexChar,
+ UINT8 *ReturnValue)
+{
+ UINT8 Value;
+
+
+ /* Digit must be ascii [0-9a-fA-F] */
+
+ if (!ACPI_IS_XDIGIT (HexChar))
+ {
+ return (AE_BAD_HEX_CONSTANT);
+ }
+
+ if (HexChar <= 0x39)
+ {
+ Value = (UINT8) (HexChar - 0x30);
+ }
+ else
+ {
+ Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37);
+ }
+
+ *ReturnValue = Value;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbHexByteToBinary
+ *
+ * PARAMETERS: HexByte - Double hex digit (0x00 - 0xFF) in format:
+ * HiByte then LoByte.
+ * ReturnValue - Where the converted value is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbHexByteToBinary (
+ char *HexByte,
+ UINT8 *ReturnValue)
+{
+ UINT8 Local0;
+ UINT8 Local1;
+ ACPI_STATUS Status;
+
+
+ /* High byte */
+
+ Status = AcpiDbHexCharToValue (HexByte[0], &Local0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Low byte */
+
+ Status = AcpiDbHexCharToValue (HexByte[1], &Local1);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ *ReturnValue = (UINT8) ((Local0 << 4) | Local1);
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToBuffer
+ *
+ * PARAMETERS: String - Input string to be converted
+ * Object - Where the buffer object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a string to a buffer object. String is treated a list
+ * of buffer elements, each separated by a space or comma.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbConvertToBuffer (
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ UINT32 i;
+ UINT32 j;
+ UINT32 Length;
+ UINT8 *Buffer;
+ ACPI_STATUS Status;
+
+
+ /* Generate the final buffer length */
+
+ for (i = 0, Length = 0; String[i];)
+ {
+ i+=2;
+ Length++;
+
+ while (String[i] &&
+ ((String[i] == ',') || (String[i] == ' ')))
+ {
+ i++;
+ }
+ }
+
+ Buffer = ACPI_ALLOCATE (Length);
+ if (!Buffer)
+ {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Convert the command line bytes to the buffer */
+
+ for (i = 0, j = 0; String[i];)
+ {
+ Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_FREE (Buffer);
+ return (Status);
+ }
+
+ j++;
+ i+=2;
+ while (String[i] &&
+ ((String[i] == ',') || (String[i] == ' ')))
+ {
+ i++;
+ }
+ }
+
+ Object->Type = ACPI_TYPE_BUFFER;
+ Object->Buffer.Pointer = Buffer;
+ Object->Buffer.Length = Length;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToPackage
+ *
+ * PARAMETERS: String - Input string to be converted
+ * Object - Where the package object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a string to a package object. Handles nested packages
+ * via recursion with AcpiDbConvertToObject.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiDbConvertToPackage (
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ char *This;
+ char *Next;
+ UINT32 i;
+ ACPI_OBJECT_TYPE Type;
+ ACPI_OBJECT *Elements;
+ ACPI_STATUS Status;
+
+
+ Elements = ACPI_ALLOCATE_ZEROED (
+ DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT));
+
+ This = String;
+ for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++)
+ {
+ This = AcpiDbGetNextToken (This, &Next, &Type);
+ if (!This)
+ {
+ break;
+ }
+
+ /* Recursive call to convert each package element */
+
+ Status = AcpiDbConvertToObject (Type, This, &Elements[i]);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiDbDeleteObjects (i + 1, Elements);
+ ACPI_FREE (Elements);
+ return (Status);
+ }
+
+ This = Next;
+ }
+
+ Object->Type = ACPI_TYPE_PACKAGE;
+ Object->Package.Count = i;
+ Object->Package.Elements = Elements;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToObject
+ *
+ * PARAMETERS: Type - Object type as determined by parser
+ * String - Input string to be converted
+ * Object - Where the new object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing:
+ * 1) String objects were surrounded by quotes.
+ * 2) Buffer objects were surrounded by parentheses.
+ * 3) Package objects were surrounded by brackets "[]".
+ * 4) All standalone tokens are treated as integers.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiDbConvertToObject (
+ ACPI_OBJECT_TYPE Type,
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ ACPI_STATUS Status = AE_OK;
+
+
+ switch (Type)
+ {
+ case ACPI_TYPE_STRING:
+ Object->Type = ACPI_TYPE_STRING;
+ Object->String.Pointer = String;
+ Object->String.Length = (UINT32) ACPI_STRLEN (String);
+ break;
+
+ case ACPI_TYPE_BUFFER:
+ Status = AcpiDbConvertToBuffer (String, Object);
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+ Status = AcpiDbConvertToPackage (String, Object);
+ break;
+
+ default:
+ Object->Type = ACPI_TYPE_INTEGER;
+ Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value);
+ break;
+ }
+
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbEncodePldBuffer
+ *
+ * PARAMETERS: PldInfo - _PLD buffer struct (Using local struct)
+ *
+ * RETURN: Encode _PLD buffer suitable for return value from _PLD
+ *
+ * DESCRIPTION: Bit-packs a _PLD buffer struct. Used to test the _PLD macros
+ *
+ ******************************************************************************/
+
+UINT8 *
+AcpiDbEncodePldBuffer (
+ ACPI_PLD_INFO *PldInfo)
+{
+ UINT32 *Buffer;
+ UINT32 Dword;
+
+
+ Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE);
+ if (!Buffer)
+ {
+ return (NULL);
+ }
+
+ /* First 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_REVISION (&Dword, PldInfo->Revision);
+ ACPI_PLD_SET_IGNORE_COLOR (&Dword, PldInfo->IgnoreColor);
+ ACPI_PLD_SET_COLOR (&Dword, PldInfo->Color);
+ ACPI_MOVE_32_TO_32 (&Buffer[0], &Dword);
+
+ /* Second 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_WIDTH (&Dword, PldInfo->Width);
+ ACPI_PLD_SET_HEIGHT (&Dword, PldInfo->Height);
+ ACPI_MOVE_32_TO_32 (&Buffer[1], &Dword);
+
+ /* Third 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_USER_VISIBLE (&Dword, PldInfo->UserVisible);
+ ACPI_PLD_SET_DOCK (&Dword, PldInfo->Dock);
+ ACPI_PLD_SET_LID (&Dword, PldInfo->Lid);
+ ACPI_PLD_SET_PANEL (&Dword, PldInfo->Panel);
+ ACPI_PLD_SET_VERTICAL (&Dword, PldInfo->VerticalPosition);
+ ACPI_PLD_SET_HORIZONTAL (&Dword, PldInfo->HorizontalPosition);
+ ACPI_PLD_SET_SHAPE (&Dword, PldInfo->Shape);
+ ACPI_PLD_SET_ORIENTATION (&Dword, PldInfo->GroupOrientation);
+ ACPI_PLD_SET_TOKEN (&Dword, PldInfo->GroupToken);
+ ACPI_PLD_SET_POSITION (&Dword, PldInfo->GroupPosition);
+ ACPI_PLD_SET_BAY (&Dword, PldInfo->Bay);
+ ACPI_MOVE_32_TO_32 (&Buffer[2], &Dword);
+
+ /* Fourth 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_EJECTABLE (&Dword, PldInfo->Ejectable);
+ ACPI_PLD_SET_OSPM_EJECT (&Dword, PldInfo->OspmEjectRequired);
+ ACPI_PLD_SET_CABINET (&Dword, PldInfo->CabinetNumber);
+ ACPI_PLD_SET_CARD_CAGE (&Dword, PldInfo->CardCageNumber);
+ ACPI_PLD_SET_REFERENCE (&Dword, PldInfo->Reference);
+ ACPI_PLD_SET_ROTATION (&Dword, PldInfo->Rotation);
+ ACPI_PLD_SET_ORDER (&Dword, PldInfo->Order);
+ ACPI_MOVE_32_TO_32 (&Buffer[3], &Dword);
+
+ if (PldInfo->Revision >= 2)
+ {
+ /* Fifth 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_VERT_OFFSET (&Dword, PldInfo->VerticalOffset);
+ ACPI_PLD_SET_HORIZ_OFFSET (&Dword, PldInfo->HorizontalOffset);
+ ACPI_MOVE_32_TO_32 (&Buffer[4], &Dword);
+ }
+
+ return (ACPI_CAST_PTR (UINT8, Buffer));
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbDumpPldBuffer
+ *
+ * PARAMETERS: ObjDesc - Object returned from _PLD method
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Dumps formatted contents of a _PLD return buffer.
+ *
+ ******************************************************************************/
+
+#define ACPI_PLD_OUTPUT "%20s : %-6X\n"
+
+void
+AcpiDbDumpPldBuffer (
+ ACPI_OBJECT *ObjDesc)
+{
+ ACPI_OBJECT *BufferDesc;
+ ACPI_PLD_INFO *PldInfo;
+ UINT8 *NewBuffer;
+ ACPI_STATUS Status;
+
+
+ /* Object must be of type Package with at least one Buffer element */
+
+ if (ObjDesc->Type != ACPI_TYPE_PACKAGE)
+ {
+ return;
+ }
+
+ BufferDesc = &ObjDesc->Package.Elements[0];
+ if (BufferDesc->Type != ACPI_TYPE_BUFFER)
+ {
+ return;
+ }
+
+ /* Convert _PLD buffer to local _PLD struct */
+
+ Status = AcpiDecodePldBuffer (BufferDesc->Buffer.Pointer,
+ BufferDesc->Buffer.Length, &PldInfo);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ /* Encode local _PLD struct back to a _PLD buffer */
+
+ NewBuffer = AcpiDbEncodePldBuffer (PldInfo);
+ if (!NewBuffer)
+ {
+ return;
+ }
+
+ /* The two bit-packed buffers should match */
+
+ if (ACPI_MEMCMP (NewBuffer, BufferDesc->Buffer.Pointer,
+ BufferDesc->Buffer.Length))
+ {
+ AcpiOsPrintf ("Converted _PLD buffer does not compare. New:\n");
+
+ AcpiUtDumpBuffer (NewBuffer,
+ BufferDesc->Buffer.Length, DB_BYTE_DISPLAY, 0);
+ }
+
+ /* First 32-bit dword */
+
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Revision", PldInfo->Revision);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "IgnoreColor", PldInfo->IgnoreColor);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Color", PldInfo->Color);
+
+ /* Second 32-bit dword */
+
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Width", PldInfo->Width);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Height", PldInfo->Height);
+
+ /* Third 32-bit dword */
+
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "UserVisible", PldInfo->UserVisible);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Dock", PldInfo->Dock);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Lid", PldInfo->Lid);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Panel", PldInfo->Panel);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalPosition", PldInfo->VerticalPosition);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalPosition", PldInfo->HorizontalPosition);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Shape", PldInfo->Shape);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupOrientation", PldInfo->GroupOrientation);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupToken", PldInfo->GroupToken);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupPosition", PldInfo->GroupPosition);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Bay", PldInfo->Bay);
+
+ /* Fourth 32-bit dword */
+
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Ejectable", PldInfo->Ejectable);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "OspmEjectRequired", PldInfo->OspmEjectRequired);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "CabinetNumber", PldInfo->CabinetNumber);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "CardCageNumber", PldInfo->CardCageNumber);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Reference", PldInfo->Reference);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Rotation", PldInfo->Rotation);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Order", PldInfo->Order);
+
+ /* Fifth 32-bit dword */
+
+ if (BufferDesc->Buffer.Length > 16)
+ {
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalOffset", PldInfo->VerticalOffset);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalOffset", PldInfo->HorizontalOffset);
+ }
+
+ ACPI_FREE (PldInfo);
+ ACPI_FREE (NewBuffer);
+}
+
+#endif /* ACPI_DEBUGGER */
diff --git a/sys/contrib/dev/acpica/components/debugger/dbdisply.c b/sys/contrib/dev/acpica/components/debugger/dbdisply.c
index 7776d55..6e82668 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbdisply.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbdisply.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbexec.c b/sys/contrib/dev/acpica/components/debugger/dbexec.c
index f1dce09..26f62b6 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbexec.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbexec.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,6 @@
static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo;
-#define DB_DEFAULT_PKG_ELEMENTS 33
/* Local prototypes */
@@ -82,308 +81,6 @@ AcpiDbExecutionWalk (
void *Context,
void **ReturnValue);
-static ACPI_STATUS
-AcpiDbHexCharToValue (
- int HexChar,
- UINT8 *ReturnValue);
-
-static ACPI_STATUS
-AcpiDbConvertToPackage (
- char *String,
- ACPI_OBJECT *Object);
-
-static ACPI_STATUS
-AcpiDbConvertToObject (
- ACPI_OBJECT_TYPE Type,
- char *String,
- ACPI_OBJECT *Object);
-
-static void
-AcpiDbDeleteObjects (
- UINT32 Count,
- ACPI_OBJECT *Objects);
-
-
-static UINT8 *
-AcpiDbEncodePldBuffer (
- ACPI_PLD_INFO *PldInfo);
-
-static void
-AcpiDbDumpPldBuffer (
- ACPI_OBJECT *ObjDesc);
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbHexCharToValue
- *
- * PARAMETERS: HexChar - Ascii Hex digit, 0-9|a-f|A-F
- * ReturnValue - Where the converted value is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbHexCharToValue (
- int HexChar,
- UINT8 *ReturnValue)
-{
- UINT8 Value;
-
-
- /* Digit must be ascii [0-9a-fA-F] */
-
- if (!ACPI_IS_XDIGIT (HexChar))
- {
- return (AE_BAD_HEX_CONSTANT);
- }
-
- if (HexChar <= 0x39)
- {
- Value = (UINT8) (HexChar - 0x30);
- }
- else
- {
- Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37);
- }
-
- *ReturnValue = Value;
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbHexByteToBinary
- *
- * PARAMETERS: HexByte - Double hex digit (0x00 - 0xFF) in format:
- * HiByte then LoByte.
- * ReturnValue - Where the converted value is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbHexByteToBinary (
- char *HexByte,
- UINT8 *ReturnValue)
-{
- UINT8 Local0;
- UINT8 Local1;
- ACPI_STATUS Status;
-
-
- /* High byte */
-
- Status = AcpiDbHexCharToValue (HexByte[0], &Local0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /* Low byte */
-
- Status = AcpiDbHexCharToValue (HexByte[1], &Local1);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- *ReturnValue = (UINT8) ((Local0 << 4) | Local1);
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbConvertToBuffer
- *
- * PARAMETERS: String - Input string to be converted
- * Object - Where the buffer object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert a string to a buffer object. String is treated a list
- * of buffer elements, each separated by a space or comma.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbConvertToBuffer (
- char *String,
- ACPI_OBJECT *Object)
-{
- UINT32 i;
- UINT32 j;
- UINT32 Length;
- UINT8 *Buffer;
- ACPI_STATUS Status;
-
-
- /* Generate the final buffer length */
-
- for (i = 0, Length = 0; String[i];)
- {
- i+=2;
- Length++;
-
- while (String[i] &&
- ((String[i] == ',') || (String[i] == ' ')))
- {
- i++;
- }
- }
-
- Buffer = ACPI_ALLOCATE (Length);
- if (!Buffer)
- {
- return (AE_NO_MEMORY);
- }
-
- /* Convert the command line bytes to the buffer */
-
- for (i = 0, j = 0; String[i];)
- {
- Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]);
- if (ACPI_FAILURE (Status))
- {
- ACPI_FREE (Buffer);
- return (Status);
- }
-
- j++;
- i+=2;
- while (String[i] &&
- ((String[i] == ',') || (String[i] == ' ')))
- {
- i++;
- }
- }
-
- Object->Type = ACPI_TYPE_BUFFER;
- Object->Buffer.Pointer = Buffer;
- Object->Buffer.Length = Length;
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbConvertToPackage
- *
- * PARAMETERS: String - Input string to be converted
- * Object - Where the package object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert a string to a package object. Handles nested packages
- * via recursion with AcpiDbConvertToObject.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbConvertToPackage (
- char *String,
- ACPI_OBJECT *Object)
-{
- char *This;
- char *Next;
- UINT32 i;
- ACPI_OBJECT_TYPE Type;
- ACPI_OBJECT *Elements;
- ACPI_STATUS Status;
-
-
- Elements = ACPI_ALLOCATE_ZEROED (
- DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT));
-
- This = String;
- for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++)
- {
- This = AcpiDbGetNextToken (This, &Next, &Type);
- if (!This)
- {
- break;
- }
-
- /* Recursive call to convert each package element */
-
- Status = AcpiDbConvertToObject (Type, This, &Elements[i]);
- if (ACPI_FAILURE (Status))
- {
- AcpiDbDeleteObjects (i + 1, Elements);
- ACPI_FREE (Elements);
- return (Status);
- }
-
- This = Next;
- }
-
- Object->Type = ACPI_TYPE_PACKAGE;
- Object->Package.Count = i;
- Object->Package.Elements = Elements;
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbConvertToObject
- *
- * PARAMETERS: Type - Object type as determined by parser
- * String - Input string to be converted
- * Object - Where the new object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing:
- * 1) String objects were surrounded by quotes.
- * 2) Buffer objects were surrounded by parentheses.
- * 3) Package objects were surrounded by brackets "[]".
- * 4) All standalone tokens are treated as integers.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbConvertToObject (
- ACPI_OBJECT_TYPE Type,
- char *String,
- ACPI_OBJECT *Object)
-{
- ACPI_STATUS Status = AE_OK;
-
-
- switch (Type)
- {
- case ACPI_TYPE_STRING:
- Object->Type = ACPI_TYPE_STRING;
- Object->String.Pointer = String;
- Object->String.Length = (UINT32) ACPI_STRLEN (String);
- break;
-
- case ACPI_TYPE_BUFFER:
- Status = AcpiDbConvertToBuffer (String, Object);
- break;
-
- case ACPI_TYPE_PACKAGE:
- Status = AcpiDbConvertToPackage (String, Object);
- break;
-
- default:
- Object->Type = ACPI_TYPE_INTEGER;
- Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value);
- break;
- }
-
- return (Status);
-}
-
/*******************************************************************************
*
@@ -399,7 +96,7 @@ AcpiDbConvertToObject (
*
******************************************************************************/
-static void
+void
AcpiDbDeleteObjects (
UINT32 Count,
ACPI_OBJECT *Objects)
@@ -720,202 +417,6 @@ AcpiDbExecutionWalk (
/*******************************************************************************
*
- * FUNCTION: AcpiDbEncodePldBuffer
- *
- * PARAMETERS: PldInfo - _PLD buffer struct (Using local struct)
- *
- * RETURN: Encode _PLD buffer suitable for return value from _PLD
- *
- * DESCRIPTION: Bit-packs a _PLD buffer struct. Used to test the _PLD macros
- *
- ******************************************************************************/
-
-static UINT8 *
-AcpiDbEncodePldBuffer (
- ACPI_PLD_INFO *PldInfo)
-{
- UINT32 *Buffer;
- UINT32 Dword;
-
-
- Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE);
- if (!Buffer)
- {
- return (NULL);
- }
-
- /* First 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_REVISION (&Dword, PldInfo->Revision);
- ACPI_PLD_SET_IGNORE_COLOR (&Dword, PldInfo->IgnoreColor);
- ACPI_PLD_SET_COLOR (&Dword, PldInfo->Color);
- ACPI_MOVE_32_TO_32 (&Buffer[0], &Dword);
-
- /* Second 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_WIDTH (&Dword, PldInfo->Width);
- ACPI_PLD_SET_HEIGHT (&Dword, PldInfo->Height);
- ACPI_MOVE_32_TO_32 (&Buffer[1], &Dword);
-
- /* Third 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_USER_VISIBLE (&Dword, PldInfo->UserVisible);
- ACPI_PLD_SET_DOCK (&Dword, PldInfo->Dock);
- ACPI_PLD_SET_LID (&Dword, PldInfo->Lid);
- ACPI_PLD_SET_PANEL (&Dword, PldInfo->Panel);
- ACPI_PLD_SET_VERTICAL (&Dword, PldInfo->VerticalPosition);
- ACPI_PLD_SET_HORIZONTAL (&Dword, PldInfo->HorizontalPosition);
- ACPI_PLD_SET_SHAPE (&Dword, PldInfo->Shape);
- ACPI_PLD_SET_ORIENTATION (&Dword, PldInfo->GroupOrientation);
- ACPI_PLD_SET_TOKEN (&Dword, PldInfo->GroupToken);
- ACPI_PLD_SET_POSITION (&Dword, PldInfo->GroupPosition);
- ACPI_PLD_SET_BAY (&Dword, PldInfo->Bay);
- ACPI_MOVE_32_TO_32 (&Buffer[2], &Dword);
-
- /* Fourth 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_EJECTABLE (&Dword, PldInfo->Ejectable);
- ACPI_PLD_SET_OSPM_EJECT (&Dword, PldInfo->OspmEjectRequired);
- ACPI_PLD_SET_CABINET (&Dword, PldInfo->CabinetNumber);
- ACPI_PLD_SET_CARD_CAGE (&Dword, PldInfo->CardCageNumber);
- ACPI_PLD_SET_REFERENCE (&Dword, PldInfo->Reference);
- ACPI_PLD_SET_ROTATION (&Dword, PldInfo->Rotation);
- ACPI_PLD_SET_ORDER (&Dword, PldInfo->Order);
- ACPI_MOVE_32_TO_32 (&Buffer[3], &Dword);
-
- if (PldInfo->Revision >= 2)
- {
- /* Fifth 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_VERT_OFFSET (&Dword, PldInfo->VerticalOffset);
- ACPI_PLD_SET_HORIZ_OFFSET (&Dword, PldInfo->HorizontalOffset);
- ACPI_MOVE_32_TO_32 (&Buffer[4], &Dword);
- }
-
- return (ACPI_CAST_PTR (UINT8, Buffer));
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbDumpPldBuffer
- *
- * PARAMETERS: ObjDesc - Object returned from _PLD method
- *
- * RETURN: None.
- *
- * DESCRIPTION: Dumps formatted contents of a _PLD return buffer.
- *
- ******************************************************************************/
-
-#define ACPI_PLD_OUTPUT "%20s : %-6X\n"
-
-static void
-AcpiDbDumpPldBuffer (
- ACPI_OBJECT *ObjDesc)
-{
- ACPI_OBJECT *BufferDesc;
- ACPI_PLD_INFO *PldInfo;
- UINT8 *NewBuffer;
- ACPI_STATUS Status;
-
-
- /* Object must be of type Package with at least one Buffer element */
-
- if (ObjDesc->Type != ACPI_TYPE_PACKAGE)
- {
- return;
- }
-
- BufferDesc = &ObjDesc->Package.Elements[0];
- if (BufferDesc->Type != ACPI_TYPE_BUFFER)
- {
- return;
- }
-
- /* Convert _PLD buffer to local _PLD struct */
-
- Status = AcpiDecodePldBuffer (BufferDesc->Buffer.Pointer,
- BufferDesc->Buffer.Length, &PldInfo);
- if (ACPI_FAILURE (Status))
- {
- return;
- }
-
- /* Encode local _PLD struct back to a _PLD buffer */
-
- NewBuffer = AcpiDbEncodePldBuffer (PldInfo);
- if (!NewBuffer)
- {
- return;
- }
-
- /* The two bit-packed buffers should match */
-
- if (ACPI_MEMCMP (NewBuffer, BufferDesc->Buffer.Pointer,
- BufferDesc->Buffer.Length))
- {
- AcpiOsPrintf ("Converted _PLD buffer does not compare. New:\n");
-
- AcpiUtDumpBuffer (NewBuffer,
- BufferDesc->Buffer.Length, DB_BYTE_DISPLAY, 0);
- }
-
- /* First 32-bit dword */
-
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Revision", PldInfo->Revision);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "IgnoreColor", PldInfo->IgnoreColor);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Color", PldInfo->Color);
-
- /* Second 32-bit dword */
-
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Width", PldInfo->Width);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Height", PldInfo->Height);
-
- /* Third 32-bit dword */
-
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "UserVisible", PldInfo->UserVisible);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Dock", PldInfo->Dock);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Lid", PldInfo->Lid);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Panel", PldInfo->Panel);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalPosition", PldInfo->VerticalPosition);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalPosition", PldInfo->HorizontalPosition);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Shape", PldInfo->Shape);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupOrientation", PldInfo->GroupOrientation);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupToken", PldInfo->GroupToken);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupPosition", PldInfo->GroupPosition);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Bay", PldInfo->Bay);
-
- /* Fourth 32-bit dword */
-
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Ejectable", PldInfo->Ejectable);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "OspmEjectRequired", PldInfo->OspmEjectRequired);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "CabinetNumber", PldInfo->CabinetNumber);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "CardCageNumber", PldInfo->CardCageNumber);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Reference", PldInfo->Reference);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Rotation", PldInfo->Rotation);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Order", PldInfo->Order);
-
- /* Fifth 32-bit dword */
-
- if (BufferDesc->Buffer.Length > 16)
- {
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalOffset", PldInfo->VerticalOffset);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalOffset", PldInfo->HorizontalOffset);
- }
-
- ACPI_FREE (PldInfo);
- ACPI_FREE (NewBuffer);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiDbExecute
*
* PARAMETERS: Name - Name of method to execute
@@ -983,12 +484,10 @@ AcpiDbExecute (
Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,
&AcpiGbl_DbMethodInfo.Method);
- if (ACPI_FAILURE (Status))
+ if (ACPI_SUCCESS (Status))
{
- return;
+ Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj);
}
-
- Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj);
ACPI_FREE (NameString);
}
@@ -998,7 +497,6 @@ AcpiDbExecute (
*/
AcpiOsSleep ((UINT64) 10);
-
#ifdef ACPI_DEBUG_OUTPUT
/* Memory allocation tracking */
diff --git a/sys/contrib/dev/acpica/components/debugger/dbfileio.c b/sys/contrib/dev/acpica/components/debugger/dbfileio.c
index 5c4b100..e03bb40 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbfileio.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbfileio.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbhistry.c b/sys/contrib/dev/acpica/components/debugger/dbhistry.c
index 1305451..0e05e14 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbhistry.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbhistry.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbinput.c b/sys/contrib/dev/acpica/components/debugger/dbinput.c
index f5db216..b5c46df 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbinput.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbinput.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -210,7 +210,7 @@ static const ACPI_DB_COMMAND_INFO AcpiGbl_DbCommands[] =
{"RESOURCES", 1},
{"RESULTS", 0},
{"SET", 3},
- {"SLEEP", 1},
+ {"SLEEP", 0},
{"STATS", 1},
{"STOP", 0},
{"TABLES", 0},
@@ -274,7 +274,7 @@ static const ACPI_DB_COMMAND_HELP AcpiGbl_DbCommandHelp[] =
{1, " References <Addr>", "Find all references to object at addr\n"},
{1, " Resources <DeviceName | *>", "Display Device resources (* = all devices)\n"},
{1, " Set N <NamedObject> <Value>", "Set value for named integer\n"},
- {1, " Sleep <SleepState>", "Simulate sleep/wake sequence\n"},
+ {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"},
{1, " Template <Object>", "Format/dump a Buffer/ResourceTemplate\n"},
{1, " Terminate", "Delete namespace and all internal objects\n"},
{1, " Type <Object>", "Display object type\n"},
@@ -1168,6 +1168,8 @@ AcpiDbUserCommands (
ACPI_STATUS Status = AE_OK;
+ AcpiOsPrintf ("\n");
+
/* TBD: [Restructure] Need a separate command line buffer for step mode */
while (!AcpiGbl_DbTerminateThreads)
diff --git a/sys/contrib/dev/acpica/components/debugger/dbmethod.c b/sys/contrib/dev/acpica/components/debugger/dbmethod.c
index ccfb7d5..d3d86dd 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbmethod.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbmethod.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -396,7 +396,7 @@ AcpiDbDisassembleMethod (
WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
Status = AcpiPsParseAml (WalkState);
- AcpiDmParseDeferredOps (Op);
+ (void) AcpiDmParseDeferredOps (Op);
/* Now we can disassemble the method */
diff --git a/sys/contrib/dev/acpica/components/debugger/dbnames.c b/sys/contrib/dev/acpica/components/debugger/dbnames.c
index aed8dfb..8efb74d 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbnames.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbnames.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -159,7 +159,7 @@ AcpiDbSetScope (
AcpiDbPrepNamestring (Name);
- if (Name[0] == '\\')
+ if (ACPI_IS_ROOT_PREFIX (Name[0]))
{
/* Validate new scope from the root */
diff --git a/sys/contrib/dev/acpica/components/debugger/dbstats.c b/sys/contrib/dev/acpica/components/debugger/dbstats.c
index 7037c2b..6a1c0bb 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbstats.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbstats.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbutils.c b/sys/contrib/dev/acpica/components/debugger/dbutils.c
index 7d1c427..33b9c19 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbutils.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -286,7 +286,7 @@ AcpiDbPrepNamestring (
/* Ignore a leading backslash, this is the root prefix */
- if (*Name == '\\')
+ if (ACPI_IS_ROOT_PREFIX (*Name))
{
Name++;
}
diff --git a/sys/contrib/dev/acpica/components/debugger/dbxface.c b/sys/contrib/dev/acpica/components/debugger/dbxface.c
index f265dba..6f97582 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbxface.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbxface.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -421,9 +421,9 @@ AcpiDbInitialize (
AcpiGbl_DbOutputFlags = ACPI_DB_CONSOLE_OUTPUT;
AcpiGbl_DbOpt_tables = FALSE;
+ AcpiGbl_DbOpt_disasm = FALSE;
AcpiGbl_DbOpt_stats = FALSE;
#ifdef ACPI_DISASSEMBLER
- AcpiGbl_DbOpt_disasm = FALSE;
AcpiGbl_DbOpt_verbose = TRUE;
#endif
AcpiGbl_DbOpt_ini_methods = TRUE;
@@ -437,7 +437,7 @@ AcpiDbInitialize (
/* Initial scope is the root */
- AcpiGbl_DbScopeBuf [0] = '\\';
+ AcpiGbl_DbScopeBuf [0] = AML_ROOT_PREFIX;
AcpiGbl_DbScopeBuf [1] = 0;
AcpiGbl_DbScopeNode = AcpiGbl_RootNode;
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
index 9be6a50..2f6ff72 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c b/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
index 1e8c224..9a68079 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -83,7 +83,7 @@ AcpiDmParseDeferredOps (
ACPI_STATUS Status;
- ACPI_FUNCTION_NAME (DmParseDeferredOps);
+ ACPI_FUNCTION_ENTRY ();
/* Traverse the entire parse tree */
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmnames.c b/sys/contrib/dev/acpica/components/disassembler/dmnames.c
index 0149bff..b2ef29d 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmnames.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmnames.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,6 @@
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
-#include <contrib/dev/acpica/include/acparser.h>
#include <contrib/dev/acpica/include/amlcode.h>
#include <contrib/dev/acpica/include/acnamesp.h>
#include <contrib/dev/acpica/include/acdisasm.h>
@@ -226,7 +225,8 @@ AcpiDmNamestring (
/* Handle all Scope Prefix operators */
- while (AcpiPsIsPrefixChar (ACPI_GET8 (Name)))
+ while (ACPI_IS_ROOT_PREFIX (ACPI_GET8 (Name)) ||
+ ACPI_IS_PARENT_PREFIX (ACPI_GET8 (Name)))
{
/* Append prefix character */
@@ -323,7 +323,7 @@ AcpiDmDisplayPath (
if ((NamePath) &&
(NamePath->Common.Value.String) &&
- (NamePath->Common.Value.String[0] == '\\'))
+ (ACPI_IS_ROOT_PREFIX (NamePath->Common.Value.String[0])))
{
AcpiDmNamestring (NamePath->Common.Value.String);
return;
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmobject.c b/sys/contrib/dev/acpica/components/disassembler/dmobject.c
index 6801af5..5dde74a 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmobject.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmobject.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
index 822a1a5..01672fa 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrc.c b/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
index 5217084..fd391b3 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -415,7 +415,8 @@ AcpiDmIsResourceTemplate (
/* Walk the byte list, abort on any invalid descriptor type or length */
- Status = AcpiUtWalkAmlResources (WalkState, Aml, Length, NULL, &EndAml);
+ Status = AcpiUtWalkAmlResources (WalkState, Aml, Length,
+ NULL, ACPI_CAST_INDIRECT_PTR (void, &EndAml));
if (ACPI_FAILURE (Status))
{
return (AE_TYPE);
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
index 700370f..c468bbd 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
index a3d046d..5da7df4 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
index 7957920..778d663 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmutils.c b/sys/contrib/dev/acpica/components/disassembler/dmutils.c
index 7ac56b7..5d35d83 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmutils.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmwalk.c b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
index f0d65b6..67a7965 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -441,7 +441,30 @@ AcpiDmDescendingOp (
* This is a first-level element of a term list,
* indent a new line
*/
- AcpiDmIndent (Level);
+ switch (Op->Common.AmlOpcode)
+ {
+ case AML_NOOP_OP:
+ /*
+ * Optionally just ignore this opcode. Some tables use
+ * NoOp opcodes for "padding" out packages that the BIOS
+ * changes dynamically. This can leave hundreds or
+ * thousands of NoOp opcodes that if disassembled,
+ * cannot be compiled because they are syntactically
+ * incorrect.
+ */
+ if (AcpiGbl_IgnoreNoopOperator)
+ {
+ Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
+ return (AE_OK);
+ }
+
+ /* Fallthrough */
+
+ default:
+ AcpiDmIndent (Level);
+ break;
+ }
+
Info->LastLevel = Level;
Info->Count = 0;
}
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsargs.c b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
index 0602905..2c574ca1 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c b/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
index 198ba0e..bcc58ca 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsfield.c b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
index 3574aa7..1ab8c3b 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsinit.c b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
index c3766fd..7aca0e8 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
index b3548e9..d2dccaf 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -163,6 +163,7 @@ AcpiDsCreateMethodMutex (
Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
if (ACPI_FAILURE (Status))
{
+ AcpiUtDeleteObjectDesc (MutexDesc);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c b/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
index 76c82af..164e0ef 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsobject.c b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
index 69985a9..d718929 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -541,7 +541,7 @@ AcpiDsBuildInternalPackageObj (
}
ACPI_INFO ((AE_INFO,
- "Actual Package length (%u) is larger than NumElements field (%u), truncated\n",
+ "Actual Package length (%u) is larger than NumElements field (%u), truncated",
i, ElementCount));
}
else if (i < ElementCount)
@@ -734,7 +734,7 @@ AcpiDsInitObjectFromOp (
/* Truncate value if we are executing from a 32-bit ACPI table */
#ifndef ACPI_NO_METHOD_EXECUTION
- AcpiExTruncateFor32bitTable (ObjDesc);
+ (void) AcpiExTruncateFor32bitTable (ObjDesc);
#endif
break;
@@ -756,8 +756,17 @@ AcpiDsInitObjectFromOp (
case AML_TYPE_LITERAL:
ObjDesc->Integer.Value = Op->Common.Value.Integer;
+
#ifndef ACPI_NO_METHOD_EXECUTION
- AcpiExTruncateFor32bitTable (ObjDesc);
+ if (AcpiExTruncateFor32bitTable (ObjDesc))
+ {
+ /* Warn if we found a 64-bit constant in a 32-bit table */
+
+ ACPI_WARNING ((AE_INFO,
+ "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
+ ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
+ (UINT32) ObjDesc->Integer.Value));
+ }
#endif
break;
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c b/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
index 8c7d314..7fed5fd 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsutils.c b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
index 13ef960..3b44c67 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -201,7 +201,7 @@ AcpiDsIsResultUsed (
if (!Op)
{
ACPI_ERROR ((AE_INFO, "Null Op"));
- return_UINT8 (TRUE);
+ return_VALUE (TRUE);
}
/*
@@ -231,7 +231,7 @@ AcpiDsIsResultUsed (
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"At Method level, result of [%s] not used\n",
AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
- return_UINT8 (FALSE);
+ return_VALUE (FALSE);
}
/* Get info on the parent. The RootOp is AML_SCOPE */
@@ -241,7 +241,7 @@ AcpiDsIsResultUsed (
{
ACPI_ERROR ((AE_INFO,
"Unknown parent opcode Op=%p", Op));
- return_UINT8 (FALSE);
+ return_VALUE (FALSE);
}
/*
@@ -331,7 +331,7 @@ ResultUsed:
AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
- return_UINT8 (TRUE);
+ return_VALUE (TRUE);
ResultNotUsed:
@@ -340,7 +340,7 @@ ResultNotUsed:
AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
- return_UINT8 (FALSE);
+ return_VALUE (FALSE);
}
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswexec.c b/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
index eed103d..f92f49b 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -164,7 +164,7 @@ AcpiDsGetPredicateValue (
/* Truncate the predicate to 32-bits if necessary */
- AcpiExTruncateFor32bitTable (LocalObjDesc);
+ (void) AcpiExTruncateFor32bitTable (LocalObjDesc);
/*
* Save the result of the predicate evaluation on
@@ -739,7 +739,7 @@ AcpiDsExecEndOp (
* ACPI 2.0 support for 64-bit integers: Truncate numeric
* result value if we are executing from a 32-bit ACPI table
*/
- AcpiExTruncateFor32bitTable (WalkState->ResultObj);
+ (void) AcpiExTruncateFor32bitTable (WalkState->ResultObj);
/*
* Check if we just completed the evaluation of a
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload.c b/sys/contrib/dev/acpica/components/dispatcher/dswload.c
index 53257b5..f86dea2 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswload.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload2.c b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
index c3f7bef..9114895 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -236,7 +236,7 @@ AcpiDsLoad2BeginOp (
*/
ACPI_WARNING ((AE_INFO,
"Type override - [%4.4s] had invalid type (%s) "
- "for Scope operator, changed to type ANY\n",
+ "for Scope operator, changed to type ANY",
AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type)));
Node->Type = ACPI_TYPE_ANY;
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswscope.c b/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
index bdbd374..8530b5d 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswstate.c b/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
index bdea4d7..8fd36bf 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evevent.c b/sys/contrib/dev/acpica/components/events/evevent.c
index 5706f8f..adad8c8 100644
--- a/sys/contrib/dev/acpica/components/events/evevent.c
+++ b/sys/contrib/dev/acpica/components/events/evevent.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evglock.c b/sys/contrib/dev/acpica/components/events/evglock.c
index 894e132..4cec447 100644
--- a/sys/contrib/dev/acpica/components/events/evglock.c
+++ b/sys/contrib/dev/acpica/components/events/evglock.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evgpe.c b/sys/contrib/dev/acpica/components/events/evgpe.c
index eb96d72..75ad956 100644
--- a/sys/contrib/dev/acpica/components/events/evgpe.c
+++ b/sys/contrib/dev/acpica/components/events/evgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -770,7 +770,7 @@ AcpiEvGpeDispatch (
{
ACPI_EXCEPTION ((AE_INFO, Status,
"Unable to clear GPE%02X", GpeNumber));
- return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
+ return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
}
@@ -788,7 +788,7 @@ AcpiEvGpeDispatch (
{
ACPI_EXCEPTION ((AE_INFO, Status,
"Unable to disable GPE%02X", GpeNumber));
- return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
+ return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
/*
@@ -846,7 +846,7 @@ AcpiEvGpeDispatch (
break;
}
- return_UINT32 (ACPI_INTERRUPT_HANDLED);
+ return_VALUE (ACPI_INTERRUPT_HANDLED);
}
#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/sys/contrib/dev/acpica/components/events/evgpeblk.c b/sys/contrib/dev/acpica/components/events/evgpeblk.c
index 6a1c04a..f223b1a 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeblk.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeblk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -443,8 +443,8 @@ AcpiEvCreateGpeBlock (
(*ReturnGpeBlock) = GpeBlock;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
+ " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X\n",
(UINT32) GpeBlock->BlockBaseNumber,
(UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)),
GpeDevice->Name.Ascii, GpeBlock->RegisterCount,
@@ -539,8 +539,10 @@ AcpiEvInitializeGpeBlock (
if (GpeEnabledCount)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Enabled %u GPEs in this block\n", GpeEnabledCount));
+ ACPI_INFO ((AE_INFO,
+ "Enabled %u GPEs in block %02X to %02X", GpeEnabledCount,
+ (UINT32) GpeBlock->BlockBaseNumber,
+ (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1))));
}
GpeBlock->Initialized = TRUE;
diff --git a/sys/contrib/dev/acpica/components/events/evgpeinit.c b/sys/contrib/dev/acpica/components/events/evgpeinit.c
index 9266d60..9e8630d 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeinit.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -94,6 +94,9 @@ AcpiEvGpeInitialize (
ACPI_FUNCTION_TRACE (EvGpeInitialize);
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
+ "Initializing General Purpose Events (GPEs):\n"));
+
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (Status))
{
diff --git a/sys/contrib/dev/acpica/components/events/evgpeutil.c b/sys/contrib/dev/acpica/components/events/evgpeutil.c
index 7f7bb3c..1841f9d 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeutil.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeutil.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evhandler.c b/sys/contrib/dev/acpica/components/events/evhandler.c
new file mode 100644
index 0000000..f32ba65
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/events/evhandler.c
@@ -0,0 +1,578 @@
+/******************************************************************************
+ *
+ * Module Name: evhandler - Support for Address Space handlers
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#define __EVHANDLER_C__
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acevents.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+#include <contrib/dev/acpica/include/acinterp.h>
+
+#define _COMPONENT ACPI_EVENTS
+ ACPI_MODULE_NAME ("evhandler")
+
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiEvInstallHandler (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+/* These are the address spaces that will get default handlers */
+
+UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
+{
+ ACPI_ADR_SPACE_SYSTEM_MEMORY,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ ACPI_ADR_SPACE_PCI_CONFIG,
+ ACPI_ADR_SPACE_DATA_TABLE
+};
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvInstallRegionHandlers
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Installs the core subsystem default address space handlers.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvInstallRegionHandlers (
+ void)
+{
+ ACPI_STATUS Status;
+ UINT32 i;
+
+
+ ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
+
+
+ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /*
+ * All address spaces (PCI Config, EC, SMBus) are scope dependent and
+ * registration must occur for a specific device.
+ *
+ * In the case of the system memory and IO address spaces there is
+ * currently no device associated with the address space. For these we
+ * use the root.
+ *
+ * We install the default PCI config space handler at the root so that
+ * this space is immediately available even though the we have not
+ * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
+ * specification which states that the PCI config space must be always
+ * available -- even though we are nowhere near ready to find the PCI root
+ * buses at this point.
+ *
+ * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
+ * has already been installed (via AcpiInstallAddressSpaceHandler).
+ * Similar for AE_SAME_HANDLER.
+ */
+ for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
+ {
+ Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
+ AcpiGbl_DefaultAddressSpaces[i],
+ ACPI_DEFAULT_HANDLER, NULL, NULL);
+ switch (Status)
+ {
+ case AE_OK:
+ case AE_SAME_HANDLER:
+ case AE_ALREADY_EXISTS:
+
+ /* These exceptions are all OK */
+
+ Status = AE_OK;
+ break;
+
+ default:
+
+ goto UnlockAndExit;
+ }
+ }
+
+UnlockAndExit:
+ (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvHasDefaultHandler
+ *
+ * PARAMETERS: Node - Namespace node for the device
+ * SpaceId - The address space ID
+ *
+ * RETURN: TRUE if default handler is installed, FALSE otherwise
+ *
+ * DESCRIPTION: Check if the default handler is installed for the requested
+ * space ID.
+ *
+ ******************************************************************************/
+
+BOOLEAN
+AcpiEvHasDefaultHandler (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_ADR_SPACE_TYPE SpaceId)
+{
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_OPERAND_OBJECT *HandlerObj;
+
+
+ /* Must have an existing internal object */
+
+ ObjDesc = AcpiNsGetAttachedObject (Node);
+ if (ObjDesc)
+ {
+ HandlerObj = ObjDesc->Device.Handler;
+
+ /* Walk the linked list of handlers for this object */
+
+ while (HandlerObj)
+ {
+ if (HandlerObj->AddressSpace.SpaceId == SpaceId)
+ {
+ if (HandlerObj->AddressSpace.HandlerFlags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
+ {
+ return (TRUE);
+ }
+ }
+
+ HandlerObj = HandlerObj->AddressSpace.Next;
+ }
+ }
+
+ return (FALSE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvInstallHandler
+ *
+ * PARAMETERS: WalkNamespace callback
+ *
+ * DESCRIPTION: This routine installs an address handler into objects that are
+ * of type Region or Device.
+ *
+ * If the Object is a Device, and the device has a handler of
+ * the same type then the search is terminated in that branch.
+ *
+ * This is because the existing handler is closer in proximity
+ * to any more regions than the one we are trying to install.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiEvInstallHandler (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_OPERAND_OBJECT *HandlerObj;
+ ACPI_OPERAND_OBJECT *NextHandlerObj;
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_NAMESPACE_NODE *Node;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_NAME (EvInstallHandler);
+
+
+ HandlerObj = (ACPI_OPERAND_OBJECT *) Context;
+
+ /* Parameter validation */
+
+ if (!HandlerObj)
+ {
+ return (AE_OK);
+ }
+
+ /* Convert and validate the device handle */
+
+ Node = AcpiNsValidateHandle (ObjHandle);
+ if (!Node)
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * We only care about regions and objects that are allowed to have
+ * address space handlers
+ */
+ if ((Node->Type != ACPI_TYPE_DEVICE) &&
+ (Node->Type != ACPI_TYPE_REGION) &&
+ (Node != AcpiGbl_RootNode))
+ {
+ return (AE_OK);
+ }
+
+ /* Check for an existing internal object */
+
+ ObjDesc = AcpiNsGetAttachedObject (Node);
+ if (!ObjDesc)
+ {
+ /* No object, just exit */
+
+ return (AE_OK);
+ }
+
+ /* Devices are handled different than regions */
+
+ if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
+ {
+ /* Check if this Device already has a handler for this address space */
+
+ NextHandlerObj = ObjDesc->Device.Handler;
+ while (NextHandlerObj)
+ {
+ /* Found a handler, is it for the same address space? */
+
+ if (NextHandlerObj->AddressSpace.SpaceId ==
+ HandlerObj->AddressSpace.SpaceId)
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Found handler for region [%s] in device %p(%p) "
+ "handler %p\n",
+ AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
+ ObjDesc, NextHandlerObj, HandlerObj));
+
+ /*
+ * Since the object we found it on was a device, then it
+ * means that someone has already installed a handler for
+ * the branch of the namespace from this device on. Just
+ * bail out telling the walk routine to not traverse this
+ * branch. This preserves the scoping rule for handlers.
+ */
+ return (AE_CTRL_DEPTH);
+ }
+
+ /* Walk the linked list of handlers attached to this device */
+
+ NextHandlerObj = NextHandlerObj->AddressSpace.Next;
+ }
+
+ /*
+ * As long as the device didn't have a handler for this space we
+ * don't care about it. We just ignore it and proceed.
+ */
+ return (AE_OK);
+ }
+
+ /* Object is a Region */
+
+ if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
+ {
+ /* This region is for a different address space, just ignore it */
+
+ return (AE_OK);
+ }
+
+ /*
+ * Now we have a region and it is for the handler's address space type.
+ *
+ * First disconnect region for any previous handler (if any)
+ */
+ AcpiEvDetachRegion (ObjDesc, FALSE);
+
+ /* Connect the region to the new handler */
+
+ Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvInstallSpaceHandler
+ *
+ * PARAMETERS: Node - Namespace node for the device
+ * SpaceId - The address space ID
+ * Handler - Address of the handler
+ * Setup - Address of the setup function
+ * Context - Value passed to the handler on each access
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
+ * Assumes namespace is locked
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvInstallSpaceHandler (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_ADR_SPACE_TYPE SpaceId,
+ ACPI_ADR_SPACE_HANDLER Handler,
+ ACPI_ADR_SPACE_SETUP Setup,
+ void *Context)
+{
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_OPERAND_OBJECT *HandlerObj;
+ ACPI_STATUS Status;
+ ACPI_OBJECT_TYPE Type;
+ UINT8 Flags = 0;
+
+
+ ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
+
+
+ /*
+ * This registration is valid for only the types below and the root. This
+ * is where the default handlers get placed.
+ */
+ if ((Node->Type != ACPI_TYPE_DEVICE) &&
+ (Node->Type != ACPI_TYPE_PROCESSOR) &&
+ (Node->Type != ACPI_TYPE_THERMAL) &&
+ (Node != AcpiGbl_RootNode))
+ {
+ Status = AE_BAD_PARAMETER;
+ goto UnlockAndExit;
+ }
+
+ if (Handler == ACPI_DEFAULT_HANDLER)
+ {
+ Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
+
+ switch (SpaceId)
+ {
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+ Handler = AcpiExSystemMemorySpaceHandler;
+ Setup = AcpiEvSystemMemoryRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ Handler = AcpiExSystemIoSpaceHandler;
+ Setup = AcpiEvIoSpaceRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_PCI_CONFIG:
+ Handler = AcpiExPciConfigSpaceHandler;
+ Setup = AcpiEvPciConfigRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_CMOS:
+ Handler = AcpiExCmosSpaceHandler;
+ Setup = AcpiEvCmosRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_PCI_BAR_TARGET:
+ Handler = AcpiExPciBarSpaceHandler;
+ Setup = AcpiEvPciBarRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_DATA_TABLE:
+ Handler = AcpiExDataTableSpaceHandler;
+ Setup = NULL;
+ break;
+
+ default:
+ Status = AE_BAD_PARAMETER;
+ goto UnlockAndExit;
+ }
+ }
+
+ /* If the caller hasn't specified a setup routine, use the default */
+
+ if (!Setup)
+ {
+ Setup = AcpiEvDefaultRegionSetup;
+ }
+
+ /* Check for an existing internal object */
+
+ ObjDesc = AcpiNsGetAttachedObject (Node);
+ if (ObjDesc)
+ {
+ /*
+ * The attached device object already exists. Make sure the handler
+ * is not already installed.
+ */
+ HandlerObj = ObjDesc->Device.Handler;
+
+ /* Walk the handler list for this device */
+
+ while (HandlerObj)
+ {
+ /* Same SpaceId indicates a handler already installed */
+
+ if (HandlerObj->AddressSpace.SpaceId == SpaceId)
+ {
+ if (HandlerObj->AddressSpace.Handler == Handler)
+ {
+ /*
+ * It is (relatively) OK to attempt to install the SAME
+ * handler twice. This can easily happen with the
+ * PCI_Config space.
+ */
+ Status = AE_SAME_HANDLER;
+ goto UnlockAndExit;
+ }
+ else
+ {
+ /* A handler is already installed */
+
+ Status = AE_ALREADY_EXISTS;
+ }
+ goto UnlockAndExit;
+ }
+
+ /* Walk the linked list of handlers */
+
+ HandlerObj = HandlerObj->AddressSpace.Next;
+ }
+ }
+ else
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Creating object on Device %p while installing handler\n", Node));
+
+ /* ObjDesc does not exist, create one */
+
+ if (Node->Type == ACPI_TYPE_ANY)
+ {
+ Type = ACPI_TYPE_DEVICE;
+ }
+ else
+ {
+ Type = Node->Type;
+ }
+
+ ObjDesc = AcpiUtCreateInternalObject (Type);
+ if (!ObjDesc)
+ {
+ Status = AE_NO_MEMORY;
+ goto UnlockAndExit;
+ }
+
+ /* Init new descriptor */
+
+ ObjDesc->Common.Type = (UINT8) Type;
+
+ /* Attach the new object to the Node */
+
+ Status = AcpiNsAttachObject (Node, ObjDesc, Type);
+
+ /* Remove local reference to the object */
+
+ AcpiUtRemoveReference (ObjDesc);
+
+ if (ACPI_FAILURE (Status))
+ {
+ goto UnlockAndExit;
+ }
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+ AcpiUtGetRegionName (SpaceId), SpaceId,
+ AcpiUtGetNodeName (Node), Node, ObjDesc));
+
+ /*
+ * Install the handler
+ *
+ * At this point there is no existing handler. Just allocate the object
+ * for the handler and link it into the list.
+ */
+ HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
+ if (!HandlerObj)
+ {
+ Status = AE_NO_MEMORY;
+ goto UnlockAndExit;
+ }
+
+ /* Init handler obj */
+
+ HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
+ HandlerObj->AddressSpace.HandlerFlags = Flags;
+ HandlerObj->AddressSpace.RegionList = NULL;
+ HandlerObj->AddressSpace.Node = Node;
+ HandlerObj->AddressSpace.Handler = Handler;
+ HandlerObj->AddressSpace.Context = Context;
+ HandlerObj->AddressSpace.Setup = Setup;
+
+ /* Install at head of Device.AddressSpace list */
+
+ HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
+
+ /*
+ * The Device object is the first reference on the HandlerObj.
+ * Each region that uses the handler adds a reference.
+ */
+ ObjDesc->Device.Handler = HandlerObj;
+
+ /*
+ * Walk the namespace finding all of the regions this
+ * handler will manage.
+ *
+ * Start at the device and search the branch toward
+ * the leaf nodes until either the leaf is encountered or
+ * a device is detected that has an address handler of the
+ * same type.
+ *
+ * In either case, back up and search down the remainder
+ * of the branch
+ */
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
+ HandlerObj, NULL);
+
+UnlockAndExit:
+ return_ACPI_STATUS (Status);
+}
diff --git a/sys/contrib/dev/acpica/components/events/evmisc.c b/sys/contrib/dev/acpica/components/events/evmisc.c
index b63aafc..034b8e0 100644
--- a/sys/contrib/dev/acpica/components/events/evmisc.c
+++ b/sys/contrib/dev/acpica/components/events/evmisc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evregion.c b/sys/contrib/dev/acpica/components/events/evregion.c
index d149181..7bfb1f5 100644
--- a/sys/contrib/dev/acpica/components/events/evregion.c
+++ b/sys/contrib/dev/acpica/components/events/evregion.c
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
+ * Module Name: evregion - Operation Region support
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,12 +54,9 @@
ACPI_MODULE_NAME ("evregion")
-/* Local prototypes */
+extern UINT8 AcpiGbl_DefaultAddressSpaces[];
-static BOOLEAN
-AcpiEvHasDefaultHandler (
- ACPI_NAMESPACE_NODE *Node,
- ACPI_ADR_SPACE_TYPE SpaceId);
+/* Local prototypes */
static void
AcpiEvOrphanEcRegMethod (
@@ -72,152 +69,6 @@ AcpiEvRegRun (
void *Context,
void **ReturnValue);
-static ACPI_STATUS
-AcpiEvInstallHandler (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue);
-
-/* These are the address spaces that will get default handlers */
-
-#define ACPI_NUM_DEFAULT_SPACES 4
-
-static UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
-{
- ACPI_ADR_SPACE_SYSTEM_MEMORY,
- ACPI_ADR_SPACE_SYSTEM_IO,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_ADR_SPACE_DATA_TABLE
-};
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvInstallRegionHandlers
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Installs the core subsystem default address space handlers.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiEvInstallRegionHandlers (
- void)
-{
- ACPI_STATUS Status;
- UINT32 i;
-
-
- ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
-
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /*
- * All address spaces (PCI Config, EC, SMBus) are scope dependent and
- * registration must occur for a specific device.
- *
- * In the case of the system memory and IO address spaces there is
- * currently no device associated with the address space. For these we
- * use the root.
- *
- * We install the default PCI config space handler at the root so that
- * this space is immediately available even though the we have not
- * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
- * specification which states that the PCI config space must be always
- * available -- even though we are nowhere near ready to find the PCI root
- * buses at this point.
- *
- * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
- * has already been installed (via AcpiInstallAddressSpaceHandler).
- * Similar for AE_SAME_HANDLER.
- */
- for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
- {
- Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
- AcpiGbl_DefaultAddressSpaces[i],
- ACPI_DEFAULT_HANDLER, NULL, NULL);
- switch (Status)
- {
- case AE_OK:
- case AE_SAME_HANDLER:
- case AE_ALREADY_EXISTS:
-
- /* These exceptions are all OK */
-
- Status = AE_OK;
- break;
-
- default:
-
- goto UnlockAndExit;
- }
- }
-
-UnlockAndExit:
- (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvHasDefaultHandler
- *
- * PARAMETERS: Node - Namespace node for the device
- * SpaceId - The address space ID
- *
- * RETURN: TRUE if default handler is installed, FALSE otherwise
- *
- * DESCRIPTION: Check if the default handler is installed for the requested
- * space ID.
- *
- ******************************************************************************/
-
-static BOOLEAN
-AcpiEvHasDefaultHandler (
- ACPI_NAMESPACE_NODE *Node,
- ACPI_ADR_SPACE_TYPE SpaceId)
-{
- ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_OPERAND_OBJECT *HandlerObj;
-
-
- /* Must have an existing internal object */
-
- ObjDesc = AcpiNsGetAttachedObject (Node);
- if (ObjDesc)
- {
- HandlerObj = ObjDesc->Device.Handler;
-
- /* Walk the linked list of handlers for this object */
-
- while (HandlerObj)
- {
- if (HandlerObj->AddressSpace.SpaceId == SpaceId)
- {
- if (HandlerObj->AddressSpace.HandlerFlags &
- ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
- {
- return (TRUE);
- }
- }
-
- HandlerObj = HandlerObj->AddressSpace.Next;
- }
- }
-
- return (FALSE);
-}
-
/*******************************************************************************
*
@@ -275,100 +126,6 @@ AcpiEvInitializeOpRegions (
/*******************************************************************************
*
- * FUNCTION: AcpiEvExecuteRegMethod
- *
- * PARAMETERS: RegionObj - Region object
- * Function - Passed to _REG: On (1) or Off (0)
- *
- * RETURN: Status
- *
- * DESCRIPTION: Execute _REG method for a region
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiEvExecuteRegMethod (
- ACPI_OPERAND_OBJECT *RegionObj,
- UINT32 Function)
-{
- ACPI_EVALUATE_INFO *Info;
- ACPI_OPERAND_OBJECT *Args[3];
- ACPI_OPERAND_OBJECT *RegionObj2;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
-
-
- RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
- if (!RegionObj2)
- {
- return_ACPI_STATUS (AE_NOT_EXIST);
- }
-
- if (RegionObj2->Extra.Method_REG == NULL)
- {
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Allocate and initialize the evaluation information block */
-
- Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
- if (!Info)
- {
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
-
- Info->PrefixNode = RegionObj2->Extra.Method_REG;
- Info->Pathname = NULL;
- Info->Parameters = Args;
- Info->Flags = ACPI_IGNORE_RETURN_VALUE;
-
- /*
- * The _REG method has two arguments:
- *
- * Arg0 - Integer:
- * Operation region space ID Same value as RegionObj->Region.SpaceId
- *
- * Arg1 - Integer:
- * connection status 1 for connecting the handler, 0 for disconnecting
- * the handler (Passed as a parameter)
- */
- Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
- if (!Args[0])
- {
- Status = AE_NO_MEMORY;
- goto Cleanup1;
- }
-
- Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
- if (!Args[1])
- {
- Status = AE_NO_MEMORY;
- goto Cleanup2;
- }
-
- Args[2] = NULL; /* Terminate list */
-
- /* Execute the method, no return value */
-
- ACPI_DEBUG_EXEC (
- AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
-
- Status = AcpiNsEvaluate (Info);
- AcpiUtRemoveReference (Args[1]);
-
-Cleanup2:
- AcpiUtRemoveReference (Args[0]);
-
-Cleanup1:
- ACPI_FREE (Info);
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiEvAddressSpaceDispatch
*
* PARAMETERS: RegionObj - Internal region object
@@ -762,377 +519,94 @@ AcpiEvAttachRegion (
/*******************************************************************************
*
- * FUNCTION: AcpiEvInstallHandler
- *
- * PARAMETERS: WalkNamespace callback
- *
- * DESCRIPTION: This routine installs an address handler into objects that are
- * of type Region or Device.
- *
- * If the Object is a Device, and the device has a handler of
- * the same type then the search is terminated in that branch.
- *
- * This is because the existing handler is closer in proximity
- * to any more regions than the one we are trying to install.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiEvInstallHandler (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue)
-{
- ACPI_OPERAND_OBJECT *HandlerObj;
- ACPI_OPERAND_OBJECT *NextHandlerObj;
- ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_NAMESPACE_NODE *Node;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_NAME (EvInstallHandler);
-
-
- HandlerObj = (ACPI_OPERAND_OBJECT *) Context;
-
- /* Parameter validation */
-
- if (!HandlerObj)
- {
- return (AE_OK);
- }
-
- /* Convert and validate the device handle */
-
- Node = AcpiNsValidateHandle (ObjHandle);
- if (!Node)
- {
- return (AE_BAD_PARAMETER);
- }
-
- /*
- * We only care about regions and objects that are allowed to have
- * address space handlers
- */
- if ((Node->Type != ACPI_TYPE_DEVICE) &&
- (Node->Type != ACPI_TYPE_REGION) &&
- (Node != AcpiGbl_RootNode))
- {
- return (AE_OK);
- }
-
- /* Check for an existing internal object */
-
- ObjDesc = AcpiNsGetAttachedObject (Node);
- if (!ObjDesc)
- {
- /* No object, just exit */
-
- return (AE_OK);
- }
-
- /* Devices are handled different than regions */
-
- if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
- {
- /* Check if this Device already has a handler for this address space */
-
- NextHandlerObj = ObjDesc->Device.Handler;
- while (NextHandlerObj)
- {
- /* Found a handler, is it for the same address space? */
-
- if (NextHandlerObj->AddressSpace.SpaceId ==
- HandlerObj->AddressSpace.SpaceId)
- {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Found handler for region [%s] in device %p(%p) "
- "handler %p\n",
- AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
- ObjDesc, NextHandlerObj, HandlerObj));
-
- /*
- * Since the object we found it on was a device, then it
- * means that someone has already installed a handler for
- * the branch of the namespace from this device on. Just
- * bail out telling the walk routine to not traverse this
- * branch. This preserves the scoping rule for handlers.
- */
- return (AE_CTRL_DEPTH);
- }
-
- /* Walk the linked list of handlers attached to this device */
-
- NextHandlerObj = NextHandlerObj->AddressSpace.Next;
- }
-
- /*
- * As long as the device didn't have a handler for this space we
- * don't care about it. We just ignore it and proceed.
- */
- return (AE_OK);
- }
-
- /* Object is a Region */
-
- if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
- {
- /* This region is for a different address space, just ignore it */
-
- return (AE_OK);
- }
-
- /*
- * Now we have a region and it is for the handler's address space type.
- *
- * First disconnect region for any previous handler (if any)
- */
- AcpiEvDetachRegion (ObjDesc, FALSE);
-
- /* Connect the region to the new handler */
-
- Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
- return (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvInstallSpaceHandler
+ * FUNCTION: AcpiEvExecuteRegMethod
*
- * PARAMETERS: Node - Namespace node for the device
- * SpaceId - The address space ID
- * Handler - Address of the handler
- * Setup - Address of the setup function
- * Context - Value passed to the handler on each access
+ * PARAMETERS: RegionObj - Region object
+ * Function - Passed to _REG: On (1) or Off (0)
*
* RETURN: Status
*
- * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
- * Assumes namespace is locked
+ * DESCRIPTION: Execute _REG method for a region
*
******************************************************************************/
ACPI_STATUS
-AcpiEvInstallSpaceHandler (
- ACPI_NAMESPACE_NODE *Node,
- ACPI_ADR_SPACE_TYPE SpaceId,
- ACPI_ADR_SPACE_HANDLER Handler,
- ACPI_ADR_SPACE_SETUP Setup,
- void *Context)
+AcpiEvExecuteRegMethod (
+ ACPI_OPERAND_OBJECT *RegionObj,
+ UINT32 Function)
{
- ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_OPERAND_OBJECT *HandlerObj;
+ ACPI_EVALUATE_INFO *Info;
+ ACPI_OPERAND_OBJECT *Args[3];
+ ACPI_OPERAND_OBJECT *RegionObj2;
ACPI_STATUS Status;
- ACPI_OBJECT_TYPE Type;
- UINT8 Flags = 0;
-
- ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
+ ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
- /*
- * This registration is valid for only the types below and the root. This
- * is where the default handlers get placed.
- */
- if ((Node->Type != ACPI_TYPE_DEVICE) &&
- (Node->Type != ACPI_TYPE_PROCESSOR) &&
- (Node->Type != ACPI_TYPE_THERMAL) &&
- (Node != AcpiGbl_RootNode))
- {
- Status = AE_BAD_PARAMETER;
- goto UnlockAndExit;
- }
- if (Handler == ACPI_DEFAULT_HANDLER)
+ RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
+ if (!RegionObj2)
{
- Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
-
- switch (SpaceId)
- {
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- Handler = AcpiExSystemMemorySpaceHandler;
- Setup = AcpiEvSystemMemoryRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_SYSTEM_IO:
- Handler = AcpiExSystemIoSpaceHandler;
- Setup = AcpiEvIoSpaceRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_PCI_CONFIG:
- Handler = AcpiExPciConfigSpaceHandler;
- Setup = AcpiEvPciConfigRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_CMOS:
- Handler = AcpiExCmosSpaceHandler;
- Setup = AcpiEvCmosRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_PCI_BAR_TARGET:
- Handler = AcpiExPciBarSpaceHandler;
- Setup = AcpiEvPciBarRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_DATA_TABLE:
- Handler = AcpiExDataTableSpaceHandler;
- Setup = NULL;
- break;
-
- default:
- Status = AE_BAD_PARAMETER;
- goto UnlockAndExit;
- }
+ return_ACPI_STATUS (AE_NOT_EXIST);
}
- /* If the caller hasn't specified a setup routine, use the default */
-
- if (!Setup)
+ if (RegionObj2->Extra.Method_REG == NULL)
{
- Setup = AcpiEvDefaultRegionSetup;
+ return_ACPI_STATUS (AE_OK);
}
- /* Check for an existing internal object */
-
- ObjDesc = AcpiNsGetAttachedObject (Node);
- if (ObjDesc)
- {
- /*
- * The attached device object already exists. Make sure the handler
- * is not already installed.
- */
- HandlerObj = ObjDesc->Device.Handler;
-
- /* Walk the handler list for this device */
-
- while (HandlerObj)
- {
- /* Same SpaceId indicates a handler already installed */
-
- if (HandlerObj->AddressSpace.SpaceId == SpaceId)
- {
- if (HandlerObj->AddressSpace.Handler == Handler)
- {
- /*
- * It is (relatively) OK to attempt to install the SAME
- * handler twice. This can easily happen with the
- * PCI_Config space.
- */
- Status = AE_SAME_HANDLER;
- goto UnlockAndExit;
- }
- else
- {
- /* A handler is already installed */
-
- Status = AE_ALREADY_EXISTS;
- }
- goto UnlockAndExit;
- }
-
- /* Walk the linked list of handlers */
+ /* Allocate and initialize the evaluation information block */
- HandlerObj = HandlerObj->AddressSpace.Next;
- }
- }
- else
+ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
+ if (!Info)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Creating object on Device %p while installing handler\n", Node));
-
- /* ObjDesc does not exist, create one */
-
- if (Node->Type == ACPI_TYPE_ANY)
- {
- Type = ACPI_TYPE_DEVICE;
- }
- else
- {
- Type = Node->Type;
- }
-
- ObjDesc = AcpiUtCreateInternalObject (Type);
- if (!ObjDesc)
- {
- Status = AE_NO_MEMORY;
- goto UnlockAndExit;
- }
-
- /* Init new descriptor */
-
- ObjDesc->Common.Type = (UINT8) Type;
-
- /* Attach the new object to the Node */
-
- Status = AcpiNsAttachObject (Node, ObjDesc, Type);
-
- /* Remove local reference to the object */
-
- AcpiUtRemoveReference (ObjDesc);
-
- if (ACPI_FAILURE (Status))
- {
- goto UnlockAndExit;
- }
+ return_ACPI_STATUS (AE_NO_MEMORY);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
- AcpiUtGetRegionName (SpaceId), SpaceId,
- AcpiUtGetNodeName (Node), Node, ObjDesc));
+ Info->PrefixNode = RegionObj2->Extra.Method_REG;
+ Info->Pathname = NULL;
+ Info->Parameters = Args;
+ Info->Flags = ACPI_IGNORE_RETURN_VALUE;
/*
- * Install the handler
+ * The _REG method has two arguments:
+ *
+ * Arg0 - Integer:
+ * Operation region space ID Same value as RegionObj->Region.SpaceId
*
- * At this point there is no existing handler. Just allocate the object
- * for the handler and link it into the list.
+ * Arg1 - Integer:
+ * connection status 1 for connecting the handler, 0 for disconnecting
+ * the handler (Passed as a parameter)
*/
- HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
- if (!HandlerObj)
+ Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
+ if (!Args[0])
{
Status = AE_NO_MEMORY;
- goto UnlockAndExit;
+ goto Cleanup1;
}
- /* Init handler obj */
+ Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
+ if (!Args[1])
+ {
+ Status = AE_NO_MEMORY;
+ goto Cleanup2;
+ }
- HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
- HandlerObj->AddressSpace.HandlerFlags = Flags;
- HandlerObj->AddressSpace.RegionList = NULL;
- HandlerObj->AddressSpace.Node = Node;
- HandlerObj->AddressSpace.Handler = Handler;
- HandlerObj->AddressSpace.Context = Context;
- HandlerObj->AddressSpace.Setup = Setup;
+ Args[2] = NULL; /* Terminate list */
- /* Install at head of Device.AddressSpace list */
+ /* Execute the method, no return value */
- HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
+ ACPI_DEBUG_EXEC (
+ AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
- /*
- * The Device object is the first reference on the HandlerObj.
- * Each region that uses the handler adds a reference.
- */
- ObjDesc->Device.Handler = HandlerObj;
+ Status = AcpiNsEvaluate (Info);
+ AcpiUtRemoveReference (Args[1]);
- /*
- * Walk the namespace finding all of the regions this
- * handler will manage.
- *
- * Start at the device and search the branch toward
- * the leaf nodes until either the leaf is encountered or
- * a device is detected that has an address handler of the
- * same type.
- *
- * In either case, back up and search down the remainder
- * of the branch
- */
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
- HandlerObj, NULL);
+Cleanup2:
+ AcpiUtRemoveReference (Args[0]);
-UnlockAndExit:
+Cleanup1:
+ ACPI_FREE (Info);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/events/evrgnini.c b/sys/contrib/dev/acpica/components/events/evrgnini.c
index 28c367f..90a6b02 100644
--- a/sys/contrib/dev/acpica/components/events/evrgnini.c
+++ b/sys/contrib/dev/acpica/components/events/evrgnini.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evsci.c b/sys/contrib/dev/acpica/components/events/evsci.c
index 0e7a65a..340c400 100644
--- a/sys/contrib/dev/acpica/components/events/evsci.c
+++ b/sys/contrib/dev/acpica/components/events/evsci.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -101,7 +101,7 @@ AcpiEvSciXruptHandler (
InterruptHandled |= AcpiEvGpeDetect (GpeXruptList);
AcpiSciCount++;
- return_UINT32 (InterruptHandled);
+ return_VALUE (InterruptHandled);
}
@@ -137,7 +137,7 @@ AcpiEvGpeXruptHandler (
InterruptHandled |= AcpiEvGpeDetect (GpeXruptList);
- return_UINT32 (InterruptHandled);
+ return_VALUE (InterruptHandled);
}
diff --git a/sys/contrib/dev/acpica/components/events/evxface.c b/sys/contrib/dev/acpica/components/events/evxface.c
index 4027dce..dfc4790 100644
--- a/sys/contrib/dev/acpica/components/events/evxface.c
+++ b/sys/contrib/dev/acpica/components/events/evxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evxfevnt.c b/sys/contrib/dev/acpica/components/events/evxfevnt.c
index 4e87cde..e0f36e2 100644
--- a/sys/contrib/dev/acpica/components/events/evxfevnt.c
+++ b/sys/contrib/dev/acpica/components/events/evxfevnt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evxfgpe.c b/sys/contrib/dev/acpica/components/events/evxfgpe.c
index a07751c..c574b79 100644
--- a/sys/contrib/dev/acpica/components/events/evxfgpe.c
+++ b/sys/contrib/dev/acpica/components/events/evxfgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evxfregn.c b/sys/contrib/dev/acpica/components/events/evxfregn.c
index 59238ef..95e598b 100644
--- a/sys/contrib/dev/acpica/components/events/evxfregn.c
+++ b/sys/contrib/dev/acpica/components/events/evxfregn.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exconfig.c b/sys/contrib/dev/acpica/components/executer/exconfig.c
index 99848a9..fa85344 100644
--- a/sys/contrib/dev/acpica/components/executer/exconfig.c
+++ b/sys/contrib/dev/acpica/components/executer/exconfig.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,7 @@
#include <contrib/dev/acpica/include/actables.h>
#include <contrib/dev/acpica/include/acdispat.h>
#include <contrib/dev/acpica/include/acevents.h>
+#include <contrib/dev/acpica/include/amlcode.h>
#define _COMPONENT ACPI_EXECUTER
@@ -185,14 +186,15 @@ AcpiExLoadTableOp (
(Operand[1]->String.Length > ACPI_OEM_ID_SIZE) ||
(Operand[2]->String.Length > ACPI_OEM_TABLE_ID_SIZE))
{
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS (AE_AML_STRING_LIMIT);
}
/* Find the ACPI table in the RSDT/XSDT */
- Status = AcpiTbFindTable (Operand[0]->String.Pointer,
- Operand[1]->String.Pointer,
- Operand[2]->String.Pointer, &TableIndex);
+ Status = AcpiTbFindTable (
+ Operand[0]->String.Pointer,
+ Operand[1]->String.Pointer,
+ Operand[2]->String.Pointer, &TableIndex);
if (ACPI_FAILURE (Status))
{
if (Status != AE_NOT_FOUND)
@@ -237,8 +239,8 @@ AcpiExLoadTableOp (
if (Operand[4]->String.Length > 0)
{
- if ((Operand[4]->String.Pointer[0] != '\\') &&
- (Operand[4]->String.Pointer[0] != '^'))
+ if ((Operand[4]->String.Pointer[0] != AML_ROOT_PREFIX) &&
+ (Operand[4]->String.Pointer[0] != AML_PARENT_PREFIX))
{
/*
* Path is not absolute, so it will be relative to the node
@@ -299,7 +301,7 @@ AcpiExLoadTableOp (
}
*ReturnDesc = DdbHandle;
- return_ACPI_STATUS (Status);
+ return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/executer/exconvrt.c b/sys/contrib/dev/acpica/components/executer/exconvrt.c
index c34f326..f185371 100644
--- a/sys/contrib/dev/acpica/components/executer/exconvrt.c
+++ b/sys/contrib/dev/acpica/components/executer/exconvrt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -199,7 +199,7 @@ AcpiExConvertToInteger (
/* Save the Result */
- AcpiExTruncateFor32bitTable (ReturnDesc);
+ (void) AcpiExTruncateFor32bitTable (ReturnDesc);
*ResultDesc = ReturnDesc;
return_ACPI_STATUS (AE_OK);
}
diff --git a/sys/contrib/dev/acpica/components/executer/excreate.c b/sys/contrib/dev/acpica/components/executer/excreate.c
index b409633..1851957 100644
--- a/sys/contrib/dev/acpica/components/executer/excreate.c
+++ b/sys/contrib/dev/acpica/components/executer/excreate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exdebug.c b/sys/contrib/dev/acpica/components/executer/exdebug.c
index 600118b..926f8e2 100644
--- a/sys/contrib/dev/acpica/components/executer/exdebug.c
+++ b/sys/contrib/dev/acpica/components/executer/exdebug.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exdump.c b/sys/contrib/dev/acpica/components/executer/exdump.c
index ec648f3..5d1527b 100644
--- a/sys/contrib/dev/acpica/components/executer/exdump.c
+++ b/sys/contrib/dev/acpica/components/executer/exdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -483,7 +483,9 @@ AcpiExDumpOperand (
ACPI_FUNCTION_NAME (ExDumpOperand)
- if (!((ACPI_LV_EXEC & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer)))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_EXEC, _COMPONENT))
{
return;
}
@@ -873,7 +875,9 @@ AcpiExDumpNamespaceNode (
if (!Flags)
{
- if (!((ACPI_LV_OBJECTS & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer)))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_OBJECTS, _COMPONENT))
{
return;
}
@@ -1080,7 +1084,9 @@ AcpiExDumpObjectDescriptor (
if (!Flags)
{
- if (!((ACPI_LV_OBJECTS & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer)))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_OBJECTS, _COMPONENT))
{
return_VOID;
}
diff --git a/sys/contrib/dev/acpica/components/executer/exfield.c b/sys/contrib/dev/acpica/components/executer/exfield.c
index 4a7fa24..bade0f8 100644
--- a/sys/contrib/dev/acpica/components/executer/exfield.c
+++ b/sys/contrib/dev/acpica/components/executer/exfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exfldio.c b/sys/contrib/dev/acpica/components/executer/exfldio.c
index c8c3a33..f735aec 100644
--- a/sys/contrib/dev/acpica/components/executer/exfldio.c
+++ b/sys/contrib/dev/acpica/components/executer/exfldio.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exmisc.c b/sys/contrib/dev/acpica/components/executer/exmisc.c
index cf32b76..93f6487 100644
--- a/sys/contrib/dev/acpica/components/executer/exmisc.c
+++ b/sys/contrib/dev/acpica/components/executer/exmisc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exmutex.c b/sys/contrib/dev/acpica/components/executer/exmutex.c
index c291449..a6e5e14 100644
--- a/sys/contrib/dev/acpica/components/executer/exmutex.c
+++ b/sys/contrib/dev/acpica/components/executer/exmutex.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exnames.c b/sys/contrib/dev/acpica/components/executer/exnames.c
index ce7fd66..16d89e3 100644
--- a/sys/contrib/dev/acpica/components/executer/exnames.c
+++ b/sys/contrib/dev/acpica/components/executer/exnames.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg1.c b/sys/contrib/dev/acpica/components/executer/exoparg1.c
index ac0860b..8ce02de 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg1.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg1.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg2.c b/sys/contrib/dev/acpica/components/executer/exoparg2.c
index 6e6e0d9..55defdc 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg2.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg3.c b/sys/contrib/dev/acpica/components/executer/exoparg3.c
index 33aa6fa..5823675 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg3.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg3.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg6.c b/sys/contrib/dev/acpica/components/executer/exoparg6.c
index 3677b80..41201f3 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg6.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg6.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exprep.c b/sys/contrib/dev/acpica/components/executer/exprep.c
index adf67dc..97fe872 100644
--- a/sys/contrib/dev/acpica/components/executer/exprep.c
+++ b/sys/contrib/dev/acpica/components/executer/exprep.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -292,7 +292,7 @@ AcpiExDecodeFieldAccess (
ACPI_ERROR ((AE_INFO,
"Unknown field access type 0x%X",
Access));
- return_UINT32 (0);
+ return_VALUE (0);
}
if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD)
@@ -306,7 +306,7 @@ AcpiExDecodeFieldAccess (
}
*ReturnByteAlignment = ByteAlignment;
- return_UINT32 (BitLength);
+ return_VALUE (BitLength);
}
diff --git a/sys/contrib/dev/acpica/components/executer/exregion.c b/sys/contrib/dev/acpica/components/executer/exregion.c
index abbbd84..bc3417a 100644
--- a/sys/contrib/dev/acpica/components/executer/exregion.c
+++ b/sys/contrib/dev/acpica/components/executer/exregion.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exresnte.c b/sys/contrib/dev/acpica/components/executer/exresnte.c
index 43819a9..c8937ec 100644
--- a/sys/contrib/dev/acpica/components/executer/exresnte.c
+++ b/sys/contrib/dev/acpica/components/executer/exresnte.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exresolv.c b/sys/contrib/dev/acpica/components/executer/exresolv.c
index bebf170..74a1b73 100644
--- a/sys/contrib/dev/acpica/components/executer/exresolv.c
+++ b/sys/contrib/dev/acpica/components/executer/exresolv.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exresop.c b/sys/contrib/dev/acpica/components/executer/exresop.c
index d46c2d4..0b7af01 100644
--- a/sys/contrib/dev/acpica/components/executer/exresop.c
+++ b/sys/contrib/dev/acpica/components/executer/exresop.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exstore.c b/sys/contrib/dev/acpica/components/executer/exstore.c
index ab07400..ae842d2 100644
--- a/sys/contrib/dev/acpica/components/executer/exstore.c
+++ b/sys/contrib/dev/acpica/components/executer/exstore.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -515,13 +515,28 @@ AcpiExStoreObjectToNode (
default:
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Storing %s (%p) directly into node (%p) with no implicit conversion\n",
- AcpiUtGetObjectTypeName (SourceDesc), SourceDesc, Node));
+ "Storing [%s] (%p) directly into node [%s] (%p)"
+ " with no implicit conversion\n",
+ AcpiUtGetObjectTypeName (SourceDesc), SourceDesc,
+ AcpiUtGetObjectTypeName (TargetDesc), Node));
- /* No conversions for all other types. Just attach the source object */
+ /*
+ * No conversions for all other types. Directly store a copy of
+ * the source object. NOTE: This is a departure from the ACPI
+ * spec, which states "If conversion is impossible, abort the
+ * running control method".
+ *
+ * This code implements "If conversion is impossible, treat the
+ * Store operation as a CopyObject".
+ */
+ Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
- Status = AcpiNsAttachObject (Node, SourceDesc,
- SourceDesc->Common.Type);
+ Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type);
+ AcpiUtRemoveReference (NewDesc);
break;
}
diff --git a/sys/contrib/dev/acpica/components/executer/exstoren.c b/sys/contrib/dev/acpica/components/executer/exstoren.c
index 0848e4d..a8ae148 100644
--- a/sys/contrib/dev/acpica/components/executer/exstoren.c
+++ b/sys/contrib/dev/acpica/components/executer/exstoren.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -269,7 +269,7 @@ AcpiExStoreObjectToObject (
/* Truncate value if we are executing from a 32-bit ACPI table */
- AcpiExTruncateFor32bitTable (DestDesc);
+ (void) AcpiExTruncateFor32bitTable (DestDesc);
break;
case ACPI_TYPE_STRING:
diff --git a/sys/contrib/dev/acpica/components/executer/exstorob.c b/sys/contrib/dev/acpica/components/executer/exstorob.c
index 8cf9de5..c68263c 100644
--- a/sys/contrib/dev/acpica/components/executer/exstorob.c
+++ b/sys/contrib/dev/acpica/components/executer/exstorob.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exsystem.c b/sys/contrib/dev/acpica/components/executer/exsystem.c
index 89fe6be..cc18d80 100644
--- a/sys/contrib/dev/acpica/components/executer/exsystem.c
+++ b/sys/contrib/dev/acpica/components/executer/exsystem.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exutils.c b/sys/contrib/dev/acpica/components/executer/exutils.c
index f1e9435..fb78123 100644
--- a/sys/contrib/dev/acpica/components/executer/exutils.c
+++ b/sys/contrib/dev/acpica/components/executer/exutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -229,14 +229,14 @@ AcpiExRelinquishInterpreter (
*
* PARAMETERS: ObjDesc - Object to be truncated
*
- * RETURN: none
+ * RETURN: TRUE if a truncation was performed, FALSE otherwise.
*
* DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
* 32-bit, as determined by the revision of the DSDT.
*
******************************************************************************/
-void
+BOOLEAN
AcpiExTruncateFor32bitTable (
ACPI_OPERAND_OBJECT *ObjDesc)
{
@@ -246,23 +246,27 @@ AcpiExTruncateFor32bitTable (
/*
* Object must be a valid number and we must be executing
- * a control method. NS node could be there for AML_INT_NAMEPATH_OP.
+ * a control method. Object could be NS node for AML_INT_NAMEPATH_OP.
*/
if ((!ObjDesc) ||
(ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) ||
(ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
{
- return;
+ return (FALSE);
}
- if (AcpiGbl_IntegerByteWidth == 4)
+ if ((AcpiGbl_IntegerByteWidth == 4) &&
+ (ObjDesc->Integer.Value > (UINT64) ACPI_UINT32_MAX))
{
/*
- * We are running a method that exists in a 32-bit ACPI table.
+ * We are executing in a 32-bit ACPI table.
* Truncate the value to 32 bits by zeroing out the upper 32-bit field
*/
ObjDesc->Integer.Value &= (UINT64) ACPI_UINT32_MAX;
+ return (TRUE);
}
+
+ return (FALSE);
}
@@ -387,7 +391,7 @@ AcpiExDigitsNeeded (
if (Value == 0)
{
- return_UINT32 (1);
+ return_VALUE (1);
}
CurrentValue = Value;
@@ -401,7 +405,7 @@ AcpiExDigitsNeeded (
NumDigits++;
}
- return_UINT32 (NumDigits);
+ return_VALUE (NumDigits);
}
diff --git a/sys/contrib/dev/acpica/components/hardware/hwacpi.c b/sys/contrib/dev/acpica/components/hardware/hwacpi.c
index e667a47..41830c3 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwacpi.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwacpi.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -141,13 +141,13 @@ AcpiHwSetMode (
Retry = 3000;
while (Retry)
{
- if (AcpiHwGetMode() == Mode)
+ if (AcpiHwGetMode () == Mode)
{
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n",
Mode));
return_ACPI_STATUS (AE_OK);
}
- AcpiOsStall(1000);
+ AcpiOsStall (ACPI_USEC_PER_MSEC);
Retry--;
}
@@ -186,22 +186,22 @@ AcpiHwGetMode (
*/
if (!AcpiGbl_FADT.SmiCommand)
{
- return_UINT32 (ACPI_SYS_MODE_ACPI);
+ return_VALUE (ACPI_SYS_MODE_ACPI);
}
Status = AcpiReadBitRegister (ACPI_BITREG_SCI_ENABLE, &Value);
if (ACPI_FAILURE (Status))
{
- return_UINT32 (ACPI_SYS_MODE_LEGACY);
+ return_VALUE (ACPI_SYS_MODE_LEGACY);
}
if (Value)
{
- return_UINT32 (ACPI_SYS_MODE_ACPI);
+ return_VALUE (ACPI_SYS_MODE_ACPI);
}
else
{
- return_UINT32 (ACPI_SYS_MODE_LEGACY);
+ return_VALUE (ACPI_SYS_MODE_LEGACY);
}
}
diff --git a/sys/contrib/dev/acpica/components/hardware/hwesleep.c b/sys/contrib/dev/acpica/components/hardware/hwesleep.c
index 4a9b7ec..6717801 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwesleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwesleep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/hardware/hwgpe.c b/sys/contrib/dev/acpica/components/hardware/hwgpe.c
index afb5f87..c08ce2e 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwgpe.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -150,7 +150,7 @@ AcpiHwLowSetGpe (
break;
default:
- ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", Action));
+ ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u", Action));
return (AE_BAD_PARAMETER);
}
diff --git a/sys/contrib/dev/acpica/components/hardware/hwpci.c b/sys/contrib/dev/acpica/components/hardware/hwpci.c
index 2b3ef1c..a89a3dd 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwpci.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwpci.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/hardware/hwregs.c b/sys/contrib/dev/acpica/components/hardware/hwregs.c
index c1440f4..8a7775b 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwregs.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwregs.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/hardware/hwsleep.c b/sys/contrib/dev/acpica/components/hardware/hwsleep.c
index 6da9e5a..0e6691a 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwsleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwsleep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -180,7 +180,7 @@ AcpiHwLegacySleep (
* to still read the right value. Ideally, this block would go
* away entirely.
*/
- AcpiOsStall (10000000);
+ AcpiOsStall (10 * ACPI_USEC_PER_SEC);
Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL,
SleepEnableRegInfo->AccessBitMask);
diff --git a/sys/contrib/dev/acpica/components/hardware/hwtimer.c b/sys/contrib/dev/acpica/components/hardware/hwtimer.c
index ea8f954..1a13f64 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwtimer.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwtimer.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -203,10 +203,11 @@ AcpiGetTimerDuration (
/*
* Compute Duration (Requires a 64-bit multiply and divide):
*
- * TimeElapsed = (DeltaTicks * 1000000) / PM_TIMER_FREQUENCY;
+ * TimeElapsed (microseconds) =
+ * (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
*/
- Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * 1000000,
- PM_TIMER_FREQUENCY, &Quotient, NULL);
+ Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * ACPI_USEC_PER_SEC,
+ ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL);
*TimeElapsed = (UINT32) Quotient;
return_ACPI_STATUS (Status);
diff --git a/sys/contrib/dev/acpica/components/hardware/hwvalid.c b/sys/contrib/dev/acpica/components/hardware/hwvalid.c
index c1487d7..85a87d1 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwvalid.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwvalid.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/hardware/hwxface.c b/sys/contrib/dev/acpica/components/hardware/hwxface.c
index d169728..25ed994 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwxface.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -377,7 +377,7 @@ ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
*
* PARAMETERS: RegisterId - ID of ACPI Bit Register to access
* Value - Value to write to the register, in bit
- * position zero. The bit is automaticallly
+ * position zero. The bit is automatically
* shifted to the correct position.
*
* RETURN: Status
@@ -492,10 +492,33 @@ ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
* *SleepTypeA - Where SLP_TYPa is returned
* *SleepTypeB - Where SLP_TYPb is returned
*
- * RETURN: Status - ACPI status
+ * RETURN: Status
+ *
+ * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested
+ * sleep state via the appropriate \_Sx object.
+ *
+ * The sleep state package returned from the corresponding \_Sx_ object
+ * must contain at least one integer.
+ *
+ * March 2005:
+ * Added support for a package that contains two integers. This
+ * goes against the ACPI specification which defines this object as a
+ * package with one encoded DWORD integer. However, existing practice
+ * by many BIOS vendors is to return a package with 2 or more integer
+ * elements, at least one per sleep type (A/B).
+ *
+ * January 2013:
+ * Therefore, we must be prepared to accept a package with either a
+ * single integer or multiple integers.
*
- * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
- * state.
+ * The single integer DWORD format is as follows:
+ * BYTE 0 - Value for the PM1A SLP_TYP register
+ * BYTE 1 - Value for the PM1B SLP_TYP register
+ * BYTE 2-3 - Reserved
+ *
+ * The dual integer format is as follows:
+ * Integer 0 - Value for the PM1A SLP_TYP register
+ * Integer 1 - Value for the PM1A SLP_TYP register
*
******************************************************************************/
@@ -505,8 +528,9 @@ AcpiGetSleepTypeData (
UINT8 *SleepTypeA,
UINT8 *SleepTypeB)
{
- ACPI_STATUS Status = AE_OK;
+ ACPI_STATUS Status;
ACPI_EVALUATE_INFO *Info;
+ ACPI_OPERAND_OBJECT **Elements;
ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
@@ -515,8 +539,7 @@ AcpiGetSleepTypeData (
/* Validate parameters */
if ((SleepState > ACPI_S_STATES_MAX) ||
- !SleepTypeA ||
- !SleepTypeB)
+ !SleepTypeA || !SleepTypeB)
{
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
@@ -529,17 +552,14 @@ AcpiGetSleepTypeData (
return_ACPI_STATUS (AE_NO_MEMORY);
}
+ /*
+ * Evaluate the \_Sx namespace object containing the register values
+ * for this state
+ */
Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
-
- /* Evaluate the namespace object containing the values for this state */
-
Status = AcpiNsEvaluate (Info);
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "%s while evaluating SleepState [%s]\n",
- AcpiFormatException (Status), Info->Pathname));
-
goto Cleanup;
}
@@ -549,66 +569,70 @@ AcpiGetSleepTypeData (
{
ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
Info->Pathname));
- Status = AE_NOT_EXIST;
+ Status = AE_AML_NO_RETURN_VALUE;
+ goto Cleanup;
}
- /* It must be of type Package */
+ /* Return object must be of type Package */
- else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
+ if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
{
ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
Status = AE_AML_OPERAND_TYPE;
+ goto Cleanup1;
}
/*
- * The package must have at least two elements. NOTE (March 2005): This
- * goes against the current ACPI spec which defines this object as a
- * package with one encoded DWORD element. However, existing practice
- * by BIOS vendors seems to be to have 2 or more elements, at least
- * one per sleep type (A/B).
+ * Any warnings about the package length or the object types have
+ * already been issued by the predefined name module -- there is no
+ * need to repeat them here.
*/
- else if (Info->ReturnObject->Package.Count < 2)
+ Elements = Info->ReturnObject->Package.Elements;
+ switch (Info->ReturnObject->Package.Count)
{
- ACPI_ERROR ((AE_INFO,
- "Sleep State return package does not have at least two elements"));
- Status = AE_AML_NO_OPERAND;
- }
+ case 0:
+ Status = AE_AML_PACKAGE_LIMIT;
+ break;
- /* The first two elements must both be of type Integer */
+ case 1:
+ if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER)
+ {
+ Status = AE_AML_OPERAND_TYPE;
+ break;
+ }
- else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
- != ACPI_TYPE_INTEGER) ||
- ((Info->ReturnObject->Package.Elements[1])->Common.Type
- != ACPI_TYPE_INTEGER))
- {
- ACPI_ERROR ((AE_INFO,
- "Sleep State return package elements are not both Integers "
- "(%s, %s)",
- AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
- AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
- Status = AE_AML_OPERAND_TYPE;
- }
- else
- {
- /* Valid _Sx_ package size, type, and value */
+ /* A valid _Sx_ package with one integer */
+
+ *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
+ *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8);
+ break;
+
+ case 2:
+ default:
+ if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) ||
+ (Elements[1]->Common.Type != ACPI_TYPE_INTEGER))
+ {
+ Status = AE_AML_OPERAND_TYPE;
+ break;
+ }
+
+ /* A valid _Sx_ package with two integers */
- *SleepTypeA = (UINT8)
- (Info->ReturnObject->Package.Elements[0])->Integer.Value;
- *SleepTypeB = (UINT8)
- (Info->ReturnObject->Package.Elements[1])->Integer.Value;
+ *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
+ *SleepTypeB = (UINT8) Elements[1]->Integer.Value;
+ break;
}
+Cleanup1:
+ AcpiUtRemoveReference (Info->ReturnObject);
+
+Cleanup:
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
- "While evaluating SleepState [%s], bad Sleep object %p type %s",
- Info->Pathname, Info->ReturnObject,
- AcpiUtGetObjectTypeName (Info->ReturnObject)));
+ "While evaluating Sleep State [%s]", Info->Pathname));
}
- AcpiUtRemoveReference (Info->ReturnObject);
-
-Cleanup:
ACPI_FREE (Info);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
index e467164..3643799 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -227,7 +227,7 @@ AcpiEnterSleepStateS4bios (
(UINT32) AcpiGbl_FADT.S4BiosRequest, 8);
do {
- AcpiOsStall(1000);
+ AcpiOsStall (ACPI_USEC_PER_MSEC);
Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
if (ACPI_FAILURE (Status))
{
diff --git a/sys/contrib/dev/acpica/components/namespace/nsaccess.c b/sys/contrib/dev/acpica/components/namespace/nsaccess.c
index 246628c..8dc8b5f 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsaccess.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsaccess.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsalloc.c b/sys/contrib/dev/acpica/components/namespace/nsalloc.c
index c76f422..ecec172 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsalloc.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsalloc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsdump.c b/sys/contrib/dev/acpica/components/namespace/nsdump.c
index fd82cdb..1411534 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsdump.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
#include <contrib/dev/acpica/include/acnamesp.h>
+#include <contrib/dev/acpica/include/acoutput.h>
#define _COMPONENT ACPI_NAMESPACE
@@ -92,7 +93,9 @@ AcpiNsPrintPathname (
ACPI_FUNCTION_NAME (NsPrintPathname);
- if (!(AcpiDbgLevel & ACPI_LV_NAMES) || !(AcpiDbgLayer & ACPI_NAMESPACE))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_NAMES, ACPI_NAMESPACE))
{
return;
}
@@ -151,7 +154,7 @@ AcpiNsDumpPathname (
/* Do this only if the requested debug level and component are enabled */
- if (!(AcpiDbgLevel & Level) || !(AcpiDbgLayer & Component))
+ if (!ACPI_IS_DEBUG_ENABLED (Level, Component))
{
return_VOID;
}
diff --git a/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c b/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
index 4b93fbe..868b104 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nseval.c b/sys/contrib/dev/acpica/components/namespace/nseval.c
index a7a3577..61e783c 100644
--- a/sys/contrib/dev/acpica/components/namespace/nseval.c
+++ b/sys/contrib/dev/acpica/components/namespace/nseval.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsinit.c b/sys/contrib/dev/acpica/components/namespace/nsinit.c
index be2c60d..e9c9781 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsinit.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -104,7 +104,7 @@ AcpiNsInitializeObjects (
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"**** Starting initialization of namespace objects ****\n"));
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "Completing Region/Field/Buffer/Package initialization:"));
+ "Completing Region/Field/Buffer/Package initialization:\n"));
/* Set all init info to zero */
@@ -121,7 +121,7 @@ AcpiNsInitializeObjects (
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nInitialized %u/%u Regions %u/%u Fields %u/%u "
+ " Initialized %u/%u Regions %u/%u Fields %u/%u "
"Buffers %u/%u Packages (%u nodes)\n",
Info.OpRegionInit, Info.OpRegionCount,
Info.FieldInit, Info.FieldCount,
@@ -172,7 +172,7 @@ AcpiNsInitializeDevices (
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
"Initializing Device/Processor/Thermal objects "
- "by executing _INI methods:"));
+ "and executing _INI/_STA methods:\n"));
/* Tree analysis: find all subtrees that contain _INI methods */
@@ -230,7 +230,7 @@ AcpiNsInitializeDevices (
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nExecuted %u _INI methods requiring %u _STA executions "
+ " Executed %u _INI methods requiring %u _STA executions "
"(examined %u objects)\n",
Info.Num_INI, Info.Num_STA, Info.DeviceCount));
@@ -381,15 +381,6 @@ AcpiNsInitOneObject (
}
/*
- * Print a dot for each object unless we are going to print the entire
- * pathname
- */
- if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
- {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
- }
-
- /*
* We ignore errors from above, and always return OK, since we don't want
* to abort the walk on any single error.
*/
@@ -627,12 +618,6 @@ AcpiNsInitOneDevice (
if (ACPI_SUCCESS (Status))
{
WalkInfo->Num_INI++;
-
- if ((AcpiDbgLevel <= ACPI_LV_ALL_EXCEPTIONS) &&
- (!(AcpiDbgLevel & ACPI_LV_INFO)))
- {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
- }
}
#ifdef ACPI_DEBUG_OUTPUT
diff --git a/sys/contrib/dev/acpica/components/namespace/nsload.c b/sys/contrib/dev/acpica/components/namespace/nsload.c
index 9cfa412..d29a891 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsload.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsnames.c b/sys/contrib/dev/acpica/components/namespace/nsnames.c
index cd2fc2c..cd4d440 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsnames.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsnames.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsobject.c b/sys/contrib/dev/acpica/components/namespace/nsobject.c
index 0920db3..b1d1f01 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsobject.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsobject.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsparse.c b/sys/contrib/dev/acpica/components/namespace/nsparse.c
index 231a440..f327f26 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsparse.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsparse.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nspredef.c b/sys/contrib/dev/acpica/components/namespace/nspredef.c
index fd003fb..8c65b84 100644
--- a/sys/contrib/dev/acpica/components/namespace/nspredef.c
+++ b/sys/contrib/dev/acpica/components/namespace/nspredef.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -78,35 +78,6 @@
/* Local prototypes */
static ACPI_STATUS
-AcpiNsCheckPackage (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **ReturnObjectPtr);
-
-static ACPI_STATUS
-AcpiNsCheckPackageList (
- ACPI_PREDEFINED_DATA *Data,
- const ACPI_PREDEFINED_INFO *Package,
- ACPI_OPERAND_OBJECT **Elements,
- UINT32 Count);
-
-static ACPI_STATUS
-AcpiNsCheckPackageElements (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **Elements,
- UINT8 Type1,
- UINT32 Count1,
- UINT8 Type2,
- UINT32 Count2,
- UINT32 StartIndex);
-
-static ACPI_STATUS
-AcpiNsCheckObjectType (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **ReturnObjectPtr,
- UINT32 ExpectedBtypes,
- UINT32 PackageIndex);
-
-static ACPI_STATUS
AcpiNsCheckReference (
ACPI_PREDEFINED_DATA *Data,
ACPI_OPERAND_OBJECT *ReturnObject);
@@ -450,574 +421,6 @@ AcpiNsCheckForPredefinedName (
/*******************************************************************************
*
- * FUNCTION: AcpiNsCheckPackage
- *
- * PARAMETERS: Data - Pointer to validation data structure
- * ReturnObjectPtr - Pointer to the object returned from the
- * evaluation of a method or object
- *
- * RETURN: Status
- *
- * DESCRIPTION: Check a returned package object for the correct count and
- * correct type of all sub-objects.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiNsCheckPackage (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **ReturnObjectPtr)
-{
- ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr;
- const ACPI_PREDEFINED_INFO *Package;
- ACPI_OPERAND_OBJECT **Elements;
- ACPI_STATUS Status = AE_OK;
- UINT32 ExpectedCount;
- UINT32 Count;
- UINT32 i;
-
-
- ACPI_FUNCTION_NAME (NsCheckPackage);
-
-
- /* The package info for this name is in the next table entry */
-
- Package = Data->Predefined + 1;
-
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "%s Validating return Package of Type %X, Count %X\n",
- Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count));
-
- /*
- * For variable-length Packages, we can safely remove all embedded
- * and trailing NULL package elements
- */
- AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject);
-
- /* Extract package count and elements array */
-
- Elements = ReturnObject->Package.Elements;
- Count = ReturnObject->Package.Count;
-
- /* The package must have at least one element, else invalid */
-
- if (!Count)
- {
- ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
- "Return Package has no elements (empty)"));
-
- return (AE_AML_OPERAND_VALUE);
- }
-
- /*
- * Decode the type of the expected package contents
- *
- * PTYPE1 packages contain no subpackages
- * PTYPE2 packages contain sub-packages
- */
- switch (Package->RetInfo.Type)
- {
- case ACPI_PTYPE1_FIXED:
-
- /*
- * The package count is fixed and there are no sub-packages
- *
- * If package is too small, exit.
- * If package is larger than expected, issue warning but continue
- */
- ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
- if (Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
- else if (Count > ExpectedCount)
- {
- ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
- "%s: Return Package is larger than needed - "
- "found %u, expected %u\n",
- Data->Pathname, Count, ExpectedCount));
- }
-
- /* Validate all elements of the returned package */
-
- Status = AcpiNsCheckPackageElements (Data, Elements,
- Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
- Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
- break;
-
-
- case ACPI_PTYPE1_VAR:
-
- /*
- * The package count is variable, there are no sub-packages, and all
- * elements must be of the same type
- */
- for (i = 0; i < Count; i++)
- {
- Status = AcpiNsCheckObjectType (Data, Elements,
- Package->RetInfo.ObjectType1, i);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- Elements++;
- }
- break;
-
-
- case ACPI_PTYPE1_OPTION:
-
- /*
- * The package count is variable, there are no sub-packages. There are
- * a fixed number of required elements, and a variable number of
- * optional elements.
- *
- * Check if package is at least as large as the minimum required
- */
- ExpectedCount = Package->RetInfo3.Count;
- if (Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- /* Variable number of sub-objects */
-
- for (i = 0; i < Count; i++)
- {
- if (i < Package->RetInfo3.Count)
- {
- /* These are the required package elements (0, 1, or 2) */
-
- Status = AcpiNsCheckObjectType (Data, Elements,
- Package->RetInfo3.ObjectType[i], i);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- }
- else
- {
- /* These are the optional package elements */
-
- Status = AcpiNsCheckObjectType (Data, Elements,
- Package->RetInfo3.TailObjectType, i);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- }
- Elements++;
- }
- break;
-
-
- case ACPI_PTYPE2_REV_FIXED:
-
- /* First element is the (Integer) revision */
-
- Status = AcpiNsCheckObjectType (Data, Elements,
- ACPI_RTYPE_INTEGER, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- Elements++;
- Count--;
-
- /* Examine the sub-packages */
-
- Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
- break;
-
-
- case ACPI_PTYPE2_PKG_COUNT:
-
- /* First element is the (Integer) count of sub-packages to follow */
-
- Status = AcpiNsCheckObjectType (Data, Elements,
- ACPI_RTYPE_INTEGER, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /*
- * Count cannot be larger than the parent package length, but allow it
- * to be smaller. The >= accounts for the Integer above.
- */
- ExpectedCount = (UINT32) (*Elements)->Integer.Value;
- if (ExpectedCount >= Count)
- {
- goto PackageTooSmall;
- }
-
- Count = ExpectedCount;
- Elements++;
-
- /* Examine the sub-packages */
-
- Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
- break;
-
-
- case ACPI_PTYPE2:
- case ACPI_PTYPE2_FIXED:
- case ACPI_PTYPE2_MIN:
- case ACPI_PTYPE2_COUNT:
- case ACPI_PTYPE2_FIX_VAR:
-
- /*
- * These types all return a single Package that consists of a
- * variable number of sub-Packages.
- *
- * First, ensure that the first element is a sub-Package. If not,
- * the BIOS may have incorrectly returned the object as a single
- * package instead of a Package of Packages (a common error if
- * there is only one entry). We may be able to repair this by
- * wrapping the returned Package with a new outer Package.
- */
- if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
- {
- /* Create the new outer package and populate it */
-
- Status = AcpiNsWrapWithPackage (Data, ReturnObject, ReturnObjectPtr);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /* Update locals to point to the new package (of 1 element) */
-
- ReturnObject = *ReturnObjectPtr;
- Elements = ReturnObject->Package.Elements;
- Count = 1;
- }
-
- /* Examine the sub-packages */
-
- Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
- break;
-
-
- default:
-
- /* Should not get here if predefined info table is correct */
-
- ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
- "Invalid internal return type in table entry: %X",
- Package->RetInfo.Type));
-
- return (AE_AML_INTERNAL);
- }
-
- return (Status);
-
-
-PackageTooSmall:
-
- /* Error exit for the case with an incorrect package count */
-
- ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
- "Return Package is too small - found %u elements, expected %u",
- Count, ExpectedCount));
-
- return (AE_AML_OPERAND_VALUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiNsCheckPackageList
- *
- * PARAMETERS: Data - Pointer to validation data structure
- * Package - Pointer to package-specific info for method
- * Elements - Element list of parent package. All elements
- * of this list should be of type Package.
- * Count - Count of subpackages
- *
- * RETURN: Status
- *
- * DESCRIPTION: Examine a list of subpackages
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiNsCheckPackageList (
- ACPI_PREDEFINED_DATA *Data,
- const ACPI_PREDEFINED_INFO *Package,
- ACPI_OPERAND_OBJECT **Elements,
- UINT32 Count)
-{
- ACPI_OPERAND_OBJECT *SubPackage;
- ACPI_OPERAND_OBJECT **SubElements;
- ACPI_STATUS Status;
- UINT32 ExpectedCount;
- UINT32 i;
- UINT32 j;
-
-
- /*
- * Validate each sub-Package in the parent Package
- *
- * NOTE: assumes list of sub-packages contains no NULL elements.
- * Any NULL elements should have been removed by earlier call
- * to AcpiNsRemoveNullElements.
- */
- for (i = 0; i < Count; i++)
- {
- SubPackage = *Elements;
- SubElements = SubPackage->Package.Elements;
- Data->ParentPackage = SubPackage;
-
- /* Each sub-object must be of type Package */
-
- Status = AcpiNsCheckObjectType (Data, &SubPackage,
- ACPI_RTYPE_PACKAGE, i);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /* Examine the different types of expected sub-packages */
-
- Data->ParentPackage = SubPackage;
- switch (Package->RetInfo.Type)
- {
- case ACPI_PTYPE2:
- case ACPI_PTYPE2_PKG_COUNT:
- case ACPI_PTYPE2_REV_FIXED:
-
- /* Each subpackage has a fixed number of elements */
-
- ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- Status = AcpiNsCheckPackageElements (Data, SubElements,
- Package->RetInfo.ObjectType1,
- Package->RetInfo.Count1,
- Package->RetInfo.ObjectType2,
- Package->RetInfo.Count2, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- break;
-
-
- case ACPI_PTYPE2_FIX_VAR:
- /*
- * Each subpackage has a fixed number of elements and an
- * optional element
- */
- ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- Status = AcpiNsCheckPackageElements (Data, SubElements,
- Package->RetInfo.ObjectType1,
- Package->RetInfo.Count1,
- Package->RetInfo.ObjectType2,
- SubPackage->Package.Count - Package->RetInfo.Count1, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- break;
-
-
- case ACPI_PTYPE2_FIXED:
-
- /* Each sub-package has a fixed length */
-
- ExpectedCount = Package->RetInfo2.Count;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- /* Check the type of each sub-package element */
-
- for (j = 0; j < ExpectedCount; j++)
- {
- Status = AcpiNsCheckObjectType (Data, &SubElements[j],
- Package->RetInfo2.ObjectType[j], j);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- }
- break;
-
-
- case ACPI_PTYPE2_MIN:
-
- /* Each sub-package has a variable but minimum length */
-
- ExpectedCount = Package->RetInfo.Count1;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- /* Check the type of each sub-package element */
-
- Status = AcpiNsCheckPackageElements (Data, SubElements,
- Package->RetInfo.ObjectType1,
- SubPackage->Package.Count, 0, 0, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- break;
-
-
- case ACPI_PTYPE2_COUNT:
-
- /*
- * First element is the (Integer) count of elements, including
- * the count field (the ACPI name is NumElements)
- */
- Status = AcpiNsCheckObjectType (Data, SubElements,
- ACPI_RTYPE_INTEGER, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /*
- * Make sure package is large enough for the Count and is
- * is as large as the minimum size
- */
- ExpectedCount = (UINT32) (*SubElements)->Integer.Value;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
- if (SubPackage->Package.Count < Package->RetInfo.Count1)
- {
- ExpectedCount = Package->RetInfo.Count1;
- goto PackageTooSmall;
- }
- if (ExpectedCount == 0)
- {
- /*
- * Either the NumEntries element was originally zero or it was
- * a NULL element and repaired to an Integer of value zero.
- * In either case, repair it by setting NumEntries to be the
- * actual size of the subpackage.
- */
- ExpectedCount = SubPackage->Package.Count;
- (*SubElements)->Integer.Value = ExpectedCount;
- }
-
- /* Check the type of each sub-package element */
-
- Status = AcpiNsCheckPackageElements (Data, (SubElements + 1),
- Package->RetInfo.ObjectType1,
- (ExpectedCount - 1), 0, 0, 1);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- break;
-
-
- default: /* Should not get here, type was validated by caller */
-
- return (AE_AML_INTERNAL);
- }
-
- Elements++;
- }
-
- return (AE_OK);
-
-
-PackageTooSmall:
-
- /* The sub-package count was smaller than required */
-
- ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
- "Return Sub-Package[%u] is too small - found %u elements, expected %u",
- i, SubPackage->Package.Count, ExpectedCount));
-
- return (AE_AML_OPERAND_VALUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiNsCheckPackageElements
- *
- * PARAMETERS: Data - Pointer to validation data structure
- * Elements - Pointer to the package elements array
- * Type1 - Object type for first group
- * Count1 - Count for first group
- * Type2 - Object type for second group
- * Count2 - Count for second group
- * StartIndex - Start of the first group of elements
- *
- * RETURN: Status
- *
- * DESCRIPTION: Check that all elements of a package are of the correct object
- * type. Supports up to two groups of different object types.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiNsCheckPackageElements (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **Elements,
- UINT8 Type1,
- UINT32 Count1,
- UINT8 Type2,
- UINT32 Count2,
- UINT32 StartIndex)
-{
- ACPI_OPERAND_OBJECT **ThisElement = Elements;
- ACPI_STATUS Status;
- UINT32 i;
-
-
- /*
- * Up to two groups of package elements are supported by the data
- * structure. All elements in each group must be of the same type.
- * The second group can have a count of zero.
- */
- for (i = 0; i < Count1; i++)
- {
- Status = AcpiNsCheckObjectType (Data, ThisElement,
- Type1, i + StartIndex);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- ThisElement++;
- }
-
- for (i = 0; i < Count2; i++)
- {
- Status = AcpiNsCheckObjectType (Data, ThisElement,
- Type2, (i + Count1 + StartIndex));
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- ThisElement++;
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiNsCheckObjectType
*
* PARAMETERS: Data - Pointer to validation data structure
@@ -1035,7 +438,7 @@ AcpiNsCheckPackageElements (
*
******************************************************************************/
-static ACPI_STATUS
+ACPI_STATUS
AcpiNsCheckObjectType (
ACPI_PREDEFINED_DATA *Data,
ACPI_OPERAND_OBJECT **ReturnObjectPtr,
diff --git a/sys/contrib/dev/acpica/components/namespace/nsprepkg.c b/sys/contrib/dev/acpica/components/namespace/nsprepkg.c
new file mode 100644
index 0000000..7b65b80
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/namespace/nsprepkg.c
@@ -0,0 +1,639 @@
+/******************************************************************************
+ *
+ * Module Name: nsprepkg - Validation of package objects for predefined names
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+#include <contrib/dev/acpica/include/acpredef.h>
+
+
+#define _COMPONENT ACPI_NAMESPACE
+ ACPI_MODULE_NAME ("nsprepkg")
+
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiNsCheckPackageList (
+ ACPI_PREDEFINED_DATA *Data,
+ const ACPI_PREDEFINED_INFO *Package,
+ ACPI_OPERAND_OBJECT **Elements,
+ UINT32 Count);
+
+static ACPI_STATUS
+AcpiNsCheckPackageElements (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **Elements,
+ UINT8 Type1,
+ UINT32 Count1,
+ UINT8 Type2,
+ UINT32 Count2,
+ UINT32 StartIndex);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiNsCheckPackage
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * ReturnObjectPtr - Pointer to the object returned from the
+ * evaluation of a method or object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check a returned package object for the correct count and
+ * correct type of all sub-objects.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiNsCheckPackage (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **ReturnObjectPtr)
+{
+ ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr;
+ const ACPI_PREDEFINED_INFO *Package;
+ ACPI_OPERAND_OBJECT **Elements;
+ ACPI_STATUS Status = AE_OK;
+ UINT32 ExpectedCount;
+ UINT32 Count;
+ UINT32 i;
+
+
+ ACPI_FUNCTION_NAME (NsCheckPackage);
+
+
+ /* The package info for this name is in the next table entry */
+
+ Package = Data->Predefined + 1;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
+ "%s Validating return Package of Type %X, Count %X\n",
+ Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count));
+
+ /*
+ * For variable-length Packages, we can safely remove all embedded
+ * and trailing NULL package elements
+ */
+ AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject);
+
+ /* Extract package count and elements array */
+
+ Elements = ReturnObject->Package.Elements;
+ Count = ReturnObject->Package.Count;
+
+ /* The package must have at least one element, else invalid */
+
+ if (!Count)
+ {
+ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
+ "Return Package has no elements (empty)"));
+
+ return (AE_AML_OPERAND_VALUE);
+ }
+
+ /*
+ * Decode the type of the expected package contents
+ *
+ * PTYPE1 packages contain no subpackages
+ * PTYPE2 packages contain sub-packages
+ */
+ switch (Package->RetInfo.Type)
+ {
+ case ACPI_PTYPE1_FIXED:
+
+ /*
+ * The package count is fixed and there are no sub-packages
+ *
+ * If package is too small, exit.
+ * If package is larger than expected, issue warning but continue
+ */
+ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
+ if (Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+ else if (Count > ExpectedCount)
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
+ "%s: Return Package is larger than needed - "
+ "found %u, expected %u\n",
+ Data->Pathname, Count, ExpectedCount));
+ }
+
+ /* Validate all elements of the returned package */
+
+ Status = AcpiNsCheckPackageElements (Data, Elements,
+ Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
+ Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
+ break;
+
+
+ case ACPI_PTYPE1_VAR:
+
+ /*
+ * The package count is variable, there are no sub-packages, and all
+ * elements must be of the same type
+ */
+ for (i = 0; i < Count; i++)
+ {
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ Package->RetInfo.ObjectType1, i);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ Elements++;
+ }
+ break;
+
+
+ case ACPI_PTYPE1_OPTION:
+
+ /*
+ * The package count is variable, there are no sub-packages. There are
+ * a fixed number of required elements, and a variable number of
+ * optional elements.
+ *
+ * Check if package is at least as large as the minimum required
+ */
+ ExpectedCount = Package->RetInfo3.Count;
+ if (Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ /* Variable number of sub-objects */
+
+ for (i = 0; i < Count; i++)
+ {
+ if (i < Package->RetInfo3.Count)
+ {
+ /* These are the required package elements (0, 1, or 2) */
+
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ Package->RetInfo3.ObjectType[i], i);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ else
+ {
+ /* These are the optional package elements */
+
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ Package->RetInfo3.TailObjectType, i);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ Elements++;
+ }
+ break;
+
+
+ case ACPI_PTYPE2_REV_FIXED:
+
+ /* First element is the (Integer) revision */
+
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ ACPI_RTYPE_INTEGER, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ Elements++;
+ Count--;
+
+ /* Examine the sub-packages */
+
+ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
+ break;
+
+
+ case ACPI_PTYPE2_PKG_COUNT:
+
+ /* First element is the (Integer) count of sub-packages to follow */
+
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ ACPI_RTYPE_INTEGER, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /*
+ * Count cannot be larger than the parent package length, but allow it
+ * to be smaller. The >= accounts for the Integer above.
+ */
+ ExpectedCount = (UINT32) (*Elements)->Integer.Value;
+ if (ExpectedCount >= Count)
+ {
+ goto PackageTooSmall;
+ }
+
+ Count = ExpectedCount;
+ Elements++;
+
+ /* Examine the sub-packages */
+
+ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
+ break;
+
+
+ case ACPI_PTYPE2:
+ case ACPI_PTYPE2_FIXED:
+ case ACPI_PTYPE2_MIN:
+ case ACPI_PTYPE2_COUNT:
+ case ACPI_PTYPE2_FIX_VAR:
+
+ /*
+ * These types all return a single Package that consists of a
+ * variable number of sub-Packages.
+ *
+ * First, ensure that the first element is a sub-Package. If not,
+ * the BIOS may have incorrectly returned the object as a single
+ * package instead of a Package of Packages (a common error if
+ * there is only one entry). We may be able to repair this by
+ * wrapping the returned Package with a new outer Package.
+ */
+ if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
+ {
+ /* Create the new outer package and populate it */
+
+ Status = AcpiNsWrapWithPackage (Data, ReturnObject, ReturnObjectPtr);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Update locals to point to the new package (of 1 element) */
+
+ ReturnObject = *ReturnObjectPtr;
+ Elements = ReturnObject->Package.Elements;
+ Count = 1;
+ }
+
+ /* Examine the sub-packages */
+
+ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
+ break;
+
+
+ default:
+
+ /* Should not get here if predefined info table is correct */
+
+ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
+ "Invalid internal return type in table entry: %X",
+ Package->RetInfo.Type));
+
+ return (AE_AML_INTERNAL);
+ }
+
+ return (Status);
+
+
+PackageTooSmall:
+
+ /* Error exit for the case with an incorrect package count */
+
+ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
+ "Return Package is too small - found %u elements, expected %u",
+ Count, ExpectedCount));
+
+ return (AE_AML_OPERAND_VALUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiNsCheckPackageList
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * Package - Pointer to package-specific info for method
+ * Elements - Element list of parent package. All elements
+ * of this list should be of type Package.
+ * Count - Count of subpackages
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Examine a list of subpackages
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiNsCheckPackageList (
+ ACPI_PREDEFINED_DATA *Data,
+ const ACPI_PREDEFINED_INFO *Package,
+ ACPI_OPERAND_OBJECT **Elements,
+ UINT32 Count)
+{
+ ACPI_OPERAND_OBJECT *SubPackage;
+ ACPI_OPERAND_OBJECT **SubElements;
+ ACPI_STATUS Status;
+ UINT32 ExpectedCount;
+ UINT32 i;
+ UINT32 j;
+
+
+ /*
+ * Validate each sub-Package in the parent Package
+ *
+ * NOTE: assumes list of sub-packages contains no NULL elements.
+ * Any NULL elements should have been removed by earlier call
+ * to AcpiNsRemoveNullElements.
+ */
+ for (i = 0; i < Count; i++)
+ {
+ SubPackage = *Elements;
+ SubElements = SubPackage->Package.Elements;
+ Data->ParentPackage = SubPackage;
+
+ /* Each sub-object must be of type Package */
+
+ Status = AcpiNsCheckObjectType (Data, &SubPackage,
+ ACPI_RTYPE_PACKAGE, i);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Examine the different types of expected sub-packages */
+
+ Data->ParentPackage = SubPackage;
+ switch (Package->RetInfo.Type)
+ {
+ case ACPI_PTYPE2:
+ case ACPI_PTYPE2_PKG_COUNT:
+ case ACPI_PTYPE2_REV_FIXED:
+
+ /* Each subpackage has a fixed number of elements */
+
+ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ Status = AcpiNsCheckPackageElements (Data, SubElements,
+ Package->RetInfo.ObjectType1,
+ Package->RetInfo.Count1,
+ Package->RetInfo.ObjectType2,
+ Package->RetInfo.Count2, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ break;
+
+
+ case ACPI_PTYPE2_FIX_VAR:
+ /*
+ * Each subpackage has a fixed number of elements and an
+ * optional element
+ */
+ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ Status = AcpiNsCheckPackageElements (Data, SubElements,
+ Package->RetInfo.ObjectType1,
+ Package->RetInfo.Count1,
+ Package->RetInfo.ObjectType2,
+ SubPackage->Package.Count - Package->RetInfo.Count1, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ break;
+
+
+ case ACPI_PTYPE2_FIXED:
+
+ /* Each sub-package has a fixed length */
+
+ ExpectedCount = Package->RetInfo2.Count;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ /* Check the type of each sub-package element */
+
+ for (j = 0; j < ExpectedCount; j++)
+ {
+ Status = AcpiNsCheckObjectType (Data, &SubElements[j],
+ Package->RetInfo2.ObjectType[j], j);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ break;
+
+
+ case ACPI_PTYPE2_MIN:
+
+ /* Each sub-package has a variable but minimum length */
+
+ ExpectedCount = Package->RetInfo.Count1;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ /* Check the type of each sub-package element */
+
+ Status = AcpiNsCheckPackageElements (Data, SubElements,
+ Package->RetInfo.ObjectType1,
+ SubPackage->Package.Count, 0, 0, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ break;
+
+
+ case ACPI_PTYPE2_COUNT:
+
+ /*
+ * First element is the (Integer) count of elements, including
+ * the count field (the ACPI name is NumElements)
+ */
+ Status = AcpiNsCheckObjectType (Data, SubElements,
+ ACPI_RTYPE_INTEGER, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /*
+ * Make sure package is large enough for the Count and is
+ * is as large as the minimum size
+ */
+ ExpectedCount = (UINT32) (*SubElements)->Integer.Value;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+ if (SubPackage->Package.Count < Package->RetInfo.Count1)
+ {
+ ExpectedCount = Package->RetInfo.Count1;
+ goto PackageTooSmall;
+ }
+ if (ExpectedCount == 0)
+ {
+ /*
+ * Either the NumEntries element was originally zero or it was
+ * a NULL element and repaired to an Integer of value zero.
+ * In either case, repair it by setting NumEntries to be the
+ * actual size of the subpackage.
+ */
+ ExpectedCount = SubPackage->Package.Count;
+ (*SubElements)->Integer.Value = ExpectedCount;
+ }
+
+ /* Check the type of each sub-package element */
+
+ Status = AcpiNsCheckPackageElements (Data, (SubElements + 1),
+ Package->RetInfo.ObjectType1,
+ (ExpectedCount - 1), 0, 0, 1);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ break;
+
+
+ default: /* Should not get here, type was validated by caller */
+
+ return (AE_AML_INTERNAL);
+ }
+
+ Elements++;
+ }
+
+ return (AE_OK);
+
+
+PackageTooSmall:
+
+ /* The sub-package count was smaller than required */
+
+ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
+ "Return Sub-Package[%u] is too small - found %u elements, expected %u",
+ i, SubPackage->Package.Count, ExpectedCount));
+
+ return (AE_AML_OPERAND_VALUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiNsCheckPackageElements
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * Elements - Pointer to the package elements array
+ * Type1 - Object type for first group
+ * Count1 - Count for first group
+ * Type2 - Object type for second group
+ * Count2 - Count for second group
+ * StartIndex - Start of the first group of elements
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check that all elements of a package are of the correct object
+ * type. Supports up to two groups of different object types.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiNsCheckPackageElements (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **Elements,
+ UINT8 Type1,
+ UINT32 Count1,
+ UINT8 Type2,
+ UINT32 Count2,
+ UINT32 StartIndex)
+{
+ ACPI_OPERAND_OBJECT **ThisElement = Elements;
+ ACPI_STATUS Status;
+ UINT32 i;
+
+
+ /*
+ * Up to two groups of package elements are supported by the data
+ * structure. All elements in each group must be of the same type.
+ * The second group can have a count of zero.
+ */
+ for (i = 0; i < Count1; i++)
+ {
+ Status = AcpiNsCheckObjectType (Data, ThisElement,
+ Type1, i + StartIndex);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ ThisElement++;
+ }
+
+ for (i = 0; i < Count2; i++)
+ {
+ Status = AcpiNsCheckObjectType (Data, ThisElement,
+ Type2, (i + Count1 + StartIndex));
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ ThisElement++;
+ }
+
+ return (AE_OK);
+}
diff --git a/sys/contrib/dev/acpica/components/namespace/nsrepair.c b/sys/contrib/dev/acpica/components/namespace/nsrepair.c
index 7a1ee9f..c5c9309 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsrepair.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsrepair.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsrepair2.c b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
index 06286f1..a6559f4 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nssearch.c b/sys/contrib/dev/acpica/components/namespace/nssearch.c
index 93e060c..255956f 100644
--- a/sys/contrib/dev/acpica/components/namespace/nssearch.c
+++ b/sys/contrib/dev/acpica/components/namespace/nssearch.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsutils.c b/sys/contrib/dev/acpica/components/namespace/nsutils.c
index 1003098..070ed26 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsutils.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsutils.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,10 +54,6 @@
/* Local prototypes */
-static BOOLEAN
-AcpiNsValidPathSeparator (
- char Sep);
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
ACPI_NAME
AcpiNsFindParentName (
@@ -112,48 +108,6 @@ AcpiNsPrintNodePathname (
/*******************************************************************************
*
- * FUNCTION: AcpiNsValidRootPrefix
- *
- * PARAMETERS: Prefix - Character to be checked
- *
- * RETURN: TRUE if a valid prefix
- *
- * DESCRIPTION: Check if a character is a valid ACPI Root prefix
- *
- ******************************************************************************/
-
-BOOLEAN
-AcpiNsValidRootPrefix (
- char Prefix)
-{
-
- return ((BOOLEAN) (Prefix == '\\'));
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiNsValidPathSeparator
- *
- * PARAMETERS: Sep - Character to be checked
- *
- * RETURN: TRUE if a valid path separator
- *
- * DESCRIPTION: Check if a character is a valid ACPI path separator
- *
- ******************************************************************************/
-
-static BOOLEAN
-AcpiNsValidPathSeparator (
- char Sep)
-{
-
- return ((BOOLEAN) (Sep == '.'));
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiNsGetType
*
* PARAMETERS: Node - Parent Node to be examined
@@ -174,10 +128,10 @@ AcpiNsGetType (
if (!Node)
{
ACPI_WARNING ((AE_INFO, "Null Node parameter"));
- return_UINT32 (ACPI_TYPE_ANY);
+ return_VALUE (ACPI_TYPE_ANY);
}
- return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type);
+ return_VALUE (Node->Type);
}
@@ -206,10 +160,10 @@ AcpiNsLocal (
/* Type code out of range */
ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
- return_UINT32 (ACPI_NS_NORMAL);
+ return_VALUE (ACPI_NS_NORMAL);
}
- return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
+ return_VALUE (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
}
@@ -250,14 +204,14 @@ AcpiNsGetInternalNameLength (
*
* strlen() + 1 covers the first NameSeg, which has no path separator
*/
- if (AcpiNsValidRootPrefix (*NextExternalChar))
+ if (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
{
Info->FullyQualified = TRUE;
NextExternalChar++;
/* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
- while (AcpiNsValidRootPrefix (*NextExternalChar))
+ while (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
{
NextExternalChar++;
}
@@ -266,7 +220,7 @@ AcpiNsGetInternalNameLength (
{
/* Handle Carat prefixes */
- while (*NextExternalChar == '^')
+ while (ACPI_IS_PARENT_PREFIX (*NextExternalChar))
{
Info->NumCarats++;
NextExternalChar++;
@@ -283,7 +237,7 @@ AcpiNsGetInternalNameLength (
Info->NumSegments = 1;
for (i = 0; NextExternalChar[i]; i++)
{
- if (AcpiNsValidPathSeparator (NextExternalChar[i]))
+ if (ACPI_IS_PATH_SEPARATOR (NextExternalChar[i]))
{
Info->NumSegments++;
}
@@ -328,7 +282,7 @@ AcpiNsBuildInternalName (
if (Info->FullyQualified)
{
- InternalName[0] = '\\';
+ InternalName[0] = AML_ROOT_PREFIX;
if (NumSegments <= 1)
{
@@ -357,7 +311,7 @@ AcpiNsBuildInternalName (
{
for (i = 0; i < Info->NumCarats; i++)
{
- InternalName[i] = '^';
+ InternalName[i] = AML_PARENT_PREFIX;
}
}
@@ -384,7 +338,7 @@ AcpiNsBuildInternalName (
{
for (i = 0; i < ACPI_NAME_SIZE; i++)
{
- if (AcpiNsValidPathSeparator (*ExternalName) ||
+ if (ACPI_IS_PATH_SEPARATOR (*ExternalName) ||
(*ExternalName == 0))
{
/* Pad the segment with underscore(s) if segment is short */
@@ -402,7 +356,7 @@ AcpiNsBuildInternalName (
/* Now we must have a path separator, or the pathname is bad */
- if (!AcpiNsValidPathSeparator (*ExternalName) &&
+ if (!ACPI_IS_PATH_SEPARATOR (*ExternalName) &&
(*ExternalName != 0))
{
return_ACPI_STATUS (AE_BAD_PATHNAME);
@@ -542,14 +496,14 @@ AcpiNsExternalizeName (
switch (InternalName[0])
{
- case '\\':
+ case AML_ROOT_PREFIX:
PrefixLength = 1;
break;
- case '^':
+ case AML_PARENT_PREFIX:
for (i = 0; i < InternalNameLength; i++)
{
- if (InternalName[i] == '^')
+ if (ACPI_IS_PARENT_PREFIX (InternalName[i]))
{
PrefixLength = i + 1;
}
@@ -829,6 +783,8 @@ AcpiNsGetNode (
ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
+ /* Simplest case is a null pathname */
+
if (!Pathname)
{
*ReturnNode = PrefixNode;
@@ -839,6 +795,14 @@ AcpiNsGetNode (
return_ACPI_STATUS (AE_OK);
}
+ /* Quick check for a reference to the root */
+
+ if (ACPI_IS_ROOT_PREFIX (Pathname[0]) && (!Pathname[1]))
+ {
+ *ReturnNode = AcpiGbl_RootNode;
+ return_ACPI_STATUS (AE_OK);
+ }
+
/* Convert path to internal representation */
Status = AcpiNsInternalizeName (Pathname, &InternalPath);
diff --git a/sys/contrib/dev/acpica/components/namespace/nswalk.c b/sys/contrib/dev/acpica/components/namespace/nswalk.c
index 008a957..3b42d91 100644
--- a/sys/contrib/dev/acpica/components/namespace/nswalk.c
+++ b/sys/contrib/dev/acpica/components/namespace/nswalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfeval.c b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
index 5d3204d..ff580be 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -255,7 +255,7 @@ AcpiEvaluateObject (
* 3) Valid handle
*/
if ((Pathname) &&
- (AcpiNsValidRootPrefix (Pathname[0])))
+ (ACPI_IS_ROOT_PREFIX (Pathname[0])))
{
/* The path is fully qualified, just evaluate by name */
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfname.c b/sys/contrib/dev/acpica/components/namespace/nsxfname.c
index a6e502b1..582ecf3 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfname.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfname.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -120,7 +120,7 @@ AcpiGetHandle (
*
* Error for <null Parent + relative path>
*/
- if (AcpiNsValidRootPrefix (Pathname[0]))
+ if (ACPI_IS_ROOT_PREFIX (Pathname[0]))
{
/* Pathname is fully qualified (starts with '\') */
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfobj.c b/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
index fb0df50..153dfaa 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/psargs.c b/sys/contrib/dev/acpica/components/parser/psargs.c
index 9bddc21..c57f485 100644
--- a/sys/contrib/dev/acpica/components/parser/psargs.c
+++ b/sys/contrib/dev/acpica/components/parser/psargs.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -118,7 +118,7 @@ AcpiPsGetNextPackageLength (
/* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
PackageLength |= (Aml[0] & ByteZeroMask);
- return_UINT32 (PackageLength);
+ return_VALUE (PackageLength);
}
@@ -182,7 +182,8 @@ AcpiPsGetNextNamestring (
/* Point past any namestring prefix characters (backslash or carat) */
- while (AcpiPsIsPrefixChar (*End))
+ while (ACPI_IS_ROOT_PREFIX (*End) ||
+ ACPI_IS_PARENT_PREFIX (*End))
{
End++;
}
@@ -868,7 +869,8 @@ AcpiPsGetNextArg (
Subop = AcpiPsPeekOpcode (ParserState);
if (Subop == 0 ||
AcpiPsIsLeadingChar (Subop) ||
- AcpiPsIsPrefixChar (Subop))
+ ACPI_IS_ROOT_PREFIX (Subop) ||
+ ACPI_IS_PARENT_PREFIX (Subop))
{
/* NullName or NameString */
diff --git a/sys/contrib/dev/acpica/components/parser/psloop.c b/sys/contrib/dev/acpica/components/parser/psloop.c
index 814bd93..4472bf1 100644
--- a/sys/contrib/dev/acpica/components/parser/psloop.c
+++ b/sys/contrib/dev/acpica/components/parser/psloop.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,46 +59,15 @@
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME ("psloop")
-static UINT32 AcpiGbl_Depth = 0;
-
/* Local prototypes */
static ACPI_STATUS
-AcpiPsGetAmlOpcode (
- ACPI_WALK_STATE *WalkState);
-
-static ACPI_STATUS
-AcpiPsBuildNamedOp (
- ACPI_WALK_STATE *WalkState,
- UINT8 *AmlOpStart,
- ACPI_PARSE_OBJECT *UnnamedOp,
- ACPI_PARSE_OBJECT **Op);
-
-static ACPI_STATUS
-AcpiPsCreateOp (
- ACPI_WALK_STATE *WalkState,
- UINT8 *AmlOpStart,
- ACPI_PARSE_OBJECT **NewOp);
-
-static ACPI_STATUS
AcpiPsGetArguments (
ACPI_WALK_STATE *WalkState,
UINT8 *AmlOpStart,
ACPI_PARSE_OBJECT *Op);
-static ACPI_STATUS
-AcpiPsCompleteOp (
- ACPI_WALK_STATE *WalkState,
- ACPI_PARSE_OBJECT **Op,
- ACPI_STATUS Status);
-
-static ACPI_STATUS
-AcpiPsCompleteFinalOp (
- ACPI_WALK_STATE *WalkState,
- ACPI_PARSE_OBJECT *Op,
- ACPI_STATUS Status);
-
static void
AcpiPsLinkModuleCode (
ACPI_PARSE_OBJECT *ParentOp,
@@ -109,341 +78,6 @@ AcpiPsLinkModuleCode (
/*******************************************************************************
*
- * FUNCTION: AcpiPsGetAmlOpcode
- *
- * PARAMETERS: WalkState - Current state
- *
- * RETURN: Status
- *
- * DESCRIPTION: Extract the next AML opcode from the input stream.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsGetAmlOpcode (
- ACPI_WALK_STATE *WalkState)
-{
-
- ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
-
-
- WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
- WalkState->ParserState.AmlStart);
- WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
-
- /*
- * First cut to determine what we have found:
- * 1) A valid AML opcode
- * 2) A name string
- * 3) An unknown/invalid opcode
- */
- WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
-
- switch (WalkState->OpInfo->Class)
- {
- case AML_CLASS_ASCII:
- case AML_CLASS_PREFIX:
- /*
- * Starts with a valid prefix or ASCII char, this is a name
- * string. Convert the bare name string to a namepath.
- */
- WalkState->Opcode = AML_INT_NAMEPATH_OP;
- WalkState->ArgTypes = ARGP_NAMESTRING;
- break;
-
- case AML_CLASS_UNKNOWN:
-
- /* The opcode is unrecognized. Complain and skip unknown opcodes */
-
- if (WalkState->PassNumber == 2)
- {
- ACPI_ERROR ((AE_INFO,
- "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
- WalkState->Opcode,
- (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))));
-
- ACPI_DUMP_BUFFER (WalkState->ParserState.Aml - 16, 48);
-
-#ifdef ACPI_ASL_COMPILER
- /*
- * This is executed for the disassembler only. Output goes
- * to the disassembled ASL output file.
- */
- AcpiOsPrintf (
- "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
- WalkState->Opcode,
- (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)));
-
- /* Dump the context surrounding the invalid opcode */
-
- AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16),
- 48, DB_BYTE_DISPLAY,
- WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16);
- AcpiOsPrintf (" */\n");
-#endif
- }
-
- /* Increment past one-byte or two-byte opcode */
-
- WalkState->ParserState.Aml++;
- if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */
- {
- WalkState->ParserState.Aml++;
- }
-
- return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
-
- default:
-
- /* Found opcode info, this is a normal opcode */
-
- WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
- WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
- break;
- }
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsBuildNamedOp
- *
- * PARAMETERS: WalkState - Current state
- * AmlOpStart - Begin of named Op in AML
- * UnnamedOp - Early Op (not a named Op)
- * Op - Returned Op
- *
- * RETURN: Status
- *
- * DESCRIPTION: Parse a named Op
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsBuildNamedOp (
- ACPI_WALK_STATE *WalkState,
- UINT8 *AmlOpStart,
- ACPI_PARSE_OBJECT *UnnamedOp,
- ACPI_PARSE_OBJECT **Op)
-{
- ACPI_STATUS Status = AE_OK;
- ACPI_PARSE_OBJECT *Arg = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
-
-
- UnnamedOp->Common.Value.Arg = NULL;
- UnnamedOp->Common.ArgListLength = 0;
- UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
-
- /*
- * Get and append arguments until we find the node that contains
- * the name (the type ARGP_NAME).
- */
- while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
- (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
- {
- Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
- GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- AcpiPsAppendArg (UnnamedOp, Arg);
- INCREMENT_ARG_LIST (WalkState->ArgTypes);
- }
-
- /*
- * Make sure that we found a NAME and didn't run out of arguments
- */
- if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
- {
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
- }
-
- /* We know that this arg is a name, move to next arg */
-
- INCREMENT_ARG_LIST (WalkState->ArgTypes);
-
- /*
- * Find the object. This will either insert the object into
- * the namespace or simply look it up
- */
- WalkState->Op = NULL;
-
- Status = WalkState->DescendingCallback (WalkState, Op);
- if (ACPI_FAILURE (Status))
- {
- ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
- return_ACPI_STATUS (Status);
- }
-
- if (!*Op)
- {
- return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
- }
-
- Status = AcpiPsNextParseState (WalkState, *Op, Status);
- if (ACPI_FAILURE (Status))
- {
- if (Status == AE_CTRL_PENDING)
- {
- return_ACPI_STATUS (AE_CTRL_PARSE_PENDING);
- }
- return_ACPI_STATUS (Status);
- }
-
- AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
- AcpiGbl_Depth++;
-
- if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
- (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
- {
- /*
- * Defer final parsing of an OperationRegion body, because we don't
- * have enough info in the first pass to parse it correctly (i.e.,
- * there may be method calls within the TermArg elements of the body.)
- *
- * However, we must continue parsing because the opregion is not a
- * standalone package -- we don't know where the end is at this point.
- *
- * (Length is unknown until parse of the body complete)
- */
- (*Op)->Named.Data = AmlOpStart;
- (*Op)->Named.Length = 0;
- }
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsCreateOp
- *
- * PARAMETERS: WalkState - Current state
- * AmlOpStart - Op start in AML
- * NewOp - Returned Op
- *
- * RETURN: Status
- *
- * DESCRIPTION: Get Op from AML
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsCreateOp (
- ACPI_WALK_STATE *WalkState,
- UINT8 *AmlOpStart,
- ACPI_PARSE_OBJECT **NewOp)
-{
- ACPI_STATUS Status = AE_OK;
- ACPI_PARSE_OBJECT *Op;
- ACPI_PARSE_OBJECT *NamedOp = NULL;
- ACPI_PARSE_OBJECT *ParentScope;
- UINT8 ArgumentCount;
- const ACPI_OPCODE_INFO *OpInfo;
-
-
- ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
-
-
- Status = AcpiPsGetAmlOpcode (WalkState);
- if (Status == AE_CTRL_PARSE_CONTINUE)
- {
- return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
- }
-
- /* Create Op structure and append to parent's argument list */
-
- WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
- Op = AcpiPsAllocOp (WalkState->Opcode);
- if (!Op)
- {
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
-
- if (WalkState->OpInfo->Flags & AML_NAMED)
- {
- Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
- AcpiPsFreeOp (Op);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- *NewOp = NamedOp;
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Not a named opcode, just allocate Op and append to parent */
-
- if (WalkState->OpInfo->Flags & AML_CREATE)
- {
- /*
- * Backup to beginning of CreateXXXfield declaration
- * BodyLength is unknown until we parse the body
- */
- Op->Named.Data = AmlOpStart;
- Op->Named.Length = 0;
- }
-
- if (WalkState->Opcode == AML_BANK_FIELD_OP)
- {
- /*
- * Backup to beginning of BankField declaration
- * BodyLength is unknown until we parse the body
- */
- Op->Named.Data = AmlOpStart;
- Op->Named.Length = 0;
- }
-
- ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
- AcpiPsAppendArg (ParentScope, Op);
-
- if (ParentScope)
- {
- OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
- if (OpInfo->Flags & AML_HAS_TARGET)
- {
- ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
- if (ParentScope->Common.ArgListLength > ArgumentCount)
- {
- Op->Common.Flags |= ACPI_PARSEOP_TARGET;
- }
- }
- else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
- {
- Op->Common.Flags |= ACPI_PARSEOP_TARGET;
- }
- }
-
- if (WalkState->DescendingCallback != NULL)
- {
- /*
- * Find the object. This will either insert the object into
- * the namespace or simply look it up
- */
- WalkState->Op = *NewOp = Op;
-
- Status = WalkState->DescendingCallback (WalkState, &Op);
- Status = AcpiPsNextParseState (WalkState, Op, Status);
- if (Status == AE_CTRL_PENDING)
- {
- Status = AE_CTRL_PARSE_PENDING;
- }
- }
-
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiPsGetArguments
*
* PARAMETERS: WalkState - Current state
@@ -746,298 +380,6 @@ AcpiPsLinkModuleCode (
}
}
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsCompleteOp
- *
- * PARAMETERS: WalkState - Current state
- * Op - Returned Op
- * Status - Parse status before complete Op
- *
- * RETURN: Status
- *
- * DESCRIPTION: Complete Op
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsCompleteOp (
- ACPI_WALK_STATE *WalkState,
- ACPI_PARSE_OBJECT **Op,
- ACPI_STATUS Status)
-{
- ACPI_STATUS Status2;
-
-
- ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
-
-
- /*
- * Finished one argument of the containing scope
- */
- WalkState->ParserState.Scope->ParseScope.ArgCount--;
-
- /* Close this Op (will result in parse subtree deletion) */
-
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
-
- *Op = NULL;
-
- switch (Status)
- {
- case AE_OK:
- break;
-
-
- case AE_CTRL_TRANSFER:
-
- /* We are about to transfer to a called method */
-
- WalkState->PrevOp = NULL;
- WalkState->PrevArgTypes = WalkState->ArgTypes;
- return_ACPI_STATUS (Status);
-
-
- case AE_CTRL_END:
-
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
-
- if (*Op)
- {
- WalkState->Op = *Op;
- WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
- WalkState->Opcode = (*Op)->Common.AmlOpcode;
-
- Status = WalkState->AscendingCallback (WalkState);
- Status = AcpiPsNextParseState (WalkState, *Op, Status);
-
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
- }
-
- Status = AE_OK;
- break;
-
-
- case AE_CTRL_BREAK:
- case AE_CTRL_CONTINUE:
-
- /* Pop off scopes until we find the While */
-
- while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
- {
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
- }
-
- /* Close this iteration of the While loop */
-
- WalkState->Op = *Op;
- WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
- WalkState->Opcode = (*Op)->Common.AmlOpcode;
-
- Status = WalkState->AscendingCallback (WalkState);
- Status = AcpiPsNextParseState (WalkState, *Op, Status);
-
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
-
- Status = AE_OK;
- break;
-
-
- case AE_CTRL_TERMINATE:
-
- /* Clean up */
- do
- {
- if (*Op)
- {
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
-
- AcpiUtDeleteGenericState (
- AcpiUtPopGenericState (&WalkState->ControlState));
- }
-
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
-
- } while (*Op);
-
- return_ACPI_STATUS (AE_OK);
-
-
- default: /* All other non-AE_OK status */
-
- do
- {
- if (*Op)
- {
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
- }
-
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
-
- } while (*Op);
-
-
-#if 0
- /*
- * TBD: Cleanup parse ops on error
- */
- if (*Op == NULL)
- {
- AcpiPsPopScope (ParserState, Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
- }
-#endif
- WalkState->PrevOp = NULL;
- WalkState->PrevArgTypes = WalkState->ArgTypes;
- return_ACPI_STATUS (Status);
- }
-
- /* This scope complete? */
-
- if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
- {
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
- }
- else
- {
- *Op = NULL;
- }
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsCompleteFinalOp
- *
- * PARAMETERS: WalkState - Current state
- * Op - Current Op
- * Status - Current parse status before complete last
- * Op
- *
- * RETURN: Status
- *
- * DESCRIPTION: Complete last Op.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsCompleteFinalOp (
- ACPI_WALK_STATE *WalkState,
- ACPI_PARSE_OBJECT *Op,
- ACPI_STATUS Status)
-{
- ACPI_STATUS Status2;
-
-
- ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
-
-
- /*
- * Complete the last Op (if not completed), and clear the scope stack.
- * It is easily possible to end an AML "package" with an unbounded number
- * of open scopes (such as when several ASL blocks are closed with
- * sequential closing braces). We want to terminate each one cleanly.
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
- do
- {
- if (Op)
- {
- if (WalkState->AscendingCallback != NULL)
- {
- WalkState->Op = Op;
- WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
- WalkState->Opcode = Op->Common.AmlOpcode;
-
- Status = WalkState->AscendingCallback (WalkState);
- Status = AcpiPsNextParseState (WalkState, Op, Status);
- if (Status == AE_CTRL_PENDING)
- {
- Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
- }
-
- if (Status == AE_CTRL_TERMINATE)
- {
- Status = AE_OK;
-
- /* Clean up */
- do
- {
- if (Op)
- {
- Status2 = AcpiPsCompleteThisOp (WalkState, Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
- }
-
- AcpiPsPopScope (&(WalkState->ParserState), &Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
-
- } while (Op);
-
- return_ACPI_STATUS (Status);
- }
-
- else if (ACPI_FAILURE (Status))
- {
- /* First error is most important */
-
- (void) AcpiPsCompleteThisOp (WalkState, Op);
- return_ACPI_STATUS (Status);
- }
- }
-
- Status2 = AcpiPsCompleteThisOp (WalkState, Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
- }
-
- AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
- &WalkState->ArgCount);
-
- } while (Op);
-
- return_ACPI_STATUS (Status);
-}
-
-
/*******************************************************************************
*
* FUNCTION: AcpiPsParseLoop
@@ -1225,11 +567,6 @@ AcpiPsParseLoop (
WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
if (WalkState->OpInfo->Flags & AML_NAMED)
{
- if (AcpiGbl_Depth)
- {
- AcpiGbl_Depth--;
- }
-
if (Op->Common.AmlOpcode == AML_REGION_OP ||
Op->Common.AmlOpcode == AML_DATA_REGION_OP)
{
diff --git a/sys/contrib/dev/acpica/components/parser/psobject.c b/sys/contrib/dev/acpica/components/parser/psobject.c
new file mode 100644
index 0000000..397c6f9
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/parser/psobject.c
@@ -0,0 +1,683 @@
+/******************************************************************************
+ *
+ * Module Name: psobject - Support for parse objects
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acparser.h>
+#include <contrib/dev/acpica/include/amlcode.h>
+
+#define _COMPONENT ACPI_PARSER
+ ACPI_MODULE_NAME ("psobject")
+
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiPsGetAmlOpcode (
+ ACPI_WALK_STATE *WalkState);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsGetAmlOpcode
+ *
+ * PARAMETERS: WalkState - Current state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Extract the next AML opcode from the input stream.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiPsGetAmlOpcode (
+ ACPI_WALK_STATE *WalkState)
+{
+
+ ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
+
+
+ WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
+ WalkState->ParserState.AmlStart);
+ WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
+
+ /*
+ * First cut to determine what we have found:
+ * 1) A valid AML opcode
+ * 2) A name string
+ * 3) An unknown/invalid opcode
+ */
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
+
+ switch (WalkState->OpInfo->Class)
+ {
+ case AML_CLASS_ASCII:
+ case AML_CLASS_PREFIX:
+ /*
+ * Starts with a valid prefix or ASCII char, this is a name
+ * string. Convert the bare name string to a namepath.
+ */
+ WalkState->Opcode = AML_INT_NAMEPATH_OP;
+ WalkState->ArgTypes = ARGP_NAMESTRING;
+ break;
+
+ case AML_CLASS_UNKNOWN:
+
+ /* The opcode is unrecognized. Complain and skip unknown opcodes */
+
+ if (WalkState->PassNumber == 2)
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
+ WalkState->Opcode,
+ (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))));
+
+ ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48);
+
+#ifdef ACPI_ASL_COMPILER
+ /*
+ * This is executed for the disassembler only. Output goes
+ * to the disassembled ASL output file.
+ */
+ AcpiOsPrintf (
+ "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
+ WalkState->Opcode,
+ (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)));
+
+ /* Dump the context surrounding the invalid opcode */
+
+ AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16),
+ 48, DB_BYTE_DISPLAY,
+ (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16));
+ AcpiOsPrintf (" */\n");
+#endif
+ }
+
+ /* Increment past one-byte or two-byte opcode */
+
+ WalkState->ParserState.Aml++;
+ if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */
+ {
+ WalkState->ParserState.Aml++;
+ }
+
+ return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
+
+ default:
+
+ /* Found opcode info, this is a normal opcode */
+
+ WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
+ WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
+ break;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsBuildNamedOp
+ *
+ * PARAMETERS: WalkState - Current state
+ * AmlOpStart - Begin of named Op in AML
+ * UnnamedOp - Early Op (not a named Op)
+ * Op - Returned Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Parse a named Op
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiPsBuildNamedOp (
+ ACPI_WALK_STATE *WalkState,
+ UINT8 *AmlOpStart,
+ ACPI_PARSE_OBJECT *UnnamedOp,
+ ACPI_PARSE_OBJECT **Op)
+{
+ ACPI_STATUS Status = AE_OK;
+ ACPI_PARSE_OBJECT *Arg = NULL;
+
+
+ ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
+
+
+ UnnamedOp->Common.Value.Arg = NULL;
+ UnnamedOp->Common.ArgListLength = 0;
+ UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
+
+ /*
+ * Get and append arguments until we find the node that contains
+ * the name (the type ARGP_NAME).
+ */
+ while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
+ (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
+ {
+ Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
+ GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ AcpiPsAppendArg (UnnamedOp, Arg);
+ INCREMENT_ARG_LIST (WalkState->ArgTypes);
+ }
+
+ /*
+ * Make sure that we found a NAME and didn't run out of arguments
+ */
+ if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
+ {
+ return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ }
+
+ /* We know that this arg is a name, move to next arg */
+
+ INCREMENT_ARG_LIST (WalkState->ArgTypes);
+
+ /*
+ * Find the object. This will either insert the object into
+ * the namespace or simply look it up
+ */
+ WalkState->Op = NULL;
+
+ Status = WalkState->DescendingCallback (WalkState, Op);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
+ return_ACPI_STATUS (Status);
+ }
+
+ if (!*Op)
+ {
+ return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
+ }
+
+ Status = AcpiPsNextParseState (WalkState, *Op, Status);
+ if (ACPI_FAILURE (Status))
+ {
+ if (Status == AE_CTRL_PENDING)
+ {
+ return_ACPI_STATUS (AE_CTRL_PARSE_PENDING);
+ }
+ return_ACPI_STATUS (Status);
+ }
+
+ AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
+
+ if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
+ (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
+ {
+ /*
+ * Defer final parsing of an OperationRegion body, because we don't
+ * have enough info in the first pass to parse it correctly (i.e.,
+ * there may be method calls within the TermArg elements of the body.)
+ *
+ * However, we must continue parsing because the opregion is not a
+ * standalone package -- we don't know where the end is at this point.
+ *
+ * (Length is unknown until parse of the body complete)
+ */
+ (*Op)->Named.Data = AmlOpStart;
+ (*Op)->Named.Length = 0;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsCreateOp
+ *
+ * PARAMETERS: WalkState - Current state
+ * AmlOpStart - Op start in AML
+ * NewOp - Returned Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get Op from AML
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiPsCreateOp (
+ ACPI_WALK_STATE *WalkState,
+ UINT8 *AmlOpStart,
+ ACPI_PARSE_OBJECT **NewOp)
+{
+ ACPI_STATUS Status = AE_OK;
+ ACPI_PARSE_OBJECT *Op;
+ ACPI_PARSE_OBJECT *NamedOp = NULL;
+ ACPI_PARSE_OBJECT *ParentScope;
+ UINT8 ArgumentCount;
+ const ACPI_OPCODE_INFO *OpInfo;
+
+
+ ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
+
+
+ Status = AcpiPsGetAmlOpcode (WalkState);
+ if (Status == AE_CTRL_PARSE_CONTINUE)
+ {
+ return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
+ }
+
+ /* Create Op structure and append to parent's argument list */
+
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
+ Op = AcpiPsAllocOp (WalkState->Opcode);
+ if (!Op)
+ {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ if (WalkState->OpInfo->Flags & AML_NAMED)
+ {
+ Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
+ AcpiPsFreeOp (Op);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ *NewOp = NamedOp;
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Not a named opcode, just allocate Op and append to parent */
+
+ if (WalkState->OpInfo->Flags & AML_CREATE)
+ {
+ /*
+ * Backup to beginning of CreateXXXfield declaration
+ * BodyLength is unknown until we parse the body
+ */
+ Op->Named.Data = AmlOpStart;
+ Op->Named.Length = 0;
+ }
+
+ if (WalkState->Opcode == AML_BANK_FIELD_OP)
+ {
+ /*
+ * Backup to beginning of BankField declaration
+ * BodyLength is unknown until we parse the body
+ */
+ Op->Named.Data = AmlOpStart;
+ Op->Named.Length = 0;
+ }
+
+ ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
+ AcpiPsAppendArg (ParentScope, Op);
+
+ if (ParentScope)
+ {
+ OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
+ if (OpInfo->Flags & AML_HAS_TARGET)
+ {
+ ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
+ if (ParentScope->Common.ArgListLength > ArgumentCount)
+ {
+ Op->Common.Flags |= ACPI_PARSEOP_TARGET;
+ }
+ }
+ else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
+ {
+ Op->Common.Flags |= ACPI_PARSEOP_TARGET;
+ }
+ }
+
+ if (WalkState->DescendingCallback != NULL)
+ {
+ /*
+ * Find the object. This will either insert the object into
+ * the namespace or simply look it up
+ */
+ WalkState->Op = *NewOp = Op;
+
+ Status = WalkState->DescendingCallback (WalkState, &Op);
+ Status = AcpiPsNextParseState (WalkState, Op, Status);
+ if (Status == AE_CTRL_PENDING)
+ {
+ Status = AE_CTRL_PARSE_PENDING;
+ }
+ }
+
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsCompleteOp
+ *
+ * PARAMETERS: WalkState - Current state
+ * Op - Returned Op
+ * Status - Parse status before complete Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Complete Op
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiPsCompleteOp (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT **Op,
+ ACPI_STATUS Status)
+{
+ ACPI_STATUS Status2;
+
+
+ ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
+
+
+ /*
+ * Finished one argument of the containing scope
+ */
+ WalkState->ParserState.Scope->ParseScope.ArgCount--;
+
+ /* Close this Op (will result in parse subtree deletion) */
+
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+
+ *Op = NULL;
+
+ switch (Status)
+ {
+ case AE_OK:
+ break;
+
+
+ case AE_CTRL_TRANSFER:
+
+ /* We are about to transfer to a called method */
+
+ WalkState->PrevOp = NULL;
+ WalkState->PrevArgTypes = WalkState->ArgTypes;
+ return_ACPI_STATUS (Status);
+
+
+ case AE_CTRL_END:
+
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+
+ if (*Op)
+ {
+ WalkState->Op = *Op;
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
+ WalkState->Opcode = (*Op)->Common.AmlOpcode;
+
+ Status = WalkState->AscendingCallback (WalkState);
+ Status = AcpiPsNextParseState (WalkState, *Op, Status);
+
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+ }
+
+ Status = AE_OK;
+ break;
+
+
+ case AE_CTRL_BREAK:
+ case AE_CTRL_CONTINUE:
+
+ /* Pop off scopes until we find the While */
+
+ while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
+ {
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+ }
+
+ /* Close this iteration of the While loop */
+
+ WalkState->Op = *Op;
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
+ WalkState->Opcode = (*Op)->Common.AmlOpcode;
+
+ Status = WalkState->AscendingCallback (WalkState);
+ Status = AcpiPsNextParseState (WalkState, *Op, Status);
+
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+
+ Status = AE_OK;
+ break;
+
+
+ case AE_CTRL_TERMINATE:
+
+ /* Clean up */
+ do
+ {
+ if (*Op)
+ {
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+
+ AcpiUtDeleteGenericState (
+ AcpiUtPopGenericState (&WalkState->ControlState));
+ }
+
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+
+ } while (*Op);
+
+ return_ACPI_STATUS (AE_OK);
+
+
+ default: /* All other non-AE_OK status */
+
+ do
+ {
+ if (*Op)
+ {
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+ }
+
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+
+ } while (*Op);
+
+
+#if 0
+ /*
+ * TBD: Cleanup parse ops on error
+ */
+ if (*Op == NULL)
+ {
+ AcpiPsPopScope (ParserState, Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+ }
+#endif
+ WalkState->PrevOp = NULL;
+ WalkState->PrevArgTypes = WalkState->ArgTypes;
+ return_ACPI_STATUS (Status);
+ }
+
+ /* This scope complete? */
+
+ if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
+ {
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
+ }
+ else
+ {
+ *Op = NULL;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsCompleteFinalOp
+ *
+ * PARAMETERS: WalkState - Current state
+ * Op - Current Op
+ * Status - Current parse status before complete last
+ * Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Complete last Op.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiPsCompleteFinalOp (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT *Op,
+ ACPI_STATUS Status)
+{
+ ACPI_STATUS Status2;
+
+
+ ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
+
+
+ /*
+ * Complete the last Op (if not completed), and clear the scope stack.
+ * It is easily possible to end an AML "package" with an unbounded number
+ * of open scopes (such as when several ASL blocks are closed with
+ * sequential closing braces). We want to terminate each one cleanly.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
+ do
+ {
+ if (Op)
+ {
+ if (WalkState->AscendingCallback != NULL)
+ {
+ WalkState->Op = Op;
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
+ WalkState->Opcode = Op->Common.AmlOpcode;
+
+ Status = WalkState->AscendingCallback (WalkState);
+ Status = AcpiPsNextParseState (WalkState, Op, Status);
+ if (Status == AE_CTRL_PENDING)
+ {
+ Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ }
+
+ if (Status == AE_CTRL_TERMINATE)
+ {
+ Status = AE_OK;
+
+ /* Clean up */
+ do
+ {
+ if (Op)
+ {
+ Status2 = AcpiPsCompleteThisOp (WalkState, Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+ }
+
+ AcpiPsPopScope (&(WalkState->ParserState), &Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+
+ } while (Op);
+
+ return_ACPI_STATUS (Status);
+ }
+
+ else if (ACPI_FAILURE (Status))
+ {
+ /* First error is most important */
+
+ (void) AcpiPsCompleteThisOp (WalkState, Op);
+ return_ACPI_STATUS (Status);
+ }
+ }
+
+ Status2 = AcpiPsCompleteThisOp (WalkState, Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+ }
+
+ AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
+ &WalkState->ArgCount);
+
+ } while (Op);
+
+ return_ACPI_STATUS (Status);
+}
diff --git a/sys/contrib/dev/acpica/components/parser/psopcode.c b/sys/contrib/dev/acpica/components/parser/psopcode.c
index 85e170d..8ae0c80 100644
--- a/sys/contrib/dev/acpica/components/parser/psopcode.c
+++ b/sys/contrib/dev/acpica/components/parser/psopcode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,6 @@
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
-#include <contrib/dev/acpica/include/acparser.h>
#include <contrib/dev/acpica/include/acopcode.h>
#include <contrib/dev/acpica/include/amlcode.h>
@@ -53,9 +52,6 @@
ACPI_MODULE_NAME ("psopcode")
-static const UINT8 AcpiGbl_ArgumentCount[] = {0,1,1,1,1,2,2,2,2,3,3,6};
-
-
/*******************************************************************************
*
* NAME: AcpiGbl_AmlOpInfo
@@ -342,181 +338,3 @@ const ACPI_OPCODE_INFO AcpiGbl_AmlOpInfo[AML_NUM_OPCODES] =
/*! [End] no source code translation !*/
};
-
-/*
- * This table is directly indexed by the opcodes, and returns an
- * index into the table above
- */
-static const UINT8 AcpiGbl_ShortOpIndex[256] =
-{
-/* 0 1 2 3 4 5 6 7 */
-/* 8 9 A B C D E F */
-/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
-/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
-/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
-/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
-/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
-/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
-/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
-/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
-/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
-/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
-/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
-/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
-/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
-/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
-/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
-/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
-};
-
-/*
- * This table is indexed by the second opcode of the extended opcode
- * pair. It returns an index into the opcode table (AcpiGbl_AmlOpInfo)
- */
-static const UINT8 AcpiGbl_LongOpIndex[NUM_EXTENDED_OPCODE] =
-{
-/* 0 1 2 3 4 5 6 7 */
-/* 8 9 A B C D E F */
-/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
-/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
-/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
-/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-/* 0x88 */ 0x7C,
-};
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsGetOpcodeInfo
- *
- * PARAMETERS: Opcode - The AML opcode
- *
- * RETURN: A pointer to the info about the opcode.
- *
- * DESCRIPTION: Find AML opcode description based on the opcode.
- * NOTE: This procedure must ALWAYS return a valid pointer!
- *
- ******************************************************************************/
-
-const ACPI_OPCODE_INFO *
-AcpiPsGetOpcodeInfo (
- UINT16 Opcode)
-{
- ACPI_FUNCTION_NAME (PsGetOpcodeInfo);
-
-
- /*
- * Detect normal 8-bit opcode or extended 16-bit opcode
- */
- if (!(Opcode & 0xFF00))
- {
- /* Simple (8-bit) opcode: 0-255, can't index beyond table */
-
- return (&AcpiGbl_AmlOpInfo [AcpiGbl_ShortOpIndex [(UINT8) Opcode]]);
- }
-
- if (((Opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
- (((UINT8) Opcode) <= MAX_EXTENDED_OPCODE))
- {
- /* Valid extended (16-bit) opcode */
-
- return (&AcpiGbl_AmlOpInfo [AcpiGbl_LongOpIndex [(UINT8) Opcode]]);
- }
-
- /* Unknown AML opcode */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Unknown AML opcode [%4.4X]\n", Opcode));
-
- return (&AcpiGbl_AmlOpInfo [_UNK]);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsGetOpcodeName
- *
- * PARAMETERS: Opcode - The AML opcode
- *
- * RETURN: A pointer to the name of the opcode (ASCII String)
- * Note: Never returns NULL.
- *
- * DESCRIPTION: Translate an opcode into a human-readable string
- *
- ******************************************************************************/
-
-char *
-AcpiPsGetOpcodeName (
- UINT16 Opcode)
-{
-#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
-
- const ACPI_OPCODE_INFO *Op;
-
-
- Op = AcpiPsGetOpcodeInfo (Opcode);
-
- /* Always guaranteed to return a valid pointer */
-
- return (Op->Name);
-
-#else
- return ("OpcodeName unavailable");
-
-#endif
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsGetArgumentCount
- *
- * PARAMETERS: OpType - Type associated with the AML opcode
- *
- * RETURN: Argument count
- *
- * DESCRIPTION: Obtain the number of expected arguments for an AML opcode
- *
- ******************************************************************************/
-
-UINT8
-AcpiPsGetArgumentCount (
- UINT32 OpType)
-{
-
- if (OpType <= AML_TYPE_EXEC_6A_0T_1R)
- {
- return (AcpiGbl_ArgumentCount[OpType]);
- }
-
- return (0);
-}
diff --git a/sys/contrib/dev/acpica/components/parser/psopinfo.c b/sys/contrib/dev/acpica/components/parser/psopinfo.c
new file mode 100644
index 0000000..3c6e4a5
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/parser/psopinfo.c
@@ -0,0 +1,238 @@
+/******************************************************************************
+ *
+ * Module Name: psopinfo - AML opcode information functions and dispatch tables
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acparser.h>
+#include <contrib/dev/acpica/include/acopcode.h>
+#include <contrib/dev/acpica/include/amlcode.h>
+
+
+#define _COMPONENT ACPI_PARSER
+ ACPI_MODULE_NAME ("psopinfo")
+
+
+extern const UINT8 AcpiGbl_ShortOpIndex[];
+extern const UINT8 AcpiGbl_LongOpIndex[];
+
+static const UINT8 AcpiGbl_ArgumentCount[] = {0,1,1,1,1,2,2,2,2,3,3,6};
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsGetOpcodeInfo
+ *
+ * PARAMETERS: Opcode - The AML opcode
+ *
+ * RETURN: A pointer to the info about the opcode.
+ *
+ * DESCRIPTION: Find AML opcode description based on the opcode.
+ * NOTE: This procedure must ALWAYS return a valid pointer!
+ *
+ ******************************************************************************/
+
+const ACPI_OPCODE_INFO *
+AcpiPsGetOpcodeInfo (
+ UINT16 Opcode)
+{
+ ACPI_FUNCTION_NAME (PsGetOpcodeInfo);
+
+
+ /*
+ * Detect normal 8-bit opcode or extended 16-bit opcode
+ */
+ if (!(Opcode & 0xFF00))
+ {
+ /* Simple (8-bit) opcode: 0-255, can't index beyond table */
+
+ return (&AcpiGbl_AmlOpInfo [AcpiGbl_ShortOpIndex [(UINT8) Opcode]]);
+ }
+
+ if (((Opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
+ (((UINT8) Opcode) <= MAX_EXTENDED_OPCODE))
+ {
+ /* Valid extended (16-bit) opcode */
+
+ return (&AcpiGbl_AmlOpInfo [AcpiGbl_LongOpIndex [(UINT8) Opcode]]);
+ }
+
+ /* Unknown AML opcode */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Unknown AML opcode [%4.4X]\n", Opcode));
+
+ return (&AcpiGbl_AmlOpInfo [_UNK]);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsGetOpcodeName
+ *
+ * PARAMETERS: Opcode - The AML opcode
+ *
+ * RETURN: A pointer to the name of the opcode (ASCII String)
+ * Note: Never returns NULL.
+ *
+ * DESCRIPTION: Translate an opcode into a human-readable string
+ *
+ ******************************************************************************/
+
+char *
+AcpiPsGetOpcodeName (
+ UINT16 Opcode)
+{
+#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
+
+ const ACPI_OPCODE_INFO *Op;
+
+
+ Op = AcpiPsGetOpcodeInfo (Opcode);
+
+ /* Always guaranteed to return a valid pointer */
+
+ return (Op->Name);
+
+#else
+ return ("OpcodeName unavailable");
+
+#endif
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsGetArgumentCount
+ *
+ * PARAMETERS: OpType - Type associated with the AML opcode
+ *
+ * RETURN: Argument count
+ *
+ * DESCRIPTION: Obtain the number of expected arguments for an AML opcode
+ *
+ ******************************************************************************/
+
+UINT8
+AcpiPsGetArgumentCount (
+ UINT32 OpType)
+{
+
+ if (OpType <= AML_TYPE_EXEC_6A_0T_1R)
+ {
+ return (AcpiGbl_ArgumentCount[OpType]);
+ }
+
+ return (0);
+}
+
+
+/*
+ * This table is directly indexed by the opcodes It returns
+ * an index into the opcode table (AcpiGbl_AmlOpInfo)
+ */
+const UINT8 AcpiGbl_ShortOpIndex[256] =
+{
+/* 0 1 2 3 4 5 6 7 */
+/* 8 9 A B C D E F */
+/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
+/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
+/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
+/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
+/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
+/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
+/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
+/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
+/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
+/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
+/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
+/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
+/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
+};
+
+/*
+ * This table is indexed by the second opcode of the extended opcode
+ * pair. It returns an index into the opcode table (AcpiGbl_AmlOpInfo)
+ */
+const UINT8 AcpiGbl_LongOpIndex[NUM_EXTENDED_OPCODE] =
+{
+/* 0 1 2 3 4 5 6 7 */
+/* 8 9 A B C D E F */
+/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
+/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
+/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
+/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+/* 0x88 */ 0x7C,
+};
diff --git a/sys/contrib/dev/acpica/components/parser/psparse.c b/sys/contrib/dev/acpica/components/parser/psparse.c
index 1193262..1dafdc1 100644
--- a/sys/contrib/dev/acpica/components/parser/psparse.c
+++ b/sys/contrib/dev/acpica/components/parser/psparse.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/psscope.c b/sys/contrib/dev/acpica/components/parser/psscope.c
index 3d88272..3aa102bd 100644
--- a/sys/contrib/dev/acpica/components/parser/psscope.c
+++ b/sys/contrib/dev/acpica/components/parser/psscope.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/pstree.c b/sys/contrib/dev/acpica/components/parser/pstree.c
index 9ad3412..277c702 100644
--- a/sys/contrib/dev/acpica/components/parser/pstree.c
+++ b/sys/contrib/dev/acpica/components/parser/pstree.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/psutils.c b/sys/contrib/dev/acpica/components/parser/psutils.c
index ca0e1d3..4b555cc 100644
--- a/sys/contrib/dev/acpica/components/parser/psutils.c
+++ b/sys/contrib/dev/acpica/components/parser/psutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -238,17 +238,6 @@ AcpiPsIsLeadingChar (
/*
- * Is "c" a namestring prefix character?
- */
-BOOLEAN
-AcpiPsIsPrefixChar (
- UINT32 c)
-{
- return ((BOOLEAN) (c == '\\' || c == '^'));
-}
-
-
-/*
* Get op's name (4-byte name segment) or 0 if unnamed
*/
UINT32
diff --git a/sys/contrib/dev/acpica/components/parser/pswalk.c b/sys/contrib/dev/acpica/components/parser/pswalk.c
index 6dd2b0d..6b6e289 100644
--- a/sys/contrib/dev/acpica/components/parser/pswalk.c
+++ b/sys/contrib/dev/acpica/components/parser/pswalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/psxface.c b/sys/contrib/dev/acpica/components/parser/psxface.c
index 1131e8c..6177baf 100644
--- a/sys/contrib/dev/acpica/components/parser/psxface.c
+++ b/sys/contrib/dev/acpica/components/parser/psxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsaddr.c b/sys/contrib/dev/acpica/components/resources/rsaddr.c
index 80eb57a..a8fa79d 100644
--- a/sys/contrib/dev/acpica/components/resources/rsaddr.c
+++ b/sys/contrib/dev/acpica/components/resources/rsaddr.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rscalc.c b/sys/contrib/dev/acpica/components/resources/rscalc.c
index 3820aa0..3b43775 100644
--- a/sys/contrib/dev/acpica/components/resources/rscalc.c
+++ b/sys/contrib/dev/acpica/components/resources/rscalc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rscreate.c b/sys/contrib/dev/acpica/components/resources/rscreate.c
index 87a9ecf..86c10aa 100644
--- a/sys/contrib/dev/acpica/components/resources/rscreate.c
+++ b/sys/contrib/dev/acpica/components/resources/rscreate.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsdump.c b/sys/contrib/dev/acpica/components/resources/rsdump.c
index acccad3..20c1893 100644
--- a/sys/contrib/dev/acpica/components/resources/rsdump.c
+++ b/sys/contrib/dev/acpica/components/resources/rsdump.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -119,315 +119,16 @@ AcpiRsDumpDescriptor (
ACPI_RSDUMP_INFO *Table);
-#define ACPI_RSD_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_RESOURCE_DATA,f)
-#define ACPI_PRT_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_PCI_ROUTING_TABLE,f)
-#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (ACPI_RSDUMP_INFO))
-
-
-/*******************************************************************************
- *
- * Resource Descriptor info tables
- *
- * Note: The first table entry must be a Title or Literal and must contain
- * the table length (number of table entries)
- *
- ******************************************************************************/
-
-ACPI_RSDUMP_INFO AcpiRsDumpIrq[7] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIrq), "IRQ", NULL},
- {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.DescriptorLength), "Descriptor Length", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Triggering), "Triggering", AcpiGbl_HeDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Polarity), "Polarity", AcpiGbl_LlDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Irq.Sharable), "Sharing", AcpiGbl_ShrDecode},
- {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.InterruptCount), "Interrupt Count", NULL},
- {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Irq.Interrupts[0]), "Interrupt List", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpDma[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpDma), "DMA", NULL},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Type), "Speed", AcpiGbl_TypDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Dma.BusMaster), "Mastering", AcpiGbl_BmDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Transfer), "Transfer Type", AcpiGbl_SizDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Dma.ChannelCount), "Channel Count", NULL},
- {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Dma.Channels[0]), "Channel List", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[4] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpStartDpf), "Start-Dependent-Functions",NULL},
- {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (StartDpf.DescriptorLength), "Descriptor Length", NULL},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.CompatibilityPriority), "Compatibility Priority", AcpiGbl_ConfigDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.PerformanceRobustness), "Performance/Robustness", AcpiGbl_ConfigDecode}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[1] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndDpf), "End-Dependent-Functions", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpIo[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIo), "I/O", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Io.IoDecode), "Address Decoding", AcpiGbl_IoDecode},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.Alignment), "Alignment", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpFixedIo[3] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedIo), "Fixed I/O", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedIo.Address), "Address", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedIo.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpVendor[3] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpVendor), "Vendor Specific", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Vendor.ByteLength), "Length", NULL},
- {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET (Vendor.ByteData[0]), "Vendor Data", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpEndTag[1] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndTag), "EndTag", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpMemory24[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory24), "24-Bit Memory Range", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory24.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Alignment), "Alignment", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpMemory32[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory32), "32-Bit Memory Range", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Alignment), "Alignment", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpFixedMemory32[4] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedMemory32), "32-Bit Fixed Memory Range",NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (FixedMemory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.Address), "Address", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpAddress16[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress16), "16-Bit WORD Address Space",NULL},
- {ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Granularity), "Granularity", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.TranslationOffset), "Translation Offset", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.AddressLength), "Address Length", NULL},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address16.ResourceSource), NULL, NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpAddress32[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress32), "32-Bit DWORD Address Space", NULL},
- {ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Granularity), "Granularity", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.TranslationOffset), "Translation Offset", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.AddressLength), "Address Length", NULL},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address32.ResourceSource), NULL, NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpAddress64[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress64), "64-Bit QWORD Address Space", NULL},
- {ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Granularity), "Granularity", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.TranslationOffset), "Translation Offset", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.AddressLength), "Address Length", NULL},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address64.ResourceSource), NULL, NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpExtAddress64[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtAddress64), "64-Bit Extended Address Space", NULL},
- {ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Granularity), "Granularity", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TranslationOffset), "Translation Offset", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.AddressLength), "Address Length", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TypeSpecific), "Type-Specific Attribute", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpExtIrq[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtIrq), "Extended IRQ", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.ProducerConsumer), "Type", AcpiGbl_ConsumeDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Triggering), "Triggering", AcpiGbl_HeDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Polarity), "Polarity", AcpiGbl_LlDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Sharable), "Sharing", AcpiGbl_ShrDecode},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (ExtendedIrq.ResourceSource), NULL, NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (ExtendedIrq.InterruptCount), "Interrupt Count", NULL},
- {ACPI_RSD_DWORDLIST,ACPI_RSD_OFFSET (ExtendedIrq.Interrupts[0]), "Interrupt List", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpGenericReg[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGenericReg), "Generic Register", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.SpaceId), "Space ID", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitWidth), "Bit Width", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitOffset), "Bit Offset", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.AccessSize), "Access Size", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (GenericReg.Address), "Address", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpGpio[16] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGpio), "GPIO", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.RevisionId), "RevisionId", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.ConnectionType), "ConnectionType", AcpiGbl_CtDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.PinConfig), "PinConfig", AcpiGbl_PpcDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Sharable), "Sharing", AcpiGbl_ShrDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.IoRestriction), "IoRestriction", AcpiGbl_IorDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.Triggering), "Triggering", AcpiGbl_HeDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Polarity), "Polarity", AcpiGbl_LlDecode},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DriveStrength), "DriveStrength", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DebounceTimeout), "DebounceTimeout", NULL},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Gpio.ResourceSource), "ResourceSource", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.PinTableLength), "PinTableLength", NULL},
- {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET (Gpio.PinTable), "PinTable", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.VendorLength), "VendorLength", NULL},
- {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (Gpio.VendorData), "VendorData", NULL},
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpFixedDma[4] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedDma), "FixedDma", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.RequestLines), "RequestLines", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.Channels), "Channels", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedDma.Width), "TransferWidth", AcpiGbl_DtsDecode},
-};
-
-#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.RevisionId), "RevisionId", NULL}, \
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.Type), "Type", AcpiGbl_SbtDecode}, \
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, \
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.SlaveMode), "SlaveMode", AcpiGbl_SmDecode}, \
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.TypeRevisionId), "TypeRevisionId", NULL}, \
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.TypeDataLength), "TypeDataLength", NULL}, \
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (CommonSerialBus.ResourceSource), "ResourceSource", NULL}, \
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.VendorLength), "VendorLength", NULL}, \
- {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (CommonSerialBus.VendorData), "VendorData", NULL},
-
-ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[10] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpCommonSerialBus), "Common Serial Bus", NULL},
- ACPI_RS_DUMP_COMMON_SERIAL_BUS
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[13] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpI2cSerialBus), "I2C Serial Bus", NULL},
- ACPI_RS_DUMP_COMMON_SERIAL_BUS
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (I2cSerialBus.AccessMode), "AccessMode", AcpiGbl_AmDecode},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (I2cSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (I2cSerialBus.SlaveAddress), "SlaveAddress", NULL},
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[17] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpSpiSerialBus), "Spi Serial Bus", NULL},
- ACPI_RS_DUMP_COMMON_SERIAL_BUS
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.WireMode), "WireMode", AcpiGbl_WmDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.DevicePolarity), "DevicePolarity", AcpiGbl_DpDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.DataBitLength), "DataBitLength", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPhase), "ClockPhase", AcpiGbl_CphDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPolarity), "ClockPolarity", AcpiGbl_CpoDecode},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (SpiSerialBus.DeviceSelection), "DeviceSelection", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (SpiSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL},
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[19] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpUartSerialBus), "Uart Serial Bus", NULL},
- ACPI_RS_DUMP_COMMON_SERIAL_BUS
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.FlowControl), "FlowControl", AcpiGbl_FcDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.StopBits), "StopBits", AcpiGbl_SbDecode},
- {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.DataBits), "DataBits", AcpiGbl_BpbDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.Endian), "Endian", AcpiGbl_EdDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.Parity), "Parity", AcpiGbl_PtDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.LinesEnabled), "LinesEnabled", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.RxFifoSize), "RxFifoSize", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.TxFifoSize), "TxFifoSize", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (UartSerialBus.DefaultBaudRate), "ConnectionSpeed", NULL},
-};
-
-/*
- * Tables used for common address descriptor flag fields
- */
-static ACPI_RSDUMP_INFO AcpiRsDumpGeneralFlags[5] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGeneralFlags), NULL, NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.ProducerConsumer), "Consumer/Producer", AcpiGbl_ConsumeDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Decode), "Address Decode", AcpiGbl_DecDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MinAddressFixed), "Min Relocatability", AcpiGbl_MinDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MaxAddressFixed), "Max Relocatability", AcpiGbl_MaxDecode}
-};
-
-static ACPI_RSDUMP_INFO AcpiRsDumpMemoryFlags[5] =
-{
- {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemoryFlags), "Resource Type", (void *) "Memory Range"},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Caching), "Caching", AcpiGbl_MemDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.RangeType), "Range Type", AcpiGbl_MtpDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Translation), "Translation", AcpiGbl_TtpDecode}
-};
-
-static ACPI_RSDUMP_INFO AcpiRsDumpIoFlags[4] =
-{
- {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIoFlags), "Resource Type", (void *) "I/O Range"},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.RangeType), "Range Type", AcpiGbl_RngDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.Translation), "Translation", AcpiGbl_TtpDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.TranslationType), "Translation Type", AcpiGbl_TrsDecode}
-};
-
-
-/*
- * Table used to dump _PRT contents
- */
-static ACPI_RSDUMP_INFO AcpiRsDumpPrt[5] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPrt), NULL, NULL},
- {ACPI_RSD_UINT64, ACPI_PRT_OFFSET (Address), "Address", NULL},
- {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (Pin), "Pin", NULL},
- {ACPI_RSD_STRING, ACPI_PRT_OFFSET (Source[0]), "Source", NULL},
- {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (SourceIndex), "Source Index", NULL}
-};
-
-
/*******************************************************************************
*
* FUNCTION: AcpiRsDumpDescriptor
*
- * PARAMETERS: Resource
+ * PARAMETERS: Resource - Buffer containing the resource
+ * Table - Table entry to decode the resource
*
* RETURN: None
*
- * DESCRIPTION:
+ * DESCRIPTION: Dump a resource descriptor based on a dump table entry.
*
******************************************************************************/
@@ -712,7 +413,9 @@ AcpiRsDumpResourceList (
ACPI_FUNCTION_ENTRY ();
- if (!(AcpiDbgLevel & ACPI_LV_RESOURCES) || !( _COMPONENT & AcpiDbgLayer))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_RESOURCES, _COMPONENT))
{
return;
}
@@ -781,7 +484,9 @@ AcpiRsDumpIrqList (
ACPI_FUNCTION_ENTRY ();
- if (!(AcpiDbgLevel & ACPI_LV_RESOURCES) || !( _COMPONENT & AcpiDbgLayer))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_RESOURCES, _COMPONENT))
{
return;
}
diff --git a/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c b/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c
new file mode 100644
index 0000000..865209b
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ *
+ * Module Name: rsdumpinfo - Tables used to display resource descriptors.
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#define __RSDUMPINFO_C__
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acresrc.h>
+
+#define _COMPONENT ACPI_RESOURCES
+ ACPI_MODULE_NAME ("rsdumpinfo")
+
+
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+
+
+#define ACPI_RSD_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_RESOURCE_DATA,f)
+#define ACPI_PRT_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_PCI_ROUTING_TABLE,f)
+#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (ACPI_RSDUMP_INFO))
+
+
+/*******************************************************************************
+ *
+ * Resource Descriptor info tables
+ *
+ * Note: The first table entry must be a Title or Literal and must contain
+ * the table length (number of table entries)
+ *
+ ******************************************************************************/
+
+ACPI_RSDUMP_INFO AcpiRsDumpIrq[7] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIrq), "IRQ", NULL},
+ {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.DescriptorLength), "Descriptor Length", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Triggering), "Triggering", AcpiGbl_HeDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Polarity), "Polarity", AcpiGbl_LlDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Irq.Sharable), "Sharing", AcpiGbl_ShrDecode},
+ {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.InterruptCount), "Interrupt Count", NULL},
+ {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Irq.Interrupts[0]), "Interrupt List", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpDma[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpDma), "DMA", NULL},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Type), "Speed", AcpiGbl_TypDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Dma.BusMaster), "Mastering", AcpiGbl_BmDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Transfer), "Transfer Type", AcpiGbl_SizDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Dma.ChannelCount), "Channel Count", NULL},
+ {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Dma.Channels[0]), "Channel List", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[4] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpStartDpf), "Start-Dependent-Functions",NULL},
+ {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (StartDpf.DescriptorLength), "Descriptor Length", NULL},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.CompatibilityPriority), "Compatibility Priority", AcpiGbl_ConfigDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.PerformanceRobustness), "Performance/Robustness", AcpiGbl_ConfigDecode}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[1] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndDpf), "End-Dependent-Functions", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpIo[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIo), "I/O", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Io.IoDecode), "Address Decoding", AcpiGbl_IoDecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.Alignment), "Alignment", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpFixedIo[3] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedIo), "Fixed I/O", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedIo.Address), "Address", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedIo.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpVendor[3] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpVendor), "Vendor Specific", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Vendor.ByteLength), "Length", NULL},
+ {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET (Vendor.ByteData[0]), "Vendor Data", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpEndTag[1] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndTag), "EndTag", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpMemory24[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory24), "24-Bit Memory Range", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory24.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Alignment), "Alignment", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpMemory32[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory32), "32-Bit Memory Range", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Alignment), "Alignment", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpFixedMemory32[4] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedMemory32), "32-Bit Fixed Memory Range",NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (FixedMemory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.Address), "Address", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpAddress16[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress16), "16-Bit WORD Address Space",NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Granularity), "Granularity", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.TranslationOffset), "Translation Offset", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.AddressLength), "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address16.ResourceSource), NULL, NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpAddress32[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress32), "32-Bit DWORD Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Granularity), "Granularity", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.TranslationOffset), "Translation Offset", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.AddressLength), "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address32.ResourceSource), NULL, NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpAddress64[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress64), "64-Bit QWORD Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Granularity), "Granularity", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.TranslationOffset), "Translation Offset", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.AddressLength), "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address64.ResourceSource), NULL, NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpExtAddress64[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtAddress64), "64-Bit Extended Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Granularity), "Granularity", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TranslationOffset), "Translation Offset", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.AddressLength), "Address Length", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TypeSpecific), "Type-Specific Attribute", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpExtIrq[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtIrq), "Extended IRQ", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.ProducerConsumer), "Type", AcpiGbl_ConsumeDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Triggering), "Triggering", AcpiGbl_HeDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Polarity), "Polarity", AcpiGbl_LlDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Sharable), "Sharing", AcpiGbl_ShrDecode},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (ExtendedIrq.ResourceSource), NULL, NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (ExtendedIrq.InterruptCount), "Interrupt Count", NULL},
+ {ACPI_RSD_DWORDLIST,ACPI_RSD_OFFSET (ExtendedIrq.Interrupts[0]), "Interrupt List", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpGenericReg[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGenericReg), "Generic Register", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.SpaceId), "Space ID", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitWidth), "Bit Width", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitOffset), "Bit Offset", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.AccessSize), "Access Size", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (GenericReg.Address), "Address", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpGpio[16] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGpio), "GPIO", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.RevisionId), "RevisionId", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.ConnectionType), "ConnectionType", AcpiGbl_CtDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.PinConfig), "PinConfig", AcpiGbl_PpcDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Sharable), "Sharing", AcpiGbl_ShrDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.IoRestriction), "IoRestriction", AcpiGbl_IorDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.Triggering), "Triggering", AcpiGbl_HeDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Polarity), "Polarity", AcpiGbl_LlDecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DriveStrength), "DriveStrength", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DebounceTimeout), "DebounceTimeout", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Gpio.ResourceSource), "ResourceSource", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.PinTableLength), "PinTableLength", NULL},
+ {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET (Gpio.PinTable), "PinTable", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.VendorLength), "VendorLength", NULL},
+ {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (Gpio.VendorData), "VendorData", NULL},
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpFixedDma[4] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedDma), "FixedDma", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.RequestLines), "RequestLines", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.Channels), "Channels", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedDma.Width), "TransferWidth", AcpiGbl_DtsDecode},
+};
+
+#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.RevisionId), "RevisionId", NULL}, \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.Type), "Type", AcpiGbl_SbtDecode}, \
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, \
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.SlaveMode), "SlaveMode", AcpiGbl_SmDecode}, \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.TypeRevisionId), "TypeRevisionId", NULL}, \
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.TypeDataLength), "TypeDataLength", NULL}, \
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (CommonSerialBus.ResourceSource), "ResourceSource", NULL}, \
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.VendorLength), "VendorLength", NULL}, \
+ {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (CommonSerialBus.VendorData), "VendorData", NULL},
+
+ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[10] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpCommonSerialBus), "Common Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[13] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpI2cSerialBus), "I2C Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (I2cSerialBus.AccessMode), "AccessMode", AcpiGbl_AmDecode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (I2cSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (I2cSerialBus.SlaveAddress), "SlaveAddress", NULL},
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[17] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpSpiSerialBus), "Spi Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.WireMode), "WireMode", AcpiGbl_WmDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.DevicePolarity), "DevicePolarity", AcpiGbl_DpDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.DataBitLength), "DataBitLength", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPhase), "ClockPhase", AcpiGbl_CphDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPolarity), "ClockPolarity", AcpiGbl_CpoDecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (SpiSerialBus.DeviceSelection), "DeviceSelection", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (SpiSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL},
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[19] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpUartSerialBus), "Uart Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.FlowControl), "FlowControl", AcpiGbl_FcDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.StopBits), "StopBits", AcpiGbl_SbDecode},
+ {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.DataBits), "DataBits", AcpiGbl_BpbDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.Endian), "Endian", AcpiGbl_EdDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.Parity), "Parity", AcpiGbl_PtDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.LinesEnabled), "LinesEnabled", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.RxFifoSize), "RxFifoSize", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.TxFifoSize), "TxFifoSize", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (UartSerialBus.DefaultBaudRate), "ConnectionSpeed", NULL},
+};
+
+/*
+ * Tables used for common address descriptor flag fields
+ */
+ACPI_RSDUMP_INFO AcpiRsDumpGeneralFlags[5] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGeneralFlags), NULL, NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.ProducerConsumer), "Consumer/Producer", AcpiGbl_ConsumeDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Decode), "Address Decode", AcpiGbl_DecDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MinAddressFixed), "Min Relocatability", AcpiGbl_MinDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MaxAddressFixed), "Max Relocatability", AcpiGbl_MaxDecode}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpMemoryFlags[5] =
+{
+ {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemoryFlags), "Resource Type", (void *) "Memory Range"},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Caching), "Caching", AcpiGbl_MemDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.RangeType), "Range Type", AcpiGbl_MtpDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Translation), "Translation", AcpiGbl_TtpDecode}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpIoFlags[4] =
+{
+ {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIoFlags), "Resource Type", (void *) "I/O Range"},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.RangeType), "Range Type", AcpiGbl_RngDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.Translation), "Translation", AcpiGbl_TtpDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.TranslationType), "Translation Type", AcpiGbl_TrsDecode}
+};
+
+
+/*
+ * Table used to dump _PRT contents
+ */
+ACPI_RSDUMP_INFO AcpiRsDumpPrt[5] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPrt), NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_PRT_OFFSET (Address), "Address", NULL},
+ {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (Pin), "Pin", NULL},
+ {ACPI_RSD_STRING, ACPI_PRT_OFFSET (Source[0]), "Source", NULL},
+ {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (SourceIndex), "Source Index", NULL}
+};
+
+#endif
diff --git a/sys/contrib/dev/acpica/components/resources/rsinfo.c b/sys/contrib/dev/acpica/components/resources/rsinfo.c
index ab2254e..cb72332 100644
--- a/sys/contrib/dev/acpica/components/resources/rsinfo.c
+++ b/sys/contrib/dev/acpica/components/resources/rsinfo.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsio.c b/sys/contrib/dev/acpica/components/resources/rsio.c
index 08119bf..1a41fb9 100644
--- a/sys/contrib/dev/acpica/components/resources/rsio.c
+++ b/sys/contrib/dev/acpica/components/resources/rsio.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsirq.c b/sys/contrib/dev/acpica/components/resources/rsirq.c
index 0179749..b3b5ee57 100644
--- a/sys/contrib/dev/acpica/components/resources/rsirq.c
+++ b/sys/contrib/dev/acpica/components/resources/rsirq.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] =
+ACPI_RSCONVERT_INFO AcpiRsGetIrq[9] =
{
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ,
ACPI_RS_SIZE (ACPI_RESOURCE_IRQ),
@@ -85,7 +85,7 @@ ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] =
{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3},
- /* Get flags: Triggering[0], Polarity[3], Sharing[4] */
+ /* Get flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */
{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Triggering),
AML_OFFSET (Irq.Flags),
@@ -97,7 +97,11 @@ ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] =
{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Sharable),
AML_OFFSET (Irq.Flags),
- 4}
+ 4},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.WakeCapable),
+ AML_OFFSET (Irq.Flags),
+ 5}
};
@@ -107,7 +111,7 @@ ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] =
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] =
+ACPI_RSCONVERT_INFO AcpiRsSetIrq[14] =
{
/* Start with a default descriptor of length 3 */
@@ -121,7 +125,7 @@ ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] =
AML_OFFSET (Irq.IrqMask),
ACPI_RS_OFFSET (Data.Irq.InterruptCount)},
- /* Set the flags byte */
+ /* Set flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */
{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Triggering),
AML_OFFSET (Irq.Flags),
@@ -135,6 +139,10 @@ ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] =
AML_OFFSET (Irq.Flags),
4},
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.WakeCapable),
+ AML_OFFSET (Irq.Flags),
+ 5},
+
/*
* All done if the output descriptor length is required to be 3
* (i.e., optimization to 2 bytes cannot be attempted)
@@ -189,7 +197,7 @@ ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] =
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[9] =
+ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[10] =
{
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ,
ACPI_RS_SIZE (ACPI_RESOURCE_EXTENDED_IRQ),
@@ -199,8 +207,10 @@ ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[9] =
sizeof (AML_RESOURCE_EXTENDED_IRQ),
0},
- /* Flag bits */
-
+ /*
+ * Flags: Producer/Consumer[0], Triggering[1], Polarity[2],
+ * Sharing[3], Wake[4]
+ */
{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.ProducerConsumer),
AML_OFFSET (ExtendedIrq.Flags),
0},
@@ -217,6 +227,10 @@ ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[9] =
AML_OFFSET (ExtendedIrq.Flags),
3},
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.WakeCapable),
+ AML_OFFSET (ExtendedIrq.Flags),
+ 4},
+
/* IRQ Table length (Byte4) */
{ACPI_RSC_COUNT, ACPI_RS_OFFSET (Data.ExtendedIrq.InterruptCount),
@@ -296,7 +310,6 @@ ACPI_RSCONVERT_INFO AcpiRsConvertFixedDma[4] =
* RequestLines
* Channels
*/
-
{ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.FixedDma.RequestLines),
AML_OFFSET (FixedDma.RequestLines),
2},
@@ -304,5 +317,4 @@ ACPI_RSCONVERT_INFO AcpiRsConvertFixedDma[4] =
{ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.FixedDma.Width),
AML_OFFSET (FixedDma.Width),
1},
-
};
diff --git a/sys/contrib/dev/acpica/components/resources/rslist.c b/sys/contrib/dev/acpica/components/resources/rslist.c
index 96b8c67..2c69c349 100644
--- a/sys/contrib/dev/acpica/components/resources/rslist.c
+++ b/sys/contrib/dev/acpica/components/resources/rslist.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -72,7 +72,7 @@ AcpiRsConvertAmlToResources (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context)
+ void **Context)
{
ACPI_RESOURCE **ResourcePtr = ACPI_CAST_INDIRECT_PTR (
ACPI_RESOURCE, Context);
diff --git a/sys/contrib/dev/acpica/components/resources/rsmemory.c b/sys/contrib/dev/acpica/components/resources/rsmemory.c
index e4e4ae0..049a7b1 100644
--- a/sys/contrib/dev/acpica/components/resources/rsmemory.c
+++ b/sys/contrib/dev/acpica/components/resources/rsmemory.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsmisc.c b/sys/contrib/dev/acpica/components/resources/rsmisc.c
index 733ac8f..c0687ca 100644
--- a/sys/contrib/dev/acpica/components/resources/rsmisc.c
+++ b/sys/contrib/dev/acpica/components/resources/rsmisc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsserial.c b/sys/contrib/dev/acpica/components/resources/rsserial.c
index 09cc7de..69e2259 100644
--- a/sys/contrib/dev/acpica/components/resources/rsserial.c
+++ b/sys/contrib/dev/acpica/components/resources/rsserial.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsConvertGpio[17] =
+ACPI_RSCONVERT_INFO AcpiRsConvertGpio[18] =
{
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GPIO,
ACPI_RS_SIZE (ACPI_RESOURCE_GPIO),
@@ -80,10 +80,14 @@ ACPI_RSCONVERT_INFO AcpiRsConvertGpio[17] =
AML_OFFSET (Gpio.Flags),
0},
- {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Gpio.Sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Gpio.Sharable),
AML_OFFSET (Gpio.IntFlags),
3},
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Gpio.WakeCapable),
+ AML_OFFSET (Gpio.IntFlags),
+ 4},
+
{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Gpio.IoRestriction),
AML_OFFSET (Gpio.IntFlags),
0},
diff --git a/sys/contrib/dev/acpica/components/resources/rsutils.c b/sys/contrib/dev/acpica/components/resources/rsutils.c
index cdbb389..78f4549 100644
--- a/sys/contrib/dev/acpica/components/resources/rsutils.c
+++ b/sys/contrib/dev/acpica/components/resources/rsutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -746,7 +746,8 @@ AcpiRsGetMethodData (
/* Execute the method, no parameters */
- Status = AcpiUtEvaluateObject (Handle, Path, ACPI_BTYPE_BUFFER, &ObjDesc);
+ Status = AcpiUtEvaluateObject (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle),
+ Path, ACPI_BTYPE_BUFFER, &ObjDesc);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
diff --git a/sys/contrib/dev/acpica/components/resources/rsxface.c b/sys/contrib/dev/acpica/components/resources/rsxface.c
index 9251aec..f70d8f6 100644
--- a/sys/contrib/dev/acpica/components/resources/rsxface.c
+++ b/sys/contrib/dev/acpica/components/resources/rsxface.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -474,7 +474,7 @@ ACPI_EXPORT_SYMBOL (AcpiResourceToAddress64)
*
* RETURN: Status
*
- * DESCRIPTION: Walk a resource template for the specified evice to find a
+ * DESCRIPTION: Walk a resource template for the specified device to find a
* vendor-defined resource that matches the supplied UUID and
* UUID subtype. Returns a ACPI_RESOURCE of type Vendor.
*
@@ -586,63 +586,45 @@ AcpiRsMatchVendorResource (
/*******************************************************************************
*
- * FUNCTION: AcpiWalkResources
+ * FUNCTION: AcpiWalkResourceBuffer
*
- * PARAMETERS: DeviceHandle - Handle to the device object for the
- * device we are querying
- * Name - Method name of the resources we want.
- * (METHOD_NAME__CRS, METHOD_NAME__PRS, or
- * METHOD_NAME__AEI)
+ * PARAMETERS: Buffer - Formatted buffer returned by one of the
+ * various Get*Resource functions
* UserFunction - Called for each resource
* Context - Passed to UserFunction
*
* RETURN: Status
*
- * DESCRIPTION: Retrieves the current or possible resource list for the
- * specified device. The UserFunction is called once for
- * each resource in the list.
+ * DESCRIPTION: Walks the input resource template. The UserFunction is called
+ * once for each resource in the list.
*
******************************************************************************/
ACPI_STATUS
-AcpiWalkResources (
- ACPI_HANDLE DeviceHandle,
- char *Name,
+AcpiWalkResourceBuffer (
+ ACPI_BUFFER *Buffer,
ACPI_WALK_RESOURCE_CALLBACK UserFunction,
void *Context)
{
- ACPI_STATUS Status;
- ACPI_BUFFER Buffer;
+ ACPI_STATUS Status = AE_OK;
ACPI_RESOURCE *Resource;
ACPI_RESOURCE *ResourceEnd;
- ACPI_FUNCTION_TRACE (AcpiWalkResources);
+ ACPI_FUNCTION_TRACE (AcpiWalkResourceBuffer);
/* Parameter validation */
- if (!DeviceHandle || !UserFunction || !Name ||
- (!ACPI_COMPARE_NAME (Name, METHOD_NAME__CRS) &&
- !ACPI_COMPARE_NAME (Name, METHOD_NAME__PRS) &&
- !ACPI_COMPARE_NAME (Name, METHOD_NAME__AEI)))
+ if (!Buffer || !Buffer->Pointer || !UserFunction)
{
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
- /* Get the _CRS/_PRS/_AEI resource list */
-
- Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- Status = AcpiRsGetMethodData (DeviceHandle, Name, &Buffer);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /* Buffer now contains the resource list */
+ /* Buffer contains the resource list and length */
- Resource = ACPI_CAST_PTR (ACPI_RESOURCE, Buffer.Pointer);
- ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Buffer.Pointer, Buffer.Length);
+ Resource = ACPI_CAST_PTR (ACPI_RESOURCE, Buffer->Pointer);
+ ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Buffer->Pointer, Buffer->Length);
/* Walk the resource list until the EndTag is found (or buffer end) */
@@ -682,6 +664,68 @@ AcpiWalkResources (
Resource = ACPI_NEXT_RESOURCE (Resource);
}
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiWalkResourceBuffer)
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiWalkResources
+ *
+ * PARAMETERS: DeviceHandle - Handle to the device object for the
+ * device we are querying
+ * Name - Method name of the resources we want.
+ * (METHOD_NAME__CRS, METHOD_NAME__PRS, or
+ * METHOD_NAME__AEI)
+ * UserFunction - Called for each resource
+ * Context - Passed to UserFunction
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Retrieves the current or possible resource list for the
+ * specified device. The UserFunction is called once for
+ * each resource in the list.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiWalkResources (
+ ACPI_HANDLE DeviceHandle,
+ char *Name,
+ ACPI_WALK_RESOURCE_CALLBACK UserFunction,
+ void *Context)
+{
+ ACPI_STATUS Status;
+ ACPI_BUFFER Buffer;
+
+
+ ACPI_FUNCTION_TRACE (AcpiWalkResources);
+
+
+ /* Parameter validation */
+
+ if (!DeviceHandle || !UserFunction || !Name ||
+ (!ACPI_COMPARE_NAME (Name, METHOD_NAME__CRS) &&
+ !ACPI_COMPARE_NAME (Name, METHOD_NAME__PRS) &&
+ !ACPI_COMPARE_NAME (Name, METHOD_NAME__AEI)))
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /* Get the _CRS/_PRS/_AEI resource list */
+
+ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ Status = AcpiRsGetMethodData (DeviceHandle, Name, &Buffer);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Walk the resource list and cleanup */
+
+ Status = AcpiWalkResourceBuffer (&Buffer, UserFunction, Context);
ACPI_FREE (Buffer.Pointer);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/tables/tbfadt.c b/sys/contrib/dev/acpica/components/tables/tbfadt.c
index 3a53ae0..327f3a6 100644
--- a/sys/contrib/dev/acpica/components/tables/tbfadt.c
+++ b/sys/contrib/dev/acpica/components/tables/tbfadt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbfind.c b/sys/contrib/dev/acpica/components/tables/tbfind.c
index ccb4029..6cd30e8 100644
--- a/sys/contrib/dev/acpica/components/tables/tbfind.c
+++ b/sys/contrib/dev/acpica/components/tables/tbfind.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbinstal.c b/sys/contrib/dev/acpica/components/tables/tbinstal.c
index c2035aa..e6558ff 100644
--- a/sys/contrib/dev/acpica/components/tables/tbinstal.c
+++ b/sys/contrib/dev/acpica/components/tables/tbinstal.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbutils.c b/sys/contrib/dev/acpica/components/tables/tbutils.c
index a97a1e9..500c2f1 100644
--- a/sys/contrib/dev/acpica/components/tables/tbutils.c
+++ b/sys/contrib/dev/acpica/components/tables/tbutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbxface.c b/sys/contrib/dev/acpica/components/tables/tbxface.c
index 33d3591..e040944 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxface.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbxfload.c b/sys/contrib/dev/acpica/components/tables/tbxfload.c
index d06683d..5a4906f 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxfload.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxfload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -208,7 +208,7 @@ AcpiTbLoadNamespace (
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
+ ACPI_INFO ((AE_INFO, "All ACPI Tables successfully acquired"));
UnlockAndExit:
(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
diff --git a/sys/contrib/dev/acpica/components/tables/tbxfroot.c b/sys/contrib/dev/acpica/components/tables/tbxfroot.c
index db06a8a..1d8909b 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxfroot.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxfroot.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utaddress.c b/sys/contrib/dev/acpica/components/utilities/utaddress.c
index ca73b69..715c77b 100644
--- a/sys/contrib/dev/acpica/components/utilities/utaddress.c
+++ b/sys/contrib/dev/acpica/components/utilities/utaddress.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -237,7 +237,7 @@ AcpiUtCheckAddressRange (
if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
{
- return_UINT32 (0);
+ return_VALUE (0);
}
RangeInfo = AcpiGbl_AddressRangeList[SpaceId];
@@ -278,7 +278,7 @@ AcpiUtCheckAddressRange (
RangeInfo = RangeInfo->Next;
}
- return_UINT32 (OverlapCount);
+ return_VALUE (OverlapCount);
}
diff --git a/sys/contrib/dev/acpica/components/utilities/utalloc.c b/sys/contrib/dev/acpica/components/utilities/utalloc.c
index 0ea15af..0bdb2ff 100644
--- a/sys/contrib/dev/acpica/components/utilities/utalloc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utalloc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utcache.c b/sys/contrib/dev/acpica/components/utilities/utcache.c
index e21cb48..2aa3e5b 100644
--- a/sys/contrib/dev/acpica/components/utilities/utcache.c
+++ b/sys/contrib/dev/acpica/components/utilities/utcache.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -95,7 +95,6 @@ AcpiOsCreateCache (
/* Populate the cache object and return it */
ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST));
- Cache->LinkOffset = 8;
Cache->ListName = CacheName;
Cache->ObjectSize = ObjectSize;
Cache->MaxDepth = MaxDepth;
@@ -121,7 +120,7 @@ ACPI_STATUS
AcpiOsPurgeCache (
ACPI_MEMORY_LIST *Cache)
{
- char *Next;
+ void *Next;
ACPI_STATUS Status;
@@ -145,8 +144,7 @@ AcpiOsPurgeCache (
{
/* Delete and unlink one cached state object */
- Next = *(ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) Cache->ListHead)[Cache->LinkOffset])));
+ Next = ACPI_GET_DESCRIPTOR_PTR (Cache->ListHead);
ACPI_FREE (Cache->ListHead);
Cache->ListHead = Next;
@@ -251,8 +249,7 @@ AcpiOsReleaseObject (
/* Put the object at the head of the cache list */
- * (ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) Object)[Cache->LinkOffset]))) = Cache->ListHead;
+ ACPI_SET_DESCRIPTOR_PTR (Object, Cache->ListHead);
Cache->ListHead = Object;
Cache->CurrentDepth++;
@@ -307,8 +304,7 @@ AcpiOsAcquireObject (
/* There is an object available, use it */
Object = Cache->ListHead;
- Cache->ListHead = *(ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) Object)[Cache->LinkOffset])));
+ Cache->ListHead = ACPI_GET_DESCRIPTOR_PTR (Object);
Cache->CurrentDepth--;
diff --git a/sys/contrib/dev/acpica/components/utilities/utcopy.c b/sys/contrib/dev/acpica/components/utilities/utcopy.c
index dd8de9e..696acf0 100644
--- a/sys/contrib/dev/acpica/components/utilities/utcopy.c
+++ b/sys/contrib/dev/acpica/components/utilities/utcopy.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utdebug.c b/sys/contrib/dev/acpica/components/utilities/utdebug.c
index 5834c0f..a299680 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdebug.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdebug.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -189,11 +189,9 @@ AcpiDebugPrint (
va_list args;
- /*
- * Stay silent if the debug level or component ID is disabled
- */
- if (!(RequestedDebugLevel & AcpiDbgLevel) ||
- !(ComponentId & AcpiDbgLayer))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (RequestedDebugLevel, ComponentId))
{
return;
}
@@ -268,8 +266,9 @@ AcpiDebugPrintRaw (
va_list args;
- if (!(RequestedDebugLevel & AcpiDbgLevel) ||
- !(ComponentId & AcpiDbgLayer))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (RequestedDebugLevel, ComponentId))
{
return;
}
@@ -309,9 +308,14 @@ AcpiUtTrace (
AcpiGbl_NestingLevel++;
AcpiUtTrackStackPtr ();
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s\n", AcpiGbl_FnEntryStr);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s\n", AcpiGbl_FnEntryStr);
+ }
}
ACPI_EXPORT_SYMBOL (AcpiUtTrace)
@@ -346,9 +350,14 @@ AcpiUtTracePtr (
AcpiGbl_NestingLevel++;
AcpiUtTrackStackPtr ();
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %p\n", AcpiGbl_FnEntryStr, Pointer);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %p\n", AcpiGbl_FnEntryStr, Pointer);
+ }
}
@@ -381,9 +390,14 @@ AcpiUtTraceStr (
AcpiGbl_NestingLevel++;
AcpiUtTrackStackPtr ();
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %s\n", AcpiGbl_FnEntryStr, String);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %s\n", AcpiGbl_FnEntryStr, String);
+ }
}
@@ -416,9 +430,14 @@ AcpiUtTraceU32 (
AcpiGbl_NestingLevel++;
AcpiUtTrackStackPtr ();
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %08X\n", AcpiGbl_FnEntryStr, Integer);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %08X\n", AcpiGbl_FnEntryStr, Integer);
+ }
}
@@ -446,9 +465,14 @@ AcpiUtExit (
UINT32 ComponentId)
{
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s\n", AcpiGbl_FnExitStr);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s\n", AcpiGbl_FnExitStr);
+ }
AcpiGbl_NestingLevel--;
}
@@ -482,19 +506,24 @@ AcpiUtStatusExit (
ACPI_STATUS Status)
{
- if (ACPI_SUCCESS (Status))
- {
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %s\n", AcpiGbl_FnExitStr,
- AcpiFormatException (Status));
- }
- else
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
{
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s ****Exception****: %s\n", AcpiGbl_FnExitStr,
- AcpiFormatException (Status));
+ if (ACPI_SUCCESS (Status))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %s\n", AcpiGbl_FnExitStr,
+ AcpiFormatException (Status));
+ }
+ else
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s ****Exception****: %s\n", AcpiGbl_FnExitStr,
+ AcpiFormatException (Status));
+ }
}
AcpiGbl_NestingLevel--;
@@ -529,10 +558,15 @@ AcpiUtValueExit (
UINT64 Value)
{
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %8.8X%8.8X\n", AcpiGbl_FnExitStr,
- ACPI_FORMAT_UINT64 (Value));
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %8.8X%8.8X\n", AcpiGbl_FnExitStr,
+ ACPI_FORMAT_UINT64 (Value));
+ }
AcpiGbl_NestingLevel--;
}
@@ -566,9 +600,14 @@ AcpiUtPtrExit (
UINT8 *Ptr)
{
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %p\n", AcpiGbl_FnExitStr, Ptr);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %p\n", AcpiGbl_FnExitStr, Ptr);
+ }
AcpiGbl_NestingLevel--;
}
diff --git a/sys/contrib/dev/acpica/components/utilities/utdecode.c b/sys/contrib/dev/acpica/components/utilities/utdecode.c
index ef423e9..3075479 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdecode.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdecode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utdelete.c b/sys/contrib/dev/acpica/components/utilities/utdelete.c
index 77dbe1b..b73e2d8 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdelete.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdelete.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -368,7 +368,7 @@ AcpiUtDeleteInternalObjectList (
ACPI_OPERAND_OBJECT **InternalObj;
- ACPI_FUNCTION_NAME (UtDeleteInternalObjectList);
+ ACPI_FUNCTION_ENTRY ();
/* Walk the null-terminated internal list */
diff --git a/sys/contrib/dev/acpica/components/utilities/uteval.c b/sys/contrib/dev/acpica/components/utilities/uteval.c
index 57dbec0..95233f4 100644
--- a/sys/contrib/dev/acpica/components/utilities/uteval.c
+++ b/sys/contrib/dev/acpica/components/utilities/uteval.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utexcep.c b/sys/contrib/dev/acpica/components/utilities/utexcep.c
index 0f38227..2d3ae17 100644
--- a/sys/contrib/dev/acpica/components/utilities/utexcep.c
+++ b/sys/contrib/dev/acpica/components/utilities/utexcep.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utglobal.c b/sys/contrib/dev/acpica/components/utilities/utglobal.c
index 5bb5991..6d2f906 100644
--- a/sys/contrib/dev/acpica/components/utilities/utglobal.c
+++ b/sys/contrib/dev/acpica/components/utilities/utglobal.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utids.c b/sys/contrib/dev/acpica/components/utilities/utids.c
index 17ad5ed..c73c8ed 100644
--- a/sys/contrib/dev/acpica/components/utilities/utids.c
+++ b/sys/contrib/dev/acpica/components/utilities/utids.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utinit.c b/sys/contrib/dev/acpica/components/utilities/utinit.c
index 7b53c9a..760d789 100644
--- a/sys/contrib/dev/acpica/components/utilities/utinit.c
+++ b/sys/contrib/dev/acpica/components/utilities/utinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utlock.c b/sys/contrib/dev/acpica/components/utilities/utlock.c
index 40fc8f8..da933c2 100644
--- a/sys/contrib/dev/acpica/components/utilities/utlock.c
+++ b/sys/contrib/dev/acpica/components/utilities/utlock.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utmath.c b/sys/contrib/dev/acpica/components/utilities/utmath.c
index ec51855..b535ffc 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmath.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmath.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utmisc.c b/sys/contrib/dev/acpica/components/utilities/utmisc.c
index 70fdb50..7d013fc 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmisc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmisc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,43 +53,6 @@
ACPI_MODULE_NAME ("utmisc")
-#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP
-/*******************************************************************************
- *
- * FUNCTION: UtConvertBackslashes
- *
- * PARAMETERS: Pathname - File pathname string to be converted
- *
- * RETURN: Modifies the input Pathname
- *
- * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within
- * the entire input file pathname string.
- *
- ******************************************************************************/
-
-void
-UtConvertBackslashes (
- char *Pathname)
-{
-
- if (!Pathname)
- {
- return;
- }
-
- while (*Pathname)
- {
- if (*Pathname == '\\')
- {
- *Pathname = '/';
- }
-
- Pathname++;
- }
-}
-#endif
-
-
/*******************************************************************************
*
* FUNCTION: AcpiUtIsPciRootBridge
@@ -158,411 +121,6 @@ AcpiUtIsAmlTable (
/*******************************************************************************
*
- * FUNCTION: AcpiUtAllocateOwnerId
- *
- * PARAMETERS: OwnerId - Where the new owner ID is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
- * track objects created by the table or method, to be deleted
- * when the method exits or the table is unloaded.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiUtAllocateOwnerId (
- ACPI_OWNER_ID *OwnerId)
-{
- UINT32 i;
- UINT32 j;
- UINT32 k;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_TRACE (UtAllocateOwnerId);
-
-
- /* Guard against multiple allocations of ID to the same location */
-
- if (*OwnerId)
- {
- ACPI_ERROR ((AE_INFO, "Owner ID [0x%2.2X] already exists", *OwnerId));
- return_ACPI_STATUS (AE_ALREADY_EXISTS);
- }
-
- /* Mutex for the global ID mask */
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /*
- * Find a free owner ID, cycle through all possible IDs on repeated
- * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
- * to be scanned twice.
- */
- for (i = 0, j = AcpiGbl_LastOwnerIdIndex;
- i < (ACPI_NUM_OWNERID_MASKS + 1);
- i++, j++)
- {
- if (j >= ACPI_NUM_OWNERID_MASKS)
- {
- j = 0; /* Wraparound to start of mask array */
- }
-
- for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++)
- {
- if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX)
- {
- /* There are no free IDs in this mask */
-
- break;
- }
-
- if (!(AcpiGbl_OwnerIdMask[j] & (1 << k)))
- {
- /*
- * Found a free ID. The actual ID is the bit index plus one,
- * making zero an invalid Owner ID. Save this as the last ID
- * allocated and update the global ID mask.
- */
- AcpiGbl_OwnerIdMask[j] |= (1 << k);
-
- AcpiGbl_LastOwnerIdIndex = (UINT8) j;
- AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1);
-
- /*
- * Construct encoded ID from the index and bit position
- *
- * Note: Last [j].k (bit 255) is never used and is marked
- * permanently allocated (prevents +1 overflow)
- */
- *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_VALUES,
- "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId));
- goto Exit;
- }
- }
-
- AcpiGbl_NextOwnerIdOffset = 0;
- }
-
- /*
- * All OwnerIds have been allocated. This typically should
- * not happen since the IDs are reused after deallocation. The IDs are
- * allocated upon table load (one per table) and method execution, and
- * they are released when a table is unloaded or a method completes
- * execution.
- *
- * If this error happens, there may be very deep nesting of invoked control
- * methods, or there may be a bug where the IDs are not released.
- */
- Status = AE_OWNER_ID_LIMIT;
- ACPI_ERROR ((AE_INFO,
- "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
-
-Exit:
- (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtReleaseOwnerId
- *
- * PARAMETERS: OwnerIdPtr - Pointer to a previously allocated OwnerID
- *
- * RETURN: None. No error is returned because we are either exiting a
- * control method or unloading a table. Either way, we would
- * ignore any error anyway.
- *
- * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
- *
- ******************************************************************************/
-
-void
-AcpiUtReleaseOwnerId (
- ACPI_OWNER_ID *OwnerIdPtr)
-{
- ACPI_OWNER_ID OwnerId = *OwnerIdPtr;
- ACPI_STATUS Status;
- UINT32 Index;
- UINT32 Bit;
-
-
- ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId);
-
-
- /* Always clear the input OwnerId (zero is an invalid ID) */
-
- *OwnerIdPtr = 0;
-
- /* Zero is not a valid OwnerID */
-
- if (OwnerId == 0)
- {
- ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId));
- return_VOID;
- }
-
- /* Mutex for the global ID mask */
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
- if (ACPI_FAILURE (Status))
- {
- return_VOID;
- }
-
- /* Normalize the ID to zero */
-
- OwnerId--;
-
- /* Decode ID to index/offset pair */
-
- Index = ACPI_DIV_32 (OwnerId);
- Bit = 1 << ACPI_MOD_32 (OwnerId);
-
- /* Free the owner ID only if it is valid */
-
- if (AcpiGbl_OwnerIdMask[Index] & Bit)
- {
- AcpiGbl_OwnerIdMask[Index] ^= Bit;
- }
- else
- {
- ACPI_ERROR ((AE_INFO,
- "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1));
- }
-
- (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtStrupr (strupr)
- *
- * PARAMETERS: SrcString - The source string to convert
- *
- * RETURN: None
- *
- * DESCRIPTION: Convert string to uppercase
- *
- * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
- *
- ******************************************************************************/
-
-void
-AcpiUtStrupr (
- char *SrcString)
-{
- char *String;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- if (!SrcString)
- {
- return;
- }
-
- /* Walk entire string, uppercasing the letters */
-
- for (String = SrcString; *String; String++)
- {
- *String = (char) ACPI_TOUPPER (*String);
- }
-
- return;
-}
-
-
-#ifdef ACPI_ASL_COMPILER
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtStrlwr (strlwr)
- *
- * PARAMETERS: SrcString - The source string to convert
- *
- * RETURN: None
- *
- * DESCRIPTION: Convert string to lowercase
- *
- * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
- *
- ******************************************************************************/
-
-void
-AcpiUtStrlwr (
- char *SrcString)
-{
- char *String;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- if (!SrcString)
- {
- return;
- }
-
- /* Walk entire string, lowercasing the letters */
-
- for (String = SrcString; *String; String++)
- {
- *String = (char) ACPI_TOLOWER (*String);
- }
-
- return;
-}
-
-
-/******************************************************************************
- *
- * FUNCTION: AcpiUtStricmp
- *
- * PARAMETERS: String1 - first string to compare
- * String2 - second string to compare
- *
- * RETURN: int that signifies string relationship. Zero means strings
- * are equal.
- *
- * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
- * strings with no case sensitivity)
- *
- ******************************************************************************/
-
-int
-AcpiUtStricmp (
- char *String1,
- char *String2)
-{
- int c1;
- int c2;
-
-
- do
- {
- c1 = tolower ((int) *String1);
- c2 = tolower ((int) *String2);
-
- String1++;
- String2++;
- }
- while ((c1 == c2) && (c1));
-
- return (c1 - c2);
-}
-#endif
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtPrintString
- *
- * PARAMETERS: String - Null terminated ASCII string
- * MaxLength - Maximum output length
- *
- * RETURN: None
- *
- * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
- * sequences.
- *
- ******************************************************************************/
-
-void
-AcpiUtPrintString (
- char *String,
- UINT8 MaxLength)
-{
- UINT32 i;
-
-
- if (!String)
- {
- AcpiOsPrintf ("<\"NULL STRING PTR\">");
- return;
- }
-
- AcpiOsPrintf ("\"");
- for (i = 0; String[i] && (i < MaxLength); i++)
- {
- /* Escape sequences */
-
- switch (String[i])
- {
- case 0x07:
- AcpiOsPrintf ("\\a"); /* BELL */
- break;
-
- case 0x08:
- AcpiOsPrintf ("\\b"); /* BACKSPACE */
- break;
-
- case 0x0C:
- AcpiOsPrintf ("\\f"); /* FORMFEED */
- break;
-
- case 0x0A:
- AcpiOsPrintf ("\\n"); /* LINEFEED */
- break;
-
- case 0x0D:
- AcpiOsPrintf ("\\r"); /* CARRIAGE RETURN*/
- break;
-
- case 0x09:
- AcpiOsPrintf ("\\t"); /* HORIZONTAL TAB */
- break;
-
- case 0x0B:
- AcpiOsPrintf ("\\v"); /* VERTICAL TAB */
- break;
-
- case '\'': /* Single Quote */
- case '\"': /* Double Quote */
- case '\\': /* Backslash */
- AcpiOsPrintf ("\\%c", (int) String[i]);
- break;
-
- default:
-
- /* Check for printable character or hex escape */
-
- if (ACPI_IS_PRINT (String[i]))
- {
- /* This is a normal character */
-
- AcpiOsPrintf ("%c", (int) String[i]);
- }
- else
- {
- /* All others will be Hex escapes */
-
- AcpiOsPrintf ("\\x%2.2X", (INT32) String[i]);
- }
- break;
- }
- }
- AcpiOsPrintf ("\"");
-
- if (i == MaxLength && String[i])
- {
- AcpiOsPrintf ("...");
- }
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiUtDwordByteSwap
*
* PARAMETERS: Value - Value to be converted
@@ -642,444 +200,6 @@ AcpiUtSetIntegerWidth (
}
-#ifdef ACPI_DEBUG_OUTPUT
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtDisplayInitPathname
- *
- * PARAMETERS: Type - Object type of the node
- * ObjHandle - Handle whose pathname will be displayed
- * Path - Additional path string to be appended.
- * (NULL if no extra path)
- *
- * RETURN: ACPI_STATUS
- *
- * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
- *
- ******************************************************************************/
-
-void
-AcpiUtDisplayInitPathname (
- UINT8 Type,
- ACPI_NAMESPACE_NODE *ObjHandle,
- char *Path)
-{
- ACPI_STATUS Status;
- ACPI_BUFFER Buffer;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- /* Only print the path if the appropriate debug level is enabled */
-
- if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
- {
- return;
- }
-
- /* Get the full pathname to the node */
-
- Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- Status = AcpiNsHandleToPathname (ObjHandle, &Buffer);
- if (ACPI_FAILURE (Status))
- {
- return;
- }
-
- /* Print what we're doing */
-
- switch (Type)
- {
- case ACPI_TYPE_METHOD:
- AcpiOsPrintf ("Executing ");
- break;
-
- default:
- AcpiOsPrintf ("Initializing ");
- break;
- }
-
- /* Print the object type and pathname */
-
- AcpiOsPrintf ("%-12s %s",
- AcpiUtGetTypeName (Type), (char *) Buffer.Pointer);
-
- /* Extra path is used to append names like _STA, _INI, etc. */
-
- if (Path)
- {
- AcpiOsPrintf (".%s", Path);
- }
- AcpiOsPrintf ("\n");
-
- ACPI_FREE (Buffer.Pointer);
-}
-#endif
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtValidAcpiChar
- *
- * PARAMETERS: Char - The character to be examined
- * Position - Byte position (0-3)
- *
- * RETURN: TRUE if the character is valid, FALSE otherwise
- *
- * DESCRIPTION: Check for a valid ACPI character. Must be one of:
- * 1) Upper case alpha
- * 2) numeric
- * 3) underscore
- *
- * We allow a '!' as the last character because of the ASF! table
- *
- ******************************************************************************/
-
-BOOLEAN
-AcpiUtValidAcpiChar (
- char Character,
- UINT32 Position)
-{
-
- if (!((Character >= 'A' && Character <= 'Z') ||
- (Character >= '0' && Character <= '9') ||
- (Character == '_')))
- {
- /* Allow a '!' in the last position */
-
- if (Character == '!' && Position == 3)
- {
- return (TRUE);
- }
-
- return (FALSE);
- }
-
- return (TRUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtValidAcpiName
- *
- * PARAMETERS: Name - The name to be examined
- *
- * RETURN: TRUE if the name is valid, FALSE otherwise
- *
- * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
- * 1) Upper case alpha
- * 2) numeric
- * 3) underscore
- *
- ******************************************************************************/
-
-BOOLEAN
-AcpiUtValidAcpiName (
- UINT32 Name)
-{
- UINT32 i;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- for (i = 0; i < ACPI_NAME_SIZE; i++)
- {
- if (!AcpiUtValidAcpiChar ((ACPI_CAST_PTR (char, &Name))[i], i))
- {
- return (FALSE);
- }
- }
-
- return (TRUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtRepairName
- *
- * PARAMETERS: Name - The ACPI name to be repaired
- *
- * RETURN: Repaired version of the name
- *
- * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
- * return the new name. NOTE: the Name parameter must reside in
- * read/write memory, cannot be a const.
- *
- * An ACPI Name must consist of valid ACPI characters. We will repair the name
- * if necessary because we don't want to abort because of this, but we want
- * all namespace names to be printable. A warning message is appropriate.
- *
- * This issue came up because there are in fact machines that exhibit
- * this problem, and we want to be able to enable ACPI support for them,
- * even though there are a few bad names.
- *
- ******************************************************************************/
-
-void
-AcpiUtRepairName (
- char *Name)
-{
- UINT32 i;
- BOOLEAN FoundBadChar = FALSE;
- UINT32 OriginalName;
-
-
- ACPI_FUNCTION_NAME (UtRepairName);
-
-
- ACPI_MOVE_NAME (&OriginalName, Name);
-
- /* Check each character in the name */
-
- for (i = 0; i < ACPI_NAME_SIZE; i++)
- {
- if (AcpiUtValidAcpiChar (Name[i], i))
- {
- continue;
- }
-
- /*
- * Replace a bad character with something printable, yet technically
- * still invalid. This prevents any collisions with existing "good"
- * names in the namespace.
- */
- Name[i] = '*';
- FoundBadChar = TRUE;
- }
-
- if (FoundBadChar)
- {
- /* Report warning only if in strict mode or debug mode */
-
- if (!AcpiGbl_EnableInterpreterSlack)
- {
- ACPI_WARNING ((AE_INFO,
- "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
- OriginalName, Name));
- }
- else
- {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
- OriginalName, Name));
- }
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtStrtoul64
- *
- * PARAMETERS: String - Null terminated string
- * Base - Radix of the string: 16 or ACPI_ANY_BASE;
- * ACPI_ANY_BASE means 'in behalf of ToInteger'
- * RetInteger - Where the converted integer is returned
- *
- * RETURN: Status and Converted value
- *
- * DESCRIPTION: Convert a string into an unsigned value. Performs either a
- * 32-bit or 64-bit conversion, depending on the current mode
- * of the interpreter.
- * NOTE: Does not support Octal strings, not needed.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiUtStrtoul64 (
- char *String,
- UINT32 Base,
- UINT64 *RetInteger)
-{
- UINT32 ThisDigit = 0;
- UINT64 ReturnValue = 0;
- UINT64 Quotient;
- UINT64 Dividend;
- UINT32 ToIntegerOp = (Base == ACPI_ANY_BASE);
- UINT32 Mode32 = (AcpiGbl_IntegerByteWidth == 4);
- UINT8 ValidDigits = 0;
- UINT8 SignOf0x = 0;
- UINT8 Term = 0;
-
-
- ACPI_FUNCTION_TRACE_STR (UtStroul64, String);
-
-
- switch (Base)
- {
- case ACPI_ANY_BASE:
- case 16:
- break;
-
- default:
- /* Invalid Base */
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- if (!String)
- {
- goto ErrorExit;
- }
-
- /* Skip over any white space in the buffer */
-
- while ((*String) && (ACPI_IS_SPACE (*String) || *String == '\t'))
- {
- String++;
- }
-
- if (ToIntegerOp)
- {
- /*
- * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
- * We need to determine if it is decimal or hexadecimal.
- */
- if ((*String == '0') && (ACPI_TOLOWER (*(String + 1)) == 'x'))
- {
- SignOf0x = 1;
- Base = 16;
-
- /* Skip over the leading '0x' */
- String += 2;
- }
- else
- {
- Base = 10;
- }
- }
-
- /* Any string left? Check that '0x' is not followed by white space. */
-
- if (!(*String) || ACPI_IS_SPACE (*String) || *String == '\t')
- {
- if (ToIntegerOp)
- {
- goto ErrorExit;
- }
- else
- {
- goto AllDone;
- }
- }
-
- /*
- * Perform a 32-bit or 64-bit conversion, depending upon the current
- * execution mode of the interpreter
- */
- Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
-
- /* Main loop: convert the string to a 32- or 64-bit integer */
-
- while (*String)
- {
- if (ACPI_IS_DIGIT (*String))
- {
- /* Convert ASCII 0-9 to Decimal value */
-
- ThisDigit = ((UINT8) *String) - '0';
- }
- else if (Base == 10)
- {
- /* Digit is out of range; possible in ToInteger case only */
-
- Term = 1;
- }
- else
- {
- ThisDigit = (UINT8) ACPI_TOUPPER (*String);
- if (ACPI_IS_XDIGIT ((char) ThisDigit))
- {
- /* Convert ASCII Hex char to value */
-
- ThisDigit = ThisDigit - 'A' + 10;
- }
- else
- {
- Term = 1;
- }
- }
-
- if (Term)
- {
- if (ToIntegerOp)
- {
- goto ErrorExit;
- }
- else
- {
- break;
- }
- }
- else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x)
- {
- /* Skip zeros */
- String++;
- continue;
- }
-
- ValidDigits++;
-
- if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32)))
- {
- /*
- * This is ToInteger operation case.
- * No any restrictions for string-to-integer conversion,
- * see ACPI spec.
- */
- goto ErrorExit;
- }
-
- /* Divide the digit into the correct position */
-
- (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit),
- Base, &Quotient, NULL);
-
- if (ReturnValue > Quotient)
- {
- if (ToIntegerOp)
- {
- goto ErrorExit;
- }
- else
- {
- break;
- }
- }
-
- ReturnValue *= Base;
- ReturnValue += ThisDigit;
- String++;
- }
-
- /* All done, normal exit */
-
-AllDone:
-
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (ReturnValue)));
-
- *RetInteger = ReturnValue;
- return_ACPI_STATUS (AE_OK);
-
-
-ErrorExit:
- /* Base was set/validated above */
-
- if (Base == 10)
- {
- return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT);
- }
- else
- {
- return_ACPI_STATUS (AE_BAD_HEX_CONSTANT);
- }
-}
-
-
/*******************************************************************************
*
* FUNCTION: AcpiUtCreateUpdateStateAndPush
@@ -1257,3 +377,79 @@ AcpiUtWalkPackageTree (
return_ACPI_STATUS (AE_AML_INTERNAL);
}
+
+
+#ifdef ACPI_DEBUG_OUTPUT
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtDisplayInitPathname
+ *
+ * PARAMETERS: Type - Object type of the node
+ * ObjHandle - Handle whose pathname will be displayed
+ * Path - Additional path string to be appended.
+ * (NULL if no extra path)
+ *
+ * RETURN: ACPI_STATUS
+ *
+ * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
+ *
+ ******************************************************************************/
+
+void
+AcpiUtDisplayInitPathname (
+ UINT8 Type,
+ ACPI_NAMESPACE_NODE *ObjHandle,
+ char *Path)
+{
+ ACPI_STATUS Status;
+ ACPI_BUFFER Buffer;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ /* Only print the path if the appropriate debug level is enabled */
+
+ if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
+ {
+ return;
+ }
+
+ /* Get the full pathname to the node */
+
+ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ Status = AcpiNsHandleToPathname (ObjHandle, &Buffer);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ /* Print what we're doing */
+
+ switch (Type)
+ {
+ case ACPI_TYPE_METHOD:
+ AcpiOsPrintf ("Executing ");
+ break;
+
+ default:
+ AcpiOsPrintf ("Initializing ");
+ break;
+ }
+
+ /* Print the object type and pathname */
+
+ AcpiOsPrintf ("%-12s %s",
+ AcpiUtGetTypeName (Type), (char *) Buffer.Pointer);
+
+ /* Extra path is used to append names like _STA, _INI, etc. */
+
+ if (Path)
+ {
+ AcpiOsPrintf (".%s", Path);
+ }
+ AcpiOsPrintf ("\n");
+
+ ACPI_FREE (Buffer.Pointer);
+}
+#endif
diff --git a/sys/contrib/dev/acpica/components/utilities/utmutex.c b/sys/contrib/dev/acpica/components/utilities/utmutex.c
index 14b9aa7..90717f1 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmutex.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmutex.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utobject.c b/sys/contrib/dev/acpica/components/utilities/utobject.c
index d4d211a..daa8e40 100644
--- a/sys/contrib/dev/acpica/components/utilities/utobject.c
+++ b/sys/contrib/dev/acpica/components/utilities/utobject.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -725,7 +725,7 @@ AcpiUtGetPackageObjectSize (
Info.NumPackages = 1;
Status = AcpiUtWalkPackageTree (InternalObject, NULL,
- AcpiUtGetElementLength, &Info);
+ AcpiUtGetElementLength, &Info);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
diff --git a/sys/contrib/dev/acpica/components/utilities/utosi.c b/sys/contrib/dev/acpica/components/utilities/utosi.c
index bd173b7..424cfb6 100644
--- a/sys/contrib/dev/acpica/components/utilities/utosi.c
+++ b/sys/contrib/dev/acpica/components/utilities/utosi.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utownerid.c b/sys/contrib/dev/acpica/components/utilities/utownerid.c
new file mode 100644
index 0000000..74f4d83
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/utilities/utownerid.c
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ *
+ * Module Name: utownerid - Support for Table/Method Owner IDs
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#define __UTOWNERID_C__
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+
+
+#define _COMPONENT ACPI_UTILITIES
+ ACPI_MODULE_NAME ("utownerid")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtAllocateOwnerId
+ *
+ * PARAMETERS: OwnerId - Where the new owner ID is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
+ * track objects created by the table or method, to be deleted
+ * when the method exits or the table is unloaded.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiUtAllocateOwnerId (
+ ACPI_OWNER_ID *OwnerId)
+{
+ UINT32 i;
+ UINT32 j;
+ UINT32 k;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (UtAllocateOwnerId);
+
+
+ /* Guard against multiple allocations of ID to the same location */
+
+ if (*OwnerId)
+ {
+ ACPI_ERROR ((AE_INFO, "Owner ID [0x%2.2X] already exists", *OwnerId));
+ return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ }
+
+ /* Mutex for the global ID mask */
+
+ Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /*
+ * Find a free owner ID, cycle through all possible IDs on repeated
+ * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
+ * to be scanned twice.
+ */
+ for (i = 0, j = AcpiGbl_LastOwnerIdIndex;
+ i < (ACPI_NUM_OWNERID_MASKS + 1);
+ i++, j++)
+ {
+ if (j >= ACPI_NUM_OWNERID_MASKS)
+ {
+ j = 0; /* Wraparound to start of mask array */
+ }
+
+ for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++)
+ {
+ if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX)
+ {
+ /* There are no free IDs in this mask */
+
+ break;
+ }
+
+ if (!(AcpiGbl_OwnerIdMask[j] & (1 << k)))
+ {
+ /*
+ * Found a free ID. The actual ID is the bit index plus one,
+ * making zero an invalid Owner ID. Save this as the last ID
+ * allocated and update the global ID mask.
+ */
+ AcpiGbl_OwnerIdMask[j] |= (1 << k);
+
+ AcpiGbl_LastOwnerIdIndex = (UINT8) j;
+ AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1);
+
+ /*
+ * Construct encoded ID from the index and bit position
+ *
+ * Note: Last [j].k (bit 255) is never used and is marked
+ * permanently allocated (prevents +1 overflow)
+ */
+ *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j));
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_VALUES,
+ "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId));
+ goto Exit;
+ }
+ }
+
+ AcpiGbl_NextOwnerIdOffset = 0;
+ }
+
+ /*
+ * All OwnerIds have been allocated. This typically should
+ * not happen since the IDs are reused after deallocation. The IDs are
+ * allocated upon table load (one per table) and method execution, and
+ * they are released when a table is unloaded or a method completes
+ * execution.
+ *
+ * If this error happens, there may be very deep nesting of invoked control
+ * methods, or there may be a bug where the IDs are not released.
+ */
+ Status = AE_OWNER_ID_LIMIT;
+ ACPI_ERROR ((AE_INFO,
+ "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
+
+Exit:
+ (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtReleaseOwnerId
+ *
+ * PARAMETERS: OwnerIdPtr - Pointer to a previously allocated OwnerID
+ *
+ * RETURN: None. No error is returned because we are either exiting a
+ * control method or unloading a table. Either way, we would
+ * ignore any error anyway.
+ *
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
+ *
+ ******************************************************************************/
+
+void
+AcpiUtReleaseOwnerId (
+ ACPI_OWNER_ID *OwnerIdPtr)
+{
+ ACPI_OWNER_ID OwnerId = *OwnerIdPtr;
+ ACPI_STATUS Status;
+ UINT32 Index;
+ UINT32 Bit;
+
+
+ ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId);
+
+
+ /* Always clear the input OwnerId (zero is an invalid ID) */
+
+ *OwnerIdPtr = 0;
+
+ /* Zero is not a valid OwnerID */
+
+ if (OwnerId == 0)
+ {
+ ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId));
+ return_VOID;
+ }
+
+ /* Mutex for the global ID mask */
+
+ Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
+ if (ACPI_FAILURE (Status))
+ {
+ return_VOID;
+ }
+
+ /* Normalize the ID to zero */
+
+ OwnerId--;
+
+ /* Decode ID to index/offset pair */
+
+ Index = ACPI_DIV_32 (OwnerId);
+ Bit = 1 << ACPI_MOD_32 (OwnerId);
+
+ /* Free the owner ID only if it is valid */
+
+ if (AcpiGbl_OwnerIdMask[Index] & Bit)
+ {
+ AcpiGbl_OwnerIdMask[Index] ^= Bit;
+ }
+ else
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1));
+ }
+
+ (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
+ return_VOID;
+}
diff --git a/sys/contrib/dev/acpica/components/utilities/utresrc.c b/sys/contrib/dev/acpica/components/utilities/utresrc.c
index 08b8550..3a47a0c 100644
--- a/sys/contrib/dev/acpica/components/utilities/utresrc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utresrc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -456,7 +456,7 @@ AcpiUtWalkAmlResources (
UINT8 *Aml,
ACPI_SIZE AmlLength,
ACPI_WALK_AML_CALLBACK UserFunction,
- void *Context)
+ void **Context)
{
ACPI_STATUS Status;
UINT8 *EndAml;
@@ -528,7 +528,7 @@ AcpiUtWalkAmlResources (
if (!UserFunction)
{
- *(void **) Context = Aml;
+ *Context = Aml;
}
/* Normal exit */
@@ -919,7 +919,7 @@ AcpiUtGetResourceEndTag (
/* Validate the template and get a pointer to the EndTag */
Status = AcpiUtWalkAmlResources (NULL, ObjDesc->Buffer.Pointer,
- ObjDesc->Buffer.Length, NULL, EndTag);
+ ObjDesc->Buffer.Length, NULL, (void **) EndTag);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/utilities/utstate.c b/sys/contrib/dev/acpica/components/utilities/utstate.c
index 8edb9cd..e0e5cce 100644
--- a/sys/contrib/dev/acpica/components/utilities/utstate.c
+++ b/sys/contrib/dev/acpica/components/utilities/utstate.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utstring.c b/sys/contrib/dev/acpica/components/utilities/utstring.c
new file mode 100644
index 0000000..49a47fe
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/utilities/utstring.c
@@ -0,0 +1,674 @@
+/*******************************************************************************
+ *
+ * Module Name: utstring - Common functions for strings and characters
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#define __UTSTRING_C__
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+
+
+#define _COMPONENT ACPI_UTILITIES
+ ACPI_MODULE_NAME ("utstring")
+
+
+/*
+ * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit
+ * version of strtoul.
+ */
+
+#ifdef ACPI_ASL_COMPILER
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtStrlwr (strlwr)
+ *
+ * PARAMETERS: SrcString - The source string to convert
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Convert string to lowercase
+ *
+ * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
+ *
+ ******************************************************************************/
+
+void
+AcpiUtStrlwr (
+ char *SrcString)
+{
+ char *String;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ if (!SrcString)
+ {
+ return;
+ }
+
+ /* Walk entire string, lowercasing the letters */
+
+ for (String = SrcString; *String; String++)
+ {
+ *String = (char) ACPI_TOLOWER (*String);
+ }
+
+ return;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiUtStricmp (stricmp)
+ *
+ * PARAMETERS: String1 - first string to compare
+ * String2 - second string to compare
+ *
+ * RETURN: int that signifies string relationship. Zero means strings
+ * are equal.
+ *
+ * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
+ * strings with no case sensitivity)
+ *
+ ******************************************************************************/
+
+int
+AcpiUtStricmp (
+ char *String1,
+ char *String2)
+{
+ int c1;
+ int c2;
+
+
+ do
+ {
+ c1 = tolower ((int) *String1);
+ c2 = tolower ((int) *String2);
+
+ String1++;
+ String2++;
+ }
+ while ((c1 == c2) && (c1));
+
+ return (c1 - c2);
+}
+#endif
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtStrupr (strupr)
+ *
+ * PARAMETERS: SrcString - The source string to convert
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Convert string to uppercase
+ *
+ * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
+ *
+ ******************************************************************************/
+
+void
+AcpiUtStrupr (
+ char *SrcString)
+{
+ char *String;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ if (!SrcString)
+ {
+ return;
+ }
+
+ /* Walk entire string, uppercasing the letters */
+
+ for (String = SrcString; *String; String++)
+ {
+ *String = (char) ACPI_TOUPPER (*String);
+ }
+
+ return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtStrtoul64
+ *
+ * PARAMETERS: String - Null terminated string
+ * Base - Radix of the string: 16 or ACPI_ANY_BASE;
+ * ACPI_ANY_BASE means 'in behalf of ToInteger'
+ * RetInteger - Where the converted integer is returned
+ *
+ * RETURN: Status and Converted value
+ *
+ * DESCRIPTION: Convert a string into an unsigned value. Performs either a
+ * 32-bit or 64-bit conversion, depending on the current mode
+ * of the interpreter.
+ * NOTE: Does not support Octal strings, not needed.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiUtStrtoul64 (
+ char *String,
+ UINT32 Base,
+ UINT64 *RetInteger)
+{
+ UINT32 ThisDigit = 0;
+ UINT64 ReturnValue = 0;
+ UINT64 Quotient;
+ UINT64 Dividend;
+ UINT32 ToIntegerOp = (Base == ACPI_ANY_BASE);
+ UINT32 Mode32 = (AcpiGbl_IntegerByteWidth == 4);
+ UINT8 ValidDigits = 0;
+ UINT8 SignOf0x = 0;
+ UINT8 Term = 0;
+
+
+ ACPI_FUNCTION_TRACE_STR (UtStroul64, String);
+
+
+ switch (Base)
+ {
+ case ACPI_ANY_BASE:
+ case 16:
+ break;
+
+ default:
+ /* Invalid Base */
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ if (!String)
+ {
+ goto ErrorExit;
+ }
+
+ /* Skip over any white space in the buffer */
+
+ while ((*String) && (ACPI_IS_SPACE (*String) || *String == '\t'))
+ {
+ String++;
+ }
+
+ if (ToIntegerOp)
+ {
+ /*
+ * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
+ * We need to determine if it is decimal or hexadecimal.
+ */
+ if ((*String == '0') && (ACPI_TOLOWER (*(String + 1)) == 'x'))
+ {
+ SignOf0x = 1;
+ Base = 16;
+
+ /* Skip over the leading '0x' */
+ String += 2;
+ }
+ else
+ {
+ Base = 10;
+ }
+ }
+
+ /* Any string left? Check that '0x' is not followed by white space. */
+
+ if (!(*String) || ACPI_IS_SPACE (*String) || *String == '\t')
+ {
+ if (ToIntegerOp)
+ {
+ goto ErrorExit;
+ }
+ else
+ {
+ goto AllDone;
+ }
+ }
+
+ /*
+ * Perform a 32-bit or 64-bit conversion, depending upon the current
+ * execution mode of the interpreter
+ */
+ Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
+
+ /* Main loop: convert the string to a 32- or 64-bit integer */
+
+ while (*String)
+ {
+ if (ACPI_IS_DIGIT (*String))
+ {
+ /* Convert ASCII 0-9 to Decimal value */
+
+ ThisDigit = ((UINT8) *String) - '0';
+ }
+ else if (Base == 10)
+ {
+ /* Digit is out of range; possible in ToInteger case only */
+
+ Term = 1;
+ }
+ else
+ {
+ ThisDigit = (UINT8) ACPI_TOUPPER (*String);
+ if (ACPI_IS_XDIGIT ((char) ThisDigit))
+ {
+ /* Convert ASCII Hex char to value */
+
+ ThisDigit = ThisDigit - 'A' + 10;
+ }
+ else
+ {
+ Term = 1;
+ }
+ }
+
+ if (Term)
+ {
+ if (ToIntegerOp)
+ {
+ goto ErrorExit;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x)
+ {
+ /* Skip zeros */
+ String++;
+ continue;
+ }
+
+ ValidDigits++;
+
+ if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32)))
+ {
+ /*
+ * This is ToInteger operation case.
+ * No any restrictions for string-to-integer conversion,
+ * see ACPI spec.
+ */
+ goto ErrorExit;
+ }
+
+ /* Divide the digit into the correct position */
+
+ (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit),
+ Base, &Quotient, NULL);
+
+ if (ReturnValue > Quotient)
+ {
+ if (ToIntegerOp)
+ {
+ goto ErrorExit;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ ReturnValue *= Base;
+ ReturnValue += ThisDigit;
+ String++;
+ }
+
+ /* All done, normal exit */
+
+AllDone:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64 (ReturnValue)));
+
+ *RetInteger = ReturnValue;
+ return_ACPI_STATUS (AE_OK);
+
+
+ErrorExit:
+ /* Base was set/validated above */
+
+ if (Base == 10)
+ {
+ return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT);
+ }
+ else
+ {
+ return_ACPI_STATUS (AE_BAD_HEX_CONSTANT);
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtPrintString
+ *
+ * PARAMETERS: String - Null terminated ASCII string
+ * MaxLength - Maximum output length
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
+ * sequences.
+ *
+ ******************************************************************************/
+
+void
+AcpiUtPrintString (
+ char *String,
+ UINT8 MaxLength)
+{
+ UINT32 i;
+
+
+ if (!String)
+ {
+ AcpiOsPrintf ("<\"NULL STRING PTR\">");
+ return;
+ }
+
+ AcpiOsPrintf ("\"");
+ for (i = 0; String[i] && (i < MaxLength); i++)
+ {
+ /* Escape sequences */
+
+ switch (String[i])
+ {
+ case 0x07:
+ AcpiOsPrintf ("\\a"); /* BELL */
+ break;
+
+ case 0x08:
+ AcpiOsPrintf ("\\b"); /* BACKSPACE */
+ break;
+
+ case 0x0C:
+ AcpiOsPrintf ("\\f"); /* FORMFEED */
+ break;
+
+ case 0x0A:
+ AcpiOsPrintf ("\\n"); /* LINEFEED */
+ break;
+
+ case 0x0D:
+ AcpiOsPrintf ("\\r"); /* CARRIAGE RETURN*/
+ break;
+
+ case 0x09:
+ AcpiOsPrintf ("\\t"); /* HORIZONTAL TAB */
+ break;
+
+ case 0x0B:
+ AcpiOsPrintf ("\\v"); /* VERTICAL TAB */
+ break;
+
+ case '\'': /* Single Quote */
+ case '\"': /* Double Quote */
+ case '\\': /* Backslash */
+ AcpiOsPrintf ("\\%c", (int) String[i]);
+ break;
+
+ default:
+
+ /* Check for printable character or hex escape */
+
+ if (ACPI_IS_PRINT (String[i]))
+ {
+ /* This is a normal character */
+
+ AcpiOsPrintf ("%c", (int) String[i]);
+ }
+ else
+ {
+ /* All others will be Hex escapes */
+
+ AcpiOsPrintf ("\\x%2.2X", (INT32) String[i]);
+ }
+ break;
+ }
+ }
+ AcpiOsPrintf ("\"");
+
+ if (i == MaxLength && String[i])
+ {
+ AcpiOsPrintf ("...");
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtValidAcpiChar
+ *
+ * PARAMETERS: Char - The character to be examined
+ * Position - Byte position (0-3)
+ *
+ * RETURN: TRUE if the character is valid, FALSE otherwise
+ *
+ * DESCRIPTION: Check for a valid ACPI character. Must be one of:
+ * 1) Upper case alpha
+ * 2) numeric
+ * 3) underscore
+ *
+ * We allow a '!' as the last character because of the ASF! table
+ *
+ ******************************************************************************/
+
+BOOLEAN
+AcpiUtValidAcpiChar (
+ char Character,
+ UINT32 Position)
+{
+
+ if (!((Character >= 'A' && Character <= 'Z') ||
+ (Character >= '0' && Character <= '9') ||
+ (Character == '_')))
+ {
+ /* Allow a '!' in the last position */
+
+ if (Character == '!' && Position == 3)
+ {
+ return (TRUE);
+ }
+
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtValidAcpiName
+ *
+ * PARAMETERS: Name - The name to be examined
+ *
+ * RETURN: TRUE if the name is valid, FALSE otherwise
+ *
+ * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
+ * 1) Upper case alpha
+ * 2) numeric
+ * 3) underscore
+ *
+ ******************************************************************************/
+
+BOOLEAN
+AcpiUtValidAcpiName (
+ UINT32 Name)
+{
+ UINT32 i;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ for (i = 0; i < ACPI_NAME_SIZE; i++)
+ {
+ if (!AcpiUtValidAcpiChar ((ACPI_CAST_PTR (char, &Name))[i], i))
+ {
+ return (FALSE);
+ }
+ }
+
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtRepairName
+ *
+ * PARAMETERS: Name - The ACPI name to be repaired
+ *
+ * RETURN: Repaired version of the name
+ *
+ * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
+ * return the new name. NOTE: the Name parameter must reside in
+ * read/write memory, cannot be a const.
+ *
+ * An ACPI Name must consist of valid ACPI characters. We will repair the name
+ * if necessary because we don't want to abort because of this, but we want
+ * all namespace names to be printable. A warning message is appropriate.
+ *
+ * This issue came up because there are in fact machines that exhibit
+ * this problem, and we want to be able to enable ACPI support for them,
+ * even though there are a few bad names.
+ *
+ ******************************************************************************/
+
+void
+AcpiUtRepairName (
+ char *Name)
+{
+ UINT32 i;
+ BOOLEAN FoundBadChar = FALSE;
+ UINT32 OriginalName;
+
+
+ ACPI_FUNCTION_NAME (UtRepairName);
+
+
+ ACPI_MOVE_NAME (&OriginalName, Name);
+
+ /* Check each character in the name */
+
+ for (i = 0; i < ACPI_NAME_SIZE; i++)
+ {
+ if (AcpiUtValidAcpiChar (Name[i], i))
+ {
+ continue;
+ }
+
+ /*
+ * Replace a bad character with something printable, yet technically
+ * still invalid. This prevents any collisions with existing "good"
+ * names in the namespace.
+ */
+ Name[i] = '*';
+ FoundBadChar = TRUE;
+ }
+
+ if (FoundBadChar)
+ {
+ /* Report warning only if in strict mode or debug mode */
+
+ if (!AcpiGbl_EnableInterpreterSlack)
+ {
+ ACPI_WARNING ((AE_INFO,
+ "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
+ OriginalName, Name));
+ }
+ else
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+ "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
+ OriginalName, Name));
+ }
+ }
+}
+
+
+#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP
+/*******************************************************************************
+ *
+ * FUNCTION: UtConvertBackslashes
+ *
+ * PARAMETERS: Pathname - File pathname string to be converted
+ *
+ * RETURN: Modifies the input Pathname
+ *
+ * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within
+ * the entire input file pathname string.
+ *
+ ******************************************************************************/
+
+void
+UtConvertBackslashes (
+ char *Pathname)
+{
+
+ if (!Pathname)
+ {
+ return;
+ }
+
+ while (*Pathname)
+ {
+ if (*Pathname == '\\')
+ {
+ *Pathname = '/';
+ }
+
+ Pathname++;
+ }
+}
+#endif
diff --git a/sys/contrib/dev/acpica/components/utilities/uttrack.c b/sys/contrib/dev/acpica/components/utilities/uttrack.c
index 76b5bb3..c829fb0 100644
--- a/sys/contrib/dev/acpica/components/utilities/uttrack.c
+++ b/sys/contrib/dev/acpica/components/utilities/uttrack.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utxface.c b/sys/contrib/dev/acpica/components/utilities/utxface.c
index 4abe72e..cd3e7b2 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxface.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utxferror.c b/sys/contrib/dev/acpica/components/utilities/utxferror.c
index e106c9b..3067294 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxferror.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxferror.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utxfinit.c b/sys/contrib/dev/acpica/components/utilities/utxfinit.c
index e6e0f5d..c828a71 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxfinit.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxfinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utxfmutex.c b/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
index ca07871..ae5a345 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acapps.h b/sys/contrib/dev/acpica/include/acapps.h
index 0b3d72a..acc6e4a 100644
--- a/sys/contrib/dev/acpica/include/acapps.h
+++ b/sys/contrib/dev/acpica/include/acapps.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@
/* Common info for tool signons */
#define ACPICA_NAME "Intel ACPI Component Architecture"
-#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2012 Intel Corporation"
+#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2013 Intel Corporation"
#if ACPI_MACHINE_WIDTH == 64
#define ACPI_WIDTH "-64"
diff --git a/sys/contrib/dev/acpica/include/acbuffer.h b/sys/contrib/dev/acpica/include/acbuffer.h
index 4b34ccd..9651024 100644
--- a/sys/contrib/dev/acpica/include/acbuffer.h
+++ b/sys/contrib/dev/acpica/include/acbuffer.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/accommon.h b/sys/contrib/dev/acpica/include/accommon.h
index 93c9031..074b6c1 100644
--- a/sys/contrib/dev/acpica/include/accommon.h
+++ b/sys/contrib/dev/acpica/include/accommon.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acconfig.h b/sys/contrib/dev/acpica/include/acconfig.h
index b414383..452ab28 100644
--- a/sys/contrib/dev/acpica/include/acconfig.h
+++ b/sys/contrib/dev/acpica/include/acconfig.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -194,6 +194,7 @@
/* Maximum SpaceIds for Operation Regions */
#define ACPI_MAX_ADDRESS_SPACE 255
+#define ACPI_NUM_DEFAULT_SPACES 4
/* Array sizes. Used for range checking also */
diff --git a/sys/contrib/dev/acpica/include/acdebug.h b/sys/contrib/dev/acpica/include/acdebug.h
index de915b4..5fef182 100644
--- a/sys/contrib/dev/acpica/include/acdebug.h
+++ b/sys/contrib/dev/acpica/include/acdebug.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -161,6 +161,34 @@ AcpiDbGenerateGpe (
/*
+ * dbconvert - miscellaneous conversion routines
+ */
+ACPI_STATUS
+AcpiDbHexCharToValue (
+ int HexChar,
+ UINT8 *ReturnValue);
+
+ACPI_STATUS
+AcpiDbConvertToPackage (
+ char *String,
+ ACPI_OBJECT *Object);
+
+ACPI_STATUS
+AcpiDbConvertToObject (
+ ACPI_OBJECT_TYPE Type,
+ char *String,
+ ACPI_OBJECT *Object);
+
+UINT8 *
+AcpiDbEncodePldBuffer (
+ ACPI_PLD_INFO *PldInfo);
+
+void
+AcpiDbDumpPldBuffer (
+ ACPI_OBJECT *ObjDesc);
+
+
+/*
* dbmethod - control method commands
*/
void
@@ -299,6 +327,11 @@ AcpiDbCreateExecutionThreads (
char *NumLoopsArg,
char *MethodNameArg);
+void
+AcpiDbDeleteObjects (
+ UINT32 Count,
+ ACPI_OBJECT *Objects);
+
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
UINT32
AcpiDbGetCacheInfo (
diff --git a/sys/contrib/dev/acpica/include/acdisasm.h b/sys/contrib/dev/acpica/include/acdisasm.h
index 20e056a..eb6553b 100644
--- a/sys/contrib/dev/acpica/include/acdisasm.h
+++ b/sys/contrib/dev/acpica/include/acdisasm.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -237,6 +237,7 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoCpep[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoCpep0[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt0[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt1[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt2[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2Device[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2Addr[];
@@ -340,6 +341,7 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat0[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat1[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat2[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoUefi[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoWaet[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoWdat[];
diff --git a/sys/contrib/dev/acpica/include/acdispat.h b/sys/contrib/dev/acpica/include/acdispat.h
index 0699ee7..fc747f1 100644
--- a/sys/contrib/dev/acpica/include/acdispat.h
+++ b/sys/contrib/dev/acpica/include/acdispat.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acevents.h b/sys/contrib/dev/acpica/include/acevents.h
index 3b874f1..fc652b4 100644
--- a/sys/contrib/dev/acpica/include/acevents.h
+++ b/sys/contrib/dev/acpica/include/acevents.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -167,6 +167,7 @@ AcpiEvGpeDispatch (
ACPI_GPE_EVENT_INFO *GpeEventInfo,
UINT32 GpeNumber);
+
/*
* evgpeinit - GPE initialization and update
*/
@@ -186,6 +187,7 @@ AcpiEvMatchGpeMethod (
void *Context,
void **ReturnValue);
+
/*
* evgpeutil - GPE utilities
*/
@@ -220,13 +222,30 @@ AcpiEvDeleteGpeHandlers (
/*
- * evregion - Address Space handling
+ * evhandler - Address space handling
*/
+BOOLEAN
+AcpiEvHasDefaultHandler (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_ADR_SPACE_TYPE SpaceId);
+
ACPI_STATUS
AcpiEvInstallRegionHandlers (
void);
ACPI_STATUS
+AcpiEvInstallSpaceHandler (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_ADR_SPACE_TYPE SpaceId,
+ ACPI_ADR_SPACE_HANDLER Handler,
+ ACPI_ADR_SPACE_SETUP Setup,
+ void *Context);
+
+
+/*
+ * evregion - Operation region support
+ */
+ACPI_STATUS
AcpiEvInitializeOpRegions (
void);
@@ -251,14 +270,6 @@ AcpiEvDetachRegion (
BOOLEAN AcpiNsIsLocked);
ACPI_STATUS
-AcpiEvInstallSpaceHandler (
- ACPI_NAMESPACE_NODE *Node,
- ACPI_ADR_SPACE_TYPE SpaceId,
- ACPI_ADR_SPACE_HANDLER Handler,
- ACPI_ADR_SPACE_SETUP Setup,
- void *Context);
-
-ACPI_STATUS
AcpiEvExecuteRegMethods (
ACPI_NAMESPACE_NODE *Node,
ACPI_ADR_SPACE_TYPE SpaceId);
diff --git a/sys/contrib/dev/acpica/include/acexcep.h b/sys/contrib/dev/acpica/include/acexcep.h
index 072ddf9..110ef18 100644
--- a/sys/contrib/dev/acpica/include/acexcep.h
+++ b/sys/contrib/dev/acpica/include/acexcep.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h
index 42c6234..83547e6 100644
--- a/sys/contrib/dev/acpica/include/acglobal.h
+++ b/sys/contrib/dev/acpica/include/acglobal.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -349,7 +349,6 @@ ACPI_EXTERN UINT32 AcpiGbl_DeepestNesting;
*
****************************************************************************/
-
ACPI_EXTERN ACPI_THREAD_STATE *AcpiGbl_CurrentWalkList;
/* Control method single step flag */
@@ -413,7 +412,7 @@ ACPI_EXTERN UINT32 AcpiGbl_TraceDbgLayer;
/*****************************************************************************
*
- * Debugger globals
+ * Debugger and Disassembler globals
*
****************************************************************************/
@@ -421,6 +420,8 @@ ACPI_EXTERN UINT8 AcpiGbl_DbOutputFlags;
#ifdef ACPI_DISASSEMBLER
+ACPI_EXTERN BOOLEAN ACPI_INIT_GLOBAL (AcpiGbl_IgnoreNoopOperator, FALSE);
+
ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_disasm;
ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_verbose;
ACPI_EXTERN ACPI_EXTERNAL_LIST *AcpiGbl_ExternalList;
diff --git a/sys/contrib/dev/acpica/include/achware.h b/sys/contrib/dev/acpica/include/achware.h
index 6dc1191..9577fd1 100644
--- a/sys/contrib/dev/acpica/include/achware.h
+++ b/sys/contrib/dev/acpica/include/achware.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acinterp.h b/sys/contrib/dev/acpica/include/acinterp.h
index 45e9814..ebf4c98 100644
--- a/sys/contrib/dev/acpica/include/acinterp.h
+++ b/sys/contrib/dev/acpica/include/acinterp.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -620,7 +620,7 @@ void
AcpiExRelinquishInterpreter (
void);
-void
+BOOLEAN
AcpiExTruncateFor32bitTable (
ACPI_OPERAND_OBJECT *ObjDesc);
diff --git a/sys/contrib/dev/acpica/include/aclocal.h b/sys/contrib/dev/acpica/include/aclocal.h
index d54455f..798c4cb 100644
--- a/sys/contrib/dev/acpica/include/aclocal.h
+++ b/sys/contrib/dev/acpica/include/aclocal.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acmacros.h b/sys/contrib/dev/acpica/include/acmacros.h
index 9b44671..a56dcd7 100644
--- a/sys/contrib/dev/acpica/include/acmacros.h
+++ b/sys/contrib/dev/acpica/include/acmacros.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -314,15 +314,23 @@
#define ACPI_EXTRACT_3BIT_FLAG(Field, Position) (ACPI_GET_3BIT_FLAG ((Field) >> Position))
#define ACPI_EXTRACT_4BIT_FLAG(Field, Position) (ACPI_GET_4BIT_FLAG ((Field) >> Position))
+/* ACPI Pathname helpers */
+
+#define ACPI_IS_ROOT_PREFIX(c) ((c) == (UINT8) 0x5C) /* Backslash */
+#define ACPI_IS_PARENT_PREFIX(c) ((c) == (UINT8) 0x5E) /* Carat */
+#define ACPI_IS_PATH_SEPARATOR(c) ((c) == (UINT8) 0x2E) /* Period (dot) */
+
/*
* An object of type ACPI_NAMESPACE_NODE can appear in some contexts
* where a pointer to an object of type ACPI_OPERAND_OBJECT can also
* appear. This macro is used to distinguish them.
*
- * The "Descriptor" field is the first field in both structures.
+ * The "DescriptorType" field is the second field in both structures.
*/
+#define ACPI_GET_DESCRIPTOR_PTR(d) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.CommonPointer)
+#define ACPI_SET_DESCRIPTOR_PTR(d, p) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.CommonPointer = (p))
#define ACPI_GET_DESCRIPTOR_TYPE(d) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.DescriptorType)
-#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.DescriptorType = t)
+#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.DescriptorType = (t))
/*
* Macros for the master AML opcode table
@@ -385,139 +393,6 @@
#endif /* ACPI_NO_ERROR_MESSAGES */
-/*
- * Debug macros that are conditionally compiled
- */
-#ifdef ACPI_DEBUG_OUTPUT
-/*
- * Function entry tracing
- */
-#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
- AcpiUtTrace(ACPI_DEBUG_PARAMETERS)
-#define ACPI_FUNCTION_TRACE_PTR(a, b) ACPI_FUNCTION_NAME(a) \
- AcpiUtTracePtr(ACPI_DEBUG_PARAMETERS, (void *)b)
-#define ACPI_FUNCTION_TRACE_U32(a, b) ACPI_FUNCTION_NAME(a) \
- AcpiUtTraceU32(ACPI_DEBUG_PARAMETERS, (UINT32)b)
-#define ACPI_FUNCTION_TRACE_STR(a, b) ACPI_FUNCTION_NAME(a) \
- AcpiUtTraceStr(ACPI_DEBUG_PARAMETERS, (char *)b)
-
-#define ACPI_FUNCTION_ENTRY() AcpiUtTrackStackPtr()
-
-/*
- * Function exit tracing.
- * WARNING: These macros include a return statement. This is usually considered
- * bad form, but having a separate exit macro is very ugly and difficult to maintain.
- * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros
- * so that "_AcpiFunctionName" is defined.
- *
- * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining
- * about these constructs.
- */
-#ifdef ACPI_USE_DO_WHILE_0
-#define ACPI_DO_WHILE0(a) do a while(0)
-#else
-#define ACPI_DO_WHILE0(a) a
-#endif
-
-#define return_VOID ACPI_DO_WHILE0 ({ \
- AcpiUtExit (ACPI_DEBUG_PARAMETERS); \
- return;})
-/*
- * There are two versions of most of the return macros. The default version is
- * safer, since it avoids side-effects by guaranteeing that the argument will
- * not be evaluated twice.
- *
- * A less-safe version of the macros is provided for optional use if the
- * compiler uses excessive CPU stack (for example, this may happen in the
- * debug case if code optimzation is disabled.)
- */
-#ifndef ACPI_SIMPLE_RETURN_MACROS
-
-#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \
- register ACPI_STATUS _s = (s); \
- AcpiUtStatusExit (ACPI_DEBUG_PARAMETERS, _s); \
- return (_s); })
-#define return_PTR(s) ACPI_DO_WHILE0 ({ \
- register void *_s = (void *) (s); \
- AcpiUtPtrExit (ACPI_DEBUG_PARAMETERS, (UINT8 *) _s); \
- return (_s); })
-#define return_VALUE(s) ACPI_DO_WHILE0 ({ \
- register UINT64 _s = (s); \
- AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, _s); \
- return (_s); })
-#define return_UINT8(s) ACPI_DO_WHILE0 ({ \
- register UINT8 _s = (UINT8) (s); \
- AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) _s); \
- return (_s); })
-#define return_UINT32(s) ACPI_DO_WHILE0 ({ \
- register UINT32 _s = (UINT32) (s); \
- AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) _s); \
- return (_s); })
-#else /* Use original less-safe macros */
-
-#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \
- AcpiUtStatusExit (ACPI_DEBUG_PARAMETERS, (s)); \
- return((s)); })
-#define return_PTR(s) ACPI_DO_WHILE0 ({ \
- AcpiUtPtrExit (ACPI_DEBUG_PARAMETERS, (UINT8 *) (s)); \
- return((s)); })
-#define return_VALUE(s) ACPI_DO_WHILE0 ({ \
- AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) (s)); \
- return((s)); })
-#define return_UINT8(s) return_VALUE(s)
-#define return_UINT32(s) return_VALUE(s)
-
-#endif /* ACPI_SIMPLE_RETURN_MACROS */
-
-/* Conditional execution */
-
-#define ACPI_DEBUG_EXEC(a) a
-#define ACPI_DEBUG_ONLY_MEMBERS(a) a;
-#define _VERBOSE_STRUCTURES
-
-
-/* Various object display routines for debug */
-
-#define ACPI_DUMP_STACK_ENTRY(a) AcpiExDumpOperand((a), 0)
-#define ACPI_DUMP_OPERANDS(a, b ,c) AcpiExDumpOperands(a, b, c)
-#define ACPI_DUMP_ENTRY(a, b) AcpiNsDumpEntry (a, b)
-#define ACPI_DUMP_PATHNAME(a, b, c, d) AcpiNsDumpPathname(a, b, c, d)
-#define ACPI_DUMP_BUFFER(a, b) AcpiUtDebugDumpBuffer((UINT8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
-
-#else
-/*
- * This is the non-debug case -- make everything go away,
- * leaving no executable debug code!
- */
-#define ACPI_DEBUG_EXEC(a)
-#define ACPI_DEBUG_ONLY_MEMBERS(a)
-#define ACPI_FUNCTION_TRACE(a)
-#define ACPI_FUNCTION_TRACE_PTR(a, b)
-#define ACPI_FUNCTION_TRACE_U32(a, b)
-#define ACPI_FUNCTION_TRACE_STR(a, b)
-#define ACPI_FUNCTION_EXIT
-#define ACPI_FUNCTION_STATUS_EXIT(s)
-#define ACPI_FUNCTION_VALUE_EXIT(s)
-#define ACPI_FUNCTION_ENTRY()
-#define ACPI_DUMP_STACK_ENTRY(a)
-#define ACPI_DUMP_OPERANDS(a, b, c)
-#define ACPI_DUMP_ENTRY(a, b)
-#define ACPI_DUMP_TABLES(a, b)
-#define ACPI_DUMP_PATHNAME(a, b, c, d)
-#define ACPI_DUMP_BUFFER(a, b)
-#define ACPI_DEBUG_PRINT(pl)
-#define ACPI_DEBUG_PRINT_RAW(pl)
-
-#define return_VOID return
-#define return_ACPI_STATUS(s) return(s)
-#define return_VALUE(s) return(s)
-#define return_UINT8(s) return(s)
-#define return_UINT32(s) return(s)
-#define return_PTR(s) return(s)
-
-#endif /* ACPI_DEBUG_OUTPUT */
-
-
#if (!ACPI_REDUCED_HARDWARE)
#define ACPI_HW_OPTIONAL_FUNCTION(addr) addr
#else
diff --git a/sys/contrib/dev/acpica/include/acnames.h b/sys/contrib/dev/acpica/include/acnames.h
index 1987b16..d6fdaa6 100644
--- a/sys/contrib/dev/acpica/include/acnames.h
+++ b/sys/contrib/dev/acpica/include/acnames.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acnamesp.h b/sys/contrib/dev/acpica/include/acnamesp.h
index 4a91108..7a92143 100644
--- a/sys/contrib/dev/acpica/include/acnamesp.h
+++ b/sys/contrib/dev/acpica/include/acnamesp.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -277,6 +277,22 @@ AcpiNsCheckParameterCount (
UINT32 UserParamCount,
const ACPI_PREDEFINED_INFO *Info);
+ACPI_STATUS
+AcpiNsCheckObjectType (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **ReturnObjectPtr,
+ UINT32 ExpectedBtypes,
+ UINT32 PackageIndex);
+
+
+/*
+ * nsprepkg - Validation of predefined name packages
+ */
+ACPI_STATUS
+AcpiNsCheckPackage (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **ReturnObjectPtr);
+
/*
* nsnames - Name and Scope manipulation
@@ -430,10 +446,6 @@ AcpiNsInstallNode (
/*
* nsutils - Utility functions
*/
-BOOLEAN
-AcpiNsValidRootPrefix (
- char Prefix);
-
ACPI_OBJECT_TYPE
AcpiNsGetType (
ACPI_NAMESPACE_NODE *Node);
diff --git a/sys/contrib/dev/acpica/include/acobject.h b/sys/contrib/dev/acpica/include/acobject.h
index 2f17375..e755daa 100644
--- a/sys/contrib/dev/acpica/include/acobject.h
+++ b/sys/contrib/dev/acpica/include/acobject.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acopcode.h b/sys/contrib/dev/acpica/include/acopcode.h
index edd1349..ba37842 100644
--- a/sys/contrib/dev/acpica/include/acopcode.h
+++ b/sys/contrib/dev/acpica/include/acopcode.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acoutput.h b/sys/contrib/dev/acpica/include/acoutput.h
index 193d0ac..4b5ca9c 100644
--- a/sys/contrib/dev/acpica/include/acoutput.h
+++ b/sys/contrib/dev/acpica/include/acoutput.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -267,18 +267,165 @@
* Common parameters used for debug output functions:
* line number, function name, module(file) name, component ID
*/
-#define ACPI_DEBUG_PARAMETERS __LINE__, ACPI_GET_FUNCTION_NAME, _AcpiModuleName, _COMPONENT
+#define ACPI_DEBUG_PARAMETERS \
+ __LINE__, ACPI_GET_FUNCTION_NAME, _AcpiModuleName, _COMPONENT
+
+/* Check if debug output is currently dynamically enabled */
+
+#define ACPI_IS_DEBUG_ENABLED(Level, Component) \
+ ((Level & AcpiDbgLevel) && (Component & AcpiDbgLayer))
/*
* Master debug print macros
* Print message if and only if:
* 1) Debug print for the current component is enabled
* 2) Debug error level or trace level for the print statement is enabled
+ *
+ * November 2012: Moved the runtime check for whether to actually emit the
+ * debug message outside of the print function itself. This improves overall
+ * performance at a relatively small code cost. Implementation involves the
+ * use of variadic macros supported by C99.
+ *
+ * Note: the ACPI_DO_WHILE0 macro is used to prevent some compilers from
+ * complaining about these constructs. On other compilers the do...while
+ * adds some extra code, so this feature is optional.
*/
-#define ACPI_DEBUG_PRINT(plist) AcpiDebugPrint plist
-#define ACPI_DEBUG_PRINT_RAW(plist) AcpiDebugPrintRaw plist
-
+#ifdef ACPI_USE_DO_WHILE_0
+#define ACPI_DO_WHILE0(a) do a while(0)
#else
+#define ACPI_DO_WHILE0(a) a
+#endif
+
+/* DEBUG_PRINT functions */
+
+#define ACPI_DEBUG_PRINT(plist) ACPI_ACTUAL_DEBUG plist
+#define ACPI_DEBUG_PRINT_RAW(plist) ACPI_ACTUAL_DEBUG_RAW plist
+
+/* Helper macros for DEBUG_PRINT */
+
+#define ACPI_DO_DEBUG_PRINT(Function, Level, Line, Filename, Modulename, Component, ...) \
+ ACPI_DO_WHILE0 ({ \
+ if (ACPI_IS_DEBUG_ENABLED (Level, Component)) \
+ { \
+ Function (Level, Line, Filename, Modulename, Component, __VA_ARGS__); \
+ } \
+ })
+
+#define ACPI_ACTUAL_DEBUG(Level, Line, Filename, Modulename, Component, ...) \
+ ACPI_DO_DEBUG_PRINT (AcpiDebugPrint, Level, Line, \
+ Filename, Modulename, Component, __VA_ARGS__)
+
+#define ACPI_ACTUAL_DEBUG_RAW(Level, Line, Filename, Modulename, Component, ...) \
+ ACPI_DO_DEBUG_PRINT (AcpiDebugPrintRaw, Level, Line, \
+ Filename, Modulename, Component, __VA_ARGS__)
+
+
+/*
+ * Function entry tracing
+ *
+ * The name of the function is emitted as a local variable that is
+ * intended to be used by both the entry trace and the exit trace.
+ */
+
+/* Helper macro */
+
+#define ACPI_TRACE_ENTRY(Name, Function, Type, Param) \
+ ACPI_FUNCTION_NAME (Name) \
+ Function (ACPI_DEBUG_PARAMETERS, (Type) (Param))
+
+/* The actual entry trace macros */
+
+#define ACPI_FUNCTION_TRACE(Name) \
+ ACPI_FUNCTION_NAME(Name) \
+ AcpiUtTrace (ACPI_DEBUG_PARAMETERS)
+
+#define ACPI_FUNCTION_TRACE_PTR(Name, Pointer) \
+ ACPI_TRACE_ENTRY (Name, AcpiUtTracePtr, void *, Pointer)
+
+#define ACPI_FUNCTION_TRACE_U32(Name, Value) \
+ ACPI_TRACE_ENTRY (Name, AcpiUtTraceU32, UINT32, Value)
+
+#define ACPI_FUNCTION_TRACE_STR(Name, String) \
+ ACPI_TRACE_ENTRY (Name, AcpiUtTraceStr, char *, String)
+
+#define ACPI_FUNCTION_ENTRY() \
+ AcpiUtTrackStackPtr()
+
+
+/*
+ * Function exit tracing
+ *
+ * These macros include a return statement. This is usually considered
+ * bad form, but having a separate exit macro before the actual return
+ * is very ugly and difficult to maintain.
+ *
+ * One of the FUNCTION_TRACE macros above must be used in conjunction
+ * with these macros so that "_AcpiFunctionName" is defined.
+ *
+ * There are two versions of most of the return macros. The default version is
+ * safer, since it avoids side-effects by guaranteeing that the argument will
+ * not be evaluated twice.
+ *
+ * A less-safe version of the macros is provided for optional use if the
+ * compiler uses excessive CPU stack (for example, this may happen in the
+ * debug case if code optimzation is disabled.)
+ */
+
+/* Exit trace helper macro */
+
+#ifndef ACPI_SIMPLE_RETURN_MACROS
+
+#define ACPI_TRACE_EXIT(Function, Type, Param) \
+ ACPI_DO_WHILE0 ({ \
+ register Type _Param = (Type) (Param); \
+ Function (ACPI_DEBUG_PARAMETERS, _Param); \
+ return (_Param); \
+ })
+
+#else /* Use original less-safe macros */
+
+#define ACPI_TRACE_EXIT(Function, Type, Param) \
+ ACPI_DO_WHILE0 ({ \
+ Function (ACPI_DEBUG_PARAMETERS, (Type) (Param)); \
+ return (Param); \
+ })
+
+#endif /* ACPI_SIMPLE_RETURN_MACROS */
+
+/* The actual exit macros */
+
+#define return_VOID \
+ ACPI_DO_WHILE0 ({ \
+ AcpiUtExit (ACPI_DEBUG_PARAMETERS); \
+ return; \
+ })
+
+#define return_ACPI_STATUS(Status) \
+ ACPI_TRACE_EXIT (AcpiUtStatusExit, ACPI_STATUS, Status)
+
+#define return_PTR(Pointer) \
+ ACPI_TRACE_EXIT (AcpiUtPtrExit, void *, Pointer)
+
+#define return_VALUE(Value) \
+ ACPI_TRACE_EXIT (AcpiUtValueExit, UINT64, Value)
+
+
+/* Conditional execution */
+
+#define ACPI_DEBUG_EXEC(a) a
+#define ACPI_DEBUG_ONLY_MEMBERS(a) a;
+#define _VERBOSE_STRUCTURES
+
+
+/* Various object display routines for debug */
+
+#define ACPI_DUMP_STACK_ENTRY(a) AcpiExDumpOperand((a), 0)
+#define ACPI_DUMP_OPERANDS(a, b ,c) AcpiExDumpOperands(a, b, c)
+#define ACPI_DUMP_ENTRY(a, b) AcpiNsDumpEntry (a, b)
+#define ACPI_DUMP_PATHNAME(a, b, c, d) AcpiNsDumpPathname(a, b, c, d)
+#define ACPI_DUMP_BUFFER(a, b) AcpiUtDebugDumpBuffer((UINT8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
+
+#else /* ACPI_DEBUG_OUTPUT */
/*
* This is the non-debug case -- make everything go away,
* leaving no executable debug code!
@@ -286,6 +433,32 @@
#define ACPI_FUNCTION_NAME(a)
#define ACPI_DEBUG_PRINT(pl)
#define ACPI_DEBUG_PRINT_RAW(pl)
+#define ACPI_DEBUG_EXEC(a)
+#define ACPI_DEBUG_ONLY_MEMBERS(a)
+#define ACPI_FUNCTION_TRACE(a)
+#define ACPI_FUNCTION_TRACE_PTR(a, b)
+#define ACPI_FUNCTION_TRACE_U32(a, b)
+#define ACPI_FUNCTION_TRACE_STR(a, b)
+#define ACPI_FUNCTION_EXIT
+#define ACPI_FUNCTION_STATUS_EXIT(s)
+#define ACPI_FUNCTION_VALUE_EXIT(s)
+#define ACPI_FUNCTION_ENTRY()
+#define ACPI_DUMP_STACK_ENTRY(a)
+#define ACPI_DUMP_OPERANDS(a, b, c)
+#define ACPI_DUMP_ENTRY(a, b)
+#define ACPI_DUMP_TABLES(a, b)
+#define ACPI_DUMP_PATHNAME(a, b, c, d)
+#define ACPI_DUMP_BUFFER(a, b)
+#define ACPI_DEBUG_PRINT(pl)
+#define ACPI_DEBUG_PRINT_RAW(pl)
+#define ACPI_IS_DEBUG_ENABLED(Level, Component) 0
+
+/* Return macros must have a return statement at the minimum */
+
+#define return_VOID return
+#define return_ACPI_STATUS(s) return(s)
+#define return_VALUE(s) return(s)
+#define return_PTR(s) return(s)
#endif /* ACPI_DEBUG_OUTPUT */
diff --git a/sys/contrib/dev/acpica/include/acparser.h b/sys/contrib/dev/acpica/include/acparser.h
index f46d3cb..7f236d8 100644
--- a/sys/contrib/dev/acpica/include/acparser.h
+++ b/sys/contrib/dev/acpica/include/acparser.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -129,7 +129,36 @@ AcpiPsGetParent (
/*
- * psopcode - AML Opcode information
+ * psobject - support for parse object processing
+ */
+ACPI_STATUS
+AcpiPsBuildNamedOp (
+ ACPI_WALK_STATE *WalkState,
+ UINT8 *AmlOpStart,
+ ACPI_PARSE_OBJECT *UnnamedOp,
+ ACPI_PARSE_OBJECT **Op);
+
+ACPI_STATUS
+AcpiPsCreateOp (
+ ACPI_WALK_STATE *WalkState,
+ UINT8 *AmlOpStart,
+ ACPI_PARSE_OBJECT **NewOp);
+
+ACPI_STATUS
+AcpiPsCompleteOp (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT **Op,
+ ACPI_STATUS Status);
+
+ACPI_STATUS
+AcpiPsCompleteFinalOp (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT *Op,
+ ACPI_STATUS Status);
+
+
+/*
+ * psopinfo - AML Opcode information
*/
const ACPI_OPCODE_INFO *
AcpiPsGetOpcodeInfo (
@@ -294,10 +323,6 @@ BOOLEAN
AcpiPsIsLeadingChar (
UINT32 c);
-BOOLEAN
-AcpiPsIsPrefixChar (
- UINT32 c);
-
UINT32
AcpiPsGetName(
ACPI_PARSE_OBJECT *op);
diff --git a/sys/contrib/dev/acpica/include/acpi.h b/sys/contrib/dev/acpica/include/acpi.h
index ad0f17b..5450ad4 100644
--- a/sys/contrib/dev/acpica/include/acpi.h
+++ b/sys/contrib/dev/acpica/include/acpi.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acpiosxf.h b/sys/contrib/dev/acpica/include/acpiosxf.h
index 462d030..ae9cf3c 100644
--- a/sys/contrib/dev/acpica/include/acpiosxf.h
+++ b/sys/contrib/dev/acpica/include/acpiosxf.h
@@ -8,7 +8,7 @@
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h
index 086e2d3..1cd6cb9 100644
--- a/sys/contrib/dev/acpica/include/acpixf.h
+++ b/sys/contrib/dev/acpica/include/acpixf.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20121114
+#define ACPI_CA_VERSION 0x20130117
#include <contrib/dev/acpica/include/acconfig.h>
#include <contrib/dev/acpica/include/actypes.h>
@@ -618,6 +618,12 @@ AcpiGetEventResources (
ACPI_BUFFER *RetBuffer);
ACPI_STATUS
+AcpiWalkResourceBuffer (
+ ACPI_BUFFER *Buffer,
+ ACPI_WALK_RESOURCE_CALLBACK UserFunction,
+ void *Context);
+
+ACPI_STATUS
AcpiWalkResources (
ACPI_HANDLE Device,
char *Name,
diff --git a/sys/contrib/dev/acpica/include/acpredef.h b/sys/contrib/dev/acpica/include/acpredef.h
index c5b115e..771e344 100644
--- a/sys/contrib/dev/acpica/include/acpredef.h
+++ b/sys/contrib/dev/acpica/include/acpredef.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -345,8 +345,8 @@ static const ACPI_PREDEFINED_INFO PredefinedNames[] =
{{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8,0}, 0,0}},
- {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */
- {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}},
+ {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (1 Str/1 Buf) */
+ {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 1, ACPI_RTYPE_BUFFER}, 1,0}},
{{"_MSG", 1, 0}},
{{"_MSM", 4, ACPI_RTYPE_INTEGER}},
diff --git a/sys/contrib/dev/acpica/include/acresrc.h b/sys/contrib/dev/acpica/include/acresrc.h
index e9ae052..b894e2f 100644
--- a/sys/contrib/dev/acpica/include/acresrc.h
+++ b/sys/contrib/dev/acpica/include/acresrc.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -265,7 +265,7 @@ AcpiRsConvertAmlToResources (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context);
+ void **Context);
ACPI_STATUS
AcpiRsConvertResourcesToAml (
@@ -405,18 +405,21 @@ extern ACPI_RSDUMP_INFO *AcpiGbl_DumpResourceDispatch[];
extern ACPI_RSDUMP_INFO *AcpiGbl_DumpSerialBusDispatch[];
/*
- * rsdump
+ * rsdumpinfo
*/
extern ACPI_RSDUMP_INFO AcpiRsDumpIrq[];
+extern ACPI_RSDUMP_INFO AcpiRsDumpPrt[];
extern ACPI_RSDUMP_INFO AcpiRsDumpDma[];
extern ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[];
extern ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[];
extern ACPI_RSDUMP_INFO AcpiRsDumpIo[];
+extern ACPI_RSDUMP_INFO AcpiRsDumpIoFlags[];
extern ACPI_RSDUMP_INFO AcpiRsDumpFixedIo[];
extern ACPI_RSDUMP_INFO AcpiRsDumpVendor[];
extern ACPI_RSDUMP_INFO AcpiRsDumpEndTag[];
extern ACPI_RSDUMP_INFO AcpiRsDumpMemory24[];
extern ACPI_RSDUMP_INFO AcpiRsDumpMemory32[];
+extern ACPI_RSDUMP_INFO AcpiRsDumpMemoryFlags[];
extern ACPI_RSDUMP_INFO AcpiRsDumpFixedMemory32[];
extern ACPI_RSDUMP_INFO AcpiRsDumpAddress16[];
extern ACPI_RSDUMP_INFO AcpiRsDumpAddress32[];
@@ -430,6 +433,7 @@ extern ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[];
extern ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[];
extern ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[];
extern ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[];
+extern ACPI_RSDUMP_INFO AcpiRsDumpGeneralFlags[];
#endif
#endif /* __ACRESRC_H__ */
diff --git a/sys/contrib/dev/acpica/include/acrestyp.h b/sys/contrib/dev/acpica/include/acrestyp.h
index 07a6076..9d69825 100644
--- a/sys/contrib/dev/acpica/include/acrestyp.h
+++ b/sys/contrib/dev/acpica/include/acrestyp.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -103,8 +103,11 @@ typedef UINT32 ACPI_RSDESC_SIZE; /* Max Resource Descr
#define ACPI_EXCLUSIVE (UINT8) 0x00
#define ACPI_SHARED (UINT8) 0x01
-#define ACPI_EXCLUSIVE_AND_WAKE (UINT8) 0x02
-#define ACPI_SHARED_AND_WAKE (UINT8) 0x03
+
+/* Wake */
+
+#define ACPI_NOT_WAKE_CAPABLE (UINT8) 0x00
+#define ACPI_WAKE_CAPABLE (UINT8) 0x01
/*
* DMA Attributes
@@ -177,6 +180,7 @@ typedef struct acpi_resource_irq
UINT8 Triggering;
UINT8 Polarity;
UINT8 Sharable;
+ UINT8 WakeCapable;
UINT8 InterruptCount;
UINT8 Interrupts[1];
@@ -402,6 +406,7 @@ typedef struct acpi_resource_extended_irq
UINT8 Triggering;
UINT8 Polarity;
UINT8 Sharable;
+ UINT8 WakeCapable;
UINT8 InterruptCount;
ACPI_RESOURCE_SOURCE ResourceSource;
UINT32 Interrupts[1];
@@ -425,6 +430,7 @@ typedef struct acpi_resource_gpio
UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */
UINT8 PinConfig;
UINT8 Sharable; /* For values, see Interrupt Attributes above */
+ UINT8 WakeCapable; /* For values, see Interrupt Attributes above */
UINT8 IoRestriction;
UINT8 Triggering; /* For values, see Interrupt Attributes above */
UINT8 Polarity; /* For values, see Interrupt Attributes above */
diff --git a/sys/contrib/dev/acpica/include/acstruct.h b/sys/contrib/dev/acpica/include/acstruct.h
index ff01e86..8923d81 100644
--- a/sys/contrib/dev/acpica/include/acstruct.h
+++ b/sys/contrib/dev/acpica/include/acstruct.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/actables.h b/sys/contrib/dev/acpica/include/actables.h
index 26a7947d..b16c6e3 100644
--- a/sys/contrib/dev/acpica/include/actables.h
+++ b/sys/contrib/dev/acpica/include/actables.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/actbl.h b/sys/contrib/dev/acpica/include/actbl.h
index 90264dd..d77d6c4 100644
--- a/sys/contrib/dev/acpica/include/actbl.h
+++ b/sys/contrib/dev/acpica/include/actbl.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/actbl1.h b/sys/contrib/dev/acpica/include/actbl1.h
index d7cc59b..67579da 100644
--- a/sys/contrib/dev/acpica/include/actbl1.h
+++ b/sys/contrib/dev/acpica/include/actbl1.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/actbl2.h b/sys/contrib/dev/acpica/include/actbl2.h
index 2d2d5ca..49b9578 100644
--- a/sys/contrib/dev/acpica/include/actbl2.h
+++ b/sys/contrib/dev/acpica/include/actbl2.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -285,6 +285,7 @@ typedef struct acpi_table_csrt
} ACPI_TABLE_CSRT;
+
/* Resource Group subtable */
typedef struct acpi_csrt_group
@@ -296,12 +297,33 @@ typedef struct acpi_csrt_group
UINT16 SubdeviceId;
UINT16 Revision;
UINT16 Reserved;
- UINT32 InfoLength;
+ UINT32 SharedInfoLength;
- /* Shared data (length = InfoLength) immediately follows */
+ /* Shared data immediately follows (Length = SharedInfoLength) */
} ACPI_CSRT_GROUP;
+/* Shared Info subtable */
+
+typedef struct acpi_csrt_shared_info
+{
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 MmioBaseLow;
+ UINT32 MmioBaseHigh;
+ UINT32 GsiInterrupt;
+ UINT8 InterruptPolarity;
+ UINT8 InterruptMode;
+ UINT8 NumChannels;
+ UINT8 DmaAddressWidth;
+ UINT16 BaseRequestLine;
+ UINT16 NumHandshakeSignals;
+ UINT32 MaxBlockSize;
+
+ /* Resource descriptors immediately follow (Length = Group Length - SharedInfoLength) */
+
+} ACPI_CSRT_SHARED_INFO;
+
/* Resource Descriptor subtable */
typedef struct acpi_csrt_descriptor
diff --git a/sys/contrib/dev/acpica/include/actbl3.h b/sys/contrib/dev/acpica/include/actbl3.h
index 874e348..46c3c6d 100644
--- a/sys/contrib/dev/acpica/include/actbl3.h
+++ b/sys/contrib/dev/acpica/include/actbl3.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,13 +70,13 @@
#define ACPI_SIG_PCCT "PCCT" /* Platform Communications Channel Table */
#define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */
#define ACPI_SIG_RASF "RASF" /* RAS Feature table */
+#define ACPI_SIG_TPM2 "TPM2" /* Trusted Platform Module 2.0 H/W interface table */
#define ACPI_SIG_S3PT "S3PT" /* S3 Performance (sub)Table */
#define ACPI_SIG_PCCS "PCC" /* PCC Shared Memory Region */
/* Reserved table signatures */
-#define ACPI_SIG_CSRT "CSRT" /* Core System Resources Table */
#define ACPI_SIG_MATR "MATR" /* Memory Address Translation Table */
#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */
#define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */
@@ -648,6 +648,41 @@ enum AcpiRasfStatus
#define ACPI_RASF_STATUS (0x1F<<3)
+/*******************************************************************************
+ *
+ * TPM2 - Trusted Platform Module (TPM) 2.0 Hardware Interface Table
+ * Version 3
+ *
+ * Conforms to "TPM 2.0 Hardware Interface Table (TPM2)" 29 November 2011
+ *
+ ******************************************************************************/
+
+typedef struct acpi_table_tpm2
+{
+ ACPI_TABLE_HEADER Header; /* Common ACPI table header */
+ UINT32 Flags;
+ UINT64 ControlAddress;
+ UINT32 StartMethod;
+
+} ACPI_TABLE_TPM2;
+
+/* Control area structure (not part of table, pointed to by ControlAddress) */
+
+typedef struct acpi_tpm2_control
+{
+ UINT32 Reserved;
+ UINT32 Error;
+ UINT32 Cancel;
+ UINT32 Start;
+ UINT64 InterruptControl;
+ UINT32 CommandSize;
+ UINT64 CommandAddress;
+ UINT32 ResponseSize;
+ UINT64 ResponseAddress;
+
+} ACPI_TPM2_CONTROL;
+
+
/* Reset to default packing */
#pragma pack()
diff --git a/sys/contrib/dev/acpica/include/actypes.h b/sys/contrib/dev/acpica/include/actypes.h
index 611c418..9c8ec7d 100644
--- a/sys/contrib/dev/acpica/include/actypes.h
+++ b/sys/contrib/dev/acpica/include/actypes.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -295,7 +295,7 @@ typedef UINT32 ACPI_PHYSICAL_ADDRESS;
/*
* Some compilers complain about unused variables. Sometimes we don't want to
* use all the variables (for example, _AcpiModuleName). This allows us
- * to to tell the compiler in a per-variable manner that a variable
+ * to tell the compiler in a per-variable manner that a variable
* is unused
*/
#ifndef ACPI_UNUSED_VAR
@@ -346,7 +346,7 @@ typedef UINT32 ACPI_PHYSICAL_ADDRESS;
/* PM Timer ticks per second (HZ) */
-#define PM_TIMER_FREQUENCY 3579545
+#define ACPI_PM_TIMER_FREQUENCY 3579545
/*******************************************************************************
@@ -381,6 +381,22 @@ typedef char * ACPI_STRING; /* Null terminated ASCII
typedef void * ACPI_HANDLE; /* Actually a ptr to a NS Node */
+/* Time constants for timer calculations */
+
+#define ACPI_MSEC_PER_SEC 1000L
+
+#define ACPI_USEC_PER_MSEC 1000L
+#define ACPI_USEC_PER_SEC 1000000L
+
+#define ACPI_100NSEC_PER_USEC 10L
+#define ACPI_100NSEC_PER_MSEC 10000L
+#define ACPI_100NSEC_PER_SEC 10000000L
+
+#define ACPI_NSEC_PER_USEC 1000L
+#define ACPI_NSEC_PER_MSEC 1000000L
+#define ACPI_NSEC_PER_SEC 1000000000L
+
+
/* Owner IDs are used to track namespace nodes for selective deletion */
typedef UINT8 ACPI_OWNER_ID;
@@ -596,7 +612,7 @@ typedef UINT32 ACPI_OBJECT_TYPE;
/*
* These are special object types that never appear in
- * a Namespace node, only in an ACPI_OPERAND_OBJECT
+ * a Namespace node, only in an object of ACPI_OPERAND_OBJECT
*/
#define ACPI_TYPE_LOCAL_EXTRA 0x1C
#define ACPI_TYPE_LOCAL_DATA 0x1D
@@ -904,6 +920,10 @@ typedef struct acpi_buffer
} ACPI_BUFFER;
+/* Free a buffer created in an ACPI_BUFFER via ACPI_ALLOCATE_LOCAL_BUFFER */
+
+#define ACPI_FREE_BUFFER(b) ACPI_FREE(b.Pointer)
+
/*
* NameType for AcpiGetName
@@ -1206,7 +1226,6 @@ typedef struct acpi_memory_list
UINT16 ObjectSize;
UINT16 MaxDepth;
UINT16 CurrentDepth;
- UINT16 LinkOffset;
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
diff --git a/sys/contrib/dev/acpica/include/acutils.h b/sys/contrib/dev/acpica/include/acutils.h
index f663a1e..e75e248 100644
--- a/sys/contrib/dev/acpica/include/acutils.h
+++ b/sys/contrib/dev/acpica/include/acutils.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -101,7 +101,7 @@ ACPI_STATUS (*ACPI_WALK_AML_CALLBACK) (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context);
+ void **Context);
typedef
ACPI_STATUS (*ACPI_PKG_CALLBACK) (
@@ -709,10 +709,6 @@ AcpiUtShortDivide (
/*
* utmisc
*/
-void
-UtConvertBackslashes (
- char *Pathname);
-
const char *
AcpiUtValidateException (
ACPI_STATUS Status);
@@ -726,56 +722,12 @@ AcpiUtIsAmlTable (
ACPI_TABLE_HEADER *Table);
ACPI_STATUS
-AcpiUtAllocateOwnerId (
- ACPI_OWNER_ID *OwnerId);
-
-void
-AcpiUtReleaseOwnerId (
- ACPI_OWNER_ID *OwnerId);
-
-ACPI_STATUS
AcpiUtWalkPackageTree (
ACPI_OPERAND_OBJECT *SourceObject,
void *TargetObject,
ACPI_PKG_CALLBACK WalkCallback,
void *Context);
-void
-AcpiUtStrupr (
- char *SrcString);
-
-void
-AcpiUtStrlwr (
- char *SrcString);
-
-int
-AcpiUtStricmp (
- char *String1,
- char *String2);
-
-void
-AcpiUtPrintString (
- char *String,
- UINT8 MaxLength);
-
-BOOLEAN
-AcpiUtValidAcpiName (
- UINT32 Name);
-
-void
-AcpiUtRepairName (
- char *Name);
-
-BOOLEAN
-AcpiUtValidAcpiChar (
- char Character,
- UINT32 Position);
-
-ACPI_STATUS
-AcpiUtStrtoul64 (
- char *String,
- UINT32 Base,
- UINT64 *RetInteger);
/* Values for Base above (16=Hex, 10=Decimal) */
@@ -799,6 +751,18 @@ AcpiUtDisplayInitPathname (
/*
+ * utownerid - Support for Table/Method Owner IDs
+ */
+ACPI_STATUS
+AcpiUtAllocateOwnerId (
+ ACPI_OWNER_ID *OwnerId);
+
+void
+AcpiUtReleaseOwnerId (
+ ACPI_OWNER_ID *OwnerId);
+
+
+/*
* utresrc
*/
ACPI_STATUS
@@ -807,7 +771,7 @@ AcpiUtWalkAmlResources (
UINT8 *Aml,
ACPI_SIZE AmlLength,
ACPI_WALK_AML_CALLBACK UserFunction,
- void *Context);
+ void **Context);
ACPI_STATUS
AcpiUtValidateResource (
@@ -838,6 +802,51 @@ AcpiUtGetResourceEndTag (
/*
+ * utstring - String and character utilities
+ */
+void
+AcpiUtStrupr (
+ char *SrcString);
+
+void
+AcpiUtStrlwr (
+ char *SrcString);
+
+int
+AcpiUtStricmp (
+ char *String1,
+ char *String2);
+
+ACPI_STATUS
+AcpiUtStrtoul64 (
+ char *String,
+ UINT32 Base,
+ UINT64 *RetInteger);
+
+void
+AcpiUtPrintString (
+ char *String,
+ UINT8 MaxLength);
+
+void
+UtConvertBackslashes (
+ char *Pathname);
+
+BOOLEAN
+AcpiUtValidAcpiName (
+ UINT32 Name);
+
+BOOLEAN
+AcpiUtValidAcpiChar (
+ char Character,
+ UINT32 Position);
+
+void
+AcpiUtRepairName (
+ char *Name);
+
+
+/*
* utmutex - mutex support
*/
ACPI_STATUS
diff --git a/sys/contrib/dev/acpica/include/amlcode.h b/sys/contrib/dev/acpica/include/amlcode.h
index f778bb0..66af4c2 100644
--- a/sys/contrib/dev/acpica/include/amlcode.h
+++ b/sys/contrib/dev/acpica/include/amlcode.h
@@ -7,7 +7,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/amlresrc.h b/sys/contrib/dev/acpica/include/amlresrc.h
index 2202bb9..8e68559 100644
--- a/sys/contrib/dev/acpica/include/amlresrc.h
+++ b/sys/contrib/dev/acpica/include/amlresrc.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/platform/acenv.h b/sys/contrib/dev/acpica/include/platform/acenv.h
index 4c23f30..dea4db2 100644
--- a/sys/contrib/dev/acpica/include/platform/acenv.h
+++ b/sys/contrib/dev/acpica/include/platform/acenv.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -300,7 +300,7 @@
*/
#ifdef ACPI_USE_SYSTEM_CLIBRARY
-/* Use the standard C library headers. We want to keep these to a minimum */
+/* Use the standard C library headers. We want to keep these to a minimum. */
#ifdef ACPI_USE_STANDARD_HEADERS
diff --git a/sys/contrib/dev/acpica/include/platform/acfreebsd.h b/sys/contrib/dev/acpica/include/platform/acfreebsd.h
index d7aa7ed..6b32ce7 100644
--- a/sys/contrib/dev/acpica/include/platform/acfreebsd.h
+++ b/sys/contrib/dev/acpica/include/platform/acfreebsd.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/platform/acgcc.h b/sys/contrib/dev/acpica/include/platform/acgcc.h
index d2eafff..1662a9b 100644
--- a/sys/contrib/dev/acpica/include/platform/acgcc.h
+++ b/sys/contrib/dev/acpica/include/platform/acgcc.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,7 +59,7 @@
/*
* Some compilers complain about unused variables. Sometimes we don't want to
* use all the variables (for example, _AcpiModuleName). This allows us
- * to to tell the compiler warning in a per-variable manner that a variable
+ * to tell the compiler warning in a per-variable manner that a variable
* is unused.
*/
#define ACPI_UNUSED_VAR __attribute__ ((unused))
diff --git a/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c b/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
index cf6382b..c18d65c 100644
--- a/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
+++ b/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -84,6 +84,10 @@ AeTableOverride (
typedef void* (*PTHREAD_CALLBACK) (void *);
+/* Buffer used by AcpiOsVprintf */
+
+#define ACPI_VPRINTF_BUFFER_SIZE 512
+
/* Apple-specific */
#ifdef __APPLE__
@@ -268,7 +272,8 @@ AcpiOsRedirectOutput (
*
* RETURN: None
*
- * DESCRIPTION: Formatted output
+ * DESCRIPTION: Formatted output. Note: very similar to AcpiOsVprintf
+ * (performance), changes should be tracked in both functions.
*
*****************************************************************************/
@@ -278,11 +283,36 @@ AcpiOsPrintf (
...)
{
va_list Args;
+ UINT8 Flags;
+
+
+ Flags = AcpiGbl_DbOutputFlags;
+ if (Flags & ACPI_DB_REDIRECTABLE_OUTPUT)
+ {
+ /* Output is directable to either a file (if open) or the console */
+
+ if (AcpiGbl_DebugFile)
+ {
+ /* Output file is open, send the output there */
+
+ va_start (Args, Fmt);
+ vfprintf (AcpiGbl_DebugFile, Fmt, Args);
+ va_end (Args);
+ }
+ else
+ {
+ /* No redirection, send output to console (once only!) */
+ Flags |= ACPI_DB_CONSOLE_OUTPUT;
+ }
+ }
- va_start (Args, Fmt);
- AcpiOsVprintf (Fmt, Args);
- va_end (Args);
+ if (Flags & ACPI_DB_CONSOLE_OUTPUT)
+ {
+ va_start (Args, Fmt);
+ vfprintf (AcpiGbl_OutputFile, Fmt, Args);
+ va_end (Args);
+ }
}
@@ -295,7 +325,9 @@ AcpiOsPrintf (
*
* RETURN: None
*
- * DESCRIPTION: Formatted output with argument list pointer
+ * DESCRIPTION: Formatted output with argument list pointer. Note: very
+ * similar to AcpiOsPrintf, changes should be tracked in both
+ * functions.
*
*****************************************************************************/
@@ -305,7 +337,20 @@ AcpiOsVprintf (
va_list Args)
{
UINT8 Flags;
+ char Buffer[ACPI_VPRINTF_BUFFER_SIZE];
+
+ /*
+ * We build the output string in a local buffer because we may be
+ * outputting the buffer twice. Using vfprintf is problematic because
+ * some implementations modify the args pointer/structure during
+ * execution. Thus, we use the local buffer for portability.
+ *
+ * Note: Since this module is intended for use by the various ACPICA
+ * utilities/applications, we can safely declare the buffer on the stack.
+ * Also, This function is used for relatively small error messages only.
+ */
+ vsnprintf (Buffer, ACPI_VPRINTF_BUFFER_SIZE, Fmt, Args);
Flags = AcpiGbl_DbOutputFlags;
if (Flags & ACPI_DB_REDIRECTABLE_OUTPUT)
@@ -316,7 +361,7 @@ AcpiOsVprintf (
{
/* Output file is open, send the output there */
- vfprintf (AcpiGbl_DebugFile, Fmt, Args);
+ fputs (Buffer, AcpiGbl_DebugFile);
}
else
{
@@ -328,7 +373,7 @@ AcpiOsVprintf (
if (Flags & ACPI_DB_CONSOLE_OUTPUT)
{
- vfprintf (AcpiGbl_OutputFile, Fmt, Args);
+ fputs (Buffer, AcpiGbl_OutputFile);
}
}
@@ -626,7 +671,7 @@ AcpiOsDeleteSemaphore (
*
* PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore
* Units - How many units to wait for
- * Timeout - How long to wait
+ * MsecTimeout - How long to wait (milliseconds)
*
* RETURN: Status
*
@@ -638,11 +683,14 @@ ACPI_STATUS
AcpiOsWaitSemaphore (
ACPI_HANDLE Handle,
UINT32 Units,
- UINT16 Timeout)
+ UINT16 MsecTimeout)
{
ACPI_STATUS Status = AE_OK;
sem_t *Sem = (sem_t *) Handle;
- struct timespec T;
+#ifndef ACPI_USE_ALTERNATE_TIMEOUT
+ struct timespec Time;
+ int RetVal;
+#endif
if (!Sem)
@@ -650,7 +698,7 @@ AcpiOsWaitSemaphore (
return (AE_BAD_PARAMETER);
}
- switch (Timeout)
+ switch (MsecTimeout)
{
/*
* No Wait:
@@ -677,37 +725,71 @@ AcpiOsWaitSemaphore (
}
break;
- /* Wait with Timeout */
+ /* Wait with MsecTimeout */
default:
- T.tv_sec = Timeout / 1000;
- T.tv_nsec = (Timeout - (T.tv_sec * 1000)) * 1000000;
-
#ifdef ACPI_USE_ALTERNATE_TIMEOUT
/*
* Alternate timeout mechanism for environments where
* sem_timedwait is not available or does not work properly.
*/
- while (Timeout)
+ while (MsecTimeout)
{
if (sem_trywait (Sem) == 0)
{
/* Got the semaphore */
return (AE_OK);
}
- usleep (1000); /* one millisecond */
- Timeout--;
+
+ if (MsecTimeout >= 10)
+ {
+ MsecTimeout -= 10;
+ usleep (10 * ACPI_USEC_PER_MSEC); /* ten milliseconds */
+ }
+ else
+ {
+ MsecTimeout--;
+ usleep (ACPI_USEC_PER_MSEC); /* one millisecond */
+ }
}
Status = (AE_TIME);
#else
+ /*
+ * The interface to sem_timedwait is an absolute time, so we need to
+ * get the current time, then add in the millisecond Timeout value.
+ */
+ if (clock_gettime (CLOCK_REALTIME, &Time) == -1)
+ {
+ perror ("clock_gettime");
+ return (AE_TIME);
+ }
+
+ Time.tv_sec += (MsecTimeout / ACPI_MSEC_PER_SEC);
+ Time.tv_nsec += ((MsecTimeout % ACPI_MSEC_PER_SEC) * ACPI_NSEC_PER_MSEC);
+
+ /* Handle nanosecond overflow (field must be less than one second) */
+
+ if (Time.tv_nsec >= ACPI_NSEC_PER_SEC)
+ {
+ Time.tv_sec += (Time.tv_nsec / ACPI_NSEC_PER_SEC);
+ Time.tv_nsec = (Time.tv_nsec % ACPI_NSEC_PER_SEC);
+ }
+
+ while (((RetVal = sem_timedwait (Sem, &Time)) == -1) && (errno == EINTR))
+ {
+ continue;
+ }
- if (sem_timedwait (Sem, &T))
+ if (RetVal != 0)
{
+ if (errno != ETIMEDOUT)
+ {
+ perror ("sem_timedwait");
+ }
Status = (AE_TIME);
}
#endif
-
break;
}
@@ -884,12 +966,15 @@ AcpiOsSleep (
UINT64 milliseconds)
{
- sleep (milliseconds / 1000); /* Sleep for whole seconds */
+ /* Sleep for whole seconds */
+
+ sleep (milliseconds / ACPI_MSEC_PER_SEC);
/*
- * Arg to usleep() must be less than 1,000,000 (1 second)
+ * Sleep for remaining microseconds.
+ * Arg to usleep() is in usecs and must be less than 1,000,000 (1 second).
*/
- usleep ((milliseconds % 1000) * 1000); /* Sleep for remaining usecs */
+ usleep ((milliseconds % ACPI_MSEC_PER_SEC) * ACPI_USEC_PER_MSEC);
}
@@ -912,11 +997,14 @@ AcpiOsGetTimer (
struct timeval time;
+ /* This timer has sufficient resolution for user-space application code */
+
gettimeofday (&time, NULL);
- /* Seconds * 10^7 = 100ns(10^-7), Microseconds(10^-6) * 10^1 = 100ns */
+ /* (Seconds * 10^7 = 100ns(10^-7)) + (Microseconds(10^-6) * 10^1 = 100ns) */
- return (((UINT64) time.tv_sec * 10000000) + ((UINT64) time.tv_usec * 10));
+ return (((UINT64) time.tv_sec * ACPI_100NSEC_PER_SEC) +
+ ((UINT64) time.tv_usec * ACPI_100NSEC_PER_USEC));
}
diff --git a/sys/contrib/octeon-sdk/cvmx-helper-board.c b/sys/contrib/octeon-sdk/cvmx-helper-board.c
index 8d2b0bd..d97813e 100644
--- a/sys/contrib/octeon-sdk/cvmx-helper-board.c
+++ b/sys/contrib/octeon-sdk/cvmx-helper-board.c
@@ -1394,6 +1394,21 @@ int __cvmx_helper_board_hardware_enable(int interface)
}
}
}
+#if defined(OCTEON_VENDOR_UBIQUITI)
+ else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_UBIQUITI_E100)
+ {
+ /* Configure ASX cloks for all ports on interface 0. */
+ if (interface == 0)
+ {
+ int port;
+
+ for (port = 0; port < 3; port++) {
+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 16);
+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 0);
+ }
+ }
+ }
+#endif
return 0;
}
diff --git a/sys/dev/acpi_support/acpi_asus_wmi.c b/sys/dev/acpi_support/acpi_asus_wmi.c
index 9e2a498..54a2893 100644
--- a/sys/dev/acpi_support/acpi_asus_wmi.c
+++ b/sys/dev/acpi_support/acpi_asus_wmi.c
@@ -304,7 +304,8 @@ static device_method_t acpi_asus_wmi_methods[] = {
DEVMETHOD(device_probe, acpi_asus_wmi_probe),
DEVMETHOD(device_attach, acpi_asus_wmi_attach),
DEVMETHOD(device_detach, acpi_asus_wmi_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t acpi_asus_wmi_driver = {
diff --git a/sys/dev/acpi_support/acpi_fujitsu.c b/sys/dev/acpi_support/acpi_fujitsu.c
index 2455b50..6f96bc5 100644
--- a/sys/dev/acpi_support/acpi_fujitsu.c
+++ b/sys/dev/acpi_support/acpi_fujitsu.c
@@ -154,7 +154,8 @@ static device_method_t acpi_fujitsu_methods[] = {
DEVMETHOD(device_detach, acpi_fujitsu_detach),
DEVMETHOD(device_suspend, acpi_fujitsu_suspend),
DEVMETHOD(device_resume, acpi_fujitsu_resume),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t acpi_fujitsu_driver = {
diff --git a/sys/dev/acpi_support/acpi_hp.c b/sys/dev/acpi_support/acpi_hp.c
index edc04b7..c190166 100644
--- a/sys/dev/acpi_support/acpi_hp.c
+++ b/sys/dev/acpi_support/acpi_hp.c
@@ -324,7 +324,8 @@ static device_method_t acpi_hp_methods[] = {
DEVMETHOD(device_probe, acpi_hp_probe),
DEVMETHOD(device_attach, acpi_hp_attach),
DEVMETHOD(device_detach, acpi_hp_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t acpi_hp_driver = {
diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c
index 46a985e..4160112 100644
--- a/sys/dev/acpi_support/acpi_ibm.c
+++ b/sys/dev/acpi_support/acpi_ibm.c
@@ -303,7 +303,7 @@ static device_method_t acpi_ibm_methods[] = {
DEVMETHOD(device_detach, acpi_ibm_detach),
DEVMETHOD(device_resume, acpi_ibm_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_ibm_driver = {
diff --git a/sys/dev/acpi_support/acpi_panasonic.c b/sys/dev/acpi_support/acpi_panasonic.c
index ad8b239..2542b0c 100644
--- a/sys/dev/acpi_support/acpi_panasonic.c
+++ b/sys/dev/acpi_support/acpi_panasonic.c
@@ -118,7 +118,7 @@ static device_method_t acpi_panasonic_methods[] = {
DEVMETHOD(device_detach, acpi_panasonic_detach),
DEVMETHOD(device_shutdown, acpi_panasonic_shutdown),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_panasonic_driver = {
diff --git a/sys/dev/acpi_support/acpi_sony.c b/sys/dev/acpi_support/acpi_sony.c
index 2a0d40e..95e7b4f 100644
--- a/sys/dev/acpi_support/acpi_sony.c
+++ b/sys/dev/acpi_support/acpi_sony.c
@@ -95,7 +95,7 @@ static device_method_t acpi_sony_methods[] = {
DEVMETHOD(device_attach, acpi_sony_attach),
DEVMETHOD(device_detach, acpi_sony_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_sony_driver = {
diff --git a/sys/dev/acpi_support/acpi_toshiba.c b/sys/dev/acpi_support/acpi_toshiba.c
index 343d3ae..9e3dc5b 100644
--- a/sys/dev/acpi_support/acpi_toshiba.c
+++ b/sys/dev/acpi_support/acpi_toshiba.c
@@ -172,7 +172,7 @@ static device_method_t acpi_toshiba_methods[] = {
DEVMETHOD(device_attach, acpi_toshiba_attach),
DEVMETHOD(device_detach, acpi_toshiba_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_toshiba_driver = {
@@ -190,7 +190,7 @@ static device_method_t acpi_toshiba_video_methods[] = {
DEVMETHOD(device_probe, acpi_toshiba_video_probe),
DEVMETHOD(device_attach, acpi_toshiba_video_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_toshiba_video_driver = {
diff --git a/sys/dev/acpica/Osd/OsdSchedule.c b/sys/dev/acpica/Osd/OsdSchedule.c
index 6d517cb..4afcec5 100644
--- a/sys/dev/acpica/Osd/OsdSchedule.c
+++ b/sys/dev/acpica/Osd/OsdSchedule.c
@@ -181,12 +181,13 @@ ACPI_STATUS
AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
void *Context)
{
+ ACPI_STATUS status;
int pri;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
if (Function == NULL)
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
switch (Type) {
case OSL_GPE_HANDLER:
@@ -208,10 +209,11 @@ AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
pri = 0;
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- return_ACPI_STATUS (acpi_task_enqueue(pri, Function, Context));
+ status = acpi_task_enqueue(pri, Function, Context);
+ return_ACPI_STATUS(status);
}
void
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index e2f8c1c..f0c750f 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -217,7 +217,7 @@ static device_method_t acpi_methods[] = {
/* ISA emulation */
DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_driver = {
@@ -613,7 +613,9 @@ acpi_attach(device_t dev)
/* Probe all supported sleep states. */
acpi_sleep_states[ACPI_STATE_S0] = TRUE;
for (state = ACPI_STATE_S1; state < ACPI_S_STATE_COUNT; state++)
- if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB)))
+ if (ACPI_SUCCESS(AcpiEvaluateObject(ACPI_ROOT_OBJECT,
+ __DECONST(char *, AcpiGbl_SleepStateNames[state]), NULL, NULL)) &&
+ ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB)))
acpi_sleep_states[state] = TRUE;
/*
@@ -2657,6 +2659,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
{
register_t intr;
ACPI_STATUS status;
+ ACPI_EVENT_STATUS power_button_status;
enum acpi_sleep_state slp_state;
int sleep_result;
@@ -2742,7 +2745,44 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
if (state != ACPI_STATE_S1) {
sleep_result = acpi_sleep_machdep(sc, state);
acpi_wakeup_machdep(sc, state, sleep_result, 0);
+
+ /*
+ * XXX According to ACPI specification SCI_EN bit should be restored
+ * by ACPI platform (BIOS, firmware) to its pre-sleep state.
+ * Unfortunately some BIOSes fail to do that and that leads to
+ * unexpected and serious consequences during wake up like a system
+ * getting stuck in SMI handlers.
+ * This hack is picked up from Linux, which claims that it follows
+ * Windows behavior.
+ */
+ if (sleep_result == 1 && state != ACPI_STATE_S4)
+ AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, ACPI_ENABLE_EVENT);
+
AcpiLeaveSleepStatePrep(state);
+
+ if (sleep_result == 1 && state == ACPI_STATE_S3) {
+ /*
+ * Prevent mis-interpretation of the wakeup by power button
+ * as a request for power off.
+ * Ideally we should post an appropriate wakeup event,
+ * perhaps using acpi_event_power_button_wake or alike.
+ *
+ * Clearing of power button status after wakeup is mandated
+ * by ACPI specification in section "Fixed Power Button".
+ *
+ * XXX As of ACPICA 20121114 AcpiGetEventStatus provides
+ * status as 0/1 corressponding to inactive/active despite
+ * its type being ACPI_EVENT_STATUS. In other words,
+ * we should not test for ACPI_EVENT_FLAG_SET for time being.
+ */
+ if (ACPI_SUCCESS(AcpiGetEventStatus(ACPI_EVENT_POWER_BUTTON,
+ &power_button_status)) && power_button_status != 0) {
+ AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
+ device_printf(sc->acpi_dev,
+ "cleared fixed power button status\n");
+ }
+ }
+
intr_restore(intr);
/* call acpi_wakeup_machdep() again with interrupt enabled */
diff --git a/sys/dev/acpica/acpi_acad.c b/sys/dev/acpica/acpi_acad.c
index 8153abc..4c9dc19 100644
--- a/sys/dev/acpica/acpi_acad.c
+++ b/sys/dev/acpica/acpi_acad.c
@@ -74,7 +74,7 @@ static device_method_t acpi_acad_methods[] = {
DEVMETHOD(device_probe, acpi_acad_probe),
DEVMETHOD(device_attach, acpi_acad_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_acad_driver = {
diff --git a/sys/dev/acpica/acpi_button.c b/sys/dev/acpica/acpi_button.c
index d1f774a..72bf5b1 100644
--- a/sys/dev/acpica/acpi_button.c
+++ b/sys/dev/acpica/acpi_button.c
@@ -79,8 +79,7 @@ static device_method_t acpi_button_methods[] = {
DEVMETHOD(device_suspend, acpi_button_suspend),
DEVMETHOD(device_shutdown, acpi_button_suspend),
DEVMETHOD(device_resume, acpi_button_resume),
-
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_button_driver = {
diff --git a/sys/dev/acpica/acpi_cmbat.c b/sys/dev/acpica/acpi_cmbat.c
index ba44da8..be57a32 100644
--- a/sys/dev/acpica/acpi_cmbat.c
+++ b/sys/dev/acpica/acpi_cmbat.c
@@ -99,7 +99,7 @@ static device_method_t acpi_cmbat_methods[] = {
DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bif),
DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_cmbat_driver = {
diff --git a/sys/dev/acpica/acpi_dock.c b/sys/dev/acpica/acpi_dock.c
index b184053..d27b4bd 100644
--- a/sys/dev/acpica/acpi_dock.c
+++ b/sys/dev/acpica/acpi_dock.c
@@ -521,7 +521,7 @@ static device_method_t acpi_dock_methods[] = {
DEVMETHOD(device_probe, acpi_dock_probe),
DEVMETHOD(device_attach, acpi_dock_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_dock_driver = {
diff --git a/sys/dev/acpica/acpi_ec.c b/sys/dev/acpica/acpi_ec.c
index 00a3073..6e2f0dd 100644
--- a/sys/dev/acpica/acpi_ec.c
+++ b/sys/dev/acpica/acpi_ec.c
@@ -253,7 +253,7 @@ static device_method_t acpi_ec_methods[] = {
DEVMETHOD(acpi_ec_read, acpi_ec_read_method),
DEVMETHOD(acpi_ec_write, acpi_ec_write_method),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_ec_driver = {
diff --git a/sys/dev/acpica/acpi_hpet.c b/sys/dev/acpica/acpi_hpet.c
index 4b0c356..c00bda4 100644
--- a/sys/dev/acpica/acpi_hpet.c
+++ b/sys/dev/acpica/acpi_hpet.c
@@ -849,7 +849,7 @@ static device_method_t hpet_methods[] = {
DEVMETHOD(bus_remap_intr, hpet_remap_intr),
#endif
- {0, 0}
+ DEVMETHOD_END
};
static driver_t hpet_driver = {
diff --git a/sys/dev/acpica/acpi_lid.c b/sys/dev/acpica/acpi_lid.c
index d84e3c9..dcdd2e6 100644
--- a/sys/dev/acpica/acpi_lid.c
+++ b/sys/dev/acpica/acpi_lid.c
@@ -69,7 +69,7 @@ static device_method_t acpi_lid_methods[] = {
DEVMETHOD(device_suspend, acpi_lid_suspend),
DEVMETHOD(device_resume, acpi_lid_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_lid_driver = {
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index 185731a..39fba88 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -94,7 +94,7 @@ static device_method_t acpi_pci_methods[] = {
/* PCI interface */
DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t pci_devclass;
diff --git a/sys/dev/acpica/acpi_pci_link.c b/sys/dev/acpica/acpi_pci_link.c
index ba03d72..1a1ae4d 100644
--- a/sys/dev/acpica/acpi_pci_link.c
+++ b/sys/dev/acpica/acpi_pci_link.c
@@ -1097,7 +1097,7 @@ static device_method_t acpi_pci_link_methods[] = {
DEVMETHOD(device_attach, acpi_pci_link_attach),
DEVMETHOD(device_resume, acpi_pci_link_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_pci_link_driver = {
diff --git a/sys/dev/acpica/acpi_pcib.c b/sys/dev/acpica/acpi_pcib.c
index 1b26b4f..1a42d74 100644
--- a/sys/dev/acpica/acpi_pcib.c
+++ b/sys/dev/acpica/acpi_pcib.c
@@ -129,7 +129,8 @@ prt_attach_devices(ACPI_PCI_ROUTING_TABLE *entry, void *arg)
int
acpi_pcib_attach(device_t dev, ACPI_BUFFER *prt, int busno)
{
- ACPI_STATUS status;
+ ACPI_STATUS status;
+ int error;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -168,7 +169,8 @@ acpi_pcib_attach(device_t dev, ACPI_BUFFER *prt, int busno)
*/
prt_walk_table(prt, prt_attach_devices, dev);
- return_VALUE (bus_generic_attach(dev));
+ error = bus_generic_attach(dev);
+ return_VALUE(error);
}
static void
@@ -273,7 +275,7 @@ acpi_pcib_route_interrupt(device_t pcib, device_t dev, int pin,
out:
ACPI_SERIAL_END(pcib);
- return_VALUE (interrupt);
+ return_VALUE(interrupt);
}
int
@@ -285,4 +287,3 @@ acpi_pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate)
acpi_device_pwr_for_sleep(acpi_dev, dev, pstate);
return (0);
}
-
diff --git a/sys/dev/acpica/acpi_pcib_pci.c b/sys/dev/acpica/acpi_pcib_pci.c
index 7dbccd6..de26a4a 100644
--- a/sys/dev/acpica/acpi_pcib_pci.c
+++ b/sys/dev/acpica/acpi_pcib_pci.c
@@ -83,7 +83,7 @@ static device_method_t acpi_pcib_pci_methods[] = {
DEVMETHOD(pcib_route_interrupt, acpi_pcib_pci_route_interrupt),
DEVMETHOD(pcib_power_for_sleep, acpi_pcib_power_for_sleep),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/sys/dev/acpica/acpi_perf.c b/sys/dev/acpica/acpi_perf.c
index 3f047cc..d95cc79 100644
--- a/sys/dev/acpica/acpi_perf.c
+++ b/sys/dev/acpica/acpi_perf.c
@@ -122,7 +122,8 @@ static device_method_t acpi_perf_methods[] = {
DEVMETHOD(cpufreq_drv_get, acpi_px_get),
DEVMETHOD(cpufreq_drv_type, acpi_px_type),
DEVMETHOD(cpufreq_drv_settings, acpi_px_settings),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t acpi_perf_driver = {
diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c
index ce6732f..0878d96 100644
--- a/sys/dev/acpica/acpi_resource.c
+++ b/sys/dev/acpica/acpi_resource.c
@@ -615,7 +615,7 @@ static device_method_t acpi_sysres_methods[] = {
DEVMETHOD(device_probe, acpi_sysres_probe),
DEVMETHOD(device_attach, acpi_sysres_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_sysres_driver = {
diff --git a/sys/dev/acpica/acpi_smbat.c b/sys/dev/acpica/acpi_smbat.c
index f83392f..dda5e75 100644
--- a/sys/dev/acpica/acpi_smbat.c
+++ b/sys/dev/acpica/acpi_smbat.c
@@ -89,7 +89,7 @@ static device_method_t acpi_smbat_methods[] = {
DEVMETHOD(acpi_batt_get_status, acpi_smbat_get_bst),
DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bif),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_smbat_driver = {
diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c
index baa8205..485da9e 100644
--- a/sys/dev/acpica/acpi_thermal.c
+++ b/sys/dev/acpica/acpi_thermal.c
@@ -152,7 +152,7 @@ static device_method_t acpi_tz_methods[] = {
DEVMETHOD(device_probe, acpi_tz_probe),
DEVMETHOD(device_attach, acpi_tz_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_tz_driver = {
@@ -509,15 +509,8 @@ acpi_tz_monitor(void *Context)
*/
newactive = TZ_ACTIVE_NONE;
for (i = TZ_NUMLEVELS - 1; i >= 0; i--) {
- if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i]) {
+ if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i])
newactive = i;
- if (sc->tz_active != newactive) {
- ACPI_VPRINT(sc->tz_dev,
- acpi_device_get_parent_softc(sc->tz_dev),
- "_AC%d: temperature %d.%d >= setpoint %d.%d\n", i,
- TZ_KELVTOC(temp), TZ_KELVTOC(sc->tz_zone.ac[i]));
- }
- }
}
/*
diff --git a/sys/dev/acpica/acpi_throttle.c b/sys/dev/acpica/acpi_throttle.c
index 40476e0..ca14215 100644
--- a/sys/dev/acpica/acpi_throttle.c
+++ b/sys/dev/acpica/acpi_throttle.c
@@ -114,7 +114,7 @@ static device_method_t acpi_throttle_methods[] = {
DEVMETHOD(cpufreq_drv_get, acpi_thr_get),
DEVMETHOD(cpufreq_drv_type, acpi_thr_type),
DEVMETHOD(cpufreq_drv_settings, acpi_thr_settings),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_throttle_driver = {
diff --git a/sys/dev/acpica/acpi_timer.c b/sys/dev/acpica/acpi_timer.c
index 9f61cd8..80e6d18 100644
--- a/sys/dev/acpica/acpi_timer.c
+++ b/sys/dev/acpica/acpi_timer.c
@@ -82,7 +82,7 @@ static device_method_t acpi_timer_methods[] = {
DEVMETHOD(device_probe, acpi_timer_probe),
DEVMETHOD(device_attach, acpi_timer_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_timer_driver = {
diff --git a/sys/dev/adlink/adlink.c b/sys/dev/adlink/adlink.c
index b625d26..4180f57 100644
--- a/sys/dev/adlink/adlink.c
+++ b/sys/dev/adlink/adlink.c
@@ -407,7 +407,8 @@ static device_method_t adlink_methods[] = {
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t adlink_driver = {
diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c
index 21c7ce6..9ec3992 100644
--- a/sys/dev/agp/agp_i810.c
+++ b/sys/dev/agp/agp_i810.c
@@ -2228,7 +2228,7 @@ agp_i830_chipset_flush(device_t dev)
bus_write_4(sc->sc_res[0], AGP_I830_HIC, hic | (1 << 31));
for (i = 0; i < 20000 /* 1 sec */; i++) {
hic = bus_read_4(sc->sc_res[0], AGP_I830_HIC);
- if ((hic & (1 << 31)) != 0)
+ if ((hic & (1 << 31)) == 0)
break;
DELAY(50);
}
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 5882c86..b17b9f3 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -114,8 +114,9 @@ static struct {
#define AHCI_Q_NOAA 512
#define AHCI_Q_NOCOUNT 1024
#define AHCI_Q_ALTSIG 2048
+#define AHCI_Q_NOMSI 4096
} ahci_ids[] = {
- {0x43801002, 0x00, "ATI IXP600", 0},
+ {0x43801002, 0x00, "ATI IXP600", AHCI_Q_NOMSI},
{0x43901002, 0x00, "ATI IXP700", 0},
{0x43911002, 0x00, "ATI IXP700", 0},
{0x43921002, 0x00, "ATI IXP700", 0},
@@ -634,6 +635,8 @@ ahci_setup_interrupt(device_t dev)
int i, msi = 1;
/* Process hints. */
+ if (ctlr->quirks & AHCI_Q_NOMSI)
+ msi = 0;
resource_int_value(device_get_name(dev),
device_get_unit(dev), "msi", &msi);
if (msi < 0)
diff --git a/sys/dev/altera/avgen/altera_avgen.c b/sys/dev/altera/avgen/altera_avgen.c
index a90b546..5429c9d 100644
--- a/sys/dev/altera/avgen/altera_avgen.c
+++ b/sys/dev/altera/avgen/altera_avgen.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2012 Robert N. M. Watson
+ * Copyright (c) 2012-2013 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$");
* system-on-chip bus environments would work fine with the same code.
*/
+devclass_t altera_avgen_devclass;
+
static d_mmap_t altera_avgen_mmap;
static d_read_t altera_avgen_read;
static d_write_t altera_avgen_write;
@@ -226,13 +228,6 @@ altera_avgen_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
return (0);
}
-static int
-altera_avgen_nexus_probe(device_t dev)
-{
-
- device_set_desc(dev, "Generic Altera Avalon device attachment");
- return (BUS_PROBE_DEFAULT);
-}
static int
altera_avgen_process_options(struct altera_avgen_softc *sc,
@@ -321,42 +316,14 @@ altera_avgen_process_options(struct altera_avgen_softc *sc,
return (0);
}
-static int
-altera_avgen_nexus_attach(device_t dev)
+int
+altera_avgen_attach(struct altera_avgen_softc *sc, const char *str_fileio,
+ const char *str_mmapio, const char *str_devname, int devunit)
{
- struct altera_avgen_softc *sc;
- const char *str_fileio, *str_mmapio;
- const char *str_devname;
+ device_t dev = sc->avg_dev;
char devname[SPECNAMELEN + 1];
- int devunit, error;
-
- sc = device_get_softc(dev);
- sc->avg_dev = dev;
- sc->avg_unit = device_get_unit(dev);
+ int error;
- /*
- * Query non-standard hints to find out what operations are permitted
- * on the device, and whether it is cached.
- */
- str_fileio = NULL;
- str_mmapio = NULL;
- str_devname = NULL;
- devunit = -1;
- sc->avg_width = 1;
- error = resource_int_value(device_get_name(dev), device_get_unit(dev),
- ALTERA_AVALON_STR_WIDTH, &sc->avg_width);
- if (error != 0 && error != ENOENT) {
- device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH);
- return (error);
- }
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio);
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio);
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname);
- (void)resource_int_value(device_get_name(dev), device_get_unit(dev),
- ALTERA_AVALON_STR_DEVUNIT, &devunit);
error = altera_avgen_process_options(sc, str_fileio, str_mmapio,
str_devname, devunit);
if (error)
@@ -374,25 +341,15 @@ altera_avgen_nexus_attach(device_t dev)
snprintf(devname, sizeof(devname), "%s%d", "avgen",
sc->avg_unit);
- /* Memory allocation and checking. */
- sc->avg_rid = 0;
- sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->avg_rid, RF_ACTIVE);
- if (sc->avg_res == NULL) {
- device_printf(dev, "couldn't map memory\n");
- return (ENXIO);
- }
if (rman_get_size(sc->avg_res) >= PAGE_SIZE || str_mmapio != NULL) {
if (rman_get_size(sc->avg_res) % PAGE_SIZE != 0) {
device_printf(dev,
"memory region not even multiple of page size\n");
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
if (rman_get_start(sc->avg_res) % PAGE_SIZE != 0) {
device_printf(dev, "memory region not page-aligned\n");
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
}
@@ -409,43 +366,16 @@ altera_avgen_nexus_attach(device_t dev)
GID_WHEEL, S_IRUSR | S_IWUSR, str_devname);
if (sc->avg_cdev == NULL) {
device_printf(sc->avg_dev, "%s: make_dev failed\n", __func__);
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
/* XXXRW: Slight race between make_dev(9) and here. */
sc->avg_cdev->si_drv1 = sc;
return (0);
-
-error:
- bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
- return (error);
}
-static int
-altera_avgen_nexus_detach(device_t dev)
+void
+altera_avgen_detach(struct altera_avgen_softc *sc)
{
- struct altera_avgen_softc *sc;
- sc = device_get_softc(dev);
destroy_dev(sc->avg_cdev);
- bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
- return (0);
}
-
-static device_method_t altera_avgen_nexus_methods[] = {
- DEVMETHOD(device_probe, altera_avgen_nexus_probe),
- DEVMETHOD(device_attach, altera_avgen_nexus_attach),
- DEVMETHOD(device_detach, altera_avgen_nexus_detach),
- { 0, 0 }
-};
-
-static driver_t altera_avgen_nexus_driver = {
- "altera_avgen",
- altera_avgen_nexus_methods,
- sizeof(struct altera_avgen_softc),
-};
-
-static devclass_t altera_avgen_devclass;
-
-DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, altera_avgen_devclass,
- 0, 0);
diff --git a/sys/dev/altera/avgen/altera_avgen.h b/sys/dev/altera/avgen/altera_avgen.h
index c8c7947..fb25a3c 100644
--- a/sys/dev/altera/avgen/altera_avgen.h
+++ b/sys/dev/altera/avgen/altera_avgen.h
@@ -77,7 +77,11 @@ struct altera_avgen_softc {
/*
* Driver setup routines from the bus attachment/teardown.
*/
-int altera_avgen_attach(struct altera_avgen_softc *sc);
+int altera_avgen_attach(struct altera_avgen_softc *sc,
+ const char *str_fileio, const char *str_mmapio,
+ const char *str_devname, int devunit);
void altera_avgen_detach(struct altera_avgen_softc *sc);
+extern devclass_t altera_avgen_devclass;
+
#endif /* _DEV_ALTERA_AVALON_H_ */
diff --git a/sys/dev/altera/avgen/altera_avgen_fdt.c b/sys/dev/altera/avgen/altera_avgen_fdt.c
new file mode 100644
index 0000000..2762ff4
--- /dev/null
+++ b/sys/dev/altera/avgen/altera_avgen_fdt.c
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * 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.
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/vm.h>
+
+#include <vm/vm.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/altera/avgen/altera_avgen.h>
+
+static int
+altera_avgen_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "sri-cambridge,avgen")) {
+ device_set_desc(dev, "Generic Altera Avalon device attachment");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+altera_avgen_fdt_attach(device_t dev)
+{
+ struct altera_avgen_softc *sc;
+ char *str_fileio, *str_mmapio;
+ char *str_devname;
+ phandle_t node;
+ pcell_t cell;
+ int devunit, error;
+
+ sc = device_get_softc(dev);
+ sc->avg_dev = dev;
+ sc->avg_unit = device_get_unit(dev);
+
+ /*
+ * Query driver-specific OpenFirmware properties to determine how to
+ * expose the device via /dev.
+ */
+ str_fileio = NULL;
+ str_mmapio = NULL;
+ str_devname = NULL;
+ devunit = -1;
+ sc->avg_width = 1;
+ node = ofw_bus_get_node(dev);
+ if (OF_getprop(node, "sri-cambridge,width", &cell, sizeof(cell)) > 0)
+ sc->avg_width = cell;
+ (void)OF_getprop_alloc(node, "sri-cambridge,fileio", sizeof(char),
+ (void **)&str_fileio);
+ (void)OF_getprop_alloc(node, "sri-cambridge,mmapio", sizeof(char),
+ (void **)&str_mmapio);
+ (void)OF_getprop_alloc(node, "sri-cambridge,devname", sizeof(char),
+ (void **)&str_devname);
+ if (OF_getprop(node, "sri-cambridge,devunit", &cell, sizeof(cell)) > 0)
+ devunit = cell;
+
+ /* Memory allocation and checking. */
+ sc->avg_rid = 0;
+ sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->avg_rid, RF_ACTIVE);
+ if (sc->avg_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname,
+ devunit);
+ if (error != 0)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
+ sc->avg_res);
+ if (str_fileio != NULL)
+ free(str_fileio, M_OFWPROP);
+ if (str_mmapio != NULL)
+ free(str_mmapio, M_OFWPROP);
+ if (str_devname != NULL)
+ free(str_devname, M_OFWPROP);
+ return (error);
+}
+
+static int
+altera_avgen_fdt_detach(device_t dev)
+{
+ struct altera_avgen_softc *sc;
+
+ sc = device_get_softc(dev);
+ altera_avgen_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
+ return (0);
+}
+
+static device_method_t altera_avgen_fdt_methods[] = {
+ DEVMETHOD(device_probe, altera_avgen_fdt_probe),
+ DEVMETHOD(device_attach, altera_avgen_fdt_attach),
+ DEVMETHOD(device_detach, altera_avgen_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t altera_avgen_fdt_driver = {
+ "altera_avgen",
+ altera_avgen_fdt_methods,
+ sizeof(struct altera_avgen_softc),
+};
+
+DRIVER_MODULE(avgen, simplebus, altera_avgen_fdt_driver,
+ altera_avgen_devclass, 0, 0);
diff --git a/sys/dev/altera/avgen/altera_avgen_nexus.c b/sys/dev/altera/avgen/altera_avgen_nexus.c
new file mode 100644
index 0000000..d0e4f9b
--- /dev/null
+++ b/sys/dev/altera/avgen/altera_avgen_nexus.c
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * 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.
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/vm.h>
+
+#include <vm/vm.h>
+
+#include <dev/altera/avgen/altera_avgen.h>
+
+static int
+altera_avgen_nexus_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Generic Altera Avalon device attachment");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+altera_avgen_nexus_attach(device_t dev)
+{
+ struct altera_avgen_softc *sc;
+ const char *str_fileio, *str_mmapio;
+ const char *str_devname;
+ int devunit, error;
+
+ sc = device_get_softc(dev);
+ sc->avg_dev = dev;
+ sc->avg_unit = device_get_unit(dev);
+
+ /*
+ * Query non-standard hints to find out what operations are permitted
+ * on the device, and whether it is cached.
+ */
+ str_fileio = NULL;
+ str_mmapio = NULL;
+ str_devname = NULL;
+ devunit = -1;
+ sc->avg_width = 1;
+ error = resource_int_value(device_get_name(dev), device_get_unit(dev),
+ ALTERA_AVALON_STR_WIDTH, &sc->avg_width);
+ if (error != 0 && error != ENOENT) {
+ device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH);
+ return (error);
+ }
+ (void)resource_string_value(device_get_name(dev),
+ device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio);
+ (void)resource_string_value(device_get_name(dev),
+ device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio);
+ (void)resource_string_value(device_get_name(dev),
+ device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname);
+ (void)resource_int_value(device_get_name(dev), device_get_unit(dev),
+ ALTERA_AVALON_STR_DEVUNIT, &devunit);
+
+ /* Memory allocation and checking. */
+ sc->avg_rid = 0;
+ sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->avg_rid, RF_ACTIVE);
+ if (sc->avg_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname,
+ devunit);
+ if (error != 0)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
+ sc->avg_res);
+ return (error);
+}
+
+static int
+altera_avgen_nexus_detach(device_t dev)
+{
+ struct altera_avgen_softc *sc;
+
+ sc = device_get_softc(dev);
+ altera_avgen_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
+ return (0);
+}
+
+static device_method_t altera_avgen_nexus_methods[] = {
+ DEVMETHOD(device_probe, altera_avgen_nexus_probe),
+ DEVMETHOD(device_attach, altera_avgen_nexus_attach),
+ DEVMETHOD(device_detach, altera_avgen_nexus_detach),
+ { 0, 0 }
+};
+
+static driver_t altera_avgen_nexus_driver = {
+ "altera_avgen",
+ altera_avgen_nexus_methods,
+ sizeof(struct altera_avgen_softc),
+};
+
+DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, altera_avgen_devclass,
+ 0, 0);
diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart.h b/sys/dev/altera/jtag_uart/altera_jtag_uart.h
index 1ff3bcb..5b5b29f 100644
--- a/sys/dev/altera/jtag_uart/altera_jtag_uart.h
+++ b/sys/dev/altera/jtag_uart/altera_jtag_uart.h
@@ -194,4 +194,6 @@ extern u_int aju_cons_jtag_missed;
int altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc);
void altera_jtag_uart_detach(struct altera_jtag_uart_softc *sc);
+extern devclass_t altera_jtag_uart_devclass;
+
#endif /* _DEV_ALTERA_JTAG_UART_H_ */
diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
index 679ebe2..ae84597 100644
--- a/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
+++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
@@ -32,6 +32,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/endian.h>
#include <sys/kdb.h>
@@ -46,6 +47,8 @@ __FBSDID("$FreeBSD$");
#include <dev/altera/jtag_uart/altera_jtag_uart.h>
+devclass_t altera_jtag_uart_devclass;
+
/*
* One-byte buffer as we can't check whether the UART is readable without
* actually reading from it, synchronised by a spinlock; this lock also
diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c
new file mode 100644
index 0000000..47f39a4
--- /dev/null
+++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * 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.
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/jtag_uart/altera_jtag_uart.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * FDT bus attachment for Altera JTAG UARTs.
+ */
+static int
+altera_jtag_uart_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "altera,jtag_uart-11_0")) {
+ device_set_desc(dev, "Altera JTAG UART");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+altera_jtag_uart_fdt_attach(device_t dev)
+{
+ struct altera_jtag_uart_softc *sc;
+ int error;
+
+ error = 0;
+ sc = device_get_softc(dev);
+ sc->ajus_dev = dev;
+ sc->ajus_unit = device_get_unit(dev);
+ sc->ajus_mem_rid = 0;
+ sc->ajus_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->ajus_mem_rid, RF_ACTIVE);
+ if (sc->ajus_mem_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ error = ENXIO;
+ goto out;
+ }
+
+ /*
+ * Interrupt support is optional -- if we can't allocate an IRQ, then
+ * we fall back on polling.
+ */
+ sc->ajus_irq_rid = 0;
+ sc->ajus_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &sc->ajus_irq_rid, RF_ACTIVE | RF_SHAREABLE);
+ if (sc->ajus_irq_res == NULL)
+ device_printf(dev,
+ "IRQ unavailable; selecting polled operation\n");
+ error = altera_jtag_uart_attach(sc);
+out:
+ if (error) {
+ if (sc->ajus_irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ sc->ajus_irq_rid, sc->ajus_irq_res);
+ if (sc->ajus_mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->ajus_mem_rid, sc->ajus_mem_res);
+ }
+ return (error);
+}
+
+static int
+altera_jtag_uart_fdt_detach(device_t dev)
+{
+ struct altera_jtag_uart_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc->ajus_mem_res != NULL, ("%s: resources not allocated",
+ __func__));
+
+ altera_jtag_uart_detach(sc);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->ajus_irq_rid,
+ sc->ajus_irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->ajus_mem_rid,
+ sc->ajus_mem_res);
+ return (0);
+}
+
+static device_method_t altera_jtag_uart_fdt_methods[] = {
+ DEVMETHOD(device_probe, altera_jtag_uart_fdt_probe),
+ DEVMETHOD(device_attach, altera_jtag_uart_fdt_attach),
+ DEVMETHOD(device_detach, altera_jtag_uart_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t altera_jtag_uart_fdt_driver = {
+ "altera_jtag_uart",
+ altera_jtag_uart_fdt_methods,
+ sizeof(struct altera_jtag_uart_softc),
+};
+
+DRIVER_MODULE(altera_jtag_uart, simplebus, altera_jtag_uart_fdt_driver,
+ altera_jtag_uart_devclass, 0, 0);
diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
index 2592249..2fe772a 100644
--- a/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
+++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
@@ -137,7 +137,5 @@ static driver_t altera_jtag_uart_nexus_driver = {
sizeof(struct altera_jtag_uart_softc),
};
-static devclass_t altera_jtag_uart_devclass;
-
DRIVER_MODULE(altera_jtag_uart, nexus, altera_jtag_uart_nexus_driver,
altera_jtag_uart_devclass, 0, 0);
diff --git a/sys/dev/altera/sdcard/altera_sdcard.c b/sys/dev/altera/sdcard/altera_sdcard.c
index 4572206..f64b9c5 100644
--- a/sys/dev/altera/sdcard/altera_sdcard.c
+++ b/sys/dev/altera/sdcard/altera_sdcard.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
* 3. Handle read-only SD Cards.
* 4. Tune timeouts based on real-world SD Card speeds.
*/
+devclass_t altera_sdcard_devclass;
void
altera_sdcard_attach(struct altera_sdcard_softc *sc)
diff --git a/sys/dev/altera/sdcard/altera_sdcard.h b/sys/dev/altera/sdcard/altera_sdcard.h
index 4a491c4..96019b2 100644
--- a/sys/dev/altera/sdcard/altera_sdcard.h
+++ b/sys/dev/altera/sdcard/altera_sdcard.h
@@ -138,7 +138,7 @@ void altera_sdcard_io_start(struct altera_sdcard_softc *sc,
* data. Software ease of use was not a design consideration.
*/
#define ALTERA_SDCARD_CSD_C_SIZE_BYTE0 7
-#define ALTERA_SDCARD_CSD_C_SIZE_MASK0 0xc /* top 2 bits */
+#define ALTERA_SDCARD_CSD_C_SIZE_MASK0 0xc0 /* top 2 bits */
#define ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0 6
#define ALTERA_SDCARD_CSD_C_SIZE_BYTE1 8
@@ -244,4 +244,6 @@ void altera_sdcard_start(struct altera_sdcard_softc *sc);
void altera_sdcard_disk_insert(struct altera_sdcard_softc *sc);
void altera_sdcard_disk_remove(struct altera_sdcard_softc *sc);
+extern devclass_t altera_sdcard_devclass;
+
#endif /* _DEV_ALTERA_SDCARD_H_ */
diff --git a/sys/dev/altera/sdcard/altera_sdcard_fdt.c b/sys/dev/altera/sdcard/altera_sdcard_fdt.c
new file mode 100644
index 0000000..027ca2d
--- /dev/null
+++ b/sys/dev/altera/sdcard/altera_sdcard_fdt.c
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * 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.
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * FDT bus attachment for the Altera SD Card IP core.
+ */
+static int
+altera_sdcard_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "altera,sdcard_11_2011")) {
+ device_set_desc(dev, "Altera Secure Data Card IP Core");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+altera_sdcard_fdt_attach(device_t dev)
+{
+ struct altera_sdcard_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->as_dev = dev;
+ sc->as_unit = device_get_unit(dev);
+ sc->as_rid = 0;
+ sc->as_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->as_rid, RF_ACTIVE);
+ if (sc->as_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ altera_sdcard_attach(sc);
+ return (0);
+}
+
+static int
+altera_sdcard_fdt_detach(device_t dev)
+{
+ struct altera_sdcard_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc->as_res != NULL, ("%s: resources not allocated",
+ __func__));
+ altera_sdcard_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->as_rid, sc->as_res);
+ return (0);
+}
+
+static device_method_t altera_sdcard_fdt_methods[] = {
+ DEVMETHOD(device_probe, altera_sdcard_fdt_probe),
+ DEVMETHOD(device_attach, altera_sdcard_fdt_attach),
+ DEVMETHOD(device_detach, altera_sdcard_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t altera_sdcard_fdt_driver = {
+ "altera_sdcardc",
+ altera_sdcard_fdt_methods,
+ sizeof(struct altera_sdcard_softc),
+};
+
+DRIVER_MODULE(altera_sdcard, simplebus, altera_sdcard_fdt_driver,
+ altera_sdcard_devclass, 0, 0);
diff --git a/sys/dev/altera/sdcard/altera_sdcard_io.c b/sys/dev/altera/sdcard/altera_sdcard_io.c
index adbd5d1..b256c0b 100644
--- a/sys/dev/altera/sdcard/altera_sdcard_io.c
+++ b/sys/dev/altera/sdcard/altera_sdcard_io.c
@@ -93,13 +93,6 @@ altera_sdcard_process_csd0(struct altera_sdcard_softc *sc)
read_bl_len = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE];
read_bl_len &= ALTERA_SDCARD_CSD_READ_BL_LEN_MASK;
- byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0];
- byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0;
- byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1];
- byte1 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1;
- c_size_mult = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0) |
- (byte0 << ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1);
-
byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE0];
byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MASK0;
byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE1];
diff --git a/sys/dev/altera/sdcard/altera_sdcard_nexus.c b/sys/dev/altera/sdcard/altera_sdcard_nexus.c
index e0fddcb..88abe1f 100644
--- a/sys/dev/altera/sdcard/altera_sdcard_nexus.c
+++ b/sys/dev/altera/sdcard/altera_sdcard_nexus.c
@@ -110,7 +110,5 @@ static driver_t altera_sdcard_nexus_driver = {
sizeof(struct altera_sdcard_softc),
};
-static devclass_t altera_sdcard_devclass;
-
DRIVER_MODULE(altera_sdcard, nexus, altera_sdcard_nexus_driver,
altera_sdcard_devclass, 0, 0);
diff --git a/sys/dev/amdsbwd/amdsbwd.c b/sys/dev/amdsbwd/amdsbwd.c
index 4256381..4726416 100644
--- a/sys/dev/amdsbwd/amdsbwd.c
+++ b/sys/dev/amdsbwd/amdsbwd.c
@@ -139,7 +139,7 @@ static device_method_t amdsbwd_methods[] = {
#if 0
DEVMETHOD(device_shutdown, amdsbwd_detach),
#endif
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t amdsbwd_devclass;
diff --git a/sys/dev/amdtemp/amdtemp.c b/sys/dev/amdtemp/amdtemp.c
index 6d106ae..c55e680 100644
--- a/sys/dev/amdtemp/amdtemp.c
+++ b/sys/dev/amdtemp/amdtemp.c
@@ -134,7 +134,7 @@ static device_method_t amdtemp_methods[] = {
DEVMETHOD(device_attach, amdtemp_attach),
DEVMETHOD(device_detach, amdtemp_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t amdtemp_driver = {
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 3a6710c..28c93f9 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -698,6 +698,8 @@ MALLOC_DECLARE(M_ATA);
#define ATA_INW(res, offset) \
bus_read_2((res), (offset))
+#define ATA_INW_STRM(res, offset) \
+ bus_read_stream_2((res), (offset))
#define ATA_INL(res, offset) \
bus_read_4((res), (offset))
#define ATA_INSW(res, offset, addr, count) \
@@ -712,6 +714,8 @@ MALLOC_DECLARE(M_ATA);
bus_write_1((res), (offset), (value))
#define ATA_OUTW(res, offset, value) \
bus_write_2((res), (offset), (value))
+#define ATA_OUTW_STRM(res, offset, value) \
+ bus_write_stream_2((res), (offset), (value))
#define ATA_OUTL(res, offset, value) \
bus_write_4((res), (offset), (value))
#define ATA_OUTSW(res, offset, addr, count) \
@@ -729,6 +733,9 @@ MALLOC_DECLARE(M_ATA);
#define ATA_IDX_INW(ch, idx) \
ATA_INW(ch->r_io[idx].res, ch->r_io[idx].offset)
+#define ATA_IDX_INW_STRM(ch, idx) \
+ ATA_INW_STRM(ch->r_io[idx].res, ch->r_io[idx].offset)
+
#define ATA_IDX_INL(ch, idx) \
ATA_INL(ch->r_io[idx].res, ch->r_io[idx].offset)
@@ -750,6 +757,9 @@ MALLOC_DECLARE(M_ATA);
#define ATA_IDX_OUTW(ch, idx, value) \
ATA_OUTW(ch->r_io[idx].res, ch->r_io[idx].offset, value)
+#define ATA_IDX_OUTW_STRM(ch, idx, value) \
+ ATA_OUTW_STRM(ch->r_io[idx].res, ch->r_io[idx].offset, value)
+
#define ATA_IDX_OUTL(ch, idx, value) \
ATA_OUTL(ch->r_io[idx].res, ch->r_io[idx].offset, value)
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index de30603..6f83db7 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -846,14 +846,28 @@ ata_pio_read(struct ata_request *request, int length)
uint8_t *addr;
int size = min(request->transfersize, length);
int resid;
- uint8_t buf[2];
+ uint8_t buf[2] __aligned(sizeof(int16_t));
+#ifndef __NO_STRICT_ALIGNMENT
+ int i;
+#endif
addr = (uint8_t *)request->data + request->donecount;
- if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
- ((uintptr_t)addr % sizeof(int32_t))) {
- ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
+ if (__predict_false(ch->flags & ATA_USE_16BIT ||
+ (size % sizeof(int32_t)) || ((uintptr_t)addr % sizeof(int32_t)))) {
+#ifndef __NO_STRICT_ALIGNMENT
+ if (__predict_false((uintptr_t)addr % sizeof(int16_t))) {
+ for (i = 0, resid = size & ~1; resid > 0; resid -=
+ sizeof(int16_t)) {
+ *(uint16_t *)&buf = ATA_IDX_INW_STRM(ch, ATA_DATA);
+ addr[i++] = buf[0];
+ addr[i++] = buf[1];
+ }
+ } else
+#endif
+ ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size /
+ sizeof(int16_t));
if (size & 1) {
- ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)buf, 1);
+ *(uint16_t *)&buf = ATA_IDX_INW_STRM(ch, ATA_DATA);
(addr + (size & ~1))[0] = buf[0];
}
} else
@@ -875,15 +889,30 @@ ata_pio_write(struct ata_request *request, int length)
uint8_t *addr;
int size = min(request->transfersize, length);
int resid;
- uint8_t buf[2];
+ uint8_t buf[2] __aligned(sizeof(int16_t));
+#ifndef __NO_STRICT_ALIGNMENT
+ int i;
+#endif
+ size = min(request->transfersize, length);
addr = (uint8_t *)request->data + request->donecount;
- if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
- ((uintptr_t)addr % sizeof(int32_t))) {
- ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
+ if (__predict_false(ch->flags & ATA_USE_16BIT ||
+ (size % sizeof(int32_t)) || ((uintptr_t)addr % sizeof(int32_t)))) {
+#ifndef __NO_STRICT_ALIGNMENT
+ if (__predict_false((uintptr_t)addr % sizeof(int16_t))) {
+ for (i = 0, resid = size & ~1; resid > 0; resid -=
+ sizeof(int16_t)) {
+ buf[0] = addr[i++];
+ buf[1] = addr[i++];
+ ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
+ }
+ } else
+#endif
+ ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size /
+ sizeof(int16_t));
if (size & 1) {
buf[0] = (addr + (size & ~1))[0];
- ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)buf, 1);
+ ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
}
} else
ATA_IDX_OUTSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
index c96e252..5b0595c 100644
--- a/sys/dev/ata/ata-raid.c
+++ b/sys/dev/ata/ata-raid.c
@@ -1351,10 +1351,11 @@ static int
ata_raid_read_metadata(device_t subdisk)
{
devclass_t pci_devclass = devclass_find("pci");
+ devclass_t atapci_devclass = devclass_find("atapci");
devclass_t devclass=device_get_devclass(GRANDPARENT(GRANDPARENT(subdisk)));
/* prioritize vendor native metadata layout if possible */
- if (devclass == pci_devclass) {
+ if (devclass == pci_devclass || devclass == atapci_devclass) {
switch (pci_get_vendor(GRANDPARENT(device_get_parent(subdisk)))) {
case ATA_HIGHPOINT_ID:
if (ata_raid_hptv3_read_meta(subdisk, ata_raid_arrays))
diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h
index 19beffe..ddc4b6a 100644
--- a/sys/dev/ath/ath_hal/ah.h
+++ b/sys/dev/ath/ath_hal/ah.h
@@ -941,6 +941,8 @@ typedef struct {
int8_t ss_nf_cal[AH_MAX_CHAINS*2]; /* nf calibrated values for ctl+ext from eeprom */
int8_t ss_nf_pwr[AH_MAX_CHAINS*2]; /* nf pwr values for ctl+ext from eeprom */
int32_t ss_nf_temp_data; /* temperature data taken during nf scan */
+ int ss_enabled;
+ int ss_active;
} HAL_SPECTRAL_PARAM;
#define HAL_SPECTRAL_PARAM_NOVAL 0xFFFF
#define HAL_SPECTRAL_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */
diff --git a/sys/dev/ath/ath_hal/ar5211/boss.ini b/sys/dev/ath/ath_hal/ar5211/boss.ini
index e054436..e054436 100755..100644
--- a/sys/dev/ath/ath_hal/ar5211/boss.ini
+++ b/sys/dev/ath/ath_hal/ar5211/boss.ini
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index bd2580f..41019fb 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -152,7 +152,6 @@ static void ath_init(void *);
static void ath_stop_locked(struct ifnet *);
static void ath_stop(struct ifnet *);
static int ath_reset_vap(struct ieee80211vap *, u_long);
-static void ath_start_queue(struct ifnet *ifp);
static int ath_media_change(struct ifnet *);
static void ath_watchdog(void *);
static int ath_ioctl(struct ifnet *, u_long, caddr_t);
@@ -213,6 +212,14 @@ static void ath_dfs_tasklet(void *, int);
static void ath_node_powersave(struct ieee80211_node *, int);
static int ath_node_set_tim(struct ieee80211_node *, int);
+static int ath_transmit(struct ifnet *ifp, struct mbuf *m);
+static void ath_qflush(struct ifnet *ifp);
+
+static void ath_txq_qinit(struct ifnet *ifp);
+static void ath_txq_qflush(struct ifnet *ifp);
+static int ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0);
+static void ath_txq_qrun(struct ifnet *ifp);
+
#ifdef IEEE80211_SUPPORT_TDMA
#include <dev/ath/if_ath_tdma.h>
#endif
@@ -429,12 +436,30 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
"%s taskq", ifp->if_xname);
+ /*
+ * This taskqueue doesn't get any higher priority
+ * than the ath(4) taskqueue (PI_NET) so TX won't
+ * pre-empt RX and other task priorities.
+ *
+ * This may not be optimal - the previous behaviour
+ * was to direct-dispatch frames via the sending
+ * task context, rather than (always) software
+ * queuing.
+ */
+ sc->sc_tx_tq = taskqueue_create("ath_tx_taskq", M_NOWAIT,
+ taskqueue_thread_enqueue, &sc->sc_tx_tq);
+ taskqueue_start_threads(&sc->sc_tx_tq, 1, PI_NET,
+ "%s TX taskq", ifp->if_xname);
+
TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc);
TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc);
TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc);
TASK_INIT(&sc->sc_resettask,0, ath_reset_proc, sc);
- TASK_INIT(&sc->sc_txqtask,0, ath_txq_sched_tasklet, sc);
- TASK_INIT(&sc->sc_fataltask,0, ath_fatal_proc, sc);
+ TASK_INIT(&sc->sc_txqtask, 0, ath_txq_sched_tasklet, sc);
+ TASK_INIT(&sc->sc_fataltask, 0, ath_fatal_proc, sc);
+
+ /* XXX make this a higher priority taskqueue? */
+ TASK_INIT(&sc->sc_txpkttask, 0, ath_start_task, sc);
/*
* Allocate hardware transmit queues: one queue for
@@ -554,13 +579,18 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
ifp->if_softc = sc;
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
- ifp->if_start = ath_start_queue;
+ /* XXX net80211 uses if_start to re-start ifnet processing */
+ ifp->if_start = ath_start;
+ ifp->if_transmit = ath_transmit;
+ ifp->if_qflush = ath_qflush;
ifp->if_ioctl = ath_ioctl;
ifp->if_init = ath_init;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
+ ath_txq_qinit(ifp);
+
ic->ic_ifp = ifp;
/* XXX not right but it's not used anywhere important */
ic->ic_phytype = IEEE80211_T_OFDM;
@@ -966,16 +996,16 @@ ath_detach(struct ath_softc *sc)
ath_stop(ifp);
ieee80211_ifdetach(ifp->if_l2com);
taskqueue_free(sc->sc_tq);
+ taskqueue_free(sc->sc_tx_tq);
#ifdef ATH_TX99_DIAG
if (sc->sc_tx99 != NULL)
sc->sc_tx99->detach(sc->sc_tx99);
#endif
ath_rate_detach(sc->sc_rc);
-
#ifdef ATH_DEBUG_ALQ
if_ath_alq_tidyup(&sc->sc_alq);
#endif
-
+ ath_txq_qflush(ifp);
ath_spectral_detach(sc);
ath_dfs_detach(sc);
ath_desc_free(sc);
@@ -1863,11 +1893,19 @@ ath_bmiss_proc(void *arg, int pending)
DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending);
+ /*
+ * Do a reset upon any becaon miss event.
+ *
+ * It may be a non-recognised RX clear hang which needs a reset
+ * to clear.
+ */
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
+ ath_reset(ifp, ATH_RESET_NOLOSS);
if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs);
+ } else {
ath_reset(ifp, ATH_RESET_NOLOSS);
- } else
ieee80211_beacon_miss(ifp->if_l2com);
+ }
}
/*
@@ -2107,6 +2145,7 @@ ath_txrx_start(struct ath_softc *sc)
{
taskqueue_unblock(sc->sc_tq);
+ taskqueue_unblock(sc->sc_tx_tq);
}
/*
@@ -2207,6 +2246,7 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
/* Try to (stop any further TX/RX from occuring */
taskqueue_block(sc->sc_tq);
+ taskqueue_block(sc->sc_tx_tq);
ATH_PCU_LOCK(sc);
ath_hal_intrset(ah, 0); /* disable interrupts */
@@ -2454,6 +2494,14 @@ ath_buf_clone(struct ath_softc *sc, const struct ath_buf *bf)
tbf->bf_flags = bf->bf_flags & ~ATH_BUF_BUSY;
tbf->bf_status = bf->bf_status;
tbf->bf_m = bf->bf_m;
+ /*
+ * XXX Copy the node reference, the caller is responsible
+ * for deleting the node reference before it frees its
+ * buffer.
+ *
+ * XXX It's done like this so we don't call the net80211
+ * code whilst having active TX queue locks held.
+ */
tbf->bf_node = bf->bf_node;
/* will be setup by the chain/setup function */
tbf->bf_lastds = NULL;
@@ -2498,13 +2546,70 @@ ath_getbuf(struct ath_softc *sc, ath_buf_type_t btype)
}
static void
-ath_start_queue(struct ifnet *ifp)
+ath_qflush(struct ifnet *ifp)
{
- struct ath_softc *sc = ifp->if_softc;
- ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: start");
+ /* XXX complete/suspend TX */
+ ath_txq_qflush(ifp);
+
+ /* Unsuspend TX? */
+}
+
+/*
+ * Transmit a frame from net80211.
+ */
+static int
+ath_transmit(struct ifnet *ifp, struct mbuf *m)
+{
+ struct ieee80211_node *ni;
+ struct ath_softc *sc = (struct ath_softc *) ifp->if_softc;
+
+ ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
+
+ if (ath_txq_qadd(ifp, m) < 0) {
+ /*
+ * If queuing fails, the if_transmit() API makes the
+ * callee responsible for freeing the mbuf (rather than
+ * the caller, who just assumes the mbuf has been dealt
+ * with somehow).
+ *
+ * BUT, net80211 will free node references if if_transmit()
+ * fails _on encapsulated buffers_. Since drivers
+ * only get fully encapsulated frames from net80211 (via
+ * raw or otherwise APIs), we must be absolutely careful
+ * to not free the node ref or things will get loopy
+ * down the track.
+ *
+ * For tx fragments, the TX code must free whatever
+ * new references it created, but NOT the original
+ * TX node ref that was passed in.
+ */
+ ath_freetx(m);
+ return (ENOBUFS);
+ }
+
+ /*
+ * Unconditionally kick the taskqueue.
+ *
+ * Now, there's a subtle race condition possible here if we
+ * went down the path of only kicking the taskqueue if it
+ * wasn't running. If we're not absolutely, positively
+ * careful, we could have a small race window between
+ * finishing the taskqueue and clearing the TX flag, which
+ * would be interpreted in _this_ context as "we don't need
+ * to kick the TX taskqueue, as said taskqueue is already
+ * running."
+ *
+ * It's a problem in some of the 1GE/10GE NIC drivers.
+ * So until a _correct_ method for implementing this is
+ * drafted up and written, which avoids (potentially)
+ * large amounts of locking contention per-frame, let's
+ * just do the inefficient "kick taskqueue each time"
+ * method.
+ */
ath_tx_kick(sc);
- ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: finished");
+
+ return (0);
}
void
@@ -2531,9 +2636,7 @@ ath_start_task(void *arg, int npending)
sc->sc_txstart_cnt++;
ATH_PCU_UNLOCK(sc);
- ATH_TX_LOCK(sc);
- ath_start(sc->sc_ifp);
- ATH_TX_UNLOCK(sc);
+ ath_txq_qrun(ifp);
ATH_PCU_LOCK(sc);
sc->sc_txstart_cnt--;
@@ -2541,91 +2644,298 @@ ath_start_task(void *arg, int npending)
ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: finished");
}
-void
-ath_start(struct ifnet *ifp)
+/*
+ * Pending TX buffer chain management routines.
+ */
+
+
+/*
+ * Initialise the TX queue!
+ */
+static void
+ath_txq_qinit(struct ifnet *ifp)
+{
+ struct ath_softc *sc = ifp->if_softc;
+
+ TAILQ_INIT(&sc->sc_txbuf_list);
+}
+
+/*
+ * Add this mbuf to the TX buffer chain.
+ *
+ * This allocates an ath_buf, links the mbuf into it, and
+ * appends it to the end of the TX buffer chain.
+ * It doesn't fill out the ath_buf in any way besides
+ * that.
+ *
+ * Since the mbuf may be a list of mbufs representing
+ * 802.11 fragments, handle allocating ath_bufs for each
+ * of the mbuf fragments.
+ *
+ * If we queued it, 0 is returned. Else, < 0 is returned.
+ *
+ * If <0 is returned, the sender is responsible for
+ * freeing the mbuf if appropriate.
+ */
+static int
+ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0)
{
struct ath_softc *sc = ifp->if_softc;
- struct ieee80211_node *ni;
struct ath_buf *bf;
- struct mbuf *m, *next;
ath_bufhead frags;
- int npkts = 0;
+ struct ieee80211_node *ni;
+ struct mbuf *m;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
- return;
+ /* XXX recursive TX completion -> TX? */
+ ATH_TX_UNLOCK_ASSERT(sc);
+
+ /*
+ * We grab the node pointer, but we don't deref
+ * the node. The caller must be responsible for
+ * freeing the node reference if it decides to
+ * free the mbuf.
+ */
+ ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
+
+ ATH_TXBUF_LOCK(sc);
+ if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) {
+ /* XXX increment counter? */
+ ATH_TXBUF_UNLOCK(sc);
+ IF_LOCK(&ifp->if_snd);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ IF_UNLOCK(&ifp->if_snd);
+ return (-1);
+ }
+ ATH_TXBUF_UNLOCK(sc);
+
+ /*
+ * Grab a TX buffer and associated resources.
+ */
+ bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL);
+ if (bf == NULL) {
+ device_printf(sc->sc_dev,
+ "%s: couldn't allocate a buffer\n",
+ __func__);
+ return (-1);
+ }
- ATH_TX_LOCK_ASSERT(sc);
+ /* Setup the initial buffer node contents */
+ bf->bf_m = m0;
+ bf->bf_node = ni;
- ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start: called");
+ /*
+ * Check for fragmentation. If this frame
+ * has been broken up verify we have enough
+ * buffers to send all the fragments so all
+ * go out or none...
+ */
+ TAILQ_INIT(&frags);
+ if (m0->m_flags & M_FRAG)
+ DPRINTF(sc, ATH_DEBUG_XMIT, "%s: txfrag\n", __func__);
+ if ((m0->m_flags & M_FRAG) &&
+ !ath_txfrag_setup(sc, &frags, m0, ni)) {
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "%s: out of txfrag buffers\n", __func__);
+ sc->sc_stats.ast_tx_nofrag++;
+ ifp->if_oerrors++;
+ goto bad;
+ }
- for (;;) {
+ /*
+ * Don't stuff the non-fragment frame onto the fragment
+ * queue. ath_txfrag_cleanup() should only be called on fragments -
+ * ie, the _extra_ ieee80211_node references - and not the single
+ * node reference already done as part of the net08211 TX call
+ * into the driver.
+ */
+
+ ATH_TX_LOCK(sc);
+
+ /*
+ * Throw the single frame onto the queue.
+ */
+ TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list);
+
+ /*
+ * Update next packet duration length if it's a fragment.
+ * It's needed for accurate NAV calculations (which for
+ * fragments include the length of the NEXT fragment.)
+ */
+ if (m0->m_nextpkt != NULL)
+ bf->bf_state.bfs_nextpktlen =
+ m0->m_nextpkt->m_pkthdr.len;
+
+ /*
+ * Append the fragments. We have to populate bf and node
+ * references here as although the txfrag setup code does
+ * create buffers and increment the node ref, it doesn't
+ * populate the fields for us.
+ */
+ m = m0->m_nextpkt;
+ while ( (bf = TAILQ_FIRST(&frags)) != NULL) {
+ bf->bf_m = m;
+ bf->bf_node = ni;
+ device_printf(sc->sc_dev, "%s: adding bf=%p, m=%p, ni=%p\n",
+ __func__,
+ bf,
+ bf->bf_m,
+ bf->bf_node);
+ TAILQ_REMOVE(&frags, bf, bf_list);
+ TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list);
+
+ /*
+ * For duration (NAV) calculations, we need
+ * to know the next fragment size.
+ *
+ * XXX This isn't entirely accurate as it doesn't
+ * take pad bytes and such into account, but it'll do
+ * for fragment length / NAV calculations.
+ */
+ if (m->m_nextpkt != NULL)
+ bf->bf_state.bfs_nextpktlen =
+ m->m_nextpkt->m_pkthdr.len;
+
+ m = m->m_nextpkt;
+ }
+ ATH_TX_UNLOCK(sc);
+
+ return (0);
+bad:
+ device_printf(sc->sc_dev, "%s: bad?!\n", __func__);
+ bf->bf_m = NULL;
+ bf->bf_node = NULL;
+ ATH_TXBUF_LOCK(sc);
+ ath_returnbuf_head(sc, bf);
+ ath_txfrag_cleanup(sc, &frags, ni);
+ ATH_TXBUF_UNLOCK(sc);
+ return (-1);
+}
+
+/*
+ * Flush the pending TX buffer chain.
+ */
+static void
+ath_txq_qflush(struct ifnet *ifp)
+{
+ struct ath_softc *sc = ifp->if_softc;
+ ath_bufhead txlist;
+ struct ath_buf *bf;
+
+ device_printf(sc->sc_dev, "%s: called\n", __func__);
+ TAILQ_INIT(&txlist);
+
+ /* Grab lock */
+ ATH_TX_LOCK(sc);
+
+ /* Copy everything out of sc_txbuf_list into txlist */
+ TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list);
+
+ /* Unlock */
+ ATH_TX_UNLOCK(sc);
+
+ /* Now, walk the list, freeing things */
+ while ((bf = TAILQ_FIRST(&txlist)) != NULL) {
+ TAILQ_REMOVE(&txlist, bf, bf_list);
+
+ if (bf->bf_node)
+ ieee80211_free_node(bf->bf_node);
+
+ m_free(bf->bf_m);
+
+ /* XXX paranoia! */
+ bf->bf_m = NULL;
+ bf->bf_node = NULL;
+
+ /*
+ * XXX Perhaps do a second pass with the TXBUF lock
+ * held and free them all at once?
+ */
ATH_TXBUF_LOCK(sc);
- if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) {
- /* XXX increment counter? */
- ATH_TXBUF_UNLOCK(sc);
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
- break;
- }
+ ath_returnbuf_head(sc, bf);
ATH_TXBUF_UNLOCK(sc);
-
+ }
+}
+
+/*
+ * Walk the TX buffer queue and call ath_tx_start() on each
+ * of them.
+ */
+static void
+ath_txq_qrun(struct ifnet *ifp)
+{
+ struct ath_softc *sc = ifp->if_softc;
+ ath_bufhead txlist;
+ struct ath_buf *bf, *bf_next;
+ struct ieee80211_node *ni;
+ struct mbuf *m;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
+ return;
+
+ TAILQ_INIT(&txlist);
+
+ /*
+ * Grab the frames to transmit from the tx queue
+ */
+
+ /* Copy everything out of sc_txbuf_list into txlist */
+ ATH_TX_LOCK(sc);
+ TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list);
+ ATH_TX_UNLOCK(sc);
+
+ /*
+ * For now, the ath_tx_start() code sits behind the same lock;
+ * worry about serialising this in a taskqueue later.
+ */
+
+ ATH_TX_LOCK(sc);
+
+ /*
+ * Attempt to transmit each frame.
+ *
+ * In the old code path - if a TX fragment fails, subsequent
+ * fragments in that group would be aborted.
+ *
+ * It would be nice to chain together TX fragments in this
+ * way so they can be aborted together.
+ */
+ TAILQ_FOREACH_SAFE(bf, &txlist, bf_list, bf_next) {
/*
- * Grab a TX buffer and associated resources.
+ * Clear, because we're going to reuse this
+ * as a real ath_buf now
*/
- bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL);
- if (bf == NULL)
- break;
+ ni = bf->bf_node;
+ m = bf->bf_m;
+
+ bf->bf_node = NULL;
+ bf->bf_m = NULL;
- IFQ_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL) {
- ATH_TXBUF_LOCK(sc);
- ath_returnbuf_head(sc, bf);
- ATH_TXBUF_UNLOCK(sc);
- break;
- }
- ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- npkts ++;
/*
- * Check for fragmentation. If this frame
- * has been broken up verify we have enough
- * buffers to send all the fragments so all
- * go out or none...
+ * Remove it from the list.
*/
- TAILQ_INIT(&frags);
- if ((m->m_flags & M_FRAG) &&
- !ath_txfrag_setup(sc, &frags, m, ni)) {
- DPRINTF(sc, ATH_DEBUG_XMIT,
- "%s: out of txfrag buffers\n", __func__);
- sc->sc_stats.ast_tx_nofrag++;
- ifp->if_oerrors++;
- ath_freetx(m);
- goto bad;
- }
- ifp->if_opackets++;
- nextfrag:
+ TAILQ_REMOVE(&txlist, bf, bf_list);
+
/*
- * Pass the frame to the h/w for transmission.
- * Fragmented frames have each frag chained together
- * with m_nextpkt. We know there are sufficient ath_buf's
- * to send all the frags because of work done by
- * ath_txfrag_setup. We leave m_nextpkt set while
- * calling ath_tx_start so it can use it to extend the
- * the tx duration to cover the subsequent frag and
- * so it can reclaim all the mbufs in case of an error;
- * ath_tx_start clears m_nextpkt once it commits to
- * handing the frame to the hardware.
+ * If we fail, free this buffer and go to the next one;
+ * ath_tx_start() frees the mbuf but not the node
+ * reference.
*/
- next = m->m_nextpkt;
if (ath_tx_start(sc, ni, bf, m)) {
- bad:
+ /*
+ * XXX m is freed by ath_tx_start(); node reference
+ * is not!
+ */
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "%s: failed; bf=%p, ni=%p, m=%p\n",
+ __func__,
+ bf,
+ ni,
+ m);
ifp->if_oerrors++;
- reclaim:
bf->bf_m = NULL;
bf->bf_node = NULL;
ATH_TXBUF_LOCK(sc);
ath_returnbuf_head(sc, bf);
- ath_txfrag_cleanup(sc, &frags, ni);
ATH_TXBUF_UNLOCK(sc);
/*
* XXX todo, free the node outside of
@@ -2633,37 +2943,84 @@ ath_start(struct ifnet *ifp)
*/
if (ni != NULL)
ieee80211_free_node(ni);
- continue;
+ } else {
+ /*
+ * Check here if the node is in power save state.
+ * XXX we should hold a node ref here, and release
+ * it after the TX has completed.
+ */
+ ath_tx_update_tim(sc, ni, 1);
+ ifp->if_opackets++;
}
/*
- * Check here if the node is in power save state.
+ * XXX should check for state change and flip out
+ * if needed.
*/
- ath_tx_update_tim(sc, ni, 1);
+ }
+ ATH_TX_UNLOCK(sc);
- if (next != NULL) {
- /*
- * Beware of state changing between frags.
- * XXX check sta power-save state?
- */
- if (ni->ni_vap->iv_state != IEEE80211_S_RUN) {
- DPRINTF(sc, ATH_DEBUG_XMIT,
- "%s: flush fragmented packet, state %s\n",
- __func__,
- ieee80211_state_name[ni->ni_vap->iv_state]);
- ath_freetx(next);
- goto reclaim;
- }
- m = next;
- bf = TAILQ_FIRST(&frags);
- KASSERT(bf != NULL, ("no buf for txfrag"));
- TAILQ_REMOVE(&frags, bf, bf_list);
- goto nextfrag;
+ /*
+ * If we break out early (eg a state change) we should prepend these
+ * frames onto the TX queue.
+ */
+}
+
+/*
+ * This is now primarily used by the net80211 layer to kick-start
+ * queue processing.
+ */
+void
+ath_start(struct ifnet *ifp)
+{
+ struct mbuf *m;
+ struct ath_softc *sc = ifp->if_softc;
+ struct ieee80211_node *ni;
+ int npkts = 0;
+
+ ATH_TX_UNLOCK_ASSERT(sc);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
+ return;
+
+ /*
+ * If we're below the free buffer limit, don't dequeue anything.
+ * The original code would not dequeue anything from the queue
+ * if allocating an ath_buf failed.
+ *
+ * For if_transmit, we have to either queue or drop the frame.
+ * So we have to try and queue it _somewhere_.
+ */
+ for (;;) {
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL) {
+ break;
}
- sc->sc_wd_timer = 5;
+ /*
+ * If we do fail here, just break out for now
+ * and wait until we've transmitted something
+ * before we attempt again?
+ */
+ if (ath_txq_qadd(ifp, m) < 0) {
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "%s: ath_txq_qadd failed\n",
+ __func__);
+ ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
+ if (ni != NULL)
+ ieee80211_free_node(ni);
+ ath_freetx(m);
+ break;
+ }
+ npkts++;
}
- ATH_KTR(sc, ATH_KTR_TX, 1, "ath_start: finished; npkts=%d", npkts);
+
+ /*
+ * Kick the taskqueue into activity, but only if we
+ * queued something.
+ */
+ if (npkts > 0)
+ ath_tx_kick(sc);
}
static int
@@ -2688,6 +3045,7 @@ ath_key_update_begin(struct ieee80211vap *vap)
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
taskqueue_block(sc->sc_tq);
+ taskqueue_block(sc->sc_tx_tq);
IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */
}
@@ -2700,6 +3058,7 @@ ath_key_update_end(struct ieee80211vap *vap)
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
IF_UNLOCK(&ifp->if_snd);
taskqueue_unblock(sc->sc_tq);
+ taskqueue_unblock(sc->sc_tx_tq);
}
static void
@@ -3873,9 +4232,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched)
/* Kick the TXQ scheduler */
if (dosched) {
- ATH_TX_LOCK(sc);
- ath_txq_sched(sc, txq);
- ATH_TX_UNLOCK(sc);
+ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask);
}
ATH_KTR(sc, ATH_KTR_TXCOMP, 1,
@@ -4373,6 +4730,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
/* (Try to) stop TX/RX from occuring */
taskqueue_block(sc->sc_tq);
+ taskqueue_block(sc->sc_tx_tq);
ATH_PCU_LOCK(sc);
ath_hal_intrset(ah, 0); /* Stop new RX/TX completion */
@@ -4719,6 +5077,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
int i, error, stamode;
u_int32_t rfilt;
int csa_run_transition = 0;
+
static const HAL_LED_STATE leds[] = {
HAL_LED_INIT, /* IEEE80211_S_INIT */
HAL_LED_SCAN, /* IEEE80211_S_SCAN */
@@ -4761,6 +5120,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
sc->sc_beacons = 0;
taskqueue_unblock(sc->sc_tq);
+ taskqueue_unblock(sc->sc_tx_tq);
}
ni = ieee80211_ref_node(vap->iv_bss);
@@ -4863,10 +5223,32 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* force a beacon update so we pick up a lack of
* beacons from an AP in CAC and thus force a
* scan.
+ *
+ * And, there's also corner cases here where
+ * after a scan, the AP may have disappeared.
+ * In that case, we may not receive an actual
+ * beacon to update the beacon timer and thus we
+ * won't get notified of the missing beacons.
*/
sc->sc_syncbeacon = 1;
+#if 0
if (csa_run_transition)
+#endif
ath_beacon_config(sc, vap);
+
+ /*
+ * PR: kern/175227
+ *
+ * Reconfigure beacons during reset; as otherwise
+ * we won't get the beacon timers reprogrammed
+ * after a reset and thus we won't pick up a
+ * beacon miss interrupt.
+ *
+ * Hopefully we'll see a beacon before the BMISS
+ * timer fires (too often), leading to a STA
+ * disassociation.
+ */
+ sc->sc_beacons = 1;
break;
case IEEE80211_M_MONITOR:
/*
@@ -4904,6 +5286,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
"%s: calibration disabled\n", __func__);
}
taskqueue_unblock(sc->sc_tq);
+ taskqueue_unblock(sc->sc_tx_tq);
} else if (nstate == IEEE80211_S_INIT) {
/*
* If there are no vaps left in RUN state then
@@ -4917,6 +5300,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
/* disable interrupts */
ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL);
taskqueue_block(sc->sc_tq);
+ taskqueue_block(sc->sc_tx_tq);
sc->sc_beacons = 0;
}
#ifdef IEEE80211_SUPPORT_TDMA
diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c
index bb1e393..51467cd 100644
--- a/sys/dev/ath/if_ath_beacon.c
+++ b/sys/dev/ath/if_ath_beacon.c
@@ -705,6 +705,16 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
if (vap == NULL)
vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
+ /*
+ * Just ensure that we aren't being called when the last
+ * VAP is destroyed.
+ */
+ if (vap == NULL) {
+ device_printf(sc->sc_dev, "%s: called with no VAPs\n",
+ __func__);
+ return;
+ }
+
ni = ieee80211_ref_node(vap->iv_bss);
/* extract tstamp from last beacon and convert to TU */
diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h
index c3b101c..a97f897 100644
--- a/sys/dev/ath/if_ath_misc.h
+++ b/sys/dev/ath/if_ath_misc.h
@@ -124,9 +124,8 @@ static inline void
ath_tx_kick(struct ath_softc *sc)
{
- ATH_TX_LOCK(sc);
- ath_start(sc->sc_ifp);
- ATH_TX_UNLOCK(sc);
+ /* XXX eventually try sc_tx_tq? */
+ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txpkttask);
}
#endif
diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c
index 5a39d16..c8d9536 100644
--- a/sys/dev/ath/if_ath_rx.c
+++ b/sys/dev/ath/if_ath_rx.c
@@ -431,18 +431,16 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
#ifdef AH_SUPPORT_AR5416
sc->sc_rx_th.wr_chan_flags &= ~CHAN_HT;
if (rs->rs_status & HAL_RXERR_PHY) {
- struct ieee80211com *ic = ifp->if_l2com;
-
/*
* PHY error - make sure the channel flags
* reflect the actual channel configuration,
* not the received frame.
*/
- if (IEEE80211_IS_CHAN_HT40U(ic->ic_curchan))
+ if (IEEE80211_IS_CHAN_HT40U(sc->sc_curchan))
sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U;
- else if (IEEE80211_IS_CHAN_HT40D(ic->ic_curchan))
+ else if (IEEE80211_IS_CHAN_HT40D(sc->sc_curchan))
sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D;
- else if (IEEE80211_IS_CHAN_HT20(ic->ic_curchan))
+ else if (IEEE80211_IS_CHAN_HT20(sc->sc_curchan))
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
} else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
struct ieee80211com *ic = ifp->if_l2com;
@@ -845,6 +843,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
int16_t nf;
u_int64_t tsf;
int npkts = 0;
+ int kickpcu = 0;
/* XXX we must not hold the ATH_LOCK here */
ATH_UNLOCK_ASSERT(sc);
@@ -852,6 +851,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
ATH_PCU_LOCK(sc);
sc->sc_rxproc_cnt++;
+ kickpcu = sc->sc_kickpcu;
ATH_PCU_UNLOCK(sc);
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: called\n", __func__);
@@ -866,7 +866,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
* latency can jump by quite a bit, causing throughput
* degredation.
*/
- if (npkts >= ATH_RX_MAX)
+ if (!kickpcu && npkts >= ATH_RX_MAX)
break;
bf = TAILQ_FIRST(&sc->sc_rxbuf);
@@ -961,6 +961,9 @@ rx_proc_next:
__func__, npkts);
/* XXX rxslink? */
+#if 0
+ ath_startrecv(sc);
+#else
/*
* XXX can we hold the PCU lock here?
* Are there any net80211 buffer calls involved?
@@ -970,6 +973,7 @@ rx_proc_next:
ath_hal_rxena(ah); /* enable recv descriptors */
ath_mode_init(sc); /* set filters, etc. */
ath_hal_startpcurecv(ah); /* re-enable PCU/DMA engine */
+#endif
ath_hal_intrset(ah, sc->sc_imask);
sc->sc_kickpcu = 0;
diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c
index 5de29af..abb180b 100644
--- a/sys/dev/ath/if_ath_sysctl.c
+++ b/sys/dev/ath/if_ath_sysctl.c
@@ -505,6 +505,33 @@ ath_sysctl_forcebstuck(SYSCTL_HANDLER_ARGS)
return 0;
}
+static int
+ath_sysctl_hangcheck(SYSCTL_HANDLER_ARGS)
+{
+ struct ath_softc *sc = arg1;
+ int val = 0;
+ int error;
+ uint32_t mask = 0xffffffff;
+ uint32_t *sp;
+ uint32_t rsize;
+ struct ath_hal *ah = sc->sc_ah;
+
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error || !req->newptr)
+ return error;
+ if (val == 0)
+ return 0;
+
+ /* Do a hang check */
+ if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS,
+ &mask, sizeof(mask),
+ (void *) &sp, &rsize))
+ return (0);
+ device_printf(sc->sc_dev, "%s: sp=0x%08x\n", __func__, *sp);
+
+ val = 0;
+ return 0;
+}
#ifdef ATH_DEBUG_ALQ
static int
@@ -661,6 +688,10 @@ ath_sysctlattach(struct ath_softc *sc)
"forcebstuck", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
ath_sysctl_forcebstuck, "I", "");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "hangcheck", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ ath_sysctl_hangcheck, "I", "");
+
if (ath_hal_hasintmit(ah)) {
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index 263e69c..b3b6079 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -1124,7 +1124,11 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf)
dur = rt->info[rix].lpAckDuration;
if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) {
dur += dur; /* additional SIFS+ACK */
- KASSERT(bf->bf_m->m_nextpkt != NULL, ("no fragment"));
+ if (bf->bf_state.bfs_nextpktlen == 0) {
+ device_printf(sc->sc_dev,
+ "%s: next txfrag len=0?\n",
+ __func__);
+ }
/*
* Include the size of next fragment so NAV is
* updated properly. The last fragment uses only
@@ -1135,7 +1139,7 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf)
* first fragment!
*/
dur += ath_hal_computetxtime(ah, rt,
- bf->bf_m->m_nextpkt->m_pkthdr.len,
+ bf->bf_state.bfs_nextpktlen,
rix, shortPreamble);
}
if (isfrag) {
@@ -1393,12 +1397,13 @@ static void
ath_tx_update_clrdmask(struct ath_softc *sc, struct ath_tid *tid,
struct ath_buf *bf)
{
+ struct ath_node *an = ATH_NODE(bf->bf_node);
ATH_TX_LOCK_ASSERT(sc);
- if (tid->clrdmask == 1) {
+ if (an->clrdmask == 1) {
bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
- tid->clrdmask = 0;
+ an->clrdmask = 0;
}
}
@@ -2884,6 +2889,29 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_txq *txq,
}
/*
+ * Only set the clrdmask bit if none of the nodes are currently
+ * filtered.
+ *
+ * XXX TODO: go through all the callers and check to see
+ * which are being called in the context of looping over all
+ * TIDs (eg, if all tids are being paused, resumed, etc.)
+ * That'll avoid O(n^2) complexity here.
+ */
+static void
+ath_tx_set_clrdmask(struct ath_softc *sc, struct ath_node *an)
+{
+ int i;
+
+ ATH_TX_LOCK_ASSERT(sc);
+
+ for (i = 0; i < IEEE80211_TID_SIZE; i++) {
+ if (an->an_tid[i].isfiltered == 1)
+ return;
+ }
+ an->clrdmask = 1;
+}
+
+/*
* Configure the per-TID node state.
*
* This likely belongs in if_ath_node.c but I can't think of anywhere
@@ -2914,12 +2942,12 @@ ath_tx_tid_init(struct ath_softc *sc, struct ath_node *an)
atid->sched = 0;
atid->hwq_depth = 0;
atid->cleanup_inprogress = 0;
- atid->clrdmask = 1; /* Always start by setting this bit */
if (i == IEEE80211_NONQOS_TID)
atid->ac = ATH_NONQOS_TID_AC;
else
atid->ac = TID_TO_WME_AC(i);
}
+ an->clrdmask = 1; /* Always start by setting this bit */
}
/*
@@ -2945,7 +2973,6 @@ ath_tx_tid_pause(struct ath_softc *sc, struct ath_tid *tid)
static void
ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
{
-
ATH_TX_LOCK_ASSERT(sc);
tid->paused--;
@@ -2960,7 +2987,7 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
* Override the clrdmask configuration for the next frame
* from this TID, just to get the ball rolling.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
if (tid->axq_depth == 0)
return;
@@ -2974,7 +3001,7 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
ath_tx_tid_sched(sc, tid);
/* Punt some frames to the hardware if needed */
//ath_txq_sched(sc, sc->sc_ac2q[tid->ac]);
- taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
+ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask);
}
/*
@@ -3043,7 +3070,8 @@ ath_tx_tid_filt_comp_complete(struct ath_softc *sc, struct ath_tid *tid)
DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: hwq=0, transition back\n",
__func__);
tid->isfiltered = 0;
- tid->clrdmask = 1;
+ /* XXX ath_tx_tid_resume() also calls ath_tx_set_clrdmask()! */
+ ath_tx_set_clrdmask(sc, tid->an);
/* XXX this is really quite inefficient */
while ((bf = ATH_TID_FILT_LAST(tid, ath_bufhead_s)) != NULL) {
@@ -3299,7 +3327,7 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, struct ath_tid *tid)
* Override the clrdmask configuration for the next frame,
* just to get the ball rolling.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
/*
* Calculate new BAW left edge, now that all frames have either
@@ -3480,7 +3508,7 @@ ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an,
*
* This won't hurt things if the TID is about to be freed.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
/*
* Now that it's completed, grab the TID lock and update
diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c
index 40a0378..a2eef65 100644
--- a/sys/dev/ath/if_ath_tx_edma.c
+++ b/sys/dev/ath/if_ath_tx_edma.c
@@ -655,7 +655,7 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched)
* the txq task for _one_ TXQ. This should be fixed.
*/
if (dosched)
- taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
+ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask);
}
static void
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 2e170a3..070fe53 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -132,7 +132,6 @@ struct ath_tid {
int bar_wait; /* waiting for BAR */
int bar_tx; /* BAR TXed */
int isfiltered; /* is this node currently filtered */
- int clrdmask; /* has clrdmask been set */
/*
* Is the TID being cleaned up after a transition
@@ -182,6 +181,7 @@ struct ath_node {
struct mtx an_mtx; /* protecting the ath_node state */
uint32_t an_swq_depth; /* how many SWQ packets for this
node */
+ int clrdmask; /* has clrdmask been set */
/* variable-length rate control state follows */
};
#define ATH_NODE(ni) ((struct ath_node *)(ni))
@@ -279,6 +279,8 @@ struct ath_buf {
int32_t bfs_keyix; /* crypto key index */
int32_t bfs_txantenna; /* TX antenna config */
+ uint16_t bfs_nextpktlen; /* length of next frag pkt */
+
/* Make this an 8 bit value? */
enum ieee80211_protmode bfs_protmode;
@@ -494,6 +496,13 @@ struct ath_softc {
struct ath_tx_methods sc_tx;
struct ath_tx_edma_fifo sc_txedma[HAL_NUM_TX_QUEUES];
+ /*
+ * This is (currently) protected by the TX queue lock;
+ * it should migrate to a separate lock later
+ * so as to minimise contention.
+ */
+ ath_bufhead sc_txbuf_list;
+
int sc_rx_statuslen;
int sc_tx_desclen;
int sc_tx_statuslen;
@@ -514,6 +523,7 @@ struct ath_softc {
struct mtx sc_tx_mtx; /* TX access mutex */
char sc_tx_mtx_name[32];
struct taskqueue *sc_tq; /* private task queue */
+ struct taskqueue *sc_tx_tq; /* private TX task queue */
struct ath_hal *sc_ah; /* Atheros HAL */
struct ath_ratectrl *sc_rc; /* tx rate control support */
struct ath_tx99 *sc_tx99; /* tx99 adjunct state */
@@ -660,6 +670,7 @@ struct ath_softc {
struct ath_txq *sc_ac2q[5]; /* WME AC -> h/w q map */
struct task sc_txtask; /* tx int processing */
struct task sc_txqtask; /* tx proc processing */
+ struct task sc_txpkttask; /* tx frame processing */
struct ath_descdma sc_txcompdma; /* TX EDMA completion */
struct mtx sc_txcomplock; /* TX EDMA completion lock */
diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c
index e58ffc7..199fcb1 100644
--- a/sys/dev/atkbdc/atkbd.c
+++ b/sys/dev/atkbdc/atkbd.c
@@ -66,7 +66,7 @@ static timeout_t atkbd_timeout;
static void atkbd_shutdown_final(void *v);
int
-atkbd_probe_unit(int unit, int ctlr, int irq, int flags)
+atkbd_probe_unit(device_t dev, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
@@ -76,27 +76,29 @@ atkbd_probe_unit(int unit, int ctlr, int irq, int flags)
if (sw == NULL)
return ENXIO;
- args[0] = ctlr;
+ args[0] = device_get_unit(device_get_parent(dev));
args[1] = irq;
- error = (*sw->probe)(unit, args, flags);
+ error = (*sw->probe)(device_get_unit(dev), args, flags);
if (error)
return error;
return 0;
}
int
-atkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags)
+atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
int error;
+ int unit;
sw = kbd_get_switch(ATKBD_DRIVER_NAME);
if (sw == NULL)
return ENXIO;
/* reset, initialize and enable the device */
- args[0] = ctlr;
+ unit = device_get_unit(dev);
+ args[0] = device_get_unit(device_get_parent(dev));
args[1] = irq;
*kbd = NULL;
error = (*sw->probe)(unit, args, flags);
@@ -401,7 +403,7 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
bcopy(&key_map, keymap, sizeof(key_map));
bcopy(&accent_map, accmap, sizeof(accent_map));
bcopy(fkey_tab, fkeymap,
- imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
+ imin(fkeymap_size * sizeof(fkeymap[0]), sizeof(fkey_tab)));
kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
kbd->kb_data = (void *)state;
@@ -424,8 +426,8 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
if (KBD_HAS_DEVICE(kbd)
- && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
- && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
+ && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
+ && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
kbd_unregister(kbd);
error = ENXIO;
goto bad;
@@ -485,8 +487,7 @@ atkbd_intr(keyboard_t *kbd, void *arg)
* The keyboard was not detected before;
* it must have been reconnected!
*/
- init_keyboard(state->kbdc, &kbd->kb_type,
- kbd->kb_config);
+ init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config);
KBD_FOUND_DEVICE(kbd);
atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
get_typematic(kbd);
@@ -645,7 +646,7 @@ next_code:
goto next_code;
}
break;
- case 0xE0: /* 0xE0 prefix */
+ case 0xE0: /* 0xE0 prefix */
state->ks_prefix = 0;
switch (keycode) {
case 0x1C: /* right enter key */
@@ -655,57 +656,57 @@ next_code:
keycode = 0x5A;
break;
case 0x35: /* keypad divide key */
- keycode = 0x5B;
- break;
+ keycode = 0x5B;
+ break;
case 0x37: /* print scrn key */
- keycode = 0x5C;
- break;
+ keycode = 0x5C;
+ break;
case 0x38: /* right alt key (alt gr) */
- keycode = 0x5D;
- break;
+ keycode = 0x5D;
+ break;
case 0x46: /* ctrl-pause/break on AT 101 (see below) */
keycode = 0x68;
- break;
+ break;
case 0x47: /* grey home key */
- keycode = 0x5E;
- break;
+ keycode = 0x5E;
+ break;
case 0x48: /* grey up arrow key */
- keycode = 0x5F;
- break;
+ keycode = 0x5F;
+ break;
case 0x49: /* grey page up key */
- keycode = 0x60;
- break;
+ keycode = 0x60;
+ break;
case 0x4B: /* grey left arrow key */
- keycode = 0x61;
- break;
+ keycode = 0x61;
+ break;
case 0x4D: /* grey right arrow key */
- keycode = 0x62;
- break;
+ keycode = 0x62;
+ break;
case 0x4F: /* grey end key */
- keycode = 0x63;
- break;
+ keycode = 0x63;
+ break;
case 0x50: /* grey down arrow key */
- keycode = 0x64;
- break;
+ keycode = 0x64;
+ break;
case 0x51: /* grey page down key */
- keycode = 0x65;
- break;
+ keycode = 0x65;
+ break;
case 0x52: /* grey insert key */
- keycode = 0x66;
- break;
+ keycode = 0x66;
+ break;
case 0x53: /* grey delete key */
- keycode = 0x67;
- break;
- /* the following 3 are only used on the MS "Natural" keyboard */
+ keycode = 0x67;
+ break;
+ /* the following 3 are only used on the MS "Natural" keyboard */
case 0x5b: /* left Window key */
- keycode = 0x69;
- break;
+ keycode = 0x69;
+ break;
case 0x5c: /* right Window key */
- keycode = 0x6a;
- break;
+ keycode = 0x6a;
+ break;
case 0x5d: /* menu key */
- keycode = 0x6b;
- break;
+ keycode = 0x6b;
+ break;
case 0x5e: /* power key */
keycode = 0x6d;
break;
@@ -716,10 +717,10 @@ next_code:
keycode = 0x6f;
break;
default: /* ignore everything else */
- goto next_code;
+ goto next_code;
}
break;
- case 0xE1: /* 0xE1 prefix */
+ case 0xE1: /* 0xE1 prefix */
/*
* The pause/break key on the 101 keyboard produces:
* E1-1D-45 E1-9D-C5
@@ -728,10 +729,10 @@ next_code:
*/
state->ks_prefix = 0;
if (keycode == 0x1D)
- state->ks_prefix = 0x1D;
+ state->ks_prefix = 0x1D;
goto next_code;
/* NOT REACHED */
- case 0x1D: /* pause / break */
+ case 0x1D: /* pause / break */
state->ks_prefix = 0;
if (keycode != 0x45)
goto next_code;
@@ -743,7 +744,7 @@ next_code:
switch (keycode) {
case 0x37: /* *(numpad)/print screen */
if (state->ks_flags & SHIFTS)
- keycode = 0x5c; /* print screen */
+ keycode = 0x5c; /* print screen */
break;
case 0x45: /* num lock/pause */
if (state->ks_flags & CTLS)
@@ -1177,7 +1178,7 @@ get_kbd_echo(KBDC kbdc)
*/
return ENXIO;
}
-
+
return 0;
}
@@ -1275,7 +1276,7 @@ init_keyboard(KBDC kbdc, int *type, int flags)
}
if (bootverbose)
printf("atkbd: the current kbd controller command byte %04x\n",
- c);
+ c);
#if 0
/* override the keyboard lock switch */
c |= KBD_OVERRIDE_KBD_LOCK;
@@ -1415,52 +1416,49 @@ init_keyboard(KBDC kbdc, int *type, int flags)
static int
write_kbd(KBDC kbdc, int command, int data)
{
- int s;
+ int s;
- /* prevent the timeout routine from polling the keyboard */
- if (!kbdc_lock(kbdc, TRUE))
- return EBUSY;
+ /* prevent the timeout routine from polling the keyboard */
+ if (!kbdc_lock(kbdc, TRUE))
+ return EBUSY;
- /* disable the keyboard and mouse interrupt */
- s = spltty();
+ /* disable the keyboard and mouse interrupt */
+ s = spltty();
#if 0
- c = get_controller_command_byte(kbdc);
- if ((c == -1)
- || !set_controller_command_byte(kbdc,
- kbdc_get_device_mask(kbdc),
- KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
- | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
- /* CONTROLLER ERROR */
- kbdc_lock(kbdc, FALSE);
+ c = get_controller_command_byte(kbdc);
+ if ((c == -1)
+ || !set_controller_command_byte(kbdc,
+ kbdc_get_device_mask(kbdc),
+ KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
+ | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
+ /* CONTROLLER ERROR */
+ kbdc_lock(kbdc, FALSE);
+ splx(s);
+ return EIO;
+ }
+ /*
+ * Now that the keyboard controller is told not to generate
+ * the keyboard and mouse interrupts, call `splx()' to allow
+ * the other tty interrupts. The clock interrupt may also occur,
+ * but the timeout routine (`scrn_timer()') will be blocked
+ * by the lock flag set via `kbdc_lock()'
+ */
splx(s);
- return EIO;
- }
- /*
- * Now that the keyboard controller is told not to generate
- * the keyboard and mouse interrupts, call `splx()' to allow
- * the other tty interrupts. The clock interrupt may also occur,
- * but the timeout routine (`scrn_timer()') will be blocked
- * by the lock flag set via `kbdc_lock()'
- */
- splx(s);
#endif
-
- if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)
- send_kbd_command(kbdc, KBDC_ENABLE_KBD);
-
+ if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)
+ send_kbd_command(kbdc, KBDC_ENABLE_KBD);
#if 0
- /* restore the interrupts */
- if (!set_controller_command_byte(kbdc,
- kbdc_get_device_mask(kbdc),
+ /* restore the interrupts */
+ if (!set_controller_command_byte(kbdc, kbdc_get_device_mask(kbdc),
c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
- /* CONTROLLER ERROR */
- }
+ /* CONTROLLER ERROR */
+ }
#else
- splx(s);
+ splx(s);
#endif
- kbdc_lock(kbdc, FALSE);
+ kbdc_lock(kbdc, FALSE);
- return 0;
+ return 0;
}
static int
diff --git a/sys/dev/atkbdc/atkbd_atkbdc.c b/sys/dev/atkbdc/atkbd_atkbdc.c
index 8181820..dd0a9d6 100644
--- a/sys/dev/atkbdc/atkbd_atkbdc.c
+++ b/sys/dev/atkbdc/atkbd_atkbdc.c
@@ -104,9 +104,7 @@ atkbdprobe(device_t dev)
bus_release_resource(dev, SYS_RES_IRQ, rid, res);
/* probe the device */
- return atkbd_probe_unit(device_get_unit(dev),
- device_get_unit(device_get_parent(dev)),
- irq, flags);
+ return atkbd_probe_unit(dev, irq, flags);
}
static int
@@ -124,9 +122,7 @@ atkbdattach(device_t dev)
rid = KBDC_RID_KBD;
irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid);
flags = device_get_flags(dev);
- error = atkbd_attach_unit(device_get_unit(dev), &kbd,
- device_get_unit(device_get_parent(dev)),
- irq, flags);
+ error = atkbd_attach_unit(dev, &kbd, irq, flags);
if (error)
return error;
diff --git a/sys/dev/atkbdc/atkbdreg.h b/sys/dev/atkbdc/atkbdreg.h
index cf7ee6b..3d09e44 100644
--- a/sys/dev/atkbdc/atkbdreg.h
+++ b/sys/dev/atkbdc/atkbdreg.h
@@ -39,9 +39,8 @@
#ifdef _KERNEL
-int atkbd_probe_unit(int unit, int ctlr, int irq, int flags);
-int atkbd_attach_unit(int unit, keyboard_t **kbd,
- int ctlr, int irq, int flags);
+int atkbd_probe_unit(device_t dev, int irq, int flags);
+int atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags);
#endif
diff --git a/sys/dev/auxio/auxio.c b/sys/dev/auxio/auxio.c
index 35fd307..b104d5a 100644
--- a/sys/dev/auxio/auxio.c
+++ b/sys/dev/auxio/auxio.c
@@ -131,7 +131,8 @@ static device_method_t auxio_sbus_methods[] = {
DEVMETHOD(device_probe, auxio_bus_probe),
DEVMETHOD(device_attach, auxio_sbus_attach),
DEVMETHOD(device_detach, auxio_bus_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t auxio_sbus_driver = {
@@ -151,7 +152,8 @@ static device_method_t auxio_ebus_methods[] = {
DEVMETHOD(device_probe, auxio_bus_probe),
DEVMETHOD(device_attach, auxio_ebus_attach),
DEVMETHOD(device_detach, auxio_bus_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t auxio_ebus_driver = {
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index e7cb2f7..db86ec2 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -35,10 +35,10 @@
__FBSDID("$FreeBSD$");
/*
- * Broadcom BCM570x family gigabit ethernet driver for FreeBSD.
+ * Broadcom BCM57xx(x)/BCM590x NetXtreme and NetLink family Ethernet driver
*
* The Broadcom BCM5700 is based on technology originally developed by
- * Alteon Networks as part of the Tigon I and Tigon II gigabit ethernet
+ * Alteon Networks as part of the Tigon I and Tigon II Gigabit Ethernet
* MAC chips. The BCM5700, sometimes referred to as the Tigon III, has
* two on-board MIPS R4000 CPUs and can have as much as 16MB of external
* SSRAM. The BCM5700 supports TCP, UDP and IP checksum offload, jumbo
@@ -367,8 +367,9 @@ static const struct bge_revision bge_majorrevs[] = {
#define BGE_IS_5717_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5717_PLUS)
#define BGE_IS_57765_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_57765_PLUS)
-const struct bge_revision * bge_lookup_rev(uint32_t);
-const struct bge_vendor * bge_lookup_vendor(uint16_t);
+static uint32_t bge_chipid(device_t);
+static const struct bge_vendor * bge_lookup_vendor(uint16_t);
+static const struct bge_revision * bge_lookup_rev(uint32_t);
typedef int (*bge_eaddr_fcn_t)(struct bge_softc *, uint8_t[]);
@@ -1916,7 +1917,7 @@ bge_chipinit(struct bge_softc *sc)
PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD,
PCIM_CMD_INTxDIS | PCIM_CMD_MWIEN, 4);
- /* Set the timer prescaler (always 66Mhz) */
+ /* Set the timer prescaler (always 66 MHz). */
CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
/* XXX: The Linux tg3 driver does this at the start of brgphy_reset. */
@@ -2586,7 +2587,7 @@ bge_blockinit(struct bge_softc *sc)
return (0);
}
-const struct bge_revision *
+static const struct bge_revision *
bge_lookup_rev(uint32_t chipid)
{
const struct bge_revision *br;
@@ -2604,7 +2605,7 @@ bge_lookup_rev(uint32_t chipid)
return (NULL);
}
-const struct bge_vendor *
+static const struct bge_vendor *
bge_lookup_vendor(uint16_t vid)
{
const struct bge_vendor *v;
@@ -2613,10 +2614,47 @@ bge_lookup_vendor(uint16_t vid)
if (v->v_id == vid)
return (v);
- panic("%s: unknown vendor %d", __func__, vid);
return (NULL);
}
+static uint32_t
+bge_chipid(device_t dev)
+{
+ uint32_t id;
+
+ id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
+ BGE_PCIMISCCTL_ASICREV_SHIFT;
+ if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) {
+ /*
+ * Find the ASCI revision. Different chips use different
+ * registers.
+ */
+ switch (pci_get_device(dev)) {
+ case BCOM_DEVICEID_BCM5717:
+ case BCOM_DEVICEID_BCM5718:
+ case BCOM_DEVICEID_BCM5719:
+ case BCOM_DEVICEID_BCM5720:
+ id = pci_read_config(dev,
+ BGE_PCI_GEN2_PRODID_ASICREV, 4);
+ break;
+ case BCOM_DEVICEID_BCM57761:
+ case BCOM_DEVICEID_BCM57762:
+ case BCOM_DEVICEID_BCM57765:
+ case BCOM_DEVICEID_BCM57766:
+ case BCOM_DEVICEID_BCM57781:
+ case BCOM_DEVICEID_BCM57785:
+ case BCOM_DEVICEID_BCM57791:
+ case BCOM_DEVICEID_BCM57795:
+ id = pci_read_config(dev,
+ BGE_PCI_GEN15_PRODID_ASICREV, 4);
+ break;
+ default:
+ id = pci_read_config(dev, BGE_PCI_PRODID_ASICREV, 4);
+ }
+ }
+ return (id);
+}
+
/*
* Probe for a Broadcom chip. Check the PCI vendor and device IDs
* against our list and return its name if we find a match.
@@ -2634,61 +2672,34 @@ bge_probe(device_t dev)
char model[64];
const struct bge_revision *br;
const char *pname;
- struct bge_softc *sc = device_get_softc(dev);
+ struct bge_softc *sc;
const struct bge_type *t = bge_devs;
const struct bge_vendor *v;
uint32_t id;
uint16_t did, vid;
+ sc = device_get_softc(dev);
sc->bge_dev = dev;
vid = pci_get_vendor(dev);
did = pci_get_device(dev);
while(t->bge_vid != 0) {
if ((vid == t->bge_vid) && (did == t->bge_did)) {
- id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
- BGE_PCIMISCCTL_ASICREV_SHIFT;
- if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) {
- /*
- * Find the ASCI revision. Different chips
- * use different registers.
- */
- switch (pci_get_device(dev)) {
- case BCOM_DEVICEID_BCM5717:
- case BCOM_DEVICEID_BCM5718:
- case BCOM_DEVICEID_BCM5719:
- case BCOM_DEVICEID_BCM5720:
- id = pci_read_config(dev,
- BGE_PCI_GEN2_PRODID_ASICREV, 4);
- break;
- case BCOM_DEVICEID_BCM57761:
- case BCOM_DEVICEID_BCM57762:
- case BCOM_DEVICEID_BCM57765:
- case BCOM_DEVICEID_BCM57766:
- case BCOM_DEVICEID_BCM57781:
- case BCOM_DEVICEID_BCM57785:
- case BCOM_DEVICEID_BCM57791:
- case BCOM_DEVICEID_BCM57795:
- id = pci_read_config(dev,
- BGE_PCI_GEN15_PRODID_ASICREV, 4);
- break;
- default:
- id = pci_read_config(dev,
- BGE_PCI_PRODID_ASICREV, 4);
- }
- }
+ id = bge_chipid(dev);
br = bge_lookup_rev(id);
- v = bge_lookup_vendor(vid);
if (bge_has_eaddr(sc) &&
pci_get_vpd_ident(dev, &pname) == 0)
- snprintf(model, 64, "%s", pname);
- else
- snprintf(model, 64, "%s %s", v->v_name,
+ snprintf(model, sizeof(model), "%s", pname);
+ else {
+ v = bge_lookup_vendor(vid);
+ snprintf(model, sizeof(model), "%s %s",
+ v != NULL ? v->v_name : "Unknown",
br != NULL ? br->br_name :
- "NetXtreme Ethernet Controller");
- snprintf(buf, 96, "%s, %sASIC rev. %#08x", model,
- br != NULL ? "" : "unknown ", id);
+ "NetXtreme/NetLink Ethernet Controller");
+ }
+ snprintf(buf, sizeof(buf), "%s, %sASIC rev. %#08x",
+ model, br != NULL ? "" : "unknown ", id);
device_set_desc_copy(dev, buf);
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
t++;
}
@@ -3247,38 +3258,7 @@ bge_attach(device_t dev)
/* Save various chip information. */
sc->bge_func_addr = pci_get_function(dev);
- sc->bge_chipid =
- pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
- BGE_PCIMISCCTL_ASICREV_SHIFT;
- if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_USE_PRODID_REG) {
- /*
- * Find the ASCI revision. Different chips use different
- * registers.
- */
- switch (pci_get_device(dev)) {
- case BCOM_DEVICEID_BCM5717:
- case BCOM_DEVICEID_BCM5718:
- case BCOM_DEVICEID_BCM5719:
- case BCOM_DEVICEID_BCM5720:
- sc->bge_chipid = pci_read_config(dev,
- BGE_PCI_GEN2_PRODID_ASICREV, 4);
- break;
- case BCOM_DEVICEID_BCM57761:
- case BCOM_DEVICEID_BCM57762:
- case BCOM_DEVICEID_BCM57765:
- case BCOM_DEVICEID_BCM57766:
- case BCOM_DEVICEID_BCM57781:
- case BCOM_DEVICEID_BCM57785:
- case BCOM_DEVICEID_BCM57791:
- case BCOM_DEVICEID_BCM57795:
- sc->bge_chipid = pci_read_config(dev,
- BGE_PCI_GEN15_PRODID_ASICREV, 4);
- break;
- default:
- sc->bge_chipid = pci_read_config(dev,
- BGE_PCI_PRODID_ASICREV, 4);
- }
- }
+ sc->bge_chipid = bge_chipid(dev);
sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
@@ -3468,6 +3448,8 @@ bge_attach(device_t dev)
pci_get_device(dev) == BCOM_DEVICEID_BCM5753F ||
pci_get_device(dev) == BCOM_DEVICEID_BCM5787F)) ||
pci_get_device(dev) == BCOM_DEVICEID_BCM57790 ||
+ pci_get_device(dev) == BCOM_DEVICEID_BCM57791 ||
+ pci_get_device(dev) == BCOM_DEVICEID_BCM57795 ||
sc->bge_asicrev == BGE_ASICREV_BCM5906) {
/* These chips are 10/100 only. */
capmask &= ~BMSR_EXTSTAT;
@@ -3479,8 +3461,8 @@ bge_attach(device_t dev)
* TSO. But the firmware is not available to FreeBSD and Linux
* claims that the TSO performed by the firmware is slower than
* hardware based TSO. Moreover the firmware based TSO has one
- * known bug which can't handle TSO if ethernet header + IP/TCP
- * header is greater than 80 bytes. The workaround for the TSO
+ * known bug which can't handle TSO if Ethernet header + IP/TCP
+ * header is greater than 80 bytes. A workaround for the TSO
* bug exist but it seems it's too expensive than not using
* TSO at all. Some hardwares also have the TSO bug so limit
* the TSO to the controllers that are not affected TSO issues
@@ -3853,8 +3835,13 @@ again:
error = ENOMEM;
goto fail;
}
- taskqueue_start_threads(&sc->bge_tq, 1, PI_NET, "%s taskq",
- device_get_nameunit(sc->bge_dev));
+ error = taskqueue_start_threads(&sc->bge_tq, 1, PI_NET,
+ "%s taskq", device_get_nameunit(sc->bge_dev));
+ if (error != 0) {
+ device_printf(dev, "could not start threads.\n");
+ ether_ifdetach(ifp);
+ goto fail;
+ }
error = bus_setup_intr(dev, sc->bge_irq,
INTR_TYPE_NET | INTR_MPSAFE, bge_msi_intr, NULL, sc,
&sc->bge_intrhand);
@@ -3899,9 +3886,9 @@ bge_detach(device_t dev)
if (sc->bge_tq)
taskqueue_drain(sc->bge_tq, &sc->bge_intr_task);
- if (sc->bge_flags & BGE_FLAG_TBI) {
+ if (sc->bge_flags & BGE_FLAG_TBI)
ifmedia_removeall(&sc->bge_ifmedia);
- } else {
+ else if (sc->bge_miibus != NULL) {
bus_generic_detach(dev);
device_delete_child(dev, sc->bge_miibus);
}
@@ -5427,7 +5414,7 @@ bge_init_locked(struct bge_softc *sc)
* this number of frames, it will drop subsequent incoming
* frames until the MBUF High Watermark is reached.
*/
- if (sc->bge_asicrev == BGE_ASICREV_BCM57765)
+ if (BGE_IS_57765_PLUS(sc))
CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1);
else
CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2);
diff --git a/sys/dev/bktr/CHANGELOG.TXT b/sys/dev/bktr/CHANGELOG.TXT
index b885e15..b885e15 100755..100644
--- a/sys/dev/bktr/CHANGELOG.TXT
+++ b/sys/dev/bktr/CHANGELOG.TXT
diff --git a/sys/dev/bvm/bvm_console.c b/sys/dev/bvm/bvm_console.c
new file mode 100644
index 0000000..a0e70e5
--- /dev/null
+++ b/sys/dev/bvm/bvm_console.c
@@ -0,0 +1,240 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/cons.h>
+#include <sys/tty.h>
+#include <sys/reboot.h>
+#include <sys/bus.h>
+
+#include <sys/kdb.h>
+#include <ddb/ddb.h>
+
+#ifndef BVMCONS_POLL_HZ
+#define BVMCONS_POLL_HZ 4
+#endif
+#define BVMBURSTLEN 16 /* max number of bytes to write in one chunk */
+
+static tsw_open_t bvm_tty_open;
+static tsw_close_t bvm_tty_close;
+static tsw_outwakeup_t bvm_tty_outwakeup;
+
+static struct ttydevsw bvm_ttydevsw = {
+ .tsw_flags = TF_NOPREFIX,
+ .tsw_open = bvm_tty_open,
+ .tsw_close = bvm_tty_close,
+ .tsw_outwakeup = bvm_tty_outwakeup,
+};
+
+static int polltime;
+static struct callout_handle bvm_timeouthandle
+ = CALLOUT_HANDLE_INITIALIZER(&bvm_timeouthandle);
+
+#if defined(KDB)
+static int alt_break_state;
+#endif
+
+#define BVM_CONS_PORT 0x220
+static int bvm_cons_port = BVM_CONS_PORT;
+
+#define BVM_CONS_SIG ('b' << 8 | 'v')
+
+static void bvm_timeout(void *);
+
+static cn_probe_t bvm_cnprobe;
+static cn_init_t bvm_cninit;
+static cn_term_t bvm_cnterm;
+static cn_getc_t bvm_cngetc;
+static cn_putc_t bvm_cnputc;
+static cn_grab_t bvm_cngrab;
+static cn_ungrab_t bvm_cnungrab;
+
+CONSOLE_DRIVER(bvm);
+
+static int
+bvm_rcons(u_char *ch)
+{
+ int c;
+
+ c = inl(bvm_cons_port);
+ if (c != -1) {
+ *ch = (u_char)c;
+ return (0);
+ } else
+ return (-1);
+}
+
+static void
+bvm_wcons(u_char ch)
+{
+
+ outl(bvm_cons_port, ch);
+}
+
+static void
+cn_drvinit(void *unused)
+{
+ struct tty *tp;
+
+ if (bvm_consdev.cn_pri != CN_DEAD &&
+ bvm_consdev.cn_name[0] != '\0') {
+ tp = tty_alloc(&bvm_ttydevsw, NULL);
+ tty_makedev(tp, NULL, "bvmcons");
+ }
+}
+
+static int
+bvm_tty_open(struct tty *tp)
+{
+ polltime = hz / BVMCONS_POLL_HZ;
+ if (polltime < 1)
+ polltime = 1;
+ bvm_timeouthandle = timeout(bvm_timeout, tp, polltime);
+
+ return (0);
+}
+
+static void
+bvm_tty_close(struct tty *tp)
+{
+
+ /* XXX Should be replaced with callout_stop(9) */
+ untimeout(bvm_timeout, tp, bvm_timeouthandle);
+}
+
+static void
+bvm_tty_outwakeup(struct tty *tp)
+{
+ int len, written;
+ u_char buf[BVMBURSTLEN];
+
+ for (;;) {
+ len = ttydisc_getc(tp, buf, sizeof(buf));
+ if (len == 0)
+ break;
+
+ written = 0;
+ while (written < len)
+ bvm_wcons(buf[written++]);
+ }
+}
+
+static void
+bvm_timeout(void *v)
+{
+ struct tty *tp;
+ int c;
+
+ tp = (struct tty *)v;
+
+ tty_lock(tp);
+ while ((c = bvm_cngetc(NULL)) != -1)
+ ttydisc_rint(tp, c, 0);
+ ttydisc_rint_done(tp);
+ tty_unlock(tp);
+
+ bvm_timeouthandle = timeout(bvm_timeout, tp, polltime);
+}
+
+static void
+bvm_cnprobe(struct consdev *cp)
+{
+ int disabled, port;
+
+ disabled = 0;
+ cp->cn_pri = CN_DEAD;
+
+ resource_int_value("bvmconsole", 0, "disabled", &disabled);
+ if (!disabled) {
+ if (resource_int_value("bvmconsole", 0, "port", &port) == 0)
+ bvm_cons_port = port;
+
+ if (inw(bvm_cons_port) == BVM_CONS_SIG)
+ cp->cn_pri = CN_REMOTE;
+ }
+}
+
+static void
+bvm_cninit(struct consdev *cp)
+{
+ int i;
+ const char *bootmsg = "Using bvm console.\n";
+
+ if (boothowto & RB_VERBOSE) {
+ for (i = 0; i < strlen(bootmsg); i++)
+ bvm_cnputc(cp, bootmsg[i]);
+ }
+
+ strcpy(cp->cn_name, "bvmcons");
+}
+
+static void
+bvm_cnterm(struct consdev *cp)
+{
+
+}
+
+static int
+bvm_cngetc(struct consdev *cp)
+{
+ unsigned char ch;
+
+ if (bvm_rcons(&ch) == 0) {
+#if defined(KDB)
+ kdb_alt_break(ch, &alt_break_state);
+#endif
+ return (ch);
+ }
+
+ return (-1);
+}
+
+static void
+bvm_cnputc(struct consdev *cp, int c)
+{
+
+ bvm_wcons(c);
+}
+
+static void
+bvm_cngrab(struct consdev *cp)
+{
+}
+
+static void
+bvm_cnungrab(struct consdev *cp)
+{
+}
+
+SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL);
diff --git a/sys/dev/bvm/bvm_dbg.c b/sys/dev/bvm/bvm_dbg.c
new file mode 100644
index 0000000..1ba7ce0
--- /dev/null
+++ b/sys/dev/bvm/bvm_dbg.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+
+#include <gdb/gdb.h>
+
+#include <machine/cpufunc.h>
+
+static gdb_probe_f bvm_dbg_probe;
+static gdb_init_f bvm_dbg_init;
+static gdb_term_f bvm_dbg_term;
+static gdb_getc_f bvm_dbg_getc;
+static gdb_putc_f bvm_dbg_putc;
+
+GDB_DBGPORT(bvm, bvm_dbg_probe, bvm_dbg_init, bvm_dbg_term,
+ bvm_dbg_getc, bvm_dbg_putc);
+
+#define BVM_DBG_PORT 0x224
+static int bvm_dbg_port = BVM_DBG_PORT;
+
+#define BVM_DBG_SIG ('B' << 8 | 'V')
+
+static int
+bvm_dbg_probe(void)
+{
+ int disabled, port;
+
+ disabled = 0;
+ resource_int_value("bvmdbg", 0, "disabled", &disabled);
+
+ if (!disabled) {
+ if (resource_int_value("bvmdbg", 0, "port", &port) == 0)
+ bvm_dbg_port = port;
+
+ if (inw(bvm_dbg_port) == BVM_DBG_SIG) {
+ /*
+ * Return a higher priority than 0 to override other
+ * gdb dbgport providers that may be present (e.g. uart)
+ */
+ return (1);
+ }
+ }
+
+ return (-1);
+}
+
+static void
+bvm_dbg_init(void)
+{
+}
+
+static void
+bvm_dbg_term(void)
+{
+}
+
+static void
+bvm_dbg_putc(int c)
+{
+
+ outl(bvm_dbg_port, c);
+}
+
+static int
+bvm_dbg_getc(void)
+{
+
+ return (inl(bvm_dbg_port));
+}
diff --git a/sys/dev/cas/if_cas.c b/sys/dev/cas/if_cas.c
index f846350..f98d4f0 100644
--- a/sys/dev/cas/if_cas.c
+++ b/sys/dev/cas/if_cas.c
@@ -214,8 +214,12 @@ cas_attach(struct cas_softc *sc)
error = ENXIO;
goto fail_ifnet;
}
- taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
+ error = taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
device_get_nameunit(sc->sc_dev));
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not start threads\n");
+ goto fail_taskq;
+ }
/* Make sure the chip is stopped. */
cas_reset(sc);
@@ -339,10 +343,13 @@ cas_attach(struct cas_softc *sc)
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
/* Enable/unfreeze the GMII pins of Saturn. */
if (sc->sc_variant == CAS_SATURN) {
- CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0);
+ CAS_WRITE_4(sc, CAS_SATURN_PCFG,
+ CAS_READ_4(sc, CAS_SATURN_PCFG) &
+ ~CAS_SATURN_PCFG_FSI);
CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
BUS_SPACE_BARRIER_READ |
BUS_SPACE_BARRIER_WRITE);
+ DELAY(10000);
}
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK,
@@ -359,10 +366,12 @@ cas_attach(struct cas_softc *sc)
/* Freeze the GMII pins of Saturn for saving power. */
if (sc->sc_variant == CAS_SATURN) {
CAS_WRITE_4(sc, CAS_SATURN_PCFG,
+ CAS_READ_4(sc, CAS_SATURN_PCFG) |
CAS_SATURN_PCFG_FSI);
CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
BUS_SPACE_BARRIER_READ |
BUS_SPACE_BARRIER_WRITE);
+ DELAY(10000);
}
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK,
@@ -2865,7 +2874,7 @@ cas_pci_attach(device_t dev)
goto fail;
}
i = 0;
- if (lma > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr))
+ if (lma > 1 && pci_get_slot(dev) < nitems(enaddr))
i = pci_get_slot(dev);
memcpy(sc->sc_enaddr, enaddr[i], ETHER_ADDR_LEN);
@@ -2874,7 +2883,7 @@ cas_pci_attach(device_t dev)
goto fail;
}
i = 0;
- if (phy > 1 && pci_get_slot(dev) < sizeof(pcs) / sizeof(*pcs))
+ if (phy > 1 && pci_get_slot(dev) < nitems(pcs))
i = pci_get_slot(dev);
if (pcs[i] != 0)
sc->sc_flags |= CAS_SERDES;
diff --git a/sys/dev/ce/if_ce.c b/sys/dev/ce/if_ce.c
index 700ab80a..3f1a550 100644
--- a/sys/dev/ce/if_ce.c
+++ b/sys/dev/ce/if_ce.c
@@ -145,7 +145,7 @@ static device_method_t ce_methods[] = {
DEVMETHOD(device_attach, ce_attach),
DEVMETHOD(device_detach, ce_detach),
- {0, 0}
+ DEVMETHOD_END
};
typedef struct _ce_dma_mem_t {
diff --git a/sys/dev/cfi/cfi_bus_fdt.c b/sys/dev/cfi/cfi_bus_fdt.c
index bfbd65f..f775e05 100644
--- a/sys/dev/cfi/cfi_bus_fdt.c
+++ b/sys/dev/cfi/cfi_bus_fdt.c
@@ -51,7 +51,7 @@ static device_method_t cfi_fdt_methods[] = {
DEVMETHOD(device_attach, cfi_attach),
DEVMETHOD(device_detach, cfi_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t cfi_fdt_driver = {
diff --git a/sys/dev/cfi/cfi_bus_ixp4xx.c b/sys/dev/cfi/cfi_bus_ixp4xx.c
index ef9da9ee..93d03fe 100644
--- a/sys/dev/cfi/cfi_bus_ixp4xx.c
+++ b/sys/dev/cfi/cfi_bus_ixp4xx.c
@@ -69,7 +69,7 @@ static device_method_t cfi_ixp4xx_methods[] = {
DEVMETHOD(device_attach, cfi_attach),
DEVMETHOD(device_detach, cfi_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t cfi_ixp4xx_driver = {
diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c
index 3291f03..a3f0a4a 100644
--- a/sys/dev/ciss/ciss.c
+++ b/sys/dev/ciss/ciss.c
@@ -1203,13 +1203,21 @@ ciss_identify_adapter(struct ciss_softc *sc)
/* XXX only really required for old 5300 adapters? */
sc->ciss_flags |= CISS_FLAG_BMIC_ABORT;
+ /*
+ * Earlier controller specs do not contain these config
+ * entries, so assume that a 0 means its old and assign
+ * these values to the defaults that were established
+ * when this driver was developed for them
+ */
+ if (sc->ciss_cfg->max_logical_supported == 0)
+ sc->ciss_cfg->max_logical_supported = CISS_MAX_LOGICAL;
+ if (sc->ciss_cfg->max_physical_supported == 0)
+ sc->ciss_cfg->max_physical_supported = CISS_MAX_PHYSICAL;
/* print information */
if (bootverbose) {
-#if 0 /* XXX proxy volumes??? */
ciss_printf(sc, " %d logical drive%s configured\n",
sc->ciss_id->configured_logical_drives,
(sc->ciss_id->configured_logical_drives == 1) ? "" : "s");
-#endif
ciss_printf(sc, " firmware %4.4s\n", sc->ciss_id->running_firmware_revision);
ciss_printf(sc, " %d SCSI channels\n", sc->ciss_id->scsi_bus_count);
@@ -1232,6 +1240,9 @@ ciss_identify_adapter(struct ciss_softc *sc)
"\20\1ultra2\2ultra3\10fibre1\11fibre2\n");
ciss_printf(sc, " server name '%.16s'\n", sc->ciss_cfg->server_name);
ciss_printf(sc, " heartbeat 0x%x\n", sc->ciss_cfg->heartbeat);
+ ciss_printf(sc, " max logical logical volumes: %d\n", sc->ciss_cfg->max_logical_supported);
+ ciss_printf(sc, " max physical disks supported: %d\n", sc->ciss_cfg->max_physical_supported);
+ ciss_printf(sc, " max physical disks per logical volume: %d\n", sc->ciss_cfg->max_physical_per_logical);
}
out:
@@ -1319,7 +1330,7 @@ ciss_report_luns(struct ciss_softc *sc, int opcode, int nunits)
break;
case CISS_CMD_STATUS_DATA_OVERRUN:
ciss_printf(sc, "WARNING: more units than driver limit (%d)\n",
- CISS_MAX_LOGICAL);
+ sc->ciss_cfg->max_logical_supported);
break;
default:
ciss_printf(sc, "error detecting logical drive configuration (%s)\n",
@@ -1353,7 +1364,7 @@ ciss_init_logical(struct ciss_softc *sc)
debug_called(1);
cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_LOGICAL_LUNS,
- CISS_MAX_LOGICAL);
+ sc->ciss_cfg->max_logical_supported);
if (cll == NULL) {
error = ENXIO;
goto out;
@@ -1361,9 +1372,9 @@ ciss_init_logical(struct ciss_softc *sc)
/* sanity-check reply */
ndrives = (ntohl(cll->list_size) / sizeof(union ciss_device_address));
- if ((ndrives < 0) || (ndrives > CISS_MAX_LOGICAL)) {
+ if ((ndrives < 0) || (ndrives > sc->ciss_cfg->max_logical_supported)) {
ciss_printf(sc, "adapter claims to report absurd number of logical drives (%d > %d)\n",
- ndrives, CISS_MAX_LOGICAL);
+ ndrives, sc->ciss_cfg->max_logical_supported);
error = ENXIO;
goto out;
}
@@ -1386,19 +1397,20 @@ ciss_init_logical(struct ciss_softc *sc)
for (i = 0; i <= sc->ciss_max_logical_bus; i++) {
sc->ciss_logical[i] =
- malloc(CISS_MAX_LOGICAL * sizeof(struct ciss_ldrive),
+ malloc(sc->ciss_cfg->max_logical_supported *
+ sizeof(struct ciss_ldrive),
CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO);
if (sc->ciss_logical[i] == NULL) {
error = ENXIO;
goto out;
}
- for (j = 0; j < CISS_MAX_LOGICAL; j++)
+ for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++)
sc->ciss_logical[i][j].cl_status = CISS_LD_NONEXISTENT;
}
- for (i = 0; i < CISS_MAX_LOGICAL; i++) {
+ for (i = 0; i < sc->ciss_cfg->max_logical_supported; i++) {
if (i < ndrives) {
struct ciss_ldrive *ld;
int bus, target;
@@ -1440,7 +1452,7 @@ ciss_init_physical(struct ciss_softc *sc)
target = 0;
cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_PHYSICAL_LUNS,
- CISS_MAX_PHYSICAL);
+ sc->ciss_cfg->max_physical_supported);
if (cll == NULL) {
error = ENXIO;
goto out;
@@ -1983,7 +1995,7 @@ ciss_free(struct ciss_softc *sc)
bus_dma_tag_destroy(sc->ciss_parent_dmat);
if (sc->ciss_logical) {
for (i = 0; i <= sc->ciss_max_logical_bus; i++) {
- for (j = 0; j < CISS_MAX_LOGICAL; j++) {
+ for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) {
if (sc->ciss_logical[i][j].cl_ldrive)
free(sc->ciss_logical[i][j].cl_ldrive, CISS_MALLOC_CLASS);
if (sc->ciss_logical[i][j].cl_lstatus)
@@ -2966,9 +2978,9 @@ ciss_cam_action(struct cam_sim *sim, union ccb *ccb)
cpi->hba_inquiry = PI_TAG_ABLE; /* XXX is this correct? */
cpi->target_sprt = 0;
cpi->hba_misc = 0;
- cpi->max_target = CISS_MAX_LOGICAL;
+ cpi->max_target = sc->ciss_cfg->max_logical_supported;
cpi->max_lun = 0; /* 'logical drive' channel only */
- cpi->initiator_id = CISS_MAX_LOGICAL;
+ cpi->initiator_id = sc->ciss_cfg->max_logical_supported;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "msmith@freebsd.org", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
@@ -3879,7 +3891,7 @@ ciss_notify_rescan_logical(struct ciss_softc *sc)
* drive address.
*/
cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_LOGICAL_LUNS,
- CISS_MAX_LOGICAL);
+ sc->ciss_cfg->max_logical_supported);
if (cll == NULL)
return;
@@ -3890,7 +3902,7 @@ ciss_notify_rescan_logical(struct ciss_softc *sc)
* firmware.
*/
for (i = 0; i < sc->ciss_max_logical_bus; i++) {
- for (j = 0; j < CISS_MAX_LOGICAL; j++) {
+ for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) {
ld = &sc->ciss_logical[i][j];
if (ld->cl_update == 0)
@@ -4059,7 +4071,7 @@ ciss_notify_hotplug(struct ciss_softc *sc, struct ciss_notify *cn)
* Rescan the physical lun list for new items
*/
cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_PHYSICAL_LUNS,
- CISS_MAX_PHYSICAL);
+ sc->ciss_cfg->max_physical_supported);
if (cll == NULL) {
ciss_printf(sc, "Warning, cannot get physical lun list\n");
break;
@@ -4307,7 +4319,7 @@ ciss_print_adapter(struct ciss_softc *sc)
"\20\1notify_ok\2control_open\3aborting\4running\21fake_synch\22bmic_abort\n");
for (i = 0; i < sc->ciss_max_logical_bus; i++) {
- for (j = 0; j < CISS_MAX_LOGICAL; j++) {
+ for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) {
ciss_printf(sc, "LOGICAL DRIVE %d: ", i);
ciss_print_ldrive(sc, &sc->ciss_logical[i][j]);
}
diff --git a/sys/dev/ciss/cissreg.h b/sys/dev/ciss/cissreg.h
index feae826..4a3349f 100644
--- a/sys/dev/ciss/cissreg.h
+++ b/sys/dev/ciss/cissreg.h
@@ -425,6 +425,15 @@ struct ciss_config_table
#define CISS_DRIVER_DAUGHTER_ATTACHED (1<<8)
#define CISS_DRIVER_SCSI_PREFETCH (1<<9)
u_int32_t max_sg_length; /* 31 in older firmware */
+/*
+ * these fields appear in OpenCISS Spec 1.06
+ * http://cciss.sourceforge.net/#docs
+ */
+ u_int32_t max_logical_supported;
+ u_int32_t max_physical_supported;
+ u_int32_t max_physical_per_logical;
+ u_int32_t max_perfomant_mode_cmds;
+ u_int32_t max_block_fetch_count;
} __packed;
/*
diff --git a/sys/dev/ciss/cissvar.h b/sys/dev/ciss/cissvar.h
index d109b7a..e89e4e9 100644
--- a/sys/dev/ciss/cissvar.h
+++ b/sys/dev/ciss/cissvar.h
@@ -45,8 +45,11 @@ typedef STAILQ_HEAD(, ciss_request) cr_qhead_t;
/*
* Maximum number of logical drives we support.
+ * If the controller does not indicate a maximum
+ * value. This is a compatibiliy value to support
+ * older ciss controllers (e.g. model 6i)
*/
-#define CISS_MAX_LOGICAL 63
+#define CISS_MAX_LOGICAL 16
/*
* Maximum number of physical devices we support.
diff --git a/sys/dev/coretemp/coretemp.c b/sys/dev/coretemp/coretemp.c
index 54e5a43..55efca2 100644
--- a/sys/dev/coretemp/coretemp.c
+++ b/sys/dev/coretemp/coretemp.c
@@ -85,7 +85,7 @@ static device_method_t coretemp_methods[] = {
DEVMETHOD(device_attach, coretemp_attach),
DEVMETHOD(device_detach, coretemp_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t coretemp_driver = {
diff --git a/sys/dev/cp/if_cp.c b/sys/dev/cp/if_cp.c
index 4ff0bcc..299a51c 100644
--- a/sys/dev/cp/if_cp.c
+++ b/sys/dev/cp/if_cp.c
@@ -93,7 +93,7 @@ static device_method_t cp_methods[] = {
DEVMETHOD(device_attach, cp_attach),
DEVMETHOD(device_detach, cp_detach),
- {0, 0}
+ DEVMETHOD_END
};
typedef struct _cp_dma_mem_t {
diff --git a/sys/dev/cpufreq/ichss.c b/sys/dev/cpufreq/ichss.c
index fc7f0ac..0eae0c9 100644
--- a/sys/dev/cpufreq/ichss.c
+++ b/sys/dev/cpufreq/ichss.c
@@ -113,7 +113,7 @@ static device_method_t ichss_methods[] = {
DEVMETHOD(cpufreq_drv_get, ichss_get),
DEVMETHOD(cpufreq_drv_type, ichss_type),
DEVMETHOD(cpufreq_drv_settings, ichss_settings),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ichss_driver = {
"ichss", ichss_methods, sizeof(struct ichss_softc)
diff --git a/sys/dev/ctau/if_ct.c b/sys/dev/ctau/if_ct.c
index 7b4abc3..fc3e916 100644
--- a/sys/dev/ctau/if_ct.c
+++ b/sys/dev/ctau/if_ct.c
@@ -93,7 +93,8 @@ static device_method_t ct_isa_methods [] = {
DEVMETHOD(device_probe, ct_probe),
DEVMETHOD(device_attach, ct_attach),
DEVMETHOD(device_detach, ct_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
typedef struct _ct_dma_mem_t {
diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c
index cb15486..ad8312c 100644
--- a/sys/dev/cx/if_cx.c
+++ b/sys/dev/cx/if_cx.c
@@ -113,7 +113,8 @@ static device_method_t cx_isa_methods [] = {
DEVMETHOD(device_probe, cx_probe),
DEVMETHOD(device_attach, cx_attach),
DEVMETHOD(device_detach, cx_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
typedef struct _cx_dma_mem_t {
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index c1d8a6b..55cfa52 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -158,6 +158,16 @@ enum {
};
enum {
+ /* flags understood by begin_synchronized_op */
+ HOLD_LOCK = (1 << 0),
+ SLEEP_OK = (1 << 1),
+ INTR_OK = (1 << 2),
+
+ /* flags understood by end_synchronized_op */
+ LOCK_HELD = HOLD_LOCK,
+};
+
+enum {
/* adapter flags */
FULL_INIT_DONE = (1 << 0),
FW_OK = (1 << 1),
@@ -174,11 +184,11 @@ enum {
PORT_SYSCTL_CTX = (1 << 2),
};
-#define IS_DOOMED(pi) (pi->flags & DOOMED)
-#define SET_DOOMED(pi) do {pi->flags |= DOOMED;} while (0)
-#define IS_BUSY(sc) (sc->flags & CXGBE_BUSY)
-#define SET_BUSY(sc) do {sc->flags |= CXGBE_BUSY;} while (0)
-#define CLR_BUSY(sc) do {sc->flags &= ~CXGBE_BUSY;} while (0)
+#define IS_DOOMED(pi) ((pi)->flags & DOOMED)
+#define SET_DOOMED(pi) do {(pi)->flags |= DOOMED;} while (0)
+#define IS_BUSY(sc) ((sc)->flags & CXGBE_BUSY)
+#define SET_BUSY(sc) do {(sc)->flags |= CXGBE_BUSY;} while (0)
+#define CLR_BUSY(sc) do {(sc)->flags &= ~CXGBE_BUSY;} while (0)
struct port_info {
device_t dev;
@@ -567,7 +577,8 @@ struct adapter {
int flags;
char fw_version[32];
- unsigned int cfcsum;
+ char cfg_file[32];
+ u_int cfcsum;
struct adapter_params params;
struct t4_virt_res vres;
@@ -591,6 +602,11 @@ struct adapter {
an_handler_t an_handler __aligned(CACHE_LINE_SIZE);
fw_msg_handler_t fw_msg_handler[4]; /* NUM_FW6_TYPES */
cpl_handler_t cpl_handler[0xef]; /* NUM_CPL_CMDS */
+
+#ifdef INVARIANTS
+ const char *last_op;
+ const void *last_op_thr;
+#endif
};
#define ADAPTER_LOCK(sc) mtx_lock(&(sc)->sc_lock)
@@ -598,6 +614,12 @@ struct adapter {
#define ADAPTER_LOCK_ASSERT_OWNED(sc) mtx_assert(&(sc)->sc_lock, MA_OWNED)
#define ADAPTER_LOCK_ASSERT_NOTOWNED(sc) mtx_assert(&(sc)->sc_lock, MA_NOTOWNED)
+/* XXX: not bulletproof, but much better than nothing */
+#define ASSERT_SYNCHRONIZED_OP(sc) \
+ KASSERT(IS_BUSY(sc) && \
+ (mtx_owned(&(sc)->sc_lock) || sc->last_op_thr == curthread), \
+ ("%s: operation not synchronized.", __func__))
+
#define PORT_LOCK(pi) mtx_lock(&(pi)->pi_lock)
#define PORT_UNLOCK(pi) mtx_unlock(&(pi)->pi_lock)
#define PORT_LOCK_ASSERT_OWNED(pi) mtx_assert(&(pi)->pi_lock, MA_OWNED)
@@ -626,18 +648,18 @@ struct adapter {
#define TXQ_LOCK_ASSERT_OWNED(txq) EQ_LOCK_ASSERT_OWNED(&(txq)->eq)
#define TXQ_LOCK_ASSERT_NOTOWNED(txq) EQ_LOCK_ASSERT_NOTOWNED(&(txq)->eq)
-#define for_each_txq(pi, iter, txq) \
- txq = &pi->adapter->sge.txq[pi->first_txq]; \
- for (iter = 0; iter < pi->ntxq; ++iter, ++txq)
-#define for_each_rxq(pi, iter, rxq) \
- rxq = &pi->adapter->sge.rxq[pi->first_rxq]; \
- for (iter = 0; iter < pi->nrxq; ++iter, ++rxq)
-#define for_each_ofld_txq(pi, iter, ofld_txq) \
- ofld_txq = &pi->adapter->sge.ofld_txq[pi->first_ofld_txq]; \
- for (iter = 0; iter < pi->nofldtxq; ++iter, ++ofld_txq)
-#define for_each_ofld_rxq(pi, iter, ofld_rxq) \
- ofld_rxq = &pi->adapter->sge.ofld_rxq[pi->first_ofld_rxq]; \
- for (iter = 0; iter < pi->nofldrxq; ++iter, ++ofld_rxq)
+#define for_each_txq(pi, iter, q) \
+ for (q = &pi->adapter->sge.txq[pi->first_txq], iter = 0; \
+ iter < pi->ntxq; ++iter, ++q)
+#define for_each_rxq(pi, iter, q) \
+ for (q = &pi->adapter->sge.rxq[pi->first_rxq], iter = 0; \
+ iter < pi->nrxq; ++iter, ++q)
+#define for_each_ofld_txq(pi, iter, q) \
+ for (q = &pi->adapter->sge.ofld_txq[pi->first_ofld_txq], iter = 0; \
+ iter < pi->nofldtxq; ++iter, ++q)
+#define for_each_ofld_rxq(pi, iter, q) \
+ for (q = &pi->adapter->sge.ofld_rxq[pi->first_ofld_rxq], iter = 0; \
+ iter < pi->nofldrxq; ++iter, ++q)
/* One for errors, one for firmware events */
#define T4_EXTRA_INTR 2
@@ -751,6 +773,8 @@ int t4_register_cpl_handler(struct adapter *, int, cpl_handler_t);
int t4_register_an_handler(struct adapter *, an_handler_t);
int t4_register_fw_msg_handler(struct adapter *, int, fw_msg_handler_t);
int t4_filter_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *);
+int begin_synchronized_op(struct adapter *, struct port_info *, int, char *);
+void end_synchronized_op(struct adapter *, int);
/* t4_sge.c */
void t4_sge_modload(void);
diff --git a/sys/dev/cxgbe/common/jhash.h b/sys/dev/cxgbe/common/jhash.h
deleted file mode 100644
index 4546b7b..0000000
--- a/sys/dev/cxgbe/common/jhash.h
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef _JHASH_H
-#define _JHASH_H
-
-/* jhash.h: Jenkins hash support.
- *
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
- *
- * http://burtleburtle.net/bob/hash/
- *
- * These are the credits from Bob's sources:
- *
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
- * hash(), hash2(), hash3, and mix() are externally useful functions.
- * Routines to test the hash are included if SELF_TEST is defined.
- * You can use this free for any purpose. It has no warranty.
- *
- * $FreeBSD$
- */
-
-/* NOTE: Arguments are modified. */
-#define __jhash_mix(a, b, c) \
-{ \
- 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); \
-}
-
-/* The golden ration: an arbitrary value */
-#define JHASH_GOLDEN_RATIO 0x9e3779b9
-
-/* The most generic version, hashes an arbitrary sequence
- * of bytes. No alignment or length assumptions are made about
- * the input key.
- */
-static inline u32 jhash(const void *key, u32 length, u32 initval)
-{
- u32 a, b, c, len;
- const u8 *k = key;
-
- len = length;
- a = b = JHASH_GOLDEN_RATIO;
- c = initval;
-
- while (len >= 12) {
- a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
- b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
- c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
-
- __jhash_mix(a,b,c);
-
- k += 12;
- len -= 12;
- }
-
- c += length;
- switch (len) {
- case 11: c += ((u32)k[10]<<24);
- case 10: c += ((u32)k[9]<<16);
- case 9 : c += ((u32)k[8]<<8);
- case 8 : b += ((u32)k[7]<<24);
- case 7 : b += ((u32)k[6]<<16);
- case 6 : b += ((u32)k[5]<<8);
- case 5 : b += k[4];
- case 4 : a += ((u32)k[3]<<24);
- case 3 : a += ((u32)k[2]<<16);
- case 2 : a += ((u32)k[1]<<8);
- case 1 : a += k[0];
- };
-
- __jhash_mix(a,b,c);
-
- return c;
-}
-
-/* A special optimized version that handles 1 or more of u32s.
- * The length parameter here is the number of u32s in the key.
- */
-static inline u32 jhash2(u32 *k, u32 length, u32 initval)
-{
- u32 a, b, c, len;
-
- a = b = JHASH_GOLDEN_RATIO;
- c = initval;
- len = length;
-
- while (len >= 3) {
- a += k[0];
- b += k[1];
- c += k[2];
- __jhash_mix(a, b, c);
- k += 3; len -= 3;
- }
-
- c += length * 4;
-
- switch (len) {
- case 2 : b += k[1];
- case 1 : a += k[0];
- };
-
- __jhash_mix(a,b,c);
-
- return c;
-}
-
-
-/* A special ultra-optimized versions that knows they are hashing exactly
- * 3, 2 or 1 word(s).
- *
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
- * done at the end is not done here.
- */
-static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
-{
- a += JHASH_GOLDEN_RATIO;
- b += JHASH_GOLDEN_RATIO;
- c += initval;
-
- __jhash_mix(a, b, c);
-
- return c;
-}
-
-static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
-{
- return jhash_3words(a, b, 0, initval);
-}
-
-static inline u32 jhash_1word(u32 a, u32 initval)
-{
- return jhash_3words(a, 0, 0, initval);
-}
-
-#endif /* _JHASH_H */
diff --git a/sys/dev/cxgbe/common/t4_msg.h b/sys/dev/cxgbe/common/t4_msg.h
index 5bd3cef..92f760b 100644
--- a/sys/dev/cxgbe/common/t4_msg.h
+++ b/sys/dev/cxgbe/common/t4_msg.h
@@ -159,6 +159,8 @@ enum CPL_error {
CPL_ERR_KEEPALIVE_TIMEDOUT = 34,
CPL_ERR_RTX_NEG_ADVICE = 35,
CPL_ERR_PERSIST_NEG_ADVICE = 36,
+ CPL_ERR_KEEPALV_NEG_ADVICE = 37,
+ CPL_ERR_WAIT_ARP_RPL = 41,
CPL_ERR_ABORT_FAILED = 42,
CPL_ERR_IWARP_FLM = 50,
};
diff --git a/sys/dev/cxgbe/firmware/t4fw_cfg.txt b/sys/dev/cxgbe/firmware/t4fw_cfg.txt
index bf6a9a1..2a9db62 100644
--- a/sys/dev/cxgbe/firmware/t4fw_cfg.txt
+++ b/sys/dev/cxgbe/firmware/t4fw_cfg.txt
@@ -56,7 +56,7 @@
[function "4"]
wx_caps = all
r_caps = all
- nvi = 54
+ nvi = 32
niqflint = 256
nethctrl = 128
neq = 256
@@ -74,8 +74,8 @@
# Each entry in these categories takes 4 cells each. nhash will use the
# TCAM iff there is room left (that is, the rest don't add up to 2048).
nroute = 32
- nclip = 0 # needed only for IPv6 offload
- nfilter = 1488
+ nclip = 32
+ nfilter = 1456
nserver = 512
nhash = 16384
@@ -137,7 +137,7 @@
[fini]
version = 0x1
- checksum = 0x162df193
+ checksum = 0xfdebb6ef
#
# $FreeBSD$
#
diff --git a/sys/dev/cxgbe/offload.h b/sys/dev/cxgbe/offload.h
index ced15a6..55ac71b 100644
--- a/sys/dev/cxgbe/offload.h
+++ b/sys/dev/cxgbe/offload.h
@@ -54,16 +54,20 @@
OPCODE_TID(w) = htonl(MK_OPCODE_TID(cpl, tid)); \
} while (0)
+TAILQ_HEAD(stid_head, stid_region);
+struct listen_ctx;
+
+struct stid_region {
+ TAILQ_ENTRY(stid_region) link;
+ int used; /* # of stids used by this region */
+ int free; /* # of contiguous stids free right after this region */
+};
+
/*
* Max # of ATIDs. The absolute HW max is 16K but we keep it lower.
*/
#define MAX_ATIDS 8192U
-union serv_entry {
- void *data;
- union serv_entry *next;
-};
-
union aopen_entry {
void *data;
union aopen_entry *next;
@@ -75,34 +79,33 @@ union aopen_entry {
*/
struct tid_info {
void **tid_tab;
- unsigned int ntids;
-
- union serv_entry *stid_tab;
- unsigned int nstids;
- unsigned int stid_base;
-
+ u_int ntids;
+ u_int tids_in_use;
+
+ struct mtx stid_lock __aligned(CACHE_LINE_SIZE);
+ struct listen_ctx **stid_tab;
+ u_int nstids;
+ u_int stid_base;
+ u_int stids_in_use;
+ u_int nstids_free_head; /* # of available stids at the begining */
+ struct stid_head stids;
+
+ struct mtx atid_lock __aligned(CACHE_LINE_SIZE);
union aopen_entry *atid_tab;
- unsigned int natids;
-
- struct filter_entry *ftid_tab;
- unsigned int nftids;
- unsigned int ftid_base;
- unsigned int ftids_in_use;
-
- struct mtx atid_lock;
+ u_int natids;
union aopen_entry *afree;
- unsigned int atids_in_use;
-
- struct mtx stid_lock;
- union serv_entry *sfree;
- unsigned int stids_in_use;
+ u_int atids_in_use;
- unsigned int tids_in_use;
+ struct mtx ftid_lock __aligned(CACHE_LINE_SIZE);
+ struct filter_entry *ftid_tab;
+ u_int nftids;
+ u_int ftid_base;
+ u_int ftids_in_use;
};
struct t4_range {
- unsigned int start;
- unsigned int size;
+ u_int start;
+ u_int size;
};
struct t4_virt_res { /* virtualized HW resources */
@@ -114,6 +117,7 @@ struct t4_virt_res { /* virtualized HW resources */
struct t4_range qp;
struct t4_range cq;
struct t4_range ocq;
+ struct t4_range l2t;
};
#ifdef TCP_OFFLOAD
diff --git a/sys/dev/cxgbe/t4_l2t.c b/sys/dev/cxgbe/t4_l2t.c
index dd8748e..dcff5e8 100644
--- a/sys/dev/cxgbe/t4_l2t.c
+++ b/sys/dev/cxgbe/t4_l2t.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include "common/common.h"
-#include "common/jhash.h"
#include "common/t4_msg.h"
#include "t4_l2t.h"
@@ -78,7 +77,7 @@ t4_alloc_l2e(struct l2t_data *d)
return (NULL);
/* there's definitely a free entry */
- for (e = d->rover, end = &d->l2tab[L2T_SIZE]; e != end; ++e)
+ for (e = d->rover, end = &d->l2tab[d->l2t_size]; e != end; ++e)
if (atomic_load_acq_int(&e->refcnt) == 0)
goto found;
@@ -115,6 +114,7 @@ t4_write_l2e(struct adapter *sc, struct l2t_entry *e, int sync)
{
struct wrqe *wr;
struct cpl_l2t_write_req *req;
+ int idx = e->idx + sc->vres.l2t.start;
mtx_assert(&e->lock, MA_OWNED);
@@ -124,10 +124,10 @@ t4_write_l2e(struct adapter *sc, struct l2t_entry *e, int sync)
req = wrtod(wr);
INIT_TP_WR(req, 0);
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx |
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, idx |
V_SYNC_WR(sync) | V_TID_QID(sc->sge.fwq.abs_id)));
req->params = htons(V_L2T_W_PORT(e->lport) | V_L2T_W_NOREPLY(!sync));
- req->l2t_idx = htons(e->idx);
+ req->l2t_idx = htons(idx);
req->vlan = htons(e->vlan);
memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
@@ -183,18 +183,24 @@ t4_l2t_set_switching(struct adapter *sc, struct l2t_entry *e, uint16_t vlan,
int
t4_init_l2t(struct adapter *sc, int flags)
{
- int i;
+ int i, l2t_size;
struct l2t_data *d;
- d = malloc(sizeof(*d), M_CXGBE, M_ZERO | flags);
+ l2t_size = sc->vres.l2t.size;
+ if (l2t_size < 2) /* At least 1 bucket for IP and 1 for IPv6 */
+ return (EINVAL);
+
+ d = malloc(sizeof(*d) + l2t_size * sizeof (struct l2t_entry), M_CXGBE,
+ M_ZERO | flags);
if (!d)
return (ENOMEM);
+ d->l2t_size = l2t_size;
d->rover = d->l2tab;
- atomic_store_rel_int(&d->nfree, L2T_SIZE);
+ atomic_store_rel_int(&d->nfree, l2t_size);
rw_init(&d->lock, "L2T");
- for (i = 0; i < L2T_SIZE; i++) {
+ for (i = 0; i < l2t_size; i++) {
struct l2t_entry *e = &d->l2tab[i];
e->idx = i;
@@ -215,7 +221,7 @@ t4_free_l2t(struct l2t_data *d)
{
int i;
- for (i = 0; i < L2T_SIZE; i++)
+ for (i = 0; i < d->l2t_size; i++)
mtx_destroy(&d->l2tab[i].lock);
rw_destroy(&d->lock);
free(d, M_CXGBE);
@@ -229,11 +235,11 @@ do_l2t_write_rpl(struct sge_iq *iq, const struct rss_header *rss,
{
const struct cpl_l2t_write_rpl *rpl = (const void *)(rss + 1);
unsigned int tid = GET_TID(rpl);
- unsigned int idx = tid & (L2T_SIZE - 1);
+ unsigned int idx = tid % L2T_SIZE;
if (__predict_false(rpl->status != CPL_ERR_NONE)) {
log(LOG_ERR,
- "Unexpected L2T_WRITE_RPL status %u for entry %u\n",
+ "Unexpected L2T_WRITE_RPL (%u) for entry at hw_idx %u\n",
rpl->status, idx);
return (EINVAL);
}
@@ -269,7 +275,7 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS)
struct l2t_entry *e;
struct sbuf *sb;
int rc, i, header = 0;
- char ip[60];
+ char ip[INET6_ADDRSTRLEN];
if (l2t == NULL)
return (ENXIO);
@@ -283,7 +289,7 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS)
return (ENOMEM);
e = &l2t->l2tab[0];
- for (i = 0; i < L2T_SIZE; i++, e++) {
+ for (i = 0; i < l2t->l2t_size; i++, e++) {
mtx_lock(&e->lock);
if (e->state == L2T_STATE_UNUSED)
goto skip;
@@ -295,11 +301,15 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS)
}
if (e->state == L2T_STATE_SWITCHING)
ip[0] = 0;
- else
- snprintf(ip, sizeof(ip), "%s",
- inet_ntoa(*(struct in_addr *)&e->addr));
+ else {
+ inet_ntop(e->ipv6 ? AF_INET6 : AF_INET, &e->addr[0],
+ &ip[0], sizeof(ip));
+ }
- /* XXX: e->ifp may not be around */
+ /*
+ * XXX: e->ifp may not be around.
+ * XXX: IPv6 addresses may not align properly in the output.
+ */
sbuf_printf(sb, "\n%4u %-15s %02x:%02x:%02x:%02x:%02x:%02x %4d"
" %u %2u %c %5u %s",
e->idx, ip, e->dmac[0], e->dmac[1], e->dmac[2],
diff --git a/sys/dev/cxgbe/t4_l2t.h b/sys/dev/cxgbe/t4_l2t.h
index 6927b81..c60eef1 100644
--- a/sys/dev/cxgbe/t4_l2t.h
+++ b/sys/dev/cxgbe/t4_l2t.h
@@ -60,7 +60,7 @@ enum {
struct l2t_entry {
uint16_t state; /* entry state */
uint16_t idx; /* entry index */
- uint32_t addr; /* next hop IP address */
+ uint32_t addr[4]; /* next hop IP or IPv6 address */
struct ifnet *ifp; /* outgoing interface */
uint16_t smt_idx; /* SMT index */
uint16_t vlan; /* VLAN TCI (id: 0-11, prio: 13-15) */
@@ -70,15 +70,17 @@ struct l2t_entry {
struct mtx lock;
volatile int refcnt; /* entry reference count */
uint16_t hash; /* hash bucket the entry is on */
+ uint8_t ipv6; /* entry is for an IPv6 address */
uint8_t lport; /* associated offload logical port */
uint8_t dmac[ETHER_ADDR_LEN]; /* next hop's MAC address */
};
struct l2t_data {
struct rwlock lock;
+ u_int l2t_size;
volatile int nfree; /* number of free entries */
struct l2t_entry *rover;/* starting point for next allocation */
- struct l2t_entry l2tab[L2T_SIZE];
+ struct l2t_entry l2tab[];
};
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index aeaa4d2..c22ec21 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -284,9 +284,7 @@ static int get_params__post_init(struct adapter *);
static void t4_set_desc(struct adapter *);
static void build_medialist(struct port_info *);
static int update_mac_settings(struct port_info *, int);
-static int cxgbe_init_locked(struct port_info *);
static int cxgbe_init_synchronized(struct port_info *);
-static int cxgbe_uninit_locked(struct port_info *);
static int cxgbe_uninit_synchronized(struct port_info *);
static int setup_intr_handlers(struct adapter *);
static int adapter_full_init(struct adapter *);
@@ -348,6 +346,7 @@ static void clear_filter(struct filter_entry *);
static int set_filter_wr(struct adapter *, int);
static int del_filter_wr(struct adapter *, int);
static int get_sge_context(struct adapter *, struct t4_sge_context *);
+static int load_fw(struct adapter *, struct t4_data *);
static int read_card_mem(struct adapter *, struct t4_mem_range *);
static int read_i2c(struct adapter *, struct t4_i2c_data *);
#ifdef TCP_OFFLOAD
@@ -820,6 +819,8 @@ t4_detach(device_t dev)
mtx_destroy(&sc->sc_lock);
}
+ if (mtx_initialized(&sc->tids.ftid_lock))
+ mtx_destroy(&sc->tids.ftid_lock);
if (mtx_initialized(&sc->sfl_lock))
mtx_destroy(&sc->sfl_lock);
@@ -874,7 +875,7 @@ cxgbe_attach(device_t dev)
ifp->if_capabilities = T4_CAP;
#ifdef TCP_OFFLOAD
if (is_offload(pi->adapter))
- ifp->if_capabilities |= IFCAP_TOE4;
+ ifp->if_capabilities |= IFCAP_TOE;
#endif
ifp->if_capenable = T4_CAP_ENABLE;
ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO |
@@ -918,6 +919,10 @@ cxgbe_detach(device_t dev)
while (IS_BUSY(sc))
mtx_sleep(&sc->flags, &sc->sc_lock, 0, "t4detach", 0);
SET_BUSY(sc);
+#ifdef INVARIANTS
+ sc->last_op = "t4detach";
+ sc->last_op_thr = curthread;
+#endif
ADAPTER_UNLOCK(sc);
if (pi->vlan_c)
@@ -939,7 +944,7 @@ cxgbe_detach(device_t dev)
ADAPTER_LOCK(sc);
CLR_BUSY(sc);
- wakeup_one(&sc->flags);
+ wakeup(&sc->flags);
ADAPTER_UNLOCK(sc);
return (0);
@@ -951,9 +956,10 @@ cxgbe_init(void *arg)
struct port_info *pi = arg;
struct adapter *sc = pi->adapter;
- ADAPTER_LOCK(sc);
- cxgbe_init_locked(pi); /* releases adapter lock */
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ if (begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4init") != 0)
+ return;
+ cxgbe_init_synchronized(pi);
+ end_synchronized_op(sc, 0);
}
static int
@@ -967,81 +973,56 @@ cxgbe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
switch (cmd) {
case SIOCSIFMTU:
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc) {
-fail:
- ADAPTER_UNLOCK(sc);
- return (rc);
- }
-
mtu = ifr->ifr_mtu;
- if ((mtu < ETHERMIN) || (mtu > ETHERMTU_JUMBO)) {
- rc = EINVAL;
- } else {
- ifp->if_mtu = mtu;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- t4_update_fl_bufsize(ifp);
- PORT_LOCK(pi);
- rc = update_mac_settings(pi, XGMAC_MTU);
- PORT_UNLOCK(pi);
- }
+ if ((mtu < ETHERMIN) || (mtu > ETHERMTU_JUMBO))
+ return (EINVAL);
+
+ rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4mtu");
+ if (rc)
+ return (rc);
+ ifp->if_mtu = mtu;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ t4_update_fl_bufsize(ifp);
+ rc = update_mac_settings(pi, XGMAC_MTU);
}
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, 0);
break;
case SIOCSIFFLAGS:
- ADAPTER_LOCK(sc);
- if (IS_DOOMED(pi)) {
- rc = ENXIO;
- goto fail;
- }
+ rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4flg");
+ if (rc)
+ return (rc);
+
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
flags = pi->if_flags;
if ((ifp->if_flags ^ flags) &
(IFF_PROMISC | IFF_ALLMULTI)) {
- if (IS_BUSY(sc)) {
- rc = EBUSY;
- goto fail;
- }
- PORT_LOCK(pi);
rc = update_mac_settings(pi,
XGMAC_PROMISC | XGMAC_ALLMULTI);
- PORT_UNLOCK(pi);
}
- ADAPTER_UNLOCK(sc);
} else
- rc = cxgbe_init_locked(pi);
+ rc = cxgbe_init_synchronized(pi);
pi->if_flags = ifp->if_flags;
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- rc = cxgbe_uninit_locked(pi);
- else
- ADAPTER_UNLOCK(sc);
-
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ rc = cxgbe_uninit_synchronized(pi);
+ end_synchronized_op(sc, 0);
break;
case SIOCADDMULTI:
- case SIOCDELMULTI: /* these two can be called with a mutex held :-( */
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
+ case SIOCDELMULTI: /* these two are called with a mutex held :-( */
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK, "t4multi");
if (rc)
- goto fail;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- PORT_LOCK(pi);
+ return (rc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rc = update_mac_settings(pi, XGMAC_MCADDRS);
- PORT_UNLOCK(pi);
- }
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
break;
case SIOCSIFCAP:
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
+ rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4cap");
if (rc)
- goto fail;
+ return (rc);
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
if (mask & IFCAP_TXCSUM) {
@@ -1122,11 +1103,8 @@ fail:
#endif
if (mask & IFCAP_VLAN_HWTAGGING) {
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- PORT_LOCK(pi);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rc = update_mac_settings(pi, XGMAC_VLANEX);
- PORT_UNLOCK(pi);
- }
}
if (mask & IFCAP_VLAN_MTU) {
ifp->if_capenable ^= IFCAP_VLAN_MTU;
@@ -1141,7 +1119,8 @@ fail:
#ifdef VLAN_CAPABILITIES
VLAN_CAPABILITIES(ifp);
#endif
- ADAPTER_UNLOCK(sc);
+fail:
+ end_synchronized_op(sc, 0);
break;
case SIOCSIFMEDIA:
@@ -1625,21 +1604,28 @@ prep_firmware(struct adapter *sc)
/* Partition adapter resources as specified in the config file. */
if (sc->flags & MASTER_PF) {
- if (strncmp(t4_cfg_file, "default", sizeof(t4_cfg_file))) {
+ snprintf(sc->cfg_file, sizeof(sc->cfg_file), "%s",
+ pci_get_device(sc->dev) == 0x440a ? "uwire" : t4_cfg_file);
+ if (strncmp(sc->cfg_file, "default", sizeof(sc->cfg_file))) {
char s[32];
- snprintf(s, sizeof(s), "t4fw_cfg_%s", t4_cfg_file);
+ snprintf(s, sizeof(s), "t4fw_cfg_%s", sc->cfg_file);
cfg = firmware_get(s);
if (cfg == NULL) {
device_printf(sc->dev,
"unable to locate %s module, "
"will use default config file.\n", s);
+ snprintf(sc->cfg_file, sizeof(sc->cfg_file),
+ "%s", "default");
}
}
rc = partition_resources(sc, cfg ? cfg : default_cfg);
if (rc != 0)
goto done; /* error message displayed already */
+ } else {
+ snprintf(sc->cfg_file, sizeof(sc->cfg_file), "%s", "notme");
+ sc->cfcsum = (u_int)-1;
}
sc->flags |= FW_OK;
@@ -1887,7 +1873,9 @@ get_params__post_init(struct adapter *sc)
param[1] = FW_PARAM_PFVF(EQ_START);
param[2] = FW_PARAM_PFVF(FILTER_START);
param[3] = FW_PARAM_PFVF(FILTER_END);
- rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 4, param, val);
+ param[4] = FW_PARAM_PFVF(L2T_START);
+ param[5] = FW_PARAM_PFVF(L2T_END);
+ rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 6, param, val);
if (rc != 0) {
device_printf(sc->dev,
"failed to query parameters (post_init): %d.\n", rc);
@@ -1898,6 +1886,11 @@ 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->vres.l2t.start = val[4];
+ sc->vres.l2t.size = val[5] - val[4] + 1;
+ KASSERT(sc->vres.l2t.size <= L2T_SIZE,
+ ("%s: L2 table size (%u) larger than expected (%u)",
+ __func__, sc->vres.l2t.size, L2T_SIZE));
/* get capabilites */
bzero(&caps, sizeof(caps));
@@ -2111,7 +2104,7 @@ update_mac_settings(struct port_info *pi, int flags)
struct adapter *sc = pi->adapter;
int mtu = -1, promisc = -1, allmulti = -1, vlanex = -1;
- PORT_LOCK_ASSERT_OWNED(pi);
+ ASSERT_SYNCHRONIZED_OP(sc);
KASSERT(flags, ("%s: not told what to update.", __func__));
if (flags & XGMAC_MTU)
@@ -2213,39 +2206,74 @@ mcfail:
return (rc);
}
-static int
-cxgbe_init_locked(struct port_info *pi)
+int
+begin_synchronized_op(struct adapter *sc, struct port_info *pi, int flags,
+ char *wmesg)
{
- struct adapter *sc = pi->adapter;
- int rc = 0;
+ int rc, pri;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
+#ifdef WITNESS
+ /* the caller thinks it's ok to sleep, but is it really? */
+ if (flags & SLEEP_OK)
+ pause("t4slptst", 1);
+#endif
- while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
- if (mtx_sleep(&sc->flags, &sc->sc_lock, PCATCH, "t4init", 0)) {
+ if (INTR_OK)
+ pri = PCATCH;
+ else
+ pri = 0;
+
+ ADAPTER_LOCK(sc);
+ for (;;) {
+
+ if (pi && IS_DOOMED(pi)) {
+ rc = ENXIO;
+ goto done;
+ }
+
+ if (!IS_BUSY(sc)) {
+ rc = 0;
+ break;
+ }
+
+ if (!(flags & SLEEP_OK)) {
+ rc = EBUSY;
+ goto done;
+ }
+
+ if (mtx_sleep(&sc->flags, &sc->sc_lock, pri, wmesg, 0)) {
rc = EINTR;
goto done;
}
}
- if (IS_DOOMED(pi)) {
- rc = ENXIO;
- goto done;
- }
- KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__));
- /* Give up the adapter lock, port init code can sleep. */
+ KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__));
SET_BUSY(sc);
- ADAPTER_UNLOCK(sc);
-
- rc = cxgbe_init_synchronized(pi);
+#ifdef INVARIANTS
+ sc->last_op = wmesg;
+ sc->last_op_thr = curthread;
+#endif
done:
- ADAPTER_LOCK(sc);
+ if (!(flags & HOLD_LOCK) || rc)
+ ADAPTER_UNLOCK(sc);
+
+ return (rc);
+}
+
+void
+end_synchronized_op(struct adapter *sc, int flags)
+{
+
+ if (flags & LOCK_HELD)
+ ADAPTER_LOCK_ASSERT_OWNED(sc);
+ else
+ ADAPTER_LOCK(sc);
+
KASSERT(IS_BUSY(sc), ("%s: controller not busy.", __func__));
CLR_BUSY(sc);
- wakeup_one(&sc->flags);
+ wakeup(&sc->flags);
ADAPTER_UNLOCK(sc);
- return (rc);
}
static int
@@ -2255,7 +2283,7 @@ cxgbe_init_synchronized(struct port_info *pi)
struct ifnet *ifp = pi->ifp;
int rc = 0;
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
if (isset(&sc->open_device_map, pi->port_id)) {
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING,
@@ -2271,9 +2299,7 @@ cxgbe_init_synchronized(struct port_info *pi)
((rc = port_full_init(pi)) != 0))
return (rc); /* error message displayed already */
- PORT_LOCK(pi);
rc = update_mac_settings(pi, XGMAC_ALL);
- PORT_UNLOCK(pi);
if (rc)
goto done; /* error message displayed already */
@@ -2291,7 +2317,9 @@ cxgbe_init_synchronized(struct port_info *pi)
/* all ok */
setbit(&sc->open_device_map, pi->port_id);
+ PORT_LOCK(pi);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ PORT_UNLOCK(pi);
callout_reset(&pi->tick, hz, cxgbe_tick, pi);
done:
@@ -2301,39 +2329,6 @@ done:
return (rc);
}
-static int
-cxgbe_uninit_locked(struct port_info *pi)
-{
- struct adapter *sc = pi->adapter;
- int rc;
-
- ADAPTER_LOCK_ASSERT_OWNED(sc);
-
- while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
- if (mtx_sleep(&sc->flags, &sc->sc_lock, PCATCH, "t4uninit", 0)) {
- rc = EINTR;
- goto done;
- }
- }
- if (IS_DOOMED(pi)) {
- rc = ENXIO;
- goto done;
- }
- KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__));
- SET_BUSY(sc);
- ADAPTER_UNLOCK(sc);
-
- rc = cxgbe_uninit_synchronized(pi);
-
- ADAPTER_LOCK(sc);
- KASSERT(IS_BUSY(sc), ("%s: controller not busy.", __func__));
- CLR_BUSY(sc);
- wakeup_one(&sc->flags);
-done:
- ADAPTER_UNLOCK(sc);
- return (rc);
-}
-
/*
* Idempotent.
*/
@@ -2344,7 +2339,7 @@ cxgbe_uninit_synchronized(struct port_info *pi)
struct ifnet *ifp = pi->ifp;
int rc;
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
/*
* Disable the VI so that all its data in either direction is discarded
@@ -2360,7 +2355,9 @@ cxgbe_uninit_synchronized(struct port_info *pi)
}
clrbit(&sc->open_device_map, pi->port_id);
+ PORT_LOCK(pi);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ PORT_UNLOCK(pi);
pi->link_cfg.link_ok = 0;
pi->link_cfg.speed = 0;
@@ -2539,7 +2536,7 @@ port_full_init(struct port_info *pi)
struct sge_rxq *rxq;
int rc, i;
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
KASSERT((pi->flags & PORT_INIT_DONE) == 0,
("%s: PORT_INIT_DONE already", __func__));
@@ -3119,7 +3116,7 @@ t4_sysctls(struct adapter *sc)
CTLFLAG_RD, &sc->fw_version, 0, "firmware version");
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "cf",
- CTLFLAG_RD, &t4_cfg_file, 0, "configuration file");
+ CTLFLAG_RD, &sc->cfg_file, 0, "configuration file");
SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "cfcsum", CTLFLAG_RD,
&sc->cfcsum, 0, "config file checksum");
@@ -3524,6 +3521,8 @@ sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS)
struct port_info *pi = arg1;
struct adapter *sc = pi->adapter;
int idx, rc, i;
+ struct sge_rxq *rxq;
+ uint8_t v;
idx = pi->tmr_idx;
@@ -3534,25 +3533,23 @@ sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS)
if (idx < 0 || idx >= SGE_NTIMERS)
return (EINVAL);
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc == 0) {
- struct sge_rxq *rxq;
- uint8_t v;
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4tmr");
+ if (rc)
+ return (rc);
- v = V_QINTR_TIMER_IDX(idx) | V_QINTR_CNT_EN(pi->pktc_idx != -1);
- for_each_rxq(pi, i, rxq) {
+ v = V_QINTR_TIMER_IDX(idx) | V_QINTR_CNT_EN(pi->pktc_idx != -1);
+ for_each_rxq(pi, i, rxq) {
#ifdef atomic_store_rel_8
- atomic_store_rel_8(&rxq->iq.intr_params, v);
+ atomic_store_rel_8(&rxq->iq.intr_params, v);
#else
- rxq->iq.intr_params = v;
+ rxq->iq.intr_params = v;
#endif
- }
- pi->tmr_idx = idx;
}
+ pi->tmr_idx = idx;
- ADAPTER_UNLOCK(sc);
- return (rc);
+ end_synchronized_op(sc, LOCK_HELD);
+ return (0);
}
static int
@@ -3571,15 +3568,17 @@ sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS)
if (idx < -1 || idx >= SGE_NCOUNTERS)
return (EINVAL);
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc == 0 && pi->flags & PORT_INIT_DONE)
- rc = EBUSY; /* cannot be changed once the queues are created */
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4pktc");
+ if (rc)
+ return (rc);
- if (rc == 0)
+ if (pi->flags & PORT_INIT_DONE)
+ rc = EBUSY; /* cannot be changed once the queues are created */
+ else
pi->pktc_idx = idx;
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
return (rc);
}
@@ -3599,15 +3598,17 @@ sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS)
if (qsize < 128 || (qsize & 7))
return (EINVAL);
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc == 0 && pi->flags & PORT_INIT_DONE)
- rc = EBUSY; /* cannot be changed once the queues are created */
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4rxqs");
+ if (rc)
+ return (rc);
- if (rc == 0)
+ if (pi->flags & PORT_INIT_DONE)
+ rc = EBUSY; /* cannot be changed once the queues are created */
+ else
pi->qsize_rxq = qsize;
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
return (rc);
}
@@ -3624,18 +3625,21 @@ sysctl_qsize_txq(SYSCTL_HANDLER_ARGS)
if (rc != 0 || req->newptr == NULL)
return (rc);
- if (qsize < 128)
+ /* bufring size must be powerof2 */
+ if (qsize < 128 || !powerof2(qsize))
return (EINVAL);
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc == 0 && pi->flags & PORT_INIT_DONE)
- rc = EBUSY; /* cannot be changed once the queues are created */
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4txqs");
+ if (rc)
+ return (rc);
- if (rc == 0)
+ if (pi->flags & PORT_INIT_DONE)
+ rc = EBUSY; /* cannot be changed once the queues are created */
+ else
pi->qsize_txq = qsize;
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
return (rc);
}
@@ -4674,8 +4678,14 @@ fspec_to_fconf(struct t4_filter_specification *fs)
static int
get_filter_mode(struct adapter *sc, uint32_t *mode)
{
+ int rc;
uint32_t fconf;
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4getfm");
+ if (rc)
+ return (rc);
+
t4_read_indirect(sc, A_TP_PIO_ADDR, A_TP_PIO_DATA, &fconf, 1,
A_TP_VLAN_PRI_MAP);
@@ -4687,6 +4697,7 @@ get_filter_mode(struct adapter *sc, uint32_t *mode)
*mode = fconf_to_mode(sc->filter_mode);
+ end_synchronized_op(sc, LOCK_HELD);
return (0);
}
@@ -4698,11 +4709,10 @@ set_filter_mode(struct adapter *sc, uint32_t mode)
fconf = mode_to_fconf(mode);
- ADAPTER_LOCK(sc);
- if (IS_BUSY(sc)) {
- rc = EAGAIN;
- goto done;
- }
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4setfm");
+ if (rc)
+ return (rc);
if (sc->tids.ftids_in_use > 0) {
rc = EBUSY;
@@ -4725,7 +4735,7 @@ set_filter_mode(struct adapter *sc, uint32_t mode)
#endif
done:
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
return (rc);
}
@@ -4746,18 +4756,18 @@ get_filter_hits(struct adapter *sc, uint32_t fid)
static int
get_filter(struct adapter *sc, struct t4_filter *t)
{
- int i, nfilters = sc->tids.nftids;
+ int i, rc, nfilters = sc->tids.nftids;
struct filter_entry *f;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
-
- if (IS_BUSY(sc))
- return (EAGAIN);
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4getf");
+ if (rc)
+ return (rc);
if (sc->tids.ftids_in_use == 0 || sc->tids.ftid_tab == NULL ||
t->idx >= nfilters) {
t->idx = 0xffffffff;
- return (0);
+ goto done;
}
f = &sc->tids.ftid_tab[t->idx];
@@ -4772,11 +4782,13 @@ get_filter(struct adapter *sc, struct t4_filter *t)
t->hits = UINT64_MAX;
t->fs = f->fs;
- return (0);
+ goto done;
}
}
t->idx = 0xffffffff;
+done:
+ end_synchronized_op(sc, LOCK_HELD);
return (0);
}
@@ -4785,40 +4797,58 @@ set_filter(struct adapter *sc, struct t4_filter *t)
{
unsigned int nfilters, nports;
struct filter_entry *f;
- int i;
+ int i, rc;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setf");
+ if (rc)
+ return (rc);
nfilters = sc->tids.nftids;
nports = sc->params.nports;
- if (nfilters == 0)
- return (ENOTSUP);
+ if (nfilters == 0) {
+ rc = ENOTSUP;
+ goto done;
+ }
- if (!(sc->flags & FULL_INIT_DONE))
- return (EAGAIN);
+ if (!(sc->flags & FULL_INIT_DONE)) {
+ rc = EAGAIN;
+ goto done;
+ }
- if (t->idx >= nfilters)
- return (EINVAL);
+ if (t->idx >= nfilters) {
+ rc = EINVAL;
+ goto done;
+ }
/* Validate against the global filter mode */
- if ((sc->filter_mode | fspec_to_fconf(&t->fs)) != sc->filter_mode)
- return (E2BIG);
+ if ((sc->filter_mode | fspec_to_fconf(&t->fs)) != sc->filter_mode) {
+ rc = E2BIG;
+ goto done;
+ }
- if (t->fs.action == FILTER_SWITCH && t->fs.eport >= nports)
- return (EINVAL);
+ if (t->fs.action == FILTER_SWITCH && t->fs.eport >= nports) {
+ rc = EINVAL;
+ goto done;
+ }
- if (t->fs.val.iport >= nports)
- return (EINVAL);
+ if (t->fs.val.iport >= nports) {
+ rc = EINVAL;
+ goto done;
+ }
/* Can't specify an iq if not steering to it */
- if (!t->fs.dirsteer && t->fs.iq)
- return (EINVAL);
+ if (!t->fs.dirsteer && t->fs.iq) {
+ rc = EINVAL;
+ goto done;
+ }
/* IPv6 filter idx must be 4 aligned */
if (t->fs.type == 1 &&
- ((t->idx & 0x3) || t->idx + 4 >= nfilters))
- return (EINVAL);
+ ((t->idx & 0x3) || t->idx + 4 >= nfilters)) {
+ rc = EINVAL;
+ goto done;
+ }
if (sc->tids.ftid_tab == NULL) {
KASSERT(sc->tids.ftids_in_use == 0,
@@ -4827,17 +4857,24 @@ set_filter(struct adapter *sc, struct t4_filter *t)
sc->tids.ftid_tab = malloc(sizeof (struct filter_entry) *
nfilters, M_CXGBE, M_NOWAIT | M_ZERO);
- if (sc->tids.ftid_tab == NULL)
- return (ENOMEM);
+ if (sc->tids.ftid_tab == NULL) {
+ rc = ENOMEM;
+ goto done;
+ }
+ mtx_init(&sc->tids.ftid_lock, "T4 filters", 0, MTX_DEF);
}
for (i = 0; i < 4; i++) {
f = &sc->tids.ftid_tab[t->idx + i];
- if (f->pending || f->valid)
- return (EBUSY);
- if (f->locked)
- return (EPERM);
+ if (f->pending || f->valid) {
+ rc = EBUSY;
+ goto done;
+ }
+ if (f->locked) {
+ rc = EPERM;
+ goto done;
+ }
if (t->fs.type == 0)
break;
@@ -4846,7 +4883,27 @@ set_filter(struct adapter *sc, struct t4_filter *t)
f = &sc->tids.ftid_tab[t->idx];
f->fs = t->fs;
- return set_filter_wr(sc, t->idx);
+ rc = set_filter_wr(sc, t->idx);
+done:
+ end_synchronized_op(sc, 0);
+
+ if (rc == 0) {
+ mtx_lock(&sc->tids.ftid_lock);
+ for (;;) {
+ if (f->pending == 0) {
+ rc = f->valid ? 0 : EIO;
+ break;
+ }
+
+ if (mtx_sleep(&sc->tids.ftid_tab, &sc->tids.ftid_lock,
+ PCATCH, "t4setfw", 0)) {
+ rc = EINPROGRESS;
+ break;
+ }
+ }
+ mtx_unlock(&sc->tids.ftid_lock);
+ }
+ return (rc);
}
static int
@@ -4854,37 +4911,67 @@ del_filter(struct adapter *sc, struct t4_filter *t)
{
unsigned int nfilters;
struct filter_entry *f;
+ int rc;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
-
- if (IS_BUSY(sc))
- return (EAGAIN);
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4delf");
+ if (rc)
+ return (rc);
nfilters = sc->tids.nftids;
- if (nfilters == 0)
- return (ENOTSUP);
+ if (nfilters == 0) {
+ rc = ENOTSUP;
+ goto done;
+ }
if (sc->tids.ftid_tab == NULL || sc->tids.ftids_in_use == 0 ||
- t->idx >= nfilters)
- return (EINVAL);
+ t->idx >= nfilters) {
+ rc = EINVAL;
+ goto done;
+ }
- if (!(sc->flags & FULL_INIT_DONE))
- return (EAGAIN);
+ if (!(sc->flags & FULL_INIT_DONE)) {
+ rc = EAGAIN;
+ goto done;
+ }
f = &sc->tids.ftid_tab[t->idx];
- if (f->pending)
- return (EBUSY);
- if (f->locked)
- return (EPERM);
+ if (f->pending) {
+ rc = EBUSY;
+ goto done;
+ }
+ if (f->locked) {
+ rc = EPERM;
+ goto done;
+ }
if (f->valid) {
t->fs = f->fs; /* extra info for the caller */
- return del_filter_wr(sc, t->idx);
+ rc = del_filter_wr(sc, t->idx);
}
- return (0);
+done:
+ end_synchronized_op(sc, 0);
+
+ if (rc == 0) {
+ mtx_lock(&sc->tids.ftid_lock);
+ for (;;) {
+ if (f->pending == 0) {
+ rc = f->valid ? EIO : 0;
+ break;
+ }
+
+ if (mtx_sleep(&sc->tids.ftid_tab, &sc->tids.ftid_lock,
+ PCATCH, "t4delfw", 0)) {
+ rc = EINPROGRESS;
+ break;
+ }
+ }
+ mtx_unlock(&sc->tids.ftid_lock);
+ }
+
+ return (rc);
}
static void
@@ -4904,7 +4991,7 @@ set_filter_wr(struct adapter *sc, int fidx)
struct fw_filter_wr *fwr;
unsigned int ftid;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
if (f->fs.newdmac || f->fs.newvlan) {
/* This filter needs an L2T entry; allocate one. */
@@ -5007,8 +5094,6 @@ del_filter_wr(struct adapter *sc, int fidx)
struct fw_filter_wr *fwr;
unsigned int ftid;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
-
ftid = sc->tids.ftid_base + fidx;
wr = alloc_wrqe(sizeof(*fwr), &sc->sge.mgmtq);
@@ -5039,8 +5124,10 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
unsigned int rc = G_COOKIE(rpl->cookie);
struct filter_entry *f = &sc->tids.ftid_tab[idx];
- ADAPTER_LOCK(sc);
+ mtx_lock(&sc->tids.ftid_lock);
if (rc == FW_FILTER_WR_FLT_ADDED) {
+ KASSERT(f->pending, ("%s: filter[%u] isn't pending.",
+ __func__, idx));
f->smtidx = (be64toh(rpl->oldval) >> 24) & 0xff;
f->pending = 0; /* asynchronous setup completed */
f->valid = 1;
@@ -5055,7 +5142,8 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
clear_filter(f);
sc->tids.ftids_in_use--;
}
- ADAPTER_UNLOCK(sc);
+ wakeup(&sc->tids.ftid_tab);
+ mtx_unlock(&sc->tids.ftid_lock);
}
return (0);
@@ -5064,29 +5152,63 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
static int
get_sge_context(struct adapter *sc, struct t4_sge_context *cntxt)
{
- int rc = EINVAL;
+ int rc;
if (cntxt->cid > M_CTXTQID)
- return (rc);
+ return (EINVAL);
if (cntxt->mem_id != CTXT_EGRESS && cntxt->mem_id != CTXT_INGRESS &&
cntxt->mem_id != CTXT_FLM && cntxt->mem_id != CTXT_CNM)
- return (rc);
+ return (EINVAL);
if (sc->flags & FW_OK) {
- ADAPTER_LOCK(sc); /* Avoid parallel t4_wr_mbox */
- rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid, cntxt->mem_id,
- &cntxt->data[0]);
- ADAPTER_UNLOCK(sc);
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4ctxt");
+ if (rc == 0) {
+ rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid,
+ cntxt->mem_id, &cntxt->data[0]);
+ end_synchronized_op(sc, LOCK_HELD);
+ if (rc == 0)
+ return (0);
+ }
}
- if (rc != 0) {
- /* Read via firmware failed or wasn't even attempted */
+ /*
+ * Read via firmware failed or wasn't even attempted. Read directly via
+ * the backdoor.
+ */
+ rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id,
+ &cntxt->data[0]);
+ return (rc);
+}
+
+static int
+load_fw(struct adapter *sc, struct t4_data *fw)
+{
+ int rc;
+ uint8_t *fw_data;
+
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ldfw");
+ if (rc)
+ return (rc);
+
+ if (sc->flags & FULL_INIT_DONE) {
+ rc = EBUSY;
+ goto done;
+ }
- rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id,
- &cntxt->data[0]);
+ fw_data = malloc(fw->len, M_CXGBE, M_WAITOK);
+ if (fw_data == NULL) {
+ rc = ENOMEM;
+ goto done;
}
+ rc = copyin(fw->data, fw_data, fw->len);
+ if (rc == 0)
+ rc = -t4_load_fw(sc, fw_data, fw->len);
+
+ free(fw_data, M_CXGBE);
+done:
+ end_synchronized_op(sc, 0);
return (rc);
}
@@ -5173,8 +5295,6 @@ read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd)
{
int rc;
- ADAPTER_LOCK_ASSERT_OWNED(sc); /* for mbox */
-
if (i2cd->len == 0 || i2cd->port_id >= sc->params.nports)
return (EINVAL);
@@ -5183,8 +5303,12 @@ read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd)
return (ENOTSUP);
}
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4i2crd");
+ if (rc)
+ return (rc);
rc = -t4_i2c_rd(sc, sc->mbox, i2cd->port_id, i2cd->dev_addr,
i2cd->offset, &i2cd->data[0]);
+ end_synchronized_op(sc, 0);
return (rc);
}
@@ -5354,56 +5478,78 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag,
rc = set_filter_mode(sc, *(uint32_t *)data);
break;
case CHELSIO_T4_GET_FILTER:
- ADAPTER_LOCK(sc);
rc = get_filter(sc, (struct t4_filter *)data);
- ADAPTER_UNLOCK(sc);
break;
case CHELSIO_T4_SET_FILTER:
- ADAPTER_LOCK(sc);
rc = set_filter(sc, (struct t4_filter *)data);
- ADAPTER_UNLOCK(sc);
break;
case CHELSIO_T4_DEL_FILTER:
- ADAPTER_LOCK(sc);
rc = del_filter(sc, (struct t4_filter *)data);
- ADAPTER_UNLOCK(sc);
break;
case CHELSIO_T4_GET_SGE_CONTEXT:
rc = get_sge_context(sc, (struct t4_sge_context *)data);
break;
- case CHELSIO_T4_LOAD_FW: {
- struct t4_data *fw = (struct t4_data *)data;
- uint8_t *fw_data;
-
- if (sc->flags & FULL_INIT_DONE)
- return (EBUSY);
-
- fw_data = malloc(fw->len, M_CXGBE, M_NOWAIT);
- if (fw_data == NULL)
- return (ENOMEM);
-
- rc = copyin(fw->data, fw_data, fw->len);
- if (rc == 0)
- rc = -t4_load_fw(sc, fw_data, fw->len);
-
- free(fw_data, M_CXGBE);
+ case CHELSIO_T4_LOAD_FW:
+ rc = load_fw(sc, (struct t4_data *)data);
break;
- }
case CHELSIO_T4_GET_MEM:
rc = read_card_mem(sc, (struct t4_mem_range *)data);
break;
case CHELSIO_T4_GET_I2C:
- ADAPTER_LOCK(sc);
rc = read_i2c(sc, (struct t4_i2c_data *)data);
- ADAPTER_UNLOCK(sc);
break;
case CHELSIO_T4_CLEAR_STATS: {
+ int i;
u_int port_id = *(uint32_t *)data;
+ struct port_info *pi;
if (port_id >= sc->params.nports)
return (EINVAL);
+ /* MAC stats */
t4_clr_port_stats(sc, port_id);
+
+ pi = sc->port[port_id];
+ if (pi->flags & PORT_INIT_DONE) {
+ struct sge_rxq *rxq;
+ struct sge_txq *txq;
+ struct sge_wrq *wrq;
+
+ for_each_rxq(pi, i, rxq) {
+#if defined(INET) || defined(INET6)
+ rxq->lro.lro_queued = 0;
+ rxq->lro.lro_flushed = 0;
+#endif
+ rxq->rxcsum = 0;
+ rxq->vlan_extraction = 0;
+ }
+
+ for_each_txq(pi, i, txq) {
+ txq->txcsum = 0;
+ txq->tso_wrs = 0;
+ txq->vlan_insertion = 0;
+ txq->imm_wrs = 0;
+ txq->sgl_wrs = 0;
+ txq->txpkt_wrs = 0;
+ txq->txpkts_wrs = 0;
+ txq->txpkts_pkts = 0;
+ txq->br->br_drops = 0;
+ txq->no_dmamap = 0;
+ txq->no_desc = 0;
+ }
+
+#ifdef TCP_OFFLOAD
+ /* nothing to clear for each ofld_rxq */
+
+ for_each_ofld_txq(pi, i, wrq) {
+ wrq->tx_wrs = 0;
+ wrq->no_desc = 0;
+ }
+#endif
+ wrq = &sc->sge.ctrlq[pi->port_id];
+ wrq->tx_wrs = 0;
+ wrq->no_desc = 0;
+ }
break;
}
default:
@@ -5420,16 +5566,16 @@ toe_capability(struct port_info *pi, int enable)
int rc;
struct adapter *sc = pi->adapter;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
if (!is_offload(sc))
return (ENODEV);
if (enable) {
if (!(sc->flags & FULL_INIT_DONE)) {
- log(LOG_WARNING,
- "You must enable a cxgbe interface first\n");
- return (EAGAIN);
+ rc = cxgbe_init_synchronized(pi);
+ if (rc)
+ return (rc);
}
if (isset(&sc->offload_map, pi->port_id))
@@ -5518,6 +5664,8 @@ t4_activate_uld(struct adapter *sc, int id)
int rc = EAGAIN;
struct uld_info *ui;
+ ASSERT_SYNCHRONIZED_OP(sc);
+
mtx_lock(&t4_uld_list_lock);
SLIST_FOREACH(ui, &t4_uld_list, link) {
@@ -5540,6 +5688,8 @@ t4_deactivate_uld(struct adapter *sc, int id)
int rc = EINVAL;
struct uld_info *ui;
+ ASSERT_SYNCHRONIZED_OP(sc);
+
mtx_lock(&t4_uld_list_lock);
SLIST_FOREACH(ui, &t4_uld_list, link) {
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 62d9eb3..62ceec4 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -2362,6 +2362,8 @@ alloc_txq(struct port_info *pi, struct sge_txq *txq, int idx,
SYSCTL_ADD_UQUAD(&pi->ctx, children, OID_AUTO, "txpkts_pkts", CTLFLAG_RD,
&txq->txpkts_pkts, "# of frames tx'd using txpkts work requests");
+ SYSCTL_ADD_UQUAD(&pi->ctx, children, OID_AUTO, "br_drops", CTLFLAG_RD,
+ &txq->br->br_drops, "# of drops in the buf_ring for this queue");
SYSCTL_ADD_UINT(&pi->ctx, children, OID_AUTO, "no_dmamap", CTLFLAG_RD,
&txq->no_dmamap, 0, "# of times txq ran out of DMA maps");
SYSCTL_ADD_UINT(&pi->ctx, children, OID_AUTO, "no_desc", CTLFLAG_RD,
diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c
index 8d36b1e..17ed1d3 100644
--- a/sys/dev/cxgbe/tom/t4_connect.c
+++ b/sys/dev/cxgbe/tom/t4_connect.c
@@ -29,6 +29,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#ifdef TCP_OFFLOAD
#include <sys/param.h>
@@ -195,7 +196,7 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
CTR3(KTR_CXGBE, "%s: atid %u, status %u ", __func__, atid, status);
/* Ignore negative advice */
- if (status == CPL_ERR_RTX_NEG_ADVICE)
+ if (negative_advice(status))
return (0);
free_atid(sc, atid);
@@ -220,10 +221,9 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
* Options2 for active open.
*/
static uint32_t
-calc_opt2a(struct socket *so)
+calc_opt2a(struct socket *so, struct toepcb *toep)
{
struct tcpcb *tp = so_sototcpcb(so);
- struct toepcb *toep = tp->t_toe;
struct port_info *pi = toep->port;
struct adapter *sc = pi->adapter;
uint32_t opt2 = 0;
@@ -260,6 +260,12 @@ t4_init_connect_cpl_handlers(struct adapter *sc)
t4_register_cpl_handler(sc, CPL_ACT_OPEN_RPL, do_act_open_rpl);
}
+#define DONT_OFFLOAD_ACTIVE_OPEN(x) do { \
+ reason = __LINE__; \
+ rc = (x); \
+ goto failed; \
+} while (0)
+
/*
* active open (soconnect).
*
@@ -275,20 +281,19 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
struct sockaddr *nam)
{
struct adapter *sc = tod->tod_softc;
+ struct tom_data *td = tod_td(tod);
struct toepcb *toep = NULL;
struct wrqe *wr = NULL;
- struct cpl_act_open_req *cpl;
- struct l2t_entry *e = NULL;
struct ifnet *rt_ifp = rt->rt_ifp;
struct port_info *pi;
- int atid = -1, mtu_idx, rscale, qid_atid, rc = ENOMEM;
+ int mtu_idx, rscale, qid_atid, rc, isipv6;
struct inpcb *inp = sotoinpcb(so);
struct tcpcb *tp = intotcpcb(inp);
+ int reason;
INP_WLOCK_ASSERT(inp);
-
- if (nam->sa_family != AF_INET)
- CXGBE_UNIMPLEMENTED("IPv6 connect");
+ KASSERT(nam->sa_family == AF_INET || nam->sa_family == AF_INET6,
+ ("%s: dest addr %p has family %u", __func__, nam, nam->sa_family));
if (rt_ifp->if_type == IFT_ETHER)
pi = rt_ifp->if_softc;
@@ -297,30 +302,29 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
pi = ifp->if_softc;
} else if (rt_ifp->if_type == IFT_IEEE8023ADLAG)
- return (ENOSYS); /* XXX: implement lagg support */
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOSYS); /* XXX: implement lagg+TOE */
else
- return (ENOTSUP);
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOTSUP);
toep = alloc_toepcb(pi, -1, -1, M_NOWAIT);
if (toep == NULL)
- goto failed;
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
- atid = alloc_atid(sc, toep);
- if (atid < 0)
- goto failed;
+ toep->tid = alloc_atid(sc, toep);
+ if (toep->tid < 0)
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
- e = t4_l2t_get(pi, rt_ifp,
+ toep->l2te = t4_l2t_get(pi, rt_ifp,
rt->rt_flags & RTF_GATEWAY ? rt->rt_gateway : nam);
- if (e == NULL)
- goto failed;
+ if (toep->l2te == NULL)
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
- wr = alloc_wrqe(sizeof(*cpl), toep->ctrlq);
+ isipv6 = nam->sa_family == AF_INET6;
+ wr = alloc_wrqe(isipv6 ? sizeof(struct cpl_act_open_req6) :
+ sizeof(struct cpl_act_open_req), toep->ctrlq);
if (wr == NULL)
- goto failed;
- cpl = wrtod(wr);
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
- toep->tid = atid;
- toep->l2te = e;
if (sc->tt.ddp && (so->so_options & SO_NO_DDP) == 0)
set_tcpddp_ulp_mode(toep);
else
@@ -330,8 +334,6 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
toep->rx_credits = min(select_rcv_wnd(so) >> 10, M_RCV_BUFSIZ);
SOCKBUF_UNLOCK(&so->so_rcv);
- offload_socket(so, toep);
-
/*
* The kernel sets request_r_scale based on sb_max whereas we need to
* take hardware's MAX_RCV_WND into account too. This is normally a
@@ -342,39 +344,78 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
else
rscale = 0;
mtu_idx = find_best_mtu_idx(sc, &inp->inp_inc, 0);
- qid_atid = (toep->ofld_rxq->iq.abs_id << 14) | atid;
-
- INIT_TP_WR(cpl, 0);
- OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, qid_atid));
- inp_4tuple_get(inp, &cpl->local_ip, &cpl->local_port, &cpl->peer_ip,
- &cpl->peer_port);
- cpl->opt0 = calc_opt0(so, pi, e, mtu_idx, rscale, toep->rx_credits,
- toep->ulp_mode);
- cpl->params = select_ntuple(pi, e, sc->filter_mode);
- cpl->opt2 = calc_opt2a(so);
+ qid_atid = (toep->ofld_rxq->iq.abs_id << 14) | toep->tid;
+
+ if (isipv6) {
+ struct cpl_act_open_req6 *cpl = wrtod(wr);
+
+ if ((inp->inp_vflag & INP_IPV6) == 0) {
+ /* XXX think about this a bit more */
+ log(LOG_ERR,
+ "%s: time to think about AF_INET6 + vflag 0x%x.\n",
+ __func__, inp->inp_vflag);
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOTSUP);
+ }
+
+ toep->ce = hold_lip(td, &inp->in6p_laddr);
+ if (toep->ce == NULL)
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOENT);
+
+ INIT_TP_WR(cpl, 0);
+ OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+ qid_atid));
+
+ cpl->local_port = inp->inp_lport;
+ cpl->local_ip_hi = *(uint64_t *)&inp->in6p_laddr.s6_addr[0];
+ cpl->local_ip_lo = *(uint64_t *)&inp->in6p_laddr.s6_addr[8];
+ cpl->peer_port = inp->inp_fport;
+ cpl->peer_ip_hi = *(uint64_t *)&inp->in6p_faddr.s6_addr[0];
+ cpl->peer_ip_lo = *(uint64_t *)&inp->in6p_faddr.s6_addr[8];
+ cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale,
+ toep->rx_credits, toep->ulp_mode);
+ cpl->params = select_ntuple(pi, toep->l2te, sc->filter_mode);
+ cpl->opt2 = calc_opt2a(so, toep);
+ } else {
+ struct cpl_act_open_req *cpl = wrtod(wr);
+
+ INIT_TP_WR(cpl, 0);
+ OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+ qid_atid));
+ inp_4tuple_get(inp, &cpl->local_ip, &cpl->local_port,
+ &cpl->peer_ip, &cpl->peer_port);
+ cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale,
+ toep->rx_credits, toep->ulp_mode);
+ cpl->params = select_ntuple(pi, toep->l2te, sc->filter_mode);
+ cpl->opt2 = calc_opt2a(so, toep);
+ }
CTR5(KTR_CXGBE, "%s: atid %u (%s), toep %p, inp %p", __func__,
toep->tid, tcpstates[tp->t_state], toep, inp);
- rc = t4_l2t_send(sc, wr, e);
+ offload_socket(so, toep);
+ rc = t4_l2t_send(sc, wr, toep->l2te);
if (rc == 0) {
toep->flags |= TPF_CPL_PENDING;
return (0);
}
undo_offload_socket(so);
+ reason = __LINE__;
failed:
- CTR5(KTR_CXGBE, "%s: FAILED, atid %d, toep %p, l2te %p, wr %p",
- __func__, atid, toep, e, wr);
+ CTR3(KTR_CXGBE, "%s: not offloading (%d), rc %d", __func__, reason, rc);
- if (e)
- t4_l2t_release(e);
if (wr)
free_wrqe(wr);
- if (atid >= 0)
- free_atid(sc, atid);
- if (toep)
+
+ if (toep) {
+ if (toep->tid >= 0)
+ free_atid(sc, toep->tid);
+ if (toep->l2te)
+ t4_l2t_release(toep->l2te);
+ if (toep->ce)
+ release_lip(td, toep->ce);
free_toepcb(toep);
+ }
return (rc);
}
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index 6ae1ec4..9aead9f 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -1018,8 +1018,7 @@ do_abort_req(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
- if (cpl->status == CPL_ERR_RTX_NEG_ADVICE ||
- cpl->status == CPL_ERR_PERSIST_NEG_ADVICE) {
+ if (negative_advice(cpl->status)) {
CTR4(KTR_CXGBE, "%s: negative advice %d for tid %d (0x%x)",
__func__, cpl->status, tid, toep->flags);
return (0); /* Ignore negative advice */
diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c
index 523f7f3..b80702d 100644
--- a/sys/dev/cxgbe/tom/t4_listen.c
+++ b/sys/dev/cxgbe/tom/t4_listen.c
@@ -29,6 +29,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#ifdef TCP_OFFLOAD
#include <sys/param.h>
@@ -50,6 +51,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet6/scope6_var.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#define TCPSTATES
@@ -63,9 +66,9 @@ __FBSDID("$FreeBSD$");
#include "tom/t4_tom.h"
/* stid services */
-static int alloc_stid(struct adapter *, void *);
-static void *lookup_stid(struct adapter *, int);
-static void free_stid(struct adapter *, int);
+static int alloc_stid(struct adapter *, struct listen_ctx *, int);
+static struct listen_ctx *lookup_stid(struct adapter *, int);
+static void free_stid(struct adapter *, struct listen_ctx *);
/* lctx services */
static struct listen_ctx *alloc_lctx(struct adapter *, struct inpcb *,
@@ -81,45 +84,105 @@ static inline void save_qids_in_mbuf(struct mbuf *, struct port_info *);
static inline void get_qids_from_mbuf(struct mbuf *m, int *, int *);
static void send_reset_synqe(struct toedev *, struct synq_entry *);
-/* XXX: won't work for IPv6 */
static int
-alloc_stid(struct adapter *sc, void *ctx)
+alloc_stid(struct adapter *sc, struct listen_ctx *lctx, int isipv6)
{
struct tid_info *t = &sc->tids;
- int stid = -1;
+ u_int stid, n, f, mask;
+ struct stid_region *sr = &lctx->stid_region;
+
+ /*
+ * An IPv6 server needs 2 naturally aligned stids (1 stid = 4 cells) in
+ * the TCAM. The start of the stid region is properly aligned (the chip
+ * requires each region to be 128-cell aligned).
+ */
+ n = isipv6 ? 2 : 1;
+ mask = n - 1;
+ KASSERT((t->stid_base & mask) == 0 && (t->nstids & mask) == 0,
+ ("%s: stid region (%u, %u) not properly aligned. n = %u",
+ __func__, t->stid_base, t->nstids, n));
mtx_lock(&t->stid_lock);
- if (t->sfree) {
- union serv_entry *p = t->sfree;
-
- stid = p - t->stid_tab;
- stid += t->stid_base;
- t->sfree = p->next;
- p->data = ctx;
- t->stids_in_use++;
+ if (n > t->nstids - t->stids_in_use) {
+ mtx_unlock(&t->stid_lock);
+ return (-1);
}
+
+ if (t->nstids_free_head >= n) {
+ /*
+ * This allocation will definitely succeed because the region
+ * starts at a good alignment and we just checked we have enough
+ * stids free.
+ */
+ f = t->nstids_free_head & mask;
+ t->nstids_free_head -= n + f;
+ stid = t->nstids_free_head;
+ TAILQ_INSERT_HEAD(&t->stids, sr, link);
+ } else {
+ struct stid_region *s;
+
+ stid = t->nstids_free_head;
+ TAILQ_FOREACH(s, &t->stids, link) {
+ stid += s->used + s->free;
+ f = stid & mask;
+ if (n <= s->free - f) {
+ stid -= n + f;
+ s->free -= n + f;
+ TAILQ_INSERT_AFTER(&t->stids, s, sr, link);
+ goto allocated;
+ }
+ }
+
+ if (__predict_false(stid != t->nstids)) {
+ panic("%s: stids TAILQ (%p) corrupt."
+ " At %d instead of %d at the end of the queue.",
+ __func__, &t->stids, stid, t->nstids);
+ }
+
+ mtx_unlock(&t->stid_lock);
+ return (-1);
+ }
+
+allocated:
+ sr->used = n;
+ sr->free = f;
+ t->stids_in_use += n;
+ t->stid_tab[stid] = lctx;
mtx_unlock(&t->stid_lock);
- return (stid);
+
+ KASSERT(((stid + t->stid_base) & mask) == 0,
+ ("%s: EDOOFUS.", __func__));
+ return (stid + t->stid_base);
}
-static void *
+static struct listen_ctx *
lookup_stid(struct adapter *sc, int stid)
{
struct tid_info *t = &sc->tids;
- return (t->stid_tab[stid - t->stid_base].data);
+ return (t->stid_tab[stid - t->stid_base]);
}
static void
-free_stid(struct adapter *sc, int stid)
+free_stid(struct adapter *sc, struct listen_ctx *lctx)
{
struct tid_info *t = &sc->tids;
- union serv_entry *p = &t->stid_tab[stid - t->stid_base];
+ struct stid_region *sr = &lctx->stid_region;
+ struct stid_region *s;
+
+ KASSERT(sr->used > 0, ("%s: nonsense free (%d)", __func__, sr->used));
mtx_lock(&t->stid_lock);
- p->next = t->sfree;
- t->sfree = p;
- t->stids_in_use--;
+ s = TAILQ_PREV(sr, stid_head, link);
+ if (s != NULL)
+ s->free += sr->used + sr->free;
+ else
+ t->nstids_free_head += sr->used + sr->free;
+ KASSERT(t->stids_in_use >= sr->used,
+ ("%s: stids_in_use (%u) < stids being freed (%u)", __func__,
+ t->stids_in_use, sr->used));
+ t->stids_in_use -= sr->used;
+ TAILQ_REMOVE(&t->stids, sr, link);
mtx_unlock(&t->stid_lock);
}
@@ -134,7 +197,7 @@ alloc_lctx(struct adapter *sc, struct inpcb *inp, struct port_info *pi)
if (lctx == NULL)
return (NULL);
- lctx->stid = alloc_stid(sc, lctx);
+ lctx->stid = alloc_stid(sc, lctx, inp->inp_vflag & INP_IPV6);
if (lctx->stid < 0) {
free(lctx, M_CXGBE);
return (NULL);
@@ -167,7 +230,7 @@ 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);
- free_stid(sc, lctx->stid);
+ free_stid(sc, lctx);
free(lctx, M_CXGBE);
return (in_pcbrele_wlocked(inp));
@@ -339,7 +402,7 @@ create_server(struct adapter *sc, struct listen_ctx *lctx)
{
struct wrqe *wr;
struct cpl_pass_open_req *req;
- struct in_conninfo *inc = &lctx->inp->inp_inc;
+ struct inpcb *inp = lctx->inp;
wr = alloc_wrqe(sizeof(*req), lctx->ctrlq);
if (wr == NULL) {
@@ -350,9 +413,9 @@ create_server(struct adapter *sc, struct listen_ctx *lctx)
INIT_TP_WR(req, 0);
OPCODE_TID(req) = htobe32(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, lctx->stid));
- req->local_port = inc->inc_lport;
+ req->local_port = inp->inp_lport;
req->peer_port = 0;
- req->local_ip = inc->inc_laddr.s_addr;
+ req->local_ip = inp->inp_laddr.s_addr;
req->peer_ip = 0;
req->opt0 = htobe64(V_TX_CHAN(lctx->ctrlq->eq.tx_chan));
req->opt1 = htobe64(V_CONN_POLICY(CPL_CONN_POLICY_ASK) |
@@ -363,6 +426,36 @@ create_server(struct adapter *sc, struct listen_ctx *lctx)
}
static int
+create_server6(struct adapter *sc, struct listen_ctx *lctx)
+{
+ struct wrqe *wr;
+ struct cpl_pass_open_req6 *req;
+ struct inpcb *inp = lctx->inp;
+
+ wr = alloc_wrqe(sizeof(*req), lctx->ctrlq);
+ if (wr == NULL) {
+ log(LOG_ERR, "%s: allocation failure", __func__);
+ return (ENOMEM);
+ }
+ req = wrtod(wr);
+
+ INIT_TP_WR(req, 0);
+ OPCODE_TID(req) = htobe32(MK_OPCODE_TID(CPL_PASS_OPEN_REQ6, lctx->stid));
+ req->local_port = inp->inp_lport;
+ req->peer_port = 0;
+ req->local_ip_hi = *(uint64_t *)&inp->in6p_laddr.s6_addr[0];
+ req->local_ip_lo = *(uint64_t *)&inp->in6p_laddr.s6_addr[8];
+ req->peer_ip_hi = 0;
+ req->peer_ip_lo = 0;
+ req->opt0 = htobe64(V_TX_CHAN(lctx->ctrlq->eq.tx_chan));
+ req->opt1 = htobe64(V_CONN_POLICY(CPL_CONN_POLICY_ASK) |
+ F_SYN_RSS_ENABLE | V_SYN_RSS_QUEUE(lctx->ofld_rxq->iq.abs_id));
+
+ t4_wrq_tx(sc, wr);
+ return (0);
+}
+
+static int
destroy_server(struct adapter *sc, struct listen_ctx *lctx)
{
struct wrqe *wr;
@@ -398,13 +491,10 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp)
struct port_info *pi;
struct inpcb *inp = tp->t_inpcb;
struct listen_ctx *lctx;
- int i;
+ int i, rc;
INP_WLOCK_ASSERT(inp);
- if ((inp->inp_vflag & INP_IPV4) == 0)
- return (0);
-
#if 0
ADAPTER_LOCK(sc);
if (IS_BUSY(sc)) {
@@ -421,8 +511,9 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp)
goto done; /* no port that's UP with IFCAP_TOE enabled */
/*
- * Find a running port with IFCAP_TOE4. We'll use the first such port's
- * queues to send the passive open and receive the reply to it.
+ * Find a running port with IFCAP_TOE (4 or 6). We'll use the first
+ * such port's queues to send the passive open and receive the reply to
+ * it.
*
* XXX: need a way to mark a port in use by offload. if_cxgbe should
* then reject any attempt to bring down such a port (and maybe reject
@@ -430,7 +521,7 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp)
*/
for_each_port(sc, i) {
if (isset(&sc->open_device_map, i) &&
- sc->port[i]->ifp->if_capenable & IFCAP_TOE4)
+ sc->port[i]->ifp->if_capenable & IFCAP_TOE)
break;
}
KASSERT(i < sc->params.nports,
@@ -449,12 +540,17 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp)
}
listen_hash_add(sc, lctx);
- CTR5(KTR_CXGBE, "%s: stid %u (%s), lctx %p, inp %p", __func__,
- lctx->stid, tcpstates[tp->t_state], lctx, inp);
+ CTR6(KTR_CXGBE, "%s: stid %u (%s), lctx %p, inp %p vflag 0x%x",
+ __func__, lctx->stid, tcpstates[tp->t_state], lctx, inp,
+ inp->inp_vflag);
- if (create_server(sc, lctx) != 0) {
- log(LOG_ERR, "%s: %s failed to create hw listener.\n", __func__,
- device_get_nameunit(sc->dev));
+ if (inp->inp_vflag & INP_IPV6)
+ rc = create_server6(sc, lctx);
+ else
+ rc = create_server(sc, lctx);
+ if (rc != 0) {
+ log(LOG_ERR, "%s: %s failed to create hw listener: %d.\n",
+ __func__, device_get_nameunit(sc->dev), rc);
(void) listen_hash_del(sc, inp);
inp = release_lctx(sc, lctx);
/* can't be freed, host stack has a reference */
@@ -558,7 +654,7 @@ t4_syncache_respond(struct toedev *tod, void *arg, struct mbuf *m)
struct l2t_entry *e;
struct tcpopt to;
struct ip *ip = mtod(m, struct ip *);
- struct tcphdr *th = (void *)(ip + 1);
+ struct tcphdr *th;
wr = (struct wrqe *)atomic_readandclear_ptr(&synqe->wr);
if (wr == NULL) {
@@ -566,6 +662,10 @@ t4_syncache_respond(struct toedev *tod, void *arg, struct mbuf *m)
return (EALREADY);
}
+ if (ip->ip_v == IPVERSION)
+ th = (void *)(ip + 1);
+ else
+ th = (void *)((struct ip6_hdr *)ip + 1);
bzero(&to, sizeof(to));
tcp_dooptions(&to, (void *)(th + 1), (th->th_off << 2) - sizeof(*th),
TO_SYN);
@@ -608,7 +708,7 @@ do_pass_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
lctx->flags &= ~LCTX_RPL_PENDING;
if (status != CPL_ERR_NONE)
- log(LOG_ERR, "listener with stid %u failed: %d", stid, status);
+ log(LOG_ERR, "listener (stid %u) failed: %d\n", stid, status);
#ifdef INVARIANTS
/*
@@ -678,7 +778,7 @@ do_close_server_rpl(struct sge_iq *iq, const struct rss_header *rss,
CTR3(KTR_CXGBE, "%s: stid %u, status %u", __func__, stid, status);
if (status != CPL_ERR_NONE) {
- log(LOG_ERR, "%s: failed (%u) to close listener for stid %u",
+ log(LOG_ERR, "%s: failed (%u) to close listener for stid %u\n",
__func__, status, stid);
return (status);
}
@@ -735,8 +835,7 @@ do_abort_req_synqe(struct sge_iq *iq, const struct rss_header *rss,
CTR6(KTR_CXGBE, "%s: tid %u, synqe %p (0x%x), lctx %p, status %d",
__func__, tid, synqe, synqe->flags, synqe->lctx, cpl->status);
- if (cpl->status == CPL_ERR_RTX_NEG_ADVICE ||
- cpl->status == CPL_ERR_PERSIST_NEG_ADVICE)
+ if (negative_advice(cpl->status))
return (0); /* Ignore negative advice */
INP_WLOCK(inp);
@@ -855,7 +954,7 @@ mbuf_to_synqe(struct mbuf *m)
return (NULL);
synqe->flags = TPF_SYNQE | TPF_SYNQE_NEEDFREE;
} else {
- synqe = (void *)(m->m_data + m->m_len + tspace - sizeof(*synqe));
+ synqe = (void *)(m->m_data + m->m_len + tspace - len);
synqe->flags = TPF_SYNQE;
}
@@ -936,21 +1035,29 @@ pass_accept_req_to_protohdrs(const struct mbuf *m, struct in_conninfo *inc,
const struct cpl_pass_accept_req *cpl = mtod(m, const void *);
const struct ether_header *eh;
unsigned int hlen = be32toh(cpl->hdr_len);
- const struct ip *ip;
+ uintptr_t l3hdr;
const struct tcphdr *tcp;
eh = (const void *)(cpl + 1);
- ip = (const void *)((uintptr_t)eh + G_ETH_HDR_LEN(hlen));
- tcp = (const void *)((uintptr_t)ip + G_IP_HDR_LEN(hlen));
+ l3hdr = ((uintptr_t)eh + G_ETH_HDR_LEN(hlen));
+ tcp = (const void *)(l3hdr + G_IP_HDR_LEN(hlen));
if (inc) {
bzero(inc, sizeof(*inc));
- inc->inc_faddr = ip->ip_src;
- inc->inc_laddr = ip->ip_dst;
inc->inc_fport = tcp->th_sport;
inc->inc_lport = tcp->th_dport;
- if (ip->ip_v == 6)
+ if (((struct ip *)l3hdr)->ip_v == IPVERSION) {
+ const struct ip *ip = (const void *)l3hdr;
+
+ inc->inc_faddr = ip->ip_src;
+ inc->inc_laddr = ip->ip_dst;
+ } else {
+ const struct ip6_hdr *ip6 = (const void *)l3hdr;
+
inc->inc_flags |= INC_ISIPV6;
+ inc->inc6_faddr = ip6->ip6_src;
+ inc->inc6_laddr = ip6->ip6_dst;
+ }
}
if (th) {
@@ -959,6 +1066,105 @@ pass_accept_req_to_protohdrs(const struct mbuf *m, struct in_conninfo *inc,
}
}
+static int
+ifnet_has_ip6(struct ifnet *ifp, struct in6_addr *ip6)
+{
+ struct ifaddr *ifa;
+ struct sockaddr_in6 *sin6;
+ int found = 0;
+ struct in6_addr in6 = *ip6;
+
+ /* Just as in ip6_input */
+ if (in6_clearscope(&in6) || in6_clearscope(&in6))
+ return (0);
+ in6_setscope(&in6, ifp, NULL);
+
+ if_addr_rlock(ifp);
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ sin6 = (void *)ifa->ifa_addr;
+ if (sin6->sin6_family != AF_INET6)
+ continue;
+
+ if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &in6)) {
+ found = 1;
+ break;
+ }
+ }
+ if_addr_runlock(ifp);
+
+ return (found);
+}
+
+static struct l2t_entry *
+get_l2te_for_nexthop(struct port_info *pi, struct ifnet *ifp,
+ struct in_conninfo *inc)
+{
+ struct rtentry *rt;
+ struct l2t_entry *e;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *dst = (void *)&sin6;
+
+ if (inc->inc_flags & INC_ISIPV6) {
+ dst->sa_len = sizeof(struct sockaddr_in6);
+ dst->sa_family = AF_INET6;
+ ((struct sockaddr_in6 *)dst)->sin6_addr = inc->inc6_faddr;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&inc->inc6_laddr)) {
+ /* no need for route lookup */
+ e = t4_l2t_get(pi, ifp, dst);
+ return (e);
+ }
+ } else {
+ dst->sa_len = sizeof(struct sockaddr_in);
+ dst->sa_family = AF_INET;
+ ((struct sockaddr_in *)dst)->sin_addr = inc->inc_faddr;
+ }
+
+ rt = rtalloc1(dst, 0, 0);
+ if (rt == NULL)
+ return (NULL);
+ else {
+ struct sockaddr *nexthop;
+
+ RT_UNLOCK(rt);
+ if (rt->rt_ifp != ifp)
+ e = NULL;
+ else {
+ if (rt->rt_flags & RTF_GATEWAY)
+ nexthop = rt->rt_gateway;
+ else
+ nexthop = dst;
+ e = t4_l2t_get(pi, ifp, nexthop);
+ }
+ RTFREE(rt);
+ }
+
+ return (e);
+}
+
+static int
+ifnet_has_ip(struct ifnet *ifp, struct in_addr in)
+{
+ struct ifaddr *ifa;
+ struct sockaddr_in *sin;
+ int found = 0;
+
+ if_addr_rlock(ifp);
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ sin = (void *)ifa->ifa_addr;
+ if (sin->sin_family != AF_INET)
+ continue;
+
+ if (sin->sin_addr.s_addr == in.s_addr) {
+ found = 1;
+ break;
+ }
+ }
+ if_addr_runlock(ifp);
+
+ return (found);
+}
+
#define REJECT_PASS_ACCEPT() do { \
reject_reason = __LINE__; \
goto reject; \
@@ -994,10 +1200,8 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
struct tcphdr th;
struct tcpopt to;
struct port_info *pi;
- struct ifnet *ifp, *ifp_vlan = NULL;
+ struct ifnet *hw_ifp, *ifp;
struct l2t_entry *e = NULL;
- struct rtentry *rt;
- struct sockaddr_in nam;
int rscale, mtu_idx, rx_credits, rxqid, ulp_mode;
struct synq_entry *synqe = NULL;
int reject_reason;
@@ -1017,31 +1221,24 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
t4opt_to_tcpopt(&cpl->tcpopt, &to);
pi = sc->port[G_SYN_INTF(be16toh(cpl->l2info))];
- ifp = pi->ifp;
- m->m_pkthdr.rcvif = ifp;
- tod = TOEDEV(ifp);
+ hw_ifp = pi->ifp; /* the cxgbeX ifnet */
+ m->m_pkthdr.rcvif = hw_ifp;
+ tod = TOEDEV(hw_ifp);
/*
- * Don't offload if the interface that received the SYN doesn't have
- * IFCAP_TOE enabled.
- */
- if ((ifp->if_capenable & IFCAP_TOE4) == 0)
- REJECT_PASS_ACCEPT();
-
- /* Don't offload IPv6 connections. XXX: add IPv6 support */
- if (inc.inc_flags & INC_ISIPV6)
- REJECT_PASS_ACCEPT();
-
- /*
- * Don't offload if the SYN had a VLAN tag and the vid doesn't match
- * anything on this interface.
+ * Figure out if there is a pseudo interface (vlan, lagg, etc.)
+ * involved. Don't offload if the SYN had a VLAN tag and the vid
+ * doesn't match anything on this interface.
+ *
+ * XXX: lagg support, lagg + vlan support.
*/
vid = EVL_VLANOFTAG(be16toh(cpl->vlan));
if (vid != 0xfff) {
- ifp_vlan = VLAN_DEVAT(ifp, vid);
- if (ifp_vlan == NULL)
+ ifp = VLAN_DEVAT(hw_ifp, vid);
+ if (ifp == NULL)
REJECT_PASS_ACCEPT();
- }
+ } else
+ ifp = hw_ifp;
/*
* Don't offload if the peer requested a TCP option that's not known to
@@ -1050,31 +1247,36 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
if (cpl->tcpopt.unknown)
REJECT_PASS_ACCEPT();
- /*
- * Don't offload if the outgoing interface for the route back to the
- * peer is not the same as the interface that received the SYN.
- * XXX: too restrictive.
- */
- nam.sin_len = sizeof(nam);
- nam.sin_family = AF_INET;
- nam.sin_addr = inc.inc_faddr;
- rt = rtalloc1((struct sockaddr *)&nam, 0, 0);
- if (rt == NULL)
- REJECT_PASS_ACCEPT();
- else {
- struct sockaddr *nexthop;
+ if (inc.inc_flags & INC_ISIPV6) {
- RT_UNLOCK(rt);
- nexthop = rt->rt_flags & RTF_GATEWAY ? rt->rt_gateway :
- (struct sockaddr *)&nam;
- if (rt->rt_ifp == ifp ||
- (ifp_vlan != NULL && rt->rt_ifp == ifp_vlan))
- e = t4_l2t_get(pi, rt->rt_ifp, nexthop);
- RTFREE(rt);
- if (e == NULL)
- REJECT_PASS_ACCEPT(); /* no l2te, or ifp mismatch */
+ /* Don't offload if the ifcap isn't enabled */
+ if ((ifp->if_capenable & IFCAP_TOE6) == 0)
+ REJECT_PASS_ACCEPT();
+
+ /*
+ * SYN must be directed to an IP6 address on this ifnet. This
+ * is more restrictive than in6_localip.
+ */
+ if (!ifnet_has_ip6(ifp, &inc.inc6_laddr))
+ REJECT_PASS_ACCEPT();
+ } else {
+
+ /* Don't offload if the ifcap isn't enabled */
+ if ((ifp->if_capenable & IFCAP_TOE4) == 0)
+ REJECT_PASS_ACCEPT();
+
+ /*
+ * SYN must be directed to an IP address on this ifnet. This
+ * is more restrictive than in_localip.
+ */
+ if (!ifnet_has_ip(ifp, inc.inc_laddr))
+ REJECT_PASS_ACCEPT();
}
+ e = get_l2te_for_nexthop(pi, ifp, &inc);
+ if (e == NULL)
+ REJECT_PASS_ACCEPT();
+
synqe = mbuf_to_synqe(m);
if (synqe == NULL)
REJECT_PASS_ACCEPT();
@@ -1133,7 +1335,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
synqe->lctx = lctx;
synqe->syn = m;
m = NULL;
- refcount_init(&synqe->refcnt, 0);
+ refcount_init(&synqe->refcnt, 1); /* 1 means extra hold */
synqe->l2e_idx = e->idx;
synqe->rcv_bufsize = rx_credits;
atomic_store_rel_ptr(&synqe->wr, (uintptr_t)wr);
@@ -1166,7 +1368,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
*/
m = m_dup(synqe->syn, M_NOWAIT);
if (m)
- m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.rcvif = hw_ifp;
remove_tid(sc, synqe->tid);
free(wr, M_CXGBE);
@@ -1179,6 +1381,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
if (inp)
INP_WUNLOCK(inp);
+ release_synqe(synqe); /* extra hold */
REJECT_PASS_ACCEPT();
}
@@ -1193,15 +1396,19 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
* this tid because there was no L2T entry for the tid at that
* time. Abort it now. The reply to the abort will clean up.
*/
- CTR5(KTR_CXGBE, "%s: stid %u, tid %u, lctx %p, synqe %p, ABORT",
- __func__, stid, tid, lctx, synqe);
- send_reset_synqe(tod, synqe);
+ CTR6(KTR_CXGBE,
+ "%s: stid %u, tid %u, lctx %p, synqe %p (0x%x), ABORT",
+ __func__, stid, tid, lctx, synqe, synqe->flags);
+ if (!(synqe->flags & TPF_SYNQE_EXPANDED))
+ send_reset_synqe(tod, synqe);
INP_WUNLOCK(inp);
+ release_synqe(synqe); /* extra hold */
return (__LINE__);
}
INP_WUNLOCK(inp);
+ release_synqe(synqe); /* extra hold */
return (0);
reject:
CTR4(KTR_CXGBE, "%s: stid %u, tid %u, REJECT (%d)", __func__, stid, tid,
@@ -1216,7 +1423,7 @@ reject:
m->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID |
CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
m->m_pkthdr.csum_data = 0xffff;
- ifp->if_input(ifp, m);
+ hw_ifp->if_input(hw_ifp, m);
}
return (reject_reason);
diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index 330172d..64e8b26 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -29,6 +29,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/types.h>
@@ -40,10 +41,14 @@ __FBSDID("$FreeBSD$");
#include <sys/domain.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
+#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/tcp_var.h>
+#include <netinet6/scope6_var.h>
#define TCPSTATES
#include <netinet/tcp_fsm.h>
#include <netinet/toecore.h>
@@ -58,6 +63,9 @@ __FBSDID("$FreeBSD$");
static struct protosw ddp_protosw;
static struct pr_usrreqs ddp_usrreqs;
+static struct protosw ddp6_protosw;
+static struct pr_usrreqs ddp6_usrreqs;
+
/* Module ops */
static int t4_tom_mod_load(void);
static int t4_tom_mod_unload(void);
@@ -77,6 +85,11 @@ static void queue_tid_release(struct adapter *, int);
static void release_offload_resources(struct toepcb *);
static int alloc_tid_tabs(struct tid_info *);
static void free_tid_tabs(struct tid_info *);
+static int add_lip(struct adapter *, struct in6_addr *);
+static int delete_lip(struct adapter *, struct in6_addr *);
+static struct clip_entry *search_lip(struct tom_data *, struct in6_addr *);
+static void init_clip_table(struct adapter *, struct tom_data *);
+static void destroy_clip_table(struct adapter *, struct tom_data *);
static void free_tom_data(struct adapter *, struct tom_data *);
struct toepcb *
@@ -170,8 +183,12 @@ offload_socket(struct socket *so, struct toepcb *toep)
sb = &so->so_rcv;
SOCKBUF_LOCK(sb);
sb->sb_flags |= SB_NOCOALESCE;
- if (toep->ulp_mode == ULP_MODE_TCPDDP)
- so->so_proto = &ddp_protosw;
+ if (toep->ulp_mode == ULP_MODE_TCPDDP) {
+ if (inp->inp_vflag & INP_IPV6)
+ so->so_proto = &ddp6_protosw;
+ else
+ so->so_proto = &ddp_protosw;
+ }
SOCKBUF_UNLOCK(sb);
/* Update TCP PCB */
@@ -237,8 +254,8 @@ release_offload_resources(struct toepcb *toep)
KASSERT(!(toep->flags & TPF_ATTACHED),
("%s: %p is still attached.", __func__, toep));
- CTR4(KTR_CXGBE, "%s: toep %p (tid %d, l2te %p)",
- __func__, toep, tid, toep->l2te);
+ CTR5(KTR_CXGBE, "%s: toep %p (tid %d, l2te %p, ce %p)",
+ __func__, toep, tid, toep->l2te, toep->ce);
if (toep->ulp_mode == ULP_MODE_TCPDDP)
release_ddp_resources(toep);
@@ -251,6 +268,9 @@ release_offload_resources(struct toepcb *toep)
release_tid(sc, tid, toep->ctrlq);
}
+ if (toep->ce)
+ release_lip(td, toep->ce);
+
mtx_lock(&td->toep_list_lock);
TAILQ_REMOVE(&td->toep_list, toep, link);
mtx_unlock(&td->toep_list_lock);
@@ -394,7 +414,7 @@ int
find_best_mtu_idx(struct adapter *sc, struct in_conninfo *inc, int pmss)
{
unsigned short *mtus = &sc->params.mtus[0];
- int i = 0, mss;
+ int i, mss, n;
KASSERT(inc != NULL || pmss > 0,
("%s: at least one of inc/pmss must be specified", __func__));
@@ -403,8 +423,13 @@ find_best_mtu_idx(struct adapter *sc, struct in_conninfo *inc, int pmss)
if (pmss > 0 && mss > pmss)
mss = pmss;
- while (i < NMTUS - 1 && mtus[i + 1] <= mss + 40)
- ++i;
+ if (inc->inc_flags & INC_ISIPV6)
+ n = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
+ else
+ n = sizeof(struct ip) + sizeof(struct tcphdr);
+
+ for (i = 0; i < NMTUS - 1 && mtus[i + 1] <= mss + n; i++)
+ continue;
return (i);
}
@@ -513,6 +538,24 @@ select_ntuple(struct port_info *pi, struct l2t_entry *e, uint32_t filter_mode)
return (htobe32(ntuple));
}
+void
+set_tcpddp_ulp_mode(struct toepcb *toep)
+{
+
+ toep->ulp_mode = ULP_MODE_TCPDDP;
+ toep->ddp_flags = DDP_OK;
+ toep->ddp_score = DDP_LOW_SCORE;
+}
+
+int
+negative_advice(int status)
+{
+
+ return (status == CPL_ERR_RTX_NEG_ADVICE ||
+ status == CPL_ERR_PERSIST_NEG_ADVICE ||
+ status == CPL_ERR_KEEPALV_NEG_ADVICE);
+}
+
static int
alloc_tid_tabs(struct tid_info *t)
{
@@ -536,12 +579,10 @@ alloc_tid_tabs(struct tid_info *t)
t->atid_tab[t->natids - 1].next = NULL;
mtx_init(&t->stid_lock, "stid lock", NULL, MTX_DEF);
- t->stid_tab = (union serv_entry *)&t->atid_tab[t->natids];
- t->sfree = t->stid_tab;
+ t->stid_tab = (struct listen_ctx **)&t->atid_tab[t->natids];
t->stids_in_use = 0;
- for (i = 1; i < t->nstids; i++)
- t->stid_tab[i - 1].next = &t->stid_tab[i];
- t->stid_tab[t->nstids - 1].next = NULL;
+ TAILQ_INIT(&t->stids);
+ t->nstids_free_head = t->nstids;
atomic_store_rel_int(&t->tids_in_use, 0);
@@ -567,9 +608,157 @@ free_tid_tabs(struct tid_info *t)
mtx_destroy(&t->stid_lock);
}
+static int
+add_lip(struct adapter *sc, struct in6_addr *lip)
+{
+ struct fw_clip_cmd c;
+
+ ASSERT_SYNCHRONIZED_OP(sc);
+ /* mtx_assert(&td->clip_table_lock, MA_OWNED); */
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE);
+ c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c));
+ c.ip_hi = *(uint64_t *)&lip->s6_addr[0];
+ c.ip_lo = *(uint64_t *)&lip->s6_addr[8];
+
+ return (t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c));
+}
+
+static int
+delete_lip(struct adapter *sc, struct in6_addr *lip)
+{
+ struct fw_clip_cmd c;
+
+ ASSERT_SYNCHRONIZED_OP(sc);
+ /* mtx_assert(&td->clip_table_lock, MA_OWNED); */
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_READ);
+ c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_FREE | FW_LEN16(c));
+ c.ip_hi = *(uint64_t *)&lip->s6_addr[0];
+ c.ip_lo = *(uint64_t *)&lip->s6_addr[8];
+
+ return (t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c));
+}
+
+static struct clip_entry *
+search_lip(struct tom_data *td, struct in6_addr *lip)
+{
+ struct clip_entry *ce;
+
+ mtx_assert(&td->clip_table_lock, MA_OWNED);
+
+ TAILQ_FOREACH(ce, &td->clip_table, link) {
+ if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip))
+ return (ce);
+ }
+
+ return (NULL);
+}
+
+struct clip_entry *
+hold_lip(struct tom_data *td, struct in6_addr *lip)
+{
+ struct clip_entry *ce;
+
+ mtx_lock(&td->clip_table_lock);
+ ce = search_lip(td, lip);
+ if (ce != NULL)
+ ce->refcount++;
+ mtx_unlock(&td->clip_table_lock);
+
+ return (ce);
+}
+
+void
+release_lip(struct tom_data *td, struct clip_entry *ce)
+{
+
+ mtx_lock(&td->clip_table_lock);
+ KASSERT(search_lip(td, &ce->lip) == ce,
+ ("%s: CLIP entry %p p not in CLIP table.", __func__, ce));
+ KASSERT(ce->refcount > 0,
+ ("%s: CLIP entry %p has refcount 0", __func__, ce));
+ --ce->refcount;
+ mtx_unlock(&td->clip_table_lock);
+}
+
+static void
+init_clip_table(struct adapter *sc, struct tom_data *td)
+{
+ struct in6_ifaddr *ia;
+ struct in6_addr *lip, tlip;
+ struct clip_entry *ce;
+
+ ASSERT_SYNCHRONIZED_OP(sc);
+
+ mtx_init(&td->clip_table_lock, "CLIP table lock", NULL, MTX_DEF);
+ TAILQ_INIT(&td->clip_table);
+
+ IN6_IFADDR_RLOCK();
+ TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
+ lip = &ia->ia_addr.sin6_addr;
+
+ KASSERT(!IN6_IS_ADDR_MULTICAST(lip),
+ ("%s: mcast address in in6_ifaddr list", __func__));
+
+ if (IN6_IS_ADDR_LOOPBACK(lip))
+ continue;
+ if (IN6_IS_SCOPE_EMBED(lip)) {
+ /* Remove the embedded scope */
+ tlip = *lip;
+ lip = &tlip;
+ in6_clearscope(lip);
+ }
+ /*
+ * XXX: how to weed out the link local address for the loopback
+ * interface? It's fe80::1 usually (always?).
+ */
+
+ mtx_lock(&td->clip_table_lock);
+ if (search_lip(td, lip) == NULL) {
+ ce = malloc(sizeof(*ce), M_CXGBE, M_NOWAIT);
+ memcpy(&ce->lip, lip, sizeof(ce->lip));
+ ce->refcount = 0;
+ if (add_lip(sc, lip) == 0)
+ TAILQ_INSERT_TAIL(&td->clip_table, ce, link);
+ else
+ free(ce, M_CXGBE);
+ }
+ mtx_unlock(&td->clip_table_lock);
+ }
+ IN6_IFADDR_RUNLOCK();
+}
+
+static void
+destroy_clip_table(struct adapter *sc, struct tom_data *td)
+{
+ struct clip_entry *ce, *ce_temp;
+
+ if (mtx_initialized(&td->clip_table_lock)) {
+ mtx_lock(&td->clip_table_lock);
+ TAILQ_FOREACH_SAFE(ce, &td->clip_table, link, ce_temp) {
+ KASSERT(ce->refcount == 0,
+ ("%s: CLIP entry %p still in use (%d)", __func__,
+ ce, ce->refcount));
+ TAILQ_REMOVE(&td->clip_table, ce, link);
+ delete_lip(sc, &ce->lip);
+ free(ce, M_CXGBE);
+ }
+ mtx_unlock(&td->clip_table_lock);
+ mtx_destroy(&td->clip_table_lock);
+ }
+}
+
static void
free_tom_data(struct adapter *sc, struct tom_data *td)
{
+
+ ASSERT_SYNCHRONIZED_OP(sc);
+
KASSERT(TAILQ_EMPTY(&td->toep_list),
("%s: TOE PCB list is not empty.", __func__));
KASSERT(td->lctx_count == 0,
@@ -578,6 +767,7 @@ free_tom_data(struct adapter *sc, struct tom_data *td)
t4_uninit_l2t_cpl_handlers(sc);
t4_uninit_cpl_io_handlers(sc);
t4_uninit_ddp(sc, td);
+ destroy_clip_table(sc, td);
if (td->listen_mask != 0)
hashdestroy(td->listen_hash, M_CXGBE, td->listen_mask);
@@ -602,7 +792,7 @@ t4_tom_activate(struct adapter *sc)
struct toedev *tod;
int i, rc;
- ADAPTER_LOCK_ASSERT_OWNED(sc); /* for sc->flags */
+ ASSERT_SYNCHRONIZED_OP(sc);
/* per-adapter softc for TOM */
td = malloc(sizeof(*td), M_CXGBE, M_ZERO | M_NOWAIT);
@@ -623,8 +813,12 @@ t4_tom_activate(struct adapter *sc)
if (rc != 0)
goto done;
+ /* DDP page pods and CPL handlers */
t4_init_ddp(sc, td);
+ /* CLIP table for IPv6 offload */
+ init_clip_table(sc, td);
+
/* CPL handlers */
t4_init_connect_cpl_handlers(sc);
t4_init_l2t_cpl_handlers(sc);
@@ -668,7 +862,7 @@ t4_tom_deactivate(struct adapter *sc)
int rc = 0;
struct tom_data *td = sc->tom_softc;
- ADAPTER_LOCK_ASSERT_OWNED(sc); /* for sc->flags */
+ ASSERT_SYNCHRONIZED_OP(sc);
if (td == NULL)
return (0); /* XXX. KASSERT? */
@@ -700,17 +894,24 @@ static int
t4_tom_mod_load(void)
{
int rc;
- struct protosw *tcp_protosw;
+ struct protosw *tcp_protosw, *tcp6_protosw;
tcp_protosw = pffindproto(PF_INET, IPPROTO_TCP, SOCK_STREAM);
if (tcp_protosw == NULL)
return (ENOPROTOOPT);
-
bcopy(tcp_protosw, &ddp_protosw, sizeof(ddp_protosw));
bcopy(tcp_protosw->pr_usrreqs, &ddp_usrreqs, sizeof(ddp_usrreqs));
ddp_usrreqs.pru_soreceive = t4_soreceive_ddp;
ddp_protosw.pr_usrreqs = &ddp_usrreqs;
+ tcp6_protosw = pffindproto(PF_INET6, IPPROTO_TCP, SOCK_STREAM);
+ if (tcp6_protosw == NULL)
+ return (ENOPROTOOPT);
+ bcopy(tcp6_protosw, &ddp6_protosw, sizeof(ddp6_protosw));
+ bcopy(tcp6_protosw->pr_usrreqs, &ddp6_usrreqs, sizeof(ddp6_usrreqs));
+ ddp6_usrreqs.pru_soreceive = t4_soreceive_ddp;
+ ddp6_protosw.pr_usrreqs = &ddp6_usrreqs;
+
rc = t4_register_uld(&tom_uld_info);
if (rc != 0)
t4_tom_mod_unload();
@@ -721,11 +922,14 @@ t4_tom_mod_load(void)
static void
tom_uninit(struct adapter *sc, void *arg __unused)
{
+ if (begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4tomun"))
+ return;
+
/* Try to free resources (works only if no port has IFCAP_TOE) */
- ADAPTER_LOCK(sc);
if (sc->flags & TOM_INIT_DONE)
t4_deactivate_uld(sc, ULD_TOM);
- ADAPTER_UNLOCK(sc);
+
+ end_synchronized_op(sc, LOCK_HELD);
}
static int
diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h
index 9549b0b..d0fbbd2 100644
--- a/sys/dev/cxgbe/tom/t4_tom.h
+++ b/sys/dev/cxgbe/tom/t4_tom.h
@@ -109,6 +109,7 @@ struct toepcb {
struct sge_ofld_rxq *ofld_rxq;
struct sge_wrq *ctrlq;
struct l2t_entry *l2te; /* L2 table entry used by this connection */
+ struct clip_entry *ce; /* CLIP table entry used by this tid */
int tid; /* Connection identifier */
unsigned int tx_credits;/* tx WR credits (in 16 byte units) remaining */
unsigned int sb_cc; /* last noted value of so_rcv->sb_cc */
@@ -140,15 +141,6 @@ struct flowc_tx_params {
#define DDP_LOW_SCORE 1
#define DDP_HIGH_SCORE 3
-static inline void
-set_tcpddp_ulp_mode(struct toepcb *toep)
-{
-
- toep->ulp_mode = ULP_MODE_TCPDDP;
- toep->ddp_flags = DDP_OK;
- toep->ddp_score = DDP_LOW_SCORE;
-}
-
/*
* Compressed state for embryonic connections for a listener. Barely fits in
* 64B, try not to grow it further.
@@ -174,6 +166,7 @@ struct listen_ctx {
LIST_ENTRY(listen_ctx) link; /* listen hash linkage */
volatile int refcount;
int stid;
+ struct stid_region stid_region;
int flags;
struct inpcb *inp; /* listening socket's inp */
struct sge_wrq *ctrlq;
@@ -183,6 +176,12 @@ struct listen_ctx {
TAILQ_HEAD(ppod_head, ppod_region);
+struct clip_entry {
+ TAILQ_ENTRY(clip_entry) link;
+ struct in6_addr lip; /* local IPv6 address */
+ u_int refcount;
+};
+
struct tom_data {
struct toedev tod;
@@ -200,6 +199,9 @@ struct tom_data {
int nppods_free; /* # of available ppods */
int nppods_free_head; /* # of available ppods at the begining */
struct ppod_head ppods;
+
+ struct mtx clip_table_lock;
+ TAILQ_HEAD(, clip_entry) clip_table;
};
static inline struct tom_data *
@@ -233,6 +235,10 @@ int select_rcv_wscale(void);
uint64_t calc_opt0(struct socket *, struct port_info *, struct l2t_entry *,
int, int, int, int);
uint32_t select_ntuple(struct port_info *, struct l2t_entry *, uint32_t);
+void set_tcpddp_ulp_mode(struct toepcb *);
+int negative_advice(int);
+struct clip_entry *hold_lip(struct tom_data *, struct in6_addr *);
+void release_lip(struct tom_data *, struct clip_entry *);
/* t4_connect.c */
void t4_init_connect_cpl_handlers(struct adapter *);
diff --git a/sys/dev/cxgbe/tom/t4_tom_l2t.c b/sys/dev/cxgbe/tom/t4_tom_l2t.c
index ffe64c5..7a75394 100644
--- a/sys/dev/cxgbe/tom/t4_tom_l2t.c
+++ b/sys/dev/cxgbe/tom/t4_tom_l2t.c
@@ -27,6 +27,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#ifdef TCP_OFFLOAD
#include <sys/param.h>
@@ -34,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/fnv_hash.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>
@@ -48,28 +50,89 @@ __FBSDID("$FreeBSD$");
#include <netinet/toecore.h>
#include "common/common.h"
-#include "common/jhash.h"
#include "common/t4_msg.h"
#include "tom/t4_tom_l2t.h"
#include "tom/t4_tom.h"
#define VLAN_NONE 0xfff
-#define SA(x) ((struct sockaddr *)(x))
-#define SIN(x) ((struct sockaddr_in *)(x))
-#define SINADDR(x) (SIN(x)->sin_addr.s_addr)
-
static inline void
l2t_hold(struct l2t_data *d, struct l2t_entry *e)
{
+
if (atomic_fetchadd_int(&e->refcnt, 1) == 0) /* 0 -> 1 transition */
atomic_subtract_int(&d->nfree, 1);
}
-static inline unsigned int
-arp_hash(const uint32_t key, int ifindex)
+static inline u_int
+l2_hash(struct l2t_data *d, const struct sockaddr *sa, int ifindex)
{
- return jhash_2words(key, ifindex, 0) & (L2T_SIZE - 1);
+ u_int hash, half = d->l2t_size / 2, start = 0;
+ const void *key;
+ size_t len;
+
+ KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
+ ("%s: sa %p has unexpected sa_family %d", __func__, sa,
+ sa->sa_family));
+
+ if (sa->sa_family == AF_INET) {
+ const struct sockaddr_in *sin = (const void *)sa;
+
+ key = &sin->sin_addr;
+ len = sizeof(sin->sin_addr);
+ } else {
+ const struct sockaddr_in6 *sin6 = (const void *)sa;
+
+ key = &sin6->sin6_addr;
+ len = sizeof(sin6->sin6_addr);
+ start = half;
+ }
+
+ hash = fnv_32_buf(key, len, FNV1_32_INIT);
+ hash = fnv_32_buf(&ifindex, sizeof(ifindex), hash);
+ hash %= half;
+
+ return (hash + start);
+}
+
+static inline int
+l2_cmp(const struct sockaddr *sa, struct l2t_entry *e)
+{
+
+ KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
+ ("%s: sa %p has unexpected sa_family %d", __func__, sa,
+ sa->sa_family));
+
+ if (sa->sa_family == AF_INET) {
+ const struct sockaddr_in *sin = (const void *)sa;
+
+ return (e->addr[0] != sin->sin_addr.s_addr);
+ } else {
+ const struct sockaddr_in6 *sin6 = (const void *)sa;
+
+ return (memcmp(&e->addr[0], &sin6->sin6_addr, sizeof(e->addr)));
+ }
+}
+
+static inline void
+l2_store(const struct sockaddr *sa, struct l2t_entry *e)
+{
+
+ KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
+ ("%s: sa %p has unexpected sa_family %d", __func__, sa,
+ sa->sa_family));
+
+ if (sa->sa_family == AF_INET) {
+ const struct sockaddr_in *sin = (const void *)sa;
+
+ e->addr[0] = sin->sin_addr.s_addr;
+ e->ipv6 = 0;
+ } else {
+ const struct sockaddr_in6 *sin6 = (const void *)sa;
+
+ memcpy(&e->addr[0], &sin6->sin6_addr, sizeof(e->addr));
+ e->ipv6 = 1;
+ }
}
/*
@@ -100,7 +163,7 @@ send_pending(struct adapter *sc, struct l2t_entry *e)
static void
resolution_failed_for_wr(struct wrqe *wr)
{
- log(LOG_ERR, "%s: leaked work request %p, wr_len %d", __func__, wr,
+ log(LOG_ERR, "%s: leaked work request %p, wr_len %d\n", __func__, wr,
wr->wr_len);
/* free(wr, M_CXGBE); */
@@ -175,15 +238,25 @@ resolve_entry(struct adapter *sc, struct l2t_entry *e)
struct tom_data *td = sc->tom_softc;
struct toedev *tod = &td->tod;
struct sockaddr_in sin = {0};
+ struct sockaddr_in6 sin6 = {0};
+ struct sockaddr *sa;
uint8_t dmac[ETHER_ADDR_LEN];
uint16_t vtag = VLAN_NONE;
int rc;
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(struct sockaddr_in);
- SINADDR(&sin) = e->addr;
+ if (e->ipv6 == 0) {
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_addr.s_addr = e->addr[0];
+ sa = (void *)&sin;
+ } else {
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&sin6.sin6_addr, &e->addr[0], sizeof(e->addr));
+ sa = (void *)&sin6;
+ }
- rc = toe_l2_resolve(tod, e->ifp, SA(&sin), dmac, &vtag);
+ rc = toe_l2_resolve(tod, e->ifp, sa, dmac, &vtag);
if (rc == EWOULDBLOCK)
return (rc);
@@ -263,7 +336,7 @@ do_l2t_write_rpl2(struct sge_iq *iq, const struct rss_header *rss,
struct adapter *sc = iq->adapter;
const struct cpl_l2t_write_rpl *rpl = (const void *)(rss + 1);
unsigned int tid = GET_TID(rpl);
- unsigned int idx = tid & (L2T_SIZE - 1);
+ unsigned int idx = tid % L2T_SIZE;
int rc;
rc = do_l2t_write_rpl(iq, rss, m);
@@ -271,7 +344,7 @@ do_l2t_write_rpl2(struct sge_iq *iq, const struct rss_header *rss,
return (rc);
if (tid & F_SYNC_WR) {
- struct l2t_entry *e = &sc->l2t->l2tab[idx];
+ struct l2t_entry *e = &sc->l2t->l2tab[idx - sc->vres.l2t.start];
mtx_lock(&e->lock);
if (e->state != L2T_STATE_SWITCHING) {
@@ -310,21 +383,22 @@ t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa)
{
struct l2t_entry *e;
struct l2t_data *d = pi->adapter->l2t;
- uint32_t addr = SINADDR(sa);
- int hash = arp_hash(addr, ifp->if_index);
- unsigned int smt_idx = pi->port_id;
+ u_int hash, smt_idx = pi->port_id;
- if (sa->sa_family != AF_INET)
- return (NULL); /* XXX: no IPv6 support right now */
+ KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
+ ("%s: sa %p has unexpected sa_family %d", __func__, sa,
+ sa->sa_family));
#ifndef VLAN_TAG
if (ifp->if_type == IFT_L2VLAN)
return (NULL);
#endif
+ hash = l2_hash(d, sa, ifp->if_index);
rw_wlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next) {
- if (e->addr == addr && e->ifp == ifp && e->smt_idx == smt_idx) {
+ if (l2_cmp(sa, e) == 0 && e->ifp == ifp &&
+ e->smt_idx == smt_idx) {
l2t_hold(d, e);
goto done;
}
@@ -338,7 +412,7 @@ t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa)
d->l2tab[hash].first = e;
e->state = L2T_STATE_RESOLVING;
- e->addr = addr;
+ l2_store(sa, e);
e->ifp = ifp;
e->smt_idx = smt_idx;
e->hash = hash;
@@ -368,14 +442,14 @@ t4_l2_update(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
struct adapter *sc = tod->tod_softc;
struct l2t_entry *e;
struct l2t_data *d = sc->l2t;
- uint32_t addr = SINADDR(sa);
- int hash = arp_hash(addr, ifp->if_index);
+ u_int hash;
KASSERT(d != NULL, ("%s: no L2 table", __func__));
+ hash = l2_hash(d, sa, ifp->if_index);
rw_rlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next) {
- if (e->addr == addr && e->ifp == ifp) {
+ if (l2_cmp(sa, e) == 0 && e->ifp == ifp) {
mtx_lock(&e->lock);
if (atomic_load_acq_int(&e->refcnt))
goto found;
diff --git a/sys/dev/digi/digi_isa.c b/sys/dev/digi/digi_isa.c
index f1f4a5f..0a0a2a0 100644
--- a/sys/dev/digi/digi_isa.c
+++ b/sys/dev/digi/digi_isa.c
@@ -462,7 +462,8 @@ static device_method_t digi_isa_methods[] = {
DEVMETHOD(device_attach, digi_isa_attach),
DEVMETHOD(device_detach, digi_detach),
DEVMETHOD(device_shutdown, digi_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t digi_isa_drv = {
diff --git a/sys/dev/digi/digi_pci.c b/sys/dev/digi/digi_pci.c
index 342858e..55814cd 100644
--- a/sys/dev/digi/digi_pci.c
+++ b/sys/dev/digi/digi_pci.c
@@ -219,7 +219,8 @@ static device_method_t digi_pci_methods[] = {
DEVMETHOD(device_attach, digi_pci_attach),
DEVMETHOD(device_detach, digi_detach),
DEVMETHOD(device_shutdown, digi_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t digi_pci_drv = {
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 8ba32e0..3344697 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -309,7 +309,7 @@ static device_method_t em_methods[] = {
DEVMETHOD(device_shutdown, em_shutdown),
DEVMETHOD(device_suspend, em_suspend),
DEVMETHOD(device_resume, em_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t em_driver = {
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 8eb3011..2921a91 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -294,7 +294,7 @@ static device_method_t igb_methods[] = {
DEVMETHOD(device_shutdown, igb_shutdown),
DEVMETHOD(device_suspend, igb_suspend),
DEVMETHOD(device_resume, igb_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t igb_driver = {
@@ -4330,8 +4330,8 @@ fail:
* the rings that completed, the failing case will have
* cleaned up for itself. 'i' is the endpoint.
*/
- for (int j = 0; j > i; ++j) {
- rxr = &adapter->rx_rings[i];
+ for (int j = 0; j < i; ++j) {
+ rxr = &adapter->rx_rings[j];
IGB_RX_LOCK(rxr);
igb_free_receive_ring(rxr);
IGB_RX_UNLOCK(rxr);
diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c
index 58e6c7e..6b2b4f7 100644
--- a/sys/dev/e1000/if_lem.c
+++ b/sys/dev/e1000/if_lem.c
@@ -262,7 +262,7 @@ static device_method_t lem_methods[] = {
DEVMETHOD(device_shutdown, lem_shutdown),
DEVMETHOD(device_suspend, lem_suspend),
DEVMETHOD(device_resume, lem_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t lem_driver = {
diff --git a/sys/dev/ep/if_ep_eisa.c b/sys/dev/ep/if_ep_eisa.c
index e25a531..bc77ec8 100644
--- a/sys/dev/ep/if_ep_eisa.c
+++ b/sys/dev/ep/if_ep_eisa.c
@@ -238,7 +238,7 @@ static device_method_t ep_eisa_methods[] = {
DEVMETHOD(device_attach, ep_eisa_attach),
DEVMETHOD(device_detach, ep_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ep_eisa_driver = {
diff --git a/sys/dev/ep/if_ep_isa.c b/sys/dev/ep/if_ep_isa.c
index 0455c40..e125daf 100644
--- a/sys/dev/ep/if_ep_isa.c
+++ b/sys/dev/ep/if_ep_isa.c
@@ -391,7 +391,7 @@ static device_method_t ep_isa_methods[] = {
DEVMETHOD(device_attach, ep_isa_attach),
DEVMETHOD(device_detach, ep_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ep_isa_driver = {
diff --git a/sys/dev/ep/if_ep_mca.c b/sys/dev/ep/if_ep_mca.c
index 3c1645c..17097ab 100644
--- a/sys/dev/ep/if_ep_mca.c
+++ b/sys/dev/ep/if_ep_mca.c
@@ -145,7 +145,7 @@ static device_method_t ep_mca_methods[] = {
DEVMETHOD(device_attach, ep_mca_attach),
DEVMETHOD(device_detach, ep_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ep_mca_driver = {
diff --git a/sys/dev/ep/if_ep_pccard.c b/sys/dev/ep/if_ep_pccard.c
index 98ebaf4..1b445f9 100644
--- a/sys/dev/ep/if_ep_pccard.c
+++ b/sys/dev/ep/if_ep_pccard.c
@@ -223,7 +223,7 @@ static device_method_t ep_pccard_methods[] = {
DEVMETHOD(device_attach, ep_pccard_attach),
DEVMETHOD(device_detach, ep_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ep_pccard_driver = {
diff --git a/sys/dev/fdc/fdc_acpi.c b/sys/dev/fdc/fdc_acpi.c
index 7769a57..fd5bf90 100644
--- a/sys/dev/fdc/fdc_acpi.c
+++ b/sys/dev/fdc/fdc_acpi.c
@@ -258,7 +258,7 @@ static device_method_t fdc_acpi_methods[] = {
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
DEVMETHOD(bus_write_ivar, fdc_write_ivar),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t fdc_acpi_driver = {
diff --git a/sys/dev/fdt/fdt_mips.c b/sys/dev/fdt/fdt_mips.c
index 0e6828e..4df31d8 100644
--- a/sys/dev/fdt/fdt_mips.c
+++ b/sys/dev/fdt/fdt_mips.c
@@ -49,8 +49,26 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+/*
+ * For PIC-free boards, provide a PIC decoder to be used with mips4k CP0
+ * interrupt control directly.
+ */
+static int
+fdt_pic_decode_mips4k_cp0(phandle_t node, pcell_t *intr, int *interrupt,
+ int *trig, int *pol)
+{
+
+ if (!fdt_is_compatible(node, "mips,mips4k"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
fdt_pic_decode_t fdt_pic_table[] = {
- NULL,
- NULL,
+ &fdt_pic_decode_mips4k_cp0,
NULL
};
diff --git a/sys/dev/hpt27xx/hpt27xx_config.c b/sys/dev/hpt27xx/hpt27xx_config.c
index f87c7ee..5203f4a 100644
--- a/sys/dev/hpt27xx/hpt27xx_config.c
+++ b/sys/dev/hpt27xx/hpt27xx_config.c
@@ -58,9 +58,9 @@ int init_config(void)
return 0;
}
-char driver_name[] = "hpt27xx";
-char driver_name_long[] = "RocketRAID 27xx controller driver";
-char driver_ver[] = "v1.0 (" __DATE__ " " __TIME__ ")";
+const char driver_name[] = "hpt27xx";
+const char driver_name_long[] = "RocketRAID 27xx controller driver";
+const char driver_ver[] = "v1.0";
int osm_max_targets = 0xff;
diff --git a/sys/dev/hpt27xx/os_bsd.h b/sys/dev/hpt27xx/os_bsd.h
index 3895f40..e3f8e7d 100644
--- a/sys/dev/hpt27xx/os_bsd.h
+++ b/sys/dev/hpt27xx/os_bsd.h
@@ -135,9 +135,9 @@ INQUIRYDATA, *PINQUIRYDATA;
#include <dev/hpt27xx/ldm.h>
/* driver parameters */
-extern char driver_name[];
-extern char driver_name_long[];
-extern char driver_ver[];
+extern const char driver_name[];
+extern const char driver_name_long[];
+extern const char driver_ver[];
extern int osm_max_targets;
/*
diff --git a/sys/dev/hpt27xx/osm_bsd.c b/sys/dev/hpt27xx/osm_bsd.c
index ac7e9d8..fab1c71d 100644
--- a/sys/dev/hpt27xx/osm_bsd.c
+++ b/sys/dev/hpt27xx/osm_bsd.c
@@ -167,7 +167,8 @@ static int hpt_alloc_mem(PVBUS_EXT vbus_ext)
HPT_ASSERT((f->size & (f->alignment-1))==0);
- for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ;
+ for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1)
+ ;
KdPrint(("%s: %d*%d=%d bytes, order %d",
f->tag, f->count, f->size, f->count*f->size, order));
@@ -1036,6 +1037,7 @@ static void hpt_final_init(void *dummy)
}
if (!i) {
+ if (bootverbose)
os_printk("no controller detected.");
return;
}
@@ -1177,7 +1179,7 @@ static void hpt_final_init(void *dummy)
}
make_dev(&hpt_cdevsw, DRIVER_MINOR, UID_ROOT, GID_OPERATOR,
- S_IRUSR | S_IWUSR, driver_name);
+ S_IRUSR | S_IWUSR, "%s", driver_name);
}
#if defined(KLD_MODULE) && (__FreeBSD_version >= 503000)
@@ -1224,6 +1226,7 @@ static void override_kernel_driver(void)
static void hpt_init(void *dummy)
{
+ if (bootverbose)
os_printk("%s %s", driver_name_long, driver_ver);
override_kernel_driver();
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
index 71d8d8a..77eb93b 100644
--- a/sys/dev/hwpmc/hwpmc_core.c
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -560,7 +560,8 @@ struct iap_event_descr {
#define IAP_F_SB (1 << 6) /* CPU: Sandy Bridge */
#define IAP_F_IB (1 << 7) /* CPU: Ivy Bridge */
#define IAP_F_SBX (1 << 8) /* CPU: Sandy Bridge Xeon */
-#define IAP_F_FM (1 << 9) /* Fixed mask */
+#define IAP_F_IBX (1 << 9) /* CPU: Ivy Bridge */
+#define IAP_F_FM (1 << 10) /* Fixed mask */
#define IAP_F_ALLCPUSCORE2 \
(IAP_F_CC | IAP_F_CC2 | IAP_F_CC2E | IAP_F_CA)
@@ -603,7 +604,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(03H_01H, 0x03, 0x01, IAP_F_FM | IAP_F_I7O | IAP_F_SB |
IAP_F_SBX),
IAPDESCR(03H_02H, 0x03, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(03H_04H, 0x03, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7O),
IAPDESCR(03H_08H, 0x03, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_SB |
IAP_F_SBX),
@@ -619,9 +620,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(05H_00H, 0x05, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(05H_01H, 0x05, 0x01, IAP_F_FM | IAP_F_I7O | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(05H_02H, 0x05, 0x02, IAP_F_FM | IAP_F_I7O | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(05H_03H, 0x05, 0x03, IAP_F_FM | IAP_F_I7O),
IAPDESCR(06H_00H, 0x06, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2 |
@@ -634,7 +635,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(07H_00H, 0x07, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
IAPDESCR(07H_01H, 0x07, 0x01, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(07H_02H, 0x07, 0x02, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(07H_03H, 0x07, 0x03, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(07H_06H, 0x07, 0x06, IAP_F_FM | IAP_F_CA),
@@ -657,9 +658,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(08H_20H, 0x08, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(08H_40H, 0x08, 0x40, IAP_F_FM | IAP_F_I7O),
IAPDESCR(08H_80H, 0x08, 0x80, IAP_F_FM | IAP_F_I7),
- IAPDESCR(08H_81H, 0x08, 0x81, IAP_F_FM | IAP_F_IB),
- IAPDESCR(08H_82H, 0x08, 0x82, IAP_F_FM | IAP_F_IB),
- IAPDESCR(08H_84H, 0x08, 0x84, IAP_F_FM | IAP_F_IB),
+ IAPDESCR(08H_81H, 0x08, 0x81, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(08H_82H, 0x08, 0x82, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(08H_84H, 0x08, 0x84, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
IAPDESCR(09H_01H, 0x09, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7O),
IAPDESCR(09H_02H, 0x09, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7O),
@@ -679,11 +680,11 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(0DH_40H, 0x0D, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(0EH_01H, 0x0E, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(0EH_02H, 0x0E, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
- IAPDESCR(0EH_10H, 0x0E, 0x10, IAP_F_FM | IAP_F_IB),
- IAPDESCR(0EH_20H, 0x0E, 0x20, IAP_F_FM | IAP_F_IB),
- IAPDESCR(0EH_40H, 0x0E, 0x40, IAP_F_FM | IAP_F_IB),
+ IAPDESCR(0EH_10H, 0x0E, 0x10, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(0EH_20H, 0x0E, 0x20, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(0EH_40H, 0x0E, 0x40, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
IAPDESCR(0FH_01H, 0x0F, 0x01, IAP_F_FM | IAP_F_I7),
IAPDESCR(0FH_02H, 0x0F, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -733,7 +734,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(14H_00H, 0x14, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
IAPDESCR(14H_01H, 0x14, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7 |
- IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(14H_02H, 0x14, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(17H_01H, 0x17, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB |
@@ -760,28 +761,28 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(24H, 0x24, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUSCORE2),
IAPDESCR(24H_01H, 0x24, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_02H, 0x24, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(24H_03H, 0x24, 0x03, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_04H, 0x24, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_08H, 0x24, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_0CH, 0x24, 0x0C, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_10H, 0x24, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_20H, 0x24, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_30H, 0x24, 0x30, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_40H, 0x24, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_80H, 0x24, 0x80, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_C0H, 0x24, 0xC0, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_AAH, 0x24, 0xAA, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(24H_FFH, 0x24, 0xFF, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -802,15 +803,15 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(27H, 0x27, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUSCORE2),
IAPDESCR(27H_01H, 0x27, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(27H_02H, 0x27, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(27H_04H, 0x27, 0x04, IAP_F_FM | IAP_F_I7O | IAP_F_SB |
IAP_F_SBX),
IAPDESCR(27H_08H, 0x27, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(27H_0EH, 0x27, 0x0E, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(27H_0FH, 0x27, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(27H_10H, 0x27, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(27H_20H, 0x27, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(27H_40H, 0x27, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -819,13 +820,15 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(27H_F0H, 0x27, 0xF0, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(28H, 0x28, IAP_M_CORE | IAP_M_MESI, IAP_F_ALLCPUSCORE2),
- IAPDESCR(28H_01H, 0x28, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_IB | IAP_F_SBX),
+ IAPDESCR(28H_01H, 0x28, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(28H_02H, 0x28, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SBX),
IAPDESCR(28H_04H, 0x28, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(28H_08H, 0x28, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
- IAPDESCR(28H_0FH, 0x28, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(28H_0FH, 0x28, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(29H, 0x29, IAP_M_CORE | IAP_M_MESI, IAP_F_CC),
IAPDESCR(29H, 0x29, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
@@ -838,9 +841,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(2EH_01H, 0x2E, 0x01, IAP_F_FM | IAP_F_WM),
IAPDESCR(2EH_02H, 0x2E, 0x02, IAP_F_FM | IAP_F_WM),
IAPDESCR(2EH_41H, 0x2E, 0x41, IAP_F_FM | IAP_F_ALLCPUSCORE2 | IAP_F_I7 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(2EH_4FH, 0x2E, 0x4F, IAP_F_FM | IAP_F_ALLCPUSCORE2 | IAP_F_I7 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(30H, 0x30, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
IAP_F_ALLCPUSCORE2),
@@ -853,9 +856,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(3BH_C0H, 0x3B, 0xC0, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(3CH_00H, 0x3C, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(3CH_01H, 0x3C, 0x01, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(3CH_02H, 0x3C, 0x02, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(3DH_01H, 0x3D, 0x01, IAP_F_FM | IAP_F_I7O),
@@ -897,18 +900,18 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(48H_00H, 0x48, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(48H_01H, 0x48, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(48H_02H, 0x48, 0x02, IAP_F_FM | IAP_F_I7O),
IAPDESCR(49H_00H, 0x49, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(49H_01H, 0x49, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(49H_02H, 0x49, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(49H_04H, 0x49, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(49H_10H, 0x49, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(49H_20H, 0x49, 0x20, IAP_F_FM | IAP_F_I7),
IAPDESCR(49H_40H, 0x49, 0x40, IAP_F_FM | IAP_F_I7O),
IAPDESCR(49H_80H, 0x49, 0x80, IAP_F_FM | IAP_F_WM | IAP_F_I7),
@@ -921,9 +924,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(4CH_00H, 0x4C, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(4CH_01H, 0x4C, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(4CH_02H, 0x4C, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(4DH_01H, 0x4D, 0x01, IAP_F_FM | IAP_F_I7O),
@@ -940,7 +943,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(4FH_10H, 0x4F, 0x10, IAP_F_FM | IAP_F_WM),
IAPDESCR(51H_01H, 0x51, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(51H_02H, 0x51, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
IAP_F_SB | IAP_F_SBX),
IAPDESCR(51H_04H, 0x51, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
@@ -952,10 +955,10 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(53H_01H, 0x53, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
- IAPDESCR(58H_01H, 0x58, 0x01, IAP_F_FM | IAP_F_IB),
- IAPDESCR(58H_02H, 0x58, 0x02, IAP_F_FM | IAP_F_IB),
- IAPDESCR(58H_04H, 0x58, 0x04, IAP_F_FM | IAP_F_IB),
- IAPDESCR(58H_08H, 0x58, 0x08, IAP_F_FM | IAP_F_IB),
+ IAPDESCR(58H_01H, 0x58, 0x01, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(58H_02H, 0x58, 0x02, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(58H_04H, 0x58, 0x04, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(58H_08H, 0x58, 0x08, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
IAPDESCR(59H_20H, 0x59, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(59H_40H, 0x59, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
@@ -967,23 +970,25 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(5BH_4FH, 0x5B, 0x4F, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(5CH_01H, 0x5C, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(5CH_02H, 0x5C, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(5EH_01H, 0x5E, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(5FH_01H, 0x5F, 0x01, IAP_F_FM | IAP_F_IB),
+ IAPDESCR(5FH_04H, 0x5F, 0x04, IAP_F_IBX),
IAPDESCR(60H, 0x60, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUSCORE2),
IAPDESCR(60H_01H, 0x60, 0x01, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
- IAPDESCR(60H_02H, 0x60, 0x02, IAP_F_FM | IAP_F_WM | IAP_F_I7O | IAP_F_IB),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(60H_02H, 0x60, 0x02, IAP_F_FM | IAP_F_WM | IAP_F_I7O | IAP_F_IB |
+ IAP_F_IBX),
IAPDESCR(60H_04H, 0x60, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(60H_08H, 0x60, 0x08, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(61H, 0x61, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
IAPDESCR(61H_00H, 0x61, 0x00, IAP_F_FM | IAP_F_CC),
@@ -995,9 +1000,9 @@ static struct iap_event_descr iap_events[] = {
IAP_F_CA | IAP_F_CC2),
IAPDESCR(63H, 0x63, IAP_M_CORE, IAP_F_CC),
IAPDESCR(63H_01H, 0x63, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(63H_02H, 0x63, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(64H, 0x64, IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
IAPDESCR(64H_40H, 0x64, 0x40, IAP_F_FM | IAP_F_CC),
@@ -1039,20 +1044,20 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(78H, 0x78, IAP_M_CORE | IAP_M_SNOOPTYPE, IAP_F_CA | IAP_F_CC2),
IAPDESCR(79H_02H, 0x79, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_04H, 0x79, 0x04, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_08H, 0x79, 0x08, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_10H, 0x79, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_20H, 0x79, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_30H, 0x79, 0x30, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
- IAPDESCR(79H_18H, 0x79, 0x18, IAP_F_FM | IAP_F_IB),
- IAPDESCR(79H_24H, 0x79, 0x24, IAP_F_FM | IAP_F_IB),
- IAPDESCR(79H_3CH, 0x79, 0x3C, IAP_F_FM | IAP_F_IB),
+ IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(79H_18H, 0x79, 0x18, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(79H_24H, 0x79, 0x24, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(79H_3CH, 0x79, 0x3C, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
IAPDESCR(7AH, 0x7A, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
@@ -1068,7 +1073,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(80H_00H, 0x80, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(80H_01H, 0x80, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(80H_02H, 0x80, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_I7 |
- IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(80H_03H, 0x80, 0x03, IAP_F_FM | IAP_F_CA | IAP_F_I7 |
IAP_F_WM),
IAPDESCR(80H_04H, 0x80, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1089,13 +1094,13 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(85H_00H, 0x85, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(85H_01H, 0x85, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(85H_02H, 0x85, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(85H_04H, 0x85, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(85H_10H, 0x85, 0x10, IAP_F_FM | IAP_F_I7O | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(85H_20H, 0x85, 0x20, IAP_F_FM | IAP_F_I7O),
IAPDESCR(85H_40H, 0x85, 0x40, IAP_F_FM | IAP_F_I7O),
IAPDESCR(85H_80H, 0x85, 0x80, IAP_F_FM | IAP_F_WM | IAP_F_I7O),
@@ -1104,57 +1109,57 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(87H_00H, 0x87, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(87H_01H, 0x87, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(87H_02H, 0x87, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(87H_04H, 0x87, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(87H_08H, 0x87, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(87H_0FH, 0x87, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(88H_00H, 0x88, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(88H_01H, 0x88, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_02H, 0x88, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_04H, 0x88, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_07H, 0x88, 0x07, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(88H_08H, 0x88, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_10H, 0x88, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_20H, 0x88, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_30H, 0x88, 0x30, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(88H_40H, 0x88, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_7FH, 0x88, 0x7F, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(88H_80H, 0x88, 0x80, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_FFH, 0x88, 0xFF, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_00H, 0x89, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(89H_01H, 0x89, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_02H, 0x89, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(89H_04H, 0x89, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_07H, 0x89, 0x07, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(89H_08H, 0x89, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_10H, 0x89, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_20H, 0x89, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_30H, 0x89, 0x30, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(89H_40H, 0x89, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_7FH, 0x89, 0x7F, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(89H_80H, 0x89, 0x80, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_FFH, 0x89, 0xFF, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(8AH_00H, 0x8A, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(8BH_00H, 0x8B, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
@@ -1170,44 +1175,44 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(94H_00H, 0x94, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(9CH_01H, 0x9C, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(97H_00H, 0x97, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(98H_00H, 0x98, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(A0H_00H, 0xA0, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(A1H_01H, 0xA1, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_02H, 0xA1, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_04H, 0xA1, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_08H, 0xA1, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_0CH, 0xA1, 0x0C, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_10H, 0xA1, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_20H, 0xA1, 0x20, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_30H, 0xA1, 0x30, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_40H, 0xA1, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_80H, 0xA1, 0x80, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_00H, 0xA2, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(A2H_01H, 0xA2, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_02H, 0xA2, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
IAP_F_SB | IAP_F_SBX),
IAPDESCR(A2H_04H, 0xA2, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_08H, 0xA2, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_10H, 0xA2, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_20H, 0xA2, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
IAP_F_SB | IAP_F_SBX),
IAPDESCR(A2H_40H, 0xA2, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
@@ -1215,9 +1220,10 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(A2H_80H, 0xA2, 0x80, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
IAP_F_SB | IAP_F_SBX),
- IAPDESCR(A3H_01H, 0xA3, 0x01, IAP_F_FM | IAP_F_SBX),
- IAPDESCR(A3H_02H, 0xA3, 0x02, IAP_F_FM | IAP_F_SBX),
- IAPDESCR(A3H_04H, 0xA3, 0x04, IAP_F_FM | IAP_F_SBX),
+ IAPDESCR(A3H_01H, 0xA3, 0x01, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(A3H_02H, 0xA3, 0x02, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(A3H_04H, 0xA3, 0x04, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(A3H_08H, 0xA3, 0x08, IAP_F_IBX),
IAPDESCR(A6H_01H, 0xA6, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(A7H_01H, 0xA7, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1229,26 +1235,27 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(AAH_08H, 0xAA, 0x08, IAP_F_FM | IAP_F_CC2),
IAPDESCR(ABH_01H, 0xAB, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(ABH_02H, 0xAB, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(ACH_02H, 0xAC, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(ACH_08H, 0xAC, 0x08, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(ACH_0AH, 0xAC, 0x0A, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(AEH_01H, 0xAE, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IB),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B0H_00H, 0xB0, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(B0H_01H, 0xB0, 0x01, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
- IAPDESCR(B0H_02H, 0xB0, 0x02, IAP_F_FM | IAP_F_WM | IAP_F_I7O | IAP_F_IB),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(B0H_02H, 0xB0, 0x02, IAP_F_FM | IAP_F_WM | IAP_F_I7O | IAP_F_IB |
+ IAP_F_IBX),
IAPDESCR(B0H_04H, 0xB0, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B0H_08H, 0xB0, 0x08, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B0H_10H, 0xB0, 0x10, IAP_F_FM | IAP_F_WM | IAP_F_I7O),
IAPDESCR(B0H_20H, 0xB0, 0x20, IAP_F_FM | IAP_F_I7O),
IAPDESCR(B0H_40H, 0xB0, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1256,9 +1263,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(B1H_00H, 0xB1, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(B1H_01H, 0xB1, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B1H_02H, 0xB1, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B1H_04H, 0xB1, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(B1H_08H, 0xB1, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(B1H_10H, 0xB1, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1295,7 +1302,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(B6H_01H, 0xB6, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(B7H_01H, 0xB7, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B8H_01H, 0xB8, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(B8H_02H, 0xB8, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1305,19 +1312,20 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(BAH_02H, 0xBA, 0x02, IAP_F_FM | IAP_F_I7O),
IAPDESCR(BBH_01H, 0xBB, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(BDH_01H, 0xBD, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(BDH_20H, 0xBD, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(BFH_05H, 0xBF, 0x05, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(C0H_00H, 0xC0, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C0H_01H, 0xC0, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C0H_02H, 0xC0, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM | IAP_F_SB),
IAPDESCR(C0H_04H, 0xC0, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
@@ -1328,18 +1336,20 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(C1H_01H, 0xC1, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(C1H_02H, 0xC1, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(C1H_08H, 0xC1, 0x08, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C1H_10H, 0xC1, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C1H_20H, 0xC1, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C1H_FEH, 0xC1, 0xFE, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(C2H_00H, 0xC2, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(C2H_01H, 0xC2, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C2H_02H, 0xC2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C2H_04H, 0xC2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
IAPDESCR(C2H_07H, 0xC2, 0x07, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
@@ -1351,44 +1361,50 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(C3H_01H, 0xC3, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
IAPDESCR(C3H_02H, 0xC3, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C3H_04H, 0xC3, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C3H_10H, 0xC3, 0x10, IAP_F_FM | IAP_F_I7O),
IAPDESCR(C3H_20H, 0xC3, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C4H_00H, 0xC4, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C4H_01H, 0xC4, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C4H_02H, 0xC4, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C4H_04H, 0xC4, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C4H_08H, 0xC4, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C4H_0CH, 0xC4, 0x0C, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(C4H_0FH, 0xC4, 0x0F, IAP_F_FM | IAP_F_CA),
IAPDESCR(C4H_10H, 0xC4, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C4H_20H, 0xC4, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C4H_40H, 0xC4, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_00H, 0xC5, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C5H_01H, 0xC5, 0x01, IAP_F_FM | IAP_F_WM | IAP_F_SB |
- IAP_F_IB | IAP_F_SBX),
+ IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_02H, 0xC5, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_04H, 0xC5, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_SB |
- IAP_F_IB | IAP_F_SBX),
+ IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_10H, 0xC5, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_20H, 0xC5, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C6H_00H, 0xC6, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(C6H_01H, 0xC6, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
@@ -1415,15 +1431,15 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(CAH_00H, 0xCA, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(CAH_01H, 0xCA, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(CAH_02H, 0xCA, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CAH_04H, 0xCA, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CAH_08H, 0xCA, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CAH_10H, 0xCA, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CAH_1EH, 0xCA, 0x1E, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CBH_01H, 0xCB, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
@@ -1445,56 +1461,59 @@ static struct iap_event_descr iap_events[] = {
IAP_F_I7 | IAP_F_WM),
IAPDESCR(CCH_03H, 0xCC, 0x03, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(CCH_20H, 0xCC, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CDH_00H, 0xCD, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(CDH_01H, 0xCD, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CDH_02H, 0xCD, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CEH_00H, 0xCE, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(CFH_00H, 0xCF, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(D0H_00H, 0xD0, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(D0H_01H, 0xD0, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_02H, 0xD0, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_10H, 0xD0, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_20H, 0xD0, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_40H, 0xD0, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_80H, 0xD0, 0X80, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_01H, 0xD1, 0x01, IAP_F_FM | IAP_F_WM | IAP_F_SB |
- IAP_F_IB | IAP_F_SBX),
+ IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_02H, 0xD1, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_04H, 0xD1, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_08H, 0xD1, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
- IAPDESCR(D1H_20H, 0xD1, 0x20, IAP_F_FM | IAP_F_SBX),
+ IAPDESCR(D1H_20H, 0xD1, 0x20, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_40H, 0xD1, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D2H_01H, 0xD2, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_IBX),
IAPDESCR(D2H_02H, 0xD2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_IBX),
IAPDESCR(D2H_04H, 0xD2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_IBX),
IAPDESCR(D2H_08H, 0xD2, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_IBX),
IAPDESCR(D2H_0FH, 0xD2, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
IAPDESCR(D2H_10H, 0xD2, 0x10, IAP_F_FM | IAP_F_CC2E),
- IAPDESCR(D3H_01H, 0xD3, 0x01, IAP_F_FM | IAP_F_IB | IAP_F_SBX),
- IAPDESCR(D3H_04H, 0xD3, 0x04, IAP_F_FM | IAP_F_SBX),
+ IAPDESCR(D3H_01H, 0xD3, 0x01, IAP_F_FM | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
+ IAPDESCR(D3H_04H, 0xD3, 0x04, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(D3H_10H, 0xD3, 0x10, IAP_F_IBX),
+ IAPDESCR(D3H_20H, 0xD3, 0x20, IAP_F_IBX),
IAPDESCR(D4H_01H, 0xD4, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
@@ -1553,6 +1572,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(E6H_01H, 0xE6, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7 |
IAP_F_WM | IAP_F_SBX),
IAPDESCR(E6H_02H, 0xE6, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
+ IAPDESCR(E6H_1FH, 0xE6, 0x1F, IAP_F_IBX),
IAPDESCR(E8H_01H, 0xE8, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(E8H_02H, 0xE8, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1562,40 +1582,41 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(F0H_00H, 0xF0, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(F0H_01H, 0xF0, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_02H, 0xF0, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_04H, 0xF0, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_08H, 0xF0, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_10H, 0xF0, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_20H, 0xF0, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_40H, 0xF0, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_80H, 0xF0, 0x80, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F1H_01H, 0xF1, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F1H_02H, 0xF1, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F1H_04H, 0xF1, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F1H_07H, 0xF1, 0x07, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F2H_01H, 0xF2, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F2H_02H, 0xF2, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F2H_04H, 0xF2, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F2H_08H, 0xF2, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
- IAPDESCR(F2H_0AH, 0xF2, 0x0A, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(F2H_0AH, 0xF2, 0x0A, IAP_F_FM | IAP_F_SB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(F2H_0FH, 0xF2, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(F3H_01H, 0xF3, 0x01, IAP_F_FM | IAP_F_I7O),
@@ -1782,7 +1803,7 @@ iap_event_westmere_ok_on_counter(enum pmc_event pe, int ri)
}
static int
-iap_event_sb_sbx_ib_ok_on_counter(enum pmc_event pe, int ri)
+iap_event_sb_sbx_ib_ibx_ok_on_counter(enum pmc_event pe, int ri)
{
uint32_t mask;
@@ -1801,6 +1822,7 @@ iap_event_sb_sbx_ib_ok_on_counter(enum pmc_event pe, int ri)
mask = 0x4;
break;
/* Events valid only on counter 3. */
+ case PMC_EV_IAP_EVENT_A3H_08H:
case PMC_EV_IAP_EVENT_BBH_01H:
case PMC_EV_IAP_EVENT_CDH_01H:
case PMC_EV_IAP_EVENT_CDH_02H:
@@ -1892,7 +1914,8 @@ iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
case PMC_CPU_INTEL_SANDYBRIDGE:
case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
case PMC_CPU_INTEL_IVYBRIDGE:
- if (iap_event_sb_sbx_ib_ok_on_counter(ev, ri) == 0)
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
+ if (iap_event_sb_sbx_ib_ibx_ok_on_counter(ev, ri) == 0)
return (EINVAL);
break;
case PMC_CPU_INTEL_WESTMERE:
@@ -1929,6 +1952,9 @@ iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
case PMC_CPU_INTEL_IVYBRIDGE:
cpuflag = IAP_F_IB;
break;
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
+ cpuflag = IAP_F_IBX;
+ break;
case PMC_CPU_INTEL_SANDYBRIDGE:
cpuflag = IAP_F_SB;
break;
@@ -2043,8 +2069,9 @@ iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
a->pm_md.pm_iap.pm_iap_rsp & ~IA_OFFCORE_RSP_MASK_I7WM)
return (EINVAL);
else if ((core_cputype == PMC_CPU_INTEL_SANDYBRIDGE ||
- core_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON ||
- core_cputype == PMC_CPU_INTEL_IVYBRIDGE) &&
+ core_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON ||
+ core_cputype == PMC_CPU_INTEL_IVYBRIDGE ||
+ core_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON) &&
a->pm_md.pm_iap.pm_iap_rsp & ~IA_OFFCORE_RSP_MASK_SBIB)
return (EINVAL);
pm->pm_md.pm_iap.pm_iap_rsp = a->pm_md.pm_iap.pm_iap_rsp;
diff --git a/sys/dev/hwpmc/hwpmc_intel.c b/sys/dev/hwpmc/hwpmc_intel.c
index f633ac9..00ec29e 100644
--- a/sys/dev/hwpmc/hwpmc_intel.c
+++ b/sys/dev/hwpmc/hwpmc_intel.c
@@ -154,6 +154,10 @@ pmc_intel_initialize(void)
cputype = PMC_CPU_INTEL_IVYBRIDGE;
nclasses = 3;
break;
+ case 0x3E: /* Per Intel document 325462-045US 01/2013. */
+ cputype = PMC_CPU_INTEL_IVYBRIDGE_XEON;
+ nclasses = 3;
+ break;
}
break;
#if defined(__i386__) || defined(__amd64__)
@@ -196,6 +200,7 @@ pmc_intel_initialize(void)
case PMC_CPU_INTEL_SANDYBRIDGE:
case PMC_CPU_INTEL_WESTMERE:
case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
error = pmc_core_initialize(pmc_mdep, ncpus);
break;
@@ -280,6 +285,7 @@ pmc_intel_finalize(struct pmc_mdep *md)
case PMC_CPU_INTEL_SANDYBRIDGE:
case PMC_CPU_INTEL_WESTMERE:
case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
pmc_core_finalize(md);
break;
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 9e82a34..2f2f05a 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -3022,7 +3022,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
}
nevent = 0;
- for (ev = PMC_EV_SOFT_FIRST; ev <= PMC_EV_SOFT_LAST; ev++) {
+ for (ev = PMC_EV_SOFT_FIRST; (int)ev <= PMC_EV_SOFT_LAST; ev++) {
ps = pmc_soft_ev_acquire(ev);
if (ps == NULL)
continue;
diff --git a/sys/dev/hwpmc/hwpmc_soft.c b/sys/dev/hwpmc/hwpmc_soft.c
index c3d2dec..dac3612 100644
--- a/sys/dev/hwpmc/hwpmc_soft.c
+++ b/sys/dev/hwpmc/hwpmc_soft.c
@@ -116,7 +116,7 @@ soft_allocate_pmc(int cpu, int ri, struct pmc *pm,
return (EPERM);
ev = pm->pm_event;
- if (ev < PMC_EV_SOFT_FIRST || ev > PMC_EV_SOFT_LAST)
+ if ((int)ev < PMC_EV_SOFT_FIRST || (int)ev > PMC_EV_SOFT_LAST)
return (EINVAL);
/* Check if event is registered. */
diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h
index cb22324..8f246f6 100644
--- a/sys/dev/hwpmc/pmc_events.h
+++ b/sys/dev/hwpmc/pmc_events.h
@@ -722,6 +722,7 @@ __PMC_EV(IAP, EVENT_5CH_01H) \
__PMC_EV(IAP, EVENT_5CH_02H) \
__PMC_EV(IAP, EVENT_5EH_01H) \
__PMC_EV(IAP, EVENT_5FH_01H) \
+__PMC_EV(IAP, EVENT_5FH_04H) \
__PMC_EV(IAP, EVENT_60H) \
__PMC_EV(IAP, EVENT_60H_01H) \
__PMC_EV(IAP, EVENT_60H_02H) \
@@ -861,6 +862,7 @@ __PMC_EV(IAP, EVENT_A2H_80H) \
__PMC_EV(IAP, EVENT_A3H_01H) \
__PMC_EV(IAP, EVENT_A3H_02H) \
__PMC_EV(IAP, EVENT_A3H_04H) \
+__PMC_EV(IAP, EVENT_A3H_08H) \
__PMC_EV(IAP, EVENT_A6H_01H) \
__PMC_EV(IAP, EVENT_A7H_01H) \
__PMC_EV(IAP, EVENT_A8H_01H) \
@@ -1021,6 +1023,8 @@ __PMC_EV(IAP, EVENT_D2H_0FH) \
__PMC_EV(IAP, EVENT_D2H_10H) \
__PMC_EV(IAP, EVENT_D3H_01H) \
__PMC_EV(IAP, EVENT_D3H_04H) \
+__PMC_EV(IAP, EVENT_D3H_10H) \
+__PMC_EV(IAP, EVENT_D3H_20H) \
__PMC_EV(IAP, EVENT_D4H_01H) \
__PMC_EV(IAP, EVENT_D4H_02H) \
__PMC_EV(IAP, EVENT_D4H_04H) \
@@ -1061,6 +1065,7 @@ __PMC_EV(IAP, EVENT_E5H_01H) \
__PMC_EV(IAP, EVENT_E6H_00H) \
__PMC_EV(IAP, EVENT_E6H_01H) \
__PMC_EV(IAP, EVENT_E6H_02H) \
+__PMC_EV(IAP, EVENT_E6H_1FH) \
__PMC_EV(IAP, EVENT_E8H_01H) \
__PMC_EV(IAP, EVENT_E8H_02H) \
__PMC_EV(IAP, EVENT_E8H_03H) \
@@ -2584,6 +2589,205 @@ __PMC_EV_ALIAS("L2_LINES_OUT.PF_CLEAN", IAP_EVENT_F2H_04H) \
__PMC_EV_ALIAS("L2_LINES_OUT.PF_DIRTY", IAP_EVENT_F2H_08H)
/*
+ * Aliases for Ivy Bridge Xeon PMC events (325462-045US January 2013)
+ */
+
+#define __PMC_EV_ALIAS_IVYBRIDGE_XEON() \
+__PMC_EV_ALIAS("LD_BLOCKS.STORE_FORWARD", IAP_EVENT_03H_02H) \
+__PMC_EV_ALIAS("MISALIGN_MEM_REF.LOADS", IAP_EVENT_05H_01H) \
+__PMC_EV_ALIAS("MISALIGN_MEM_REF.STORES", IAP_EVENT_05H_02H) \
+__PMC_EV_ALIAS("LD_BLOCKS_PARTIAL.ADDRESS_ALIAS", IAP_EVENT_07H_01H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK", IAP_EVENT_08H_81H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.DEMAND_LD_WALK_COMPLETED", IAP_EVENT_08H_82H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.DEMAND_LD_WALK_DURATION", IAP_EVENT_08H_84H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.ANY", IAP_EVENT_0EH_01H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.FLAGS_MERGE", IAP_EVENT_0EH_10H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.SLOW_LEA", IAP_EVENT_0EH_20H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.SINGLE_MUL", IAP_EVENT_0EH_40H) \
+__PMC_EV_ALIAS("ARITH.FPU_DIV_ACTIVE", IAP_EVENT_14H_01H) \
+__PMC_EV_ALIAS("L2_RQSTS.DEMAND_DATA_RD_HIT", IAP_EVENT_24H_01H) \
+__PMC_EV_ALIAS("L2_RQSTS.ALL_DEMAND_DATA_RD", IAP_EVENT_24H_03H) \
+__PMC_EV_ALIAS("L2_RQSTS.RFO_HITS", IAP_EVENT_24H_04H) \
+__PMC_EV_ALIAS("L2_RQSTS.RFO_MISS", IAP_EVENT_24H_08H) \
+__PMC_EV_ALIAS("L2_RQSTS.ALL_RFO", IAP_EVENT_24H_0CH) \
+__PMC_EV_ALIAS("L2_RQSTS.CODE_RD_HIT", IAP_EVENT_24H_10H) \
+__PMC_EV_ALIAS("L2_RQSTS.CODE_RD_MISS", IAP_EVENT_24H_20H) \
+__PMC_EV_ALIAS("L2_RQSTS.ALL_CODE_RD", IAP_EVENT_24H_30H) \
+__PMC_EV_ALIAS("L2_RQSTS.PF_HIT", IAP_EVENT_24H_40H) \
+__PMC_EV_ALIAS("L2_RQSTS.PF_MISS", IAP_EVENT_24H_80H) \
+__PMC_EV_ALIAS("L2_RQSTS.ALL_PF", IAP_EVENT_24H_C0H) \
+__PMC_EV_ALIAS("L2_STORE_LOCK_RQSTS.MISS", IAP_EVENT_27H_01H) \
+__PMC_EV_ALIAS("L2_STORE_LOCK_RQSTS.HIT_M", IAP_EVENT_27H_08H) \
+__PMC_EV_ALIAS("L2_STORE_LOCK_RQSTS.ALL", IAP_EVENT_27H_0FH) \
+__PMC_EV_ALIAS("L2_L1D_WB_RQSTS.MISS", IAP_EVENT_28H_01H) \
+__PMC_EV_ALIAS("L2_L1D_WB_RQSTS.HIT_E", IAP_EVENT_28H_04H) \
+__PMC_EV_ALIAS("L2_L1D_WB_RQSTS.HIT_M", IAP_EVENT_28H_08H) \
+__PMC_EV_ALIAS("L2_L1D_WB_RQSTS.ALL", IAP_EVENT_28H_0FH) \
+__PMC_EV_ALIAS("LONGEST_LAT_CACHE.REFERENCE", IAP_EVENT_2EH_4FH) \
+__PMC_EV_ALIAS("LONGEST_LAT_CACHE.MISS", IAP_EVENT_2EH_41H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.THREAD_P", IAP_EVENT_3CH_00H) \
+__PMC_EV_ALIAS("CPU_CLK_THREAD_UNHALTED.REF_XCLK", IAP_EVENT_3CH_01H) \
+__PMC_EV_ALIAS("L1D_PEND_MISS.PENDING", IAP_EVENT_48H_01H) \
+__PMC_EV_ALIAS("DTLB_STORE_MISSES.MISS_CAUSES_A_WALK", IAP_EVENT_49H_01H) \
+__PMC_EV_ALIAS("DTLB_STORE_MISSES.WALK_COMPLETED", IAP_EVENT_49H_02H) \
+__PMC_EV_ALIAS("DTLB_STORE_MISSES.WALK_DURATION", IAP_EVENT_49H_04H) \
+__PMC_EV_ALIAS("DTLB_STORE_MISSES.STLB_HIT", IAP_EVENT_49H_10H) \
+__PMC_EV_ALIAS("LOAD_HIT_PRE.SW_PF", IAP_EVENT_4CH_01H) \
+__PMC_EV_ALIAS("LOAD_HIT_PRE.HW_PF", IAP_EVENT_4CH_02H) \
+__PMC_EV_ALIAS("L1D.REPLACEMENT", IAP_EVENT_51H_01H) \
+__PMC_EV_ALIAS("MOVE_ELIMINATION.INT_NOT_ELIMINATED", IAP_EVENT_58H_01H) \
+__PMC_EV_ALIAS("MOVE_ELIMINATION.SIMD_NOT_ELIMINATED", IAP_EVENT_58H_02H) \
+__PMC_EV_ALIAS("MOVE_ELIMINATION.INT_ELIMINATED", IAP_EVENT_58H_04H) \
+__PMC_EV_ALIAS("MOVE_ELIMINATION.SIMD_ELIMINATED", IAP_EVENT_58H_08H) \
+__PMC_EV_ALIAS("CPL_CYCLES.RING0", IAP_EVENT_5CH_01H) \
+__PMC_EV_ALIAS("CPL_CYCLES.RING123", IAP_EVENT_5CH_02H) \
+__PMC_EV_ALIAS("RS_EVENTS.EMPTY_CYCLES", IAP_EVENT_5EH_01H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.STLB_HIT", IAP_EVENT_5FH_04H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD", IAP_EVENT_60H_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD", IAP_EVENT_60H_02H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO", IAP_EVENT_60H_04H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD", IAP_EVENT_60H_08H) \
+__PMC_EV_ALIAS("LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION", IAP_EVENT_63H_01H) \
+__PMC_EV_ALIAS("LOCK_CYCLES.CACHE_LOCK_DURATION", IAP_EVENT_63H_02H) \
+__PMC_EV_ALIAS("IDQ.EMPTY", IAP_EVENT_79H_02H) \
+__PMC_EV_ALIAS("IDQ.MITE_UOPS", IAP_EVENT_79H_04H) \
+__PMC_EV_ALIAS("IDQ.DSB_UOPS", IAP_EVENT_79H_08H) \
+__PMC_EV_ALIAS("IDQ.MS_DSB_UOPS", IAP_EVENT_79H_10H) \
+__PMC_EV_ALIAS("IDQ.MS_MITE_UOPS", IAP_EVENT_79H_20H) \
+__PMC_EV_ALIAS("IDQ.MS_UOPS", IAP_EVENT_79H_30H) \
+__PMC_EV_ALIAS("IDQ.ALL_DSB_CYCLES_ANY_UOPS", IAP_EVENT_79H_18H) \
+__PMC_EV_ALIAS("IDQ.ALL_DSB_CYCLES_4_UOPS", IAP_EVENT_79H_18H) \
+__PMC_EV_ALIAS("IDQ.ALL_MITE_CYCLES_ANY_UOPS", IAP_EVENT_79H_24H) \
+__PMC_EV_ALIAS("IDQ.ALL_MITE_CYCLES_4_UOPS", IAP_EVENT_79H_24H) \
+__PMC_EV_ALIAS("IDQ.MITE_ALL_UOPS", IAP_EVENT_79H_3CH) \
+__PMC_EV_ALIAS("ICACHE.MISSES", IAP_EVENT_80H_02H) \
+__PMC_EV_ALIAS("ITLB_MISSES.MISS_CAUSES_A_WALK", IAP_EVENT_85H_01H) \
+__PMC_EV_ALIAS("ITLB_MISSES.WALK_COMPLETED", IAP_EVENT_85H_02H) \
+__PMC_EV_ALIAS("ITLB_MISSES.WALK_DURATION", IAP_EVENT_85H_04H) \
+__PMC_EV_ALIAS("ITLB_MISSES.STLB_HIT", IAP_EVENT_85H_10H) \
+__PMC_EV_ALIAS("ILD_STALL.LCP", IAP_EVENT_87H_01H) \
+__PMC_EV_ALIAS("ILD_STALL.IQ_FULL", IAP_EVENT_87H_04H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.COND", IAP_EVENT_88H_01H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.DIRECT_JMP", IAP_EVENT_88H_02H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.INDIRECT_JMP_NON_CALL_RET", IAP_EVENT_88H_04H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.RETURN_NEAR", IAP_EVENT_88H_08H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.DIRECT_NEAR_CALL", IAP_EVENT_88H_10H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.INDIRECT_NEAR_CALL", IAP_EVENT_88H_20H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.NONTAKEN", IAP_EVENT_88H_40H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.TAKEN", IAP_EVENT_88H_80H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.ALL_BRANCHES", IAP_EVENT_88H_FFH) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.COND", IAP_EVENT_89H_01H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.INDIRECT_JMP_NON_CALL_RET", IAP_EVENT_89H_04H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.RETURN_NEAR", IAP_EVENT_89H_08H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.DIRECT_NEAR_CALL", IAP_EVENT_89H_10H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.INDIRECT_NEAR_CALL", IAP_EVENT_89H_20H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.NONTAKEN", IAP_EVENT_89H_40H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.TAKEN", IAP_EVENT_89H_80H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.ALL_BRANCHES", IAP_EVENT_89H_FFH) \
+__PMC_EV_ALIAS("IDQ_UOPS_NOT_DELIVERED.CORE", IAP_EVENT_9CH_01H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_0", IAP_EVENT_A1H_01H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_1", IAP_EVENT_A1H_02H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_2_LD", IAP_EVENT_A1H_04H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_2_STA", IAP_EVENT_A1H_08H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_2", IAP_EVENT_A1H_0CH) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_3_LD", IAP_EVENT_A1H_10H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_3_STA", IAP_EVENT_A1H_20H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_3", IAP_EVENT_A1H_30H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_4", IAP_EVENT_A1H_40H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_5", IAP_EVENT_A1H_80H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ANY", IAP_EVENT_A2H_01H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.RS", IAP_EVENT_A2H_04H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.SB", IAP_EVENT_A2H_08H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ROB", IAP_EVENT_A2H_10H) \
+__PMC_EV_ALIAS("CYCLE_ACTIVITY.CYCLES_L2_PENDING", IAP_EVENT_A3H_01H) \
+__PMC_EV_ALIAS("CYCLE_ACTIVITY.CYCLES_LDM_PENDING", IAP_EVENT_A3H_02H) \
+__PMC_EV_ALIAS("CYCLE_ACTIVITY.CYCLES_NO_EXECUTE", IAP_EVENT_A3H_04H) \
+__PMC_EV_ALIAS("CYCLE_ACTIVITY.CYCLES_L1D_PENDING", IAP_EVENT_A3H_08H) \
+__PMC_EV_ALIAS("DSB2MITE_SWITCHES.COUNT", IAP_EVENT_ABH_01H) \
+__PMC_EV_ALIAS("DSB2MITE_SWITCHES.PENALTY_CYCLES", IAP_EVENT_ABH_02H) \
+__PMC_EV_ALIAS("DSB_FILL.EXCEED_DSB_LINES", IAP_EVENT_ACH_08H) \
+__PMC_EV_ALIAS("ITLB.ITLB_FLUSH", IAP_EVENT_AEH_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND_DATA_RD", IAP_EVENT_B0H_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND_CODE_RD", IAP_EVENT_B0H_02H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND_RFO", IAP_EVENT_B0H_04H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.ALL_DATA_RD", IAP_EVENT_B0H_08H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.THREAD", IAP_EVENT_B1H_01H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.CORE", IAP_EVENT_B1H_02H) \
+__PMC_EV_ALIAS("OFF_CORE_RESPONSE_0", IAP_EVENT_B7H_01H) \
+__PMC_EV_ALIAS("OFF_CORE_RESPONSE_1", IAP_EVENT_BBH_01H) \
+__PMC_EV_ALIAS("TLB_FLUSH.DTLB_THREAD", IAP_EVENT_BDH_01H) \
+__PMC_EV_ALIAS("TLB_FLUSH.STLB_ANY", IAP_EVENT_BDH_20H) \
+__PMC_EV_ALIAS("INST_RETIRED.ANY_P", IAP_EVENT_C0H_00H) \
+__PMC_EV_ALIAS("INST_RETIRED.ALL", IAP_EVENT_C0H_01H) \
+__PMC_EV_ALIAS("OTHER_ASSISTS.AVX_STORE", IAP_EVENT_C1H_08H) \
+__PMC_EV_ALIAS("OTHER_ASSISTS.AVX_TO_SSE", IAP_EVENT_C1H_10H) \
+__PMC_EV_ALIAS("OTHER_ASSISTS.SSE_TO_AVX", IAP_EVENT_C1H_20H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.ALL", IAP_EVENT_C2H_01H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.RETIRE_SLOTS", IAP_EVENT_C2H_02H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.MEMORY_ORDERING", IAP_EVENT_C3H_02H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.SMC", IAP_EVENT_C3H_04H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.MASKMOV", IAP_EVENT_C3H_20H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ALL_BRANCHES", IAP_EVENT_C4H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.CONDITIONAL", IAP_EVENT_C4H_01H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NEAR_CALL", IAP_EVENT_C4H_02H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ALL_BRANCHES", IAP_EVENT_C4H_04H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NEAR_RETURN", IAP_EVENT_C4H_08H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NOT_TAKEN", IAP_EVENT_C4H_10H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NEAR_TAKEN", IAP_EVENT_C4H_20H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.FAR_BRANCH", IAP_EVENT_C4H_40H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.ALL_BRANCHES", IAP_EVENT_C5H_00H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.CONDITIONAL", IAP_EVENT_C5H_01H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.NEAR_CALL", IAP_EVENT_C5H_02H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.ALL_BRANCHES", IAP_EVENT_C5H_04H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.NOT_TAKEN", IAP_EVENT_C5H_10H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.TAKEN", IAP_EVENT_C5H_20H) \
+__PMC_EV_ALIAS("FP_ASSIST.X87_OUTPUT", IAP_EVENT_CAH_02H) \
+__PMC_EV_ALIAS("FP_ASSIST.X87_INPUT", IAP_EVENT_CAH_04H) \
+__PMC_EV_ALIAS("FP_ASSIST.SIMD_OUTPUT", IAP_EVENT_CAH_08H) \
+__PMC_EV_ALIAS("FP_ASSIST.SIMD_INPUT", IAP_EVENT_CAH_10H) \
+__PMC_EV_ALIAS("FP_ASSIST.ANY", IAP_EVENT_CAH_1EH) \
+__PMC_EV_ALIAS("ROB_MISC_EVENTS.LBR_INSERTS", IAP_EVENT_CCH_20H) \
+__PMC_EV_ALIAS("MEM_TRANS_RETIRED.LOAD_LATENCY", IAP_EVENT_CDH_01H) \
+__PMC_EV_ALIAS("MEM_TRANS_RETIRED.PRECISE_STORE", IAP_EVENT_CDH_02H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.LOADS", IAP_EVENT_D0H_01H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.STORES", IAP_EVENT_D0H_02H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.STLB_MISS", IAP_EVENT_D0H_10H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.LOCK", IAP_EVENT_D0H_20H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.SPLIT", IAP_EVENT_D0H_40H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.ALL", IAP_EVENT_D0H_80H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.L1_HIT", IAP_EVENT_D1H_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.L2_HIT", IAP_EVENT_D1H_02H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.LLC_HIT", IAP_EVENT_D1H_04H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.LLC_MISS", IAP_EVENT_D1H_20H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.HIT_LFB", IAP_EVENT_D1H_40H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS", IAP_EVENT_D2H_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT", IAP_EVENT_D2H_02H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM", IAP_EVENT_D2H_04H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE", IAP_EVENT_D2H_08H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM", IAP_EVENT_D3H_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_DRAM", IAP_EVENT_D3H_04H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_HITM", IAP_EVENT_D3H_10H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_FWD", IAP_EVENT_D3H_20H) \
+__PMC_EV_ALIAS("BACLEARS.ANY", IAP_EVENT_E6H_1FH) \
+__PMC_EV_ALIAS("L2_TRANS.DEMAND_DATA_RD", IAP_EVENT_F0H_01H) \
+__PMC_EV_ALIAS("L2_TRANS.RFO", IAP_EVENT_F0H_02H) \
+__PMC_EV_ALIAS("L2_TRANS.CODE_RD", IAP_EVENT_F0H_04H) \
+__PMC_EV_ALIAS("L2_TRANS.ALL_PF", IAP_EVENT_F0H_08H) \
+__PMC_EV_ALIAS("L2_TRANS.L1D_WB", IAP_EVENT_F0H_10H) \
+__PMC_EV_ALIAS("L2_TRANS.L2_FILL", IAP_EVENT_F0H_20H) \
+__PMC_EV_ALIAS("L2_TRANS.L2_WB", IAP_EVENT_F0H_40H) \
+__PMC_EV_ALIAS("L2_TRANS.ALL_REQUESTS", IAP_EVENT_F0H_80H) \
+__PMC_EV_ALIAS("L2_LINES_IN.I", IAP_EVENT_F1H_01H) \
+__PMC_EV_ALIAS("L2_LINES_IN.S", IAP_EVENT_F1H_02H) \
+__PMC_EV_ALIAS("L2_LINES_IN.E", IAP_EVENT_F1H_04H) \
+__PMC_EV_ALIAS("L2_LINES_IN.ALL", IAP_EVENT_F1H_07H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.DEMAND_CLEAN", IAP_EVENT_F2H_01H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.DEMAND_DIRTY", IAP_EVENT_F2H_02H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.PF_CLEAN", IAP_EVENT_F2H_04H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.PF_DIRTY", IAP_EVENT_F2H_08H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.DIRTY_ALL", IAP_EVENT_F2H_0AH)
+
+/*
* Aliases for Sandy Bridge PMC events (253669-039US May 2011)
*/
diff --git a/sys/dev/iicbus/ad7418.c b/sys/dev/iicbus/ad7418.c
index 3875307..dcb8b95 100644
--- a/sys/dev/iicbus/ad7418.c
+++ b/sys/dev/iicbus/ad7418.c
@@ -219,7 +219,7 @@ static device_method_t ad7418_methods[] = {
DEVMETHOD(device_probe, ad7418_probe),
DEVMETHOD(device_attach, ad7418_attach),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t ad7418_driver = {
diff --git a/sys/dev/iicbus/ds133x.c b/sys/dev/iicbus/ds133x.c
index 572384f..20f1d40 100644
--- a/sys/dev/iicbus/ds133x.c
+++ b/sys/dev/iicbus/ds133x.c
@@ -347,7 +347,7 @@ static device_method_t ds133x_methods[] = {
DEVMETHOD(clock_gettime, ds133x_gettime),
DEVMETHOD(clock_settime, ds133x_settime),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t ds133x_driver = {
diff --git a/sys/dev/iicbus/ds1672.c b/sys/dev/iicbus/ds1672.c
index a9209bd..1dd0ab0 100644
--- a/sys/dev/iicbus/ds1672.c
+++ b/sys/dev/iicbus/ds1672.c
@@ -167,7 +167,7 @@ static device_method_t ds1672_methods[] = {
DEVMETHOD(clock_gettime, ds1672_gettime),
DEVMETHOD(clock_settime, ds1672_settime),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t ds1672_driver = {
diff --git a/sys/dev/iicbus/icee.c b/sys/dev/iicbus/icee.c
index 93c03ad..2e26d0e 100644
--- a/sys/dev/iicbus/icee.c
+++ b/sys/dev/iicbus/icee.c
@@ -262,7 +262,7 @@ static device_method_t icee_methods[] = {
DEVMETHOD(device_probe, icee_probe),
DEVMETHOD(device_attach, icee_attach),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t icee_driver = {
diff --git a/sys/dev/isf/isf.c b/sys/dev/isf/isf.c
index e537799..eaaad15 100644
--- a/sys/dev/isf/isf.c
+++ b/sys/dev/isf/isf.c
@@ -150,6 +150,7 @@ static void isf_task(void *arg);
* physical package, due to variable block size support in the StrataFlash
* part.
*/
+devclass_t isf_devclass;
static uint16_t
isf_read_reg(struct isf_softc *sc, uint16_t reg)
diff --git a/sys/dev/isf/isf.h b/sys/dev/isf/isf.h
index f5cdc08..bfcca07 100644
--- a/sys/dev/isf/isf.h
+++ b/sys/dev/isf/isf.h
@@ -89,6 +89,8 @@ struct isf_softc {
int isf_attach(struct isf_softc *sc);
void isf_detach(struct isf_softc *sc);
+
+extern devclass_t isf_devclass;
#endif /* _KERNEL */
#endif /* _DEV_ISF_H_ */
diff --git a/sys/dev/isf/isf_fdt.c b/sys/dev/isf/isf_fdt.c
new file mode 100644
index 0000000..f4c20a2
--- /dev/null
+++ b/sys/dev/isf/isf_fdt.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * Copyright (c) 2012 SRI International
+ * 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.
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/isf/isf.h>
+
+/*
+ * FDT bus attachment for the Intel Strata Flash devices.
+ */
+static int
+isf_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "intel,strataflash")) {
+ device_set_desc(dev, "Intel StrataFlash NOR flash device");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+isf_fdt_attach(device_t dev)
+{
+ int error;
+ struct isf_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->isf_dev = dev;
+ sc->isf_unit = device_get_unit(dev);
+ sc->isf_rid = 0;
+ sc->isf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->isf_rid, RF_ACTIVE);
+ if (sc->isf_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ error = isf_attach(sc);
+ if (error)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid,
+ sc->isf_res);
+ return (error);
+}
+
+static int
+isf_fdt_detach(device_t dev)
+{
+ struct isf_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc->isf_res != NULL, ("%s: resources not allocated",
+ __func__));
+ isf_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid, sc->isf_res);
+ return (0);
+}
+
+static device_method_t isf_fdt_methods[] = {
+ DEVMETHOD(device_probe, isf_fdt_probe),
+ DEVMETHOD(device_attach, isf_fdt_attach),
+ DEVMETHOD(device_detach, isf_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t isf_fdt_driver = {
+ "isf",
+ isf_fdt_methods,
+ sizeof(struct isf_softc),
+};
+
+DRIVER_MODULE(isf, simplebus, isf_fdt_driver, isf_devclass, 0, 0);
diff --git a/sys/dev/isf/isf_nexus.c b/sys/dev/isf/isf_nexus.c
index af2f874..7631453 100644
--- a/sys/dev/isf/isf_nexus.c
+++ b/sys/dev/isf/isf_nexus.c
@@ -115,6 +115,4 @@ static driver_t isf_nexus_driver = {
sizeof(struct isf_softc),
};
-static devclass_t isf_devclass;
-
DRIVER_MODULE(isf, nexus, isf_nexus_driver, isf_devclass, 0, 0);
diff --git a/sys/dev/ixgb/if_ixgb.c b/sys/dev/ixgb/if_ixgb.c
index e9acae0..69a8fb9 100644
--- a/sys/dev/ixgb/if_ixgb.c
+++ b/sys/dev/ixgb/if_ixgb.c
@@ -159,7 +159,8 @@ static device_method_t ixgb_methods[] = {
DEVMETHOD(device_attach, ixgb_attach),
DEVMETHOD(device_detach, ixgb_detach),
DEVMETHOD(device_shutdown, ixgb_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ixgb_driver = {
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index 1d97343..cfcc342 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -216,7 +216,8 @@ static device_method_t ixgbe_methods[] = {
DEVMETHOD(device_attach, ixgbe_attach),
DEVMETHOD(device_detach, ixgbe_detach),
DEVMETHOD(device_shutdown, ixgbe_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ixgbe_driver = {
diff --git a/sys/dev/ixgbe/ixgbe_82598.h b/sys/dev/ixgbe/ixgbe_82598.h
index a195b15..a195b15 100755..100644
--- a/sys/dev/ixgbe/ixgbe_82598.h
+++ b/sys/dev/ixgbe/ixgbe_82598.h
diff --git a/sys/dev/ixgbe/ixgbe_82599.h b/sys/dev/ixgbe/ixgbe_82599.h
index dca39b7..dca39b7 100755..100644
--- a/sys/dev/ixgbe/ixgbe_82599.h
+++ b/sys/dev/ixgbe/ixgbe_82599.h
diff --git a/sys/dev/ixgbe/ixgbe_x540.c b/sys/dev/ixgbe/ixgbe_x540.c
index 0635cda..0635cda 100755..100644
--- a/sys/dev/ixgbe/ixgbe_x540.c
+++ b/sys/dev/ixgbe/ixgbe_x540.c
diff --git a/sys/dev/ixgbe/ixgbe_x540.h b/sys/dev/ixgbe/ixgbe_x540.h
index 29cf8bb..29cf8bb 100755..100644
--- a/sys/dev/ixgbe/ixgbe_x540.h
+++ b/sys/dev/ixgbe/ixgbe_x540.h
diff --git a/sys/dev/ixgbe/ixv.c b/sys/dev/ixgbe/ixv.c
index b9aff80..ef5f753 100644
--- a/sys/dev/ixgbe/ixv.c
+++ b/sys/dev/ixgbe/ixv.c
@@ -169,7 +169,8 @@ static device_method_t ixv_methods[] = {
DEVMETHOD(device_attach, ixv_attach),
DEVMETHOD(device_detach, ixv_detach),
DEVMETHOD(device_shutdown, ixv_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ixv_driver = {
diff --git a/sys/dev/mfi/mfi_cam.c b/sys/dev/mfi/mfi_cam.c
index 599ff3b..2bbfafe 100644
--- a/sys/dev/mfi/mfi_cam.c
+++ b/sys/dev/mfi/mfi_cam.c
@@ -99,7 +99,8 @@ static device_method_t mfip_methods[] = {
DEVMETHOD(device_probe, mfip_probe),
DEVMETHOD(device_attach, mfip_attach),
DEVMETHOD(device_detach, mfip_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t mfip_driver = {
"mfip",
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index 27447ad..e7f6648 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -353,7 +353,8 @@ mmc_highest_voltage(uint32_t ocr)
{
int i;
- for (i = 30; i >= 0; i--)
+ for (i = MMC_OCR_MAX_VOLTAGE_SHIFT;
+ i >= MMC_OCR_MIN_VOLTAGE_SHIFT; i--)
if (ocr & (1 << i))
return (i);
return (-1);
diff --git a/sys/dev/mmc/mmcreg.h b/sys/dev/mmc/mmcreg.h
index 3d2b569..f454ddb 100644
--- a/sys/dev/mmc/mmcreg.h
+++ b/sys/dev/mmc/mmcreg.h
@@ -353,6 +353,7 @@ struct mmc_request {
#define MMC_OCR_VOLTAGE 0x3fffffffU /* Vdd Voltage mask */
#define MMC_OCR_LOW_VOLTAGE (1u << 7) /* Low Voltage Range -- tbd */
#define MMC_OCR_200_210 (1U << 8) /* Vdd voltage 2.00 ~ 2.10 */
+#define MMC_OCR_MIN_VOLTAGE_SHIFT 8
#define MMC_OCR_210_220 (1U << 9) /* Vdd voltage 2.10 ~ 2.20 */
#define MMC_OCR_220_230 (1U << 10) /* Vdd voltage 2.20 ~ 2.30 */
#define MMC_OCR_230_240 (1U << 11) /* Vdd voltage 2.30 ~ 2.40 */
@@ -368,6 +369,7 @@ struct mmc_request {
#define MMC_OCR_330_340 (1U << 21) /* Vdd voltage 3.30 ~ 3.40 */
#define MMC_OCR_340_350 (1U << 22) /* Vdd voltage 3.40 ~ 3.50 */
#define MMC_OCR_350_360 (1U << 23) /* Vdd voltage 3.50 ~ 3.60 */
+#define MMC_OCR_MAX_VOLTAGE_SHIFT 23
#define MMC_OCR_CCS (1u << 30) /* Card Capacity status (SD vs SDHC) */
#define MMC_OCR_CARD_BUSY (1U << 31) /* Card Power up status */
diff --git a/sys/dev/mn/if_mn.c b/sys/dev/mn/if_mn.c
index 48fc3dc..239aa0f 100644
--- a/sys/dev/mn/if_mn.c
+++ b/sys/dev/mn/if_mn.c
@@ -1418,7 +1418,7 @@ static device_method_t mn_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t mn_driver = {
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c
index c04e0df2..feefc3b 100644
--- a/sys/dev/mxge/if_mxge.c
+++ b/sys/dev/mxge/if_mxge.c
@@ -124,7 +124,8 @@ static device_method_t mxge_methods[] =
DEVMETHOD(device_attach, mxge_attach),
DEVMETHOD(device_detach, mxge_detach),
DEVMETHOD(device_shutdown, mxge_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t mxge_driver =
diff --git a/sys/dev/my/if_my.c b/sys/dev/my/if_my.c
index 9648412..a487d90 100644
--- a/sys/dev/my/if_my.c
+++ b/sys/dev/my/if_my.c
@@ -153,7 +153,7 @@ static device_method_t my_methods[] = {
DEVMETHOD(device_detach, my_detach),
DEVMETHOD(device_shutdown, my_shutdown),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t my_driver = {
diff --git a/sys/dev/nand/nand_id.c b/sys/dev/nand/nand_id.c
index 75c5834..76c5f9f 100644
--- a/sys/dev/nand/nand_id.c
+++ b/sys/dev/nand/nand_id.c
@@ -37,6 +37,8 @@ struct nand_params nand_ids[] = {
0x20, 0x200, 0x10, 0x20, 0 },
{ { NAND_MAN_SAMSUNG, 0xd3 }, "Samsung NAND 1GiB 3,3V 8-bit",
0x400, 0x800, 0x40, 0x40, 0 },
+ { { NAND_MAN_SAMSUNG, 0xdc }, "Samsung NAND 512MiB 3,3V 8-bit",
+ 0x200, 0x800, 0x40, 0x40, 0 },
{ { NAND_MAN_HYNIX, 0x76 }, "Hynix NAND 64MiB 3,3V 8-bit",
0x40, 0x200, 0x10, 0x20, 0 },
{ { NAND_MAN_HYNIX, 0xdc }, "Hynix NAND 512MiB 3,3V 8-bit",
diff --git a/sys/dev/netmap/if_em_netmap.h b/sys/dev/netmap/if_em_netmap.h
index b4b268a..776f0e0 100644
--- a/sys/dev/netmap/if_em_netmap.h
+++ b/sys/dev/netmap/if_em_netmap.h
@@ -292,6 +292,8 @@ em_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
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;
+
for (n = 0; ; n++) {
struct e1000_rx_desc *curr = &rxr->rx_base[l];
uint32_t staterr = le32toh(curr->status);
@@ -299,6 +301,7 @@ em_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
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,
BUS_DMASYNC_POSTREAD);
j = (j == lim) ? 0 : j + 1;
diff --git a/sys/dev/netmap/if_igb_netmap.h b/sys/dev/netmap/if_igb_netmap.h
index bd83563..e817341 100644
--- a/sys/dev/netmap/if_igb_netmap.h
+++ b/sys/dev/netmap/if_igb_netmap.h
@@ -263,6 +263,8 @@ igb_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
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;
+
for (n = 0; ; n++) {
union e1000_adv_rx_desc *curr = &rxr->rx_base[l];
uint32_t staterr = le32toh(curr->wb.upper.status_error);
@@ -270,6 +272,7 @@ igb_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
if ((staterr & E1000_RXD_STAT_DD) == 0)
break;
ring->slot[j].len = le16toh(curr->wb.upper.length);
+ ring->slot[j].flags = slot_flags;
bus_dmamap_sync(rxr->ptag,
rxr->rx_buffers[l].pmap, BUS_DMASYNC_POSTREAD);
j = (j == lim) ? 0 : j + 1;
diff --git a/sys/dev/netmap/if_lem_netmap.h b/sys/dev/netmap/if_lem_netmap.h
index 9f24580..d3be700 100644
--- a/sys/dev/netmap/if_lem_netmap.h
+++ b/sys/dev/netmap/if_lem_netmap.h
@@ -253,6 +253,8 @@ lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
l = adapter->next_rx_desc_to_check;
j = netmap_idx_n2k(kring, l);
if (netmap_no_pendintr || force_update) {
+ uint16_t slot_flags = kring->nkr_slot_flags;
+
for (n = 0; ; n++) {
struct e1000_rx_desc *curr = &adapter->rx_desc_base[l];
uint32_t staterr = le32toh(curr->status);
@@ -266,6 +268,7 @@ lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
len = 0;
}
ring->slot[j].len = len;
+ ring->slot[j].flags = slot_flags;
bus_dmamap_sync(adapter->rxtag,
adapter->rx_buffer_area[l].map,
BUS_DMASYNC_POSTREAD);
diff --git a/sys/dev/netmap/if_re_netmap.h b/sys/dev/netmap/if_re_netmap.h
index bdd5703..1c747b7 100644
--- a/sys/dev/netmap/if_re_netmap.h
+++ b/sys/dev/netmap/if_re_netmap.h
@@ -245,6 +245,8 @@ re_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
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;
+
for (n = kring->nr_hwavail; n < lim ; n++) {
struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[l];
uint32_t rxstat = le32toh(cur_rx->rl_cmdstat);
@@ -256,6 +258,7 @@ re_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
/* 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;
/* sync was in re_newbuf() */
bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag,
rxd[l].rx_dmamap, BUS_DMASYNC_POSTREAD);
diff --git a/sys/dev/netmap/ixgbe_netmap.h b/sys/dev/netmap/ixgbe_netmap.h
index 55bd21f..55660ec 100644
--- a/sys/dev/netmap/ixgbe_netmap.h
+++ b/sys/dev/netmap/ixgbe_netmap.h
@@ -63,9 +63,6 @@
* This is tricky, much better to use TDH for now.
*/
SYSCTL_DECL(_dev_netmap);
-static int ix_write_len;
-SYSCTL_INT(_dev_netmap, OID_AUTO, ix_write_len,
- CTLFLAG_RW, &ix_write_len, 0, "write rx len");
static int ix_rx_miss, ix_rx_miss_bufs, ix_use_dd, ix_crcstrip;
SYSCTL_INT(_dev_netmap, OID_AUTO, ix_crcstrip,
CTLFLAG_RW, &ix_crcstrip, 0, "strip CRC on rx frames");
@@ -485,12 +482,9 @@ ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
* rxr->next_to_check is set to 0 on a ring reinit
*/
if (netmap_no_pendintr || force_update) {
- /* XXX apparently the length field in advanced descriptors
- * does not include the CRC irrespective of the setting
- * of CRCSTRIP. The data sheets say differently.
- * Very strange.
- */
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);
@@ -501,8 +495,7 @@ ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
if ((staterr & IXGBE_RXD_STAT_DD) == 0)
break;
ring->slot[j].len = le16toh(curr->wb.upper.length) - crclen;
- if (ix_write_len)
- D("rx[%d] len %d", j, ring->slot[j].len);
+ ring->slot[j].flags = slot_flags;
bus_dmamap_sync(rxr->ptag,
rxr->rx_buffers[l].pmap, BUS_DMASYNC_POSTREAD);
j = (j == lim) ? 0 : j + 1;
diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c
index 4f5d486..35d5303 100644
--- a/sys/dev/netmap/netmap.c
+++ b/sys/dev/netmap/netmap.c
@@ -120,10 +120,12 @@ SYSCTL_INT(_dev_netmap, OID_AUTO, no_pendintr,
int netmap_drop = 0; /* debugging */
int netmap_flags = 0; /* debug flags */
+int netmap_fwd = 0; /* force transparent mode */
int netmap_copy = 0; /* debugging, copy content */
SYSCTL_INT(_dev_netmap, OID_AUTO, drop, CTLFLAG_RW, &netmap_drop, 0 , "");
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, copy, CTLFLAG_RW, &netmap_copy, 0 , "");
#ifdef NM_BRIDGE /* support for netmap bridge */
@@ -275,6 +277,51 @@ nm_find_bridge(const char *name)
}
#endif /* NM_BRIDGE */
+
+/*
+ * Fetch configuration from the device, to cope with dynamic
+ * reconfigurations after loading the module.
+ */
+static int
+netmap_update_config(struct netmap_adapter *na)
+{
+ struct ifnet *ifp = na->ifp;
+ u_int txr, txd, rxr, rxd;
+
+ txr = txd = rxr = rxd = 0;
+ if (na->nm_config) {
+ na->nm_config(ifp, &txr, &txd, &rxr, &rxd);
+ } else {
+ /* take whatever we had at init time */
+ txr = na->num_tx_rings;
+ txd = na->num_tx_desc;
+ rxr = na->num_rx_rings;
+ rxd = na->num_rx_desc;
+ }
+
+ 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) {
+ D("stored config %s: txring %d x %d, rxring %d x %d",
+ ifp->if_xname,
+ 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);
+ }
+ if (na->refcount == 0) {
+ D("configuration changed (but fine)");
+ na->num_tx_rings = txr;
+ na->num_tx_desc = txd;
+ na->num_rx_rings = rxr;
+ na->num_rx_desc = rxd;
+ return 0;
+ }
+ D("configuration changed while active, this is bad...");
+ return 1;
+}
+
/*------------- memory allocator -----------------*/
#ifdef NETMAP_MEM2
#include "netmap_mem2.c"
@@ -351,7 +398,8 @@ netmap_dtor_locked(void *data)
if (na->refcount <= 0) { /* last instance */
u_int i, j, lim;
- D("deleting last netmap instance for %s", ifp->if_xname);
+ if (netmap_verbose)
+ D("deleting last instance for %s", ifp->if_xname);
/*
* there is a race here with *_netmap_task() and
* netmap_poll(), which don't run under NETMAP_REG_LOCK.
@@ -482,7 +530,8 @@ 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)
{
- D("first mmap for %p", handle);
+ if (netmap_verbose)
+ D("first mmap for %p", handle);
return saved_cdev_pager_ops.cdev_pg_ctor(handle,
size, prot, foff, cred, color);
}
@@ -491,7 +540,7 @@ static void
netmap_dev_pager_dtor(void *handle)
{
saved_cdev_pager_ops.cdev_pg_dtor(handle);
- D("ready to release memory for %p", handle);
+ ND("ready to release memory for %p", handle);
}
@@ -507,7 +556,7 @@ netmap_mmap_single(struct cdev *cdev, vm_ooffset_t *foff,
{
vm_object_t obj;
- D("cdev %p foff %jd size %jd objp %p prot %d", cdev,
+ ND("cdev %p foff %jd size %jd objp %p prot %d", cdev,
(intmax_t )*foff, (intmax_t )objsize, objp, prot);
obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff,
curthread->td_ucred);
@@ -515,7 +564,7 @@ netmap_mmap_single(struct cdev *cdev, vm_ooffset_t *foff,
if (obj == NULL)
return EINVAL;
if (saved_cdev_pager_ops.cdev_pg_fault == NULL) {
- D("initialize cdev_pager_ops");
+ ND("initialize cdev_pager_ops");
saved_cdev_pager_ops = *(obj->un_pager.devp.ops);
netmap_cdev_pager_ops.cdev_pg_fault =
saved_cdev_pager_ops.cdev_pg_fault;
@@ -572,7 +621,9 @@ netmap_mmap(__unused struct cdev *dev,
static int
netmap_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
- D("dev %p fflag 0x%x devtype %d td %p", dev, fflag, devtype, td);
+ if (netmap_verbose)
+ D("dev %p fflag 0x%x devtype %d td %p",
+ dev, fflag, devtype, td);
return 0;
}
@@ -598,63 +649,170 @@ netmap_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
/*
* Handlers for synchronization of the queues from/to the host.
- *
- * netmap_sync_to_host() passes packets up. We are called from a
- * system call in user process context, and the only contention
- * can be among multiple user threads erroneously calling
- * this routine concurrently. In principle we should not even
- * need to lock.
+ * Netmap has two operating modes:
+ * - in the default mode, the rings connected to the host stack are
+ * just another ring pair managed by userspace;
+ * - in transparent mode (XXX to be defined) incoming packets
+ * (from the host or the NIC) are marked as NS_FORWARD upon
+ * arrival, and the user application has a chance to reset the
+ * flag for packets that should be dropped.
+ * On the RXSYNC or poll(), packets in RX rings between
+ * kring->nr_kcur and ring->cur with NS_FORWARD still set are moved
+ * to the other side.
+ * The transfer NIC --> host is relatively easy, just encapsulate
+ * into mbufs and we are done. The host --> NIC side is slightly
+ * harder because there might not be room in the tx ring so it
+ * might take a while before releasing the buffer.
+ */
+
+/*
+ * pass a chain of buffers to the host stack as coming from 'dst'
*/
static void
-netmap_sync_to_host(struct netmap_adapter *na)
+netmap_send_up(struct ifnet *dst, struct mbuf *head)
{
- struct netmap_kring *kring = &na->tx_rings[na->num_tx_rings];
- struct netmap_ring *ring = kring->ring;
- struct mbuf *head = NULL, *tail = NULL, *m;
- u_int k, n, lim = kring->nkr_num_slots - 1;
+ struct mbuf *m;
- k = ring->cur;
- if (k > lim) {
- netmap_ring_reinit(kring);
- return;
+ /* send packets up, outside the lock */
+ while ((m = head) != NULL) {
+ head = head->m_nextpkt;
+ m->m_nextpkt = NULL;
+ if (netmap_verbose & NM_VERB_HOST)
+ D("sending up pkt %p size %d", m, MBUF_LEN(m));
+ NM_SEND_UP(dst, m);
}
- // na->nm_lock(na->ifp, NETMAP_CORE_LOCK, 0);
+}
- /* Take packets from hwcur to cur and pass them up.
+struct mbq {
+ struct mbuf *head;
+ struct mbuf *tail;
+ int count;
+};
+
+/*
+ * put a copy of the buffers marked NS_FORWARD into an mbuf chain.
+ * Run from hwcur to cur - reserved
+ */
+static void
+netmap_grab_packets(struct netmap_kring *kring, struct mbq *q, int force)
+{
+ /* Take packets from hwcur to cur-reserved and pass them up.
* In case of no buffers we give up. At the end of the loop,
* the queue is drained in all cases.
+ * XXX handle reserved
*/
+ int k = kring->ring->cur - kring->ring->reserved;
+ u_int n, lim = kring->nkr_num_slots - 1;
+ struct mbuf *m, *tail = q->tail;
+
+ if (k < 0)
+ k = k + kring->nkr_num_slots;
for (n = kring->nr_hwcur; n != k;) {
- struct netmap_slot *slot = &ring->slot[n];
+ struct netmap_slot *slot = &kring->ring->slot[n];
n = (n == lim) ? 0 : n + 1;
+ if ((slot->flags & NS_FORWARD) == 0 && !force)
+ continue;
if (slot->len < 14 || slot->len > NETMAP_BUF_SIZE) {
D("bad pkt at %d len %d", n, slot->len);
continue;
}
- m = m_devget(NMB(slot), slot->len, 0, na->ifp, NULL);
+ slot->flags &= ~NS_FORWARD; // XXX needed ?
+ m = m_devget(NMB(slot), slot->len, 0, kring->na->ifp, NULL);
if (m == NULL)
break;
if (tail)
tail->m_nextpkt = m;
else
- head = m;
+ q->head = m;
tail = m;
+ q->count++;
m->m_nextpkt = NULL;
}
+ q->tail = tail;
+}
+
+/*
+ * called under main lock to send packets from the host to the NIC
+ * The host ring has packets from nr_hwcur to (cur - reserved)
+ * to be sent down. We scan the tx rings, which have just been
+ * flushed so nr_hwcur == cur. Pushing packets down means
+ * increment cur and decrement avail.
+ * XXX to be verified
+ */
+static void
+netmap_sw_to_nic(struct netmap_adapter *na)
+{
+ struct netmap_kring *kring = &na->rx_rings[na->num_rx_rings];
+ struct netmap_kring *k1 = &na->tx_rings[0];
+ int i, howmany, src_lim, dst_lim;
+
+ howmany = kring->nr_hwavail; /* XXX otherwise cur - reserved - nr_hwcur */
+
+ src_lim = kring->nkr_num_slots;
+ for (i = 0; howmany > 0 && i < na->num_tx_rings; i++, k1++) {
+ ND("%d packets left to ring %d (space %d)", howmany, i, k1->nr_hwavail);
+ dst_lim = k1->nkr_num_slots;
+ while (howmany > 0 && k1->ring->avail > 0) {
+ struct netmap_slot *src, *dst, tmp;
+ src = &kring->ring->slot[kring->nr_hwcur];
+ dst = &k1->ring->slot[k1->ring->cur];
+ tmp = *src;
+ src->buf_idx = dst->buf_idx;
+ src->flags = NS_BUF_CHANGED;
+
+ dst->buf_idx = tmp.buf_idx;
+ dst->len = tmp.len;
+ dst->flags = NS_BUF_CHANGED;
+ ND("out len %d buf %d from %d to %d",
+ dst->len, dst->buf_idx,
+ kring->nr_hwcur, k1->ring->cur);
+
+ if (++kring->nr_hwcur >= src_lim)
+ kring->nr_hwcur = 0;
+ howmany--;
+ kring->nr_hwavail--;
+ if (++k1->ring->cur >= dst_lim)
+ k1->ring->cur = 0;
+ k1->ring->avail--;
+ }
+ kring->ring->cur = kring->nr_hwcur; // XXX
+ k1++;
+ }
+}
+
+/*
+ * netmap_sync_to_host() passes packets up. We are called from a
+ * system call in user process context, and the only contention
+ * can be among multiple user threads erroneously calling
+ * this routine concurrently.
+ */
+static void
+netmap_sync_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 };
+
+ k = ring->cur;
+ if (k > lim) {
+ netmap_ring_reinit(kring);
+ return;
+ }
+ // na->nm_lock(na->ifp, NETMAP_CORE_LOCK, 0);
+
+ /* Take packets from hwcur to cur and pass them up.
+ * In case of no buffers we give up. At the end of the loop,
+ * the queue is drained in all cases.
+ */
+ netmap_grab_packets(kring, &q, 1);
kring->nr_hwcur = k;
kring->nr_hwavail = ring->avail = lim;
// na->nm_lock(na->ifp, NETMAP_CORE_UNLOCK, 0);
- /* send packets up, outside the lock */
- while ((m = head) != NULL) {
- head = head->m_nextpkt;
- m->m_nextpkt = NULL;
- if (netmap_verbose & NM_VERB_HOST)
- D("sending up pkt %p size %d", m, MBUF_LEN(m));
- NM_SEND_UP(na->ifp, m);
- }
+ netmap_send_up(na->ifp, q.head);
}
/*
@@ -877,6 +1035,7 @@ netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid)
priv->np_txpoll = (ringid & NETMAP_NO_TX_POLL) ? 0 : 1;
if (need_lock)
na->nm_lock(ifp, NETMAP_CORE_UNLOCK, 0);
+ if (netmap_verbose) {
if (ringid & NETMAP_SW_RING)
D("ringid %s set to SW RING", ifp->if_xname);
else if (ringid & NETMAP_HW_RING)
@@ -884,6 +1043,7 @@ netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid)
priv->np_qfirst);
else
D("ringid %s set to all %d HW RINGS", ifp->if_xname, lim);
+ }
return 0;
}
@@ -965,6 +1125,7 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
if (error)
break;
na = NA(ifp); /* retrieve netmap_adapter */
+ netmap_update_config(na);
nmr->nr_rx_rings = na->num_rx_rings;
nmr->nr_tx_rings = na->num_tx_rings;
nmr->nr_rx_slots = na->num_rx_desc;
@@ -1014,6 +1175,8 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
break;
}
+ /* ring configuration may have changed, fetch from the card */
+ netmap_update_config(na);
priv->np_ifp = ifp; /* store the reference */
error = netmap_set_ringid(priv, nmr->nr_ringid);
if (error)
@@ -1182,7 +1345,8 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
struct ifnet *ifp;
struct netmap_kring *kring;
u_int core_lock, i, check_all, want_tx, want_rx, revents = 0;
- u_int lim_tx, lim_rx;
+ u_int lim_tx, lim_rx, host_forwarded = 0;
+ struct mbq q = { NULL, NULL, 0 };
enum {NO_CL, NEED_CL, LOCKED_CL }; /* see below */
void *pwait = dev; /* linux compatibility */
@@ -1230,6 +1394,17 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
return (revents);
}
+ /* if we are in transparent mode, check also the host rx ring */
+ kring = &na->rx_rings[lim_rx];
+ if ( (priv->np_qlast == NETMAP_HW_RING) // XXX check_all
+ && want_rx
+ && (netmap_fwd || kring->ring->flags & NR_FORWARD) ) {
+ if (kring->ring->avail == 0)
+ netmap_sync_from_host(na, td, dev);
+ if (kring->ring->avail > 0)
+ revents |= want_rx;
+ }
+
/*
* 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
@@ -1305,6 +1480,7 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
* to avoid that the tx rings stall).
*/
if (priv->np_txpoll || want_tx) {
+flush_tx:
for (i = priv->np_qfirst; i < lim_tx; i++) {
kring = &na->tx_rings[i];
/*
@@ -1357,6 +1533,11 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
}
if (na->separate_locks)
na->nm_lock(ifp, NETMAP_RX_LOCK, i);
+ if (netmap_fwd ||kring->ring->flags & NR_FORWARD) {
+ ND(10, "forwarding some buffers up %d to %d",
+ kring->nr_hwcur, kring->ring->cur);
+ netmap_grab_packets(kring, &q, netmap_fwd);
+ }
if (na->nm_rxsync(ifp, i, 0 /* no lock */))
revents |= POLLERR;
@@ -1379,8 +1560,28 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
if (want_rx)
selrecord(td, &na->rx_si);
}
+
+ /* forward host to the netmap ring */
+ kring = &na->rx_rings[lim_rx];
+ if (kring->nr_hwavail > 0)
+ ND("host rx %d has %d packets", lim_rx, kring->nr_hwavail);
+ if ( (priv->np_qlast == NETMAP_HW_RING) // XXX check_all
+ && (netmap_fwd || kring->ring->flags & NR_FORWARD)
+ && kring->nr_hwavail > 0 && !host_forwarded) {
+ if (core_lock == NEED_CL) {
+ na->nm_lock(ifp, NETMAP_CORE_LOCK, 0);
+ core_lock = LOCKED_CL;
+ }
+ netmap_sw_to_nic(na);
+ host_forwarded = 1; /* prevent another pass */
+ want_rx = 0;
+ goto flush_tx;
+ }
+
if (core_lock == LOCKED_CL)
na->nm_lock(ifp, NETMAP_CORE_UNLOCK, 0);
+ if (q.head)
+ netmap_send_up(na->ifp, q.head);
return (revents);
}
@@ -1444,46 +1645,28 @@ netmap_lock_wrapper(struct ifnet *dev, int what, u_int queueid)
* setups.
*/
int
-netmap_attach(struct netmap_adapter *na, int num_queues)
+netmap_attach(struct netmap_adapter *arg, int num_queues)
{
- int n, size;
- void *buf;
- struct ifnet *ifp = na->ifp;
+ struct netmap_adapter *na = NULL;
+ struct ifnet *ifp = arg ? arg->ifp : NULL;
- if (ifp == NULL) {
- D("ifp not set, giving up");
- return EINVAL;
- }
- /* clear other fields ? */
- na->refcount = 0;
+ if (arg == NULL || ifp == NULL)
+ goto fail;
+ na = malloc(sizeof(*na), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (na == 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;
- /* on each direction we have N+1 resources
- * 0..n-1 are the hardware rings
- * n is the ring attached to the stack.
- */
- n = na->num_rx_rings + na->num_tx_rings + 2;
- size = sizeof(*na) + n * sizeof(struct netmap_kring);
-
- buf = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
- if (buf) {
- WNA(ifp) = buf;
- na->tx_rings = (void *)((char *)buf + sizeof(*na));
- na->rx_rings = na->tx_rings + na->num_tx_rings + 1;
- bcopy(na, buf, sizeof(*na));
- NETMAP_SET_CAPABLE(ifp);
-
- na = buf;
- /* Core lock initialized here. Others are initialized after
- * netmap_if_new.
- */
- mtx_init(&na->core_lock, "netmap core lock", MTX_NETWORK_LOCK,
- MTX_DEF);
- if (na->nm_lock == NULL) {
- ND("using default locks for %s", ifp->if_xname);
- na->nm_lock = netmap_lock_wrapper;
- }
+ 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);
+ if (na->nm_lock == NULL) {
+ ND("using default locks for %s", ifp->if_xname);
+ na->nm_lock = netmap_lock_wrapper;
}
#ifdef linux
if (ifp->netdev_ops) {
@@ -1493,9 +1676,12 @@ netmap_attach(struct netmap_adapter *na, int num_queues)
}
na->nm_ndo.ndo_start_xmit = linux_netmap_start;
#endif
- D("%s for %s", buf ? "ok" : "failed", ifp->if_xname);
+ D("success for %s", ifp->if_xname);
+ return 0;
- return (buf ? 0 : ENOMEM);
+fail:
+ D("fail, arg %p ifp %p na %p", arg, ifp, na);
+ return (na ? EINVAL : ENOMEM);
}
@@ -1513,6 +1699,10 @@ netmap_detach(struct ifnet *ifp)
mtx_destroy(&na->core_lock);
+ if (na->tx_rings) { /* XXX should not happen */
+ D("freeing leftover tx_rings");
+ free(na->tx_rings, M_DEVBUF);
+ }
bzero(na, sizeof(*na));
WNA(ifp) = NULL;
free(na, M_DEVBUF);
@@ -1543,7 +1733,8 @@ netmap_start(struct ifnet *ifp, struct mbuf *m)
goto done; /* no space */
}
if (len > NETMAP_BUF_SIZE) {
- D("drop packet size %d > %d", len, NETMAP_BUF_SIZE);
+ D("%s from_host, drop packet size %d > %d", ifp->if_xname,
+ len, NETMAP_BUF_SIZE);
goto done; /* too long for us */
}
@@ -1554,6 +1745,7 @@ netmap_start(struct ifnet *ifp, struct mbuf *m)
slot = &kring->ring->slot[i];
m_copydata(m, 0, len, NMB(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);
diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h
index bb0d3fa..86a26fb 100644
--- a/sys/dev/netmap/netmap_kern.h
+++ b/sys/dev/netmap/netmap_kern.h
@@ -119,6 +119,10 @@ struct netmap_adapter;
* RX rings: the next empty buffer (hwcur + hwavail + hwofs) coincides with
* the next empty buffer as known by the hardware (next_to_check or so).
* TX rings: hwcur + hwofs coincides with next_to_send
+ *
+ * For received packets, slot->flags is set to nkr_slot_flags
+ * so we can provide a proper initial value (e.g. set NS_FORWARD
+ * when operating in 'transparent' mode).
*/
struct netmap_kring {
struct netmap_ring *ring;
@@ -128,6 +132,7 @@ struct netmap_kring {
#define NKR_PENDINTR 0x1 // Pending interrupt.
u_int nkr_num_slots;
+ uint16_t nkr_slot_flags; /* initial value for flags */
int nkr_hwofs; /* offset between NIC and netmap ring */
struct netmap_adapter *na;
NM_SELINFO_T si; /* poll/select wait queue */
@@ -198,6 +203,9 @@ struct netmap_adapter {
void (*nm_lock)(struct ifnet *, int what, u_int ringid);
int (*nm_txsync)(struct ifnet *, u_int ring, int lock);
int (*nm_rxsync)(struct ifnet *, u_int ring, int lock);
+ /* return configuration information */
+ int (*nm_config)(struct ifnet *, u_int *txr, u_int *txd,
+ u_int *rxr, u_int *rxd);
int bdg_port;
#ifdef linux
diff --git a/sys/dev/netmap/netmap_mem1.c b/sys/dev/netmap/netmap_mem1.c
deleted file mode 100644
index 521855a..0000000
--- a/sys/dev/netmap/netmap_mem1.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) 2011 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:
- * 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$
- *
- * The original netmap memory allocator, using a single large
- * chunk of memory allocated with contigmalloc.
- */
-
-/*
- * Default amount of memory pre-allocated by the module.
- * We start with a large size and then shrink our demand
- * according to what is avalable when the module is loaded.
- */
-#define NETMAP_MEMORY_SIZE (64 * 1024 * PAGE_SIZE)
-static void * netmap_malloc(size_t size, const char *msg);
-static void netmap_free(void *addr, const char *msg);
-
-#define netmap_if_malloc(len) netmap_malloc(len, "nifp")
-#define netmap_if_free(v) netmap_free((v), "nifp")
-
-#define netmap_ring_malloc(len) netmap_malloc(len, "ring")
-#define netmap_free_rings(na) \
- netmap_free((na)->tx_rings[0].ring, "shadow rings");
-
-/*
- * Allocator for a pool of packet buffers. For each buffer we have
- * one entry in the bitmap to signal the state. Allocation scans
- * the bitmap, but since this is done only on attach, we are not
- * too worried about performance
- * XXX if we need to allocate small blocks, a translation
- * table is used both for kernel virtual address and physical
- * addresses.
- */
-struct netmap_buf_pool {
- u_int total_buffers; /* total buffers. */
- u_int free;
- u_int bufsize;
- char *base; /* buffer base address */
- uint32_t *bitmap; /* one bit per buffer, 1 means free */
-};
-struct netmap_buf_pool nm_buf_pool;
-SYSCTL_INT(_dev_netmap, OID_AUTO, total_buffers,
- CTLFLAG_RD, &nm_buf_pool.total_buffers, 0, "total_buffers");
-SYSCTL_INT(_dev_netmap, OID_AUTO, free_buffers,
- CTLFLAG_RD, &nm_buf_pool.free, 0, "free_buffers");
-
-
-/*
- * Allocate n buffers from the ring, and fill the slot.
- * Buffer 0 is the 'junk' buffer.
- */
-static void
-netmap_new_bufs(struct netmap_if *nifp __unused,
- struct netmap_slot *slot, u_int n)
-{
- struct netmap_buf_pool *p = &nm_buf_pool;
- uint32_t bi = 0; /* index in the bitmap */
- uint32_t mask, j, i = 0; /* slot counter */
-
- if (n > p->free) {
- D("only %d out of %d buffers available", i, n);
- return;
- }
- /* termination is guaranteed by p->free */
- while (i < n && p->free > 0) {
- uint32_t cur = p->bitmap[bi];
- if (cur == 0) { /* bitmask is fully used */
- bi++;
- continue;
- }
- /* locate a slot */
- for (j = 0, mask = 1; (cur & mask) == 0; j++, mask <<= 1) ;
- p->bitmap[bi] &= ~mask; /* slot in use */
- p->free--;
- slot[i].buf_idx = bi*32+j;
- slot[i].len = p->bufsize;
- slot[i].flags = NS_BUF_CHANGED;
- i++;
- }
- ND("allocated %d buffers, %d available", n, p->free);
-}
-
-
-static void
-netmap_free_buf(struct netmap_if *nifp __unused, uint32_t i)
-{
- struct netmap_buf_pool *p = &nm_buf_pool;
-
- uint32_t pos, mask;
- if (i >= p->total_buffers) {
- D("invalid free index %d", i);
- return;
- }
- pos = i / 32;
- mask = 1 << (i % 32);
- if (p->bitmap[pos] & mask) {
- D("slot %d already free", i);
- return;
- }
- p->bitmap[pos] |= mask;
- p->free++;
-}
-
-
-/* Descriptor of the memory objects handled by our memory allocator. */
-struct netmap_mem_obj {
- TAILQ_ENTRY(netmap_mem_obj) nmo_next; /* next object in the
- chain. */
- int nmo_used; /* flag set on used memory objects. */
- size_t nmo_size; /* size of the memory area reserved for the
- object. */
- void *nmo_data; /* pointer to the memory area. */
-};
-
-/* Wrap our memory objects to make them ``chainable``. */
-TAILQ_HEAD(netmap_mem_obj_h, netmap_mem_obj);
-
-
-/* Descriptor of our custom memory allocator. */
-struct netmap_mem_d {
- struct mtx nm_mtx; /* lock used to handle the chain of memory
- objects. */
- struct netmap_mem_obj_h nm_molist; /* list of memory objects */
- size_t nm_size; /* total amount of memory used for rings etc. */
- size_t nm_totalsize; /* total amount of allocated memory
- (the difference is used for buffers) */
- size_t nm_buf_start; /* offset of packet buffers.
- This is page-aligned. */
- size_t nm_buf_len; /* total memory for buffers */
- void *nm_buffer; /* pointer to the whole pre-allocated memory
- area. */
-};
-
-/* Shorthand to compute a netmap interface offset. */
-#define netmap_if_offset(v) \
- ((char *) (v) - (char *) nm_mem->nm_buffer)
-/* .. and get a physical address given a memory offset */
-#define netmap_ofstophys(o) \
- (vtophys(nm_mem->nm_buffer) + (o))
-
-
-/*------ netmap memory allocator -------*/
-/*
- * Request for a chunk of memory.
- *
- * Memory objects are arranged into a list, hence we need to walk this
- * list until we find an object with the needed amount of data free.
- * This sounds like a completely inefficient implementation, but given
- * the fact that data allocation is done once, we can handle it
- * flawlessly.
- *
- * Return NULL on failure.
- */
-static void *
-netmap_malloc(size_t size, __unused const char *msg)
-{
- struct netmap_mem_obj *mem_obj, *new_mem_obj;
- void *ret = NULL;
-
- NMA_LOCK();
- TAILQ_FOREACH(mem_obj, &nm_mem->nm_molist, nmo_next) {
- if (mem_obj->nmo_used != 0 || mem_obj->nmo_size < size)
- continue;
-
- new_mem_obj = malloc(sizeof(struct netmap_mem_obj), M_NETMAP,
- M_WAITOK | M_ZERO);
- TAILQ_INSERT_BEFORE(mem_obj, new_mem_obj, nmo_next);
-
- new_mem_obj->nmo_used = 1;
- new_mem_obj->nmo_size = size;
- new_mem_obj->nmo_data = mem_obj->nmo_data;
- memset(new_mem_obj->nmo_data, 0, new_mem_obj->nmo_size);
-
- mem_obj->nmo_size -= size;
- mem_obj->nmo_data = (char *) mem_obj->nmo_data + size;
- if (mem_obj->nmo_size == 0) {
- TAILQ_REMOVE(&nm_mem->nm_molist, mem_obj,
- nmo_next);
- free(mem_obj, M_NETMAP);
- }
-
- ret = new_mem_obj->nmo_data;
-
- break;
- }
- NMA_UNLOCK();
- ND("%s: %d bytes at %p", msg, size, ret);
-
- return (ret);
-}
-
-/*
- * Return the memory to the allocator.
- *
- * While freeing a memory object, we try to merge adjacent chunks in
- * order to reduce memory fragmentation.
- */
-static void
-netmap_free(void *addr, const char *msg)
-{
- size_t size;
- struct netmap_mem_obj *cur, *prev, *next;
-
- if (addr == NULL) {
- D("NULL addr for %s", msg);
- return;
- }
-
- NMA_LOCK();
- TAILQ_FOREACH(cur, &nm_mem->nm_molist, nmo_next) {
- if (cur->nmo_data == addr && cur->nmo_used)
- break;
- }
- if (cur == NULL) {
- NMA_UNLOCK();
- D("invalid addr %s %p", msg, addr);
- return;
- }
-
- size = cur->nmo_size;
- cur->nmo_used = 0;
-
- /* merge current chunk of memory with the previous one,
- if present. */
- prev = TAILQ_PREV(cur, netmap_mem_obj_h, nmo_next);
- if (prev && prev->nmo_used == 0) {
- TAILQ_REMOVE(&nm_mem->nm_molist, cur, nmo_next);
- prev->nmo_size += cur->nmo_size;
- free(cur, M_NETMAP);
- cur = prev;
- }
-
- /* merge with the next one */
- next = TAILQ_NEXT(cur, nmo_next);
- if (next && next->nmo_used == 0) {
- TAILQ_REMOVE(&nm_mem->nm_molist, next, nmo_next);
- cur->nmo_size += next->nmo_size;
- free(next, M_NETMAP);
- }
- NMA_UNLOCK();
- ND("freed %s %d bytes at %p", msg, size, addr);
-}
-
-
-/*
- * Create and return a new ``netmap_if`` object, and possibly also
- * rings and packet buffors.
- *
- * Return NULL on failure.
- */
-static void *
-netmap_if_new(const char *ifname, struct netmap_adapter *na)
-{
- struct netmap_if *nifp;
- struct netmap_ring *ring;
- struct netmap_kring *kring;
- char *buff;
- u_int i, len, ofs, numdesc;
- u_int nrx = na->num_rx_rings + 1; /* shorthand, include stack queue */
- u_int ntx = na->num_tx_rings + 1; /* shorthand, include stack queue */
-
- /*
- * the descriptor is followed inline by an array of offsets
- * to the tx and rx rings in the shared memory region.
- */
- len = sizeof(struct netmap_if) + (nrx + ntx) * sizeof(ssize_t);
- nifp = netmap_if_malloc(len);
- if (nifp == NULL)
- return (NULL);
-
- /* initialize base fields */
- *(int *)(uintptr_t)&nifp->ni_rx_rings = na->num_rx_rings;
- *(int *)(uintptr_t)&nifp->ni_tx_rings = na->num_tx_rings;
- strncpy(nifp->ni_name, ifname, IFNAMSIZ);
-
- (na->refcount)++; /* XXX atomic ? we are under lock */
- if (na->refcount > 1)
- goto final;
-
- /*
- * First instance. Allocate the netmap rings
- * (one for each hw queue, one pair for the host).
- * The rings are contiguous, but have variable size.
- * The entire block is reachable at
- * na->tx_rings[0]
- */
- len = (ntx + nrx) * sizeof(struct netmap_ring) +
- (ntx * na->num_tx_desc + nrx * na->num_rx_desc) *
- sizeof(struct netmap_slot);
- buff = netmap_ring_malloc(len);
- if (buff == NULL) {
- D("failed to allocate %d bytes for %s shadow ring",
- len, ifname);
-error:
- (na->refcount)--;
- netmap_if_free(nifp);
- return (NULL);
- }
- /* Check whether we have enough buffers */
- len = ntx * na->num_tx_desc + nrx * na->num_rx_desc;
- NMA_LOCK();
- if (nm_buf_pool.free < len) {
- NMA_UNLOCK();
- netmap_free(buff, "not enough bufs");
- goto error;
- }
- /*
- * in the kring, store the pointers to the shared rings
- * and initialize the rings. We are under NMA_LOCK().
- */
- ofs = 0;
- for (i = 0; i < ntx; i++) { /* Transmit rings */
- kring = &na->tx_rings[i];
- numdesc = na->num_tx_desc;
- bzero(kring, sizeof(*kring));
- kring->na = na;
-
- ring = kring->ring = (struct netmap_ring *)(buff + ofs);
- *(ssize_t *)(uintptr_t)&ring->buf_ofs =
- nm_buf_pool.base - (char *)ring;
- ND("txring[%d] at %p ofs %d", i, ring, ring->buf_ofs);
- *(uint32_t *)(uintptr_t)&ring->num_slots =
- kring->nkr_num_slots = numdesc;
-
- /*
- * 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 = numdesc - 1;
- ring->cur = kring->nr_hwcur = 0;
- *(uint16_t *)(uintptr_t)&ring->nr_buf_size = NETMAP_BUF_SIZE;
- netmap_new_bufs(nifp, ring->slot, numdesc);
-
- ofs += sizeof(struct netmap_ring) +
- numdesc * sizeof(struct netmap_slot);
- }
-
- for (i = 0; i < nrx; i++) { /* Receive rings */
- kring = &na->rx_rings[i];
- numdesc = na->num_rx_desc;
- bzero(kring, sizeof(*kring));
- kring->na = na;
-
- ring = kring->ring = (struct netmap_ring *)(buff + ofs);
- *(ssize_t *)(uintptr_t)&ring->buf_ofs =
- nm_buf_pool.base - (char *)ring;
- ND("rxring[%d] at %p offset %d", i, ring, ring->buf_ofs);
- *(uint32_t *)(uintptr_t)&ring->num_slots =
- kring->nkr_num_slots = numdesc;
- ring->cur = kring->nr_hwcur = 0;
- ring->avail = kring->nr_hwavail = 0; /* empty */
- *(uint16_t *)(uintptr_t)&ring->nr_buf_size = NETMAP_BUF_SIZE;
- netmap_new_bufs(nifp, ring->slot, numdesc);
- ofs += sizeof(struct netmap_ring) +
- numdesc * sizeof(struct netmap_slot);
- }
- NMA_UNLOCK();
- // XXX initialize the selrecord structs.
-
-final:
- /*
- * fill the slots for the rx and tx queues. They contain the offset
- * between the ring and nifp, so the information is usable in
- * userspace to reach the ring from the nifp.
- */
- for (i = 0; i < ntx; i++) {
- *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i] =
- (char *)na->tx_rings[i].ring - (char *)nifp;
- }
- for (i = 0; i < nrx; i++) {
- *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i+ntx] =
- (char *)na->rx_rings[i].ring - (char *)nifp;
- }
- return (nifp);
-}
-
-/*
- * Initialize the memory allocator.
- *
- * Create the descriptor for the memory , allocate the pool of memory
- * and initialize the list of memory objects with a single chunk
- * containing the whole pre-allocated memory marked as free.
- *
- * Start with a large size, then halve as needed if we fail to
- * allocate the block. While halving, always add one extra page
- * because buffers 0 and 1 are used for special purposes.
- * Return 0 on success, errno otherwise.
- */
-static int
-netmap_memory_init(void)
-{
- struct netmap_mem_obj *mem_obj;
- void *buf = NULL;
- int i, n, sz = NETMAP_MEMORY_SIZE;
- int extra_sz = 0; // space for rings and two spare buffers
-
- for (; sz >= 1<<20; sz >>=1) {
- extra_sz = sz/200;
- extra_sz = (extra_sz + 2*PAGE_SIZE - 1) & ~(PAGE_SIZE-1);
- buf = contigmalloc(sz + extra_sz,
- M_NETMAP,
- M_WAITOK | M_ZERO,
- 0, /* low address */
- -1UL, /* high address */
- PAGE_SIZE, /* alignment */
- 0 /* boundary */
- );
- if (buf)
- break;
- }
- if (buf == NULL)
- return (ENOMEM);
- sz += extra_sz;
- nm_mem = malloc(sizeof(struct netmap_mem_d), M_NETMAP,
- M_WAITOK | M_ZERO);
- mtx_init(&nm_mem->nm_mtx, "netmap memory allocator lock", NULL,
- MTX_DEF);
- TAILQ_INIT(&nm_mem->nm_molist);
- nm_mem->nm_buffer = buf;
- nm_mem->nm_totalsize = sz;
-
- /*
- * A buffer takes 2k, a slot takes 8 bytes + ring overhead,
- * so the ratio is 200:1. In other words, we can use 1/200 of
- * the memory for the rings, and the rest for the buffers,
- * and be sure we never run out.
- */
- nm_mem->nm_size = sz/200;
- nm_mem->nm_buf_start =
- (nm_mem->nm_size + PAGE_SIZE - 1) & ~(PAGE_SIZE-1);
- nm_mem->nm_buf_len = sz - nm_mem->nm_buf_start;
-
- nm_buf_pool.base = nm_mem->nm_buffer;
- nm_buf_pool.base += nm_mem->nm_buf_start;
- netmap_buffer_base = nm_buf_pool.base;
- D("netmap_buffer_base %p (offset %d)",
- netmap_buffer_base, (int)nm_mem->nm_buf_start);
- /* number of buffers, they all start as free */
-
- netmap_total_buffers = nm_buf_pool.total_buffers =
- nm_mem->nm_buf_len / NETMAP_BUF_SIZE;
- nm_buf_pool.bufsize = NETMAP_BUF_SIZE;
-
- D("Have %d MB, use %dKB for rings, %d buffers at %p",
- (sz >> 20), (int)(nm_mem->nm_size >> 10),
- nm_buf_pool.total_buffers, nm_buf_pool.base);
-
- /* allocate and initialize the bitmap. Entry 0 is considered
- * always busy (used as default when there are no buffers left).
- */
- n = (nm_buf_pool.total_buffers + 31) / 32;
- nm_buf_pool.bitmap = malloc(sizeof(uint32_t) * n, M_NETMAP,
- M_WAITOK | M_ZERO);
- nm_buf_pool.bitmap[0] = ~3; /* slot 0 and 1 always busy */
- for (i = 1; i < n; i++)
- nm_buf_pool.bitmap[i] = ~0;
- nm_buf_pool.free = nm_buf_pool.total_buffers - 2;
-
- mem_obj = malloc(sizeof(struct netmap_mem_obj), M_NETMAP,
- M_WAITOK | M_ZERO);
- TAILQ_INSERT_HEAD(&nm_mem->nm_molist, mem_obj, nmo_next);
- mem_obj->nmo_used = 0;
- mem_obj->nmo_size = nm_mem->nm_size;
- mem_obj->nmo_data = nm_mem->nm_buffer;
-
- return (0);
-}
-
-
-/*
- * Finalize the memory allocator.
- *
- * Free all the memory objects contained inside the list, and deallocate
- * the pool of memory; finally free the memory allocator descriptor.
- */
-static void
-netmap_memory_fini(void)
-{
- struct netmap_mem_obj *mem_obj;
-
- while (!TAILQ_EMPTY(&nm_mem->nm_molist)) {
- mem_obj = TAILQ_FIRST(&nm_mem->nm_molist);
- TAILQ_REMOVE(&nm_mem->nm_molist, mem_obj, nmo_next);
- if (mem_obj->nmo_used == 1) {
- printf("netmap: leaked %d bytes at %p\n",
- (int)mem_obj->nmo_size,
- mem_obj->nmo_data);
- }
- free(mem_obj, M_NETMAP);
- }
- contigfree(nm_mem->nm_buffer, nm_mem->nm_totalsize, M_NETMAP);
- // XXX mutex_destroy(nm_mtx);
- free(nm_mem, M_NETMAP);
-}
-/*------------- end of memory allocator -----------------*/
diff --git a/sys/dev/netmap/netmap_mem2.c b/sys/dev/netmap/netmap_mem2.c
index 7472178..03a52b6 100644
--- a/sys/dev/netmap/netmap_mem2.c
+++ b/sys/dev/netmap/netmap_mem2.c
@@ -388,7 +388,7 @@ netmap_obj_free_va(struct netmap_obj_pool *p, void *vaddr)
netmap_obj_free(p, j);
return;
}
- ND("address %p is not contained inside any cluster (%s)",
+ D("address %p is not contained inside any cluster (%s)",
vaddr, p->name);
}
@@ -559,8 +559,9 @@ netmap_config_obj_allocator(struct netmap_obj_pool *p, u_int objtotal, u_int obj
i = (clustsize & (PAGE_SIZE - 1));
if (i)
clustsize += PAGE_SIZE - i;
- D("objsize %d clustsize %d objects %d",
- objsize, clustsize, clustentries);
+ if (netmap_verbose)
+ D("objsize %d clustsize %d objects %d",
+ objsize, clustsize, clustentries);
/*
* The number of clusters is n = ceil(objtotal/clustentries)
@@ -649,9 +650,10 @@ netmap_finalize_obj_allocator(struct netmap_obj_pool *p)
}
}
p->bitmap[0] = ~3; /* objs 0 and 1 is always busy */
- D("Pre-allocated %d clusters (%d/%dKB) for '%s'",
- p->_numclusters, p->_clustsize >> 10,
- p->_memtotal >> 10, p->name);
+ if (netmap_verbose)
+ D("Pre-allocated %d clusters (%d/%dKB) for '%s'",
+ p->_numclusters, p->_clustsize >> 10,
+ p->_memtotal >> 10, p->name);
return 0;
@@ -721,7 +723,7 @@ netmap_memory_finalize(void)
nm_mem.refcount++;
if (nm_mem.refcount > 1) {
- D("busy (refcount %d)", nm_mem.refcount);
+ ND("busy (refcount %d)", nm_mem.refcount);
goto out;
}
@@ -796,6 +798,8 @@ static void
netmap_free_rings(struct netmap_adapter *na)
{
int i;
+ if (!na->tx_rings)
+ return;
for (i = 0; i < na->num_tx_rings + 1; i++) {
netmap_ring_free(na->tx_rings[i].ring);
na->tx_rings[i].ring = NULL;
@@ -804,22 +808,32 @@ netmap_free_rings(struct netmap_adapter *na)
netmap_ring_free(na->rx_rings[i].ring);
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 the per-fd structure netmap_if.
+ * If this is the first instance, also allocate the krings, rings etc.
+ */
static void *
netmap_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;
- u_int ntx = na->num_tx_rings + 1; /* shorthand, include stack ring */
- u_int nrx = na->num_rx_rings + 1; /* shorthand, include stack ring */
+ u_int i, len, ndesc, ntx, nrx;
struct netmap_kring *kring;
+ if (netmap_update_config(na)) {
+ /* configuration mismatch, report and fail */
+ return NULL;
+ }
+ ntx = na->num_tx_rings + 1; /* shorthand, include stack ring */
+ nrx = na->num_rx_rings + 1; /* shorthand, include stack ring */
/*
* the descriptor is followed inline by an array of offsets
* to the tx and rx rings in the shared memory region.
@@ -840,6 +854,14 @@ netmap_if_new(const char *ifname, struct netmap_adapter *na)
goto final;
}
+ len = (ntx + nrx) * sizeof(struct netmap_kring);
+ na->tx_rings = malloc(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;
+
/*
* First instance, allocate netmap rings and buffers for this card
* The rings are contiguous, but have variable size.
@@ -947,5 +969,6 @@ static void
netmap_memory_deref(void)
{
nm_mem.refcount--;
- D("refcount = %d", nm_mem.refcount);
+ if (netmap_verbose)
+ D("refcount = %d", nm_mem.refcount);
}
diff --git a/sys/dev/nvram2env/nvram2env.c b/sys/dev/nvram2env/nvram2env.c
index 32f17f9..5de4f87 100644
--- a/sys/dev/nvram2env/nvram2env.c
+++ b/sys/dev/nvram2env/nvram2env.c
@@ -303,7 +303,8 @@ static device_method_t nvram2env_methods[] = {
DEVMETHOD(device_identify, nvram2env_identify),
DEVMETHOD(device_probe, nvram2env_probe),
DEVMETHOD(device_attach, nvram2env_attach),
- {0, 0},
+
+ DEVMETHOD_END
};
static driver_t nvram2env_driver = {
diff --git a/sys/dev/nxge/if_nxge.c b/sys/dev/nxge/if_nxge.c
index c7dbeb6..df1b9ec 100644
--- a/sys/dev/nxge/if_nxge.c
+++ b/sys/dev/nxge/if_nxge.c
@@ -3507,7 +3507,8 @@ static device_method_t xge_methods[] = {
DEVMETHOD(device_attach, xge_attach),
DEVMETHOD(device_detach, xge_detach),
DEVMETHOD(device_shutdown, xge_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t xge_driver = {
diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c
index 7d15fcc..cba57bf 100644
--- a/sys/dev/oce/oce_if.c
+++ b/sys/dev/oce/oce_if.c
@@ -108,7 +108,8 @@ static device_method_t oce_dispatch[] = {
DEVMETHOD(device_attach, oce_attach),
DEVMETHOD(device_detach, oce_detach),
DEVMETHOD(device_shutdown, oce_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t oce_driver = {
diff --git a/sys/dev/puc/puc.c b/sys/dev/puc/puc.c
index 7b93306..d7bfb63 100644
--- a/sys/dev/puc/puc.c
+++ b/sys/dev/puc/puc.c
@@ -622,7 +622,7 @@ puc_bus_setup_intr(device_t dev, device_t child, struct resource *res,
if (cookiep == NULL || res != port->p_ires)
return (EINVAL);
/* We demand that serdev devices use filter_only interrupts. */
- if (ihand != NULL)
+ if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL)
return (ENXIO);
if (rman_get_device(port->p_ires) != originator)
return (ENXIO);
diff --git a/sys/dev/sdhci/sdhci_pci.c b/sys/dev/sdhci/sdhci_pci.c
index 02dc2a1..b8d8530 100644
--- a/sys/dev/sdhci/sdhci_pci.c
+++ b/sys/dev/sdhci/sdhci_pci.c
@@ -426,7 +426,7 @@ static device_method_t sdhci_methods[] = {
DEVMETHOD(sdhci_write_4, sdhci_pci_write_4),
DEVMETHOD(sdhci_write_multi_4, sdhci_pci_write_multi_4),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t sdhci_pci_driver = {
diff --git a/sys/dev/sound/pci/emu10kx-midi.c b/sys/dev/sound/pci/emu10kx-midi.c
index c85800e..0d5fa30 100644
--- a/sys/dev/sound/pci/emu10kx-midi.c
+++ b/sys/dev/sound/pci/emu10kx-midi.c
@@ -239,7 +239,7 @@ static device_method_t emu_midi_methods[] = {
DEVMETHOD(device_attach, emu_midi_attach),
DEVMETHOD(device_detach, emu_midi_detach),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t emu_midi_driver = {
diff --git a/sys/dev/sound/pci/emu10kx-pcm.c b/sys/dev/sound/pci/emu10kx-pcm.c
index ab20dc6..406a85f 100644
--- a/sys/dev/sound/pci/emu10kx-pcm.c
+++ b/sys/dev/sound/pci/emu10kx-pcm.c
@@ -1520,7 +1520,8 @@ static device_method_t emu_pcm_methods[] = {
DEVMETHOD(device_probe, emu_pcm_probe),
DEVMETHOD(device_attach, emu_pcm_attach),
DEVMETHOD(device_detach, emu_pcm_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t emu_pcm_driver = {
diff --git a/sys/dev/sound/pci/emu10kx.c b/sys/dev/sound/pci/emu10kx.c
index 5f217c1..35a4957 100644
--- a/sys/dev/sound/pci/emu10kx.c
+++ b/sys/dev/sound/pci/emu10kx.c
@@ -3529,7 +3529,7 @@ static device_method_t emu_methods[] = {
DEVMETHOD(bus_read_ivar, emu_read_ivar),
DEVMETHOD(bus_write_ivar, emu_write_ivar),
- {0, 0}
+ DEVMETHOD_END
};
diff --git a/sys/dev/sound/sbus/cs4231.c b/sys/dev/sound/sbus/cs4231.c
index e643a4e..83f70f3 100644
--- a/sys/dev/sound/sbus/cs4231.c
+++ b/sys/dev/sound/sbus/cs4231.c
@@ -231,7 +231,8 @@ static device_method_t cs4231_sbus_methods[] = {
DEVMETHOD(device_detach, cs4231_bus_detach),
DEVMETHOD(device_suspend, cs4231_bus_suspend),
DEVMETHOD(device_resume, cs4231_bus_resume),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t cs4231_sbus_driver = {
@@ -249,7 +250,8 @@ static device_method_t cs4231_ebus_methods[] = {
DEVMETHOD(device_detach, cs4231_bus_detach),
DEVMETHOD(device_suspend, cs4231_bus_suspend),
DEVMETHOD(device_resume, cs4231_bus_resume),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t cs4231_ebus_driver = {
diff --git a/sys/dev/sound/usb/uaudio_pcm.c b/sys/dev/sound/usb/uaudio_pcm.c
index b57d0fb..bd00a01 100644
--- a/sys/dev/sound/usb/uaudio_pcm.c
+++ b/sys/dev/sound/usb/uaudio_pcm.c
@@ -227,7 +227,7 @@ static device_method_t ua_pcm_methods[] = {
DEVMETHOD(device_attach, ua_attach),
DEVMETHOD(device_detach, ua_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ua_pcm_driver = {
diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c
index b644f94..7d0450c 100644
--- a/sys/dev/sym/sym_hipd.c
+++ b/sys/dev/sym/sym_hipd.c
@@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
+#include <machine/atomic.h>
#ifdef __sparc64__
#include <dev/ofw/openfirm.h>
@@ -136,7 +137,7 @@ typedef u_int32_t u32;
#elif defined __sparc64__
#define MEMORY_BARRIER() __asm__ volatile("membar #Sync" : : : "memory")
#elif defined __arm__
-#define MEMORY_BARRIER() __do_dmb()
+#define MEMORY_BARRIER() dmb()
#else
#error "Not supported platform"
#endif
@@ -3426,7 +3427,6 @@ sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
/*
* Check against our hardware limits, or bugs :).
*/
- if (fak < 0) {fak = 0; ret = -1;}
if (fak > 2) {fak = 2; ret = -1;}
/*
diff --git a/sys/dev/terasic/de4led/terasic_de4led.c b/sys/dev/terasic/de4led/terasic_de4led.c
index 1fb92d2..bcef7af 100644
--- a/sys/dev/terasic/de4led/terasic_de4led.c
+++ b/sys/dev/terasic/de4led/terasic_de4led.c
@@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
#include <dev/led/led.h>
#include <dev/terasic/de4led/terasic_de4led.h>
+devclass_t terasic_de4led_devclass;
+
static void
terasic_de4led_update(struct terasic_de4led_softc *sc)
{
diff --git a/sys/dev/terasic/de4led/terasic_de4led.h b/sys/dev/terasic/de4led/terasic_de4led.h
index 89461d1..4475e9b 100644
--- a/sys/dev/terasic/de4led/terasic_de4led.h
+++ b/sys/dev/terasic/de4led/terasic_de4led.h
@@ -72,4 +72,6 @@ struct terasic_de4led_softc {
void terasic_de4led_attach(struct terasic_de4led_softc *sc);
void terasic_de4led_detach(struct terasic_de4led_softc *sc);
+extern devclass_t terasic_de4led_devclass;
+
#endif /* _DEV_TERASIC_DE4LED_H_ */
diff --git a/sys/dev/terasic/de4led/terasic_de4led_fdt.c b/sys/dev/terasic/de4led/terasic_de4led_fdt.c
new file mode 100644
index 0000000..0888d6d
--- /dev/null
+++ b/sys/dev/terasic/de4led/terasic_de4led_fdt.c
@@ -0,0 +1,118 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * 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.
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/terasic/de4led/terasic_de4led.h>
+
+/*
+ * Nexus bus attachment for the 8-element LED on the Terasic DE-4 FPGA board,
+ * which is hooked up to the processor via a memory-mapped Avalon bus.
+ */
+static int
+terasic_de4led_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "sri-cambridge,de4led")) {
+ device_set_desc(dev, "Terasic DE4 8-element LED");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+terasic_de4led_fdt_attach(device_t dev)
+{
+ struct terasic_de4led_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->tdl_dev = dev;
+ sc->tdl_unit = device_get_unit(dev);
+ sc->tdl_rid = 0;
+ sc->tdl_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->tdl_rid, RF_ACTIVE);
+ if (sc->tdl_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ terasic_de4led_attach(sc);
+ return (0);
+}
+
+static int
+terasic_de4led_fdt_detach(device_t dev)
+{
+ struct terasic_de4led_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc->tdl_res != NULL, ("%s: resources not allocated",
+ __func__));
+ terasic_de4led_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->tdl_rid, sc->tdl_res);
+ return (0);
+}
+
+static device_method_t terasic_de4led_fdt_methods[] = {
+ DEVMETHOD(device_probe, terasic_de4led_fdt_probe),
+ DEVMETHOD(device_attach, terasic_de4led_fdt_attach),
+ DEVMETHOD(device_detach, terasic_de4led_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t terasic_de4led_fdt_driver = {
+ "terasic_de4led",
+ terasic_de4led_fdt_methods,
+ sizeof(struct terasic_de4led_softc),
+};
+
+DRIVER_MODULE(terasic_de4led, simplebus, terasic_de4led_fdt_driver,
+ terasic_de4led_devclass, 0, 0);
diff --git a/sys/dev/terasic/de4led/terasic_de4led_nexus.c b/sys/dev/terasic/de4led/terasic_de4led_nexus.c
index 92da503..870d412 100644
--- a/sys/dev/terasic/de4led/terasic_de4led_nexus.c
+++ b/sys/dev/terasic/de4led/terasic_de4led_nexus.c
@@ -106,7 +106,5 @@ static driver_t terasic_de4led_nexus_driver = {
sizeof(struct terasic_de4led_softc),
};
-static devclass_t terasic_de4led_devclass;
-
DRIVER_MODULE(terasic_de4led, nexus, terasic_de4led_nexus_driver,
terasic_de4led_devclass, 0, 0);
diff --git a/sys/dev/terasic/mtl/terasic_mtl.c b/sys/dev/terasic/mtl/terasic_mtl.c
index 48e60c7..5305172 100644
--- a/sys/dev/terasic/mtl/terasic_mtl.c
+++ b/sys/dev/terasic/mtl/terasic_mtl.c
@@ -63,6 +63,9 @@ __FBSDID("$FreeBSD$");
* attached as they may be called even if the attach routine hasn't been, on
* an error.
*/
+
+devclass_t terasic_mtl_devclass;
+
int
terasic_mtl_attach(struct terasic_mtl_softc *sc)
{
diff --git a/sys/dev/terasic/mtl/terasic_mtl.h b/sys/dev/terasic/mtl/terasic_mtl.h
index ae41067..e07bbf4 100644
--- a/sys/dev/terasic/mtl/terasic_mtl.h
+++ b/sys/dev/terasic/mtl/terasic_mtl.h
@@ -159,6 +159,8 @@ struct terasic_mtl_softc {
int terasic_mtl_attach(struct terasic_mtl_softc *sc);
void terasic_mtl_detach(struct terasic_mtl_softc *sc);
+extern devclass_t terasic_mtl_devclass;
+
/*
* Sub-driver setup routines.
*/
diff --git a/sys/dev/terasic/mtl/terasic_mtl_fdt.c b/sys/dev/terasic/mtl/terasic_mtl_fdt.c
new file mode 100644
index 0000000..7ffffb2
--- /dev/null
+++ b/sys/dev/terasic/mtl/terasic_mtl_fdt.c
@@ -0,0 +1,200 @@
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * 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.
+ *
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/consio.h> /* struct vt_mode */
+#include <sys/fbio.h> /* video_adapter_t */
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/terasic/mtl/terasic_mtl.h>
+
+static int
+terasic_mtl_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "sri-cambridge,mtl")) {
+ device_set_desc(dev, "Terasic Multi-touch LCD (MTL)");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+terasic_mtl_fdt_attach(device_t dev)
+{
+ struct terasic_mtl_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->mtl_dev = dev;
+ sc->mtl_unit = device_get_unit(dev);
+
+ /*
+ * FDT allows multiple memory resources to be defined for a device;
+ * query them in the order registers, pixel buffer, text buffer.
+ * However, we need to sanity-check that they are page-aligned and
+ * page-sized, so we may still abort.
+ */
+ sc->mtl_reg_rid = 0;
+ sc->mtl_reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->mtl_reg_rid, RF_ACTIVE);
+ if (sc->mtl_reg_res == NULL) {
+ device_printf(dev, "couldn't map register memory\n");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_start(sc->mtl_reg_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper register address");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_size(sc->mtl_reg_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper register size");
+ error = ENXIO;
+ goto error;
+ }
+ device_printf(sc->mtl_dev, "registers at mem %p-%p\n",
+ (void *)rman_get_start(sc->mtl_reg_res),
+ (void *)(rman_get_start(sc->mtl_reg_res) +
+ rman_get_size(sc->mtl_reg_res)));
+
+ sc->mtl_pixel_rid = 1;
+ sc->mtl_pixel_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->mtl_pixel_rid, RF_ACTIVE);
+ if (sc->mtl_pixel_res == NULL) {
+ device_printf(dev, "couldn't map pixel memory\n");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_start(sc->mtl_pixel_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper pixel address");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_size(sc->mtl_pixel_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper pixel size");
+ error = ENXIO;
+ goto error;
+ }
+ device_printf(sc->mtl_dev, "pixel frame buffer at mem %p-%p\n",
+ (void *)rman_get_start(sc->mtl_pixel_res),
+ (void *)(rman_get_start(sc->mtl_pixel_res) +
+ rman_get_size(sc->mtl_pixel_res)));
+
+ sc->mtl_text_rid = 2;
+ sc->mtl_text_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->mtl_text_rid, RF_ACTIVE);
+ if (sc->mtl_text_res == NULL) {
+ device_printf(dev, "couldn't map text memory\n");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_start(sc->mtl_text_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper text address");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_size(sc->mtl_text_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper text size");
+ error = ENXIO;
+ goto error;
+ }
+ device_printf(sc->mtl_dev, "text frame buffer at mem %p-%p\n",
+ (void *)rman_get_start(sc->mtl_text_res),
+ (void *)(rman_get_start(sc->mtl_text_res) +
+ rman_get_size(sc->mtl_text_res)));
+
+ error = terasic_mtl_attach(sc);
+ if (error == 0)
+ return (0);
+error:
+ if (sc->mtl_text_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid,
+ sc->mtl_text_res);
+ if (sc->mtl_pixel_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid,
+ sc->mtl_pixel_res);
+ if (sc->mtl_reg_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid,
+ sc->mtl_reg_res);
+ return (error);
+}
+
+static int
+terasic_mtl_fdt_detach(device_t dev)
+{
+ struct terasic_mtl_softc *sc;
+
+ sc = device_get_softc(dev);
+ terasic_mtl_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid,
+ sc->mtl_text_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid,
+ sc->mtl_pixel_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid,
+ sc->mtl_reg_res);
+ return (0);
+}
+
+static device_method_t terasic_mtl_fdt_methods[] = {
+ DEVMETHOD(device_probe, terasic_mtl_fdt_probe),
+ DEVMETHOD(device_attach, terasic_mtl_fdt_attach),
+ DEVMETHOD(device_detach, terasic_mtl_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t terasic_mtl_fdt_driver = {
+ "terasic_mtl",
+ terasic_mtl_fdt_methods,
+ sizeof(struct terasic_mtl_softc),
+};
+
+DRIVER_MODULE(mtl, simplebus, terasic_mtl_fdt_driver, terasic_mtl_devclass, 0,
+ 0);
diff --git a/sys/dev/terasic/mtl/terasic_mtl_nexus.c b/sys/dev/terasic/mtl/terasic_mtl_nexus.c
index 4a6f2ba..2dff7db 100644
--- a/sys/dev/terasic/mtl/terasic_mtl_nexus.c
+++ b/sys/dev/terasic/mtl/terasic_mtl_nexus.c
@@ -190,7 +190,5 @@ static driver_t terasic_mtl_nexus_driver = {
sizeof(struct terasic_mtl_softc),
};
-static devclass_t terasic_mtl_devclass;
-
DRIVER_MODULE(mtl, nexus, terasic_mtl_nexus_driver, terasic_mtl_devclass, 0,
0);
diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h
index 01752d0..322e9a8 100644
--- a/sys/dev/uart/uart_bus.h
+++ b/sys/dev/uart/uart_bus.h
@@ -138,6 +138,7 @@ extern char uart_driver_name[];
int uart_bus_attach(device_t dev);
int uart_bus_detach(device_t dev);
+int uart_bus_resume(device_t dev);
serdev_intr_t *uart_bus_ihand(device_t dev, int ipend);
int uart_bus_ipend(device_t dev);
int uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan);
diff --git a/sys/dev/uart/uart_bus_acpi.c b/sys/dev/uart/uart_bus_acpi.c
index 756f7f2..ccd213d 100644
--- a/sys/dev/uart/uart_bus_acpi.c
+++ b/sys/dev/uart/uart_bus_acpi.c
@@ -47,6 +47,7 @@ static device_method_t uart_acpi_methods[] = {
DEVMETHOD(device_probe, uart_acpi_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
+ DEVMETHOD(device_resume, uart_bus_resume),
{ 0, 0 }
};
diff --git a/sys/dev/uart/uart_bus_isa.c b/sys/dev/uart/uart_bus_isa.c
index 1836663..1fda15f 100644
--- a/sys/dev/uart/uart_bus_isa.c
+++ b/sys/dev/uart/uart_bus_isa.c
@@ -50,6 +50,7 @@ static device_method_t uart_isa_methods[] = {
DEVMETHOD(device_probe, uart_isa_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
+ DEVMETHOD(device_resume, uart_bus_resume),
{ 0, 0 }
};
diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c
index 307ee340..4237fa4 100644
--- a/sys/dev/uart/uart_bus_pci.c
+++ b/sys/dev/uart/uart_bus_pci.c
@@ -51,6 +51,7 @@ static device_method_t uart_pci_methods[] = {
DEVMETHOD(device_probe, uart_pci_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
+ DEVMETHOD(device_resume, uart_bus_resume),
{ 0, 0 }
};
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index 47d5f3d..f5a9a1c 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -590,3 +590,12 @@ uart_bus_detach(device_t dev)
return (0);
}
+
+int
+uart_bus_resume(device_t dev)
+{
+ struct uart_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (UART_ATTACH(sc));
+}
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 5d56a68..eb36da1 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
@@ -845,6 +847,11 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig)
return (0);
}
+static int broken_txfifo = 0;
+SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
+ &broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
+TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
+
static int
ns8250_bus_transmit(struct uart_softc *sc)
{
@@ -862,7 +869,12 @@ ns8250_bus_transmit(struct uart_softc *sc)
uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
uart_barrier(bas);
}
- sc->sc_txbusy = 1;
+ if (broken_txfifo)
+ ns8250_drain(bas, UART_DRAIN_TRANSMITTER);
+ else
+ sc->sc_txbusy = 1;
uart_unlock(sc->sc_hwmtx);
+ if (broken_txfifo)
+ uart_sched_softih(sc, SER_INT_TXIDLE);
return (0);
}
diff --git a/sys/dev/usb/controller/at91dci.c b/sys/dev/usb/controller/at91dci.c
index 55688d9..6ebd37c 100644
--- a/sys/dev/usb/controller/at91dci.c
+++ b/sys/dev/usb/controller/at91dci.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
*
@@ -44,6 +42,9 @@ __FBSDID("$FreeBSD$");
* endpoints, Function-address and more.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -79,6 +80,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/at91dci.h>
#define AT9100_DCI_BUS2SC(bus) \
@@ -1737,18 +1740,12 @@ static const struct usb_hub_descriptor_min at91dci_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'A', 0, 'T', 0, 'M', 0, 'E', 0, 'L', 0
+ "A\0T\0M\0E\0L"
#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, at91dci_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, at91dci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, at91dci_product);
@@ -1950,8 +1947,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(at91dci_langtab);
- ptr = (const void *)&at91dci_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c
index 132fd48..0dc726c 100644
--- a/sys/dev/usb/controller/atmegadci.c
+++ b/sys/dev/usb/controller/atmegadci.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
*
@@ -36,6 +34,9 @@ __FBSDID("$FreeBSD$");
* endpoints, Function-address and more.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -71,6 +72,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/atmegadci.h>
#define ATMEGA_BUS2SC(bus) \
@@ -1562,18 +1565,12 @@ static const struct usb_hub_descriptor_min atmegadci_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'A', 0, 'T', 0, 'M', 0, 'E', 0, 'G', 0, 'A', 0
+ "A\0T\0M\0E\0G\0A"
#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, atmegadci_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, atmegadci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, atmegadci_product);
@@ -1776,8 +1773,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(atmegadci_langtab);
- ptr = (const void *)&atmegadci_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/avr32dci.c b/sys/dev/usb/controller/avr32dci.c
index 14b4f64..1d2ce87 100644
--- a/sys/dev/usb/controller/avr32dci.c
+++ b/sys/dev/usb/controller/avr32dci.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
*
@@ -35,7 +33,9 @@ __FBSDID("$FreeBSD$");
* NOTE: When the chip detects BUS-reset it will also reset the
* endpoints, Function-address and more.
*/
-
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -71,6 +71,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/avr32dci.h>
#define AVR32_BUS2SC(bus) \
@@ -1503,18 +1505,12 @@ static const struct usb_hub_descriptor_min avr32dci_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'A', 0, 'V', 0, 'R', 0, '3', 0, '2', 0
+ "A\0V\0R\0003\0002"
#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, avr32dci_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, avr32dci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, avr32dci_product);
@@ -1717,8 +1713,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(avr32dci_langtab);
- ptr = (const void *)&avr32dci_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index 89e312a..d08b3d9 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2012 Hans Petter Selasky. All rights reserved.
* Copyright (c) 2010-2011 Aleksandr Rybalko. All rights reserved.
@@ -41,9 +42,9 @@
* internal reset.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#include <dev/usb/controller/dwc_otg.h>
#include <dev/usb/controller/dwc_otgreg.h>
@@ -3489,18 +3491,12 @@ static const struct usb_hub_descriptor_min dwc_otg_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'D', 0, 'W', 0, 'C', 0, 'O', 0, 'T', 0, 'G', 0
+ "D\0W\0C\0O\0T\0G"
#define STRING_PRODUCT \
- 'O', 0, 'T', 0, 'G', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "O\0T\0G\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, dwc_otg_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, dwc_otg_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, dwc_otg_product);
@@ -3702,8 +3698,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(dwc_otg_langtab);
- ptr = (const void *)&dwc_otg_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c
index b301ea4..51b012b 100644
--- a/sys/dev/usb/controller/ehci.c
+++ b/sys/dev/usb/controller/ehci.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 2004 The NetBSD Foundation, Inc. All rights reserved.
@@ -43,9 +44,9 @@
* 1) command failures are not recovered correctly
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -81,6 +82,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/ehci.h>
#include <dev/usb/controller/ehcireg.h>
diff --git a/sys/dev/usb/controller/musb_otg.c b/sys/dev/usb/controller/musb_otg.c
index 627b40b..10dc90b 100644
--- a/sys/dev/usb/controller/musb_otg.c
+++ b/sys/dev/usb/controller/musb_otg.c
@@ -36,6 +36,9 @@
* NOTE: The current implementation only supports Device Side Mode!
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -71,6 +74,8 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/musb_otg.h>
#define MUSBOTG_INTR_ENDPT 1
@@ -2206,19 +2211,12 @@ static const struct usb_hub_descriptor_min musbotg_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'M', 0, 'e', 0, 'n', 0, 't', 0, 'o', 0, 'r', 0, ' ', 0, \
- 'G', 0, 'r', 0, 'a', 0, 'p', 0, 'h', 0, 'i', 0, 'c', 0, 's', 0
+ "M\0e\0n\0t\0o\0r\0 \0G\0r\0a\0p\0h\0i\0c\0s"
#define STRING_PRODUCT \
- 'O', 0, 'T', 0, 'G', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "O\0T\0G\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, musbotg_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, musbotg_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, musbotg_product);
@@ -2420,8 +2418,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(musbotg_langtab);
- ptr = (const void *)&musbotg_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/ohci.c b/sys/dev/usb/controller/ohci.c
index d499506..e78c9e9 100644
--- a/sys/dev/usb/controller/ohci.c
+++ b/sys/dev/usb/controller/ohci.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -25,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* USB Open Host Controller driver.
*
@@ -35,6 +33,9 @@ __FBSDID("$FreeBSD$");
* USB spec: http://www.usb.org/developers/docs/usbspec.zip
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -70,6 +71,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/ohci.h>
#include <dev/usb/controller/ohcireg.h>
diff --git a/sys/dev/usb/controller/uhci.c b/sys/dev/usb/controller/uhci.c
index 78399cc..fe3cf93 100644
--- a/sys/dev/usb/controller/uhci.c
+++ b/sys/dev/usb/controller/uhci.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -25,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* USB Universal Host Controller driver.
* Handles e.g. PIIX3 and PIIX4.
@@ -38,6 +36,9 @@ __FBSDID("$FreeBSD$");
* ftp://download.intel.com/design/intarch/datashts/29056201.pdf
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -73,6 +74,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/uhci.h>
#include <dev/usb/controller/uhcireg.h>
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 5f28640..204569f 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include "opt_ddb.h"
#include <sys/stdint.h>
@@ -62,6 +65,7 @@
#include <dev/usb/usb_bus.h>
#include <dev/usb/usb_pf.h>
#include "usb_if.h"
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
@@ -84,10 +88,12 @@ SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0,
"Debug level");
#endif
+#if USB_HAVE_ROOT_MOUNT_HOLD
static int usb_no_boot_wait = 0;
TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RD|CTLFLAG_TUN, &usb_no_boot_wait, 0,
"No USB device enumerate waiting at boot.");
+#endif
static int usb_no_suspend_wait = 0;
TUNABLE_INT("hw.usb.no_suspend_wait", &usb_no_suspend_wait);
@@ -108,7 +114,8 @@ static device_method_t usb_methods[] = {
DEVMETHOD(device_suspend, usb_suspend),
DEVMETHOD(device_resume, usb_resume),
DEVMETHOD(device_shutdown, usb_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t usb_driver = {
@@ -144,6 +151,7 @@ usb_probe(device_t dev)
return (0);
}
+#if USB_HAVE_ROOT_MOUNT_HOLD
static void
usb_root_mount_rel(struct usb_bus *bus)
{
@@ -153,6 +161,7 @@ usb_root_mount_rel(struct usb_bus *bus)
bus->bus_roothold = NULL;
}
}
+#endif
/*------------------------------------------------------------------------*
* usb_attach
@@ -169,11 +178,12 @@ usb_attach(device_t dev)
return (ENXIO);
}
+#if USB_HAVE_ROOT_MOUNT_HOLD
if (usb_no_boot_wait == 0) {
/* delay vfs_mountroot until the bus is explored */
bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
}
-
+#endif
usb_attach_sub(dev, bus);
return (0); /* return success */
@@ -196,8 +206,10 @@ usb_detach(device_t dev)
/* Stop power watchdog */
usb_callout_drain(&bus->power_wdog);
+#if USB_HAVE_ROOT_MOUNT_HOLD
/* Let the USB explore process detach all devices. */
usb_root_mount_rel(bus);
+#endif
USB_BUS_LOCK(bus);
@@ -363,7 +375,9 @@ usb_bus_explore(struct usb_proc_msg *pm)
(udev->hub->explore) (udev);
USB_BUS_LOCK(bus);
}
+#if USB_HAVE_ROOT_MOUNT_HOLD
usb_root_mount_rel(bus);
+#endif
}
/*------------------------------------------------------------------------*
@@ -630,7 +644,9 @@ usb_bus_attach(struct usb_proc_msg *pm)
default:
device_printf(bus->bdev, "Unsupported USB revision\n");
+#if USB_HAVE_ROOT_MOUNT_HOLD
usb_root_mount_rel(bus);
+#endif
return;
}
@@ -672,7 +688,9 @@ usb_bus_attach(struct usb_proc_msg *pm)
if (err) {
device_printf(bus->bdev, "Root HUB problem, error=%s\n",
usbd_errstr(err));
+#if USB_HAVE_ROOT_MOUNT_HOLD
usb_root_mount_rel(bus);
+#endif
}
/* set softc - we are ready */
diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c
index bbb9f75..6750f32 100644
--- a/sys/dev/usb/controller/uss820dci.c
+++ b/sys/dev/usb/controller/uss820dci.c
@@ -32,6 +32,9 @@
* NOTE: The datasheet does not document everything.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -67,6 +70,8 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/uss820dci.h>
#define USS820_DCI_BUS2SC(bus) \
@@ -1803,18 +1808,12 @@ static const struct usb_hub_descriptor_min uss820dci_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'A', 0, 'G', 0, 'E', 0, 'R', 0, 'E', 0
+ "A\0G\0E\0R\0E"
#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, uss820dci_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, uss820dci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, uss820dci_product);
@@ -2016,8 +2015,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(uss820dci_langtab);
- ptr = (const void *)&uss820dci_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index c62f781..4023ecc 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -38,9 +39,9 @@
* way we avoid too much diveration among USB drivers.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -76,6 +77,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/xhci.h>
#include <dev/usb/controller/xhcireg.h>
@@ -886,6 +889,12 @@ xhci_check_transfer(struct xhci_softc *sc, struct xhci_trb *trb)
* a short packet also makes the transfer done
*/
if (td->remainder > 0) {
+ if (td->alt_next == NULL) {
+ DPRINTF(
+ "short TD has no alternate next\n");
+ xhci_generic_done(xfer);
+ break;
+ }
DPRINTF("TD has short pkt\n");
if (xfer->flags_int.short_frames_ok ||
xfer->flags_int.isochronous_xfr ||
diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c
index 333d437..48d9c4f 100644
--- a/sys/dev/usb/input/uhid.c
+++ b/sys/dev/usb/input/uhid.c
@@ -852,7 +852,8 @@ static device_method_t uhid_methods[] = {
DEVMETHOD(device_probe, uhid_probe),
DEVMETHOD(device_attach, uhid_attach),
DEVMETHOD(device_detach, uhid_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t uhid_driver = {
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index 45ac8fc..0c56ce0 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -995,13 +995,12 @@ ukbd_probe(device_t dev)
if (uaa->info.bInterfaceClass != UICLASS_HID)
return (ENXIO);
+ if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
+ return (ENXIO);
+
if ((uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) &&
- (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD)) {
- if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
- return (ENXIO);
- else
- return (BUS_PROBE_DEFAULT);
- }
+ (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD))
+ return (BUS_PROBE_DEFAULT);
error = usbd_req_get_hid_desc(uaa->device, NULL,
&d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex);
@@ -1009,23 +1008,20 @@ ukbd_probe(device_t dev)
if (error)
return (ENXIO);
- /*
- * NOTE: we currently don't support USB mouse and USB keyboard
- * on the same USB endpoint.
- */
- if (hid_is_collection(d_ptr, d_len,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) {
- /* most likely a mouse */
- error = ENXIO;
- } else if (hid_is_collection(d_ptr, d_len,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) {
- if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
+ if (hid_is_keyboard(d_ptr, d_len)) {
+ if (hid_is_mouse(d_ptr, d_len)) {
+ /*
+ * NOTE: We currently don't support USB mouse
+ * and USB keyboard on the same USB endpoint.
+ * Let "ums" driver win.
+ */
error = ENXIO;
- else
+ } else {
error = BUS_PROBE_DEFAULT;
- } else
+ }
+ } else {
error = ENXIO;
-
+ }
free(d_ptr, M_TEMP);
return (error);
}
@@ -2124,7 +2120,8 @@ static device_method_t ukbd_methods[] = {
DEVMETHOD(device_attach, ukbd_attach),
DEVMETHOD(device_detach, ukbd_detach),
DEVMETHOD(device_resume, ukbd_resume),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ukbd_driver = {
diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c
index c20c986..cc52b99 100644
--- a/sys/dev/usb/input/ums.c
+++ b/sys/dev/usb/input/ums.c
@@ -368,9 +368,7 @@ ums_probe(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
void *d_ptr;
- struct hid_data *hd;
- struct hid_item hi;
- int error, mdepth, found;
+ int error;
uint16_t d_len;
DPRINTFN(11, "\n");
@@ -394,44 +392,13 @@ ums_probe(device_t dev)
if (error)
return (ENXIO);
- hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
- if (hd == NULL)
- return (0);
- mdepth = 0;
- found = 0;
- while (hid_get_item(hd, &hi)) {
- switch (hi.kind) {
- case hid_collection:
- if (mdepth != 0)
- mdepth++;
- else if (hi.collection == 1 &&
- hi.usage ==
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
- mdepth++;
- break;
- case hid_endcollection:
- if (mdepth != 0)
- mdepth--;
- break;
- case hid_input:
- if (mdepth == 0)
- break;
- if (hi.usage ==
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
- (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
- found++;
- if (hi.usage ==
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
- (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
- found++;
- break;
- default:
- break;
- }
- }
- hid_end_parse(hd);
+ if (hid_is_mouse(d_ptr, d_len))
+ error = BUS_PROBE_DEFAULT;
+ else
+ error = ENXIO;
+
free(d_ptr, M_TEMP);
- return (found ? BUS_PROBE_DEFAULT : ENXIO);
+ return (error);
}
static void
@@ -1072,7 +1039,8 @@ static device_method_t ums_methods[] = {
DEVMETHOD(device_probe, ums_probe),
DEVMETHOD(device_attach, ums_attach),
DEVMETHOD(device_detach, ums_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ums_driver = {
diff --git a/sys/dev/usb/misc/udbp.c b/sys/dev/usb/misc/udbp.c
index 56f86ae..8b949ef 100644
--- a/sys/dev/usb/misc/udbp.c
+++ b/sys/dev/usb/misc/udbp.c
@@ -248,7 +248,8 @@ static device_method_t udbp_methods[] = {
DEVMETHOD(device_probe, udbp_probe),
DEVMETHOD(device_attach, udbp_attach),
DEVMETHOD(device_detach, udbp_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t udbp_driver = {
diff --git a/sys/dev/usb/misc/ufm.c b/sys/dev/usb/misc/ufm.c
index 032b635..0612dd2 100644
--- a/sys/dev/usb/misc/ufm.c
+++ b/sys/dev/usb/misc/ufm.c
@@ -105,7 +105,8 @@ static device_method_t ufm_methods[] = {
DEVMETHOD(device_probe, ufm_probe),
DEVMETHOD(device_attach, ufm_attach),
DEVMETHOD(device_detach, ufm_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ufm_driver = {
diff --git a/sys/dev/usb/net/if_axe.c b/sys/dev/usb/net/if_axe.c
index 694e5a5..f0d1044 100644
--- a/sys/dev/usb/net/if_axe.c
+++ b/sys/dev/usb/net/if_axe.c
@@ -159,6 +159,7 @@ static const STRUCT_USB_HOST_ID axe_devs[] = {
AXE_DEV(COREGA, FETHER_USB2_TX, 0),
AXE_DEV(DLINK, DUBE100, 0),
AXE_DEV(DLINK, DUBE100B1, AXE_FLAG_772),
+ AXE_DEV(DLINK, DUBE100C1, AXE_FLAG_772B),
AXE_DEV(GOODWAY, GWUSB2E, 0),
AXE_DEV(IODATA, ETGUS2, AXE_FLAG_178),
AXE_DEV(JVC, MP_PRX1, 0),
diff --git a/sys/dev/usb/net/if_cdce.c b/sys/dev/usb/net/if_cdce.c
index 6e0ce97..6649bc0 100644
--- a/sys/dev/usb/net/if_cdce.c
+++ b/sys/dev/usb/net/if_cdce.c
@@ -237,7 +237,7 @@ static device_method_t cdce_methods[] = {
DEVMETHOD(device_suspend, cdce_suspend),
DEVMETHOD(device_resume, cdce_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t cdce_driver = {
@@ -500,6 +500,7 @@ cdce_attach(device_t dev)
const struct usb_interface_descriptor *id;
const struct usb_cdc_ethernet_descriptor *ued;
const struct usb_config *pcfg;
+ uint32_t seed;
int error;
uint8_t i;
uint8_t data_iface_no;
@@ -612,8 +613,9 @@ alloc_transfers:
/* fake MAC address */
device_printf(dev, "faking MAC address\n");
+ seed = ticks;
sc->sc_ue.ue_eaddr[0] = 0x2a;
- memcpy(&sc->sc_ue.ue_eaddr[1], &ticks, sizeof(uint32_t));
+ memcpy(&sc->sc_ue.ue_eaddr[1], &seed, sizeof(uint32_t));
sc->sc_ue.ue_eaddr[5] = device_get_unit(dev);
} else {
diff --git a/sys/dev/usb/net/if_cue.c b/sys/dev/usb/net/if_cue.c
index 30c5247a..6414e7a 100644
--- a/sys/dev/usb/net/if_cue.c
+++ b/sys/dev/usb/net/if_cue.c
@@ -157,7 +157,7 @@ static device_method_t cue_methods[] = {
DEVMETHOD(device_attach, cue_attach),
DEVMETHOD(device_detach, cue_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t cue_driver = {
diff --git a/sys/dev/usb/net/if_ipheth.c b/sys/dev/usb/net/if_ipheth.c
index 28f941c..3eb2582 100644
--- a/sys/dev/usb/net/if_ipheth.c
+++ b/sys/dev/usb/net/if_ipheth.c
@@ -116,7 +116,7 @@ static device_method_t ipheth_methods[] = {
DEVMETHOD(device_attach, ipheth_attach),
DEVMETHOD(device_detach, ipheth_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ipheth_driver = {
diff --git a/sys/dev/usb/net/if_kue.c b/sys/dev/usb/net/if_kue.c
index 791c73a..ec0c5f0 100644
--- a/sys/dev/usb/net/if_kue.c
+++ b/sys/dev/usb/net/if_kue.c
@@ -199,7 +199,7 @@ static device_method_t kue_methods[] = {
DEVMETHOD(device_attach, kue_attach),
DEVMETHOD(device_detach, kue_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t kue_driver = {
diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c
index 5ce45bc..5c3db72 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -1009,6 +1009,10 @@ smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
/* Check if RX TCP/UDP checksumming is being offloaded */
if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
+
+ struct ether_header *eh;
+
+ eh = mtod(m, struct ether_header *);
/* Remove the extra 2 bytes of the csum */
pktlen -= 2;
@@ -1020,8 +1024,10 @@ smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
* the padding bytes as well. Therefore to be safe we
* ignore the H/W csum on frames less than or equal to
* 64 bytes.
+ *
+ * Ignore H/W csum for non-IPv4 packets.
*/
- if (pktlen > ETHER_MIN_LEN) {
+ if (be16toh(eh->ether_type) == ETHERTYPE_IP && pktlen > ETHER_MIN_LEN) {
/* Indicate the UDP/TCP csum has been calculated */
m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
@@ -1810,7 +1816,7 @@ static device_method_t smsc_methods[] = {
DEVMETHOD(miibus_writereg, smsc_miibus_writereg),
DEVMETHOD(miibus_statchg, smsc_miibus_statchg),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t smsc_driver = {
diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c
index b8f07aa..52f511d 100644
--- a/sys/dev/usb/quirk/usb_quirk.c
+++ b/sys/dev/usb/quirk/usb_quirk.c
@@ -111,6 +111,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(ITUNERNET, USBLCD2X20, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(ITUNERNET, USBLCD4X20, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(LIEBERT, POWERSURE_PXT, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(LIEBERT2, PSI1000, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(MGE, UPS1, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(MGE, UPS2, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(APPLE, IPHONE, 0x0000, 0xffff, UQ_HID_IGNORE),
@@ -302,7 +303,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(ONSPEC, READER, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(ONSPEC, UCF100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
- UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY | UQ_MSC_NO_GETMAXLUN),
+ UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(ONSPEC2, IMAGEMATE_SDDR55, 0x0000, 0xffff,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(PANASONIC, KXL840AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -338,6 +339,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
USB_QUIRK(SANDISK, SDDR31, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
+ USB_QUIRK(SANDISK, IMAGEMATE_SDDR289, 0x0000, 0xffff,
+ UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(SCANLOGIC, SL11R, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(SHUTTLE, EUSB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
@@ -799,7 +802,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data,
}
if (x == USB_SUB_QUIRKS_MAX) {
/* all quirk entries are unused - release */
- memset(pqe, 0, sizeof(pqe));
+ memset(pqe, 0, sizeof(*pqe));
}
mtx_unlock(&usb_quirk_mtx);
return (0); /* success */
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index dc670d66..f2c3a45 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -356,6 +356,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(NOVATEL, V740, 0),
U3G_DEV(NOVATEL, X950D, 0),
U3G_DEV(NOVATEL, XU870, 0),
+ U3G_DEV(MOTOROLA2, MB886, U3GINIT_SCSIEJECT),
U3G_DEV(OPTION, E6500, 0),
U3G_DEV(OPTION, E6501, 0),
U3G_DEV(OPTION, E6601, 0),
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 48ae389..e2ff0ef 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -698,7 +698,8 @@ static device_method_t umass_methods[] = {
DEVMETHOD(device_probe, umass_probe),
DEVMETHOD(device_attach, umass_attach),
DEVMETHOD(device_detach, umass_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t umass_driver = {
@@ -2251,8 +2252,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
/*ascq*/ 0x00,
/*extra args*/ SSD_ELEM_NONE);
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
- CAM_AUTOSNS_VALID;
+ ccb->ccb_h.status =
+ CAM_SCSI_STATUS_ERROR |
+ CAM_AUTOSNS_VALID |
+ CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
xpt_done(ccb);
goto done;
}
@@ -2512,7 +2516,8 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* recovered. We return an error to CAM and let CAM
* retry the command if necessary.
*/
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
xpt_done(ccb);
break;
}
@@ -2575,8 +2580,9 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* usual.
*/
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
+ | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
#if 0
@@ -2587,18 +2593,23 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
/* the rest of the command was filled in at attach */
- if (umass_std_transform(sc, ccb,
+ if ((sc->sc_transform)(sc,
&sc->cam_scsi_test_unit_ready.opcode,
- sizeof(sc->cam_scsi_test_unit_ready))) {
+ sizeof(sc->cam_scsi_test_unit_ready)) == 1) {
umass_command_start(sc, DIR_NONE, NULL, 0,
ccb->ccb_h.timeout,
&umass_cam_quirk_cb, ccb);
+ break;
}
- break;
} else {
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ if (key >= 0) {
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
+ | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
+ ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ } else
+ ccb->ccb_h.status = CAM_AUTOSENSE_FAIL
+ | CAM_DEV_QFRZN;
}
xpt_done(ccb);
break;
@@ -2606,15 +2617,16 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
default:
DPRINTF(sc, UDMASS_SCSI, "Autosense failed, "
"status %d\n", status);
- ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_AUTOSENSE_FAIL | CAM_DEV_QFRZN;
xpt_done(ccb);
}
}
/*
* This completion code just handles the fact that we sent a test-unit-ready
- * after having previously failed a READ CAPACITY with CHECK_COND. Even
- * though this command succeeded, we have to tell CAM to retry.
+ * after having previously failed a READ CAPACITY with CHECK_COND. The CCB
+ * status for CAM is already set earlier.
*/
static void
umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
@@ -2623,9 +2635,6 @@ umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
DPRINTF(sc, UDMASS_SCSI, "Test unit ready "
"returned status %d\n", status);
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
xpt_done(ccb);
}
@@ -2914,7 +2923,8 @@ umass_std_transform(struct umass_softc *sc, union ccb *ccb,
xpt_done(ccb);
return (0);
} else if (retval == 0) {
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_REQ_INVALID | CAM_DEV_QFRZN;
xpt_done(ccb);
return (0);
}
diff --git a/sys/dev/usb/storage/urio.c b/sys/dev/usb/storage/urio.c
index 39fcbe9..6cbb596 100644
--- a/sys/dev/usb/storage/urio.c
+++ b/sys/dev/usb/storage/urio.c
@@ -185,7 +185,8 @@ static device_method_t urio_methods[] = {
DEVMETHOD(device_probe, urio_probe),
DEVMETHOD(device_attach, urio_attach),
DEVMETHOD(device_detach, urio_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t urio_driver = {
diff --git a/sys/dev/usb/storage/ustorage_fs.c b/sys/dev/usb/storage/ustorage_fs.c
index df89619..15a5ba9 100644
--- a/sys/dev/usb/storage/ustorage_fs.c
+++ b/sys/dev/usb/storage/ustorage_fs.c
@@ -36,6 +36,9 @@
* Linux USB gadget stack.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -62,6 +65,7 @@
#define USB_DEBUG_VAR ustorage_fs_debug
#include <dev/usb/usb_debug.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#ifdef USB_DEBUG
static int ustorage_fs_debug = 0;
@@ -252,7 +256,7 @@ static device_method_t ustorage_fs_methods[] = {
DEVMETHOD(device_suspend, ustorage_fs_suspend),
DEVMETHOD(device_resume, ustorage_fs_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ustorage_fs_driver = {
diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c
index 9934202..36c11d9 100644
--- a/sys/dev/usb/template/usb_template.c
+++ b/sys/dev/usb/template/usb_template.c
@@ -29,6 +29,9 @@
* USB templates.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -67,6 +70,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
MODULE_DEPEND(usb_template, usb, 1, 1, 1);
MODULE_VERSION(usb_template, 1);
diff --git a/sys/dev/usb/template/usb_template_audio.c b/sys/dev/usb/template/usb_template_audio.c
index 8e9e7f0..7c7cebe 100644
--- a/sys/dev/usb/template/usb_template_audio.c
+++ b/sys/dev/usb/template/usb_template_audio.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -30,6 +28,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB template for an USB Audio Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,9 +52,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
INDEX_AUDIO_LANG,
@@ -64,30 +67,21 @@ enum {
INDEX_AUDIO_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_AUDIO_PRODUCT \
- 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 0, \
- 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
- 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0,
+ "A\0u\0d\0i\0o\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
#define STRING_AUDIO_MIXER \
- 'M', 0, 'i', 0, 'x', 0, 'e', 0, 'r', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "M\0i\0x\0e\0r\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_AUDIO_RECORD \
- 'R', 0, 'e', 0, 'c', 0, 'o', 0, 'r', 0, 'd', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "R\0e\0c\0o\0r\0d\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_AUDIO_PLAYBACK \
- 'P', 0, 'l', 0, 'a', 0, 'y', 0, 'b', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "P\0l\0a\0y\0b\0a\0c\0k\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_AUDIO_MIXER, string_audio_mixer);
USB_MAKE_STRING_DESC(STRING_AUDIO_RECORD, string_audio_record);
USB_MAKE_STRING_DESC(STRING_AUDIO_PLAYBACK, string_audio_playback);
@@ -385,7 +379,7 @@ static const void *
audio_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[INDEX_AUDIO_MAX] = {
- [INDEX_AUDIO_LANG] = &string_lang,
+ [INDEX_AUDIO_LANG] = &usb_string_lang_en,
[INDEX_AUDIO_MIXER] = &string_audio_mixer,
[INDEX_AUDIO_RECORD] = &string_audio_record,
[INDEX_AUDIO_PLAYBACK] = &string_audio_playback,
@@ -393,7 +387,7 @@ audio_get_string_desc(uint16_t lang_id, uint8_t string_index)
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_cdce.c b/sys/dev/usb/template/usb_template_cdce.c
index 481a69c..68f69d0 100644
--- a/sys/dev/usb/template/usb_template_cdce.c
+++ b/sys/dev/usb/template/usb_template_cdce.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2007 Hans Petter Selasky <hselasky@FreeBSD.org>
* All rights reserved.
@@ -31,6 +29,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB templates for a CDC USB ethernet device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -52,9 +53,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
STRING_LANG_INDEX,
@@ -68,61 +71,31 @@ enum {
STRING_ETH_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_MAC \
- '2', 0, 'A', 0, '2', 0, '3', 0, \
- '4', 0, '5', 0, '6', 0, '7', 0, \
- '8', 0, '9', 0, 'A', 0, 'B', 0,
+ "2\0A\0002\0003\0004\0005\0006\0007\08\09\0A\0B"
#define STRING_ETH_CONTROL \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'E', 0, 't', 0, 'h', 0, 'e', 0, \
- 'r', 0, 'n', 0, 'e', 0, 't', 0, \
- ' ', 0, 'C', 0, 'o', 0, 'm', 0, \
- 'm', 0, ' ', 0, 'i', 0, 'n', 0, \
- 't', 0, 'e', 0, 'r', 0, 'f', 0, \
- 'a', 0, 'c', 0, 'e', 0,
+ "U\0S\0B\0 \0E\0t\0h\0e\0r\0n\0e\0t\0 " \
+ "\0C\0o\0m\0m\0 \0I\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_ETH_DATA \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'E', 0, 't', 0, 'h', 0, 'e', 0, \
- 'r', 0, 'n', 0, 'e', 0, 't', 0, \
- ' ', 0, 'D', 0, 'a', 0, 't', 0, \
- 'a', 0, ' ', 0, 'i', 0, 'n', 0, \
- 't', 0, 'e', 0, 'r', 0, 'f', 0, \
- 'a', 0, 'c', 0, 'e', 0,
+ "U\0S\0B\0 \0E\0t\0h\0e\0r\0n\0e\0t\0 \0D\0a\0t\0a\0 " \
+ "\0I\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_ETH_CONFIG \
- 'D', 0, 'e', 0, 'f', 0, 'a', 0, \
- 'u', 0, 'l', 0, 't', 0, ' ', 0, \
- 'c', 0, 'o', 0, 'n', 0, 'f', 0, \
- 'i', 0, 'g', 0,
+ "D\0e\0f\0a\0u\0l\0t\0 \0c\0o\0n\0f\0i\0g"
#define STRING_ETH_VENDOR \
- 'F', 0, 'r', 0, 'e', 0, 'e', 0, \
- 'B', 0, 'S', 0, 'D', 0, ' ', 0, \
- 'f', 0, 'o', 0, 'u', 0, 'n', 0, \
- 'd', 0, 'a', 0, 't', 0, 'i', 0, \
- 'o', 0, 'n', 0,
+ "F\0r\0e\0e\0B\0S\0D\0 \0f\0o\0u\0n\0d\0a\0t\0i\0o\0n"
#define STRING_ETH_PRODUCT \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'E', 0, 't', 0, 'h', 0, 'e', 0, \
- 'r', 0, 'n', 0, 'e', 0, 't', 0, \
- ' ', 0, 'A', 0, 'd', 0, 'a', 0, \
- 'p', 0, 't', 0, 'e', 0, 'r', 0,
+ "U\0S\0B\0 \0E\0t\0h\0e\0r\0n\0e\0t\0 \0A\0d\0a\0p\0t\0e\0r"
#define STRING_ETH_SERIAL \
- 'D', 0, 'e', 0, 'c', 0, 'e', 0, \
- 'm', 0, 'b', 0, 'e', 0, 'r', 0, \
- ' ', 0, '2', 0, '0', 0, '0', 0, \
- '7', 0,
+ "D\0e\0c\0e\0m\0b\0e\0r\0 \0002\0000\0000\0007"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MAC, string_mac);
USB_MAKE_STRING_DESC(STRING_ETH_CONTROL, string_eth_control);
USB_MAKE_STRING_DESC(STRING_ETH_DATA, string_eth_data);
@@ -286,7 +259,7 @@ static const void *
eth_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[STRING_ETH_MAX] = {
- [STRING_LANG_INDEX] = &string_lang,
+ [STRING_LANG_INDEX] = &usb_string_lang_en,
[STRING_MAC_INDEX] = &string_mac,
[STRING_ETH_CONTROL_INDEX] = &string_eth_control,
[STRING_ETH_DATA_INDEX] = &string_eth_data,
@@ -297,7 +270,7 @@ eth_get_string_desc(uint16_t lang_id, uint8_t string_index)
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_kbd.c b/sys/dev/usb/template/usb_template_kbd.c
index 6295825..306b2fe 100644
--- a/sys/dev/usb/template/usb_template_kbd.c
+++ b/sys/dev/usb/template/usb_template_kbd.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -30,6 +28,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB template for an USB Keyboard Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,9 +52,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
INDEX_LANG,
@@ -62,21 +65,14 @@ enum {
INDEX_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_PRODUCT \
- 'K', 0, 'e', 0, 'y', 0, 'b', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0, \
- 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
- 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0,
+ "K\0e\0y\0b\0o\0a\0r\0d\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
#define STRING_KEYBOARD \
- 'K', 0, 'e', 0, 'y', 0, 'b', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "K\0e\0y\0b\0o\0a\0r\0d\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_KEYBOARD, string_keyboard);
USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product);
@@ -206,13 +202,13 @@ static const void *
keyboard_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[INDEX_MAX] = {
- [INDEX_LANG] = &string_lang,
+ [INDEX_LANG] = &usb_string_lang_en,
[INDEX_KEYBOARD] = &string_keyboard,
[INDEX_PRODUCT] = &string_product,
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_modem.c b/sys/dev/usb/template/usb_template_modem.c
index abc6f26..6a976f7 100644
--- a/sys/dev/usb/template/usb_template_modem.c
+++ b/sys/dev/usb/template/usb_template_modem.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -30,6 +28,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB template for an USB Modem Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,9 +52,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
INDEX_LANG,
@@ -62,21 +65,14 @@ enum {
INDEX_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_PRODUCT \
- 'M', 0, 'o', 0, 'd', 0, 'e', 0, 'm', 0, ' ', 0, \
- 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
- 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0,
+ "M\0o\0d\0e\0m\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
#define STRING_MODEM \
- 'M', 0, 'o', 0, 'd', 0, 'e', 0, 'm', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "M\0o\0d\0e\0m\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MODEM, string_modem);
USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product);
@@ -234,13 +230,13 @@ static const void *
modem_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[INDEX_MAX] = {
- [INDEX_LANG] = &string_lang,
+ [INDEX_LANG] = &usb_string_lang_en,
[INDEX_MODEM] = &string_modem,
[INDEX_PRODUCT] = &string_product,
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_mouse.c b/sys/dev/usb/template/usb_template_mouse.c
index 628c9a5..a48ccf4 100644
--- a/sys/dev/usb/template/usb_template_mouse.c
+++ b/sys/dev/usb/template/usb_template_mouse.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -30,6 +28,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB template for an USB Mouse Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,9 +52,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
INDEX_LANG,
@@ -62,21 +65,14 @@ enum {
INDEX_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_PRODUCT \
- 'M', 0, 'o', 0, 'u', 0, 's', 0, 'e', 0, ' ', 0, \
- 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
- 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
+ "M\0o\0u\0s\0e\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
#define STRING_MOUSE \
- 'M', 0, 'o', 0, 'u', 0, 's', 0, 'e', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "M\0o\0u\0s\0e\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MOUSE, string_mouse);
USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product);
@@ -204,13 +200,13 @@ static const void *
mouse_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[INDEX_MAX] = {
- [INDEX_LANG] = &string_lang,
+ [INDEX_LANG] = &usb_string_lang_en,
[INDEX_MOUSE] = &string_mouse,
[INDEX_PRODUCT] = &string_product,
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_msc.c b/sys/dev/usb/template/usb_template_msc.c
index 5c05ffe..6809e63 100644
--- a/sys/dev/usb/template/usb_template_msc.c
+++ b/sys/dev/usb/template/usb_template_msc.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
* All rights reserved.
@@ -31,6 +29,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB templates for an USB Mass Storage Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -52,8 +53,10 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
STRING_LANG_INDEX,
@@ -65,45 +68,24 @@ enum {
STRING_MSC_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_MSC_DATA \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'M', 0, 'a', 0, 's', 0, 's', 0, \
- ' ', 0, 'S', 0, 't', 0, 'o', 0, \
- 'r', 0, 'a', 0, 'g', 0, 'e', 0, \
- ' ', 0, 'I', 0, 'n', 0, 't', 0, \
- 'e', 0, 'r', 0, 'f', 0, 'a', 0, \
- 'c', 0, 'e', 0,
+ "U\0S\0B\0 \0M\0a\0s\0s\0 \0S\0t\0o\0r\0a\0g\0e\0 " \
+ "\0I\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_MSC_CONFIG \
- 'D', 0, 'e', 0, 'f', 0, 'a', 0, \
- 'u', 0, 'l', 0, 't', 0, ' ', 0, \
- 'c', 0, 'o', 0, 'n', 0, 'f', 0, \
- 'i', 0, 'g', 0,
+ "D\0e\0f\0a\0u\0l\0t\0 \0c\0o\0n\0f\0i\0g"
#define STRING_MSC_VENDOR \
- 'F', 0, 'r', 0, 'e', 0, 'e', 0, \
- 'B', 0, 'S', 0, 'D', 0, ' ', 0, \
- 'f', 0, 'o', 0, 'u', 0, 'n', 0, \
- 'd', 0, 'a', 0, 't', 0, 'i', 0, \
- 'o', 0, 'n', 0,
+ "F\0r\0e\0e\0B\0S\0D\0 \0f\0o\0u\0n\0d\0a\0t\0i\0o\0n"
#define STRING_MSC_PRODUCT \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'M', 0, 'e', 0, 'm', 0, 'o', 0, \
- 'r', 0, 'y', 0, ' ', 0, 'S', 0, \
- 't', 0, 'i', 0, 'c', 0, 'k', 0
+ "U\0S\0B\0 \0M\0e\0m\0o\0r\0y\0 \0S\0t\0i\0c\0k"
#define STRING_MSC_SERIAL \
- 'M', 0, 'a', 0, 'r', 0, 'c', 0, \
- 'h', 0, ' ', 0, '2', 0, '0', 0, \
- '0', 0, '8', 0,
+ "M\0a\0r\0c\0h\0 \0002\0000\0000\08"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MSC_DATA, string_msc_data);
USB_MAKE_STRING_DESC(STRING_MSC_CONFIG, string_msc_config);
USB_MAKE_STRING_DESC(STRING_MSC_VENDOR, string_msc_vendor);
@@ -195,7 +177,7 @@ static const void *
msc_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[STRING_MSC_MAX] = {
- [STRING_LANG_INDEX] = &string_lang,
+ [STRING_LANG_INDEX] = &usb_string_lang_en,
[STRING_MSC_DATA_INDEX] = &string_msc_data,
[STRING_MSC_CONFIG_INDEX] = &string_msc_config,
[STRING_MSC_VENDOR_INDEX] = &string_msc_vendor,
@@ -204,7 +186,7 @@ msc_get_string_desc(uint16_t lang_id, uint8_t string_index)
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_mtp.c b/sys/dev/usb/template/usb_template_mtp.c
index f48fbf4..f0528a5 100644
--- a/sys/dev/usb/template/usb_template_mtp.c
+++ b/sys/dev/usb/template/usb_template_mtp.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
* All rights reserved.
@@ -38,6 +36,9 @@ __FBSDID("$FreeBSD$");
* operating system the VID and PID of your device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -59,7 +60,10 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
+
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#define MTP_BREQUEST 0x08
@@ -73,41 +77,23 @@ enum {
STRING_MTP_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_MTP_DATA \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'M', 0, 'T', 0, 'P', 0, \
- ' ', 0, 'I', 0, 'n', 0, 't', 0, \
- 'e', 0, 'r', 0, 'f', 0, 'a', 0, \
- 'c', 0, 'e', 0,
+ "U\0S\0B\0 \0M\0T\0P\0 \0I\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_MTP_CONFIG \
- 'D', 0, 'e', 0, 'f', 0, 'a', 0, \
- 'u', 0, 'l', 0, 't', 0, ' ', 0, \
- 'c', 0, 'o', 0, 'n', 0, 'f', 0, \
- 'i', 0, 'g', 0,
+ "D\0e\0f\0a\0u\0l\0t\0 \0c\0o\0n\0f\0i\0g"
#define STRING_MTP_VENDOR \
- 'F', 0, 'r', 0, 'e', 0, 'e', 0, \
- 'B', 0, 'S', 0, 'D', 0, ' ', 0, \
- 'f', 0, 'o', 0, 'u', 0, 'n', 0, \
- 'd', 0, 'a', 0, 't', 0, 'i', 0, \
- 'o', 0, 'n', 0,
+ "F\0r\0e\0e\0B\0S\0D\0 \0f\0o\0u\0n\0d\0a\0t\0i\0o\0n"
#define STRING_MTP_PRODUCT \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'M', 0, 'T', 0, 'P', 0,
+ "U\0S\0B\0 \0M\0T\0P"
#define STRING_MTP_SERIAL \
- 'J', 0, 'u', 0, 'n', 0, 'e', 0, \
- ' ', 0, '2', 0, '0', 0, '0', 0, \
- '8', 0,
+ "J\0u\0n\0e\0 \0002\0000\0000\08"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MTP_DATA, string_mtp_data);
USB_MAKE_STRING_DESC(STRING_MTP_CONFIG, string_mtp_config);
USB_MAKE_STRING_DESC(STRING_MTP_VENDOR, string_mtp_vendor);
@@ -244,7 +230,7 @@ static const void *
mtp_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[STRING_MTP_MAX] = {
- [STRING_LANG_INDEX] = &string_lang,
+ [STRING_LANG_INDEX] = &usb_string_lang_en,
[STRING_MTP_DATA_INDEX] = &string_mtp_data,
[STRING_MTP_CONFIG_INDEX] = &string_mtp_config,
[STRING_MTP_VENDOR_INDEX] = &string_mtp_vendor,
@@ -266,7 +252,7 @@ mtp_get_string_desc(uint16_t lang_id, uint8_t string_index)
return (dummy_desc);
}
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/ufm_ioctl.h b/sys/dev/usb/ufm_ioctl.h
index 921b3d4..5a23388 100644
--- a/sys/dev/usb/ufm_ioctl.h
+++ b/sys/dev/usb/ufm_ioctl.h
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2001 M. Warner Losh
* All rights reserved.
@@ -28,7 +29,8 @@
* its contributors.
*/
-/* $FreeBSD$ */
+#ifndef _UFM_IOCTL_H_
+#define _UFM_IOCTL_H_
#include <sys/ioccom.h>
@@ -37,3 +39,5 @@
#define FM_START _IOWR('U', 202, int)
#define FM_STOP _IOWR('U', 203, int)
#define FM_GET_STAT _IOWR('U', 204, int)
+
+#endif /* _UFM_IOCTL_H_ */
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index a47c9d8..b8b52d5 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -40,22 +40,28 @@
#define _USB_STANDARD_H_
#if defined(_KERNEL)
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include "opt_usb.h"
+#endif
/* Declare parent SYSCTL USB node. */
#ifdef SYSCTL_DECL
SYSCTL_DECL(_hw_usb);
#endif
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/malloc.h>
+#endif
MALLOC_DECLARE(M_USB);
MALLOC_DECLARE(M_USBDEV);
MALLOC_DECLARE(M_USBHC);
#endif /* _KERNEL */
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <dev/usb/usb_endian.h>
#include <dev/usb/usb_freebsd.h>
+#endif
#define USB_STACK_VERSION 2000 /* 2.0 */
@@ -560,17 +566,23 @@ struct usb_string_descriptor {
typedef struct usb_string_descriptor usb_string_descriptor_t;
#define USB_MAKE_STRING_DESC(m,name) \
-struct name { \
+static const struct { \
uByte bLength; \
uByte bDescriptorType; \
uByte bData[sizeof((uint8_t []){m})]; \
-} __packed; \
-static const struct name name = { \
- .bLength = sizeof(struct name), \
+} __packed name = { \
+ .bLength = sizeof(name), \
.bDescriptorType = UDESC_STRING, \
.bData = { m }, \
}
+struct usb_string_lang {
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bData[2];
+} __packed;
+typedef struct usb_string_lang usb_string_lang_t;
+
struct usb_hub_descriptor {
uByte bDescLength;
uByte bDescriptorType;
diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c
index f3c4833..1808ab4 100644
--- a/sys/dev/usb/usb_busdma.c
+++ b/sys/dev/usb/usb_busdma.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -59,6 +62,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#if USB_HAVE_BUSDMA
static void usb_dma_tag_create(struct usb_dma_tag *, usb_size_t, usb_size_t);
@@ -440,7 +444,6 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
pc->page_offset_buf = rem;
pc->page_offset_end += rem;
- nseg--;
#ifdef USB_DEBUG
if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
/*
@@ -451,7 +454,7 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
goto done;
}
#endif
- while (nseg > 0) {
+ while (1) {
off += USB_PAGE_SIZE;
if (off >= (segs->ds_len + rem)) {
/* page crossing */
@@ -459,6 +462,8 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
segs++;
off = 0;
rem = 0;
+ if (nseg == 0)
+ break;
}
pg++;
pg->physaddr = (segs->ds_addr + off) & ~(USB_PAGE_SIZE - 1);
diff --git a/sys/dev/usb/usb_busdma.h b/sys/dev/usb/usb_busdma.h
index 6b6e403..1050af5 100644
--- a/sys/dev/usb/usb_busdma.h
+++ b/sys/dev/usb/usb_busdma.h
@@ -27,10 +27,12 @@
#ifndef _USB_BUSDMA_H_
#define _USB_BUSDMA_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/uio.h>
#include <sys/mbuf.h>
#include <machine/bus.h>
+#endif
/* defines */
diff --git a/sys/dev/usb/usb_compat_linux.c b/sys/dev/usb/usb_compat_linux.c
index 22bf1f4..a42f636 100644
--- a/sys/dev/usb/usb_compat_linux.c
+++ b/sys/dev/usb/usb_compat_linux.c
@@ -25,6 +25,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -61,6 +64,7 @@
#include <dev/usb/usb_hub.h>
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_debug.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
struct usb_linux_softc {
LIST_ENTRY(usb_linux_softc) sc_attached_list;
@@ -109,7 +113,7 @@ static device_method_t usb_linux_methods[] = {
DEVMETHOD(device_suspend, usb_linux_suspend),
DEVMETHOD(device_resume, usb_linux_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t usb_linux_driver = {
diff --git a/sys/dev/usb/usb_core.c b/sys/dev/usb/usb_core.c
index 1bd05c8..8a5b93c 100644
--- a/sys/dev/usb/usb_core.c
+++ b/sys/dev/usb/usb_core.c
@@ -30,6 +30,9 @@
* http://www.usb.org/developers/devclass_docs/
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,6 +54,12 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
+const struct usb_string_lang usb_string_lang_en = {
+ sizeof(usb_string_lang_en), UDESC_STRING,
+ { 0x09, 0x04 } /* American English */
+};
MALLOC_DEFINE(M_USB, "USB", "USB");
MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device");
diff --git a/sys/dev/usb/usb_core.h b/sys/dev/usb/usb_core.h
index 776cf17..afd74ed 100644
--- a/sys/dev/usb/usb_core.h
+++ b/sys/dev/usb/usb_core.h
@@ -69,6 +69,7 @@ struct usb_page;
struct usb_page_cache;
struct usb_xfer;
struct usb_xfer_root;
+struct usb_string_lang;
/* typedefs */
@@ -174,6 +175,7 @@ struct usb_xfer {
/* external variables */
extern struct mtx usb_ref_lock;
+extern const struct usb_string_lang usb_string_lang_en;
/* typedefs */
diff --git a/sys/dev/usb/usb_debug.c b/sys/dev/usb/usb_debug.c
index 7ca4daa..3382988 100644
--- a/sys/dev/usb/usb_debug.c
+++ b/sys/dev/usb/usb_debug.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -55,6 +58,7 @@
#include <ddb/ddb.h>
#include <ddb/db_sym.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*
* Define this unconditionally in case a kernel module is loaded that
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index a8adbf6..c4264c5 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -27,6 +27,9 @@
* usb_dev.c - An abstraction layer for creating devices under /dev/...
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -75,6 +78,7 @@
#include <sys/syscallsubr.h>
#include <machine/stdarg.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#if USB_HAVE_UGEN
diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h
index aa9197f..3c75701 100644
--- a/sys/dev/usb/usb_dev.h
+++ b/sys/dev/usb/usb_dev.h
@@ -27,11 +27,13 @@
#ifndef _USB_DEV_H_
#define _USB_DEV_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/file.h>
#include <sys/selinfo.h>
#include <sys/poll.h>
#include <sys/signalvar.h>
#include <sys/proc.h>
+#endif
struct usb_fifo;
struct usb_mbuf;
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 05c0a4c..8d88bf5 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -78,6 +81,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
diff --git a/sys/dev/usb/usb_dynamic.c b/sys/dev/usb/usb_dynamic.c
index 1358b30..f8bb03f 100644
--- a/sys/dev/usb/usb_dynamic.c
+++ b/sys/dev/usb/usb_dynamic.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -50,6 +53,7 @@
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_dynamic.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
static usb_handle_req_t usb_temp_get_desc_w;
diff --git a/sys/dev/usb/usb_endian.h b/sys/dev/usb/usb_endian.h
index 29479f1..0bbcb9b 100644
--- a/sys/dev/usb/usb_endian.h
+++ b/sys/dev/usb/usb_endian.h
@@ -27,8 +27,10 @@
#ifndef _USB_ENDIAN_H_
#define _USB_ENDIAN_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/stdint.h>
#include <sys/endian.h>
+#endif
/*
* Declare the basic USB record types. USB records have an alignment
diff --git a/sys/dev/usb/usb_error.c b/sys/dev/usb/usb_error.c
index 119c617..5987d81 100644
--- a/sys/dev/usb/usb_error.c
+++ b/sys/dev/usb/usb_error.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -45,6 +48,7 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
static const char* usb_errstr_table[USB_ERR_MAX] = {
[USB_ERR_NORMAL_COMPLETION] = "USB_ERR_NORMAL_COMPLETION",
diff --git a/sys/dev/usb/usb_freebsd.h b/sys/dev/usb/usb_freebsd.h
index 42a54c5..e93bee7 100644
--- a/sys/dev/usb/usb_freebsd.h
+++ b/sys/dev/usb/usb_freebsd.h
@@ -42,6 +42,8 @@
#define USB_HAVE_POWERD 1
#define USB_HAVE_MSCTEST 1
#define USB_HAVE_PF 1
+#define USB_HAVE_ROOT_MOUNT_HOLD 1
+#define USB_HAVE_ID_SECTION 1
#define USB_TD_GET_PROC(td) (td)->td_proc
#define USB_PROC_GET_GID(td) (td)->p_pgid
diff --git a/sys/dev/usb/usb_freebsd_loader.h b/sys/dev/usb/usb_freebsd_loader.h
new file mode 100644
index 0000000..566f922
--- /dev/null
+++ b/sys/dev/usb/usb_freebsd_loader.h
@@ -0,0 +1,84 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. 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.
+ */
+
+/*
+ * Including this file is mandatory for all USB related c-files in the loader.
+ */
+
+#ifndef _USB_FREEBSD_LOADER_H_
+#define _USB_FREEBSD_LOADER_H_
+
+/* Default USB configuration */
+#define USB_HAVE_UGEN 0
+#define USB_HAVE_DEVCTL 0
+#define USB_HAVE_BUSDMA 1
+#define USB_HAVE_COMPAT_LINUX 0
+#define USB_HAVE_USER_IO 0
+#define USB_HAVE_MBUF 0
+#define USB_HAVE_TT_SUPPORT 1
+#define USB_HAVE_POWERD 1
+#define USB_HAVE_MSCTEST 0
+#define USB_HAVE_PF 0
+#define USB_HAVE_ROOT_MOUNT_HOLD 0
+#define USB_HAVE_ID_SECTION 0
+
+#define USB_TD_GET_PROC(td) (td)->td_proc
+#define USB_PROC_GET_GID(td) (td)->p_pgid
+
+#if (!defined(USB_HOST_ALIGN)) || (USB_HOST_ALIGN <= 0)
+/* Use default value. */
+#undef USB_HOST_ALIGN
+#define USB_HOST_ALIGN 8 /* bytes, must be power of two */
+#endif
+/* Sanity check for USB_HOST_ALIGN: Verify power of two. */
+#if ((-USB_HOST_ALIGN) & USB_HOST_ALIGN) != USB_HOST_ALIGN
+#error "USB_HOST_ALIGN is not power of two."
+#endif
+#define USB_FS_ISOC_UFRAME_MAX 4 /* exclusive unit */
+#define USB_BUS_MAX 256 /* units */
+#define USB_MAX_DEVICES 128 /* units */
+#define USB_IFACE_MAX 32 /* units */
+#define USB_FIFO_MAX 128 /* units */
+#define USB_MAX_EP_STREAMS 8 /* units */
+
+#define USB_MAX_FS_ISOC_FRAMES_PER_XFER (120) /* units */
+#define USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */
+
+#define USB_HUB_MAX_DEPTH 5
+#define USB_EP0_BUFSIZE 1024 /* bytes */
+#define USB_CS_RESET_LIMIT 20 /* failures = 20 * 50 ms = 1sec */
+
+#define USB_MAX_AUTO_QUIRK 4 /* maximum number of dynamic quirks */
+
+typedef uint32_t usb_timeout_t; /* milliseconds */
+typedef uint32_t usb_frlength_t; /* bytes */
+typedef uint32_t usb_frcount_t; /* units */
+typedef uint32_t usb_size_t; /* bytes */
+typedef uint32_t usb_ticks_t; /* system defined */
+typedef uint16_t usb_power_mask_t; /* see "USB_HW_POWER_XXX" */
+typedef uint16_t usb_stream_t; /* stream ID */
+
+#endif /* _USB_FREEBSD_LOADER_H_ */
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
index f8376bf..13f5bd6 100644
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -67,6 +70,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#if USB_HAVE_UGEN
diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c
index f5b226e..13fff91 100644
--- a/sys/dev/usb/usb_handle_request.c
+++ b/sys/dev/usb/usb_handle_request.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -61,6 +64,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
diff --git a/sys/dev/usb/usb_hid.c b/sys/dev/usb/usb_hid.c
index 6552546..e6361a6 100644
--- a/sys/dev/usb/usb_hid.c
+++ b/sys/dev/usb/usb_hid.c
@@ -1,8 +1,5 @@
+/* $FreeBSD$ */
/* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */
-
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -33,6 +30,9 @@ __FBSDID("$FreeBSD$");
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_request.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
static void hid_clear_local(struct hid_item *);
static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize);
@@ -845,3 +846,79 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
}
return (USB_ERR_NORMAL_COMPLETION);
}
+
+/*------------------------------------------------------------------------*
+ * hid_is_mouse
+ *
+ * This function will decide if a USB descriptor belongs to a USB mouse.
+ *
+ * Return values:
+ * Zero: Not a USB mouse.
+ * Else: Is a USB mouse.
+ *------------------------------------------------------------------------*/
+int
+hid_is_mouse(const void *d_ptr, uint16_t d_len)
+{
+ struct hid_data *hd;
+ struct hid_item hi;
+ int mdepth;
+ int found;
+
+ hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
+ if (hd == NULL)
+ return (0);
+
+ mdepth = 0;
+ found = 0;
+
+ while (hid_get_item(hd, &hi)) {
+ switch (hi.kind) {
+ case hid_collection:
+ if (mdepth != 0)
+ mdepth++;
+ else if (hi.collection == 1 &&
+ hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
+ mdepth++;
+ break;
+ case hid_endcollection:
+ if (mdepth != 0)
+ mdepth--;
+ break;
+ case hid_input:
+ if (mdepth == 0)
+ break;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
+ (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+ found++;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
+ (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+ found++;
+ break;
+ default:
+ break;
+ }
+ }
+ hid_end_parse(hd);
+ return (found);
+}
+
+/*------------------------------------------------------------------------*
+ * hid_is_keyboard
+ *
+ * This function will decide if a USB descriptor belongs to a USB keyboard.
+ *
+ * Return values:
+ * Zero: Not a USB keyboard.
+ * Else: Is a USB keyboard.
+ *------------------------------------------------------------------------*/
+int
+hid_is_keyboard(const void *d_ptr, uint16_t d_len)
+{
+ if (hid_is_collection(d_ptr, d_len,
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
+ return (1);
+ return (0);
+}
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index e3a673d..5e372c8 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -30,6 +30,9 @@
* USB spec: http://www.usb.org/developers/docs/usbspec.zip
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -69,6 +72,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#define UHUB_INTR_INTERVAL 250 /* ms */
#define UHUB_N_TRANSFER 1
diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h
index 62edb99..1d9b223 100644
--- a/sys/dev/usb/usb_ioctl.h
+++ b/sys/dev/usb/usb_ioctl.h
@@ -29,12 +29,14 @@
#ifndef _USB_IOCTL_H_
#define _USB_IOCTL_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/ioccom.h>
/* Building "kdump" depends on these includes */
#include <dev/usb/usb_endian.h>
#include <dev/usb/usb.h>
+#endif
#define USB_DEVICE_NAME "usbctl"
#define USB_DEVICE_DIR "usb"
diff --git a/sys/dev/usb/usb_lookup.c b/sys/dev/usb/usb_lookup.c
index e03f9b6..f3dc551 100644
--- a/sys/dev/usb/usb_lookup.c
+++ b/sys/dev/usb/usb_lookup.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -47,6 +50,7 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*------------------------------------------------------------------------*
* usbd_lookup_id_by_info
@@ -174,7 +178,7 @@ usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id,
#define MFL_SIZE "0"
#endif
-#ifdef KLD_MODULE
+#if defined(KLD_MODULE) && (USB_HAVE_ID_SECTION != 0)
static const char __section("bus_autoconf_format") __used usb_id_format[] = {
/* Declare that three different sections use the same format */
diff --git a/sys/dev/usb/usb_mbuf.c b/sys/dev/usb/usb_mbuf.c
index 65b2a91..ff2f6da 100644
--- a/sys/dev/usb/usb_mbuf.c
+++ b/sys/dev/usb/usb_mbuf.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -47,6 +50,7 @@
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_dev.h>
#include <dev/usb/usb_mbuf.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*------------------------------------------------------------------------*
* usb_alloc_mbufs - allocate mbufs to an usbd interface queue
diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c
index c5e8f49..497e382 100644
--- a/sys/dev/usb/usb_msctest.c
+++ b/sys/dev/usb/usb_msctest.c
@@ -32,6 +32,9 @@
* mass storage quirks for not supported SCSI commands!
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -66,6 +69,7 @@
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/quirk/usb_quirk.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
ST_COMMAND,
diff --git a/sys/dev/usb/usb_parse.c b/sys/dev/usb/usb_parse.c
index 66ab5fa..d6e54ad 100644
--- a/sys/dev/usb/usb_parse.c
+++ b/sys/dev/usb/usb_parse.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -46,7 +49,7 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
-
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*------------------------------------------------------------------------*
* usb_desc_foreach
diff --git a/sys/dev/usb/usb_pci.h b/sys/dev/usb/usb_pci.h
index 071dfc3..6eebc55 100644
--- a/sys/dev/usb/usb_pci.h
+++ b/sys/dev/usb/usb_pci.h
@@ -31,9 +31,11 @@
* We don't want the following files included everywhere, that's why
* they are in a separate file.
*/
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <sys/rman.h>
+#endif
#endif /* _USB_PCI_H_ */
diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
index d9c8dac..98705eb 100644
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 1990, 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -32,8 +33,9 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
@@ -59,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_bus.h>
#include <dev/usb/usb_pf.h>
#include <dev/usb/usb_transfer.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
static void usbpf_init(void);
static void usbpf_uninit(void);
diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c
index c006f51..34314f4 100644
--- a/sys/dev/usb/usb_process.c
+++ b/sys/dev/usb/usb_process.c
@@ -26,6 +26,9 @@
#define USB_DEBUG_VAR usb_proc_debug
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -55,6 +58,7 @@
#include <sys/proc.h>
#include <sys/kthread.h>
#include <sys/sched.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#if (__FreeBSD_version < 700000)
#define thread_lock(td) mtx_lock_spin(&sched_lock)
diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h
index 23cf660..923f645 100644
--- a/sys/dev/usb/usb_process.h
+++ b/sys/dev/usb/usb_process.h
@@ -27,9 +27,11 @@
#ifndef _USB_PROCESS_H_
#define _USB_PROCESS_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/interrupt.h>
#include <sys/priority.h>
#include <sys/runq.h>
+#endif
/* defines */
#define USB_PRI_HIGH PI_SWI(SWI_NET)
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index ce50d9b..6a81945 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -26,6 +26,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -66,6 +69,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <sys/ctype.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
static int usb_no_cs_fail;
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 6e48a3e..397b0b7 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -61,6 +64,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/usb_pf.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
struct usb_std_packet_size {
struct {
diff --git a/sys/dev/usb/usb_util.c b/sys/dev/usb/usb_util.c
index 4fe79c5..f9fec76 100644
--- a/sys/dev/usb/usb_util.c
+++ b/sys/dev/usb/usb_util.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -56,6 +59,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*------------------------------------------------------------------------*
* device_set_usb_desc
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 0cd43ef..aff55fd 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -581,6 +581,7 @@ vendor CCYU 0x1065 CCYU Technology
vendor CURITEL 0x106c Curitel Communications Inc
vendor SILABS2 0x10a6 SILABS2
vendor USI 0x10ab USI
+vendor LIEBERT2 0x10af Liebert
vendor PLX 0x10b5 PLX
vendor ASANTE 0x10bd Asante
vendor SILABS 0x10c4 Silicon Labs
@@ -1486,6 +1487,7 @@ product DIGIANSWER ZIGBEE802154 0x000a ZigBee/802.15.4 MAC
/* D-Link products */
/*product DLINK DSBS25 0x0100 DSB-S25 serial*/
product DLINK DUBE100 0x1a00 10/100 Ethernet
+product DLINK DUBE100C1 0x1a02 DUB-E100 rev C1
product DLINK DSB650TX4 0x200c 10/100 Ethernet
product DLINK DWL120E 0x3200 DWL-120 rev E
product DLINK DWL122 0x3700 DWL-122
@@ -2426,6 +2428,7 @@ product LEXMARK S2450 0x0009 Optra S 2450
/* Liebert products */
product LIEBERT POWERSURE_PXT 0xffff PowerSure Personal XT
+product LIEBERT2 PSI1000 0x0004 UPS PSI 1000 FW:08
/* Link Instruments Inc. products */
product LINKINSTRUMENTS MSO19 0xf190 Link Instruments MSO-19
@@ -2939,6 +2942,7 @@ product MOTOROLA2 A41XV32X 0x2a22 A41x/V32x Mobile Phones
product MOTOROLA2 E398 0x4810 E398 Mobile Phone
product MOTOROLA2 USBLAN 0x600c USBLAN
product MOTOROLA2 USBLAN2 0x6027 USBLAN
+product MOTOROLA2 MB886 0x710f MB886 Mobile Phone (Atria HD)
product MOTOROLA4 RT2770 0x9031 RT2770
product MOTOROLA4 RT3070 0x9032 RT3070
@@ -3560,6 +3564,7 @@ product SANDISK SDDR75 0x0810 ImageMate SDDR-75
product SANDISK SDCZ2_256 0x7104 Cruzer Mini 256MB
product SANDISK SDCZ4_128 0x7112 Cruzer Micro 128MB
product SANDISK SDCZ4_256 0x7113 Cruzer Micro 256MB
+product SANDISK IMAGEMATE_SDDR289 0xb6ba ImageMate SDDR-289
/* Sanwa Electric Instrument Co., Ltd. products */
product SANWA KB_USB2 0x0701 KB-USB2 multimeter cable
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index d753fe1..26f7769 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -102,7 +102,9 @@ typedef void (usb_fifo_filter_t)(struct usb_fifo *fifo, struct usb_mbuf *m);
/* USB events */
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/eventhandler.h>
+#endif
typedef void (*usb_dev_configured_t)(void *, struct usb_device *,
struct usb_attach_arg *);
EVENTHANDLER_DECLARE(usb_dev_configured, usb_dev_configured_t);
@@ -239,12 +241,21 @@ struct usb_config {
* have your driver module automatically loaded in host, device or
* both modes respectivly:
*/
+#if USB_HAVE_ID_SECTION
#define STRUCT_USB_HOST_ID \
struct usb_device_id __section("usb_host_id")
#define STRUCT_USB_DEVICE_ID \
struct usb_device_id __section("usb_device_id")
#define STRUCT_USB_DUAL_ID \
struct usb_device_id __section("usb_dual_id")
+#else
+#define STRUCT_USB_HOST_ID \
+ struct usb_device_id
+#define STRUCT_USB_DEVICE_ID \
+ struct usb_device_id
+#define STRUCT_USB_DUAL_ID \
+ struct usb_device_id
+#endif /* USB_HAVE_ID_SECTION */
/*
* The following structure is used when looking up an USB driver for
diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h
index f40232a..28dfede 100644
--- a/sys/dev/usb/usbhid.h
+++ b/sys/dev/usb/usbhid.h
@@ -29,7 +29,9 @@
#ifndef _USB_HID_H_
#define _USB_HID_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <dev/usb/usb_endian.h>
+#endif
#define UR_GET_HID_DESCRIPTOR 0x06
#define UDESC_HID 0x21
@@ -242,5 +244,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb(
usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
void **descp, uint16_t *sizep, struct malloc_type *mem,
uint8_t iface_index);
+int hid_is_mouse(const void *d_ptr, uint16_t d_len);
+int hid_is_keyboard(const void *d_ptr, uint16_t d_len);
#endif /* _KERNEL */
#endif /* _USB_HID_H_ */
diff --git a/sys/dev/vx/if_vx_eisa.c b/sys/dev/vx/if_vx_eisa.c
index 80fb5c6..24dc2dd 100644
--- a/sys/dev/vx/if_vx_eisa.c
+++ b/sys/dev/vx/if_vx_eisa.c
@@ -177,7 +177,7 @@ static device_method_t vx_eisa_methods[] = {
DEVMETHOD(device_probe, vx_eisa_probe),
DEVMETHOD(device_attach, vx_eisa_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t vx_eisa_driver = {
diff --git a/sys/dev/vx/if_vx_pci.c b/sys/dev/vx/if_vx_pci.c
index 0412778..38037fa 100644
--- a/sys/dev/vx/if_vx_pci.c
+++ b/sys/dev/vx/if_vx_pci.c
@@ -61,7 +61,7 @@ static device_method_t vx_methods[] = {
DEVMETHOD(device_attach, vx_pci_attach),
DEVMETHOD(device_shutdown, vx_pci_shutdown),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t vx_driver = {
diff --git a/sys/dev/vxge/vxge.c b/sys/dev/vxge/vxge.c
index c35d84b..3650843 100644
--- a/sys/dev/vxge/vxge.c
+++ b/sys/dev/vxge/vxge.c
@@ -4188,7 +4188,8 @@ static device_method_t vxge_methods[] = {
DEVMETHOD(device_attach, vxge_attach),
DEVMETHOD(device_detach, vxge_detach),
DEVMETHOD(device_shutdown, vxge_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t vxge_driver = {
diff --git a/sys/dev/wbwd/wbwd.c b/sys/dev/wbwd/wbwd.c
index dfd8f3c..484b5bf 100644
--- a/sys/dev/wbwd/wbwd.c
+++ b/sys/dev/wbwd/wbwd.c
@@ -179,6 +179,12 @@ struct winbond_vendor_device_id {
.device_rev = 0x73,
.descr = "Winbond 83627DHG-P",
},
+ {
+ .vendor_id = 0x5ca3,
+ .device_id = 0xc3,
+ .device_rev = 0x33,
+ .descr = "Nuvoton WPCM450RA0BX",
+ },
};
static void
@@ -596,6 +602,9 @@ wb_probe_enable(device_t dev, int probe)
goto cleanup;
}
+ if (dev_id == 0xff && dev_rev == 0xff)
+ goto cleanup;
+
for (j = 0; j < sizeof(wb_devs) / sizeof(*wb_devs); j++) {
if (wb_devs[j].device_id == dev_id &&
wb_devs[j].device_rev == dev_rev) {
@@ -605,6 +614,16 @@ wb_probe_enable(device_t dev, int probe)
break;
}
}
+
+ if (!found) {
+ if (probe && dev != NULL) {
+ device_set_desc(dev, "Unknown Winbond/Nuvoton model");
+ device_printf(dev, "DevID 0x%02x DevRev 0x%02x, "
+ "please report this.\n", dev_id, dev_rev);
+ }
+ found++;
+ }
+
if (probe && found && bootverbose && dev != NULL)
device_printf(dev, "%s EFER 0x%02x ID 0x%02x Rev 0x%02x"
" CR26 0x%02x (probing)\n", device_get_desc(dev),
diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c
index 6a845ca..6281bf2 100644
--- a/sys/dev/xen/console/console.c
+++ b/sys/dev/xen/console/console.c
@@ -410,7 +410,8 @@ static device_method_t xc_methods[] = {
DEVMETHOD(device_identify, xc_identify),
DEVMETHOD(device_probe, xc_probe),
DEVMETHOD(device_attach, xc_attach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t xc_driver = {
diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c
index a701087..cafd32d 100644
--- a/sys/fs/ext2fs/ext2_alloc.c
+++ b/sys/fs/ext2fs/ext2_alloc.c
@@ -151,11 +151,11 @@ nospace:
static SYSCTL_NODE(_vfs, OID_AUTO, ext2fs, CTLFLAG_RW, 0, "EXT2FS filesystem");
-static int doasyncfree = 1;
+static int doasyncfree = 0;
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0,
"Use asychronous writes to update block pointers when freeing blocks");
-static int doreallocblks = 1;
+static int doreallocblks = 0;
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, "");
int
@@ -169,7 +169,7 @@ ext2_reallocblks(ap)
struct inode *ip;
struct vnode *vp;
struct buf *sbp, *ebp;
- int32_t *bap, *sbap, *ebap = 0;
+ uint32_t *bap, *sbap, *ebap = 0;
struct ext2mount *ump;
struct cluster_save *buflist;
struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
@@ -242,7 +242,7 @@ ext2_reallocblks(ap)
} else {
#ifdef DIAGNOSTIC
if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
- panic("ext2_reallocblk: start == end");
+ panic("ext2_reallocblks: start == end");
#endif
ssize = len - (idp->in_off + 1);
if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &ebp))
@@ -1004,7 +1004,7 @@ ext2_blkfree(ip, bno, size)
if (isclr(bbp, bno)) {
printf("block = %lld, fs = %s\n",
(long long)bno, fs->e2fs_fsmnt);
- panic("blkfree: freeing free block");
+ panic("ext2_blkfree: freeing free block");
}
clrbit(bbp, bno);
EXT2_LOCK(ump);
@@ -1032,7 +1032,6 @@ ext2_vfree(pvp, ino, mode)
struct ext2mount *ump;
int error, cg;
char * ibp;
-/* mode_t save_i_mode; */
pip = VTOI(pvp);
fs = pip->i_e2fs;
@@ -1055,7 +1054,7 @@ ext2_vfree(pvp, ino, mode)
printf("ino = %llu, fs = %s\n",
(unsigned long long)ino, fs->e2fs_fsmnt);
if (fs->e2fs_ronly == 0)
- panic("ifree: freeing free inode");
+ panic("ext2_vfree: freeing free inode");
}
clrbit(ibp, ino);
EXT2_LOCK(ump);
@@ -1100,7 +1099,7 @@ ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref)
if (loc == NULL) {
printf("start = %d, len = %d, fs = %s\n",
start, len, fs->e2fs_fsmnt);
- panic("ext2fs_alloccg: map corrupted");
+ panic("ext2_mapsearch: map corrupted");
/* NOTREACHED */
}
}
diff --git a/sys/fs/ext2fs/ext2_balloc.c b/sys/fs/ext2fs/ext2_balloc.c
index 6e60c6e..1861f69 100644
--- a/sys/fs/ext2fs/ext2_balloc.c
+++ b/sys/fs/ext2fs/ext2_balloc.c
@@ -69,7 +69,7 @@ ext2_balloc(ip, lbn, size, cred, bpp, flags)
struct buf *bp, *nbp;
struct vnode *vp = ITOV(ip);
struct indir indirs[NIADDR + 2];
- int32_t newb, *bap, pref;
+ uint32_t newb, *bap, pref;
int osize, nsize, num, i, error;
*bpp = NULL;
diff --git a/sys/fs/ext2fs/ext2_dinode.h b/sys/fs/ext2fs/ext2_dinode.h
index 7d97bb8..7d97bb8 100755..100644
--- a/sys/fs/ext2fs/ext2_dinode.h
+++ b/sys/fs/ext2fs/ext2_dinode.h
diff --git a/sys/fs/ext2fs/ext2_dir.h b/sys/fs/ext2fs/ext2_dir.h
index 5e11166..2bad4cd 100755..100644
--- a/sys/fs/ext2fs/ext2_dir.h
+++ b/sys/fs/ext2fs/ext2_dir.h
@@ -37,7 +37,7 @@
struct ext2fs_direct {
uint32_t e2d_ino; /* inode number of entry */
uint16_t e2d_reclen; /* length of this record */
- uint16_t e2d_namlen; /* length of string in d_name */
+ uint16_t e2d_namlen; /* length of string in e2d_name */
char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */
};
/*
@@ -49,7 +49,7 @@ struct ext2fs_direct {
struct ext2fs_direct_2 {
uint32_t e2d_ino; /* inode number of entry */
uint16_t e2d_reclen; /* length of this record */
- uint8_t e2d_namlen; /* length of string in d_name */
+ uint8_t e2d_namlen; /* length of string in e2d_name */
uint8_t e2d_type; /* file type */
char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */
};
diff --git a/sys/fs/ext2fs/ext2_inode.c b/sys/fs/ext2fs/ext2_inode.c
index e7fc9a8..fe9b50d 100644
--- a/sys/fs/ext2fs/ext2_inode.c
+++ b/sys/fs/ext2fs/ext2_inode.c
@@ -119,7 +119,7 @@ ext2_truncate(vp, length, flags, cred, td)
int32_t lastblock;
struct inode *oip;
int32_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
- int32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
+ uint32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
struct bufobj *bo;
struct m_ext2fs *fs;
struct buf *bp;
@@ -180,7 +180,7 @@ ext2_truncate(vp, length, flags, cred, td)
else
bawrite(bp);
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (ext2_update(ovp, 1));
+ return (ext2_update(ovp, !DOINGASYNC(ovp)));
}
/*
* Shorten the size of the file. If the file is not being
@@ -238,7 +238,7 @@ ext2_truncate(vp, length, flags, cred, td)
for (i = NDADDR - 1; i > lastblock; i--)
oip->i_db[i] = 0;
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- allerror = ext2_update(ovp, 1);
+ allerror = ext2_update(ovp, !DOINGASYNC(ovp));
/*
* Having written the new inode to disk, save its new configuration
@@ -311,7 +311,7 @@ ext2_truncate(vp, length, flags, cred, td)
oip->i_size = length;
newspace = blksize(fs, oip, lastblock);
if (newspace == 0)
- panic("itrunc: newspace");
+ panic("ext2_truncate: newspace");
if (oldspace - newspace > 0) {
/*
* Block number of space to be free'd is
@@ -341,8 +341,9 @@ done:
* Put back the real size.
*/
oip->i_size = length;
- oip->i_blocks -= blocksreleased;
- if (oip->i_blocks < 0) /* sanity */
+ if (oip->i_blocks >= blocksreleased)
+ oip->i_blocks -= blocksreleased;
+ else /* sanity */
oip->i_blocks = 0;
oip->i_flag |= IN_CHANGE;
vnode_pager_setsize(ovp, length);
@@ -420,9 +421,13 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
(u_int)(NINDIR(fs) - (last + 1)) * sizeof(int32_t));
if (last == -1)
bp->b_flags |= B_INVAL;
- error = bwrite(bp);
- if (error)
- allerror = error;
+ if (DOINGASYNC(vp)) {
+ bdwrite(bp);
+ } else {
+ error = bwrite(bp);
+ if (error)
+ allerror = error;
+ }
bap = copy;
/*
diff --git a/sys/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c
index c279998..9aadb6a 100644
--- a/sys/fs/ext2fs/ext2_lookup.c
+++ b/sys/fs/ext2fs/ext2_lookup.c
@@ -812,7 +812,7 @@ ext2_direnter(ip, dvp, cnp)
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & SAVENAME) == 0)
- panic("direnter: missing name");
+ panic("ext2_direnter: missing name");
#endif
dp = VTOI(dvp);
newdir.e2d_ino = ip->i_number;
diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c
index 3f181fd..136f01c 100644
--- a/sys/fs/ext2fs/ext2_vfsops.c
+++ b/sys/fs/ext2fs/ext2_vfsops.c
@@ -127,7 +127,7 @@ ext2_mount(struct mount *mp)
vfs_getopt(opts, "fspath", (void **)&path, NULL);
/* Double-check the length of path.. */
- if (strlen(path) >= MAXMNTLEN - 1)
+ if (strlen(path) >= MAXMNTLEN)
return (ENAMETOOLONG);
fspec = NULL;
@@ -318,12 +318,12 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
int i;
int logic_sb_block = 1; /* XXX for now */
struct buf *bp;
+ uint32_t e2fs_descpb;
fs->e2fs_bsize = EXT2_MIN_BLOCK_SIZE << es->e2fs_log_bsize;
fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize;
fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1;
fs->e2fs_qbmask = fs->e2fs_bsize - 1;
- fs->e2fs_blocksize_bits = es->e2fs_log_bsize + 10;
fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize;
if (fs->e2fs_fsize)
fs->e2fs_fpb = fs->e2fs_bsize / fs->e2fs_fsize;
@@ -331,10 +331,8 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
fs->e2fs_fpg = es->e2fs_fpg;
fs->e2fs_ipg = es->e2fs_ipg;
if (es->e2fs_rev == E2FS_REV0) {
- fs->e2fs_first_inode = EXT2_FIRSTINO;
fs->e2fs_isize = E2FS_REV0_INODE_SIZE ;
} else {
- fs->e2fs_first_inode = es->e2fs_first_ino;
fs->e2fs_isize = es->e2fs_inode_size;
/*
@@ -357,12 +355,11 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
fs->e2fs_itpg = fs->e2fs_ipg /fs->e2fs_ipb;
- fs->e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
/* s_resuid / s_resgid ? */
fs->e2fs_gcount = (es->e2fs_bcount - es->e2fs_first_dblock +
EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs);
- db_count = (fs->e2fs_gcount + EXT2_DESC_PER_BLOCK(fs) - 1) /
- EXT2_DESC_PER_BLOCK(fs);
+ e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
+ db_count = (fs->e2fs_gcount + e2fs_descpb - 1) / e2fs_descpb;
fs->e2fs_gdbcount = db_count;
fs->e2fs_gd = malloc(db_count * fs->e2fs_bsize,
M_EXT2MNT, M_WAITOK);
@@ -766,7 +763,7 @@ ext2_statfs(struct mount *mp, struct statfs *sbp)
ump = VFSTOEXT2(mp);
fs = ump->um_e2fs;
if (fs->e2fs->e2fs_magic != E2FS_MAGIC)
- panic("ext2fs_statfs");
+ panic("ext2_statfs");
/*
* Compute the overhead (FS structures)
diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h
index 5cafc7b..c5a4c15 100755..100644
--- a/sys/fs/ext2fs/ext2fs.h
+++ b/sys/fs/ext2fs/ext2fs.h
@@ -153,7 +153,6 @@ struct m_ext2fs {
char e2fs_fmod; /* super block modified flag */
uint32_t e2fs_bsize; /* Block size */
uint32_t e2fs_bshift; /* calc of logical block no */
- int32_t e2fs_bmask; /* calc of block offset */
int32_t e2fs_bpg; /* Number of blocks per group */
int64_t e2fs_qbmask; /* = s_blocksize -1 */
uint32_t e2fs_fsbtodb; /* Shift to get disk block */
@@ -163,14 +162,9 @@ struct m_ext2fs {
uint32_t e2fs_fsize; /* Size of fragments per block */
uint32_t e2fs_fpb; /* Number of fragments per block */
uint32_t e2fs_fpg; /* Number of fragments per group */
- uint32_t e2fs_dbpg; /* Number of descriptor blocks per group */
- uint32_t e2fs_descpb; /* Number of group descriptors per block */
uint32_t e2fs_gdbcount; /* Number of group descriptors */
uint32_t e2fs_gcount; /* Number of groups */
- uint32_t e2fs_first_inode;/* First inode on fs */
int32_t e2fs_isize; /* Size of inode */
- uint32_t e2fs_mount_opt;
- uint32_t e2fs_blocksize_bits;
uint32_t e2fs_total_dir; /* Total number of directories */
uint8_t *e2fs_contigdirs; /* (u) # of contig. allocated dirs */
char e2fs_wasvalid; /* valid at mount time */
@@ -313,27 +307,9 @@ struct csum {
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
-#if defined(_KERNEL)
-# define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize)
-#else
-# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->e2fs_log_bsize)
-#endif
+#define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize)
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(uint32_t))
-#if defined(_KERNEL)
-# define EXT2_BLOCK_SIZE_BITS(s) ((s)->e2fs_blocksize_bits)
-#else
-# define EXT2_BLOCK_SIZE_BITS(s) ((s)->e2fs_log_bsize + 10)
-#endif
-#if defined(_KERNEL)
-#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_addr_per_block_bits)
#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->e2fs_isize)
-#define EXT2_FIRST_INO(s) (EXT2_SB(s)->e2fs_first_inode)
-#else
-#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == E2FS_REV0) ? \
- E2FS_REV0 : (s)->s_inode_size)
-#define EXT2_FIRST_INO(s) (((s)->s_rev_level == E2FS_REV0) ? \
- E2FS_REV0 : (s)->e2fs_first_ino)
-#endif
/*
* Macro-instructions used to manage fragments
@@ -341,25 +317,12 @@ struct csum {
#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 4096
#define EXT2_MIN_FRAG_LOG_SIZE 10
-#if defined(_KERNEL)
-# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->e2fs_fsize)
-# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->e2fs_fpb)
-#else
-# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->e2fs_log_fsize)
-# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
-#endif
+#define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->e2fs_fsize)
+#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->e2fs_fpb)
/*
* Macro-instructions used to manage group descriptors
*/
-#if defined(_KERNEL)
-# define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg)
-# define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->e2fs_descpb)
-# define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits)
-#else
-# define EXT2_BLOCKS_PER_GROUP(s) ((s)->e2fs_bpg)
-# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(struct ext2_gd))
-
-#endif
+#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg)
#endif /* !_FS_EXT2FS_EXT2FS_H_ */
diff --git a/sys/fs/ext2fs/fs.h b/sys/fs/ext2fs/fs.h
index 880c500..7068e79 100644
--- a/sys/fs/ext2fs/fs.h
+++ b/sys/fs/ext2fs/fs.h
@@ -149,7 +149,4 @@
*/
#define NINDIR(fs) (EXT2_ADDR_PER_BLOCK(fs))
-extern int inside[], around[];
-extern u_char *fragtbl[];
-
#endif /* !_FS_EXT2FS_FS_H_ */
diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h
index d8aaac9..ec47216 100644
--- a/sys/fs/ext2fs/inode.h
+++ b/sys/fs/ext2fs/inode.h
@@ -90,11 +90,11 @@ struct inode {
int32_t i_atimensec; /* Last access time. */
int32_t i_ctimensec; /* Last inode change time. */
int32_t i_birthnsec; /* Inode creation time. */
- int32_t i_db[NDADDR]; /* Direct disk blocks. */
- int32_t i_ib[NIADDR]; /* Indirect disk blocks. */
+ uint32_t i_db[NDADDR]; /* Direct disk blocks. */
+ uint32_t i_ib[NIADDR]; /* Indirect disk blocks. */
uint32_t i_flags; /* Status flags (chflags). */
- int32_t i_blocks; /* Blocks actually held. */
- int32_t i_gen; /* Generation number. */
+ uint32_t i_blocks; /* Blocks actually held. */
+ uint32_t i_gen; /* Generation number. */
uint32_t i_uid; /* File owner. */
uint32_t i_gid; /* File group. */
};
@@ -162,7 +162,7 @@ struct ufid {
uint16_t ufid_len; /* Length of structure. */
uint16_t ufid_pad; /* Force 32-bit alignment. */
ino_t ufid_ino; /* File number (ino). */
- int32_t ufid_gen; /* Generation number. */
+ uint32_t ufid_gen; /* Generation number. */
};
#endif /* _KERNEL */
diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c
index 0b1899f..3994042 100644
--- a/sys/fs/msdosfs/msdosfs_fat.c
+++ b/sys/fs/msdosfs/msdosfs_fat.c
@@ -321,8 +321,8 @@ updatefats(pmp, bp, fatbn)
struct buf *bp;
u_long fatbn;
{
- int i;
struct buf *bpn;
+ int cleanfat, i;
#ifdef MSDOSFS_DEBUG
printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn);
@@ -362,13 +362,24 @@ updatefats(pmp, bp, fatbn)
* filesystem was mounted. If synch is asked for then use
* bwrite()'s and really slow things down.
*/
+ if (fatbn != pmp->pm_fatblk || FAT12(pmp))
+ cleanfat = 0;
+ else if (FAT16(pmp))
+ cleanfat = 16;
+ else
+ cleanfat = 32;
for (i = 1; i < pmp->pm_FATs; i++) {
fatbn += pmp->pm_FATsecs;
/* getblk() never fails */
bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount,
0, 0, 0);
bcopy(bp->b_data, bpn->b_data, bp->b_bcount);
- if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
+ /* Force the clean bit on in the other copies. */
+ if (cleanfat == 16)
+ ((u_int8_t *)bpn->b_data)[3] |= 0x80;
+ else if (cleanfat == 32)
+ ((u_int8_t *)bpn->b_data)[7] |= 0x08;
+ if (pmp->pm_mountp->mnt_flag & MNT_SYNCHRONOUS)
bwrite(bpn);
else
bdwrite(bpn);
@@ -378,7 +389,7 @@ updatefats(pmp, bp, fatbn)
/*
* Write out the first (or current) fat last.
*/
- if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
+ if (pmp->pm_mountp->mnt_flag & MNT_SYNCHRONOUS)
bwrite(bp);
else
bdwrite(bp);
@@ -1114,7 +1125,7 @@ extendfile(dep, count, bpp, ncp, flags)
* Routine to mark a FAT16 or FAT32 volume as "clean" or "dirty" by
* manipulating the upper bit of the FAT entry for cluster 1. Note that
* this bit is not defined for FAT12 volumes, which are always assumed to
- * be dirty.
+ * be clean.
*
* The fatentry() routine only works on cluster numbers that a file could
* occupy, so it won't manipulate the entry for cluster 1. So we have to do
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index e99fff3..a209970 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -553,8 +553,7 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp)
}
if (pmp->pm_RootDirEnts == 0) {
- if (pmp->pm_Sectors
- || pmp->pm_FATsecs
+ if (pmp->pm_FATsecs
|| getushort(b710->bpbFSVers)) {
error = EINVAL;
#ifdef MSDOSFS_DEBUG
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index a90ee8d..8e045cb 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -973,7 +973,7 @@ msdosfs_rename(ap)
u_char to_count;
int doingdirectory = 0, newparent = 0;
int error;
- u_long cn;
+ u_long cn, pcl;
daddr_t bn;
struct denode *fddep; /* from file's parent directory */
struct msdosfsmount *pmp;
@@ -1246,9 +1246,12 @@ abortit:
goto bad;
}
dotdotp = (struct direntry *)bp->b_data + 1;
- putushort(dotdotp->deStartCluster, dp->de_StartCluster);
+ pcl = dp->de_StartCluster;
+ if (FAT32(pmp) && pcl == pmp->pm_rootdirblk)
+ pcl = MSDOSFSROOT;
+ putushort(dotdotp->deStartCluster, pcl);
if (FAT32(pmp))
- putushort(dotdotp->deHighClust, dp->de_StartCluster >> 16);
+ putushort(dotdotp->deHighClust, pcl >> 16);
if (DOINGASYNC(fvp))
bdwrite(bp);
else if ((error = bwrite(bp)) != 0) {
@@ -1369,8 +1372,13 @@ msdosfs_mkdir(ap)
putushort(denp[0].deMDate, ndirent.de_MDate);
putushort(denp[0].deMTime, ndirent.de_MTime);
pcl = pdep->de_StartCluster;
+ /*
+ * Although the root directory has a non-magic starting cluster
+ * number for FAT32, chkdsk and fsck_msdosfs still require
+ * references to it in dotdot entries to be magic.
+ */
if (FAT32(pmp) && pcl == pmp->pm_rootdirblk)
- pcl = 0;
+ pcl = MSDOSFSROOT;
putushort(denp[1].deStartCluster, pcl);
putushort(denp[1].deCDate, ndirent.de_CDate);
putushort(denp[1].deCTime, ndirent.de_CTime);
@@ -1380,7 +1388,7 @@ msdosfs_mkdir(ap)
putushort(denp[1].deMTime, ndirent.de_MTime);
if (FAT32(pmp)) {
putushort(denp[0].deHighClust, newcluster >> 16);
- putushort(denp[1].deHighClust, pdep->de_StartCluster >> 16);
+ putushort(denp[1].deHighClust, pcl >> 16);
}
if (DOINGASYNC(ap->a_dvp))
diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h
index 3cc8c8f..febb631 100644
--- a/sys/fs/nfs/nfs.h
+++ b/sys/fs/nfs/nfs.h
@@ -523,7 +523,6 @@ struct nfsrv_descript {
int *nd_errp; /* Pointer to ret status */
u_int32_t nd_retxid; /* Reply xid */
struct nfsrvcache *nd_rp; /* Assoc. cache entry */
- struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred *nd_cred; /* Credentials */
uid_t nd_saveduid; /* Saved uid */
diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c
index 6640c1f..23d8954 100644
--- a/sys/fs/nfs/nfs_commonkrpc.c
+++ b/sys/fs/nfs/nfs_commonkrpc.c
@@ -459,18 +459,17 @@ nfs_feedback(int type, int proc, void *arg)
{
struct nfs_feedback_arg *nf = (struct nfs_feedback_arg *) arg;
struct nfsmount *nmp = nf->nf_mount;
- struct timeval now;
-
- getmicrouptime(&now);
+ time_t now;
switch (type) {
case FEEDBACK_REXMIT2:
case FEEDBACK_RECONNECT:
- if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now.tv_sec) {
+ now = NFSD_MONOSEC;
+ if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now) {
nfs_down(nmp, nf->nf_td,
"not responding", 0, NFSSTA_TIMEO);
nf->nf_tprintfmsg = TRUE;
- nf->nf_lastmsg = now.tv_sec;
+ nf->nf_lastmsg = now;
}
break;
@@ -501,7 +500,7 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
u_int16_t procnum;
u_int trylater_delay = 1;
struct nfs_feedback_arg nf;
- struct timeval timo, now;
+ struct timeval timo;
AUTH *auth;
struct rpc_callextra ext;
enum clnt_stat stat;
@@ -617,8 +616,7 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
bzero(&nf, sizeof(struct nfs_feedback_arg));
nf.nf_mount = nmp;
nf.nf_td = td;
- getmicrouptime(&now);
- nf.nf_lastmsg = now.tv_sec -
+ nf.nf_lastmsg = NFSD_MONOSEC -
((nmp->nm_tprintf_delay)-(nmp->nm_tprintf_initial_delay));
}
@@ -767,12 +765,18 @@ tryagain:
if (stat == RPC_SUCCESS) {
error = 0;
} else if (stat == RPC_TIMEDOUT) {
+ NFSINCRGLOBAL(newnfsstats.rpctimeouts);
error = ETIMEDOUT;
} else if (stat == RPC_VERSMISMATCH) {
+ NFSINCRGLOBAL(newnfsstats.rpcinvalid);
error = EOPNOTSUPP;
} else if (stat == RPC_PROGVERSMISMATCH) {
+ NFSINCRGLOBAL(newnfsstats.rpcinvalid);
error = EPROTONOSUPPORT;
+ } else if (stat == RPC_INTR) {
+ error = EINTR;
} else {
+ NFSINCRGLOBAL(newnfsstats.rpcinvalid);
error = EACCES;
}
if (error) {
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 95aa7bd..b2d74c7 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -218,6 +218,7 @@ nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
}
mbufcp = NFSMTOD(mp, caddr_t);
len = mbuf_len(mp);
+ KASSERT(len > 0, ("len %d", len));
}
xfer = (left > len) ? len : left;
#ifdef notdef
@@ -1998,7 +1999,6 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
struct statfs fs;
struct nfsfsinfo fsinf;
struct timespec temptime;
- struct timeval curtime;
NFSACL_T *aclp, *naclp = NULL;
#ifdef QUOTA
struct dqblk dqb;
@@ -2412,8 +2412,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
retnum += NFSX_V4TIME;
break;
case NFSATTRBIT_TIMEACCESSSET:
- NFSGETTIME(&curtime);
- if (vap->va_atime.tv_sec != curtime.tv_sec) {
+ if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
*tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
txdr_nfsv4time(&vap->va_atime, tl);
@@ -2442,8 +2441,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
retnum += NFSX_V4TIME;
break;
case NFSATTRBIT_TIMEMODIFYSET:
- NFSGETTIME(&curtime);
- if (vap->va_mtime.tv_sec != curtime.tv_sec) {
+ if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
*tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
txdr_nfsv4time(&vap->va_mtime, tl);
diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h
index 3f22b7a..ea04525 100644
--- a/sys/fs/nfs/nfsport.h
+++ b/sys/fs/nfs/nfsport.h
@@ -588,12 +588,6 @@ void nfsrvd_rcv(struct socket *, void *, int);
#define NCHNAMLEN 9999999
/*
- * Define these to use the time of day clock.
- */
-#define NFSGETTIME(t) (getmicrotime(t))
-#define NFSGETNANOTIME(t) (getnanotime(t))
-
-/*
* These macros are defined to initialize and set the timer routine.
*/
#define NFS_TIMERINIT \
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 145ff63..1179eb5 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -726,7 +726,6 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
u_int32_t *tl;
struct nfsv2_sattr *sp;
nfsattrbit_t attrbits;
- struct timeval curtime;
switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
case ND_NFSV2:
@@ -755,7 +754,6 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
break;
case ND_NFSV3:
- getmicrotime(&curtime);
if (vap->va_mode != (mode_t)VNOVAL) {
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
*tl++ = newnfs_true;
@@ -789,7 +787,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
*tl = newnfs_false;
}
if (vap->va_atime.tv_sec != VNOVAL) {
- if (vap->va_atime.tv_sec != curtime.tv_sec) {
+ if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
txdr_nfsv3time(&vap->va_atime, tl);
@@ -802,7 +800,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
*tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
}
if (vap->va_mtime.tv_sec != VNOVAL) {
- if (vap->va_mtime.tv_sec != curtime.tv_sec) {
+ if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
txdr_nfsv3time(&vap->va_mtime, tl);
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index be0476a..a89b907 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -1444,7 +1444,7 @@ nfsrpc_readrpc(vnode_t vp, struct uio *uiop, struct ucred *cred,
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
eof = fxdr_unsigned(int, *tl);
}
- NFSM_STRSIZ(retlen, rsize);
+ NFSM_STRSIZ(retlen, len);
error = nfsm_mbufuio(nd, uiop, retlen);
if (error)
goto nfsmout;
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c
index 8b5acb9..a774103 100644
--- a/sys/fs/nfsclient/nfs_clstate.c
+++ b/sys/fs/nfsclient/nfs_clstate.c
@@ -2447,7 +2447,7 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p)
u_int32_t clidrev;
int error, cbpathdown, islept, igotlock, ret, clearok;
uint32_t recover_done_time = 0;
- struct timespec mytime;
+ time_t mytime;
static time_t prevsec = 0;
struct nfscllockownerfh *lfhp, *nlfhp;
struct nfscllockownerfhhead lfh;
@@ -2720,9 +2720,9 @@ tryagain2:
* Call nfscl_cleanupkext() once per second to check for
* open/lock owners where the process has exited.
*/
- NFSGETNANOTIME(&mytime);
- if (prevsec != mytime.tv_sec) {
- prevsec = mytime.tv_sec;
+ mytime = NFSD_MONOSEC;
+ if (prevsec != mytime) {
+ prevsec = mytime;
nfscl_cleanupkext(clp, &lfh);
}
@@ -4611,7 +4611,7 @@ nfscl_delegmodtime(vnode_t vp)
}
dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_WRITE)) {
- NFSGETNANOTIME(&dp->nfsdl_modtime);
+ nanotime(&dp->nfsdl_modtime);
dp->nfsdl_flags |= NFSCLDL_MODTIMESET;
}
NFSUNLOCKCLSTATE();
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 3a898f2..f778009 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -3247,7 +3247,7 @@ nfsfifo_read(struct vop_read_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_flag |= NACC;
- getnanotime(&np->n_atim);
+ vfs_timestamp(&np->n_atim);
mtx_unlock(&np->n_mtx);
error = fifo_specops.vop_read(ap);
return error;
@@ -3266,7 +3266,7 @@ nfsfifo_write(struct vop_write_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_flag |= NUPD;
- getnanotime(&np->n_mtim);
+ vfs_timestamp(&np->n_mtim);
mtx_unlock(&np->n_mtx);
return(fifo_specops.vop_write(ap));
}
@@ -3286,7 +3286,7 @@ nfsfifo_close(struct vop_close_args *ap)
mtx_lock(&np->n_mtx);
if (np->n_flag & (NACC | NUPD)) {
- getnanotime(&ts);
+ vfs_timestamp(&ts);
if (np->n_flag & NACC)
np->n_atim = ts;
if (np->n_flag & NUPD)
diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c
index 337951b..cffb46f 100644
--- a/sys/fs/nfsserver/nfs_nfsdkrpc.c
+++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c
@@ -310,7 +310,6 @@ nfs_proc(struct nfsrv_descript *nd, u_int32_t xid, struct socket *so,
} else {
isdgram = 1;
}
- NFSGETTIME(&nd->nd_starttime);
/*
* Two cases:
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index f56a292..1731c72 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -1476,7 +1476,7 @@ nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap,
struct vattr va;
VATTR_NULL(&va);
- getnanotime(&va.va_mtime);
+ vfs_timestamp(&va.va_mtime);
(void) VOP_SETATTR(vp, &va, cred);
(void) nfsvno_getattr(vp, nvap, cred, p, 1);
}
@@ -2248,7 +2248,6 @@ nfsrv_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
{
u_int32_t *tl;
struct nfsv2_sattr *sp;
- struct timeval curtime;
int error = 0, toclient = 0;
switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
@@ -2307,9 +2306,7 @@ nfsrv_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
toclient = 1;
break;
case NFSV3SATTRTIME_TOSERVER:
- NFSGETTIME(&curtime);
- nvap->na_atime.tv_sec = curtime.tv_sec;
- nvap->na_atime.tv_nsec = curtime.tv_usec * 1000;
+ vfs_timestamp(&nvap->na_atime);
nvap->na_vaflags |= VA_UTIMES_NULL;
break;
};
@@ -2321,9 +2318,7 @@ nfsrv_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
nvap->na_vaflags &= ~VA_UTIMES_NULL;
break;
case NFSV3SATTRTIME_TOSERVER:
- NFSGETTIME(&curtime);
- nvap->na_mtime.tv_sec = curtime.tv_sec;
- nvap->na_mtime.tv_nsec = curtime.tv_usec * 1000;
+ vfs_timestamp(&nvap->na_mtime);
if (!toclient)
nvap->na_vaflags |= VA_UTIMES_NULL;
break;
@@ -2353,7 +2348,6 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
u_char *cp, namestr[NFSV4_SMALLSTR + 1];
uid_t uid;
gid_t gid;
- struct timeval curtime;
error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup);
if (error)
@@ -2488,9 +2482,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
toclient = 1;
attrsum += NFSX_V4TIME;
} else {
- NFSGETTIME(&curtime);
- nvap->na_atime.tv_sec = curtime.tv_sec;
- nvap->na_atime.tv_nsec = curtime.tv_usec * 1000;
+ vfs_timestamp(&nvap->na_atime);
nvap->na_vaflags |= VA_UTIMES_NULL;
}
break;
@@ -2515,9 +2507,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
nvap->na_vaflags &= ~VA_UTIMES_NULL;
attrsum += NFSX_V4TIME;
} else {
- NFSGETTIME(&curtime);
- nvap->na_mtime.tv_sec = curtime.tv_sec;
- nvap->na_mtime.tv_nsec = curtime.tv_usec * 1000;
+ vfs_timestamp(&nvap->na_mtime);
if (!toclient)
nvap->na_vaflags |= VA_UTIMES_NULL;
}
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 85fbbd2..307b1f6 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -55,6 +55,11 @@ extern int nfs_rootfhset;
extern int nfsrv_enable_crossmntpt;
#endif /* !APPLEKEXT */
+static int nfs_async = 0;
+SYSCTL_DECL(_vfs_nfsd);
+SYSCTL_INT(_vfs_nfsd, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
+ "Tell client that writes were synced even though they were not");
+
/*
* This list defines the GSS mechanisms supported.
* (Don't ask me how you get these strings from the RFC stuff like
@@ -912,7 +917,13 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
goto out;
NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(retlen);
- if (stable == NFSWRITE_UNSTABLE)
+ /*
+ * If nfs_async is set, then pretend the write was FILESYNC.
+ * Warning: Doing this violates RFC1813 and runs a risk
+ * of data written by a client being lost when the server
+ * crashes/reboots.
+ */
+ if (stable == NFSWRITE_UNSTABLE && nfs_async == 0)
*tl++ = txdr_unsigned(stable);
else
*tl++ = txdr_unsigned(NFSWRITE_FILESYNC);
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c
index 8b2f8b8..d74a5a9 100644
--- a/sys/fs/nfsserver/nfs_nfsdstate.c
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -3967,7 +3967,6 @@ nfsrv_setupstable(NFSPROC_T *p)
int error, i, tryagain;
off_t off = 0;
ssize_t aresid, len;
- struct timeval curtime;
/*
* If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without
@@ -3978,8 +3977,7 @@ nfsrv_setupstable(NFSPROC_T *p)
/*
* Set Grace over just until the file reads successfully.
*/
- NFSGETTIME(&curtime);
- nfsrvboottime = curtime.tv_sec;
+ nfsrvboottime = time_second;
LIST_INIT(&sf->nsf_head);
sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA;
@@ -4650,8 +4648,7 @@ out:
APPLESTATIC void
nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
{
- struct timespec mytime;
- int32_t starttime;
+ time_t starttime;
int error;
/*
@@ -4675,8 +4672,7 @@ nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
* Now, call nfsrv_checkremove() in a loop while it returns
* NFSERR_DELAY. Return upon any other error or when timed out.
*/
- NFSGETNANOTIME(&mytime);
- starttime = (u_int32_t)mytime.tv_sec;
+ starttime = NFSD_MONOSEC;
do {
if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
error = nfsrv_checkremove(vp, 0, p);
@@ -4684,11 +4680,7 @@ nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
} else
error = EPERM;
if (error == NFSERR_DELAY) {
- NFSGETNANOTIME(&mytime);
- if (((u_int32_t)mytime.tv_sec - starttime) >
- NFS_REMOVETIMEO &&
- ((u_int32_t)mytime.tv_sec - starttime) <
- 100000)
+ if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO)
break;
/* Sleep for a short period of time */
(void) nfs_catnap(PZERO, 0, "nfsremove");
@@ -4949,9 +4941,7 @@ nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp)
static time_t
nfsrv_leaseexpiry(void)
{
- struct timeval curtime;
- NFSGETTIME(&curtime);
if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC)
return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA));
return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA);
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 0b72249..90e56ea 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -46,9 +46,6 @@
#include <fs/nullfs/null.h>
-#define LOG2_SIZEVNODE 8 /* log2(sizeof struct vnode) */
-#define NNULLNODECACHE 16
-
/*
* Null layer cache:
* Each cache entry holds a reference to the lower vnode
@@ -57,12 +54,11 @@
* alias is removed the lower vnode is vrele'd.
*/
-#define NULL_NHASH(vp) \
- (&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
+#define NULL_NHASH(vp) (&null_node_hashtbl[vfs_hash_index(vp) & null_hash_mask])
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
-static u_long null_node_hash;
-struct mtx null_hashmtx;
+static struct mtx null_hashmtx;
+static u_long null_hash_mask;
static MALLOC_DEFINE(M_NULLFSHASH, "nullfs_hash", "NULLFS hash table");
MALLOC_DEFINE(M_NULLFSNODE, "nullfs_node", "NULLFS vnode private part");
@@ -77,8 +73,8 @@ nullfs_init(vfsp)
struct vfsconf *vfsp;
{
- NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */
- null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash);
+ null_node_hashtbl = hashinit(desiredvnodes, M_NULLFSHASH,
+ &null_hash_mask);
mtx_init(&null_hashmtx, "nullhs", NULL, MTX_DEF);
return (0);
}
@@ -89,7 +85,7 @@ nullfs_uninit(vfsp)
{
mtx_destroy(&null_hashmtx);
- hashdestroy(null_node_hashtbl, M_NULLFSHASH, null_node_hash);
+ hashdestroy(null_node_hashtbl, M_NULLFSHASH, null_hash_mask);
return (0);
}
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 5abfa49..3724e0a 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -67,15 +67,6 @@ static vfs_vget_t nullfs_vget;
static vfs_extattrctl_t nullfs_extattrctl;
static vfs_reclaim_lowervp_t nullfs_reclaim_lowervp;
-/* Mount options that we support. */
-static const char *nullfs_opts[] = {
- "cache",
- "export",
- "from",
- "target",
- NULL
-};
-
/*
* Mount null layer
*/
@@ -97,8 +88,6 @@ nullfs_mount(struct mount *mp)
return (EPERM);
if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP);
- if (vfs_filteropt(mp->mnt_optnew, nullfs_opts))
- return (EINVAL);
/*
* Update is a no-op
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index cc35d81..f59865f 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -740,6 +740,14 @@ null_reclaim(struct vop_reclaim_args *ap)
vp->v_object = NULL;
vp->v_vnlock = &vp->v_lock;
VI_UNLOCK(vp);
+
+ /*
+ * If we were opened for write, we leased one write reference
+ * to the lower vnode. If this is a reclamation due to the
+ * forced unmount, undo the reference now.
+ */
+ if (vp->v_writecount > 0)
+ VOP_ADD_WRITECOUNT(lowervp, -1);
vput(lowervp);
free(xp, M_NULLFSNODE);
diff --git a/sys/geom/journal/g_journal.c b/sys/geom/journal/g_journal.c
index 4581430..a3c996c 100644
--- a/sys/geom/journal/g_journal.c
+++ b/sys/geom/journal/g_journal.c
@@ -2976,7 +2976,7 @@ g_journal_do_switch(struct g_class *classp)
g_journal_switch_wait(sc);
mtx_unlock(&sc->sc_mtx);
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
next:
mtx_lock(&mountlist_mtx);
vfs_unbusy(mp);
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index 17271dd..0a8aeb0 100644
--- a/sys/geom/mirror/g_mirror.c
+++ b/sys/geom/mirror/g_mirror.c
@@ -81,7 +81,8 @@ SYSCTL_UINT(_kern_geom_mirror, OID_AUTO, sync_requests, CTLFLAG_RDTUN,
G_MIRROR_DEBUG(4, "%s: Woken up %p.", __func__, (ident)); \
} while (0)
-static eventhandler_tag g_mirror_pre_sync = NULL;
+static eventhandler_tag g_mirror_post_sync = NULL;
+static int g_mirror_shutdown = 0;
static int g_mirror_destroy_geom(struct gctl_req *req, struct g_class *mp,
struct g_geom *gp);
@@ -456,9 +457,7 @@ g_mirror_init_disk(struct g_mirror_softc *sc, struct g_provider *pp,
disk->d_priority = md->md_priority;
disk->d_flags = md->md_dflags;
error = g_getattr("GEOM::candelete", disk->d_consumer, &i);
- if (error != 0)
- goto fail;
- if (i)
+ if (error == 0 && i != 0)
disk->d_flags |= G_MIRROR_DISK_FLAG_CANDELETE;
if (md->md_provider[0] != '\0')
disk->d_flags |= G_MIRROR_DISK_FLAG_HARDCODED;
@@ -815,7 +814,7 @@ g_mirror_idle(struct g_mirror_softc *sc, int acw)
return (0);
if (acw > 0 || (acw == -1 && sc->sc_provider->acw > 0)) {
timeout = g_mirror_idletime - (time_uptime - sc->sc_last_write);
- if (timeout > 0)
+ if (!g_mirror_shutdown && timeout > 0)
return (timeout);
}
sc->sc_idle = 1;
@@ -2821,7 +2820,7 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
error = ENXIO;
goto end;
}
- if (dcw == 0 && !sc->sc_idle)
+ if (dcw == 0)
g_mirror_idle(sc, dcw);
if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0) {
if (acr > 0 || acw > 0 || ace > 0) {
@@ -3232,7 +3231,7 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
}
static void
-g_mirror_shutdown_pre_sync(void *arg, int howto)
+g_mirror_shutdown_post_sync(void *arg, int howto)
{
struct g_class *mp;
struct g_geom *gp, *gp2;
@@ -3242,6 +3241,7 @@ g_mirror_shutdown_pre_sync(void *arg, int howto)
mp = arg;
DROP_GIANT();
g_topology_lock();
+ g_mirror_shutdown = 1;
LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
if ((sc = gp->softc) == NULL)
continue;
@@ -3250,6 +3250,7 @@ g_mirror_shutdown_pre_sync(void *arg, int howto)
continue;
g_topology_unlock();
sx_xlock(&sc->sc_lock);
+ g_mirror_idle(sc, -1);
g_cancel_event(sc);
error = g_mirror_destroy(sc, G_MIRROR_DESTROY_DELAYED);
if (error != 0)
@@ -3264,9 +3265,9 @@ static void
g_mirror_init(struct g_class *mp)
{
- g_mirror_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync,
- g_mirror_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST);
- if (g_mirror_pre_sync == NULL)
+ g_mirror_post_sync = EVENTHANDLER_REGISTER(shutdown_post_sync,
+ g_mirror_shutdown_post_sync, mp, SHUTDOWN_PRI_FIRST);
+ if (g_mirror_post_sync == NULL)
G_MIRROR_DEBUG(0, "Warning! Cannot register shutdown event.");
}
@@ -3274,8 +3275,8 @@ static void
g_mirror_fini(struct g_class *mp)
{
- if (g_mirror_pre_sync != NULL)
- EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_mirror_pre_sync);
+ if (g_mirror_post_sync != NULL)
+ EVENTHANDLER_DEREGISTER(shutdown_post_sync, g_mirror_post_sync);
}
DECLARE_GEOM_CLASS(g_mirror_class, g_mirror);
diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c
index 19b6d9b..91d14c3 100644
--- a/sys/geom/raid/g_raid.c
+++ b/sys/geom/raid/g_raid.c
@@ -163,6 +163,8 @@ g_raid_disk_state2str(int state)
return ("NONE");
case G_RAID_DISK_S_OFFLINE:
return ("OFFLINE");
+ case G_RAID_DISK_S_DISABLED:
+ return ("DISABLED");
case G_RAID_DISK_S_FAILED:
return ("FAILED");
case G_RAID_DISK_S_STALE_FAILED:
@@ -535,7 +537,9 @@ g_raid_report_disk_state(struct g_raid_disk *disk)
if (disk->d_consumer == NULL)
return;
- if (disk->d_state == G_RAID_DISK_S_FAILED ||
+ if (disk->d_state == G_RAID_DISK_S_DISABLED) {
+ s = G_STATE_ACTIVE; /* XXX */
+ } else if (disk->d_state == G_RAID_DISK_S_FAILED ||
disk->d_state == G_RAID_DISK_S_STALE_FAILED) {
s = G_STATE_FAILED;
} else {
diff --git a/sys/geom/raid/g_raid.h b/sys/geom/raid/g_raid.h
index 20b0822..183edff6 100644
--- a/sys/geom/raid/g_raid.h
+++ b/sys/geom/raid/g_raid.h
@@ -140,11 +140,12 @@ struct g_raid_event {
};
#define G_RAID_DISK_S_NONE 0x00 /* State is unknown. */
#define G_RAID_DISK_S_OFFLINE 0x01 /* Missing disk placeholder. */
-#define G_RAID_DISK_S_FAILED 0x02 /* Failed. */
-#define G_RAID_DISK_S_STALE_FAILED 0x03 /* Old failed. */
-#define G_RAID_DISK_S_SPARE 0x04 /* Hot-spare. */
-#define G_RAID_DISK_S_STALE 0x05 /* Old disk, unused now. */
-#define G_RAID_DISK_S_ACTIVE 0x06 /* Operational. */
+#define G_RAID_DISK_S_DISABLED 0x02 /* Disabled. */
+#define G_RAID_DISK_S_FAILED 0x03 /* Failed. */
+#define G_RAID_DISK_S_STALE_FAILED 0x04 /* Old failed. */
+#define G_RAID_DISK_S_SPARE 0x05 /* Hot-spare. */
+#define G_RAID_DISK_S_STALE 0x06 /* Old disk, unused now. */
+#define G_RAID_DISK_S_ACTIVE 0x07 /* Operational. */
#define G_RAID_DISK_E_DISCONNECTED 0x01
diff --git a/sys/geom/raid/md_intel.c b/sys/geom/raid/md_intel.c
index 12122b0..eeb42d5 100644
--- a/sys/geom/raid/md_intel.c
+++ b/sys/geom/raid/md_intel.c
@@ -98,6 +98,9 @@ struct intel_raid_vol {
uint8_t cng_master_disk;
uint16_t cache_policy;
uint8_t cng_state;
+#define INTEL_CNGST_UPDATED 0
+#define INTEL_CNGST_NEEDS_UPDATE 1
+#define INTEL_CNGST_MASTER_MISSING 2
uint8_t cng_sub_state;
uint32_t filler_0[10];
@@ -130,6 +133,7 @@ struct intel_raid_disk {
#define INTEL_F_ASSIGNED 0x02
#define INTEL_F_FAILED 0x04
#define INTEL_F_ONLINE 0x08
+#define INTEL_F_DISABLED 0x80
uint32_t owner_cfg_num;
uint32_t sectors_hi;
uint32_t filler[3];
@@ -162,18 +166,33 @@ struct intel_raid_conf {
#define INTEL_ATTR_RAID1E 0x00000008
#define INTEL_ATTR_RAID5 0x00000010
#define INTEL_ATTR_RAIDCNG 0x00000020
+#define INTEL_ATTR_EXT_STRIP 0x00000040
+#define INTEL_ATTR_NVM_CACHE 0x02000000
+#define INTEL_ATTR_2TB_DISK 0x04000000
+#define INTEL_ATTR_BBM 0x08000000
+#define INTEL_ATTR_NVM_CACHE2 0x10000000
#define INTEL_ATTR_2TB 0x20000000
#define INTEL_ATTR_PM 0x40000000
#define INTEL_ATTR_CHECKSUM 0x80000000
uint8_t total_disks;
uint8_t total_volumes;
- uint8_t dummy_2[2];
- uint32_t filler_0[39];
+ uint8_t error_log_pos;
+ uint8_t dummy_2[1];
+ uint32_t cache_size;
+ uint32_t orig_config_id;
+ uint32_t pwr_cycle_count;
+ uint32_t bbm_log_size;
+ uint32_t filler_0[35];
struct intel_raid_disk disk[1]; /* total_disks entries. */
/* Here goes total_volumes of struct intel_raid_vol. */
} __packed;
+#define INTEL_ATTR_SUPPORTED ( INTEL_ATTR_RAID0 | INTEL_ATTR_RAID1 | \
+ INTEL_ATTR_RAID10 | INTEL_ATTR_RAID1E | INTEL_ATTR_RAID5 | \
+ INTEL_ATTR_RAIDCNG | INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | \
+ INTEL_ATTR_2TB | INTEL_ATTR_PM | INTEL_ATTR_CHECKSUM )
+
#define INTEL_MAX_MD_SIZE(ndisks) \
(sizeof(struct intel_raid_conf) + \
sizeof(struct intel_raid_disk) * (ndisks - 1) + \
@@ -187,9 +206,17 @@ struct g_raid_md_intel_perdisk {
struct intel_raid_disk pd_disk_meta;
};
+struct g_raid_md_intel_pervolume {
+ int pv_volume_pos;
+ int pv_cng;
+ int pv_cng_man_sync;
+ int pv_cng_master_disk;
+};
+
struct g_raid_md_intel_object {
struct g_raid_md_object mdio_base;
uint32_t mdio_config_id;
+ uint32_t mdio_orig_config_id;
uint32_t mdio_generation;
struct intel_raid_conf *mdio_meta;
struct callout mdio_start_co; /* STARTING state timer. */
@@ -206,6 +233,7 @@ static g_raid_md_ctl_t g_raid_md_ctl_intel;
static g_raid_md_write_t g_raid_md_write_intel;
static g_raid_md_fail_disk_t g_raid_md_fail_disk_intel;
static g_raid_md_free_disk_t g_raid_md_free_disk_intel;
+static g_raid_md_free_volume_t g_raid_md_free_volume_intel;
static g_raid_md_free_t g_raid_md_free_intel;
static kobj_method_t g_raid_md_intel_methods[] = {
@@ -216,6 +244,7 @@ static kobj_method_t g_raid_md_intel_methods[] = {
KOBJMETHOD(g_raid_md_write, g_raid_md_write_intel),
KOBJMETHOD(g_raid_md_fail_disk, g_raid_md_fail_disk_intel),
KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_intel),
+ KOBJMETHOD(g_raid_md_free_volume, g_raid_md_free_volume_intel),
KOBJMETHOD(g_raid_md_free, g_raid_md_free_intel),
{ 0, 0 }
};
@@ -354,29 +383,45 @@ g_raid_md_intel_print(struct intel_raid_conf *meta)
printf("config_size 0x%08x\n", meta->config_size);
printf("config_id 0x%08x\n", meta->config_id);
printf("generation 0x%08x\n", meta->generation);
+ printf("error_log_size %d\n", meta->error_log_size);
printf("attributes 0x%08x\n", meta->attributes);
printf("total_disks %u\n", meta->total_disks);
printf("total_volumes %u\n", meta->total_volumes);
- printf("DISK# serial disk_sectors disk_sectors_hi disk_id flags\n");
+ printf("error_log_pos %u\n", meta->error_log_pos);
+ printf("cache_size %u\n", meta->cache_size);
+ printf("orig_config_id 0x%08x\n", meta->orig_config_id);
+ printf("pwr_cycle_count %u\n", meta->pwr_cycle_count);
+ printf("bbm_log_size %u\n", meta->bbm_log_size);
+ printf("DISK# serial disk_sectors disk_sectors_hi disk_id flags owner\n");
for (i = 0; i < meta->total_disks; i++ ) {
- printf(" %d <%.16s> %u %u 0x%08x 0x%08x\n", i,
+ printf(" %d <%.16s> %u %u 0x%08x 0x%08x %08x\n", i,
meta->disk[i].serial, meta->disk[i].sectors,
- meta->disk[i].sectors_hi,
- meta->disk[i].id, meta->disk[i].flags);
+ meta->disk[i].sectors_hi, meta->disk[i].id,
+ meta->disk[i].flags, meta->disk[i].owner_cfg_num);
}
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
printf(" ****** Volume %d ******\n", i);
printf(" name %.16s\n", mvol->name);
printf(" total_sectors %ju\n", mvol->total_sectors);
- printf(" state %u\n", mvol->state);
+ printf(" state 0x%08x\n", mvol->state);
printf(" reserved %u\n", mvol->reserved);
+ printf(" migr_priority %u\n", mvol->migr_priority);
+ printf(" num_sub_vols %u\n", mvol->num_sub_vols);
+ printf(" tid %u\n", mvol->tid);
+ printf(" cng_master_disk %u\n", mvol->cng_master_disk);
+ printf(" cache_policy %u\n", mvol->cache_policy);
+ printf(" cng_state %u\n", mvol->cng_state);
+ printf(" cng_sub_state %u\n", mvol->cng_sub_state);
printf(" curr_migr_unit %u\n", mvol->curr_migr_unit);
printf(" curr_migr_unit_hi %u\n", mvol->curr_migr_unit_hi);
printf(" checkpoint_id %u\n", mvol->checkpoint_id);
printf(" migr_state %u\n", mvol->migr_state);
printf(" migr_type %u\n", mvol->migr_type);
printf(" dirty %u\n", mvol->dirty);
+ printf(" fs_state %u\n", mvol->fs_state);
+ printf(" verify_errors %u\n", mvol->verify_errors);
+ printf(" bad_blocks %u\n", mvol->bad_blocks);
for (j = 0; j < (mvol->migr_state ? 2 : 1); j++) {
printf(" *** Map %d ***\n", j);
@@ -432,7 +477,7 @@ intel_meta_read(struct g_consumer *cp)
struct g_provider *pp;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
- struct intel_raid_map *mmap;
+ struct intel_raid_map *mmap, *mmap1;
char *buf;
int error, i, j, k, left, size;
uint32_t checksum, *ptr;
@@ -525,6 +570,23 @@ badsize:
}
}
+ g_raid_md_intel_print(meta);
+
+ if (strncmp(meta->version, INTEL_VERSION_1300, 6) > 0) {
+ G_RAID_DEBUG(1, "Intel unsupported version: '%.6s'",
+ meta->version);
+ free(meta, M_MD_INTEL);
+ return (NULL);
+ }
+
+ if (strncmp(meta->version, INTEL_VERSION_1300, 6) >= 0 &&
+ (meta->attributes & ~INTEL_ATTR_SUPPORTED) != 0) {
+ G_RAID_DEBUG(1, "Intel unsupported attributes: 0x%08x",
+ meta->attributes & ~INTEL_ATTR_SUPPORTED);
+ free(meta, M_MD_INTEL);
+ return (NULL);
+ }
+
/* Validate disk indexes. */
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
@@ -547,16 +609,39 @@ badsize:
/* Validate migration types. */
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
+ /* Deny unknown migration types. */
if (mvol->migr_state &&
mvol->migr_type != INTEL_MT_INIT &&
mvol->migr_type != INTEL_MT_REBUILD &&
mvol->migr_type != INTEL_MT_VERIFY &&
+ mvol->migr_type != INTEL_MT_GEN_MIGR &&
mvol->migr_type != INTEL_MT_REPAIR) {
G_RAID_DEBUG(1, "Intel metadata has unsupported"
" migration type %d", mvol->migr_type);
free(meta, M_MD_INTEL);
return (NULL);
}
+ /* Deny general migrations except SINGLE->RAID1. */
+ if (mvol->migr_state &&
+ mvol->migr_type == INTEL_MT_GEN_MIGR) {
+ mmap = intel_get_map(mvol, 0);
+ mmap1 = intel_get_map(mvol, 1);
+ if (mmap1->total_disks != 1 ||
+ mmap->type != INTEL_T_RAID1 ||
+ mmap->total_disks != 2 ||
+ mmap->offset != mmap1->offset ||
+ mmap->disk_sectors != mmap1->disk_sectors ||
+ mmap->total_domains != mmap->total_disks ||
+ mmap->offset_hi != mmap1->offset_hi ||
+ mmap->disk_sectors_hi != mmap1->disk_sectors_hi ||
+ (mmap->disk_idx[0] != mmap1->disk_idx[0] &&
+ mmap->disk_idx[0] != mmap1->disk_idx[1])) {
+ G_RAID_DEBUG(1, "Intel metadata has unsupported"
+ " variant of general migration");
+ free(meta, M_MD_INTEL);
+ return (NULL);
+ }
+ }
}
return (meta);
@@ -633,7 +718,7 @@ intel_meta_write_spare(struct g_consumer *cp, struct intel_raid_disk *d)
memcpy(&meta->version[0], INTEL_VERSION_1000,
sizeof(INTEL_VERSION_1000) - 1);
meta->config_size = INTEL_MAX_MD_SIZE(1);
- meta->config_id = arc4random();
+ meta->config_id = meta->orig_config_id = arc4random();
meta->generation = 1;
meta->total_disks = 1;
meta->disk[0] = *d;
@@ -699,9 +784,11 @@ static struct g_raid_volume *
g_raid_md_intel_get_volume(struct g_raid_softc *sc, int id)
{
struct g_raid_volume *mvol;
+ struct g_raid_md_intel_pervolume *pv;
TAILQ_FOREACH(mvol, &sc->sc_volumes, v_next) {
- if ((intptr_t)(mvol->v_md_data) == id)
+ pv = mvol->v_md_data;
+ if (pv->pv_volume_pos == id)
break;
}
return (mvol);
@@ -715,11 +802,12 @@ g_raid_md_intel_start_disk(struct g_raid_disk *disk)
struct g_raid_disk *olddisk, *tmpdisk;
struct g_raid_md_object *md;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd, *oldpd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
struct intel_raid_map *mmap0, *mmap1;
- int disk_pos, resurrection = 0;
+ int disk_pos, resurrection = 0, migr_global, i;
sc = disk->d_softc;
md = sc->sc_md;
@@ -733,7 +821,8 @@ g_raid_md_intel_start_disk(struct g_raid_disk *disk)
if (disk_pos < 0) {
G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk");
/* Failed stale disk is useless for us. */
- if (pd->pd_disk_meta.flags & INTEL_F_FAILED) {
+ if ((pd->pd_disk_meta.flags & INTEL_F_FAILED) &&
+ !(pd->pd_disk_meta.flags & INTEL_F_DISABLED)) {
g_raid_change_disk_state(disk, G_RAID_DISK_S_STALE_FAILED);
return (0);
}
@@ -824,7 +913,10 @@ nofit:
}
/* Welcome the new disk. */
- if (resurrection)
+ if ((meta->disk[disk_pos].flags & INTEL_F_DISABLED) &&
+ !(pd->pd_disk_meta.flags & INTEL_F_SPARE))
+ g_raid_change_disk_state(disk, G_RAID_DISK_S_DISABLED);
+ else if (resurrection)
g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
else if (meta->disk[disk_pos].flags & INTEL_F_FAILED)
g_raid_change_disk_state(disk, G_RAID_DISK_S_FAILED);
@@ -833,15 +925,27 @@ nofit:
else
g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
- mvol = intel_get_volume(meta,
- (uintptr_t)(sd->sd_volume->v_md_data));
+ pv = sd->sd_volume->v_md_data;
+ mvol = intel_get_volume(meta, pv->pv_volume_pos);
mmap0 = intel_get_map(mvol, 0);
if (mvol->migr_state)
mmap1 = intel_get_map(mvol, 1);
else
mmap1 = mmap0;
- if (resurrection) {
+ migr_global = 1;
+ for (i = 0; i < mmap0->total_disks; i++) {
+ if ((mmap0->disk_idx[i] & INTEL_DI_RBLD) == 0 &&
+ (mmap1->disk_idx[i] & INTEL_DI_RBLD) != 0)
+ migr_global = 0;
+ }
+
+ if ((meta->disk[disk_pos].flags & INTEL_F_DISABLED) &&
+ !(pd->pd_disk_meta.flags & INTEL_F_SPARE)) {
+ /* Disabled disk, useless. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_NONE);
+ } else if (resurrection) {
/* Stale disk, almost same as new. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_NEW);
@@ -850,7 +954,8 @@ nofit:
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_FAILED);
} else if (mvol->migr_state == 0) {
- if (mmap0->status == INTEL_S_UNINITIALIZED) {
+ if (mmap0->status == INTEL_S_UNINITIALIZED &&
+ (!pv->pv_cng || pv->pv_cng_master_disk != disk_pos)) {
/* Freshly created uninitialized volume. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_UNINITIALIZED);
@@ -858,7 +963,8 @@ nofit:
/* Freshly inserted disk. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_NEW);
- } else if (mvol->dirty) {
+ } else if (mvol->dirty && (!pv->pv_cng ||
+ pv->pv_cng_master_disk != disk_pos)) {
/* Dirty volume (unclean shutdown). */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_STALE);
@@ -885,7 +991,13 @@ nofit:
sd->sd_volume->v_strip_size *
mmap0->total_domains;
}
- } else if (mvol->dirty) {
+ } else if (mvol->migr_type == INTEL_MT_INIT &&
+ migr_global) {
+ /* Freshly created uninitialized volume. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_UNINITIALIZED);
+ } else if (mvol->dirty && (!pv->pv_cng ||
+ pv->pv_cng_master_disk != disk_pos)) {
/* Dirty volume (unclean shutdown). */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_STALE);
@@ -900,7 +1012,8 @@ nofit:
/* Freshly inserted disk. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_NEW);
- } else if (mmap1->disk_idx[sd->sd_pos] & INTEL_DI_RBLD) {
+ } else if ((mmap1->disk_idx[sd->sd_pos] & INTEL_DI_RBLD) ||
+ migr_global) {
/* Resyncing disk. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_RESYNC);
@@ -921,6 +1034,16 @@ nofit:
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_ACTIVE);
}
+ } else if (mvol->migr_type == INTEL_MT_GEN_MIGR) {
+ if ((mmap1->disk_idx[0] & INTEL_DI_IDX) != disk_pos) {
+ /* Freshly inserted disk. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_NEW);
+ } else {
+ /* Up to date disk. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_ACTIVE);
+ }
}
g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW,
G_RAID_EVENT_SUBDISK);
@@ -929,7 +1052,8 @@ nofit:
/* Update status of our need for spare. */
if (mdi->mdio_started) {
mdi->mdio_incomplete =
- (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) <
+ (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) +
+ g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED) <
meta->total_disks);
}
@@ -961,7 +1085,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc)
update = 0;
do {
/* Make sure we miss anything. */
- na = g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE);
+ na = g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) +
+ g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED);
if (na == meta->total_disks)
break;
@@ -973,7 +1098,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc)
TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
if (disk->d_state == G_RAID_DISK_S_STALE) {
update += g_raid_md_intel_start_disk(disk);
- if (disk->d_state == G_RAID_DISK_S_ACTIVE)
+ if (disk->d_state == G_RAID_DISK_S_ACTIVE ||
+ disk->d_state == G_RAID_DISK_S_DISABLED)
break;
}
}
@@ -997,8 +1123,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc)
}
/* Update status of our need for spare. */
- mdi->mdio_incomplete = (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) <
- meta->total_disks);
+ mdi->mdio_incomplete = (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) +
+ g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED) < meta->total_disks);
/* Request retaste hoping to find spare. */
if (mdi->mdio_incomplete) {
@@ -1014,6 +1140,7 @@ g_raid_md_intel_start(struct g_raid_softc *sc)
{
struct g_raid_md_object *md;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
@@ -1031,8 +1158,14 @@ g_raid_md_intel_start(struct g_raid_softc *sc)
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
mmap = intel_get_map(mvol, 0);
- vol = g_raid_create_volume(sc, mvol->name, -1);
- vol->v_md_data = (void *)(intptr_t)i;
+ vol = g_raid_create_volume(sc, mvol->name, mvol->tid - 1);
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = i;
+ pv->pv_cng = (mvol->state & INTEL_ST_CLONE_N_GO) != 0;
+ pv->pv_cng_man_sync = (mvol->state & INTEL_ST_CLONE_MAN_SYNC) != 0;
+ if (mvol->cng_master_disk < mmap->total_disks)
+ pv->pv_cng_master_disk = mvol->cng_master_disk;
+ vol->v_md_data = pv;
vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
if (mmap->type == INTEL_T_RAID0)
vol->v_raid_level = G_RAID_VOLUME_RL_RAID0;
@@ -1186,7 +1319,7 @@ g_raid_md_create_intel(struct g_raid_md_object *md, struct g_class *mp,
char name[16];
mdi = (struct g_raid_md_intel_object *)md;
- mdi->mdio_config_id = arc4random();
+ mdi->mdio_config_id = mdi->mdio_orig_config_id = arc4random();
mdi->mdio_generation = 0;
snprintf(name, sizeof(name), "Intel-%08x", mdi->mdio_config_id);
sc = g_raid_create_node(mp, name, md);
@@ -1294,8 +1427,6 @@ g_raid_md_taste_intel(struct g_raid_md_object *md, struct g_class *mp,
goto fail1;
}
- /* Metadata valid. Print it. */
- g_raid_md_intel_print(meta);
G_RAID_DEBUG(1, "Intel disk position %d", disk_pos);
spare = meta->disk[disk_pos].flags & INTEL_F_SPARE;
@@ -1333,6 +1464,7 @@ search:
} else { /* Not found matching node -- create one. */
result = G_RAID_MD_TASTE_NEW;
mdi->mdio_config_id = meta->config_id;
+ mdi->mdio_orig_config_id = meta->orig_config_id;
snprintf(name, sizeof(name), "Intel-%08x", meta->config_id);
sc = g_raid_create_node(mp, name, md);
md->mdo_softc = sc;
@@ -1450,6 +1582,7 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md,
struct g_raid_subdisk *sd;
struct g_raid_disk *disk;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct g_consumer *cp;
struct g_provider *pp;
@@ -1621,7 +1754,9 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md,
/* We have all we need, create things: volume, ... */
mdi->mdio_started = 1;
vol = g_raid_create_volume(sc, volname, -1);
- vol->v_md_data = (void *)(intptr_t)0;
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = 0;
+ vol->v_md_data = pv;
vol->v_raid_level = level;
vol->v_raid_level_qualifier = qual;
vol->v_strip_size = strip;
@@ -1814,7 +1949,9 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md,
/* We have all we need, create things: volume, ... */
vol = g_raid_create_volume(sc, volname, -1);
- vol->v_md_data = (void *)(intptr_t)i;
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = i;
+ vol->v_md_data = pv;
vol->v_raid_level = level;
vol->v_raid_level_qualifier = qual;
vol->v_strip_size = strip;
@@ -2105,6 +2242,7 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
struct g_raid_subdisk *sd;
struct g_raid_disk *disk;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
@@ -2133,9 +2271,14 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
pd->pd_disk_meta.flags =
INTEL_F_ONLINE | INTEL_F_ASSIGNED;
} else if (disk->d_state == G_RAID_DISK_S_FAILED) {
- pd->pd_disk_meta.flags = INTEL_F_FAILED | INTEL_F_ASSIGNED;
+ pd->pd_disk_meta.flags = INTEL_F_FAILED |
+ INTEL_F_ASSIGNED;
+ } else if (disk->d_state == G_RAID_DISK_S_DISABLED) {
+ pd->pd_disk_meta.flags = INTEL_F_FAILED |
+ INTEL_F_ASSIGNED | INTEL_F_DISABLED;
} else {
- pd->pd_disk_meta.flags = INTEL_F_ASSIGNED;
+ if (!(pd->pd_disk_meta.flags & INTEL_F_DISABLED))
+ pd->pd_disk_meta.flags = INTEL_F_ASSIGNED;
if (pd->pd_disk_meta.id != 0xffffffff) {
pd->pd_disk_meta.id = 0xffffffff;
len = strlen(pd->pd_disk_meta.serial);
@@ -2151,6 +2294,7 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
memcpy(&meta->intel_id[0], INTEL_MAGIC, sizeof(INTEL_MAGIC) - 1);
meta->config_size = INTEL_MAX_MD_SIZE(numdisks);
meta->config_id = mdi->mdio_config_id;
+ meta->orig_config_id = mdi->mdio_orig_config_id;
meta->generation = mdi->mdio_generation;
meta->attributes = INTEL_ATTR_CHECKSUM;
meta->total_disks = numdisks;
@@ -2159,18 +2303,21 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
if (pd->pd_disk_pos < 0)
continue;
meta->disk[pd->pd_disk_pos] = pd->pd_disk_meta;
+ if (pd->pd_disk_meta.sectors_hi != 0)
+ meta->attributes |= INTEL_ATTR_2TB_DISK;
}
/* Fill volumes and maps. */
vi = 0;
version = INTEL_VERSION_1000;
TAILQ_FOREACH(vol, &sc->sc_volumes, v_next) {
+ pv = vol->v_md_data;
if (vol->v_stopping)
continue;
mvol = intel_get_volume(meta, vi);
/* New metadata may have different volumes order. */
- vol->v_md_data = (void *)(intptr_t)vi;
+ pv->pv_volume_pos = vi;
for (sdi = 0; sdi < vol->v_disks_count; sdi++) {
sd = &vol->v_subdisks[sdi];
@@ -2187,21 +2334,23 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
meta->attributes |= INTEL_ATTR_RAID1;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5)
meta->attributes |= INTEL_ATTR_RAID5;
- else
+ else if ((vol->v_disks_count & 1) == 0)
meta->attributes |= INTEL_ATTR_RAID10;
-
- if (meta->attributes & INTEL_ATTR_2TB)
- cv = INTEL_VERSION_1300;
-// else if (dev->status == DEV_CLONE_N_GO)
-// cv = INTEL_VERSION_1206;
+ else
+ meta->attributes |= INTEL_ATTR_RAID1E;
+ if (pv->pv_cng)
+ meta->attributes |= INTEL_ATTR_RAIDCNG;
+ if (vol->v_strip_size > 131072)
+ meta->attributes |= INTEL_ATTR_EXT_STRIP;
+
+ if (pv->pv_cng)
+ cv = INTEL_VERSION_1206;
else if (vol->v_disks_count > 4)
cv = INTEL_VERSION_1204;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5)
cv = INTEL_VERSION_1202;
else if (vol->v_disks_count > 2)
cv = INTEL_VERSION_1201;
- else if (vi > 0)
- cv = INTEL_VERSION_1200;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1)
cv = INTEL_VERSION_1100;
else
@@ -2211,6 +2360,22 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
strlcpy(&mvol->name[0], vol->v_name, sizeof(mvol->name));
mvol->total_sectors = vol->v_mediasize / sectorsize;
+ mvol->state = (INTEL_ST_READ_COALESCING |
+ INTEL_ST_WRITE_COALESCING);
+ mvol->tid = vol->v_global_id + 1;
+ if (pv->pv_cng) {
+ mvol->state |= INTEL_ST_CLONE_N_GO;
+ if (pv->pv_cng_man_sync)
+ mvol->state |= INTEL_ST_CLONE_MAN_SYNC;
+ mvol->cng_master_disk = pv->pv_cng_master_disk;
+ if (vol->v_subdisks[pv->pv_cng_master_disk].sd_state ==
+ G_RAID_SUBDISK_S_NONE)
+ mvol->cng_state = INTEL_CNGST_MASTER_MISSING;
+ else if (vol->v_state != G_RAID_VOLUME_S_OPTIMAL)
+ mvol->cng_state = INTEL_CNGST_NEEDS_UPDATE;
+ else
+ mvol->cng_state = INTEL_CNGST_UPDATED;
+ }
/* Check for any recovery in progress. */
state = G_RAID_SUBDISK_S_ACTIVE;
@@ -2305,7 +2470,8 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
mmap1->disk_idx[sdi] |= INTEL_DI_RBLD;
}
if ((sd->sd_state == G_RAID_SUBDISK_S_NONE ||
- sd->sd_state == G_RAID_SUBDISK_S_FAILED) &&
+ sd->sd_state == G_RAID_SUBDISK_S_FAILED ||
+ sd->sd_state == G_RAID_SUBDISK_S_REBUILD) &&
mmap0->failed_disk_num == 0xff) {
mmap0->failed_disk_num = sdi;
if (mvol->migr_state)
@@ -2315,7 +2481,10 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
vi++;
}
meta->total_volumes = vi;
- if (strcmp(version, INTEL_VERSION_1300) != 0)
+ if (vi > 1 || meta->attributes &
+ (INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | INTEL_ATTR_2TB))
+ version = INTEL_VERSION_1300;
+ if (strcmp(version, INTEL_VERSION_1300) < 0)
meta->attributes &= INTEL_ATTR_CHECKSUM;
memcpy(&meta->version[0], version, sizeof(INTEL_VERSION_1000) - 1);
@@ -2403,6 +2572,18 @@ g_raid_md_free_disk_intel(struct g_raid_md_object *md,
}
static int
+g_raid_md_free_volume_intel(struct g_raid_md_object *md,
+ struct g_raid_volume *vol)
+{
+ struct g_raid_md_intel_pervolume *pv;
+
+ pv = (struct g_raid_md_intel_pervolume *)vol->v_md_data;
+ free(pv, M_MD_INTEL);
+ vol->v_md_data = NULL;
+ return (0);
+}
+
+static int
g_raid_md_free_intel(struct g_raid_md_object *md)
{
struct g_raid_md_intel_object *mdi;
diff --git a/sys/geom/raid/md_promise.c b/sys/geom/raid/md_promise.c
index 5512b5a..0007b20 100644
--- a/sys/geom/raid/md_promise.c
+++ b/sys/geom/raid/md_promise.c
@@ -84,7 +84,7 @@ struct promise_raid_conf {
struct promise_raid_disk disk; /* This subdisk info. */
uint32_t disk_offset; /* Subdisk offset. */
uint32_t disk_sectors; /* Subdisk size */
- uint32_t rebuild_lba; /* Rebuild position. */
+ uint32_t disk_rebuild; /* Rebuild position. */
uint16_t generation; /* Generation number. */
uint8_t status; /* Volume status. */
#define PROMISE_S_VALID 0x01
@@ -123,7 +123,18 @@ struct promise_raid_conf {
uint32_t magic_4;
uint32_t magic_5;
uint32_t total_sectors_high;
- uint32_t filler3[324];
+ uint8_t magic_6;
+ uint8_t sector_size;
+ uint16_t magic_7;
+ uint32_t magic_8[31];
+ uint32_t backup_time;
+ uint16_t magic_9;
+ uint32_t disk_offset_high;
+ uint32_t disk_sectors_high;
+ uint32_t disk_rebuild_high;
+ uint16_t magic_10;
+ uint32_t magic_11[3];
+ uint32_t filler3[284];
uint32_t checksum;
} __packed;
@@ -191,7 +202,7 @@ g_raid_md_promise_print(struct promise_raid_conf *meta)
meta->disk.device, meta->disk.id);
printf("disk_offset %u\n", meta->disk_offset);
printf("disk_sectors %u\n", meta->disk_sectors);
- printf("rebuild_lba %u\n", meta->rebuild_lba);
+ printf("disk_rebuild %u\n", meta->disk_rebuild);
printf("generation %u\n", meta->generation);
printf("status 0x%02x\n", meta->status);
printf("type %u\n", meta->type);
@@ -217,6 +228,11 @@ g_raid_md_promise_print(struct promise_raid_conf *meta)
printf("magic_4 0x%08x\n", meta->magic_4);
printf("magic_5 0x%08x\n", meta->magic_5);
printf("total_sectors_high 0x%08x\n", meta->total_sectors_high);
+ printf("sector_size %u\n", meta->sector_size);
+ printf("backup_time %d\n", meta->backup_time);
+ printf("disk_offset_high 0x%08x\n", meta->disk_offset_high);
+ printf("disk_sectors_high 0x%08x\n", meta->disk_sectors_high);
+ printf("disk_rebuild_high 0x%08x\n", meta->disk_rebuild_high);
printf("=================================================\n");
}
@@ -244,9 +260,9 @@ promise_meta_find_disk(struct promise_raid_conf *meta, uint64_t id)
static int
promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
- uint32_t sectors, uint32_t *off, uint32_t *size)
+ off_t sectors, off_t *off, off_t *size)
{
- uint32_t coff, csize;
+ off_t coff, csize, tmp;
int i, j;
sectors -= 131072;
@@ -257,10 +273,10 @@ promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
i = 0;
while (1) {
for (j = 0; j < nsd; j++) {
- if (metaarr[j]->disk_offset >= coff) {
- csize = MIN(csize,
- metaarr[j]->disk_offset - coff);
- }
+ tmp = ((off_t)metaarr[j]->disk_offset_high << 32) +
+ metaarr[j]->disk_offset;
+ if (tmp >= coff)
+ csize = MIN(csize, tmp - coff);
}
if (csize > *size) {
*off = coff;
@@ -268,7 +284,10 @@ promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
}
if (i >= nsd)
break;
- coff = metaarr[i]->disk_offset + metaarr[i]->disk_sectors;
+ coff = ((off_t)metaarr[i]->disk_offset_high << 32) +
+ metaarr[i]->disk_offset +
+ ((off_t)metaarr[i]->disk_sectors_high << 32) +
+ metaarr[i]->disk_sectors;
csize = sectors - coff;
i++;
};
@@ -369,6 +388,26 @@ next:
return (subdisks);
}
+ /* Remove filler garbage from fields used in newer metadata. */
+ if (meta->disk_offset_high == 0x8b8c8d8e &&
+ meta->disk_sectors_high == 0x8788898a &&
+ meta->disk_rebuild_high == 0x83848586) {
+ meta->disk_offset_high = 0;
+ meta->disk_sectors_high = 0;
+ if (meta->disk_rebuild == UINT32_MAX)
+ meta->disk_rebuild_high = UINT32_MAX;
+ else
+ meta->disk_rebuild_high = 0;
+ if (meta->total_sectors_high == 0x15161718) {
+ meta->total_sectors_high = 0;
+ meta->backup_time = 0;
+ if (meta->rebuild_lba64 == 0x2122232425262728)
+ meta->rebuild_lba64 = UINT64_MAX;
+ }
+ }
+ if (meta->sector_size < 1 || meta->sector_size > 8)
+ meta->sector_size = 1;
+
/* Save this part and look for next. */
*metaarr = meta;
metaarr++;
@@ -386,8 +425,9 @@ promise_meta_write(struct g_consumer *cp,
struct g_provider *pp;
struct promise_raid_conf *meta;
char *buf;
+ off_t off, size;
int error, i, subdisk, fake;
- uint32_t checksum, *ptr, off, size;
+ uint32_t checksum, *ptr;
pp = cp->provider;
subdisk = 0;
@@ -409,9 +449,12 @@ next:
meta->disk.flags = PROMISE_F_ONLINE | PROMISE_F_VALID;
meta->disk.number = 0xff;
arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
- meta->disk_offset = off;
- meta->disk_sectors = size;
- meta->rebuild_lba = UINT32_MAX;
+ meta->disk_offset_high = off >> 32;
+ meta->disk_offset = (uint32_t)off;
+ meta->disk_sectors_high = size >> 32;
+ meta->disk_sectors = (uint32_t)size;
+ meta->disk_rebuild_high = UINT32_MAX;
+ meta->disk_rebuild = UINT32_MAX;
fake = 1;
}
if (meta != NULL) {
@@ -464,6 +507,7 @@ static int
promise_meta_write_spare(struct g_consumer *cp)
{
struct promise_raid_conf *meta;
+ off_t tmp;
int error;
meta = malloc(sizeof(*meta), M_MD_PROMISE, M_WAITOK | M_ZERO);
@@ -473,9 +517,11 @@ promise_meta_write_spare(struct g_consumer *cp)
meta->disk.flags = PROMISE_F_SPARE | PROMISE_F_ONLINE | PROMISE_F_VALID;
meta->disk.number = 0xff;
arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
- meta->disk_sectors = cp->provider->mediasize / cp->provider->sectorsize;
- meta->disk_sectors -= 131072;
- meta->rebuild_lba = UINT32_MAX;
+ tmp = cp->provider->mediasize / cp->provider->sectorsize - 131072;
+ meta->disk_sectors_high = tmp >> 32;
+ meta->disk_sectors = (uint32_t)tmp;
+ meta->disk_rebuild_high = UINT32_MAX;
+ meta->disk_rebuild = UINT32_MAX;
error = promise_meta_write(cp, &meta, 1);
free(meta, M_MD_PROMISE);
return (error);
@@ -617,9 +663,8 @@ g_raid_md_promise_start_disk(struct g_raid_disk *disk, int sdn,
struct g_raid_md_promise_perdisk *pd;
struct g_raid_md_promise_pervolume *pv;
struct promise_raid_conf *meta;
- off_t size;
+ off_t eoff, esize, size;
int disk_pos, md_disk_pos, i, resurrection = 0;
- uint32_t eoff, esize;
sc = disk->d_softc;
pd = (struct g_raid_md_promise_perdisk *)disk->d_md_data;
@@ -729,8 +774,10 @@ nofit:
sd->sd_offset = (off_t)eoff * 512;
sd->sd_size = (off_t)esize * 512;
} else {
- sd->sd_offset = (off_t)pd->pd_meta[sdn]->disk_offset * 512;
- sd->sd_size = (off_t)pd->pd_meta[sdn]->disk_sectors * 512;
+ sd->sd_offset = (((off_t)pd->pd_meta[sdn]->disk_offset_high
+ << 32) + pd->pd_meta[sdn]->disk_offset) * 512;
+ sd->sd_size = (((off_t)pd->pd_meta[sdn]->disk_sectors_high
+ << 32) + pd->pd_meta[sdn]->disk_sectors) * 512;
}
if (resurrection) {
@@ -749,7 +796,8 @@ nofit:
sd->sd_rebuild_pos = 0;
else {
sd->sd_rebuild_pos =
- (off_t)pd->pd_meta[sdn]->rebuild_lba * 512;
+ (((off_t)pd->pd_meta[sdn]->disk_rebuild_high << 32) +
+ pd->pd_meta[sdn]->disk_rebuild) * 512;
}
} else if (!(meta->disks[md_disk_pos].flags & PROMISE_F_ONLINE)) {
/* Rebuilding disk. */
@@ -875,13 +923,15 @@ g_raid_md_promise_start(struct g_raid_volume *vol)
vol->v_disks_count = meta->total_disks;
vol->v_mediasize = (off_t)meta->total_sectors * 512; //ZZZ
if (meta->total_sectors_high < 256) /* If value looks sane. */
- vol->v_mediasize |=
+ vol->v_mediasize +=
((off_t)meta->total_sectors_high << 32) * 512; //ZZZ
- vol->v_sectorsize = 512; //ZZZ
+ vol->v_sectorsize = 512 * meta->sector_size;
for (i = 0; i < vol->v_disks_count; i++) {
sd = &vol->v_subdisks[i];
- sd->sd_offset = (off_t)meta->disk_offset * 512; //ZZZ
- sd->sd_size = (off_t)meta->disk_sectors * 512; //ZZZ
+ sd->sd_offset = (((off_t)meta->disk_offset_high << 32) +
+ meta->disk_offset) * 512;
+ sd->sd_size = (((off_t)meta->disk_sectors_high << 32) +
+ meta->disk_sectors) * 512;
}
g_raid_start_volume(vol);
@@ -1213,9 +1263,8 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
const char *nodename, *verb, *volname, *levelname, *diskname;
char *tmp;
int *nargs, *force;
- off_t size, sectorsize, strip;
+ off_t esize, offs[PROMISE_MAX_DISKS], size, sectorsize, strip;
intmax_t *sizearg, *striparg;
- uint32_t offs[PROMISE_MAX_DISKS], esize;
int numdisks, i, len, level, qual;
int error;
@@ -1323,13 +1372,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
cp->private = disk;
g_topology_unlock();
- if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
- gctl_error(req,
- "Disk '%s' is too big.", diskname);
- error = -8;
- break;
- }
-
g_raid_get_disk_info(disk);
/* Reserve some space for metadata. */
@@ -1394,10 +1436,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
gctl_error(req, "Size too small.");
return (-13);
}
- if (size > 0xffffffffllu * sectorsize) {
- gctl_error(req, "Size too big.");
- return (-14);
- }
/* We have all we need, create things: volume, ... */
pv = malloc(sizeof(*pv), M_MD_PROMISE, M_WAITOK | M_ZERO);
@@ -1629,14 +1667,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
pp = cp->provider;
g_topology_unlock();
- if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
- gctl_error(req,
- "Disk '%s' is too big.", diskname);
- g_raid_kill_consumer(sc, cp);
- error = -8;
- break;
- }
-
pd = malloc(sizeof(*pd), M_MD_PROMISE, M_WAITOK | M_ZERO);
disk = g_raid_create_disk(sc);
@@ -1733,9 +1763,9 @@ g_raid_md_write_promise(struct g_raid_md_object *md, struct g_raid_volume *tvol,
vol->v_raid_level == G_RAID_VOLUME_RL_RAID1E)
meta->array_width /= 2;
meta->array_number = vol->v_global_id;
- meta->total_sectors = vol->v_mediasize / vol->v_sectorsize;
- meta->total_sectors_high =
- (vol->v_mediasize / vol->v_sectorsize) >> 32;
+ meta->total_sectors = vol->v_mediasize / 512;
+ meta->total_sectors_high = (vol->v_mediasize / 512) >> 32;
+ meta->sector_size = vol->v_sectorsize / 512;
meta->cylinders = meta->total_sectors / (255 * 63) - 1;
meta->heads = 254;
meta->sectors = 63;
@@ -1828,15 +1858,24 @@ g_raid_md_write_promise(struct g_raid_md_object *md, struct g_raid_volume *tvol,
pd->pd_meta[j] = promise_meta_copy(meta);
pd->pd_meta[j]->disk = meta->disks[pos];
pd->pd_meta[j]->disk.number = pos;
+ pd->pd_meta[j]->disk_offset_high =
+ (sd->sd_offset / 512) >> 32;
pd->pd_meta[j]->disk_offset = sd->sd_offset / 512;
+ pd->pd_meta[j]->disk_sectors_high =
+ (sd->sd_size / 512) >> 32;
pd->pd_meta[j]->disk_sectors = sd->sd_size / 512;
if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD) {
- pd->pd_meta[j]->rebuild_lba =
+ pd->pd_meta[j]->disk_rebuild_high =
+ (sd->sd_rebuild_pos / 512) >> 32;
+ pd->pd_meta[j]->disk_rebuild =
sd->sd_rebuild_pos / 512;
- } else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD)
- pd->pd_meta[j]->rebuild_lba = 0;
- else
- pd->pd_meta[j]->rebuild_lba = UINT32_MAX;
+ } else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD) {
+ pd->pd_meta[j]->disk_rebuild_high = 0;
+ pd->pd_meta[j]->disk_rebuild = 0;
+ } else {
+ pd->pd_meta[j]->disk_rebuild_high = UINT32_MAX;
+ pd->pd_meta[j]->disk_rebuild = UINT32_MAX;
+ }
pd->pd_updated = 1;
}
}
diff --git a/sys/geom/raid/tr_concat.c b/sys/geom/raid/tr_concat.c
index f3935d7..60db472 100644
--- a/sys/geom/raid/tr_concat.c
+++ b/sys/geom/raid/tr_concat.c
@@ -124,7 +124,8 @@ g_raid_tr_update_state_concat(struct g_raid_volume *vol)
* Some metadata modules may not know CONCAT volume
* mediasize until all disks connected. Recalculate.
*/
- if (G_RAID_VOLUME_S_ALIVE(s) &&
+ if (vol->v_raid_level == G_RAID_VOLUME_RL_CONCAT &&
+ G_RAID_VOLUME_S_ALIVE(s) &&
!G_RAID_VOLUME_S_ALIVE(vol->v_state)) {
size = 0;
for (i = 0; i < vol->v_disks_count; i++) {
diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c
index 711e9e1..927cb31 100644
--- a/sys/geom/raid3/g_raid3.c
+++ b/sys/geom/raid3/g_raid3.c
@@ -104,7 +104,8 @@ SYSCTL_UINT(_kern_geom_raid3_stat, OID_AUTO, parity_mismatch, CTLFLAG_RD,
G_RAID3_DEBUG(4, "%s: Woken up %p.", __func__, (ident)); \
} while (0)
-static eventhandler_tag g_raid3_pre_sync = NULL;
+static eventhandler_tag g_raid3_post_sync = NULL;
+static int g_raid3_shutdown = 0;
static int g_raid3_destroy_geom(struct gctl_req *req, struct g_class *mp,
struct g_geom *gp);
@@ -876,7 +877,7 @@ g_raid3_idle(struct g_raid3_softc *sc, int acw)
return (0);
if (acw > 0 || (acw == -1 && sc->sc_provider->acw > 0)) {
timeout = g_raid3_idletime - (time_uptime - sc->sc_last_write);
- if (timeout > 0)
+ if (!g_raid3_shutdown && timeout > 0)
return (timeout);
}
sc->sc_idle = 1;
@@ -3098,7 +3099,7 @@ g_raid3_access(struct g_provider *pp, int acr, int acw, int ace)
error = ENXIO;
goto end;
}
- if (dcw == 0 && !sc->sc_idle)
+ if (dcw == 0)
g_raid3_idle(sc, dcw);
if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_DESTROYING) != 0) {
if (acr > 0 || acw > 0 || ace > 0) {
@@ -3544,7 +3545,7 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
}
static void
-g_raid3_shutdown_pre_sync(void *arg, int howto)
+g_raid3_shutdown_post_sync(void *arg, int howto)
{
struct g_class *mp;
struct g_geom *gp, *gp2;
@@ -3554,6 +3555,7 @@ g_raid3_shutdown_pre_sync(void *arg, int howto)
mp = arg;
DROP_GIANT();
g_topology_lock();
+ g_raid3_shutdown = 1;
LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
if ((sc = gp->softc) == NULL)
continue;
@@ -3562,6 +3564,7 @@ g_raid3_shutdown_pre_sync(void *arg, int howto)
continue;
g_topology_unlock();
sx_xlock(&sc->sc_lock);
+ g_raid3_idle(sc, -1);
g_cancel_event(sc);
error = g_raid3_destroy(sc, G_RAID3_DESTROY_DELAYED);
if (error != 0)
@@ -3576,9 +3579,9 @@ static void
g_raid3_init(struct g_class *mp)
{
- g_raid3_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync,
- g_raid3_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST);
- if (g_raid3_pre_sync == NULL)
+ g_raid3_post_sync = EVENTHANDLER_REGISTER(shutdown_post_sync,
+ g_raid3_shutdown_post_sync, mp, SHUTDOWN_PRI_FIRST);
+ if (g_raid3_post_sync == NULL)
G_RAID3_DEBUG(0, "Warning! Cannot register shutdown event.");
}
@@ -3586,8 +3589,8 @@ static void
g_raid3_fini(struct g_class *mp)
{
- if (g_raid3_pre_sync != NULL)
- EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_raid3_pre_sync);
+ if (g_raid3_post_sync != NULL)
+ EVENTHANDLER_DEREGISTER(shutdown_post_sync, g_raid3_post_sync);
}
DECLARE_GEOM_CLASS(g_raid3_class, g_raid3);
diff --git a/sys/geom/raid3/g_raid3_ctl.c b/sys/geom/raid3/g_raid3_ctl.c
index 952ac2b..b3a42ff 100644
--- a/sys/geom/raid3/g_raid3_ctl.c
+++ b/sys/geom/raid3/g_raid3_ctl.c
@@ -404,7 +404,7 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
u_char *sector;
off_t compsize;
intmax_t *no;
- int *hardcode, *nargs, error;
+ int *hardcode, *nargs, error, autono;
nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
if (nargs == NULL) {
@@ -425,11 +425,10 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "No 'arg%u' argument.", 1);
return;
}
- no = gctl_get_paraml(req, "number", sizeof(*no));
- if (no == NULL) {
- gctl_error(req, "No '%s' argument.", "no");
- return;
- }
+ if (gctl_get_param(req, "number", NULL) != NULL)
+ no = gctl_get_paraml(req, "number", sizeof(*no));
+ else
+ no = NULL;
if (strncmp(name, "/dev/", 5) == 0)
name += 5;
g_topology_lock();
@@ -465,16 +464,30 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "No such device: %s.", name);
goto end;
}
- if (*no >= sc->sc_ndisks) {
- sx_xunlock(&sc->sc_lock);
- gctl_error(req, "Invalid component number.");
- goto end;
- }
- disk = &sc->sc_disks[*no];
- if (disk->d_state != G_RAID3_DISK_STATE_NODISK) {
- sx_xunlock(&sc->sc_lock);
- gctl_error(req, "Component %jd is already connected.", *no);
- goto end;
+ if (no != NULL) {
+ if (*no < 0 || *no >= sc->sc_ndisks) {
+ sx_xunlock(&sc->sc_lock);
+ gctl_error(req, "Invalid component number.");
+ goto end;
+ }
+ disk = &sc->sc_disks[*no];
+ if (disk->d_state != G_RAID3_DISK_STATE_NODISK) {
+ sx_xunlock(&sc->sc_lock);
+ gctl_error(req, "Component %jd is already connected.",
+ *no);
+ goto end;
+ }
+ } else {
+ disk = NULL;
+ for (autono = 0; autono < sc->sc_ndisks && disk == NULL; autono++)
+ if (sc->sc_disks[autono].d_state ==
+ G_RAID3_DISK_STATE_NODISK)
+ disk = &sc->sc_disks[autono];
+ if (disk == NULL) {
+ sx_xunlock(&sc->sc_lock);
+ gctl_error(req, "No disconnected components.");
+ goto end;
+ }
}
if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) {
sx_xunlock(&sc->sc_lock);
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index 3a808ba..47af43b 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -208,7 +208,6 @@ device uart # Generic UART driver
device ppc
device ppbus # Parallel port bus (required)
device lpt # Printer
-device plip # TCP/IP over parallel
device ppi # Parallel port interface device
#device vpo # Requires scbus and da
@@ -346,3 +345,11 @@ device snd_via8233 # VIA VT8233x Audio
device mmc # MMC/SD bus
device mmcsd # MMC/SD memory card
device sdhci # Generic PCI SD Host Controller
+
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI device
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 1868595..95ccd4e 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -771,6 +771,15 @@ device glxiic # AMD Geode LX CS5536 System Management Bus
#
device glxsb # AMD Geode LX Security Block
+#
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI Interface
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
+
#####################################################################
#
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 89c0430..a7046d8 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -1528,11 +1528,11 @@ cpususpend_handler(void)
while (!CPU_ISSET(cpu, &started_cpus))
ia32_pause();
- CPU_CLR_ATOMIC(cpu, &started_cpus);
-
/* Resume MCA and local APIC */
mca_resume();
lapic_setup(0);
+
+ CPU_CLR_ATOMIC(cpu, &started_cpus);
}
/*
* This is called once the rest of the system is up and running and we're
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index d719e80..f6ce067 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$");
* and to when physical maps must be made correct.
*/
+#include "opt_apic.h"
#include "opt_cpu.h"
#include "opt_pmap.h"
#include "opt_smp.h"
@@ -135,6 +136,11 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_reserv.h>
#include <vm/uma.h>
+#ifdef DEV_APIC
+#include <sys/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/apicvar.h>
+#endif
#include <machine/cpu.h>
#include <machine/cputypes.h>
#include <machine/md_var.h>
@@ -1176,6 +1182,16 @@ pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
else if ((cpu_feature & CPUID_CLFSH) != 0 &&
eva - sva < PMAP_CLFLUSH_THRESHOLD) {
+#ifdef DEV_APIC
+ /*
+ * XXX: Some CPUs fault, hang, or trash the local APIC
+ * registers if we use CLFLUSH on the local APIC
+ * range. The local APIC is always uncached, so we
+ * don't need to flush for that range anyway.
+ */
+ if (pmap_kextract(sva) == lapic_paddr)
+ return;
+#endif
/*
* Otherwise, do per-cache line flush. Use the mfence
* instruction to insure that previous stores are
diff --git a/sys/i386/include/intr_machdep.h b/sys/i386/include/intr_machdep.h
index 004ed52..b3dd122 100644
--- a/sys/i386/include/intr_machdep.h
+++ b/sys/i386/include/intr_machdep.h
@@ -94,7 +94,7 @@ struct pic {
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
int (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
- STAILQ_ENTRY(pic) pics;
+ TAILQ_ENTRY(pic) pics;
};
/* Flags for pic_disable_source() */
diff --git a/sys/i386/include/vmparam.h b/sys/i386/include/vmparam.h
index 9cfd692..f974495 100644
--- a/sys/i386/include/vmparam.h
+++ b/sys/i386/include/vmparam.h
@@ -206,9 +206,4 @@
#define VM_MAX_AUTOTUNE_MAXUSERS 384
#endif
-#ifndef VM_MAX_AUTOTUNE_NMBCLUSTERS
-/* old maxusers max value. */
-#define VM_MAX_AUTOTUNE_NMBCLUSTERS (1024 + VM_MAX_AUTOTUNE_MAXUSERS * 64)
-#endif
-
#endif /* _MACHINE_VMPARAM_H_ */
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
index 799259c..87d419f 100644
--- a/sys/i386/linux/linux.h
+++ b/sys/i386/linux/linux.h
@@ -101,11 +101,6 @@ typedef struct {
/*
* Miscellaneous
*/
-#define LINUX_NAME_MAX 255
-#define LINUX_MAX_UTSNAME 65
-
-#define LINUX_CTL_MAXNAME 10
-
#define LINUX_AT_COUNT 16 /* Count of used aux entry types.
* Keep this synchronized with
* elf_linux_fixup() code.
@@ -121,11 +116,6 @@ struct l___sysctl_args
l_ulong __spare[4];
};
-/* Scheduling policies */
-#define LINUX_SCHED_OTHER 0
-#define LINUX_SCHED_FIFO 1
-#define LINUX_SCHED_RR 2
-
/* Resource limits */
#define LINUX_RLIMIT_CPU 0
#define LINUX_RLIMIT_FSIZE 1
@@ -240,15 +230,6 @@ struct l_statfs64 {
l_int f_spare[6];
};
-struct l_new_utsname {
- char sysname[LINUX_MAX_UTSNAME];
- char nodename[LINUX_MAX_UTSNAME];
- char release[LINUX_MAX_UTSNAME];
- char version[LINUX_MAX_UTSNAME];
- char machine[LINUX_MAX_UTSNAME];
- char domainname[LINUX_MAX_UTSNAME];
-};
-
/*
* Signalling
*/
@@ -510,28 +491,10 @@ struct l_rt_sigframe {
l_handler_t sf_handler;
};
-extern int bsd_to_linux_signal[];
-extern int linux_to_bsd_signal[];
extern struct sysentvec linux_sysvec;
extern struct sysentvec elf_linux_sysvec;
/*
- * Pluggable ioctl handlers
- */
-struct linux_ioctl_args;
-struct thread;
-
-typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *);
-
-struct linux_ioctl_handler {
- linux_ioctl_function_t *func;
- int low, high;
-};
-
-int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
-int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
-
-/*
* open/fcntl flags
*/
#define LINUX_O_RDONLY 00000000
@@ -573,65 +536,6 @@ int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
#define LINUX_F_WRLCK 1
#define LINUX_F_UNLCK 2
-/*
- * posix_fadvise advice
- */
-#define LINUX_POSIX_FADV_NORMAL 0
-#define LINUX_POSIX_FADV_RANDOM 1
-#define LINUX_POSIX_FADV_SEQUENTIAL 2
-#define LINUX_POSIX_FADV_WILLNEED 3
-#define LINUX_POSIX_FADV_DONTNEED 4
-#define LINUX_POSIX_FADV_NOREUSE 5
-
-/*
- * mount flags
- */
-#define LINUX_MS_RDONLY 0x0001
-#define LINUX_MS_NOSUID 0x0002
-#define LINUX_MS_NODEV 0x0004
-#define LINUX_MS_NOEXEC 0x0008
-#define LINUX_MS_REMOUNT 0x0020
-
-/*
- * SystemV IPC defines
- */
-#define LINUX_SEMOP 1
-#define LINUX_SEMGET 2
-#define LINUX_SEMCTL 3
-#define LINUX_MSGSND 11
-#define LINUX_MSGRCV 12
-#define LINUX_MSGGET 13
-#define LINUX_MSGCTL 14
-#define LINUX_SHMAT 21
-#define LINUX_SHMDT 22
-#define LINUX_SHMGET 23
-#define LINUX_SHMCTL 24
-
-#define LINUX_IPC_RMID 0
-#define LINUX_IPC_SET 1
-#define LINUX_IPC_STAT 2
-#define LINUX_IPC_INFO 3
-
-#define LINUX_SHM_LOCK 11
-#define LINUX_SHM_UNLOCK 12
-#define LINUX_SHM_STAT 13
-#define LINUX_SHM_INFO 14
-
-#define LINUX_SHM_RDONLY 0x1000
-#define LINUX_SHM_RND 0x2000
-#define LINUX_SHM_REMAP 0x4000
-
-/* semctl commands */
-#define LINUX_GETPID 11
-#define LINUX_GETVAL 12
-#define LINUX_GETALL 13
-#define LINUX_GETNCNT 14
-#define LINUX_GETZCNT 15
-#define LINUX_SETVAL 16
-#define LINUX_SETALL 17
-#define LINUX_SEM_STAT 18
-#define LINUX_SEM_INFO 19
-
union l_semun {
l_int val;
struct l_semid_ds *buf;
@@ -643,25 +547,6 @@ union l_semun {
/*
* Socket defines
*/
-#define LINUX_SOCKET 1
-#define LINUX_BIND 2
-#define LINUX_CONNECT 3
-#define LINUX_LISTEN 4
-#define LINUX_ACCEPT 5
-#define LINUX_GETSOCKNAME 6
-#define LINUX_GETPEERNAME 7
-#define LINUX_SOCKETPAIR 8
-#define LINUX_SEND 9
-#define LINUX_RECV 10
-#define LINUX_SENDTO 11
-#define LINUX_RECVFROM 12
-#define LINUX_SHUTDOWN 13
-#define LINUX_SETSOCKOPT 14
-#define LINUX_GETSOCKOPT 15
-#define LINUX_SENDMSG 16
-#define LINUX_RECVMSG 17
-#define LINUX_ACCEPT4 18
-
#define LINUX_SOL_SOCKET 1
#define LINUX_SOL_IP 0
#define LINUX_SOL_IPX 256
@@ -690,17 +575,6 @@ union l_semun {
#define LINUX_SO_TIMESTAMP 29
#define LINUX_SO_ACCEPTCONN 30
-#define LINUX_IP_TOS 1
-#define LINUX_IP_TTL 2
-#define LINUX_IP_HDRINCL 3
-#define LINUX_IP_OPTIONS 4
-
-#define LINUX_IP_MULTICAST_IF 32
-#define LINUX_IP_MULTICAST_TTL 33
-#define LINUX_IP_MULTICAST_LOOP 34
-#define LINUX_IP_ADD_MEMBERSHIP 35
-#define LINUX_IP_DROP_MEMBERSHIP 36
-
struct l_sockaddr {
l_ushort sa_family;
char sa_data[14];
@@ -860,30 +734,6 @@ struct l_desc_struct {
#define LINUX_GET_USEABLE(desc) \
(((desc)->b >> LINUX_ENTRY_B_USEABLE) & 1)
-#define LINUX_CLOCK_REALTIME 0
-#define LINUX_CLOCK_MONOTONIC 1
-#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
-#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
-#define LINUX_CLOCK_REALTIME_HR 4
-#define LINUX_CLOCK_MONOTONIC_HR 5
-
-#define LINUX_CLONE_VM 0x00000100
-#define LINUX_CLONE_FS 0x00000200
-#define LINUX_CLONE_FILES 0x00000400
-#define LINUX_CLONE_SIGHAND 0x00000800
-#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
-#define LINUX_CLONE_VFORK 0x00004000
-#define LINUX_CLONE_PARENT 0x00008000
-#define LINUX_CLONE_THREAD 0x00010000
-#define LINUX_CLONE_SETTLS 0x00080000
-#define LINUX_CLONE_PARENT_SETTID 0x00100000
-#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
-#define LINUX_CLONE_CHILD_SETTID 0x01000000
-
-#define LINUX_THREADING_FLAGS \
- (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
- LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
-
/* robust futexes */
struct linux_robust_list {
struct linux_robust_list *next;
@@ -895,7 +745,4 @@ struct linux_robust_list_head {
struct linux_robust_list *pending_list;
};
-int linux_set_upcall_kse(struct thread *td, register_t stack);
-int linux_set_cloned_tls(struct thread *td, void *desc);
-
#endif /* !_I386_LINUX_H_ */
diff --git a/sys/i386/linux/linux_ptrace.c b/sys/i386/linux/linux_ptrace.c
index e9559f8..1074d21 100644
--- a/sys/i386/linux/linux_ptrace.c
+++ b/sys/i386/linux/linux_ptrace.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <i386/linux/linux.h>
#include <i386/linux/linux_proto.h>
+#include <compat/linux/linux_signal.h>
#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
#define CPU_ENABLE_SSE
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index d4e23e1..71417e0 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <i386/linux/linux_proto.h>
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_signal.h>
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 00b1c3f..a92b6db 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -325,6 +325,7 @@ print_version(void *data __unused)
while (len > 0 && version[len - 1] == '\n')
len--;
printf("%.*s %s\n", len, version, machine);
+ printf("%s\n", compiler_version);
}
SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t,
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 5e10200..9d62c58 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -382,7 +382,7 @@ static void watchdog_config(void *, u_int, int *);
int stathz;
int profhz;
int profprocs;
-int ticks;
+volatile int ticks;
int psratio;
static DPCPU_DEFINE(int, pcputicks); /* Per-CPU version of ticks. */
@@ -469,7 +469,7 @@ void
hardclock(int usermode, uintfptr_t pc)
{
- atomic_add_int((volatile int *)&ticks, 1);
+ atomic_add_int(&ticks, 1);
hardclock_cpu(usermode);
tc_ticktock(1);
cpu_tick_calibration();
diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
index 05e47e0..6fd40a8 100644
--- a/sys/kern/kern_clocksource.c
+++ b/sys/kern/kern_clocksource.c
@@ -317,14 +317,16 @@ getnextevent(struct bintime *event)
nonidle = !state->idle;
if ((timer->et_flags & ET_FLAGS_PERCPU) == 0) {
#ifdef SMP
- CPU_FOREACH(cpu) {
- if (curcpu == cpu)
- continue;
- state = DPCPU_ID_PTR(cpu, timerstate);
- nonidle += !state->idle;
- if (bintime_cmp(event, &state->nextevent, >)) {
- *event = state->nextevent;
- c = cpu;
+ if (smp_started) {
+ CPU_FOREACH(cpu) {
+ if (curcpu == cpu)
+ continue;
+ state = DPCPU_ID_PTR(cpu, timerstate);
+ nonidle += !state->idle;
+ if (bintime_cmp(event, &state->nextevent, >)) {
+ *event = state->nextevent;
+ c = cpu;
+ }
}
}
#endif
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 6dae173..87d75ea 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -779,8 +779,10 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
if (arg != 0) {
vp = fp->f_vnode;
error = vn_lock(vp, LK_SHARED);
- if (error != 0)
- goto readahead_vnlock_fail;
+ if (error != 0) {
+ fdrop(fp, td);
+ break;
+ }
bsize = fp->f_vnode->v_mount->mnt_stat.f_iosize;
VOP_UNLOCK(vp, 0);
fp->f_seqcount = (arg + bsize - 1) / bsize;
@@ -788,7 +790,6 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
new = old = fp->f_flag;
new |= FRDAHEAD;
} while (!atomic_cmpset_rel_int(&fp->f_flag, old, new));
- readahead_vnlock_fail:;
} else {
do {
new = old = fp->f_flag;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 50b47fb..3a9a3a4 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1024,20 +1024,18 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options,
struct rusage *rusage)
{
struct __wrusage wru, *wrup;
- struct proc *q;
idtype_t idtype;
id_t id;
int ret;
+ /*
+ * Translate the special pid values into the (idtype, pid)
+ * pair for kern_wait6. The WAIT_MYPGRP case is handled by
+ * kern_wait6() on its own.
+ */
if (pid == WAIT_ANY) {
idtype = P_ALL;
id = 0;
- } else if (pid == WAIT_MYPGRP) {
- idtype = P_PGID;
- q = td->td_proc;
- PROC_LOCK(q);
- id = (id_t)q->p_pgid;
- PROC_UNLOCK(q);
} else if (pid < 0) {
idtype = P_PGID;
id = (id_t)-pid;
@@ -1045,10 +1043,12 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options,
idtype = P_PID;
id = (id_t)pid;
}
+
if (rusage != NULL)
wrup = &wru;
else
wrup = NULL;
+
/*
* For backward compatibility we implicitly add flags WEXITED
* and WTRAPPED here.
diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c
index a83cedf..5b9d7aa 100644
--- a/sys/kern/kern_ktr.c
+++ b/sys/kern/kern_ktr.c
@@ -66,6 +66,10 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_output.h>
#endif
+#ifndef KTR_BOOT_ENTRIES
+#define KTR_BOOT_ENTRIES 1024
+#endif
+
#ifndef KTR_ENTRIES
#define KTR_ENTRIES 1024
#endif
@@ -96,9 +100,9 @@ FEATURE(ktr, "Kernel support for KTR kernel tracing facility");
volatile int ktr_idx = 0;
int ktr_mask = KTR_MASK;
int ktr_compile = KTR_COMPILE;
-int ktr_entries = KTR_ENTRIES;
+int ktr_entries = KTR_BOOT_ENTRIES;
int ktr_version = KTR_VERSION;
-struct ktr_entry ktr_buf_init[KTR_ENTRIES];
+struct ktr_entry ktr_buf_init[KTR_BOOT_ENTRIES];
struct ktr_entry *ktr_buf = ktr_buf_init;
cpuset_t ktr_cpumask = CPUSET_T_INITIALIZER(KTR_CPUMASK);
static char ktr_cpumask_str[CPUSETBUFSIZ];
@@ -194,6 +198,28 @@ SYSCTL_PROC(_debug_ktr, OID_AUTO, mask, CTLTYPE_UINT|CTLFLAG_RW, 0, 0,
sysctl_debug_ktr_mask, "IU",
"Bitmask of KTR event classes for which logging is enabled");
+#if KTR_ENTRIES != KTR_BOOT_ENTRIES
+/*
+ * A simplified version of sysctl_debug_ktr_entries.
+ * No need to care about SMP, scheduling, etc.
+ */
+static void
+ktr_entries_initializer(void *dummy __unused)
+{
+ int mask;
+
+ /* Temporarily disable ktr in case malloc() is being traced. */
+ mask = ktr_mask;
+ ktr_mask = 0;
+ ktr_buf = malloc(sizeof(*ktr_buf) * KTR_ENTRIES, M_KTR,
+ M_WAITOK | M_ZERO);
+ ktr_entries = KTR_ENTRIES;
+ ktr_mask = mask;
+}
+SYSINIT(ktr_entries_initializer, SI_SUB_KMEM, SI_ORDER_ANY,
+ ktr_entries_initializer, NULL);
+#endif
+
static int
sysctl_debug_ktr_entries(SYSCTL_HANDLER_ARGS)
{
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index 3bdfd88..2259aa2 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
+#include <vm/vm_map.h>
#include <vm/uma.h>
#include <vm/uma_int.h>
#include <vm/uma_dbg.h>
@@ -104,15 +105,24 @@ int nmbjumbo16; /* limits number of 16k jumbo clusters */
struct mbstat mbstat;
/*
- * tunable_mbinit() has to be run before init_maxsockets() thus
- * the SYSINIT order below is SI_ORDER_MIDDLE while init_maxsockets()
- * runs at SI_ORDER_ANY.
- *
- * NB: This has to be done before VM init.
+ * tunable_mbinit() has to be run before any mbuf allocations are done.
*/
static void
tunable_mbinit(void *dummy)
{
+ quad_t realmem, maxmbufmem;
+
+ /*
+ * The default limit for all mbuf related memory is 1/2 of all
+ * available kernel memory (physical or kmem).
+ * At most it can be 3/4 of available kernel memory.
+ */
+ realmem = qmin((quad_t)physmem * PAGE_SIZE,
+ vm_map_max(kernel_map) - vm_map_min(kernel_map));
+ maxmbufmem = realmem / 2;
+ TUNABLE_QUAD_FETCH("kern.maxmbufmem", &maxmbufmem);
+ if (maxmbufmem > realmem / 4 * 3)
+ maxmbufmem = realmem / 4 * 3;
TUNABLE_INT_FETCH("kern.ipc.nmbclusters", &nmbclusters);
if (nmbclusters == 0)
@@ -139,7 +149,7 @@ tunable_mbinit(void *dummy)
nmbufs = lmax(maxmbufmem / MSIZE / 5,
nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16);
}
-SYSINIT(tunable_mbinit, SI_SUB_TUNABLES, SI_ORDER_MIDDLE, tunable_mbinit, NULL);
+SYSINIT(tunable_mbinit, SI_SUB_KMEM, SI_ORDER_MIDDLE, tunable_mbinit, NULL);
static int
sysctl_nmbclusters(SYSCTL_HANDLER_ARGS)
@@ -279,16 +289,14 @@ static int mb_zinit_pack(void *, int, int);
static void mb_zfini_pack(void *, int);
static void mb_reclaim(void *);
-static void mbuf_init(void *);
static void *mbuf_jumbo_alloc(uma_zone_t, int, uint8_t *, int);
-/* Ensure that MSIZE must be a power of 2. */
+/* Ensure that MSIZE is a power of 2. */
CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE);
/*
* Initialize FreeBSD Network buffer allocation.
*/
-SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL);
static void
mbuf_init(void *dummy)
{
@@ -396,6 +404,7 @@ mbuf_init(void *dummy)
mbstat.sf_iocnt = 0;
mbstat.sf_allocwait = mbstat.sf_allocfail = 0;
}
+SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL);
/*
* UMA backend page allocator for the jumbo frame zones.
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index 29864a8..c84d4b2 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -99,6 +99,9 @@ SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD|CTLFLAG_CAPRD,
SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD|CTLFLAG_MPSAFE,
version, 0, "Kernel version");
+SYSCTL_STRING(_kern, OID_AUTO, compiler_version, CTLFLAG_RD|CTLFLAG_MPSAFE,
+ compiler_version, 0, "Version of compiler used to compile kernel");
+
SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD|CTLFLAG_MPSAFE|
CTLFLAG_CAPRD, ostype, 0, "Operating system type");
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index a08b218..2ffa2f9 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -103,8 +103,8 @@ static struct timecounter *timecounters = &dummy_timecounter;
int tc_min_ticktock_freq = 1;
-time_t time_second = 1;
-time_t time_uptime = 1;
+volatile time_t time_second = 1;
+volatile time_t time_uptime = 1;
struct bintime boottimebin;
struct timeval boottime;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index c41fba0..1d45f28 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -3318,7 +3318,7 @@ resource_list_release(struct resource_list *rl, device_t bus, device_t child,
/**
* @brief Fully release a reserved resource
*
- * Fully releases a resouce reserved via resource_list_reserve().
+ * Fully releases a resource reserved via resource_list_reserve().
*
* @param rl the resource list which was allocated from
* @param bus the parent device of @p child
diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c
index fe10a87..f36c769 100644
--- a/sys/kern/subr_param.c
+++ b/sys/kern/subr_param.c
@@ -93,7 +93,6 @@ int ncallout; /* maximum # of timer events */
int nbuf;
int ngroups_max; /* max # groups per process */
int nswbuf;
-quad_t maxmbufmem; /* max mbuf memory */
pid_t pid_max = PID_MAX;
long maxswzone; /* max swmeta KVA storage */
long maxbcache; /* max buffer cache KVA storage */
@@ -161,6 +160,7 @@ static const char *const vm_bnames[] = {
"Bochs", /* Bochs */
"Xen", /* Xen */
"BHYVE", /* bhyve */
+ "Seabios", /* KVM */
NULL
};
@@ -169,6 +169,7 @@ static const char *const vm_pnames[] = {
"Virtual Machine", /* Microsoft VirtualPC */
"VirtualBox", /* Sun xVM VirtualBox */
"Parallels Virtual Platform", /* Parallels VM */
+ "KVM", /* KVM */
NULL
};
@@ -272,7 +273,6 @@ init_param1(void)
void
init_param2(long physpages)
{
- quad_t realmem;
/* Base parameters */
maxusers = MAXUSERS;
@@ -324,23 +324,14 @@ init_param2(long physpages)
/*
* XXX: Does the callout wheel have to be so big?
+ *
+ * Clip callout to result of previous function of maxusers maximum
+ * 384. This is still huge, but acceptable.
*/
- ncallout = 16 + maxproc + maxfiles;
+ ncallout = imin(16 + maxproc + maxfiles, 18508);
TUNABLE_INT_FETCH("kern.ncallout", &ncallout);
/*
- * The default limit for all mbuf related memory is 1/2 of all
- * available kernel memory (physical or kmem).
- * At most it can be 3/4 of available kernel memory.
- */
- realmem = qmin((quad_t)physpages * PAGE_SIZE,
- VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS);
- maxmbufmem = realmem / 2;
- TUNABLE_QUAD_FETCH("kern.maxmbufmem", &maxmbufmem);
- if (maxmbufmem > (realmem / 4) * 3)
- maxmbufmem = (realmem / 4) * 3;
-
- /*
* The default for maxpipekva is min(1/64 of the kernel address space,
* max(1/64 of main memory, 512KB)). See sys_pipe.c for more details.
*/
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index ab6163d..4606f37 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -85,6 +85,79 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragrandomfailures, CTLFLAG_RW,
#endif
/*
+ * m_get2() allocates minimum mbuf that would fit "size" argument.
+ */
+struct mbuf *
+m_get2(int how, short type, int flags, int size)
+{
+ struct mb_args args;
+ struct mbuf *m, *n;
+ uma_zone_t zone;
+
+ args.flags = flags;
+ args.type = type;
+
+ if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
+ return (uma_zalloc_arg(zone_mbuf, &args, how));
+ if (size <= MCLBYTES)
+ return (uma_zalloc_arg(zone_pack, &args, how));
+ if (size > MJUM16BYTES)
+ return (NULL);
+
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ if (m == NULL)
+ return (NULL);
+
+#if MJUMPAGESIZE != MCLBYTES
+ if (size <= MJUMPAGESIZE)
+ zone = zone_jumbop;
+ else
+#endif
+ if (size <= MJUM9BYTES)
+ zone = zone_jumbo9;
+ else
+ zone = zone_jumbo16;
+
+ n = uma_zalloc_arg(zone, m, how);
+ if (n == NULL) {
+ uma_zfree(zone_mbuf, m);
+ return (NULL);
+ }
+
+ return (m);
+}
+
+/*
+ * m_getjcl() returns an mbuf with a cluster of the specified size attached.
+ * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
+ */
+struct mbuf *
+m_getjcl(int how, short type, int flags, int size)
+{
+ struct mb_args args;
+ struct mbuf *m, *n;
+ uma_zone_t zone;
+
+ if (size == MCLBYTES)
+ return m_getcl(how, type, flags);
+
+ args.flags = flags;
+ args.type = type;
+
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ if (m == NULL)
+ return (NULL);
+
+ zone = m_getzone(size);
+ n = uma_zalloc_arg(zone, m, how);
+ if (n == NULL) {
+ uma_zfree(zone_mbuf, m);
+ return (NULL);
+ }
+ return (m);
+}
+
+/*
* Allocate a given length worth of mbufs and/or clusters (whatever fits
* best) and return a pointer to the top of the allocated chain. If an
* existing mbuf chain is provided, then we will append the new chain
diff --git a/sys/kern/vfs_hash.c b/sys/kern/vfs_hash.c
index aad22e0..0271e49 100644
--- a/sys/kern/vfs_hash.c
+++ b/sys/kern/vfs_hash.c
@@ -54,11 +54,18 @@ vfs_hashinit(void *dummy __unused)
/* Must be SI_ORDER_SECOND so desiredvnodes is available */
SYSINIT(vfs_hash, SI_SUB_VFS, SI_ORDER_SECOND, vfs_hashinit, NULL);
+u_int
+vfs_hash_index(struct vnode *vp)
+{
+
+ return (vp->v_hash + vp->v_mount->mnt_hashseed);
+}
+
static struct vfs_hash_head *
-vfs_hash_index(const struct mount *mp, u_int hash)
+vfs_hash_bucket(const struct mount *mp, u_int hash)
{
- return(&vfs_hash_tbl[(hash + mp->mnt_hashseed) & vfs_hash_mask]);
+ return (&vfs_hash_tbl[(hash + mp->mnt_hashseed) & vfs_hash_mask]);
}
int
@@ -69,7 +76,7 @@ vfs_hash_get(const struct mount *mp, u_int hash, int flags, struct thread *td, s
while (1) {
mtx_lock(&vfs_hash_mtx);
- LIST_FOREACH(vp, vfs_hash_index(mp, hash), v_hashlist) {
+ LIST_FOREACH(vp, vfs_hash_bucket(mp, hash), v_hashlist) {
if (vp->v_hash != hash)
continue;
if (vp->v_mount != mp)
@@ -113,7 +120,7 @@ vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, stru
while (1) {
mtx_lock(&vfs_hash_mtx);
LIST_FOREACH(vp2,
- vfs_hash_index(vp->v_mount, hash), v_hashlist) {
+ vfs_hash_bucket(vp->v_mount, hash), v_hashlist) {
if (vp2->v_hash != hash)
continue;
if (vp2->v_mount != vp->v_mount)
@@ -138,7 +145,7 @@ vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, stru
}
vp->v_hash = hash;
- LIST_INSERT_HEAD(vfs_hash_index(vp->v_mount, hash), vp, v_hashlist);
+ LIST_INSERT_HEAD(vfs_hash_bucket(vp->v_mount, hash), vp, v_hashlist);
mtx_unlock(&vfs_hash_mtx);
return (0);
}
@@ -149,7 +156,7 @@ vfs_hash_rehash(struct vnode *vp, u_int hash)
mtx_lock(&vfs_hash_mtx);
LIST_REMOVE(vp, v_hashlist);
- LIST_INSERT_HEAD(vfs_hash_index(vp->v_mount, hash), vp, v_hashlist);
+ LIST_INSERT_HEAD(vfs_hash_bucket(vp->v_mount, hash), vp, v_hashlist);
vp->v_hash = hash;
mtx_unlock(&vfs_hash_mtx);
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 7c243b6..1c26368 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -279,6 +279,8 @@ SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW,
#define VSHOULDFREE(vp) (!((vp)->v_iflag & VI_FREE) && !(vp)->v_holdcnt)
#define VSHOULDBUSY(vp) (((vp)->v_iflag & VI_FREE) && (vp)->v_holdcnt)
+/* Shift count for (uintptr_t)vp to initialize vp->v_hash. */
+static int vnsz2log;
/*
* Initialize the vnode management data structures.
@@ -293,6 +295,7 @@ SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW,
static void
vntblinit(void *dummy __unused)
{
+ u_int i;
int physvnodes, virtvnodes;
/*
@@ -332,6 +335,9 @@ vntblinit(void *dummy __unused)
syncer_maxdelay = syncer_mask + 1;
mtx_init(&sync_mtx, "Syncer mtx", NULL, MTX_DEF);
cv_init(&sync_wakeup, "syncer");
+ for (i = 1; i <= sizeof(struct vnode); i <<= 1)
+ vnsz2log++;
+ vnsz2log--;
}
SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vntblinit, NULL);
@@ -1067,6 +1073,14 @@ alloc:
}
rangelock_init(&vp->v_rl);
+ /*
+ * For the filesystems which do not use vfs_hash_insert(),
+ * still initialize v_hash to have vfs_hash_index() useful.
+ * E.g., nullfs uses vfs_hash_index() on the lower vnode for
+ * its own hashing.
+ */
+ vp->v_hash = (uintptr_t)vp >> vnsz2log;
+
*vpp = vp;
return (0);
}
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 3f2e523..1a5f2ae 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -187,8 +187,8 @@ sys_quotactl(td, uap)
AUDIT_ARG_UID(uap->uid);
if (!prison_allow(td->td_ucred, PR_ALLOW_QUOTAS))
return (EPERM);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -293,8 +293,8 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF |
- AUDITVNODE1, pathseg, path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, td);
error = namei(&nd);
if (error)
return (error);
@@ -871,8 +871,8 @@ sys_chroot(td, uap)
error = priv_check(td, PRIV_VFS_CHROOT);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF |
- AUDITVNODE1, UIO_USERSPACE, uap->path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
+ UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
goto error;
@@ -1077,8 +1077,8 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
/* Set the flags early so the finit in devfs can pick them up. */
fp->f_flag = flags & FMASK;
cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
- NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg,
- path, fd, rights_needed, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
+ rights_needed, td);
td->td_dupfd = -1; /* XXX check for fdopen */
error = vn_open(&nd, &flags, cmode, fp);
if (error) {
@@ -1108,7 +1108,7 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
if (error == ERESTART)
error = EINTR;
- goto bad_unlocked;
+ goto bad;
}
td->td_dupfd = 0;
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -1150,12 +1150,11 @@ success:
*/
if ((error = kern_capwrap(td, fp, nd.ni_baserights,
&indx)) != 0)
- goto bad_unlocked;
+ goto bad;
} else
#endif
if ((error = finstall(td, fp, &indx, flags)) != 0)
- goto bad_unlocked;
-
+ goto bad;
}
/*
@@ -1166,7 +1165,6 @@ success:
td->td_retval[0] = indx;
return (0);
bad:
-bad_unlocked:
KASSERT(indx == -1, ("indx=%d, should be -1", indx));
fdrop(fp, td);
return (error);
@@ -1279,9 +1277,8 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
return (error);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE,
- LOCKPARENT | SAVENAME | AUDITVNODE1, pathseg, path, fd,
- CAP_MKNOD, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
+ pathseg, path, fd, CAP_MKNOD, td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -1400,9 +1397,8 @@ kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_MODE(mode);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE,
- LOCKPARENT | SAVENAME | AUDITVNODE1, pathseg, path, fd,
- CAP_MKFIFO, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
+ pathseg, path, fd, CAP_MKFIFO, td);
if ((error = namei(&nd)) != 0)
return (error);
if (nd.ni_vp != NULL) {
@@ -1541,8 +1537,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
int error;
bwillwrite();
- NDINIT_AT(&nd, LOOKUP, follow | AUDITVNODE1, segflg, path1,
- fd1, td);
+ NDINIT_AT(&nd, LOOKUP, follow | AUDITVNODE1, segflg, path1, fd1, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -1556,8 +1551,8 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
vrele(vp);
return (error);
}
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME |
- AUDITVNODE2, segflg, path2, fd2, CAP_CREATE, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2,
+ segflg, path2, fd2, CAP_CREATE, td);
if ((error = namei(&nd)) == 0) {
if (nd.ni_vp != NULL) {
if (nd.ni_dvp == nd.ni_vp)
@@ -1649,8 +1644,8 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2,
AUDIT_ARG_TEXT(syspath);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME |
- AUDITVNODE1, segflg, path2, fd, CAP_CREATE, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
+ segflg, path2, fd, CAP_CREATE, td);
if ((error = namei(&nd)) != 0)
goto out;
if (nd.ni_vp) {
@@ -1801,8 +1796,8 @@ kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF |
- AUDITVNODE1, pathseg, path, fd, CAP_DELETE, td);
+ NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, fd, CAP_DELETE, td);
if ((error = namei(&nd)) != 0)
return (error == EINVAL ? EPERM : error);
vp = nd.ni_vp;
@@ -2309,8 +2304,8 @@ kern_statat_vnhook(struct thread *td, int flag, int fd, char *path,
return (EINVAL);
NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :
- FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg,
- path, fd, CAP_FSTAT, td);
+ FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd,
+ CAP_FSTAT, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2486,7 +2481,8 @@ sys_lpathconf(td, uap)
} */ *uap;
{
- return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name, NOFOLLOW));
+ return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name,
+ NOFOLLOW));
}
int
@@ -2572,8 +2568,8 @@ kern_readlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
if (count > IOSIZE_MAX)
return (EINVAL);
- NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF |
- AUDITVNODE1, pathseg, path, fd, td);
+ NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, fd, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2670,8 +2666,7 @@ sys_chflags(td, uap)
struct nameidata nd;
AUDIT_ARG_FFLAGS(uap->flags);
- NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE,
- uap->path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2695,8 +2690,8 @@ sys_lchflags(td, uap)
struct nameidata nd;
AUDIT_ARG_FFLAGS(uap->flags);
- NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
- uap->path, td);
+ NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path,
+ td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2852,8 +2847,8 @@ kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_MODE(mode);
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
- NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg,
- path, fd, CAP_FCHMOD, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
+ CAP_FCHMOD, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2982,8 +2977,8 @@ kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_OWNER(uid, gid);
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
- NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg,
- path, fd, CAP_FCHOWN, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
+ CAP_FCHOWN, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3188,8 +3183,8 @@ kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
return (error);
- NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg,
- path, fd, CAP_FUTIMES, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
+ CAP_FUTIMES, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3510,8 +3505,8 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |
AUDITVNODE1, pathseg, old, oldfd, CAP_DELETE, td);
#else
- NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART |
- AUDITVNODE1, pathseg, old, oldfd, CAP_DELETE, td);
+ NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1,
+ pathseg, old, oldfd, CAP_DELETE, td);
#endif
if ((error = namei(&fromnd)) != 0)
@@ -3656,8 +3651,8 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg,
AUDIT_ARG_MODE(mode);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME |
- AUDITVNODE1, segflg, path, fd, CAP_MKDIR, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
+ segflg, path, fd, CAP_MKDIR, td);
nd.ni_cnd.cn_flags |= WILLBEDIR;
if ((error = namei(&nd)) != 0)
return (error);
@@ -3740,8 +3735,8 @@ kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg)
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF |
- AUDITVNODE1, pathseg, path, fd, CAP_RMDIR, td);
+ NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, fd, CAP_RMDIR, td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -4123,8 +4118,8 @@ sys_revoke(td, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -4230,8 +4225,8 @@ sys_lgetfh(td, uap)
error = priv_check(td, PRIV_VFS_GETFH);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->fname, td);
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ uap->fname, td);
error = namei(&nd);
if (error)
return (error);
@@ -4266,8 +4261,8 @@ sys_getfh(td, uap)
error = priv_check(td, PRIV_VFS_GETFH);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->fname, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ uap->fname, td);
error = namei(&nd);
if (error)
return (error);
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index bbe837a..4ebf4b5 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1642,7 +1642,7 @@ vfs_write_suspend(mp)
else
MNT_IUNLOCK(mp);
if ((error = VFS_SYNC(mp, MNT_SUSPEND)) != 0)
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
return (error);
}
@@ -1650,7 +1650,7 @@ vfs_write_suspend(mp)
* Request a filesystem to resume write operations.
*/
void
-vfs_write_resume_flags(struct mount *mp, int flags)
+vfs_write_resume(struct mount *mp, int flags)
{
MNT_ILOCK(mp);
@@ -1677,23 +1677,14 @@ vfs_write_resume_flags(struct mount *mp, int flags)
}
}
-void
-vfs_write_resume(struct mount *mp)
-{
-
- vfs_write_resume_flags(mp, 0);
-}
-
/*
* Implement kqueues for files by translating it to vnode operation.
*/
static int
vn_kqfilter(struct file *fp, struct knote *kn)
{
- int error;
- error = VOP_KQFILTER(fp->f_vnode, kn);
- return (error);
+ return (VOP_KQFILTER(fp->f_vnode, kn));
}
/*
diff --git a/sys/libkern/arm/divsi3.S b/sys/libkern/arm/divsi3.S
index 00bacfa..700ae37 100644
--- a/sys/libkern/arm/divsi3.S
+++ b/sys/libkern/arm/divsi3.S
@@ -49,6 +49,10 @@ ENTRY_NP(__modsi3)
#endif
RET
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_uidiv)
+ENTRY_NP(__aeabi_uidivmod)
+#endif
ENTRY_NP(__udivsi3)
.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */
eor r0, r1, r0
@@ -71,6 +75,10 @@ ENTRY_NP(__udivsi3)
mov r1, #0
RET
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_idiv)
+ENTRY_NP(__aeabi_idivmod)
+#endif
ENTRY_NP(__divsi3)
.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */
eor r0, r1, r0
diff --git a/sys/libkern/arm/ldivmod.S b/sys/libkern/arm/ldivmod.S
new file mode 100644
index 0000000..a88db54
--- /dev/null
+++ b/sys/libkern/arm/ldivmod.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef __ARM_EABI__
+
+/*
+ * These calculate:
+ * q = n / m
+ * With a remainer r.
+ *
+ * They take n in {r0, r1} and m in {r2, r3} then pass them into the
+ * helper function. The hepler functions return q in {r0, r1} as
+ * required by the API spec however r is returned on the stack. The
+ * ABI required us to return r in {r2, r3}.
+ *
+ * We need to allocate 8 bytes on the stack to store r, the link
+ * register, and a pointer to the space where the helper function
+ * will write r to. After returning from the helper fuinction we load
+ * the old link register and r from the stack and return.
+ */
+ENTRY_NP(__aeabi_ldivmod)
+ sub sp, sp, #8 /* Space for the remainder */
+ stmfd sp!, {sp, lr} /* Save a pointer to the above space and lr */
+ bl PIC_SYM(_C_LABEL(__kern_ldivmod), PLT)
+ ldr lr, [sp, #4] /* Restore lr */
+ add sp, sp, #8 /* Move sp to the remainder value */
+ ldmfd sp!, {r2, r3} /* Load the remainder */
+ RET
+
+ENTRY_NP(__aeabi_uldivmod)
+ sub sp, sp, #8 /* Space for the remainder */
+ stmfd sp!, {sp, lr} /* Save a pointer to the above space and lr */
+ bl PIC_SYM(_C_LABEL(__qdivrem), PLT)
+ ldr lr, [sp, #4] /* Restore lr */
+ add sp, sp, #8 /* Move sp to the remainder value */
+ ldmfd sp!, {r2, r3} /* Load the remainder */
+ RET
+
+#endif
+
diff --git a/sys/libkern/arm/ldivmod_helper.c b/sys/libkern/arm/ldivmod_helper.c
new file mode 100644
index 0000000..9061ae4
--- /dev/null
+++ b/sys/libkern/arm/ldivmod_helper.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef __ARM_EABI__
+#include <libkern/quad.h>
+
+/*
+ * Helper for __aeabi_ldivmod.
+ * TODO: __divdi3 calls __qdivrem. We should do the same and use the
+ * remainder value rather than re-calculating it.
+ */
+long long __kern_ldivmod(long long, long long, long long *);
+
+long long
+__kern_ldivmod(long long n, long long m, long long *rem)
+{
+ long long q;
+
+ q = __divdi3(n, m); /* q = n / m */
+ *rem = n - m * q;
+
+ return q;
+}
+
+#endif
+
diff --git a/sys/libkern/quad.h b/sys/libkern/quad.h
index 5d4f844..4850d89 100644
--- a/sys/libkern/quad.h
+++ b/sys/libkern/quad.h
@@ -110,4 +110,9 @@ u_quad_t __udivdi3(u_quad_t a, u_quad_t b);
u_quad_t __umoddi3(u_quad_t a, u_quad_t b);
int __ucmpdi2(u_quad_t a, u_quad_t b);
+/* ARM EABI support functions. */
+#ifdef __ARM_EABI__
+int __aeabi_ulcmp(unsigned long long, unsigned long long);
+#endif
+
#endif /* !_LIBKERN_QUAD_H_ */
diff --git a/sys/libkern/ucmpdi2.c b/sys/libkern/ucmpdi2.c
index 376d9c4..cd41c69 100644
--- a/sys/libkern/ucmpdi2.c
+++ b/sys/libkern/ucmpdi2.c
@@ -51,3 +51,15 @@ __ucmpdi2(a, b)
return (aa.ul[H] < bb.ul[H] ? 0 : aa.ul[H] > bb.ul[H] ? 2 :
aa.ul[L] < bb.ul[L] ? 0 : aa.ul[L] > bb.ul[L] ? 2 : 1);
}
+
+#ifdef __ARM_EABI__
+/*
+ * Return -1, 0 or 1 as a <, =, > b respectively.
+ */
+int
+__aeabi_ulcmp(unsigned long long a, unsigned long long b)
+{
+ return __ucmpdi2(a, b) - 1;
+}
+#endif
+
diff --git a/sys/mips/beri/beri_machdep.c b/sys/mips/beri/beri_machdep.c
index f2ef5a7..98fcb85a 100644
--- a/sys/mips/beri/beri_machdep.c
+++ b/sys/mips/beri/beri_machdep.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/cpu.h>
#include <sys/cons.h>
#include <sys/exec.h>
+#include <sys/linker.h>
#include <sys/ucontext.h>
#include <sys/proc.h>
#include <sys/kdb.h>
@@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
+#include <machine/metadata.h>
#include <machine/pmap.h>
#include <machine/trap.h>
@@ -87,17 +89,6 @@ mips_init(void)
{
int i;
-#ifdef FDT
-#ifndef FDT_DTB_STATIC
-#error "mips_init with FDT requires FDT_DTB_STATIC"
-#endif
-
- if (OF_install(OFW_FDT, 0) == FALSE)
- while (1);
- if (OF_init(&fdt_static_dtb) != 0)
- while (1);
-#endif
-
for (i = 0; i < 10; i++) {
phys_avail[i] = 0;
}
@@ -146,6 +137,10 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
char **argv = (char **)a1;
char **envp = (char **)a2;
unsigned int memsize = a3;
+#ifdef FDT
+ vm_offset_t dtbp;
+ void *kmdp;
+#endif
int i;
/* clear the BSS and SBSS segments */
@@ -156,6 +151,33 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
mips_pcpu0_init();
+#ifdef FDT
+ /*
+ * Find the dtb passed in by the boot loader (currently fictional).
+ */
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp != NULL)
+ dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
+ else
+ dtbp = (vm_offset_t)NULL;
+
+#if defined(FDT_DTB_STATIC)
+ /*
+ * In case the device tree blob was not retrieved (from metadata) try
+ * to use the statically embedded one.
+ */
+ if (dtbp == (vm_offset_t)NULL)
+ dtbp = (vm_offset_t)&fdt_static_dtb;
+#else
+#error "Non-static FDT not yet supported on BERI"
+#endif
+
+ if (OF_install(OFW_FDT, 0) == FALSE)
+ while (1);
+ if (OF_init(&fdt_static_dtb) != 0)
+ while (1);
+#endif
+
/*
* XXXRW: We have no way to compare wallclock time to cycle rate on
* BERI, so for now assume we run at the MALTA default (100MHz).
diff --git a/sys/mips/beri/files.beri b/sys/mips/beri/files.beri
index 02a27f8..6794793 100644
--- a/sys/mips/beri/files.beri
+++ b/sys/mips/beri/files.beri
@@ -1,10 +1,13 @@
# $FreeBSD$
dev/altera/jtag_uart/altera_jtag_uart_cons.c optional altera_jtag_uart
dev/altera/jtag_uart/altera_jtag_uart_tty.c optional altera_jtag_uart
+dev/altera/jtag_uart/altera_jtag_uart_fdt.c optional altera_jtag_uart fdt
dev/altera/jtag_uart/altera_jtag_uart_nexus.c optional altera_jtag_uart
dev/terasic/de4led/terasic_de4led.c optional terasic_de4led
+dev/terasic/de4led/terasic_de4led_fdt.c optional terasic_de4led fdt
dev/terasic/de4led/terasic_de4led_nexus.c optional terasic_de4led
dev/terasic/mtl/terasic_mtl.c optional terasic_mtl
+dev/terasic/mtl/terasic_mtl_fdt.c optional terasic_mtl fdt
dev/terasic/mtl/terasic_mtl_nexus.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_pixel.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_reg.c optional terasic_mtl
diff --git a/sys/mips/include/bus.h b/sys/mips/include/bus.h
index b904a5d..6825b23 100644
--- a/sys/mips/include/bus.h
+++ b/sys/mips/include/bus.h
@@ -728,6 +728,8 @@ void __bs_c(f,_bs_c_8) (void *t, bus_space_handle_t bsh1, \
*/
DECLARE_BUS_SPACE_PROTOTYPES(generic);
extern bus_space_tag_t mips_bus_space_generic;
+extern bus_space_tag_t mips_bus_space_fdt;
+
/* Special bus space for RMI processors */
#if defined(CPU_RMI) || defined (CPU_NLM)
extern bus_space_tag_t rmi_bus_space;
diff --git a/sys/mips/include/fdt.h b/sys/mips/include/fdt.h
index 3b20a72..2f1fda5 100644
--- a/sys/mips/include/fdt.h
+++ b/sys/mips/include/fdt.h
@@ -51,7 +51,7 @@
#if defined(CPU_RMI) || defined(CPU_NLM)
#define fdtbus_bs_tag rmi_uart_bus_space
#else
-#define fdtbus_bs_tag NULL
+#define fdtbus_bs_tag mips_bus_space_fdt
#endif
#endif /* _MACHINE_FDT_H_ */
diff --git a/sys/mips/include/metadata.h b/sys/mips/include/metadata.h
index 84e6f87..779c2f6 100644
--- a/sys/mips/include/metadata.h
+++ b/sys/mips/include/metadata.h
@@ -30,5 +30,6 @@
#define _MACHINE_METADATA_H_
#define MODINFOMD_SMAP 0x1001
+#define MODINFOMD_DTBP 0x1002
#endif /* !_MACHINE_METADATA_H_ */
diff --git a/sys/mips/include/vmparam.h b/sys/mips/include/vmparam.h
index aa0a5d7..ef97336 100644
--- a/sys/mips/include/vmparam.h
+++ b/sys/mips/include/vmparam.h
@@ -130,10 +130,11 @@
#endif
/*
- * Ceiling on amount of kmem_map kva space.
+ * Ceiling on the amount of kmem_map KVA space: 40% of the entire KVA space.
*/
#ifndef VM_KMEM_SIZE_MAX
-#define VM_KMEM_SIZE_MAX (200 * 1024 * 1024)
+#define VM_KMEM_SIZE_MAX ((VM_MAX_KERNEL_ADDRESS - \
+ VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5)
#endif
/* initial pagein size of beginning of executable file */
diff --git a/sys/mips/mips/bus_space_fdt.c b/sys/mips/mips/bus_space_fdt.c
new file mode 100644
index 0000000..38efea1
--- /dev/null
+++ b/sys/mips/mips/bus_space_fdt.c
@@ -0,0 +1,212 @@
+/* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */
+/*-
+ * $Id: bus.h,v 1.6 2007/08/09 11:23:32 katta Exp $
+ *
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: src/sys/alpha/include/bus.h,v 1.5 1999/08/28 00:38:40 peter
+ * $FreeBSD$
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/ktr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/cache.h>
+
+static int fdt_bs_map(void *, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
+
+static struct bus_space fdt_space = {
+ /* cookie */
+ (void *) 0,
+
+ /* mapping/unmapping */
+ fdt_bs_map,
+ generic_bs_unmap,
+ generic_bs_subregion,
+
+ /* allocation/deallocation */
+ generic_bs_alloc,
+ generic_bs_free,
+
+ /* barrier */
+ generic_bs_barrier,
+
+ /* read (single) */
+ generic_bs_r_1,
+ generic_bs_r_2,
+ generic_bs_r_4,
+ generic_bs_r_8,
+
+ /* read multiple */
+ generic_bs_rm_1,
+ generic_bs_rm_2,
+ generic_bs_rm_4,
+ generic_bs_rm_8,
+
+ /* read region */
+ generic_bs_rr_1,
+ generic_bs_rr_2,
+ generic_bs_rr_4,
+ generic_bs_rr_8,
+
+ /* write (single) */
+ generic_bs_w_1,
+ generic_bs_w_2,
+ generic_bs_w_4,
+ generic_bs_w_8,
+
+ /* write multiple */
+ generic_bs_wm_1,
+ generic_bs_wm_2,
+ generic_bs_wm_4,
+ generic_bs_wm_8,
+
+ /* write region */
+ generic_bs_wr_1,
+ generic_bs_wr_2,
+ generic_bs_wr_4,
+ generic_bs_wr_8,
+
+ /* set multiple */
+ generic_bs_sm_1,
+ generic_bs_sm_2,
+ generic_bs_sm_4,
+ generic_bs_sm_8,
+
+ /* set region */
+ generic_bs_sr_1,
+ generic_bs_sr_2,
+ generic_bs_sr_4,
+ generic_bs_sr_8,
+
+ /* copy */
+ generic_bs_c_1,
+ generic_bs_c_2,
+ generic_bs_c_4,
+ generic_bs_c_8,
+
+ /* read (single) stream */
+ generic_bs_r_1,
+ generic_bs_r_2,
+ generic_bs_r_4,
+ generic_bs_r_8,
+
+ /* read multiple stream */
+ generic_bs_rm_1,
+ generic_bs_rm_2,
+ generic_bs_rm_4,
+ generic_bs_rm_8,
+
+ /* read region stream */
+ generic_bs_rr_1,
+ generic_bs_rr_2,
+ generic_bs_rr_4,
+ generic_bs_rr_8,
+
+ /* write (single) stream */
+ generic_bs_w_1,
+ generic_bs_w_2,
+ generic_bs_w_4,
+ generic_bs_w_8,
+
+ /* write multiple stream */
+ generic_bs_wm_1,
+ generic_bs_wm_2,
+ generic_bs_wm_4,
+ generic_bs_wm_8,
+
+ /* write region stream */
+ generic_bs_wr_1,
+ generic_bs_wr_2,
+ generic_bs_wr_4,
+ generic_bs_wr_8,
+};
+
+/* generic bus_space tag */
+bus_space_tag_t mips_bus_space_fdt = &fdt_space;
+
+static int
+fdt_bs_map(void *t __unused, bus_addr_t addr, bus_size_t size __unused,
+ int flags __unused, bus_space_handle_t *bshp)
+{
+
+ *bshp = MIPS_PHYS_TO_DIRECT_UNCACHED(addr);
+ return (0);
+}
diff --git a/sys/mips/nlm/dev/net/mdio.c b/sys/mips/nlm/dev/net/mdio.c
index ed2abe4..0845339 100644
--- a/sys/mips/nlm/dev/net/mdio.c
+++ b/sys/mips/nlm/dev/net/mdio.c
@@ -149,7 +149,8 @@ nlm_int_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
uint32_t val;
val = (7 << INT_MDIO_CTRL_XDIV_POS) |
- (1 << INT_MDIO_CTRL_MCDIV_POS);
+ (1 << INT_MDIO_CTRL_MCDIV_POS) |
+ (INT_MDIO_CTRL_SMP);
nlm_write_nae_reg(nae_base,
NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
@@ -302,10 +303,13 @@ nlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
{
uint32_t ctrlval;
+ ctrlval = nlm_read_nae_reg(nae_base,
+ NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)));
+
if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax())
- ctrlval = EXT_G_MDIO_DIV;
+ ctrlval |= EXT_G_MDIO_DIV;
else
- ctrlval = EXT_G_MDIO_DIV_WITH_HW_DIV64;
+ ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64;
nlm_write_nae_reg(nae_base,
NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)),
@@ -314,3 +318,16 @@ nlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), ctrlval);
return (0);
}
+
+/*
+ * nlm_mdio_reset_all : reset all internal and external MDIO
+ */
+void
+nlm_mdio_reset_all(uint64_t nae_base)
+{
+ /* reset internal MDIO */
+ nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
+ /* reset external MDIO */
+ nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
+ nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG);
+}
diff --git a/sys/mips/nlm/dev/net/nae.c b/sys/mips/nlm/dev/net/nae.c
index dce4836..d97b290 100644
--- a/sys/mips/nlm/dev/net/nae.c
+++ b/sys/mips/nlm/dev/net/nae.c
@@ -1427,9 +1427,8 @@ nlm_nae_open_if(uint64_t nae_base, int nblock, int port_type,
int port, uint32_t desc_size)
{
uint32_t netwk_inf;
- uint32_t mac_cfg1, mac_cfg2, netior_ctrl3;
- int iface, speed, duplex, ifmode;
- int iface_ctrl_reg, iface_ctrl3_reg, conf1_reg, conf2_reg;
+ uint32_t mac_cfg1, netior_ctrl3;
+ int iface, iface_ctrl_reg, iface_ctrl3_reg, conf1_reg, conf2_reg;
switch (port_type) {
case XAUIC:
@@ -1487,6 +1486,7 @@ nlm_nae_open_if(uint64_t nae_base, int nblock, int port_type,
/* clear gmac reset */
mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
nlm_write_nae_reg(nae_base, conf1_reg, mac_cfg1 & ~(1 << 31));
+
/* clear speed debug bit */
iface_ctrl3_reg = SGMII_NET_IFACE_CTRL3(nblock, iface);
netior_ctrl3 = nlm_read_nae_reg(nae_base, iface_ctrl3_reg);
@@ -1500,33 +1500,21 @@ nlm_nae_open_if(uint64_t nae_base, int nblock, int port_type,
nlm_write_nae_reg(nae_base, iface_ctrl_reg,
netwk_inf & ~(0x1 << 2));
- /* setup defaults */ /* XXXJC: take defaults from sc? */
- speed = 2;
- duplex = 1;
- ifmode = 0x2;
- netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
- netwk_inf &= ~(0x3);
- nlm_write_nae_reg(nae_base, iface_ctrl_reg,
- netwk_inf | (speed & 0x3));
- mac_cfg2 = nlm_read_nae_reg(nae_base, conf2_reg);
- mac_cfg2 &= ~(0x3 << 8);
- nlm_write_nae_reg(nae_base, conf2_reg,
- mac_cfg2 |
- ((ifmode & 0x3) << 8) | /* interface mode */
- (duplex & 0x1));
-
/* clear stats counters */
netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
nlm_write_nae_reg(nae_base, iface_ctrl_reg,
netwk_inf | (1 << 15));
+
/* enable stats counters */
netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
nlm_write_nae_reg(nae_base, iface_ctrl_reg,
(netwk_inf & ~(1 << 15)) | (1 << 16));
+
+ /* flow control? */
mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
nlm_write_nae_reg(nae_base, conf1_reg,
mac_cfg1 | (0x3 << 4));
- break;
+ break;
}
nlm_nae_init_ingress(nae_base, desc_size);
diff --git a/sys/mips/nlm/dev/net/sgmii.c b/sys/mips/nlm/dev/net/sgmii.c
index 91f5f7a..18b1411 100644
--- a/sys/mips/nlm/dev/net/sgmii.c
+++ b/sys/mips/nlm/dev/net/sgmii.c
@@ -69,13 +69,6 @@ nlm_configure_sgmii_interface(uint64_t nae_base, int block, int port,
void
nlm_sgmii_pcs_init(uint64_t nae_base, uint32_t cplx_mask)
{
- /* reset internal MDIO */
- nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
-
- /* reset external MDIO */
- nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
- nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG);
-
xlp_nae_config_lane_gmac(nae_base, cplx_mask);
}
diff --git a/sys/mips/nlm/dev/net/xlpge.c b/sys/mips/nlm/dev/net/xlpge.c
index 0e41559..6d221e4 100644
--- a/sys/mips/nlm/dev/net/xlpge.c
+++ b/sys/mips/nlm/dev/net/xlpge.c
@@ -444,6 +444,8 @@ nlm_xlpnae_init(int node, struct nlm_xlpnae_softc *sc)
val = nlm_set_device_frequency(node, DFS_DEVICE_NAE, sc->freq);
printf("Setup NAE frequency to %dMHz\n", val);
+ nlm_mdio_reset_all(nae_base);
+
printf("Initialze SGMII PCS for blocks 0x%x\n", sc->sgmiimask);
nlm_sgmii_pcs_init(nae_base, sc->sgmiimask);
@@ -797,8 +799,9 @@ nlm_xlpge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
nlm_xlpge_init(sc);
- nlm_xlpge_mac_set_rx_mode(sc);
- nlm_xlpge_port_enable(sc);
+ else
+ nlm_xlpge_port_enable(sc);
+ nlm_xlpge_mac_set_rx_mode(sc);
sc->link = NLM_LINK_UP;
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -866,6 +869,7 @@ xlpge_tx(struct ifnet *ifp, struct mbuf *mbuf_chain)
vm_offset_t buf = (vm_offset_t) m->m_data;
int len = m->m_len;
int frag_sz;
+ uint64_t desc;
/*printf("m_data = %p len %d\n", m->m_data, len); */
while (len) {
@@ -880,8 +884,9 @@ xlpge_tx(struct ifnet *ifp, struct mbuf *mbuf_chain)
frag_sz = PAGE_SIZE - (buf & PAGE_MASK);
if (len < frag_sz)
frag_sz = len;
- p2p->frag[pos] = nae_tx_desc(P2D_NEOP, 0, 127,
+ desc = nae_tx_desc(P2D_NEOP, 0, 127,
frag_sz, paddr);
+ p2p->frag[pos] = htobe64(desc);
pos++;
len -= frag_sz;
buf += frag_sz;
@@ -891,7 +896,7 @@ xlpge_tx(struct ifnet *ifp, struct mbuf *mbuf_chain)
KASSERT(pos != 0, ("Zero-length mbuf chain?\n"));
/* Make the last one P2D EOP */
- p2p->frag[pos-1] |= (uint64_t)P2D_EOP << 62;
+ p2p->frag[pos-1] |= htobe64((uint64_t)P2D_EOP << 62);
/* stash useful pointers in the desc */
p2p->frag[XLP_NTXFRAGS-3] = 0xf00bad;
@@ -1128,7 +1133,8 @@ get_buf(void)
if ((m_new = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR)) == NULL)
return (NULL);
m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
- m_adj(m_new, NAE_CACHELINE_SIZE - ((uintptr_t)m_new->m_data & 0x1f));
+ KASSERT(((uintptr_t)m_new->m_data & (NAE_CACHELINE_SIZE - 1)) == 0,
+ ("m_new->m_data is not cacheline aligned"));
md = (uint64_t *)m_new->m_data;
md[0] = (intptr_t)m_new; /* Back Ptr */
md[1] = 0xf00bad;
@@ -1137,10 +1143,9 @@ get_buf(void)
#ifdef INVARIANTS
temp1 = vtophys((vm_offset_t) m_new->m_data);
temp2 = vtophys((vm_offset_t) m_new->m_data + 1536);
- KASSERT(temp1 + 1536) != temp2,
+ KASSERT((temp1 + 1536) != temp2,
("Alloced buffer is not contiguous"));
#endif
-
return ((void *)m_new->m_data);
}
@@ -1288,6 +1293,7 @@ nlm_xlpge_attach(device_t dev)
nlm_xlpge_ifinit(sc);
ifp_ports[port].xlpge_sc = sc;
nlm_xlpge_mii_init(dev, sc);
+
nlm_xlpge_setup_stats_sysctl(dev, sc);
return (0);
@@ -1364,13 +1370,13 @@ nlm_xlpge_mii_statchg(device_t dev)
if (mii->mii_media_status & IFM_ACTIVE) {
if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) {
sc->speed = NLM_SGMII_SPEED_10;
- speed = "10-Mbps";
+ speed = "10Mbps";
} else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {
sc->speed = NLM_SGMII_SPEED_100;
- speed = "100-Mbps";
+ speed = "100Mbps";
} else { /* default to 1G */
sc->speed = NLM_SGMII_SPEED_1000;
- speed = "1-Gbps";
+ speed = "1Gbps";
}
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
@@ -1381,11 +1387,11 @@ nlm_xlpge_mii_statchg(device_t dev)
duplexity = "half";
}
- printf("Setup [complex=%d, port=%d] with speed=%s duplex=%s\n",
+ printf("Port [%d, %d] setup with speed=%s duplex=%s\n",
sc->block, sc->port, speed, duplexity);
nlm_nae_setup_mac(sc->base_addr, sc->block, sc->port, 0, 1, 1,
- sc->speed, sc->duplexity);
+ sc->speed, sc->duplexity);
}
}
@@ -1548,7 +1554,7 @@ nlm_xlpge_msgring_handler(int vc, int size, int code, int src_id,
ifp->if_opackets++;
} else if (size > 1) { /* Recieve packet */
- phys_addr = msg->msg[1] & 0xffffffffe0ULL;
+ phys_addr = msg->msg[1] & 0xffffffffc0ULL;
length = (msg->msg[1] >> 40) & 0x3fff;
length -= MAC_CRC_LEN;
diff --git a/sys/mips/nlm/hal/fmn.c b/sys/mips/nlm/hal/fmn.c
index 6d40134..8ebc7537 100644
--- a/sys/mips/nlm/hal/fmn.c
+++ b/sys/mips/nlm/hal/fmn.c
@@ -138,9 +138,9 @@ uint32_t nlm_cms_total_stations = 18 * 4 /*xlp_num_nodes*/;
void nlm_cms_setup_credits(uint64_t base, int destid, int srcid, int credit)
{
- uint32_t val;
+ uint64_t val;
- val = ((credit << 24) | (destid << 12) | (srcid << 0));
+ val = (((uint64_t)credit << 24) | (destid << 12) | (srcid << 0));
nlm_write_cms_reg(base, CMS_OUTPUTQ_CREDIT_CFG, val);
}
diff --git a/sys/mips/nlm/hal/mdio.h b/sys/mips/nlm/hal/mdio.h
index a1e720b..31b2aa0 100644
--- a/sys/mips/nlm/hal/mdio.h
+++ b/sys/mips/nlm/hal/mdio.h
@@ -100,6 +100,7 @@ int nlm_int_gmac_mdio_reset(uint64_t, int, int, int);
int nlm_gmac_mdio_read(uint64_t, int, int, int, int, int);
int nlm_gmac_mdio_write(uint64_t, int, int, int, int, int, uint16_t);
int nlm_gmac_mdio_reset(uint64_t, int, int, int);
+void nlm_mdio_reset_all(uint64_t);
#endif /* !(LOCORE) && !(__ASSEMBLY__) */
#endif
diff --git a/sys/mips/nlm/hal/sys.h b/sys/mips/nlm/hal/sys.h
index adfd8a8..2092d37 100644
--- a/sys/mips/nlm/hal/sys.h
+++ b/sys/mips/nlm/hal/sys.h
@@ -140,5 +140,18 @@ enum {
INVALID_DFS_DEVICE = 0xFF
};
+static __inline
+void nlm_sys_enable_block(uint64_t sys_base, int block)
+{
+ uint32_t dfsdis, mask;
+
+ mask = 1 << block;
+ dfsdis = nlm_read_sys_reg(sys_base, SYS_DFS_DIS_CTRL);
+ if ((dfsdis & mask) == 0)
+ return; /* already enabled, nothing to do */
+ dfsdis &= ~mask;
+ nlm_write_sys_reg(sys_base, SYS_DFS_DIS_CTRL, dfsdis);
+}
+
#endif
#endif
diff --git a/sys/mips/nlm/hal/ucore_loader.h b/sys/mips/nlm/hal/ucore_loader.h
index 8298c82..cace077 100644
--- a/sys/mips/nlm/hal/ucore_loader.h
+++ b/sys/mips/nlm/hal/ucore_loader.h
@@ -49,7 +49,7 @@ nlm_ucore_load_image(uint64_t nae_base, int ucore)
size = sizeof(ucore_app_bin)/sizeof(uint32_t);
for (i = 0; i < size; i++, addr += 4)
- nlm_store_word_daddr(addr, p[i]);
+ nlm_store_word_daddr(addr, htobe32(p[i]));
/* add a 'nop' if number of instructions are odd */
if (size & 0x1)
diff --git a/sys/mips/nlm/xlp_machdep.c b/sys/mips/nlm/xlp_machdep.c
index a4ffc73..f95592e 100644
--- a/sys/mips/nlm/xlp_machdep.c
+++ b/sys/mips/nlm/xlp_machdep.c
@@ -157,6 +157,20 @@ xlp_setup_mmu(void)
}
static void
+xlp_enable_blocks(void)
+{
+ uint64_t sysbase;
+ int i;
+
+ for (i = 0; i < XLP_MAX_NODES; i++) {
+ if (!nlm_dev_exists(XLP_IO_SYS_OFFSET(i)))
+ continue;
+ sysbase = nlm_get_sys_regbase(i);
+ nlm_sys_enable_block(sysbase, DFS_DEVICE_RSA);
+ }
+}
+
+static void
xlp_parse_mmu_options(void)
{
uint64_t sysbase;
@@ -420,9 +434,8 @@ xlp_pic_init(void)
#define XLP_MEM_LIM 0xfffff000UL
#endif
static vm_paddr_t xlp_mem_excl[] = {
- 0, 0, /* entry for kernel image, set by xlp_mem_init*/
- 0x0c000000, 0x0d000000, /* uboot mess */
- 0x10000000, 0x14000000, /* cms queue and other stuff */
+ 0, 0, /* for kernel image region, see xlp_mem_init */
+ 0x0c000000, 0x14000000, /* uboot area, cms queue and other stuff */
0x1fc00000, 0x1fd00000, /* reset vec */
0x1e000000, 0x1e200000, /* poe buffers */
};
@@ -559,6 +572,8 @@ platform_start(__register_t a0 __unused,
/* setup for the startup core */
xlp_setup_mmu();
+ xlp_enable_blocks();
+
/* Read/Guess/setup board information */
nlm_board_info_setup();
diff --git a/sys/mips/nlm/xlp_pci.c b/sys/mips/nlm/xlp_pci.c
index 0610a15..23bd46c 100644
--- a/sys/mips/nlm/xlp_pci.c
+++ b/sys/mips/nlm/xlp_pci.c
@@ -487,12 +487,14 @@ xlp_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
}
/*
- * Enable byte swap in hardware. Program a link's PCIe SWAP regions
- * from the link's IO and MEM address ranges.
+ * Enable byte swap in hardware when compiled big-endian.
+ * Programs a link's PCIe SWAP regions from the link's IO and MEM address
+ * ranges.
*/
static void
xlp_pcib_hardware_swap_enable(int node, int link)
{
+#if BYTE_ORDER == BIG_ENDIAN
uint64_t bbase, linkpcibase;
uint32_t bar;
int pcieoffset;
@@ -514,6 +516,7 @@ xlp_pcib_hardware_swap_enable(int node, int link)
bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_LIMIT0 + link);
nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_LIM, bar | 0xFFF);
+#endif
}
static int
diff --git a/sys/mips/rmi/msgring_xls.cfg b/sys/mips/rmi/msgring_xls.cfg
index 35bfb17..35bfb17 100755..100644
--- a/sys/mips/rmi/msgring_xls.cfg
+++ b/sys/mips/rmi/msgring_xls.cfg
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 1344297..28cb56c 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -335,6 +335,7 @@ SUBDIR= \
vge \
${_viawd} \
vkbd \
+ ${_vmm} \
${_vpo} \
vr \
vte \
@@ -720,6 +721,7 @@ _twa= twa
_vesa= vesa
_viawd= viawd
_virtio= virtio
+_vmm= vmm
_vxge= vxge
_x86bios= x86bios
_wbwd= wbwd
diff --git a/sys/modules/cxgbe/tom/Makefile b/sys/modules/cxgbe/tom/Makefile
index 72721be..d02afd4 100644
--- a/sys/modules/cxgbe/tom/Makefile
+++ b/sys/modules/cxgbe/tom/Makefile
@@ -10,15 +10,20 @@ CXGBE = ${.CURDIR}/../../../dev/cxgbe
KMOD = t4_tom
SRCS = t4_tom.c t4_connect.c t4_listen.c t4_cpl_io.c t4_tom_l2t.c t4_ddp.c
SRCS+= device_if.h bus_if.h pci_if.h
-SRCS+= opt_inet.h
+SRCS+= opt_inet.h opt_inet6.h
CFLAGS+= -I${CXGBE}
.if !defined(KERNBUILDDIR)
.if ${MK_INET_SUPPORT} != "no"
opt_inet.h:
- echo "#define INET 1" > ${.TARGET}
- echo "#define TCP_OFFLOAD 1" >> ${.TARGET}
+ @echo "#define INET 1" > ${.TARGET}
+ @echo "#define TCP_OFFLOAD 1" >> ${.TARGET}
+.endif
+
+.if ${MK_INET6_SUPPORT} != "no"
+opt_inet6.h:
+ @echo "#define INET6 1" > ${.TARGET}
.endif
.endif
diff --git a/sys/modules/digi/Makefile b/sys/modules/digi/Makefile
index 9d9aea6..9d9aea6 100755..100644
--- a/sys/modules/digi/Makefile
+++ b/sys/modules/digi/Makefile
diff --git a/sys/modules/digi/Makefile.inc b/sys/modules/digi/Makefile.inc
index 265f86d..265f86d 100755..100644
--- a/sys/modules/digi/Makefile.inc
+++ b/sys/modules/digi/Makefile.inc
diff --git a/sys/modules/hpt27xx/Makefile b/sys/modules/hpt27xx/Makefile
index 883229b..82b51408 100644
--- a/sys/modules/hpt27xx/Makefile
+++ b/sys/modules/hpt27xx/Makefile
@@ -12,6 +12,3 @@ hpt27xx_lib.o:
uudecode -p < ${HPT27XX}/$(MACHINE_ARCH)-elf.hpt27xx_lib.o.uu > ${.TARGET}
.include <bsd.kmod.mk>
-
-CWARNFLAGS.osm_bsd.c= ${NO_WFORMAT_SECURITY}
-CWARNFLAGS+= ${CWARNFLAGS.${.IMPSRC:T}}
diff --git a/sys/modules/isci/Makefile b/sys/modules/isci/Makefile
index 82d4018..82d4018 100755..100644
--- a/sys/modules/isci/Makefile
+++ b/sys/modules/isci/Makefile
diff --git a/sys/modules/sound/driver/ich/Makefile b/sys/modules/sound/driver/ich/Makefile
index e0f2ce7..e0f2ce7 100755..100644
--- a/sys/modules/sound/driver/ich/Makefile
+++ b/sys/modules/sound/driver/ich/Makefile
diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile
index 4492755..6481838 100644
--- a/sys/modules/usb/Makefile
+++ b/sys/modules/usb/Makefile
@@ -36,7 +36,7 @@ SUBDIR += ${_rum} run ${_uath} upgt usie ural ${_zyd} ${_urtw}
SUBDIR += atp uhid ukbd ums udbp ufm uep
SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \
umct umcs umodem umoscom uplcom uslcom uvisor uvscom
-SUBDIR += uether aue axe cdce cue ${_kue} mos rue udav uhso ipheth
+SUBDIR += uether aue axe cdce cue ${_kue} mos rue smsc udav uhso ipheth
SUBDIR += usfs umass urio
SUBDIR += quirk template
diff --git a/sys/modules/usb/smsc/Makefile b/sys/modules/usb/smsc/Makefile
index a97e9ba..c6f2de8 100644
--- a/sys/modules/usb/smsc/Makefile
+++ b/sys/modules/usb/smsc/Makefile
@@ -31,7 +31,7 @@ S= ${.CURDIR}/../../..
KMOD= if_smsc
SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \
- miibus_if.h opt_inet.h \
+ miibus_if.h opt_inet.h opt_platform.h \
if_smsc.c
.include <bsd.kmod.mk>
diff --git a/sys/modules/vmm/Makefile b/sys/modules/vmm/Makefile
new file mode 100644
index 0000000..8b565da
--- /dev/null
+++ b/sys/modules/vmm/Makefile
@@ -0,0 +1,62 @@
+# $FreeBSD$
+
+KMOD= vmm
+
+SRCS= opt_ddb.h device_if.h bus_if.h pci_if.h
+
+CFLAGS+= -DVMM_KEEP_STATS -DSMP
+CFLAGS+= -I${.CURDIR}/../../amd64/vmm
+CFLAGS+= -I${.CURDIR}/../../amd64/vmm/io
+CFLAGS+= -I${.CURDIR}/../../amd64/vmm/intel
+
+# generic vmm support
+.PATH: ${.CURDIR}/../../amd64/vmm
+SRCS+= vmm.c \
+ vmm_dev.c \
+ vmm_host.c \
+ vmm_instruction_emul.c \
+ vmm_ipi.c \
+ vmm_lapic.c \
+ vmm_mem.c \
+ vmm_msr.c \
+ vmm_stat.c \
+ vmm_util.c \
+ x86.c \
+ vmm_support.S
+
+.PATH: ${.CURDIR}/../../amd64/vmm/io
+SRCS+= iommu.c \
+ ppt.c \
+ vdev.c \
+ vlapic.c
+
+# intel-specific files
+.PATH: ${.CURDIR}/../../amd64/vmm/intel
+SRCS+= ept.c \
+ vmcs.c \
+ vmx_msr.c \
+ vmx.c \
+ vtd.c
+
+# amd-specific files
+.PATH: ${.CURDIR}/../../amd64/vmm/amd
+SRCS+= amdv.c
+
+OBJS= vmx_support.o
+
+CLEANFILES= vmx_assym.s vmx_genassym.o
+
+vmx_assym.s: vmx_genassym.o
+.if exists(@)
+vmx_assym.s: @/kern/genassym.sh
+.endif
+ sh @/kern/genassym.sh vmx_genassym.o > ${.TARGET}
+
+vmx_support.o: vmx_support.S vmx_assym.s
+ ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
+ ${.IMPSRC} -o ${.TARGET}
+
+vmx_genassym.o: vmx_genassym.c @ machine x86
+ ${CC} -c ${CFLAGS:N-fno-common} ${.IMPSRC}
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/wlan/Makefile b/sys/modules/wlan/Makefile
index 7205e28..30aa745 100644
--- a/sys/modules/wlan/Makefile
+++ b/sys/modules/wlan/Makefile
@@ -12,7 +12,7 @@ SRCS= ieee80211.c ieee80211_action.c ieee80211_ageq.c \
ieee80211_ratectl_none.c ieee80211_regdomain.c \
ieee80211_ht.c ieee80211_hwmp.c ieee80211_adhoc.c ieee80211_hostap.c \
ieee80211_monitor.c ieee80211_sta.c ieee80211_wds.c ieee80211_ddb.c \
- ieee80211_tdma.c
+ ieee80211_tdma.c ieee80211_superg.c
SRCS+= bus_if.h device_if.h opt_ddb.h opt_inet.h opt_inet6.h opt_ipx.h \
opt_tdma.h opt_wlan.h
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 9ee1964..ba31c66 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -522,32 +522,15 @@ bpf_movein(struct uio *uio, int linktype, struct ifnet *ifp, struct mbuf **mp,
}
len = uio->uio_resid;
-
- if (len - hlen > ifp->if_mtu)
+ if (len < hlen || len - hlen > ifp->if_mtu)
return (EMSGSIZE);
- if ((unsigned)len > MJUM16BYTES)
+ m = m_get2(M_WAITOK, MT_DATA, M_PKTHDR, len);
+ if (m == NULL)
return (EIO);
-
- if (len <= MHLEN)
- MGETHDR(m, M_WAITOK, MT_DATA);
- else if (len <= MCLBYTES)
- m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
- else
- m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR,
-#if (MJUMPAGESIZE > MCLBYTES)
- len <= MJUMPAGESIZE ? MJUMPAGESIZE :
-#endif
- (len <= MJUM9BYTES ? MJUM9BYTES : MJUM16BYTES));
m->m_pkthdr.len = m->m_len = len;
- m->m_pkthdr.rcvif = NULL;
*mp = m;
- if (m->m_len < hlen) {
- error = EPERM;
- goto bad;
- }
-
error = uiomove(mtod(m, u_char *), len, uio);
if (error)
goto bad;
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 0428cbe..3634d0b 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -789,7 +789,7 @@ lagg_port_output(struct ifnet *ifp, struct mbuf *m,
/* drop any other frames */
m_freem(m);
- return (EBUSY);
+ return (ENETDOWN);
}
static void
@@ -1862,7 +1862,7 @@ lagg_lacp_start(struct lagg_softc *sc, struct mbuf *m)
lp = lacp_select_tx_port(sc, m);
if (lp == NULL) {
m_freem(m);
- return (EBUSY);
+ return (ENETDOWN);
}
/* Send mbuf */
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index 5812623..84ea6c6 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -273,10 +273,9 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
u_int laflags = 0, flags = 0;
int error = 0;
- if (dl == NULL || dl->sdl_family != AF_LINK) {
- log(LOG_INFO, "%s: invalid dl\n", __func__);
- return EINVAL;
- }
+ KASSERT(dl != NULL && dl->sdl_family == AF_LINK,
+ ("%s: invalid dl\n", __func__));
+
ifp = ifnet_byindex(dl->sdl_index);
if (ifp == NULL) {
log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
@@ -286,28 +285,8 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
switch (rtm->rtm_type) {
case RTM_ADD:
- if (rtm->rtm_flags & RTF_ANNOUNCE) {
+ if (rtm->rtm_flags & RTF_ANNOUNCE)
flags |= LLE_PUB;
-#ifdef INET
- if (dst->sa_family == AF_INET &&
- ((struct sockaddr_inarp *)dst)->sin_other != 0) {
- struct rtentry *rt;
- ((struct sockaddr_inarp *)dst)->sin_other = 0;
- rt = rtalloc1(dst, 0, 0);
- if (rt == NULL || !(rt->rt_flags & RTF_HOST)) {
- log(LOG_INFO, "%s: RTM_ADD publish "
- "(proxy only) is invalid\n",
- __func__);
- if (rt)
- RTFREE_LOCKED(rt);
- return EINVAL;
- }
- RTFREE_LOCKED(rt);
-
- flags |= LLE_PROXY;
- }
-#endif
- }
flags |= LLE_CREATE;
break;
@@ -346,7 +325,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
* LLE_DELETED flag, and reset the expiration timer
*/
bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen);
- lle->la_flags |= (flags & (LLE_PUB | LLE_PROXY));
+ lle->la_flags |= (flags & LLE_PUB);
lle->la_flags |= LLE_VALID;
lle->la_flags &= ~LLE_DELETED;
#ifdef INET6
@@ -368,15 +347,12 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
laflags = lle->la_flags;
LLE_WUNLOCK(lle);
#ifdef INET
- /* gratuitous ARP */
- if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) {
+ /* gratuitous ARP */
+ if ((laflags & LLE_PUB) && dst->sa_family == AF_INET)
arprequest(ifp,
&((struct sockaddr_in *)dst)->sin_addr,
&((struct sockaddr_in *)dst)->sin_addr,
- ((laflags & LLE_PROXY) ?
- (u_char *)IF_LLADDR(ifp) :
- (u_char *)LLADDR(dl)));
- }
+ (u_char *)LLADDR(dl));
#endif
} else {
if (flags & LLE_EXCLUSIVE)
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
index 8da08ba..693ccd5 100644
--- a/sys/net/if_llatbl.h
+++ b/sys/net/if_llatbl.h
@@ -172,7 +172,6 @@ MALLOC_DECLARE(M_LLTABLE);
#define LLE_STATIC 0x0002 /* entry is static */
#define LLE_IFADDR 0x0004 /* entry is interface addr */
#define LLE_VALID 0x0008 /* ll_addr is valid */
-#define LLE_PROXY 0x0010 /* proxy entry ??? */
#define LLE_PUB 0x0020 /* publish entry ??? */
#define LLE_LINKED 0x0040 /* linked to lookup structure */
#define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */
@@ -205,4 +204,14 @@ lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
}
int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
+
+#include <sys/eventhandler.h>
+enum {
+ LLENTRY_RESOLVED,
+ LLENTRY_TIMEDOUT,
+ LLENTRY_DELETED,
+ LLENTRY_EXPIRED,
+};
+typedef void (*lle_event_fn)(void *, struct llentry *, int);
+EVENTHANDLER_DECLARE(lle_event, lle_event_fn);
#endif /* _NET_IF_LLATBL_H_ */
diff --git a/sys/net/netmap.h b/sys/net/netmap.h
index 1aa5e29..638cb18 100644
--- a/sys/net/netmap.h
+++ b/sys/net/netmap.h
@@ -32,7 +32,7 @@
/*
* $FreeBSD$
- * $Id: netmap.h 10601 2012-02-21 16:40:14Z luigi $
+ * $Id: netmap.h 11997 2013-01-17 21:59:12Z luigi $
*
* Definitions of constants and the structures used by the netmap
* framework, for the part visible to both kernel and userspace.
@@ -113,15 +113,28 @@
* In the kernel, buffers do not necessarily need to be contiguous,
* and the virtual and physical addresses are derived through
* a lookup table.
- * To associate a different buffer to a slot, applications must
- * write the new index in buf_idx, and set NS_BUF_CHANGED flag to
- * make sure that the kernel updates the hardware ring as needed.
*
- * Normally the driver is not requested to report the result of
- * transmissions (this can dramatically speed up operation).
- * However the user may request to report completion by setting
- * NS_REPORT.
+ * struct netmap_slot:
+ *
+ * buf_idx is the index of the buffer associated to the slot.
+ * len is the length of the payload
+ * NS_BUF_CHANGED must be set whenever userspace wants
+ * to change buf_idx (it might be necessary to
+ * reprogram the NIC slot)
+ * NS_REPORT must be set if we want the NIC to generate an interrupt
+ * when this slot is used. Leaving it to 0 improves
+ * performance.
+ * NS_FORWARD if set on a receive ring, and the device is in
+ * transparent mode, buffers released with the flag set
+ * will be forwarded to the 'other' side (host stack
+ * or NIC, respectively) on the next select() or ioctl()
+ * NS_NO_LEARN on a VALE switch, do not 'learn' the source port for
+ * this packet.
+ * NS_PORT_MASK the high 8 bits of the flag, if not zero, indicate the
+ * destination port for the VALE switch, overriding
+ * the lookup table.
*/
+
struct netmap_slot {
uint32_t buf_idx; /* buffer index */
uint16_t len; /* packet length, to be copied to/from the hw ring */
@@ -130,6 +143,12 @@ struct netmap_slot {
#define NS_REPORT 0x0002 /* ask the hardware to report results
* e.g. by generating an interrupt
*/
+#define NS_FORWARD 0x0004 /* pass packet to the other endpoint
+ * (host stack or device)
+ */
+#define NS_NO_LEARN 0x0008
+#define NS_PORT_SHIFT 8
+#define NS_PORT_MASK (0xff << NS_PORT_SHIFT)
};
/*
@@ -186,6 +205,18 @@ struct netmap_slot {
* a system call.
*
* The netmap_kring is only modified by the upper half of the kernel.
+ *
+ * FLAGS
+ * NR_TIMESTAMP updates the 'ts' field on each syscall. This is
+ * a global timestamp for all packets.
+ * NR_RX_TSTMP if set, the last 64 byte in each buffer will
+ * contain a timestamp for the frame supplied by
+ * the hardware (if supported)
+ * NR_FORWARD if set, the NS_FORWARD flag in each slot of the
+ * RX ring is checked, and if set the packet is
+ * passed to the other side (host stack or device,
+ * respectively). This permits bpf-like behaviour
+ * or transparency for selected packets.
*/
struct netmap_ring {
/*
@@ -202,6 +233,8 @@ struct netmap_ring {
const uint16_t nr_buf_size;
uint16_t flags;
#define NR_TIMESTAMP 0x0002 /* set timestamp on *sync() */
+#define NR_FORWARD 0x0004 /* enable NS_FORWARD for ring */
+#define NR_RX_TSTMP 0x0008 /* set rx timestamp in slots */
struct timeval ts; /* time of last *sync() */
diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c
index 0220474..b0998f5 100644
--- a/sys/net80211/ieee80211_adhoc.c
+++ b/sys/net80211/ieee80211_adhoc.c
@@ -688,6 +688,7 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
struct ieee80211_frame *wh;
uint8_t *frm, *efrm, *sfrm;
uint8_t *ssid, *rates, *xrates;
+ int ht_state_change = 0;
wh = mtod(m0, struct ieee80211_frame *);
frm = (uint8_t *)&wh[1];
@@ -748,10 +749,27 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
memcpy(ni->ni_tstamp.data, scan.tstamp,
sizeof(ni->ni_tstamp));
}
+ /*
+ * This isn't enabled yet - otherwise it would
+ * update the HT parameters and channel width
+ * from any node, which could lead to lots of
+ * strange behaviour if the 11n nodes aren't
+ * exactly configured to match.
+ */
+#if 0
+ if (scan.htcap != NULL && scan.htinfo != NULL &&
+ (vap->iv_flags_ht & IEEE80211_FHT_HT)) {
+ if (ieee80211_ht_updateparams(ni,
+ scan.htcap, scan.htinfo))
+ ht_state_change = 1;
+ }
+#endif
if (ni != NULL) {
IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
ni->ni_noise = nf;
}
+ if (ht_state_change)
+ ieee80211_update_chw(ic);
}
break;
}
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 7ed3523..a81c481 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -771,6 +771,7 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan,
/* XXX msg */
return 0;
}
+
/*
* Expand scan state into node's format.
* XXX may not need all this stuff
@@ -821,6 +822,29 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan,
IEEE80211_F_DOSORT);
if (ieee80211_iserp_rateset(&ni->ni_rates))
ni->ni_flags |= IEEE80211_NODE_ERP;
+
+ /*
+ * Setup HT state for this node if it's available, otherwise
+ * non-STA modes won't pick this state up.
+ *
+ * For IBSS and related modes that don't go through an
+ * association request/response, the only appropriate place
+ * to setup the HT state is here.
+ */
+ if (ni->ni_ies.htinfo_ie != NULL &&
+ ni->ni_ies.htcap_ie != NULL &&
+ vap->iv_flags_ht & IEEE80211_FHT_HT) {
+ ieee80211_ht_node_init(ni);
+ ieee80211_ht_updateparams(ni,
+ ni->ni_ies.htcap_ie,
+ ni->ni_ies.htinfo_ie);
+ ieee80211_setup_htrates(ni, ni->ni_ies.htcap_ie,
+ IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
+ ieee80211_setup_basic_htrates(ni, ni->ni_ies.htinfo_ie);
+ }
+ /* XXX else check for ath FF? */
+ /* XXX QoS? Difficult given that WME config is specific to a master */
+
ieee80211_node_setuptxparms(ni);
ieee80211_ratectl_node_init(ni);
@@ -938,6 +962,9 @@ ieee80211_ies_expand(struct ieee80211_ies *ies)
case IEEE80211_ELEMID_HTCAP:
ies->htcap_ie = ie;
break;
+ case IEEE80211_ELEMID_HTINFO:
+ ies->htinfo_ie = ie;
+ break;
#ifdef IEEE80211_SUPPORT_MESH
case IEEE80211_ELEMID_MESHID:
ies->meshid_ie = ie;
@@ -1404,7 +1431,7 @@ ieee80211_fakeup_adhoc_node(struct ieee80211vap *vap,
{
struct ieee80211_node *ni;
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE | IEEE80211_MSG_ASSOC,
"%s: mac<%s>\n", __func__, ether_sprintf(macaddr));
ni = ieee80211_dup_bss(vap, macaddr);
if (ni != NULL) {
@@ -1444,6 +1471,8 @@ ieee80211_init_neighbor(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const struct ieee80211_scanparams *sp)
{
+ int do_ht_setup = 0;
+
ni->ni_esslen = sp->ssid[1];
memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
@@ -1469,12 +1498,41 @@ ieee80211_init_neighbor(struct ieee80211_node *ni,
if (ni->ni_ies.ath_ie != NULL)
ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
#endif
+ if (ni->ni_ies.htcap_ie != NULL)
+ ieee80211_parse_htcap(ni, ni->ni_ies.htcap_ie);
+ if (ni->ni_ies.htinfo_ie != NULL)
+ ieee80211_parse_htinfo(ni, ni->ni_ies.htinfo_ie);
+
+ if ((ni->ni_ies.htcap_ie != NULL) &&
+ (ni->ni_ies.htinfo_ie != NULL) &&
+ (ni->ni_vap->iv_flags_ht & IEEE80211_FHT_HT)) {
+ do_ht_setup = 1;
+ }
}
/* NB: must be after ni_chan is setup */
ieee80211_setup_rates(ni, sp->rates, sp->xrates,
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
+
+ /*
+ * If the neighbor is HT compatible, flip that on.
+ */
+ if (do_ht_setup) {
+ IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_ASSOC,
+ "%s: doing HT setup\n", __func__);
+ ieee80211_ht_node_init(ni);
+ ieee80211_ht_updateparams(ni,
+ ni->ni_ies.htcap_ie,
+ ni->ni_ies.htinfo_ie);
+ ieee80211_setup_htrates(ni,
+ ni->ni_ies.htcap_ie,
+ IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
+ ieee80211_setup_basic_htrates(ni,
+ ni->ni_ies.htinfo_ie);
+ ieee80211_node_setuptxparms(ni);
+ ieee80211_ratectl_node_init(ni);
+ }
}
/*
@@ -1490,7 +1548,7 @@ ieee80211_add_neighbor(struct ieee80211vap *vap,
{
struct ieee80211_node *ni;
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
"%s: mac<%s>\n", __func__, ether_sprintf(wh->i_addr2));
ni = ieee80211_dup_bss(vap, wh->i_addr2);/* XXX alloc_node? */
if (ni != NULL) {
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 558e1f3..31bc578 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -416,6 +416,8 @@ pwrsave_flushq(struct ieee80211_node *ni)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_psq_head *qhead;
struct ifnet *parent, *ifp;
+ struct mbuf *parent_q = NULL, *ifp_q = NULL;
+ struct mbuf *m;
IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
"flush ps queue, %u packets queued", psq->psq_len);
@@ -427,8 +429,7 @@ pwrsave_flushq(struct ieee80211_node *ni)
parent = vap->iv_ic->ic_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
- IF_PREPEND_LIST(&parent->if_snd, qhead->head, qhead->tail,
- qhead->len);
+ parent_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
} else
@@ -439,8 +440,7 @@ pwrsave_flushq(struct ieee80211_node *ni)
ifp = vap->iv_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
- IF_PREPEND_LIST(&ifp->if_snd, qhead->head, qhead->tail,
- qhead->len);
+ ifp_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
} else
@@ -450,10 +450,34 @@ pwrsave_flushq(struct ieee80211_node *ni)
/* NB: do this outside the psq lock */
/* XXX packets might get reordered if parent is OACTIVE */
- if (parent != NULL)
- if_start(parent);
- if (ifp != NULL)
- if_start(ifp);
+ /* parent frames, should be encapsulated */
+ if (parent != NULL) {
+ while (parent_q != NULL) {
+ m = parent_q;
+ parent_q = m->m_nextpkt;
+ /* must be encapsulated */
+ KASSERT((m->m_flags & M_ENCAP),
+ ("%s: parentq with non-M_ENCAP frame!\n",
+ __func__));
+ /*
+ * For encaped frames, we need to free the node
+ * reference upon failure.
+ */
+ if (parent->if_transmit(parent, m) != 0)
+ ieee80211_free_node(ni);
+ }
+ }
+
+ /* VAP frames, aren't encapsulated */
+ if (ifp != NULL) {
+ while (ifp_q != NULL) {
+ m = ifp_q;
+ ifp_q = m->m_nextpkt;
+ KASSERT((!(m->m_flags & M_ENCAP)),
+ ("%s: vapq with M_ENCAP frame!\n", __func__));
+ (void) ifp->if_transmit(ifp, m);
+ }
+ }
}
/*
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index 6f5e9d2..381faca 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#ifdef IEEE80211_SUPPORT_MESH
#include <net80211/ieee80211_mesh.h>
#endif
+#include <net80211/ieee80211_ratectl.h>
#include <net/bpf.h>
@@ -1567,6 +1568,7 @@ adhoc_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
struct sta_table *st = ss->ss_priv;
struct sta_entry *selbs;
struct ieee80211_channel *chan;
+ struct ieee80211com *ic = vap->iv_ic;
KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||
vap->iv_opmode == IEEE80211_M_AHDEMO ||
@@ -1612,15 +1614,19 @@ notfound:
*/
if (vap->iv_des_chan == IEEE80211_CHAN_ANYC ||
IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
- struct ieee80211com *ic = vap->iv_ic;
-
chan = adhoc_pick_channel(ss, 0);
- if (chan != NULL)
- chan = ieee80211_ht_adjust_channel(ic,
- chan, vap->iv_flags_ht);
} else
chan = vap->iv_des_chan;
if (chan != NULL) {
+ struct ieee80211com *ic = vap->iv_ic;
+ /*
+ * Create a HT capable IBSS; the per-node
+ * probe request/response will result in
+ * "correct" rate control capabilities being
+ * negotiated.
+ */
+ chan = ieee80211_ht_adjust_channel(ic,
+ chan, vap->iv_flags_ht);
ieee80211_create_ibss(vap, chan);
return 1;
}
@@ -1644,6 +1650,14 @@ notfound:
chan = selbs->base.se_chan;
if (selbs->se_flags & STA_DEMOTE11B)
chan = demote11b(vap, chan);
+ /*
+ * If HT is available, make it a possibility here.
+ * The intent is to enable HT20/HT40 when joining a non-HT
+ * IBSS node; we can then advertise HT IEs and speak HT
+ * to any subsequent nodes that support it.
+ */
+ chan = ieee80211_ht_adjust_channel(ic,
+ chan, vap->iv_flags_ht);
if (!ieee80211_sta_join(vap, chan, &selbs->base))
goto notfound;
return 1; /* terminate scan */
diff --git a/sys/net80211/ieee80211_superg.c b/sys/net80211/ieee80211_superg.c
index 0599f45..9ac5878 100644
--- a/sys/net80211/ieee80211_superg.c
+++ b/sys/net80211/ieee80211_superg.c
@@ -28,6 +28,8 @@ __FBSDID("$FreeBSD$");
#include "opt_wlan.h"
+#ifdef IEEE80211_SUPPORT_SUPERG
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
@@ -921,3 +923,5 @@ superg_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
return 0;
}
IEEE80211_IOCTL_SET(superg, superg_ioctl_set80211);
+
+#endif /* IEEE80211_SUPPORT_SUPERG */
diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c
index 05d2e6e..6266f40 100644
--- a/sys/netgraph/ng_ether.c
+++ b/sys/netgraph/ng_ether.c
@@ -117,6 +117,8 @@ static ng_rcvdata_t ng_ether_rcvdata;
static ng_disconnect_t ng_ether_disconnect;
static int ng_ether_mod_event(module_t mod, int event, void *data);
+static eventhandler_tag ng_ether_ifnet_arrival_cookie;
+
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_ether_cmdlist[] = {
{
@@ -214,6 +216,24 @@ static struct ng_type ng_ether_typestruct = {
NETGRAPH_INIT(ether, &ng_ether_typestruct);
/******************************************************************
+ UTILITY FUNCTIONS
+******************************************************************/
+static void
+ng_ether_sanitize_ifname(const char *ifname, char *name)
+{
+ int i;
+
+ for (i = 0; i < IFNAMSIZ; i++) {
+ if (ifname[i] == '.' || ifname[i] == ':')
+ name[i] = '_';
+ else
+ name[i] = ifname[i];
+ if (name[i] == '\0')
+ break;
+ }
+}
+
+/******************************************************************
ETHERNET FUNCTION HOOKS
******************************************************************/
@@ -282,6 +302,7 @@ ng_ether_output(struct ifnet *ifp, struct mbuf **mp)
static void
ng_ether_attach(struct ifnet *ifp)
{
+ char name[IFNAMSIZ];
priv_p priv;
node_p node;
@@ -319,10 +340,9 @@ ng_ether_attach(struct ifnet *ifp)
priv->hwassist = ifp->if_hwassist;
/* Try to give the node the same name as the interface */
- if (ng_name_node(node, ifp->if_xname) != 0) {
- log(LOG_WARNING, "%s: can't name node %s\n",
- __func__, ifp->if_xname);
- }
+ ng_ether_sanitize_ifname(ifp->if_xname, name);
+ if (ng_name_node(node, name) != 0)
+ log(LOG_WARNING, "%s: can't name node %s\n", __func__, name);
}
/*
@@ -378,6 +398,32 @@ ng_ether_link_state(struct ifnet *ifp, int state)
}
}
+/*
+ * Interface arrival notification handler.
+ * The notification is produced in two cases:
+ * o a new interface arrives
+ * o an existing interface got renamed
+ * Currently the first case is handled by ng_ether_attach via special
+ * hook ng_ether_attach_p.
+ */
+static void
+ng_ether_ifnet_arrival_event(void *arg __unused, struct ifnet *ifp)
+{
+ char name[IFNAMSIZ];
+ node_p node = IFP2NG(ifp);
+
+ /*
+ * Just return if it's a new interface without an ng_ether companion.
+ */
+ if (node == NULL)
+ return;
+
+ /* Try to give the node the same name as the new interface name */
+ ng_ether_sanitize_ifname(ifp->if_xname, name);
+ if (ng_name_node(node, name) != 0)
+ log(LOG_WARNING, "%s: can't re-name node %s\n", __func__, name);
+}
+
/******************************************************************
NETGRAPH NODE METHODS
******************************************************************/
@@ -771,6 +817,9 @@ ng_ether_mod_event(module_t mod, int event, void *data)
ng_ether_input_orphan_p = ng_ether_input_orphan;
ng_ether_link_state_p = ng_ether_link_state;
+ ng_ether_ifnet_arrival_cookie =
+ EVENTHANDLER_REGISTER(ifnet_arrival_event,
+ ng_ether_ifnet_arrival_event, NULL, EVENTHANDLER_PRI_ANY);
break;
case MOD_UNLOAD:
@@ -783,6 +832,9 @@ ng_ether_mod_event(module_t mod, int event, void *data)
* is MOD_UNLOAD, so there's no need to detach any nodes.
*/
+ EVENTHANDLER_DEREGISTER(ifnet_arrival_event,
+ ng_ether_ifnet_arrival_cookie);
+
/* Unregister function hooks */
ng_ether_attach_p = NULL;
ng_ether_detach_p = NULL;
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index e37a964..6b47912 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -89,6 +89,7 @@ struct ether_arp {
#define arp_pln ea_hdr.ar_pln
#define arp_op ea_hdr.ar_op
+#ifndef BURN_BRIDGES /* Can be used by third party software. */
struct sockaddr_inarp {
u_char sin_len;
u_char sin_family;
@@ -99,6 +100,8 @@ struct sockaddr_inarp {
u_short sin_other;
#define SIN_PROXY 1
};
+#endif /* !BURN_BRIDGES */
+
/*
* IP and ethernet specific routing flags
*/
@@ -120,17 +123,6 @@ void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
void arp_ifinit(struct ifnet *, struct ifaddr *);
void arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *);
void arp_ifscrub(struct ifnet *, uint32_t);
-
-#include <sys/eventhandler.h>
-enum {
- LLENTRY_RESOLVED,
- LLENTRY_TIMEDOUT,
- LLENTRY_DELETED,
- LLENTRY_EXPIRED,
-};
-typedef void (*lle_event_fn)(void *, struct llentry *, int);
-EVENTHANDLER_DECLARE(lle_event, lle_event_fn);
-
#endif
#endif
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 2b805c6..3ddb46c 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1494,7 +1494,7 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
/* XXX stack use */
struct {
struct rt_msghdr rtm;
- struct sockaddr_inarp sin;
+ struct sockaddr_in sin;
struct sockaddr_dl sdl;
} arpc;
int error, i;
@@ -1515,7 +1515,7 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
/*
* produce a msg made of:
* struct rt_msghdr;
- * struct sockaddr_inarp; (IPv4)
+ * struct sockaddr_in; (IPv4)
* struct sockaddr_dl;
*/
bzero(&arpc, sizeof(arpc));
@@ -1529,12 +1529,8 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
/* publish */
- if (lle->la_flags & LLE_PUB) {
+ if (lle->la_flags & LLE_PUB)
arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
- /* proxy only */
- if (lle->la_flags & LLE_PROXY)
- arpc.sin.sin_other = SIN_PROXY;
- }
sdl = &arpc.sdl;
sdl->sdl_family = AF_LINK;
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 6706bc4..f5e2ef2 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -334,8 +334,7 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY)
return (EINVAL);
- anonport = inp->inp_lport == 0 && (nam == NULL ||
- ((struct sockaddr_in *)nam)->sin_port == 0);
+ anonport = nam == NULL || ((struct sockaddr_in *)nam)->sin_port == 0;
error = in_pcbbind_setup(inp, nam, &inp->inp_laddr.s_addr,
&inp->inp_lport, cred);
if (error)
diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c
index da28b22..3b2068b 100644
--- a/sys/netinet/libalias/alias.c
+++ b/sys/netinet/libalias/alias.c
@@ -1760,21 +1760,7 @@ m_megapullup(struct mbuf *m, int len) {
if (m->m_next == NULL && M_WRITABLE(m) && M_TRAILINGSPACE(m) >= RESERVE)
return (m);
- if (len <= MCLBYTES - RESERVE) {
- mcl = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
- } else if (len < MJUM16BYTES) {
- int size;
- if (len <= MJUMPAGESIZE - RESERVE) {
- size = MJUMPAGESIZE;
- } else if (len <= MJUM9BYTES - RESERVE) {
- size = MJUM9BYTES;
- } else {
- size = MJUM16BYTES;
- };
- mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, size);
- } else {
- goto bad;
- }
+ mcl = m_get2(M_NOWAIT, MT_DATA, M_PKTHDR, len + RESERVE);
if (mcl == NULL)
goto bad;
diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3
index 1837c29..4d02cc4 100644
--- a/sys/netinet/libalias/libalias.3
+++ b/sys/netinet/libalias/libalias.3
@@ -901,39 +901,6 @@ is provided for error checking purposes.
This function can be used if an already-aliased packet needs to have its
original IP header restored for further processing (e.g.\& logging).
.Ed
-.Sh AUTHORS
-.An Charles Mott Aq cm@linktel.net ,
-versions 1.0 - 1.8, 2.0 - 2.4.
-.An Eivind Eklund Aq eivind@FreeBSD.org ,
-versions 1.8b, 1.9 and 2.5.
-Added IRC DCC support as well as contributing a number of architectural
-improvements; added the firewall bypass for FTP/IRC DCC.
-.An Erik Salander Aq erik@whistle.com
-added support for PPTP and RTSP.
-.An Junichi Satoh Aq junichi@junichi.org
-added support for RTSP/PNA.
-.An Ruslan Ermilov Aq ru@FreeBSD.org
-added support for PPTP and LSNAT as well as general hacking.
-.An Paolo Pisati Aq piso@FreeBSD.org
-made the library modular, moving support for all
-protocols (except for IP, TCP and UDP) to external modules.
-.Sh ACKNOWLEDGEMENTS
-Listed below, in approximate chronological order, are individuals who
-have provided valuable comments and/or debugging assistance.
-.Bd -ragged -offset indent
-.An -split
-.An Gary Roberts
-.An Tom Torrance
-.An Reto Burkhalter
-.An Martin Renters
-.An Brian Somers
-.An Paul Traina
-.An Ari Suutari
-.An Dave Remien
-.An J. Fortes
-.An Andrzej Bialecki
-.An Gordon Burditt
-.Ed
.Sh CONCEPTUAL BACKGROUND
This section is intended for those who are planning to modify the source
code or want to create somewhat esoteric applications using the packet
@@ -1475,3 +1442,38 @@ with the
facility and the
.Dv LOG_INFO
level.
+.Sh AUTHORS
+.An Charles Mott Aq cm@linktel.net ,
+versions 1.0 - 1.8, 2.0 - 2.4.
+.An Eivind Eklund Aq eivind@FreeBSD.org ,
+versions 1.8b, 1.9 and 2.5.
+Added IRC DCC support as well as contributing a number of architectural
+improvements; added the firewall bypass for FTP/IRC DCC.
+.An Erik Salander Aq erik@whistle.com
+added support for PPTP and RTSP.
+.An Junichi Satoh Aq junichi@junichi.org
+added support for RTSP/PNA.
+.An Ruslan Ermilov Aq ru@FreeBSD.org
+added support for PPTP and LSNAT as well as general hacking.
+.An Gleb Smirnoff Aq glebius@FreeBSD.org
+ported the library to kernel space.
+.An Paolo Pisati Aq piso@FreeBSD.org
+made the library modular, moving support for all
+protocols (except for IP, TCP and UDP) to external modules.
+.Sh ACKNOWLEDGEMENTS
+Listed below, in approximate chronological order, are individuals who
+have provided valuable comments and/or debugging assistance.
+.Bd -ragged -offset indent
+.An -split
+.An Gary Roberts
+.An Tom Torrance
+.An Reto Burkhalter
+.An Martin Renters
+.An Brian Somers
+.An Paul Traina
+.An Ari Suutari
+.An Dave Remien
+.An J. Fortes
+.An Andrzej Bialecki
+.An Gordon Burditt
+.Ed
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
index c714360..fb2f810 100644
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -149,20 +149,25 @@ struct tcphdr {
#endif /* __BSD_VISIBLE */
/*
- * User-settable options (used with setsockopt).
+ * User-settable options (used with setsockopt). These are discrete
+ * values and are not masked together. Some values appear to be
+ * bitmasks for historical reasons.
*/
-#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
+#define TCP_NODELAY 1 /* don't delay send to coalesce packets */
#if __BSD_VISIBLE
-#define TCP_MAXSEG 0x02 /* set maximum segment size */
-#define TCP_NOPUSH 0x04 /* don't push last block of write */
-#define TCP_NOOPT 0x08 /* don't use TCP options */
-#define TCP_MD5SIG 0x10 /* use MD5 digests (RFC2385) */
-#define TCP_INFO 0x20 /* retrieve tcp_info structure */
-#define TCP_CONGESTION 0x40 /* get/set congestion control algorithm */
-#define TCP_KEEPINIT 0x80 /* N, time to establish connection */
-#define TCP_KEEPIDLE 0x100 /* L,N,X start keeplives after this period */
-#define TCP_KEEPINTVL 0x200 /* L,N interval between keepalives */
-#define TCP_KEEPCNT 0x400 /* L,N number of keepalives before close */
+#define TCP_MAXSEG 2 /* set maximum segment size */
+#define TCP_NOPUSH 4 /* don't push last block of write */
+#define TCP_NOOPT 8 /* don't use TCP options */
+#define TCP_MD5SIG 16 /* use MD5 digests (RFC2385) */
+#define TCP_INFO 32 /* retrieve tcp_info structure */
+#define TCP_CONGESTION 64 /* get/set congestion control algorithm */
+#define TCP_KEEPINIT 128 /* N, time to establish connection */
+#define TCP_KEEPIDLE 256 /* L,N,X start keeplives after this period */
+#define TCP_KEEPINTVL 512 /* L,N interval between keepalives */
+#define TCP_KEEPCNT 1024 /* L,N number of keepalives before close */
+
+/* Start of reserved space for third-party user-settable options. */
+#define TCP_VENDOR SO_VENDOR
#define TCP_CA_NAME_MAX 16 /* max congestion control name length */
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 846887d2..e37de24 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -285,7 +285,7 @@ cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type)
INP_WLOCK_ASSERT(tp->t_inpcb);
tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th);
- if (tp->snd_cwnd == min(tp->snd_cwnd, tp->snd_wnd))
+ if (tp->snd_cwnd <= tp->snd_wnd)
tp->ccv->flags |= CCF_CWND_LIMITED;
else
tp->ccv->flags &= ~CCF_CWND_LIMITED;
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 289b58a..5fd29b8 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -106,8 +106,8 @@ tcp_reass_zone_change(void *tag)
/* Set the zone limit and read back the effective value. */
V_tcp_reass_maxseg = nmbclusters / 16;
- uma_zone_set_max(V_tcp_reass_zone, V_tcp_reass_maxseg);
- V_tcp_reass_maxseg = uma_zone_get_max(V_tcp_reass_zone);
+ V_tcp_reass_maxseg = uma_zone_set_max(V_tcp_reass_zone,
+ V_tcp_reass_maxseg);
}
void
@@ -120,8 +120,8 @@ tcp_reass_init(void)
V_tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
/* Set the zone limit and read back the effective value. */
- uma_zone_set_max(V_tcp_reass_zone, V_tcp_reass_maxseg);
- V_tcp_reass_maxseg = uma_zone_get_max(V_tcp_reass_zone);
+ V_tcp_reass_maxseg = uma_zone_set_max(V_tcp_reass_zone,
+ V_tcp_reass_maxseg);
EVENTHANDLER_REGISTER(nmbclusters_change,
tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY);
}
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 5baf3b8..441c269 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -268,8 +268,8 @@ syncache_init(void)
/* Create the syncache entry zone. */
V_tcp_syncache.zone = uma_zcreate("syncache", sizeof(struct syncache),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
- uma_zone_set_max(V_tcp_syncache.zone, V_tcp_syncache.cache_limit);
- V_tcp_syncache.cache_limit = uma_zone_get_max(V_tcp_syncache.zone);
+ V_tcp_syncache.cache_limit = uma_zone_set_max(V_tcp_syncache.zone,
+ V_tcp_syncache.cache_limit);
}
#ifdef VIMAGE
@@ -1493,6 +1493,15 @@ syncache_respond(struct syncache *sc)
th->th_sum = in6_cksum_pseudo(ip6, tlen + optlen - hlen,
IPPROTO_TCP, 0);
ip6->ip6_hlim = in6_selecthlim(NULL, NULL);
+#ifdef TCP_OFFLOAD
+ if (ADDED_BY_TOE(sc)) {
+ struct toedev *tod = sc->sc_tod;
+
+ error = tod->tod_syncache_respond(tod, sc->sc_todctx, m);
+
+ return (error);
+ }
+#endif
error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
}
#endif
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index b943eb6..48444c1 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -119,6 +119,11 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0,
/* max idle probes */
int tcp_maxpersistidle;
+static int tcp_rexmit_drop_options = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW,
+ &tcp_rexmit_drop_options, 0,
+ "Drop TCP options from 3rd and later retransmitted SYN");
+
static int per_cpu_timers = 0;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, per_cpu_timers, CTLFLAG_RW,
&per_cpu_timers , 0, "run tcp timers on all cpus");
@@ -595,7 +600,8 @@ tcp_timer_rexmt(void * xtp)
* header compression code which trashes TCP segments containing
* unknown-to-them TCP options.
*/
- if ((tp->t_state == TCPS_SYN_SENT) && (tp->t_rxtshift == 3))
+ if (tcp_rexmit_drop_options && (tp->t_state == TCPS_SYN_SENT) &&
+ (tp->t_rxtshift == 3))
tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_SACK_PERMIT);
/*
* If we backed off this far, our srtt estimate is probably bogus.
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 85597d9..ef0aad1 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -370,7 +370,8 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td)
tp->t_state = TCPS_LISTEN;
solisten_proto(so, backlog);
#ifdef TCP_OFFLOAD
- tcp_offload_listen_start(tp);
+ if ((so->so_options & SO_NO_OFFLOAD) == 0)
+ tcp_offload_listen_start(tp);
#endif
}
SOCK_UNLOCK(so);
@@ -414,7 +415,8 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td)
tp->t_state = TCPS_LISTEN;
solisten_proto(so, backlog);
#ifdef TCP_OFFLOAD
- tcp_offload_listen_start(tp);
+ if ((so->so_options & SO_NO_OFFLOAD) == 0)
+ tcp_offload_listen_start(tp);
#endif
}
SOCK_UNLOCK(so);
@@ -468,6 +470,7 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto out;
#ifdef TCP_OFFLOAD
if (registered_toedevs > 0 &&
+ (so->so_options & SO_NO_OFFLOAD) == 0 &&
(error = tcp_offload_connect(so, nam)) == 0)
goto out;
#endif
@@ -534,6 +537,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto out;
#ifdef TCP_OFFLOAD
if (registered_toedevs > 0 &&
+ (so->so_options & SO_NO_OFFLOAD) == 0 &&
(error = tcp_offload_connect(so, nam)) == 0)
goto out;
#endif
@@ -550,6 +554,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto out;
#ifdef TCP_OFFLOAD
if (registered_toedevs > 0 &&
+ (so->so_options & SO_NO_OFFLOAD) == 0 &&
(error = tcp_offload_connect(so, nam)) == 0)
goto out;
#endif
@@ -766,6 +771,7 @@ tcp_usr_rcvd(struct socket *so, int flags)
#ifdef TCP_OFFLOAD
if (tp->t_flags & TF_TOE)
tcp_offload_rcvd(tp);
+ else
#endif
tcp_output(tp);
diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c
index 7e498dd..53d4778 100644
--- a/sys/netinet/toecore.c
+++ b/sys/netinet/toecore.c
@@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/in6_pcb.h>
#include <netinet6/nd6.h>
#define TCPSTATES
#include <netinet/tcp.h>
@@ -355,11 +357,14 @@ toe_4tuple_check(struct in_conninfo *inc, struct tcphdr *th, struct ifnet *ifp)
{
struct inpcb *inp;
- if (inc->inc_flags & INC_ISIPV6)
- return (ENOSYS); /* XXX: implement */
-
- inp = in_pcblookup(&V_tcbinfo, inc->inc_faddr, inc->inc_fport,
- inc->inc_laddr, inc->inc_lport, INPLOOKUP_WLOCKPCB, ifp);
+ if (inc->inc_flags & INC_ISIPV6) {
+ inp = in6_pcblookup(&V_tcbinfo, &inc->inc6_faddr,
+ inc->inc_fport, &inc->inc6_laddr, inc->inc_lport,
+ INPLOOKUP_WLOCKPCB, ifp);
+ } else {
+ inp = in_pcblookup(&V_tcbinfo, inc->inc_faddr, inc->inc_fport,
+ inc->inc_laddr, inc->inc_lport, INPLOOKUP_WLOCKPCB, ifp);
+ }
if (inp != NULL) {
INP_WLOCK_ASSERT(inp);
@@ -440,6 +445,68 @@ toe_route_redirect_event(void *arg __unused, struct rtentry *rt0,
return;
}
+#ifdef INET6
+/*
+ * XXX: no checks to verify that sa is really a neighbor because we assume it is
+ * the result of a route lookup and is on-link on the given ifp.
+ */
+static int
+toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
+{
+ struct llentry *lle;
+ struct sockaddr_in6 *sin6 = (void *)sa;
+ int rc, flags = 0;
+
+restart:
+ IF_AFDATA_RLOCK(ifp);
+ lle = lla_lookup(LLTABLE6(ifp), flags, sa);
+ IF_AFDATA_RUNLOCK(ifp);
+ if (lle == NULL) {
+ IF_AFDATA_LOCK(ifp);
+ lle = nd6_lookup(&sin6->sin6_addr, ND6_CREATE | ND6_EXCLUSIVE,
+ ifp);
+ IF_AFDATA_UNLOCK(ifp);
+ if (lle == NULL)
+ return (ENOMEM); /* Couldn't create entry in cache. */
+ lle->ln_state = ND6_LLINFO_INCOMPLETE;
+ nd6_llinfo_settimer_locked(lle,
+ (long)ND_IFINFO(ifp)->retrans * hz / 1000);
+ LLE_WUNLOCK(lle);
+
+ nd6_ns_output(ifp, NULL, &sin6->sin6_addr, NULL, 0);
+
+ return (EWOULDBLOCK);
+ }
+
+ if (lle->ln_state == ND6_LLINFO_STALE) {
+ if ((flags & LLE_EXCLUSIVE) == 0) {
+ LLE_RUNLOCK(lle);
+ flags |= LLE_EXCLUSIVE;
+ goto restart;
+ }
+
+ LLE_WLOCK_ASSERT(lle);
+
+ lle->la_asked = 0;
+ lle->ln_state = ND6_LLINFO_DELAY;
+ nd6_llinfo_settimer_locked(lle, (long)V_nd6_delay * hz);
+ }
+
+ if (lle->la_flags & LLE_VALID) {
+ memcpy(lladdr, &lle->ll_addr, ifp->if_addrlen);
+ rc = 0;
+ } else
+ rc = EWOULDBLOCK;
+
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(lle);
+ else
+ LLE_RUNLOCK(lle);
+
+ return (rc);
+}
+#endif
+
/*
* Returns 0 or EWOULDBLOCK on success (any other value is an error). 0 means
* lladdr and vtag are valid on return, EWOULDBLOCK means the TOE driver's
@@ -449,7 +516,9 @@ int
toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
uint8_t *lladdr, uint16_t *vtag)
{
+#ifdef INET
struct llentry *lle;
+#endif
int rc;
switch (sa->sa_family) {
@@ -460,7 +529,7 @@ toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
#endif
#ifdef INET6
case AF_INET6:
- rc = nd6_storelladdr(ifp, NULL, sa, lladdr, &lle);
+ rc = toe_nd6_resolve(ifp, sa, lladdr);
break;
#endif
default:
diff --git a/sys/netinet/udp.h b/sys/netinet/udp.h
index 2dbcaca..c2d638d 100644
--- a/sys/netinet/udp.h
+++ b/sys/netinet/udp.h
@@ -48,8 +48,10 @@ struct udphdr {
/*
* User-settable options (used with setsockopt).
*/
-#define UDP_ENCAP 0x01
+#define UDP_ENCAP 1
+/* Start of reserved space for third-party user-settable options. */
+#define UDP_VENDOR SO_VENDOR
/*
* UDP Encapsulation of IPsec Packets options.
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index fb7e6f0..8d04c46 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -383,10 +383,12 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*/
/* Rule 5: Prefer outgoing interface */
- if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp)
- NEXT(5);
- if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp)
- REPLACE(5);
+ if (!(ND_IFINFO(ifp)->flags & ND6_IFF_NO_PREFER_IFACE)) {
+ if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp)
+ NEXT(5);
+ if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp)
+ REPLACE(5);
+ }
/*
* Rule 6: Prefer matching label
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 5107f1d..fd420d8 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -509,6 +509,7 @@ nd6_llinfo_timer(void *arg)
ln->la_hold = m0;
clear_llinfo_pqueue(ln);
}
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_TIMEDOUT);
(void)nd6_free(ln, 0);
ln = NULL;
if (m != NULL)
@@ -526,6 +527,7 @@ nd6_llinfo_timer(void *arg)
case ND6_LLINFO_STALE:
/* Garbage Collection(RFC 2461 5.3) */
if (!ND6_LLINFO_PERMANENT(ln)) {
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
(void)nd6_free(ln, 1);
ln = NULL;
}
@@ -553,6 +555,7 @@ nd6_llinfo_timer(void *arg)
nd6_ns_output(ifp, dst, dst, ln, 0);
LLE_WLOCK(ln);
} else {
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
(void)nd6_free(ln, 0);
ln = NULL;
}
@@ -1601,6 +1604,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
*/
bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
ln->la_flags |= LLE_VALID;
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
}
if (!is_newentry) {
@@ -2166,7 +2170,7 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
*lle = NULL;
IF_AFDATA_UNLOCK_ASSERT(ifp);
- if (m->m_flags & M_MCAST) {
+ if (m != NULL && m->m_flags & M_MCAST) {
int i;
switch (ifp->if_type) {
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 1655a6c..94202e1 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -86,6 +86,7 @@ struct nd_ifinfo {
#define ND6_IFF_DONT_SET_IFROUTE 0x10
#define ND6_IFF_AUTO_LINKLOCAL 0x20
#define ND6_IFF_NO_RADR 0x40
+#define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */
#define ND6_CREATE LLE_CREATE
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 31d0ccb..7fe75bf 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -762,6 +762,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
ln->la_flags |= LLE_VALID;
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
if (is_solicited) {
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
@@ -837,6 +838,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
if (lladdr != NULL) {
bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
ln->la_flags |= LLE_VALID;
+ EVENTHANDLER_INVOKE(lle_event, ln,
+ LLENTRY_RESOLVED);
}
/*
diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c
index 74d034e..b6479a1 100644
--- a/sys/netinet6/scope6.c
+++ b/sys/netinet6/scope6.c
@@ -336,7 +336,6 @@ scope6_addr2default(struct in6_addr *addr)
int
sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
{
- struct ifnet *ifp;
u_int32_t zoneid;
if ((zoneid = sin6->sin6_scope_id) == 0 && defaultok)
@@ -351,15 +350,11 @@ sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
* zone IDs assuming a one-to-one mapping between interfaces
* and links.
*/
- if (V_if_index < zoneid)
- return (ENXIO);
- ifp = ifnet_byindex(zoneid);
- if (ifp == NULL) /* XXX: this can happen for some OS */
+ if (V_if_index < zoneid || ifnet_byindex(zoneid) == NULL)
return (ENXIO);
/* XXX assignment to 16bit from 32bit variable */
sin6->sin6_addr.s6_addr16[1] = htons(zoneid & 0xffff);
-
sin6->sin6_scope_id = 0;
}
@@ -425,59 +420,30 @@ in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
* interface.
*/
if (IN6_IS_ADDR_LOOPBACK(in6)) {
- if (!(ifp->if_flags & IFF_LOOPBACK)) {
+ if (!(ifp->if_flags & IFF_LOOPBACK))
return (EINVAL);
- } else {
- if (ret_id != NULL)
- *ret_id = 0; /* there's no ambiguity */
- return (0);
+ } else {
+ scope = in6_addrscope(in6);
+ if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL ||
+ scope == IPV6_ADDR_SCOPE_LINKLOCAL) {
+ /*
+ * Currently we use interface indeces as the
+ * zone IDs for interface-local and link-local
+ * scopes.
+ */
+ zoneid = ifp->if_index;
+ in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
+ } else if (scope != IPV6_ADDR_SCOPE_GLOBAL) {
+ IF_AFDATA_RLOCK(ifp);
+ sid = SID(ifp);
+ zoneid = sid->s6id_list[scope];
+ IF_AFDATA_RUNLOCK(ifp);
}
}
- if (ret_id == NULL && !IN6_IS_SCOPE_EMBED(in6))
- return (0);
-
- IF_AFDATA_RLOCK(ifp);
-
- sid = SID(ifp);
-
-#ifdef DIAGNOSTIC
- if (sid == NULL) { /* should not happen */
- panic("in6_setscope: scope array is NULL");
- /* NOTREACHED */
- }
-#endif
-
- scope = in6_addrscope(in6);
- switch (scope) {
- case IPV6_ADDR_SCOPE_INTFACELOCAL: /* should be interface index */
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_LINKLOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_SITELOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_ORGLOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL];
- break;
-
- default:
- zoneid = 0; /* XXX: treat as global. */
- break;
- }
- IF_AFDATA_RUNLOCK(ifp);
-
if (ret_id != NULL)
*ret_id = zoneid;
- if (IN6_IS_SCOPE_EMBED(in6))
- in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
-
return (0);
}
diff --git a/sys/nfs/nfs_common.c b/sys/nfs/nfs_common.c
index 6f03948..83e7125 100644
--- a/sys/nfs/nfs_common.c
+++ b/sys/nfs/nfs_common.c
@@ -90,15 +90,6 @@ static int nfs_realign_count;
SYSCTL_INT(_vfs_nfs_common, OID_AUTO, realign_count, CTLFLAG_RD,
&nfs_realign_count, 0, "Number of mbuf realignments done");
-u_quad_t
-nfs_curusec(void)
-{
- struct timeval tv;
-
- getmicrotime(&tv);
- return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec);
-}
-
/*
* copies mbuf chain to the uio scatter/gather list
*/
diff --git a/sys/nfs/nfs_common.h b/sys/nfs/nfs_common.h
index 1c0b315..c3420b3 100644
--- a/sys/nfs/nfs_common.h
+++ b/sys/nfs/nfs_common.h
@@ -46,7 +46,6 @@ extern nfstype nfsv3_type[];
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))])
int nfs_adv(struct mbuf **, caddr_t *, int, int);
-u_quad_t nfs_curusec(void);
void *nfsm_disct(struct mbuf **, caddr_t *, int, int, int);
int nfs_realign(struct mbuf **, int);
diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c
index 0e4a83e..dd441ae 100644
--- a/sys/nfsclient/nfs_krpc.c
+++ b/sys/nfsclient/nfs_krpc.c
@@ -394,18 +394,17 @@ nfs_feedback(int type, int proc, void *arg)
{
struct nfs_feedback_arg *nf = (struct nfs_feedback_arg *) arg;
struct nfsmount *nmp = nf->nf_mount;
- struct timeval now;
-
- getmicrouptime(&now);
+ time_t now;
switch (type) {
case FEEDBACK_REXMIT2:
case FEEDBACK_RECONNECT:
- if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now.tv_sec) {
+ now = time_uptime;
+ if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now) {
nfs_down(nmp, nf->nf_td,
"not responding", 0, NFSSTA_TIMEO);
nf->nf_tprintfmsg = TRUE;
- nf->nf_lastmsg = now.tv_sec;
+ nf->nf_lastmsg = now;
}
break;
@@ -438,7 +437,6 @@ nfs_request(struct vnode *vp, struct mbuf *mreq, int procnum,
time_t waituntil;
caddr_t dpos;
int error = 0, timeo;
- struct timeval now;
AUTH *auth = NULL;
enum nfs_rto_timer_t timer;
struct nfs_feedback_arg nf;
@@ -455,8 +453,7 @@ nfs_request(struct vnode *vp, struct mbuf *mreq, int procnum,
bzero(&nf, sizeof(struct nfs_feedback_arg));
nf.nf_mount = nmp;
nf.nf_td = td;
- getmicrouptime(&now);
- nf.nf_lastmsg = now.tv_sec -
+ nf.nf_lastmsg = time_uptime -
((nmp->nm_tprintf_delay) - (nmp->nm_tprintf_initial_delay));
/*
@@ -549,14 +546,21 @@ tryagain:
*/
if (stat == RPC_SUCCESS)
error = 0;
- else if (stat == RPC_TIMEDOUT)
+ else if (stat == RPC_TIMEDOUT) {
+ nfsstats.rpctimeouts++;
error = ETIMEDOUT;
- else if (stat == RPC_VERSMISMATCH)
+ } else if (stat == RPC_VERSMISMATCH) {
+ nfsstats.rpcinvalid++;
error = EOPNOTSUPP;
- else if (stat == RPC_PROGVERSMISMATCH)
+ } else if (stat == RPC_PROGVERSMISMATCH) {
+ nfsstats.rpcinvalid++;
error = EPROTONOSUPPORT;
- else
+ } else if (stat == RPC_INTR) {
+ error = EINTR;
+ } else {
+ nfsstats.rpcinvalid++;
error = EACCES;
+ }
if (error)
goto nfsmout;
@@ -572,6 +576,7 @@ tryagain:
if (error == ENOMEM) {
m_freem(mrep);
AUTH_DESTROY(auth);
+ nfsstats.rpcinvalid++;
return (error);
}
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index fd83794..3723223 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -1110,7 +1110,7 @@ nfsm_v3attrbuild_xx(struct vattr *va, int full, struct mbuf **mb,
*tl = nfs_false;
}
if (va->va_atime.tv_sec != VNOVAL) {
- if (va->va_atime.tv_sec != time_second) {
+ if ((va->va_vaflags & VA_UTIMES_NULL) == 0) {
tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos);
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
txdr_nfsv3time(&va->va_atime, tl);
@@ -1123,7 +1123,7 @@ nfsm_v3attrbuild_xx(struct vattr *va, int full, struct mbuf **mb,
*tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
}
if (va->va_mtime.tv_sec != VNOVAL) {
- if (va->va_mtime.tv_sec != time_second) {
+ if ((va->va_vaflags & VA_UTIMES_NULL) == 0) {
tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos);
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
txdr_nfsv3time(&va->va_mtime, tl);
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index ca9edad..5026daf 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -3458,7 +3458,7 @@ nfsfifo_read(struct vop_read_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_flag |= NACC;
- getnanotime(&np->n_atim);
+ vfs_timestamp(&np->n_atim);
mtx_unlock(&np->n_mtx);
error = fifo_specops.vop_read(ap);
return error;
@@ -3477,7 +3477,7 @@ nfsfifo_write(struct vop_write_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_flag |= NUPD;
- getnanotime(&np->n_mtim);
+ vfs_timestamp(&np->n_mtim);
mtx_unlock(&np->n_mtx);
return(fifo_specops.vop_write(ap));
}
@@ -3497,7 +3497,7 @@ nfsfifo_close(struct vop_close_args *ap)
mtx_lock(&np->n_mtx);
if (np->n_flag & (NACC | NUPD)) {
- getnanotime(&ts);
+ vfs_timestamp(&ts);
if (np->n_flag & NACC)
np->n_atim = ts;
if (np->n_flag & NUPD)
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index eedac6c..04371da 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -1393,7 +1393,7 @@ nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
toclient = 1;
break;
case NFSV3SATTRTIME_TOSERVER:
- getnanotime(&(a)->va_atime);
+ vfs_timestamp(&a->va_atime);
a->va_vaflags |= VA_UTIMES_NULL;
break;
}
@@ -1409,7 +1409,7 @@ nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
a->va_vaflags &= ~VA_UTIMES_NULL;
break;
case NFSV3SATTRTIME_TOSERVER:
- getnanotime(&(a)->va_mtime);
+ vfs_timestamp(&a->va_mtime);
if (toclient == 0)
a->va_vaflags |= VA_UTIMES_NULL;
break;
diff --git a/sys/pc98/cbus/pckbd.c b/sys/pc98/cbus/pckbd.c
index 5efb983..e424294 100644
--- a/sys/pc98/cbus/pckbd.c
+++ b/sys/pc98/cbus/pckbd.c
@@ -77,9 +77,9 @@ DRIVER_MODULE(pckbd, isa, pckbd_driver, pckbd_devclass, 0, 0);
static bus_addr_t pckbd_iat[] = {0, 2};
-static int pckbd_probe_unit(int unit, int port, int irq,
+static int pckbd_probe_unit(device_t dev, int port, int irq,
int flags);
-static int pckbd_attach_unit(int unit, keyboard_t **kbd,
+static int pckbd_attach_unit(device_t dev, keyboard_t **kbd,
int port, int irq, int flags);
static timeout_t pckbd_timeout;
@@ -103,7 +103,7 @@ pckbdprobe(device_t dev)
return ENXIO;
isa_load_resourcev(res, pckbd_iat, 2);
- error = pckbd_probe_unit(device_get_unit(dev),
+ error = pckbd_probe_unit(dev,
isa_get_port(dev),
(1 << isa_get_irq(dev)),
device_get_flags(dev));
@@ -128,7 +128,7 @@ pckbdattach(device_t dev)
return ENXIO;
isa_load_resourcev(res, pckbd_iat, 2);
- error = pckbd_attach_unit(device_get_unit(dev), &kbd,
+ error = pckbd_attach_unit(dev, &kbd,
isa_get_port(dev),
(1 << isa_get_irq(dev)),
device_get_flags(dev));
@@ -164,7 +164,7 @@ pckbd_isa_intr(void *arg)
}
static int
-pckbd_probe_unit(int unit, int port, int irq, int flags)
+pckbd_probe_unit(device_t dev, int port, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
@@ -176,24 +176,26 @@ pckbd_probe_unit(int unit, int port, int irq, int flags)
args[0] = port;
args[1] = irq;
- error = (*sw->probe)(unit, args, flags);
+ error = (*sw->probe)(device_get_unit(dev), args, flags);
if (error)
return error;
return 0;
}
static int
-pckbd_attach_unit(int unit, keyboard_t **kbd, int port, int irq, int flags)
+pckbd_attach_unit(device_t dev, keyboard_t **kbd, int port, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
int error;
+ int unit;
sw = kbd_get_switch(DRIVER_NAME);
if (sw == NULL)
return ENXIO;
/* reset, initialize and enable the device */
+ unit = device_get_unit(dev);
args[0] = port;
args[1] = irq;
*kbd = NULL;
diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC
index 2b048a9..eda1d14 100644
--- a/sys/pc98/conf/GENERIC
+++ b/sys/pc98/conf/GENERIC
@@ -151,7 +151,6 @@ device mse
device ppc
device ppbus # Parallel port bus (required)
device lpt # Printer
-device plip # TCP/IP over parallel
device ppi # Parallel port interface device
#device vpo # Requires scbus and da
# OLD Parallel port
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index 98e3352..4f91d1f 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -148,6 +148,8 @@ static const struct rl_type rl_devs[] = {
"Delta Electronics 8139 10/100BaseTX" },
{ ADDTRON_VENDORID, ADDTRON_DEVICEID_8139, RL_8139,
"Addtron Technology 8139 10/100BaseTX" },
+ { DLINK_VENDORID, DLINK_DEVICEID_520TX_REVC1, RL_8139,
+ "D-Link DFE-520TX (rev. C1) 10/100BaseTX" },
{ DLINK_VENDORID, DLINK_DEVICEID_530TXPLUS, RL_8139,
"D-Link DFE-530TX+ 10/100BaseTX" },
{ DLINK_VENDORID, DLINK_DEVICEID_690TXD, RL_8139,
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index 7822ce3..be89c4f5 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -1048,6 +1048,11 @@ struct rl_softc {
#define DLINK_DEVICEID_530TXPLUS 0x1300
/*
+ * D-Link DFE-520TX rev. C1 device ID
+ */
+#define DLINK_DEVICEID_520TX_REVC1 0x4200
+
+/*
* D-Link DFE-5280T device ID
*/
#define DLINK_DEVICEID_528T 0x4300
diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c
index 793ae80..ead7d43 100644
--- a/sys/pci/ncr.c
+++ b/sys/pci/ncr.c
@@ -1386,7 +1386,7 @@ static char *ncr_name (ncb_p np)
* Kernel variables referenced in the scripts.
* THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY.
*/
-static void *script_kvars[] =
+static volatile void *script_kvars[] =
{ &time_second, &ticks, &ncr_cache };
static struct script script0 = {
diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c
index 2063c9d..cb3406d 100644
--- a/sys/security/audit/audit.c
+++ b/sys/security/audit/audit.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/filedesc.h>
#include <sys/fcntl.h>
#include <sys/ipc.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/malloc.h>
@@ -211,6 +212,7 @@ audit_record_ctor(void *mem, int size, void *arg, int flags)
struct kaudit_record *ar;
struct thread *td;
struct ucred *cred;
+ struct prison *pr;
KASSERT(sizeof(*ar) == size, ("audit_record_ctor: wrong size"));
@@ -233,6 +235,17 @@ audit_record_ctor(void *mem, int size, void *arg, int flags)
ar->k_ar.ar_subj_pid = td->td_proc->p_pid;
ar->k_ar.ar_subj_amask = cred->cr_audit.ai_mask;
ar->k_ar.ar_subj_term_addr = cred->cr_audit.ai_termid;
+ /*
+ * If this process is jailed, make sure we capture the name of the
+ * jail so we can use it to generate a zonename token when we covert
+ * this record to BSM.
+ */
+ if (jailed(cred)) {
+ pr = cred->cr_prison;
+ (void) strlcpy(ar->k_ar.ar_jailname, pr->pr_name,
+ sizeof(ar->k_ar.ar_jailname));
+ } else
+ ar->k_ar.ar_jailname[0] = '\0';
return (0);
}
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
index 6e49b51..b02d677 100644
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -462,7 +462,7 @@ audit_sys_auditon(struct audit_record *ar, struct au_record *rec)
int
kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
{
- struct au_token *tok, *subj_tok;
+ struct au_token *tok, *subj_tok, *jail_tok;
struct au_record *rec;
au_tid_t tid;
struct audit_record *ar;
@@ -475,8 +475,13 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
rec = kau_open();
/*
- * Create the subject token.
+ * Create the subject token. If this credential was jailed be sure to
+ * generate a zonename token.
*/
+ if (ar->ar_jailname[0] != '\0')
+ jail_tok = au_to_zonename(ar->ar_jailname);
+ else
+ jail_tok = NULL;
switch (ar->ar_subj_term_addr.at_type) {
case AU_IPv4:
tid.port = ar->ar_subj_term_addr.at_port;
@@ -1623,11 +1628,15 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
/*
* Write the subject token so it is properly freed here.
*/
+ if (jail_tok != NULL)
+ kau_write(rec, jail_tok);
kau_write(rec, subj_tok);
kau_free(rec);
return (BSM_NOAUDIT);
}
+ if (jail_tok != NULL)
+ kau_write(rec, jail_tok);
kau_write(rec, subj_tok);
tok = au_to_return32(au_errno_to_bsm(ar->ar_errno), ar->ar_retval);
kau_write(rec, tok); /* Every record gets a return token */
diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h
index ad931c0..a5716d0 100644
--- a/sys/security/audit/audit_private.h
+++ b/sys/security/audit/audit_private.h
@@ -230,6 +230,7 @@ struct audit_record {
int ar_arg_exitretval;
struct sockaddr_storage ar_arg_sockaddr;
cap_rights_t ar_arg_rights;
+ char ar_jailname[MAXHOSTNAMELEN];
};
/*
diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC
index f9d3b93..79124ab 100644
--- a/sys/sparc64/conf/GENERIC
+++ b/sys/sparc64/conf/GENERIC
@@ -161,7 +161,6 @@ device uart # Multi-uart driver
#device ppc
#device ppbus # Parallel port bus (required)
#device lpt # Printer
-#device plip # TCP/IP over parallel
#device ppi # Parallel port interface device
#device vpo # Requires scbus and da
diff --git a/sys/sparc64/include/smp.h b/sys/sparc64/include/smp.h
index db17309..2e1110b 100644
--- a/sys/sparc64/include/smp.h
+++ b/sys/sparc64/include/smp.h
@@ -42,6 +42,7 @@
#include <sys/cpuset.h>
#include <sys/proc.h>
#include <sys/sched.h>
+#include <sys/smp.h>
#include <machine/intr_machdep.h>
#include <machine/pcb.h>
@@ -202,6 +203,7 @@ ipi_rd(u_int cpu, void *func, u_long *val)
return (NULL);
sched_pin();
ira = &ipi_rd_args;
+ mtx_lock_spin(&smp_ipi_mtx);
CPU_SETOF(cpu, &ira->ira_mask);
ira->ira_val = val;
cpu_ipi_single(cpu, 0, (u_long)func, (u_long)ira);
@@ -298,18 +300,6 @@ ipi_wait(void *cookie)
}
}
-static __inline void
-ipi_wait_unlocked(void *cookie)
-{
- volatile cpuset_t *mask;
-
- if ((mask = cookie) != NULL) {
- while (!CPU_EMPTY(mask))
- ;
- sched_unpin();
- }
-}
-
#endif /* _MACHINE_PMAP_H_ && _SYS_MUTEX_H_ */
#endif /* !LOCORE */
@@ -368,12 +358,6 @@ ipi_wait(void *cookie __unused)
}
static __inline void
-ipi_wait_unlocked(void *cookie __unused)
-{
-
-}
-
-static __inline void
tl_ipi_cheetah_dcache_page_inval(void)
{
diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c
index 69062ec..cfd5776 100644
--- a/sys/sparc64/sparc64/tick.c
+++ b/sys/sparc64/sparc64/tick.c
@@ -334,7 +334,7 @@ stick_get_timecount_mp(struct timecounter *tc)
if (curcpu == 0)
stick = rdstick();
else
- ipi_wait_unlocked(ipi_rd(0, tl_ipi_stick_rd, &stick));
+ ipi_wait(ipi_rd(0, tl_ipi_stick_rd, &stick));
sched_unpin();
return (stick);
}
@@ -348,7 +348,7 @@ tick_get_timecount_mp(struct timecounter *tc)
if (curcpu == 0)
tick = rd(tick);
else
- ipi_wait_unlocked(ipi_rd(0, tl_ipi_tick_rd, &tick));
+ ipi_wait(ipi_rd(0, tl_ipi_tick_rd, &tick));
sched_unpin();
return (tick);
}
diff --git a/sys/sys/bufobj.h b/sys/sys/bufobj.h
index 3934553..79bef84 100644
--- a/sys/sys/bufobj.h
+++ b/sys/sys/bufobj.h
@@ -89,12 +89,7 @@ struct buf_ops {
struct bufobj {
struct mtx bo_mtx; /* Mutex which protects "i" things */
- struct bufv bo_clean; /* i Clean buffers */
- struct bufv bo_dirty; /* i Dirty buffers */
- long bo_numoutput; /* i Writes in progress */
- u_int bo_flag; /* i Flags */
struct buf_ops *bo_ops; /* - Buffer operations */
- int bo_bsize; /* - Block size for i/o */
struct vm_object *bo_object; /* v Place to store VM object */
LIST_ENTRY(bufobj) bo_synclist; /* S dirty vnode list */
void *bo_private; /* private pointer */
@@ -103,6 +98,11 @@ struct bufobj {
* XXX: only to keep the syncer working
* XXX: for now.
*/
+ struct bufv bo_clean; /* i Clean buffers */
+ struct bufv bo_dirty; /* i Dirty buffers */
+ long bo_numoutput; /* i Writes in progress */
+ u_int bo_flag; /* i Flags */
+ int bo_bsize; /* - Block size for i/o */
};
/*
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index 441bcb3..c54677a 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -63,7 +63,7 @@ extern int psratio; /* ratio: prof / stat */
extern int stathz; /* statistics clock's frequency */
extern int profhz; /* profiling clock's frequency */
extern int profprocs; /* number of process's profiling */
-extern int ticks;
+extern volatile int ticks;
#endif /* _KERNEL */
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 22742c9..af7f92b 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -52,11 +52,14 @@
* stored. Additionally, it is possible to allocate a separate buffer
* externally and attach it to the mbuf in a way similar to that of mbuf
* clusters.
+ *
+ * MLEN is data length in a normal mbuf.
+ * MHLEN is data length in an mbuf with pktheader.
+ * MINCLSIZE is a smallest amount of data that should be put into cluster.
*/
-#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */
-#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */
-#define MINCLSIZE (MHLEN + 1) /* smallest amount to put in cluster */
-#define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */
+#define MLEN ((int)(MSIZE - sizeof(struct m_hdr)))
+#define MHLEN ((int)(MLEN - sizeof(struct pkthdr)))
+#define MINCLSIZE (MHLEN + 1)
#ifdef _KERNEL
/*-
@@ -384,7 +387,6 @@ struct mbstat {
*
* The rest of it is defined in kern/kern_mbuf.c
*/
-extern quad_t maxmbufmem;
extern uma_zone_t zone_mbuf;
extern uma_zone_t zone_clust;
extern uma_zone_t zone_pack;
@@ -393,23 +395,8 @@ extern uma_zone_t zone_jumbo9;
extern uma_zone_t zone_jumbo16;
extern uma_zone_t zone_ext_refcnt;
-static __inline struct mbuf *m_getcl(int how, short type, int flags);
-static __inline struct mbuf *m_get(int how, short type);
-static __inline struct mbuf *m_get2(int how, short type, int flags,
- u_int size);
-static __inline struct mbuf *m_gethdr(int how, short type);
-static __inline struct mbuf *m_getjcl(int how, short type, int flags,
- int size);
-static __inline struct mbuf *m_getclr(int how, short type); /* XXX */
-static __inline int m_init(struct mbuf *m, uma_zone_t zone,
- int size, int how, short type, int flags);
-static __inline struct mbuf *m_free(struct mbuf *m);
-static __inline void m_clget(struct mbuf *m, int how);
-static __inline void *m_cljget(struct mbuf *m, int how, int size);
-static __inline void m_chtype(struct mbuf *m, short new_type);
-void mb_free_ext(struct mbuf *);
-static __inline struct mbuf *m_last(struct mbuf *m);
-int m_pkthdr_init(struct mbuf *m, int how);
+void mb_free_ext(struct mbuf *);
+int m_pkthdr_init(struct mbuf *, int);
static __inline int
m_gettype(int size)
@@ -502,7 +489,7 @@ m_get(int how, short type)
args.flags = 0;
args.type = type;
- return ((struct mbuf *)(uma_zalloc_arg(zone_mbuf, &args, how)));
+ return (uma_zalloc_arg(zone_mbuf, &args, how));
}
/*
@@ -529,7 +516,7 @@ m_gethdr(int how, short type)
args.flags = M_PKTHDR;
args.type = type;
- return ((struct mbuf *)(uma_zalloc_arg(zone_mbuf, &args, how)));
+ return (uma_zalloc_arg(zone_mbuf, &args, how));
}
static __inline struct mbuf *
@@ -539,85 +526,7 @@ m_getcl(int how, short type, int flags)
args.flags = flags;
args.type = type;
- return ((struct mbuf *)(uma_zalloc_arg(zone_pack, &args, how)));
-}
-
-/*
- * m_get2() allocates minimum mbuf that would fit "size" argument.
- *
- * XXX: This is rather large, should be real function maybe.
- */
-static __inline struct mbuf *
-m_get2(int how, short type, int flags, u_int size)
-{
- struct mb_args args;
- struct mbuf *m, *n;
- uma_zone_t zone;
-
- args.flags = flags;
- args.type = type;
-
- if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
- return ((struct mbuf *)(uma_zalloc_arg(zone_mbuf, &args, how)));
- if (size <= MCLBYTES)
- return ((struct mbuf *)(uma_zalloc_arg(zone_pack, &args, how)));
-
- if (size > MJUM16BYTES)
- return (NULL);
-
- m = uma_zalloc_arg(zone_mbuf, &args, how);
- if (m == NULL)
- return (NULL);
-
-#if MJUMPAGESIZE != MCLBYTES
- if (size <= MJUMPAGESIZE)
- zone = zone_jumbop;
- else
-#endif
- if (size <= MJUM9BYTES)
- zone = zone_jumbo9;
- else
- zone = zone_jumbo16;
-
- n = uma_zalloc_arg(zone, m, how);
- if (n == NULL) {
- uma_zfree(zone_mbuf, m);
- return (NULL);
- }
-
- return (m);
-}
-
-/*
- * m_getjcl() returns an mbuf with a cluster of the specified size attached.
- * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
- *
- * XXX: This is rather large, should be real function maybe.
- */
-static __inline struct mbuf *
-m_getjcl(int how, short type, int flags, int size)
-{
- struct mb_args args;
- struct mbuf *m, *n;
- uma_zone_t zone;
-
- if (size == MCLBYTES)
- return m_getcl(how, type, flags);
-
- args.flags = flags;
- args.type = type;
-
- m = uma_zalloc_arg(zone_mbuf, &args, how);
- if (m == NULL)
- return (NULL);
-
- zone = m_getzone(size);
- n = uma_zalloc_arg(zone, m, how);
- if (n == NULL) {
- uma_zfree(zone_mbuf, m);
- return (NULL);
- }
- return (m);
+ return (uma_zalloc_arg(zone_pack, &args, how));
}
static __inline void
@@ -881,7 +790,7 @@ struct mbuf *m_copymdata(struct mbuf *, struct mbuf *,
int, int, int, int);
struct mbuf *m_copypacket(struct mbuf *, int);
void m_copy_pkthdr(struct mbuf *, struct mbuf *);
-struct mbuf *m_copyup(struct mbuf *n, int len, int dstoff);
+struct mbuf *m_copyup(struct mbuf *, int, int);
struct mbuf *m_defrag(struct mbuf *, int);
void m_demote(struct mbuf *, int);
struct mbuf *m_devget(char *, int, int, struct ifnet *,
@@ -891,6 +800,8 @@ int m_dup_pkthdr(struct mbuf *, struct mbuf *, int);
u_int m_fixhdr(struct mbuf *);
struct mbuf *m_fragment(struct mbuf *, int, int);
void m_freem(struct mbuf *);
+struct mbuf *m_get2(int, short, int, int);
+struct mbuf *m_getjcl(int, short, int, int);
struct mbuf *m_getm2(struct mbuf *, int, int, short, int);
struct mbuf *m_getptr(struct mbuf *, int, int *);
u_int m_length(struct mbuf *, struct mbuf **);
@@ -900,10 +811,10 @@ struct mbuf *m_prepend(struct mbuf *, int, int);
void m_print(const struct mbuf *, int);
struct mbuf *m_pulldown(struct mbuf *, int, int, int *);
struct mbuf *m_pullup(struct mbuf *, int);
-int m_sanity(struct mbuf *, int);
+int m_sanity(struct mbuf *, int);
struct mbuf *m_split(struct mbuf *, int, int);
struct mbuf *m_uiotombuf(struct uio *, int, int, int, int);
-struct mbuf *m_unshare(struct mbuf *, int how);
+struct mbuf *m_unshare(struct mbuf *, int);
/*-
* Network packets may have annotations attached by affixing a list of
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 992227c..bbbc569 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -762,8 +762,9 @@ extern struct nfs_public nfs_pub;
/*
* Declarations for these vfs default operations are located in
- * kern/vfs_default.c, they should be used instead of making "dummy"
- * functions or casting entries in the VFS op table to "enopnotsupp()".
+ * kern/vfs_default.c. They will be automatically used to replace
+ * null entries in VFS ops tables when registering a new filesystem
+ * type in the global table.
*/
vfs_root_t vfs_stdroot;
vfs_quotactl_t vfs_stdquotactl;
diff --git a/sys/sys/param.h b/sys/sys/param.h
index d7a74f2..c290466 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -48,9 +48,9 @@
* __FreeBSD_version numbers are documented in the Porter's Handbook.
* If you bump the version for any reason, you should update the documentation
* there.
- * Currently this lives here:
+ * Currently this lives here in the doc/ repository:
*
- * doc/en_US.ISO8859-1/books/porters-handbook/book.sgml
+ * head/en_US.ISO8859-1/books/porters-handbook/book.xml
*
* scheme is: <major><two digit minor>Rxx
* 'R' is in the range 0 to 4 if this is a release branch or
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1000025 /* Master, propagated to newvers */
+#define __FreeBSD_version 1000027 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
@@ -156,8 +156,8 @@
* MCLBYTES must be no larger than PAGE_SIZE.
*/
#ifndef MSIZE
-#define MSIZE 256 /* size of an mbuf */
-#endif /* MSIZE */
+#define MSIZE 256 /* size of an mbuf */
+#endif
#ifndef MCLSHIFT
#define MCLSHIFT 11 /* convert bytes to mbuf clusters */
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
index 7db7dff..2d7665a 100644
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -89,6 +89,7 @@
__PMC_CPU(INTEL_SANDYBRIDGE, 0x8D, "Intel Sandy Bridge") \
__PMC_CPU(INTEL_IVYBRIDGE, 0x8E, "Intel Ivy Bridge") \
__PMC_CPU(INTEL_SANDYBRIDGE_XEON, 0x8F, "Intel Sandy Bridge Xeon") \
+ __PMC_CPU(INTEL_IVYBRIDGE_XEON, 0x90, "Intel Ivy Bridge Xeon") \
__PMC_CPU(INTEL_XSCALE, 0x100, "Intel XScale") \
__PMC_CPU(MIPS_24K, 0x200, "MIPS 24K") \
__PMC_CPU(MIPS_OCTEON, 0x201, "Cavium Octeon") \
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index d7c6c79..c29a689 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -143,6 +143,15 @@ typedef __uid_t uid_t;
#endif
/*
+ * Space reserved for new socket options added by third-party vendors.
+ * This range applies to all socket option levels. New socket options
+ * in FreeBSD should always use an option value less than SO_VENDOR.
+ */
+#if __BSD_VISIBLE
+#define SO_VENDOR 0x80000000
+#endif
+
+/*
* Structure used for manipulating linger option.
*/
struct linger {
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 7c3f13e..dd96d70 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -49,6 +49,7 @@ extern int cold; /* nonzero if we are doing a cold boot */
extern int rebooting; /* kern_reboot() has been called. */
extern const char *panicstr; /* panic message */
extern char version[]; /* system version */
+extern char compiler_version[]; /* compiler version */
extern char copyright[]; /* system copyright */
extern int kstack_pages; /* number of kernel stack pages */
diff --git a/sys/sys/time.h b/sys/sys/time.h
index 12d43cf..80878c0 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -287,8 +287,8 @@ struct clockinfo {
void inittodr(time_t base);
void resettodr(void);
-extern time_t time_second;
-extern time_t time_uptime;
+extern volatile time_t time_second;
+extern volatile time_t time_uptime;
extern struct bintime boottimebin;
extern struct timeval boottime;
diff --git a/sys/sys/un.h b/sys/sys/un.h
index 1f4731e..7837e76 100644
--- a/sys/sys/un.h
+++ b/sys/sys/un.h
@@ -53,9 +53,12 @@ struct sockaddr_un {
#if __BSD_VISIBLE
/* Socket options. */
-#define LOCAL_PEERCRED 0x001 /* retrieve peer credentials */
-#define LOCAL_CREDS 0x002 /* pass credentials to receiver */
-#define LOCAL_CONNWAIT 0x004 /* connects block until accepted */
+#define LOCAL_PEERCRED 1 /* retrieve peer credentials */
+#define LOCAL_CREDS 2 /* pass credentials to receiver */
+#define LOCAL_CONNWAIT 4 /* connects block until accepted */
+
+/* Start of reserved space for third-party socket options. */
+#define LOCAL_VENDOR SO_VENDOR
#ifndef _KERNEL
diff --git a/sys/sys/vdso.h b/sys/sys/vdso.h
index 653a606..f584315 100644
--- a/sys/sys/vdso.h
+++ b/sys/sys/vdso.h
@@ -61,13 +61,9 @@ struct timeval;
struct timezone;
int __vdso_clock_gettime(clockid_t clock_id, struct timespec *ts);
-#pragma weak __vdso_clock_gettime
-
int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz);
-#pragma weak __vdso_gettimeofday
-
u_int __vdso_gettc(const struct vdso_timehands *vdso_th);
-#pragma weak __vdso_gettc
+int __vdso_gettimekeep(struct vdso_timekeep **tk);
#endif
diff --git a/sys/sys/vmmeter.h b/sys/sys/vmmeter.h
index 1a29ec1..59b430d 100644
--- a/sys/sys/vmmeter.h
+++ b/sys/sys/vmmeter.h
@@ -61,6 +61,7 @@ struct vmmeter {
* Virtual memory activity.
*/
u_int v_vm_faults; /* (p) address memory faults */
+ u_int v_io_faults; /* (p) page faults requiring I/O */
u_int v_cow_faults; /* (p) copy-on-writes faults */
u_int v_cow_optim; /* (p) optimized copy-on-writes faults */
u_int v_zfod; /* (p) pages zero filled on demand */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index f487f37..b54dc04 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -99,7 +99,6 @@ struct vnode {
* Fields which define the identity of the vnode. These fields are
* owned by the filesystem (XXX: and vgone() ?)
*/
- enum vtype v_type; /* u vnode type */
const char *v_tag; /* u type of underlying data */
struct vop_vector *v_op; /* u vnode operations vector */
void *v_data; /* u private data for fs */
@@ -122,10 +121,10 @@ struct vnode {
} v_un;
/*
- * vfs_hash: (mount + inode) -> vnode hash.
+ * vfs_hash: (mount + inode) -> vnode hash. The hash value
+ * itself is grouped with other int fields, to avoid padding.
*/
LIST_ENTRY(vnode) v_hashlist;
- u_int v_hash;
/*
* VFS_namecache stuff
@@ -135,24 +134,11 @@ struct vnode {
struct namecache *v_cache_dd; /* c Cache entry for .. vnode */
/*
- * clustering stuff
- */
- daddr_t v_cstart; /* v start block of cluster */
- daddr_t v_lasta; /* v last allocation */
- daddr_t v_lastw; /* v last write */
- int v_clen; /* v length of cur. cluster */
-
- /*
* Locking
*/
struct lock v_lock; /* u (if fs don't have one) */
struct mtx v_interlock; /* lock for "i" things */
struct lock *v_vnlock; /* u pointer to vnode lock */
- int v_holdcnt; /* i prevents recycling. */
- int v_usecount; /* i ref count of users */
- u_int v_iflag; /* i vnode flags (see below) */
- u_int v_vflag; /* v vnode flags */
- int v_writecount; /* v ref count of writers */
/*
* The machinery of being a vnode
@@ -167,6 +153,22 @@ struct vnode {
struct label *v_label; /* MAC label for vnode */
struct lockf *v_lockf; /* Byte-level advisory lock list */
struct rangelock v_rl; /* Byte-range lock */
+
+ /*
+ * clustering stuff
+ */
+ daddr_t v_cstart; /* v start block of cluster */
+ daddr_t v_lasta; /* v last allocation */
+ daddr_t v_lastw; /* v last write */
+ int v_clen; /* v length of cur. cluster */
+
+ int v_holdcnt; /* i prevents recycling. */
+ int v_usecount; /* i ref count of users */
+ u_int v_iflag; /* i vnode flags (see below) */
+ u_int v_vflag; /* v vnode flags */
+ int v_writecount; /* v ref count of writers */
+ u_int v_hash;
+ enum vtype v_type; /* u vnode type */
};
#endif /* defined(_KERNEL) || defined(_KVM_VNODE) */
@@ -703,8 +705,7 @@ int vn_io_fault_uiomove(char *data, int xfersize, struct uio *uio);
int vfs_cache_lookup(struct vop_lookup_args *ap);
void vfs_timestamp(struct timespec *);
-void vfs_write_resume(struct mount *mp);
-void vfs_write_resume_flags(struct mount *mp, int flags);
+void vfs_write_resume(struct mount *mp, int flags);
int vfs_write_suspend(struct mount *mp);
int vop_stdbmap(struct vop_bmap_args *);
int vop_stdfsync(struct vop_fsync_args *);
@@ -813,6 +814,7 @@ int fifo_printinfo(struct vnode *);
typedef int vfs_hash_cmp_t(struct vnode *vp, void *arg);
int vfs_hash_get(const struct mount *mp, u_int hash, int flags, struct thread *td, struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg);
+u_int vfs_hash_index(struct vnode *vp);
int vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg);
void vfs_hash_rehash(struct vnode *vp, u_int hash);
void vfs_hash_remove(struct vnode *vp);
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index f8584d5..4571a1c 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -546,9 +546,9 @@ done:
*/
ip->i_size = length;
DIP_SET(ip, i_size, length);
- DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased);
-
- if (DIP(ip, i_blocks) < 0) /* sanity */
+ if (DIP(ip, i_blocks) >= blocksreleased)
+ DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased);
+ else /* sanity */
DIP_SET(ip, i_blocks, 0);
ip->i_flag |= IN_CHANGE;
#ifdef QUOTA
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 5f67ae5..0c653c2 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -687,7 +687,7 @@ out1:
/*
* Resume operation on filesystem.
*/
- vfs_write_resume_flags(vp->v_mount, VR_START_WRITE | VR_NO_SUSPCLR);
+ vfs_write_resume(vp->v_mount, VR_START_WRITE | VR_NO_SUSPCLR);
if (collectsnapstats && starttime.tv_sec > 0) {
nanotime(&endtime);
timespecsub(&endtime, &starttime);
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 4ee16ab..16fe134 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -2802,7 +2802,7 @@ journal_unsuspend(struct ufsmount *ump)
jblocks->jb_suspended = 0;
FREE_LOCK(&lk);
mp->mnt_susp_owner = curthread;
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
ACQUIRE_LOCK(&lk);
return (1);
}
diff --git a/sys/ufs/ffs/ffs_suspend.c b/sys/ufs/ffs/ffs_suspend.c
index 9d8e2c1..3198c1a 100644
--- a/sys/ufs/ffs/ffs_suspend.c
+++ b/sys/ufs/ffs/ffs_suspend.c
@@ -252,7 +252,7 @@ ffs_susp_dtor(void *data)
*/
mp->mnt_susp_owner = curthread;
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
vfs_unbusy(mp);
ump->um_writesuspended = 0;
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 83ae202..0204613 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -292,7 +292,7 @@ ffs_mount(struct mount *mp)
error = ffs_flushfiles(mp, flags, td);
}
if (error) {
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
return (error);
}
if (fs->fs_pendingblocks != 0 ||
@@ -309,7 +309,7 @@ ffs_mount(struct mount *mp)
if ((error = ffs_sbupdate(ump, MNT_WAIT, 0)) != 0) {
fs->fs_ronly = 0;
fs->fs_clean = 0;
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
return (error);
}
if (MOUNTEDSOFTDEP(mp))
@@ -330,7 +330,7 @@ ffs_mount(struct mount *mp)
* Allow the writers to note that filesystem
* is ro now.
*/
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
}
if ((mp->mnt_flag & MNT_RELOAD) &&
(error = ffs_reload(mp, td, 0)) != 0)
@@ -1294,10 +1294,8 @@ ffs_unmount(mp, mntflags)
goto fail;
}
}
- if (susp) {
- vfs_write_resume(mp);
- vn_start_write(NULL, &mp, V_WAIT);
- }
+ if (susp)
+ vfs_write_resume(mp, VR_START_WRITE);
DROP_GIANT();
g_topology_lock();
if (ump->um_fsckpid > 0) {
@@ -1329,10 +1327,8 @@ ffs_unmount(mp, mntflags)
return (error);
fail:
- if (susp) {
- vfs_write_resume(mp);
- vn_start_write(NULL, &mp, V_WAIT);
- }
+ if (susp)
+ vfs_write_resume(mp, VR_START_WRITE);
#ifdef UFS_EXTATTR
if (e_restart) {
ufs_extattr_uepm_init(&ump->um_extattr);
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 2a18b0d..30aaac0 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -160,6 +160,7 @@ cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops,
object1->pg_color = color;
object1->handle = handle;
object1->un_pager.devp.ops = ops;
+ object1->un_pager.devp.dev = handle;
TAILQ_INIT(&object1->un_pager.devp.devp_pglist);
mtx_lock(&dev_pager_mtx);
object = vm_pager_object_lookup(&dev_pager_object_list, handle);
@@ -237,7 +238,7 @@ dev_pager_dealloc(object)
vm_page_t m;
VM_OBJECT_UNLOCK(object);
- object->un_pager.devp.ops->cdev_pg_dtor(object->handle);
+ object->un_pager.devp.ops->cdev_pg_dtor(object->un_pager.devp.dev);
mtx_lock(&dev_pager_mtx);
TAILQ_REMOVE(&dev_pager_object_list, object, pager_object_list);
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 36a149e..2d5b555 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -1702,7 +1702,7 @@ uma_startup(void *bootmem, int boot_pages)
#ifdef UMA_DEBUG
printf("Calculated uma_max_ipers (for OFFPAGE) is %d\n", uma_max_ipers);
- printf("Calculated uma_max_ipers_slab (for OFFPAGE) is %d\n",
+ printf("Calculated uma_max_ipers_ref (for OFFPAGE) is %d\n",
uma_max_ipers_ref);
#endif
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 2274464..9883dcf 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -937,9 +937,10 @@ vnode_locked:
* Unlock everything, and return
*/
unlock_and_deallocate(&fs);
- if (hardfault)
+ if (hardfault) {
+ PCPU_INC(cnt.v_io_faults);
curthread->td_ru.ru_majflt++;
- else
+ } else
curthread->td_ru.ru_minflt++;
return (KERN_SUCCESS);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index f87e5b9..26de826 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -726,12 +726,6 @@ vmspace_resident_count(struct vmspace *vmspace)
return pmap_resident_count(vmspace_pmap(vmspace));
}
-long
-vmspace_wired_count(struct vmspace *vmspace)
-{
- return pmap_wired_count(vmspace_pmap(vmspace));
-}
-
/*
* vm_map_create:
*
@@ -3281,8 +3275,7 @@ vm_map_stack(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize,
}
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
- if (ptoa(vmspace_wired_count(curproc->p_vmspace)) +
- init_ssize > lmemlim) {
+ if (ptoa(pmap_wired_count(map->pmap)) + init_ssize > lmemlim) {
vm_map_unlock(map);
return (KERN_NO_SPACE);
}
@@ -3505,8 +3498,7 @@ Retry:
grow_amount = limit - ctob(vm->vm_ssize);
#endif
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
- if (ptoa(vmspace_wired_count(p->p_vmspace)) + grow_amount >
- lmemlim) {
+ if (ptoa(pmap_wired_count(map->pmap)) + grow_amount > lmemlim) {
vm_map_unlock_read(map);
rv = KERN_NO_SPACE;
goto out;
@@ -3514,7 +3506,7 @@ Retry:
#ifdef RACCT
PROC_LOCK(p);
if (racct_set(p, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(p->p_vmspace)) + grow_amount)) {
+ ptoa(pmap_wired_count(map->pmap)) + grow_amount)) {
PROC_UNLOCK(p);
vm_map_unlock_read(map);
rv = KERN_NO_SPACE;
@@ -3645,7 +3637,7 @@ out:
KASSERT(error == 0, ("decreasing RACCT_VMEM failed"));
if (!old_mlock) {
error = racct_set(p, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(p->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
KASSERT(error == 0, ("decreasing RACCT_MEMLOCK failed"));
}
error = racct_set(p, RACCT_STACK, ctob(vm->vm_ssize));
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index b3b1ad4..135b555 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -298,7 +298,6 @@ void vm_map_wait_busy(vm_map_t map);
_vm_map_lock_downgrade(map, LOCK_FILE, LOCK_LINE)
long vmspace_resident_count(struct vmspace *vmspace);
-long vmspace_wired_count(struct vmspace *vmspace);
#endif /* _KERNEL */
diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c
index b5bb0fa..05174e9 100644
--- a/sys/vm/vm_meter.c
+++ b/sys/vm/vm_meter.c
@@ -283,6 +283,7 @@ VM_STATS_SYS(v_syscall, "System calls");
VM_STATS_SYS(v_intr, "Device interrupts");
VM_STATS_SYS(v_soft, "Software interrupts");
VM_STATS_VM(v_vm_faults, "Address memory faults");
+VM_STATS_VM(v_io_faults, "Page faults requiring I/O");
VM_STATS_VM(v_cow_faults, "Copy-on-write faults");
VM_STATS_VM(v_cow_optim, "Optimized COW faults");
VM_STATS_VM(v_zfod, "Pages zero-filled on demand");
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 3ad7c37..4ae1f90 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -1044,6 +1044,7 @@ sys_mlock(td, uap)
struct proc *proc;
vm_offset_t addr, end, last, start;
vm_size_t npages, size;
+ vm_map_t map;
unsigned long nsize;
int error;
@@ -1061,8 +1062,9 @@ sys_mlock(td, uap)
if (npages > vm_page_max_wired)
return (ENOMEM);
proc = td->td_proc;
+ map = &proc->p_vmspace->vm_map;
PROC_LOCK(proc);
- nsize = ptoa(npages + vmspace_wired_count(proc->p_vmspace));
+ nsize = ptoa(npages + pmap_wired_count(map->pmap));
if (nsize > lim_cur(proc, RLIMIT_MEMLOCK)) {
PROC_UNLOCK(proc);
return (ENOMEM);
@@ -1077,13 +1079,13 @@ sys_mlock(td, uap)
if (error != 0)
return (ENOMEM);
#endif
- error = vm_map_wire(&proc->p_vmspace->vm_map, start, end,
+ error = vm_map_wire(map, start, end,
VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
#ifdef RACCT
if (error != KERN_SUCCESS) {
PROC_LOCK(proc);
racct_set(proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(proc->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
PROC_UNLOCK(proc);
}
#endif
@@ -1157,7 +1159,7 @@ sys_mlockall(td, uap)
if (error != KERN_SUCCESS) {
PROC_LOCK(td->td_proc);
racct_set(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(td->td_proc->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
PROC_UNLOCK(td->td_proc);
}
#endif
@@ -1491,16 +1493,15 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
return (ENOMEM);
}
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
- if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
- size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
+ if (ptoa(pmap_wired_count(map->pmap)) + size >
+ lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
racct_set_force(td->td_proc, RACCT_VMEM,
map->size);
PROC_UNLOCK(td->td_proc);
return (ENOMEM);
}
error = racct_set(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
- size);
+ ptoa(pmap_wired_count(map->pmap)) + size);
if (error != 0) {
racct_set_force(td->td_proc, RACCT_VMEM,
map->size);
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 6aee2bc..7beee59 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -138,6 +138,7 @@ struct vm_object {
struct {
TAILQ_HEAD(, vm_page) devp_pglist;
struct cdev_pager_ops *ops;
+ struct cdev *dev;
} devp;
/*
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index b5e9747..ac593a4 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -151,18 +151,21 @@ static struct mtx vm_daemon_mtx;
MTX_SYSINIT(vm_daemon, &vm_daemon_mtx, "vm daemon", MTX_DEF);
#endif
static int vm_max_launder = 32;
-static int vm_pageout_stats_max=0, vm_pageout_stats_interval = 0;
-static int vm_pageout_full_stats_interval = 0;
-static int vm_pageout_algorithm=0;
-static int defer_swap_pageouts=0;
-static int disable_swap_pageouts=0;
+static int vm_pageout_stats_max;
+static int vm_pageout_stats;
+static int vm_pageout_stats_interval;
+static int vm_pageout_full_stats;
+static int vm_pageout_full_stats_interval;
+static int vm_pageout_algorithm;
+static int defer_swap_pageouts;
+static int disable_swap_pageouts;
#if defined(NO_SWAPPING)
-static int vm_swap_enabled=0;
-static int vm_swap_idle_enabled=0;
+static int vm_swap_enabled = 0;
+static int vm_swap_idle_enabled = 0;
#else
-static int vm_swap_enabled=1;
-static int vm_swap_idle_enabled=0;
+static int vm_swap_enabled = 1;
+static int vm_swap_idle_enabled = 0;
#endif
SYSCTL_INT(_vm, VM_PAGEOUT_ALGORITHM, pageout_algorithm,
@@ -174,12 +177,18 @@ SYSCTL_INT(_vm, OID_AUTO, max_launder,
SYSCTL_INT(_vm, OID_AUTO, pageout_stats_max,
CTLFLAG_RW, &vm_pageout_stats_max, 0, "Max pageout stats scan length");
-SYSCTL_INT(_vm, OID_AUTO, pageout_full_stats_interval,
- CTLFLAG_RW, &vm_pageout_full_stats_interval, 0, "Interval for full stats scan");
+SYSCTL_INT(_vm, OID_AUTO, pageout_stats,
+ CTLFLAG_RD, &vm_pageout_stats, 0, "Number of partial stats scans");
SYSCTL_INT(_vm, OID_AUTO, pageout_stats_interval,
CTLFLAG_RW, &vm_pageout_stats_interval, 0, "Interval for partial stats scan");
+SYSCTL_INT(_vm, OID_AUTO, pageout_full_stats,
+ CTLFLAG_RD, &vm_pageout_full_stats, 0, "Number of full stats scans");
+
+SYSCTL_INT(_vm, OID_AUTO, pageout_full_stats_interval,
+ CTLFLAG_RW, &vm_pageout_full_stats_interval, 0, "Interval for full stats scan");
+
#if defined(NO_SWAPPING)
SYSCTL_INT(_vm, VM_SWAPPING_ENABLED, swap_enabled,
CTLFLAG_RD, &vm_swap_enabled, 0, "Enable entire process swapout");
@@ -1512,12 +1521,12 @@ vm_pageout_oom(int shortage)
* helps the situation where paging just starts to occur.
*/
static void
-vm_pageout_page_stats()
+vm_pageout_page_stats(void)
{
struct vm_pagequeue *pq;
vm_object_t object;
- vm_page_t m,next;
- int pcount,tpcount; /* Number of pages to check */
+ vm_page_t m, next;
+ int pcount, tpcount; /* Number of pages to check */
static int fullintervalcount = 0;
int page_shortage;
@@ -1531,11 +1540,13 @@ vm_pageout_page_stats()
pcount = cnt.v_active_count;
fullintervalcount += vm_pageout_stats_interval;
if (fullintervalcount < vm_pageout_full_stats_interval) {
+ vm_pageout_stats++;
tpcount = (int64_t)vm_pageout_stats_max * cnt.v_active_count /
cnt.v_page_count;
if (pcount > tpcount)
pcount = tpcount;
} else {
+ vm_pageout_full_stats++;
fullintervalcount = 0;
}
@@ -1624,7 +1635,7 @@ vm_pageout_page_stats()
* vm_pageout is the high level pageout daemon.
*/
static void
-vm_pageout()
+vm_pageout(void)
{
int error, pass;
@@ -1757,7 +1768,7 @@ vm_pageout()
* the free page queue lock is held until the msleep() is performed.
*/
void
-pagedaemon_wakeup()
+pagedaemon_wakeup(void)
{
if (!vm_pages_needed && curthread->td_proc != pageproc) {
@@ -1782,7 +1793,7 @@ vm_req_vmdaemon(int req)
}
static void
-vm_daemon()
+vm_daemon(void)
{
struct rlimit rsslim;
struct proc *p;
diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c
index d6da08b..edb6ecc 100644
--- a/sys/vm/vm_unix.c
+++ b/sys/vm/vm_unix.c
@@ -76,6 +76,7 @@ sys_obreak(td, uap)
struct obreak_args *uap;
{
struct vmspace *vm = td->td_proc->p_vmspace;
+ vm_map_t map = &vm->vm_map;
vm_offset_t new, old, base;
rlim_t datalim, lmemlim, vmemlim;
int prot, rv;
@@ -90,7 +91,7 @@ sys_obreak(td, uap)
do_map_wirefuture = FALSE;
new = round_page((vm_offset_t)uap->nsize);
- vm_map_lock(&vm->vm_map);
+ vm_map_lock(map);
base = round_page((vm_offset_t) vm->vm_daddr);
old = base + ctob(vm->vm_dsize);
@@ -103,7 +104,7 @@ sys_obreak(td, uap)
error = ENOMEM;
goto done;
}
- if (new > vm_map_max(&vm->vm_map)) {
+ if (new > vm_map_max(map)) {
error = ENOMEM;
goto done;
}
@@ -117,14 +118,14 @@ sys_obreak(td, uap)
goto done;
}
if (new > old) {
- if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
- if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
+ if (!old_mlock && map->flags & MAP_WIREFUTURE) {
+ if (ptoa(pmap_wired_count(map->pmap)) +
(new - old) > lmemlim) {
error = ENOMEM;
goto done;
}
}
- if (vm->vm_map.size + (new - old) > vmemlim) {
+ if (map->size + (new - old) > vmemlim) {
error = ENOMEM;
goto done;
}
@@ -137,22 +138,21 @@ sys_obreak(td, uap)
goto done;
}
error = racct_set(td->td_proc, RACCT_VMEM,
- vm->vm_map.size + (new - old));
+ map->size + (new - old));
if (error != 0) {
racct_set_force(td->td_proc, RACCT_DATA, old - base);
PROC_UNLOCK(td->td_proc);
error = ENOMEM;
goto done;
}
- if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
+ if (!old_mlock && map->flags & MAP_WIREFUTURE) {
error = racct_set(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
- (new - old));
+ ptoa(pmap_wired_count(map->pmap)) + (new - old));
if (error != 0) {
racct_set_force(td->td_proc, RACCT_DATA,
old - base);
racct_set_force(td->td_proc, RACCT_VMEM,
- vm->vm_map.size);
+ map->size);
PROC_UNLOCK(td->td_proc);
error = ENOMEM;
goto done;
@@ -167,17 +167,15 @@ sys_obreak(td, uap)
prot |= VM_PROT_EXECUTE;
#endif
#endif
- rv = vm_map_insert(&vm->vm_map, NULL, 0, old, new,
- prot, VM_PROT_ALL, 0);
+ rv = vm_map_insert(map, NULL, 0, old, new, prot, VM_PROT_ALL, 0);
if (rv != KERN_SUCCESS) {
#ifdef RACCT
PROC_LOCK(td->td_proc);
racct_set_force(td->td_proc, RACCT_DATA, old - base);
- racct_set_force(td->td_proc, RACCT_VMEM, vm->vm_map.size);
- if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
+ racct_set_force(td->td_proc, RACCT_VMEM, map->size);
+ if (!old_mlock && map->flags & MAP_WIREFUTURE) {
racct_set_force(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(
- td->td_proc->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
}
PROC_UNLOCK(td->td_proc);
#endif
@@ -194,13 +192,13 @@ sys_obreak(td, uap)
*
* XXX If the pages cannot be wired, no error is returned.
*/
- if ((vm->vm_map.flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) {
+ if ((map->flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) {
if (bootverbose)
printf("obreak: MAP_WIREFUTURE set\n");
do_map_wirefuture = TRUE;
}
} else if (new < old) {
- rv = vm_map_delete(&vm->vm_map, new, old);
+ rv = vm_map_delete(map, new, old);
if (rv != KERN_SUCCESS) {
error = ENOMEM;
goto done;
@@ -209,19 +207,19 @@ sys_obreak(td, uap)
#ifdef RACCT
PROC_LOCK(td->td_proc);
racct_set_force(td->td_proc, RACCT_DATA, new - base);
- racct_set_force(td->td_proc, RACCT_VMEM, vm->vm_map.size);
- if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
+ racct_set_force(td->td_proc, RACCT_VMEM, map->size);
+ if (!old_mlock && map->flags & MAP_WIREFUTURE) {
racct_set_force(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(td->td_proc->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
}
PROC_UNLOCK(td->td_proc);
#endif
}
done:
- vm_map_unlock(&vm->vm_map);
+ vm_map_unlock(map);
if (do_map_wirefuture)
- (void) vm_map_wire(&vm->vm_map, old, new,
+ (void) vm_map_wire(map, old, new,
VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
return (error);
diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c
index 31cc80b..e21635f 100644
--- a/sys/x86/x86/intr_machdep.c
+++ b/sys/x86/x86/intr_machdep.c
@@ -78,7 +78,7 @@ static int intrcnt_index;
static struct intsrc *interrupt_sources[NUM_IO_INTS];
static struct mtx intr_table_lock;
static struct mtx intrcnt_lock;
-static STAILQ_HEAD(, pic) pics;
+static TAILQ_HEAD(pics_head, pic) pics;
#ifdef SMP
static int assign_cpu;
@@ -102,7 +102,7 @@ intr_pic_registered(struct pic *pic)
{
struct pic *p;
- STAILQ_FOREACH(p, &pics, pics) {
+ TAILQ_FOREACH(p, &pics, pics) {
if (p == pic)
return (1);
}
@@ -124,7 +124,7 @@ intr_register_pic(struct pic *pic)
if (intr_pic_registered(pic))
error = EBUSY;
else {
- STAILQ_INSERT_TAIL(&pics, pic, pics);
+ TAILQ_INSERT_TAIL(&pics, pic, pics);
error = 0;
}
mtx_unlock(&intr_table_lock);
@@ -287,7 +287,7 @@ intr_resume(void)
atpic_reset();
#endif
mtx_lock(&intr_table_lock);
- STAILQ_FOREACH(pic, &pics, pics) {
+ TAILQ_FOREACH(pic, &pics, pics) {
if (pic->pic_resume != NULL)
pic->pic_resume(pic);
}
@@ -300,7 +300,7 @@ intr_suspend(void)
struct pic *pic;
mtx_lock(&intr_table_lock);
- STAILQ_FOREACH(pic, &pics, pics) {
+ TAILQ_FOREACH_REVERSE(pic, &pics, pics_head, pics) {
if (pic->pic_suspend != NULL)
pic->pic_suspend(pic);
}
@@ -381,7 +381,7 @@ intr_init(void *dummy __unused)
intrcnt_setname("???", 0);
intrcnt_index = 1;
- STAILQ_INIT(&pics);
+ TAILQ_INIT(&pics);
mtx_init(&intr_table_lock, "intr sources", NULL, MTX_DEF);
mtx_init(&intrcnt_lock, "intrcnt", NULL, MTX_SPIN);
}
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index e994172..c60db22 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -227,8 +227,8 @@ lapic_init(vm_paddr_t addr)
/* Map the local APIC and setup the spurious interrupt handler. */
KASSERT(trunc_page(addr) == addr,
("local APIC not aligned on a page boundary"));
- lapic = pmap_mapdev(addr, sizeof(lapic_t));
lapic_paddr = addr;
+ lapic = pmap_mapdev(addr, sizeof(lapic_t));
setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_APIC, SEL_KPL,
GSEL_APIC);
@@ -1360,11 +1360,19 @@ apic_setup_io(void *dummy __unused)
if (best_enum == NULL)
return;
+
+ /*
+ * Local APIC must be registered before other PICs and pseudo PICs
+ * for proper suspend/resume order.
+ */
+#ifndef XEN
+ intr_register_pic(&lapic_pic);
+#endif
+
retval = best_enum->apic_setup_io();
if (retval != 0)
printf("%s: Failed to setup I/O APICs: returned %d\n",
best_enum->apic_name, retval);
-
#ifdef XEN
return;
#endif
@@ -1373,7 +1381,6 @@ apic_setup_io(void *dummy __unused)
* properly program the LINT pins.
*/
lapic_setup(1);
- intr_register_pic(&lapic_pic);
if (bootverbose)
lapic_dump("BSP");
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 04231b8..4f67818 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -67,6 +67,11 @@ SYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RDTUN, &smp_tsc, 0,
TUNABLE_INT("kern.timecounter.smp_tsc", &smp_tsc);
#endif
+static int tsc_shift = 1;
+SYSCTL_INT(_kern_timecounter, OID_AUTO, tsc_shift, CTLFLAG_RDTUN,
+ &tsc_shift, 0, "Shift to pre-apply for the maximum TSC frequency");
+TUNABLE_INT("kern.timecounter.tsc_shift", &tsc_shift);
+
static int tsc_disabled;
SYSCTL_INT(_machdep, OID_AUTO, disable_tsc, CTLFLAG_RDTUN, &tsc_disabled, 0,
"Disable x86 Time Stamp Counter");
@@ -399,12 +404,12 @@ comp_smp_tsc(void *arg)
}
static int
-test_smp_tsc(void)
+test_tsc(void)
{
uint64_t *data, *tsc;
u_int i, size;
- if (!smp_tsc && !tsc_is_invariant)
+ if ((!smp_tsc && !tsc_is_invariant) || vm_guest)
return (-100);
size = (mp_maxid + 1) * 3;
data = malloc(sizeof(*data) * size * N, M_TEMP, M_WAITOK);
@@ -444,6 +449,19 @@ test_smp_tsc(void)
#undef N
+#else
+
+/*
+ * The function is not called, it is provided to avoid linking failure
+ * on uniprocessor kernel.
+ */
+static int
+test_tsc(void)
+{
+
+ return (0);
+}
+
#endif /* SMP */
static void
@@ -492,41 +510,37 @@ init_TSC_tc(void)
goto init;
}
-#ifdef SMP
/*
- * We can not use the TSC in SMP mode unless the TSCs on all CPUs are
- * synchronized. If the user is sure that the system has synchronized
- * TSCs, set kern.timecounter.smp_tsc tunable to a non-zero value.
- * We also limit the frequency even lower to avoid "temporal anomalies"
- * as much as possible. The TSC seems unreliable in virtualized SMP
+ * We can not use the TSC in SMP mode unless the TSCs on all CPUs
+ * are synchronized. If the user is sure that the system has
+ * synchronized TSCs, set kern.timecounter.smp_tsc tunable to a
+ * non-zero value. The TSC seems unreliable in virtualized SMP
* environments, so it is set to a negative quality in those cases.
*/
- if (smp_cpus > 1) {
- if (vm_guest != 0) {
- tsc_timecounter.tc_quality = -100;
- } else {
- tsc_timecounter.tc_quality = test_smp_tsc();
- max_freq >>= 8;
- }
- } else
-#endif
- if (tsc_is_invariant)
+ if (mp_ncpus > 1)
+ tsc_timecounter.tc_quality = test_tsc();
+ else if (tsc_is_invariant)
tsc_timecounter.tc_quality = 1000;
+ max_freq >>= tsc_shift;
init:
- for (shift = 0; shift < 31 && (tsc_freq >> shift) > max_freq; shift++)
+ for (shift = 0; shift <= 31 && (tsc_freq >> shift) > max_freq; shift++)
;
+ if ((cpu_feature & CPUID_SSE2) != 0 && mp_ncpus > 1) {
+ if (cpu_vendor_id == CPU_VENDOR_AMD) {
+ tsc_timecounter.tc_get_timecount = shift > 0 ?
+ tsc_get_timecount_low_mfence :
+ tsc_get_timecount_mfence;
+ } else {
+ tsc_timecounter.tc_get_timecount = shift > 0 ?
+ tsc_get_timecount_low_lfence :
+ tsc_get_timecount_lfence;
+ }
+ } else {
+ tsc_timecounter.tc_get_timecount = shift > 0 ?
+ tsc_get_timecount_low : tsc_get_timecount;
+ }
if (shift > 0) {
- if (cpu_feature & CPUID_SSE2) {
- if (cpu_vendor_id == CPU_VENDOR_AMD) {
- tsc_timecounter.tc_get_timecount =
- tsc_get_timecount_low_mfence;
- } else {
- tsc_timecounter.tc_get_timecount =
- tsc_get_timecount_low_lfence;
- }
- } else
- tsc_timecounter.tc_get_timecount = tsc_get_timecount_low;
tsc_timecounter.tc_name = "TSC-low";
if (bootverbose)
printf("TSC timecounter discards lower %d bit(s)\n",
diff --git a/tools/build/Makefile b/tools/build/Makefile
index 76493f7..b9b548e 100644
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -21,6 +21,22 @@ config.h: ${.CURDIR}/../../lib/libmagic/config.h
grep -v HAVE_GETLINE ${.ALLSRC} > ${.TARGET}
.endif
+_WITH_PWCACHEDB!= grep -c pwcache_groupdb /usr/include/pwd.h || true
+.if ${_WITH_PWCACHEDB} == 0
+.PATH: ${.CURDIR}/../../contrib/libc-pwcache
+CFLAGS+= -I${.CURDIR}/../../contrib/libc-pwcache \
+ -I${.CURDIR}/../../lib/libc/include
+SRCS+= pwcache.c
+.endif
+
+_WITH_STRSVIS!= grep -c strsvis /usr/include/vis.h || true
+.if ${_WITH_STRSVIS} == 0
+.PATH: ${.CURDIR}/../../contrib/libc-vis
+SRCS+= vis.c
+CFLAGS+= -I${.CURDIR}/../../contrib/libc-vis \
+ -I${.CURDIR}/../../lib/libc/include
+.endif
+
.if empty(SRCS)
SRCS= dummy.c
.endif
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 8377ab1..b464c98 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -3654,6 +3654,95 @@ OLD_FILES+=usr/share/man/man8/ntptime.8.gz
# to be filled in
#.endif
+.if ${MK_PC_SYSINSTALL} == no
+# backend-partmanager
+OLD_FILES+=usr/share/pc-sysinstall/backend-partmanager/create-part.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-partmanager/delete-part.sh
+# backend-query
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/detect-emulation.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/detect-laptop.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/detect-nics.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/disk-info.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/disk-list.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/disk-part.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/enable-net.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/get-packages.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/list-components.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/list-config.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/list-mirrors.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/list-packages.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/list-rsync-backups.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/list-tzones.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/query-langs.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/send-logs.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/setup-ssh-keys.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/set-mirror.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/sys-mem.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/test-live.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/test-netup.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/update-part-list.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/xkeyboard-layouts.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/xkeyboard-models.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend-query/xkeyboard-variants.sh
+# backend
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-bsdlabel.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-cleanup.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-disk.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-extractimage.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-ftp.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-installcomponents.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-installpackages.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-localize.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-mountdisk.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-mountoptical.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-networking.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-newfs.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-parse.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-packages.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-runcommands.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-unmount.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-upgrade.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions-users.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/functions.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/installimage.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/parseconfig.sh
+OLD_FILES+=usr/share/pc-sysinstall/backend/startautoinstall.sh
+# conf
+OLD_FILES+=usr/share/pc-sysinstall/conf/avail-langs
+OLD_FILES+=usr/share/pc-sysinstall/conf/exclude-from-upgrade
+OLD_FILES+=usr/share/pc-sysinstall/conf/license/bsd-en.txt
+OLD_FILES+=usr/share/pc-sysinstall/conf/license/intel-en.txt
+OLD_FILES+=usr/share/pc-sysinstall/conf/license/nvidia-en.txt
+OLD_FILES+=usr/share/pc-sysinstall/conf/pc-sysinstall.conf
+# doc
+OLD_FILES+=usr/share/pc-sysinstall/doc/help-disk-list
+OLD_FILES+=usr/share/pc-sysinstall/doc/help-disk-size
+OLD_FILES+=usr/share/pc-sysinstall/doc/help-index
+OLD_FILES+=usr/share/pc-sysinstall/doc/help-start-autoinstall
+# examples
+OLD_FILES+=usr/share/examples/pc-sysinstall/README
+OLD_FILES+=usr/share/examples/pc-sysinstall/pc-autoinstall.conf
+OLD_FILES+=usr/share/examples/pc-sysinstall/pcinstall.cfg.fbsd-netinstall
+OLD_FILES+=usr/share/examples/pc-sysinstall/pcinstall.cfg.geli
+OLD_FILES+=usr/share/examples/pc-sysinstall/pcinstall.cfg.gmirror
+OLD_FILES+=usr/share/examples/pc-sysinstall/pcinstall.cfg.netinstall
+OLD_FILES+=usr/share/examples/pc-sysinstall/pcinstall.cfg.restore
+OLD_FILES+=usr/share/examples/pc-sysinstall/pcinstall.cfg.rsync
+OLD_FILES+=usr/share/examples/pc-sysinstall/pcinstall.cfg.upgrade
+OLD_FILES+=usr/share/examples/pc-sysinstall/pcinstall.cfg.zfs
+# pc-sysinstall
+OLD_FILES+=usr/sbin/pc-sysinstall
+OLD_FILES+=usr/share/man/man8/pc-sysinstall.8.gz
+OLD_DIRS+=usr/share/pc-sysinstall/backend
+OLD_DIRS+=usr/share/pc-sysinstall/backend-partmanager
+OLD_DIRS+=usr/share/pc-sysinstall/backend-query
+OLD_DIRS+=usr/share/pc-sysinstall/conf/license
+OLD_DIRS+=usr/share/pc-sysinstall/conf
+OLD_DIRS+=usr/share/pc-sysinstall/doc
+OLD_DIRS+=usr/share/pc-sysinstall
+OLD_DIRS+=usr/share/examples/pc-sysinstall
+.endif
+
.if ${MK_PF} == no
OLD_FILES+=etc/periodic/security/520.pfdenied
OLD_FILES+=etc/pf.os
diff --git a/tools/build/options/WITHOUT_CLANG_FULL b/tools/build/options/WITHOUT_CLANG_FULL
new file mode 100644
index 0000000..418b7d6
--- /dev/null
+++ b/tools/build/options/WITHOUT_CLANG_FULL
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+Set to avoid building the ARCMigrate, Rewriter and StaticAnalyzer components of
+the Clang C/C++ compiler.
diff --git a/tools/build/options/WITHOUT_LIBCPLUSPLUS b/tools/build/options/WITHOUT_LIBCPLUSPLUS
new file mode 100644
index 0000000..2449e30
--- /dev/null
+++ b/tools/build/options/WITHOUT_LIBCPLUSPLUS
@@ -0,0 +1,2 @@
+.\" $FreeBSD$
+Set to avoid building libcxxrt and libc++.
diff --git a/tools/build/options/WITHOUT_PC_SYSINSTALL b/tools/build/options/WITHOUT_PC_SYSINSTALL
new file mode 100644
index 0000000..73b5ea3
--- /dev/null
+++ b/tools/build/options/WITHOUT_PC_SYSINSTALL
@@ -0,0 +1,4 @@
+.\" $FreeBSD$
+Set to not build
+.Xr pc-sysinstall 8
+and related programs.
diff --git a/tools/build/options/WITH_ARM_EABI b/tools/build/options/WITH_ARM_EABI
new file mode 100644
index 0000000..dba6e5f
--- /dev/null
+++ b/tools/build/options/WITH_ARM_EABI
@@ -0,0 +1,2 @@
+.\" $FreeBSD$
+Set the ARM ABI to EABI.
diff --git a/tools/build/options/WITH_BSD_PATCH b/tools/build/options/WITH_BSD_PATCH
new file mode 100644
index 0000000..8430d2a
--- /dev/null
+++ b/tools/build/options/WITH_BSD_PATCH
@@ -0,0 +1,2 @@
+.\" $FreeBSD$
+Install BSD-licensed patch as 'patch' instead of GNU patch.
diff --git a/tools/build/options/WITH_CLANG_FULL b/tools/build/options/WITH_CLANG_FULL
new file mode 100644
index 0000000..59b4dec
--- /dev/null
+++ b/tools/build/options/WITH_CLANG_FULL
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+Set to build the ARCMigrate, Rewriter and StaticAnalyzer components of the
+Clang C/C++ compiler.
diff --git a/tools/build/options/WITH_GPL_DTC b/tools/build/options/WITH_GPL_DTC
new file mode 100644
index 0000000..e5a1e95
--- /dev/null
+++ b/tools/build/options/WITH_GPL_DTC
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+Set to build the GPL'd version of the device tree compiler from elinux.org,
+instead of the BSD licensed one.
diff --git a/tools/build/options/WITH_NMTREE b/tools/build/options/WITH_NMTREE
new file mode 100644
index 0000000..cbaa873
--- /dev/null
+++ b/tools/build/options/WITH_NMTREE
@@ -0,0 +1,9 @@
+.\" $FreeBSD$
+Set to install
+.Xr nmtree 8
+as
+.Xr mtree 8 .
+By default
+.Xr fmtree 8
+is installed as
+.Xr mtree 8 .
diff --git a/tools/build/options/WITH_OPENSSH_NONE_CIPHER b/tools/build/options/WITH_OPENSSH_NONE_CIPHER
new file mode 100644
index 0000000..8d44cc0
--- /dev/null
+++ b/tools/build/options/WITH_OPENSSH_NONE_CIPHER
@@ -0,0 +1,9 @@
+.\" $FreeBSD$
+Set to include the "None" cipher support in OpenSSH and its libraries.
+Additional adjustments may need to be done to system configuration
+files, such as
+.Xr sshd_config 5 ,
+to enable this cipher.
+Please see
+.Pa /usr/src/crypto/openssh/README.hpn
+for full details.
diff --git a/tools/install.sh b/tools/install.sh
index 489424f..c28bd89 100644
--- a/tools/install.sh
+++ b/tools/install.sh
@@ -30,12 +30,22 @@
# parse install's options and ignore them completely.
dirmode=""
+linkmode=""
while [ $# -gt 0 ]; do
case $1 in
-d) dirmode="YES"; shift;;
- -[bCcMpSsv]) shift;;
- -[Bfgmo]) shift; shift;;
- -[Bfgmo]*) shift;;
+ -[bCcpSsv]) shift;;
+ -[BDfghMmNoTU]) shift; shift;;
+ -[BDfghMmNoTU]*) shift;;
+ -l)
+ shift
+ case $1 in
+ *[sm]*) linkmode="symbolic";; # XXX: 'm' should prefer hard
+ *h*) linkmode="hard";;
+ *) echo "invalid link mode"; exit 1;;
+ esac
+ shift
+ ;;
*) break;
esac
done
@@ -51,7 +61,13 @@ if [ -z "$dirmode" ] && [ "$#" -lt 2 ]; then
fi
# the remaining arguments are assumed to be files/dirs only.
-if [ -z "$dirmode" ]; then
+if [ -n "${linkmode}" ]; then
+ if [ "${linkmode}" = "symbolic" ]; then
+ ln -fsh "$@"
+ else
+ ln -f "$@"
+ fi
+elif [ -z "$dirmode" ]; then
exec install -p "$@"
else
exec install -d "$@"
diff --git a/tools/regression/bin/sh/execution/subshell1.0 b/tools/regression/bin/sh/execution/subshell1.0
new file mode 100644
index 0000000..347806e
--- /dev/null
+++ b/tools/regression/bin/sh/execution/subshell1.0
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+(eval "cd /
+v=$(printf %0100000d 1)
+echo \${#v}")
+echo end
diff --git a/tools/regression/bin/sh/execution/subshell1.0.stdout b/tools/regression/bin/sh/execution/subshell1.0.stdout
new file mode 100644
index 0000000..8c71af3
--- /dev/null
+++ b/tools/regression/bin/sh/execution/subshell1.0.stdout
@@ -0,0 +1,2 @@
+100000
+end
diff --git a/tools/regression/bin/sh/execution/subshell2.0 b/tools/regression/bin/sh/execution/subshell2.0
new file mode 100644
index 0000000..3216449
--- /dev/null
+++ b/tools/regression/bin/sh/execution/subshell2.0
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+f() {
+ x=2
+}
+(
+ x=1
+ f
+ [ "$x" = 2 ]
+)
diff --git a/tools/regression/bin/sh/execution/subshell3.0 b/tools/regression/bin/sh/execution/subshell3.0
new file mode 100644
index 0000000..9a87acb
--- /dev/null
+++ b/tools/regression/bin/sh/execution/subshell3.0
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+(false; exit) && exit 3
+exit 0
diff --git a/tools/regression/bin/sh/execution/subshell4.0 b/tools/regression/bin/sh/execution/subshell4.0
new file mode 100644
index 0000000..b39edb1
--- /dev/null
+++ b/tools/regression/bin/sh/execution/subshell4.0
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+(eval "set v=1"; false) && echo bad; :
diff --git a/tools/regression/bin/sh/expansion/cmdsubst14.0 b/tools/regression/bin/sh/expansion/cmdsubst14.0
new file mode 100644
index 0000000..bdbbb82
--- /dev/null
+++ b/tools/regression/bin/sh/expansion/cmdsubst14.0
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+! v=`false
+
+`
diff --git a/tools/regression/bin/sh/expansion/cmdsubst15.0 b/tools/regression/bin/sh/expansion/cmdsubst15.0
new file mode 100644
index 0000000..31d85d4
--- /dev/null
+++ b/tools/regression/bin/sh/expansion/cmdsubst15.0
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+! v=`false;
+
+`
diff --git a/tools/regression/bin/sh/expansion/cmdsubst16.0 b/tools/regression/bin/sh/expansion/cmdsubst16.0
new file mode 100644
index 0000000..71df562
--- /dev/null
+++ b/tools/regression/bin/sh/expansion/cmdsubst16.0
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+f() { return 3; }
+f
+[ `echo $?` = 3 ]
diff --git a/tools/regression/bin/sh/expansion/cmdsubst17.0 b/tools/regression/bin/sh/expansion/cmdsubst17.0
new file mode 100644
index 0000000..8c29e83
--- /dev/null
+++ b/tools/regression/bin/sh/expansion/cmdsubst17.0
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+f() { return 3; }
+f
+[ `echo $?; :` = 3 ]
diff --git a/tools/regression/bin/sh/parser/empty-braces1.0 b/tools/regression/bin/sh/parser/empty-braces1.0
new file mode 100644
index 0000000..5ab443c
--- /dev/null
+++ b/tools/regression/bin/sh/parser/empty-braces1.0
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+# Unfortunately, some scripts depend on the extension of allowing an empty
+# pair of braces.
+
+{ } &
+wait $!
diff --git a/tools/regression/lib/libc/stdio/test-fmemopen.c b/tools/regression/lib/libc/stdio/test-fmemopen.c
new file mode 100644
index 0000000..2788279
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/test-fmemopen.c
@@ -0,0 +1,252 @@
+/*-
+Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org>
+
+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 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 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.
+*/
+
+/*
+ * Test basic FILE * functions (fread, fwrite, fseek, fclose) against
+ * a FILE * retrieved using fmemopen()
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+void
+test_preexisting()
+{
+ /*
+ * Use a pre-existing buffer.
+ */
+
+ char buf[512];
+ char buf2[512];
+ char str[] = "Test writing some stuff";
+ char str2[] = "AAAAAAAAA";
+ char str3[] = "AAAA writing some stuff";
+ FILE *fp;
+ size_t nofw, nofr;
+ int rc;
+
+ /* Open a FILE * using fmemopen. */
+ fp = fmemopen(buf, sizeof(buf), "w");
+ assert(fp != NULL);
+
+ /* Write to the buffer. */
+ nofw = fwrite(str, 1, sizeof(str), fp);
+ assert(nofw == sizeof(str));
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ assert(rc == 0);
+
+ /* Re-open the FILE * to read back the data. */
+ fp = fmemopen(buf, sizeof(buf), "r");
+ assert(fp != NULL);
+
+ /* Read from the buffer. */
+ bzero(buf2, sizeof(buf2));
+ nofr = fread(buf2, 1, sizeof(buf2), fp);
+ assert(nofr == sizeof(buf2));
+
+ /*
+ * Since a write on a FILE * retrieved by fmemopen
+ * will add a '\0' (if there's space), we can check
+ * the strings for equality.
+ */
+ assert(strcmp(str, buf2) == 0);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ assert(rc == 0);
+
+ /* Now open a FILE * on the first 4 bytes of the string. */
+ fp = fmemopen(str, 4, "w");
+ assert(fp != NULL);
+
+ /*
+ * Try to write more bytes than we shoud, we'll get a short count (4).
+ */
+ nofw = fwrite(str2, 1, sizeof(str2), fp);
+ assert(nofw == 4);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+
+ /* Check that the string was not modified after the first 4 bytes. */
+ assert(strcmp(str, str3) == 0);
+}
+
+void
+test_autoalloc()
+{
+ /*
+ * Let fmemopen allocate the buffer.
+ */
+
+ char str[] = "A quick test";
+ FILE *fp;
+ long pos;
+ size_t nofw, nofr, i;
+ int rc;
+
+ /* Open a FILE * using fmemopen. */
+ fp = fmemopen(NULL, 512, "w+");
+ assert(fp != NULL);
+
+ /* fill the buffer */
+ for (i = 0; i < 512; i++) {
+ nofw = fwrite("a", 1, 1, fp);
+ assert(nofw == 1);
+ }
+
+ /* Get the current position into the stream. */
+ pos = ftell(fp);
+ assert(pos == 512);
+
+ /*
+ * Try to write past the end, we should get a short object count (0)
+ */
+ nofw = fwrite("a", 1, 1, fp);
+ assert(nofw == 0);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ assert(rc == 0);
+}
+
+void
+test_data_length()
+{
+ /*
+ * Here we test that a read operation doesn't go past the end of the
+ * data actually written, and that a SEEK_END seeks from the end of the
+ * data, not of the whole buffer.
+ */
+ FILE *fp;
+ char buf[512] = {'\0'};
+ char str[] = "Test data length. ";
+ char str2[] = "Do we have two sentences?";
+ char str3[sizeof(str) + sizeof(str2) -1];
+ long pos;
+ size_t nofw, nofr;
+ int rc;
+
+ /* Open a FILE * for updating our buffer. */
+ fp = fmemopen(buf, sizeof(buf), "w+");
+ assert(fp != NULL);
+
+ /* Write our string into the buffer. */
+ nofw = fwrite(str, 1, sizeof(str), fp);
+ assert(nofw == sizeof(str));
+
+ /*
+ * Now seek to the end and check that ftell
+ * gives us sizeof(str).
+ */
+ rc = fseek(fp, 0, SEEK_END);
+ assert(rc == 0);
+ pos = ftell(fp);
+ assert(pos == sizeof(str));
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ assert(rc == 0);
+
+ /* Reopen the buffer for appending. */
+ fp = fmemopen(buf, sizeof(buf), "a+");
+ assert(fp != NULL);
+
+ /* We should now be writing after the first string. */
+ nofw = fwrite(str2, 1, sizeof(str2), fp);
+ assert(nofw == sizeof(str2));
+
+ /* Rewind the FILE *. */
+ rc = fseek(fp, 0, SEEK_SET);
+ assert(rc == 0);
+
+ /* Make sure we're at the beginning. */
+ pos = ftell(fp);
+ assert(pos == 0);
+
+ /* Read the whole buffer. */
+ nofr = fread(str3, 1, sizeof(buf), fp);
+ assert(nofr == sizeof(str3));
+
+ /* Make sure the two strings are there. */
+ assert(strncmp(str3, str, sizeof(str) - 1) == 0);
+ assert(strncmp(str3 + sizeof(str) - 1, str2, sizeof(str2)) == 0);
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ assert(rc == 0);
+}
+
+void
+test_binary()
+{
+ /*
+ * Make sure that NULL bytes are never appended when opening a buffer
+ * in binary mode.
+ */
+
+ FILE *fp;
+ char buf[20];
+ char str[] = "Test";
+ size_t nofw;
+ int rc, i;
+
+ /* Pre-fill the buffer. */
+ memset(buf, 'A', sizeof(buf));
+
+ /* Open a FILE * in binary mode. */
+ fp = fmemopen(buf, sizeof(buf), "w+b");
+ assert(fp != NULL);
+
+ /* Write some data into it. */
+ nofw = fwrite(str, 1, strlen(str), fp);
+ assert(nofw == strlen(str));
+
+ /* Make sure that the buffer doesn't contain any NULL bytes. */
+ for (i = 0; i < sizeof(buf); i++)
+ assert(buf[i] != '\0');
+
+ /* Close the FILE *. */
+ rc = fclose(fp);
+ assert(rc == 0);
+}
+
+int
+main(void)
+{
+ test_autoalloc();
+ test_preexisting();
+ test_data_length();
+ test_binary();
+ return (0);
+}
diff --git a/tools/regression/lib/libc/stdio/test-fmemopen.t b/tools/regression/lib/libc/stdio/test-fmemopen.t
new file mode 100644
index 0000000..8bdfd03
--- /dev/null
+++ b/tools/regression/lib/libc/stdio/test-fmemopen.t
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $FreeBSD$
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/test/pthread_vfork/pthread_vfork_test.c b/tools/test/pthread_vfork/pthread_vfork_test.c
index e004727..925c862 100644
--- a/tools/test/pthread_vfork/pthread_vfork_test.c
+++ b/tools/test/pthread_vfork/pthread_vfork_test.c
@@ -29,6 +29,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/types.h>
+#include <sys/wait.h>
#include <err.h>
#include <pthread.h>
#include <signal.h>
@@ -39,10 +41,11 @@ __FBSDID("$FreeBSD$");
#define NUM_THREADS 100
-void *
-vfork_test(void *threadid)
+static void *
+vfork_test(void *threadid __unused)
{
- pid_t pid;
+ pid_t pid, wpid;
+ int status;
for (;;) {
pid = vfork();
@@ -50,10 +53,20 @@ vfork_test(void *threadid)
_exit(0);
else if (pid == -1)
err(1, "Failed to vfork");
+ else {
+ wpid = waitpid(pid, &status, 0);
+ if (wpid == -1)
+ err(1, "waitpid");
+ }
}
return (NULL);
}
+static void
+sighandler(int signo __unused)
+{
+}
+
/*
* This program invokes multiple threads and each thread calls
* vfork() system call.
@@ -63,19 +76,24 @@ main(void)
{
pthread_t threads[NUM_THREADS];
struct sigaction reapchildren;
+ sigset_t sigchld_mask;
int rc, t;
memset(&reapchildren, 0, sizeof(reapchildren));
- reapchildren.sa_handler = SIG_IGN;
-
- /* Automatically reap zombies. */
+ reapchildren.sa_handler = sighandler;
if (sigaction(SIGCHLD, &reapchildren, NULL) == -1)
err(1, "Could not sigaction(SIGCHLD)");
+ sigemptyset(&sigchld_mask);
+ sigaddset(&sigchld_mask, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &sigchld_mask, NULL) == -1)
+ err(1, "sigprocmask");
+
for (t = 0; t < NUM_THREADS; t++) {
- rc = pthread_create(&threads[t], NULL, vfork_test, (void *)t);
+ rc = pthread_create(&threads[t], NULL, vfork_test, &t);
if (rc)
errc(1, rc, "pthread_create");
}
+ pause();
return (0);
}
diff --git a/tools/tools/ath/athalq/ar5212_ds.c b/tools/tools/ath/athalq/ar5212_ds.c
index a1b12db..a6364a4 100644
--- a/tools/tools/ath/athalq/ar5212_ds.c
+++ b/tools/tools/ath/athalq/ar5212_ds.c
@@ -45,9 +45,11 @@ ar5212_decode_txstatus(struct if_ath_alq_payload *a)
/* XXX assumes txs is smaller than PAYLOAD_LEN! */
memcpy(&txs, &a->payload, sizeof(struct ar5212_desc));
- printf("[%u] [%llu] TXSTATUS\n",
+ printf("[%u] [%llu] TXSTATUS: TxDone=%d, TS=0x%08x\n\n",
(unsigned int) be32toh(a->hdr.tstamp),
- (unsigned long long) be64toh(a->hdr.threadid));
+ (unsigned long long) be64toh(a->hdr.threadid),
+ MF(txs.u.tx.status1, AR_Done),
+ MS(txs.u.tx.status0, AR_SendTimestamp));
/* ds_txstatus0 */
printf(" Frmok=%d, xretries=%d, fifounderrun=%d, filt=%d\n",
@@ -147,9 +149,11 @@ ar5212_decode_rxstatus(struct if_ath_alq_payload *a)
/* XXX assumes rxs is smaller than PAYLOAD_LEN! */
memcpy(&rxs, &a->payload, sizeof(struct ar5212_desc));
- printf("[%u] [%llu] RXSTATUS\n",
+ printf("[%u] [%llu] RXSTATUS: RxOK=%d TS=0x%08x\n",
(unsigned int) be32toh(a->hdr.tstamp),
- (unsigned long long) be64toh(a->hdr.threadid));
+ (unsigned long long) be64toh(a->hdr.threadid),
+ MF(rxs.ds_rxstatus1, AR_Done),
+ MS(rxs.ds_rxstatus1, AR_RcvTimestamp));
printf(" link=0x%08x, data=0x%08x, ctl0=0x%08x, ctl2=0x%08x\n",
rxs.ds_link,
diff --git a/tools/tools/ath/athalq/ar5416_ds.c b/tools/tools/ath/athalq/ar5416_ds.c
index 6d429ed..55fa1db 100644
--- a/tools/tools/ath/athalq/ar5416_ds.c
+++ b/tools/tools/ath/athalq/ar5416_ds.c
@@ -45,9 +45,11 @@ ar5416_decode_txstatus(struct if_ath_alq_payload *a)
/* XXX assumes txs is smaller than PAYLOAD_LEN! */
memcpy(&txs, &a->payload, sizeof(struct ar5416_desc));
- printf("[%u] [%llu] TXSTATUS\n",
+ printf("[%u] [%llu] TXSTATUS: TxDone=%d, TS=0x%08x\n",
(unsigned int) be32toh(a->hdr.tstamp),
- (unsigned long long) be64toh(a->hdr.threadid));
+ (unsigned long long) be64toh(a->hdr.threadid),
+ MF(txs.u.tx.status[9], AR_TxDone),
+ txs.u.tx.status[2]);
/* ds_txstatus0 */
printf(" RX RSSI 0 [%d %d %d]\n",
@@ -250,9 +252,11 @@ ar5416_decode_rxstatus(struct if_ath_alq_payload *a)
/* XXX assumes rxs is smaller than PAYLOAD_LEN! */
memcpy(&rxs, &a->payload, sizeof(struct ar5416_desc));
- printf("[%u] [%llu] RXSTATUS\n",
+ printf("[%u] [%llu] RXSTATUS: RxDone=%d, TS=0x%08x\n",
(unsigned int) be32toh(a->hdr.tstamp),
- (unsigned long long) be64toh(a->hdr.threadid));
+ (unsigned long long) be64toh(a->hdr.threadid),
+ MF(rxs.ds_rxstatus8, AR_RxDone),
+ rxs.ds_rxstatus2);
printf(" link=0x%08x, data=0x%08x, ctl0=0x%08x, ctl2=0x%08x\n",
rxs.ds_link,
diff --git a/tools/tools/ath/athspectral/athspectral.c b/tools/tools/ath/athspectral/athspectral.c
index 8e6962a..7bdfa2b 100644
--- a/tools/tools/ath/athspectral/athspectral.c
+++ b/tools/tools/ath/athspectral/athspectral.c
@@ -187,6 +187,29 @@ spectral_stop(struct spectralhandler *spectral)
err(1, spectral->atd.ad_name);
}
+static void
+spectral_enable_at_reset(struct spectralhandler *spectral, int val)
+{
+ int v = val;
+
+ spectral->atd.ad_id = SPECTRAL_CONTROL_ENABLE_AT_RESET
+ | ATH_DIAG_IN;
+
+ /*
+ * XXX don't need these, but need to eliminate the ATH_DIAG_DYN flag
+ * and debug
+ */
+ spectral->atd.ad_out_data = NULL;
+ spectral->atd.ad_out_size = 0;
+ spectral->atd.ad_in_data = (caddr_t) &v;
+ spectral->atd.ad_in_size = sizeof(v);
+
+ printf("%s: val=%d\n", __func__, v);
+
+ if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0)
+ err(1, spectral->atd.ad_name);
+}
+
static int
spectral_set_param(struct spectralhandler *spectral, const char *param,
const char *val)
@@ -258,6 +281,7 @@ usage(const char *progname)
printf("\tset <param> <value>:\t\tSet spectral parameter\n");
printf("\tstart: Start spectral scan\n");
printf("\tstop: Stop spectral scan\n");
+ printf("\tenable_at_reset <0|1>: enable reporting upon channel reset\n");
}
int
@@ -312,6 +336,12 @@ main(int argc, char *argv[])
spectral_start(&spectral);
} else if (strcasecmp(argv[1], "stop") == 0) {
spectral_stop(&spectral);
+ } else if (strcasecmp(argv[1], "enable_at_reset") == 0) {
+ if (argc < 3) {
+ usage(progname);
+ exit(127);
+ }
+ spectral_enable_at_reset(&spectral, atoi(argv[2]));
} else {
usage(progname);
exit(127);
diff --git a/tools/tools/cxgbetool/cxgbetool.c b/tools/tools/cxgbetool/cxgbetool.c
index 7d0faa6..39e7376 100644
--- a/tools/tools/cxgbetool/cxgbetool.c
+++ b/tools/tools/cxgbetool/cxgbetool.c
@@ -955,7 +955,7 @@ set_filter(uint32_t idx, int argc, const char *argv[])
t.fs.mask.vnic = mask;
t.fs.val.vnic_vld = 1;
t.fs.mask.vnic_vld = 1;
- } else if (!parse_val_mask("vlan", args, &val, &mask)) {
+ } else if (!parse_val_mask("ivlan", args, &val, &mask)) {
t.fs.val.vlan = val;
t.fs.mask.vlan = mask;
t.fs.val.vlan_vld = 1;
@@ -1047,10 +1047,17 @@ set_filter(uint32_t idx, int argc, const char *argv[])
t.fs.newvlan = VLAN_REWRITE;
} else if (argv[start_arg + 1][0] == '+') {
t.fs.newvlan = VLAN_INSERT;
+ } else if (isdigit(argv[start_arg + 1][0]) &&
+ !parse_val_mask("vlan", args, &val, &mask)) {
+ t.fs.val.vlan = val;
+ t.fs.mask.vlan = mask;
+ t.fs.val.vlan_vld = 1;
+ t.fs.mask.vlan_vld = 1;
} else {
warnx("unknown vlan parameter \"%s\"; must"
- " be one of \"none\", \"=<vlan>\" or"
- " \"+<vlan>\"", argv[start_arg + 1]);
+ " be one of \"none\", \"=<vlan>\", "
+ " \"+<vlan>\", or \"<vlan>\"",
+ argv[start_arg + 1]);
return (EINVAL);
}
if (t.fs.newvlan == VLAN_REWRITE ||
diff --git a/tools/tools/notescheck/notescheck.py b/tools/tools/notescheck/notescheck.py
index 5aae296..35915b9 100644
--- a/tools/tools/notescheck/notescheck.py
+++ b/tools/tools/notescheck/notescheck.py
@@ -7,14 +7,16 @@
#
# $FreeBSD$
+from __future__ import print_function
+
import glob
import os.path
import sys
def usage():
- print >>sys.stderr, "notescheck <path>"
- print >>sys.stderr
- print >>sys.stderr, "Where 'path' is a path to a kernel source tree."
+ print("notescheck <path>", file=sys.stderr)
+ print(file=sys.stderr)
+ print("Where 'path' is a path to a kernel source tree.", file=sys.stderr)
# These files are used to determine if a path is a valid kernel source tree.
requiredfiles = ['conf/files', 'conf/options', 'conf/NOTES']
@@ -62,9 +64,9 @@ class Option:
self.type = type
self.type_location = location
elif self.type != type:
- print "WARN: Attempt to change type of %s from %s to %s%s" % \
- (self.name, self.type, type, location)
- print " Previous type set%s" % (self.type_location)
+ print("WARN: Attempt to change type of %s from %s to %s%s" % \
+ (self.name, self.type, type, location))
+ print(" Previous type set%s" % (self.type_location))
def add_define(self, platform):
self.defines.add(platform)
@@ -93,8 +95,8 @@ class Option:
if global_platform in self.defines:
# If the device is defined globally ans is never tested, whine.
if len(self.tests) == 0:
- print 'WARN: %s is defined globally but never tested' % \
- (self.title())
+ print('WARN: %s is defined globally but never tested' % \
+ (self.title()))
return
# If the device is defined globally and is tested on
@@ -106,25 +108,25 @@ class Option:
# If a device is defined globally but is only tested on a
# single MD platform, then whine about this.
- print 'WARN: %s is defined globally but only tested in %s NOTES' % \
- (self.title(), format_set(self.tests))
+ print('WARN: %s is defined globally but only tested in %s NOTES' % \
+ (self.title(), format_set(self.tests)))
return
# If an option or device is never tested, whine.
if len(self.tests) == 0:
- print 'WARN: %s is defined in %s but never tested' % \
- (self.title(), format_set(self.defines))
+ print('WARN: %s is defined in %s but never tested' % \
+ (self.title(), format_set(self.defines)))
return
# The set of MD platforms where this option is defined, but not tested.
notest = self.defines - self.tests
if len(notest) != 0:
- print 'WARN: %s is not tested in %s NOTES' % \
- (self.title(), format_set(notest))
+ print('WARN: %s is not tested in %s NOTES' % \
+ (self.title(), format_set(notest)))
return
- print 'ERROR: bad state for %s: defined in %s, tested in %s' % \
- (self.title(), format_set(self.defines), format_set(self.tests))
+ print('ERROR: bad state for %s: defined in %s, tested in %s' % \
+ (self.title(), format_set(self.defines), format_set(self.tests)))
# This class maintains a dictionary of options keyed by name.
class Options:
@@ -143,7 +145,7 @@ class Options:
# Warn about inconsistencies
def warn(self):
- keys = self.options.keys()
+ keys = list(self.options.keys())
keys.sort()
for key in keys:
option = self.options[key]
@@ -158,11 +160,11 @@ def find_platforms(tree):
platforms = []
for file in glob.glob(tree + '*/conf/NOTES'):
if not file.startswith(tree):
- print >>sys.stderr, "Bad MD NOTES file %s" %(file)
+ print("Bad MD NOTES file %s" %(file), file=sys.stderr)
sys.exit(1)
platforms.append(file[len(tree):].split('/')[0])
if global_platform in platforms:
- print >>sys.stderr, "Found MD NOTES file for global platform"
+ print("Found MD NOTES file for global platform", file=sys.stderr)
sys.exit(1)
return platforms
@@ -224,7 +226,7 @@ def tokenize(line):
# will contain 'number of quotes' + 1 entries, so it should have
# an odd number of entries.
if len(groups) % 2 == 0:
- print >>sys.stderr, "Failed to tokenize: %s%s" (line, location)
+ print("Failed to tokenize: %s%s" (line, location), file=sys.stderr)
return []
# String split all the "odd" groups since they are not quoted strings.
@@ -256,7 +258,7 @@ def parse_files_line(line, platform):
# Remaining lines better be optional or mandatory lines.
if words[1] != 'optional' and words[1] != 'mandatory':
- print >>sys.stderr, "Invalid files line: %s%s" % (line, location)
+ print("Invalid files line: %s%s" % (line, location), file=sys.stderr)
# Drop the first two words and begin parsing keywords and devices.
skip = False
@@ -334,7 +336,7 @@ def main(argv=None):
tree = tree + '/'
for file in requiredfiles:
if not os.path.exists(tree + file):
- print>> sys.stderr, "Kernel source tree missing %s" % (file)
+ print("Kernel source tree missing %s" % (file), file=sys.stderr)
return 1
platforms = find_platforms(tree)
diff --git a/usr.bin/Makefile b/usr.bin/Makefile
index 17aafa8..2923f74 100644
--- a/usr.bin/Makefile
+++ b/usr.bin/Makefile
@@ -123,6 +123,7 @@ SUBDIR= alias \
pagesize \
passwd \
paste \
+ patch \
pathchk \
perror \
pr \
diff --git a/usr.bin/bmake/Makefile b/usr.bin/bmake/Makefile
index 7ae5e5f..6cac1ec 100644
--- a/usr.bin/bmake/Makefile
+++ b/usr.bin/bmake/Makefile
@@ -10,109 +10,109 @@ SRCTOP?= ${.CURDIR:H:H}
# look here first for config.h
CFLAGS+= -I${.CURDIR}
-# $NetBSD: Makefile,v 1.56 2012/05/30 21:54:23 sjg Exp $
-# @(#)Makefile 5.2 (Berkeley) 12/28/90
-
-# $Id: Makefile.in,v 1.178 2012/11/15 16:48:59 sjg Exp $
+# for after-import
+CLEANDIRS+= FreeBSD
+CLEANFILES+= bootstrap
-PROG?= ${.CURDIR:T}
-SRCS= arch.c buf.c compat.c cond.c dir.c for.c hash.c job.c main.c \
- make.c parse.c str.c suff.c targ.c trace.c var.c util.c
-SRCS+= strlist.c
-SRCS+= make_malloc.c
-SRCS+= lstAppend.c lstAtEnd.c lstAtFront.c lstClose.c lstConcat.c \
- lstDatum.c lstDeQueue.c lstDestroy.c lstDupl.c lstEnQueue.c \
- lstFind.c lstFindFrom.c lstFirst.c lstForEach.c lstForEachFrom.c \
- lstInit.c lstInsert.c lstIsAtEnd.c lstIsEmpty.c lstLast.c \
- lstMember.c lstNext.c lstOpen.c lstRemove.c lstReplace.c lstSucc.c
-SRCS += lstPrev.c
-
-# you can use this Makefile if you have an earlier version of bmake.
-prefix= /usr
-srcdir= ${SRCTOP}/contrib/bmake
-CC?= gcc
+# $Id: Makefile,v 1.5 2013/01/28 19:31:58 sjg Exp $
# Base version on src date
-MAKE_VERSION= 20121111
-DEFAULT_SYS_PATH = .../share/mk:/usr/share/mk
+MAKE_VERSION= 20130123
-CPPFLAGS+=
-CFLAGS+= ${CPPFLAGS}
-CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"
-CFLAGS+= -I. -I${srcdir} -DHAVE_CONFIG_H ${XDEFS} -DMAKE_NATIVE
-CFLAGS+= ${CFLAGS_${.TARGET:T}}
-CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}}
-COPTS.main.c+= "-DMAKE_VERSION=\"${MAKE_VERSION}\""
-LDFLAGS=
-LIBOBJS= ${LIBOBJDIR}stresep$U.o
-LDADD=
+PROG?= ${.CURDIR:T}
+
+SRCS= \
+ arch.c \
+ buf.c \
+ compat.c \
+ cond.c \
+ dir.c \
+ for.c \
+ hash.c \
+ job.c \
+ main.c \
+ make.c \
+ make_malloc.c \
+ meta.c \
+ parse.c \
+ str.c \
+ strlist.c \
+ suff.c \
+ targ.c \
+ trace.c \
+ util.c \
+ var.c
+
+# from lst.lib/
+SRCS+= \
+ lstAppend.c \
+ lstAtEnd.c \
+ lstAtFront.c \
+ lstClose.c \
+ lstConcat.c \
+ lstDatum.c \
+ lstDeQueue.c \
+ lstDestroy.c \
+ lstDupl.c \
+ lstEnQueue.c \
+ lstFind.c \
+ lstFindFrom.c \
+ lstFirst.c \
+ lstForEach.c \
+ lstForEachFrom.c \
+ lstInit.c \
+ lstInsert.c \
+ lstIsAtEnd.c \
+ lstIsEmpty.c \
+ lstLast.c \
+ lstMember.c \
+ lstNext.c \
+ lstOpen.c \
+ lstPrev.c \
+ lstRemove.c \
+ lstReplace.c \
+ lstSucc.c
+
+# this file gets generated by configure
+.sinclude "Makefile.config"
.if !empty(LIBOBJS)
SRCS+= ${LIBOBJS:T:.o=.c}
.endif
-USE_META = yes
-.if ${USE_META} != "no"
-SRCS+= meta.c
+# just in case
+prefix?= /usr
+srcdir?= ${.CURDIR}
+
+DEFAULT_SYS_PATH?= .../share/mk:${prefix}/share/mk
+
CPPFLAGS+= -DUSE_META
+CFLAGS+= ${CPPFLAGS}
+CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"
+CFLAGS+= -I. -I${srcdir} ${XDEFS} -DMAKE_NATIVE
+CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}}
+COPTS.main.c+= "-DMAKE_VERSION=\"${MAKE_VERSION}\""
+
+# meta mode can be useful even without filemon
FILEMON_H ?= /usr/include/dev/filemon/filemon.h
.if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h"
COPTS.meta.c += -DHAVE_FILEMON_H -I${FILEMON_H:H}
.endif
-.endif
.PATH: ${srcdir}
.PATH: ${srcdir}/lst.lib
-OS!= uname -s
-ARCH!= uname -p 2>/dev/null || uname -m
-
-# list of OS's which are derrived from BSD4.4
-isBSD44= NetBSD FreeBSD OpenBSD DragonFly
-
-.if ${OS} == "NetBSD"
-# Don't set these for anyone else since we don't know what the effect may be.
-# On FreeBSD WARNS=2 sets a bunch of -W flags that make does not handle.
-WFORMAT= 1
-WARNS=4
-.NOPATH: bmake.cat1
-.if make(install) && exists(${DESTDIR}/usr/share/doc)
-SUBDIR= PSD.doc
-.endif
-.endif
-
-.if defined(.PARSEDIR)
-# we cannot rely on anything but bmake to parse this correctly.
-.if empty(isBSD44:M${OS})
-MANTARGET=cat
-INSTALL?=${srcdir}/install-sh
-.if (${MACHINE} == "sun386")
-# even I don't have one of these anymore :-)
-CFLAGS+= -DPORTAR
-.elif (${MACHINE} != "sunos")
-SRCS+= sigcompat.c
-CFLAGS+= -DSIGNAL_FLAGS=SA_RESTART
-.endif
-.endif
-
.if make(obj) || make(clean)
SUBDIR+= unit-tests
.endif
-.endif
-
-# many systems use gcc these days
-CC_IS_GCC=yes
-.if ${CC_IS_GCC} == "yes"
-# problem with gcc3
-CFLAGS_var.o+= -Wno-cast-qual
-.endif
-CFLAGS_main.o+= "-DMACHINE=\"${MACHINE}\"" "-DMACHINE_ARCH=\"${MACHINE_ARCH}\""
-EXTRACT_MAN=no
+MAN= ${PROG}.1
+MAN1= ${MAN}
-MAN=${PROG}.1
.if (${PROG} != "make")
+CLEANFILES+= my.history
+.if make(${MAN}) || !exists(${srcdir}/${MAN})
my.history: ${MAKEFILE}
@(echo ".Nm"; \
echo "is derived from NetBSD"; \
@@ -120,19 +120,16 @@ my.history: ${MAKEFILE}
echo "It uses autoconf to facilitate portability to other platforms."; \
echo ".Pp") > $@
+.NOPATH: ${MAN}
${MAN}: make.1 my.history
- @echo making ${PROG}.1
+ @echo making $@
@sed -e 's/^.Nx/NetBSD/' -e '/^.Nm/s/make/${PROG}/' \
-e '/^.Sh HISTORY/rmy.history' \
-e '/^.Sh HISTORY/,$$s,^.Nm,make,' ${srcdir}/make.1 > $@
+all beforeinstall: ${MAN}
+_mfromdir=.
.endif
-
-.if !empty(isBSD44:M${OS})
-.if "${OS}" != "NetBSD"
-MAN1=${MAN}
-.endif
-MANTARGET?=man
.endif
MANTARGET?= cat
@@ -142,58 +139,26 @@ MANDEST?= ${MANDIR}/${MANTARGET}1
_mfromdir=${srcdir}
.endif
-.if exists(${srcdir}/../Makefile.inc)
-.include "${srcdir}/../Makefile.inc"
-.endif
-.sinclude <bsd.prog.mk>
-# sigh, FreeBSD at least includes bsd.subdir.mk via bsd.obj.mk
-# so the inclusion below, results in complaints about re-defined
-# targets. For NetBSD though we need to explicitly include it.
-.if defined(.PARSEDIR)
-.if defined(SUBDIR) && !target(${SUBDIR:[1]})
-.sinclude <bsd.subdir.mk>
-.endif
-.endif
+.include <bsd.prog.mk>
-CPPFLAGS+= -DMAKE_NATIVE
+CPPFLAGS+= -DMAKE_NATIVE -DHAVE_CONFIG_H
COPTS.var.c += -Wno-cast-qual
COPTS.job.c += -Wno-format-nonliteral
COPTS.parse.c += -Wno-format-nonliteral
COPTS.var.c += -Wno-format-nonliteral
# Force these
+SHAREDIR= ${prefix}/share
BINDIR= ${prefix}/bin
-MANDIR= ${prefix}/man
+MANDIR= ${SHAREDIR}/man
+
+.if !exists(.depend)
+${OBJS}: config.h
+.endif
-arch.o: config.h
# make sure that MAKE_VERSION gets updated.
main.o: ${SRCS} ${MAKEFILE}
-MK?=${prefix}/share/mk
-MKSRC?=mk
-INSTALL?=${srcdir}/install-sh
-
-beforeinstall:
- test -d ${DESTDIR}${BINDIR} || ${INSTALL} -m 775 -d ${DESTDIR}${BINDIR}
- test -d ${DESTDIR}${MANDEST} || ${INSTALL} -m 775 -d ${DESTDIR}${MANDEST}
-
-# latest version of *.mk includes an installer.
-# you should not need to set USE_OS
-install-mk:
-.if exists(${MKSRC}/install-mk)
- test -d ${DESTDIR}${MK} || ${INSTALL} -m 775 -d ${DESTDIR}${MK}
- ${MKSRC}/install-mk -v -m 644 ${DESTDIR}${MK} ${USE_OS}
-.else
- @echo need to unpack mk.tar.gz under ${srcdir} or set MKSRC; false
-.endif
-
-.ifdef TOOLDIR
-# this is a native netbsd build,
-# use libutil rather than the local emalloc etc.
-CPPFLAGS+= -DUSE_EMALLOC
-LDADD+=-lutil
-DPADD+=${LIBUTIL}
-.endif
# A simple unit-test driver to help catch regressions
accept test:
@@ -205,7 +170,6 @@ MANDIR= /usr/share/man/man
# make sure we get this
CFLAGS+= ${COPTS.${.IMPSRC:T}}
-CLEANFILES+= bootstrap
after-import: ${SRCTOP}/contrib/bmake/bsd.after-import.mk
cd ${.CURDIR} && ${.MAKE} -f ${SRCTOP}/contrib/bmake/bsd.after-import.mk
diff --git a/usr.bin/bmake/config.h b/usr.bin/bmake/config.h
index 64777b8..32026c7 100644
--- a/usr.bin/bmake/config.h
+++ b/usr.bin/bmake/config.h
@@ -1,6 +1,6 @@
+/* $FreeBSD$ */
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.in by autoheader. */
-/* $FreeBSD$ */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
@@ -230,7 +230,7 @@
#define PACKAGE_NAME "bmake"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "bmake 20120620"
+#define PACKAGE_STRING "bmake 20121212"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "bmake"
@@ -239,7 +239,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "20120620"
+#define PACKAGE_VERSION "20121212"
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
diff --git a/usr.bin/bmake/unit-tests/Makefile b/usr.bin/bmake/unit-tests/Makefile
index 89c7fe0..8b2f514 100644
--- a/usr.bin/bmake/unit-tests/Makefile
+++ b/usr.bin/bmake/unit-tests/Makefile
@@ -5,7 +5,7 @@
SRCTOP?= ${.CURDIR:H:H:H}
-# $Id: Makefile.in,v 1.39 2012/11/09 19:16:10 sjg Exp $
+# $Id: Makefile.in,v 1.40 2012/12/28 21:28:19 sjg Exp $
#
# $NetBSD: Makefile,v 1.35 2012/11/09 19:08:28 sjg Exp $
#
diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd
index 810f47b..f7f449b 100644
--- a/usr.bin/calendar/calendars/calendar.freebsd
+++ b/usr.bin/calendar/calendars/calendar.freebsd
@@ -165,6 +165,7 @@
05/22 Clive Tong-I Lin <clive@FreeBSD.org> born in Changhua, Taiwan, Republic of China, 1978
05/22 Michael Bushkov <bushman@FreeBSD.org> born in Rostov-on-Don, Russian Federation, 1985
05/22 Rui Paulo <rpaulo@FreeBSD.org> born in Evora, Portugal, 1986
+05/22 David Naylor <dbn@FreeBSD.org> born in Johannesburg, South Africa, 1988
05/23 Munechika Sumikawa <sumikawa@FreeBSD.org> born in Osaka, Osaka, Japan, 1972
05/24 Duncan McLennan Barclay <dmlb@FreeBSD.org> born in London, Middlesex, United Kingdom, 1970
05/24 Oliver Lehmann <oliver@FreeBSD.org> born in Karlsburg, Germany, 1981
diff --git a/usr.bin/clang/clang/Makefile b/usr.bin/clang/clang/Makefile
index 6fa9b80..18a768b 100644
--- a/usr.bin/clang/clang/Makefile
+++ b/usr.bin/clang/clang/Makefile
@@ -35,6 +35,19 @@ TGHDRS= CC1AsOptions \
DiagnosticLexKinds \
DiagnosticSemaKinds \
Options
+
+.if !defined(EARLY_BUILD) && defined(MK_CLANG_FULL) && ${MK_CLANG_FULL} != "no"
+_clangstaticanalyzer= \
+ clangstaticanalyzerfrontend \
+ clangstaticanalyzercheckers \
+ clangstaticanalyzercore
+_clangarcmigrate= \
+ clangarcmigrate
+_clangrewriter= \
+ clangrewritefrontend \
+ clangrewritecore
+.endif # !EARLY_BUILD && MK_CLANG_FULL
+
LIBDEPS=clangfrontendtool \
clangfrontend \
clangdriver \
@@ -42,13 +55,10 @@ LIBDEPS=clangfrontendtool \
clangcodegen \
clangparse \
clangsema \
- clangstaticanalyzerfrontend \
- clangstaticanalyzercheckers \
- clangstaticanalyzercore \
+ ${_clangstaticanalyzer} \
clanganalysis \
- clangarcmigrate \
- clangrewritefrontend \
- clangrewritecore \
+ ${_clangarcmigrate} \
+ ${_clangrewriter} \
clangedit \
clangast \
clanglex \
diff --git a/usr.bin/dtc/HACKING b/usr.bin/dtc/HACKING
new file mode 100644
index 0000000..4fb46da
--- /dev/null
+++ b/usr.bin/dtc/HACKING
@@ -0,0 +1,65 @@
+$FreeBSD$
+
+Notes for people hacking on dtc
+===============================
+
+This file contains some notes for people wishing to hack on dtc.
+
+Upstreaming
+-----------
+
+This code is developed in the FreeBSD svn repository:
+
+https://svn.freebsd.org/base/head/usr.bin/dtc
+
+If you got the source from anywhere else and wish to make changes, please
+ensure that you are working against the latest version, or you may end up
+fixing bugs that are already fixed upstream. Although the license makes no
+requirement that you share any improvements that you make, patches are very
+welcome.
+
+C++11
+-----
+
+This project currently aims to compile with g++ 4.2.1 and so doesn't make any
+use of C++11 features. It would be a good idea to relax this restriction once
+clang is the default compiler for ARM, MIPS and PowerPC.
+
+This code makes use of a lot of iterator loops, which would be cleaner using
+the new syntax in C++11. It also explicitly deletes a lot of objects held in
+collections in destructors that have these collections as their members. This
+could be simplified by using `shared_ptr`.
+
+The code does make use of `static_assert()`, but uses a macro in utility.hh to
+remove these if they are not supported. The FreeBSD standard headers also
+define a compatibility macro the implements static asserts in terms of an array
+with 1 element on success and -1 elements on failure.
+
+Adding New Checks
+-----------------
+
+Currently, the biggest weakness of this version of the tool is that it lacks
+most of the semantic checkers that can be implemented by simply reading the
+ePAPR spec. The `checker` class provides a simple superclass for implementing
+these quite easily. There are also helper methods on `device_tree` for finding
+specific nodes, for checks that require some understanding of the structure of
+the tree.
+
+We should probably add a parent pointer to the `node` class for easily walking
+up the tree.
+
+Adding Direct C Output
+----------------------
+
+The FreeBSD build system currently uses dtc to generate a blob and then
+converts this to C source code. A new `output_writer` subclass could easily
+generate the C directly.
+
+Parser Improvements
+-------------------
+
+There are a few FIXME lines in the parser for some corner cases that are not
+currently used by FreeBSD. These are mainly related to labels in the middle of
+values. These can be fixed by creating a new `property_value` with the
+specified label, starting at the location of the label. Don't forget to remove
+the associated comments from the BUGS section of the man page if you fix this.
diff --git a/usr.bin/dtc/Makefile b/usr.bin/dtc/Makefile
new file mode 100644
index 0000000..78973fc
--- /dev/null
+++ b/usr.bin/dtc/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+PROG_CXX=dtc
+SRCS= dtc.cc input_buffer.cc string.cc dtb.cc fdt.cc checking.cc
+MAN= dtc.1
+
+WARNS?= 3
+
+NO_SHARED?=NO
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/dtc/checking.cc b/usr.bin/dtc/checking.cc
new file mode 100644
index 0000000..5462a49
--- /dev/null
+++ b/usr.bin/dtc/checking.cc
@@ -0,0 +1,211 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 "checking.hh"
+#include <stdio.h>
+
+namespace dtc
+{
+namespace fdt
+{
+namespace checking
+{
+
+bool
+checker::visit_node(device_tree *tree, node *n)
+{
+ path.push_back(std::make_pair(n->name, n->unit_address));
+ // Check this node
+ if (!check_node(tree, n))
+ {
+ return false;
+ }
+ // Now check its properties
+ for (node::property_iterator i=n->property_begin(), e=n->property_end()
+ ; i!=e ; ++i)
+ {
+ if (!check_property(tree, n, *i))
+ {
+ return false;
+ }
+ }
+ // And then recursively check the children
+ for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ;
+ ++i)
+ {
+ if (!visit_node(tree, *i))
+ {
+ return false;
+ }
+ }
+ path.pop_back();
+ return true;
+}
+
+void
+checker::report_error(const char *errmsg)
+{
+ fprintf(stderr, "Error: %s, while checking node: ", errmsg);
+ for (device_tree::node_path::iterator p=path.begin()+1, pe=path.end() ;
+ p!=pe ; ++p)
+ {
+ putc('/', stderr);
+ p->first.dump();
+ if (!(p->second.empty()))
+ {
+ putc('@', stderr);
+ p->second.dump();
+ }
+ }
+ fprintf(stderr, " [-W%s]\n", checker_name);
+}
+
+bool
+property_checker::check_property(device_tree *tree, node *n, property *p)
+{
+ if (p->get_key() == key)
+ {
+ if (!check(tree, n, p))
+ {
+ report_error("property check failed");
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+property_size_checker::check(device_tree *tree, node *n, property *p)
+{
+ uint32_t psize = 0;
+ for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; ++i)
+ {
+ if (!i->is_binary())
+ {
+ return false;
+ }
+ psize += i->byte_data.size();
+ }
+ return psize == size;
+}
+
+template<property_value::value_type T>
+void
+check_manager::add_property_type_checker(const char *name, string prop)
+{
+ checkers.insert(std::make_pair(string(name),
+ new property_type_checker<T>(name, prop)));
+}
+
+void
+check_manager::add_property_size_checker(const char *name,
+ string prop,
+ uint32_t size)
+{
+ checkers.insert(std::make_pair(string(name),
+ new property_size_checker(name, prop, size)));
+}
+
+check_manager::~check_manager()
+{
+ while (checkers.begin() != checkers.end())
+ {
+ delete checkers.begin()->second;
+ checkers.erase(checkers.begin());
+ }
+ while (disabled_checkers.begin() != disabled_checkers.end())
+ {
+ delete disabled_checkers.begin()->second;
+ }
+}
+
+check_manager::check_manager()
+{
+ // NOTE: All checks listed here MUST have a corresponding line
+ // in the man page!
+ add_property_type_checker<property_value::STRING_LIST>(
+ "type-compatible", string("compatible"));
+ add_property_type_checker<property_value::STRING>(
+ "type-model", string("model"));
+ add_property_size_checker("type-phandle", string("phandle"), 4);
+}
+
+bool
+check_manager::run_checks(device_tree *tree, bool keep_going)
+{
+ bool success = true;
+ for (std::map<string, checker*>::iterator i=checkers.begin(),
+ e=checkers.end() ; i!=e ; ++i)
+ {
+ success &= i->second->check_tree(tree);
+ if (!(success || keep_going))
+ {
+ break;
+ }
+ }
+ return success;
+}
+
+bool
+check_manager::disable_checker(string name)
+{
+ std::map<string, checker*>::iterator checker = checkers.find(name);
+ if (checker != checkers.end())
+ {
+ disabled_checkers.insert(std::make_pair(name,
+ checker->second));
+ checkers.erase(checker);
+ return true;
+ }
+ return false;
+}
+
+bool
+check_manager::enable_checker(string name)
+{
+ std::map<string, checker*>::iterator checker =
+ disabled_checkers.find(name);
+ if (checker != disabled_checkers.end())
+ {
+ checkers.insert(std::make_pair(name, checker->second));
+ disabled_checkers.erase(checker);
+ return true;
+ }
+ return false;
+}
+
+} // namespace checking
+
+} // namespace fdt
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/checking.hh b/usr.bin/dtc/checking.hh
new file mode 100644
index 0000000..0de1d60
--- /dev/null
+++ b/usr.bin/dtc/checking.hh
@@ -0,0 +1,308 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 _CHECKING_HH_
+#define _CHECKING_HH_
+#include "string.hh"
+#include "fdt.hh"
+
+namespace dtc
+{
+namespace fdt
+{
+namespace checking
+{
+/**
+ * Base class for all checkers. This will visit the entire tree and perform
+ * semantic checks defined in subclasses. Note that device trees are generally
+ * small (a few dozen nodes at most) and so we optimise for flexibility and
+ * extensibility here, not for performance. Each checker will visit the entire
+ * tree.
+ */
+class checker
+{
+ /**
+ * The path to the current node being checked. This is used for
+ * printing error messages.
+ */
+ device_tree::node_path path;
+ /**
+ * The name of the checker. This is used for printing error messages
+ * and for enabling / disabling specific checkers from the command
+ * line.
+ */
+ const char *checker_name;
+ /**
+ * Visits each node, calling the checker functions on properties and
+ * nodes.
+ */
+ bool visit_node(device_tree *tree, node *n);
+ protected:
+ /**
+ * Prints the error message, along with the path to the node that
+ * caused the error and the name of the checker.
+ */
+ void report_error(const char *errmsg);
+ public:
+ /**
+ * Constructor. Takes the name of this checker, which is which is used
+ * when reporting errors.
+ */
+ checker(const char *name) : checker_name(name) {}
+ /**
+ * Virtual destructor in case any subclasses need to do cleanup.
+ */
+ virtual ~checker() {}
+ /**
+ * Method for checking that a node is valid. The root class version
+ * does nothing, subclasses should override this.
+ */
+ virtual bool check_node(device_tree *tree, node *n)
+ {
+ return true;
+ }
+ /**
+ * Method for checking that a property is valid. The root class
+ * version does nothing, subclasses should override this.
+ */
+ virtual bool check_property(device_tree *tree, node *n, property *p)
+ {
+ return true;
+ }
+ /**
+ * Runs the checker on the specified device tree.
+ */
+ bool check_tree(fdt::device_tree *tree)
+ {
+ return visit_node(tree, tree->get_root());
+ }
+};
+
+/**
+ * Abstract base class for simple property checks. This class defines a check
+ * method for subclasses, which is invoked only when it finds a property with
+ * the matching name. To define simple property checkers, just subclass this
+ * and override the check() method.
+ */
+class property_checker : public checker
+{
+ /**
+ * The name of the property that this checker is looking for.
+ */
+ string key;
+ public:
+ /**
+ * Implementation of the generic property-checking method that checks
+ * for a property with the name specified in the constructor
+ */
+ virtual bool check_property(device_tree *tree, node *n, property *p);
+ /**
+ * Constructor. Takes the name of the checker and the name of the
+ * property to check.
+ */
+ property_checker(const char* name, string property_name)
+ : checker(name), key(property_name) {}
+ /**
+ * The check method, which subclasses should implement.
+ */
+ virtual bool check(device_tree *tree, node *n, property *p) = 0;
+};
+
+/**
+ * Property type checker.
+ */
+template<property_value::value_type T>
+struct property_type_checker : public property_checker
+{
+ /**
+ * Constructor, takes the name of the checker and the name of the
+ * property to check as arguments.
+ */
+ property_type_checker(const char* name, string property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *tree, node *n, property *p) = 0;
+};
+
+/**
+ * Empty property checker. This checks that the property has no value.
+ */
+template<>
+struct property_type_checker <property_value::EMPTY> : public property_checker
+{
+ property_type_checker(const char* name, string property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *tree, node *n, property *p)
+ {
+ return p->begin() == p->end();
+ }
+};
+
+/**
+ * String property checker. This checks that the property has exactly one
+ * value, which is a string.
+ */
+template<>
+struct property_type_checker <property_value::STRING> : public property_checker
+{
+ property_type_checker(const char* name, string property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *tree, node *n, property *p)
+ {
+ return (p->begin() + 1 == p->end()) && p->begin()->is_string();
+ }
+};
+/**
+ * String list property checker. This checks that the property has at least
+ * one value, all of which are strings.
+ */
+template<>
+struct property_type_checker <property_value::STRING_LIST> :
+ public property_checker
+{
+ property_type_checker(const char* name, string property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *tree, node *n, property *p)
+ {
+ for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ;
+ ++i)
+ {
+ if (!(i->is_string() || i->is_string_list()))
+ {
+ return false;
+ }
+ }
+ return p->begin() != p->end();
+ }
+};
+
+/**
+ * Phandle property checker. This checks that the property has exactly one
+ * value, which is a valid phandle.
+ */
+template<>
+struct property_type_checker <property_value::PHANDLE> : public property_checker
+{
+ property_type_checker(const char* name, string property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *tree, node *n, property *p)
+ {
+ return (p->begin() + 1 == p->end()) &&
+ (tree->referenced_node(*p->begin()) != 0);
+ }
+};
+
+/**
+ * Check that a property has the correct size.
+ */
+struct property_size_checker : public property_checker
+{
+ /**
+ * The expected size of the property.
+ */
+ uint32_t size;
+ public:
+ /**
+ * Constructor, takes the name of the checker, the name of the property
+ * to check, and its expected size as arguments.
+ */
+ property_size_checker(const char* name, string property_name, uint32_t bytes)
+ : property_checker(name, property_name), size(bytes) {}
+ /**
+ * Check, validates that the property has the correct size.
+ */
+ virtual bool check(device_tree *tree, node *n, property *p);
+};
+
+
+/**
+ * The check manager is the interface to running the checks. This allows
+ * default checks to be enabled, non-default checks to be enabled, and so on.
+ */
+class check_manager
+{
+ /**
+ * The enabled checkers, indexed by their names. The name is used when
+ * disabling checkers from the command line. When this manager runs,
+ * it will only run the checkers from this map.
+ */
+ std::map<string, checker*> checkers;
+ /**
+ * The disabled checkers. Moving checkers to this list disables them,
+ * but allows them to be easily moved back.
+ */
+ std::map<string, checker*> disabled_checkers;
+ /**
+ * Helper function for adding a property value checker.
+ */
+ template<property_value::value_type T>
+ void add_property_type_checker(const char *name, string prop);
+ /**
+ * Helper function for adding a simple type checker.
+ */
+ void add_property_type_checker(const char *name, string prop);
+ /**
+ * Helper function for adding a property value checker.
+ */
+ void add_property_size_checker(const char *name,
+ string prop,
+ uint32_t size);
+ public:
+ /**
+ * Delete all of the checkers that are part of this checker manager.
+ */
+ ~check_manager();
+ /**
+ * Default constructor, creates check manager containing all of the
+ * default checks.
+ */
+ check_manager();
+ /**
+ * Run all of the checks on the specified tree.
+ */
+ bool run_checks(device_tree *tree, bool keep_going);
+ /**
+ * Disables the named checker.
+ */
+ bool disable_checker(string name);
+ /**
+ * Enables the named checker.
+ */
+ bool enable_checker(string name);
+};
+
+} // namespace checking
+
+} // namespace fdt
+
+} // namespace dtc
+
+#endif // !_CHECKING_HH_
diff --git a/usr.bin/dtc/dtb.cc b/usr.bin/dtc/dtb.cc
new file mode 100644
index 0000000..986ef6f
--- /dev/null
+++ b/usr.bin/dtc/dtb.cc
@@ -0,0 +1,312 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 "dtb.hh"
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+namespace dtc
+{
+namespace dtb
+{
+
+void output_writer::write_data(byte_buffer b)
+{
+ for (byte_buffer::iterator i=b.begin(), e=b.end(); i!=e ; i++)
+ {
+ write_data(*i);
+ }
+}
+
+void
+binary_writer::write_string(string name)
+{
+ name.push_to_buffer(buffer);
+ // Trailing nul
+ buffer.push_back(0);
+}
+
+void
+binary_writer::write_data(uint8_t v)
+{
+ buffer.push_back(v);
+}
+
+void
+binary_writer::write_data(uint32_t v)
+{
+ while (buffer.size() % 4 != 0)
+ {
+ buffer.push_back(0);
+ }
+ push_big_endian(buffer, v);
+}
+
+void
+binary_writer::write_data(uint64_t v)
+{
+ while (buffer.size() % 8 != 0)
+ {
+ buffer.push_back(0);
+ }
+ push_big_endian(buffer, v);
+}
+
+void
+binary_writer::write_to_file(int fd)
+{
+ // FIXME: Check return
+ write(fd, buffer.data(), buffer.size());
+}
+
+uint32_t
+binary_writer::size()
+{
+ return buffer.size();
+}
+
+void
+asm_writer::write_string(const char *c)
+{
+ while (*c)
+ {
+ buffer.push_back((uint8_t)*(c++));
+ }
+}
+
+void
+asm_writer::write_line(const char *c)
+{
+ if (byte_count != 0)
+ {
+ byte_count = 0;
+ buffer.push_back('\n');
+ }
+ write_string(c);
+}
+
+void
+asm_writer::write_byte(uint8_t b)
+{
+ char out[3] = {0};
+ if (byte_count++ == 0)
+ {
+ buffer.push_back('\t');
+ }
+ write_string(".byte 0x");
+ snprintf(out, 3, "%.2hhx", b);
+ buffer.push_back(out[0]);
+ buffer.push_back(out[1]);
+ if (byte_count == 4)
+ {
+ buffer.push_back('\n');
+ byte_count = 0;
+ }
+ else
+ {
+ buffer.push_back(';');
+ buffer.push_back(' ');
+ }
+}
+
+void
+asm_writer::write_label(string name)
+{
+ write_line("\t.globl ");
+ name.push_to_buffer(buffer);
+ buffer.push_back('\n');
+ name.push_to_buffer(buffer);
+ buffer.push_back(':');
+ buffer.push_back('\n');
+ buffer.push_back('_');
+ name.push_to_buffer(buffer);
+ buffer.push_back(':');
+ buffer.push_back('\n');
+
+}
+
+void
+asm_writer::write_comment(string name)
+{
+ write_line("\t/* ");
+ name.push_to_buffer(buffer);
+ write_string(" */\n");
+}
+
+void
+asm_writer::write_string(string name)
+{
+ write_line("\t.string \"");
+ name.push_to_buffer(buffer);
+ write_line("\"\n");
+ bytes_written += name.size() + 1;
+}
+
+void
+asm_writer::write_data(uint8_t v)
+{
+ write_byte(v);
+ bytes_written++;
+}
+
+void
+asm_writer::write_data(uint32_t v)
+{
+ if (bytes_written % 4 != 0)
+ {
+ write_line("\t.balign 4\n");
+ bytes_written += (4 - (bytes_written % 4));
+ }
+ write_byte((v >> 24) & 0xff);
+ write_byte((v >> 16) & 0xff);
+ write_byte((v >> 8) & 0xff);
+ write_byte((v >> 0) & 0xff);
+ bytes_written += 4;
+}
+
+void
+asm_writer::write_data(uint64_t v)
+{
+ if (bytes_written % 8 != 0)
+ {
+ write_line("\t.balign 8\n");
+ bytes_written += (8 - (bytes_written % 8));
+ }
+ write_byte((v >> 56) & 0xff);
+ write_byte((v >> 48) & 0xff);
+ write_byte((v >> 40) & 0xff);
+ write_byte((v >> 32) & 0xff);
+ write_byte((v >> 24) & 0xff);
+ write_byte((v >> 16) & 0xff);
+ write_byte((v >> 8) & 0xff);
+ write_byte((v >> 0) & 0xff);
+ bytes_written += 8;
+}
+
+void
+asm_writer::write_to_file(int fd)
+{
+ // FIXME: Check return
+ write(fd, buffer.data(), buffer.size());
+}
+
+uint32_t
+asm_writer::size()
+{
+ return bytes_written;
+}
+
+void
+header::write(output_writer &out)
+{
+ out.write_label(string("dt_blob_start"));
+ out.write_label(string("dt_header"));
+ out.write_comment("magic");
+ out.write_data(magic);
+ out.write_comment("totalsize");
+ out.write_data(totalsize);
+ out.write_comment("off_dt_struct");
+ out.write_data(off_dt_struct);
+ out.write_comment("off_dt_strings");
+ out.write_data(off_dt_strings);
+ out.write_comment("off_mem_rsvmap");
+ out.write_data(off_mem_rsvmap);
+ out.write_comment("version");
+ out.write_data(version);
+ out.write_comment("last_comp_version");
+ out.write_data(last_comp_version);
+ out.write_comment("boot_cpuid_phys");
+ out.write_data(boot_cpuid_phys);
+ out.write_comment("size_dt_strings");
+ out.write_data(size_dt_strings);
+ out.write_comment("size_dt_struct");
+ out.write_data(size_dt_struct);
+}
+
+bool
+header::read_dtb(input_buffer &input)
+{
+ if (!(input.consume_binary(magic) && magic == 0xd00dfeed))
+ {
+ fprintf(stderr, "Missing magic token in header. Got %" PRIx32
+ " expected 0xd00dfeed\n", magic);
+ return false;
+ }
+ return input.consume_binary(totalsize) &&
+ input.consume_binary(off_dt_struct) &&
+ input.consume_binary(off_dt_strings) &&
+ input.consume_binary(off_mem_rsvmap) &&
+ input.consume_binary(version) &&
+ input.consume_binary(last_comp_version) &&
+ input.consume_binary(boot_cpuid_phys) &&
+ input.consume_binary(size_dt_strings) &&
+ input.consume_binary(size_dt_struct);
+}
+uint32_t
+string_table::add_string(string str)
+{
+ std::map<string, uint32_t>::iterator old = string_offsets.find(str);
+ if (old == string_offsets.end())
+ {
+ uint32_t start = size;
+ // Don't forget the trailing nul
+ size += str.size() + 1;
+ string_offsets.insert(std::make_pair(str, start));
+ strings.push_back(str);
+ return start;
+ }
+ else
+ {
+ return old->second;
+ }
+}
+
+void
+string_table::write(dtb::output_writer &writer)
+{
+ writer.write_comment(string("Strings table."));
+ writer.write_label(string("dt_strings_start"));
+ for (std::vector<string>::iterator i=strings.begin(), e=strings.end() ;
+ i!=e ; ++i)
+ {
+ writer.write_string(*i);
+ }
+ writer.write_label(string("dt_strings_end"));
+}
+
+} // namespace dtb
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/dtb.hh b/usr.bin/dtc/dtb.hh
new file mode 100644
index 0000000..2c5f39e
--- /dev/null
+++ b/usr.bin/dtc/dtb.hh
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 _DTB_HH_
+#define _DTB_HH_
+#include <map>
+#include "string.hh"
+
+#include <assert.h>
+
+namespace dtc
+{
+/**
+ * The dtb namespace contains code related to the generation of device tree
+ * blobs, the binary representation of flattened device trees. The abstract
+ * tree representation calls into this code to generate the output.
+ */
+namespace dtb
+{
+/** The token types in the DTB, as defined by §7.4.1 of the ePAPR
+ * specification. All of these values are written in big-endian format in the
+ * output.
+ */
+enum token_type
+{
+ /**
+ * Marker indicating the start of a node in the tree. This is followed
+ * by the nul-terminated name. If a unit address is specified, then
+ * the name also contains the address, with an @ symbol between the end
+ * of the name and the start of the address.
+ *
+ * The name is then padded such that the next token begins on a 4-byte
+ * boundary. The node may contain properties, other nodes, both, or be
+ * empty.
+ */
+ FDT_BEGIN_NODE = 0x00000001,
+ /**
+ * Marker indicating the end of a node.
+ */
+ FDT_END_NODE = 0x00000002,
+ /**
+ * The start of a property. This is followed by two 32-bit big-endian
+ * values. The first indicates the length of the property value, the
+ * second its index in the strings table. It is then followed by the
+ * property value, if the value is of non-zero length.
+ */
+ FDT_PROP = 0x00000003,
+ /**
+ * Ignored token. May be used for padding inside DTB nodes.
+ */
+ FDT_NOP = 0x00000004,
+ /**
+ * Marker indicating the end of the tree.
+ */
+ FDT_END = 0x00000009
+};
+
+/**
+ * Returns the token as a string. This is used for debugging and for printing
+ * human-friendly error messages about malformed DTB input.
+ */
+inline const char *token_type_name(token_type t)
+{
+ switch(t)
+ {
+ case FDT_BEGIN_NODE:
+ return "FDT_BEGIN_NODE";
+ case FDT_END_NODE:
+ return "FDT_END_NODE";
+ case FDT_PROP:
+ return "FDT_PROP";
+ case FDT_NOP:
+ return "FDT_NOP";
+ case FDT_END:
+ return "FDT_END";
+ }
+ assert(0);
+}
+
+/**
+ * Abstract class for writing a section of the output. We create one
+ * of these for each section that needs to be written. It is intended to build
+ * a temporary buffer of the output in memory and then write it to a file
+ * stream. The size can be returned after all of the data has been written
+ * into the internal buffer, so the sizes of the three tables can be calculated
+ * before storing them in the buffer.
+ */
+struct output_writer
+{
+ /**
+ * Writes a label into the output stream. This is only applicable for
+ * assembly output, where the labels become symbols that can be
+ * resolved at link time.
+ */
+ virtual void write_label(string name) = 0;
+ /**
+ * Writes a comment into the output stream. Useful only when debugging
+ * the output.
+ */
+ virtual void write_comment(string name) = 0;
+ /**
+ * Writes a string. A nul terminator is implicitly added.
+ */
+ virtual void write_string(string name) = 0;
+ /**
+ * Writes a single 8-bit value.
+ */
+ virtual void write_data(uint8_t) = 0;
+ /**
+ * Writes a single 32-bit value. The value is written in big-endian
+ * format, but should be passed in the host's native endian.
+ */
+ virtual void write_data(uint32_t) = 0;
+ /**
+ * Writes a single 64-bit value. The value is written in big-endian
+ * format, but should be passed in the host's native endian.
+ */
+ virtual void write_data(uint64_t) = 0;
+ /**
+ * Writes the collected output to the specified file descriptor.
+ */
+ virtual void write_to_file(int fd) = 0;
+ /**
+ * Returns the number of bytes.
+ */
+ virtual uint32_t size() = 0;
+ /**
+ * Helper for writing tokens to the output stream. This writes a
+ * comment above the token describing its value, for easier debugging
+ * of the output.
+ */
+ inline void write_token(token_type t)
+ {
+ write_comment(token_type_name(t));
+ write_data((uint32_t)t);
+ }
+ /**
+ * Helper function that writes a byte buffer to the output, one byte at
+ * a time.
+ */
+ void write_data(byte_buffer b);
+};
+
+/**
+ * Binary file writer. This class is responsible for writing the DTB output
+ * directly in blob format.
+ */
+class binary_writer : public output_writer
+{
+ /**
+ * The internal buffer used to store the blob while it is being
+ * constructed.
+ */
+ byte_buffer buffer;
+ public:
+ /**
+ * The binary format does not support labels, so this method
+ * does nothing.
+ */
+ virtual void write_label(string name) {}
+ /**
+ * Comments are ignored by the binary writer.
+ */
+ virtual void write_comment(string name) {}
+ virtual void write_string(string name);
+ virtual void write_data(uint8_t v);
+ virtual void write_data(uint32_t v);
+ virtual void write_data(uint64_t v);
+ virtual void write_to_file(int fd);
+ virtual uint32_t size();
+};
+/**
+ * Assembly writer. This class is responsible for writing the output in an
+ * assembly format that is suitable for linking into a kernel, loader, and so
+ * on.
+ */
+class asm_writer : public output_writer
+{
+ /**
+ * The internal buffer for temporary values. Note that this actually
+ * contains ASCII text, but it is a byte buffer so that we can just
+ * copy strings across as-is.
+ */
+ byte_buffer buffer;
+ /**
+ * The number of bytes written to the current line. This is used to
+ * allow line wrapping, where we aim to write four .byte directives to
+ * make the alignment clearer.
+ */
+ int byte_count;
+ /**
+ * The current number of bytes written. This is the number in binary
+ * format, not the number of bytes in the buffer.
+ */
+ uint32_t bytes_written;
+
+ /**
+ * Writes a C string directly to the ouput as-is. This is mainly used
+ * for writing directives.
+ */
+ void write_string(const char *c);
+ /**
+ * Writes the string, starting on a new line.
+ */
+ void write_line(const char *c);
+ /**
+ * Writes a byte in binary format. This will emit a single .byte
+ * directive, with up to four per line.
+ */
+ void write_byte(uint8_t b);
+ public:
+ asm_writer() : byte_count(0), bytes_written(0) {}
+ virtual void write_label(string name);
+ virtual void write_comment(string name);
+ virtual void write_string(string name);
+ virtual void write_data(uint8_t v);
+ virtual void write_data(uint32_t v);
+ virtual void write_data(uint64_t v);
+ virtual void write_to_file(int fd);
+ virtual uint32_t size();
+};
+
+/**
+ * Class encapsulating the device tree blob header. This class stores all of
+ * the values found in the header and is responsible for writing them to the
+ * output.
+ */
+struct header
+{
+ /**
+ * Magic value, used to validate that this really is a device tree
+ * blob. Should always be set to 0xd00dfeed.
+ */
+ uint32_t magic;
+ /**
+ * The total size of the blob, including header, reservations, strings
+ * table, and padding.
+ */
+ uint32_t totalsize;
+ /**
+ * The offset from the start of the blob of the struct table (i.e. the
+ * part of the blob containing the entire device tree).
+ */
+ uint32_t off_dt_struct;
+ /**
+ * The offset from the start of the blob of the strings table.
+ */
+ uint32_t off_dt_strings;
+ /**
+ * The offset of the reservation map from the start of the blob.
+ */
+ uint32_t off_mem_rsvmap;
+ /**
+ * The version of the blob. This should always be 17.
+ */
+ uint32_t version;
+ /**
+ * The earliest version of the DTB specification with which this blob
+ * is backwards compatible. This should always be 16.
+ */
+ uint32_t last_comp_version;
+ /**
+ * The ID of the CPU where this boots.
+ */
+ uint32_t boot_cpuid_phys;
+ /**
+ * The size of the strings table.
+ */
+ uint32_t size_dt_strings;
+ /**
+ * The size of the struct table.
+ */
+ uint32_t size_dt_struct;
+ /**
+ * Writes the entire header to the specified output buffer.
+ */
+ void write(output_writer &out);
+ /**
+ * Reads the header from bits binary representation in a blob.
+ */
+ bool read_dtb(input_buffer &input);
+ /**
+ * Default constructor. Initialises the values that have sensible
+ * defaults, leaves the others blank.
+ */
+ header() : magic(0xd00dfeed), version(17), last_comp_version(16),
+ boot_cpuid_phys(0) {}
+};
+
+/**
+ * Class encapsulating the string table. FDT strings are stored in a string
+ * section. This maintains a map from strings to their offsets in the strings
+ * section.
+ *
+ * Note: We don't currently do suffix matching, which may save a small amount
+ * of space.
+ */
+class string_table {
+ /**
+ * Map from strings to their offset.
+ */
+ std::map<string, uint32_t> string_offsets;
+ /**
+ * The strings, in the order in which they should be written to the
+ * output. The order must be stable - adding another string must not
+ * change the offset of any that we have already referenced - and so we
+ * simply write the strings in the order that they are passed.
+ */
+ std::vector<string> strings;
+ /**
+ * The current size of the strings section.
+ */
+ uint32_t size;
+ public:
+ /**
+ * Default constructor, creates an empty strings table.
+ */
+ string_table() : size(0) {}
+ /**
+ * Adds a string to the table, returning the offset from the start
+ * where it will be written. If the string is already present, this
+ * will return its existing offset, otherwise it will return a new
+ * offset.
+ */
+ uint32_t add_string(string str);
+ /**
+ * Writes the strings table to the specified output.
+ */
+ void write(dtb::output_writer &writer);
+};
+
+} // namespace dtb
+
+} // namespace dtc
+
+#endif // !_DTB_HH_
diff --git a/usr.bin/dtc/dtc.1 b/usr.bin/dtc/dtc.1
new file mode 100644
index 0000000..567aa03
--- /dev/null
+++ b/usr.bin/dtc/dtc.1
@@ -0,0 +1,309 @@
+.\"-
+.\" Copyright (c) 2013 David Chisnall
+.\" 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
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"/
+.Dd January 1, 2013
+.Dt DTC 1
+.Os
+.Sh NAME
+.Nm dtc
+.Nd device tree compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl fhsv
+.Op Fl b Ar boot_cpu_id
+.Op Fl d Ar dependency_file
+.Op Fl E Ar [no-]checker_name
+.Op Fl H Ar phandle_format
+.Op Fl I Ar input_format
+.Op Fl O Ar output_format
+.Op Fl o Ar output_file
+.Op Fl R Ar entries
+.Op Fl S Ar bytes
+.Op Fl p Ar bytes
+.Op Fl V Ar blob_version
+.Op Fl W Ar [no-]checker_name
+.Ar input_file
+.Sh DESCRIPTION
+The
+.Nm
+utility converts flattened device tree (FDT) representations.
+ It is most commonly used to generate device tree blobs (DTB), the binary
+representation of an FDT, from device tree sources (DTS), the ASCII text source
+representation.
+.Pp
+The binary can be written in two formats, binary and assembly.
+The binary is identical to the in-memory representation and can be used
+directly by firmware, loaders, and so on.
+The assembly format, documented in
+.Sx "ASM FORMAT" ,
+will produce the same binary format when assembled, but also includes some
+global variables that refer to parts of the table.
+This format is most commonly used to produce a kernel specific to a device,
+with the device tree blob compiled in.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar dependency_file
+Writes a dependency file understandable by make to the specified file.
+This file can be included in a Makefile and will ensure that the output file
+depends on the input file and any files that it includes.
+This argument is only useful when the input is DTS, as only the source format
+has a notion of inclusions.
+.It Fl E Ar [no-]checker_name
+Enable or disable a specified checker.
+The argument is the name of the checker.
+The full list of checkers is given in
+.Sx CHECKERS .
+.It Fl f
+Force the tool to attempt to generate the output, even if the input had errors.
+.It Fl h
+Display the help text and exit.
+.It Fl H Ar phandle_format
+Specifies the type of phandle nodes to generate in the output.
+Valid values are:
+.Pp
+.Bl -tag -width indent -compact
+.It Ar linux
+Generate the legacy linux,phandle nodes expected by older systems.
+.It Ar epapr
+Generate the phandle nodes, as described in the ePAPR specification.
+This is the most sensible option for device trees being used with
+.Fx .
+.It Ar both
+Generate both, for maximum compatibility.
+.El
+.It Fl I Ar input_format
+Specifies the input format.
+Valid values are:
+.Pp
+.Bl -tag -width indent -compact
+.It Ar dtb
+Device tree blob.
+The binary representation of the FDT.
+.It Ar dts
+Device tree source.
+The ASCII representation of the FDT.
+This is the default if the input format is not explicitly stated.
+.El
+.It Fl O Ar output_format
+Specifies the output format.
+Valid values are:
+.Pp
+.Bl -tag -width indent -compact
+.It Ar asm
+Assembler source for generating a device tree blob, as described in
+.Sx "ASM FORMAT" .
+.It Ar dtb
+Device tree blob.
+The binary representation of the FDT.
+This is the default if the output format is not explicitly stated.
+.It Ar dts
+Device tree source.
+The ASCII representation of the FDT.
+.El
+.It Fl o Ar output_file
+The file to which to write the output.
+.It Fl R Ar entries
+The number of empty reservation table entries to pad the table with.
+This is
+useful if you are generating a device tree blob for bootloader or similar that
+needs to reserve some memory before passing control to the operating system.
+.It Fl S Ar bytes
+The minimum size in bytes of the blob.
+The blob will be padded after the strings table to ensure that it is the
+correct size.
+This is useful for environments where the device tree blob must be modified in
+place.
+.It Fl p Ar bytes
+The number of bytes of padding to add to the blob.
+The blob will be padded after the strings table to ensure that it is the
+correct size.
+This is useful for environments where the device tree blob must be modified in
+place.
+.It Fl W Ar [no-]checker_name
+Enable or disable a specified checker.
+This is an alias for
+.Fl E .
+.It Fl s
+Sorts the properties and nodes in the tree.
+This is mainly useful when using tools like
+.Xr diff 1
+to compare two device tree sources.
+.It Fl V Ar output_version
+The version of the format to output.
+This is only relevant for binary outputs, and only a value of 17 is currently
+supported.
+.It Fl v
+Display the tool version and exit.
+.It Ar input_file
+The source file.
+.El
+.Sh "ASM FORMAT"
+The assembly format defines several globals that can be referred to from other
+compilation units, in addition to any labels specified in the source.
+These are:
+.Pp
+.Bl -tag -width "dt_strings_start" -compact -offset indent
+.It dt_blob_start
+start of the device tree blob.
+.It dt_header
+start of the header, usually identical to the start of the blob.
+.It dt_reserve_map
+start of the reservation map.
+.It dt_struct_start
+start of the structure table.
+.It dt_struct_end
+end of the structure table.
+.It dt_strings_start
+start of the strings table.
+.It dt_strings_end
+end of the strings table.
+.It dt_blob_end
+end of the device tree blob.
+.El
+.Sh CHECKERS
+The utility provides a number of semantic checks on the correctness of the
+tree.
+These can be disabled with the
+.Fl W
+flag.
+For example,
+.Fl W Ar no-type-phandle
+will disable the phandle type check.
+The supported checks are:
+.Pp
+.Bl -tag -width "no-type-phandle" -compact -offset indent
+.It type-compatible
+Checks the type of the
+.Va compatible
+property.
+.It type-model
+Checks the type of the
+.Va model
+property.
+.It type-compatible
+Checks the type of the
+.Va compatible
+property.
+.El
+.Sh EXAMPLES
+The command:
+.Pp
+.Dl "dtc -o blob.S -O asm device.dts"
+.Pp
+will generate a
+.Pa blob.S
+file from the device tree source
+.Pa device.dts
+and print errors if any occur during parsing or property checking.
+The
+resulting file can be assembled and linked into a binary.
+.Pp
+The command:
+.Pp
+.Dl "dtc -o - -O dts -I dtb device.dtb"
+.Pp
+will write the device tree source for the device tree blob
+.Pa device.dtb
+to the standard output.
+This is useful when debugging device trees.
+.Sh COMPATIBILITY
+This utility is intended to be compatible with the device tree compiler
+provided by elinux.org.
+Currently, it implements the subset of features
+required to build FreeBSD and others that have been requested by FreeBSD
+developers.
+.Pp
+The
+.Ar fs
+input format is not supported.
+This builds a tree from a Linux
+.Pa /proc/device-tree ,
+a file system hierarchy not found in FreeBSD, which instead exposes the DTB
+directly via a sysctl.
+.Pp
+The warnings and errors supported by the elinux.org tool are not documented.
+This tool supports the warnings described in the
+.Sx CHECKERS
+section.
+.Sh SEE ALSO
+.Xr fdt 4
+.Sh STANDARDS
+The device tree formats understood by this tool conform to the Power.org
+Standard for Embedded Power Architecture Platform Requirements
+.Pq Vt ePAPR ,
+except as noted in the
+.Sx BUGS
+section and with the following exceptions for compatibility with the elinux.org
+tool:
+.Pp
+.Bl -bullet -compact
+.It
+The target of cross references is defined to be a node name in the
+specification, but is in fact a label.
+.El
+.Pp
+The /include/ directive is not part of the standard, however it is implemented
+with the semantics compatible with the elinux.org tool.
+It must appear in the top level of a file, and imports a new root definition.
+If a file, plus all of its inclusions, contains multiple roots then they are
+merged.
+All nodes that are present in the second but not the first are imported.
+Any that appear in both are recursively merged, with properties from the second
+replacing those from the first and properties child nodes being recursively
+merged.
+.Sh HISTORY
+A dtc tool first appeared in
+.Fx 9.0 .
+This version of the tool first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+.An David T. Chisnall
+.Pp
+Note: The fact that the tool and the author share the same initials is entirely
+coincidental.
+.Sh BUGS
+The device tree compiler does not yet support the following features:
+.Pp
+.Bl -bullet -compact
+.It
+Labels in the middle of property values.
+This is only useful in the assembly output, and only vaguely useful there, so
+is unlikely to be added soon.
+.It
+Full paths, rather than labels, as the targets for phandles.
+This is not very hard to add, but will probably not be added until something
+actually needs it.
+.El
+.Pp
+The current version performs a very limited set of semantic checks on the tree.
+This will be improved in future versions.
diff --git a/usr.bin/dtc/dtc.cc b/usr.bin/dtc/dtc.cc
new file mode 100644
index 0000000..cffb3eb
--- /dev/null
+++ b/usr.bin/dtc/dtc.cc
@@ -0,0 +1,337 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 <sys/resource.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#include "fdt.hh"
+#include "checking.hh"
+
+using namespace dtc;
+
+/**
+ * The current major version of the tool.
+ */
+int version_major = 0;
+/**
+ * The current minor version of the tool.
+ */
+int version_minor = 4;
+/**
+ * The current patch level of the tool.
+ */
+int version_patch = 0;
+
+static void usage(const char* argv0)
+{
+ fprintf(stderr, "Usage:\n"
+ "\t%s\t[-fhsv] [-b boot_cpu_id] [-d dependency_file]"
+ "[-E [no-]checker_name]\n"
+ "\t\t[-H phandle_format] [-I input_format]"
+ "[-O output_format]\n"
+ "\t\t[-o output_file] [-R entries] [-S bytes] [-p bytes]"
+ "[-V blob_version]\n"
+ "\t\t-W [no-]checker_name] input_file\n", basename(argv0));
+}
+
+/**
+ * Prints the current version of this program..
+ */
+static void version(const char* progname)
+{
+ fprintf(stderr, "Version: %s %d.%d.%d\n", progname, version_major,
+ version_minor, version_patch);
+}
+
+using fdt::device_tree;
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ int outfile = fileno(stdout);
+ const char *outfile_name = "-";
+ const char *in_file = "-";
+ FILE *depfile = 0;
+ bool debug_mode = false;
+ void (device_tree::*write_fn)(int) = &device_tree::write_binary;
+ void (device_tree::*read_fn)(const char*, FILE*) =
+ &device_tree::parse_dts;
+ uint32_t boot_cpu;
+ bool boot_cpu_specified = false;
+ bool keep_going = false;
+ bool sort = false;
+ clock_t c0 = clock();
+ class device_tree tree;
+ fdt::checking::check_manager checks;
+ const char *options = "hqI:O:o:V:d:R:S:p:b:fisvH:W:E:D";
+
+ // Don't forget to update the man page if any more options are added.
+ while ((ch = getopt(argc, argv, options)) != -1)
+ {
+ switch (ch)
+ {
+ case 'h':
+ usage(argv[0]);
+ return EXIT_SUCCESS;
+ case 'v':
+ version(argv[0]);
+ return EXIT_SUCCESS;
+ case 'I':
+ {
+ string arg = string(optarg);
+ if (arg == string("dtb"))
+ {
+ read_fn = &device_tree::parse_dtb;
+ }
+ else if (arg == string("dts"))
+ {
+ read_fn = &device_tree::parse_dts;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown input format: %s\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ case 'O':
+ {
+ string arg = string(optarg);
+ if (arg == string("dtb"))
+ {
+ write_fn = &device_tree::write_binary;
+ }
+ else if (arg == string("asm"))
+ {
+ write_fn = &device_tree::write_asm;
+ }
+ else if (arg == string("dts"))
+ {
+ write_fn = &device_tree::write_dts;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown output format: %s\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ case 'o':
+ {
+ outfile_name = optarg;
+ outfile = open(optarg, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (outfile == -1)
+ {
+ perror("Unable to open output file");
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ case 'D':
+ debug_mode = true;
+ break;
+ case 'V':
+ if (string(optarg) != string("17"))
+ {
+ fprintf(stderr, "Unknown output format version: %s\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'd':
+ {
+ if (depfile != 0)
+ {
+ fclose(depfile);
+ }
+ if (string(optarg) == string("-"))
+ {
+ depfile = stdout;
+ }
+ else
+ {
+ depfile = fdopen(open(optarg, O_CREAT | O_TRUNC | O_WRONLY, 0666), "w");
+ if (depfile == 0)
+ {
+ perror("Unable to open dependency file");
+ return EXIT_FAILURE;
+ }
+ }
+ break;
+ }
+ case 'H':
+ {
+ string arg = string(optarg);
+ if (arg == string("both"))
+ {
+ tree.set_phandle_format(device_tree::BOTH);
+ }
+ else if (arg == string("epapr"))
+ {
+ tree.set_phandle_format(device_tree::EPAPR);
+ }
+ else if (arg == string("linux"))
+ {
+ tree.set_phandle_format(device_tree::LINUX);
+ }
+ else
+ {
+ fprintf(stderr, "Unknown phandle format: %s\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ case 'b':
+ // Don't bother to check if strtoll fails, just
+ // use the 0 it returns.
+ boot_cpu = (uint32_t)strtoll(optarg, 0, 10);
+ boot_cpu_specified = true;
+ break;
+ case 'f':
+ keep_going = true;
+ break;
+ case 'W':
+ case 'E':
+ {
+ string arg = string(optarg);
+ if ((arg.size() > 3) && (strncmp(optarg, "no-", 3) == 0))
+ {
+ arg = string(optarg+3);
+ if (!checks.disable_checker(arg))
+ {
+ fprintf(stderr, "Checker %s either does not exist or is already disabled\n", optarg+3);
+ }
+ break;
+ }
+ if (!checks.enable_checker(arg))
+ {
+ fprintf(stderr, "Checker %s either does not exist or is already enabled\n", optarg);
+ }
+ break;
+ }
+ case 's':
+ {
+ sort = true;
+ break;
+ }
+ case 'i':
+ {
+ tree.add_include_path(optarg);
+ break;
+ }
+ // Should quiet warnings, but for now is silently ignored.
+ case 'q':
+ break;
+ case 'R':
+ tree.set_empty_reserve_map_entries(strtoll(optarg, 0, 10));
+ break;
+ case 'S':
+ tree.set_blob_minimum_size(strtoll(optarg, 0, 10));
+ break;
+ case 'p':
+ tree.set_blob_padding(strtoll(optarg, 0, 10));
+ break;
+ default:
+ fprintf(stderr, "Unknown option %c\n", ch);
+ return EXIT_FAILURE;
+ }
+ }
+ if (optind < argc)
+ {
+ in_file = argv[optind];
+ }
+ if (depfile != 0)
+ {
+ fputs(outfile_name, depfile);
+ fputs(": ", depfile);
+ fputs(in_file, depfile);
+ }
+ clock_t c1 = clock();
+ (tree.*read_fn)(in_file, depfile);
+ // Override the boot CPU found in the header, if we're loading from dtb
+ if (boot_cpu_specified)
+ {
+ tree.set_boot_cpu(boot_cpu);
+ }
+ if (sort)
+ {
+ tree.sort();
+ }
+ if (depfile != 0)
+ {
+ putc('\n', depfile);
+ fclose(depfile);
+ }
+ if (!(tree.is_valid() || keep_going))
+ {
+ fprintf(stderr, "Failed to parse tree. Unhappy face!\n");
+ return EXIT_FAILURE;
+ }
+ clock_t c2 = clock();
+ if (!(checks.run_checks(&tree, true) || keep_going))
+ {
+ return EXIT_FAILURE;
+ }
+ clock_t c3 = clock();
+ (tree.*write_fn)(outfile);
+ close(outfile);
+ clock_t c4 = clock();
+
+ if (debug_mode)
+ {
+ struct rusage r;
+
+ getrusage(RUSAGE_SELF, &r);
+ fprintf(stderr, "Peak memory usage: %ld bytes\n", r.ru_maxrss);
+ fprintf(stderr, "Setup and option parsing took %f seconds\n",
+ ((double)(c1-c0))/CLOCKS_PER_SEC);
+ fprintf(stderr, "Parsing took %f seconds\n",
+ ((double)(c2-c1))/CLOCKS_PER_SEC);
+ fprintf(stderr, "Checking took %f seconds\n",
+ ((double)(c3-c2))/CLOCKS_PER_SEC);
+ fprintf(stderr, "Generating output took %f seconds\n",
+ ((double)(c4-c3))/CLOCKS_PER_SEC);
+ fprintf(stderr, "Total time: %f seconds\n",
+ ((double)(c4-c0))/CLOCKS_PER_SEC);
+ // This is not needed, but keeps valgrind quiet.
+ fclose(stdin);
+ }
+ return EXIT_SUCCESS;
+}
+
diff --git a/usr.bin/dtc/fdt.cc b/usr.bin/dtc/fdt.cc
new file mode 100644
index 0000000..b6e7d56
--- /dev/null
+++ b/usr.bin/dtc/fdt.cc
@@ -0,0 +1,1361 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 "fdt.hh"
+
+#include <algorithm>
+#include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "dtb.hh"
+
+namespace dtc
+{
+
+namespace fdt
+{
+
+uint32_t
+property_value::get_as_uint32()
+{
+ if (byte_data.size() != 4)
+ {
+ return 0;
+ }
+ uint32_t v = 0;
+ v &= byte_data[0] << 24;
+ v &= byte_data[1] << 16;
+ v &= byte_data[2] << 8;
+ v &= byte_data[3] << 0;
+ return v;
+}
+
+void
+property_value::push_to_buffer(byte_buffer &buffer)
+{
+ if (!byte_data.empty())
+ {
+ buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
+ }
+ else
+ {
+ string_data.push_to_buffer(buffer, true);
+ // Trailing nul
+ buffer.push_back(0);
+ }
+}
+
+void
+property_value::write_dts(FILE *file)
+{
+ resolve_type();
+ switch (type)
+ {
+ default:
+ assert(0 && "Invalid type");
+ case STRING:
+ case STRING_LIST:
+ case CROSS_REFERENCE:
+ write_as_string(file);
+ break;
+ case PHANDLE:
+ write_as_cells(file);
+ break;
+ case BINARY:
+ if (byte_data.size() % 4 == 0)
+ {
+ write_as_cells(file);
+ break;
+ }
+ write_as_bytes(file);
+ break;
+ }
+}
+
+void
+property_value::resolve_type()
+{
+ if (type != UNKNOWN)
+ {
+ return;
+ }
+ if (byte_data.empty())
+ {
+ type = STRING;
+ return;
+ }
+ if (byte_data.back() == 0)
+ {
+ bool is_all_printable = true;
+ int nuls = 0;
+ int bytes = 0;
+ for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i<e ; i++)
+ {
+ bytes++;
+ is_all_printable &= (*i == '\0') || isprint(*i);
+ if (*i == '\0')
+ {
+ nuls++;
+ }
+ if (!is_all_printable)
+ {
+ break;
+ }
+ }
+ if (is_all_printable && (bytes > nuls))
+ {
+ type = STRING;
+ if (nuls > 0)
+ {
+ type = STRING_LIST;
+ }
+ return;
+ }
+ }
+ type = BINARY;
+}
+
+void
+property_value::write_as_string(FILE *file)
+{
+ putc('"', file);
+ if (byte_data.empty())
+ {
+ string_data.print(file);
+ }
+ else
+ {
+ for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end()-1; i!=e ; ++i)
+ {
+ // FIXME Escape tabs, newlines, and so on.
+ if (*i == '\0')
+ {
+ fputs("\", \"", file);
+ continue;
+ }
+ putc(*i, file);
+ }
+ }
+ putc('"', file);
+}
+
+void
+property_value::write_as_cells(FILE *file)
+{
+ putc('<', file);
+ assert((byte_data.size() % 4) == 0);
+ for (byte_buffer::iterator i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
+ {
+ uint32_t v = 0;
+ v = (v << 8) | *i;
+ ++i;
+ v = (v << 8) | *i;
+ ++i;
+ v = (v << 8) | *i;
+ ++i;
+ v = (v << 8) | *i;
+ fprintf(file, "0x%" PRIx32, v);
+ if (i+1 != e)
+ {
+ putc(' ', file);
+ }
+ }
+ putc('>', file);
+}
+
+void
+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);
+ if (i+1 != e)
+ {
+ putc(' ', file);
+ }
+ }
+ putc(']', file);
+}
+
+void
+property::parse_string(input_buffer &input)
+{
+ property_value v;
+ assert(input[0] == '"');
+ ++input;
+ const char *start = (const char*)input;
+ int length = 0;
+ while (char c = input[0])
+ {
+ if (c == '"' && input[-1] != '\\')
+ {
+ input.consume('"');
+ break;
+ }
+ ++input;
+ ++length;
+ }
+ v.string_data = string(start, length);
+ values.push_back(v);
+}
+
+void
+property::parse_cells(input_buffer &input)
+{
+ assert(input[0] == '<');
+ ++input;
+ property_value v;
+ input.next_token();
+ while (!input.consume('>'))
+ {
+ input.next_token();
+ // If this is a phandle then we need to get the name of the
+ // referenced node
+ if (input.consume('&'))
+ {
+ input.next_token();
+ // FIXME: We should support full paths here, but we
+ // don't.
+ string referenced = string::parse_node_name(input);
+ if (referenced.empty())
+ {
+ input.parse_error("Expected node name");
+ valid = false;
+ return;
+ }
+ input.next_token();
+ // If we already have some bytes, make the phandle a
+ // separate component.
+ if (!v.byte_data.empty())
+ {
+ values.push_back(v);
+ v = property_value();
+ }
+ v.string_data = referenced;
+ v.type = property_value::PHANDLE;
+ values.push_back(v);
+ v = property_value();
+ }
+ else
+ {
+ //FIXME: We should support labels in the middle
+ //of these, but we don't.
+ long long val;
+ if (!input.consume_integer(val))
+ {
+ input.parse_error("Expected numbers in array of cells");
+ valid = false;
+ return;
+ }
+ push_big_endian(v.byte_data, (uint32_t)val);
+ input.next_token();
+ }
+ }
+ // Don't store an empty string value here.
+ if (v.byte_data.size() > 0)
+ {
+ values.push_back(v);
+ }
+}
+
+void
+property::parse_bytes(input_buffer &input)
+{
+ assert(input[0] == '[');
+ ++input;
+ property_value v;
+ input.next_token();
+ while (!input.consume(']'))
+ {
+ {
+ //FIXME: We should support
+ //labels in the middle of
+ //these, but we don't.
+ uint8_t val;
+ if (!input.consume_hex_byte(val))
+ {
+ input.parse_error("Expected hex bytes in array of bytes");
+ valid = false;
+ return;
+ }
+ v.byte_data.push_back(val);
+ input.next_token();
+ }
+ }
+ values.push_back(v);
+}
+
+void
+property::parse_reference(input_buffer &input)
+{
+ assert(input[0] == '&');
+ ++input;
+ input.next_token();
+ property_value v;
+ v.string_data = string::parse_node_name(input);
+ if (v.string_data.empty())
+ {
+ input.parse_error("Expected node name");
+ valid = false;
+ return;
+ }
+ v.type = property_value::CROSS_REFERENCE;
+ values.push_back(v);
+}
+
+property::property(input_buffer &structs, input_buffer &strings)
+{
+ uint32_t name_offset;
+ uint32_t length;
+ valid = structs.consume_binary(length) &&
+ structs.consume_binary(name_offset);
+ if (!valid)
+ {
+ fprintf(stderr, "Failed to read property\n");
+ return;
+ }
+ // Find the name
+ input_buffer name_buffer = strings.buffer_from_offset(name_offset);
+ if (name_buffer.empty())
+ {
+ fprintf(stderr, "Property name offset %" PRIu32
+ " is past the end of the strings table\n",
+ name_offset);
+ valid = false;
+ return;
+ }
+ key = string(name_buffer);
+ // Read the value
+ uint8_t byte;
+ property_value v;
+ for (uint32_t i=0 ; i<length ; i++)
+ {
+ if (!(valid = structs.consume_binary(byte)))
+ {
+ fprintf(stderr, "Failed to read property value\n");
+ return;
+ }
+ v.byte_data.push_back(byte);
+ }
+ values.push_back(v);
+}
+
+property::property(input_buffer &input, string k, string l) : key(k), label(l),
+ valid(true)
+{
+ do {
+ input.next_token();
+ switch (input[0])
+ {
+ default:
+ input.parse_error("Invalid property value.");
+ valid = false;
+ return;
+ case '"':
+ parse_string(input);
+ break;
+ case '<':
+ parse_cells(input);
+ break;
+ case '[':
+ parse_bytes(input);
+ break;
+ case '&':
+ parse_reference(input);
+ break;
+ case ';':
+ {
+ break;
+ }
+ }
+ input.next_token();
+ } while (input.consume(','));
+ if (!input.consume(';'))
+ {
+ input.parse_error("Expected ; at end of property");
+ valid = false;
+ }
+}
+
+property*
+property::parse_dtb(input_buffer &structs, input_buffer &strings)
+{
+ property *p = new property(structs, strings);
+ if (!p->valid)
+ {
+ delete p;
+ p = 0;
+ }
+ return p;
+}
+
+property*
+property::parse(input_buffer &input, string key, string label)
+{
+ property *p = new property(input, key, label);
+ if (!p->valid)
+ {
+ delete p;
+ p = 0;
+ }
+ return p;
+}
+
+void
+property::write(dtb::output_writer &writer, dtb::string_table &strings)
+{
+ writer.write_token(dtb::FDT_PROP);
+ byte_buffer value_buffer;
+ for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
+ {
+ i->push_to_buffer(value_buffer);
+ }
+ writer.write_data((uint32_t)value_buffer.size());
+ writer.write_comment(key);
+ writer.write_data(strings.add_string(key));
+ writer.write_data(value_buffer);
+}
+
+void
+property::write_dts(FILE *file, int indent)
+{
+ for (int i=0 ; i<indent ; i++)
+ {
+ putc('\t', file);
+ }
+ if (label != string())
+ {
+ label.print(file);
+ fputs(": ", file);
+ }
+ if (key != string())
+ {
+ key.print(file);
+ }
+ if (!values.empty())
+ {
+ fputs(" = ", file);
+ for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
+ {
+ i->write_dts(file);
+ if (i+1 != e)
+ {
+ putc(',', file);
+ putc(' ', file);
+ }
+ }
+ }
+ fputs(";\n", file);
+}
+
+string
+node::parse_name(input_buffer &input, bool &is_property, const char *error)
+{
+ if (!valid)
+ {
+ return string();
+ }
+ input.next_token();
+ if (is_property)
+ {
+ return string::parse_property_name(input);
+ }
+ string n = string::parse_node_or_property_name(input, is_property);
+ if (n.empty())
+ {
+ if (n.empty())
+ {
+ input.parse_error(error);
+ valid = false;
+ }
+ }
+ return n;
+}
+
+node::node(input_buffer &structs, input_buffer &strings) : valid(true)
+{
+ const char *name_start = (const char*)structs;
+ int name_length = 0;
+ while (structs[0] != '\0' && structs[0] != '@')
+ {
+ name_length++;
+ ++structs;
+ }
+ name = string(name_start, name_length);
+ if (structs[0] == '@')
+ {
+ ++structs;
+ name_start = (const char*)structs;
+ name_length = 0;
+ while (structs[0] != '\0')
+ {
+ name_length++;
+ ++structs;
+ }
+ unit_address = string(name_start, name_length);
+ }
+ ++structs;
+ uint32_t token;
+ while (structs.consume_binary(token))
+ {
+ switch (token)
+ {
+ default:
+ fprintf(stderr, "Unexpected token 0x%" PRIx32
+ " while parsing node.\n", token);
+ valid = false;
+ return;
+ // Child node, parse it.
+ case dtb::FDT_BEGIN_NODE:
+ {
+ node *child = node::parse_dtb(structs, strings);
+ if (child == 0)
+ {
+ valid = false;
+ return;
+ }
+ children.push_back(child);
+ break;
+ }
+ // End of this node, no errors.
+ case dtb::FDT_END_NODE:
+ return;
+ // Property, parse it.
+ case dtb::FDT_PROP:
+ {
+ property *prop = property::parse_dtb(structs, strings);
+ if (prop == 0)
+ {
+ valid = false;
+ return;
+ }
+ properties.push_back(prop);
+ break;
+ }
+ break;
+ // End of structs table. Should appear after
+ // the end of the last node.
+ case dtb::FDT_END:
+ fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
+ valid = false;
+ return;
+ // NOPs are padding. Ignore them.
+ case dtb::FDT_NOP:
+ break;
+ }
+ }
+ fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
+ valid = false;
+ return;
+}
+
+node::node(input_buffer &input, string n, string l, string a) :
+ label(l), name(n), unit_address(a), valid(true)
+{
+ if (!input.consume('{'))
+ {
+ input.parse_error("Expected { to start new device tree node.\n");
+ }
+ input.next_token();
+ while (valid && !input.consume('}'))
+ {
+ // flag set if we find any characters that are only in
+ // the property name character set, not the node
+ bool is_property = false;
+ string child_name, child_label, child_address;
+ child_name = parse_name(input, is_property,
+ "Expected property or node name");
+ if (input.consume(':'))
+ {
+ // Node labels can contain any characters? The
+ // spec doesn't say, so we guess so...
+ is_property = false;
+ child_label = child_name;
+ child_name = parse_name(input, is_property, "Expected property or node name");
+ }
+ if (input.consume('@'))
+ {
+ child_address = parse_name(input, is_property, "Expected unit address");
+ }
+ if (!valid)
+ {
+ return;
+ }
+ input.next_token();
+ // If we're parsing a property, then we must actually do that.
+ if (input.consume('='))
+ {
+ property *p= property::parse(input, child_name,
+ child_label);
+ if (p == 0)
+ {
+ valid = false;
+ }
+ else
+ {
+ properties.push_back(p);
+ }
+ }
+ else if (!is_property && input[0] == ('{'))
+ {
+ node *child = node::parse(input, child_name,
+ child_label, child_address);
+ if (child)
+ {
+ children.push_back(child);
+ }
+ else
+ {
+ valid = false;
+ }
+ }
+ else if (input.consume(';'))
+ {
+ properties.push_back(new property(child_name, child_label));
+ }
+ else
+ {
+ input.parse_error("Error parsing property.");
+ valid = false;
+ }
+ input.next_token();
+ }
+ input.consume(';');
+}
+
+bool
+node::cmp_properties(property *p1, property *p2)
+{
+ return p1->get_key() < p2->get_key();
+}
+
+bool
+node::cmp_children(node *c1, node *c2)
+{
+ if (c1->name == c2->name)
+ {
+ return c1->unit_address < c2->unit_address;
+ }
+ return c1->name < c2->name;
+}
+
+void
+node::sort()
+{
+ std::sort(property_begin(), property_end(), cmp_properties);
+ std::sort(child_begin(), child_end(), cmp_children);
+ for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
+ {
+ (*i)->sort();
+ }
+}
+
+node*
+node::parse(input_buffer &input, string name, string label, string address)
+{
+ node *n = new node(input, name, label, address);
+ if (!n->valid)
+ {
+ delete n;
+ n = 0;
+ }
+ return n;
+}
+
+node*
+node::parse_dtb(input_buffer &structs, input_buffer &strings)
+{
+ node *n = new node(structs, strings);
+ if (!n->valid)
+ {
+ delete n;
+ n = 0;
+ }
+ return n;
+}
+
+node::~node()
+{
+ while (!children.empty())
+ {
+ delete children.back();
+ children.pop_back();
+ }
+ while (!properties.empty())
+ {
+ delete properties.back();
+ properties.pop_back();
+ }
+}
+
+property*
+node::get_property(string key)
+{
+ for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
+ {
+ if ((*i)->get_key() == key)
+ {
+ return *i;
+ }
+ }
+ return 0;
+}
+
+void
+node::merge_node(node *other)
+{
+ if (!other->label.empty())
+ {
+ label = other->label;
+ }
+ // Note: this is an O(n*m) operation. It might be sensible to
+ // optimise this if we find that there are nodes with very
+ // large numbers of properties, but for typical usage the
+ // entire vector will fit (easily) into cache, so iterating
+ // over it repeatedly isn't that expensive.
+ while (!other->properties.empty())
+ {
+ property *p = other->properties.front();
+ for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
+ {
+ if ((*i)->get_key() == p->get_key())
+ {
+ delete *i;
+ properties.erase(i);
+ break;
+ }
+ }
+ add_property(p);
+ other->properties.erase(other->properties.begin());
+ }
+ while (!other->children.empty())
+ {
+ node *c = other->children.front();
+ bool found = false;
+ for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
+ {
+ if ((*i)->name == c->name && (*i)->unit_address == c->unit_address)
+ {
+ (*i)->merge_node(c);
+ delete c;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ children.push_back(c);
+ }
+ other->children.erase(other->children.begin());
+ }
+}
+
+void
+node::write(dtb::output_writer &writer, dtb::string_table &strings)
+{
+ writer.write_token(dtb::FDT_BEGIN_NODE);
+ byte_buffer name_buffer;
+ name.push_to_buffer(name_buffer);
+ if (unit_address != string())
+ {
+ name_buffer.push_back('@');
+ unit_address.push_to_buffer(name_buffer);
+ }
+ writer.write_comment(name);
+ writer.write_data(name_buffer);
+ writer.write_data((uint8_t)0);
+ for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
+ {
+ (*i)->write(writer, strings);
+ }
+ for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
+ {
+ (*i)->write(writer, strings);
+ }
+ writer.write_token(dtb::FDT_END_NODE);
+}
+
+void
+node::write_dts(FILE *file, int indent)
+{
+ for (int i=0 ; i<indent ; i++)
+ {
+ putc('\t', file);
+ }
+ if (label != string())
+ {
+ label.print(file);
+ fputs(": ", file);
+ }
+ if (name != string())
+ {
+ name.print(file);
+ }
+ if (unit_address != string())
+ {
+ putc('@', file);
+ unit_address.print(file);
+ }
+ fputs(" {\n\n", file);
+ for (property_iterator i=property_begin(), e=property_end() ; i!=e ; ++i)
+ {
+ (*i)->write_dts(file, indent+1);
+ }
+ for (child_iterator i=child_begin(), e=child_end() ; i!=e ; ++i)
+ {
+ (*i)->write_dts(file, indent+1);
+ }
+ for (int i=0 ; i<indent ; i++)
+ {
+ putc('\t', file);
+ }
+ fputs("};\n", file);
+}
+
+void
+device_tree::collect_names_recursive(node* n, node_path &path)
+{
+ string name = n->label;
+ path.push_back(std::make_pair(n->name, n->unit_address));
+ if (name != string())
+ {
+ if (node_names.find(name) == node_names.end())
+ {
+ node_names.insert(std::make_pair(name, n));
+ node_paths.insert(std::make_pair(name, path));
+ }
+ else
+ {
+ node_names[name] = (node*)-1;
+ std::map<string, node_path>::iterator i = node_paths.find(name);
+ if (i != node_paths.end())
+ {
+ node_paths.erase(name);
+ }
+ fprintf(stderr, "Label not unique: ");
+ name.dump();
+ fprintf(stderr, ". References to this label will not be resolved.");
+ }
+ }
+ for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ; ++i)
+ {
+ collect_names_recursive(*i, path);
+ }
+ path.pop_back();
+ // Now we collect the phandles and properties that reference
+ // other nodes.
+ for (node::property_iterator i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
+ {
+ for (property::value_iterator p=(*i)->begin(),pe=(*i)->end() ; p!=pe ; ++p)
+ {
+ if (p->is_phandle())
+ {
+ phandles.push_back(&*p);
+ }
+ if (p->is_cross_reference())
+ {
+ cross_references.push_back(&*p);
+ }
+ }
+ if ((*i)->get_key() == string("phandle") ||
+ (*i)->get_key() == string("linux,phandle"))
+ {
+ if ((*i)->begin()->byte_data.size() != 4)
+ {
+ fprintf(stderr, "Invalid phandle value for node ");
+ n->name.dump();
+ fprintf(stderr, ". Should be a 4-byte value.\n");
+ valid = false;
+ }
+ else
+ {
+ uint32_t phandle = (*i)->begin()->get_as_uint32();
+ used_phandles.insert(std::make_pair(phandle, n));
+ }
+ }
+ }
+}
+
+void
+device_tree::collect_names()
+{
+ node_path p;
+ collect_names_recursive(root, p);
+}
+
+void
+device_tree::resolve_cross_references()
+{
+ for (std::vector<property_value*>::iterator i=cross_references.begin(), e=cross_references.end() ; i!=e ; ++i)
+ {
+ property_value* pv = *i;
+ node_path path = node_paths[pv->string_data];
+ // Skip the first name in the path. It's always "", and implicitly /
+ for (node_path::iterator p=path.begin()+1, pe=path.end() ; p!=pe ; ++p)
+ {
+ pv->byte_data.push_back('/');
+ p->first.push_to_buffer(pv->byte_data);
+ if (!(p->second.empty()))
+ {
+ pv->byte_data.push_back('@');
+ p->second.push_to_buffer(pv->byte_data);
+ }
+ }
+ pv->byte_data.push_back(0);
+ }
+ uint32_t phandle = 1;
+ for (std::vector<property_value*>::iterator i=phandles.begin(), e=phandles.end() ; i!=e ; ++i)
+ {
+ string target_name = (*i)->string_data;
+ node *target = node_names[target_name];
+ if (target == 0)
+ {
+ fprintf(stderr, "Failed to find node with label:");
+ target_name.dump();
+ fprintf(stderr, "\n");
+ valid = 0;
+ return;
+ }
+ // If there is an existing phandle, use it
+ property *p = target->get_property("phandle");
+ if (p == 0)
+ {
+ p = target->get_property("linux,phandle");
+ }
+ if (p == 0)
+ {
+ // Otherwise insert a new phandle node
+ property_value v;
+ while (used_phandles.find(phandle) != used_phandles.end())
+ {
+ // Note that we only don't need to
+ // store this phandle in the set,
+ // because we are monotonically
+ // increasing the value of phandle and
+ // so will only ever revisit this value
+ // if we have used 2^32 phandles, at
+ // which point our blob won't fit in
+ // any 32-bit system and we've done
+ // something badly wrong elsewhere
+ // already.
+ phandle++;
+ }
+ push_big_endian(v.byte_data, phandle++);
+ if (phandle_node_name == BOTH || phandle_node_name == LINUX)
+ {
+ p = new property(string("linux,phandle"));
+ p->add_value(v);
+ target->add_property(p);
+ }
+ if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
+ {
+ p = new property(string("phandle"));
+ p->add_value(v);
+ target->add_property(p);
+ }
+ }
+ p->begin()->push_to_buffer((*i)->byte_data);
+ assert((*i)->byte_data.size() == 4);
+ }
+}
+
+void
+device_tree::parse_roots(input_buffer &input, std::vector<node*> &roots)
+{
+ input.next_token();
+ while (valid && input.consume('/'))
+ {
+ input.next_token();
+ node *n = node::parse(input, string("", 1));
+ if (n)
+ {
+ roots.push_back(n);
+ }
+ else
+ {
+ valid = false;
+ }
+ }
+}
+
+input_buffer*
+device_tree::buffer_for_file(const char *path)
+{
+ if (string(path) == string("-"))
+ {
+ input_buffer *b = new stream_input_buffer();
+ buffers.push_back(b);
+ return b;
+ }
+ int source = open(path, O_RDONLY);
+ if (source == -1)
+ {
+ fprintf(stderr, "Unable to open file %s\n", path);
+ return 0;
+ }
+ input_buffer *b = new mmap_input_buffer(source);
+ // Keep the buffer that owns the memory around for the lifetime
+ // of this FDT. Ones simply referring to it may have shorter
+ // lifetimes.
+ buffers.push_back(b);
+ close(source);
+ return b;
+}
+
+template<class writer> void
+device_tree::write(int fd)
+{
+ dtb::string_table st;
+ dtb::header head;
+ writer head_writer;
+ writer reservation_writer;
+ writer struct_writer;
+ writer strings_writer;
+
+ // Build the reservation table
+ reservation_writer.write_comment(string("Memory reservations"));
+ reservation_writer.write_label(string("dt_reserve_map"));
+ for (std::vector<reservation>::iterator i=reservations.begin(),
+ e=reservations.end() ; i!=e ; ++i)
+ {
+ reservation_writer.write_comment(string("Reservation start"));
+ reservation_writer.write_data(i->first);
+ reservation_writer.write_comment(string("Reservation length"));
+ reservation_writer.write_data(i->first);
+ }
+ // Write n spare reserve map entries, plus the trailing 0.
+ for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
+ {
+ reservation_writer.write_data((uint64_t)0);
+ reservation_writer.write_data((uint64_t)0);
+ }
+
+
+ struct_writer.write_comment(string("Device tree"));
+ struct_writer.write_label(string("dt_struct_start"));
+ root->write(struct_writer, st);
+ struct_writer.write_token(dtb::FDT_END);
+ struct_writer.write_label(string("dt_struct_end"));
+
+ st.write(strings_writer);
+ // Find the strings size before we stick padding on the end.
+ // Note: We should possibly use a new writer for the padding.
+ head.size_dt_strings = strings_writer.size();
+
+ // Stick the padding in the strings writer, but after the
+ // marker indicating that it's the end.
+ // Note: We probably should add a padding call to the writer so
+ // that the asm back end can write padding directives instead
+ // of a load of 0 bytes.
+ for (uint32_t i=0 ; i<blob_padding ; i++)
+ {
+ strings_writer.write_data((uint8_t)0);
+ }
+ head.totalsize = sizeof(head) + strings_writer.size() +
+ struct_writer.size() + reservation_writer.size();
+ while (head.totalsize < minimum_blob_size)
+ {
+ head.totalsize++;
+ strings_writer.write_data((uint8_t)0);
+ }
+ head.off_dt_struct = sizeof(head) + reservation_writer.size();;
+ head.off_dt_strings = head.off_dt_struct + struct_writer.size();
+ head.off_mem_rsvmap = sizeof(head);
+ head.boot_cpuid_phys = boot_cpu;
+ head.size_dt_struct = struct_writer.size();
+ head.write(head_writer);
+
+ head_writer.write_to_file(fd);
+ reservation_writer.write_to_file(fd);
+ struct_writer.write_to_file(fd);
+ strings_writer.write_label(string("dt_blob_end"));
+ strings_writer.write_to_file(fd);
+}
+
+node*
+device_tree::referenced_node(property_value &v)
+{
+ if (v.is_phandle())
+ {
+ return node_names[v.string_data];
+ }
+ if (v.is_binary())
+ {
+ return used_phandles[v.get_as_uint32()];
+ }
+ return 0;
+}
+
+void
+device_tree::write_binary(int fd)
+{
+ write<dtb::binary_writer>(fd);
+}
+
+void
+device_tree::write_asm(int fd)
+{
+ write<dtb::asm_writer>(fd);
+}
+
+void
+device_tree::write_dts(int fd)
+{
+ FILE *file = fdopen(fd, "w");
+ fputs("/dtc-v1/;\n\n", file);
+
+ if (!reservations.empty())
+ {
+ const char msg[] = "/memreserve/";
+ fwrite(msg, sizeof(msg), 1, file);
+ for (std::vector<reservation>::iterator i=reservations.begin(),
+ e=reservations.end() ; i!=e ; ++i)
+ {
+ fprintf(stderr, " %" PRIx64 " %" PRIx64, i->first, i->second);
+ }
+ fputs(";\n\n", file);
+ }
+ putc('/', file);
+ putc(' ', file);
+ root->write_dts(file, 0);
+ fclose(file);
+}
+
+void
+device_tree::parse_dtb(const char *fn, FILE *depfile)
+{
+ input_buffer *in = buffer_for_file(fn);
+ if (in == 0)
+ {
+ valid = false;
+ return;
+ }
+ input_buffer &input = *in;
+ dtb::header h;
+ valid = h.read_dtb(input);
+ boot_cpu = h.boot_cpuid_phys;
+ if (h.last_comp_version > 17)
+ {
+ fprintf(stderr, "Don't know how to read this version of the device tree blob");
+ valid = false;
+ }
+ if (!valid)
+ {
+ return;
+ }
+ input_buffer reservation_map =
+ input.buffer_from_offset(h.off_mem_rsvmap, 0);
+ uint64_t start, length;
+ do
+ {
+ if (!(reservation_map.consume_binary(start) &&
+ reservation_map.consume_binary(length)))
+ {
+ fprintf(stderr, "Failed to read memory reservation table\n");
+ valid = false;
+ return;
+ }
+ } while (!((start == 0) && (length == 0)));
+ input_buffer struct_table =
+ input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
+ input_buffer strings_table =
+ input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
+ uint32_t token;
+ if (!(struct_table.consume_binary(token) &&
+ (token == dtb::FDT_BEGIN_NODE)))
+ {
+ fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
+ valid = false;
+ return;
+ }
+ root = node::parse_dtb(struct_table, strings_table);
+ if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
+ {
+ fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
+ valid = false;
+ return;
+ }
+ valid = (root != 0);
+}
+
+void
+device_tree::parse_dts(const char *fn, FILE *depfile)
+{
+ input_buffer *in = buffer_for_file(fn);
+ if (in == 0)
+ {
+ valid = false;
+ return;
+ }
+ std::vector<node*> roots;
+ input_buffer &input = *in;
+ input.next_token();
+ bool read_header = false;
+ // Read the header
+ if (input.consume("/dts-v1/;"))
+ {
+ read_header = true;
+ }
+ input.next_token();
+ while(input.consume("/include/"))
+ {
+ input.next_token();
+ if (!input.consume('"'))
+ {
+ input.parse_error("Expected quoted filename");
+ valid = false;
+ return;
+ }
+ int length = 0;
+ while (input[length] != '"') length++;
+
+ const char *file = (const char*)input;
+ const char *dir = dirname(fn);
+ int dir_length = strlen(dir);
+ char *include_file = (char*)malloc(strlen(dir) + length + 2);
+ memcpy(include_file, dir, dir_length);
+ include_file[dir_length] = '/';
+ memcpy(include_file+dir_length+1, file, length);
+ include_file[dir_length+length+1] = 0;
+ input_buffer *include_buffer = buffer_for_file(include_file);
+
+ if (include_buffer == 0)
+ {
+ for (std::vector<const char*>::iterator i=include_paths.begin(), e=include_paths.end() ; e!=i ; ++i)
+ {
+ free(include_file);
+ dir = *i;
+ dir_length = strlen(dir);
+ include_file = (char*)malloc(strlen(dir) +
+ length + 2);
+ memcpy(include_file, dir, dir_length);
+ include_file[dir_length] = '/';
+ memcpy(include_file+dir_length+1, file, length);
+ include_file[dir_length+length+1] = 0;
+ include_buffer = buffer_for_file(include_file);
+ if (include_buffer != 0)
+ {
+ break;
+ }
+ }
+ }
+ if (depfile != 0)
+ {
+ putc(' ', depfile);
+ fputs(include_file, depfile);
+ }
+ if (include_buffer == 0)
+ {
+ valid = false;
+ return;
+ }
+ input_buffer &include = *include_buffer;
+ input.consume(include_file+dir_length+1);
+ input.consume('"');
+ free((void*)include_file);
+
+ if (!read_header)
+ {
+ include.next_token();
+ read_header = include.consume("/dts-v1/;");
+ }
+ parse_roots(include, roots);
+ }
+ input.next_token();
+ if (!read_header)
+ {
+ input.parse_error("Expected /dts-v1/; version string");
+ }
+ // Read any memory reservations
+ while(input.consume("/memreserve/"))
+ {
+ long long start, len;
+ input.next_token();
+ // Read the start and length.
+ if (!(input.consume_integer(start) &&
+ (input.next_token(),
+ input.consume_integer(len))))
+ {
+ input.parse_error("Expected /dts-v1/; version string");
+ }
+ input.next_token();
+ input.consume(';');
+ reservations.push_back(reservation(start, len));
+ }
+ parse_roots(input, roots);
+ switch (roots.size())
+ {
+ case 0:
+ valid = false;
+ input.parse_error("Failed to find root node /.");
+ return;
+ case 1:
+ root = roots[0];
+ break;
+ default:
+ {
+ root = roots[0];
+ for (std::vector<node*>::iterator i=roots.begin()+1,
+ e=roots.end() ; i!=e ; ++i)
+ {
+ root->merge_node(*i);
+ delete *i;
+ }
+ roots.resize(1);
+ }
+ }
+ collect_names();
+ resolve_cross_references();
+}
+
+device_tree::~device_tree()
+{
+ if (root != 0)
+ {
+ delete root;
+ }
+ while (!buffers.empty())
+ {
+ delete buffers.back();
+ buffers.pop_back();
+ }
+}
+
+} // namespace fdt
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/fdt.hh b/usr.bin/dtc/fdt.hh
new file mode 100644
index 0000000..b00ea48
--- /dev/null
+++ b/usr.bin/dtc/fdt.hh
@@ -0,0 +1,782 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 _FDT_HH_
+#define _FDT_HH_
+#include <map>
+
+#include "util.hh"
+#include "string.hh"
+
+namespace dtc
+{
+
+namespace dtb
+{
+struct output_writer;
+class string_table;
+}
+
+namespace fdt
+{
+/**
+ * Properties may contain a number of different value, each with a different
+ * label. This class encapsulates a single value.
+ */
+struct property_value
+{
+ /**
+ * The label for this data. This is usually empty.
+ */
+ string label;
+ /**
+ * If this value is a string, or something resolved from a string (a
+ * reference) then this contains the source string.
+ */
+ string string_data;
+ /**
+ * The data that should be written to the final output.
+ */
+ byte_buffer byte_data;
+ /**
+ * Enumeration describing the possible types of a value. Note that
+ * property-coded arrays will appear simply as binary (or possibly
+ * string, if they happen to be nul-terminated and printable), and must
+ * be checked separately.
+ */
+ enum value_type
+ {
+ /**
+ * This is a list of strings. When read from source, string
+ * lists become one property value for each string, however
+ * when read from binary we have a single property value
+ * incorporating the entire text, with nul bytes separating the
+ * strings.
+ */
+ STRING_LIST,
+ /**
+ * This property contains a single string.
+ */
+ STRING,
+ /**
+ * This is a binary value. Check the size of byte_data to
+ * determine how many bytes this contains.
+ */
+ BINARY,
+ /** This contains a short-form address that should be replaced
+ * by a fully-qualified version. This will only appear when
+ * the input is a device tree source. When parsed from a
+ * device tree blob, the cross reference will have already been
+ * resolved and the property value will be a string containing
+ * the full path of the target node. */
+ CROSS_REFERENCE,
+ /**
+ * This is a phandle reference. When parsed from source, the
+ * string_data will contain the node label for the target and,
+ * after cross references have been resolved, the binary data
+ * will contain a 32-bit integer that should match the phandle
+ * property of the target node.
+ */
+ PHANDLE,
+ /**
+ * An empty property value. This will never appear on a real
+ * property value, it is used by checkers to indicate that no
+ * property values should exist for a property.
+ */
+ EMPTY,
+ /**
+ * The type of this property has not yet been determined.
+ */
+ UNKNOWN
+ };
+ /**
+ * The type of this property.
+ */
+ value_type type;
+ /**
+ * Returns true if this value is a cross reference, false otherwise.
+ */
+ inline bool is_cross_reference()
+ {
+ return is_type(CROSS_REFERENCE);
+ }
+ /**
+ * Returns true if this value is a phandle reference, false otherwise.
+ */
+ inline bool is_phandle()
+ {
+ return is_type(PHANDLE);
+ }
+ /**
+ * Returns true if this value is a string, false otherwise.
+ */
+ inline bool is_string()
+ {
+ return is_type(STRING);
+ }
+ /**
+ * Returns true if this value is a string list (a nul-separated
+ * sequence of strings), false otherwise.
+ */
+ inline bool is_string_list()
+ {
+ return is_type(STRING_LIST);
+ }
+ /**
+ * Returns true if this value is binary, false otherwise.
+ */
+ inline bool is_binary()
+ {
+ return is_type(BINARY);
+ }
+ /**
+ * Returns this property value as a 32-bit integer. Returns 0 if this
+ * property value is not 32 bits long. The bytes in the property value
+ * are assumed to be in big-endian format, but the return value is in
+ * the host native endian.
+ */
+ uint32_t get_as_uint32();
+ /**
+ * Default constructor, specifying the label of the value.
+ */
+ property_value(string l=string()) : label(l), type(UNKNOWN) {}
+ /**
+ * Writes the data for this value into an output buffer.
+ */
+ void push_to_buffer(byte_buffer &buffer);
+
+ /**
+ * Writes the property value to the standard output. This uses the
+ * following heuristics for deciding how to print the output:
+ *
+ * - If the value is nul-terminated and only contains printable
+ * characters, it is written as a string.
+ * - If it is a multiple of 4 bytes long, then it is printed as cells.
+ * - Otherwise, it is printed as a byte buffer.
+ */
+ void write_dts(FILE *file);
+ private:
+ /**
+ * Returns whether the value is of the specified type. If the type of
+ * the value has not yet been determined, then this calculates it.
+ */
+ inline bool is_type(value_type v)
+ {
+ if (type == UNKNOWN)
+ {
+ resolve_type();
+ }
+ return type == v;
+ }
+ /**
+ * Determines the type of the value based on its contents.
+ */
+ void resolve_type();
+ /**
+ * Writes the property value to the specified file as a quoted string.
+ * This is used when generating DTS.
+ */
+ void write_as_string(FILE *file);
+ /**
+ * Writes the property value to the specified file as a sequence of
+ * 32-bit big-endian cells. This is used when generating DTS.
+ */
+ void write_as_cells(FILE *file);
+ /**
+ * Writes the property value to the specified file as a sequence of
+ * bytes. This is used when generating DTS.
+ */
+ void write_as_bytes(FILE *file);
+};
+
+/**
+ * A value encapsulating a single property. This contains a key, optionally a
+ * label, and optionally one or more values.
+ */
+class property
+{
+ /**
+ * The name of this property.
+ */
+ string key;
+ /**
+ * An optional label.
+ */
+ string label;
+ /**
+ * The values in this property.
+ */
+ std::vector<property_value> values;
+ /**
+ * Value indicating that this is a valid property. If a parse error
+ * occurs, then this value is false.
+ */
+ bool valid;
+ /**
+ * Parses a string property value, i.e. a value enclosed in double quotes.
+ */
+ void parse_string(input_buffer &input);
+ /**
+ * Parses one or more 32-bit values enclosed in angle brackets.
+ */
+ void parse_cells(input_buffer &input);
+ /**
+ * Parses an array of bytes, contained within square brackets.
+ */
+ void parse_bytes(input_buffer &input);
+ /**
+ * Parses a reference. This is a node label preceded by an ampersand
+ * symbol, which should expand to the full path to that node.
+ *
+ * Note: The specification says that the target of such a reference is
+ * a node name, however dtc assumes that it is a label, and so we
+ * follow their interpretation for compatibility.
+ */
+ void parse_reference(input_buffer &input);
+ /**
+ * Constructs a new property from two input buffers, pointing to the
+ * struct and strings tables in the device tree blob, respectively.
+ * The structs input buffer is assumed to have just consumed the
+ * FDT_PROP token.
+ */
+ property(input_buffer &structs, input_buffer &strings);
+ /**
+ * Parses a new property from the input buffer.
+ */
+ property(input_buffer &input, string k, string l);
+ public:
+ /**
+ * Creates an empty property.
+ */
+ property(string k, string l=string()) : key(k), label(l), valid(true)
+ {}
+ /**
+ * Copy constructor.
+ */
+ property(property &p) : key(p.key), label(p.label), values(p.values),
+ valid(p.valid) {}
+ /**
+ * Factory method for constructing a new property. Attempts to parse a
+ * property from the input, and returns it on success. On any parse
+ * error, this will return 0.
+ */
+ static property* parse_dtb(input_buffer &structs,
+ input_buffer &strings);
+ /**
+ * Factory method for constructing a new property. Attempts to parse a
+ * property from the input, and returns it on success. On any parse
+ * error, this will return 0.
+ */
+ static property* parse(input_buffer &input,
+ string key,
+ string label=string());
+ /**
+ * Iterator type used for accessing the values of a property.
+ */
+ typedef std::vector<property_value>::iterator value_iterator;
+ /**
+ * Returns an iterator referring to the first value in this property.
+ */
+ inline value_iterator begin()
+ {
+ return values.begin();
+ }
+ /**
+ * Returns an iterator referring to the last value in this property.
+ */
+ inline value_iterator end()
+ {
+ return values.end();
+ }
+ /**
+ * Adds a new value to an existing property.
+ */
+ inline void add_value(property_value v)
+ {
+ values.push_back(v);
+ }
+ /**
+ * Returns the key for this property.
+ */
+ inline string get_key()
+ {
+ return key;
+ }
+ /**
+ * Writes the property to the specified writer. The property name is a
+ * reference into the strings table.
+ */
+ void write(dtb::output_writer &writer, dtb::string_table &strings);
+ /**
+ * Writes in DTS format to the specified file, at the given indent
+ * level. This will begin the line with the number of tabs specified
+ * as the indent level and then write the property in the most
+ * applicable way that it can determine.
+ */
+ void write_dts(FILE *file, int indent);
+};
+
+/**
+ * Class encapsulating a device tree node. Nodes may contain properties and
+ * other nodes.
+ */
+class node
+{
+ public:
+ /**
+ * The label for this node, if any. Node labels are used as the
+ * targets for cross references.
+ */
+ string label;
+ /**
+ * The name of the node.
+ */
+ string name;
+ /**
+ * The unit address of the node, which is optionally written after the
+ * name followed by an at symbol.
+ */
+ string unit_address;
+ private:
+ /**
+ * The properties contained within this node.
+ */
+ std::vector<property*> properties;
+ /**
+ * The children of this node.
+ */
+ std::vector<node*> children;
+ /**
+ * A flag indicating whether this node is valid. This is set to false
+ * if an error occurs during parsing.
+ */
+ bool valid;
+ /**
+ * Parses a name inside a node, writing the string passed as the last
+ * argument as an error if it fails.
+ */
+ string parse_name(input_buffer &input,
+ bool &is_property,
+ const char *error);
+ /**
+ * Constructs a new node from two input buffers, pointing to the struct
+ * and strings tables in the device tree blob, respectively.
+ */
+ node(input_buffer &structs, input_buffer &strings);
+ /**
+ * Parses a new node from the specified input buffer. This is called
+ * when the input cursor is on the open brace for the start of the
+ * node. The name, and optionally label and unit address, should have
+ * already been parsed.
+ */
+ node(input_buffer &input, string n, string l, string a);
+ /**
+ * Comparison function for properties, used when sorting the properties
+ * vector. Orders the properties based on their names.
+ */
+ static inline bool cmp_properties(property *p1, property *p2);
+ /*
+ {
+ return p1->get_key() < p2->get_key();
+ }
+ */
+ /**
+ * Comparison function for nodes, used when sorting the children
+ * vector. Orders the nodes based on their names or, if the names are
+ * the same, by the unit addresses.
+ */
+ static inline bool cmp_children(node *c1, node *c2);
+ /*
+ {
+ if (c1->name == c2->name)
+ {
+ return c1->unit_address < c2->unit_address;
+ }
+ return c1->name < c2->name;
+ }
+ */
+ public:
+ /**
+ * Sorts the node's properties and children into alphabetical order and
+ * recursively sorts the children.
+ */
+ void sort();
+ /**
+ * Iterator type for child nodes.
+ */
+ typedef std::vector<node*>::iterator child_iterator;
+ /**
+ * Returns an iterator for the first child of this node.
+ */
+ inline child_iterator child_begin()
+ {
+ return children.begin();
+ }
+ /**
+ * Returns an iterator after the last child of this node.
+ */
+ inline child_iterator child_end()
+ {
+ return children.end();
+ }
+ /**
+ * Iterator type for properties of a node.
+ */
+ typedef std::vector<property*>::iterator property_iterator;
+ /**
+ * Returns an iterator after the last property of this node.
+ */
+ inline property_iterator property_begin()
+ {
+ return properties.begin();
+ }
+ /**
+ * Returns an iterator for the first property of this node.
+ */
+ inline property_iterator property_end()
+ {
+ return properties.end();
+ }
+ /**
+ * Factory method for constructing a new node. Attempts to parse a
+ * node in DTS format from the input, and returns it on success. On
+ * any parse error, this will return 0. This should be called with the
+ * cursor on the open brace of the property, after the name and so on
+ * have been parsed.
+ */
+ static node* parse(input_buffer &input,
+ string name,
+ string label=string(),
+ string address=string());
+ /**
+ * Factory method for constructing a new node. Attempts to parse a
+ * node in DTB format from the input, and returns it on success. On
+ * any parse error, this will return 0. This should be called with the
+ * cursor on the open brace of the property, after the name and so on
+ * have been parsed.
+ */
+ static node* parse_dtb(input_buffer &structs, input_buffer &strings);
+ /**
+ * Destroys the node, recursively deleting all of its properties and
+ * children.
+ */
+ ~node();
+ /**
+ * Returns a property corresponding to the specified key, or 0 if this
+ * node does not contain a property of that name.
+ */
+ property *get_property(string key);
+ /**
+ * Adds a new property to this node.
+ */
+ inline void add_property(property *p)
+ {
+ properties.push_back(p);
+ }
+ /**
+ * Merges a node into this one. Any properties present in both are
+ * overridden, any properties present in only one are preserved.
+ */
+ void merge_node(node *other);
+ /**
+ * Write this node to the specified output. Although nodes do not
+ * refer to a string table directly, their properties do. The string
+ * table passed as the second argument is used for the names of
+ * properties within this node and its children.
+ */
+ void write(dtb::output_writer &writer, dtb::string_table &strings);
+ /**
+ * Writes the current node as DTS to the specified file. The second
+ * parameter is the indent level. This function will start every line
+ * with this number of tabs.
+ */
+ void write_dts(FILE *file, int indent);
+};
+
+/**
+ * Class encapsulating the entire parsed FDT. This is the top-level class,
+ * which parses the entire DTS representation and write out the finished
+ * version.
+ */
+class device_tree
+{
+ public:
+ /**
+ * Type used for node paths. A node path is sequence of names and unit
+ * addresses.
+ */
+ typedef std::vector<std::pair<string,string> > node_path;
+ /**
+ * Name that we should use for phandle nodes.
+ */
+ enum phandle_format
+ {
+ /** linux,phandle */
+ LINUX,
+ /** phandle */
+ EPAPR,
+ /** Create both nodes. */
+ BOTH
+ };
+ private:
+ /**
+ * The format that we should use for writing phandles.
+ */
+ phandle_format phandle_node_name;
+ /**
+ * Flag indicating that this tree is valid. This will be set to false
+ * on parse errors.
+ */
+ bool valid;
+ /**
+ * Type used for memory reservations. A reservation is two 64-bit
+ * values indicating a base address and length in memory that the
+ * kernel should not use. The high 32 bits are ignored on 32-bit
+ * platforms.
+ */
+ typedef std::pair<uint64_t, uint64_t> reservation;
+ /**
+ * The memory reserves table.
+ */
+ std::vector<reservation> reservations;
+ /**
+ * Root node. All other nodes are children of this node.
+ */
+ node *root;
+ /**
+ * Mapping from names to nodes. Only unambiguous names are recorded,
+ * duplicate names are stored as (node*)-1.
+ */
+ std::map<string, node*> node_names;
+ /**
+ * A map from labels to node paths. When resolving cross references,
+ * we look up referenced nodes in this and replace the cross reference
+ * with the full path to its target.
+ */
+ std::map<string, node_path> node_paths;
+ /**
+ * A collection of property values that are references to other nodes.
+ * These should be expanded to the full path of their targets.
+ */
+ std::vector<property_value*> cross_references;
+ /**
+ * A collection of property values that refer to phandles. These will
+ * be replaced by the value of the phandle property in their
+ * destination.
+ */
+ std::vector<property_value*> phandles;
+ /**
+ * A collection of input buffers that we are using. These input
+ * buffers are the ones that own their memory, and so we must preserve
+ * them for the lifetime of the device tree.
+ */
+ std::vector<input_buffer*> buffers;
+ /**
+ * A map of used phandle values to nodes. All phandles must be unique,
+ * so we keep a set of ones that the user explicitly provides in the
+ * input to ensure that we don't reuse them.
+ *
+ * This is a map, rather than a set, because we also want to be able to
+ * find phandles that were provided by the user explicitly when we are
+ * doing checking.
+ */
+ std::map<uint32_t, node*> used_phandles;
+ /**
+ * Paths to search for include files. This contains a set of
+ * nul-terminated strings, which are not owned by this class and so
+ * must be freed separately.
+ */
+ std::vector<const char*> include_paths;
+ /**
+ * The default boot CPU, specified in the device tree header.
+ */
+ uint32_t boot_cpu;
+ /**
+ * The number of empty reserve map entries to generate in the blob.
+ */
+ uint32_t spare_reserve_map_entries;
+ /**
+ * The minimum size in bytes of the blob.
+ */
+ uint32_t minimum_blob_size;
+ /**
+ * The number of bytes of padding to add to the end of the blob.
+ */
+ uint32_t blob_padding;
+ /**
+ * Visit all of the nodes recursively, and if they have labels then add
+ * them to the node_paths and node_names vectors so that they can be
+ * used in resolving cross references. Also collects phandle
+ * properties that have been explicitly added.
+ */
+ void collect_names_recursive(node* n, node_path &path);
+ /**
+ * Calls the recursive version of this method on every root node.
+ */
+ void collect_names();
+ /**
+ * Resolves all cross references. Any properties that refer to another
+ * node must have their values replaced by either the node path or
+ * phandle value.
+ */
+ void resolve_cross_references();
+ /**
+ * Parses root nodes from the top level of a dts file.
+ */
+ void parse_roots(input_buffer &input, std::vector<node*> &roots);
+ /**
+ * Allocates a new mmap()'d input buffer for use in parsing. This
+ * object then keeps a reference to it, ensuring that it is not
+ * deallocated until the device tree is destroyed.
+ */
+ input_buffer *buffer_for_file(const char *path);
+ /**
+ * Template function that writes a dtb blob using the specified writer.
+ * The writer defines the output format (assembly, blob).
+ */
+ template<class writer>
+ void write(int fd);
+ public:
+ /**
+ * Returns the node referenced by the property. If this is a tree that
+ * is in source form, then we have a string that we can use to index
+ * the cross_references array and so we can just look that up.
+ */
+ node *referenced_node(property_value &v);
+ /**
+ * Writes this FDT as a DTB to the specified output.
+ */
+ void write_binary(int fd);
+ /**
+ * Writes this FDT as an assembly representation of the DTB to the
+ * specified output. The result can then be assembled and linked into
+ * a program.
+ */
+ void write_asm(int fd);
+ /**
+ * Writes the tree in DTS (source) format.
+ */
+ void write_dts(int fd);
+ /**
+ * Default constructor. Creates a valid, but empty FDT.
+ */
+ device_tree() : phandle_node_name(EPAPR), valid(true), root(0),
+ boot_cpu(0), spare_reserve_map_entries(0),
+ minimum_blob_size(0), blob_padding(0) {}
+ /**
+ * Constructs a device tree from the specified file name, referring to
+ * a file that contains a device tree blob.
+ */
+ void parse_dtb(const char *fn, FILE *depfile);
+ /**
+ * Constructs a device tree from the specified file name, referring to
+ * a file that contains device tree source.
+ */
+ void parse_dts(const char *fn, FILE *depfile);
+ /**
+ * Destroy the tree and any input buffers that it holds.
+ */
+ ~device_tree();
+ /**
+ * Returns whether this tree is valid.
+ */
+ inline bool is_valid()
+ {
+ return valid;
+ }
+ /**
+ * Sets the format for writing phandle properties.
+ */
+ inline void set_phandle_format(phandle_format f)
+ {
+ phandle_node_name = f;
+ }
+ /**
+ * Returns a pointer to the root node of this tree. No ownership
+ * transfer.
+ */
+ inline node *get_root() const
+ {
+ return root;
+ }
+ /**
+ * Sets the physical boot CPU.
+ */
+ void set_boot_cpu(uint32_t cpu)
+ {
+ boot_cpu = cpu;
+ }
+ /**
+ * Sorts the tree. Useful for debugging device trees.
+ */
+ void sort()
+ {
+ root->sort();
+ }
+ /**
+ * Adds a path to search for include files. The argument must be a
+ * nul-terminated string representing the path. The device tree keeps
+ * a pointer to this string, but does not own it: the caller is
+ * responsible for freeing it if required.
+ */
+ void add_include_path(const char *path)
+ {
+ include_paths.push_back(path);
+ }
+ /**
+ * Sets the number of empty reserve map entries to add.
+ */
+ void set_empty_reserve_map_entries(uint32_t e)
+ {
+ spare_reserve_map_entries = e;
+ }
+ /**
+ * Sets the minimum size, in bytes, of the blob.
+ */
+ void set_blob_minimum_size(uint32_t s)
+ {
+ minimum_blob_size = s;
+ }
+ /**
+ * Sets the amount of padding to add to the blob.
+ */
+ void set_blob_padding(uint32_t p)
+ {
+ blob_padding = p;
+ }
+};
+
+} // namespace fdt
+
+} // namespace dtc
+
+#endif // !_FDT_HH_
diff --git a/usr.bin/dtc/input_buffer.cc b/usr.bin/dtc/input_buffer.cc
new file mode 100644
index 0000000..2a483f3
--- /dev/null
+++ b/usr.bin/dtc/input_buffer.cc
@@ -0,0 +1,263 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 "input_buffer.hh"
+#include <ctype.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <assert.h>
+
+namespace dtc
+{
+
+void
+input_buffer::skip_spaces()
+{
+ if (cursor >= size) { return; }
+ if (cursor < 0) { return; }
+ char c = buffer[cursor];
+ while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f')
+ || (c == '\v') || (c == '\r'))
+ {
+ cursor++;
+ if (cursor > size)
+ {
+ c = '\0';
+ }
+ else
+ {
+ c = buffer[cursor];
+ }
+ }
+}
+
+input_buffer
+input_buffer::buffer_from_offset(int offset, int s)
+{
+ if (s == 0)
+ {
+ s = size - offset;
+ }
+ if (offset > size)
+ {
+ return input_buffer();
+ }
+ if (s > (size-offset))
+ {
+ return input_buffer();
+ }
+ return input_buffer(&buffer[offset], s);
+}
+
+bool
+input_buffer::consume(const char *str)
+{
+ int len = strlen(str);
+ if (len > size - cursor)
+ {
+ return false;
+ }
+ else
+ {
+ for (int i=0 ; i<len ; ++i)
+ {
+ if (str[i] != buffer[cursor + i])
+ {
+ return false;
+ }
+ }
+ cursor += len;
+ return true;
+ }
+ return false;
+}
+
+bool
+input_buffer::consume_integer(long long &outInt)
+{
+ // The first character must be a digit. Hex and octal strings
+ // are prefixed by 0 and 0x, respectively.
+ if (!isdigit((*this)[0]))
+ {
+ return false;
+ }
+ char *end=0;
+ outInt = strtoll(&buffer[cursor], &end, 0);
+ if (end == &buffer[cursor])
+ {
+ return false;
+ }
+ cursor = end - buffer;
+ return true;
+}
+
+bool
+input_buffer::consume_hex_byte(uint8_t &outByte)
+{
+ if (!ishexdigit((*this)[0]) && !ishexdigit((*this)[1]))
+ {
+ return false;
+ }
+ outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]);
+ cursor += 2;
+ return true;
+}
+
+input_buffer&
+input_buffer::next_token()
+{
+ int start;
+ do {
+ start = cursor;
+ skip_spaces();
+ // Parse /* comments
+ if (((*this)[0] == '/') && ((*this)[1] == '*'))
+ {
+ // eat the start of the comment
+ ++(*this);
+ ++(*this);
+ do {
+ // Find the ending * of */
+ while ((**this != '\0') && (**this != '*'))
+ {
+ ++(*this);
+ }
+ // Eat the *
+ ++(*this);
+ } while ((**this != '\0') && (**this != '/'));
+ // Eat the /
+ ++(*this);
+ }
+ // Parse // comments
+ if (((*this)[0] == '/') && ((*this)[1] == '/'))
+ {
+ // eat the start of the comment
+ ++(*this);
+ ++(*this);
+ // Find the ending * of */
+ while (**this != '\n')
+ {
+ ++(*this);
+ }
+ // Eat the \n
+ ++(*this);
+ }
+ } while (start != cursor);
+ return *this;
+}
+
+void
+input_buffer::parse_error(const char *msg)
+{
+ int line_count = 1;
+ int line_start = 0;
+ int line_end = cursor;
+ for (int i=cursor ; i>0 ; --i)
+ {
+ if (buffer[i] == '\n')
+ {
+ line_count++;
+ if (line_start == 0)
+ {
+ line_start = i+1;
+ }
+ }
+ }
+ for (int i=cursor+1 ; i<size ; ++i)
+ {
+ if (buffer[i] == '\n')
+ {
+ line_end = i;
+ break;
+ }
+ }
+ fprintf(stderr, "Error on line %d: %s\n", line_count, msg);
+ fwrite(&buffer[line_start], line_end-line_start, 1, stderr);
+ putc('\n', stderr);
+ for (int i=0 ; i<(cursor-line_start) ; ++i)
+ {
+ putc(' ', stderr);
+ }
+ putc('^', stderr);
+ putc('\n', stderr);
+}
+void
+input_buffer::dump()
+{
+ fprintf(stderr, "Current cursor: %d\n", cursor);
+ fwrite(&buffer[cursor], size-cursor, 1, stderr);
+}
+
+mmap_input_buffer::mmap_input_buffer(int fd) : input_buffer(0, 0)
+{
+ struct stat sb;
+ if (fstat(fd, &sb))
+ {
+ perror("Failed to stat file");
+ }
+ size = sb.st_size;
+ buffer = (const char*)mmap(0, size, PROT_READ,
+ MAP_PREFAULT_READ, fd, 0);
+ if (buffer == 0)
+ {
+ perror("Failed to mmap file");
+ }
+}
+
+mmap_input_buffer::~mmap_input_buffer()
+{
+ if (buffer != 0)
+ {
+ munmap((void*)buffer, size);
+ }
+}
+
+stream_input_buffer::stream_input_buffer() : input_buffer(0, 0)
+{
+ int c;
+ while ((c = fgetc(stdin)) != EOF)
+ {
+ b.push_back(c);
+ }
+ buffer = b.data();
+ size = b.size();
+}
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/input_buffer.hh b/usr.bin/dtc/input_buffer.hh
new file mode 100644
index 0000000..9a38312
--- /dev/null
+++ b/usr.bin/dtc/input_buffer.hh
@@ -0,0 +1,289 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 _INPUT_BUFFER_HH_
+#define _INPUT_BUFFER_HH_
+#include "util.hh"
+#include <assert.h>
+
+namespace dtc
+{
+
+/**
+ * Class encapsulating the input file. Can be used as a const char*, but has
+ * range checking. Attempting to access anything out of range will return a 0
+ * byte. The input buffer can be cheaply copied, without copying the
+ * underlying memory, however it is the user's responsibility to ensure that
+ * such copies do not persist beyond the lifetime of the underlying memory.
+ *
+ * This also contains methods for reporting errors and for consuming the token
+ * stream.
+ */
+class input_buffer
+{
+ protected:
+ /**
+ * The buffer. This class doesn't own the buffer, but the
+ * mmap_input_buffer subclass does.
+ */
+ const char* buffer;
+ /**
+ * The size of the buffer.
+ */
+ int size;
+ private:
+ /**
+ * The current place in the buffer where we are reading. This class
+ * keeps a separate size, pointer, and cursor so that we can move
+ * forwards and backwards and still have checks that we haven't fallen
+ * off either end.
+ */
+ int cursor;
+ /**
+ * Private constructor. This is used to create input buffers that
+ * refer to the same memory, but have different cursors.
+ */
+ input_buffer(const char* b, int s, int c) : buffer(b), size(s),
+ cursor(c) {}
+ /**
+ * Reads forward past any spaces. The DTS format is not whitespace
+ * sensitive and so we want to scan past whitespace when reading it.
+ */
+ void skip_spaces();
+ public:
+ /**
+ * Virtual destructor. Does nothing, but exists so that subclasses
+ * that own the memory can run cleanup code for deallocating it.
+ */
+ virtual ~input_buffer() {};
+ /**
+ * Constructs an empty buffer.
+ */
+ input_buffer() : buffer(0), size(0), cursor(0) {}
+ /**
+ * Constructs a new buffer with a specified memory region and size.
+ */
+ input_buffer(const char* b, int s) : buffer(b), size(s), cursor(0){}
+ /**
+ * Returns a new input buffer referring into this input, clamped to the
+ * specified size. If the requested buffer would fall outside the
+ * range of this one, then it returns an empty buffer.
+ *
+ * The returned buffer shares the same underlying storage as the
+ * original. This is intended to be used for splitting up the various
+ * sections of a device tree blob. Requesting a size of 0 will give a
+ * buffer that extends to the end of the available memory.
+ */
+ input_buffer buffer_from_offset(int offset, int s=0);
+ /**
+ * Returns true if this buffer has no unconsumed space in it.
+ */
+ inline bool empty()
+ {
+ return cursor >= size;
+ }
+ /**
+ * Dereferencing operator, allows the buffer to be treated as a char*
+ * and dereferenced to give a character. This returns a null byte if
+ * the cursor is out of range.
+ */
+ inline char operator*()
+ {
+ if (cursor >= size) { return '\0'; }
+ if (cursor < 0) { return '\0'; }
+ return buffer[cursor];
+ }
+ /**
+ * Array subscripting operator, returns a character at the specified
+ * index offset from the current cursor. The offset may be negative,
+ * to reread characters that have already been read. If the current
+ * cursor plus offset is outside of the range, this returns a nul
+ * byte.
+ */
+ inline char operator[](int offset)
+ {
+ if (cursor + offset >= size) { return '\0'; }
+ if (cursor + offset < 0) { return '\0'; }
+ return buffer[cursor + offset];
+ }
+ /**
+ * Increments the cursor, iterating forward in the buffer.
+ */
+ inline input_buffer &operator++()
+ {
+ cursor++;
+ return *this;
+ }
+ /**
+ * Cast to char* operator. Returns a pointer into the buffer that can
+ * be used for constructing strings.
+ */
+ inline operator const char*()
+ {
+ if (cursor >= size) { return 0; }
+ if (cursor < 0) { return 0; }
+ return &buffer[cursor];
+ }
+ /**
+ * Consumes a character. Moves the cursor one character forward if the
+ * next character matches the argument, returning true. If the current
+ * character does not match the argument, returns false.
+ */
+ inline bool consume(char c)
+ {
+ if ((*this)[0] == c)
+ {
+ ++(*this);
+ return true;
+ }
+ return false;
+ }
+ /**
+ * Consumes a string. If the (null-terminated) string passed as the
+ * argument appears in the input, advances the cursor to the end and
+ * returns true. Returns false if the string does not appear at the
+ * current point in the input.
+ */
+ bool consume(const char *str);
+ /**
+ * Reads an integer in base 8, 10, or 16. Returns true and advances
+ * the cursor to the end of the integer if the cursor points to an
+ * integer, returns false and does not move the cursor otherwise.
+ *
+ * The parsed value is returned via the argument.
+ */
+ bool consume_integer(long long &outInt);
+ /**
+ * Template function that consumes a binary value in big-endian format
+ * from the input stream. Returns true and advances the cursor if
+ * there is a value of the correct size. This function assumes that
+ * all values must be natively aligned, and so advances the cursor to
+ * the correct alignment before reading.
+ */
+ template<typename T>
+ bool consume_binary(T &out)
+ {
+ int align = 0;
+ int type_size = sizeof(T);
+ if (cursor % type_size != 0)
+ {
+ align = type_size - (cursor % type_size);
+ }
+ if (size < cursor + align + type_size)
+ {
+ return false;
+ }
+ cursor += align;
+ assert(cursor % type_size == 0);
+ out = 0;
+ for (int i=0 ; i<type_size ; ++i)
+ {
+ out <<= 8;
+ out |= (((T)buffer[cursor++]) & 0xff);
+ }
+ return true;
+ }
+ /**
+ * Consumes two hex digits and return the resulting byte via the first
+ * argument. If the next two characters are hex digits, returns true
+ * and advances the cursor. If not, then returns false and leaves the
+ * cursor in place.
+ */
+ bool consume_hex_byte(uint8_t &outByte);
+ /**
+ * Advances the cursor to the start of the next token, skipping
+ * comments and whitespace. If the cursor already points to the start
+ * of a token, then this function does nothing.
+ */
+ input_buffer &next_token();
+ /**
+ * Prints a message indicating the location of a parse error.
+ */
+ void parse_error(const char *msg);
+ /**
+ * Dumps the current cursor value and the unconsumed values in the
+ * input buffer to the standard error. This method is intended solely
+ * for debugging.
+ */
+ void dump();
+};
+/**
+ * Explicit specialisation for reading a single byte.
+ */
+template<>
+inline bool input_buffer::consume_binary(uint8_t &out)
+{
+ if (size < cursor + 1)
+ {
+ return false;
+ }
+ out = buffer[cursor++];
+ return true;
+}
+
+/**
+ * Subclass of input_buffer that mmap()s a file and owns the resulting memory.
+ * When this object is destroyed, the memory is unmapped.
+ */
+struct mmap_input_buffer : public input_buffer
+{
+ /**
+ * Constructs a new buffer from the file passed in as a file
+ * descriptor.
+ */
+ mmap_input_buffer(int fd);
+ /**
+ * Unmaps the buffer, if one exists.
+ */
+ virtual ~mmap_input_buffer();
+};
+/**
+ * Input buffer read from standard input. This is used for reading device tree
+ * blobs and source from standard input. It reads the entire input into
+ * malloc'd memory, so will be very slow for large inputs. DTS and DTB files
+ * are very rarely more than 10KB though, so this is probably not a problem.
+ */
+struct stream_input_buffer : public input_buffer
+{
+ /**
+ * The buffer that will store the data read from the standard input.
+ */
+ std::vector<char> b;
+ /**
+ * Constructs a new buffer from the standard input.
+ */
+ stream_input_buffer();
+};
+
+} // namespace dtc
+
+#endif // !_INPUT_BUFFER_HH_
diff --git a/usr.bin/dtc/string.cc b/usr.bin/dtc/string.cc
new file mode 100644
index 0000000..283bafa
--- /dev/null
+++ b/usr.bin/dtc/string.cc
@@ -0,0 +1,258 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 "string.hh"
+#include <ctype.h>
+#include <stdio.h>
+
+namespace
+{
+/**
+ * The source files are ASCII, so we provide a non-locale-aware version of
+ * isalpha. This is a class so that it can be used with a template function
+ * for parsing strings.
+ */
+struct is_alpha
+{
+ static inline bool check(const char c)
+ {
+ return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') &&
+ (c <= 'Z'));
+ }
+};
+/**
+ * Check whether a character is in the set allowed for node names. This is a
+ * class so that it can be used with a template function for parsing strings.
+ */
+struct is_node_name_character
+{
+ static inline bool check(const char c)
+ {
+ switch(c)
+ {
+ default:
+ return false;
+ case 'a'...'z': case 'A'...'Z': case '0'...'9':
+ case ',': case '.': case '+': case '-':
+ case '_':
+ return true;
+ }
+ }
+};
+/**
+ * Check whether a character is in the set allowed for property names. This is
+ * a class so that it can be used with a template function for parsing strings.
+ */
+struct is_property_name_character
+{
+ static inline bool check(const char c)
+ {
+ switch(c)
+ {
+ default:
+ return false;
+ case 'a'...'z': case 'A'...'Z': case '0'...'9':
+ case ',': case '.': case '+': case '-':
+ case '_': case '#':
+ return true;
+ }
+ }
+};
+
+}
+
+namespace dtc
+{
+
+template<class T> string
+string::parse(input_buffer &s)
+{
+ const char *start = s;
+ int l=0;
+ while (T::check(*s)) { l++; ++s; }
+ return string(start, l);
+}
+
+string::string(input_buffer &s) : start((const char*)s), length(0)
+{
+ while(s[length] != '\0')
+ {
+ length++;
+ }
+}
+
+string
+string::parse_node_name(input_buffer &s)
+{
+ return parse<is_node_name_character>(s);
+}
+
+string
+string::parse_property_name(input_buffer &s)
+{
+ return parse<is_property_name_character>(s);
+}
+string
+string::parse_node_or_property_name(input_buffer &s, bool &is_property)
+{
+ if (is_property)
+ {
+ return parse_property_name(s);
+ }
+ const char *start = s;
+ int l=0;
+ while (is_node_name_character::check(*s))
+ {
+ l++;
+ ++s;
+ }
+ while (is_property_name_character::check(*s))
+ {
+ l++;
+ ++s;
+ is_property = true;
+ }
+ return string(start, l);
+}
+
+bool
+string::operator==(const string& other) const
+{
+ return (length == other.length) &&
+ (memcmp(start, other.start, length) == 0);
+}
+
+bool
+string::operator==(const char *other) const
+{
+ return strncmp(other, start, length) == 0;
+}
+
+bool
+string::operator<(const string& other) const
+{
+ if (length < other.length) { return true; }
+ if (length > other.length) { return false; }
+ return memcmp(start, other.start, length) < 0;
+}
+
+void
+string::push_to_buffer(byte_buffer &buffer, bool escapes)
+{
+ for (int i=0 ; i<length ; ++i)
+ {
+ uint8_t c = start[i];
+ if (escapes && c == '\\' && i+1 < length)
+ {
+ c = start[++i];
+ switch (c)
+ {
+ // For now, we just ignore invalid escape sequences.
+ default:
+ case '"':
+ case '\'':
+ case '\\':
+ break;
+ case 'a':
+ c = '\a';
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case '0'...'7':
+ {
+ int v = digittoint(c);
+ if (i+1 < length && start[i+1] <= '7' && start[i+1] >= '0')
+ {
+ v <<= 3;
+ v |= digittoint(start[i+1]);
+ i++;
+ if (i+1 < length && start[i+1] <= '7' && start[i+1] >= '0')
+ {
+ v <<= 3;
+ v |= digittoint(start[i+1]);
+ }
+ }
+ c = (uint8_t)v;
+ break;
+ }
+ case 'x':
+ {
+ ++i;
+ if (i >= length)
+ {
+ break;
+ }
+ int v = digittoint(start[i]);
+ if (i+1 < length && ishexdigit(start[i+1]))
+ {
+ v <<= 4;
+ v |= digittoint(start[++i]);
+ }
+ c = (uint8_t)v;
+ break;
+ }
+ }
+ }
+ buffer.push_back(c);
+ }
+}
+
+void
+string::print(FILE *file)
+{
+ fwrite(start, length, 1, file);
+}
+
+void
+string::dump()
+{
+ print(stderr);
+}
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/string.hh b/usr.bin/dtc/string.hh
new file mode 100644
index 0000000..45bc4fd
--- /dev/null
+++ b/usr.bin/dtc/string.hh
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 _STRING_HH_
+#define _STRING_HH_
+#include "input_buffer.hh"
+
+namespace dtc
+{
+
+/**
+ * String, referring to a place in the input file. We don't bother copying
+ * strings until we write them to the final output. These strings should be
+ * two words long: a start and a length. They are intended to be cheap to copy
+ * and store in collections. Copying the string object does not copy the
+ * underlying storage.
+ *
+ * Strings are not nul-terminated.
+ */
+class string
+{
+ /** Start address. Contained within the mmap()'d input file and not
+ * owned by this object. */
+ const char *start;
+ /** length of the string. DTS strings are allowed to contain nuls */
+ int length;
+ /** Generic function for parsing strings matching the character set
+ * defined by the template argument. */
+ template<class T>
+ static string parse(input_buffer &s);
+ public:
+ /**
+ * Constructs a string referring into another buffer.
+ */
+ string(const char *s, int l) : start(s), length(l) {}
+ /** Constructs a string from a C string. */
+ string(const char *s) : start(s), length(strlen(s)) {}
+ /** Default constructor, returns an empty string. */
+ string() : start(0), length(0) {}
+ /** Construct a from an input buffer, ending with a nul terminator. */
+ string(input_buffer &s);
+ /**
+ * Returns the longest string in the input buffer starting at the
+ * current cursor and composed entirely of characters that are valid in
+ * node names.
+ */
+ static string parse_node_name(input_buffer &s);
+ /**
+ * Returns the longest string in the input buffer starting at the
+ * current cursor and composed entirely of characters that are valid in
+ * property names.
+ */
+ static string parse_property_name(input_buffer &s);
+ /**
+ * Parses either a node or a property name. If is_property is true on
+ * entry, then only property names are parsed. If it is false, then it
+ * will be set, on return, to indicate whether the parsed name is only
+ * valid as a property.
+ */
+ static string parse_node_or_property_name(input_buffer &s,
+ bool &is_property);
+ /**
+ * Compares two strings for equality. Strings are equal if they refer
+ * to identical byte sequences.
+ */
+ bool operator==(const string& other) const;
+ /**
+ * Compares a string against a C string. The trailing nul in the C
+ * string is ignored for the purpose of comparison, so this will always
+ * fail if the string contains nul bytes.
+ */
+ bool operator==(const char *other) const;
+ /**
+ * Inequality operator, defined as the inverse of the equality
+ * operator.
+ */
+ template <typename T>
+ inline bool operator!=(T other)
+ {
+ return !(*this == other);
+ }
+ /**
+ * Comparison operator, defined to allow strings to be used as keys in
+ * maps.
+ */
+ bool operator<(const string& other) const;
+ /**
+ * Returns true if this is the empty string, false otherwise.
+ */
+ inline bool empty() const
+ {
+ return length == 0;
+ }
+ /**
+ * Returns the size of the string, in bytes.
+ */
+ inline size_t size()
+ {
+ return length;
+ }
+ /**
+ * Writes the string to the specified buffer.
+ */
+ void push_to_buffer(byte_buffer &buffer, bool escapes=false);
+ /**
+ * Prints the string to the specified output stream.
+ */
+ void print(FILE *file);
+ /**
+ * Dumps the string to the standard error stream. Intended to be used
+ * for debugging.
+ */
+ void dump();
+};
+
+} // namespace dtc
+
+#endif // !_STRING_HH_
diff --git a/usr.bin/dtc/util.hh b/usr.bin/dtc/util.hh
new file mode 100644
index 0000000..7f2ec67
--- /dev/null
+++ b/usr.bin/dtc/util.hh
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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.
+ *
+ * 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 _UTIL_HH_
+#define _UTIL_HH_
+
+#include <vector>
+
+// If we aren't using C++11, then just ignore static asserts.
+#if __cplusplus < 201103L
+#ifndef static_assert
+#define static_assert(x, y) ((void)0)
+#endif
+#endif
+
+namespace dtc {
+
+/**
+ * Type for a buffer of bytes. This is used for a lot of short-lived temporary
+ * variables, so may eventually be changed to something like LLVM's
+ * SmallVector, but currently the program runs in a tiny fraction of a second,
+ * so this is not an issue.
+ */
+typedef std::vector<uint8_t> byte_buffer;
+
+/**
+ * Helper function to push a big endian value into a byte buffer. We use
+ * native-endian values for all of the in-memory data structures and only
+ * transform them into big endian form for output.
+ */
+template<typename T>
+inline void push_big_endian(byte_buffer &v, T val)
+{
+ static_assert(sizeof(T) > 1,
+ "Big endian doesn't make sense for single-byte values");
+ for (int bit=(sizeof(T) - 1)*8 ; bit>=0 ; bit-= 8)
+ {
+ v.push_back((val >> bit) & 0xff);
+ }
+}
+
+/**
+ * Simple inline non-locale-aware check that this is a valid ASCII
+ * digit.
+ */
+inline bool isdigit(char c)
+{
+ return (c >= '0') && (c <= '9');
+}
+
+/**
+ * Simple inline non-locale-aware check that this is a valid ASCII
+ * hex digit.
+ */
+inline bool ishexdigit(char c)
+{
+ return ((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) ||
+ ((c >= 'A') && (c <= 'Z'));
+}
+
+}// namespace dtc
+
+#endif // !_UTIL_HH_
diff --git a/usr.bin/ee/Makefile b/usr.bin/ee/Makefile
index ffa47b9..2236777 100644
--- a/usr.bin/ee/Makefile
+++ b/usr.bin/ee/Makefile
@@ -13,7 +13,7 @@ LDADD= -lncurses
WARNS?= 2
-NLS= en_US.US-ASCII fr_FR.ISO8859-1 de_DE.ISO8859-1 pl_PL.ISO8859-2 \
+NLS= C fr_FR.ISO8859-1 de_DE.ISO8859-1 pl_PL.ISO8859-2 \
uk_UA.KOI8-U pt_BR.ISO8859-1 ru_RU.KOI8-R hu_HU.ISO8859-2
NLSLINKS_en_US.US-ASCII= en_US.ISO8859-1 en_US.ISO8859-15
diff --git a/usr.bin/grep/grep.c b/usr.bin/grep/grep.c
index 70fd9bd..117a5a9 100644
--- a/usr.bin/grep/grep.c
+++ b/usr.bin/grep/grep.c
@@ -481,7 +481,7 @@ main(int argc, char *argv[])
case 'e':
{
char *token;
- char *string = strdup(optarg);
+ char *string = optarg;
while ((token = strsep(&string, "\n")) != NULL)
add_pattern(token, strlen(token));
@@ -675,7 +675,7 @@ main(int argc, char *argv[])
/* Process patterns from command line */
if (aargc != 0 && needpattern) {
char *token;
- char *string = strdup(*aargv);
+ char *string = *aargv;
while ((token = strsep(&string, "\n")) != NULL)
add_pattern(token, strlen(token));
diff --git a/usr.bin/man/man.1 b/usr.bin/man/man.1
index d8486bd..4763cc6 100644
--- a/usr.bin/man/man.1
+++ b/usr.bin/man/man.1
@@ -84,7 +84,7 @@ environment variable.
.It Fl S Ar mansect
Restricts manual sections searched to the specified colon delimited list.
Defaults to
-.Dq Li 1:1aout:8:2:3:n:4:5:6:7:9:l .
+.Dq Li 1:8:2:3:n:4:5:6:7:9:l .
Overrides the
.Ev MANSECT
environment variable.
diff --git a/usr.bin/man/man.sh b/usr.bin/man/man.sh
index 0725e0b..0f6249a 100755
--- a/usr.bin/man/man.sh
+++ b/usr.bin/man/man.sh
@@ -945,7 +945,7 @@ STTY=/bin/stty
SYSCTL=/sbin/sysctl
debug=0
-man_default_sections='1:1aout:8:2:3:n:4:5:6:7:9:l'
+man_default_sections='1:8:2:3:n:4:5:6:7:9:l'
man_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/man'
cattool='/usr/bin/zcat -f'
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 9d8c97e..8094e5b 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -699,7 +699,7 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n");
p(tcps_sc_recvcookie, "\t%lu cookie%s received\n");
- p(tcps_hc_added, "\t%lu hostcache entrie%s added\n");
+ p3(tcps_hc_added, "\t%lu hostcache entr%s added\n");
p1a(tcps_hc_bucketoverflow, "\t\t%lu bucket overflow\n");
p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n");
diff --git a/usr.bin/patch/Makefile b/usr.bin/patch/Makefile
new file mode 100644
index 0000000..382a05f
--- /dev/null
+++ b/usr.bin/patch/Makefile
@@ -0,0 +1,18 @@
+# $OpenBSD: Makefile,v 1.4 2005/05/16 15:22:46 espie Exp $
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+.if ${MK_BSD_PATCH} == "yes"
+PROG= patch
+.else
+PROG= bsdpatch
+CLEANFILES+= bsdpatch.1
+
+bsdpatch.1: patch.1
+ cp ${.ALLSRC} ${.TARGET}
+.endif
+
+SRCS= backupfile.c inp.c mkpath.c patch.c pch.c util.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/patch/backupfile.c b/usr.bin/patch/backupfile.c
new file mode 100644
index 0000000..d22d607
--- /dev/null
+++ b/usr.bin/patch/backupfile.c
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (C) 1990 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * without restriction.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * backupfile.c -- make Emacs style backup file names
+ *
+ * David MacKenzie <djm@ai.mit.edu>. Some algorithms adapted from GNU Emacs.
+ *
+ * $OpenBSD: backupfile.c,v 1.20 2009/10/27 23:59:41 deraadt Exp $
+ * $FreeBSD$
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "backupfile.h"
+
+
+#define ISDIGIT(c) (isascii ((unsigned char)c) && isdigit ((unsigned char)c))
+
+/* Which type of backup file names are generated. */
+enum backup_type backup_type = none;
+
+/*
+ * The extension added to file names to produce a simple (as opposed to
+ * numbered) backup file name.
+ */
+const char *simple_backup_suffix = "~";
+
+static char *concat(const char *, const char *);
+static char *make_version_name(const char *, int);
+static int max_backup_version(const char *, const char *);
+static int version_number(const char *, const char *, size_t);
+static int argmatch(const char *, const char **);
+static void invalid_arg(const char *, const char *, int);
+
+/*
+ * Return the name of the new backup file for file FILE, allocated with
+ * malloc. Return 0 if out of memory. FILE must not end with a '/' unless it
+ * is the root directory. Do not call this function if backup_type == none.
+ */
+char *
+find_backup_file_name(const char *file)
+{
+ char *dir, *base_versions, *tmp_file;
+ int highest_backup;
+
+ if (backup_type == simple)
+ return concat(file, simple_backup_suffix);
+ tmp_file = strdup(file);
+ if (tmp_file == NULL)
+ return NULL;
+ base_versions = concat(basename(tmp_file), ".~");
+ free(tmp_file);
+ if (base_versions == NULL)
+ return NULL;
+ tmp_file = strdup(file);
+ if (tmp_file == NULL) {
+ free(base_versions);
+ return NULL;
+ }
+ dir = dirname(tmp_file);
+ if (dir == NULL) {
+ free(base_versions);
+ free(tmp_file);
+ return NULL;
+ }
+ highest_backup = max_backup_version(base_versions, dir);
+ free(base_versions);
+ free(tmp_file);
+ if (backup_type == numbered_existing && highest_backup == 0)
+ return concat(file, simple_backup_suffix);
+ return make_version_name(file, highest_backup + 1);
+}
+
+/*
+ * Return the number of the highest-numbered backup file for file FILE in
+ * directory DIR. If there are no numbered backups of FILE in DIR, or an
+ * error occurs reading DIR, return 0. FILE should already have ".~" appended
+ * to it.
+ */
+static int
+max_backup_version(const char *file, const char *dir)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ int highest_version, this_version;
+ size_t file_name_length;
+
+ dirp = opendir(dir);
+ if (dirp == NULL)
+ return 0;
+
+ highest_version = 0;
+ file_name_length = strlen(file);
+
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_namlen <= file_name_length)
+ continue;
+
+ this_version = version_number(file, dp->d_name, file_name_length);
+ if (this_version > highest_version)
+ highest_version = this_version;
+ }
+ closedir(dirp);
+ return highest_version;
+}
+
+/*
+ * Return a string, allocated with malloc, containing "FILE.~VERSION~".
+ * Return 0 if out of memory.
+ */
+static char *
+make_version_name(const char *file, int version)
+{
+ char *backup_name;
+
+ if (asprintf(&backup_name, "%s.~%d~", file, version) == -1)
+ return NULL;
+ return backup_name;
+}
+
+/*
+ * If BACKUP is a numbered backup of BASE, return its version number;
+ * otherwise return 0. BASE_LENGTH is the length of BASE. BASE should
+ * already have ".~" appended to it.
+ */
+static int
+version_number(const char *base, const char *backup, size_t base_length)
+{
+ int version;
+ const char *p;
+
+ version = 0;
+ if (!strncmp(base, backup, base_length) && ISDIGIT(backup[base_length])) {
+ for (p = &backup[base_length]; ISDIGIT(*p); ++p)
+ version = version * 10 + *p - '0';
+ if (p[0] != '~' || p[1])
+ version = 0;
+ }
+ return version;
+}
+
+/*
+ * Return the newly-allocated concatenation of STR1 and STR2. If out of
+ * memory, return 0.
+ */
+static char *
+concat(const char *str1, const char *str2)
+{
+ char *newstr;
+
+ if (asprintf(&newstr, "%s%s", str1, str2) == -1)
+ return NULL;
+ return newstr;
+}
+
+/*
+ * If ARG is an unambiguous match for an element of the null-terminated array
+ * OPTLIST, return the index in OPTLIST of the matched element, else -1 if it
+ * does not match any element or -2 if it is ambiguous (is a prefix of more
+ * than one element).
+ */
+static int
+argmatch(const char *arg, const char **optlist)
+{
+ int i; /* Temporary index in OPTLIST. */
+ size_t arglen; /* Length of ARG. */
+ int matchind = -1; /* Index of first nonexact match. */
+ int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
+
+ arglen = strlen(arg);
+
+ /* Test all elements for either exact match or abbreviated matches. */
+ for (i = 0; optlist[i]; i++) {
+ if (!strncmp(optlist[i], arg, arglen)) {
+ if (strlen(optlist[i]) == arglen)
+ /* Exact match found. */
+ return i;
+ else if (matchind == -1)
+ /* First nonexact match found. */
+ matchind = i;
+ else
+ /* Second nonexact match found. */
+ ambiguous = 1;
+ }
+ }
+ if (ambiguous)
+ return -2;
+ else
+ return matchind;
+}
+
+/*
+ * Error reporting for argmatch. KIND is a description of the type of entity
+ * that was being matched. VALUE is the invalid value that was given. PROBLEM
+ * is the return value from argmatch.
+ */
+static void
+invalid_arg(const char *kind, const char *value, int problem)
+{
+ fprintf(stderr, "patch: ");
+ if (problem == -1)
+ fprintf(stderr, "invalid");
+ else /* Assume -2. */
+ fprintf(stderr, "ambiguous");
+ fprintf(stderr, " %s `%s'\n", kind, value);
+}
+
+static const char *backup_args[] = {
+ "never", "simple", "nil", "existing", "t", "numbered", 0
+};
+
+static enum backup_type backup_types[] = {
+ simple, simple, numbered_existing,
+ numbered_existing, numbered, numbered
+};
+
+/*
+ * Return the type of backup indicated by VERSION. Unique abbreviations are
+ * accepted.
+ */
+enum backup_type
+get_version(const char *version)
+{
+ int i;
+
+ if (version == NULL || *version == '\0')
+ return numbered_existing;
+ i = argmatch(version, backup_args);
+ if (i >= 0)
+ return backup_types[i];
+ invalid_arg("version control type", version, i);
+ exit(2);
+}
diff --git a/usr.bin/patch/backupfile.h b/usr.bin/patch/backupfile.h
new file mode 100644
index 0000000..71999f7
--- /dev/null
+++ b/usr.bin/patch/backupfile.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (C) 1990 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * without restriction.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * backupfile.h -- declarations for making Emacs style backup file names
+ *
+ * $OpenBSD: backupfile.h,v 1.6 2003/07/28 18:35:36 otto Exp $
+ * $FreeBSD$
+ */
+
+/* When to make backup files. */
+enum backup_type {
+ /* Never make backups. */
+ none,
+
+ /* Make simple backups of every file. */
+ simple,
+
+ /*
+ * Make numbered backups of files that already have numbered backups,
+ * and simple backups of the others.
+ */
+ numbered_existing,
+
+ /* Make numbered backups of every file. */
+ numbered
+};
+
+extern enum backup_type backup_type;
+extern const char *simple_backup_suffix;
+
+char *find_backup_file_name(const char *file);
+enum backup_type get_version(const char *version);
diff --git a/usr.bin/patch/common.h b/usr.bin/patch/common.h
new file mode 100644
index 0000000..9425968
--- /dev/null
+++ b/usr.bin/patch/common.h
@@ -0,0 +1,119 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: common.h,v 1.26 2006/03/11 19:41:30 otto Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define DEBUGGING
+
+/* constants */
+
+#define MAXHUNKSIZE 200000 /* is this enough lines? */
+#define INITHUNKMAX 125 /* initial dynamic allocation size */
+#define INITLINELEN 4096
+#define BUFFERSIZE 4096
+
+#define SCCSPREFIX "s."
+#define GET "get -e %s"
+#define SCCSDIFF "get -p %s | diff - %s >/dev/null"
+
+#define RCSSUFFIX ",v"
+#define CHECKOUT "co -l %s"
+#define RCSDIFF "rcsdiff %s > /dev/null"
+
+#define ORIGEXT ".orig"
+#define REJEXT ".rej"
+
+/* handy definitions */
+
+#define strNE(s1,s2) (strcmp(s1, s2))
+#define strEQ(s1,s2) (!strcmp(s1, s2))
+#define strnNE(s1,s2,l) (strncmp(s1, s2, l))
+#define strnEQ(s1,s2,l) (!strncmp(s1, s2, l))
+
+/* typedefs */
+
+typedef long LINENUM; /* must be signed */
+
+/* globals */
+
+extern mode_t filemode;
+
+extern char *buf; /* general purpose buffer */
+extern size_t buf_size; /* size of general purpose buffer */
+
+extern bool using_plan_a; /* try to keep everything in memory */
+extern bool out_of_mem; /* ran out of memory in plan a */
+
+#define MAXFILEC 2
+
+extern char *filearg[MAXFILEC];
+extern bool ok_to_create_file;
+extern char *outname;
+extern char *origprae;
+
+extern char *TMPOUTNAME;
+extern char *TMPINNAME;
+extern char *TMPREJNAME;
+extern char *TMPPATNAME;
+extern bool toutkeep;
+extern bool trejkeep;
+
+#ifdef DEBUGGING
+extern int debug;
+#endif
+
+extern bool force;
+extern bool batch;
+extern bool verbose;
+extern bool reverse;
+extern bool noreverse;
+extern bool skip_rest_of_patch;
+extern int strippath;
+extern bool canonicalize;
+/* TRUE if -C was specified on command line. */
+extern bool check_only;
+extern bool warn_on_invalid_line;
+extern bool last_line_missing_eol;
+
+
+#define CONTEXT_DIFF 1
+#define NORMAL_DIFF 2
+#define ED_DIFF 3
+#define NEW_CONTEXT_DIFF 4
+#define UNI_DIFF 5
+
+extern int diff_type;
+extern char *revision; /* prerequisite revision, if any */
+extern LINENUM input_lines; /* how long is input file in lines */
+
+extern int posix;
+
diff --git a/usr.bin/patch/inp.c b/usr.bin/patch/inp.c
new file mode 100644
index 0000000..54b0bf2
--- /dev/null
+++ b/usr.bin/patch/inp.c
@@ -0,0 +1,484 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: inp.c,v 1.36 2012/04/10 14:46:34 ajacoutot Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <ctype.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "util.h"
+#include "pch.h"
+#include "inp.h"
+
+
+/* Input-file-with-indexable-lines abstract type */
+
+static size_t i_size; /* size of the input file */
+static char *i_womp; /* plan a buffer for entire file */
+static char **i_ptr; /* pointers to lines in i_womp */
+static char empty_line[] = { '\0' };
+
+static int tifd = -1; /* plan b virtual string array */
+static char *tibuf[2]; /* plan b buffers */
+static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
+static LINENUM lines_per_buf; /* how many lines per buffer */
+static int tireclen; /* length of records in tmp file */
+
+static bool rev_in_string(const char *);
+static bool reallocate_lines(size_t *);
+
+/* returns false if insufficient memory */
+static bool plan_a(const char *);
+
+static void plan_b(const char *);
+
+/* New patch--prepare to edit another file. */
+
+void
+re_input(void)
+{
+ if (using_plan_a) {
+ free(i_ptr);
+ i_ptr = NULL;
+ if (i_womp != NULL) {
+ munmap(i_womp, i_size);
+ i_womp = NULL;
+ }
+ i_size = 0;
+ } else {
+ using_plan_a = true; /* maybe the next one is smaller */
+ close(tifd);
+ tifd = -1;
+ free(tibuf[0]);
+ free(tibuf[1]);
+ tibuf[0] = tibuf[1] = NULL;
+ tiline[0] = tiline[1] = -1;
+ tireclen = 0;
+ }
+}
+
+/* Construct the line index, somehow or other. */
+
+void
+scan_input(const char *filename)
+{
+ if (!plan_a(filename))
+ plan_b(filename);
+ if (verbose) {
+ say("Patching file %s using Plan %s...\n", filename,
+ (using_plan_a ? "A" : "B"));
+ }
+}
+
+static bool
+reallocate_lines(size_t *lines_allocated)
+{
+ char **p;
+ size_t new_size;
+
+ new_size = *lines_allocated * 3 / 2;
+ p = realloc(i_ptr, (new_size + 2) * sizeof(char *));
+ if (p == NULL) { /* shucks, it was a near thing */
+ munmap(i_womp, i_size);
+ i_womp = NULL;
+ free(i_ptr);
+ i_ptr = NULL;
+ *lines_allocated = 0;
+ return false;
+ }
+ *lines_allocated = new_size;
+ i_ptr = p;
+ return true;
+}
+
+/* Try keeping everything in memory. */
+
+static bool
+plan_a(const char *filename)
+{
+ int ifd, statfailed;
+ char *p, *s, lbuf[INITLINELEN];
+ struct stat filestat;
+ ptrdiff_t sz;
+ size_t i;
+ size_t iline, lines_allocated;
+
+#ifdef DEBUGGING
+ if (debug & 8)
+ return false;
+#endif
+
+ if (filename == NULL || *filename == '\0')
+ return false;
+
+ statfailed = stat(filename, &filestat);
+ if (statfailed && ok_to_create_file) {
+ if (verbose)
+ say("(Creating file %s...)\n", filename);
+
+ /*
+ * in check_patch case, we still display `Creating file' even
+ * though we're not. The rule is that -C should be as similar
+ * to normal patch behavior as possible
+ */
+ if (check_only)
+ return true;
+ makedirs(filename, true);
+ close(creat(filename, 0666));
+ statfailed = stat(filename, &filestat);
+ }
+ if (statfailed && check_only)
+ fatal("%s not found, -C mode, can't probe further\n", filename);
+ /* For nonexistent or read-only files, look for RCS or SCCS versions. */
+ if (statfailed ||
+ /* No one can write to it. */
+ (filestat.st_mode & 0222) == 0 ||
+ /* I can't write to it. */
+ ((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
+ const char *cs = NULL, *filebase, *filedir;
+ struct stat cstat;
+ char *tmp_filename1, *tmp_filename2;
+
+ tmp_filename1 = strdup(filename);
+ tmp_filename2 = strdup(filename);
+ if (tmp_filename1 == NULL || tmp_filename2 == NULL)
+ fatal("strdupping filename");
+ filebase = basename(tmp_filename1);
+ filedir = dirname(tmp_filename2);
+
+ /* Leave room in lbuf for the diff command. */
+ s = lbuf + 20;
+
+#define try(f, a1, a2, a3) \
+ (snprintf(s, buf_size - 20, f, a1, a2, a3), stat(s, &cstat) == 0)
+
+ if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
+ try("%s/RCS/%s%s", filedir, filebase, "") ||
+ try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
+ snprintf(buf, buf_size, CHECKOUT, filename);
+ snprintf(lbuf, sizeof lbuf, RCSDIFF, filename);
+ cs = "RCS";
+ } else if (try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
+ try("%s/%s%s", filedir, SCCSPREFIX, filebase)) {
+ snprintf(buf, buf_size, GET, s);
+ snprintf(lbuf, sizeof lbuf, SCCSDIFF, s, filename);
+ cs = "SCCS";
+ } else if (statfailed)
+ fatal("can't find %s\n", filename);
+
+ free(tmp_filename1);
+ free(tmp_filename2);
+
+ /*
+ * else we can't write to it but it's not under a version
+ * control system, so just proceed.
+ */
+ if (cs) {
+ if (!statfailed) {
+ if ((filestat.st_mode & 0222) != 0)
+ /* The owner can write to it. */
+ fatal("file %s seems to be locked "
+ "by somebody else under %s\n",
+ filename, cs);
+ /*
+ * It might be checked out unlocked. See if
+ * it's safe to check out the default version
+ * locked.
+ */
+ if (verbose)
+ say("Comparing file %s to default "
+ "%s version...\n",
+ filename, cs);
+ if (system(lbuf))
+ fatal("can't check out file %s: "
+ "differs from default %s version\n",
+ filename, cs);
+ }
+ if (verbose)
+ say("Checking out file %s from %s...\n",
+ filename, cs);
+ if (system(buf) || stat(filename, &filestat))
+ fatal("can't check out file %s from %s\n",
+ filename, cs);
+ }
+ }
+ filemode = filestat.st_mode;
+ if (!S_ISREG(filemode))
+ fatal("%s is not a normal file--can't patch\n", filename);
+ if ((uint64_t)filestat.st_size > SIZE_MAX) {
+ say("block too large to mmap\n");
+ return false;
+ }
+ i_size = (size_t)filestat.st_size;
+ if (out_of_mem) {
+ set_hunkmax(); /* make sure dynamic arrays are allocated */
+ out_of_mem = false;
+ return false; /* force plan b because plan a bombed */
+ }
+ if ((ifd = open(filename, O_RDONLY)) < 0)
+ pfatal("can't open file %s", filename);
+
+ if (i_size) {
+ i_womp = mmap(NULL, i_size, PROT_READ, MAP_PRIVATE, ifd, 0);
+ if (i_womp == MAP_FAILED) {
+ perror("mmap failed");
+ i_womp = NULL;
+ close(ifd);
+ return false;
+ }
+ } else {
+ i_womp = NULL;
+ }
+
+ close(ifd);
+ if (i_size)
+ madvise(i_womp, i_size, MADV_SEQUENTIAL);
+
+ /* estimate the number of lines */
+ lines_allocated = i_size / 25;
+ if (lines_allocated < 100)
+ lines_allocated = 100;
+
+ if (!reallocate_lines(&lines_allocated))
+ return false;
+
+ /* now scan the buffer and build pointer array */
+ iline = 1;
+ i_ptr[iline] = i_womp;
+ /* test for NUL too, to maintain the behavior of the original code */
+ for (s = i_womp, i = 0; i < i_size && *s != '\0'; s++, i++) {
+ if (*s == '\n') {
+ if (iline == lines_allocated) {
+ if (!reallocate_lines(&lines_allocated))
+ return false;
+ }
+ /* these are NOT NUL terminated */
+ i_ptr[++iline] = s + 1;
+ }
+ }
+ /* if the last line contains no EOL, append one */
+ if (i_size > 0 && i_womp[i_size - 1] != '\n') {
+ last_line_missing_eol = true;
+ /* fix last line */
+ sz = s - i_ptr[iline];
+ p = malloc(sz + 1);
+ if (p == NULL) {
+ free(i_ptr);
+ i_ptr = NULL;
+ munmap(i_womp, i_size);
+ i_womp = NULL;
+ return false;
+ }
+
+ memcpy(p, i_ptr[iline], sz);
+ p[sz] = '\n';
+ i_ptr[iline] = p;
+ /* count the extra line and make it point to some valid mem */
+ i_ptr[++iline] = empty_line;
+ } else
+ last_line_missing_eol = false;
+
+ input_lines = iline - 1;
+
+ /* now check for revision, if any */
+
+ if (revision != NULL) {
+ if (!rev_in_string(i_womp)) {
+ if (force) {
+ if (verbose)
+ say("Warning: this file doesn't appear "
+ "to be the %s version--patching anyway.\n",
+ revision);
+ } else if (batch) {
+ fatal("this file doesn't appear to be the "
+ "%s version--aborting.\n",
+ revision);
+ } else {
+ ask("This file doesn't appear to be the "
+ "%s version--patch anyway? [n] ",
+ revision);
+ if (*buf != 'y')
+ fatal("aborted\n");
+ }
+ } else if (verbose)
+ say("Good. This file appears to be the %s version.\n",
+ revision);
+ }
+ return true; /* plan a will work */
+}
+
+/* Keep (virtually) nothing in memory. */
+
+static void
+plan_b(const char *filename)
+{
+ FILE *ifp;
+ size_t i = 0, j, maxlen = 1;
+ char *p;
+ bool found_revision = (revision == NULL);
+
+ using_plan_a = false;
+ if ((ifp = fopen(filename, "r")) == NULL)
+ pfatal("can't open file %s", filename);
+ unlink(TMPINNAME);
+ if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0)
+ pfatal("can't open file %s", TMPINNAME);
+ while (fgets(buf, buf_size, ifp) != NULL) {
+ if (revision != NULL && !found_revision && rev_in_string(buf))
+ found_revision = true;
+ if ((i = strlen(buf)) > maxlen)
+ maxlen = i; /* find longest line */
+ }
+ last_line_missing_eol = i > 0 && buf[i - 1] != '\n';
+ if (last_line_missing_eol && maxlen == i)
+ maxlen++;
+
+ if (revision != NULL) {
+ if (!found_revision) {
+ if (force) {
+ if (verbose)
+ say("Warning: this file doesn't appear "
+ "to be the %s version--patching anyway.\n",
+ revision);
+ } else if (batch) {
+ fatal("this file doesn't appear to be the "
+ "%s version--aborting.\n",
+ revision);
+ } else {
+ ask("This file doesn't appear to be the %s "
+ "version--patch anyway? [n] ",
+ revision);
+ if (*buf != 'y')
+ fatal("aborted\n");
+ }
+ } else if (verbose)
+ say("Good. This file appears to be the %s version.\n",
+ revision);
+ }
+ fseek(ifp, 0L, SEEK_SET); /* rewind file */
+ lines_per_buf = BUFFERSIZE / maxlen;
+ tireclen = maxlen;
+ tibuf[0] = malloc(BUFFERSIZE + 1);
+ if (tibuf[0] == NULL)
+ fatal("out of memory\n");
+ tibuf[1] = malloc(BUFFERSIZE + 1);
+ if (tibuf[1] == NULL)
+ fatal("out of memory\n");
+ for (i = 1;; i++) {
+ p = tibuf[0] + maxlen * (i % lines_per_buf);
+ if (i % lines_per_buf == 0) /* new block */
+ if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
+ pfatal("can't write temp file");
+ if (fgets(p, maxlen + 1, ifp) == NULL) {
+ input_lines = i - 1;
+ if (i % lines_per_buf != 0)
+ if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
+ pfatal("can't write temp file");
+ break;
+ }
+ j = strlen(p);
+ /* These are '\n' terminated strings, so no need to add a NUL */
+ if (j == 0 || p[j - 1] != '\n')
+ p[j] = '\n';
+ }
+ fclose(ifp);
+ close(tifd);
+ if ((tifd = open(TMPINNAME, O_RDONLY)) < 0)
+ pfatal("can't reopen file %s", TMPINNAME);
+}
+
+/*
+ * Fetch a line from the input file, \n terminated, not necessarily \0.
+ */
+char *
+ifetch(LINENUM line, int whichbuf)
+{
+ if (line < 1 || line > input_lines) {
+ if (warn_on_invalid_line) {
+ say("No such line %ld in input file, ignoring\n", line);
+ warn_on_invalid_line = false;
+ }
+ return NULL;
+ }
+ if (using_plan_a)
+ return i_ptr[line];
+ else {
+ LINENUM offline = line % lines_per_buf;
+ LINENUM baseline = line - offline;
+
+ if (tiline[0] == baseline)
+ whichbuf = 0;
+ else if (tiline[1] == baseline)
+ whichbuf = 1;
+ else {
+ tiline[whichbuf] = baseline;
+
+ if (lseek(tifd, (off_t) (baseline / lines_per_buf *
+ BUFFERSIZE), SEEK_SET) < 0)
+ pfatal("cannot seek in the temporary input file");
+
+ if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
+ pfatal("error reading tmp file %s", TMPINNAME);
+ }
+ return tibuf[whichbuf] + (tireclen * offline);
+ }
+}
+
+/*
+ * True if the string argument contains the revision number we want.
+ */
+static bool
+rev_in_string(const char *string)
+{
+ const char *s;
+ size_t patlen;
+
+ if (revision == NULL)
+ return true;
+ patlen = strlen(revision);
+ if (strnEQ(string, revision, patlen) && isspace((unsigned char)string[patlen]))
+ return true;
+ for (s = string; *s; s++) {
+ if (isspace((unsigned char)*s) && strnEQ(s + 1, revision, patlen) &&
+ isspace((unsigned char)s[patlen + 1])) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/usr.bin/patch/inp.h b/usr.bin/patch/inp.h
new file mode 100644
index 0000000..062798a
--- /dev/null
+++ b/usr.bin/patch/inp.h
@@ -0,0 +1,32 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: inp.h,v 1.8 2003/08/15 08:00:51 otto Exp $
+ * $FreeBSD$
+ */
+
+void re_input(void);
+void scan_input(const char *);
+char *ifetch(LINENUM, int);
diff --git a/usr.bin/patch/mkpath.c b/usr.bin/patch/mkpath.c
new file mode 100644
index 0000000..04fd537
--- /dev/null
+++ b/usr.bin/patch/mkpath.c
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $OpenBSD: mkpath.c,v 1.2 2005/06/20 07:14:06 otto Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+
+int mkpath(char *);
+
+/* Code taken directly from mkdir(1).
+
+ * mkpath -- create directories.
+ * path - path
+ */
+int
+mkpath(char *path)
+{
+ struct stat sb;
+ char *slash;
+ int done = 0;
+
+ slash = path;
+
+ while (!done) {
+ slash += strspn(slash, "/");
+ slash += strcspn(slash, "/");
+
+ done = (*slash == '\0');
+ *slash = '\0';
+
+ if (stat(path, &sb)) {
+ if (errno != ENOENT || (mkdir(path, 0777) &&
+ errno != EEXIST)) {
+ warn("%s", path);
+ return (-1);
+ }
+ } else if (!S_ISDIR(sb.st_mode)) {
+ warnx("%s: %s", path, strerror(ENOTDIR));
+ return (-1);
+ }
+
+ *slash = '/';
+ }
+
+ return (0);
+}
+
diff --git a/usr.bin/patch/patch.1 b/usr.bin/patch/patch.1
new file mode 100644
index 0000000..312b8a2
--- /dev/null
+++ b/usr.bin/patch/patch.1
@@ -0,0 +1,700 @@
+.\"-
+.\" Copyright 1986, Larry Wall
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following condition
+.\" is met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this condition and the following disclaimer.
+.\"
+.\" 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.
+.\"
+.\" $OpenBSD: patch.1,v 1.26 2010/09/03 11:09:29 jmc Exp $
+.\" $FreeBSD$
+.Dd January 29, 2013
+.Dt PATCH 1
+.Os
+.Sh NAME
+.Nm patch
+.Nd apply a diff file to an original
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl bCcEeflNnRstuv
+.Op Fl B Ar backup-prefix
+.Op Fl D Ar symbol
+.Op Fl d Ar directory
+.Op Fl F Ar max-fuzz
+.Op Fl i Ar patchfile
+.Op Fl o Ar out-file
+.Op Fl p Ar strip-count
+.Op Fl r Ar rej-name
+.Op Fl V Cm t | nil | never
+.Op Fl x Ar number
+.Op Fl z Ar backup-ext
+.Op Fl Fl posix
+.Op Ar origfile Op Ar patchfile
+.Ek
+.Nm
+.Pf \*(Lt Ar patchfile
+.Sh DESCRIPTION
+.Nm
+will take a patch file containing any of the four forms of difference
+listing produced by the
+.Xr diff 1
+program and apply those differences to an original file,
+producing a patched version.
+If
+.Ar patchfile
+is omitted, or is a hyphen, the patch will be read from the standard input.
+.Pp
+.Nm
+will attempt to determine the type of the diff listing, unless overruled by a
+.Fl c ,
+.Fl e ,
+.Fl n ,
+or
+.Fl u
+option.
+Context diffs (old-style, new-style, and unified) and
+normal diffs are applied directly by the
+.Nm
+program itself, whereas ed diffs are simply fed to the
+.Xr ed 1
+editor via a pipe.
+.Pp
+If the
+.Ar patchfile
+contains more than one patch,
+.Nm
+will try to apply each of them as if they came from separate patch files.
+This means, among other things, that it is assumed that the name of the file
+to patch must be determined for each diff listing, and that the garbage before
+each diff listing will be examined for interesting things such as file names
+and revision level (see the section on
+.Sx Filename Determination
+below).
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Xo
+.Fl B Ar backup-prefix ,
+.Fl Fl prefix Ar backup-prefix
+.Xc
+Causes the next argument to be interpreted as a prefix to the backup file
+name.
+If this argument is specified, any argument to
+.Fl z
+will be ignored.
+.It Fl b , Fl Fl backup
+Save a backup copy of the file before it is modified.
+By default the original file is saved with a backup extension of
+.Qq .orig
+unless the file already has a numbered backup, in which case a numbered
+backup is made.
+This is equivalent to specifying
+.Qo Fl V Cm existing Qc .
+This option is currently the default, unless
+.Fl -posix
+is specified.
+.It Fl C , Fl Fl check
+Checks that the patch would apply cleanly, but does not modify anything.
+.It Fl c , Fl Fl context
+Forces
+.Nm
+to interpret the patch file as a context diff.
+.It Xo
+.Fl D Ar symbol ,
+.Fl Fl ifdef Ar symbol
+.Xc
+Causes
+.Nm
+to use the
+.Qq #ifdef...#endif
+construct to mark changes.
+The argument following will be used as the differentiating symbol.
+Note that, unlike the C compiler, there must be a space between the
+.Fl D
+and the argument.
+.It Xo
+.Fl d Ar directory ,
+.Fl Fl directory Ar directory
+.Xc
+Causes
+.Nm
+to interpret the next argument as a directory,
+and change the working directory to it before doing anything else.
+.It Fl E , Fl Fl remove-empty-files
+Causes
+.Nm
+to remove output files that are empty after the patches have been applied.
+This option is useful when applying patches that create or remove files.
+.It Fl e , Fl Fl ed
+Forces
+.Nm
+to interpret the patch file as an
+.Xr ed 1
+script.
+.It Xo
+.Fl F Ar max-fuzz ,
+.Fl Fl fuzz Ar max-fuzz
+.Xc
+Sets the maximum fuzz factor.
+This option only applies to context diffs, and causes
+.Nm
+to ignore up to that many lines in looking for places to install a hunk.
+Note that a larger fuzz factor increases the odds of a faulty patch.
+The default fuzz factor is 2, and it may not be set to more than
+the number of lines of context in the context diff, ordinarily 3.
+.It Fl f , Fl Fl force
+Forces
+.Nm
+to assume that the user knows exactly what he or she is doing, and to not
+ask any questions.
+It assumes the following:
+skip patches for which a file to patch can't be found;
+patch files even though they have the wrong version for the
+.Qq Prereq:
+line in the patch;
+and assume that patches are not reversed even if they look like they are.
+This option does not suppress commentary; use
+.Fl s
+for that.
+.It Xo
+.Fl i Ar patchfile ,
+.Fl Fl input Ar patchfile
+.Xc
+Causes the next argument to be interpreted as the input file name
+(i.e. a patchfile).
+This option may be specified multiple times.
+.It Fl l , Fl Fl ignore-whitespace
+Causes the pattern matching to be done loosely, in case the tabs and
+spaces have been munged in your input file.
+Any sequence of whitespace in the pattern line will match any sequence
+in the input file.
+Normal characters must still match exactly.
+Each line of the context must still match a line in the input file.
+.It Fl N , Fl Fl forward
+Causes
+.Nm
+to ignore patches that it thinks are reversed or already applied.
+See also
+.Fl R .
+.It Fl n , Fl Fl normal
+Forces
+.Nm
+to interpret the patch file as a normal diff.
+.It Xo
+.Fl o Ar out-file ,
+.Fl Fl output Ar out-file
+.Xc
+Causes the next argument to be interpreted as the output file name.
+.It Xo
+.Fl p Ar strip-count ,
+.Fl Fl strip Ar strip-count
+.Xc
+Sets the pathname strip count,
+which controls how pathnames found in the patch file are treated,
+in case you keep your files in a different directory than the person who sent
+out the patch.
+The strip count specifies how many slashes are to be stripped from
+the front of the pathname.
+(Any intervening directory names also go away.)
+For example, supposing the file name in the patch file was
+.Pa /u/howard/src/blurfl/blurfl.c :
+.Pp
+Setting
+.Fl p Ns Ar 0
+gives the entire pathname unmodified.
+.Pp
+.Fl p Ns Ar 1
+gives
+.Pp
+.D1 Pa u/howard/src/blurfl/blurfl.c
+.Pp
+without the leading slash.
+.Pp
+.Fl p Ns Ar 4
+gives
+.Pp
+.D1 Pa blurfl/blurfl.c
+.Pp
+Not specifying
+.Fl p
+at all just gives you
+.Pa blurfl.c ,
+unless all of the directories in the leading path
+.Pq Pa u/howard/src/blurfl
+exist and that path is relative,
+in which case you get the entire pathname unmodified.
+Whatever you end up with is looked for either in the current directory,
+or the directory specified by the
+.Fl d
+option.
+.It Fl R , Fl Fl reverse
+Tells
+.Nm
+that this patch was created with the old and new files swapped.
+(Yes, I'm afraid that does happen occasionally, human nature being what it
+is.)
+.Nm
+will attempt to swap each hunk around before applying it.
+Rejects will come out in the swapped format.
+The
+.Fl R
+option will not work with ed diff scripts because there is too little
+information to reconstruct the reverse operation.
+.Pp
+If the first hunk of a patch fails,
+.Nm
+will reverse the hunk to see if it can be applied that way.
+If it can, you will be asked if you want to have the
+.Fl R
+option set.
+If it can't, the patch will continue to be applied normally.
+(Note: this method cannot detect a reversed patch if it is a normal diff
+and if the first command is an append (i.e. it should have been a delete)
+since appends always succeed, due to the fact that a null context will match
+anywhere.
+Luckily, most patches add or change lines rather than delete them, so most
+reversed normal diffs will begin with a delete, which will fail, triggering
+the heuristic.)
+.It Xo
+.Fl r Ar rej-name ,
+.Fl Fl reject-file Ar rej-name
+.Xc
+Causes the next argument to be interpreted as the reject file name.
+.It Xo
+.Fl s , Fl Fl quiet ,
+.Fl Fl silent
+.Xc
+Makes
+.Nm
+do its work silently, unless an error occurs.
+.It Fl t , Fl Fl batch
+Similar to
+.Fl f ,
+in that it suppresses questions, but makes some different assumptions:
+skip patches for which a file to patch can't be found (the same as
+.Fl f ) ;
+skip patches for which the file has the wrong version for the
+.Qq Prereq:
+line in the patch;
+and assume that patches are reversed if they look like they are.
+.It Fl u , Fl Fl unified
+Forces
+.Nm
+to interpret the patch file as a unified context diff (a unidiff).
+.It Xo
+.Fl V Cm t | nil | never ,
+.Fl Fl version-control Cm t | nil | never
+.Xc
+Causes the next argument to be interpreted as a method for creating
+backup file names.
+The type of backups made can also be given in the
+.Ev PATCH_VERSION_CONTROL
+or
+.Ev VERSION_CONTROL
+environment variables, which are overridden by this option.
+The
+.Fl B
+option overrides this option, causing the prefix to always be used for
+making backup file names.
+The values of the
+.Ev PATCH_VERSION_CONTROL
+and
+.Ev VERSION_CONTROL
+environment variables and the argument to the
+.Fl V
+option are like the GNU Emacs
+.Dq version-control
+variable; they also recognize synonyms that are more descriptive.
+The valid values are (unique abbreviations are accepted):
+.Bl -tag -width Ds -offset indent
+.It Cm t , numbered
+Always make numbered backups.
+.It Cm nil , existing
+Make numbered backups of files that already have them,
+simple backups of the others.
+.It Cm never , simple
+Always make simple backups.
+.El
+.It Fl v , Fl Fl version
+Causes
+.Nm
+to print out its revision header and patch level.
+.It Xo
+.Fl x Ar number ,
+.Fl Fl debug Ar number
+.Xc
+Sets internal debugging flags, and is of interest only to
+.Nm
+patchers.
+.It Xo
+.Fl z Ar backup-ext ,
+.Fl Fl suffix Ar backup-ext
+.Xc
+Causes the next argument to be interpreted as the backup extension, to be
+used in place of
+.Qq .orig .
+.It Fl Fl posix
+Enables strict
+.St -p1003.1-2008
+conformance, specifically:
+.Bl -enum
+.It
+Backup files are not created unless the
+.Fl b
+option is specified.
+.It
+If unspecified, the file name used is the first of the old, new and
+index files that exists.
+.El
+.El
+.Ss Patch Application
+.Nm
+will try to skip any leading garbage, apply the diff,
+and then skip any trailing garbage.
+Thus you could feed an article or message containing a
+diff listing to
+.Nm ,
+and it should work.
+If the entire diff is indented by a consistent amount,
+this will be taken into account.
+.Pp
+With context diffs, and to a lesser extent with normal diffs,
+.Nm
+can detect when the line numbers mentioned in the patch are incorrect,
+and will attempt to find the correct place to apply each hunk of the patch.
+As a first guess, it takes the line number mentioned for the hunk, plus or
+minus any offset used in applying the previous hunk.
+If that is not the correct place,
+.Nm
+will scan both forwards and backwards for a set of lines matching the context
+given in the hunk.
+First
+.Nm
+looks for a place where all lines of the context match.
+If no such place is found, and it's a context diff, and the maximum fuzz factor
+is set to 1 or more, then another scan takes place ignoring the first and last
+line of context.
+If that fails, and the maximum fuzz factor is set to 2 or more,
+the first two and last two lines of context are ignored,
+and another scan is made.
+.Pq The default maximum fuzz factor is 2.
+.Pp
+If
+.Nm
+cannot find a place to install that hunk of the patch, it will put the hunk
+out to a reject file, which normally is the name of the output file plus
+.Qq .rej .
+(Note that the rejected hunk will come out in context diff form whether the
+input patch was a context diff or a normal diff.
+If the input was a normal diff, many of the contexts will simply be null.)
+The line numbers on the hunks in the reject file may be different than
+in the patch file: they reflect the approximate location patch thinks the
+failed hunks belong in the new file rather than the old one.
+.Pp
+As each hunk is completed, you will be told whether the hunk succeeded or
+failed, and which line (in the new file)
+.Nm
+thought the hunk should go on.
+If this is different from the line number specified in the diff,
+you will be told the offset.
+A single large offset MAY be an indication that a hunk was installed in the
+wrong place.
+You will also be told if a fuzz factor was used to make the match, in which
+case you should also be slightly suspicious.
+.Ss Filename Determination
+If no original file is specified on the command line,
+.Nm
+will try to figure out from the leading garbage what the name of the file
+to edit is.
+When checking a prospective file name, pathname components are stripped
+as specified by the
+.Fl p
+option and the file's existence and writability are checked relative
+to the current working directory (or the directory specified by the
+.Fl d
+option).
+.Pp
+If the diff is a context or unified diff,
+.Nm
+is able to determine the old and new file names from the diff header.
+For context diffs, the
+.Dq old
+file is specified in the line beginning with
+.Qq ***
+and the
+.Dq new
+file is specified in the line beginning with
+.Qq --- .
+For a unified diff, the
+.Dq old
+file is specified in the line beginning with
+.Qq ---
+and the
+.Dq new
+file is specified in the line beginning with
+.Qq +++ .
+If there is an
+.Qq Index:
+line in the leading garbage (regardless of the diff type),
+.Nm
+will use the file name from that line as the
+.Dq index
+file.
+.Pp
+.Nm
+will choose the file name by performing the following steps, with the first
+match used:
+.Bl -enum
+.It
+If
+.Nm
+is operating in strict
+.St -p1003.1-2008
+mode, the first of the
+.Dq old ,
+.Dq new
+and
+.Dq index
+file names that exist is used.
+Otherwise,
+.Nm
+will examine either the
+.Dq old
+and
+.Dq new
+file names or, for a non-context diff, the
+.Dq index
+file name, and choose the file name with the fewest path components,
+the shortest basename, and the shortest total file name length (in that order).
+.It
+If no file exists,
+.Nm
+checks for the existence of the files in an SCCS or RCS directory
+(using the appropriate prefix or suffix) using the criteria specified
+above.
+If found,
+.Nm
+will attempt to get or check out the file.
+.It
+If no suitable file was found to patch, the patch file is a context or
+unified diff, and the old file was zero length, the new file name is
+created and used.
+.It
+If the file name still cannot be determined,
+.Nm
+will prompt the user for the file name to use.
+.El
+.Pp
+Additionally, if the leading garbage contains a
+.Qq Prereq:\ \&
+line,
+.Nm
+will take the first word from the prerequisites line (normally a version
+number) and check the input file to see if that word can be found.
+If not,
+.Nm
+will ask for confirmation before proceeding.
+.Pp
+The upshot of all this is that you should be able to say, while in a news
+interface, the following:
+.Pp
+.Dl | patch -d /usr/src/local/blurfl
+.Pp
+and patch a file in the blurfl directory directly from the article containing
+the patch.
+.Ss Backup Files
+By default, the patched version is put in place of the original, with
+the original file backed up to the same name with the extension
+.Qq .orig ,
+or as specified by the
+.Fl B ,
+.Fl V ,
+or
+.Fl z
+options.
+The extension used for making backup files may also be specified in the
+.Ev SIMPLE_BACKUP_SUFFIX
+environment variable, which is overridden by the options above.
+.Pp
+If the backup file is a symbolic or hard link to the original file,
+.Nm
+creates a new backup file name by changing the first lowercase letter
+in the last component of the file's name into uppercase.
+If there are no more lowercase letters in the name,
+it removes the first character from the name.
+It repeats this process until it comes up with a
+backup file that does not already exist or is not linked to the original file.
+.Pp
+You may also specify where you want the output to go with the
+.Fl o
+option; if that file already exists, it is backed up first.
+.Ss Notes For Patch Senders
+There are several things you should bear in mind if you are going to
+be sending out patches:
+.Pp
+First, you can save people a lot of grief by keeping a
+.Pa patchlevel.h
+file which is patched to increment the patch level as the first diff in the
+patch file you send out.
+If you put a
+.Qq Prereq:
+line in with the patch, it won't let them apply
+patches out of order without some warning.
+.Pp
+Second, make sure you've specified the file names right, either in a
+context diff header, or with an
+.Qq Index:
+line.
+If you are patching something in a subdirectory, be sure to tell the patch
+user to specify a
+.Fl p
+option as needed.
+.Pp
+Third, you can create a file by sending out a diff that compares a
+null file to the file you want to create.
+This will only work if the file you want to create doesn't exist already in
+the target directory.
+.Pp
+Fourth, take care not to send out reversed patches, since it makes people wonder
+whether they already applied the patch.
+.Pp
+Fifth, while you may be able to get away with putting 582 diff listings into
+one file, it is probably wiser to group related patches into separate files in
+case something goes haywire.
+.Sh ENVIRONMENT
+.Bl -tag -width "PATCH_VERSION_CONTROL" -compact
+.It Ev POSIXLY_CORRECT
+When set,
+.Nm
+behaves as if the
+.Fl Fl posix
+option has been specified.
+.It Ev SIMPLE_BACKUP_SUFFIX
+Extension to use for backup file names instead of
+.Qq .orig .
+.It Ev TMPDIR
+Directory to put temporary files in; default is
+.Pa /tmp .
+.It Ev PATCH_VERSION_CONTROL
+Selects when numbered backup files are made.
+.It Ev VERSION_CONTROL
+Same as
+.Ev PATCH_VERSION_CONTROL .
+.El
+.Sh FILES
+.Bl -tag -width "$TMPDIR/patch*" -compact
+.It Pa $TMPDIR/patch*
+.Nm
+temporary files
+.It Pa /dev/tty
+used to read input when
+.Nm
+prompts the user
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It 0
+Successful completion.
+.It 1
+One or more lines were written to a reject file.
+.It \*(Gt1
+An error occurred.
+.El
+.Pp
+When applying a set of patches in a loop it behooves you to check this
+exit status so you don't apply a later patch to a partially patched file.
+.Sh DIAGNOSTICS
+Too many to list here, but generally indicative that
+.Nm
+couldn't parse your patch file.
+.Pp
+The message
+.Qq Hmm...
+indicates that there is unprocessed text in the patch file and that
+.Nm
+is attempting to intuit whether there is a patch in that text and, if so,
+what kind of patch it is.
+.Sh SEE ALSO
+.Xr diff 1
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification
+(except as detailed above for the
+.Fl -posix
+option),
+though the presence of
+.Nm
+itself is optional.
+.Pp
+The flags
+.Op Fl BCEFfstVvxz
+and
+.Op Fl -posix
+are extensions to that specification.
+.Sh AUTHORS
+.An Larry Wall
+with many other contributors.
+.Sh CAVEATS
+.Nm
+cannot tell if the line numbers are off in an ed script, and can only detect
+bad line numbers in a normal diff when it finds a
+.Qq change
+or a
+.Qq delete
+command.
+A context diff using fuzz factor 3 may have the same problem.
+Until a suitable interactive interface is added, you should probably do
+a context diff in these cases to see if the changes made sense.
+Of course, compiling without errors is a pretty good indication that the patch
+worked, but not always.
+.Pp
+.Nm
+usually produces the correct results, even when it has to do a lot of
+guessing.
+However, the results are guaranteed to be correct only when the patch is
+applied to exactly the same version of the file that the patch was
+generated from.
+.Sh BUGS
+Could be smarter about partial matches, excessively deviant offsets and
+swapped code, but that would take an extra pass.
+.Pp
+Check patch mode
+.Pq Fl C
+will fail if you try to check several patches in succession that build on
+each other.
+The entire
+.Nm
+code would have to be restructured to keep temporary files around so that it
+can handle this situation.
+.Pp
+If code has been duplicated (for instance with #ifdef OLDCODE ... #else ...
+#endif),
+.Nm
+is incapable of patching both versions, and, if it works at all, will likely
+patch the wrong one, and tell you that it succeeded to boot.
+.Pp
+If you apply a patch you've already applied,
+.Nm
+will think it is a reversed patch, and offer to un-apply the patch.
+This could be construed as a feature.
diff --git a/usr.bin/patch/patch.c b/usr.bin/patch/patch.c
new file mode 100644
index 0000000..d008c0f
--- /dev/null
+++ b/usr.bin/patch/patch.c
@@ -0,0 +1,1069 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: patch.c,v 1.50 2012/05/15 19:32:02 millert Exp $
+ * $FreeBSD$
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "util.h"
+#include "pch.h"
+#include "inp.h"
+#include "backupfile.h"
+#include "pathnames.h"
+
+mode_t filemode = 0644;
+
+char *buf; /* general purpose buffer */
+size_t buf_size; /* size of the general purpose buffer */
+
+bool using_plan_a = true; /* try to keep everything in memory */
+bool out_of_mem = false; /* ran out of memory in plan a */
+
+#define MAXFILEC 2
+
+char *filearg[MAXFILEC];
+bool ok_to_create_file = false;
+char *outname = NULL;
+char *origprae = NULL;
+char *TMPOUTNAME;
+char *TMPINNAME;
+char *TMPREJNAME;
+char *TMPPATNAME;
+bool toutkeep = false;
+bool trejkeep = false;
+bool warn_on_invalid_line;
+bool last_line_missing_eol;
+
+#ifdef DEBUGGING
+int debug = 0;
+#endif
+
+bool force = false;
+bool batch = false;
+bool verbose = true;
+bool reverse = false;
+bool noreverse = false;
+bool skip_rest_of_patch = false;
+int strippath = 957;
+bool canonicalize = false;
+bool check_only = false;
+int diff_type = 0;
+char *revision = NULL; /* prerequisite revision, if any */
+LINENUM input_lines = 0; /* how long is input file in lines */
+int posix = 0; /* strict POSIX mode? */
+
+static void reinitialize_almost_everything(void);
+static void get_some_switches(void);
+static LINENUM locate_hunk(LINENUM);
+static void abort_context_hunk(void);
+static void rej_line(int, LINENUM);
+static void abort_hunk(void);
+static void apply_hunk(LINENUM);
+static void init_output(const char *);
+static void init_reject(const char *);
+static void copy_till(LINENUM, bool);
+static bool spew_output(void);
+static void dump_line(LINENUM, bool);
+static bool patch_match(LINENUM, LINENUM, LINENUM);
+static bool similar(const char *, const char *, int);
+static void usage(void);
+
+/* true if -E was specified on command line. */
+static bool remove_empty_files = false;
+
+/* true if -R was specified on command line. */
+static bool reverse_flag_specified = false;
+
+/* buffer holding the name of the rejected patch file. */
+static char rejname[NAME_MAX + 1];
+
+/* how many input lines have been irretractibly output */
+static LINENUM last_frozen_line = 0;
+
+static int Argc; /* guess */
+static char **Argv;
+static int Argc_last; /* for restarting plan_b */
+static char **Argv_last;
+
+static FILE *ofp = NULL; /* output file pointer */
+static FILE *rejfp = NULL; /* reject file pointer */
+
+static int filec = 0; /* how many file arguments? */
+static LINENUM last_offset = 0;
+static LINENUM maxfuzz = 2;
+
+/* patch using ifdef, ifndef, etc. */
+static bool do_defines = false;
+/* #ifdef xyzzy */
+static char if_defined[128];
+/* #ifndef xyzzy */
+static char not_defined[128];
+/* #else */
+static const char else_defined[] = "#else\n";
+/* #endif xyzzy */
+static char end_defined[128];
+
+
+/* Apply a set of diffs as appropriate. */
+
+int
+main(int argc, char *argv[])
+{
+ int error = 0, hunk, failed, i, fd;
+ bool patch_seen;
+ LINENUM where = 0, newwhere, fuzz, mymaxfuzz;
+ const char *tmpdir;
+ char *v;
+
+ setlinebuf(stdout);
+ setlinebuf(stderr);
+ for (i = 0; i < MAXFILEC; i++)
+ filearg[i] = NULL;
+
+ buf_size = INITLINELEN;
+ buf = malloc((unsigned)(buf_size));
+ if (buf == NULL)
+ fatal("out of memory\n");
+
+ /* Cons up the names of the temporary files. */
+ if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
+ tmpdir = _PATH_TMP;
+ for (i = strlen(tmpdir) - 1; i > 0 && tmpdir[i] == '/'; i--)
+ ;
+ i++;
+ if (asprintf(&TMPOUTNAME, "%.*s/patchoXXXXXXXXXX", i, tmpdir) == -1)
+ fatal("cannot allocate memory");
+ if ((fd = mkstemp(TMPOUTNAME)) < 0)
+ pfatal("can't create %s", TMPOUTNAME);
+ close(fd);
+
+ if (asprintf(&TMPINNAME, "%.*s/patchiXXXXXXXXXX", i, tmpdir) == -1)
+ fatal("cannot allocate memory");
+ if ((fd = mkstemp(TMPINNAME)) < 0)
+ pfatal("can't create %s", TMPINNAME);
+ close(fd);
+
+ if (asprintf(&TMPREJNAME, "%.*s/patchrXXXXXXXXXX", i, tmpdir) == -1)
+ fatal("cannot allocate memory");
+ if ((fd = mkstemp(TMPREJNAME)) < 0)
+ pfatal("can't create %s", TMPREJNAME);
+ close(fd);
+
+ if (asprintf(&TMPPATNAME, "%.*s/patchpXXXXXXXXXX", i, tmpdir) == -1)
+ fatal("cannot allocate memory");
+ if ((fd = mkstemp(TMPPATNAME)) < 0)
+ pfatal("can't create %s", TMPPATNAME);
+ close(fd);
+
+ v = getenv("SIMPLE_BACKUP_SUFFIX");
+ if (v)
+ simple_backup_suffix = v;
+ else
+ simple_backup_suffix = ORIGEXT;
+
+ /* parse switches */
+ Argc = argc;
+ Argv = argv;
+ get_some_switches();
+
+ if (backup_type == none) {
+ if ((v = getenv("PATCH_VERSION_CONTROL")) == NULL)
+ v = getenv("VERSION_CONTROL");
+ if (v != NULL || !posix)
+ backup_type = get_version(v); /* OK to pass NULL. */
+ }
+
+ /* make sure we clean up /tmp in case of disaster */
+ set_signals(0);
+
+ patch_seen = false;
+ for (open_patch_file(filearg[1]); there_is_another_patch();
+ reinitialize_almost_everything()) {
+ /* for each patch in patch file */
+
+ patch_seen = true;
+
+ warn_on_invalid_line = true;
+
+ if (outname == NULL)
+ outname = savestr(filearg[0]);
+
+ /* for ed script just up and do it and exit */
+ if (diff_type == ED_DIFF) {
+ do_ed_script();
+ continue;
+ }
+ /* initialize the patched file */
+ if (!skip_rest_of_patch)
+ init_output(TMPOUTNAME);
+
+ /* initialize reject file */
+ init_reject(TMPREJNAME);
+
+ /* find out where all the lines are */
+ if (!skip_rest_of_patch)
+ scan_input(filearg[0]);
+
+ /* from here on, open no standard i/o files, because malloc */
+ /* might misfire and we can't catch it easily */
+
+ /* apply each hunk of patch */
+ hunk = 0;
+ failed = 0;
+ out_of_mem = false;
+ while (another_hunk()) {
+ hunk++;
+ fuzz = 0;
+ mymaxfuzz = pch_context();
+ if (maxfuzz < mymaxfuzz)
+ mymaxfuzz = maxfuzz;
+ if (!skip_rest_of_patch) {
+ do {
+ where = locate_hunk(fuzz);
+ if (hunk == 1 && where == 0 && !force) {
+ /* dwim for reversed patch? */
+ if (!pch_swap()) {
+ if (fuzz == 0)
+ say("Not enough memory to try swapped hunk! Assuming unswapped.\n");
+ continue;
+ }
+ reverse = !reverse;
+ /* try again */
+ where = locate_hunk(fuzz);
+ if (where == 0) {
+ /* didn't find it swapped */
+ if (!pch_swap())
+ /* put it back to normal */
+ fatal("lost hunk on alloc error!\n");
+ reverse = !reverse;
+ } else if (noreverse) {
+ if (!pch_swap())
+ /* put it back to normal */
+ fatal("lost hunk on alloc error!\n");
+ reverse = !reverse;
+ say("Ignoring previously applied (or reversed) patch.\n");
+ skip_rest_of_patch = true;
+ } else if (batch) {
+ if (verbose)
+ say("%seversed (or previously applied) patch detected! %s -R.",
+ reverse ? "R" : "Unr",
+ reverse ? "Assuming" : "Ignoring");
+ } else {
+ ask("%seversed (or previously applied) patch detected! %s -R? [y] ",
+ reverse ? "R" : "Unr",
+ reverse ? "Assume" : "Ignore");
+ if (*buf == 'n') {
+ ask("Apply anyway? [n] ");
+ if (*buf != 'y')
+ skip_rest_of_patch = true;
+ where = 0;
+ reverse = !reverse;
+ if (!pch_swap())
+ /* put it back to normal */
+ fatal("lost hunk on alloc error!\n");
+ }
+ }
+ }
+ } while (!skip_rest_of_patch && where == 0 &&
+ ++fuzz <= mymaxfuzz);
+
+ if (skip_rest_of_patch) { /* just got decided */
+ if (ferror(ofp) || fclose(ofp)) {
+ say("Error writing %s\n",
+ TMPOUTNAME);
+ error = 1;
+ }
+ ofp = NULL;
+ }
+ }
+ newwhere = pch_newfirst() + last_offset;
+ if (skip_rest_of_patch) {
+ abort_hunk();
+ failed++;
+ if (verbose)
+ say("Hunk #%d ignored at %ld.\n",
+ hunk, newwhere);
+ } else if (where == 0) {
+ abort_hunk();
+ failed++;
+ if (verbose)
+ say("Hunk #%d failed at %ld.\n",
+ hunk, newwhere);
+ } else {
+ apply_hunk(where);
+ if (verbose) {
+ say("Hunk #%d succeeded at %ld",
+ hunk, newwhere);
+ if (fuzz != 0)
+ say(" with fuzz %ld", fuzz);
+ if (last_offset)
+ say(" (offset %ld line%s)",
+ last_offset,
+ last_offset == 1L ? "" : "s");
+ say(".\n");
+ }
+ }
+ }
+
+ if (out_of_mem && using_plan_a) {
+ Argc = Argc_last;
+ Argv = Argv_last;
+ say("\n\nRan out of memory using Plan A--trying again...\n\n");
+ if (ofp)
+ fclose(ofp);
+ ofp = NULL;
+ if (rejfp)
+ fclose(rejfp);
+ rejfp = NULL;
+ continue;
+ }
+ if (hunk == 0)
+ fatal("Internal error: hunk should not be 0\n");
+
+ /* finish spewing out the new file */
+ if (!skip_rest_of_patch && !spew_output()) {
+ say("Can't write %s\n", TMPOUTNAME);
+ error = 1;
+ }
+
+ /* and put the output where desired */
+ ignore_signals();
+ if (!skip_rest_of_patch) {
+ struct stat statbuf;
+ char *realout = outname;
+
+ if (!check_only) {
+ if (move_file(TMPOUTNAME, outname) < 0) {
+ toutkeep = true;
+ realout = TMPOUTNAME;
+ chmod(TMPOUTNAME, filemode);
+ } else
+ chmod(outname, filemode);
+
+ if (remove_empty_files &&
+ stat(realout, &statbuf) == 0 &&
+ statbuf.st_size == 0) {
+ if (verbose)
+ say("Removing %s (empty after patching).\n",
+ realout);
+ unlink(realout);
+ }
+ }
+ }
+ if (ferror(rejfp) || fclose(rejfp)) {
+ say("Error writing %s\n", rejname);
+ error = 1;
+ }
+ rejfp = NULL;
+ if (failed) {
+ error = 1;
+ if (*rejname == '\0') {
+ if (strlcpy(rejname, outname,
+ sizeof(rejname)) >= sizeof(rejname))
+ fatal("filename %s is too long\n", outname);
+ if (strlcat(rejname, REJEXT,
+ sizeof(rejname)) >= sizeof(rejname))
+ fatal("filename %s is too long\n", outname);
+ }
+ if (!check_only)
+ say("%d out of %d hunks %s--saving rejects to %s\n",
+ failed, hunk, skip_rest_of_patch ? "ignored" : "failed", rejname);
+ else
+ say("%d out of %d hunks %s\n",
+ failed, hunk, skip_rest_of_patch ? "ignored" : "failed");
+ if (!check_only && move_file(TMPREJNAME, rejname) < 0)
+ trejkeep = true;
+ }
+ set_signals(1);
+ }
+
+ if (!patch_seen)
+ error = 2;
+
+ my_exit(error);
+ /* NOTREACHED */
+}
+
+/* Prepare to find the next patch to do in the patch file. */
+
+static void
+reinitialize_almost_everything(void)
+{
+ re_patch();
+ re_input();
+
+ input_lines = 0;
+ last_frozen_line = 0;
+
+ filec = 0;
+ if (!out_of_mem) {
+ free(filearg[0]);
+ filearg[0] = NULL;
+ }
+
+ free(outname);
+ outname = NULL;
+
+ last_offset = 0;
+ diff_type = 0;
+
+ free(revision);
+ revision = NULL;
+
+ reverse = reverse_flag_specified;
+ skip_rest_of_patch = false;
+
+ get_some_switches();
+}
+
+/* Process switches and filenames. */
+
+static void
+get_some_switches(void)
+{
+ const char *options = "b::B:cCd:D:eEfF:i:lnNo:p:r:RstuvV:x:z:";
+ static struct option longopts[] = {
+ {"backup", no_argument, 0, 'b'},
+ {"batch", no_argument, 0, 't'},
+ {"check", no_argument, 0, 'C'},
+ {"context", no_argument, 0, 'c'},
+ {"debug", required_argument, 0, 'x'},
+ {"directory", required_argument, 0, 'd'},
+ {"ed", no_argument, 0, 'e'},
+ {"force", no_argument, 0, 'f'},
+ {"forward", no_argument, 0, 'N'},
+ {"fuzz", required_argument, 0, 'F'},
+ {"ifdef", required_argument, 0, 'D'},
+ {"input", required_argument, 0, 'i'},
+ {"ignore-whitespace", no_argument, 0, 'l'},
+ {"normal", no_argument, 0, 'n'},
+ {"output", required_argument, 0, 'o'},
+ {"prefix", required_argument, 0, 'B'},
+ {"quiet", no_argument, 0, 's'},
+ {"reject-file", required_argument, 0, 'r'},
+ {"remove-empty-files", no_argument, 0, 'E'},
+ {"reverse", no_argument, 0, 'R'},
+ {"silent", no_argument, 0, 's'},
+ {"strip", required_argument, 0, 'p'},
+ {"suffix", required_argument, 0, 'z'},
+ {"unified", no_argument, 0, 'u'},
+ {"version", no_argument, 0, 'v'},
+ {"version-control", required_argument, 0, 'V'},
+ {"posix", no_argument, &posix, 1},
+ {NULL, 0, 0, 0}
+ };
+ int ch;
+
+ rejname[0] = '\0';
+ Argc_last = Argc;
+ Argv_last = Argv;
+ if (!Argc)
+ return;
+ optreset = optind = 1;
+ while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) {
+ switch (ch) {
+ case 'b':
+ if (backup_type == none)
+ backup_type = numbered_existing;
+ if (optarg == NULL)
+ break;
+ if (verbose)
+ say("Warning, the ``-b suffix'' option has been"
+ " obsoleted by the -z option.\n");
+ /* FALLTHROUGH */
+ case 'z':
+ /* must directly follow 'b' case for backwards compat */
+ simple_backup_suffix = savestr(optarg);
+ break;
+ case 'B':
+ origprae = savestr(optarg);
+ break;
+ case 'c':
+ diff_type = CONTEXT_DIFF;
+ break;
+ case 'C':
+ check_only = true;
+ break;
+ case 'd':
+ if (chdir(optarg) < 0)
+ pfatal("can't cd to %s", optarg);
+ break;
+ case 'D':
+ do_defines = true;
+ if (!isalpha((unsigned char)*optarg) && *optarg != '_')
+ fatal("argument to -D is not an identifier\n");
+ snprintf(if_defined, sizeof if_defined,
+ "#ifdef %s\n", optarg);
+ snprintf(not_defined, sizeof not_defined,
+ "#ifndef %s\n", optarg);
+ snprintf(end_defined, sizeof end_defined,
+ "#endif /* %s */\n", optarg);
+ break;
+ case 'e':
+ diff_type = ED_DIFF;
+ break;
+ case 'E':
+ remove_empty_files = true;
+ break;
+ case 'f':
+ force = true;
+ break;
+ case 'F':
+ maxfuzz = atoi(optarg);
+ break;
+ case 'i':
+ if (++filec == MAXFILEC)
+ fatal("too many file arguments\n");
+ filearg[filec] = savestr(optarg);
+ break;
+ case 'l':
+ canonicalize = true;
+ break;
+ case 'n':
+ diff_type = NORMAL_DIFF;
+ break;
+ case 'N':
+ noreverse = true;
+ break;
+ case 'o':
+ outname = savestr(optarg);
+ break;
+ case 'p':
+ strippath = atoi(optarg);
+ break;
+ case 'r':
+ if (strlcpy(rejname, optarg,
+ sizeof(rejname)) >= sizeof(rejname))
+ fatal("argument for -r is too long\n");
+ break;
+ case 'R':
+ reverse = true;
+ reverse_flag_specified = true;
+ break;
+ case 's':
+ verbose = false;
+ break;
+ case 't':
+ batch = true;
+ break;
+ case 'u':
+ diff_type = UNI_DIFF;
+ break;
+ case 'v':
+ version();
+ break;
+ case 'V':
+ backup_type = get_version(optarg);
+ break;
+#ifdef DEBUGGING
+ case 'x':
+ debug = atoi(optarg);
+ break;
+#endif
+ default:
+ if (ch != '\0')
+ usage();
+ break;
+ }
+ }
+ Argc -= optind;
+ Argv += optind;
+
+ if (Argc > 0) {
+ filearg[0] = savestr(*Argv++);
+ Argc--;
+ while (Argc > 0) {
+ if (++filec == MAXFILEC)
+ fatal("too many file arguments\n");
+ filearg[filec] = savestr(*Argv++);
+ Argc--;
+ }
+ }
+
+ if (getenv("POSIXLY_CORRECT") != NULL)
+ posix = 1;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+"usage: patch [-bCcEeflNnRstuv] [-B backup-prefix] [-D symbol] [-d directory]\n"
+" [-F max-fuzz] [-i patchfile] [-o out-file] [-p strip-count]\n"
+" [-r rej-name] [-V t | nil | never] [-x number] [-z backup-ext]\n"
+" [--posix] [origfile [patchfile]]\n"
+" patch <patchfile\n");
+ my_exit(EXIT_SUCCESS);
+}
+
+/*
+ * Attempt to find the right place to apply this hunk of patch.
+ */
+static LINENUM
+locate_hunk(LINENUM fuzz)
+{
+ LINENUM first_guess = pch_first() + last_offset;
+ LINENUM offset;
+ LINENUM pat_lines = pch_ptrn_lines();
+ LINENUM max_pos_offset = input_lines - first_guess - pat_lines + 1;
+ LINENUM max_neg_offset = first_guess - last_frozen_line - 1 + pch_context();
+
+ if (pat_lines == 0) { /* null range matches always */
+ if (verbose && fuzz == 0 && (diff_type == CONTEXT_DIFF
+ || diff_type == NEW_CONTEXT_DIFF
+ || diff_type == UNI_DIFF)) {
+ say("Empty context always matches.\n");
+ }
+ return (first_guess);
+ }
+ if (max_neg_offset >= first_guess) /* do not try lines < 0 */
+ max_neg_offset = first_guess - 1;
+ if (first_guess <= input_lines && patch_match(first_guess, 0, fuzz))
+ return first_guess;
+ for (offset = 1; ; offset++) {
+ bool check_after = (offset <= max_pos_offset);
+ bool check_before = (offset <= max_neg_offset);
+
+ if (check_after && patch_match(first_guess, offset, fuzz)) {
+#ifdef DEBUGGING
+ if (debug & 1)
+ say("Offset changing from %ld to %ld\n",
+ last_offset, offset);
+#endif
+ last_offset = offset;
+ return first_guess + offset;
+ } else if (check_before && patch_match(first_guess, -offset, fuzz)) {
+#ifdef DEBUGGING
+ if (debug & 1)
+ say("Offset changing from %ld to %ld\n",
+ last_offset, -offset);
+#endif
+ last_offset = -offset;
+ return first_guess - offset;
+ } else if (!check_before && !check_after)
+ return 0;
+ }
+}
+
+/* We did not find the pattern, dump out the hunk so they can handle it. */
+
+static void
+abort_context_hunk(void)
+{
+ LINENUM i;
+ const LINENUM pat_end = pch_end();
+ /*
+ * add in last_offset to guess the same as the previous successful
+ * hunk
+ */
+ const LINENUM oldfirst = pch_first() + last_offset;
+ const LINENUM newfirst = pch_newfirst() + last_offset;
+ const LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
+ const LINENUM newlast = newfirst + pch_repl_lines() - 1;
+ const char *stars = (diff_type >= NEW_CONTEXT_DIFF ? " ****" : "");
+ const char *minuses = (diff_type >= NEW_CONTEXT_DIFF ? " ----" : " -----");
+
+ fprintf(rejfp, "***************\n");
+ for (i = 0; i <= pat_end; i++) {
+ switch (pch_char(i)) {
+ case '*':
+ if (oldlast < oldfirst)
+ fprintf(rejfp, "*** 0%s\n", stars);
+ else if (oldlast == oldfirst)
+ fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
+ else
+ fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst,
+ oldlast, stars);
+ break;
+ case '=':
+ if (newlast < newfirst)
+ fprintf(rejfp, "--- 0%s\n", minuses);
+ else if (newlast == newfirst)
+ fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
+ else
+ fprintf(rejfp, "--- %ld,%ld%s\n", newfirst,
+ newlast, minuses);
+ break;
+ case '\n':
+ fprintf(rejfp, "%s", pfetch(i));
+ break;
+ case ' ':
+ case '-':
+ case '+':
+ case '!':
+ fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
+ break;
+ default:
+ fatal("fatal internal error in abort_context_hunk\n");
+ }
+ }
+}
+
+static void
+rej_line(int ch, LINENUM i)
+{
+ size_t len;
+ const char *line = pfetch(i);
+
+ len = strlen(line);
+
+ fprintf(rejfp, "%c%s", ch, line);
+ if (len == 0 || line[len-1] != '\n')
+ fprintf(rejfp, "\n\\ No newline at end of file\n");
+}
+
+static void
+abort_hunk(void)
+{
+ LINENUM i, j, split;
+ int ch1, ch2;
+ const LINENUM pat_end = pch_end();
+ const LINENUM oldfirst = pch_first() + last_offset;
+ const LINENUM newfirst = pch_newfirst() + last_offset;
+
+ if (diff_type != UNI_DIFF) {
+ abort_context_hunk();
+ return;
+ }
+ split = -1;
+ for (i = 0; i <= pat_end; i++) {
+ if (pch_char(i) == '=') {
+ split = i;
+ break;
+ }
+ }
+ if (split == -1) {
+ fprintf(rejfp, "malformed hunk: no split found\n");
+ return;
+ }
+ i = 0;
+ j = split + 1;
+ fprintf(rejfp, "@@ -%ld,%ld +%ld,%ld @@\n",
+ pch_ptrn_lines() ? oldfirst : 0,
+ pch_ptrn_lines(), newfirst, pch_repl_lines());
+ while (i < split || j <= pat_end) {
+ ch1 = i < split ? pch_char(i) : -1;
+ ch2 = j <= pat_end ? pch_char(j) : -1;
+ if (ch1 == '-') {
+ rej_line('-', i);
+ i++;
+ } else if (ch1 == ' ' && ch2 == ' ') {
+ rej_line(' ', i);
+ i++;
+ j++;
+ } else if (ch1 == '!' && ch2 == '!') {
+ while (i < split && ch1 == '!') {
+ rej_line('-', i);
+ i++;
+ ch1 = i < split ? pch_char(i) : -1;
+ }
+ while (j <= pat_end && ch2 == '!') {
+ rej_line('+', j);
+ j++;
+ ch2 = j <= pat_end ? pch_char(j) : -1;
+ }
+ } else if (ch1 == '*') {
+ i++;
+ } else if (ch2 == '+' || ch2 == ' ') {
+ rej_line(ch2, j);
+ j++;
+ } else {
+ fprintf(rejfp, "internal error on (%ld %ld %ld)\n",
+ i, split, j);
+ rej_line(ch1, i);
+ rej_line(ch2, j);
+ return;
+ }
+ }
+}
+
+/* We found where to apply it (we hope), so do it. */
+
+static void
+apply_hunk(LINENUM where)
+{
+ LINENUM old = 1;
+ const LINENUM lastline = pch_ptrn_lines();
+ LINENUM new = lastline + 1;
+#define OUTSIDE 0
+#define IN_IFNDEF 1
+#define IN_IFDEF 2
+#define IN_ELSE 3
+ int def_state = OUTSIDE;
+ const LINENUM pat_end = pch_end();
+
+ where--;
+ while (pch_char(new) == '=' || pch_char(new) == '\n')
+ new++;
+
+ while (old <= lastline) {
+ if (pch_char(old) == '-') {
+ copy_till(where + old - 1, false);
+ if (do_defines) {
+ if (def_state == OUTSIDE) {
+ fputs(not_defined, ofp);
+ def_state = IN_IFNDEF;
+ } else if (def_state == IN_IFDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ fputs(pfetch(old), ofp);
+ }
+ last_frozen_line++;
+ old++;
+ } else if (new > pat_end) {
+ break;
+ } else if (pch_char(new) == '+') {
+ copy_till(where + old - 1, false);
+ if (do_defines) {
+ if (def_state == IN_IFNDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ } else if (def_state == OUTSIDE) {
+ fputs(if_defined, ofp);
+ def_state = IN_IFDEF;
+ }
+ }
+ fputs(pfetch(new), ofp);
+ new++;
+ } else if (pch_char(new) != pch_char(old)) {
+ say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
+ pch_hunk_beg() + old,
+ pch_hunk_beg() + new);
+#ifdef DEBUGGING
+ say("oldchar = '%c', newchar = '%c'\n",
+ pch_char(old), pch_char(new));
+#endif
+ my_exit(2);
+ } else if (pch_char(new) == '!') {
+ copy_till(where + old - 1, false);
+ if (do_defines) {
+ fputs(not_defined, ofp);
+ def_state = IN_IFNDEF;
+ }
+ while (pch_char(old) == '!') {
+ if (do_defines) {
+ fputs(pfetch(old), ofp);
+ }
+ last_frozen_line++;
+ old++;
+ }
+ if (do_defines) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ while (pch_char(new) == '!') {
+ fputs(pfetch(new), ofp);
+ new++;
+ }
+ } else {
+ if (pch_char(new) != ' ')
+ fatal("Internal error: expected ' '\n");
+ old++;
+ new++;
+ if (do_defines && def_state != OUTSIDE) {
+ fputs(end_defined, ofp);
+ def_state = OUTSIDE;
+ }
+ }
+ }
+ if (new <= pat_end && pch_char(new) == '+') {
+ copy_till(where + old - 1, false);
+ if (do_defines) {
+ if (def_state == OUTSIDE) {
+ fputs(if_defined, ofp);
+ def_state = IN_IFDEF;
+ } else if (def_state == IN_IFNDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ }
+ while (new <= pat_end && pch_char(new) == '+') {
+ fputs(pfetch(new), ofp);
+ new++;
+ }
+ }
+ if (do_defines && def_state != OUTSIDE) {
+ fputs(end_defined, ofp);
+ }
+}
+
+/*
+ * Open the new file.
+ */
+static void
+init_output(const char *name)
+{
+ ofp = fopen(name, "w");
+ if (ofp == NULL)
+ pfatal("can't create %s", name);
+}
+
+/*
+ * Open a file to put hunks we can't locate.
+ */
+static void
+init_reject(const char *name)
+{
+ rejfp = fopen(name, "w");
+ if (rejfp == NULL)
+ pfatal("can't create %s", name);
+}
+
+/*
+ * Copy input file to output, up to wherever hunk is to be applied.
+ * If endoffile is true, treat the last line specially since it may
+ * lack a newline.
+ */
+static void
+copy_till(LINENUM lastline, bool endoffile)
+{
+ if (last_frozen_line > lastline)
+ fatal("misordered hunks! output would be garbled\n");
+ while (last_frozen_line < lastline) {
+ if (++last_frozen_line == lastline && endoffile)
+ dump_line(last_frozen_line, !last_line_missing_eol);
+ else
+ dump_line(last_frozen_line, true);
+ }
+}
+
+/*
+ * Finish copying the input file to the output file.
+ */
+static bool
+spew_output(void)
+{
+ int rv;
+
+#ifdef DEBUGGING
+ if (debug & 256)
+ say("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
+#endif
+ if (input_lines)
+ copy_till(input_lines, true); /* dump remainder of file */
+ rv = ferror(ofp) == 0 && fclose(ofp) == 0;
+ ofp = NULL;
+ return rv;
+}
+
+/*
+ * Copy one line from input to output.
+ */
+static void
+dump_line(LINENUM line, bool write_newline)
+{
+ char *s;
+
+ s = ifetch(line, 0);
+ if (s == NULL)
+ return;
+ /* Note: string is not NUL terminated. */
+ for (; *s != '\n'; s++)
+ putc(*s, ofp);
+ if (write_newline)
+ putc('\n', ofp);
+}
+
+/*
+ * Does the patch pattern match at line base+offset?
+ */
+static bool
+patch_match(LINENUM base, LINENUM offset, LINENUM fuzz)
+{
+ LINENUM pline = 1 + fuzz;
+ LINENUM iline;
+ LINENUM pat_lines = pch_ptrn_lines() - fuzz;
+ const char *ilineptr;
+ const char *plineptr;
+ short plinelen;
+
+ for (iline = base + offset + fuzz; pline <= pat_lines; pline++, iline++) {
+ ilineptr = ifetch(iline, offset >= 0);
+ if (ilineptr == NULL)
+ return false;
+ plineptr = pfetch(pline);
+ plinelen = pch_line_len(pline);
+ if (canonicalize) {
+ if (!similar(ilineptr, plineptr, plinelen))
+ return false;
+ } else if (strnNE(ilineptr, plineptr, plinelen))
+ return false;
+ if (iline == input_lines) {
+ /*
+ * We are looking at the last line of the file.
+ * If the file has no eol, the patch line should
+ * not have one either and vice-versa. Note that
+ * plinelen > 0.
+ */
+ if (last_line_missing_eol) {
+ if (plineptr[plinelen - 1] == '\n')
+ return false;
+ } else {
+ if (plineptr[plinelen - 1] != '\n')
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/*
+ * Do two lines match with canonicalized white space?
+ */
+static bool
+similar(const char *a, const char *b, int len)
+{
+ while (len) {
+ if (isspace((unsigned char)*b)) { /* whitespace (or \n) to match? */
+ if (!isspace((unsigned char)*a)) /* no corresponding whitespace? */
+ return false;
+ while (len && isspace((unsigned char)*b) && *b != '\n')
+ b++, len--; /* skip pattern whitespace */
+ while (isspace((unsigned char)*a) && *a != '\n')
+ a++; /* skip target whitespace */
+ if (*a == '\n' || *b == '\n')
+ return (*a == *b); /* should end in sync */
+ } else if (*a++ != *b++) /* match non-whitespace chars */
+ return false;
+ else
+ len--; /* probably not necessary */
+ }
+ return true; /* actually, this is not reached */
+ /* since there is always a \n */
+}
diff --git a/usr.bin/patch/pathnames.h b/usr.bin/patch/pathnames.h
new file mode 100644
index 0000000..d31300e
--- /dev/null
+++ b/usr.bin/patch/pathnames.h
@@ -0,0 +1,12 @@
+/*-
+ * Placed in the public domain by Todd C. Miller <Todd.Miller@courtesan.com>
+ * on July 29, 2003.
+ *
+ * $OpenBSD: pathnames.h,v 1.1 2003/07/29 20:10:17 millert Exp $
+ * $FreeBSD$
+ */
+
+
+#include <paths.h>
+
+#define _PATH_ED "/bin/ed"
diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c
new file mode 100644
index 0000000..4c06bbf
--- /dev/null
+++ b/usr.bin/patch/pch.c
@@ -0,0 +1,1593 @@
+
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: pch.c,v 1.39 2012/04/11 08:07:13 ajacoutot Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "util.h"
+#include "pch.h"
+#include "pathnames.h"
+
+/* Patch (diff listing) abstract type. */
+
+static long p_filesize; /* size of the patch file */
+static LINENUM p_first; /* 1st line number */
+static LINENUM p_newfirst; /* 1st line number of replacement */
+static LINENUM p_ptrn_lines; /* # lines in pattern */
+static LINENUM p_repl_lines; /* # lines in replacement text */
+static LINENUM p_end = -1; /* last line in hunk */
+static LINENUM p_max; /* max allowed value of p_end */
+static LINENUM p_context = 3; /* # of context lines */
+static LINENUM p_input_line = 0; /* current line # from patch file */
+static char **p_line = NULL;/* the text of the hunk */
+static short *p_len = NULL; /* length of each line */
+static char *p_char = NULL; /* +, -, and ! */
+static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */
+static int p_indent; /* indent to patch */
+static LINENUM p_base; /* where to intuit this time */
+static LINENUM p_bline; /* line # of p_base */
+static LINENUM p_start; /* where intuit found a patch */
+static LINENUM p_sline; /* and the line number for it */
+static LINENUM p_hunk_beg; /* line number of current hunk */
+static LINENUM p_efake = -1; /* end of faked up lines--don't free */
+static LINENUM p_bfake = -1; /* beg of faked up lines */
+static FILE *pfp = NULL; /* patch file pointer */
+static char *bestguess = NULL; /* guess at correct filename */
+
+static void grow_hunkmax(void);
+static int intuit_diff_type(void);
+static void next_intuit_at(LINENUM, LINENUM);
+static void skip_to(LINENUM, LINENUM);
+static size_t pgets(bool _do_indent);
+static char *best_name(const struct file_name *, bool);
+static char *posix_name(const struct file_name *, bool);
+static size_t num_components(const char *);
+
+/*
+ * Prepare to look for the next patch in the patch file.
+ */
+void
+re_patch(void)
+{
+ p_first = 0;
+ p_newfirst = 0;
+ p_ptrn_lines = 0;
+ p_repl_lines = 0;
+ p_end = (LINENUM) - 1;
+ p_max = 0;
+ p_indent = 0;
+}
+
+/*
+ * Open the patch file at the beginning of time.
+ */
+void
+open_patch_file(const char *filename)
+{
+ struct stat filestat;
+
+ if (filename == NULL || *filename == '\0' || strEQ(filename, "-")) {
+ pfp = fopen(TMPPATNAME, "w");
+ if (pfp == NULL)
+ pfatal("can't create %s", TMPPATNAME);
+ while (fgets(buf, buf_size, stdin) != NULL)
+ fputs(buf, pfp);
+ if (ferror(pfp) || fclose(pfp))
+ pfatal("can't write %s", TMPPATNAME);
+ filename = TMPPATNAME;
+ }
+ pfp = fopen(filename, "r");
+ if (pfp == NULL)
+ pfatal("patch file %s not found", filename);
+ fstat(fileno(pfp), &filestat);
+ p_filesize = filestat.st_size;
+ next_intuit_at(0L, 1L); /* start at the beginning */
+ set_hunkmax();
+}
+
+/*
+ * Make sure our dynamically realloced tables are malloced to begin with.
+ */
+void
+set_hunkmax(void)
+{
+ if (p_line == NULL)
+ p_line = calloc((size_t) hunkmax, sizeof(char *));
+ if (p_len == NULL)
+ p_len = calloc((size_t) hunkmax, sizeof(short));
+ if (p_char == NULL)
+ p_char = calloc((size_t) hunkmax, sizeof(char));
+}
+
+/*
+ * Enlarge the arrays containing the current hunk of patch.
+ */
+static void
+grow_hunkmax(void)
+{
+ int new_hunkmax;
+ char **new_p_line;
+ short *new_p_len;
+ char *new_p_char;
+
+ new_hunkmax = hunkmax * 2;
+
+ if (p_line == NULL || p_len == NULL || p_char == NULL)
+ fatal("Internal memory allocation error\n");
+
+ new_p_line = realloc(p_line, new_hunkmax * sizeof(char *));
+ if (new_p_line == NULL)
+ free(p_line);
+
+ new_p_len = realloc(p_len, new_hunkmax * sizeof(short));
+ if (new_p_len == NULL)
+ free(p_len);
+
+ new_p_char = realloc(p_char, new_hunkmax * sizeof(char));
+ if (new_p_char == NULL)
+ free(p_char);
+
+ p_char = new_p_char;
+ p_len = new_p_len;
+ p_line = new_p_line;
+
+ if (p_line != NULL && p_len != NULL && p_char != NULL) {
+ hunkmax = new_hunkmax;
+ return;
+ }
+
+ if (!using_plan_a)
+ fatal("out of memory\n");
+ out_of_mem = true; /* whatever is null will be allocated again */
+ /* from within plan_a(), of all places */
+}
+
+/* True if the remainder of the patch file contains a diff of some sort. */
+
+bool
+there_is_another_patch(void)
+{
+ bool exists = false;
+
+ if (p_base != 0L && p_base >= p_filesize) {
+ if (verbose)
+ say("done\n");
+ return false;
+ }
+ if (verbose)
+ say("Hmm...");
+ diff_type = intuit_diff_type();
+ if (!diff_type) {
+ if (p_base != 0L) {
+ if (verbose)
+ say(" Ignoring the trailing garbage.\ndone\n");
+ } else
+ say(" I can't seem to find a patch in there anywhere.\n");
+ return false;
+ }
+ if (verbose)
+ say(" %sooks like %s to me...\n",
+ (p_base == 0L ? "L" : "The next patch l"),
+ diff_type == UNI_DIFF ? "a unified diff" :
+ diff_type == CONTEXT_DIFF ? "a context diff" :
+ diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
+ diff_type == NORMAL_DIFF ? "a normal diff" :
+ "an ed script");
+ if (p_indent && verbose)
+ say("(Patch is indented %d space%s.)\n", p_indent,
+ p_indent == 1 ? "" : "s");
+ skip_to(p_start, p_sline);
+ while (filearg[0] == NULL) {
+ if (force || batch) {
+ say("No file to patch. Skipping...\n");
+ filearg[0] = savestr(bestguess);
+ skip_rest_of_patch = true;
+ return true;
+ }
+ ask("File to patch: ");
+ if (*buf != '\n') {
+ free(bestguess);
+ bestguess = savestr(buf);
+ filearg[0] = fetchname(buf, &exists, 0);
+ }
+ if (!exists) {
+ ask("No file found--skip this patch? [n] ");
+ if (*buf != 'y')
+ continue;
+ if (verbose)
+ say("Skipping patch...\n");
+ free(filearg[0]);
+ filearg[0] = fetchname(bestguess, &exists, 0);
+ skip_rest_of_patch = true;
+ return true;
+ }
+ }
+ return true;
+}
+
+static void
+p4_fetchname(struct file_name *name, char *str)
+{
+ char *t, *h;
+
+ /* Skip leading whitespace. */
+ while (isspace((unsigned char)*str))
+ str++;
+
+ /* Remove the file revision number. */
+ for (t = str, h = NULL; *t != '\0' && !isspace((unsigned char)*t); t++)
+ if (*t == '#')
+ h = t;
+ if (h != NULL)
+ *h = '\0';
+
+ name->path = fetchname(str, &name->exists, strippath);
+}
+
+/* Determine what kind of diff is in the remaining part of the patch file. */
+
+static int
+intuit_diff_type(void)
+{
+ long this_line = 0, previous_line;
+ long first_command_line = -1;
+ LINENUM fcl_line = -1;
+ bool last_line_was_command = false, this_is_a_command = false;
+ bool stars_last_line = false, stars_this_line = false;
+ char *s, *t;
+ int indent, retval;
+ struct file_name names[MAX_FILE];
+
+ memset(names, 0, sizeof(names));
+ ok_to_create_file = false;
+ fseek(pfp, p_base, SEEK_SET);
+ p_input_line = p_bline - 1;
+ for (;;) {
+ previous_line = this_line;
+ last_line_was_command = this_is_a_command;
+ stars_last_line = stars_this_line;
+ this_line = ftell(pfp);
+ indent = 0;
+ p_input_line++;
+ if (pgets(false) == 0) {
+ if (first_command_line >= 0L) {
+ /* nothing but deletes!? */
+ p_start = first_command_line;
+ p_sline = fcl_line;
+ retval = ED_DIFF;
+ goto scan_exit;
+ } else {
+ p_start = this_line;
+ p_sline = p_input_line;
+ retval = 0;
+ goto scan_exit;
+ }
+ }
+ for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
+ if (*s == '\t')
+ indent += 8 - (indent % 8);
+ else
+ indent++;
+ }
+ for (t = s; isdigit((unsigned char)*t) || *t == ','; t++)
+ ;
+ this_is_a_command = (isdigit((unsigned char)*s) &&
+ (*t == 'd' || *t == 'c' || *t == 'a'));
+ if (first_command_line < 0L && this_is_a_command) {
+ first_command_line = this_line;
+ fcl_line = p_input_line;
+ p_indent = indent; /* assume this for now */
+ }
+ if (!stars_last_line && strnEQ(s, "*** ", 4))
+ names[OLD_FILE].path = fetchname(s + 4,
+ &names[OLD_FILE].exists, strippath);
+ else if (strnEQ(s, "--- ", 4))
+ names[NEW_FILE].path = fetchname(s + 4,
+ &names[NEW_FILE].exists, strippath);
+ else if (strnEQ(s, "+++ ", 4))
+ /* pretend it is the old name */
+ names[OLD_FILE].path = fetchname(s + 4,
+ &names[OLD_FILE].exists, strippath);
+ else if (strnEQ(s, "Index:", 6))
+ names[INDEX_FILE].path = fetchname(s + 6,
+ &names[INDEX_FILE].exists, strippath);
+ else if (strnEQ(s, "Prereq:", 7)) {
+ for (t = s + 7; isspace((unsigned char)*t); t++)
+ ;
+ revision = savestr(t);
+ for (t = revision; *t && !isspace((unsigned char)*t); t++)
+ ;
+ *t = '\0';
+ if (*revision == '\0') {
+ free(revision);
+ revision = NULL;
+ }
+ } else if (strnEQ(s, "==== ", 5)) {
+ /* Perforce-style diffs. */
+ if ((t = strstr(s + 5, " - ")) != NULL)
+ p4_fetchname(&names[NEW_FILE], t + 3);
+ p4_fetchname(&names[OLD_FILE], s + 5);
+ }
+ if ((!diff_type || diff_type == ED_DIFF) &&
+ first_command_line >= 0L &&
+ strEQ(s, ".\n")) {
+ p_indent = indent;
+ p_start = first_command_line;
+ p_sline = fcl_line;
+ retval = ED_DIFF;
+ goto scan_exit;
+ }
+ if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {
+ if (strnEQ(s + 4, "0,0", 3))
+ ok_to_create_file = true;
+ p_indent = indent;
+ p_start = this_line;
+ p_sline = p_input_line;
+ retval = UNI_DIFF;
+ goto scan_exit;
+ }
+ stars_this_line = strnEQ(s, "********", 8);
+ if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
+ strnEQ(s, "*** ", 4)) {
+ if (atol(s + 4) == 0)
+ ok_to_create_file = true;
+ /*
+ * If this is a new context diff the character just
+ * before the newline is a '*'.
+ */
+ while (*s != '\n')
+ s++;
+ p_indent = indent;
+ p_start = previous_line;
+ p_sline = p_input_line - 1;
+ retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
+ goto scan_exit;
+ }
+ if ((!diff_type || diff_type == NORMAL_DIFF) &&
+ last_line_was_command &&
+ (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) {
+ p_start = previous_line;
+ p_sline = p_input_line - 1;
+ p_indent = indent;
+ retval = NORMAL_DIFF;
+ goto scan_exit;
+ }
+ }
+scan_exit:
+ if (retval == UNI_DIFF) {
+ /* unswap old and new */
+ struct file_name tmp = names[OLD_FILE];
+ names[OLD_FILE] = names[NEW_FILE];
+ names[NEW_FILE] = tmp;
+ }
+ if (filearg[0] == NULL) {
+ if (posix)
+ filearg[0] = posix_name(names, ok_to_create_file);
+ else {
+ /* Ignore the Index: name for context diffs, like GNU */
+ if (names[OLD_FILE].path != NULL ||
+ names[NEW_FILE].path != NULL) {
+ free(names[INDEX_FILE].path);
+ names[INDEX_FILE].path = NULL;
+ }
+ filearg[0] = best_name(names, ok_to_create_file);
+ }
+ }
+
+ free(bestguess);
+ bestguess = NULL;
+ if (filearg[0] != NULL)
+ bestguess = savestr(filearg[0]);
+ else if (!ok_to_create_file) {
+ /*
+ * We don't want to create a new file but we need a
+ * filename to set bestguess. Avoid setting filearg[0]
+ * so the file is not created automatically.
+ */
+ if (posix)
+ bestguess = posix_name(names, true);
+ else
+ bestguess = best_name(names, true);
+ }
+ free(names[OLD_FILE].path);
+ free(names[NEW_FILE].path);
+ free(names[INDEX_FILE].path);
+ return retval;
+}
+
+/*
+ * Remember where this patch ends so we know where to start up again.
+ */
+static void
+next_intuit_at(LINENUM file_pos, LINENUM file_line)
+{
+ p_base = file_pos;
+ p_bline = file_line;
+}
+
+/*
+ * Basically a verbose fseek() to the actual diff listing.
+ */
+static void
+skip_to(LINENUM file_pos, LINENUM file_line)
+{
+ size_t len;
+
+ if (p_base > file_pos)
+ fatal("Internal error: seek %ld>%ld\n", p_base, file_pos);
+ if (verbose && p_base < file_pos) {
+ fseek(pfp, p_base, SEEK_SET);
+ say("The text leading up to this was:\n--------------------------\n");
+ while (ftell(pfp) < file_pos) {
+ len = pgets(false);
+ if (len == 0)
+ fatal("Unexpected end of file\n");
+ say("|%s", buf);
+ }
+ say("--------------------------\n");
+ } else
+ fseek(pfp, file_pos, SEEK_SET);
+ p_input_line = file_line - 1;
+}
+
+/* Make this a function for better debugging. */
+static void
+malformed(void)
+{
+ fatal("malformed patch at line %ld: %s", p_input_line, buf);
+ /* about as informative as "Syntax error" in C */
+}
+
+/*
+ * True if the line has been discarded (i.e. it is a line saying
+ * "\ No newline at end of file".)
+ */
+static bool
+remove_special_line(void)
+{
+ int c;
+
+ c = fgetc(pfp);
+ if (c == '\\') {
+ do {
+ c = fgetc(pfp);
+ } while (c != EOF && c != '\n');
+
+ return true;
+ }
+ if (c != EOF)
+ fseek(pfp, -1L, SEEK_CUR);
+
+ return false;
+}
+
+/*
+ * True if there is more of the current diff listing to process.
+ */
+bool
+another_hunk(void)
+{
+ long line_beginning; /* file pos of the current line */
+ LINENUM repl_beginning; /* index of --- line */
+ LINENUM fillcnt; /* #lines of missing ptrn or repl */
+ LINENUM fillsrc; /* index of first line to copy */
+ LINENUM filldst; /* index of first missing line */
+ bool ptrn_spaces_eaten; /* ptrn was slightly misformed */
+ bool repl_could_be_missing; /* no + or ! lines in this hunk */
+ bool repl_missing; /* we are now backtracking */
+ long repl_backtrack_position; /* file pos of first repl line */
+ LINENUM repl_patch_line; /* input line number for same */
+ LINENUM ptrn_copiable; /* # of copiable lines in ptrn */
+ char *s;
+ size_t len;
+ int context = 0;
+
+ while (p_end >= 0) {
+ if (p_end == p_efake)
+ p_end = p_bfake; /* don't free twice */
+ else
+ free(p_line[p_end]);
+ p_end--;
+ }
+ p_efake = -1;
+
+ p_max = hunkmax; /* gets reduced when --- found */
+ if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
+ line_beginning = ftell(pfp);
+ repl_beginning = 0;
+ fillcnt = 0;
+ fillsrc = 0;
+ filldst = 0;
+ ptrn_spaces_eaten = false;
+ repl_could_be_missing = true;
+ repl_missing = false;
+ repl_backtrack_position = 0;
+ repl_patch_line = 0;
+ ptrn_copiable = 0;
+
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0 || strnNE(buf, "********", 8)) {
+ next_intuit_at(line_beginning, p_input_line);
+ return false;
+ }
+ p_context = 100;
+ p_hunk_beg = p_input_line + 1;
+ while (p_end < p_max) {
+ line_beginning = ftell(pfp);
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0) {
+ if (p_max - p_end < 4) {
+ /* assume blank lines got chopped */
+ strlcpy(buf, " \n", buf_size);
+ } else {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ fatal("unexpected end of file in patch\n");
+ }
+ }
+ p_end++;
+ if (p_end >= hunkmax)
+ fatal("Internal error: hunk larger than hunk "
+ "buffer size");
+ p_char[p_end] = *buf;
+ p_line[p_end] = NULL;
+ switch (*buf) {
+ case '*':
+ if (strnEQ(buf, "********", 8)) {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ } else
+ fatal("unexpected end of hunk "
+ "at line %ld\n",
+ p_input_line);
+ }
+ if (p_end != 0) {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ fatal("unexpected *** at line %ld: %s",
+ p_input_line, buf);
+ }
+ context = 0;
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ for (s = buf; *s && !isdigit((unsigned char)*s); s++)
+ ;
+ if (!*s)
+ malformed();
+ if (strnEQ(s, "0,0", 3))
+ memmove(s, s + 2, strlen(s + 2) + 1);
+ p_first = (LINENUM) atol(s);
+ while (isdigit((unsigned char)*s))
+ s++;
+ if (*s == ',') {
+ for (; *s && !isdigit((unsigned char)*s); s++)
+ ;
+ if (!*s)
+ malformed();
+ p_ptrn_lines = ((LINENUM) atol(s)) - p_first + 1;
+ } else if (p_first)
+ p_ptrn_lines = 1;
+ else {
+ p_ptrn_lines = 0;
+ p_first = 1;
+ }
+
+ /* we need this much at least */
+ p_max = p_ptrn_lines + 6;
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ p_max = hunkmax;
+ break;
+ case '-':
+ if (buf[1] == '-') {
+ if (repl_beginning ||
+ (p_end != p_ptrn_lines + 1 +
+ (p_char[p_end - 1] == '\n'))) {
+ if (p_end == 1) {
+ /*
+ * `old' lines were omitted;
+ * set up to fill them in
+ * from 'new' context lines.
+ */
+ p_end = p_ptrn_lines + 1;
+ fillsrc = p_end + 1;
+ filldst = 1;
+ fillcnt = p_ptrn_lines;
+ } else {
+ if (repl_beginning) {
+ if (repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ fatal("duplicate \"---\" at line %ld--check line numbers at line %ld\n",
+ p_input_line, p_hunk_beg + repl_beginning);
+ } else {
+ fatal("%s \"---\" at line %ld--check line numbers at line %ld\n",
+ (p_end <= p_ptrn_lines
+ ? "Premature"
+ : "Overdue"),
+ p_input_line, p_hunk_beg);
+ }
+ }
+ }
+ repl_beginning = p_end;
+ repl_backtrack_position = ftell(pfp);
+ repl_patch_line = p_input_line;
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ p_char[p_end] = '=';
+ for (s = buf; *s && !isdigit((unsigned char)*s); s++)
+ ;
+ if (!*s)
+ malformed();
+ p_newfirst = (LINENUM) atol(s);
+ while (isdigit((unsigned char)*s))
+ s++;
+ if (*s == ',') {
+ for (; *s && !isdigit((unsigned char)*s); s++)
+ ;
+ if (!*s)
+ malformed();
+ p_repl_lines = ((LINENUM) atol(s)) -
+ p_newfirst + 1;
+ } else if (p_newfirst)
+ p_repl_lines = 1;
+ else {
+ p_repl_lines = 0;
+ p_newfirst = 1;
+ }
+ p_max = p_repl_lines + p_end;
+ if (p_max > MAXHUNKSIZE)
+ fatal("hunk too large (%ld lines) at line %ld: %s",
+ p_max, p_input_line, buf);
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ if (p_repl_lines != ptrn_copiable &&
+ (p_context != 0 || p_repl_lines != 1))
+ repl_could_be_missing = false;
+ break;
+ }
+ goto change_line;
+ case '+':
+ case '!':
+ repl_could_be_missing = false;
+ change_line:
+ if (buf[1] == '\n' && canonicalize)
+ strlcpy(buf + 1, " \n", buf_size - 1);
+ if (!isspace((unsigned char)buf[1]) && buf[1] != '>' &&
+ buf[1] != '<' &&
+ repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ if (context >= 0) {
+ if (context < p_context)
+ p_context = context;
+ context = -1000;
+ }
+ p_line[p_end] = savestr(buf + 2);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ if (p_end == p_ptrn_lines) {
+ if (remove_special_line()) {
+ int l;
+
+ l = strlen(p_line[p_end]) - 1;
+ (p_line[p_end])[l] = 0;
+ }
+ }
+ break;
+ case '\t':
+ case '\n': /* assume the 2 spaces got eaten */
+ if (repl_beginning && repl_could_be_missing &&
+ (!ptrn_spaces_eaten ||
+ diff_type == NEW_CONTEXT_DIFF)) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ if (p_end != p_ptrn_lines + 1) {
+ ptrn_spaces_eaten |= (repl_beginning != 0);
+ context++;
+ if (!repl_beginning)
+ ptrn_copiable++;
+ p_char[p_end] = ' ';
+ }
+ break;
+ case ' ':
+ if (!isspace((unsigned char)buf[1]) &&
+ repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ context++;
+ if (!repl_beginning)
+ ptrn_copiable++;
+ p_line[p_end] = savestr(buf + 2);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ break;
+ default:
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ malformed();
+ }
+ /* set up p_len for strncmp() so we don't have to */
+ /* assume null termination */
+ if (p_line[p_end])
+ p_len[p_end] = strlen(p_line[p_end]);
+ else
+ p_len[p_end] = 0;
+ }
+
+hunk_done:
+ if (p_end >= 0 && !repl_beginning)
+ fatal("no --- found in patch at line %ld\n", pch_hunk_beg());
+
+ if (repl_missing) {
+
+ /* reset state back to just after --- */
+ p_input_line = repl_patch_line;
+ for (p_end--; p_end > repl_beginning; p_end--)
+ free(p_line[p_end]);
+ fseek(pfp, repl_backtrack_position, SEEK_SET);
+
+ /* redundant 'new' context lines were omitted - set */
+ /* up to fill them in from the old file context */
+ if (!p_context && p_repl_lines == 1) {
+ p_repl_lines = 0;
+ p_max--;
+ }
+ fillsrc = 1;
+ filldst = repl_beginning + 1;
+ fillcnt = p_repl_lines;
+ p_end = p_max;
+ } else if (!p_context && fillcnt == 1) {
+ /* the first hunk was a null hunk with no context */
+ /* and we were expecting one line -- fix it up. */
+ while (filldst < p_end) {
+ p_line[filldst] = p_line[filldst + 1];
+ p_char[filldst] = p_char[filldst + 1];
+ p_len[filldst] = p_len[filldst + 1];
+ filldst++;
+ }
+#if 0
+ repl_beginning--; /* this doesn't need to be fixed */
+#endif
+ p_end--;
+ p_first++; /* do append rather than insert */
+ fillcnt = 0;
+ p_ptrn_lines = 0;
+ }
+ if (diff_type == CONTEXT_DIFF &&
+ (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) {
+ if (verbose)
+ say("%s\n%s\n%s\n",
+ "(Fascinating--this is really a new-style context diff but without",
+ "the telltale extra asterisks on the *** line that usually indicate",
+ "the new style...)");
+ diff_type = NEW_CONTEXT_DIFF;
+ }
+ /* if there were omitted context lines, fill them in now */
+ if (fillcnt) {
+ p_bfake = filldst; /* remember where not to free() */
+ p_efake = filldst + fillcnt - 1;
+ while (fillcnt-- > 0) {
+ while (fillsrc <= p_end && p_char[fillsrc] != ' ')
+ fillsrc++;
+ if (fillsrc > p_end)
+ fatal("replacement text or line numbers mangled in hunk at line %ld\n",
+ p_hunk_beg);
+ p_line[filldst] = p_line[fillsrc];
+ p_char[filldst] = p_char[fillsrc];
+ p_len[filldst] = p_len[fillsrc];
+ fillsrc++;
+ filldst++;
+ }
+ while (fillsrc <= p_end && fillsrc != repl_beginning &&
+ p_char[fillsrc] != ' ')
+ fillsrc++;
+#ifdef DEBUGGING
+ if (debug & 64)
+ printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
+ fillsrc, filldst, repl_beginning, p_end + 1);
+#endif
+ if (fillsrc != p_end + 1 && fillsrc != repl_beginning)
+ malformed();
+ if (filldst != p_end + 1 && filldst != repl_beginning)
+ malformed();
+ }
+ if (p_line[p_end] != NULL) {
+ if (remove_special_line()) {
+ p_len[p_end] -= 1;
+ (p_line[p_end])[p_len[p_end]] = 0;
+ }
+ }
+ } else if (diff_type == UNI_DIFF) {
+ LINENUM fillold; /* index of old lines */
+ LINENUM fillnew; /* index of new lines */
+ char ch;
+
+ line_beginning = ftell(pfp); /* file pos of the current line */
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0 || strnNE(buf, "@@ -", 4)) {
+ next_intuit_at(line_beginning, p_input_line);
+ return false;
+ }
+ s = buf + 4;
+ if (!*s)
+ malformed();
+ p_first = (LINENUM) atol(s);
+ while (isdigit((unsigned char)*s))
+ s++;
+ if (*s == ',') {
+ p_ptrn_lines = (LINENUM) atol(++s);
+ while (isdigit((unsigned char)*s))
+ s++;
+ } else
+ p_ptrn_lines = 1;
+ if (*s == ' ')
+ s++;
+ if (*s != '+' || !*++s)
+ malformed();
+ p_newfirst = (LINENUM) atol(s);
+ while (isdigit((unsigned char)*s))
+ s++;
+ if (*s == ',') {
+ p_repl_lines = (LINENUM) atol(++s);
+ while (isdigit((unsigned char)*s))
+ s++;
+ } else
+ p_repl_lines = 1;
+ if (*s == ' ')
+ s++;
+ if (*s != '@')
+ malformed();
+ if (!p_ptrn_lines)
+ p_first++; /* do append rather than insert */
+ p_max = p_ptrn_lines + p_repl_lines + 1;
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ fillold = 1;
+ fillnew = fillold + p_ptrn_lines;
+ p_end = fillnew + p_repl_lines;
+ snprintf(buf, buf_size, "*** %ld,%ld ****\n", p_first,
+ p_first + p_ptrn_lines - 1);
+ p_line[0] = savestr(buf);
+ if (out_of_mem) {
+ p_end = -1;
+ return false;
+ }
+ p_char[0] = '*';
+ snprintf(buf, buf_size, "--- %ld,%ld ----\n", p_newfirst,
+ p_newfirst + p_repl_lines - 1);
+ p_line[fillnew] = savestr(buf);
+ if (out_of_mem) {
+ p_end = 0;
+ return false;
+ }
+ p_char[fillnew++] = '=';
+ p_context = 100;
+ context = 0;
+ p_hunk_beg = p_input_line + 1;
+ while (fillold <= p_ptrn_lines || fillnew <= p_end) {
+ line_beginning = ftell(pfp);
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0) {
+ if (p_max - fillnew < 3) {
+ /* assume blank lines got chopped */
+ strlcpy(buf, " \n", buf_size);
+ } else {
+ fatal("unexpected end of file in patch\n");
+ }
+ }
+ if (*buf == '\t' || *buf == '\n') {
+ ch = ' '; /* assume the space got eaten */
+ s = savestr(buf);
+ } else {
+ ch = *buf;
+ s = savestr(buf + 1);
+ }
+ if (out_of_mem) {
+ while (--fillnew > p_ptrn_lines)
+ free(p_line[fillnew]);
+ p_end = fillold - 1;
+ return false;
+ }
+ switch (ch) {
+ case '-':
+ if (fillold > p_ptrn_lines) {
+ free(s);
+ p_end = fillnew - 1;
+ malformed();
+ }
+ p_char[fillold] = ch;
+ p_line[fillold] = s;
+ p_len[fillold++] = strlen(s);
+ if (fillold > p_ptrn_lines) {
+ if (remove_special_line()) {
+ p_len[fillold - 1] -= 1;
+ s[p_len[fillold - 1]] = 0;
+ }
+ }
+ break;
+ case '=':
+ ch = ' ';
+ /* FALL THROUGH */
+ case ' ':
+ if (fillold > p_ptrn_lines) {
+ free(s);
+ while (--fillnew > p_ptrn_lines)
+ free(p_line[fillnew]);
+ p_end = fillold - 1;
+ malformed();
+ }
+ context++;
+ p_char[fillold] = ch;
+ p_line[fillold] = s;
+ p_len[fillold++] = strlen(s);
+ s = savestr(s);
+ if (out_of_mem) {
+ while (--fillnew > p_ptrn_lines)
+ free(p_line[fillnew]);
+ p_end = fillold - 1;
+ return false;
+ }
+ if (fillold > p_ptrn_lines) {
+ if (remove_special_line()) {
+ p_len[fillold - 1] -= 1;
+ s[p_len[fillold - 1]] = 0;
+ }
+ }
+ /* FALL THROUGH */
+ case '+':
+ if (fillnew > p_end) {
+ free(s);
+ while (--fillnew > p_ptrn_lines)
+ free(p_line[fillnew]);
+ p_end = fillold - 1;
+ malformed();
+ }
+ p_char[fillnew] = ch;
+ p_line[fillnew] = s;
+ p_len[fillnew++] = strlen(s);
+ if (fillold > p_ptrn_lines) {
+ if (remove_special_line()) {
+ p_len[fillnew - 1] -= 1;
+ s[p_len[fillnew - 1]] = 0;
+ }
+ }
+ break;
+ default:
+ p_end = fillnew;
+ malformed();
+ }
+ if (ch != ' ' && context > 0) {
+ if (context < p_context)
+ p_context = context;
+ context = -1000;
+ }
+ } /* while */
+ } else { /* normal diff--fake it up */
+ char hunk_type;
+ int i;
+ LINENUM min, max;
+
+ line_beginning = ftell(pfp);
+ p_context = 0;
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0 || !isdigit((unsigned char)*buf)) {
+ next_intuit_at(line_beginning, p_input_line);
+ return false;
+ }
+ p_first = (LINENUM) atol(buf);
+ for (s = buf; isdigit((unsigned char)*s); s++)
+ ;
+ if (*s == ',') {
+ p_ptrn_lines = (LINENUM) atol(++s) - p_first + 1;
+ while (isdigit((unsigned char)*s))
+ s++;
+ } else
+ p_ptrn_lines = (*s != 'a');
+ hunk_type = *s;
+ if (hunk_type == 'a')
+ p_first++; /* do append rather than insert */
+ min = (LINENUM) atol(++s);
+ for (; isdigit((unsigned char)*s); s++)
+ ;
+ if (*s == ',')
+ max = (LINENUM) atol(++s);
+ else
+ max = min;
+ if (hunk_type == 'd')
+ min++;
+ p_end = p_ptrn_lines + 1 + max - min + 1;
+ if (p_end > MAXHUNKSIZE)
+ fatal("hunk too large (%ld lines) at line %ld: %s",
+ p_end, p_input_line, buf);
+ while (p_end >= hunkmax)
+ grow_hunkmax();
+ p_newfirst = min;
+ p_repl_lines = max - min + 1;
+ snprintf(buf, buf_size, "*** %ld,%ld\n", p_first,
+ p_first + p_ptrn_lines - 1);
+ p_line[0] = savestr(buf);
+ if (out_of_mem) {
+ p_end = -1;
+ return false;
+ }
+ p_char[0] = '*';
+ for (i = 1; i <= p_ptrn_lines; i++) {
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0)
+ fatal("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '<')
+ fatal("< expected at line %ld of patch\n",
+ p_input_line);
+ p_line[i] = savestr(buf + 2);
+ if (out_of_mem) {
+ p_end = i - 1;
+ return false;
+ }
+ p_len[i] = strlen(p_line[i]);
+ p_char[i] = '-';
+ }
+
+ if (remove_special_line()) {
+ p_len[i - 1] -= 1;
+ (p_line[i - 1])[p_len[i - 1]] = 0;
+ }
+ if (hunk_type == 'c') {
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0)
+ fatal("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '-')
+ fatal("--- expected at line %ld of patch\n",
+ p_input_line);
+ }
+ snprintf(buf, buf_size, "--- %ld,%ld\n", min, max);
+ p_line[i] = savestr(buf);
+ if (out_of_mem) {
+ p_end = i - 1;
+ return false;
+ }
+ p_char[i] = '=';
+ for (i++; i <= p_end; i++) {
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0)
+ fatal("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '>')
+ fatal("> expected at line %ld of patch\n",
+ p_input_line);
+ p_line[i] = savestr(buf + 2);
+ if (out_of_mem) {
+ p_end = i - 1;
+ return false;
+ }
+ p_len[i] = strlen(p_line[i]);
+ p_char[i] = '+';
+ }
+
+ if (remove_special_line()) {
+ p_len[i - 1] -= 1;
+ (p_line[i - 1])[p_len[i - 1]] = 0;
+ }
+ }
+ if (reverse) /* backwards patch? */
+ if (!pch_swap())
+ say("Not enough memory to swap next hunk!\n");
+#ifdef DEBUGGING
+ if (debug & 2) {
+ int i;
+ char special;
+
+ for (i = 0; i <= p_end; i++) {
+ if (i == p_ptrn_lines)
+ special = '^';
+ else
+ special = ' ';
+ fprintf(stderr, "%3d %c %c %s", i, p_char[i],
+ special, p_line[i]);
+ fflush(stderr);
+ }
+ }
+#endif
+ if (p_end + 1 < hunkmax)/* paranoia reigns supreme... */
+ p_char[p_end + 1] = '^'; /* add a stopper for apply_hunk */
+ return true;
+}
+
+/*
+ * Input a line from the patch file.
+ * Worry about indentation if do_indent is true.
+ * The line is read directly into the buf global variable which
+ * is resized if necessary in order to hold the complete line.
+ * Returns the number of characters read including the terminating
+ * '\n', if any.
+ */
+size_t
+pgets(bool do_indent)
+{
+ char *line;
+ size_t len;
+ int indent = 0, skipped = 0;
+
+ line = fgetln(pfp, &len);
+ if (line != NULL) {
+ if (len + 1 > buf_size) {
+ while (len + 1 > buf_size)
+ buf_size *= 2;
+ free(buf);
+ buf = malloc(buf_size);
+ if (buf == NULL)
+ fatal("out of memory\n");
+ }
+ if (do_indent == 1 && p_indent) {
+ for (;
+ indent < p_indent && (*line == ' ' || *line == '\t' || *line == 'X');
+ line++, skipped++) {
+ if (*line == '\t')
+ indent += 8 - (indent %7);
+ else
+ indent++;
+ }
+ }
+ strncpy(buf, line, len - skipped);
+ buf[len - skipped] = '\0';
+ }
+ return len;
+}
+
+
+/*
+ * Reverse the old and new portions of the current hunk.
+ */
+bool
+pch_swap(void)
+{
+ char **tp_line; /* the text of the hunk */
+ short *tp_len; /* length of each line */
+ char *tp_char; /* +, -, and ! */
+ LINENUM i;
+ LINENUM n;
+ bool blankline = false;
+ char *s;
+
+ i = p_first;
+ p_first = p_newfirst;
+ p_newfirst = i;
+
+ /* make a scratch copy */
+
+ tp_line = p_line;
+ tp_len = p_len;
+ tp_char = p_char;
+ p_line = NULL; /* force set_hunkmax to allocate again */
+ p_len = NULL;
+ p_char = NULL;
+ set_hunkmax();
+ if (p_line == NULL || p_len == NULL || p_char == NULL) {
+
+ free(p_line);
+ p_line = tp_line;
+ free(p_len);
+ p_len = tp_len;
+ free(p_char);
+ p_char = tp_char;
+ return false; /* not enough memory to swap hunk! */
+ }
+ /* now turn the new into the old */
+
+ i = p_ptrn_lines + 1;
+ if (tp_char[i] == '\n') { /* account for possible blank line */
+ blankline = true;
+ i++;
+ }
+ if (p_efake >= 0) { /* fix non-freeable ptr range */
+ if (p_efake <= i)
+ n = p_end - i + 1;
+ else
+ n = -i;
+ p_efake += n;
+ p_bfake += n;
+ }
+ for (n = 0; i <= p_end; i++, n++) {
+ p_line[n] = tp_line[i];
+ p_char[n] = tp_char[i];
+ if (p_char[n] == '+')
+ p_char[n] = '-';
+ p_len[n] = tp_len[i];
+ }
+ if (blankline) {
+ i = p_ptrn_lines + 1;
+ p_line[n] = tp_line[i];
+ p_char[n] = tp_char[i];
+ p_len[n] = tp_len[i];
+ n++;
+ }
+ if (p_char[0] != '=')
+ fatal("Malformed patch at line %ld: expected '=' found '%c'\n",
+ p_input_line, p_char[0]);
+ p_char[0] = '*';
+ for (s = p_line[0]; *s; s++)
+ if (*s == '-')
+ *s = '*';
+
+ /* now turn the old into the new */
+
+ if (p_char[0] != '*')
+ fatal("Malformed patch at line %ld: expected '*' found '%c'\n",
+ p_input_line, p_char[0]);
+ tp_char[0] = '=';
+ for (s = tp_line[0]; *s; s++)
+ if (*s == '*')
+ *s = '-';
+ for (i = 0; n <= p_end; i++, n++) {
+ p_line[n] = tp_line[i];
+ p_char[n] = tp_char[i];
+ if (p_char[n] == '-')
+ p_char[n] = '+';
+ p_len[n] = tp_len[i];
+ }
+
+ if (i != p_ptrn_lines + 1)
+ fatal("Malformed patch at line %ld: expected %ld lines, "
+ "got %ld\n",
+ p_input_line, p_ptrn_lines + 1, i);
+
+ i = p_ptrn_lines;
+ p_ptrn_lines = p_repl_lines;
+ p_repl_lines = i;
+
+ free(tp_line);
+ free(tp_len);
+ free(tp_char);
+
+ return true;
+}
+
+/*
+ * Return the specified line position in the old file of the old context.
+ */
+LINENUM
+pch_first(void)
+{
+ return p_first;
+}
+
+/*
+ * Return the number of lines of old context.
+ */
+LINENUM
+pch_ptrn_lines(void)
+{
+ return p_ptrn_lines;
+}
+
+/*
+ * Return the probable line position in the new file of the first line.
+ */
+LINENUM
+pch_newfirst(void)
+{
+ return p_newfirst;
+}
+
+/*
+ * Return the number of lines in the replacement text including context.
+ */
+LINENUM
+pch_repl_lines(void)
+{
+ return p_repl_lines;
+}
+
+/*
+ * Return the number of lines in the whole hunk.
+ */
+LINENUM
+pch_end(void)
+{
+ return p_end;
+}
+
+/*
+ * Return the number of context lines before the first changed line.
+ */
+LINENUM
+pch_context(void)
+{
+ return p_context;
+}
+
+/*
+ * Return the length of a particular patch line.
+ */
+short
+pch_line_len(LINENUM line)
+{
+ return p_len[line];
+}
+
+/*
+ * Return the control character (+, -, *, !, etc) for a patch line.
+ */
+char
+pch_char(LINENUM line)
+{
+ return p_char[line];
+}
+
+/*
+ * Return a pointer to a particular patch line.
+ */
+char *
+pfetch(LINENUM line)
+{
+ return p_line[line];
+}
+
+/*
+ * Return where in the patch file this hunk began, for error messages.
+ */
+LINENUM
+pch_hunk_beg(void)
+{
+ return p_hunk_beg;
+}
+
+/*
+ * Apply an ed script by feeding ed itself.
+ */
+void
+do_ed_script(void)
+{
+ char *t;
+ long beginning_of_this_line;
+ FILE *pipefp = NULL;
+
+ if (!skip_rest_of_patch) {
+ if (copy_file(filearg[0], TMPOUTNAME) < 0) {
+ unlink(TMPOUTNAME);
+ fatal("can't create temp file %s", TMPOUTNAME);
+ }
+ snprintf(buf, buf_size, "%s%s%s", _PATH_ED,
+ verbose ? " " : " -s ", TMPOUTNAME);
+ pipefp = popen(buf, "w");
+ }
+ for (;;) {
+ beginning_of_this_line = ftell(pfp);
+ if (pgets(true) == 0) {
+ next_intuit_at(beginning_of_this_line, p_input_line);
+ break;
+ }
+ p_input_line++;
+ for (t = buf; isdigit((unsigned char)*t) || *t == ','; t++)
+ ;
+ /* POSIX defines allowed commands as {a,c,d,i,s} */
+ if (isdigit((unsigned char)*buf) && (*t == 'a' || *t == 'c' ||
+ *t == 'd' || *t == 'i' || *t == 's')) {
+ if (pipefp != NULL)
+ fputs(buf, pipefp);
+ if (*t != 'd') {
+ while (pgets(true)) {
+ p_input_line++;
+ if (pipefp != NULL)
+ fputs(buf, pipefp);
+ if (strEQ(buf, ".\n"))
+ break;
+ }
+ }
+ } else {
+ next_intuit_at(beginning_of_this_line, p_input_line);
+ break;
+ }
+ }
+ if (pipefp == NULL)
+ return;
+ fprintf(pipefp, "w\n");
+ fprintf(pipefp, "q\n");
+ fflush(pipefp);
+ pclose(pipefp);
+ ignore_signals();
+ if (!check_only) {
+ if (move_file(TMPOUTNAME, outname) < 0) {
+ toutkeep = true;
+ chmod(TMPOUTNAME, filemode);
+ } else
+ chmod(outname, filemode);
+ }
+ set_signals(1);
+}
+
+/*
+ * Choose the name of the file to be patched based on POSIX rules.
+ * NOTE: the POSIX rules are amazingly stupid and we only follow them
+ * if the user specified --posix or set POSIXLY_CORRECT.
+ */
+static char *
+posix_name(const struct file_name *names, bool assume_exists)
+{
+ char *path = NULL;
+ int i;
+
+ /*
+ * POSIX states that the filename will be chosen from one
+ * of the old, new and index names (in that order) if
+ * the file exists relative to CWD after -p stripping.
+ */
+ for (i = 0; i < MAX_FILE; i++) {
+ if (names[i].path != NULL && names[i].exists) {
+ path = names[i].path;
+ break;
+ }
+ }
+ if (path == NULL && !assume_exists) {
+ /*
+ * No files found, look for something we can checkout from
+ * RCS/SCCS dirs. Same order as above.
+ */
+ for (i = 0; i < MAX_FILE; i++) {
+ if (names[i].path != NULL &&
+ (path = checked_in(names[i].path)) != NULL)
+ break;
+ }
+ /*
+ * Still no match? Check to see if the diff could be creating
+ * a new file.
+ */
+ if (path == NULL && ok_to_create_file &&
+ names[NEW_FILE].path != NULL)
+ path = names[NEW_FILE].path;
+ }
+
+ return path ? savestr(path) : NULL;
+}
+
+/*
+ * Choose the name of the file to be patched based the "best" one
+ * available.
+ */
+static char *
+best_name(const struct file_name *names, bool assume_exists)
+{
+ size_t min_components, min_baselen, min_len, tmp;
+ char *best = NULL;
+ int i;
+
+ /*
+ * The "best" name is the one with the fewest number of path
+ * components, the shortest basename length, and the shortest
+ * overall length (in that order). We only use the Index: file
+ * if neither of the old or new files could be intuited from
+ * the diff header.
+ */
+ min_components = min_baselen = min_len = SIZE_MAX;
+ for (i = INDEX_FILE; i >= OLD_FILE; i--) {
+ if (names[i].path == NULL ||
+ (!names[i].exists && !assume_exists))
+ continue;
+ if ((tmp = num_components(names[i].path)) > min_components)
+ continue;
+ min_components = tmp;
+ if ((tmp = strlen(basename(names[i].path))) > min_baselen)
+ continue;
+ min_baselen = tmp;
+ if ((tmp = strlen(names[i].path)) > min_len)
+ continue;
+ min_len = tmp;
+ best = names[i].path;
+ }
+ if (best == NULL) {
+ /*
+ * No files found, look for something we can checkout from
+ * RCS/SCCS dirs. Logic is identical to that above...
+ */
+ min_components = min_baselen = min_len = SIZE_MAX;
+ for (i = INDEX_FILE; i >= OLD_FILE; i--) {
+ if (names[i].path == NULL ||
+ checked_in(names[i].path) == NULL)
+ continue;
+ if ((tmp = num_components(names[i].path)) > min_components)
+ continue;
+ min_components = tmp;
+ if ((tmp = strlen(basename(names[i].path))) > min_baselen)
+ continue;
+ min_baselen = tmp;
+ if ((tmp = strlen(names[i].path)) > min_len)
+ continue;
+ min_len = tmp;
+ best = names[i].path;
+ }
+ /*
+ * Still no match? Check to see if the diff could be creating
+ * a new file.
+ */
+ if (best == NULL && ok_to_create_file &&
+ names[NEW_FILE].path != NULL)
+ best = names[NEW_FILE].path;
+ }
+
+ return best ? savestr(best) : NULL;
+}
+
+static size_t
+num_components(const char *path)
+{
+ size_t n;
+ const char *cp;
+
+ for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++, cp++) {
+ while (*cp == '/')
+ cp++; /* skip consecutive slashes */
+ }
+ return n;
+}
diff --git a/usr.bin/patch/pch.h b/usr.bin/patch/pch.h
new file mode 100644
index 0000000..42910c2
--- /dev/null
+++ b/usr.bin/patch/pch.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: pch.h,v 1.9 2003/10/31 20:20:45 millert Exp $
+ * $FreeBSD$
+ */
+
+#define OLD_FILE 0
+#define NEW_FILE 1
+#define INDEX_FILE 2
+#define MAX_FILE 3
+
+struct file_name {
+ char *path;
+ bool exists;
+};
+
+void re_patch(void);
+void open_patch_file(const char *);
+void set_hunkmax(void);
+bool there_is_another_patch(void);
+bool another_hunk(void);
+bool pch_swap(void);
+char *pfetch(LINENUM);
+short pch_line_len(LINENUM);
+LINENUM pch_first(void);
+LINENUM pch_ptrn_lines(void);
+LINENUM pch_newfirst(void);
+LINENUM pch_repl_lines(void);
+LINENUM pch_end(void);
+LINENUM pch_context(void);
+LINENUM pch_hunk_beg(void);
+char pch_char(LINENUM);
+void do_ed_script(void);
diff --git a/usr.bin/patch/util.c b/usr.bin/patch/util.c
new file mode 100644
index 0000000..3895b2c
--- /dev/null
+++ b/usr.bin/patch/util.c
@@ -0,0 +1,432 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: util.c,v 1.35 2010/07/24 01:10:12 ray Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "util.h"
+#include "backupfile.h"
+#include "pathnames.h"
+
+/* Rename a file, copying it if necessary. */
+
+int
+move_file(const char *from, const char *to)
+{
+ int fromfd;
+ ssize_t i;
+
+ /* to stdout? */
+
+ if (strEQ(to, "-")) {
+#ifdef DEBUGGING
+ if (debug & 4)
+ say("Moving %s to stdout.\n", from);
+#endif
+ fromfd = open(from, O_RDONLY);
+ if (fromfd < 0)
+ pfatal("internal error, can't reopen %s", from);
+ while ((i = read(fromfd, buf, buf_size)) > 0)
+ if (write(STDOUT_FILENO, buf, i) != i)
+ pfatal("write failed");
+ close(fromfd);
+ return 0;
+ }
+ if (backup_file(to) < 0) {
+ say("Can't backup %s, output is in %s: %s\n", to, from,
+ strerror(errno));
+ return -1;
+ }
+#ifdef DEBUGGING
+ if (debug & 4)
+ say("Moving %s to %s.\n", from, to);
+#endif
+ if (rename(from, to) < 0) {
+ if (errno != EXDEV || copy_file(from, to) < 0) {
+ say("Can't create %s, output is in %s: %s\n",
+ to, from, strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Backup the original file. */
+
+int
+backup_file(const char *orig)
+{
+ struct stat filestat;
+ char bakname[MAXPATHLEN], *s, *simplename;
+ dev_t orig_device;
+ ino_t orig_inode;
+
+ if (backup_type == none || stat(orig, &filestat) != 0)
+ return 0; /* nothing to do */
+ /*
+ * If the user used zero prefixes or suffixes, then
+ * he doesn't want backups. Yet we have to remove
+ * orig to break possible hardlinks.
+ */
+ if ((origprae && *origprae == 0) || *simple_backup_suffix == 0) {
+ unlink(orig);
+ return 0;
+ }
+ orig_device = filestat.st_dev;
+ orig_inode = filestat.st_ino;
+
+ if (origprae) {
+ if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) ||
+ strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname))
+ fatal("filename %s too long for buffer\n", origprae);
+ } else {
+ if ((s = find_backup_file_name(orig)) == NULL)
+ fatal("out of memory\n");
+ if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname))
+ fatal("filename %s too long for buffer\n", s);
+ free(s);
+ }
+
+ if ((simplename = strrchr(bakname, '/')) != NULL)
+ simplename = simplename + 1;
+ else
+ simplename = bakname;
+
+ /*
+ * Find a backup name that is not the same file. Change the
+ * first lowercase char into uppercase; if that isn't
+ * sufficient, chop off the first char and try again.
+ */
+ while (stat(bakname, &filestat) == 0 &&
+ orig_device == filestat.st_dev && orig_inode == filestat.st_ino) {
+ /* Skip initial non-lowercase chars. */
+ for (s = simplename; *s && !islower((unsigned char)*s); s++)
+ ;
+ if (*s)
+ *s = toupper((unsigned char)*s);
+ else
+ memmove(simplename, simplename + 1,
+ strlen(simplename + 1) + 1);
+ }
+#ifdef DEBUGGING
+ if (debug & 4)
+ say("Moving %s to %s.\n", orig, bakname);
+#endif
+ if (rename(orig, bakname) < 0) {
+ if (errno != EXDEV || copy_file(orig, bakname) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Copy a file.
+ */
+int
+copy_file(const char *from, const char *to)
+{
+ int tofd, fromfd;
+ ssize_t i;
+
+ tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666);
+ if (tofd < 0)
+ return -1;
+ fromfd = open(from, O_RDONLY, 0);
+ if (fromfd < 0)
+ pfatal("internal error, can't reopen %s", from);
+ while ((i = read(fromfd, buf, buf_size)) > 0)
+ if (write(tofd, buf, i) != i)
+ pfatal("write to %s failed", to);
+ close(fromfd);
+ close(tofd);
+ return 0;
+}
+
+/*
+ * Allocate a unique area for a string.
+ */
+char *
+savestr(const char *s)
+{
+ char *rv;
+
+ if (!s)
+ s = "Oops";
+ rv = strdup(s);
+ if (rv == NULL) {
+ if (using_plan_a)
+ out_of_mem = true;
+ else
+ fatal("out of memory\n");
+ }
+ return rv;
+}
+
+/*
+ * Vanilla terminal output (buffered).
+ */
+void
+say(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ fflush(stdout);
+}
+
+/*
+ * Terminal output, pun intended.
+ */
+void
+fatal(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "patch: **** ");
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ my_exit(2);
+}
+
+/*
+ * Say something from patch, something from the system, then silence . . .
+ */
+void
+pfatal(const char *fmt, ...)
+{
+ va_list ap;
+ int errnum = errno;
+
+ fprintf(stderr, "patch: **** ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, ": %s\n", strerror(errnum));
+ my_exit(2);
+}
+
+/*
+ * Get a response from the user via /dev/tty
+ */
+void
+ask(const char *fmt, ...)
+{
+ va_list ap;
+ ssize_t nr = 0;
+ static int ttyfd = -1;
+
+ va_start(ap, fmt);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ fflush(stdout);
+ if (ttyfd < 0)
+ ttyfd = open(_PATH_TTY, O_RDONLY);
+ if (ttyfd >= 0) {
+ if ((nr = read(ttyfd, buf, buf_size)) > 0 &&
+ buf[nr - 1] == '\n')
+ buf[nr - 1] = '\0';
+ }
+ if (ttyfd < 0 || nr <= 0) {
+ /* no tty or error reading, pretend user entered 'return' */
+ putchar('\n');
+ buf[0] = '\0';
+ }
+}
+
+/*
+ * How to handle certain events when not in a critical region.
+ */
+void
+set_signals(int reset)
+{
+ static sig_t hupval, intval;
+
+ if (!reset) {
+ hupval = signal(SIGHUP, SIG_IGN);
+ if (hupval != SIG_IGN)
+ hupval = my_exit;
+ intval = signal(SIGINT, SIG_IGN);
+ if (intval != SIG_IGN)
+ intval = my_exit;
+ }
+ signal(SIGHUP, hupval);
+ signal(SIGINT, intval);
+}
+
+/*
+ * How to handle certain events when in a critical region.
+ */
+void
+ignore_signals(void)
+{
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+}
+
+/*
+ * Make sure we'll have the directories to create a file. If `striplast' is
+ * true, ignore the last element of `filename'.
+ */
+
+void
+makedirs(const char *filename, bool striplast)
+{
+ char *tmpbuf;
+
+ if ((tmpbuf = strdup(filename)) == NULL)
+ fatal("out of memory\n");
+
+ if (striplast) {
+ char *s = strrchr(tmpbuf, '/');
+ if (s == NULL) {
+ free(tmpbuf);
+ return; /* nothing to be done */
+ }
+ *s = '\0';
+ }
+ if (mkpath(tmpbuf) != 0)
+ pfatal("creation of %s failed", tmpbuf);
+ free(tmpbuf);
+}
+
+/*
+ * Make filenames more reasonable.
+ */
+char *
+fetchname(const char *at, bool *exists, int strip_leading)
+{
+ char *fullname, *name, *t;
+ int sleading, tab;
+ struct stat filestat;
+
+ if (at == NULL || *at == '\0')
+ return NULL;
+ while (isspace((unsigned char)*at))
+ at++;
+#ifdef DEBUGGING
+ if (debug & 128)
+ say("fetchname %s %d\n", at, strip_leading);
+#endif
+ /* So files can be created by diffing against /dev/null. */
+ if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1))
+ return NULL;
+ name = fullname = t = savestr(at);
+
+ tab = strchr(t, '\t') != NULL;
+ /* Strip off up to `strip_leading' path components and NUL terminate. */
+ for (sleading = strip_leading; *t != '\0' && ((tab && *t != '\t') ||
+ !isspace((unsigned char)*t)); t++) {
+ if (t[0] == '/' && t[1] != '/' && t[1] != '\0')
+ if (--sleading >= 0)
+ name = t + 1;
+ }
+ *t = '\0';
+
+ /*
+ * If no -p option was given (957 is the default value!), we were
+ * given a relative pathname, and the leading directories that we
+ * just stripped off all exist, put them back on.
+ */
+ if (strip_leading == 957 && name != fullname && *fullname != '/') {
+ name[-1] = '\0';
+ if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
+ name[-1] = '/';
+ name = fullname;
+ }
+ }
+ name = savestr(name);
+ free(fullname);
+
+ *exists = stat(name, &filestat) == 0;
+ return name;
+}
+
+/*
+ * Takes the name returned by fetchname and looks in RCS/SCCS directories
+ * for a checked in version.
+ */
+char *
+checked_in(char *file)
+{
+ char *filebase, *filedir, tmpbuf[MAXPATHLEN];
+ struct stat filestat;
+
+ filebase = basename(file);
+ filedir = dirname(file);
+
+#define try(f, a1, a2, a3) \
+(snprintf(tmpbuf, sizeof tmpbuf, f, a1, a2, a3), stat(tmpbuf, &filestat) == 0)
+
+ if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
+ try("%s/RCS/%s%s", filedir, filebase, "") ||
+ try("%s/%s%s", filedir, filebase, RCSSUFFIX) ||
+ try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
+ try("%s/%s%s", filedir, SCCSPREFIX, filebase))
+ return file;
+
+ return NULL;
+}
+
+void
+version(void)
+{
+ fprintf(stderr, "patch (BSD patch) 2.0-FreeBSD\n");
+ my_exit(EXIT_SUCCESS);
+}
+
+/*
+ * Exit with cleanup.
+ */
+void
+my_exit(int status)
+{
+ unlink(TMPINNAME);
+ if (!toutkeep)
+ unlink(TMPOUTNAME);
+ if (!trejkeep)
+ unlink(TMPREJNAME);
+ unlink(TMPPATNAME);
+ exit(status);
+}
diff --git a/usr.bin/patch/util.h b/usr.bin/patch/util.h
new file mode 100644
index 0000000..5759d68
--- /dev/null
+++ b/usr.bin/patch/util.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: util.h,v 1.15 2005/06/20 07:14:06 otto Exp $
+ * $FreeBSD$
+ */
+
+char *fetchname(const char *, bool *, int);
+char *checked_in(char *);
+int backup_file(const char *);
+int move_file(const char *, const char *);
+int copy_file(const char *, const char *);
+void say(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void fatal(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void pfatal(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void ask(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+char *savestr(const char *);
+void set_signals(int);
+void ignore_signals(void);
+void makedirs(const char *, bool);
+void version(void);
+void my_exit(int) __attribute__((noreturn));
+
+/* in mkpath.c */
+extern int mkpath(char *);
diff --git a/usr.bin/procstat/procstat.c b/usr.bin/procstat/procstat.c
index b0cee6b..934e292 100644
--- a/usr.bin/procstat/procstat.c
+++ b/usr.bin/procstat/procstat.c
@@ -216,8 +216,8 @@ main(int argc, char *argv[])
argv += optind;
/* We require that either 0 or 1 mode flags be set. */
- tmp = bflag + cflag + eflag + fflag + (kflag ? 1 : 0) + lflag + sflag +
- tflag + vflag + xflag;
+ tmp = bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) +
+ lflag + sflag + tflag + vflag + xflag;
if (!(tmp == 0 || tmp == 1))
usage();
diff --git a/usr.bin/sort/sort.c b/usr.bin/sort/sort.c
index 69a5a74..7e0ab69 100644
--- a/usr.bin/sort/sort.c
+++ b/usr.bin/sort/sort.c
@@ -434,8 +434,7 @@ parse_memory_buffer_value(const char *value)
100;
break;
default:
- fprintf(stderr, "%s: %s\n", strerror(EINVAL),
- optarg);
+ warnc(EINVAL, "%s", optarg);
membuf = available_free_memory;
}
}
@@ -658,7 +657,7 @@ parse_pos(const char *s, struct key_specs *ks, bool *mef_flags, bool second)
errno = 0;
ks->f2 = (size_t) strtoul(f, NULL, 10);
if (errno != 0)
- errx(2, "%s: -k", strerror(errno));
+ err(2, "-k");
if (ks->f2 == 0) {
warn("%s",getstr(5));
goto end;
@@ -667,7 +666,7 @@ parse_pos(const char *s, struct key_specs *ks, bool *mef_flags, bool second)
errno = 0;
ks->f1 = (size_t) strtoul(f, NULL, 10);
if (errno != 0)
- errx(2, "%s: -k", strerror(errno));
+ err(2, "-k");
if (ks->f1 == 0) {
warn("%s",getstr(5));
goto end;
@@ -685,12 +684,12 @@ parse_pos(const char *s, struct key_specs *ks, bool *mef_flags, bool second)
errno = 0;
ks->c2 = (size_t) strtoul(c, NULL, 10);
if (errno != 0)
- errx(2, "%s: -k", strerror(errno));
+ err(2, "-k");
} else {
errno = 0;
ks->c1 = (size_t) strtoul(c, NULL, 10);
if (errno != 0)
- errx(2, "%s: -k", strerror(errno));
+ err(2, "-k");
if (ks->c1 == 0) {
warn("%s",getstr(6));
goto end;
@@ -987,21 +986,6 @@ main(int argc, char **argv)
set_tmpdir();
set_sort_opts();
-#if 0
- {
- static int counter = 0;
- char fn[128];
- sprintf(fn, "/var/tmp/debug.sort.%d", counter++);
- FILE* f = fopen(fn, "w");
- fprintf(f, ">>sort>>");
- for (int i = 0; i < argc; i++) {
- fprintf(f, "<%s>", argv[i]);
- }
- fprintf(f, "<<sort<<\n");
- fclose(f);
- }
-#endif
-
fix_obsolete_keys(&argc, argv);
while (((c = getopt_long(argc, argv, OPTIONS, long_options, NULL))
@@ -1041,8 +1025,7 @@ main(int argc, char **argv)
if (parse_k(optarg, &(keys[keys_num - 1]))
< 0) {
- errx(2, "%s: -k %s\n",
- strerror(EINVAL), optarg);
+ errc(2, EINVAL, "-k %s", optarg);
}
break;
@@ -1067,8 +1050,7 @@ main(int argc, char **argv)
case 't':
while (strlen(optarg) > 1) {
if (optarg[0] != '\\') {
- errx(2, "%s: %s\n",
- strerror(EINVAL), optarg);
+ errc(2, EINVAL, "%s", optarg);
}
optarg += 1;
if (*optarg == '0') {
@@ -1155,8 +1137,7 @@ main(int argc, char **argv)
errno = 0;
long mof = strtol(optarg, NULL, 10);
if (errno != 0)
- errx(2, "--batch-size: %s",
- strerror(errno));
+ err(2, "--batch-size");
if (mof >= 2)
max_open_files = (size_t) mof + 1;
}
diff --git a/usr.bin/stdbuf/stdbuf.c b/usr.bin/stdbuf/stdbuf.c
index 3831b5e..4346cc8 100644
--- a/usr.bin/stdbuf/stdbuf.c
+++ b/usr.bin/stdbuf/stdbuf.c
@@ -39,7 +39,7 @@ extern char *__progname;
static void
usage(int s)
{
-
+
fprintf(stderr, "Usage: %s [-e 0|L|<sz>] [-i 0|L|<sz>] [-o 0|L|<sz>] "
"<cmd> [args ...]\n", __progname);
exit(s);
@@ -72,8 +72,8 @@ main(int argc, char *argv[])
}
argc -= optind;
argv += optind;
- if (argc < 2)
- usage(0);
+ if (argc == 0)
+ exit(0);
if (ibuf != NULL && setenv("_STDBUF_I", ibuf, 1) == -1)
warn("Failed to set environment variable: %s=%s",
@@ -94,7 +94,7 @@ main(int argc, char *argv[])
if (i < 0 || putenv(preload1) == -1)
warn("Failed to set environment variable: LD_PRELOAD");
-
+
preload0 = getenv("LD_32_PRELOAD");
if (preload0 == NULL)
i = asprintf(&preload1, "LD_32_PRELOAD=" LIBSTDBUF32);
diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c
index 459b58d..856a9a6 100644
--- a/usr.bin/systat/vmstat.c
+++ b/usr.bin/systat/vmstat.c
@@ -79,6 +79,7 @@ static struct Info {
* Virtual memory activity.
*/
u_int v_vm_faults; /* number of address memory faults */
+ u_int v_io_faults; /* page faults requiring I/O */
u_int v_cow_faults; /* number of copy-on-writes */
u_int v_zfod; /* pages zero filled on demand */
u_int v_ozfod; /* optimized zero fill pages */
@@ -324,24 +325,25 @@ labelkre(void)
mvprintw(INTSROW, INTSCOL + 1, "Interrupts");
mvprintw(INTSROW + 1, INTSCOL + 6, "total");
- mvprintw(VMSTATROW, VMSTATCOL + 9, "cow");
- mvprintw(VMSTATROW + 1, VMSTATCOL + 9, "zfod");
- mvprintw(VMSTATROW + 2, VMSTATCOL + 9, "ozfod");
- mvprintw(VMSTATROW + 3, VMSTATCOL + 9 - 1, "%%ozfod");
- mvprintw(VMSTATROW + 4, VMSTATCOL + 9, "daefr");
- mvprintw(VMSTATROW + 5, VMSTATCOL + 9, "prcfr");
- mvprintw(VMSTATROW + 6, VMSTATCOL + 9, "totfr");
- mvprintw(VMSTATROW + 7, VMSTATCOL + 9, "react");
- mvprintw(VMSTATROW + 8, VMSTATCOL + 9, "pdwak");
- mvprintw(VMSTATROW + 9, VMSTATCOL + 9, "pdpgs");
- mvprintw(VMSTATROW + 10, VMSTATCOL + 9, "intrn");
- mvprintw(VMSTATROW + 11, VMSTATCOL + 9, "wire");
- mvprintw(VMSTATROW + 12, VMSTATCOL + 9, "act");
- mvprintw(VMSTATROW + 13, VMSTATCOL + 9, "inact");
- mvprintw(VMSTATROW + 14, VMSTATCOL + 9, "cache");
- mvprintw(VMSTATROW + 15, VMSTATCOL + 9, "free");
- if (LINES - 1 > VMSTATROW + 16)
- mvprintw(VMSTATROW + 16, VMSTATCOL + 9, "buf");
+ mvprintw(VMSTATROW, VMSTATCOL + 9, "ioflt");
+ mvprintw(VMSTATROW + 1, VMSTATCOL + 9, "cow");
+ mvprintw(VMSTATROW + 2, VMSTATCOL + 9, "zfod");
+ mvprintw(VMSTATROW + 3, VMSTATCOL + 9, "ozfod");
+ mvprintw(VMSTATROW + 4, VMSTATCOL + 9 - 1, "%%ozfod");
+ mvprintw(VMSTATROW + 5, VMSTATCOL + 9, "daefr");
+ mvprintw(VMSTATROW + 6, VMSTATCOL + 9, "prcfr");
+ mvprintw(VMSTATROW + 7, VMSTATCOL + 9, "totfr");
+ mvprintw(VMSTATROW + 8, VMSTATCOL + 9, "react");
+ mvprintw(VMSTATROW + 9, VMSTATCOL + 9, "pdwak");
+ mvprintw(VMSTATROW + 10, VMSTATCOL + 9, "pdpgs");
+ mvprintw(VMSTATROW + 11, VMSTATCOL + 9, "intrn");
+ mvprintw(VMSTATROW + 12, VMSTATCOL + 9, "wire");
+ mvprintw(VMSTATROW + 13, VMSTATCOL + 9, "act");
+ mvprintw(VMSTATROW + 14, VMSTATCOL + 9, "inact");
+ mvprintw(VMSTATROW + 15, VMSTATCOL + 9, "cache");
+ mvprintw(VMSTATROW + 16, VMSTATCOL + 9, "free");
+ if (LINES - 1 > VMSTATROW + 17)
+ mvprintw(VMSTATROW + 17, VMSTATCOL + 9, "buf");
mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt");
@@ -493,25 +495,26 @@ showkre(void)
putint(total.t_dw, PROCSROW + 2, PROCSCOL + 8, 3);
putint(total.t_sl, PROCSROW + 2, PROCSCOL + 12, 3);
putint(total.t_sw, PROCSROW + 2, PROCSCOL + 16, 3);
- PUTRATE(v_cow_faults, VMSTATROW, VMSTATCOL + 2, 8 - 2);
- PUTRATE(v_zfod, VMSTATROW + 1, VMSTATCOL + 2, 8 - 2);
- PUTRATE(v_ozfod, VMSTATROW + 2, VMSTATCOL, 8);
+ PUTRATE(v_io_faults, VMSTATROW, VMSTATCOL + 2, 8 - 2);
+ PUTRATE(v_cow_faults, VMSTATROW + 1, VMSTATCOL + 2, 8 - 2);
+ PUTRATE(v_zfod, VMSTATROW + 2, VMSTATCOL + 2, 8 - 2);
+ PUTRATE(v_ozfod, VMSTATROW + 3, VMSTATCOL, 8);
putint(s.v_zfod != 0 ? (int)(s.v_ozfod * 100.0 / s.v_zfod) : 0,
- VMSTATROW + 3, VMSTATCOL + 1, 8 - 1);
- PUTRATE(v_dfree, VMSTATROW + 4, VMSTATCOL + 2, 8 - 2);
- PUTRATE(v_pfree, VMSTATROW + 5, VMSTATCOL + 2, 8 - 2);
- PUTRATE(v_tfree, VMSTATROW + 6, VMSTATCOL, 8);
- PUTRATE(v_reactivated, VMSTATROW + 7, VMSTATCOL, 8);
- PUTRATE(v_pdwakeups, VMSTATROW + 8, VMSTATCOL, 8);
- PUTRATE(v_pdpages, VMSTATROW + 9, VMSTATCOL, 8);
- PUTRATE(v_intrans, VMSTATROW + 10, VMSTATCOL, 8);
- putint(pgtokb(s.v_wire_count), VMSTATROW + 11, VMSTATCOL, 8);
- putint(pgtokb(s.v_active_count), VMSTATROW + 12, VMSTATCOL, 8);
- putint(pgtokb(s.v_inactive_count), VMSTATROW + 13, VMSTATCOL, 8);
- putint(pgtokb(s.v_cache_count), VMSTATROW + 14, VMSTATCOL, 8);
- putint(pgtokb(s.v_free_count), VMSTATROW + 15, VMSTATCOL, 8);
- if (LINES - 1 > VMSTATROW + 16)
- putint(s.bufspace / 1024, VMSTATROW + 16, VMSTATCOL, 8);
+ VMSTATROW + 4, VMSTATCOL + 1, 8 - 1);
+ PUTRATE(v_dfree, VMSTATROW + 5, VMSTATCOL + 2, 8 - 2);
+ PUTRATE(v_pfree, VMSTATROW + 6, VMSTATCOL + 2, 8 - 2);
+ PUTRATE(v_tfree, VMSTATROW + 7, VMSTATCOL, 8);
+ PUTRATE(v_reactivated, VMSTATROW + 8, VMSTATCOL, 8);
+ PUTRATE(v_pdwakeups, VMSTATROW + 9, VMSTATCOL, 8);
+ PUTRATE(v_pdpages, VMSTATROW + 10, VMSTATCOL, 8);
+ PUTRATE(v_intrans, VMSTATROW + 11, VMSTATCOL, 8);
+ putint(pgtokb(s.v_wire_count), VMSTATROW + 12, VMSTATCOL, 8);
+ putint(pgtokb(s.v_active_count), VMSTATROW + 13, VMSTATCOL, 8);
+ putint(pgtokb(s.v_inactive_count), VMSTATROW + 14, VMSTATCOL, 8);
+ putint(pgtokb(s.v_cache_count), VMSTATROW + 15, VMSTATCOL, 8);
+ putint(pgtokb(s.v_free_count), VMSTATROW + 16, VMSTATCOL, 8);
+ if (LINES - 1 > VMSTATROW + 17)
+ putint(s.bufspace / 1024, VMSTATROW + 17, VMSTATCOL, 8);
PUTRATE(v_vnodein, PAGEROW + 2, PAGECOL + 6, 5);
PUTRATE(v_vnodeout, PAGEROW + 2, PAGECOL + 12, 5);
PUTRATE(v_swapin, PAGEROW + 2, PAGECOL + 19, 5);
@@ -751,6 +754,7 @@ getinfo(struct Info *ls)
GETSYSCTL("vm.stats.sys.v_intr", ls->v_intr);
GETSYSCTL("vm.stats.sys.v_soft", ls->v_soft);
GETSYSCTL("vm.stats.vm.v_vm_faults", ls->v_vm_faults);
+ GETSYSCTL("vm.stats.vm.v_io_faults", ls->v_io_faults);
GETSYSCTL("vm.stats.vm.v_cow_faults", ls->v_cow_faults);
GETSYSCTL("vm.stats.vm.v_zfod", ls->v_zfod);
GETSYSCTL("vm.stats.vm.v_ozfod", ls->v_ozfod);
diff --git a/usr.bin/tr/tr.c b/usr.bin/tr/tr.c
index c2b6bf8..6eea2cb 100644
--- a/usr.bin/tr/tr.c
+++ b/usr.bin/tr/tr.c
@@ -47,6 +47,7 @@ static const char sccsid[] = "@(#)tr.c 8.2 (Berkeley) 5/4/95";
#include <err.h>
#include <limits.h>
#include <locale.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -267,7 +268,7 @@ endloop:
*/
s2.str = argv[1];
s2.state = NORMAL;
- for (cnt = 0; cnt < WCHAR_MAX; cnt++) {
+ for (cnt = 0; cnt < WINT_MAX; cnt++) {
if (Cflag && !iswrune(cnt))
continue;
if (cmap_lookup(map, cnt) == OOBCH) {
diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c
index 02c6930..4e9f74b 100644
--- a/usr.bin/truss/main.c
+++ b/usr.bin/truss/main.c
@@ -234,15 +234,12 @@ main(int ac, char **av)
usage();
if (fname != NULL) { /* Use output file */
- if ((trussinfo->outfile = fopen(fname, "w")) == NULL)
- errx(1, "cannot open %s", fname);
/*
- * Set FD_CLOEXEC, so that the output file is not shared with
- * the traced process.
+ * Set close-on-exec ('e'), so that the output file is not
+ * shared with the traced process.
*/
- if (fcntl(fileno(trussinfo->outfile), F_SETFD, FD_CLOEXEC) ==
- -1)
- warn("fcntl()");
+ if ((trussinfo->outfile = fopen(fname, "we")) == NULL)
+ err(1, "cannot open %s", fname);
}
/*
diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c
index fe3a29c..c089dbf 100644
--- a/usr.bin/vmstat/vmstat.c
+++ b/usr.bin/vmstat/vmstat.c
@@ -469,6 +469,7 @@ fill_vmmeter(struct vmmeter *vmmp)
ADD_FROM_PCPU(i, v_intr);
ADD_FROM_PCPU(i, v_soft);
ADD_FROM_PCPU(i, v_vm_faults);
+ ADD_FROM_PCPU(i, v_io_faults);
ADD_FROM_PCPU(i, v_cow_faults);
ADD_FROM_PCPU(i, v_cow_optim);
ADD_FROM_PCPU(i, v_zfod);
@@ -507,6 +508,7 @@ fill_vmmeter(struct vmmeter *vmmp)
/* vm */
GET_VM_STATS(vm, v_vm_faults);
+ GET_VM_STATS(vm, v_io_faults);
GET_VM_STATS(vm, v_cow_faults);
GET_VM_STATS(vm, v_cow_optim);
GET_VM_STATS(vm, v_zfod);
@@ -968,6 +970,7 @@ dosum(void)
(void)printf("%9u zero fill pages prezeroed\n", sum.v_ozfod);
(void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
(void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
+ (void)printf("%9u page faults requiring I/O\n", sum.v_io_faults);
(void)printf("%9u pages affected by kernel thread creation\n", sum.v_kthreadpages);
(void)printf("%9u pages affected by fork()\n", sum.v_forkpages);
(void)printf("%9u pages affected by vfork()\n", sum.v_vforkpages);
diff --git a/usr.bin/w/w.c b/usr.bin/w/w.c
index 2e19bb1..1b9af5f 100644
--- a/usr.bin/w/w.c
+++ b/usr.bin/w/w.c
@@ -123,7 +123,7 @@ static struct stat *ttystat(char *);
static void usage(int);
static int this_is_uptime(const char *s);
-char *fmt_argv(char **, char *, int); /* ../../bin/ps/fmt.c */
+char *fmt_argv(char **, char *, char *, size_t); /* ../../bin/ps/fmt.c */
int
main(int argc, char *argv[])
@@ -320,7 +320,7 @@ main(int argc, char *argv[])
continue;
}
ep->args = fmt_argv(kvm_getargv(kd, ep->kp, argwidth),
- ep->kp->ki_comm, MAXCOMLEN);
+ ep->kp->ki_comm, NULL, MAXCOMLEN);
if (ep->args == NULL)
err(1, NULL);
}
@@ -404,7 +404,7 @@ main(int argc, char *argv[])
const char *ptr;
ptr = fmt_argv(kvm_getargv(kd, dkp, argwidth),
- dkp->ki_comm, MAXCOMLEN);
+ dkp->ki_comm, NULL, MAXCOMLEN);
if (ptr == NULL)
ptr = "-";
(void)printf("\t\t%-9d %s\n",
diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile
index e6ff88e..d9d5873 100644
--- a/usr.bin/xinstall/Makefile
+++ b/usr.bin/xinstall/Makefile
@@ -3,6 +3,14 @@
PROG= xinstall
PROGNAME= install
+SRCS= xinstall.c getid.c
MAN= install.1
+.PATH: ${.CURDIR}/../../contrib/mtree
+CFLAGS+= -I${.CURDIR}/../../contrib/mtree
+CFLAGS+= -I${.CURDIR}/../../lib/libnetbsd
+
+DPADD+= ${LIBUTIL} ${LIBMD}
+LDADD+= -lutil -lmd
+
.include <bsd.prog.mk>
diff --git a/usr.bin/xinstall/install.1 b/usr.bin/xinstall/install.1
index 1c7c415..6fc038e 100644
--- a/usr.bin/xinstall/install.1
+++ b/usr.bin/xinstall/install.1
@@ -28,7 +28,7 @@
.\" From: @(#)install.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd March 6, 2006
+.Dd January 18, 2013
.Dt INSTALL 1
.Os
.Sh NAME
@@ -36,31 +36,50 @@
.Nd install binaries
.Sh SYNOPSIS
.Nm
-.Op Fl bCcMpSsv
+.Op Fl bCcpSsUv
.Op Fl B Ar suffix
+.Op Fl D Ar destdir
.Op Fl f Ar flags
.Op Fl g Ar group
+.Op Fl h Ar hash
+.Op Fl l Ar linkflags
+.Op Fl M Ar metalog
.Op Fl m Ar mode
+.Op Fl N Ar dbdir
.Op Fl o Ar owner
+.Op Fl T Ar tags
.Ar file1 file2
.Nm
-.Op Fl bCcMpSsv
+.Op Fl bCcpSsUv
.Op Fl B Ar suffix
+.Op Fl D Ar destdir
.Op Fl f Ar flags
.Op Fl g Ar group
+.Op Fl h Ar hash
+.Op Fl l Ar linkflags
+.Op Fl M Ar metalog
.Op Fl m Ar mode
+.Op Fl N Ar dbdir
.Op Fl o Ar owner
+.Op Fl T Ar tags
.Ar file1 ... fileN directory
.Nm
.Fl d
-.Op Fl v
+.Op Fl Uv
+.Op Fl D Ar destdir
.Op Fl g Ar group
+.Op Fl h Ar hash
+.Op Fl M Ar metalog
.Op Fl m Ar mode
+.Op Fl N Ar dbdir
.Op Fl o Ar owner
+.Op Fl T Ar tags
.Ar directory ...
.Sh DESCRIPTION
The file(s) are copied
-to the target file or directory.
+(or linked if the
+.Fl l
+option is specified) to the target file or directory.
If the destination is a directory, then the
.Ar file
is copied into
@@ -105,6 +124,17 @@ This is actually the default.
The
.Fl c
option is only included for backwards compatibility.
+.It Fl D Ar destdir
+Specify the
+.Ev DESTDIR
+(top of the file hierarchy) that the items are installed in to.
+If
+.Fl M Ar metalog
+is in use, a leading string of
+.Dq Ar destdir
+will be removed from the file names logged to the
+.Ar metalog .
+This option does not affect where the actual files are installed.
.It Fl d
Create directories.
Missing parent directories are created as required.
@@ -115,15 +145,82 @@ for a list of possible flags and their meanings.
.It Fl g
Specify a group.
A numeric GID is allowed.
-.It Fl M
-Disable all use of
-.Xr mmap 2 .
+.It Fl h Ar hash
+When copying, calculate the digest of the files with
+.Ar hash
+to store in the
+.Fl M Ar metalog .
+When
+.Fl d
+is given no hash is emitted.
+Supported digests:
+.Bl -tag -width rmd160 -offset indent
+.It Sy none
+No hash.
+This is the default.
+.It Sy md5
+The MD5 cryptographic message digest.
+.It Sy rmd160
+The RMD-160 cryptographic message digest.
+.It Sy sha1
+The SHA-1 cryptographic message digest.
+.It Sy sha256
+The 256-bits
+.Tn SHA-2
+cryptographic message digest of the file.
+.It Sy sha512
+The 512-bits
+.Tn SHA-2
+cryptographic message digest of the file.
+.El
+.It Fl l Ar linkflags
+Instead of copying the file make a link to the source.
+The type of the link is determined by the
+.Ar linkflags
+argument.
+Valid
+.Ar linkflags
+are:
+.Ar a
+(absolute),
+.Ar r
+(relative),
+.Ar h
+(hard),
+.Ar s
+(symbolic),
+.Ar m
+(mixed).
+Absolute and relative have effect only for symbolic links.
+Mixed links
+are hard links for files on the same filesystem, symbolic otherwise.
+.It Fl M Ar metalog
+Write the metadata associated with each item installed to
+.Ar metalog
+in an
+.Xr mtree 8
+.Dq full path
+specification line.
+The metadata includes: the file name and file type, and depending upon
+other options, the owner, group, file flags, modification time, and tags.
.It Fl m
Specify an alternate mode.
The default mode is set to rwxr-xr-x (0755).
The specified mode may be either an octal or symbolic value; see
.Xr chmod 1
for a description of possible mode values.
+.It Fl N
+Use the user database text file
+.Pa master.passwd
+and group database text file
+.Pa group
+from
+.Ar dbdir ,
+rather than using the results from the system's
+.Xr getpwnam 3
+and
+.Xr getgrnam 3
+(and related) library calls.
.It Fl o
Specify an owner.
A numeric UID is allowed.
@@ -156,6 +253,17 @@ number of systems and binary types.
See below for how
.Nm
can be instructed to use another program to strip binaries.
+.It Fl T Ar tags
+Specify the
+.Xr mtree 8
+tags to write out for the file when using
+.Fl M Ar metalog .
+.It Fl U
+Indicate that install is running unprivileged, and that it should not
+try to change the owner, the group, or the file flags of the destination.
+The information that would have been updated can be stored in a log
+file with
+.Fl M Ar metalog .
.It Fl v
Cause
.Nm
@@ -231,6 +339,8 @@ The default was changed to copy in
.Xr mv 1 ,
.Xr strip 1 ,
.Xr mmap 2 ,
+.Xr getgrnam 3 ,
+.Xr getpwnam 3 ,
.Xr chown 8
.Sh HISTORY
The
@@ -238,6 +348,16 @@ The
utility appeared in
.Bx 4.2 .
.Sh BUGS
+The meaning of the
+.Fl M
+option has changed as of
+.Fx 10
+and it now takes an argument.
+Command lines that used the old
+.Fl M
+will get an error or in rare cases will append logs to the first of
+multiple source files rather than installing it.
+.Pp
Temporary files may be left in the target directory if
.Nm
exits abnormally.
diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c
index 583348a..15b115a 100644
--- a/usr.bin/xinstall/xinstall.c
+++ b/usr.bin/xinstall/xinstall.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2012, 2013 SRI International
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -53,14 +54,23 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
+#include <libgen.h>
+#include <md5.h>
#include <paths.h>
#include <pwd.h>
+#include <ripemd.h>
+#include <sha.h>
+#include <sha256.h>
+#include <sha512.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
+#include <vis.h>
+
+#include "mtree.h"
/* Bootstrap aid - this doesn't exist in most older releases */
#ifndef MAP_FAILED
@@ -69,27 +79,63 @@ __FBSDID("$FreeBSD$");
#define MAX_CMP_SIZE (16 * 1024 * 1024)
+#define LN_ABSOLUTE 0x01
+#define LN_RELATIVE 0x02
+#define LN_HARD 0x04
+#define LN_SYMBOLIC 0x08
+#define LN_MIXED 0x10
+
#define DIRECTORY 0x01 /* Tell install it's a directory. */
#define SETFLAGS 0x02 /* Tell install to set flags. */
#define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
#define BACKUP_SUFFIX ".old"
-static struct passwd *pp;
-static struct group *gp;
+typedef union {
+ MD5_CTX MD5;
+ RIPEMD160_CTX RIPEMD160;
+ SHA1_CTX SHA1;
+ SHA256_CTX SHA256;
+ SHA512_CTX SHA512;
+} DIGEST_CTX;
+
+static enum {
+ DIGEST_NONE = 0,
+ DIGEST_MD5,
+ DIGEST_RIPEMD160,
+ DIGEST_SHA1,
+ DIGEST_SHA256,
+ DIGEST_SHA512,
+} digesttype = DIGEST_NONE;
+
static gid_t gid;
static uid_t uid;
-static int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy,
- verbose;
+static int dobackup, docompare, dodir, dolink, dopreserve, dostrip, dounpriv,
+ safecopy, verbose;
+static int haveopt_f, haveopt_g, haveopt_m, haveopt_o;
static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+static FILE *metafp;
+static const char *group, *owner;
static const char *suffix = BACKUP_SUFFIX;
+static char *destdir, *digest, *fflags, *metafile, *tags;
-static int compare(int, const char *, size_t, int, const char *, size_t);
-static void copy(int, const char *, int, const char *, off_t);
+static int compare(int, const char *, size_t, int, const char *, size_t,
+ char **);
+static char *copy(int, const char *, int, const char *, off_t);
static int create_newfile(const char *, int, struct stat *);
static int create_tempfile(const char *, char *, size_t);
+static char *quiet_mktemp(char *template);
+static char *digest_file(const char *);
+static void digest_init(DIGEST_CTX *);
+static void digest_update(DIGEST_CTX *, const unsigned char *, size_t);
+static char *digest_end(DIGEST_CTX *, char *);
+static int do_link(const char *, const char *, const struct stat *);
+static void do_symlink(const char *, const char *, const struct stat *);
+static void makelink(const char *, const char *, const struct stat *);
static void install(const char *, const char *, u_long, u_int);
static void install_dir(char *);
-static u_long numeric_id(const char *, const char *);
+static void metadata_log(const char *, const char *, struct timeval *,
+ const char *, const char *, off_t);
+static int parseid(const char *, id_t *);
static void strip(const char *);
static int trymmap(int);
static void usage(void);
@@ -102,12 +148,13 @@ main(int argc, char *argv[])
u_long fset;
int ch, no_target;
u_int iflags;
- char *flags;
- const char *group, *owner, *to_name;
+ char *p;
+ const char *to_name;
iflags = 0;
group = owner = NULL;
- while ((ch = getopt(argc, argv, "B:bCcdf:g:Mm:o:pSsv")) != -1)
+ while ((ch = getopt(argc, argv, "B:bCcD:df:g:h:l:M:m:N:o:pSsT:Uv")) !=
+ -1)
switch((char)ch) {
case 'B':
suffix = optarg;
@@ -121,29 +168,69 @@ main(int argc, char *argv[])
case 'c':
/* For backwards compatibility. */
break;
+ case 'D':
+ destdir = optarg;
+ break;
case 'd':
dodir = 1;
break;
case 'f':
- flags = optarg;
- if (strtofflags(&flags, &fset, NULL))
- errx(EX_USAGE, "%s: invalid flag", flags);
- iflags |= SETFLAGS;
+ haveopt_f = 1;
+ fflags = optarg;
break;
case 'g':
+ haveopt_g = 1;
group = optarg;
break;
+ case 'h':
+ digest = optarg;
+ break;
+ case 'l':
+ for (p = optarg; *p != '\0'; p++)
+ switch (*p) {
+ case 's':
+ dolink &= ~(LN_HARD|LN_MIXED);
+ dolink |= LN_SYMBOLIC;
+ break;
+ case 'h':
+ dolink &= ~(LN_SYMBOLIC|LN_MIXED);
+ dolink |= LN_HARD;
+ break;
+ case 'm':
+ dolink &= ~(LN_SYMBOLIC|LN_HARD);
+ dolink |= LN_MIXED;
+ break;
+ case 'a':
+ dolink &= ~LN_RELATIVE;
+ dolink |= LN_ABSOLUTE;
+ break;
+ case 'r':
+ dolink &= ~LN_ABSOLUTE;
+ dolink |= LN_RELATIVE;
+ break;
+ default:
+ errx(1, "%c: invalid link type", *p);
+ /* NOTREACHED */
+ }
+ break;
case 'M':
- nommap = 1;
+ metafile = optarg;
break;
case 'm':
+ haveopt_m = 1;
if (!(set = setmode(optarg)))
errx(EX_USAGE, "invalid file mode: %s",
optarg);
mode = getmode(set, 0);
free(set);
break;
+ case 'N':
+ if (!setup_getid(optarg))
+ err(EX_OSERR, "Unable to use user and group "
+ "databases in `%s'", optarg);
+ break;
case 'o':
+ haveopt_o = 1;
owner = optarg;
break;
case 'p':
@@ -155,6 +242,12 @@ main(int argc, char *argv[])
case 's':
dostrip = 1;
break;
+ case 'T':
+ tags = optarg;
+ break;
+ case 'U':
+ dounpriv = 1;
+ break;
case 'v':
verbose = 1;
break;
@@ -180,27 +273,62 @@ main(int argc, char *argv[])
if (argc == 0 || (argc == 1 && !dodir))
usage();
+ if (digest != NULL) {
+ if (strcmp(digest, "none") == 0) {
+ digesttype = DIGEST_NONE;
+ } else if (strcmp(digest, "md5") == 0) {
+ digesttype = DIGEST_MD5;
+ } else if (strcmp(digest, "rmd160") == 0) {
+ digesttype = DIGEST_RIPEMD160;
+ } else if (strcmp(digest, "sha1") == 0) {
+ digesttype = DIGEST_SHA1;
+ } else if (strcmp(digest, "sha256") == 0) {
+ digesttype = DIGEST_SHA256;
+ } else if (strcmp(digest, "sha512") == 0) {
+ digesttype = DIGEST_SHA512;
+ } else {
+ warnx("unknown digest `%s'", digest);
+ usage();
+ }
+ }
+
/* need to make a temp copy so we can compare stripped version */
if (docompare && dostrip)
safecopy = 1;
/* get group and owner id's */
- if (group != NULL) {
- if ((gp = getgrnam(group)) != NULL)
- gid = gp->gr_gid;
- else
- gid = (gid_t)numeric_id(group, "group");
+ if (group != NULL && !dounpriv) {
+ if (gid_from_group(group, &gid) == -1) {
+ id_t id;
+ if (!parseid(group, &id))
+ errx(1, "unknown group %s", group);
+ gid = id;
+ }
} else
gid = (gid_t)-1;
- if (owner != NULL) {
- if ((pp = getpwnam(owner)) != NULL)
- uid = pp->pw_uid;
- else
- uid = (uid_t)numeric_id(owner, "user");
+ if (owner != NULL && !dounpriv) {
+ if (uid_from_user(owner, &uid) == -1) {
+ id_t id;
+ if (!parseid(owner, &id))
+ errx(1, "unknown user %s", owner);
+ uid = id;
+ }
} else
uid = (uid_t)-1;
+ if (fflags != NULL && !dounpriv) {
+ if (strtofflags(&fflags, &fset, NULL))
+ errx(EX_USAGE, "%s: invalid flag", fflags);
+ iflags |= SETFLAGS;
+ }
+
+ if (metafile != NULL) {
+ if ((metafp = fopen(metafile, "a")) == NULL)
+ warn("open %s", metafile);
+ } else
+ digesttype = DIGEST_NONE;
+
if (dodir) {
for (; *argv != NULL; ++argv)
install_dir(*argv);
@@ -208,8 +336,21 @@ main(int argc, char *argv[])
/* NOTREACHED */
}
- no_target = stat(to_name = argv[argc - 1], &to_sb);
+ to_name = argv[argc - 1];
+ no_target = stat(to_name, &to_sb);
if (!no_target && S_ISDIR(to_sb.st_mode)) {
+ if (dolink & LN_SYMBOLIC) {
+ if (lstat(to_name, &to_sb) != 0)
+ err(EX_OSERR, "%s vanished", to_name);
+ if (S_ISLNK(to_sb.st_mode)) {
+ if (argc != 2) {
+ errno = ENOTDIR;
+ err(EX_USAGE, "%s", to_name);
+ }
+ install(*argv, to_name, fset, iflags);
+ exit(EX_OK);
+ }
+ }
for (; *argv != to_name; ++argv)
install(*argv, to_name, fset, iflags | DIRECTORY);
exit(EX_OK);
@@ -227,7 +368,7 @@ main(int argc, char *argv[])
usage();
}
- if (!no_target) {
+ if (!no_target && !dolink) {
if (stat(*argv, &from_sb))
err(EX_OSERR, "%s", *argv);
if (!S_ISREG(to_sb.st_mode)) {
@@ -244,23 +385,327 @@ main(int argc, char *argv[])
/* NOTREACHED */
}
-static u_long
-numeric_id(const char *name, const char *type)
+static char *
+digest_file(const char *name)
+{
+
+ switch (digesttype) {
+ case DIGEST_MD5:
+ return (MD5File(name, NULL));
+ case DIGEST_RIPEMD160:
+ return (RIPEMD160_File(name, NULL));
+ case DIGEST_SHA1:
+ return (SHA1_File(name, NULL));
+ case DIGEST_SHA256:
+ return (SHA256_File(name, NULL));
+ case DIGEST_SHA512:
+ return (SHA512_File(name, NULL));
+ default:
+ return (NULL);
+ }
+}
+
+static void
+digest_init(DIGEST_CTX *c)
+{
+
+ switch (digesttype) {
+ case DIGEST_NONE:
+ break;
+ case DIGEST_MD5:
+ MD5Init(&(c->MD5));
+ break;
+ case DIGEST_RIPEMD160:
+ RIPEMD160_Init(&(c->RIPEMD160));
+ break;
+ case DIGEST_SHA1:
+ SHA1_Init(&(c->SHA1));
+ break;
+ case DIGEST_SHA256:
+ SHA256_Init(&(c->SHA256));
+ break;
+ case DIGEST_SHA512:
+ SHA512_Init(&(c->SHA512));
+ break;
+ }
+}
+
+static void
+digest_update(DIGEST_CTX *c, const unsigned char *data, size_t len)
+{
+
+ switch (digesttype) {
+ case DIGEST_NONE:
+ break;
+ case DIGEST_MD5:
+ MD5Update(&(c->MD5), data, len);
+ break;
+ case DIGEST_RIPEMD160:
+ RIPEMD160_Update(&(c->RIPEMD160), data, len);
+ break;
+ case DIGEST_SHA1:
+ SHA1_Update(&(c->SHA1), data, len);
+ break;
+ case DIGEST_SHA256:
+ SHA256_Update(&(c->SHA256), data, len);
+ break;
+ case DIGEST_SHA512:
+ SHA512_Update(&(c->SHA512), data, len);
+ break;
+ }
+}
+
+static char *
+digest_end(DIGEST_CTX *c, char *buf)
+{
+
+ switch (digesttype) {
+ case DIGEST_MD5:
+ return (MD5End(&(c->MD5), buf));
+ case DIGEST_RIPEMD160:
+ return (RIPEMD160_End(&(c->RIPEMD160), buf));
+ case DIGEST_SHA1:
+ return (SHA1_End(&(c->SHA1), buf));
+ case DIGEST_SHA256:
+ return (SHA256_End(&(c->SHA256), buf));
+ case DIGEST_SHA512:
+ return (SHA512_End(&(c->SHA512), buf));
+ default:
+ return (NULL);
+ }
+}
+
+/*
+ * parseid --
+ * parse uid or gid from arg into id, returning non-zero if successful
+ */
+static int
+parseid(const char *name, id_t *id)
+{
+ char *ep;
+ errno = 0;
+ *id = (id_t)strtoul(name, &ep, 10);
+ if (errno || *ep != '\0')
+ return (0);
+ return (1);
+}
+
+/*
+ * quiet_mktemp --
+ * mktemp implementation used mkstemp to avoid mktemp warnings. We
+ * really do need mktemp semantics here as we will be creating a link.
+ */
+static char *
+quiet_mktemp(char *template)
+{
+ int fd;
+
+ if ((fd = mkstemp(template)) == -1)
+ return (NULL);
+ close (fd);
+ if (unlink(template) == -1)
+ err(EX_OSERR, "unlink %s", template);
+ return (template);
+}
+
+/*
+ * do_link --
+ * make a hard link, obeying dorename if set
+ * return -1 on failure
+ */
+static int
+do_link(const char *from_name, const char *to_name,
+ const struct stat *target_sb)
+{
+ char tmpl[MAXPATHLEN];
+ int ret;
+
+ if (safecopy && target_sb != NULL) {
+ (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
+ /* This usage is safe. */
+ if (quiet_mktemp(tmpl) == NULL)
+ err(EX_OSERR, "%s: mktemp", tmpl);
+ ret = link(from_name, tmpl);
+ if (ret == 0) {
+ if (target_sb->st_mode & S_IFDIR && rmdir(to_name) ==
+ -1) {
+ unlink(tmpl);
+ err(EX_OSERR, "%s", to_name);
+ }
+ if (target_sb->st_flags & NOCHANGEBITS)
+ (void)chflags(to_name, target_sb->st_flags &
+ ~NOCHANGEBITS);
+ unlink(to_name);
+ ret = rename(tmpl, to_name);
+ /*
+ * If rename has posix semantics, then the temporary
+ * file may still exist when from_name and to_name point
+ * to the same file, so unlink it unconditionally.
+ */
+ (void)unlink(tmpl);
+ }
+ return (ret);
+ } else
+ return (link(from_name, to_name));
+}
+
+/*
+ * do_symlink --
+ * Make a symbolic link, obeying dorename if set. Exit on failure.
+ */
+static void
+do_symlink(const char *from_name, const char *to_name,
+ const struct stat *target_sb)
{
- u_long val;
- char *ep;
+ char tmpl[MAXPATHLEN];
+
+ if (safecopy && target_sb != NULL) {
+ (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
+ /* This usage is safe. */
+ if (quiet_mktemp(tmpl) == NULL)
+ err(EX_OSERR, "%s: mktemp", tmpl);
+
+ if (symlink(from_name, tmpl) == -1)
+ err(EX_OSERR, "symlink %s -> %s", from_name, tmpl);
+
+ if (target_sb->st_mode & S_IFDIR && rmdir(to_name) == -1) {
+ (void)unlink(tmpl);
+ err(EX_OSERR, "%s", to_name);
+ }
+ if (target_sb->st_flags & NOCHANGEBITS)
+ (void)chflags(to_name, target_sb->st_flags &
+ ~NOCHANGEBITS);
+ unlink(to_name);
+
+ if (rename(tmpl, to_name) == -1) {
+ /* Remove temporary link before exiting. */
+ (void)unlink(tmpl);
+ err(EX_OSERR, "%s: rename", to_name);
+ }
+ } else {
+ if (symlink(from_name, to_name) == -1)
+ err(EX_OSERR, "symlink %s -> %s", from_name, to_name);
+ }
+}
+
+/*
+ * makelink --
+ * make a link from source to destination
+ */
+static void
+makelink(const char *from_name, const char *to_name,
+ const struct stat *target_sb)
+{
+ char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN];
+ struct stat to_sb;
+
+ /* Try hard links first. */
+ if (dolink & (LN_HARD|LN_MIXED)) {
+ if (do_link(from_name, to_name, target_sb) == -1) {
+ if ((dolink & LN_HARD) || errno != EXDEV)
+ err(EX_OSERR, "link %s -> %s", from_name, to_name);
+ } else {
+ if (stat(to_name, &to_sb))
+ err(EX_OSERR, "%s: stat", to_name);
+ if (S_ISREG(to_sb.st_mode)) {
+ /*
+ * XXX: hard links to anything other than
+ * plain files are not metalogged
+ */
+ int omode;
+ const char *oowner, *ogroup;
+ char *offlags;
+ char *dres;
+
+ /*
+ * XXX: use underlying perms, unless
+ * overridden on command line.
+ */
+ omode = mode;
+ if (!haveopt_m)
+ mode = (to_sb.st_mode & 0777);
+ oowner = owner;
+ if (!haveopt_o)
+ owner = NULL;
+ ogroup = group;
+ if (!haveopt_g)
+ group = NULL;
+ offlags = fflags;
+ if (!haveopt_f)
+ fflags = NULL;
+ dres = digest_file(from_name);
+ metadata_log(to_name, "file", NULL, NULL,
+ dres, to_sb.st_size);
+ free(dres);
+ mode = omode;
+ owner = oowner;
+ group = ogroup;
+ fflags = offlags;
+ }
+ return;
+ }
+ }
+
+ /* Symbolic links. */
+ if (dolink & LN_ABSOLUTE) {
+ /* Convert source path to absolute. */
+ if (realpath(from_name, src) == NULL)
+ err(EX_OSERR, "%s: realpath", from_name);
+ do_symlink(src, to_name, target_sb);
+ /* XXX: src may point outside of destdir */
+ metadata_log(to_name, "link", NULL, src, NULL, 0);
+ return;
+ }
+
+ if (dolink & LN_RELATIVE) {
+ char *cp, *d, *s;
+
+ /* Resolve pathnames. */
+ if (realpath(from_name, src) == NULL)
+ err(EX_OSERR, "%s: realpath", from_name);
+
+ /*
+ * The last component of to_name may be a symlink,
+ * so use realpath to resolve only the directory.
+ */
+ cp = dirname(to_name);
+ if (realpath(cp, dst) == NULL)
+ err(EX_OSERR, "%s: realpath", cp);
+ /* .. and add the last component. */
+ if (strcmp(dst, "/") != 0) {
+ if (strlcat(dst, "/", sizeof(dst)) > sizeof(dst))
+ errx(1, "resolved pathname too long");
+ }
+ cp = basename(to_name);
+ if (strlcat(dst, cp, sizeof(dst)) > sizeof(dst))
+ errx(1, "resolved pathname too long");
+
+ /* Trim common path components. */
+ for (s = src, d = dst; *s == *d; s++, d++)
+ continue;
+ while (*s != '/')
+ s--, d--;
+
+ /* Count the number of directories we need to backtrack. */
+ for (++d, lnk[0] = '\0'; *d; d++)
+ if (*d == '/')
+ (void)strlcat(lnk, "../", sizeof(lnk));
+
+ (void)strlcat(lnk, ++s, sizeof(lnk));
+
+ do_symlink(lnk, to_name, target_sb);
+ /* XXX: Link may point outside of destdir. */
+ metadata_log(to_name, "link", NULL, lnk, NULL, 0);
+ return;
+ }
/*
- * XXX
- * We know that uid_t's and gid_t's are unsigned longs.
+ * If absolute or relative was not specified, try the names the
+ * user provided.
*/
- errno = 0;
- val = strtoul(name, &ep, 10);
- if (errno)
- err(EX_NOUSER, "%s", name);
- if (*ep != '\0')
- errx(EX_NOUSER, "unknown %s %s", type, name);
- return (val);
+ do_symlink(from_name, to_name, target_sb);
+ /* XXX: from_name may point outside of destdir. */
+ metadata_log(to_name, "link", NULL, from_name, NULL, 0);
}
/*
@@ -275,6 +720,7 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
int devnull, files_match, from_fd, serrno, target;
int tempcopy, temp_fd, to_fd;
char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
+ char *digestresult;
files_match = 0;
from_fd = -1;
@@ -282,11 +728,13 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
/* If try to install NULL file to a directory, fails. */
if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
- if (stat(from_name, &from_sb))
- err(EX_OSERR, "%s", from_name);
- if (!S_ISREG(from_sb.st_mode)) {
- errno = EFTYPE;
- err(EX_OSERR, "%s", from_name);
+ if (!dolink) {
+ if (stat(from_name, &from_sb))
+ err(EX_OSERR, "%s", from_name);
+ if (!S_ISREG(from_sb.st_mode)) {
+ errno = EFTYPE;
+ err(EX_OSERR, "%s", from_name);
+ }
}
/* Build the target path. */
if (flags & DIRECTORY) {
@@ -300,7 +748,23 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
devnull = 1;
}
- target = stat(to_name, &to_sb) == 0;
+ if (!dolink)
+ target = (stat(to_name, &to_sb) == 0);
+ else
+ target = (lstat(to_name, &to_sb) == 0);
+
+ if (dolink) {
+ if (target && !safecopy) {
+ if (to_sb.st_mode & S_IFDIR && rmdir(to_name) == -1)
+ err(EX_OSERR, "%s", to_name);
+ if (to_sb.st_flags & NOCHANGEBITS)
+ (void)chflags(to_name,
+ to_sb.st_flags & ~NOCHANGEBITS);
+ unlink(to_name);
+ }
+ makelink(from_name, to_name, target ? &to_sb : NULL);
+ return;
+ }
/* Only install to regular files. */
if (target && !S_ISREG(to_sb.st_mode)) {
@@ -324,7 +788,7 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
else
files_match = !(compare(from_fd, from_name,
(size_t)from_sb.st_size, to_fd,
- to_name, (size_t)to_sb.st_size));
+ to_name, (size_t)to_sb.st_size, &digestresult));
/* Close "to" file unless we match. */
if (!files_match)
@@ -346,8 +810,10 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
from_name, to_name);
}
if (!devnull)
- copy(from_fd, from_name, to_fd,
+ digestresult = copy(from_fd, from_name, to_fd,
tempcopy ? tempfile : to_name, from_sb.st_size);
+ else
+ digestresult = NULL;
}
if (dostrip) {
@@ -381,7 +847,8 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
}
if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd,
- to_name, (size_t)to_sb.st_size) == 0) {
+ to_name, (size_t)to_sb.st_size, &digestresult)
+ == 0) {
/*
* If target has more than one link we need to
* replace it in order to snap the extra links.
@@ -401,6 +868,9 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
}
}
+ if (dostrip && (!docompare || !target))
+ digestresult = digest_file(tempfile);
+
/*
* Move the new file into place if doing a safe copy
* and the files are different (or just not compared).
@@ -464,15 +934,16 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
* Set owner, group, mode for target; do the chown first,
* chown may lose the setuid bits.
*/
- if ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
+ if (!dounpriv && ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
(uid != (uid_t)-1 && uid != to_sb.st_uid) ||
- (mode != (to_sb.st_mode & ALLPERMS))) {
+ (mode != (to_sb.st_mode & ALLPERMS)))) {
/* Try to turn off the immutable bits. */
if (to_sb.st_flags & NOCHANGEBITS)
(void)fchflags(to_fd, to_sb.st_flags & ~NOCHANGEBITS);
}
- if ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
+ if (!dounpriv &
+ (gid != (gid_t)-1 && gid != to_sb.st_gid) ||
(uid != (uid_t)-1 && uid != to_sb.st_uid))
if (fchown(to_fd, uid, gid) == -1) {
serrno = errno;
@@ -481,13 +952,15 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
err(EX_OSERR,"%s: chown/chgrp", to_name);
}
- if (mode != (to_sb.st_mode & ALLPERMS))
- if (fchmod(to_fd, mode)) {
+ if (mode != (to_sb.st_mode & ALLPERMS)) {
+ if (fchmod(to_fd,
+ dounpriv ? mode & (S_IRWXU|S_IRWXG|S_IRWXO) : mode)) {
serrno = errno;
(void)unlink(to_name);
errno = serrno;
err(EX_OSERR, "%s: chmod", to_name);
}
+ }
/*
* If provided a set of flags, set them, otherwise, preserve the
@@ -496,7 +969,7 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
* trying to turn off UF_NODUMP. If we're trying to set real flags,
* then warn if the fs doesn't support it, otherwise fail.
*/
- if (!devnull && (flags & SETFLAGS ||
+ if (!dounpriv & !devnull && (flags & SETFLAGS ||
(from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) &&
fchflags(to_fd,
flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) {
@@ -515,6 +988,9 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
(void)close(to_fd);
if (!devnull)
(void)close(from_fd);
+
+ metadata_log(to_name, "file", tvb, NULL, digestresult, to_sb.st_size);
+ free(digestresult);
}
/*
@@ -523,29 +999,37 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
*/
static int
compare(int from_fd, const char *from_name __unused, size_t from_len,
- int to_fd, const char *to_name __unused, size_t to_len)
+ int to_fd, const char *to_name __unused, size_t to_len,
+ char **dresp)
{
char *p, *q;
int rv;
int done_compare;
+ DIGEST_CTX ctx;
rv = 0;
if (from_len != to_len)
return 1;
if (from_len <= MAX_CMP_SIZE) {
+ if (dresp != NULL)
+ digest_init(&ctx);
done_compare = 0;
if (trymmap(from_fd) && trymmap(to_fd)) {
- p = mmap(NULL, from_len, PROT_READ, MAP_SHARED, from_fd, (off_t)0);
+ p = mmap(NULL, from_len, PROT_READ, MAP_SHARED,
+ from_fd, (off_t)0);
if (p == (char *)MAP_FAILED)
goto out;
- q = mmap(NULL, from_len, PROT_READ, MAP_SHARED, to_fd, (off_t)0);
+ q = mmap(NULL, from_len, PROT_READ, MAP_SHARED,
+ to_fd, (off_t)0);
if (q == (char *)MAP_FAILED) {
munmap(p, from_len);
goto out;
}
rv = memcmp(p, q, from_len);
+ if (dresp != NULL)
+ digest_update(&ctx, p, from_len);
munmap(p, from_len);
munmap(q, from_len);
done_compare = 1;
@@ -571,6 +1055,7 @@ compare(int from_fd, const char *from_name __unused, size_t from_len,
rv = 1; /* out of sync */
} else
rv = 1; /* read failure */
+ digest_update(&ctx, buf1, n1);
}
lseek(from_fd, 0, SEEK_SET);
lseek(to_fd, 0, SEEK_SET);
@@ -578,6 +1063,13 @@ compare(int from_fd, const char *from_name __unused, size_t from_len,
} else
rv = 1; /* don't bother in this case */
+ if (dresp != NULL) {
+ if (rv == 0)
+ *dresp = digest_end(&ctx, NULL);
+ else
+ (void)digest_end(&ctx, NULL);
+ }
+
return rv;
}
@@ -648,7 +1140,7 @@ create_newfile(const char *path, int target, struct stat *sbp)
* copy --
* copy from one file to another
*/
-static void
+static char *
copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
off_t size)
{
@@ -656,6 +1148,7 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
int serrno;
char *p, buf[MAXBSIZE];
int done_copy;
+ DIGEST_CTX ctx;
/* Rewind file descriptors. */
if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1)
@@ -663,6 +1156,8 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1)
err(EX_OSERR, "lseek: %s", to_name);
+ digest_init(&ctx);
+
/*
* Mmap and write if less than 8M (the limit is so we don't totally
* trash memory on big files. This is really a minor hack, but it
@@ -685,10 +1180,12 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
err(EX_OSERR, "%s", to_name);
}
}
+ digest_update(&ctx, p, size);
+ (void)munmap(p, size);
done_copy = 1;
}
if (!done_copy) {
- while ((nr = read(from_fd, buf, sizeof(buf))) > 0)
+ while ((nr = read(from_fd, buf, sizeof(buf))) > 0) {
if ((nw = write(to_fd, buf, nr)) != nr) {
serrno = errno;
(void)unlink(to_name);
@@ -702,6 +1199,8 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
err(EX_OSERR, "%s", to_name);
}
}
+ digest_update(&ctx, buf, nr);
+ }
if (nr != 0) {
serrno = errno;
(void)unlink(to_name);
@@ -709,6 +1208,7 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
err(EX_OSERR, "%s", from_name);
}
}
+ return (digest_end(&ctx, NULL));
}
/*
@@ -771,10 +1271,96 @@ install_dir(char *path)
break;
}
- if ((gid != (gid_t)-1 || uid != (uid_t)-1) && chown(path, uid, gid))
- warn("chown %u:%u %s", uid, gid, path);
- if (chmod(path, mode))
- warn("chmod %o %s", mode, path);
+ if (!dounpriv) {
+ if ((gid != (gid_t)-1 || uid != (uid_t)-1) &&
+ chown(path, uid, gid))
+ warn("chown %u:%u %s", uid, gid, path);
+ /* XXXBED: should we do the chmod in the dounpriv case? */
+ if (chmod(path, mode))
+ warn("chmod %o %s", mode, path);
+ }
+ metadata_log(path, "dir", NULL, NULL, NULL, 0);
+}
+
+/*
+ * metadata_log --
+ * if metafp is not NULL, output mtree(8) full path name and settings to
+ * metafp, to allow permissions to be set correctly by other tools,
+ * or to allow integrity checks to be performed.
+ */
+static void
+metadata_log(const char *path, const char *type, struct timeval *tv,
+ const char *slink, const char *digestresult, off_t size)
+{
+ static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' };
+ const char *p;
+ char *buf;
+ size_t destlen;
+ struct flock metalog_lock;
+
+ if (!metafp)
+ return;
+ /* Buffer for strsvis(3). */
+ buf = (char *)malloc(4 * strlen(path) + 1);
+ if (buf == NULL) {
+ warnx("%s", strerror(ENOMEM));
+ return;
+ }
+
+ /* Lock log file. */
+ metalog_lock.l_start = 0;
+ metalog_lock.l_len = 0;
+ metalog_lock.l_whence = SEEK_SET;
+ metalog_lock.l_type = F_WRLCK;
+ if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1) {
+ warn("can't lock %s", metafile);
+ free(buf);
+ return;
+ }
+
+ /* Remove destdir. */
+ p = path;
+ if (destdir) {
+ destlen = strlen(destdir);
+ if (strncmp(p, destdir, destlen) == 0 &&
+ (p[destlen] == '/' || p[destlen] == '\0'))
+ p += destlen;
+ }
+ while (*p && *p == '/')
+ p++;
+ strsvis(buf, p, VIS_OCTAL, extra);
+ p = buf;
+ /* Print details. */
+ fprintf(metafp, ".%s%s type=%s", *p ? "/" : "", p, type);
+ if (owner)
+ fprintf(metafp, " uname=%s", owner);
+ if (group)
+ fprintf(metafp, " gname=%s", group);
+ fprintf(metafp, " mode=%#o", mode);
+ if (slink) {
+ strsvis(buf, slink, VIS_CSTYLE, extra); /* encode link */
+ fprintf(metafp, " link=%s", buf);
+ }
+ if (*type == 'f') /* type=file */
+ fprintf(metafp, " size=%lld", (long long)size);
+ if (tv != NULL && dopreserve)
+ fprintf(metafp, " time=%lld.%ld",
+ (long long)tv[1].tv_sec, (long)tv[1].tv_usec);
+ if (digestresult && digest)
+ fprintf(metafp, " %s=%s", digest, digestresult);
+ if (fflags)
+ fprintf(metafp, " flags=%s", fflags);
+ if (tags)
+ fprintf(metafp, " tags=%s", tags);
+ fputc('\n', metafp);
+ /* Flush line. */
+ fflush(metafp);
+
+ /* Unlock log file. */
+ metalog_lock.l_type = F_UNLCK;
+ if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1)
+ warn("can't unlock %s", metafile);
+ free(buf);
}
/*
@@ -785,11 +1371,17 @@ static void
usage(void)
{
(void)fprintf(stderr,
-"usage: install [-bCcMpSsv] [-B suffix] [-f flags] [-g group] [-m mode]\n"
-" [-o owner] file1 file2\n"
-" install [-bCcMpSsv] [-B suffix] [-f flags] [-g group] [-m mode]\n"
-" [-o owner] file1 ... fileN directory\n"
-" install -d [-v] [-g group] [-m mode] [-o owner] directory ...\n");
+"usage: install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n"
+" [-M log] [-D dest] [-h hash] [-T tags]\n"
+" [-B suffix] [-l linkflags] [-N dbdir]\n"
+" file1 file2\n"
+" install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n"
+" [-M log] [-D dest] [-h hash] [-T tags]\n"
+" [-B suffix] [-l linkflags] [-N dbdir]\n"
+" file1 ... fileN directory\n"
+" install -dU [-vU] [-g group] [-m mode] [-N dbdir] [-o owner]\n"
+" [-M log] [-D dest] [-h hash] [-T tags]\n"
+" directory ...\n");
exit(EX_USAGE);
/* NOTREACHED */
}
@@ -808,7 +1400,7 @@ trymmap(int fd)
#ifdef MFSNAMELEN
struct statfs stfs;
- if (nommap || fstatfs(fd, &stfs) != 0)
+ if (fstatfs(fd, &stfs) != 0)
return (0);
if (strcmp(stfs.f_fstypename, "ufs") == 0 ||
strcmp(stfs.f_fstypename, "cd9660") == 0)
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 8a2d5be..532595b 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -39,7 +39,6 @@ SUBDIR= adduser \
kldxref \
mailwrapper \
makefs \
- manctl \
memcontrol \
mergemaster \
mfiutil \
@@ -57,7 +56,7 @@ SUBDIR= adduser \
nfsuserd \
nmtree \
nologin \
- pc-sysinstall \
+ ${_pc_sysinstall} \
pciconf \
periodic \
powerd \
@@ -265,6 +264,10 @@ SUBDIR+= ntp
SUBDIR+= keyserv
.endif
+.if ${MK_PC_SYSINSTALL} != "no"
+_pc_sysinstall= pc-sysinstall
+.endif
+
.if ${MK_PF} != "no"
SUBDIR+= ftp-proxy
.endif
diff --git a/usr.sbin/Makefile.amd64 b/usr.sbin/Makefile.amd64
index 1a1bffe..5ee2165 100644
--- a/usr.sbin/Makefile.amd64
+++ b/usr.sbin/Makefile.amd64
@@ -10,6 +10,9 @@ SUBDIR+= acpi
SUBDIR+= apm
.endif
SUBDIR+= asf
+SUBDIR+= bhyve
+SUBDIR+= bhyvectl
+SUBDIR+= bhyveload
SUBDIR+= boot0cfg
.if ${MK_TOOLCHAIN} != "no"
SUBDIR+= btxld
diff --git a/usr.sbin/acpi/acpidb/Makefile b/usr.sbin/acpi/acpidb/Makefile
index 548a800..9eccb4d 100644
--- a/usr.sbin/acpi/acpidb/Makefile
+++ b/usr.sbin/acpi/acpidb/Makefile
@@ -4,9 +4,9 @@ PROG= acpidb
SRCS= acpidb.c
# components/debugger
-SRCS+= dbcmds.c dbdisply.c dbexec.c dbfileio.c dbhistry.c \
- dbinput.c dbmethod.c dbnames.c dbstats.c dbutils.c \
- dbxface.c
+SRCS+= dbcmds.c dbconvert.c dbdisply.c dbexec.c dbfileio.c \
+ dbhistry.c dbinput.c dbmethod.c dbnames.c dbstats.c \
+ dbutils.c dbxface.c
# components/disassembler
SRCS+= dmbuffer.c dmdeferred.c dmnames.c dmobject.c dmopcode.c \
@@ -20,8 +20,8 @@ SRCS+= dsargs.c dscontrol.c dsfield.c dsinit.c dsmethod.c \
# components/events
SRCS+= evevent.c evglock.c evgpe.c evgpeblk.c evgpeinit.c \
- evgpeutil.c evmisc.c evregion.c evrgnini.c evsci.c \
- evxface.c evxfevnt.c evxfregn.c
+ evgpeutil.c evhandler.c evmisc.c evregion.c evrgnini.c \
+ evsci.c evxface.c evxfevnt.c evxfregn.c
# components/executer
SRCS+= exconfig.c exconvrt.c excreate.c exdebug.c exdump.c \
@@ -37,19 +37,20 @@ SRCS+= hwacpi.c hwesleep.c hwgpe.c hwpci.c hwregs.c hwsleep.c \
# components/namespace
SRCS+= nsaccess.c nsalloc.c nsdump.c nseval.c nsinit.c \
nsload.c nsnames.c nsobject.c nsparse.c nspredef.c \
- nsrepair.c nsrepair2.c nssearch.c nsutils.c nswalk.c \
- nsxfeval.c nsxfname.c nsxfobj.c
+ nsprepkg.c nsrepair.c nsrepair2.c nssearch.c nsutils.c \
+ nswalk.c nsxfeval.c nsxfname.c nsxfobj.c
# components/parser
-SRCS+= psargs.c psloop.c psopcode.c psparse.c psscope.c \
- pstree.c psutils.c pswalk.c psxface.c
+SRCS+= psargs.c psloop.c psobject.c psopcode.c psopinfo.c \
+ psparse.c psscope.c pstree.c psutils.c pswalk.c \
+ psxface.c
# components/os_specific/service_layers
SRCS+= osunixxf.c
# components/resources
-SRCS+= rsaddr.c rscalc.c rscreate.c rsdump.c rsinfo.c \
- rsio.c rsirq.c rslist.c rsmemory.c rsmisc.c \
+SRCS+= rsaddr.c rscalc.c rscreate.c rsdump.c rsdumpinfo.c \
+ rsinfo.c rsio.c rsirq.c rslist.c rsmemory.c rsmisc.c \
rsserial.c rsutils.c rsxface.c
# components/tables
@@ -60,8 +61,8 @@ SRCS+= tbfadt.c tbfind.c tbinstal.c tbutils.c tbxface.c \
SRCS+= utaddress.c utalloc.c utcache.c utcopy.c utdebug.c \
utdecode.c utdelete.c uteval.c utexcep.c utglobal.c \
utids.c utinit.c utlock.c utmath.c utmisc.c utmutex.c \
- utobject.c utosi.c utresrc.c utstate.c uttrack.c \
- utxface.c utxferror.c utxfinit.c
+ utobject.c utosi.c utownerid.c utresrc.c utstate.c \
+ utstring.c uttrack.c utxface.c utxferror.c utxfinit.c
MAN= acpidb.8
WARNS?= 2
diff --git a/usr.sbin/acpi/iasl/Makefile b/usr.sbin/acpi/iasl/Makefile
index f4eda5f..b348141 100644
--- a/usr.sbin/acpi/iasl/Makefile
+++ b/usr.sbin/acpi/iasl/Makefile
@@ -10,18 +10,19 @@ SRCS+= ahpredef.c dmextern.c dmrestag.c dmtable.c dmtbdump.c \
# compiler
SRCS+= aslanalyze.c aslbtypes.c aslcodegen.c aslcompile.c \
aslcompiler.y.h aslcompilerlex.c aslcompilerparse.c \
- aslerror.c aslfiles.c aslfold.c asllength.c \
- asllisting.c aslload.c asllookup.c aslmain.c aslmap.c \
- aslopcodes.c asloperands.c aslopt.c aslpredef.c \
- aslresource.c aslrestype1.c aslrestype1i.c \
- aslrestype2.c aslrestype2d.c aslrestype2e.c \
- aslrestype2q.c aslrestype2s.c aslrestype2w.c \
- aslstartup.c aslstubs.c asltransform.c asltree.c \
- aslutils.c asluuid.c aslwalks.c dtcompile.c dtexpress.c \
- dtfield.c dtio.c dtparser.y.h dtparserlex.c \
- dtparserparse.c dtsubtable.c dttable.c dttemplate.c \
- dtutils.c prexpress.c prmacros.c prparser.y.h \
- prparserlex.c prparserparse.c prscan.c prutils.c
+ aslerror.c aslfileio.c aslfiles.c aslfold.c aslhex.c \
+ asllength.c asllisting.c aslload.c asllookup.c \
+ aslmain.c aslmap.c aslmethod.c aslnamesp.c aslopcodes.c \
+ asloperands.c aslopt.c aslpredef.c aslresource.c \
+ aslrestype1.c aslrestype1i.c aslrestype2.c \
+ aslrestype2d.c aslrestype2e.c aslrestype2q.c \
+ aslrestype2s.c aslrestype2w.c aslstartup.c aslstubs.c \
+ asltransform.c asltree.c aslutils.c asluuid.c \
+ aslwalks.c aslxref.c dtcompile.c dtexpress.c dtfield.c \
+ dtio.c dtparser.y.h dtparserlex.c dtparserparse.c \
+ dtsubtable.c dttable.c dttemplate.c dtutils.c \
+ prexpress.c prmacros.c prparser.y.h prparserlex.c \
+ prparserparse.c prscan.c prutils.c
# components/debugger
SRCS+= dbfileio.c
@@ -42,8 +43,8 @@ SRCS+= exconvrt.c excreate.c exdump.c exmisc.c exmutex.c \
exstoren.c exstorob.c exsystem.c exutils.c
# components/parser
-SRCS+= psargs.c psloop.c psopcode.c psparse.c psscope.c \
- pstree.c psutils.c pswalk.c
+SRCS+= psargs.c psloop.c psobject.c psopcode.c psopinfo.c \
+ psparse.c psscope.c pstree.c psutils.c pswalk.c
# components/namespace
SRCS+= nsaccess.c nsalloc.c nsdump.c nsnames.c nsobject.c \
@@ -56,7 +57,8 @@ SRCS+= tbfadt.c tbinstal.c tbutils.c tbxface.c
SRCS+= utaddress.c utalloc.c utcache.c utcopy.c utdebug.c \
utdecode.c utdelete.c utexcep.c utglobal.c utinit.c \
utlock.c utmath.c utmisc.c utmutex.c utobject.c \
- utresrc.c utstate.c utxface.c utxferror.c
+ utownerid.c utresrc.c utstate.c utstring.c utxface.c \
+ utxferror.c
# os_specific/service_layers
SRCS+= osunixxf.c
diff --git a/usr.sbin/arp/arp.8 b/usr.sbin/arp/arp.8
index d7306d3..87c5c5f 100644
--- a/usr.sbin/arp/arp.8
+++ b/usr.sbin/arp/arp.8
@@ -28,7 +28,7 @@
.\" @(#)arp.8 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd December 25, 2008
+.Dd January 31, 2013
.Dt ARP 8
.Os
.Sh NAME
@@ -54,12 +54,12 @@
.Fl s Ar hostname ether_addr
.Op Cm temp
.Op Cm blackhole No \&| Cm reject
-.Op Cm pub Op Cm only
+.Op Cm pub
.Nm
.Fl S Ar hostname ether_addr
.Op Cm temp
.Op Cm blackhole No \&| Cm reject
-.Op Cm pub Op Cm only
+.Op Cm pub
.Nm
.Fl f Ar filename
.Sh DESCRIPTION
@@ -140,16 +140,6 @@ can be given as
in which case the interfaces on this host will be examined,
and if one of them is found to occupy the same subnet, its
Ethernet address will be used.
-If the
-.Cm only
-keyword is also specified, this will create a
-.Dq "published (proxy only)"
-entry.
-This type of entry is created automatically if
-.Nm
-detects that a routing table entry for
-.Ar hostname
-already exists.
.Pp
If the
.Cm reject
@@ -181,7 +171,7 @@ in the file should be of the form
.Ar hostname ether_addr
.Op Cm temp
.Op Cm blackhole No \&| Cm reject
-.Op Cm pub Op Cm only
+.Op Cm pub
.Ed
.Pp
with argument meanings as given above.
diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c
index 9a7f91f..8bdd555 100644
--- a/usr.sbin/arp/arp.c
+++ b/usr.sbin/arp/arp.c
@@ -81,28 +81,28 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
typedef void (action_fn)(struct sockaddr_dl *sdl,
- struct sockaddr_inarp *s_in, struct rt_msghdr *rtm);
+ struct sockaddr_in *s_in, struct rt_msghdr *rtm);
static int search(u_long addr, action_fn *action);
static action_fn print_entry;
static action_fn nuke_entry;
-static int delete(char *host, int do_proxy);
+static int delete(char *host);
static void usage(void);
static int set(int argc, char **argv);
static int get(char *host);
static int file(char *name);
static struct rt_msghdr *rtmsg(int cmd,
- struct sockaddr_inarp *dst, struct sockaddr_dl *sdl);
+ struct sockaddr_in *dst, struct sockaddr_dl *sdl);
static int get_ether_addr(in_addr_t ipaddr, struct ether_addr *hwaddr);
-static struct sockaddr_inarp *getaddr(char *host);
+static struct sockaddr_in *getaddr(char *host);
static int valid_type(int type);
static int nflag; /* no reverse dns lookups */
static char *rifname;
static time_t expire_time;
-static int flags, doing_proxy, proxy_only;
+static int flags, doing_proxy;
/* which function we're supposed to do */
#define F_GET 1
@@ -179,7 +179,7 @@ main(int argc, char *argv[])
if (argc < 2 || argc > 6)
usage();
if (func == F_REPLACE)
- (void)delete(argv[0], 0);
+ (void)delete(argv[0]);
rtn = set(argc, argv) ? 1 : 0;
break;
case F_DELETE:
@@ -187,15 +187,8 @@ main(int argc, char *argv[])
if (argc != 0)
usage();
search(0, nuke_entry);
- } else {
- if (argc == 2 && strncmp(argv[1], "pub", 3) == 0)
- ch = SIN_PROXY;
- else if (argc == 1)
- ch = 0;
- else
- usage();
- rtn = delete(argv[0], ch);
- }
+ } else
+ rtn = delete(argv[0]);
break;
case F_FILESET:
if (argc != 1)
@@ -246,15 +239,15 @@ file(char *name)
}
/*
- * Given a hostname, fills up a (static) struct sockaddr_inarp with
+ * Given a hostname, fills up a (static) struct sockaddr_in with
* the address of the host and returns a pointer to the
* structure.
*/
-static struct sockaddr_inarp *
+static struct sockaddr_in *
getaddr(char *host)
{
struct hostent *hp;
- static struct sockaddr_inarp reply;
+ static struct sockaddr_in reply;
bzero(&reply, sizeof(reply));
reply.sin_len = sizeof(reply);
@@ -298,8 +291,8 @@ valid_type(int type)
static int
set(int argc, char **argv)
{
- struct sockaddr_inarp *addr;
- struct sockaddr_inarp *dst; /* what are we looking for */
+ struct sockaddr_in *addr;
+ struct sockaddr_in *dst; /* what are we looking for */
struct sockaddr_dl *sdl;
struct rt_msghdr *rtm;
struct ether_addr *ea;
@@ -316,7 +309,7 @@ set(int argc, char **argv)
dst = getaddr(host);
if (dst == NULL)
return (1);
- doing_proxy = flags = proxy_only = expire_time = 0;
+ doing_proxy = flags = expire_time = 0;
while (argc-- > 0) {
if (strncmp(argv[0], "temp", 4) == 0) {
struct timespec tp;
@@ -332,7 +325,12 @@ set(int argc, char **argv)
flags |= RTF_ANNOUNCE;
doing_proxy = 1;
if (argc && strncmp(argv[1], "only", 3) == 0) {
- proxy_only = 1;
+ /*
+ * Compatibility: in pre FreeBSD 8 times
+ * the "only" keyword used to mean that
+ * an ARP entry should be announced, but
+ * not installed into routing table.
+ */
argc--; argv++;
}
} else if (strncmp(argv[0], "blackhole", 9) == 0) {
@@ -385,7 +383,7 @@ set(int argc, char **argv)
warn("%s", host);
return (1);
}
- addr = (struct sockaddr_inarp *)(rtm + 1);
+ addr = (struct sockaddr_in *)(rtm + 1);
sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
if ((sdl->sdl_family != AF_LINK) ||
@@ -405,7 +403,7 @@ set(int argc, char **argv)
static int
get(char *host)
{
- struct sockaddr_inarp *addr;
+ struct sockaddr_in *addr;
addr = getaddr(host);
if (addr == NULL)
@@ -425,9 +423,9 @@ get(char *host)
* Delete an arp entry
*/
static int
-delete(char *host, int do_proxy)
+delete(char *host)
{
- struct sockaddr_inarp *addr, *dst;
+ struct sockaddr_in *addr, *dst;
struct rt_msghdr *rtm;
struct sockaddr_dl *sdl;
struct sockaddr_dl sdl_m;
@@ -456,7 +454,7 @@ delete(char *host, int do_proxy)
warn("%s", host);
return (1);
}
- addr = (struct sockaddr_inarp *)(rtm + 1);
+ addr = (struct sockaddr_in *)(rtm + 1);
sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
/*
@@ -504,7 +502,7 @@ search(u_long addr, action_fn *action)
size_t needed;
char *lim, *buf, *next;
struct rt_msghdr *rtm;
- struct sockaddr_inarp *sin2;
+ struct sockaddr_in *sin2;
struct sockaddr_dl *sdl;
char ifname[IF_NAMESIZE];
int st, found_entry = 0;
@@ -538,7 +536,7 @@ search(u_long addr, action_fn *action)
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
- sin2 = (struct sockaddr_inarp *)(rtm + 1);
+ sin2 = (struct sockaddr_in *)(rtm + 1);
sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2));
if (rifname && if_indextoname(sdl->sdl_index, ifname) &&
strcmp(ifname, rifname))
@@ -562,7 +560,7 @@ static int64_t lifindex = -1;
static void
print_entry(struct sockaddr_dl *sdl,
- struct sockaddr_inarp *addr, struct rt_msghdr *rtm)
+ struct sockaddr_in *addr, struct rt_msghdr *rtm)
{
const char *host;
struct hostent *hp;
@@ -612,8 +610,6 @@ print_entry(struct sockaddr_dl *sdl,
else
printf(" expired");
}
- if (addr->sin_other & SIN_PROXY)
- printf(" published (proxy only)");
if (rtm->rtm_flags & RTF_ANNOUNCE)
printf(" published");
switch(sdl->sdl_type) {
@@ -659,12 +655,12 @@ print_entry(struct sockaddr_dl *sdl,
*/
static void
nuke_entry(struct sockaddr_dl *sdl __unused,
- struct sockaddr_inarp *addr, struct rt_msghdr *rtm __unused)
+ struct sockaddr_in *addr, struct rt_msghdr *rtm __unused)
{
char ip[20];
snprintf(ip, sizeof(ip), "%s", inet_ntoa(addr->sin_addr));
- (void)delete(ip, 0);
+ delete(ip);
}
static void
@@ -682,7 +678,7 @@ usage(void)
}
static struct rt_msghdr *
-rtmsg(int cmd, struct sockaddr_inarp *dst, struct sockaddr_dl *sdl)
+rtmsg(int cmd, struct sockaddr_in *dst, struct sockaddr_dl *sdl)
{
static int seq;
int rlen;
@@ -728,14 +724,9 @@ rtmsg(int cmd, struct sockaddr_inarp *dst, struct sockaddr_dl *sdl)
rtm->rtm_rmx.rmx_expire = expire_time;
rtm->rtm_inits = RTV_EXPIRE;
rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA);
- dst->sin_other = 0;
if (doing_proxy) {
- if (proxy_only)
- dst->sin_other = SIN_PROXY;
- else {
- rtm->rtm_addrs |= RTA_NETMASK;
- rtm->rtm_flags &= ~RTF_HOST;
- }
+ rtm->rtm_addrs |= RTA_NETMASK;
+ rtm->rtm_flags &= ~RTF_HOST;
}
/* FALLTHROUGH */
case RTM_GET:
diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
new file mode 100644
index 0000000..078ef9a
--- /dev/null
+++ b/usr.sbin/bhyve/Makefile
@@ -0,0 +1,27 @@
+#
+# $FreeBSD$
+#
+
+PROG= bhyve
+
+DEBUG_FLAGS= -g -O0
+
+SRCS= acpi.c atpic.c bhyverun.c consport.c dbgport.c elcr.c inout.c
+SRCS+= ioapic.c mem.c mevent.c mptbl.c
+SRCS+= pci_emul.c pci_hostbridge.c pci_passthru.c pci_virtio_block.c
+SRCS+= pci_virtio_net.c pci_uart.c pit_8254.c pmtmr.c post.c rtc.c uart.c
+SRCS+= xmsr.c spinup_ap.c
+
+.PATH: ${.CURDIR}/../../sys/amd64/vmm
+SRCS+= vmm_instruction_emul.c
+
+NO_MAN=
+
+DPADD= ${LIBVMMAPI} ${LIBMD} ${LIBPTHREAD}
+LDADD= -lvmmapi -lmd -lpthread
+
+WARNS?= 2
+
+CFLAGS+= -I${.CURDIR}/../../sys
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c
new file mode 100644
index 0000000..32effdc
--- /dev/null
+++ b/usr.sbin/bhyve/acpi.c
@@ -0,0 +1,844 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * bhyve ACPI table generator.
+ *
+ * Create the minimal set of ACPI tables required to boot FreeBSD (and
+ * hopefully other o/s's) by writing out ASL template files for each of
+ * the tables and the compiling them to AML with the Intel iasl compiler.
+ * The AML files are then read into guest memory.
+ *
+ * The tables are placed in the guest's ROM area just below 1MB physical,
+ * above the MPTable.
+ *
+ * Layout
+ * ------
+ * RSDP -> 0xf0400 (36 bytes fixed)
+ * RSDT -> 0xf0440 (36 bytes + 4*N table addrs, 2 used)
+ * XSDT -> 0xf0480 (36 bytes + 8*N table addrs, 2 used)
+ * MADT -> 0xf0500 (depends on #CPUs)
+ * FADT -> 0xf0600 (268 bytes)
+ * FACS -> 0xf0780 (64 bytes)
+ * DSDT -> 0xf0800 (variable - can go up to 0x100000)
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bhyverun.h"
+#include "acpi.h"
+
+/*
+ * Define the base address of the ACPI tables, and the offsets to
+ * the individual tables
+ */
+#define BHYVE_ACPI_BASE 0xf0400
+#define RSDT_OFFSET 0x040
+#define XSDT_OFFSET 0x080
+#define MADT_OFFSET 0x100
+#define FADT_OFFSET 0x200
+#define FACS_OFFSET 0x380
+#define DSDT_OFFSET 0x400
+
+#define BHYVE_ASL_TEMPLATE "bhyve.XXXXXXX"
+#define BHYVE_ASL_SUFFIX ".aml"
+#define BHYVE_ASL_COMPILER "/usr/sbin/iasl"
+
+#define BHYVE_PM_TIMER_ADDR 0x408
+
+static int basl_keep_temps;
+static int basl_verbose_iasl;
+static int basl_ncpu;
+static uint32_t basl_acpi_base = BHYVE_ACPI_BASE;
+
+/*
+ * Contains the full pathname of the template to be passed
+ * to mkstemp/mktemps(3)
+ */
+static char basl_template[MAXPATHLEN];
+static char basl_stemplate[MAXPATHLEN];
+
+struct basl_fio {
+ int fd;
+ FILE *fp;
+ char f_name[MAXPATHLEN];
+};
+
+#define EFPRINTF(...) \
+ err = fprintf(__VA_ARGS__); if (err < 0) goto err_exit;
+
+#define EFFLUSH(x) \
+ err = fflush(x); if (err != 0) goto err_exit;
+
+static int
+basl_fwrite_rsdp(FILE *fp)
+{
+ int err;
+
+ err = 0;
+
+ EFPRINTF(fp, "/*\n");
+ EFPRINTF(fp, " * bhyve RSDP template\n");
+ EFPRINTF(fp, " */\n");
+ EFPRINTF(fp, "[0008]\t\tSignature : \"RSD PTR \"\n");
+ EFPRINTF(fp, "[0001]\t\tChecksum : 43\n");
+ EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
+ EFPRINTF(fp, "[0001]\t\tRevision : 02\n");
+ EFPRINTF(fp, "[0004]\t\tRSDT Address : %08X\n",
+ basl_acpi_base + RSDT_OFFSET);
+ EFPRINTF(fp, "[0004]\t\tLength : 00000024\n");
+ EFPRINTF(fp, "[0008]\t\tXSDT Address : 00000000%08X\n",
+ basl_acpi_base + XSDT_OFFSET);
+ EFPRINTF(fp, "[0001]\t\tExtended Checksum : 00\n");
+ EFPRINTF(fp, "[0003]\t\tReserved : 000000\n");
+
+ EFFLUSH(fp);
+
+ return (0);
+
+err_exit:
+ return (errno);
+}
+
+static int
+basl_fwrite_rsdt(FILE *fp)
+{
+ int err;
+
+ err = 0;
+
+ EFPRINTF(fp, "/*\n");
+ EFPRINTF(fp, " * bhyve RSDT template\n");
+ EFPRINTF(fp, " */\n");
+ EFPRINTF(fp, "[0004]\t\tSignature : \"RSDT\"\n");
+ EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
+ EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
+ EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
+ EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
+ EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVRSDT \"\n");
+ EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
+ /* iasl will fill in the compiler ID/revision fields */
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
+ EFPRINTF(fp, "\n");
+
+ /* Add in pointers to the MADT and FADT */
+ EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : %08X\n",
+ basl_acpi_base + MADT_OFFSET);
+ EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : %08X\n",
+ basl_acpi_base + FADT_OFFSET);
+
+ EFFLUSH(fp);
+
+ return (0);
+
+err_exit:
+ return (errno);
+}
+
+static int
+basl_fwrite_xsdt(FILE *fp)
+{
+ int err;
+
+ err = 0;
+
+ EFPRINTF(fp, "/*\n");
+ EFPRINTF(fp, " * bhyve XSDT template\n");
+ EFPRINTF(fp, " */\n");
+ EFPRINTF(fp, "[0004]\t\tSignature : \"XSDT\"\n");
+ EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
+ EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
+ EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
+ EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
+ EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVXSDT \"\n");
+ EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
+ /* iasl will fill in the compiler ID/revision fields */
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
+ EFPRINTF(fp, "\n");
+
+ /* Add in pointers to the MADT and FADT */
+ EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : 00000000%08X\n",
+ basl_acpi_base + MADT_OFFSET);
+ EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : 00000000%08X\n",
+ basl_acpi_base + FADT_OFFSET);
+
+ EFFLUSH(fp);
+
+ return (0);
+
+err_exit:
+ return (errno);
+}
+
+static int
+basl_fwrite_madt(FILE *fp)
+{
+ int err;
+ int i;
+
+ err = 0;
+
+ EFPRINTF(fp, "/*\n");
+ EFPRINTF(fp, " * bhyve MADT template\n");
+ EFPRINTF(fp, " */\n");
+ EFPRINTF(fp, "[0004]\t\tSignature : \"APIC\"\n");
+ EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
+ EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
+ EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
+ EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
+ EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVMADT \"\n");
+ EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
+
+ /* iasl will fill in the compiler ID/revision fields */
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp, "[0004]\t\tLocal Apic Address : FEE00000\n");
+ EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n");
+ EFPRINTF(fp, "\t\t\tPC-AT Compatibility : 1\n");
+ EFPRINTF(fp, "\n");
+
+ /* Add a Processor Local APIC entry for each CPU */
+ for (i = 0; i < basl_ncpu; i++) {
+ EFPRINTF(fp, "[0001]\t\tSubtable Type : 00\n");
+ EFPRINTF(fp, "[0001]\t\tLength : 08\n");
+ EFPRINTF(fp, "[0001]\t\tProcessor ID : %02d\n", i);
+ EFPRINTF(fp, "[0001]\t\tLocal Apic ID : %02d\n", i);
+ EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n");
+ EFPRINTF(fp, "\t\t\tProcessor Enabled : 1\n");
+ EFPRINTF(fp, "\n");
+ }
+
+ /* Always a single IOAPIC entry, with ID ncpu+1 */
+ EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n");
+ EFPRINTF(fp, "[0001]\t\tLength : 0C\n");
+ EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02d\n", basl_ncpu);
+ EFPRINTF(fp, "[0001]\t\tReserved : 00\n");
+ EFPRINTF(fp, "[0004]\t\tAddress : fec00000\n");
+ EFPRINTF(fp, "[0004]\t\tInterrupt : 00000000\n");
+ EFPRINTF(fp, "\n");
+
+ /* Override the 8259 chained vector. XXX maybe not needed */
+ EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n");
+ EFPRINTF(fp, "[0001]\t\tLength : 0A\n");
+ EFPRINTF(fp, "[0001]\t\tBus : 00\n");
+ EFPRINTF(fp, "[0001]\t\tSource : 09\n");
+ EFPRINTF(fp, "[0004]\t\tInterrupt : 00000009\n");
+ EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0000\n");
+ EFPRINTF(fp, "\t\t\tPolarity : 0\n");
+ EFPRINTF(fp, "\t\t\tTrigger Mode : 0\n");
+ EFPRINTF(fp, "\n");
+
+ EFFLUSH(fp);
+
+ return (0);
+
+err_exit:
+ return (errno);
+}
+
+static int
+basl_fwrite_fadt(FILE *fp)
+{
+ int err;
+
+ err = 0;
+
+ EFPRINTF(fp, "/*\n");
+ EFPRINTF(fp, " * bhyve FADT template\n");
+ EFPRINTF(fp, " */\n");
+ EFPRINTF(fp, "[0004]\t\tSignature : \"FACP\"\n");
+ EFPRINTF(fp, "[0004]\t\tTable Length : 0000010C\n");
+ EFPRINTF(fp, "[0001]\t\tRevision : 05\n");
+ EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
+ EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
+ EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVFACP \"\n");
+ EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
+ /* iasl will fill in the compiler ID/revision fields */
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp, "[0004]\t\tFACS Address : %08X\n",
+ basl_acpi_base + FACS_OFFSET);
+ EFPRINTF(fp, "[0004]\t\tDSDT Address : %08X\n",
+ basl_acpi_base + DSDT_OFFSET);
+ EFPRINTF(fp, "[0001]\t\tModel : 00\n");
+ EFPRINTF(fp, "[0001]\t\tPM Profile : 00 [Unspecified]\n");
+ EFPRINTF(fp, "[0002]\t\tSCI Interrupt : 0009\n");
+ EFPRINTF(fp, "[0004]\t\tSMI Command Port : 00000000\n");
+ EFPRINTF(fp, "[0001]\t\tACPI Enable Value : 00\n");
+ EFPRINTF(fp, "[0001]\t\tACPI Disable Value : 00\n");
+ EFPRINTF(fp, "[0001]\t\tS4BIOS Command : 00\n");
+ EFPRINTF(fp, "[0001]\t\tP-State Control : 00\n");
+ EFPRINTF(fp, "[0004]\t\tPM1A Event Block Address : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tPM1B Event Block Address : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tPM1A Control Block Address : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tPM1B Control Block Address : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tPM2 Control Block Address : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tPM Timer Block Address : %08X\n",
+ BHYVE_PM_TIMER_ADDR);
+ EFPRINTF(fp, "[0004]\t\tGPE0 Block Address : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tGPE1 Block Address : 00000000\n");
+ EFPRINTF(fp, "[0001]\t\tPM1 Event Block Length : 04\n");
+ EFPRINTF(fp, "[0001]\t\tPM1 Control Block Length : 02\n");
+ EFPRINTF(fp, "[0001]\t\tPM2 Control Block Length : 00\n");
+ EFPRINTF(fp, "[0001]\t\tPM Timer Block Length : 04\n");
+ EFPRINTF(fp, "[0001]\t\tGPE0 Block Length : 00\n");
+ EFPRINTF(fp, "[0001]\t\tGPE1 Block Length : 00\n");
+ EFPRINTF(fp, "[0001]\t\tGPE1 Base Offset : 00\n");
+ EFPRINTF(fp, "[0001]\t\t_CST Support : 00\n");
+ EFPRINTF(fp, "[0002]\t\tC2 Latency : 0000\n");
+ EFPRINTF(fp, "[0002]\t\tC3 Latency : 0000\n");
+ EFPRINTF(fp, "[0002]\t\tCPU Cache Size : 0000\n");
+ EFPRINTF(fp, "[0002]\t\tCache Flush Stride : 0000\n");
+ EFPRINTF(fp, "[0001]\t\tDuty Cycle Offset : 00\n");
+ EFPRINTF(fp, "[0001]\t\tDuty Cycle Width : 00\n");
+ EFPRINTF(fp, "[0001]\t\tRTC Day Alarm Index : 00\n");
+ EFPRINTF(fp, "[0001]\t\tRTC Month Alarm Index : 00\n");
+ EFPRINTF(fp, "[0001]\t\tRTC Century Index : 00\n");
+ EFPRINTF(fp, "[0002]\t\tBoot Flags (decoded below) : 0000\n");
+ EFPRINTF(fp, "\t\t\tLegacy Devices Supported (V2) : 0\n");
+ EFPRINTF(fp, "\t\t\t8042 Present on ports 60/64 (V2) : 0\n");
+ EFPRINTF(fp, "\t\t\tVGA Not Present (V4) : 1\n");
+ EFPRINTF(fp, "\t\t\tMSI Not Supported (V4) : 0\n");
+ EFPRINTF(fp, "\t\t\tPCIe ASPM Not Supported (V4) : 1\n");
+ EFPRINTF(fp, "\t\t\tCMOS RTC Not Present (V5) : 0\n");
+ EFPRINTF(fp, "[0001]\t\tReserved : 00\n");
+ EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n");
+ EFPRINTF(fp, "\t\t\tWBINVD instruction is operational (V1) : 1\n");
+ EFPRINTF(fp, "\t\t\tWBINVD flushes all caches (V1) : 0\n");
+ EFPRINTF(fp, "\t\t\tAll CPUs support C1 (V1) : 0\n");
+ EFPRINTF(fp, "\t\t\tC2 works on MP system (V1) : 0\n");
+ EFPRINTF(fp, "\t\t\tControl Method Power Button (V1) : 1\n");
+ EFPRINTF(fp, "\t\t\tControl Method Sleep Button (V1) : 1\n");
+ EFPRINTF(fp, "\t\t\tRTC wake not in fixed reg space (V1) : 0\n");
+ EFPRINTF(fp, "\t\t\tRTC can wake system from S4 (V1) : 0\n");
+ EFPRINTF(fp, "\t\t\t32-bit PM Timer (V1) : 1\n");
+ EFPRINTF(fp, "\t\t\tDocking Supported (V1) : 0\n");
+ EFPRINTF(fp, "\t\t\tReset Register Supported (V2) : 0\n");
+ EFPRINTF(fp, "\t\t\tSealed Case (V3) : 0\n");
+ EFPRINTF(fp, "\t\t\tHeadless - No Video (V3) : 1\n");
+ EFPRINTF(fp, "\t\t\tUse native instr after SLP_TYPx (V3) : 0\n");
+ EFPRINTF(fp, "\t\t\tPCIEXP_WAK Bits Supported (V4) : 0\n");
+ EFPRINTF(fp, "\t\t\tUse Platform Timer (V4) : 0\n");
+ EFPRINTF(fp, "\t\t\tRTC_STS valid on S4 wake (V4) : 0\n");
+ EFPRINTF(fp, "\t\t\tRemote Power-on capable (V4) : 0\n");
+ EFPRINTF(fp, "\t\t\tUse APIC Cluster Model (V4) : 0\n");
+ EFPRINTF(fp, "\t\t\tUse APIC Physical Destination Mode (V4) : 1\n");
+ EFPRINTF(fp, "\t\t\tHardware Reduced (V5) : 0\n");
+ EFPRINTF(fp, "\t\t\tLow Power S0 Idle (V5) : 0\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp,
+ "[0012]\t\tReset Register : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp, "[0001]\t\tValue to cause reset : 00\n");
+ EFPRINTF(fp, "[0003]\t\tReserved : 000000\n");
+ EFPRINTF(fp, "[0008]\t\tFACS Address : 00000000%08X\n",
+ basl_acpi_base + FACS_OFFSET);
+ EFPRINTF(fp, "[0008]\t\tDSDT Address : 00000000%08X\n",
+ basl_acpi_base + DSDT_OFFSET);
+ EFPRINTF(fp,
+ "[0012]\t\tPM1A Event Block : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 20\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp,
+ "[0012]\t\tPM1B Event Block : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp,
+ "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp,
+ "[0012]\t\tPM1A Control Block : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 10\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp,
+ "[0012]\t\tPM1B Control Block : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp,
+ "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp,
+ "[0012]\t\tPM2 Control Block : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp,
+ "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
+ EFPRINTF(fp, "\n");
+
+ /* Valid for bhyve */
+ EFPRINTF(fp,
+ "[0012]\t\tPM Timer Block : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 32\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp,
+ "[0001]\t\tEncoded Access Width : 03 [DWord Access:32]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n",
+ BHYVE_PM_TIMER_ADDR);
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp, "[0012]\t\tGPE0 Block : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 80\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp, "[0012]\t\tGPE1 Block : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp,
+ "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp,
+ "[0012]\t\tSleep Control Register : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp,
+ "[0012]\t\tSleep Status Register : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
+
+ EFFLUSH(fp);
+
+ return (0);
+
+err_exit:
+ return (errno);
+}
+
+static int
+basl_fwrite_facs(FILE *fp)
+{
+ int err;
+
+ err = 0;
+
+ EFPRINTF(fp, "/*\n");
+ EFPRINTF(fp, " * bhyve FACS template\n");
+ EFPRINTF(fp, " */\n");
+ EFPRINTF(fp, "[0004]\t\tSignature : \"FACS\"\n");
+ EFPRINTF(fp, "[0004]\t\tLength : 00000040\n");
+ EFPRINTF(fp, "[0004]\t\tHardware Signature : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\t32 Firmware Waking Vector : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tGlobal Lock : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n");
+ EFPRINTF(fp, "\t\t\tS4BIOS Support Present : 0\n");
+ EFPRINTF(fp, "\t\t\t64-bit Wake Supported (V2) : 0\n");
+ EFPRINTF(fp,
+ "[0008]\t\t64 Firmware Waking Vector : 0000000000000000\n");
+ EFPRINTF(fp, "[0001]\t\tVersion : 02\n");
+ EFPRINTF(fp, "[0003]\t\tReserved : 000000\n");
+ EFPRINTF(fp, "[0004]\t\tOspmFlags (decoded below) : 00000000\n");
+ EFPRINTF(fp, "\t\t\t64-bit Wake Env Required (V2) : 0\n");
+
+ EFFLUSH(fp);
+
+ return (0);
+
+err_exit:
+ return (errno);
+}
+
+static int
+basl_fwrite_dsdt(FILE *fp)
+{
+ int err;
+
+ err = 0;
+
+ EFPRINTF(fp, "/*\n");
+ EFPRINTF(fp, " * bhyve DSDT template\n");
+ EFPRINTF(fp, " */\n");
+ EFPRINTF(fp, "DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2,"
+ "\"BHYVE \", \"BVDSDT \", 0x00000001)\n");
+ EFPRINTF(fp, "{\n");
+ EFPRINTF(fp, " Scope (_SB)\n");
+ EFPRINTF(fp, " {\n");
+ EFPRINTF(fp, " Device (PCI0)\n");
+ EFPRINTF(fp, " {\n");
+ EFPRINTF(fp, " Name (_HID, EisaId (\"PNP0A03\"))\n");
+ EFPRINTF(fp, " Name (_ADR, Zero)\n");
+ EFPRINTF(fp, " Name (_UID, One)\n");
+ EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n");
+ EFPRINTF(fp, " {\n");
+ EFPRINTF(fp, " WordBusNumber (ResourceProducer, MinFixed,"
+ "MaxFixed, PosDecode,\n");
+ EFPRINTF(fp, " 0x0000, // Granularity\n");
+ EFPRINTF(fp, " 0x0000, // Range Minimum\n");
+ EFPRINTF(fp, " 0x00FF, // Range Maximum\n");
+ EFPRINTF(fp, " 0x0000, // Transl Offset\n");
+ EFPRINTF(fp, " 0x0100, // Length\n");
+ EFPRINTF(fp, " ,, )\n");
+ EFPRINTF(fp, " IO (Decode16,\n");
+ EFPRINTF(fp, " 0x0CF8, // Range Minimum\n");
+ EFPRINTF(fp, " 0x0CF8, // Range Maximum\n");
+ EFPRINTF(fp, " 0x01, // Alignment\n");
+ EFPRINTF(fp, " 0x08, // Length\n");
+ EFPRINTF(fp, " )\n");
+ EFPRINTF(fp, " WordIO (ResourceProducer, MinFixed, MaxFixed,"
+ "PosDecode, EntireRange,\n");
+ EFPRINTF(fp, " 0x0000, // Granularity\n");
+ EFPRINTF(fp, " 0x0000, // Range Minimum\n");
+ EFPRINTF(fp, " 0x0CF7, // Range Maximum\n");
+ EFPRINTF(fp, " 0x0000, // Transl Offset\n");
+ EFPRINTF(fp, " 0x0CF8, // Length\n");
+ EFPRINTF(fp, " ,, , TypeStatic)\n");
+ EFPRINTF(fp, " WordIO (ResourceProducer, MinFixed, MaxFixed,"
+ "PosDecode, EntireRange,\n");
+ EFPRINTF(fp, " 0x0000, // Granularity\n");
+ EFPRINTF(fp, " 0x0D00, // Range Minimum\n");
+ EFPRINTF(fp, " 0xFFFF, // Range Maximum\n");
+ EFPRINTF(fp, " 0x0000, // Transl Offset\n");
+ EFPRINTF(fp, " 0xF300, // Length\n");
+ EFPRINTF(fp, " ,, , TypeStatic)\n");
+ EFPRINTF(fp, " })\n");
+ EFPRINTF(fp, " }\n");
+ EFPRINTF(fp, " }\n");
+ EFPRINTF(fp, "\n");
+ EFPRINTF(fp, " Scope (_SB.PCI0)\n");
+ EFPRINTF(fp, " {\n");
+ EFPRINTF(fp, " Device (ISA)\n");
+ EFPRINTF(fp, " {\n");
+ EFPRINTF(fp, " Name (_ADR, 0x00010000)\n");
+ EFPRINTF(fp, " OperationRegion (P40C, PCI_Config, 0x60, 0x04)\n");
+ EFPRINTF(fp, " }\n");
+ EFPRINTF(fp, " }\n");
+ EFPRINTF(fp, "\n");
+ EFPRINTF(fp, " Scope (_SB.PCI0.ISA)\n");
+ EFPRINTF(fp, " {\n");
+ EFPRINTF(fp, " Device (RTC)\n");
+ EFPRINTF(fp, " {\n");
+ EFPRINTF(fp, " Name (_HID, EisaId (\"PNP0B00\"))\n");
+ EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n");
+ EFPRINTF(fp, " {\n");
+ EFPRINTF(fp, " IO (Decode16,\n");
+ EFPRINTF(fp, " 0x0070, // Range Minimum\n");
+ EFPRINTF(fp, " 0x0070, // Range Maximum\n");
+ EFPRINTF(fp, " 0x10, // Alignment\n");
+ EFPRINTF(fp, " 0x02, // Length\n");
+ EFPRINTF(fp, " )\n");
+ EFPRINTF(fp, " IRQNoFlags ()\n");
+ EFPRINTF(fp, " {8}\n");
+ EFPRINTF(fp, " IO (Decode16,\n");
+ EFPRINTF(fp, " 0x0072, // Range Minimum\n");
+ EFPRINTF(fp, " 0x0072, // Range Maximum\n");
+ EFPRINTF(fp, " 0x02, // Alignment\n");
+ EFPRINTF(fp, " 0x06, // Length\n");
+ EFPRINTF(fp, " )\n");
+ EFPRINTF(fp, " })\n");
+ EFPRINTF(fp, " }\n");
+ EFPRINTF(fp, " }\n");
+ EFPRINTF(fp, "}\n");
+
+ EFFLUSH(fp);
+
+ return (0);
+
+err_exit:
+ return (errno);
+}
+
+static int
+basl_open(struct basl_fio *bf, int suffix)
+{
+ int err;
+
+ err = 0;
+
+ if (suffix) {
+ strncpy(bf->f_name, basl_stemplate, MAXPATHLEN);
+ bf->fd = mkstemps(bf->f_name, strlen(BHYVE_ASL_SUFFIX));
+ } else {
+ strncpy(bf->f_name, basl_template, MAXPATHLEN);
+ bf->fd = mkstemp(bf->f_name);
+ }
+
+ if (bf->fd > 0) {
+ bf->fp = fdopen(bf->fd, "w+");
+ if (bf->fp == NULL) {
+ unlink(bf->f_name);
+ close(bf->fd);
+ }
+ } else {
+ err = 1;
+ }
+
+ return (err);
+}
+
+static void
+basl_close(struct basl_fio *bf)
+{
+
+ if (!basl_keep_temps)
+ unlink(bf->f_name);
+ fclose(bf->fp);
+}
+
+static int
+basl_start(struct basl_fio *in, struct basl_fio *out)
+{
+ int err;
+
+ err = basl_open(in, 0);
+ if (!err) {
+ err = basl_open(out, 1);
+ if (err) {
+ basl_close(in);
+ }
+ }
+
+ return (err);
+}
+
+static void
+basl_end(struct basl_fio *in, struct basl_fio *out)
+{
+
+ basl_close(in);
+ basl_close(out);
+}
+
+static int
+basl_load(int fd, uint64_t off)
+{
+ struct stat sb;
+ int err;
+
+ err = 0;
+
+ if (fstat(fd, &sb) < 0 ||
+ read(fd, paddr_guest2host(basl_acpi_base + off), sb.st_size) < 0)
+ err = errno;
+
+ return (err);
+}
+
+static int
+basl_compile(int (*fwrite_section)(FILE *fp), uint64_t offset)
+{
+ struct basl_fio io[2];
+ static char iaslbuf[3*MAXPATHLEN + 10];
+ char *fmt;
+ int err;
+
+ err = basl_start(&io[0], &io[1]);
+ if (!err) {
+ err = (*fwrite_section)(io[0].fp);
+
+ if (!err) {
+ /*
+ * iasl sends the results of the compilation to
+ * stdout. Shut this down by using the shell to
+ * redirect stdout to /dev/null, unless the user
+ * has requested verbose output for debugging
+ * purposes
+ */
+ fmt = basl_verbose_iasl ?
+ "%s -p %s %s" :
+ "/bin/sh -c \"%s -p %s %s\" 1> /dev/null";
+
+ snprintf(iaslbuf, sizeof(iaslbuf),
+ fmt,
+ BHYVE_ASL_COMPILER,
+ io[1].f_name, io[0].f_name);
+ err = system(iaslbuf);
+
+ if (!err) {
+ /*
+ * Copy the aml output file into guest
+ * memory at the specified location
+ */
+ err = basl_load(io[1].fd, offset);
+ }
+ }
+ basl_end(&io[0], &io[1]);
+ }
+
+ return (err);
+}
+
+static int
+basl_make_templates(void)
+{
+ const char *tmpdir;
+ int err;
+ int len;
+
+ err = 0;
+
+ /*
+ *
+ */
+ if ((tmpdir = getenv("BHYVE_TMPDIR")) == NULL || *tmpdir == '\0' ||
+ (tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') {
+ tmpdir = _PATH_TMP;
+ }
+
+ len = strlen(tmpdir);
+
+ if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1) < MAXPATHLEN) {
+ strcpy(basl_template, tmpdir);
+ while (len > 0 && basl_template[len - 1] == '/')
+ len--;
+ basl_template[len] = '/';
+ strcpy(&basl_template[len + 1], BHYVE_ASL_TEMPLATE);
+ } else
+ err = E2BIG;
+
+ if (!err) {
+ /*
+ * len has been intialized (and maybe adjusted) above
+ */
+ if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1 +
+ sizeof(BHYVE_ASL_SUFFIX)) < MAXPATHLEN) {
+ strcpy(basl_stemplate, tmpdir);
+ basl_stemplate[len] = '/';
+ strcpy(&basl_stemplate[len + 1], BHYVE_ASL_TEMPLATE);
+ len = strlen(basl_stemplate);
+ strcpy(&basl_stemplate[len], BHYVE_ASL_SUFFIX);
+ } else
+ err = E2BIG;
+ }
+
+ return (err);
+}
+
+static struct {
+ int (*wsect)(FILE *fp);
+ uint64_t offset;
+} basl_ftables[] =
+{
+ { basl_fwrite_rsdp, 0},
+ { basl_fwrite_rsdt, RSDT_OFFSET },
+ { basl_fwrite_xsdt, XSDT_OFFSET },
+ { basl_fwrite_madt, MADT_OFFSET },
+ { basl_fwrite_fadt, FADT_OFFSET },
+ { basl_fwrite_facs, FACS_OFFSET },
+ { basl_fwrite_dsdt, DSDT_OFFSET },
+ { NULL }
+};
+
+int
+acpi_build(struct vmctx *ctx, int ncpu, int ioapic)
+{
+ int err;
+ int i;
+
+ err = 0;
+ basl_ncpu = ncpu;
+
+ if (!ioapic) {
+ fprintf(stderr, "ACPI tables require an ioapic\n");
+ return (EINVAL);
+ }
+
+ /*
+ * For debug, allow the user to have iasl compiler output sent
+ * to stdout rather than /dev/null
+ */
+ if (getenv("BHYVE_ACPI_VERBOSE_IASL"))
+ basl_verbose_iasl = 1;
+
+ /*
+ * Allow the user to keep the generated ASL files for debugging
+ * instead of deleting them following use
+ */
+ if (getenv("BHYVE_ACPI_KEEPTMPS"))
+ basl_keep_temps = 1;
+
+ i = 0;
+ err = basl_make_templates();
+
+ /*
+ * Run through all the ASL files, compiling them and
+ * copying them into guest memory
+ */
+ while (!err && basl_ftables[i].wsect != NULL) {
+ err = basl_compile(basl_ftables[i].wsect,
+ basl_ftables[i].offset);
+ i++;
+ }
+
+ return (err);
+}
diff --git a/usr.sbin/bhyve/acpi.h b/usr.sbin/bhyve/acpi.h
new file mode 100644
index 0000000..fec6c9d
--- /dev/null
+++ b/usr.sbin/bhyve/acpi.h
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _ACPI_H_
+#define _ACPI_H_
+
+int acpi_build(struct vmctx *ctx, int ncpu, int ioapic);
+
+#endif /* _ACPI_H_ */
diff --git a/usr.sbin/bhyve/atpic.c b/usr.sbin/bhyve/atpic.c
new file mode 100644
index 0000000..a9fb084
--- /dev/null
+++ b/usr.sbin/bhyve/atpic.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "inout.h"
+
+/*
+ * FreeBSD only writes to the 8259 interrupt controllers to put them in a
+ * shutdown state.
+ *
+ * So, we just ignore the writes.
+ */
+
+#define IO_ICU1 0x20
+#define IO_ICU2 0xA0
+#define ICU_IMR_OFFSET 1
+
+static int
+atpic_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ if (bytes != 1)
+ return (-1);
+
+ if (in)
+ return (-1);
+
+ /* Pretend all writes to the 8259 are alright */
+ return (0);
+}
+
+INOUT_PORT(atpic, IO_ICU1, IOPORT_F_INOUT, atpic_handler);
+INOUT_PORT(atpic, IO_ICU1 + ICU_IMR_OFFSET, IOPORT_F_INOUT, atpic_handler);
+INOUT_PORT(atpic, IO_ICU2, IOPORT_F_INOUT, atpic_handler);
+INOUT_PORT(atpic, IO_ICU2 + ICU_IMR_OFFSET, IOPORT_F_INOUT, atpic_handler);
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
new file mode 100644
index 0000000..8d03649
--- /dev/null
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -0,0 +1,789 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#include <machine/segments.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <pthread.h>
+#include <pthread_np.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
+#include "bhyverun.h"
+#include "acpi.h"
+#include "inout.h"
+#include "dbgport.h"
+#include "mem.h"
+#include "mevent.h"
+#include "mptbl.h"
+#include "pci_emul.h"
+#include "xmsr.h"
+#include "ioapic.h"
+#include "spinup_ap.h"
+
+#define DEFAULT_GUEST_HZ 100
+#define DEFAULT_GUEST_TSLICE 200
+
+#define GUEST_NIO_PORT 0x488 /* guest upcalls via i/o port */
+
+#define VMEXIT_SWITCH 0 /* force vcpu switch in mux mode */
+#define VMEXIT_CONTINUE 1 /* continue from next instruction */
+#define VMEXIT_RESTART 2 /* restart current instruction */
+#define VMEXIT_ABORT 3 /* abort the vm run loop */
+#define VMEXIT_RESET 4 /* guest machine has reset */
+
+#define MB (1024UL * 1024)
+#define GB (1024UL * MB)
+
+typedef int (*vmexit_handler_t)(struct vmctx *, struct vm_exit *, int *vcpu);
+
+int guest_tslice = DEFAULT_GUEST_TSLICE;
+int guest_hz = DEFAULT_GUEST_HZ;
+char *vmname;
+
+u_long lomem_sz;
+u_long himem_sz;
+
+int guest_ncpus;
+
+static int pincpu = -1;
+static int guest_vcpu_mux;
+static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic;
+
+static int foundcpus;
+
+static int strictio;
+
+static int acpi;
+
+static char *lomem_addr;
+static char *himem_addr;
+
+static char *progname;
+static const int BSP = 0;
+
+static int cpumask;
+
+static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip);
+
+struct vm_exit vmexit[VM_MAXCPU];
+
+struct fbsdstats {
+ uint64_t vmexit_bogus;
+ uint64_t vmexit_bogus_switch;
+ uint64_t vmexit_hlt;
+ uint64_t vmexit_pause;
+ uint64_t vmexit_mtrap;
+ uint64_t vmexit_paging;
+ uint64_t cpu_switch_rotate;
+ uint64_t cpu_switch_direct;
+ int io_reset;
+} stats;
+
+struct mt_vmm_info {
+ pthread_t mt_thr;
+ struct vmctx *mt_ctx;
+ int mt_vcpu;
+} mt_vmm_info[VM_MAXCPU];
+
+static void
+usage(int code)
+{
+
+ fprintf(stderr,
+ "Usage: %s [-aehABHIP][-g <gdb port>][-z <hz>][-s <pci>]"
+ "[-S <pci>][-p pincpu][-n <pci>][-m lowmem][-M highmem]"
+ " <vmname>\n"
+ " -a: local apic is in XAPIC mode (default is X2APIC)\n"
+ " -A: create an ACPI table\n"
+ " -g: gdb port (default is %d and 0 means don't open)\n"
+ " -c: # cpus (default 1)\n"
+ " -p: pin vcpu 'n' to host cpu 'pincpu + n'\n"
+ " -B: inject breakpoint exception on vm entry\n"
+ " -H: vmexit from the guest on hlt\n"
+ " -I: present an ioapic to the guest\n"
+ " -P: vmexit from the guest on pause\n"
+ " -e: exit on unhandled i/o access\n"
+ " -h: help\n"
+ " -z: guest hz (default is %d)\n"
+ " -s: <slot,driver,configinfo> PCI slot config\n"
+ " -S: <slot,driver,configinfo> legacy PCI slot config\n"
+ " -m: lowmem in MB\n"
+ " -M: highmem in MB\n"
+ " -x: mux vcpus to 1 hcpu\n"
+ " -t: mux vcpu timeslice hz (default %d)\n",
+ progname, DEFAULT_GDB_PORT, DEFAULT_GUEST_HZ,
+ DEFAULT_GUEST_TSLICE);
+ exit(code);
+}
+
+void *
+paddr_guest2host(uintptr_t gaddr)
+{
+ if (lomem_sz == 0)
+ return (NULL);
+
+ if (gaddr < lomem_sz) {
+ return ((void *)(lomem_addr + gaddr));
+ } else if (gaddr >= 4*GB && gaddr < (4*GB + himem_sz)) {
+ return ((void *)(himem_addr + gaddr - 4*GB));
+ } else
+ return (NULL);
+}
+
+int
+fbsdrun_disable_x2apic(void)
+{
+
+ return (disable_x2apic);
+}
+
+int
+fbsdrun_vmexit_on_pause(void)
+{
+
+ return (guest_vmexit_on_pause);
+}
+
+int
+fbsdrun_vmexit_on_hlt(void)
+{
+
+ return (guest_vmexit_on_hlt);
+}
+
+int
+fbsdrun_muxed(void)
+{
+
+ return (guest_vcpu_mux);
+}
+
+static void *
+fbsdrun_start_thread(void *param)
+{
+ char tname[MAXCOMLEN + 1];
+ struct mt_vmm_info *mtp;
+ int vcpu;
+
+ mtp = param;
+ vcpu = mtp->mt_vcpu;
+
+ snprintf(tname, sizeof(tname), "%s vcpu %d", vmname, vcpu);
+ pthread_set_name_np(mtp->mt_thr, tname);
+
+ vm_loop(mtp->mt_ctx, vcpu, vmexit[vcpu].rip);
+
+ /* not reached */
+ exit(1);
+ return (NULL);
+}
+
+void
+fbsdrun_addcpu(struct vmctx *ctx, int vcpu, uint64_t rip)
+{
+ int error;
+
+ if (cpumask & (1 << vcpu)) {
+ fprintf(stderr, "addcpu: attempting to add existing cpu %d\n",
+ vcpu);
+ exit(1);
+ }
+
+ cpumask |= 1 << vcpu;
+ foundcpus++;
+
+ /*
+ * Set up the vmexit struct to allow execution to start
+ * at the given RIP
+ */
+ vmexit[vcpu].rip = rip;
+ vmexit[vcpu].inst_length = 0;
+
+ if (vcpu == BSP || !guest_vcpu_mux){
+ mt_vmm_info[vcpu].mt_ctx = ctx;
+ mt_vmm_info[vcpu].mt_vcpu = vcpu;
+
+ error = pthread_create(&mt_vmm_info[vcpu].mt_thr, NULL,
+ fbsdrun_start_thread, &mt_vmm_info[vcpu]);
+ assert(error == 0);
+ }
+}
+
+static int
+fbsdrun_get_next_cpu(int curcpu)
+{
+
+ /*
+ * Get the next available CPU. Assumes they arrive
+ * in ascending order with no gaps.
+ */
+ return ((curcpu + 1) % foundcpus);
+}
+
+static int
+vmexit_catch_reset(void)
+{
+ stats.io_reset++;
+ return (VMEXIT_RESET);
+}
+
+static int
+vmexit_catch_inout(void)
+{
+ return (VMEXIT_ABORT);
+}
+
+static int
+vmexit_handle_notify(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu,
+ uint32_t eax)
+{
+#if PG_DEBUG /* put all types of debug here */
+ if (eax == 0) {
+ pause_noswitch = 1;
+ } else if (eax == 1) {
+ pause_noswitch = 0;
+ } else {
+ pause_noswitch = 0;
+ if (eax == 5) {
+ vm_set_capability(ctx, *pvcpu, VM_CAP_MTRAP_EXIT, 1);
+ }
+ }
+#endif
+ return (VMEXIT_CONTINUE);
+}
+
+static int
+vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
+{
+ int error;
+ int bytes, port, in, out;
+ uint32_t eax;
+ int vcpu;
+
+ vcpu = *pvcpu;
+
+ port = vme->u.inout.port;
+ bytes = vme->u.inout.bytes;
+ eax = vme->u.inout.eax;
+ in = vme->u.inout.in;
+ out = !in;
+
+ /* We don't deal with these */
+ if (vme->u.inout.string || vme->u.inout.rep)
+ return (VMEXIT_ABORT);
+
+ /* Special case of guest reset */
+ if (out && port == 0x64 && (uint8_t)eax == 0xFE)
+ return (vmexit_catch_reset());
+
+ /* Extra-special case of host notifications */
+ if (out && port == GUEST_NIO_PORT)
+ return (vmexit_handle_notify(ctx, vme, pvcpu, eax));
+
+ error = emulate_inout(ctx, vcpu, in, port, bytes, &eax, strictio);
+ if (error == 0 && in)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RAX, eax);
+
+ if (error == 0)
+ return (VMEXIT_CONTINUE);
+ else {
+ fprintf(stderr, "Unhandled %s%c 0x%04x\n",
+ in ? "in" : "out",
+ bytes == 1 ? 'b' : (bytes == 2 ? 'w' : 'l'), port);
+ return (vmexit_catch_inout());
+ }
+}
+
+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);
+}
+
+static int
+vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
+{
+ int newcpu;
+ int retval = VMEXIT_CONTINUE;
+
+ newcpu = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code,vme->u.msr.wval);
+
+ if (guest_vcpu_mux && *pvcpu != newcpu) {
+ retval = VMEXIT_SWITCH;
+ *pvcpu = newcpu;
+ }
+
+ return (retval);
+}
+
+static int
+vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
+{
+ int newcpu;
+ int retval = VMEXIT_CONTINUE;
+
+ newcpu = spinup_ap(ctx, *pvcpu,
+ vme->u.spinup_ap.vcpu, vme->u.spinup_ap.rip);
+
+ if (guest_vcpu_mux && *pvcpu != newcpu) {
+ retval = VMEXIT_SWITCH;
+ *pvcpu = newcpu;
+ }
+
+ return (retval);
+}
+
+static int
+vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+
+ fprintf(stderr, "vm exit[%d]\n", *pvcpu);
+ fprintf(stderr, "\treason\t\tVMX\n");
+ fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
+ fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length);
+ fprintf(stderr, "\terror\t\t%d\n", vmexit->u.vmx.error);
+ fprintf(stderr, "\texit_reason\t%u\n", vmexit->u.vmx.exit_reason);
+ fprintf(stderr, "\tqualification\t0x%016lx\n",
+ vmexit->u.vmx.exit_qualification);
+
+ return (VMEXIT_ABORT);
+}
+
+static int bogus_noswitch = 1;
+
+static int
+vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+ stats.vmexit_bogus++;
+
+ if (!guest_vcpu_mux || guest_ncpus == 1 || bogus_noswitch) {
+ return (VMEXIT_RESTART);
+ } else {
+ stats.vmexit_bogus_switch++;
+ vmexit->inst_length = 0;
+ *pvcpu = -1;
+ return (VMEXIT_SWITCH);
+ }
+}
+
+static int
+vmexit_hlt(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+ stats.vmexit_hlt++;
+ if (fbsdrun_muxed()) {
+ *pvcpu = -1;
+ return (VMEXIT_SWITCH);
+ } else {
+ /*
+ * Just continue execution with the next instruction. We use
+ * the HLT VM exit as a way to be friendly with the host
+ * scheduler.
+ */
+ return (VMEXIT_CONTINUE);
+ }
+}
+
+static int pause_noswitch;
+
+static int
+vmexit_pause(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+ stats.vmexit_pause++;
+
+ if (fbsdrun_muxed() && !pause_noswitch) {
+ *pvcpu = -1;
+ return (VMEXIT_SWITCH);
+ } else {
+ return (VMEXIT_CONTINUE);
+ }
+}
+
+static int
+vmexit_mtrap(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+ stats.vmexit_mtrap++;
+
+ return (VMEXIT_RESTART);
+}
+
+static int
+vmexit_paging(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+ int err;
+ stats.vmexit_paging++;
+
+ err = emulate_mem(ctx, *pvcpu, vmexit->u.paging.gpa,
+ &vmexit->u.paging.vie);
+
+ if (err) {
+ if (err == EINVAL) {
+ fprintf(stderr,
+ "Failed to emulate instruction at 0x%lx\n",
+ vmexit->rip);
+ } else if (err == ESRCH) {
+ fprintf(stderr, "Unhandled memory access to 0x%lx\n",
+ vmexit->u.paging.gpa);
+ }
+
+ return (VMEXIT_ABORT);
+ }
+
+ return (VMEXIT_CONTINUE);
+}
+
+static void
+sigalrm(int sig)
+{
+ return;
+}
+
+static void
+setup_timeslice(void)
+{
+ struct sigaction sa;
+ struct itimerval itv;
+ int error;
+
+ /*
+ * Setup a realtime timer to generate a SIGALRM at a
+ * frequency of 'guest_tslice' ticks per second.
+ */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = sigalrm;
+
+ error = sigaction(SIGALRM, &sa, NULL);
+ assert(error == 0);
+
+ itv.it_interval.tv_sec = 0;
+ itv.it_interval.tv_usec = 1000000 / guest_tslice;
+ itv.it_value.tv_sec = 0;
+ itv.it_value.tv_usec = 1000000 / guest_tslice;
+
+ error = setitimer(ITIMER_REAL, &itv, NULL);
+ assert(error == 0);
+}
+
+static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
+ [VM_EXITCODE_INOUT] = vmexit_inout,
+ [VM_EXITCODE_VMX] = vmexit_vmx,
+ [VM_EXITCODE_BOGUS] = vmexit_bogus,
+ [VM_EXITCODE_RDMSR] = vmexit_rdmsr,
+ [VM_EXITCODE_WRMSR] = vmexit_wrmsr,
+ [VM_EXITCODE_MTRAP] = vmexit_mtrap,
+ [VM_EXITCODE_PAGING] = vmexit_paging,
+ [VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
+};
+
+static void
+vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
+{
+ int error, rc, prevcpu;
+
+ if (guest_vcpu_mux)
+ setup_timeslice();
+
+ if (pincpu >= 0) {
+ error = vm_set_pinning(ctx, vcpu, pincpu + vcpu);
+ assert(error == 0);
+ }
+
+ while (1) {
+ error = vm_run(ctx, vcpu, rip, &vmexit[vcpu]);
+ if (error != 0) {
+ /*
+ * It is possible that 'vmmctl' or some other process
+ * has transitioned the vcpu to CANNOT_RUN state right
+ * before we tried to transition it to RUNNING.
+ *
+ * This is expected to be temporary so just retry.
+ */
+ if (errno == EBUSY)
+ continue;
+ else
+ break;
+ }
+
+ prevcpu = vcpu;
+ rc = (*handler[vmexit[vcpu].exitcode])(ctx, &vmexit[vcpu],
+ &vcpu);
+ switch (rc) {
+ case VMEXIT_SWITCH:
+ assert(guest_vcpu_mux);
+ if (vcpu == -1) {
+ stats.cpu_switch_rotate++;
+ vcpu = fbsdrun_get_next_cpu(prevcpu);
+ } else {
+ stats.cpu_switch_direct++;
+ }
+ /* fall through */
+ case VMEXIT_CONTINUE:
+ rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length;
+ break;
+ case VMEXIT_RESTART:
+ rip = vmexit[vcpu].rip;
+ break;
+ case VMEXIT_RESET:
+ exit(0);
+ default:
+ exit(1);
+ }
+ }
+ fprintf(stderr, "vm_run error %d, errno %d\n", error, errno);
+}
+
+static int
+num_vcpus_allowed(struct vmctx *ctx)
+{
+ int tmp, error;
+
+ error = vm_get_capability(ctx, BSP, VM_CAP_UNRESTRICTED_GUEST, &tmp);
+
+ /*
+ * The guest is allowed to spinup more than one processor only if the
+ * UNRESTRICTED_GUEST capability is available.
+ */
+ if (error == 0)
+ return (VM_MAXCPU);
+ else
+ return (1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c, error, gdb_port, inject_bkpt, tmp, err, ioapic, bvmcons;
+ int max_vcpus;
+ struct vmctx *ctx;
+ uint64_t rip;
+
+ bvmcons = 0;
+ inject_bkpt = 0;
+ progname = basename(argv[0]);
+ gdb_port = DEFAULT_GDB_PORT;
+ guest_ncpus = 1;
+ ioapic = 0;
+
+ while ((c = getopt(argc, argv, "abehABHIPxp:g:c:z:s:S:n:m:M:")) != -1) {
+ switch (c) {
+ case 'a':
+ disable_x2apic = 1;
+ break;
+ case 'A':
+ acpi = 1;
+ break;
+ case 'b':
+ bvmcons = 1;
+ break;
+ case 'B':
+ inject_bkpt = 1;
+ break;
+ case 'x':
+ guest_vcpu_mux = 1;
+ break;
+ case 'p':
+ pincpu = atoi(optarg);
+ break;
+ case 'c':
+ guest_ncpus = atoi(optarg);
+ break;
+ case 'g':
+ gdb_port = atoi(optarg);
+ break;
+ case 'z':
+ guest_hz = atoi(optarg);
+ break;
+ case 't':
+ guest_tslice = atoi(optarg);
+ break;
+ case 's':
+ pci_parse_slot(optarg, 0);
+ break;
+ case 'S':
+ pci_parse_slot(optarg, 1);
+ break;
+ case 'm':
+ lomem_sz = strtoul(optarg, NULL, 0) * MB;
+ break;
+ case 'M':
+ himem_sz = strtoul(optarg, NULL, 0) * MB;
+ break;
+ case 'H':
+ guest_vmexit_on_hlt = 1;
+ break;
+ case 'I':
+ ioapic = 1;
+ break;
+ case 'P':
+ guest_vmexit_on_pause = 1;
+ break;
+ case 'e':
+ strictio = 1;
+ break;
+ case 'h':
+ usage(0);
+ default:
+ usage(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage(1);
+
+ /* No need to mux if guest is uni-processor */
+ if (guest_ncpus <= 1)
+ guest_vcpu_mux = 0;
+
+ /* vmexit on hlt if guest is muxed */
+ if (guest_vcpu_mux) {
+ guest_vmexit_on_hlt = 1;
+ guest_vmexit_on_pause = 1;
+ }
+
+ vmname = argv[0];
+
+ ctx = vm_open(vmname);
+ if (ctx == NULL) {
+ perror("vm_open");
+ exit(1);
+ }
+
+ max_vcpus = num_vcpus_allowed(ctx);
+ if (guest_ncpus > max_vcpus) {
+ fprintf(stderr, "%d vCPUs requested but only %d available\n",
+ guest_ncpus, max_vcpus);
+ exit(1);
+ }
+
+ if (fbsdrun_vmexit_on_hlt()) {
+ err = vm_get_capability(ctx, BSP, VM_CAP_HALT_EXIT, &tmp);
+ if (err < 0) {
+ fprintf(stderr, "VM exit on HLT not supported\n");
+ exit(1);
+ }
+ vm_set_capability(ctx, BSP, VM_CAP_HALT_EXIT, 1);
+ handler[VM_EXITCODE_HLT] = vmexit_hlt;
+ }
+
+ if (fbsdrun_vmexit_on_pause()) {
+ /*
+ * pause exit support required for this mode
+ */
+ err = vm_get_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, &tmp);
+ if (err < 0) {
+ fprintf(stderr,
+ "SMP mux requested, no pause support\n");
+ exit(1);
+ }
+ vm_set_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, 1);
+ handler[VM_EXITCODE_PAUSE] = vmexit_pause;
+ }
+
+ if (fbsdrun_disable_x2apic())
+ err = vm_set_x2apic_state(ctx, BSP, X2APIC_DISABLED);
+ else
+ err = vm_set_x2apic_state(ctx, BSP, X2APIC_ENABLED);
+
+ if (err) {
+ fprintf(stderr, "Unable to set x2apic state (%d)\n", err);
+ exit(1);
+ }
+
+ if (lomem_sz != 0) {
+ lomem_addr = vm_map_memory(ctx, 0, lomem_sz);
+ if (lomem_addr == (char *) MAP_FAILED) {
+ lomem_sz = 0;
+ } else if (himem_sz != 0) {
+ himem_addr = vm_map_memory(ctx, 4*GB, himem_sz);
+ if (himem_addr == (char *) MAP_FAILED) {
+ lomem_sz = 0;
+ himem_sz = 0;
+ }
+ }
+ }
+
+ init_inout();
+ init_pci(ctx);
+ if (ioapic)
+ ioapic_init(0);
+
+ if (gdb_port != 0)
+ init_dbgport(gdb_port);
+
+ if (bvmcons)
+ init_bvmcons();
+
+ error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip);
+ assert(error == 0);
+
+ if (inject_bkpt) {
+ error = vm_inject_event(ctx, BSP, VM_HW_EXCEPTION, IDT_BP);
+ assert(error == 0);
+ }
+
+ /*
+ * build the guest tables, MP etc.
+ */
+ mptable_build(ctx, guest_ncpus, ioapic);
+
+ if (acpi) {
+ error = acpi_build(ctx, guest_ncpus, ioapic);
+ assert(error == 0);
+ }
+
+ /*
+ * Add CPU 0
+ */
+ fbsdrun_addcpu(ctx, BSP, rip);
+
+ /*
+ * Head off to the main event dispatch loop
+ */
+ mevent_dispatch();
+
+ exit(1);
+}
diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h
new file mode 100644
index 0000000..45033b8
--- /dev/null
+++ b/usr.sbin/bhyve/bhyverun.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _FBSDRUN_H_
+#define _FBSDRUN_H_
+
+#ifndef CTASSERT /* Allow lint to override */
+#define CTASSERT(x) _CTASSERT(x, __LINE__)
+#define _CTASSERT(x, y) __CTASSERT(x, y)
+#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1]
+#endif
+
+struct vmctx;
+extern int guest_hz;
+extern int guest_tslice;
+extern int guest_ncpus;
+extern char *vmname;
+
+extern u_long lomem_sz, himem_sz;
+
+void *paddr_guest2host(uintptr_t);
+
+void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip);
+int fbsdrun_muxed(void);
+int fbsdrun_vmexit_on_hlt(void);
+int fbsdrun_vmexit_on_pause(void);
+int fbsdrun_disable_x2apic(void);
+#endif
diff --git a/usr.sbin/bhyve/consport.c b/usr.sbin/bhyve/consport.c
new file mode 100644
index 0000000..3915b6d
--- /dev/null
+++ b/usr.sbin/bhyve/consport.c
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/select.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "inout.h"
+
+#define BVM_CONSOLE_PORT 0x220
+#define BVM_CONS_SIG ('b' << 8 | 'v')
+
+static struct termios tio_orig, tio_new;
+
+static void
+ttyclose(void)
+{
+ tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig);
+}
+
+static void
+ttyopen(void)
+{
+ tcgetattr(STDIN_FILENO, &tio_orig);
+
+ cfmakeraw(&tio_new);
+ tcsetattr(STDIN_FILENO, TCSANOW, &tio_new);
+
+ atexit(ttyclose);
+}
+
+static bool
+tty_char_available(void)
+{
+ fd_set rfds;
+ struct timeval tv;
+
+ FD_ZERO(&rfds);
+ FD_SET(STDIN_FILENO, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0) {
+ return (true);
+ } else {
+ return (false);
+ }
+}
+
+static int
+ttyread(void)
+{
+ char rb;
+
+ if (tty_char_available()) {
+ read(STDIN_FILENO, &rb, 1);
+ return (rb & 0xff);
+ } else {
+ return (-1);
+ }
+}
+
+static void
+ttywrite(unsigned char wb)
+{
+ (void) write(STDOUT_FILENO, &wb, 1);
+}
+
+static int
+console_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ static int opened;
+
+ if (bytes == 2 && in) {
+ *eax = BVM_CONS_SIG;
+ return (0);
+ }
+
+ if (bytes != 4)
+ return (-1);
+
+ if (!opened) {
+ ttyopen();
+ opened = 1;
+ }
+
+ if (in)
+ *eax = ttyread();
+ else
+ ttywrite(*eax);
+
+ return (0);
+}
+
+static struct inout_port consport = {
+ "bvmcons",
+ BVM_CONSOLE_PORT,
+ IOPORT_F_INOUT,
+ console_handler
+};
+
+void
+init_bvmcons(void)
+{
+
+ register_inout(&consport);
+}
diff --git a/usr.sbin/bhyve/dbgport.c b/usr.sbin/bhyve/dbgport.c
new file mode 100644
index 0000000..034531c
--- /dev/null
+++ b/usr.sbin/bhyve/dbgport.c
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "inout.h"
+#include "dbgport.h"
+
+#define BVM_DBG_PORT 0x224
+#define BVM_DBG_SIG ('B' << 8 | 'V')
+
+static int listen_fd, conn_fd;
+
+static struct sockaddr_in sin;
+
+static int
+dbg_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ char ch;
+ int nwritten, nread, printonce;
+
+ if (bytes == 2 && in) {
+ *eax = BVM_DBG_SIG;
+ return (0);
+ }
+
+ if (bytes != 4)
+ return (-1);
+
+again:
+ printonce = 0;
+ while (conn_fd < 0) {
+ if (!printonce) {
+ printf("Waiting for connection from gdb\r\n");
+ printonce = 1;
+ }
+ conn_fd = accept(listen_fd, NULL, NULL);
+ if (conn_fd >= 0)
+ fcntl(conn_fd, F_SETFL, O_NONBLOCK);
+ else if (errno != EINTR)
+ perror("accept");
+ }
+
+ if (in) {
+ nread = read(conn_fd, &ch, 1);
+ if (nread == -1 && errno == EAGAIN)
+ *eax = -1;
+ else if (nread == 1)
+ *eax = ch;
+ else {
+ close(conn_fd);
+ conn_fd = -1;
+ goto again;
+ }
+ } else {
+ ch = *eax;
+ nwritten = write(conn_fd, &ch, 1);
+ if (nwritten != 1) {
+ close(conn_fd);
+ conn_fd = -1;
+ goto again;
+ }
+ }
+ return (0);
+}
+
+static struct inout_port dbgport = {
+ "bvmdbg",
+ BVM_DBG_PORT,
+ IOPORT_F_INOUT,
+ dbg_handler
+};
+
+void
+init_dbgport(int sport)
+{
+ conn_fd = -1;
+
+ if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons(sport);
+
+ if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ perror("bind");
+ exit(1);
+ }
+
+ if (listen(listen_fd, 1) < 0) {
+ perror("listen");
+ exit(1);
+ }
+
+ register_inout(&dbgport);
+}
diff --git a/usr.sbin/bhyve/dbgport.h b/usr.sbin/bhyve/dbgport.h
new file mode 100644
index 0000000..8c7dab7
--- /dev/null
+++ b/usr.sbin/bhyve/dbgport.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DBGPORT_H_
+#define _DBGPORT_H_
+
+#define DEFAULT_GDB_PORT 6466
+
+void init_dbgport(int port);
+
+#endif
diff --git a/usr.sbin/bhyve/elcr.c b/usr.sbin/bhyve/elcr.c
new file mode 100644
index 0000000..2417ae1
--- /dev/null
+++ b/usr.sbin/bhyve/elcr.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include "inout.h"
+
+/*
+ * EISA interrupt Level Control Register.
+ *
+ * This is a 16-bit register with one bit for each of the IRQ0 through IRQ15.
+ * A level triggered irq is indicated by setting the corresponding bit to '1'.
+ */
+#define ELCR_PORT 0x4d0
+
+static uint8_t elcr[2] = { 0x00, 0x00 };
+
+static int
+elcr_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ int idx;
+
+ if (bytes != 1)
+ return (-1);
+
+ idx = port - ELCR_PORT;
+
+ if (in)
+ *eax = elcr[idx];
+ else
+ elcr[idx] = *eax;
+
+ return (0);
+}
+INOUT_PORT(elcr, ELCR_PORT + 0, IOPORT_F_INOUT, elcr_handler);
+INOUT_PORT(elcr, ELCR_PORT + 1, IOPORT_F_INOUT, elcr_handler);
diff --git a/usr.sbin/bhyve/inout.c b/usr.sbin/bhyve/inout.c
new file mode 100644
index 0000000..5f47a89f
--- /dev/null
+++ b/usr.sbin/bhyve/inout.c
@@ -0,0 +1,151 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/linker_set.h>
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "inout.h"
+
+SET_DECLARE(inout_port_set, struct inout_port);
+
+#define MAX_IOPORTS (1 << 16)
+
+static struct {
+ const char *name;
+ int flags;
+ inout_func_t handler;
+ void *arg;
+} inout_handlers[MAX_IOPORTS];
+
+static int
+default_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ if (in) {
+ switch (bytes) {
+ case 4:
+ *eax = 0xffffffff;
+ break;
+ case 2:
+ *eax = 0xffff;
+ break;
+ case 1:
+ *eax = 0xff;
+ break;
+ }
+ }
+
+ return (0);
+}
+
+int
+emulate_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, int strict)
+{
+ int flags;
+ uint32_t mask;
+ inout_func_t handler;
+ void *arg;
+
+ assert(port < MAX_IOPORTS);
+
+ handler = inout_handlers[port].handler;
+
+ if (strict && handler == default_inout)
+ return (-1);
+
+ if (!in) {
+ switch (bytes) {
+ case 1:
+ mask = 0xff;
+ break;
+ case 2:
+ mask = 0xffff;
+ break;
+ default:
+ mask = 0xffffffff;
+ break;
+ }
+ *eax = *eax & mask;
+ }
+
+ flags = inout_handlers[port].flags;
+ arg = inout_handlers[port].arg;
+
+ if ((in && (flags & IOPORT_F_IN)) || (!in && (flags & IOPORT_F_OUT)))
+ return ((*handler)(ctx, vcpu, in, port, bytes, eax, arg));
+ else
+ return (-1);
+}
+
+void
+init_inout(void)
+{
+ struct inout_port **iopp, *iop;
+ int i;
+
+ /*
+ * Set up the default handler for all ports
+ */
+ for (i = 0; i < MAX_IOPORTS; i++) {
+ inout_handlers[i].name = "default";
+ inout_handlers[i].flags = IOPORT_F_IN | IOPORT_F_OUT;
+ inout_handlers[i].handler = default_inout;
+ inout_handlers[i].arg = NULL;
+ }
+
+ /*
+ * Overwrite with specified handlers
+ */
+ SET_FOREACH(iopp, inout_port_set) {
+ iop = *iopp;
+ assert(iop->port < MAX_IOPORTS);
+ inout_handlers[iop->port].name = iop->name;
+ inout_handlers[iop->port].flags = iop->flags;
+ inout_handlers[iop->port].handler = iop->handler;
+ inout_handlers[iop->port].arg = NULL;
+ }
+}
+
+int
+register_inout(struct inout_port *iop)
+{
+ assert(iop->port < MAX_IOPORTS);
+ inout_handlers[iop->port].name = iop->name;
+ inout_handlers[iop->port].flags = iop->flags;
+ inout_handlers[iop->port].handler = iop->handler;
+ inout_handlers[iop->port].arg = iop->arg;
+
+ return (0);
+}
diff --git a/usr.sbin/bhyve/inout.h b/usr.sbin/bhyve/inout.h
new file mode 100644
index 0000000..a73b78d
--- /dev/null
+++ b/usr.sbin/bhyve/inout.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _INOUT_H_
+#define _INOUT_H_
+
+#include <sys/linker_set.h>
+
+struct vmctx;
+
+typedef int (*inout_func_t)(struct vmctx *ctx, int vcpu, int in, int port,
+ int bytes, uint32_t *eax, void *arg);
+
+struct inout_port {
+ const char *name;
+ int port;
+ int flags;
+ inout_func_t handler;
+ void *arg;
+};
+#define IOPORT_F_IN 0x1
+#define IOPORT_F_OUT 0x2
+#define IOPORT_F_INOUT 0x3
+
+#define INOUT_PORT(name, port, flags, handler) \
+ static struct inout_port __CONCAT(__inout_port, __LINE__) = { \
+ #name, \
+ (port), \
+ (flags), \
+ (handler), \
+ 0 \
+ }; \
+ DATA_SET(inout_port_set, __CONCAT(__inout_port, __LINE__))
+
+void init_inout(void);
+int emulate_inout(struct vmctx *, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, int strict);
+int register_inout(struct inout_port *iop);
+
+void init_bvmcons(void);
+
+#endif /* _INOUT_H_ */
diff --git a/usr.sbin/bhyve/ioapic.c b/usr.sbin/bhyve/ioapic.c
new file mode 100644
index 0000000..c712692
--- /dev/null
+++ b/usr.sbin/bhyve/ioapic.c
@@ -0,0 +1,324 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <x86/apicreg.h>
+#include <machine/vmm.h>
+
+#include <string.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include <vmmapi.h>
+
+#include "inout.h"
+#include "mem.h"
+#include "bhyverun.h"
+
+#include <stdio.h>
+
+#define IOAPIC_PADDR 0xFEC00000
+
+#define IOREGSEL 0x00
+#define IOWIN 0x10
+
+#define REDIR_ENTRIES 16
+#define INTR_ASSERTED(ioapic, pin) ((ioapic)->pinstate[(pin)] == true)
+
+struct ioapic {
+ int inited;
+ uint32_t id;
+ uint64_t redtbl[REDIR_ENTRIES];
+ bool pinstate[REDIR_ENTRIES];
+
+ uintptr_t paddr; /* gpa where the ioapic is mapped */
+ uint32_t ioregsel;
+ struct memory_region *region;
+};
+
+static struct ioapic ioapics[1]; /* only a single ioapic for now */
+
+static int ioapic_region_read(struct ioapic *ioapic, uintptr_t paddr,
+ int size, uint64_t *data);
+static int ioapic_region_write(struct ioapic *ioapic, uintptr_t paddr,
+ int size, uint64_t data);
+static int ioapic_region_handler(struct vmctx *vm, int vcpu, int dir,
+ uintptr_t paddr, int size, uint64_t *val,
+ void *arg1, long arg2);
+
+static void
+ioapic_set_pinstate(struct vmctx *ctx, int pin, bool newstate)
+{
+ int vector, apicid, vcpu;
+ uint32_t low, high;
+ struct ioapic *ioapic;
+
+ ioapic = &ioapics[0]; /* assume a single ioapic */
+
+ if (pin < 0 || pin >= REDIR_ENTRIES)
+ return;
+
+ /* Nothing to do if interrupt pin has not changed state */
+ if (ioapic->pinstate[pin] == newstate)
+ return;
+
+ ioapic->pinstate[pin] = newstate; /* record it */
+
+ /* Nothing to do if interrupt pin is deasserted */
+ if (!INTR_ASSERTED(ioapic, pin))
+ return;
+
+ /*
+ * XXX
+ * We only deal with:
+ * - edge triggered interrupts
+ * - physical destination mode
+ * - fixed delivery mode
+ */
+ low = ioapic->redtbl[pin];
+ high = ioapic->redtbl[pin] >> 32;
+ if ((low & IOART_INTMASK) == IOART_INTMCLR &&
+ (low & IOART_TRGRMOD) == IOART_TRGREDG &&
+ (low & IOART_DESTMOD) == IOART_DESTPHY &&
+ (low & IOART_DELMOD) == IOART_DELFIXED) {
+ vector = low & IOART_INTVEC;
+ apicid = high >> APIC_ID_SHIFT;
+ if (apicid != 0xff) {
+ /* unicast */
+ vcpu = vm_apicid2vcpu(ctx, apicid);
+ vm_lapic_irq(ctx, vcpu, vector);
+ } else {
+ /* broadcast */
+ vcpu = 0;
+ while (vcpu < guest_ncpus) {
+ vm_lapic_irq(ctx, vcpu, vector);
+ vcpu++;
+ }
+ }
+ }
+}
+
+void
+ioapic_deassert_pin(struct vmctx *ctx, int pin)
+{
+ ioapic_set_pinstate(ctx, pin, false);
+}
+
+void
+ioapic_assert_pin(struct vmctx *ctx, int pin)
+{
+ ioapic_set_pinstate(ctx, pin, true);
+}
+
+void
+ioapic_init(int which)
+{
+ struct mem_range memp;
+ struct ioapic *ioapic;
+ int error;
+ int i;
+
+ assert(which == 0);
+
+ ioapic = &ioapics[which];
+ assert(ioapic->inited == 0);
+
+ bzero(ioapic, sizeof(struct ioapic));
+
+ /* Initialize all redirection entries to mask all interrupts */
+ for (i = 0; i < REDIR_ENTRIES; i++)
+ ioapic->redtbl[i] = 0x0001000000010000UL;
+
+ ioapic->paddr = IOAPIC_PADDR;
+
+ /* Register emulated memory region */
+ memp.name = "ioapic";
+ memp.flags = MEM_F_RW;
+ memp.handler = ioapic_region_handler;
+ memp.arg1 = ioapic;
+ memp.arg2 = which;
+ memp.base = ioapic->paddr;
+ memp.size = sizeof(struct IOAPIC);
+ error = register_mem(&memp);
+
+ assert (error == 0);
+
+ ioapic->inited = 1;
+}
+
+static uint32_t
+ioapic_read(struct ioapic *ioapic, uint32_t addr)
+{
+ int regnum, pin, rshift;
+
+ assert(ioapic->inited);
+
+ regnum = addr & 0xff;
+ switch (regnum) {
+ case IOAPIC_ID:
+ return (ioapic->id);
+ break;
+ case IOAPIC_VER:
+ return ((REDIR_ENTRIES << MAXREDIRSHIFT) | 0x11);
+ break;
+ case IOAPIC_ARB:
+ return (ioapic->id);
+ break;
+ default:
+ break;
+ }
+
+ /* redirection table entries */
+ if (regnum >= IOAPIC_REDTBL &&
+ regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) {
+ pin = (regnum - IOAPIC_REDTBL) / 2;
+ if ((regnum - IOAPIC_REDTBL) % 2)
+ rshift = 32;
+ else
+ rshift = 0;
+
+ return (ioapic->redtbl[pin] >> rshift);
+ }
+
+ return (0);
+}
+
+static void
+ioapic_write(struct ioapic *ioapic, uint32_t addr, uint32_t data)
+{
+ int regnum, pin, lshift;
+
+ assert(ioapic->inited);
+
+ regnum = addr & 0xff;
+ switch (regnum) {
+ case IOAPIC_ID:
+ ioapic->id = data & APIC_ID_MASK;
+ break;
+ case IOAPIC_VER:
+ case IOAPIC_ARB:
+ /* readonly */
+ break;
+ default:
+ break;
+ }
+
+ /* redirection table entries */
+ if (regnum >= IOAPIC_REDTBL &&
+ regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) {
+ pin = (regnum - IOAPIC_REDTBL) / 2;
+ if ((regnum - IOAPIC_REDTBL) % 2)
+ lshift = 32;
+ else
+ lshift = 0;
+
+ ioapic->redtbl[pin] &= ~((uint64_t)0xffffffff << lshift);
+ ioapic->redtbl[pin] |= ((uint64_t)data << lshift);
+ }
+}
+
+static int
+ioapic_region_read(struct ioapic *ioapic, uintptr_t paddr, int size,
+ uint64_t *data)
+{
+ int offset;
+
+ offset = paddr - ioapic->paddr;
+
+ /*
+ * The IOAPIC specification allows 32-bit wide accesses to the
+ * IOREGSEL (offset 0) and IOWIN (offset 16) registers.
+ */
+ if (size != 4 || (offset != IOREGSEL && offset != IOWIN)) {
+#if 1
+ printf("invalid access to ioapic%d: size %d, offset %d\n",
+ (int)(ioapic - ioapics), size, offset);
+#endif
+ *data = 0;
+ return (0);
+ }
+
+ if (offset == IOREGSEL)
+ *data = ioapic->ioregsel;
+ else
+ *data = ioapic_read(ioapic, ioapic->ioregsel);
+
+ return (0);
+}
+
+static int
+ioapic_region_write(struct ioapic *ioapic, uintptr_t paddr, int size,
+ uint64_t data)
+{
+ int offset;
+
+ offset = paddr - ioapic->paddr;
+
+ /*
+ * The ioapic specification allows 32-bit wide accesses to the
+ * IOREGSEL (offset 0) and IOWIN (offset 16) registers.
+ */
+ if (size != 4 || (offset != IOREGSEL && offset != IOWIN)) {
+#if 1
+ printf("invalid access to ioapic%d: size %d, offset %d\n",
+ (int)(ioapic - ioapics), size, offset);
+#endif
+ return (0);
+ }
+
+ if (offset == IOREGSEL)
+ ioapic->ioregsel = data;
+ else
+ ioapic_write(ioapic, ioapic->ioregsel, data);
+
+ return (0);
+}
+
+static int
+ioapic_region_handler(struct vmctx *vm, int vcpu, int dir, uintptr_t paddr,
+ int size, uint64_t *val, void *arg1, long arg2)
+{
+ struct ioapic *ioapic;
+ int which;
+
+ ioapic = arg1;
+ which = arg2;
+
+ assert(ioapic == &ioapics[which]);
+
+ if (dir == MEM_F_READ)
+ ioapic_region_read(ioapic, paddr, size, val);
+ else
+ ioapic_region_write(ioapic, paddr, size, *val);
+
+ return (0);
+}
diff --git a/usr.sbin/bhyve/ioapic.h b/usr.sbin/bhyve/ioapic.h
new file mode 100644
index 0000000..4696f9a
--- /dev/null
+++ b/usr.sbin/bhyve/ioapic.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IOAPIC_H_
+#define _IOAPIC_H_
+
+struct vmctx;
+
+void ioapic_init(int num);
+void ioapic_deassert_pin(struct vmctx *ctx, int pin);
+void ioapic_assert_pin(struct vmctx *ctx, int pin);
+
+#endif
diff --git a/usr.sbin/bhyve/mem.c b/usr.sbin/bhyve/mem.c
new file mode 100644
index 0000000..27f4782
--- /dev/null
+++ b/usr.sbin/bhyve/mem.c
@@ -0,0 +1,218 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Memory ranges are represented with an RB tree. On insertion, the range
+ * is checked for overlaps. On lookup, the key has the same base and limit
+ * so it can be searched within the range.
+ *
+ * It is assumed that all setup of ranges takes place in single-threaded
+ * mode before vCPUs have been started. As such, no locks are used on the
+ * RB tree. If this is no longer the case, then a r/w lock could be used,
+ * with readers on the lookup and a writer if the tree needs to be changed
+ * (and per vCPU caches flushed)
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/tree.h>
+#include <sys/errno.h>
+#include <machine/vmm.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "mem.h"
+
+struct mmio_rb_range {
+ RB_ENTRY(mmio_rb_range) mr_link; /* RB tree links */
+ struct mem_range mr_param;
+ uint64_t mr_base;
+ uint64_t mr_end;
+};
+
+struct mmio_rb_tree;
+RB_PROTOTYPE(mmio_rb_tree, mmio_rb_range, mr_link, mmio_rb_range_compare);
+
+RB_HEAD(mmio_rb_tree, mmio_rb_range) mmio_rbroot;
+
+/*
+ * Per-vCPU cache. Since most accesses from a vCPU will be to
+ * consecutive addresses in a range, it makes sense to cache the
+ * result of a lookup.
+ */
+static struct mmio_rb_range *mmio_hint[VM_MAXCPU];
+
+static int
+mmio_rb_range_compare(struct mmio_rb_range *a, struct mmio_rb_range *b)
+{
+ if (a->mr_end < b->mr_base)
+ return (-1);
+ else if (a->mr_base > b->mr_end)
+ return (1);
+ return (0);
+}
+
+static int
+mmio_rb_lookup(uint64_t addr, struct mmio_rb_range **entry)
+{
+ struct mmio_rb_range find, *res;
+
+ find.mr_base = find.mr_end = addr;
+
+ res = RB_FIND(mmio_rb_tree, &mmio_rbroot, &find);
+
+ if (res != NULL) {
+ *entry = res;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+mmio_rb_add(struct mmio_rb_range *new)
+{
+ struct mmio_rb_range *overlap;
+
+ overlap = RB_INSERT(mmio_rb_tree, &mmio_rbroot, new);
+
+ if (overlap != NULL) {
+#ifdef RB_DEBUG
+ printf("overlap detected: new %lx:%lx, tree %lx:%lx\n",
+ new->mr_base, new->mr_end,
+ overlap->mr_base, overlap->mr_end);
+#endif
+
+ return (EEXIST);
+ }
+
+ return (0);
+}
+
+#if 0
+static void
+mmio_rb_dump(void)
+{
+ struct mmio_rb_range *np;
+
+ RB_FOREACH(np, mmio_rb_tree, &mmio_rbroot) {
+ printf(" %lx:%lx, %s\n", np->mr_base, np->mr_end,
+ np->mr_param.name);
+ }
+}
+#endif
+
+RB_GENERATE(mmio_rb_tree, mmio_rb_range, mr_link, mmio_rb_range_compare);
+
+static int
+mem_read(void *ctx, int vcpu, uint64_t gpa, uint64_t *rval, int size, void *arg)
+{
+ int error;
+ struct mem_range *mr = arg;
+
+ error = (*mr->handler)(ctx, vcpu, MEM_F_READ, gpa, size,
+ rval, mr->arg1, mr->arg2);
+ return (error);
+}
+
+static int
+mem_write(void *ctx, int vcpu, uint64_t gpa, uint64_t wval, int size, void *arg)
+{
+ int error;
+ struct mem_range *mr = arg;
+
+ error = (*mr->handler)(ctx, vcpu, MEM_F_WRITE, gpa, size,
+ &wval, mr->arg1, mr->arg2);
+ return (error);
+}
+
+int
+emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie)
+{
+ struct mmio_rb_range *entry;
+ int err;
+
+ /*
+ * First check the per-vCPU cache
+ */
+ if (mmio_hint[vcpu] &&
+ paddr >= mmio_hint[vcpu]->mr_base &&
+ paddr <= mmio_hint[vcpu]->mr_end) {
+ entry = mmio_hint[vcpu];
+ } else
+ entry = NULL;
+
+ if (entry == NULL) {
+ if (mmio_rb_lookup(paddr, &entry))
+ return (ESRCH);
+
+ /* Update the per-vCPU cache */
+ mmio_hint[vcpu] = entry;
+ }
+
+ assert(entry != NULL && entry == mmio_hint[vcpu]);
+
+ err = vmm_emulate_instruction(ctx, vcpu, paddr, vie,
+ mem_read, mem_write, &entry->mr_param);
+ return (err);
+}
+
+int
+register_mem(struct mem_range *memp)
+{
+ struct mmio_rb_range *mrp;
+ int err;
+
+ err = 0;
+
+ mrp = malloc(sizeof(struct mmio_rb_range));
+
+ if (mrp != NULL) {
+ mrp->mr_param = *memp;
+ mrp->mr_base = memp->base;
+ mrp->mr_end = memp->base + memp->size - 1;
+
+ err = mmio_rb_add(mrp);
+ if (err)
+ free(mrp);
+ } else
+ err = ENOMEM;
+
+ return (err);
+}
+
+void
+init_mem(void)
+{
+
+ RB_INIT(&mmio_rbroot);
+}
diff --git a/usr.sbin/bhyve/mem.h b/usr.sbin/bhyve/mem.h
new file mode 100644
index 0000000..88fafe1
--- /dev/null
+++ b/usr.sbin/bhyve/mem.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MEM_H_
+#define _MEM_H_
+
+#include <sys/linker_set.h>
+
+struct vmctx;
+
+typedef int (*mem_func_t)(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
+ int size, uint64_t *val, void *arg1, long arg2);
+
+struct mem_range {
+ const char *name;
+ int flags;
+ mem_func_t handler;
+ void *arg1;
+ long arg2;
+ uint64_t base;
+ uint64_t size;
+};
+#define MEM_F_READ 0x1
+#define MEM_F_WRITE 0x2
+#define MEM_F_RW 0x3
+
+void init_mem(void);
+int emulate_mem(struct vmctx *, int vcpu, uint64_t paddr, struct vie *vie);
+
+int register_mem(struct mem_range *memp);
+
+#endif /* _MEM_H_ */
diff --git a/usr.sbin/bhyve/mevent.c b/usr.sbin/bhyve/mevent.c
new file mode 100644
index 0000000..a6109db
--- /dev/null
+++ b/usr.sbin/bhyve/mevent.c
@@ -0,0 +1,432 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Micro event library for FreeBSD, designed for a single i/o thread
+ * using kqueue, and having events be persistent by default.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+
+#include <pthread.h>
+#include <pthread_np.h>
+
+#include "mevent.h"
+
+#define MEVENT_MAX 64
+
+#define MEV_ENABLE 1
+#define MEV_DISABLE 2
+#define MEV_DEL_PENDING 3
+
+extern char *vmname;
+
+static pthread_t mevent_tid;
+static int mevent_pipefd[2];
+static pthread_mutex_t mevent_lmutex = PTHREAD_MUTEX_INITIALIZER;
+
+struct mevent {
+ void (*me_func)(int, enum ev_type, void *);
+ int me_fd;
+ enum ev_type me_type;
+ void *me_param;
+ int me_cq;
+ int me_state;
+ int me_closefd;
+ LIST_ENTRY(mevent) me_list;
+};
+
+static LIST_HEAD(listhead, mevent) global_head, change_head;
+
+static void
+mevent_qlock(void)
+{
+ pthread_mutex_lock(&mevent_lmutex);
+}
+
+static void
+mevent_qunlock(void)
+{
+ pthread_mutex_unlock(&mevent_lmutex);
+}
+
+static void
+mevent_pipe_read(int fd, enum ev_type type, void *param)
+{
+ char buf[MEVENT_MAX];
+ int status;
+
+ /*
+ * Drain the pipe read side. The fd is non-blocking so this is
+ * safe to do.
+ */
+ do {
+ status = read(fd, buf, sizeof(buf));
+ } while (status == MEVENT_MAX);
+}
+
+static void
+mevent_notify(void)
+{
+ char c;
+
+ /*
+ * If calling from outside the i/o thread, write a byte on the
+ * pipe to force the i/o thread to exit the blocking kevent call.
+ */
+ if (mevent_pipefd[1] != 0 && pthread_self() != mevent_tid) {
+ write(mevent_pipefd[1], &c, 1);
+ }
+}
+
+static int
+mevent_kq_filter(struct mevent *mevp)
+{
+ int retval;
+
+ retval = 0;
+
+ if (mevp->me_type == EVF_READ)
+ retval = EVFILT_READ;
+
+ if (mevp->me_type == EVF_WRITE)
+ retval = EVFILT_WRITE;
+
+ return (retval);
+}
+
+static int
+mevent_kq_flags(struct mevent *mevp)
+{
+ int ret;
+
+ switch (mevp->me_state) {
+ case MEV_ENABLE:
+ ret = EV_ADD;
+ break;
+ case MEV_DISABLE:
+ ret = EV_DISABLE;
+ break;
+ case MEV_DEL_PENDING:
+ ret = EV_DELETE;
+ break;
+ }
+
+ return (ret);
+}
+
+static int
+mevent_kq_fflags(struct mevent *mevp)
+{
+ /* XXX nothing yet, perhaps EV_EOF for reads ? */
+ return (0);
+}
+
+static int
+mevent_build(int mfd, struct kevent *kev)
+{
+ struct mevent *mevp, *tmpp;
+ int i;
+
+ i = 0;
+
+ mevent_qlock();
+
+ LIST_FOREACH_SAFE(mevp, &change_head, me_list, tmpp) {
+ if (mevp->me_closefd) {
+ /*
+ * A close of the file descriptor will remove the
+ * event
+ */
+ close(mevp->me_fd);
+ } else {
+ kev[i].ident = mevp->me_fd;
+ kev[i].filter = mevent_kq_filter(mevp);
+ kev[i].flags = mevent_kq_flags(mevp);
+ kev[i].fflags = mevent_kq_fflags(mevp);
+ kev[i].data = 0;
+ kev[i].udata = mevp;
+ i++;
+ }
+
+ mevp->me_cq = 0;
+ LIST_REMOVE(mevp, me_list);
+
+ if (mevp->me_state == MEV_DEL_PENDING) {
+ free(mevp);
+ } else {
+ LIST_INSERT_HEAD(&global_head, mevp, me_list);
+ }
+
+ assert(i < MEVENT_MAX);
+ }
+
+ mevent_qunlock();
+
+ return (i);
+}
+
+static void
+mevent_handle(struct kevent *kev, int numev)
+{
+ struct mevent *mevp;
+ int i;
+
+ for (i = 0; i < numev; i++) {
+ mevp = kev[i].udata;
+
+ /* XXX check for EV_ERROR ? */
+
+ (*mevp->me_func)(mevp->me_fd, mevp->me_type, mevp->me_param);
+ }
+}
+
+struct mevent *
+mevent_add(int fd, enum ev_type type,
+ void (*func)(int, enum ev_type, void *), void *param)
+{
+ struct mevent *lp, *mevp;
+
+ if (fd < 0 || func == NULL) {
+ return (NULL);
+ }
+
+ mevp = NULL;
+
+ mevent_qlock();
+
+ /*
+ * Verify that the fd/type tuple is not present in any list
+ */
+ LIST_FOREACH(lp, &global_head, me_list) {
+ if (lp->me_fd == fd && lp->me_type == type) {
+ goto exit;
+ }
+ }
+
+ LIST_FOREACH(lp, &change_head, me_list) {
+ if (lp->me_fd == fd && lp->me_type == type) {
+ goto exit;
+ }
+ }
+
+ /*
+ * Allocate an entry, populate it, and add it to the change list.
+ */
+ mevp = malloc(sizeof(struct mevent));
+ if (mevp == NULL) {
+ goto exit;
+ }
+
+ memset(mevp, 0, sizeof(struct mevent));
+ mevp->me_fd = fd;
+ mevp->me_type = type;
+ mevp->me_func = func;
+ mevp->me_param = param;
+
+ LIST_INSERT_HEAD(&change_head, mevp, me_list);
+ mevp->me_cq = 1;
+ mevp->me_state = MEV_ENABLE;
+ mevent_notify();
+
+exit:
+ mevent_qunlock();
+
+ return (mevp);
+}
+
+static int
+mevent_update(struct mevent *evp, int newstate)
+{
+ /*
+ * It's not possible to enable/disable a deleted event
+ */
+ if (evp->me_state == MEV_DEL_PENDING)
+ return (EINVAL);
+
+ /*
+ * No update needed if state isn't changing
+ */
+ if (evp->me_state == newstate)
+ return (0);
+
+ mevent_qlock();
+
+ evp->me_state = newstate;
+
+ /*
+ * Place the entry onto the changed list if not already there.
+ */
+ if (evp->me_cq == 0) {
+ evp->me_cq = 1;
+ LIST_REMOVE(evp, me_list);
+ LIST_INSERT_HEAD(&change_head, evp, me_list);
+ mevent_notify();
+ }
+
+ mevent_qunlock();
+
+ return (0);
+}
+
+int
+mevent_enable(struct mevent *evp)
+{
+
+ return (mevent_update(evp, MEV_ENABLE));
+}
+
+int
+mevent_disable(struct mevent *evp)
+{
+
+ return (mevent_update(evp, MEV_DISABLE));
+}
+
+static int
+mevent_delete_event(struct mevent *evp, int closefd)
+{
+ mevent_qlock();
+
+ /*
+ * Place the entry onto the changed list if not already there, and
+ * mark as to be deleted.
+ */
+ if (evp->me_cq == 0) {
+ evp->me_cq = 1;
+ LIST_REMOVE(evp, me_list);
+ LIST_INSERT_HEAD(&change_head, evp, me_list);
+ mevent_notify();
+ }
+ evp->me_state = MEV_DEL_PENDING;
+
+ if (closefd)
+ evp->me_closefd = 1;
+
+ mevent_qunlock();
+
+ return (0);
+}
+
+int
+mevent_delete(struct mevent *evp)
+{
+
+ return (mevent_delete_event(evp, 0));
+}
+
+int
+mevent_delete_close(struct mevent *evp)
+{
+
+ return (mevent_delete_event(evp, 1));
+}
+
+static void
+mevent_set_name(void)
+{
+ char tname[MAXCOMLEN + 1];
+
+ snprintf(tname, sizeof(tname), "%s mevent", vmname);
+ pthread_set_name_np(mevent_tid, tname);
+}
+
+void
+mevent_dispatch(void)
+{
+ struct kevent changelist[MEVENT_MAX];
+ struct kevent eventlist[MEVENT_MAX];
+ struct mevent *pipev;
+ int mfd;
+ int numev;
+ int ret;
+
+ mevent_tid = pthread_self();
+ mevent_set_name();
+
+ mfd = kqueue();
+ assert(mfd > 0);
+
+ /*
+ * Open the pipe that will be used for other threads to force
+ * the blocking kqueue call to exit by writing to it. Set the
+ * descriptor to non-blocking.
+ */
+ ret = pipe(mevent_pipefd);
+ if (ret < 0) {
+ perror("pipe");
+ exit(0);
+ }
+
+ /*
+ * Add internal event handler for the pipe write fd
+ */
+ pipev = mevent_add(mevent_pipefd[0], EVF_READ, mevent_pipe_read, NULL);
+ assert(pipev != NULL);
+
+ for (;;) {
+ /*
+ * Build changelist if required.
+ * XXX the changelist can be put into the blocking call
+ * to eliminate the extra syscall. Currently better for
+ * debug.
+ */
+ numev = mevent_build(mfd, changelist);
+ if (numev) {
+ ret = kevent(mfd, changelist, numev, NULL, 0, NULL);
+ if (ret == -1) {
+ perror("Error return from kevent change");
+ }
+ }
+
+ /*
+ * Block awaiting events
+ */
+ ret = kevent(mfd, NULL, 0, eventlist, MEVENT_MAX, NULL);
+ if (ret == -1) {
+ perror("Error return from kevent monitor");
+ }
+
+ /*
+ * Handle reported events
+ */
+ mevent_handle(eventlist, ret);
+ }
+}
diff --git a/usr.sbin/bhyve/mevent.h b/usr.sbin/bhyve/mevent.h
new file mode 100644
index 0000000..32a9d74
--- /dev/null
+++ b/usr.sbin/bhyve/mevent.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MEVENT_H_
+#define _MEVENT_H_
+
+enum ev_type {
+ EVF_READ,
+ EVF_WRITE
+};
+
+struct mevent;
+
+struct mevent *mevent_add(int fd, enum ev_type type,
+ void (*func)(int, enum ev_type, void *),
+ void *param);
+int mevent_enable(struct mevent *evp);
+int mevent_disable(struct mevent *evp);
+int mevent_delete(struct mevent *evp);
+int mevent_delete_close(struct mevent *evp);
+
+void mevent_dispatch(void);
+
+#endif /* _MEVENT_H_ */
diff --git a/usr.sbin/bhyve/mevent_test.c b/usr.sbin/bhyve/mevent_test.c
new file mode 100644
index 0000000..c72a497
--- /dev/null
+++ b/usr.sbin/bhyve/mevent_test.c
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Test program for the micro event library. Set up a simple TCP echo
+ * service.
+ *
+ * cc mevent_test.c mevent.c -lpthread
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "mevent.h"
+
+#define TEST_PORT 4321
+
+static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t accept_condvar = PTHREAD_COND_INITIALIZER;
+
+#define MEVENT_ECHO
+
+#ifdef MEVENT_ECHO
+struct esync {
+ pthread_mutex_t e_mt;
+ pthread_cond_t e_cond;
+};
+
+static void
+echoer_callback(int fd, enum ev_type type, void *param)
+{
+ struct esync *sync = param;
+
+ pthread_mutex_lock(&sync->e_mt);
+ pthread_cond_signal(&sync->e_cond);
+ pthread_mutex_unlock(&sync->e_mt);
+}
+
+static void *
+echoer(void *param)
+{
+ struct esync sync;
+ struct mevent *mev;
+ char buf[128];
+ int fd = (int)(uintptr_t) param;
+ int len;
+
+ pthread_mutex_init(&sync.e_mt, NULL);
+ pthread_cond_init(&sync.e_cond, NULL);
+
+ pthread_mutex_lock(&sync.e_mt);
+
+ mev = mevent_add(fd, EVF_READ, echoer_callback, &sync);
+ if (mev == NULL) {
+ printf("Could not allocate echoer event\n");
+ exit(1);
+ }
+
+ while (!pthread_cond_wait(&sync.e_cond, &sync.e_mt)) {
+ len = read(fd, buf, sizeof(buf));
+ if (len > 0) {
+ write(fd, buf, len);
+ write(0, buf, len);
+ } else {
+ break;
+ }
+ }
+
+ mevent_delete_close(mev);
+
+ pthread_mutex_unlock(&sync.e_mt);
+ pthread_mutex_destroy(&sync.e_mt);
+ pthread_cond_destroy(&sync.e_cond);
+}
+
+#else
+
+static void *
+echoer(void *param)
+{
+ char buf[128];
+ int fd = (int)(uintptr_t) param;
+ int len;
+
+ while ((len = read(fd, buf, sizeof(buf))) > 0) {
+ write(1, buf, len);
+ }
+}
+#endif /* MEVENT_ECHO */
+
+static void
+acceptor_callback(int fd, enum ev_type type, void *param)
+{
+ pthread_mutex_lock(&accept_mutex);
+ pthread_cond_signal(&accept_condvar);
+ pthread_mutex_unlock(&accept_mutex);
+}
+
+static void *
+acceptor(void *param)
+{
+ struct sockaddr_in sin;
+ pthread_t tid;
+ int news;
+ int s;
+
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons(TEST_PORT);
+
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ perror("bind");
+ exit(1);
+ }
+
+ if (listen(s, 1) < 0) {
+ perror("listen");
+ exit(1);
+ }
+
+ (void) mevent_add(s, EVF_READ, acceptor_callback, NULL);
+
+ pthread_mutex_lock(&accept_mutex);
+
+ while (!pthread_cond_wait(&accept_condvar, &accept_mutex)) {
+ news = accept(s, NULL, NULL);
+ if (news < 0) {
+ perror("accept error");
+ } else {
+ printf("incoming connection, spawning thread\n");
+ pthread_create(&tid, NULL, echoer,
+ (void *)(uintptr_t)news);
+ }
+ }
+}
+
+main()
+{
+ pthread_t tid;
+
+ pthread_create(&tid, NULL, acceptor, NULL);
+
+ mevent_dispatch();
+}
diff --git a/usr.sbin/bhyve/mptbl.c b/usr.sbin/bhyve/mptbl.c
new file mode 100644
index 0000000..52790f3
--- /dev/null
+++ b/usr.sbin/bhyve/mptbl.c
@@ -0,0 +1,398 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <x86/mptable.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "bhyverun.h"
+#include "mptbl.h"
+
+#define MPTABLE_BASE 0xF0000
+
+#define LAPIC_PADDR 0xFEE00000
+#define LAPIC_VERSION 16
+
+#define IOAPIC_PADDR 0xFEC00000
+#define IOAPIC_VERSION 0x11
+
+#define MP_SPECREV 4
+#define MPFP_SIG "_MP_"
+
+/* Configuration header defines */
+#define MPCH_SIG "PCMP"
+#define MPCH_OEMID "BHyVe "
+#define MPCH_OEMID_LEN 8
+#define MPCH_PRODID "Hypervisor "
+#define MPCH_PRODID_LEN 12
+
+/* Processor entry defines */
+#define MPEP_SIG_FAMILY 6 /* XXX bhyve should supply this */
+#define MPEP_SIG_MODEL 26
+#define MPEP_SIG_STEPPING 5
+#define MPEP_SIG \
+ ((MPEP_SIG_FAMILY << 8) | \
+ (MPEP_SIG_MODEL << 4) | \
+ (MPEP_SIG_STEPPING))
+
+#define MPEP_FEATURES (0xBFEBFBFF) /* XXX Intel i7 */
+
+/* Define processor entry struct since <x86/mptable.h> gets it wrong */
+typedef struct BPROCENTRY {
+ u_char type;
+ u_char apic_id;
+ u_char apic_version;
+ u_char cpu_flags;
+ uint32_t cpu_signature;
+ uint32_t feature_flags;
+ uint32_t reserved1;
+ uint32_t reserved2;
+} *bproc_entry_ptr;
+CTASSERT(sizeof(struct BPROCENTRY) == 20);
+
+/* Bus entry defines */
+#define MPE_NUM_BUSES 2
+#define MPE_BUSNAME_LEN 6
+#define MPE_BUSNAME_ISA "ISA "
+#define MPE_BUSNAME_PCI "PCI "
+
+static void *oem_tbl_start;
+static int oem_tbl_size;
+
+static uint8_t
+mpt_compute_checksum(void *base, size_t len)
+{
+ uint8_t *bytes;
+ uint8_t sum;
+
+ for(bytes = base, sum = 0; len > 0; len--) {
+ sum += *bytes++;
+ }
+
+ return (256 - sum);
+}
+
+static void
+mpt_build_mpfp(mpfps_t mpfp, vm_paddr_t gpa)
+{
+
+ memset(mpfp, 0, sizeof(*mpfp));
+ memcpy(mpfp->signature, MPFP_SIG, 4);
+ mpfp->pap = gpa + sizeof(*mpfp);
+ mpfp->length = 1;
+ mpfp->spec_rev = MP_SPECREV;
+ mpfp->checksum = mpt_compute_checksum(mpfp, sizeof(*mpfp));
+}
+
+static void
+mpt_build_mpch(mpcth_t mpch)
+{
+
+ memset(mpch, 0, sizeof(*mpch));
+ memcpy(mpch->signature, MPCH_SIG, 4);
+ mpch->spec_rev = MP_SPECREV;
+ memcpy(mpch->oem_id, MPCH_OEMID, MPCH_OEMID_LEN);
+ memcpy(mpch->product_id, MPCH_PRODID, MPCH_PRODID_LEN);
+ mpch->apic_address = LAPIC_PADDR;
+}
+
+static void
+mpt_build_proc_entries(bproc_entry_ptr mpep, int ncpu)
+{
+ int i;
+
+ for (i = 0; i < ncpu; i++) {
+ memset(mpep, 0, sizeof(*mpep));
+ mpep->type = MPCT_ENTRY_PROCESSOR;
+ mpep->apic_id = i; // XXX
+ mpep->apic_version = LAPIC_VERSION;
+ mpep->cpu_flags = PROCENTRY_FLAG_EN;
+ if (i == 0)
+ mpep->cpu_flags |= PROCENTRY_FLAG_BP;
+ mpep->cpu_signature = MPEP_SIG;
+ mpep->feature_flags = MPEP_FEATURES;
+ mpep++;
+ }
+}
+
+static void
+mpt_build_bus_entries(bus_entry_ptr mpeb)
+{
+
+ memset(mpeb, 0, sizeof(*mpeb));
+ mpeb->type = MPCT_ENTRY_BUS;
+ mpeb->bus_id = ISA;
+ memcpy(mpeb->bus_type, MPE_BUSNAME_ISA, MPE_BUSNAME_LEN);
+ mpeb++;
+
+ memset(mpeb, 0, sizeof(*mpeb));
+ mpeb->type = MPCT_ENTRY_BUS;
+ mpeb->bus_id = PCI;
+ memcpy(mpeb->bus_type, MPE_BUSNAME_PCI, MPE_BUSNAME_LEN);
+}
+
+static void
+mpt_build_ioapic_entries(io_apic_entry_ptr mpei, int id)
+{
+
+ memset(mpei, 0, sizeof(*mpei));
+ mpei->type = MPCT_ENTRY_IOAPIC;
+ mpei->apic_id = id;
+ mpei->apic_version = IOAPIC_VERSION;
+ mpei->apic_flags = IOAPICENTRY_FLAG_EN;
+ mpei->apic_address = IOAPIC_PADDR;
+}
+
+#ifdef notyet
+static void
+mpt_build_ioint_entries(struct mpe_ioint *mpeii, int num_pins, int id)
+{
+ int pin;
+
+ /*
+ * The following config is taken from kernel mptable.c
+ * mptable_parse_default_config_ints(...), for now
+ * just use the default config, tweek later if needed.
+ */
+
+
+ /* Run through all 16 pins. */
+ for (pin = 0; pin < num_pins; pin++) {
+ memset(mpeii, 0, sizeof(*mpeii));
+ mpeii->entry_type = MP_ENTRY_IOINT;
+ mpeii->src_bus_id = MPE_BUSID_ISA;
+ mpeii->dst_apic_id = id;
+
+ /*
+ * All default configs route IRQs from bus 0 to the first 16
+ * pins of the first I/O APIC with an APIC ID of 2.
+ */
+ mpeii->dst_apic_intin = pin;
+ switch (pin) {
+ case 0:
+ /* Pin 0 is an ExtINT pin. */
+ mpeii->intr_type = MPEII_INTR_EXTINT;
+ break;
+ case 2:
+ /* IRQ 0 is routed to pin 2. */
+ mpeii->intr_type = MPEII_INTR_INT;
+ mpeii->src_bus_irq = 0;
+ break;
+ case 5:
+ case 10:
+ case 11:
+ /*
+ * PCI Irqs set to level triggered.
+ */
+ mpeii->intr_flags = MPEII_FLAGS_TRIGMODE_LEVEL;
+ mpeii->src_bus_id = MPE_BUSID_PCI;
+ default:
+ /* All other pins are identity mapped. */
+ mpeii->intr_type = MPEII_INTR_INT;
+ mpeii->src_bus_irq = pin;
+ break;
+ }
+ mpeii++;
+ }
+
+}
+
+#define COPYSTR(dest, src, bytes) \
+ memcpy(dest, src, bytes); \
+ str[bytes] = 0;
+
+static void
+mptable_dump(struct mp_floating_pointer *mpfp, struct mp_config_hdr *mpch)
+{
+ static char str[16];
+ int i;
+ char *cur;
+
+ union mpe {
+ struct mpe_proc *proc;
+ struct mpe_bus *bus;
+ struct mpe_ioapic *ioapic;
+ struct mpe_ioint *ioint;
+ struct mpe_lint *lnit;
+ char *p;
+ };
+
+ union mpe mpe;
+
+ printf(" MP Floating Pointer :\n");
+ COPYSTR(str, mpfp->signature, 4);
+ printf("\tsignature:\t%s\n", str);
+ printf("\tmpch paddr:\t%x\n", mpfp->mptable_paddr);
+ printf("\tlength:\t%x\n", mpfp->length);
+ printf("\tspecrec:\t%x\n", mpfp->specrev);
+ printf("\tchecksum:\t%x\n", mpfp->checksum);
+ printf("\tfeature1:\t%x\n", mpfp->feature1);
+ printf("\tfeature2:\t%x\n", mpfp->feature2);
+ printf("\tfeature3:\t%x\n", mpfp->feature3);
+ printf("\tfeature4:\t%x\n", mpfp->feature4);
+
+ printf(" MP Configuration Header :\n");
+ COPYSTR(str, mpch->signature, 4);
+ printf(" signature: %s\n", str);
+ printf(" length: %x\n", mpch->length);
+ printf(" specrec: %x\n", mpch->specrev);
+ printf(" checksum: %x\n", mpch->checksum);
+ COPYSTR(str, mpch->oemid, MPCH_OEMID_LEN);
+ printf(" oemid: %s\n", str);
+ COPYSTR(str, mpch->prodid, MPCH_PRODID_LEN);
+ printf(" prodid: %s\n", str);
+ printf(" oem_ptr: %x\n", mpch->oem_ptr);
+ printf(" oem_sz: %x\n", mpch->oem_sz);
+ printf(" nr_entries: %x\n", mpch->nr_entries);
+ printf(" apic paddr: %x\n", mpch->lapic_paddr);
+ printf(" ext_length: %x\n", mpch->ext_length);
+ printf(" ext_checksum: %x\n", mpch->ext_checksum);
+
+ cur = (char *)mpch + sizeof(*mpch);
+ for (i = 0; i < mpch->nr_entries; i++) {
+ mpe.p = cur;
+ switch(*mpe.p) {
+ case MP_ENTRY_PROC:
+ printf(" MP Processor Entry :\n");
+ printf(" lapic_id: %x\n", mpe.proc->lapic_id);
+ printf(" lapic_version: %x\n", mpe.proc->lapic_version);
+ printf(" proc_flags: %x\n", mpe.proc->proc_flags);
+ printf(" proc_signature: %x\n", mpe.proc->proc_signature);
+ printf(" feature_flags: %x\n", mpe.proc->feature_flags);
+ cur += sizeof(struct mpe_proc);
+ break;
+ case MP_ENTRY_BUS:
+ printf(" MP Bus Entry :\n");
+ printf(" busid: %x\n", mpe.bus->busid);
+ COPYSTR(str, mpe.bus->busname, MPE_BUSNAME_LEN);
+ printf(" busname: %s\n", str);
+ cur += sizeof(struct mpe_bus);
+ break;
+ case MP_ENTRY_IOAPIC:
+ printf(" MP IOAPIC Entry :\n");
+ printf(" ioapi_id: %x\n", mpe.ioapic->ioapic_id);
+ printf(" ioapi_version: %x\n", mpe.ioapic->ioapic_version);
+ printf(" ioapi_flags: %x\n", mpe.ioapic->ioapic_flags);
+ printf(" ioapi_paddr: %x\n", mpe.ioapic->ioapic_paddr);
+ cur += sizeof(struct mpe_ioapic);
+ break;
+ case MP_ENTRY_IOINT:
+ printf(" MP IO Interrupt Entry :\n");
+ printf(" intr_type: %x\n", mpe.ioint->intr_type);
+ printf(" intr_flags: %x\n", mpe.ioint->intr_flags);
+ printf(" src_bus_id: %x\n", mpe.ioint->src_bus_id);
+ printf(" src_bus_irq: %x\n", mpe.ioint->src_bus_irq);
+ printf(" dst_apic_id: %x\n", mpe.ioint->dst_apic_id);
+ printf(" dst_apic_intin: %x\n", mpe.ioint->dst_apic_intin);
+ cur += sizeof(struct mpe_ioint);
+ break;
+ case MP_ENTRY_LINT:
+ printf(" MP Local Interrupt Entry :\n");
+ cur += sizeof(struct mpe_lint);
+ break;
+ }
+
+ }
+}
+#endif
+
+void
+mptable_add_oemtbl(void *tbl, int tblsz)
+{
+
+ oem_tbl_start = tbl;
+ oem_tbl_size = tblsz;
+}
+
+int
+mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
+{
+ mpcth_t mpch;
+ bus_entry_ptr mpeb;
+ io_apic_entry_ptr mpei;
+ bproc_entry_ptr mpep;
+ mpfps_t mpfp;
+ char *curraddr;
+ char *startaddr;
+
+ if (paddr_guest2host(0) == NULL) {
+ printf("mptable requires mapped mem\n");
+ return (ENOMEM);
+ }
+
+ startaddr = curraddr = paddr_guest2host(MPTABLE_BASE);
+
+ mpfp = (mpfps_t)curraddr;
+ mpt_build_mpfp(mpfp, MPTABLE_BASE);
+ curraddr += sizeof(*mpfp);
+
+ mpch = (mpcth_t)curraddr;
+ mpt_build_mpch(mpch);
+ curraddr += sizeof(*mpch);
+
+ mpep = (bproc_entry_ptr)curraddr;
+ mpt_build_proc_entries(mpep, ncpu);
+ curraddr += sizeof(*mpep) * ncpu;
+ mpch->entry_count += ncpu;
+
+ mpeb = (bus_entry_ptr) curraddr;
+ mpt_build_bus_entries(mpeb);
+ curraddr += sizeof(*mpeb) * MPE_NUM_BUSES;
+ mpch->entry_count += MPE_NUM_BUSES;
+
+ if (ioapic) {
+ mpei = (io_apic_entry_ptr)curraddr;
+ mpt_build_ioapic_entries(mpei, ncpu + 1);
+ curraddr += sizeof(*mpei);
+ mpch->entry_count++;
+ }
+
+#ifdef notyet
+ mpt_build_ioint_entries((struct mpe_ioint*)curraddr, MPEII_MAX_IRQ,
+ ncpu + 1);
+ curraddr += sizeof(struct mpe_ioint) * MPEII_MAX_IRQ;
+ mpch->entry_count += MPEII_MAX_IRQ;
+#endif
+
+ if (oem_tbl_start) {
+ mpch->oem_table_pointer = curraddr - startaddr + MPTABLE_BASE;
+ mpch->oem_table_size = oem_tbl_size;
+ memcpy(curraddr, oem_tbl_start, oem_tbl_size);
+ }
+
+ mpch->base_table_length = curraddr - (char *)mpch;
+ mpch->checksum = mpt_compute_checksum(mpch, sizeof(*mpch));
+
+ return (0);
+}
diff --git a/usr.sbin/bhyve/mptbl.h b/usr.sbin/bhyve/mptbl.h
new file mode 100644
index 0000000..3c4c527
--- /dev/null
+++ b/usr.sbin/bhyve/mptbl.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MPTBL_H_
+#define _MPTBL_H_
+
+int mptable_build(struct vmctx *ctx, int ncpu, int ioapic);
+void mptable_add_oemtbl(void *tbl, int tblsz);
+
+#endif /* _MPTBL_H_ */
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
new file mode 100644
index 0000000..32a3deb
--- /dev/null
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -0,0 +1,1339 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/linker_set.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
+#include "bhyverun.h"
+#include "inout.h"
+#include "mem.h"
+#include "mptbl.h"
+#include "pci_emul.h"
+#include "ioapic.h"
+
+#define CONF1_ADDR_PORT 0x0cf8
+#define CONF1_DATA_PORT 0x0cfc
+
+#define CFGWRITE(pi,off,val,b) \
+do { \
+ if ((b) == 1) { \
+ pci_set_cfgdata8((pi),(off),(val)); \
+ } else if ((b) == 2) { \
+ pci_set_cfgdata16((pi),(off),(val)); \
+ } else { \
+ pci_set_cfgdata32((pi),(off),(val)); \
+ } \
+} while (0)
+
+#define MAXSLOTS (PCI_SLOTMAX + 1)
+#define MAXFUNCS (PCI_FUNCMAX + 1)
+
+static struct slotinfo {
+ char *si_name;
+ char *si_param;
+ struct pci_devinst *si_devi;
+ int si_legacy;
+} pci_slotinfo[MAXSLOTS][MAXFUNCS];
+
+/*
+ * Used to keep track of legacy interrupt owners/requestors
+ */
+#define NLIRQ 16
+
+static struct lirqinfo {
+ int li_generic;
+ int li_acount;
+ struct pci_devinst *li_owner; /* XXX should be a list */
+} lirq[NLIRQ];
+
+SET_DECLARE(pci_devemu_set, struct pci_devemu);
+
+static uint64_t pci_emul_iobase;
+static uint64_t pci_emul_membase32;
+static uint64_t pci_emul_membase64;
+
+#define PCI_EMUL_IOBASE 0x2000
+#define PCI_EMUL_IOLIMIT 0x10000
+
+#define PCI_EMUL_MEMBASE32 (lomem_sz)
+#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */
+
+#define PCI_EMUL_MEMBASE64 0xD000000000UL
+#define PCI_EMUL_MEMLIMIT64 0xFD00000000UL
+
+static int pci_emul_devices;
+
+/*
+ * I/O access
+ */
+
+/*
+ * Slot options are in the form:
+ *
+ * <slot>[:<func>],<emul>[,<config>]
+ *
+ * slot is 0..31
+ * func is 0..7
+ * emul is a string describing the type of PCI device e.g. virtio-net
+ * config is an optional string, depending on the device, that can be
+ * used for configuration.
+ * Examples are:
+ * 1,virtio-net,tap0
+ * 3:0,dummy
+ */
+static void
+pci_parse_slot_usage(char *aopt)
+{
+ printf("Invalid PCI slot info field \"%s\"\n", aopt);
+ free(aopt);
+}
+
+void
+pci_parse_slot(char *opt, int legacy)
+{
+ char *slot, *func, *emul, *config;
+ char *str, *cpy;
+ int snum, fnum;
+
+ str = cpy = strdup(opt);
+
+ config = NULL;
+
+ if (strchr(str, ':') != NULL) {
+ slot = strsep(&str, ":");
+ func = strsep(&str, ",");
+ } else {
+ slot = strsep(&str, ",");
+ func = NULL;
+ }
+
+ emul = strsep(&str, ",");
+ if (str != NULL) {
+ config = strsep(&str, ",");
+ }
+
+ if (emul == NULL) {
+ pci_parse_slot_usage(cpy);
+ return;
+ }
+
+ snum = atoi(slot);
+ fnum = func ? atoi(func) : 0;
+ if (snum < 0 || snum >= MAXSLOTS || fnum < 0 || fnum >= MAXFUNCS) {
+ pci_parse_slot_usage(cpy);
+ } else {
+ pci_slotinfo[snum][fnum].si_name = emul;
+ pci_slotinfo[snum][fnum].si_param = config;
+ pci_slotinfo[snum][fnum].si_legacy = legacy;
+ }
+}
+
+static int
+pci_valid_pba_offset(struct pci_devinst *pi, uint64_t offset)
+{
+
+ if (offset < pi->pi_msix.pba_offset)
+ return (0);
+
+ if (offset >= pi->pi_msix.pba_offset + pi->pi_msix.pba_size) {
+ return (0);
+ }
+
+ return (1);
+}
+
+int
+pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size,
+ uint64_t value)
+{
+ int msix_entry_offset;
+ int tab_index;
+ char *dest;
+
+ /* support only 4 or 8 byte writes */
+ if (size != 4 && size != 8)
+ return (-1);
+
+ /*
+ * Return if table index is beyond what device supports
+ */
+ tab_index = offset / MSIX_TABLE_ENTRY_SIZE;
+ if (tab_index >= pi->pi_msix.table_count)
+ return (-1);
+
+ msix_entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
+
+ /* support only aligned writes */
+ if ((msix_entry_offset % size) != 0)
+ return (-1);
+
+ dest = (char *)(pi->pi_msix.table + tab_index);
+ dest += msix_entry_offset;
+
+ if (size == 4)
+ *((uint32_t *)dest) = value;
+ else
+ *((uint64_t *)dest) = value;
+
+ return (0);
+}
+
+uint64_t
+pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size)
+{
+ char *dest;
+ int msix_entry_offset;
+ int tab_index;
+ uint64_t retval = ~0;
+
+ /* support only 4 or 8 byte reads */
+ if (size != 4 && size != 8)
+ return (retval);
+
+ msix_entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
+
+ /* support only aligned reads */
+ if ((msix_entry_offset % size) != 0) {
+ return (retval);
+ }
+
+ tab_index = offset / MSIX_TABLE_ENTRY_SIZE;
+
+ if (tab_index < pi->pi_msix.table_count) {
+ /* valid MSI-X Table access */
+ dest = (char *)(pi->pi_msix.table + tab_index);
+ dest += msix_entry_offset;
+
+ if (size == 4)
+ retval = *((uint32_t *)dest);
+ else
+ retval = *((uint64_t *)dest);
+ } else if (pci_valid_pba_offset(pi, offset)) {
+ /* return 0 for PBA access */
+ retval = 0;
+ }
+
+ return (retval);
+}
+
+int
+pci_msix_table_bar(struct pci_devinst *pi)
+{
+
+ if (pi->pi_msix.table != NULL)
+ return (pi->pi_msix.table_bar);
+ else
+ return (-1);
+}
+
+int
+pci_msix_pba_bar(struct pci_devinst *pi)
+{
+
+ if (pi->pi_msix.table != NULL)
+ return (pi->pi_msix.pba_bar);
+ else
+ return (-1);
+}
+
+static int
+pci_emul_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ struct pci_devinst *pdi = arg;
+ struct pci_devemu *pe = pdi->pi_d;
+ uint64_t offset;
+ int i;
+
+ for (i = 0; i <= PCI_BARMAX; i++) {
+ if (pdi->pi_bar[i].type == PCIBAR_IO &&
+ port >= pdi->pi_bar[i].addr &&
+ port + bytes <= pdi->pi_bar[i].addr + pdi->pi_bar[i].size) {
+ offset = port - pdi->pi_bar[i].addr;
+ if (in)
+ *eax = (*pe->pe_barread)(ctx, vcpu, pdi, i,
+ offset, bytes);
+ else
+ (*pe->pe_barwrite)(ctx, vcpu, pdi, i, offset,
+ bytes, *eax);
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+static int
+pci_emul_mem_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
+ int size, uint64_t *val, void *arg1, long arg2)
+{
+ struct pci_devinst *pdi = arg1;
+ struct pci_devemu *pe = pdi->pi_d;
+ uint64_t offset;
+ int bidx = (int) arg2;
+
+ assert(bidx <= PCI_BARMAX);
+ assert(pdi->pi_bar[bidx].type == PCIBAR_MEM32 ||
+ pdi->pi_bar[bidx].type == PCIBAR_MEM64);
+ assert(addr >= pdi->pi_bar[bidx].addr &&
+ addr + size <= pdi->pi_bar[bidx].addr + pdi->pi_bar[bidx].size);
+
+ offset = addr - pdi->pi_bar[bidx].addr;
+
+ if (dir == MEM_F_WRITE)
+ (*pe->pe_barwrite)(ctx, vcpu, pdi, bidx, offset, size, *val);
+ else
+ *val = (*pe->pe_barread)(ctx, vcpu, pdi, bidx, offset, size);
+
+ return (0);
+}
+
+
+static int
+pci_emul_alloc_resource(uint64_t *baseptr, uint64_t limit, uint64_t size,
+ uint64_t *addr)
+{
+ uint64_t base;
+
+ assert((size & (size - 1)) == 0); /* must be a power of 2 */
+
+ base = roundup2(*baseptr, size);
+
+ if (base + size <= limit) {
+ *addr = base;
+ *baseptr = base + size;
+ return (0);
+ } else
+ return (-1);
+}
+
+int
+pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type,
+ uint64_t size)
+{
+
+ return (pci_emul_alloc_pbar(pdi, idx, 0, type, size));
+}
+
+int
+pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase,
+ enum pcibar_type type, uint64_t size)
+{
+ int i, error;
+ uint64_t *baseptr, limit, addr, mask, lobits, bar;
+ struct inout_port iop;
+ struct mem_range memp;
+
+ assert(idx >= 0 && idx <= PCI_BARMAX);
+
+ if ((size & (size - 1)) != 0)
+ size = 1UL << flsl(size); /* round up to a power of 2 */
+
+ switch (type) {
+ case PCIBAR_NONE:
+ baseptr = NULL;
+ addr = mask = lobits = 0;
+ break;
+ case PCIBAR_IO:
+ if (hostbase &&
+ pci_slotinfo[pdi->pi_slot][pdi->pi_func].si_legacy) {
+ assert(hostbase < PCI_EMUL_IOBASE);
+ baseptr = &hostbase;
+ } else {
+ baseptr = &pci_emul_iobase;
+ }
+ limit = PCI_EMUL_IOLIMIT;
+ mask = PCIM_BAR_IO_BASE;
+ lobits = PCIM_BAR_IO_SPACE;
+ break;
+ case PCIBAR_MEM64:
+ /*
+ * XXX
+ * Some drivers do not work well if the 64-bit BAR is allocated
+ * above 4GB. Allow for this by allocating small requests under
+ * 4GB unless then allocation size is larger than some arbitrary
+ * number (32MB currently).
+ */
+ if (size > 32 * 1024 * 1024) {
+ /*
+ * XXX special case for device requiring peer-peer DMA
+ */
+ if (size == 0x100000000UL)
+ baseptr = &hostbase;
+ else
+ baseptr = &pci_emul_membase64;
+ limit = PCI_EMUL_MEMLIMIT64;
+ mask = PCIM_BAR_MEM_BASE;
+ lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 |
+ PCIM_BAR_MEM_PREFETCH;
+ break;
+ } else {
+ baseptr = &pci_emul_membase32;
+ limit = PCI_EMUL_MEMLIMIT32;
+ mask = PCIM_BAR_MEM_BASE;
+ lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64;
+ }
+ break;
+ case PCIBAR_MEM32:
+ baseptr = &pci_emul_membase32;
+ limit = PCI_EMUL_MEMLIMIT32;
+ mask = PCIM_BAR_MEM_BASE;
+ lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
+ break;
+ default:
+ printf("pci_emul_alloc_base: invalid bar type %d\n", type);
+ assert(0);
+ }
+
+ if (baseptr != NULL) {
+ error = pci_emul_alloc_resource(baseptr, limit, size, &addr);
+ if (error != 0)
+ return (error);
+ }
+
+ pdi->pi_bar[idx].type = type;
+ pdi->pi_bar[idx].addr = addr;
+ pdi->pi_bar[idx].size = size;
+
+ /* Initialize the BAR register in config space */
+ bar = (addr & mask) | lobits;
+ pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar);
+
+ if (type == PCIBAR_MEM64) {
+ assert(idx + 1 <= PCI_BARMAX);
+ pdi->pi_bar[idx + 1].type = PCIBAR_MEMHI64;
+ pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32);
+ }
+
+ /* add a handler to intercept accesses to the I/O bar */
+ if (type == PCIBAR_IO) {
+ iop.name = pdi->pi_name;
+ iop.flags = IOPORT_F_INOUT;
+ iop.handler = pci_emul_io_handler;
+ iop.arg = pdi;
+
+ for (i = 0; i < size; i++) {
+ iop.port = addr + i;
+ register_inout(&iop);
+ }
+ } else if (type == PCIBAR_MEM32 || type == PCIBAR_MEM64) {
+ /* add memory bar intercept handler */
+ memp.name = pdi->pi_name;
+ memp.flags = MEM_F_RW;
+ memp.base = addr;
+ memp.size = size;
+ memp.handler = pci_emul_mem_handler;
+ memp.arg1 = pdi;
+ memp.arg2 = idx;
+
+ error = register_mem(&memp);
+ assert(error == 0);
+ }
+
+ return (0);
+}
+
+#define CAP_START_OFFSET 0x40
+static int
+pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen)
+{
+ int i, capoff, capid, reallen;
+ uint16_t sts;
+
+ static u_char endofcap[4] = {
+ PCIY_RESERVED, 0, 0, 0
+ };
+
+ assert(caplen > 0 && capdata[0] != PCIY_RESERVED);
+
+ reallen = roundup2(caplen, 4); /* dword aligned */
+
+ sts = pci_get_cfgdata16(pi, PCIR_STATUS);
+ if ((sts & PCIM_STATUS_CAPPRESENT) == 0) {
+ capoff = CAP_START_OFFSET;
+ pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff);
+ pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT);
+ } else {
+ capoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR);
+ while (1) {
+ assert((capoff & 0x3) == 0);
+ capid = pci_get_cfgdata8(pi, capoff);
+ if (capid == PCIY_RESERVED)
+ break;
+ capoff = pci_get_cfgdata8(pi, capoff + 1);
+ }
+ }
+
+ /* Check if we have enough space */
+ if (capoff + reallen + sizeof(endofcap) > PCI_REGMAX + 1)
+ return (-1);
+
+ /* Copy the capability */
+ for (i = 0; i < caplen; i++)
+ pci_set_cfgdata8(pi, capoff + i, capdata[i]);
+
+ /* Set the next capability pointer */
+ pci_set_cfgdata8(pi, capoff + 1, capoff + reallen);
+
+ /* Copy of the reserved capability which serves as the end marker */
+ for (i = 0; i < sizeof(endofcap); i++)
+ pci_set_cfgdata8(pi, capoff + reallen + i, endofcap[i]);
+
+ return (0);
+}
+
+static struct pci_devemu *
+pci_emul_finddev(char *name)
+{
+ struct pci_devemu **pdpp, *pdp;
+
+ SET_FOREACH(pdpp, pci_devemu_set) {
+ pdp = *pdpp;
+ if (!strcmp(pdp->pe_emu, name)) {
+ return (pdp);
+ }
+ }
+
+ return (NULL);
+}
+
+static void
+pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, int func,
+ char *params)
+{
+ struct pci_devinst *pdi;
+ pdi = malloc(sizeof(struct pci_devinst));
+ bzero(pdi, sizeof(*pdi));
+
+ pdi->pi_vmctx = ctx;
+ pdi->pi_bus = 0;
+ pdi->pi_slot = slot;
+ pdi->pi_func = func;
+ pdi->pi_d = pde;
+ snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot);
+
+ /* Disable legacy interrupts */
+ pci_set_cfgdata8(pdi, PCIR_INTLINE, 255);
+ pci_set_cfgdata8(pdi, PCIR_INTPIN, 0);
+
+ pci_set_cfgdata8(pdi, PCIR_COMMAND,
+ PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
+
+ if ((*pde->pe_init)(ctx, pdi, params) != 0) {
+ free(pdi);
+ } else {
+ pci_emul_devices++;
+ pci_slotinfo[slot][func].si_devi = pdi;
+ }
+}
+
+void
+pci_populate_msicap(struct msicap *msicap, int msgnum, int nextptr)
+{
+ int mmc;
+
+ CTASSERT(sizeof(struct msicap) == 14);
+
+ /* Number of msi messages must be a power of 2 between 1 and 32 */
+ assert((msgnum & (msgnum - 1)) == 0 && msgnum >= 1 && msgnum <= 32);
+ mmc = ffs(msgnum) - 1;
+
+ bzero(msicap, sizeof(struct msicap));
+ msicap->capid = PCIY_MSI;
+ msicap->nextptr = nextptr;
+ msicap->msgctrl = PCIM_MSICTRL_64BIT | (mmc << 1);
+}
+
+int
+pci_emul_add_msicap(struct pci_devinst *pi, int msgnum)
+{
+ struct msicap msicap;
+
+ pci_populate_msicap(&msicap, msgnum, 0);
+
+ return (pci_emul_add_capability(pi, (u_char *)&msicap, sizeof(msicap)));
+}
+
+static void
+pci_populate_msixcap(struct msixcap *msixcap, int msgnum, int barnum,
+ uint32_t msix_tab_size, int nextptr)
+{
+ CTASSERT(sizeof(struct msixcap) == 12);
+
+ assert(msix_tab_size % 4096 == 0);
+
+ bzero(msixcap, sizeof(struct msixcap));
+ msixcap->capid = PCIY_MSIX;
+ msixcap->nextptr = nextptr;
+
+ /*
+ * Message Control Register, all fields set to
+ * zero except for the Table Size.
+ * Note: Table size N is encoded as N-1
+ */
+ msixcap->msgctrl = msgnum - 1;
+
+ /*
+ * MSI-X BAR setup:
+ * - MSI-X table start at offset 0
+ * - PBA table starts at a 4K aligned offset after the MSI-X table
+ */
+ msixcap->table_info = barnum & PCIM_MSIX_BIR_MASK;
+ msixcap->pba_info = msix_tab_size | (barnum & PCIM_MSIX_BIR_MASK);
+}
+
+static void
+pci_msix_table_init(struct pci_devinst *pi, int table_entries)
+{
+ int i, table_size;
+
+ assert(table_entries > 0);
+ assert(table_entries <= MAX_MSIX_TABLE_ENTRIES);
+
+ table_size = table_entries * MSIX_TABLE_ENTRY_SIZE;
+ pi->pi_msix.table = malloc(table_size);
+ bzero(pi->pi_msix.table, table_size);
+
+ /* set mask bit of vector control register */
+ for (i = 0; i < table_entries; i++)
+ pi->pi_msix.table[i].vector_control |= PCIM_MSIX_VCTRL_MASK;
+}
+
+int
+pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum)
+{
+ uint16_t pba_index;
+ uint32_t tab_size;
+ struct msixcap msixcap;
+
+ assert(msgnum >= 1 && msgnum <= MAX_MSIX_TABLE_ENTRIES);
+ assert(barnum >= 0 && barnum <= PCIR_MAX_BAR_0);
+
+ tab_size = msgnum * MSIX_TABLE_ENTRY_SIZE;
+
+ /* Align table size to nearest 4K */
+ tab_size = roundup2(tab_size, 4096);
+
+ pi->pi_msix.table_bar = barnum;
+ pi->pi_msix.pba_bar = barnum;
+ pi->pi_msix.table_offset = 0;
+ pi->pi_msix.table_count = msgnum;
+ pi->pi_msix.pba_offset = tab_size;
+
+ /* calculate the MMIO size required for MSI-X PBA */
+ pba_index = (msgnum - 1) / (PBA_TABLE_ENTRY_SIZE * 8);
+ pi->pi_msix.pba_size = (pba_index + 1) * PBA_TABLE_ENTRY_SIZE;
+
+ pci_msix_table_init(pi, msgnum);
+
+ pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size, 0);
+
+ /* allocate memory for MSI-X Table and PBA */
+ pci_emul_alloc_bar(pi, barnum, PCIBAR_MEM32,
+ tab_size + pi->pi_msix.pba_size);
+
+ return (pci_emul_add_capability(pi, (u_char *)&msixcap,
+ sizeof(msixcap)));
+}
+
+void
+msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
+ int bytes, uint32_t val)
+{
+ uint16_t msgctrl, rwmask;
+ int off, table_bar;
+
+ off = offset - capoff;
+ table_bar = pi->pi_msix.table_bar;
+ /* Message Control Register */
+ if (off == 2 && bytes == 2) {
+ rwmask = PCIM_MSIXCTRL_MSIX_ENABLE | PCIM_MSIXCTRL_FUNCTION_MASK;
+ msgctrl = pci_get_cfgdata16(pi, offset);
+ msgctrl &= ~rwmask;
+ msgctrl |= val & rwmask;
+ val = msgctrl;
+
+ pi->pi_msix.enabled = val & PCIM_MSIXCTRL_MSIX_ENABLE;
+ pi->pi_msix.function_mask = val & PCIM_MSIXCTRL_FUNCTION_MASK;
+ }
+
+ CFGWRITE(pi, offset, val, bytes);
+}
+
+void
+msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
+ int bytes, uint32_t val)
+{
+ uint16_t msgctrl, rwmask, msgdata, mme;
+ uint32_t addrlo;
+
+ /*
+ * If guest is writing to the message control register make sure
+ * we do not overwrite read-only fields.
+ */
+ if ((offset - capoff) == 2 && bytes == 2) {
+ rwmask = PCIM_MSICTRL_MME_MASK | PCIM_MSICTRL_MSI_ENABLE;
+ msgctrl = pci_get_cfgdata16(pi, offset);
+ msgctrl &= ~rwmask;
+ msgctrl |= val & rwmask;
+ val = msgctrl;
+
+ addrlo = pci_get_cfgdata32(pi, capoff + 4);
+ if (msgctrl & PCIM_MSICTRL_64BIT)
+ msgdata = pci_get_cfgdata16(pi, capoff + 12);
+ 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);
+ } else {
+ pi->pi_msi.cpu = 0;
+ pi->pi_msi.vector = 0;
+ pi->pi_msi.msgnum = 0;
+ }
+ }
+
+ CFGWRITE(pi, offset, val, bytes);
+}
+
+/*
+ * This function assumes that 'coff' is in the capabilities region of the
+ * config space.
+ */
+static void
+pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val)
+{
+ int capid;
+ uint8_t capoff, nextoff;
+
+ /* Do not allow un-aligned writes */
+ if ((offset & (bytes - 1)) != 0)
+ return;
+
+ /* Find the capability that we want to update */
+ capoff = CAP_START_OFFSET;
+ while (1) {
+ capid = pci_get_cfgdata8(pi, capoff);
+ if (capid == PCIY_RESERVED)
+ break;
+
+ nextoff = pci_get_cfgdata8(pi, capoff + 1);
+ if (offset >= capoff && offset < nextoff)
+ break;
+
+ capoff = nextoff;
+ }
+ assert(offset >= capoff);
+
+ /*
+ * Capability ID and Next Capability Pointer are readonly
+ */
+ if (offset == capoff || offset == capoff + 1)
+ return;
+
+ switch (capid) {
+ case PCIY_MSI:
+ msicap_cfgwrite(pi, capoff, offset, bytes, val);
+ break;
+ case PCIY_MSIX:
+ msixcap_cfgwrite(pi, capoff, offset, bytes, val);
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+pci_emul_iscap(struct pci_devinst *pi, int offset)
+{
+ int found;
+ uint16_t sts;
+ uint8_t capid, lastoff;
+
+ found = 0;
+ sts = pci_get_cfgdata16(pi, PCIR_STATUS);
+ if ((sts & PCIM_STATUS_CAPPRESENT) != 0) {
+ lastoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR);
+ while (1) {
+ assert((lastoff & 0x3) == 0);
+ capid = pci_get_cfgdata8(pi, lastoff);
+ if (capid == PCIY_RESERVED)
+ break;
+ lastoff = pci_get_cfgdata8(pi, lastoff + 1);
+ }
+ if (offset >= CAP_START_OFFSET && offset <= lastoff)
+ found = 1;
+ }
+ return (found);
+}
+
+void
+init_pci(struct vmctx *ctx)
+{
+ struct pci_devemu *pde;
+ struct slotinfo *si;
+ int slot, func;
+
+ pci_emul_iobase = PCI_EMUL_IOBASE;
+ pci_emul_membase32 = PCI_EMUL_MEMBASE32;
+ pci_emul_membase64 = PCI_EMUL_MEMBASE64;
+
+ for (slot = 0; slot < MAXSLOTS; slot++) {
+ for (func = 0; func < MAXFUNCS; func++) {
+ si = &pci_slotinfo[slot][func];
+ if (si->si_name != NULL) {
+ pde = pci_emul_finddev(si->si_name);
+ if (pde != NULL) {
+ pci_emul_init(ctx, pde, slot, func,
+ si->si_param);
+ }
+ }
+ }
+ }
+
+ /*
+ * Allow ISA IRQs 5,10,11,12, and 15 to be available for
+ * generic use
+ */
+ lirq[5].li_generic = 1;
+ lirq[10].li_generic = 1;
+ lirq[11].li_generic = 1;
+ lirq[12].li_generic = 1;
+ lirq[15].li_generic = 1;
+}
+
+int
+pci_msi_enabled(struct pci_devinst *pi)
+{
+ return (pi->pi_msi.enabled);
+}
+
+int
+pci_msi_msgnum(struct pci_devinst *pi)
+{
+ if (pi->pi_msi.enabled)
+ return (pi->pi_msi.msgnum);
+ else
+ return (0);
+}
+
+int
+pci_msix_enabled(struct pci_devinst *pi)
+{
+
+ return (pi->pi_msix.enabled && !pi->pi_msi.enabled);
+}
+
+void
+pci_generate_msix(struct pci_devinst *pi, int index)
+{
+ struct msix_table_entry *mte;
+
+ if (!pci_msix_enabled(pi))
+ return;
+
+ if (pi->pi_msix.function_mask)
+ return;
+
+ if (index >= pi->pi_msix.table_count)
+ return;
+
+ 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);
+ }
+}
+
+void
+pci_generate_msi(struct pci_devinst *pi, int msg)
+{
+
+ 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);
+ }
+}
+
+int
+pci_is_legacy(struct pci_devinst *pi)
+{
+
+ return (pci_slotinfo[pi->pi_slot][pi->pi_func].si_legacy);
+}
+
+static int
+pci_lintr_alloc(struct pci_devinst *pi, int vec)
+{
+ int i;
+
+ assert(vec < NLIRQ);
+
+ if (vec == -1) {
+ for (i = 0; i < NLIRQ; i++) {
+ if (lirq[i].li_generic &&
+ lirq[i].li_owner == NULL) {
+ vec = i;
+ break;
+ }
+ }
+ } else {
+ if (lirq[vec].li_owner != NULL) {
+ vec = -1;
+ }
+ }
+ assert(vec != -1);
+
+ lirq[vec].li_owner = pi;
+ pi->pi_lintr_pin = vec;
+
+ return (vec);
+}
+
+int
+pci_lintr_request(struct pci_devinst *pi, int vec)
+{
+
+ vec = pci_lintr_alloc(pi, vec);
+ pci_set_cfgdata8(pi, PCIR_INTLINE, vec);
+ pci_set_cfgdata8(pi, PCIR_INTPIN, 1);
+ return (0);
+}
+
+void
+pci_lintr_assert(struct pci_devinst *pi)
+{
+
+ assert(pi->pi_lintr_pin);
+ ioapic_assert_pin(pi->pi_vmctx, pi->pi_lintr_pin);
+}
+
+void
+pci_lintr_deassert(struct pci_devinst *pi)
+{
+
+ assert(pi->pi_lintr_pin);
+ ioapic_deassert_pin(pi->pi_vmctx, pi->pi_lintr_pin);
+}
+
+/*
+ * Return 1 if the emulated device in 'slot' is a multi-function device.
+ * Return 0 otherwise.
+ */
+static int
+pci_emul_is_mfdev(int slot)
+{
+ int f, numfuncs;
+
+ numfuncs = 0;
+ for (f = 0; f < MAXFUNCS; f++) {
+ if (pci_slotinfo[slot][f].si_devi != NULL) {
+ numfuncs++;
+ }
+ }
+ return (numfuncs > 1);
+}
+
+/*
+ * Ensure that the PCIM_MFDEV bit is properly set (or unset) depending on
+ * whether or not is a multi-function being emulated in the pci 'slot'.
+ */
+static void
+pci_emul_hdrtype_fixup(int slot, int off, int bytes, uint32_t *rv)
+{
+ int mfdev;
+
+ if (off <= PCIR_HDRTYPE && off + bytes > PCIR_HDRTYPE) {
+ mfdev = pci_emul_is_mfdev(slot);
+ switch (bytes) {
+ case 1:
+ case 2:
+ *rv &= ~PCIM_MFDEV;
+ if (mfdev) {
+ *rv |= PCIM_MFDEV;
+ }
+ break;
+ case 4:
+ *rv &= ~(PCIM_MFDEV << 16);
+ if (mfdev) {
+ *rv |= (PCIM_MFDEV << 16);
+ }
+ break;
+ }
+ }
+}
+
+static int cfgbus, cfgslot, cfgfunc, cfgoff;
+
+static int
+pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ uint32_t x;
+
+ assert(!in);
+
+ if (bytes != 4)
+ return (-1);
+
+ x = *eax;
+ cfgoff = x & PCI_REGMAX;
+ cfgfunc = (x >> 8) & PCI_FUNCMAX;
+ cfgslot = (x >> 11) & PCI_SLOTMAX;
+ cfgbus = (x >> 16) & PCI_BUSMAX;
+
+ return (0);
+}
+INOUT_PORT(pci_cfgaddr, CONF1_ADDR_PORT, IOPORT_F_OUT, pci_emul_cfgaddr);
+
+static int
+pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ struct pci_devinst *pi;
+ struct pci_devemu *pe;
+ int coff, idx, needcfg;
+ uint64_t mask, bar;
+
+ assert(bytes == 1 || bytes == 2 || bytes == 4);
+
+ if (cfgbus == 0)
+ pi = pci_slotinfo[cfgslot][cfgfunc].si_devi;
+ else
+ pi = NULL;
+
+ coff = cfgoff + (port - CONF1_DATA_PORT);
+
+#if 0
+ printf("pcicfg-%s from 0x%0x of %d bytes (%d/%d/%d)\n\r",
+ in ? "read" : "write", coff, bytes, cfgbus, cfgslot, cfgfunc);
+#endif
+
+ /*
+ * Just return if there is no device at this cfgslot:cfgfunc or
+ * if the guest is doing an un-aligned access
+ */
+ if (pi == NULL || (coff & (bytes - 1)) != 0) {
+ if (in)
+ *eax = 0xffffffff;
+ return (0);
+ }
+
+ pe = pi->pi_d;
+
+ /*
+ * Config read
+ */
+ if (in) {
+ /* Let the device emulation override the default handler */
+ if (pe->pe_cfgread != NULL) {
+ needcfg = pe->pe_cfgread(ctx, vcpu, pi,
+ coff, bytes, eax);
+ } else {
+ needcfg = 1;
+ }
+
+ if (needcfg) {
+ if (bytes == 1)
+ *eax = pci_get_cfgdata8(pi, coff);
+ else if (bytes == 2)
+ *eax = pci_get_cfgdata16(pi, coff);
+ else
+ *eax = pci_get_cfgdata32(pi, coff);
+ }
+
+ pci_emul_hdrtype_fixup(cfgslot, coff, bytes, eax);
+ } else {
+ /* Let the device emulation override the default handler */
+ if (pe->pe_cfgwrite != NULL &&
+ (*pe->pe_cfgwrite)(ctx, vcpu, pi, coff, bytes, *eax) == 0)
+ return (0);
+
+ /*
+ * Special handling for write to BAR registers
+ */
+ if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) {
+ /*
+ * Ignore writes to BAR registers that are not
+ * 4-byte aligned.
+ */
+ if (bytes != 4 || (coff & 0x3) != 0)
+ return (0);
+ idx = (coff - PCIR_BAR(0)) / 4;
+ switch (pi->pi_bar[idx].type) {
+ case PCIBAR_NONE:
+ bar = 0;
+ break;
+ case PCIBAR_IO:
+ mask = ~(pi->pi_bar[idx].size - 1);
+ mask &= PCIM_BAR_IO_BASE;
+ bar = (*eax & mask) | PCIM_BAR_IO_SPACE;
+ break;
+ case PCIBAR_MEM32:
+ mask = ~(pi->pi_bar[idx].size - 1);
+ mask &= PCIM_BAR_MEM_BASE;
+ bar = *eax & mask;
+ bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
+ break;
+ case PCIBAR_MEM64:
+ mask = ~(pi->pi_bar[idx].size - 1);
+ mask &= PCIM_BAR_MEM_BASE;
+ bar = *eax & mask;
+ bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 |
+ PCIM_BAR_MEM_PREFETCH;
+ break;
+ case PCIBAR_MEMHI64:
+ mask = ~(pi->pi_bar[idx - 1].size - 1);
+ mask &= PCIM_BAR_MEM_BASE;
+ bar = ((uint64_t)*eax << 32) & mask;
+ bar = bar >> 32;
+ break;
+ default:
+ assert(0);
+ }
+ pci_set_cfgdata32(pi, coff, bar);
+
+ } else if (pci_emul_iscap(pi, coff)) {
+ pci_emul_capwrite(pi, coff, bytes, *eax);
+ } else {
+ CFGWRITE(pi, coff, *eax, bytes);
+ }
+ }
+
+ return (0);
+}
+
+INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+0, IOPORT_F_INOUT, pci_emul_cfgdata);
+INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+1, IOPORT_F_INOUT, pci_emul_cfgdata);
+INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+2, IOPORT_F_INOUT, pci_emul_cfgdata);
+INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+3, IOPORT_F_INOUT, pci_emul_cfgdata);
+
+/*
+ * I/O ports to configure PCI IRQ routing. We ignore all writes to it.
+ */
+static int
+pci_irq_port_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ assert(in == 0);
+ return (0);
+}
+INOUT_PORT(pci_irq, 0xC00, IOPORT_F_OUT, pci_irq_port_handler);
+INOUT_PORT(pci_irq, 0xC01, IOPORT_F_OUT, pci_irq_port_handler);
+
+#define PCI_EMUL_TEST
+#ifdef PCI_EMUL_TEST
+/*
+ * Define a dummy test device
+ */
+#define DIOSZ 20
+#define DMEMSZ 4096
+struct pci_emul_dsoftc {
+ uint8_t ioregs[DIOSZ];
+ uint8_t memregs[DMEMSZ];
+};
+
+#define PCI_EMUL_MSI_MSGS 4
+#define PCI_EMUL_MSIX_MSGS 16
+
+static int
+pci_emul_dinit(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ int error;
+ struct pci_emul_dsoftc *sc;
+
+ sc = malloc(sizeof(struct pci_emul_dsoftc));
+ memset(sc, 0, sizeof(struct pci_emul_dsoftc));
+
+ pi->pi_arg = sc;
+
+ pci_set_cfgdata16(pi, PCIR_DEVICE, 0x0001);
+ pci_set_cfgdata16(pi, PCIR_VENDOR, 0x10DD);
+ pci_set_cfgdata8(pi, PCIR_CLASS, 0x02);
+
+ error = pci_emul_add_msicap(pi, PCI_EMUL_MSI_MSGS);
+ assert(error == 0);
+
+ error = pci_emul_alloc_bar(pi, 0, PCIBAR_IO, DIOSZ);
+ assert(error == 0);
+
+ error = pci_emul_alloc_bar(pi, 1, PCIBAR_MEM32, DMEMSZ);
+ assert(error == 0);
+
+ return (0);
+}
+
+static void
+pci_emul_diow(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
+ uint64_t offset, int size, uint64_t value)
+{
+ int i;
+ struct pci_emul_dsoftc *sc = pi->pi_arg;
+
+ if (baridx == 0) {
+ if (offset + size > DIOSZ) {
+ printf("diow: iow too large, offset %ld size %d\n",
+ offset, size);
+ return;
+ }
+
+ if (size == 1) {
+ sc->ioregs[offset] = value & 0xff;
+ } else if (size == 2) {
+ *(uint16_t *)&sc->ioregs[offset] = value & 0xffff;
+ } else if (size == 4) {
+ *(uint32_t *)&sc->ioregs[offset] = value;
+ } else {
+ printf("diow: iow unknown size %d\n", size);
+ }
+
+ /*
+ * 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));
+
+ if (value == 0xabcdef) {
+ for (i = 0; i < pci_msi_msgnum(pi); i++)
+ pci_generate_msi(pi, i);
+ }
+ }
+
+ if (baridx == 1) {
+ if (offset + size > DMEMSZ) {
+ printf("diow: memw too large, offset %ld size %d\n",
+ offset, size);
+ return;
+ }
+
+ if (size == 1) {
+ sc->memregs[offset] = value;
+ } else if (size == 2) {
+ *(uint16_t *)&sc->memregs[offset] = value;
+ } else if (size == 4) {
+ *(uint32_t *)&sc->memregs[offset] = value;
+ } else if (size == 8) {
+ *(uint64_t *)&sc->memregs[offset] = value;
+ } else {
+ printf("diow: memw unknown size %d\n", size);
+ }
+
+ /*
+ * magic interrupt ??
+ */
+ }
+
+ if (baridx > 1) {
+ printf("diow: unknown bar idx %d\n", baridx);
+ }
+}
+
+static uint64_t
+pci_emul_dior(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
+ uint64_t offset, int size)
+{
+ struct pci_emul_dsoftc *sc = pi->pi_arg;
+ uint32_t value;
+
+ if (baridx == 0) {
+ if (offset + size > DIOSZ) {
+ printf("dior: ior too large, offset %ld size %d\n",
+ offset, size);
+ return (0);
+ }
+
+ if (size == 1) {
+ value = sc->ioregs[offset];
+ } else if (size == 2) {
+ value = *(uint16_t *) &sc->ioregs[offset];
+ } else if (size == 4) {
+ value = *(uint32_t *) &sc->ioregs[offset];
+ } else {
+ printf("dior: ior unknown size %d\n", size);
+ }
+ }
+
+ if (baridx == 1) {
+ if (offset + size > DMEMSZ) {
+ printf("dior: memr too large, offset %ld size %d\n",
+ offset, size);
+ return (0);
+ }
+
+ if (size == 1) {
+ value = sc->memregs[offset];
+ } else if (size == 2) {
+ value = *(uint16_t *) &sc->memregs[offset];
+ } else if (size == 4) {
+ value = *(uint32_t *) &sc->memregs[offset];
+ } else if (size == 8) {
+ value = *(uint64_t *) &sc->memregs[offset];
+ } else {
+ printf("dior: ior unknown size %d\n", size);
+ }
+ }
+
+
+ if (baridx > 1) {
+ printf("dior: unknown bar idx %d\n", baridx);
+ return (0);
+ }
+
+ return (value);
+}
+
+struct pci_devemu pci_dummy = {
+ .pe_emu = "dummy",
+ .pe_init = pci_emul_dinit,
+ .pe_barwrite = pci_emul_diow,
+ .pe_barread = pci_emul_dior
+};
+PCI_EMUL_SET(pci_dummy);
+
+#endif /* PCI_EMUL_TEST */
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
new file mode 100644
index 0000000..8c6260c
--- /dev/null
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _PCI_EMUL_H_
+#define _PCI_EMUL_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/kernel.h>
+
+#include <dev/pci/pcireg.h>
+
+#include <assert.h>
+
+#define PCI_BARMAX PCIR_MAX_BAR_0 /* BAR registers in a Type 0 header */
+#define PCIY_RESERVED 0x00
+
+struct vmctx;
+struct pci_devinst;
+struct memory_region;
+
+struct pci_devemu {
+ char *pe_emu; /* Name of device emulation */
+
+ /* instance creation */
+ int (*pe_init)(struct vmctx *, struct pci_devinst *,
+ char *opts);
+
+ /* config space read/write callbacks */
+ int (*pe_cfgwrite)(struct vmctx *ctx, int vcpu,
+ struct pci_devinst *pi, int offset,
+ int bytes, uint32_t val);
+ int (*pe_cfgread)(struct vmctx *ctx, int vcpu,
+ struct pci_devinst *pi, int offset,
+ int bytes, uint32_t *retval);
+
+ /* BAR read/write callbacks */
+ void (*pe_barwrite)(struct vmctx *ctx, int vcpu,
+ struct pci_devinst *pi, int baridx,
+ uint64_t offset, int size, uint64_t value);
+ uint64_t (*pe_barread)(struct vmctx *ctx, int vcpu,
+ struct pci_devinst *pi, int baridx,
+ uint64_t offset, int size);
+};
+#define PCI_EMUL_SET(x) DATA_SET(pci_devemu_set, x);
+
+enum pcibar_type {
+ PCIBAR_NONE,
+ PCIBAR_IO,
+ PCIBAR_MEM32,
+ PCIBAR_MEM64,
+ PCIBAR_MEMHI64
+};
+
+struct pcibar {
+ enum pcibar_type type; /* io or memory */
+ uint64_t size;
+ uint64_t addr;
+};
+
+#define PI_NAMESZ 40
+
+struct msix_table_entry {
+ uint64_t addr;
+ uint32_t msg_data;
+ uint32_t vector_control;
+} __packed;
+
+/*
+ * In case the structure is modified to hold extra information, use a define
+ * for the size that should be emulated.
+ */
+#define MSIX_TABLE_ENTRY_SIZE 16
+#define MAX_MSIX_TABLE_ENTRIES 2048
+#define PBA_TABLE_ENTRY_SIZE 8
+
+struct pci_devinst {
+ struct pci_devemu *pi_d;
+ struct vmctx *pi_vmctx;
+ uint8_t pi_bus, pi_slot, pi_func;
+ uint8_t pi_lintr_pin;
+ char pi_name[PI_NAMESZ];
+ uint16_t pi_iobase;
+ int pi_bar_getsize;
+
+ struct {
+ int enabled;
+ int cpu;
+ int vector;
+ int msgnum;
+ } pi_msi;
+
+ struct {
+ int enabled;
+ int table_bar;
+ int pba_bar;
+ size_t table_offset;
+ int table_count;
+ size_t pba_offset;
+ size_t pba_size;
+ int function_mask;
+ struct msix_table_entry *table; /* allocated at runtime */
+ } pi_msix;
+
+ void *pi_arg; /* devemu-private data */
+
+ u_char pi_cfgdata[PCI_REGMAX + 1];
+ struct pcibar pi_bar[PCI_BARMAX + 1];
+};
+
+struct msicap {
+ uint8_t capid;
+ uint8_t nextptr;
+ uint16_t msgctrl;
+ uint32_t addrlo;
+ uint32_t addrhi;
+ uint16_t msgdata;
+} __packed;
+
+struct msixcap {
+ uint8_t capid;
+ uint8_t nextptr;
+ uint16_t msgctrl;
+ uint32_t table_info; /* bar index and offset within it */
+ uint32_t pba_info; /* bar index and offset within it */
+} __packed;
+
+void init_pci(struct vmctx *ctx);
+void msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
+ int bytes, uint32_t val);
+void msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
+ int bytes, uint32_t val);
+void pci_callback(void);
+int pci_emul_alloc_bar(struct pci_devinst *pdi, int idx,
+ enum pcibar_type type, uint64_t size);
+int pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx,
+ uint64_t hostbase, enum pcibar_type type, uint64_t size);
+int pci_emul_add_msicap(struct pci_devinst *pi, int msgnum);
+int pci_is_legacy(struct pci_devinst *pi);
+void pci_generate_msi(struct pci_devinst *pi, int msgnum);
+void pci_generate_msix(struct pci_devinst *pi, int msgnum);
+void pci_lintr_assert(struct pci_devinst *pi);
+void pci_lintr_deassert(struct pci_devinst *pi);
+int pci_lintr_request(struct pci_devinst *pi, int ivec);
+int pci_msi_enabled(struct pci_devinst *pi);
+int pci_msix_enabled(struct pci_devinst *pi);
+int pci_msix_table_bar(struct pci_devinst *pi);
+int pci_msix_pba_bar(struct pci_devinst *pi);
+int pci_msi_msgnum(struct pci_devinst *pi);
+void pci_parse_slot(char *opt, int legacy);
+void pci_populate_msicap(struct msicap *cap, int msgs, int nextptr);
+int pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum);
+int pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size,
+ uint64_t value);
+uint64_t pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size);
+
+static __inline void
+pci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val)
+{
+ assert(offset <= PCI_REGMAX);
+ *(uint8_t *)(pi->pi_cfgdata + offset) = val;
+}
+
+static __inline void
+pci_set_cfgdata16(struct pci_devinst *pi, int offset, uint16_t val)
+{
+ assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0);
+ *(uint16_t *)(pi->pi_cfgdata + offset) = val;
+}
+
+static __inline void
+pci_set_cfgdata32(struct pci_devinst *pi, int offset, uint32_t val)
+{
+ assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0);
+ *(uint32_t *)(pi->pi_cfgdata + offset) = val;
+}
+
+static __inline uint8_t
+pci_get_cfgdata8(struct pci_devinst *pi, int offset)
+{
+ assert(offset <= PCI_REGMAX);
+ return (*(uint8_t *)(pi->pi_cfgdata + offset));
+}
+
+static __inline uint16_t
+pci_get_cfgdata16(struct pci_devinst *pi, int offset)
+{
+ assert(offset <= (PCI_REGMAX - 1) && (offset & 1) == 0);
+ return (*(uint16_t *)(pi->pi_cfgdata + offset));
+}
+
+static __inline uint32_t
+pci_get_cfgdata32(struct pci_devinst *pi, int offset)
+{
+ assert(offset <= (PCI_REGMAX - 3) && (offset & 3) == 0);
+ return (*(uint32_t *)(pi->pi_cfgdata + offset));
+}
+
+#endif /* _PCI_EMUL_H_ */
diff --git a/usr.sbin/bhyve/pci_hostbridge.c b/usr.sbin/bhyve/pci_hostbridge.c
new file mode 100644
index 0000000..c77762d
--- /dev/null
+++ b/usr.sbin/bhyve/pci_hostbridge.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "pci_emul.h"
+
+static int
+pci_hostbridge_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+
+ /* config space */
+ pci_set_cfgdata16(pi, PCIR_VENDOR, 0x1275); /* NetApp */
+ pci_set_cfgdata16(pi, PCIR_DEVICE, 0x1275); /* NetApp */
+ pci_set_cfgdata8(pi, PCIR_HDRTYPE, PCIM_HDRTYPE_BRIDGE);
+ pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE);
+ pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_HOST);
+
+ return (0);
+}
+
+struct pci_devemu pci_de_hostbridge = {
+ .pe_emu = "hostbridge",
+ .pe_init = pci_hostbridge_init,
+};
+PCI_EMUL_SET(pci_de_hostbridge);
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
new file mode 100644
index 0000000..08a9a58
--- /dev/null
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -0,0 +1,759 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/pciio.h>
+#include <sys/ioctl.h>
+
+#include <dev/io/iodev.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/iodev.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+#include "pci_emul.h"
+#include "mem.h"
+
+#ifndef _PATH_DEVPCI
+#define _PATH_DEVPCI "/dev/pci"
+#endif
+
+#ifndef _PATH_DEVIO
+#define _PATH_DEVIO "/dev/io"
+#endif
+
+#define LEGACY_SUPPORT 1
+
+#define MSIX_TABLE_COUNT(ctrl) (((ctrl) & PCIM_MSIXCTRL_TABLE_SIZE) + 1)
+#define MSIX_CAPLEN 12
+
+static int pcifd = -1;
+static int iofd = -1;
+
+struct passthru_softc {
+ struct pci_devinst *psc_pi;
+ struct pcibar psc_bar[PCI_BARMAX + 1];
+ struct {
+ int capoff;
+ int msgctrl;
+ int emulated;
+ } psc_msi;
+ struct {
+ int capoff;
+ } psc_msix;
+ struct pcisel psc_sel;
+};
+
+static int
+msi_caplen(int msgctrl)
+{
+ int len;
+
+ len = 10; /* minimum length of msi capability */
+
+ if (msgctrl & PCIM_MSICTRL_64BIT)
+ len += 4;
+
+#if 0
+ /*
+ * Ignore the 'mask' and 'pending' bits in the MSI capability.
+ * We'll let the guest manipulate them directly.
+ */
+ if (msgctrl & PCIM_MSICTRL_VECTOR)
+ len += 10;
+#endif
+
+ return (len);
+}
+
+static uint32_t
+read_config(const struct pcisel *sel, long reg, int width)
+{
+ struct pci_io pi;
+
+ bzero(&pi, sizeof(pi));
+ pi.pi_sel = *sel;
+ pi.pi_reg = reg;
+ pi.pi_width = width;
+
+ if (ioctl(pcifd, PCIOCREAD, &pi) < 0)
+ return (0); /* XXX */
+ else
+ return (pi.pi_data);
+}
+
+static void
+write_config(const struct pcisel *sel, long reg, int width, uint32_t data)
+{
+ struct pci_io pi;
+
+ bzero(&pi, sizeof(pi));
+ pi.pi_sel = *sel;
+ pi.pi_reg = reg;
+ pi.pi_width = width;
+ pi.pi_data = data;
+
+ (void)ioctl(pcifd, PCIOCWRITE, &pi); /* XXX */
+}
+
+#ifdef LEGACY_SUPPORT
+static int
+passthru_add_msicap(struct pci_devinst *pi, int msgnum, int nextptr)
+{
+ int capoff, i;
+ struct msicap msicap;
+ u_char *capdata;
+
+ pci_populate_msicap(&msicap, msgnum, nextptr);
+
+ /*
+ * XXX
+ * Copy the msi capability structure in the last 16 bytes of the
+ * config space. This is wrong because it could shadow something
+ * useful to the device.
+ */
+ capoff = 256 - roundup(sizeof(msicap), 4);
+ capdata = (u_char *)&msicap;
+ for (i = 0; i < sizeof(msicap); i++)
+ pci_set_cfgdata8(pi, capoff + i, capdata[i]);
+
+ return (capoff);
+}
+#endif /* LEGACY_SUPPORT */
+
+static int
+cfginitmsi(struct passthru_softc *sc)
+{
+ int i, ptr, capptr, cap, sts, caplen, table_size;
+ uint32_t u32;
+ struct pcisel sel;
+ struct pci_devinst *pi;
+ struct msixcap msixcap;
+ uint32_t *msixcap_ptr;
+
+ pi = sc->psc_pi;
+ sel = sc->psc_sel;
+
+ /*
+ * Parse the capabilities and cache the location of the MSI
+ * and MSI-X capabilities.
+ */
+ sts = read_config(&sel, PCIR_STATUS, 2);
+ if (sts & PCIM_STATUS_CAPPRESENT) {
+ ptr = read_config(&sel, PCIR_CAP_PTR, 1);
+ while (ptr != 0 && ptr != 0xff) {
+ cap = read_config(&sel, ptr + PCICAP_ID, 1);
+ if (cap == PCIY_MSI) {
+ /*
+ * Copy the MSI capability into the config
+ * space of the emulated pci device
+ */
+ sc->psc_msi.capoff = ptr;
+ sc->psc_msi.msgctrl = read_config(&sel,
+ ptr + 2, 2);
+ sc->psc_msi.emulated = 0;
+ caplen = msi_caplen(sc->psc_msi.msgctrl);
+ capptr = ptr;
+ while (caplen > 0) {
+ u32 = read_config(&sel, capptr, 4);
+ pci_set_cfgdata32(pi, capptr, u32);
+ caplen -= 4;
+ capptr += 4;
+ }
+ } else if (cap == PCIY_MSIX) {
+ /*
+ * Copy the MSI-X capability
+ */
+ sc->psc_msix.capoff = ptr;
+ caplen = 12;
+ msixcap_ptr = (uint32_t*) &msixcap;
+ capptr = ptr;
+ while (caplen > 0) {
+ u32 = read_config(&sel, capptr, 4);
+ *msixcap_ptr = u32;
+ pci_set_cfgdata32(pi, capptr, u32);
+ caplen -= 4;
+ capptr += 4;
+ msixcap_ptr++;
+ }
+ }
+ ptr = read_config(&sel, ptr + PCICAP_NEXTPTR, 1);
+ }
+ }
+
+ if (sc->psc_msix.capoff != 0) {
+ pi->pi_msix.pba_bar =
+ msixcap.pba_info & PCIM_MSIX_BIR_MASK;
+ pi->pi_msix.pba_offset =
+ msixcap.pba_info & ~PCIM_MSIX_BIR_MASK;
+ pi->pi_msix.table_bar =
+ msixcap.table_info & PCIM_MSIX_BIR_MASK;
+ pi->pi_msix.table_offset =
+ msixcap.table_info & ~PCIM_MSIX_BIR_MASK;
+ pi->pi_msix.table_count = MSIX_TABLE_COUNT(msixcap.msgctrl);
+
+ /* Allocate the emulated MSI-X table array */
+ table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
+ pi->pi_msix.table = malloc(table_size);
+ bzero(pi->pi_msix.table, table_size);
+
+ /* Mask all table entries */
+ for (i = 0; i < pi->pi_msix.table_count; i++) {
+ pi->pi_msix.table[i].vector_control |=
+ PCIM_MSIX_VCTRL_MASK;
+ }
+ }
+
+#ifdef LEGACY_SUPPORT
+ /*
+ * If the passthrough device does not support MSI then craft a
+ * MSI capability for it. We link the new MSI capability at the
+ * head of the list of capabilities.
+ */
+ if ((sts & PCIM_STATUS_CAPPRESENT) != 0 && sc->psc_msi.capoff == 0) {
+ int origptr, msiptr;
+ origptr = read_config(&sel, PCIR_CAP_PTR, 1);
+ msiptr = passthru_add_msicap(pi, 1, origptr);
+ sc->psc_msi.capoff = msiptr;
+ sc->psc_msi.msgctrl = pci_get_cfgdata16(pi, msiptr + 2);
+ sc->psc_msi.emulated = 1;
+ pci_set_cfgdata8(pi, PCIR_CAP_PTR, msiptr);
+ }
+#endif
+
+ /* Make sure one of the capabilities is present */
+ if (sc->psc_msi.capoff == 0 && sc->psc_msix.capoff == 0)
+ return (-1);
+ else
+ return (0);
+}
+
+static uint64_t
+msix_table_read(struct passthru_softc *sc, uint64_t offset, int size)
+{
+ struct pci_devinst *pi;
+ struct msix_table_entry *entry;
+ uint8_t *src8;
+ uint16_t *src16;
+ uint32_t *src32;
+ uint64_t *src64;
+ uint64_t data;
+ size_t entry_offset;
+ int index;
+
+ pi = sc->psc_pi;
+
+ index = offset / MSIX_TABLE_ENTRY_SIZE;
+ if (index >= pi->pi_msix.table_count)
+ return (-1);
+
+ entry = &pi->pi_msix.table[index];
+ entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
+
+ switch(size) {
+ case 1:
+ src8 = (uint8_t *)((void *)entry + entry_offset);
+ data = *src8;
+ break;
+ case 2:
+ src16 = (uint16_t *)((void *)entry + entry_offset);
+ data = *src16;
+ break;
+ case 4:
+ src32 = (uint32_t *)((void *)entry + entry_offset);
+ data = *src32;
+ break;
+ case 8:
+ src64 = (uint64_t *)((void *)entry + entry_offset);
+ data = *src64;
+ break;
+ default:
+ return (-1);
+ }
+
+ return (data);
+}
+
+static void
+msix_table_write(struct vmctx *ctx, int vcpu, struct passthru_softc *sc,
+ uint64_t offset, int size, uint64_t data)
+{
+ struct pci_devinst *pi;
+ struct msix_table_entry *entry;
+ uint32_t *dest;
+ size_t entry_offset;
+ uint32_t vector_control;
+ int error, index;
+
+ pi = sc->psc_pi;
+ index = offset / MSIX_TABLE_ENTRY_SIZE;
+ if (index >= pi->pi_msix.table_count)
+ return;
+
+ entry = &pi->pi_msix.table[index];
+ entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
+
+ /* Only 4 byte naturally-aligned writes are supported */
+ assert(size == 4);
+ assert(entry_offset % 4 == 0);
+
+ vector_control = entry->vector_control;
+ dest = (uint32_t *)((void *)entry + entry_offset);
+ *dest = data;
+ /* If MSI-X hasn't been enabled, do nothing */
+ if (pi->pi_msix.enabled) {
+ /* 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->msg_data,
+ entry->vector_control,
+ entry->addr);
+ }
+ }
+}
+
+static int
+init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
+{
+ int b, s, f;
+ int error, idx;
+ size_t len, remaining, table_size;
+ vm_paddr_t start;
+ struct pci_devinst *pi = sc->psc_pi;
+
+ assert(pci_msix_table_bar(pi) >= 0 && pci_msix_pba_bar(pi) >= 0);
+
+ b = sc->psc_sel.pc_bus;
+ s = sc->psc_sel.pc_dev;
+ f = sc->psc_sel.pc_func;
+
+ /*
+ * If the MSI-X table BAR maps memory intended for
+ * other uses, it is at least assured that the table
+ * either resides in its own page within the region,
+ * or it resides in a page shared with only the PBA.
+ */
+ if (pi->pi_msix.pba_bar == pi->pi_msix.table_bar &&
+ ((pi->pi_msix.pba_offset - pi->pi_msix.table_offset) < 4096)) {
+ /* Need to also emulate the PBA, not supported yet */
+ printf("Unsupported MSI-X configuration: %d/%d/%d\n", b, s, f);
+ return (-1);
+ }
+
+ /* Compute the MSI-X table size */
+ table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
+ table_size = roundup2(table_size, 4096);
+
+ idx = pi->pi_msix.table_bar;
+ start = pi->pi_bar[idx].addr;
+ remaining = pi->pi_bar[idx].size;
+
+ /* Map everything before the MSI-X table */
+ if (pi->pi_msix.table_offset > 0) {
+ len = pi->pi_msix.table_offset;
+ error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
+ if (error)
+ return (error);
+
+ base += len;
+ start += len;
+ remaining -= len;
+ }
+
+ /* Skip the MSI-X table */
+ base += table_size;
+ start += table_size;
+ remaining -= table_size;
+
+ /* Map everything beyond the end of the MSI-X table */
+ if (remaining > 0) {
+ len = remaining;
+ error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
+ if (error)
+ return (error);
+ }
+
+ return (0);
+}
+
+static int
+cfginitbar(struct vmctx *ctx, struct passthru_softc *sc)
+{
+ int i, error;
+ struct pci_devinst *pi;
+ struct pci_bar_io bar;
+ enum pcibar_type bartype;
+ uint64_t base;
+
+ pi = sc->psc_pi;
+
+ /*
+ * Initialize BAR registers
+ */
+ for (i = 0; i <= PCI_BARMAX; i++) {
+ bzero(&bar, sizeof(bar));
+ bar.pbi_sel = sc->psc_sel;
+ bar.pbi_reg = PCIR_BAR(i);
+
+ if (ioctl(pcifd, PCIOCGETBAR, &bar) < 0)
+ continue;
+
+ if (PCI_BAR_IO(bar.pbi_base)) {
+ bartype = PCIBAR_IO;
+ base = bar.pbi_base & PCIM_BAR_IO_BASE;
+ } else {
+ switch (bar.pbi_base & PCIM_BAR_MEM_TYPE) {
+ case PCIM_BAR_MEM_64:
+ bartype = PCIBAR_MEM64;
+ break;
+ default:
+ bartype = PCIBAR_MEM32;
+ break;
+ }
+ base = bar.pbi_base & PCIM_BAR_MEM_BASE;
+ }
+
+ /* Cache information about the "real" BAR */
+ sc->psc_bar[i].type = bartype;
+ sc->psc_bar[i].size = bar.pbi_length;
+ sc->psc_bar[i].addr = base;
+
+ /* Allocate the BAR in the guest I/O or MMIO space */
+ error = pci_emul_alloc_pbar(pi, i, base, bartype,
+ bar.pbi_length);
+ if (error)
+ return (-1);
+
+ /* The MSI-X table needs special handling */
+ if (i == pci_msix_table_bar(pi)) {
+ error = init_msix_table(ctx, sc, base);
+ if (error)
+ return (-1);
+ } else if (bartype != PCIBAR_IO) {
+ /* Map the physical MMIO space in the guest MMIO space */
+ error = vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev, sc->psc_sel.pc_func,
+ pi->pi_bar[i].addr, pi->pi_bar[i].size, base);
+ if (error)
+ return (-1);
+ }
+
+ /*
+ * 64-bit BAR takes up two slots so skip the next one.
+ */
+ if (bartype == PCIBAR_MEM64) {
+ i++;
+ assert(i <= PCI_BARMAX);
+ sc->psc_bar[i].type = PCIBAR_MEMHI64;
+ }
+ }
+ return (0);
+}
+
+static int
+cfginit(struct vmctx *ctx, struct pci_devinst *pi, int bus, int slot, int func)
+{
+ int error;
+ struct passthru_softc *sc;
+
+ error = 1;
+ sc = pi->pi_arg;
+
+ bzero(&sc->psc_sel, sizeof(struct pcisel));
+ sc->psc_sel.pc_bus = bus;
+ sc->psc_sel.pc_dev = slot;
+ sc->psc_sel.pc_func = func;
+
+ if (cfginitmsi(sc) != 0)
+ goto done;
+
+ if (cfginitbar(ctx, sc) != 0)
+ goto done;
+
+ error = 0; /* success */
+done:
+ return (error);
+}
+
+static int
+passthru_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ int bus, slot, func, error;
+ struct passthru_softc *sc;
+
+ sc = NULL;
+ error = 1;
+
+ if (pcifd < 0) {
+ pcifd = open(_PATH_DEVPCI, O_RDWR, 0);
+ if (pcifd < 0)
+ goto done;
+ }
+
+ if (iofd < 0) {
+ iofd = open(_PATH_DEVIO, O_RDWR, 0);
+ if (iofd < 0)
+ goto done;
+ }
+
+ if (opts == NULL ||
+ sscanf(opts, "%d/%d/%d", &bus, &slot, &func) != 3)
+ goto done;
+
+ if (vm_assign_pptdev(ctx, bus, slot, func) != 0)
+ goto done;
+
+ sc = malloc(sizeof(struct passthru_softc));
+ memset(sc, 0, sizeof(struct passthru_softc));
+
+ pi->pi_arg = sc;
+ sc->psc_pi = pi;
+
+ /* initialize config space */
+ if ((error = cfginit(ctx, pi, bus, slot, func)) != 0)
+ goto done;
+
+ error = 0; /* success */
+done:
+ if (error) {
+ free(sc);
+ vm_unassign_pptdev(ctx, bus, slot, func);
+ }
+ return (error);
+}
+
+static int
+bar_access(int coff)
+{
+ if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1))
+ return (1);
+ else
+ return (0);
+}
+
+static int
+msicap_access(struct passthru_softc *sc, int coff)
+{
+ int caplen;
+
+ if (sc->psc_msi.capoff == 0)
+ return (0);
+
+ caplen = msi_caplen(sc->psc_msi.msgctrl);
+
+ if (coff >= sc->psc_msi.capoff && coff < sc->psc_msi.capoff + caplen)
+ return (1);
+ else
+ return (0);
+}
+
+static int
+msixcap_access(struct passthru_softc *sc, int coff)
+{
+ if (sc->psc_msix.capoff == 0)
+ return (0);
+
+ return (coff >= sc->psc_msix.capoff &&
+ coff < sc->psc_msix.capoff + MSIX_CAPLEN);
+}
+
+static int
+passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int coff, int bytes, uint32_t *rv)
+{
+ struct passthru_softc *sc;
+
+ sc = pi->pi_arg;
+
+ /*
+ * PCI BARs and MSI capability is emulated.
+ */
+ if (bar_access(coff) || msicap_access(sc, coff))
+ return (-1);
+
+#ifdef LEGACY_SUPPORT
+ /*
+ * Emulate PCIR_CAP_PTR if this device does not support MSI capability
+ * natively.
+ */
+ if (sc->psc_msi.emulated) {
+ if (coff >= PCIR_CAP_PTR && coff < PCIR_CAP_PTR + 4)
+ return (-1);
+ }
+#endif
+
+ /* Everything else just read from the device's config space */
+ *rv = read_config(&sc->psc_sel, coff, bytes);
+
+ return (0);
+}
+
+static int
+passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int coff, int bytes, uint32_t val)
+{
+ int error, msix_table_entries, i;
+ struct passthru_softc *sc;
+
+ sc = pi->pi_arg;
+
+ /*
+ * PCI BARs are emulated
+ */
+ if (bar_access(coff))
+ return (-1);
+
+ /*
+ * MSI capability is emulated
+ */
+ 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,
+ sc->psc_sel.pc_dev, sc->psc_sel.pc_func, pi->pi_msi.cpu,
+ pi->pi_msi.vector, pi->pi_msi.msgnum);
+ if (error != 0) {
+ printf("vm_setup_msi returned error %d\r\n", errno);
+ exit(1);
+ }
+ return (0);
+ }
+
+ if (msixcap_access(sc, coff)) {
+ msixcap_cfgwrite(pi, sc->psc_msix.capoff, coff, bytes, val);
+ 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);
+
+ if (error) {
+ printf("vm_setup_msix returned error %d\r\n", errno);
+ exit(1);
+ }
+ }
+ }
+ return (0);
+ }
+
+#ifdef LEGACY_SUPPORT
+ /*
+ * If this device does not support MSI natively then we cannot let
+ * the guest disable legacy interrupts from the device. It is the
+ * legacy interrupt that is triggering the virtual MSI to the guest.
+ */
+ if (sc->psc_msi.emulated && pci_msi_enabled(pi)) {
+ if (coff == PCIR_COMMAND && bytes == 2)
+ val &= ~PCIM_CMD_INTxDIS;
+ }
+#endif
+
+ write_config(&sc->psc_sel, coff, bytes, val);
+
+ return (0);
+}
+
+static void
+passthru_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
+ uint64_t offset, int size, uint64_t value)
+{
+ struct passthru_softc *sc;
+ struct iodev_pio_req pio;
+
+ sc = pi->pi_arg;
+
+ if (baridx == pci_msix_table_bar(pi)) {
+ msix_table_write(ctx, vcpu, sc, offset, size, value);
+ } else {
+ assert(pi->pi_bar[baridx].type == PCIBAR_IO);
+ bzero(&pio, sizeof(struct iodev_pio_req));
+ pio.access = IODEV_PIO_WRITE;
+ pio.port = sc->psc_bar[baridx].addr + offset;
+ pio.width = size;
+ pio.val = value;
+
+ (void)ioctl(iofd, IODEV_PIO, &pio);
+ }
+}
+
+static uint64_t
+passthru_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
+ uint64_t offset, int size)
+{
+ struct passthru_softc *sc;
+ struct iodev_pio_req pio;
+ uint64_t val;
+
+ sc = pi->pi_arg;
+
+ if (baridx == pci_msix_table_bar(pi)) {
+ val = msix_table_read(sc, offset, size);
+ } else {
+ assert(pi->pi_bar[baridx].type == PCIBAR_IO);
+ bzero(&pio, sizeof(struct iodev_pio_req));
+ pio.access = IODEV_PIO_READ;
+ pio.port = sc->psc_bar[baridx].addr + offset;
+ pio.width = size;
+ pio.val = 0;
+
+ (void)ioctl(iofd, IODEV_PIO, &pio);
+
+ val = pio.val;
+ }
+
+ return (val);
+}
+
+struct pci_devemu passthru = {
+ .pe_emu = "passthru",
+ .pe_init = passthru_init,
+ .pe_cfgwrite = passthru_cfgwrite,
+ .pe_cfgread = passthru_cfgread,
+ .pe_barwrite = passthru_write,
+ .pe_barread = passthru_read,
+};
+PCI_EMUL_SET(passthru);
diff --git a/usr.sbin/bhyve/pci_uart.c b/usr.sbin/bhyve/pci_uart.c
new file mode 100644
index 0000000..dd30551
--- /dev/null
+++ b/usr.sbin/bhyve/pci_uart.c
@@ -0,0 +1,626 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <dev/ic/ns16550.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <termios.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "bhyverun.h"
+#include "pci_emul.h"
+#include "mevent.h"
+
+#define COM1_BASE 0x3F8
+#define COM1_IRQ 4
+#define COM2_BASE 0x2F8
+#define COM2_IRQ 3
+
+#define DEFAULT_RCLK 1843200
+#define DEFAULT_BAUD 9600
+
+#define FCR_RX_MASK 0xC0
+
+#define MCR_OUT1 0x04
+#define MCR_OUT2 0x08
+
+#define MSR_DELTA_MASK 0x0f
+
+#ifndef REG_SCR
+#define REG_SCR com_scr
+#endif
+
+#define FIFOSZ 16
+
+/*
+ * Pick a PCI vid/did of a chip with a single uart at
+ * BAR0, that most versions of FreeBSD can understand:
+ * Siig CyberSerial 1-port.
+ */
+#define COM_VENDOR 0x131f
+#define COM_DEV 0x2000
+
+static int pci_uart_stdio; /* stdio in use for i/o */
+
+static int pci_uart_nldevs; /* number of legacy devices - 2 max */
+
+static struct {
+ uint64_t baddr;
+ int vector;
+} pci_uart_lres[] = {
+ { COM1_BASE, COM1_IRQ},
+ { COM2_BASE, COM2_IRQ},
+ { 0, 0 }
+};
+
+struct fifo {
+ uint8_t buf[FIFOSZ];
+ int rindex; /* index to read from */
+ int windex; /* index to write to */
+ int num; /* number of characters in the fifo */
+ int size; /* size of the fifo */
+};
+
+struct pci_uart_softc {
+ struct pci_devinst *pi;
+ pthread_mutex_t mtx; /* protects all softc elements */
+ uint8_t data; /* Data register (R/W) */
+ uint8_t ier; /* Interrupt enable register (R/W) */
+ uint8_t lcr; /* Line control register (R/W) */
+ uint8_t mcr; /* Modem control register (R/W) */
+ uint8_t lsr; /* Line status register (R/W) */
+ uint8_t msr; /* Modem status register (R/W) */
+ uint8_t fcr; /* FIFO control register (W) */
+ uint8_t scr; /* Scratch register (R/W) */
+
+ uint8_t dll; /* Baudrate divisor latch LSB */
+ uint8_t dlh; /* Baudrate divisor latch MSB */
+
+ struct fifo rxfifo;
+
+ int opened;
+ int stdio;
+ bool thre_int_pending; /* THRE interrupt pending */
+};
+
+static void pci_uart_drain(int fd, enum ev_type ev, void *arg);
+
+static struct termios tio_orig, tio_new; /* I/O Terminals */
+
+static void
+ttyclose(void)
+{
+ tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig);
+}
+
+static void
+ttyopen(void)
+{
+ tcgetattr(STDIN_FILENO, &tio_orig);
+
+ cfmakeraw(&tio_new);
+ tcsetattr(STDIN_FILENO, TCSANOW, &tio_new);
+
+ atexit(ttyclose);
+}
+
+static bool
+tty_char_available(void)
+{
+ fd_set rfds;
+ struct timeval tv;
+
+ FD_ZERO(&rfds);
+ FD_SET(STDIN_FILENO, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0 ) {
+ return (true);
+ } else {
+ return (false);
+ }
+}
+
+static int
+ttyread(void)
+{
+ char rb;
+
+ if (tty_char_available()) {
+ read(STDIN_FILENO, &rb, 1);
+ return (rb & 0xff);
+ } else {
+ return (-1);
+ }
+}
+
+static void
+ttywrite(unsigned char wb)
+{
+ (void) write(STDIN_FILENO, &wb, 1);
+}
+
+static void
+fifo_reset(struct fifo *fifo, int size)
+{
+ bzero(fifo, sizeof(struct fifo));
+ fifo->size = size;
+}
+
+static int
+fifo_putchar(struct fifo *fifo, uint8_t ch)
+{
+
+ if (fifo->num < fifo->size) {
+ fifo->buf[fifo->windex] = ch;
+ fifo->windex = (fifo->windex + 1) % fifo->size;
+ fifo->num++;
+ return (0);
+ } else
+ return (-1);
+}
+
+static int
+fifo_getchar(struct fifo *fifo)
+{
+ int c;
+
+ if (fifo->num > 0) {
+ c = fifo->buf[fifo->rindex];
+ fifo->rindex = (fifo->rindex + 1) % fifo->size;
+ fifo->num--;
+ return (c);
+ } else
+ return (-1);
+}
+
+static int
+fifo_numchars(struct fifo *fifo)
+{
+
+ return (fifo->num);
+}
+
+static int
+fifo_available(struct fifo *fifo)
+{
+
+ return (fifo->num < fifo->size);
+}
+
+static void
+pci_uart_opentty(struct pci_uart_softc *sc)
+{
+ struct mevent *mev;
+
+ assert(sc->opened == 0);
+ assert(sc->stdio);
+
+ ttyopen();
+ mev = mevent_add(STDIN_FILENO, EVF_READ, pci_uart_drain, sc);
+ assert(mev);
+}
+
+static void
+pci_uart_legacy_res(uint64_t *bar, int *ivec)
+{
+ if (pci_uart_lres[pci_uart_nldevs].baddr != 0) {
+ *bar = pci_uart_lres[pci_uart_nldevs].baddr;
+ *ivec = pci_uart_lres[pci_uart_nldevs].vector;
+ pci_uart_nldevs++;
+ } else {
+ /* TODO: print warning ? */
+ *bar = 0;
+ *ivec= -1;
+ }
+}
+
+/*
+ * The IIR returns a prioritized interrupt reason:
+ * - receive data available
+ * - transmit holding register empty
+ * - modem status change
+ *
+ * Return an interrupt reason if one is available.
+ */
+static int
+pci_uart_intr_reason(struct pci_uart_softc *sc)
+{
+
+ if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0)
+ return (IIR_RLS);
+ else if (fifo_numchars(&sc->rxfifo) > 0 && (sc->ier & IER_ERXRDY) != 0)
+ return (IIR_RXTOUT);
+ else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0)
+ return (IIR_TXRDY);
+ else if ((sc->msr & MSR_DELTA_MASK) != 0 && (sc->ier & IER_EMSC) != 0)
+ return (IIR_MLSC);
+ else
+ return (IIR_NOPEND);
+}
+
+static void
+pci_uart_reset(struct pci_uart_softc *sc)
+{
+ uint16_t divisor;
+
+ divisor = DEFAULT_RCLK / DEFAULT_BAUD / 16;
+ sc->dll = divisor;
+ sc->dlh = divisor >> 16;
+
+ fifo_reset(&sc->rxfifo, 1); /* no fifo until enabled by software */
+}
+
+/*
+ * Toggle the COM port's intr pin depending on whether or not we have an
+ * interrupt condition to report to the processor.
+ */
+static void
+pci_uart_toggle_intr(struct pci_uart_softc *sc)
+{
+ uint8_t intr_reason;
+
+ intr_reason = pci_uart_intr_reason(sc);
+
+ if (intr_reason == IIR_NOPEND)
+ pci_lintr_deassert(sc->pi);
+ else
+ pci_lintr_assert(sc->pi);
+}
+
+static void
+pci_uart_drain(int fd, enum ev_type ev, void *arg)
+{
+ struct pci_uart_softc *sc;
+ int ch;
+
+ sc = arg;
+
+ assert(fd == STDIN_FILENO);
+ assert(ev == EVF_READ);
+
+ /*
+ * This routine is called in the context of the mevent thread
+ * to take out the softc lock to protect against concurrent
+ * access from a vCPU i/o exit
+ */
+ pthread_mutex_lock(&sc->mtx);
+
+ if ((sc->mcr & MCR_LOOPBACK) != 0) {
+ (void) ttyread();
+ } else {
+ while (fifo_available(&sc->rxfifo) &&
+ ((ch = ttyread()) != -1)) {
+ fifo_putchar(&sc->rxfifo, ch);
+ }
+ pci_uart_toggle_intr(sc);
+ }
+
+ pthread_mutex_unlock(&sc->mtx);
+}
+
+static void
+pci_uart_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size, uint64_t value)
+{
+ struct pci_uart_softc *sc;
+ int fifosz;
+ uint8_t msr;
+
+ sc = pi->pi_arg;
+
+ assert(baridx == 0);
+ assert(size == 1);
+
+ /* Open terminal */
+ if (!sc->opened && sc->stdio) {
+ pci_uart_opentty(sc);
+ sc->opened = 1;
+ }
+
+ pthread_mutex_lock(&sc->mtx);
+
+ /*
+ * Take care of the special case DLAB accesses first
+ */
+ if ((sc->lcr & LCR_DLAB) != 0) {
+ if (offset == REG_DLL) {
+ sc->dll = value;
+ goto done;
+ }
+
+ if (offset == REG_DLH) {
+ sc->dlh = value;
+ goto done;
+ }
+ }
+
+ switch (offset) {
+ case REG_DATA:
+ if (sc->mcr & MCR_LOOPBACK) {
+ if (fifo_putchar(&sc->rxfifo, value) != 0)
+ sc->lsr |= LSR_OE;
+ } else if (sc->stdio) {
+ ttywrite(value);
+ } /* else drop on floor */
+ sc->thre_int_pending = true;
+ break;
+ case REG_IER:
+ /*
+ * Apply mask so that bits 4-7 are 0
+ * Also enables bits 0-3 only if they're 1
+ */
+ sc->ier = value & 0x0F;
+ break;
+ case REG_FCR:
+ /*
+ * When moving from FIFO and 16450 mode and vice versa,
+ * the FIFO contents are reset.
+ */
+ if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) {
+ fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1;
+ fifo_reset(&sc->rxfifo, fifosz);
+ }
+
+ /*
+ * The FCR_ENABLE bit must be '1' for the programming
+ * of other FCR bits to be effective.
+ */
+ if ((value & FCR_ENABLE) == 0) {
+ sc->fcr = 0;
+ } else {
+ if ((value & FCR_RCV_RST) != 0)
+ fifo_reset(&sc->rxfifo, FIFOSZ);
+
+ sc->fcr = value &
+ (FCR_ENABLE | FCR_DMA | FCR_RX_MASK);
+ }
+ break;
+ case REG_LCR:
+ sc->lcr = value;
+ break;
+ case REG_MCR:
+ /* Apply mask so that bits 5-7 are 0 */
+ sc->mcr = value & 0x1F;
+
+ msr = 0;
+ if (sc->mcr & MCR_LOOPBACK) {
+ /*
+ * In the loopback mode certain bits from the
+ * MCR are reflected back into MSR
+ */
+ if (sc->mcr & MCR_RTS)
+ msr |= MSR_CTS;
+ if (sc->mcr & MCR_DTR)
+ msr |= MSR_DSR;
+ if (sc->mcr & MCR_OUT1)
+ msr |= MSR_RI;
+ if (sc->mcr & MCR_OUT2)
+ msr |= MSR_DCD;
+ }
+
+ /*
+ * Detect if there has been any change between the
+ * previous and the new value of MSR. If there is
+ * then assert the appropriate MSR delta bit.
+ */
+ if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS))
+ sc->msr |= MSR_DCTS;
+ if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR))
+ sc->msr |= MSR_DDSR;
+ if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD))
+ sc->msr |= MSR_DDCD;
+ if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0)
+ sc->msr |= MSR_TERI;
+
+ /*
+ * Update the value of MSR while retaining the delta
+ * bits.
+ */
+ sc->msr &= MSR_DELTA_MASK;
+ sc->msr |= msr;
+ break;
+ case REG_LSR:
+ /*
+ * Line status register is not meant to be written to
+ * during normal operation.
+ */
+ break;
+ case REG_MSR:
+ /*
+ * As far as I can tell MSR is a read-only register.
+ */
+ break;
+ case REG_SCR:
+ sc->scr = value;
+ break;
+ default:
+ break;
+ }
+
+done:
+ pci_uart_toggle_intr(sc);
+ pthread_mutex_unlock(&sc->mtx);
+}
+
+uint64_t
+pci_uart_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size)
+{
+ struct pci_uart_softc *sc;
+ uint8_t iir, intr_reason;
+ uint64_t reg;
+
+ sc = pi->pi_arg;
+
+ assert(baridx == 0);
+ assert(size == 1);
+
+ /* Open terminal */
+ if (!sc->opened && sc->stdio) {
+ pci_uart_opentty(sc);
+ sc->opened = 1;
+ }
+
+ pthread_mutex_lock(&sc->mtx);
+
+ /*
+ * Take care of the special case DLAB accesses first
+ */
+ if ((sc->lcr & LCR_DLAB) != 0) {
+ if (offset == REG_DLL) {
+ reg = sc->dll;
+ goto done;
+ }
+
+ if (offset == REG_DLH) {
+ reg = sc->dlh;
+ goto done;
+ }
+ }
+
+ switch (offset) {
+ case REG_DATA:
+ reg = fifo_getchar(&sc->rxfifo);
+ break;
+ case REG_IER:
+ reg = sc->ier;
+ break;
+ case REG_IIR:
+ iir = (sc->fcr & FCR_ENABLE) ? IIR_FIFO_MASK : 0;
+
+ intr_reason = pci_uart_intr_reason(sc);
+
+ /*
+ * Deal with side effects of reading the IIR register
+ */
+ if (intr_reason == IIR_TXRDY)
+ sc->thre_int_pending = false;
+
+ iir |= intr_reason;
+
+ reg = iir;
+ break;
+ case REG_LCR:
+ reg = sc->lcr;
+ break;
+ case REG_MCR:
+ reg = sc->mcr;
+ break;
+ case REG_LSR:
+ /* Transmitter is always ready for more data */
+ sc->lsr |= LSR_TEMT | LSR_THRE;
+
+ /* Check for new receive data */
+ if (fifo_numchars(&sc->rxfifo) > 0)
+ sc->lsr |= LSR_RXRDY;
+ else
+ sc->lsr &= ~LSR_RXRDY;
+
+ reg = sc->lsr;
+
+ /* The LSR_OE bit is cleared on LSR read */
+ sc->lsr &= ~LSR_OE;
+ break;
+ case REG_MSR:
+ /*
+ * MSR delta bits are cleared on read
+ */
+ reg = sc->msr;
+ sc->msr &= ~MSR_DELTA_MASK;
+ break;
+ case REG_SCR:
+ reg = sc->scr;
+ break;
+ default:
+ reg = 0xFF;
+ break;
+ }
+
+done:
+ pci_uart_toggle_intr(sc);
+ pthread_mutex_unlock(&sc->mtx);
+
+ return (reg);
+}
+
+static int
+pci_uart_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ struct pci_uart_softc *sc;
+ uint64_t bar;
+ int ivec;
+
+ sc = malloc(sizeof(struct pci_uart_softc));
+ memset(sc, 0, sizeof(struct pci_uart_softc));
+
+ pi->pi_arg = sc;
+ sc->pi = pi;
+
+ pthread_mutex_init(&sc->mtx, NULL);
+
+ /* initialize config space */
+ pci_set_cfgdata16(pi, PCIR_DEVICE, COM_DEV);
+ pci_set_cfgdata16(pi, PCIR_VENDOR, COM_VENDOR);
+ pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SIMPLECOMM);
+ if (pci_is_legacy(pi)) {
+ pci_uart_legacy_res(&bar, &ivec);
+ pci_emul_alloc_pbar(pi, 0, bar, PCIBAR_IO, 8);
+ } else {
+ ivec = -1;
+ pci_emul_alloc_bar(pi, 0, PCIBAR_IO, 8);
+ }
+ pci_lintr_request(pi, ivec);
+
+ if (opts != NULL && !strcmp("stdio", opts) && !pci_uart_stdio) {
+ pci_uart_stdio = 1;
+ sc->stdio = 1;
+ }
+
+ pci_uart_reset(sc);
+
+ return (0);
+}
+
+struct pci_devemu pci_de_com = {
+ .pe_emu = "uart",
+ .pe_init = pci_uart_init,
+ .pe_barwrite = pci_uart_write,
+ .pe_barread = pci_uart_read
+};
+PCI_EMUL_SET(pci_de_com);
diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
new file mode 100644
index 0000000..c8fc914
--- /dev/null
+++ b/usr.sbin/bhyve/pci_virtio_block.c
@@ -0,0 +1,624 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/linker_set.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/disk.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <assert.h>
+#include <pthread.h>
+
+#include "bhyverun.h"
+#include "pci_emul.h"
+#include "virtio.h"
+
+#define VTBLK_RINGSZ 64
+
+#define VTBLK_CFGSZ 28
+
+#define VTBLK_R_CFG VTCFG_R_CFG1
+#define VTBLK_R_CFG_END VTBLK_R_CFG + VTBLK_CFGSZ -1
+#define VTBLK_R_MAX VTBLK_R_CFG_END
+
+#define VTBLK_REGSZ VTBLK_R_MAX+1
+
+#define VTBLK_MAXSEGS 32
+
+#define VTBLK_S_OK 0
+#define VTBLK_S_IOERR 1
+
+/*
+ * Host capabilities
+ */
+#define VTBLK_S_HOSTCAPS \
+ ( 0x00000004 | /* host maximum request segments */ \
+ 0x10000000 ) /* supports indirect descriptors */
+
+static int use_msix = 1;
+
+struct vring_hqueue {
+ /* Internal state */
+ uint16_t hq_size;
+ uint16_t hq_cur_aidx; /* trails behind 'avail_idx' */
+
+ /* Host-context pointers to the queue */
+ struct virtio_desc *hq_dtable;
+ uint16_t *hq_avail_flags;
+ uint16_t *hq_avail_idx; /* monotonically increasing */
+ uint16_t *hq_avail_ring;
+
+ uint16_t *hq_used_flags;
+ uint16_t *hq_used_idx; /* monotonically increasing */
+ struct virtio_used *hq_used_ring;
+};
+
+/*
+ * Config space
+ */
+struct vtblk_config {
+ uint64_t vbc_capacity;
+ uint32_t vbc_size_max;
+ uint32_t vbc_seg_max;
+ uint16_t vbc_geom_c;
+ uint8_t vbc_geom_h;
+ uint8_t vbc_geom_s;
+ uint32_t vbc_blk_size;
+ uint32_t vbc_sectors_max;
+} __packed;
+CTASSERT(sizeof(struct vtblk_config) == VTBLK_CFGSZ);
+
+/*
+ * Fixed-size block header
+ */
+struct virtio_blk_hdr {
+#define VBH_OP_READ 0
+#define VBH_OP_WRITE 1
+ uint32_t vbh_type;
+ uint32_t vbh_ioprio;
+ uint64_t vbh_sector;
+} __packed;
+
+/*
+ * Debug printf
+ */
+static int pci_vtblk_debug;
+#define DPRINTF(params) if (pci_vtblk_debug) printf params
+#define WPRINTF(params) printf params
+
+/*
+ * Per-device softc
+ */
+struct pci_vtblk_softc {
+ struct pci_devinst *vbsc_pi;
+ int vbsc_fd;
+ int vbsc_status;
+ int vbsc_isr;
+ int vbsc_lastq;
+ uint32_t vbsc_features;
+ uint64_t vbsc_pfn;
+ struct vring_hqueue vbsc_q;
+ struct vtblk_config vbsc_cfg;
+ uint16_t msix_table_idx_req;
+ uint16_t msix_table_idx_cfg;
+};
+
+/*
+ * Return the size of IO BAR that maps virtio header and device specific
+ * region. The size would vary depending on whether MSI-X is enabled or
+ * not
+ */
+static uint64_t
+pci_vtblk_iosize(struct pci_devinst *pi)
+{
+
+ if (pci_msix_enabled(pi))
+ return (VTBLK_REGSZ);
+ else
+ return (VTBLK_REGSZ - (VTCFG_R_CFG1 - VTCFG_R_MSIX));
+}
+
+/*
+ * Return the number of available descriptors in the vring taking care
+ * of the 16-bit index wraparound.
+ */
+static int
+hq_num_avail(struct vring_hqueue *hq)
+{
+ int ndesc;
+
+ if (*hq->hq_avail_idx >= hq->hq_cur_aidx)
+ ndesc = *hq->hq_avail_idx - hq->hq_cur_aidx;
+ else
+ ndesc = UINT16_MAX - hq->hq_cur_aidx + *hq->hq_avail_idx + 1;
+
+ assert(ndesc >= 0 && ndesc <= hq->hq_size);
+
+ return (ndesc);
+}
+
+static void
+pci_vtblk_update_status(struct pci_vtblk_softc *sc, uint32_t value)
+{
+ if (value == 0) {
+ DPRINTF(("vtblk: device reset requested !\n"));
+ }
+
+ sc->vbsc_status = value;
+}
+
+static void
+pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
+{
+ struct iovec iov[VTBLK_MAXSEGS];
+ struct virtio_blk_hdr *vbh;
+ struct virtio_desc *vd, *vid;
+ struct virtio_used *vu;
+ uint8_t *status;
+ int i;
+ int err;
+ int iolen;
+ int nsegs;
+ int uidx, aidx, didx;
+ int writeop;
+ off_t offset;
+
+ uidx = *hq->hq_used_idx;
+ aidx = hq->hq_cur_aidx;
+ didx = hq->hq_avail_ring[aidx % hq->hq_size];
+ assert(didx >= 0 && didx < hq->hq_size);
+
+ vd = &hq->hq_dtable[didx];
+
+ /*
+ * Verify that the descriptor is indirect, and obtain
+ * the pointer to the indirect descriptor.
+ * There has to be space for at least 3 descriptors
+ * in the indirect descriptor array: the block header,
+ * 1 or more data descriptors, and a status byte.
+ */
+ assert(vd->vd_flags & VRING_DESC_F_INDIRECT);
+
+ nsegs = vd->vd_len / sizeof(struct virtio_desc);
+ assert(nsegs >= 3);
+ assert(nsegs < VTBLK_MAXSEGS + 2);
+
+ vid = paddr_guest2host(vd->vd_addr);
+ assert((vid->vd_flags & VRING_DESC_F_INDIRECT) == 0);
+
+ /*
+ * The first descriptor will be the read-only fixed header
+ */
+ vbh = paddr_guest2host(vid[0].vd_addr);
+ assert(vid[0].vd_len == sizeof(struct virtio_blk_hdr));
+ assert(vid[0].vd_flags & VRING_DESC_F_NEXT);
+ assert((vid[0].vd_flags & VRING_DESC_F_WRITE) == 0);
+
+ writeop = (vbh->vbh_type == VBH_OP_WRITE);
+
+ offset = vbh->vbh_sector * DEV_BSIZE;
+
+ /*
+ * Build up the iovec based on the guest's data descriptors
+ */
+ for (i = 1, iolen = 0; i < nsegs - 1; i++) {
+ iov[i-1].iov_base = paddr_guest2host(vid[i].vd_addr);
+ iov[i-1].iov_len = vid[i].vd_len;
+ iolen += vid[i].vd_len;
+
+ assert(vid[i].vd_flags & VRING_DESC_F_NEXT);
+ assert((vid[i].vd_flags & VRING_DESC_F_INDIRECT) == 0);
+
+ /*
+ * - write op implies read-only descriptor,
+ * - read op implies write-only descriptor,
+ * therefore test the inverse of the descriptor bit
+ * to the op.
+ */
+ assert(((vid[i].vd_flags & VRING_DESC_F_WRITE) == 0) ==
+ writeop);
+ }
+
+ /* Lastly, get the address of the status byte */
+ status = paddr_guest2host(vid[nsegs - 1].vd_addr);
+ assert(vid[nsegs - 1].vd_len == 1);
+ assert((vid[nsegs - 1].vd_flags & VRING_DESC_F_NEXT) == 0);
+ assert(vid[nsegs - 1].vd_flags & VRING_DESC_F_WRITE);
+
+ DPRINTF(("virtio-block: %s op, %d bytes, %d segs, offset %ld\n\r",
+ writeop ? "write" : "read", iolen, nsegs - 2, offset));
+
+ if (writeop){
+ err = pwritev(sc->vbsc_fd, iov, nsegs - 2, offset);
+ } else {
+ err = preadv(sc->vbsc_fd, iov, nsegs - 2, offset);
+ }
+
+ *status = err < 0 ? VTBLK_S_IOERR : VTBLK_S_OK;
+
+ /*
+ * Return the single indirect descriptor back to the host
+ */
+ vu = &hq->hq_used_ring[uidx % hq->hq_size];
+ vu->vu_idx = didx;
+ vu->vu_tlen = 1;
+ hq->hq_cur_aidx++;
+ *hq->hq_used_idx += 1;
+}
+
+static void
+pci_vtblk_qnotify(struct pci_vtblk_softc *sc)
+{
+ struct vring_hqueue *hq = &sc->vbsc_q;
+ int i;
+ int ndescs;
+
+ /*
+ * Calculate number of ring entries to process
+ */
+ ndescs = hq_num_avail(hq);
+
+ if (ndescs == 0)
+ return;
+
+ /*
+ * Run through all the entries, placing them into iovecs and
+ * sending when an end-of-packet is found
+ */
+ for (i = 0; i < ndescs; i++)
+ pci_vtblk_proc(sc, hq);
+
+ /*
+ * Generate an interrupt if able
+ */
+ if ((*hq->hq_avail_flags & VRING_AVAIL_F_NO_INTERRUPT) == 0) {
+ if (use_msix) {
+ pci_generate_msix(sc->vbsc_pi, sc->msix_table_idx_req);
+ } else if (sc->vbsc_isr == 0) {
+ sc->vbsc_isr = 1;
+ pci_generate_msi(sc->vbsc_pi, 0);
+ }
+ }
+
+}
+
+static void
+pci_vtblk_ring_init(struct pci_vtblk_softc *sc, uint64_t pfn)
+{
+ struct vring_hqueue *hq;
+
+ sc->vbsc_pfn = pfn << VRING_PFN;
+
+ /*
+ * Set up host pointers to the various parts of the
+ * queue
+ */
+ hq = &sc->vbsc_q;
+ hq->hq_size = VTBLK_RINGSZ;
+
+ hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN);
+ hq->hq_avail_flags = (uint16_t *)(hq->hq_dtable + hq->hq_size);
+ hq->hq_avail_idx = hq->hq_avail_flags + 1;
+ hq->hq_avail_ring = hq->hq_avail_flags + 2;
+ hq->hq_used_flags = (uint16_t *)roundup2((uintptr_t)hq->hq_avail_ring,
+ VRING_ALIGN);
+ hq->hq_used_idx = hq->hq_used_flags + 1;
+ hq->hq_used_ring = (struct virtio_used *)(hq->hq_used_flags + 2);
+
+ /*
+ * Initialize queue indexes
+ */
+ hq->hq_cur_aidx = 0;
+}
+
+static int
+pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ struct stat sbuf;
+ struct pci_vtblk_softc *sc;
+ off_t size;
+ int fd;
+ int sectsz;
+ const char *env_msi;
+
+ if (opts == NULL) {
+ printf("virtio-block: backing device required\n");
+ return (1);
+ }
+
+ /*
+ * Access to guest memory is required. Fail if
+ * memory not mapped
+ */
+ if (paddr_guest2host(0) == NULL)
+ return (1);
+
+ /*
+ * The supplied backing file has to exist
+ */
+ fd = open(opts, O_RDWR);
+ if (fd < 0) {
+ perror("Could not open backing file");
+ return (1);
+ }
+
+ if (fstat(fd, &sbuf) < 0) {
+ perror("Could not stat backing file");
+ close(fd);
+ return (1);
+ }
+
+ /*
+ * Deal with raw devices
+ */
+ size = sbuf.st_size;
+ sectsz = DEV_BSIZE;
+ if (S_ISCHR(sbuf.st_mode)) {
+ if (ioctl(fd, DIOCGMEDIASIZE, &size) < 0 ||
+ ioctl(fd, DIOCGSECTORSIZE, &sectsz)) {
+ perror("Could not fetch dev blk/sector size");
+ close(fd);
+ return (1);
+ }
+ assert(size != 0);
+ assert(sectsz != 0);
+ }
+
+ sc = malloc(sizeof(struct pci_vtblk_softc));
+ memset(sc, 0, sizeof(struct pci_vtblk_softc));
+
+ pi->pi_arg = sc;
+ sc->vbsc_pi = pi;
+ sc->vbsc_fd = fd;
+
+ /* setup virtio block config space */
+ sc->vbsc_cfg.vbc_capacity = size / sectsz;
+ sc->vbsc_cfg.vbc_seg_max = VTBLK_MAXSEGS;
+ sc->vbsc_cfg.vbc_blk_size = sectsz;
+ sc->vbsc_cfg.vbc_size_max = 0; /* not negotiated */
+ sc->vbsc_cfg.vbc_geom_c = 0; /* no geometry */
+ sc->vbsc_cfg.vbc_geom_h = 0;
+ sc->vbsc_cfg.vbc_geom_s = 0;
+ sc->vbsc_cfg.vbc_sectors_max = 0;
+
+ /* initialize config space */
+ pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_BLOCK);
+ pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
+ pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_STORAGE);
+ pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_BLOCK);
+
+ if ((env_msi = getenv("BHYVE_USE_MSI"))) {
+ if (strcasecmp(env_msi, "yes") == 0)
+ use_msix = 0;
+ }
+
+ if (use_msix) {
+ /* MSI-X Support */
+ sc->msix_table_idx_req = VIRTIO_MSI_NO_VECTOR;
+ sc->msix_table_idx_cfg = VIRTIO_MSI_NO_VECTOR;
+
+ if (pci_emul_add_msixcap(pi, 2, 1))
+ return (1);
+ } else {
+ /* MSI Support */
+ pci_emul_add_msicap(pi, 1);
+ }
+
+ pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VTBLK_REGSZ);
+
+ return (0);
+}
+
+static uint64_t
+vtblk_adjust_offset(struct pci_devinst *pi, uint64_t offset)
+{
+ /*
+ * Device specific offsets used by guest would change
+ * based on whether MSI-X capability is enabled or not
+ */
+ if (!pci_msix_enabled(pi)) {
+ if (offset >= VTCFG_R_MSIX)
+ return (offset + (VTCFG_R_CFG1 - VTCFG_R_MSIX));
+ }
+
+ return (offset);
+}
+
+static void
+pci_vtblk_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size, uint64_t value)
+{
+ struct pci_vtblk_softc *sc = pi->pi_arg;
+
+ if (use_msix) {
+ if (baridx == pci_msix_table_bar(pi) ||
+ baridx == pci_msix_pba_bar(pi)) {
+ pci_emul_msix_twrite(pi, offset, size, value);
+ return;
+ }
+ }
+
+ assert(baridx == 0);
+
+ if (offset + size > pci_vtblk_iosize(pi)) {
+ DPRINTF(("vtblk_write: 2big, offset %ld size %d\n",
+ offset, size));
+ return;
+ }
+
+ offset = vtblk_adjust_offset(pi, offset);
+
+ switch (offset) {
+ case VTCFG_R_GUESTCAP:
+ assert(size == 4);
+ sc->vbsc_features = value & VTBLK_S_HOSTCAPS;
+ break;
+ case VTCFG_R_PFN:
+ assert(size == 4);
+ pci_vtblk_ring_init(sc, value);
+ break;
+ case VTCFG_R_QSEL:
+ assert(size == 2);
+ sc->vbsc_lastq = value;
+ break;
+ case VTCFG_R_QNOTIFY:
+ assert(size == 2);
+ assert(value == 0);
+ pci_vtblk_qnotify(sc);
+ break;
+ case VTCFG_R_STATUS:
+ assert(size == 1);
+ pci_vtblk_update_status(sc, value);
+ break;
+ case VTCFG_R_CFGVEC:
+ assert(size == 2);
+ sc->msix_table_idx_cfg = value;
+ break;
+ case VTCFG_R_QVEC:
+ assert(size == 2);
+ sc->msix_table_idx_req = value;
+ break;
+ case VTCFG_R_HOSTCAP:
+ case VTCFG_R_QNUM:
+ case VTCFG_R_ISR:
+ case VTBLK_R_CFG ... VTBLK_R_CFG_END:
+ DPRINTF(("vtblk: write to readonly reg %ld\n\r", offset));
+ break;
+ default:
+ DPRINTF(("vtblk: unknown i/o write offset %ld\n\r", offset));
+ value = 0;
+ break;
+ }
+}
+
+uint64_t
+pci_vtblk_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size)
+{
+ struct pci_vtblk_softc *sc = pi->pi_arg;
+ void *ptr;
+ uint32_t value;
+
+ if (use_msix) {
+ if (baridx == pci_msix_table_bar(pi) ||
+ baridx == pci_msix_pba_bar(pi)) {
+ return (pci_emul_msix_tread(pi, offset, size));
+ }
+ }
+
+ assert(baridx == 0);
+
+ if (offset + size > pci_vtblk_iosize(pi)) {
+ DPRINTF(("vtblk_read: 2big, offset %ld size %d\n",
+ offset, size));
+ return (0);
+ }
+
+ offset = vtblk_adjust_offset(pi, offset);
+
+ switch (offset) {
+ case VTCFG_R_HOSTCAP:
+ assert(size == 4);
+ value = VTBLK_S_HOSTCAPS;
+ break;
+ case VTCFG_R_GUESTCAP:
+ assert(size == 4);
+ value = sc->vbsc_features; /* XXX never read ? */
+ break;
+ case VTCFG_R_PFN:
+ assert(size == 4);
+ value = sc->vbsc_pfn >> VRING_PFN;
+ break;
+ case VTCFG_R_QNUM:
+ value = (sc->vbsc_lastq == 0) ? VTBLK_RINGSZ: 0;
+ break;
+ case VTCFG_R_QSEL:
+ assert(size == 2);
+ value = sc->vbsc_lastq; /* XXX never read ? */
+ break;
+ case VTCFG_R_QNOTIFY:
+ assert(size == 2);
+ value = 0; /* XXX never read ? */
+ break;
+ case VTCFG_R_STATUS:
+ assert(size == 1);
+ value = sc->vbsc_status;
+ break;
+ case VTCFG_R_ISR:
+ assert(size == 1);
+ value = sc->vbsc_isr;
+ sc->vbsc_isr = 0; /* a read clears this flag */
+ break;
+ case VTCFG_R_CFGVEC:
+ assert(size == 2);
+ value = sc->msix_table_idx_cfg;
+ break;
+ case VTCFG_R_QVEC:
+ assert(size == 2);
+ value = sc->msix_table_idx_req;
+ break;
+ case VTBLK_R_CFG ... VTBLK_R_CFG_END:
+ assert(size + offset <= (VTBLK_R_CFG_END + 1));
+ ptr = (uint8_t *)&sc->vbsc_cfg + offset - VTBLK_R_CFG;
+ if (size == 1) {
+ value = *(uint8_t *) ptr;
+ } else if (size == 2) {
+ value = *(uint16_t *) ptr;
+ } else {
+ value = *(uint32_t *) ptr;
+ }
+ break;
+ default:
+ DPRINTF(("vtblk: unknown i/o read offset %ld\n\r", offset));
+ value = 0;
+ break;
+ }
+
+ return (value);
+}
+
+struct pci_devemu pci_de_vblk = {
+ .pe_emu = "virtio-blk",
+ .pe_init = pci_vtblk_init,
+ .pe_barwrite = pci_vtblk_write,
+ .pe_barread = pci_vtblk_read
+};
+PCI_EMUL_SET(pci_de_vblk);
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
new file mode 100644
index 0000000..327ebf7
--- /dev/null
+++ b/usr.sbin/bhyve/pci_virtio_net.c
@@ -0,0 +1,886 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/linker_set.h>
+#include <sys/select.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <assert.h>
+#include <md5.h>
+#include <pthread.h>
+
+#include "bhyverun.h"
+#include "pci_emul.h"
+#include "mevent.h"
+#include "virtio.h"
+
+#define VTNET_RINGSZ 256
+
+#define VTNET_MAXSEGS 32
+
+/*
+ * PCI config-space register offsets
+ */
+#define VTNET_R_CFG0 24
+#define VTNET_R_CFG1 25
+#define VTNET_R_CFG2 26
+#define VTNET_R_CFG3 27
+#define VTNET_R_CFG4 28
+#define VTNET_R_CFG5 29
+#define VTNET_R_CFG6 30
+#define VTNET_R_CFG7 31
+#define VTNET_R_MAX 31
+
+#define VTNET_REGSZ VTNET_R_MAX+1
+
+/*
+ * Host capabilities
+ */
+#define VTNET_S_HOSTCAPS \
+ ( 0x00000020 | /* host supplies MAC */ \
+ 0x00008000 | /* host can merge Rx buffers */ \
+ 0x00010000 ) /* config status available */
+
+/*
+ * Queue definitions.
+ */
+#define VTNET_RXQ 0
+#define VTNET_TXQ 1
+#define VTNET_CTLQ 2
+
+#define VTNET_MAXQ 3
+
+static int use_msix = 1;
+
+struct vring_hqueue {
+ /* Internal state */
+ uint16_t hq_size;
+ uint16_t hq_cur_aidx; /* trails behind 'avail_idx' */
+
+ /* Host-context pointers to the queue */
+ struct virtio_desc *hq_dtable;
+ uint16_t *hq_avail_flags;
+ uint16_t *hq_avail_idx; /* monotonically increasing */
+ uint16_t *hq_avail_ring;
+
+ uint16_t *hq_used_flags;
+ uint16_t *hq_used_idx; /* monotonically increasing */
+ struct virtio_used *hq_used_ring;
+};
+
+/*
+ * Fixed network header size
+ */
+struct virtio_net_rxhdr {
+ uint8_t vrh_flags;
+ uint8_t vrh_gso_type;
+ uint16_t vrh_hdr_len;
+ uint16_t vrh_gso_size;
+ uint16_t vrh_csum_start;
+ uint16_t vrh_csum_offset;
+ uint16_t vrh_bufs;
+} __packed;
+
+/*
+ * Debug printf
+ */
+static int pci_vtnet_debug;
+#define DPRINTF(params) if (pci_vtnet_debug) printf params
+#define WPRINTF(params) printf params
+
+/*
+ * Per-device softc
+ */
+struct pci_vtnet_softc {
+ struct pci_devinst *vsc_pi;
+ pthread_mutex_t vsc_mtx;
+ struct mevent *vsc_mevp;
+
+ int vsc_curq;
+ int vsc_status;
+ int vsc_isr;
+ int vsc_tapfd;
+ int vsc_rx_ready;
+ int vsc_rxpend;
+
+ uint32_t vsc_features;
+ uint8_t vsc_macaddr[6];
+
+ uint64_t vsc_pfn[VTNET_MAXQ];
+ struct vring_hqueue vsc_hq[VTNET_MAXQ];
+ uint16_t vsc_msix_table_idx[VTNET_MAXQ];
+};
+
+/*
+ * Return the size of IO BAR that maps virtio header and device specific
+ * region. The size would vary depending on whether MSI-X is enabled or
+ * not.
+ */
+static uint64_t
+pci_vtnet_iosize(struct pci_devinst *pi)
+{
+ if (pci_msix_enabled(pi))
+ return (VTNET_REGSZ);
+ else
+ return (VTNET_REGSZ - (VTCFG_R_CFG1 - VTCFG_R_MSIX));
+}
+
+/*
+ * Return the number of available descriptors in the vring taking care
+ * of the 16-bit index wraparound.
+ */
+static int
+hq_num_avail(struct vring_hqueue *hq)
+{
+ int ndesc;
+
+ if (*hq->hq_avail_idx >= hq->hq_cur_aidx)
+ ndesc = *hq->hq_avail_idx - hq->hq_cur_aidx;
+ else
+ ndesc = UINT16_MAX - hq->hq_cur_aidx + *hq->hq_avail_idx + 1;
+
+ assert(ndesc >= 0 && ndesc <= hq->hq_size);
+
+ return (ndesc);
+}
+
+static uint16_t
+pci_vtnet_qsize(int qnum)
+{
+ /* XXX no ctl queue currently */
+ if (qnum == VTNET_CTLQ) {
+ return (0);
+ }
+
+ /* XXX fixed currently. Maybe different for tx/rx/ctl */
+ return (VTNET_RINGSZ);
+}
+
+static void
+pci_vtnet_ring_reset(struct pci_vtnet_softc *sc, int ring)
+{
+ struct vring_hqueue *hq;
+
+ assert(ring < VTNET_MAXQ);
+
+ hq = &sc->vsc_hq[ring];
+
+ /*
+ * Reset all soft state
+ */
+ hq->hq_cur_aidx = 0;
+}
+
+static void
+pci_vtnet_update_status(struct pci_vtnet_softc *sc, uint32_t value)
+{
+
+ if (value == 0) {
+ DPRINTF(("vtnet: device reset requested !\n"));
+ pci_vtnet_ring_reset(sc, VTNET_RXQ);
+ pci_vtnet_ring_reset(sc, VTNET_TXQ);
+ sc->vsc_rx_ready = 0;
+ }
+
+ sc->vsc_status = value;
+}
+
+/*
+ * Called to send a buffer chain out to the tap device
+ */
+static void
+pci_vtnet_tap_tx(struct pci_vtnet_softc *sc, struct iovec *iov, int iovcnt,
+ int len)
+{
+ char pad[60];
+
+ if (sc->vsc_tapfd == -1)
+ return;
+
+ /*
+ * If the length is < 60, pad out to that and add the
+ * extra zero'd segment to the iov. It is guaranteed that
+ * there is always an extra iov available by the caller.
+ */
+ if (len < 60) {
+ memset(pad, 0, 60 - len);
+ iov[iovcnt].iov_base = pad;
+ iov[iovcnt].iov_len = 60 - len;
+ iovcnt++;
+ }
+ (void) writev(sc->vsc_tapfd, iov, iovcnt);
+}
+
+/*
+ * Called when there is read activity on the tap file descriptor.
+ * Each buffer posted by the guest is assumed to be able to contain
+ * an entire ethernet frame + rx header.
+ * MP note: the dummybuf is only used for discarding frames, so there
+ * is no need for it to be per-vtnet or locked.
+ */
+static uint8_t dummybuf[2048];
+
+static void
+pci_vtnet_tap_rx(struct pci_vtnet_softc *sc)
+{
+ struct virtio_desc *vd;
+ struct virtio_used *vu;
+ struct vring_hqueue *hq;
+ struct virtio_net_rxhdr *vrx;
+ uint8_t *buf;
+ int i;
+ int len;
+ int ndescs;
+ int didx, uidx, aidx; /* descriptor, avail and used index */
+
+ /*
+ * Should never be called without a valid tap fd
+ */
+ assert(sc->vsc_tapfd != -1);
+
+ /*
+ * But, will be called when the rx ring hasn't yet
+ * been set up.
+ */
+ if (sc->vsc_rx_ready == 0) {
+ /*
+ * Drop the packet and try later.
+ */
+ (void) read(sc->vsc_tapfd, dummybuf, sizeof(dummybuf));
+ return;
+ }
+
+ /*
+ * Calculate the number of available rx buffers
+ */
+ hq = &sc->vsc_hq[VTNET_RXQ];
+
+ ndescs = hq_num_avail(hq);
+
+ if (ndescs == 0) {
+ /*
+ * Need to wait for host notification to read
+ */
+ if (sc->vsc_rxpend == 0) {
+ WPRINTF(("vtnet: no rx descriptors !\n"));
+ sc->vsc_rxpend = 1;
+ }
+
+ /*
+ * Drop the packet and try later
+ */
+ (void) read(sc->vsc_tapfd, dummybuf, sizeof(dummybuf));
+ return;
+ }
+
+ aidx = hq->hq_cur_aidx;
+ uidx = *hq->hq_used_idx;
+ for (i = 0; i < ndescs; i++) {
+ /*
+ * 'aidx' indexes into the an array of descriptor indexes
+ */
+ didx = hq->hq_avail_ring[aidx % hq->hq_size];
+ assert(didx >= 0 && didx < hq->hq_size);
+
+ vd = &hq->hq_dtable[didx];
+
+ /*
+ * Get a pointer to the rx header, and use the
+ * data immediately following it for the packet buffer.
+ */
+ vrx = (struct virtio_net_rxhdr *)paddr_guest2host(vd->vd_addr);
+ buf = (uint8_t *)(vrx + 1);
+
+ len = read(sc->vsc_tapfd, buf,
+ vd->vd_len - sizeof(struct virtio_net_rxhdr));
+
+ if (len < 0 && errno == EWOULDBLOCK) {
+ break;
+ }
+
+ /*
+ * The only valid field in the rx packet header is the
+ * number of buffers, which is always 1 without TSO
+ * support.
+ */
+ memset(vrx, 0, sizeof(struct virtio_net_rxhdr));
+ vrx->vrh_bufs = 1;
+
+ /*
+ * Write this descriptor into the used ring
+ */
+ vu = &hq->hq_used_ring[uidx % hq->hq_size];
+ vu->vu_idx = didx;
+ vu->vu_tlen = len + sizeof(struct virtio_net_rxhdr);
+ uidx++;
+ aidx++;
+ }
+
+ /*
+ * Update the used pointer, and signal an interrupt if allowed
+ */
+ *hq->hq_used_idx = uidx;
+ hq->hq_cur_aidx = aidx;
+
+ if ((*hq->hq_avail_flags & VRING_AVAIL_F_NO_INTERRUPT) == 0) {
+ if (use_msix) {
+ pci_generate_msix(sc->vsc_pi,
+ sc->vsc_msix_table_idx[VTNET_RXQ]);
+ } else {
+ sc->vsc_isr |= 1;
+ pci_generate_msi(sc->vsc_pi, 0);
+ }
+ }
+}
+
+static void
+pci_vtnet_tap_callback(int fd, enum ev_type type, void *param)
+{
+ struct pci_vtnet_softc *sc = param;
+
+ pthread_mutex_lock(&sc->vsc_mtx);
+ pci_vtnet_tap_rx(sc);
+ pthread_mutex_unlock(&sc->vsc_mtx);
+
+}
+
+static void
+pci_vtnet_ping_rxq(struct pci_vtnet_softc *sc)
+{
+ /*
+ * A qnotify means that the rx process can now begin
+ */
+ if (sc->vsc_rx_ready == 0) {
+ sc->vsc_rx_ready = 1;
+ }
+
+ /*
+ * If the rx queue was empty, attempt to receive a
+ * packet that was previously blocked due to no rx bufs
+ * available
+ */
+ if (sc->vsc_rxpend) {
+ WPRINTF(("vtnet: rx resumed\n\r"));
+ sc->vsc_rxpend = 0;
+ pci_vtnet_tap_rx(sc);
+ }
+}
+
+static void
+pci_vtnet_proctx(struct pci_vtnet_softc *sc, struct vring_hqueue *hq)
+{
+ struct iovec iov[VTNET_MAXSEGS + 1];
+ struct virtio_desc *vd;
+ struct virtio_used *vu;
+ int i;
+ int plen;
+ int tlen;
+ int uidx, aidx, didx;
+
+ uidx = *hq->hq_used_idx;
+ aidx = hq->hq_cur_aidx;
+ didx = hq->hq_avail_ring[aidx % hq->hq_size];
+ assert(didx >= 0 && didx < hq->hq_size);
+
+ vd = &hq->hq_dtable[didx];
+
+ /*
+ * Run through the chain of descriptors, ignoring the
+ * first header descriptor. However, include the header
+ * length in the total length that will be put into the
+ * used queue.
+ */
+ tlen = vd->vd_len;
+ vd = &hq->hq_dtable[vd->vd_next];
+
+ for (i = 0, plen = 0;
+ i < VTNET_MAXSEGS;
+ i++, vd = &hq->hq_dtable[vd->vd_next]) {
+ iov[i].iov_base = paddr_guest2host(vd->vd_addr);
+ iov[i].iov_len = vd->vd_len;
+ plen += vd->vd_len;
+ tlen += vd->vd_len;
+
+ if ((vd->vd_flags & VRING_DESC_F_NEXT) == 0)
+ break;
+ }
+ assert(i < VTNET_MAXSEGS);
+
+ DPRINTF(("virtio: packet send, %d bytes, %d segs\n\r", plen, i + 1));
+ pci_vtnet_tap_tx(sc, iov, i + 1, plen);
+
+ /*
+ * Return this chain back to the host
+ */
+ vu = &hq->hq_used_ring[uidx % hq->hq_size];
+ vu->vu_idx = didx;
+ vu->vu_tlen = tlen;
+ hq->hq_cur_aidx = aidx + 1;
+ *hq->hq_used_idx = uidx + 1;
+
+ /*
+ * Generate an interrupt if able
+ */
+ if ((*hq->hq_avail_flags & VRING_AVAIL_F_NO_INTERRUPT) == 0) {
+ if (use_msix) {
+ pci_generate_msix(sc->vsc_pi,
+ sc->vsc_msix_table_idx[VTNET_TXQ]);
+ } else {
+ sc->vsc_isr |= 1;
+ pci_generate_msi(sc->vsc_pi, 0);
+ }
+ }
+}
+
+static void
+pci_vtnet_ping_txq(struct pci_vtnet_softc *sc)
+{
+ struct vring_hqueue *hq = &sc->vsc_hq[VTNET_TXQ];
+ int i;
+ int ndescs;
+
+ /*
+ * Calculate number of ring entries to process
+ */
+ ndescs = hq_num_avail(hq);
+
+ if (ndescs == 0)
+ return;
+
+ /*
+ * Run through all the entries, placing them into iovecs and
+ * sending when an end-of-packet is found
+ */
+ for (i = 0; i < ndescs; i++)
+ pci_vtnet_proctx(sc, hq);
+}
+
+static void
+pci_vtnet_ping_ctlq(struct pci_vtnet_softc *sc)
+{
+
+ DPRINTF(("vtnet: control qnotify!\n\r"));
+}
+
+static void
+pci_vtnet_ring_init(struct pci_vtnet_softc *sc, uint64_t pfn)
+{
+ struct vring_hqueue *hq;
+ int qnum = sc->vsc_curq;
+
+ assert(qnum < VTNET_MAXQ);
+
+ sc->vsc_pfn[qnum] = pfn << VRING_PFN;
+
+ /*
+ * Set up host pointers to the various parts of the
+ * queue
+ */
+ hq = &sc->vsc_hq[qnum];
+ hq->hq_size = pci_vtnet_qsize(qnum);
+
+ hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN);
+ hq->hq_avail_flags = (uint16_t *)(hq->hq_dtable + hq->hq_size);
+ hq->hq_avail_idx = hq->hq_avail_flags + 1;
+ hq->hq_avail_ring = hq->hq_avail_flags + 2;
+ hq->hq_used_flags = (uint16_t *)roundup2((uintptr_t)hq->hq_avail_ring,
+ VRING_ALIGN);
+ hq->hq_used_idx = hq->hq_used_flags + 1;
+ hq->hq_used_ring = (struct virtio_used *)(hq->hq_used_flags + 2);
+
+ /*
+ * Initialize queue indexes
+ */
+ hq->hq_cur_aidx = 0;
+}
+
+static int
+pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ MD5_CTX mdctx;
+ unsigned char digest[16];
+ char nstr[80];
+ struct pci_vtnet_softc *sc;
+ const char *env_msi;
+
+ /*
+ * Access to guest memory is required. Fail if
+ * memory not mapped
+ */
+ if (paddr_guest2host(0) == NULL)
+ return (1);
+
+ sc = malloc(sizeof(struct pci_vtnet_softc));
+ memset(sc, 0, sizeof(struct pci_vtnet_softc));
+
+ pi->pi_arg = sc;
+ sc->vsc_pi = pi;
+
+ pthread_mutex_init(&sc->vsc_mtx, NULL);
+
+ /*
+ * Use MSI if set by user
+ */
+ if ((env_msi = getenv("BHYVE_USE_MSI")) != NULL) {
+ if (strcasecmp(env_msi, "yes") == 0)
+ use_msix = 0;
+ }
+
+ /*
+ * Attempt to open the tap device
+ */
+ sc->vsc_tapfd = -1;
+ if (opts != NULL) {
+ char tbuf[80];
+
+ strcpy(tbuf, "/dev/");
+ strlcat(tbuf, opts, sizeof(tbuf));
+
+ sc->vsc_tapfd = open(tbuf, O_RDWR);
+ if (sc->vsc_tapfd == -1) {
+ WPRINTF(("open of tap device %s failed\n", tbuf));
+ } else {
+ /*
+ * Set non-blocking and register for read
+ * notifications with the event loop
+ */
+ int opt = 1;
+ if (ioctl(sc->vsc_tapfd, FIONBIO, &opt) < 0) {
+ WPRINTF(("tap device O_NONBLOCK failed\n"));
+ close(sc->vsc_tapfd);
+ sc->vsc_tapfd = -1;
+ }
+
+ sc->vsc_mevp = mevent_add(sc->vsc_tapfd,
+ EVF_READ,
+ pci_vtnet_tap_callback,
+ sc);
+ if (sc->vsc_mevp == NULL) {
+ WPRINTF(("Could not register event\n"));
+ close(sc->vsc_tapfd);
+ sc->vsc_tapfd = -1;
+ }
+ }
+ }
+
+ /*
+ * The MAC address is the standard NetApp OUI of 00-a0-98,
+ * followed by an MD5 of the vm name. The slot/func number is
+ * prepended to this for slots other than 1:0, so that
+ * a bootloader can netboot from the equivalent of slot 1.
+ */
+ if (pi->pi_slot == 1 && pi->pi_func == 0) {
+ strncpy(nstr, vmname, sizeof(nstr));
+ } else {
+ snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot,
+ pi->pi_func, vmname);
+ }
+
+ MD5Init(&mdctx);
+ MD5Update(&mdctx, nstr, strlen(nstr));
+ MD5Final(digest, &mdctx);
+
+ sc->vsc_macaddr[0] = 0x00;
+ sc->vsc_macaddr[1] = 0xa0;
+ sc->vsc_macaddr[2] = 0x98;
+ sc->vsc_macaddr[3] = digest[0];
+ sc->vsc_macaddr[4] = digest[1];
+ sc->vsc_macaddr[5] = digest[2];
+
+ /* initialize config space */
+ pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_NET);
+ pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
+ pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK);
+ pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_NET);
+
+ if (use_msix) {
+ /* MSI-X support */
+ int i;
+
+ for (i = 0; i < VTNET_MAXQ; i++)
+ sc->vsc_msix_table_idx[i] = VIRTIO_MSI_NO_VECTOR;
+
+ /*
+ * BAR 1 used to map MSI-X table and PBA
+ */
+ if (pci_emul_add_msixcap(pi, VTNET_MAXQ, 1))
+ return (1);
+ } else {
+ /* MSI support */
+ pci_emul_add_msicap(pi, 1);
+ }
+
+ pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VTNET_REGSZ);
+
+ return (0);
+}
+
+/*
+ * Function pointer array to handle queue notifications
+ */
+static void (*pci_vtnet_qnotify[VTNET_MAXQ])(struct pci_vtnet_softc *) = {
+ pci_vtnet_ping_rxq,
+ pci_vtnet_ping_txq,
+ pci_vtnet_ping_ctlq
+};
+
+static uint64_t
+vtnet_adjust_offset(struct pci_devinst *pi, uint64_t offset)
+{
+ /*
+ * Device specific offsets used by guest would change based on
+ * whether MSI-X capability is enabled or not
+ */
+ if (!pci_msix_enabled(pi)) {
+ if (offset >= VTCFG_R_MSIX)
+ return (offset + (VTCFG_R_CFG1 - VTCFG_R_MSIX));
+ }
+
+ return (offset);
+}
+
+static void
+pci_vtnet_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size, uint64_t value)
+{
+ struct pci_vtnet_softc *sc = pi->pi_arg;
+ void *ptr;
+
+ if (use_msix) {
+ if (baridx == pci_msix_table_bar(pi) ||
+ baridx == pci_msix_pba_bar(pi)) {
+ pci_emul_msix_twrite(pi, offset, size, value);
+ return;
+ }
+ }
+
+ assert(baridx == 0);
+
+ if (offset + size > pci_vtnet_iosize(pi)) {
+ DPRINTF(("vtnet_write: 2big, offset %ld size %d\n",
+ offset, size));
+ return;
+ }
+
+ pthread_mutex_lock(&sc->vsc_mtx);
+
+ offset = vtnet_adjust_offset(pi, offset);
+
+ switch (offset) {
+ case VTCFG_R_GUESTCAP:
+ assert(size == 4);
+ sc->vsc_features = value & VTNET_S_HOSTCAPS;
+ break;
+ case VTCFG_R_PFN:
+ assert(size == 4);
+ pci_vtnet_ring_init(sc, value);
+ break;
+ case VTCFG_R_QSEL:
+ assert(size == 2);
+ assert(value < VTNET_MAXQ);
+ sc->vsc_curq = value;
+ break;
+ case VTCFG_R_QNOTIFY:
+ assert(size == 2);
+ assert(value < VTNET_MAXQ);
+ (*pci_vtnet_qnotify[value])(sc);
+ break;
+ case VTCFG_R_STATUS:
+ assert(size == 1);
+ pci_vtnet_update_status(sc, value);
+ break;
+ case VTCFG_R_CFGVEC:
+ assert(size == 2);
+ sc->vsc_msix_table_idx[VTNET_CTLQ] = value;
+ break;
+ case VTCFG_R_QVEC:
+ assert(size == 2);
+ assert(sc->vsc_curq != VTNET_CTLQ);
+ sc->vsc_msix_table_idx[sc->vsc_curq] = value;
+ break;
+ case VTNET_R_CFG0:
+ case VTNET_R_CFG1:
+ case VTNET_R_CFG2:
+ case VTNET_R_CFG3:
+ case VTNET_R_CFG4:
+ case VTNET_R_CFG5:
+ assert((size + offset) <= (VTNET_R_CFG5 + 1));
+ ptr = &sc->vsc_macaddr[offset - VTNET_R_CFG0];
+ /*
+ * The driver is allowed to change the MAC address
+ */
+ sc->vsc_macaddr[offset - VTNET_R_CFG0] = value;
+ if (size == 1) {
+ *(uint8_t *) ptr = value;
+ } else if (size == 2) {
+ *(uint16_t *) ptr = value;
+ } else {
+ *(uint32_t *) ptr = value;
+ }
+ break;
+ case VTCFG_R_HOSTCAP:
+ case VTCFG_R_QNUM:
+ case VTCFG_R_ISR:
+ case VTNET_R_CFG6:
+ case VTNET_R_CFG7:
+ DPRINTF(("vtnet: write to readonly reg %ld\n\r", offset));
+ break;
+ default:
+ DPRINTF(("vtnet: unknown i/o write offset %ld\n\r", offset));
+ value = 0;
+ break;
+ }
+
+ pthread_mutex_unlock(&sc->vsc_mtx);
+}
+
+uint64_t
+pci_vtnet_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size)
+{
+ struct pci_vtnet_softc *sc = pi->pi_arg;
+ void *ptr;
+ uint64_t value;
+
+ if (use_msix) {
+ if (baridx == pci_msix_table_bar(pi) ||
+ baridx == pci_msix_pba_bar(pi)) {
+ return (pci_emul_msix_tread(pi, offset, size));
+ }
+ }
+
+ assert(baridx == 0);
+
+ if (offset + size > pci_vtnet_iosize(pi)) {
+ DPRINTF(("vtnet_read: 2big, offset %ld size %d\n",
+ offset, size));
+ return (0);
+ }
+
+ pthread_mutex_lock(&sc->vsc_mtx);
+
+ offset = vtnet_adjust_offset(pi, offset);
+
+ switch (offset) {
+ case VTCFG_R_HOSTCAP:
+ assert(size == 4);
+ value = VTNET_S_HOSTCAPS;
+ break;
+ case VTCFG_R_GUESTCAP:
+ assert(size == 4);
+ value = sc->vsc_features; /* XXX never read ? */
+ break;
+ case VTCFG_R_PFN:
+ assert(size == 4);
+ value = sc->vsc_pfn[sc->vsc_curq] >> VRING_PFN;
+ break;
+ case VTCFG_R_QNUM:
+ assert(size == 2);
+ value = pci_vtnet_qsize(sc->vsc_curq);
+ break;
+ case VTCFG_R_QSEL:
+ assert(size == 2);
+ value = sc->vsc_curq; /* XXX never read ? */
+ break;
+ case VTCFG_R_QNOTIFY:
+ assert(size == 2);
+ value = sc->vsc_curq; /* XXX never read ? */
+ break;
+ case VTCFG_R_STATUS:
+ assert(size == 1);
+ value = sc->vsc_status;
+ break;
+ case VTCFG_R_ISR:
+ assert(size == 1);
+ value = sc->vsc_isr;
+ sc->vsc_isr = 0; /* a read clears this flag */
+ break;
+ case VTCFG_R_CFGVEC:
+ assert(size == 2);
+ value = sc->vsc_msix_table_idx[VTNET_CTLQ];
+ break;
+ case VTCFG_R_QVEC:
+ assert(size == 2);
+ assert(sc->vsc_curq != VTNET_CTLQ);
+ value = sc->vsc_msix_table_idx[sc->vsc_curq];
+ break;
+ case VTNET_R_CFG0:
+ case VTNET_R_CFG1:
+ case VTNET_R_CFG2:
+ case VTNET_R_CFG3:
+ case VTNET_R_CFG4:
+ case VTNET_R_CFG5:
+ assert((size + offset) <= (VTNET_R_CFG5 + 1));
+ ptr = &sc->vsc_macaddr[offset - VTNET_R_CFG0];
+ if (size == 1) {
+ value = *(uint8_t *) ptr;
+ } else if (size == 2) {
+ value = *(uint16_t *) ptr;
+ } else {
+ value = *(uint32_t *) ptr;
+ }
+ break;
+ case VTNET_R_CFG6:
+ assert(size != 4);
+ value = 0x01; /* XXX link always up */
+ break;
+ case VTNET_R_CFG7:
+ assert(size == 1);
+ value = 0; /* XXX link status in LSB */
+ break;
+ default:
+ DPRINTF(("vtnet: unknown i/o read offset %ld\n\r", offset));
+ value = 0;
+ break;
+ }
+
+ pthread_mutex_unlock(&sc->vsc_mtx);
+
+ return (value);
+}
+
+struct pci_devemu pci_de_vnet = {
+ .pe_emu = "virtio-net",
+ .pe_init = pci_vtnet_init,
+ .pe_barwrite = pci_vtnet_write,
+ .pe_barread = pci_vtnet_read
+};
+PCI_EMUL_SET(pci_de_vnet);
diff --git a/usr.sbin/bhyve/pit_8254.c b/usr.sbin/bhyve/pit_8254.c
new file mode 100644
index 0000000..c96596a
--- /dev/null
+++ b/usr.sbin/bhyve/pit_8254.c
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/time.h>
+
+#include <machine/clock.h>
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "bhyverun.h"
+#include "inout.h"
+#include "pit_8254.h"
+
+#define TIMER_SEL_MASK 0xc0
+#define TIMER_RW_MASK 0x30
+#define TIMER_MODE_MASK 0x0f
+#define TIMER_SEL_READBACK 0xc0
+
+#define TIMER_DIV(freq, hz) (((freq) + (hz) / 2) / (hz))
+
+#define PIT_8254_FREQ 1193182
+static const int nsecs_per_tick = 1000000000 / PIT_8254_FREQ;
+
+struct counter {
+ struct timeval tv; /* uptime when counter was loaded */
+ uint16_t initial; /* initial counter value */
+ uint8_t cr[2];
+ uint8_t ol[2];
+ int crbyte;
+ int olbyte;
+};
+
+static void
+timevalfix(struct timeval *t1)
+{
+
+ if (t1->tv_usec < 0) {
+ t1->tv_sec--;
+ t1->tv_usec += 1000000;
+ }
+ if (t1->tv_usec >= 1000000) {
+ t1->tv_sec++;
+ t1->tv_usec -= 1000000;
+ }
+}
+
+static void
+timevalsub(struct timeval *t1, const struct timeval *t2)
+{
+
+ t1->tv_sec -= t2->tv_sec;
+ t1->tv_usec -= t2->tv_usec;
+ timevalfix(t1);
+}
+
+static void
+latch(struct counter *c)
+{
+ struct timeval tv2;
+ uint16_t lval;
+ uint64_t delta_nsecs, delta_ticks;
+
+ /* cannot latch a new value until the old one has been consumed */
+ if (c->olbyte != 0)
+ return;
+
+ if (c->initial == 0 || c->initial == 1) {
+ /*
+ * XXX the program that runs the VM can be stopped and
+ * restarted at any time. This means that state that was
+ * created by the guest is destroyed between invocations
+ * of the program.
+ *
+ * If the counter's initial value is not programmed we
+ * assume a value that would be set to generate 'guest_hz'
+ * interrupts per second.
+ */
+ c->initial = TIMER_DIV(PIT_8254_FREQ, guest_hz);
+ gettimeofday(&c->tv, NULL);
+ }
+
+ (void)gettimeofday(&tv2, NULL);
+ timevalsub(&tv2, &c->tv);
+ delta_nsecs = tv2.tv_sec * 1000000000 + tv2.tv_usec * 1000;
+ delta_ticks = delta_nsecs / nsecs_per_tick;
+
+ lval = c->initial - delta_ticks % c->initial;
+ c->olbyte = 2;
+ c->ol[1] = lval; /* LSB */
+ c->ol[0] = lval >> 8; /* MSB */
+}
+
+static int
+pit_8254_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ int sel, rw, mode;
+ uint8_t val;
+ struct counter *c;
+
+ static struct counter counter[3];
+
+ if (bytes != 1)
+ return (-1);
+
+ val = *eax;
+
+ if (port == TIMER_MODE) {
+ assert(in == 0);
+ sel = val & TIMER_SEL_MASK;
+ rw = val & TIMER_RW_MASK;
+ mode = val & TIMER_MODE_MASK;
+
+ if (sel == TIMER_SEL_READBACK)
+ return (-1);
+ if (rw != TIMER_LATCH && rw != TIMER_16BIT)
+ return (-1);
+
+ if (rw != TIMER_LATCH) {
+ /*
+ * Counter mode is not affected when issuing a
+ * latch command.
+ */
+ if (mode != TIMER_RATEGEN && mode != TIMER_SQWAVE)
+ return (-1);
+ }
+
+ c = &counter[sel >> 6];
+ if (rw == TIMER_LATCH)
+ latch(c);
+ else
+ c->olbyte = 0; /* reset latch after reprogramming */
+
+ return (0);
+ }
+
+ /* counter ports */
+ assert(port >= TIMER_CNTR0 && port <= TIMER_CNTR2);
+ c = &counter[port - TIMER_CNTR0];
+
+ if (in) {
+ /*
+ * XXX
+ * The spec says that once the output latch is completely
+ * read it should revert to "following" the counter. We don't
+ * do this because it is hard and any reasonable OS should
+ * always latch the counter before trying to read it.
+ */
+ if (c->olbyte == 0)
+ c->olbyte = 2;
+ *eax = c->ol[--c->olbyte];
+ } else {
+ c->cr[c->crbyte++] = *eax;
+ if (c->crbyte == 2) {
+ c->crbyte = 0;
+ c->initial = c->cr[0] | (uint16_t)c->cr[1] << 8;
+ if (c->initial == 0)
+ c->initial = 0xffff;
+ gettimeofday(&c->tv, NULL);
+ }
+ }
+
+ return (0);
+}
+
+INOUT_PORT(8254, TIMER_MODE, IOPORT_F_OUT, pit_8254_handler);
+INOUT_PORT(8254, TIMER_CNTR0, IOPORT_F_INOUT, pit_8254_handler);
+INOUT_PORT(8254, TIMER_CNTR1, IOPORT_F_INOUT, pit_8254_handler);
+INOUT_PORT(8254, TIMER_CNTR2, IOPORT_F_INOUT, pit_8254_handler);
diff --git a/usr.sbin/bhyve/pit_8254.h b/usr.sbin/bhyve/pit_8254.h
new file mode 100644
index 0000000..61bd15d
--- /dev/null
+++ b/usr.sbin/bhyve/pit_8254.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _PIT_8254_H_
+#define _PIT_8254_H_
+
+/*
+ * Borrowed from amd64/include/timerreg.h because in that file it is
+ * conditionally compiled for #ifdef _KERNEL only.
+ */
+
+#include <dev/ic/i8253reg.h>
+
+#define IO_TIMER1 0x40 /* 8253 Timer #1 */
+#define TIMER_CNTR0 (IO_TIMER1 + TIMER_REG_CNTR0)
+#define TIMER_CNTR1 (IO_TIMER1 + TIMER_REG_CNTR1)
+#define TIMER_CNTR2 (IO_TIMER1 + TIMER_REG_CNTR2)
+#define TIMER_MODE (IO_TIMER1 + TIMER_REG_MODE)
+
+#endif /* _PIT_8254_H_ */
diff --git a/usr.sbin/bhyve/pmtmr.c b/usr.sbin/bhyve/pmtmr.c
new file mode 100644
index 0000000..b85b0a7
--- /dev/null
+++ b/usr.sbin/bhyve/pmtmr.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <machine/cpufunc.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <assert.h>
+#include <pthread.h>
+
+#include "inout.h"
+
+/*
+ * The ACPI Power Management timer is a free-running 24- or 32-bit
+ * timer with a frequency of 3.579545MHz
+ *
+ * This implementation will be 32-bits
+ */
+
+#define IO_PMTMR 0x408 /* 4-byte i/o port for the timer */
+
+#define PMTMR_FREQ 3579545 /* 3.579545MHz */
+
+static pthread_mutex_t pmtmr_mtx;
+static uint64_t pmtmr_tscf;
+static uint64_t pmtmr_old;
+static uint64_t pmtmr_tsc_old;
+
+static uint32_t
+pmtmr_val(void)
+{
+ uint64_t pmtmr_tsc_new;
+ uint64_t pmtmr_new;
+ static int inited = 0;
+
+ if (!inited) {
+ size_t len;
+
+ inited = 1;
+ pthread_mutex_init(&pmtmr_mtx, NULL);
+ len = sizeof(pmtmr_tscf);
+ sysctlbyname("machdep.tsc_freq", &pmtmr_tscf, &len,
+ NULL, 0);
+ pmtmr_tsc_old = rdtsc();
+ pmtmr_old = pmtmr_tsc_old / pmtmr_tscf * PMTMR_FREQ;
+ }
+
+ pthread_mutex_lock(&pmtmr_mtx);
+ pmtmr_tsc_new = rdtsc();
+ pmtmr_new = (pmtmr_tsc_new - pmtmr_tsc_old) * PMTMR_FREQ / pmtmr_tscf +
+ pmtmr_old;
+ pmtmr_old = pmtmr_new;
+ pmtmr_tsc_old = pmtmr_tsc_new;
+ pthread_mutex_unlock(&pmtmr_mtx);
+
+ return (pmtmr_new);
+}
+
+static int
+pmtmr_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ assert(in == 1);
+
+ if (bytes != 4)
+ return (-1);
+
+ *eax = pmtmr_val();
+
+ return (0);
+}
+
+INOUT_PORT(pmtmr, IO_PMTMR, IOPORT_F_IN, pmtmr_handler);
+
diff --git a/usr.sbin/bhyve/post.c b/usr.sbin/bhyve/post.c
new file mode 100644
index 0000000..092a551
--- /dev/null
+++ b/usr.sbin/bhyve/post.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <assert.h>
+
+#include "inout.h"
+
+static int
+post_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ assert(in == 1);
+
+ if (bytes != 1)
+ return (-1);
+
+ *eax = 0xff; /* return some garbage */
+ return (0);
+}
+
+INOUT_PORT(post, 0x84, IOPORT_F_IN, post_data_handler);
diff --git a/usr.sbin/bhyve/rtc.c b/usr.sbin/bhyve/rtc.c
new file mode 100644
index 0000000..df21ac8
--- /dev/null
+++ b/usr.sbin/bhyve/rtc.c
@@ -0,0 +1,284 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <assert.h>
+
+#include "inout.h"
+
+#define IO_RTC 0x70
+
+#define RTC_SEC 0x00 /* seconds */
+#define RTC_MIN 0x02
+#define RTC_HRS 0x04
+#define RTC_WDAY 0x06
+#define RTC_DAY 0x07
+#define RTC_MONTH 0x08
+#define RTC_YEAR 0x09
+#define RTC_CENTURY 0x32 /* current century */
+
+#define RTC_STATUSA 0xA
+#define RTCSA_TUP 0x80 /* time update, don't look now */
+
+#define RTC_STATUSB 0xB
+#define RTCSB_DST 0x01
+#define RTCSB_24HR 0x02
+#define RTCSB_BIN 0x04 /* 0 = BCD, 1 = Binary */
+#define RTCSB_PINTR 0x40 /* 1 = enable periodic clock interrupt */
+#define RTCSB_HALT 0x80 /* stop clock updates */
+
+#define RTC_INTR 0x0c /* status register C (R) interrupt source */
+
+#define RTC_STATUSD 0x0d /* status register D (R) Lost Power */
+#define RTCSD_PWR 0x80 /* clock power OK */
+
+#define RTC_DIAG 0x0e
+
+#define RTC_RSTCODE 0x0f
+
+#define RTC_EQUIPMENT 0x14
+
+static int addr;
+
+/* XXX initialize these to default values as they would be from BIOS */
+static uint8_t status_a, status_b, rstcode;
+
+static u_char const bin2bcd_data[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99
+};
+#define bin2bcd(bin) (bin2bcd_data[bin])
+
+#define rtcout(val) ((status_b & RTCSB_BIN) ? (val) : bin2bcd((val)))
+
+static void
+timevalfix(struct timeval *t1)
+{
+
+ if (t1->tv_usec < 0) {
+ t1->tv_sec--;
+ t1->tv_usec += 1000000;
+ }
+ if (t1->tv_usec >= 1000000) {
+ t1->tv_sec++;
+ t1->tv_usec -= 1000000;
+ }
+}
+
+static void
+timevalsub(struct timeval *t1, const struct timeval *t2)
+{
+
+ t1->tv_sec -= t2->tv_sec;
+ t1->tv_usec -= t2->tv_usec;
+ timevalfix(t1);
+}
+
+static int
+rtc_addr_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ if (bytes != 1)
+ return (-1);
+
+ if (in) {
+ /* straight read of this register will return 0xFF */
+ *eax = 0xff;
+ return (0);
+ }
+
+ switch (*eax & 0x7f) {
+ case RTC_SEC:
+ case RTC_MIN:
+ case RTC_HRS:
+ case RTC_WDAY:
+ case RTC_DAY:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ case RTC_CENTURY:
+ case RTC_STATUSA:
+ case RTC_STATUSB:
+ case RTC_INTR:
+ case RTC_STATUSD:
+ case RTC_DIAG:
+ case RTC_RSTCODE:
+ case RTC_EQUIPMENT:
+ break;
+ default:
+ return (-1);
+ }
+
+ addr = *eax & 0x7f;
+ return (0);
+}
+
+static int
+rtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ int hour;
+ time_t t;
+ struct timeval cur, delta;
+
+ static struct timeval last;
+ static struct tm tm;
+
+ if (bytes != 1)
+ return (-1);
+
+ gettimeofday(&cur, NULL);
+
+ /*
+ * Increment the cached time only once per second so we can guarantee
+ * that the guest has at least one second to read the hour:min:sec
+ * separately and still get a coherent view of the time.
+ */
+ delta = cur;
+ timevalsub(&delta, &last);
+ if (delta.tv_sec >= 1 && (status_b & RTCSB_HALT) == 0) {
+ t = cur.tv_sec;
+ localtime_r(&t, &tm);
+ last = cur;
+ }
+
+ if (in) {
+ switch (addr) {
+ case RTC_SEC:
+ *eax = rtcout(tm.tm_sec);
+ return (0);
+ case RTC_MIN:
+ *eax = rtcout(tm.tm_min);
+ return (0);
+ case RTC_HRS:
+ if (status_b & RTCSB_24HR)
+ hour = tm.tm_hour;
+ else
+ hour = (tm.tm_hour % 12) + 1;
+
+ *eax = rtcout(hour);
+
+ /*
+ * If we are representing time in the 12-hour format
+ * then set the MSB to indicate PM.
+ */
+ if ((status_b & RTCSB_24HR) == 0 && tm.tm_hour >= 12)
+ *eax |= 0x80;
+
+ return (0);
+ case RTC_WDAY:
+ *eax = rtcout(tm.tm_wday + 1);
+ return (0);
+ case RTC_DAY:
+ *eax = rtcout(tm.tm_mday);
+ return (0);
+ case RTC_MONTH:
+ *eax = rtcout(tm.tm_mon + 1);
+ return (0);
+ case RTC_YEAR:
+ *eax = rtcout(tm.tm_year % 100);
+ return (0);
+ case RTC_CENTURY:
+ *eax = rtcout(tm.tm_year / 100);
+ break;
+ case RTC_STATUSA:
+ *eax = status_a;
+ return (0);
+ case RTC_STATUSB:
+ *eax = status_b;
+ return (0);
+ case RTC_INTR:
+ *eax = 0;
+ return (0);
+ case RTC_STATUSD:
+ *eax = RTCSD_PWR;
+ return (0);
+ case RTC_DIAG:
+ *eax = 0;
+ return (0);
+ case RTC_RSTCODE:
+ *eax = rstcode;
+ return (0);
+ case RTC_EQUIPMENT:
+ *eax = 0;
+ return (0);
+ default:
+ return (-1);
+ }
+ }
+
+ switch (addr) {
+ case RTC_STATUSA:
+ status_a = *eax & ~RTCSA_TUP;
+ break;
+ case RTC_STATUSB:
+ /* XXX not implemented yet XXX */
+ if (*eax & RTCSB_PINTR)
+ return (-1);
+ status_b = *eax;
+ break;
+ case RTC_STATUSD:
+ /* ignore write */
+ break;
+ case RTC_RSTCODE:
+ rstcode = *eax;
+ break;
+ case RTC_SEC:
+ case RTC_MIN:
+ case RTC_HRS:
+ case RTC_WDAY:
+ case RTC_DAY:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ case RTC_CENTURY:
+ /*
+ * Ignore writes to the time of day registers
+ */
+ break;
+ default:
+ return (-1);
+ }
+ return (0);
+}
+
+INOUT_PORT(rtc, IO_RTC, IOPORT_F_INOUT, rtc_addr_handler);
+INOUT_PORT(rtc, IO_RTC + 1, IOPORT_F_INOUT, rtc_data_handler);
diff --git a/usr.sbin/bhyve/spinup_ap.c b/usr.sbin/bhyve/spinup_ap.c
new file mode 100644
index 0000000..2632aed
--- /dev/null
+++ b/usr.sbin/bhyve/spinup_ap.c
@@ -0,0 +1,119 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "bhyverun.h"
+#include "spinup_ap.h"
+
+static void
+spinup_ap_realmode(struct vmctx *ctx, int newcpu, uint64_t *rip)
+{
+ int vector, error;
+ uint16_t cs;
+ uint64_t desc_base;
+ uint32_t desc_limit, desc_access;
+
+ vector = *rip >> PAGE_SHIFT;
+ *rip = 0;
+
+ /*
+ * Update the %cs and %rip of the guest so that it starts
+ * executing real mode code at at 'vector << 12'.
+ */
+ error = vm_set_register(ctx, newcpu, VM_REG_GUEST_RIP, *rip);
+ assert(error == 0);
+
+ error = vm_get_desc(ctx, newcpu, VM_REG_GUEST_CS, &desc_base,
+ &desc_limit, &desc_access);
+ assert(error == 0);
+
+ desc_base = vector << PAGE_SHIFT;
+ error = vm_set_desc(ctx, newcpu, VM_REG_GUEST_CS,
+ desc_base, desc_limit, desc_access);
+ assert(error == 0);
+
+ cs = (vector << PAGE_SHIFT) >> 4;
+ error = vm_set_register(ctx, newcpu, VM_REG_GUEST_CS, cs);
+ assert(error == 0);
+}
+
+int
+spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip)
+{
+ int error;
+
+ assert(newcpu != 0);
+ assert(newcpu < guest_ncpus);
+
+ error = vcpu_reset(ctx, newcpu);
+ assert(error == 0);
+
+ /* Set up capabilities */
+ if (fbsdrun_vmexit_on_hlt()) {
+ error = vm_set_capability(ctx, newcpu, VM_CAP_HALT_EXIT, 1);
+ assert(error == 0);
+ }
+
+ if (fbsdrun_vmexit_on_pause()) {
+ error = vm_set_capability(ctx, newcpu, VM_CAP_PAUSE_EXIT, 1);
+ assert(error == 0);
+ }
+
+ if (fbsdrun_disable_x2apic())
+ error = vm_set_x2apic_state(ctx, newcpu, X2APIC_DISABLED);
+ else
+ error = vm_set_x2apic_state(ctx, newcpu, X2APIC_ENABLED);
+ assert(error == 0);
+
+ /*
+ * Enable the 'unrestricted guest' mode for 'newcpu'.
+ *
+ * Set up the processor state in power-on 16-bit mode, with the CS:IP
+ * init'd to the specified low-mem 4K page.
+ */
+ error = vm_set_capability(ctx, newcpu, VM_CAP_UNRESTRICTED_GUEST, 1);
+ assert(error == 0);
+
+ spinup_ap_realmode(ctx, newcpu, &rip);
+
+ fbsdrun_addcpu(ctx, newcpu, rip);
+
+ return (newcpu);
+}
diff --git a/usr.sbin/bhyve/spinup_ap.h b/usr.sbin/bhyve/spinup_ap.h
new file mode 100644
index 0000000..2749ee9
--- /dev/null
+++ b/usr.sbin/bhyve/spinup_ap.h
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SPINUP_AP_H_
+#define _SPINUP_AP_H_
+
+int spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip);
+
+#endif
diff --git a/usr.sbin/bhyve/uart.c b/usr.sbin/bhyve/uart.c
new file mode 100644
index 0000000..640f3bf
--- /dev/null
+++ b/usr.sbin/bhyve/uart.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <assert.h>
+
+#include "inout.h"
+
+#define COM1 0x3F8
+#define COM2 0x2F8
+
+#define REG_IIR 2
+
+static int
+com_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ assert(in);
+
+ if (bytes != 1)
+ return (-1);
+
+ /*
+ * COM port is not implemented so we return 0xFF for all registers
+ */
+ *eax = 0xFF;
+
+ return (0);
+}
+
+INOUT_PORT(uart, COM1 + REG_IIR, IOPORT_F_IN, com_handler);
+INOUT_PORT(uart, COM2 + REG_IIR, IOPORT_F_IN, com_handler);
diff --git a/usr.sbin/bhyve/virtio.h b/usr.sbin/bhyve/virtio.h
new file mode 100644
index 0000000..04ef586
--- /dev/null
+++ b/usr.sbin/bhyve/virtio.h
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VIRTIO_H_
+#define _VIRTIO_H_
+
+#define VRING_ALIGN 4096
+
+#define VRING_DESC_F_NEXT (1 << 0)
+#define VRING_DESC_F_WRITE (1 << 1)
+#define VRING_DESC_F_INDIRECT (1 << 2)
+
+#define VRING_AVAIL_F_NO_INTERRUPT 1
+#define VIRTIO_MSI_NO_VECTOR 0xFFFF
+
+struct virtio_desc {
+ uint64_t vd_addr;
+ uint32_t vd_len;
+ uint16_t vd_flags;
+ uint16_t vd_next;
+} __packed;
+
+struct virtio_used {
+ uint32_t vu_idx;
+ uint32_t vu_tlen;
+} __packed;
+
+/*
+ * PFN register shift amount
+ */
+#define VRING_PFN 12
+
+/*
+ * Virtio device types
+ */
+#define VIRTIO_TYPE_NET 1
+#define VIRTIO_TYPE_BLOCK 2
+
+/*
+ * PCI vendor/device IDs
+ */
+#define VIRTIO_VENDOR 0x1AF4
+#define VIRTIO_DEV_NET 0x1000
+#define VIRTIO_DEV_BLOCK 0x1001
+
+/*
+ * PCI config space constants
+ */
+#define VTCFG_R_HOSTCAP 0
+#define VTCFG_R_GUESTCAP 4
+#define VTCFG_R_PFN 8
+#define VTCFG_R_QNUM 12
+#define VTCFG_R_QSEL 14
+#define VTCFG_R_QNOTIFY 16
+#define VTCFG_R_STATUS 18
+#define VTCFG_R_ISR 19
+#define VTCFG_R_CFGVEC 20
+#define VTCFG_R_QVEC 22
+#define VTCFG_R_CFG0 20 /* No MSI-X */
+#define VTCFG_R_CFG1 24 /* With MSI-X */
+#define VTCFG_R_MSIX 20
+
+#endif /* _VIRTIO_H_ */
diff --git a/usr.sbin/bhyve/xmsr.c b/usr.sbin/bhyve/xmsr.c
new file mode 100644
index 0000000..9c05f02
--- /dev/null
+++ b/usr.sbin/bhyve/xmsr.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "xmsr.h"
+
+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);
+}
diff --git a/usr.sbin/bhyve/xmsr.h b/usr.sbin/bhyve/xmsr.h
new file mode 100644
index 0000000..8cebcea
--- /dev/null
+++ b/usr.sbin/bhyve/xmsr.h
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _XMSR_H_
+#define _XMSR_H_
+
+int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val);
+
+#endif
diff --git a/usr.sbin/bhyvectl/Makefile b/usr.sbin/bhyvectl/Makefile
new file mode 100644
index 0000000..9fde12c
--- /dev/null
+++ b/usr.sbin/bhyvectl/Makefile
@@ -0,0 +1,17 @@
+#
+# $FreeBSD$
+#
+
+PROG= bhyvectl
+SRCS= bhyvectl.c
+
+NO_MAN=
+
+DPADD= ${LIBVMMAPI}
+LDADD= -lvmmapi
+
+WARNS?= 3
+
+CFLAGS+= -I${.CURDIR}/../../sys/amd64/vmm
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c
new file mode 100644
index 0000000..35e1388
--- /dev/null
+++ b/usr.sbin/bhyvectl/bhyvectl.c
@@ -0,0 +1,1524 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/errno.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <libutil.h>
+#include <fcntl.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
+#include "intel/vmcs.h"
+
+#define MB (1UL << 20)
+#define GB (1UL << 30)
+
+#define REQ_ARG required_argument
+#define NO_ARG no_argument
+#define OPT_ARG optional_argument
+
+static const char *progname;
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "Usage: %s --vm=<vmname>\n"
+ " [--cpu=<vcpu_number>]\n"
+ " [--create]\n"
+ " [--destroy]\n"
+ " [--get-all]\n"
+ " [--get-stats]\n"
+ " [--set-desc-ds]\n"
+ " [--get-desc-ds]\n"
+ " [--set-desc-es]\n"
+ " [--get-desc-es]\n"
+ " [--set-desc-gs]\n"
+ " [--get-desc-gs]\n"
+ " [--set-desc-fs]\n"
+ " [--get-desc-fs]\n"
+ " [--set-desc-cs]\n"
+ " [--get-desc-cs]\n"
+ " [--set-desc-ss]\n"
+ " [--get-desc-ss]\n"
+ " [--set-desc-tr]\n"
+ " [--get-desc-tr]\n"
+ " [--set-desc-ldtr]\n"
+ " [--get-desc-ldtr]\n"
+ " [--set-desc-gdtr]\n"
+ " [--get-desc-gdtr]\n"
+ " [--set-desc-idtr]\n"
+ " [--get-desc-idtr]\n"
+ " [--run]\n"
+ " [--capname=<capname>]\n"
+ " [--getcap]\n"
+ " [--setcap=<0|1>]\n"
+ " [--desc-base=<BASE>]\n"
+ " [--desc-limit=<LIMIT>]\n"
+ " [--desc-access=<ACCESS>]\n"
+ " [--set-cr0=<CR0>]\n"
+ " [--get-cr0]\n"
+ " [--set-cr3=<CR3>]\n"
+ " [--get-cr3]\n"
+ " [--set-cr4=<CR4>]\n"
+ " [--get-cr4]\n"
+ " [--set-dr7=<DR7>]\n"
+ " [--get-dr7]\n"
+ " [--set-rsp=<RSP>]\n"
+ " [--get-rsp]\n"
+ " [--set-rip=<RIP>]\n"
+ " [--get-rip]\n"
+ " [--get-rax]\n"
+ " [--set-rax=<RAX>]\n"
+ " [--get-rbx]\n"
+ " [--get-rcx]\n"
+ " [--get-rdx]\n"
+ " [--get-rsi]\n"
+ " [--get-rdi]\n"
+ " [--get-rbp]\n"
+ " [--get-r8]\n"
+ " [--get-r9]\n"
+ " [--get-r10]\n"
+ " [--get-r11]\n"
+ " [--get-r12]\n"
+ " [--get-r13]\n"
+ " [--get-r14]\n"
+ " [--get-r15]\n"
+ " [--set-rflags=<RFLAGS>]\n"
+ " [--get-rflags]\n"
+ " [--set-cs]\n"
+ " [--get-cs]\n"
+ " [--set-ds]\n"
+ " [--get-ds]\n"
+ " [--set-es]\n"
+ " [--get-es]\n"
+ " [--set-fs]\n"
+ " [--get-fs]\n"
+ " [--set-gs]\n"
+ " [--get-gs]\n"
+ " [--set-ss]\n"
+ " [--get-ss]\n"
+ " [--get-tr]\n"
+ " [--get-ldtr]\n"
+ " [--get-vmcs-pinbased-ctls]\n"
+ " [--get-vmcs-procbased-ctls]\n"
+ " [--get-vmcs-procbased-ctls2]\n"
+ " [--get-vmcs-entry-interruption-info]\n"
+ " [--set-vmcs-entry-interruption-info=<info>]\n"
+ " [--get-vmcs-eptp]\n"
+ " [--get-vmcs-guest-physical-address\n"
+ " [--get-vmcs-guest-linear-address\n"
+ " [--set-vmcs-exception-bitmap]\n"
+ " [--get-vmcs-exception-bitmap]\n"
+ " [--get-vmcs-io-bitmap-address]\n"
+ " [--get-vmcs-tsc-offset]\n"
+ " [--get-vmcs-guest-pat]\n"
+ " [--get-vmcs-host-pat]\n"
+ " [--get-vmcs-host-cr0]\n"
+ " [--get-vmcs-host-cr3]\n"
+ " [--get-vmcs-host-cr4]\n"
+ " [--get-vmcs-host-rip]\n"
+ " [--get-vmcs-host-rsp]\n"
+ " [--get-vmcs-cr0-mask]\n"
+ " [--get-vmcs-cr0-shadow]\n"
+ " [--get-vmcs-cr4-mask]\n"
+ " [--get-vmcs-cr4-shadow]\n"
+ " [--get-vmcs-cr3-targets]\n"
+ " [--get-vmcs-apic-access-address]\n"
+ " [--get-vmcs-virtual-apic-address]\n"
+ " [--get-vmcs-tpr-threshold]\n"
+ " [--get-vmcs-msr-bitmap]\n"
+ " [--get-vmcs-msr-bitmap-address]\n"
+ " [--get-vmcs-vpid]\n"
+ " [--get-vmcs-ple-gap]\n"
+ " [--get-vmcs-ple-window]\n"
+ " [--get-vmcs-instruction-error]\n"
+ " [--get-vmcs-exit-ctls]\n"
+ " [--get-vmcs-entry-ctls]\n"
+ " [--get-vmcs-guest-sysenter]\n"
+ " [--get-vmcs-link]\n"
+ " [--get-vmcs-exit-reason]\n"
+ " [--get-vmcs-exit-qualification]\n"
+ " [--get-vmcs-exit-interruption-info]\n"
+ " [--get-vmcs-exit-interruption-error]\n"
+ " [--get-vmcs-interruptibility]\n"
+ " [--set-pinning=<host_cpuid>]\n"
+ " [--get-pinning]\n"
+ " [--set-x2apic-state=<state>]\n"
+ " [--get-x2apic-state]\n"
+ " [--set-lowmem=<memory below 4GB in units of MB>]\n"
+ " [--get-lowmem]\n"
+ " [--set-highmem=<memory above 4GB in units of MB>]\n"
+ " [--get-highmem]\n",
+ progname);
+ exit(1);
+}
+
+static int get_stats, getcap, setcap, capval;
+static const char *capname;
+static int create, destroy, get_lowmem, get_highmem;
+static uint64_t lowmem, highmem;
+static int set_cr0, get_cr0, set_cr3, get_cr3, set_cr4, get_cr4;
+static int set_efer, get_efer;
+static int set_dr7, get_dr7;
+static int set_rsp, get_rsp, set_rip, get_rip, set_rflags, get_rflags;
+static int set_rax, get_rax;
+static int get_rbx, get_rcx, get_rdx, get_rsi, get_rdi, get_rbp;
+static int get_r8, get_r9, get_r10, get_r11, get_r12, get_r13, get_r14, get_r15;
+static int set_desc_ds, get_desc_ds;
+static int set_desc_es, get_desc_es;
+static int set_desc_fs, get_desc_fs;
+static int set_desc_gs, get_desc_gs;
+static int set_desc_cs, get_desc_cs;
+static int set_desc_ss, get_desc_ss;
+static int set_desc_gdtr, get_desc_gdtr;
+static int set_desc_idtr, get_desc_idtr;
+static int set_desc_tr, get_desc_tr;
+static int set_desc_ldtr, get_desc_ldtr;
+static int set_cs, set_ds, set_es, set_fs, set_gs, set_ss, set_tr, set_ldtr;
+static int get_cs, get_ds, get_es, get_fs, get_gs, get_ss, get_tr, get_ldtr;
+static int set_pinning, get_pinning, pincpu;
+static int set_x2apic_state, get_x2apic_state;
+enum x2apic_state x2apic_state;
+static int run;
+
+/*
+ * VMCS-specific fields
+ */
+static int get_pinbased_ctls, get_procbased_ctls, get_procbased_ctls2;
+static int get_eptp, get_io_bitmap, get_tsc_offset;
+static int get_vmcs_entry_interruption_info, set_vmcs_entry_interruption_info;
+static int get_vmcs_interruptibility;
+uint32_t vmcs_entry_interruption_info;
+static int get_vmcs_gpa, get_vmcs_gla;
+static int get_exception_bitmap, set_exception_bitmap, exception_bitmap;
+static int get_cr0_mask, get_cr0_shadow;
+static int get_cr4_mask, get_cr4_shadow;
+static int get_cr3_targets;
+static int get_apic_access_addr, get_virtual_apic_addr, get_tpr_threshold;
+static int get_msr_bitmap, get_msr_bitmap_address;
+static int get_vpid, get_ple_gap, get_ple_window;
+static int get_inst_err, get_exit_ctls, get_entry_ctls;
+static int get_host_cr0, get_host_cr3, get_host_cr4;
+static int get_host_rip, get_host_rsp;
+static int get_guest_pat, get_host_pat;
+static int get_guest_sysenter, get_vmcs_link;
+static int get_vmcs_exit_reason, get_vmcs_exit_qualification;
+static int get_vmcs_exit_interruption_info, get_vmcs_exit_interruption_error;
+
+static uint64_t desc_base;
+static uint32_t desc_limit, desc_access;
+
+static int get_all;
+
+static void
+dump_vm_run_exitcode(struct vm_exit *vmexit, int vcpu)
+{
+ printf("vm exit[%d]\n", vcpu);
+ printf("\trip\t\t0x%016lx\n", vmexit->rip);
+ printf("\tinst_length\t%d\n", vmexit->inst_length);
+ switch (vmexit->exitcode) {
+ case VM_EXITCODE_INOUT:
+ printf("\treason\t\tINOUT\n");
+ printf("\tdirection\t%s\n", vmexit->u.inout.in ? "IN" : "OUT");
+ printf("\tbytes\t\t%d\n", vmexit->u.inout.bytes);
+ printf("\tflags\t\t%s%s\n",
+ vmexit->u.inout.string ? "STRING " : "",
+ vmexit->u.inout.rep ? "REP " : "");
+ printf("\tport\t\t0x%04x\n", vmexit->u.inout.port);
+ printf("\teax\t\t0x%08x\n", vmexit->u.inout.eax);
+ break;
+ case VM_EXITCODE_VMX:
+ printf("\treason\t\tVMX\n");
+ printf("\terror\t\t%d\n", vmexit->u.vmx.error);
+ printf("\texit_reason\t0x%08x (%u)\n",
+ vmexit->u.vmx.exit_reason, vmexit->u.vmx.exit_reason);
+ printf("\tqualification\t0x%016lx\n",
+ vmexit->u.vmx.exit_qualification);
+ break;
+ default:
+ printf("*** unknown vm run exitcode %d\n", vmexit->exitcode);
+ break;
+ }
+}
+
+static int
+dump_vmcs_msr_bitmap(int vcpu, u_long addr)
+{
+ int error, fd, byte, bit, readable, writeable;
+ u_int msr;
+ const char *bitmap;
+
+ error = -1;
+ bitmap = MAP_FAILED;
+
+ fd = open("/dev/mem", O_RDONLY, 0);
+ if (fd < 0)
+ goto done;
+
+ bitmap = mmap(NULL, PAGE_SIZE, PROT_READ, 0, fd, addr);
+ if (bitmap == MAP_FAILED)
+ goto done;
+
+ for (msr = 0; msr < 0x2000; msr++) {
+ byte = msr / 8;
+ bit = msr & 0x7;
+
+ /* Look at MSRs in the range 0x00000000 to 0x00001FFF */
+ readable = (bitmap[byte] & (1 << bit)) ? 0 : 1;
+ writeable = (bitmap[2048 + byte] & (1 << bit)) ? 0 : 1;
+ if (readable || writeable) {
+ printf("msr 0x%08x[%d]\t\t%c%c\n", msr, vcpu,
+ readable ? 'R' : '-',
+ writeable ? 'W' : '-');
+ }
+
+ /* Look at MSRs in the range 0xC0000000 to 0xC0001FFF */
+ byte += 1024;
+ readable = (bitmap[byte] & (1 << bit)) ? 0 : 1;
+ writeable = (bitmap[2048 + byte] & (1 << bit)) ? 0 : 1;
+ if (readable || writeable) {
+ printf("msr 0x%08x[%d]\t\t%c%c\n",
+ 0xc0000000 + msr, vcpu,
+ readable ? 'R' : '-',
+ writeable ? 'W' : '-');
+ }
+ }
+
+ error = 0;
+done:
+ if (bitmap != MAP_FAILED)
+ munmap((void *)bitmap, PAGE_SIZE);
+ if (fd >= 0)
+ close(fd);
+ return (error);
+}
+
+static int
+vm_get_vmcs_field(struct vmctx *ctx, int vcpu, int field, uint64_t *ret_val)
+{
+
+ return (vm_get_register(ctx, vcpu, VMCS_IDENT(field), ret_val));
+}
+
+static int
+vm_set_vmcs_field(struct vmctx *ctx, int vcpu, int field, uint64_t val)
+{
+
+ return (vm_set_register(ctx, vcpu, VMCS_IDENT(field), val));
+}
+
+enum {
+ VMNAME = 1000, /* avoid collision with return values from getopt */
+ VCPU,
+ SET_LOWMEM,
+ SET_HIGHMEM,
+ SET_EFER,
+ SET_CR0,
+ SET_CR3,
+ SET_CR4,
+ SET_DR7,
+ SET_RSP,
+ SET_RIP,
+ SET_RAX,
+ SET_RFLAGS,
+ DESC_BASE,
+ DESC_LIMIT,
+ DESC_ACCESS,
+ SET_CS,
+ SET_DS,
+ SET_ES,
+ SET_FS,
+ SET_GS,
+ SET_SS,
+ SET_TR,
+ SET_LDTR,
+ SET_PINNING,
+ SET_X2APIC_STATE,
+ SET_VMCS_EXCEPTION_BITMAP,
+ SET_VMCS_ENTRY_INTERRUPTION_INFO,
+ SET_CAP,
+ CAPNAME,
+};
+
+int
+main(int argc, char *argv[])
+{
+ char *vmname;
+ int error, ch, vcpu;
+ vm_paddr_t gpa;
+ size_t len;
+ struct vm_exit vmexit;
+ uint64_t ctl, eptp, bm, addr, u64;
+ struct vmctx *ctx;
+
+ uint64_t cr0, cr3, cr4, dr7, rsp, rip, rflags, efer, pat;
+ uint64_t rax, rbx, rcx, rdx, rsi, rdi, rbp;
+ uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
+ uint64_t cs, ds, es, fs, gs, ss, tr, ldtr;
+
+ struct option opts[] = {
+ { "vm", REQ_ARG, 0, VMNAME },
+ { "cpu", REQ_ARG, 0, VCPU },
+ { "set-lowmem", REQ_ARG, 0, SET_LOWMEM },
+ { "set-highmem",REQ_ARG, 0, SET_HIGHMEM },
+ { "set-efer", REQ_ARG, 0, SET_EFER },
+ { "set-cr0", REQ_ARG, 0, SET_CR0 },
+ { "set-cr3", REQ_ARG, 0, SET_CR3 },
+ { "set-cr4", REQ_ARG, 0, SET_CR4 },
+ { "set-dr7", REQ_ARG, 0, SET_DR7 },
+ { "set-rsp", REQ_ARG, 0, SET_RSP },
+ { "set-rip", REQ_ARG, 0, SET_RIP },
+ { "set-rax", REQ_ARG, 0, SET_RAX },
+ { "set-rflags", REQ_ARG, 0, SET_RFLAGS },
+ { "desc-base", REQ_ARG, 0, DESC_BASE },
+ { "desc-limit", REQ_ARG, 0, DESC_LIMIT },
+ { "desc-access",REQ_ARG, 0, DESC_ACCESS },
+ { "set-cs", REQ_ARG, 0, SET_CS },
+ { "set-ds", REQ_ARG, 0, SET_DS },
+ { "set-es", REQ_ARG, 0, SET_ES },
+ { "set-fs", REQ_ARG, 0, SET_FS },
+ { "set-gs", REQ_ARG, 0, SET_GS },
+ { "set-ss", REQ_ARG, 0, SET_SS },
+ { "set-tr", REQ_ARG, 0, SET_TR },
+ { "set-ldtr", REQ_ARG, 0, SET_LDTR },
+ { "set-pinning",REQ_ARG, 0, SET_PINNING },
+ { "set-x2apic-state",REQ_ARG, 0, SET_X2APIC_STATE },
+ { "set-vmcs-exception-bitmap",
+ REQ_ARG, 0, SET_VMCS_EXCEPTION_BITMAP },
+ { "set-vmcs-entry-interruption-info",
+ REQ_ARG, 0, SET_VMCS_ENTRY_INTERRUPTION_INFO },
+ { "capname", REQ_ARG, 0, CAPNAME },
+ { "setcap", REQ_ARG, 0, SET_CAP },
+ { "getcap", NO_ARG, &getcap, 1 },
+ { "get-stats", NO_ARG, &get_stats, 1 },
+ { "get-desc-ds",NO_ARG, &get_desc_ds, 1 },
+ { "set-desc-ds",NO_ARG, &set_desc_ds, 1 },
+ { "get-desc-es",NO_ARG, &get_desc_es, 1 },
+ { "set-desc-es",NO_ARG, &set_desc_es, 1 },
+ { "get-desc-ss",NO_ARG, &get_desc_ss, 1 },
+ { "set-desc-ss",NO_ARG, &set_desc_ss, 1 },
+ { "get-desc-cs",NO_ARG, &get_desc_cs, 1 },
+ { "set-desc-cs",NO_ARG, &set_desc_cs, 1 },
+ { "get-desc-fs",NO_ARG, &get_desc_fs, 1 },
+ { "set-desc-fs",NO_ARG, &set_desc_fs, 1 },
+ { "get-desc-gs",NO_ARG, &get_desc_gs, 1 },
+ { "set-desc-gs",NO_ARG, &set_desc_gs, 1 },
+ { "get-desc-tr",NO_ARG, &get_desc_tr, 1 },
+ { "set-desc-tr",NO_ARG, &set_desc_tr, 1 },
+ { "set-desc-ldtr", NO_ARG, &set_desc_ldtr, 1 },
+ { "get-desc-ldtr", NO_ARG, &get_desc_ldtr, 1 },
+ { "set-desc-gdtr", NO_ARG, &set_desc_gdtr, 1 },
+ { "get-desc-gdtr", NO_ARG, &get_desc_gdtr, 1 },
+ { "set-desc-idtr", NO_ARG, &set_desc_idtr, 1 },
+ { "get-desc-idtr", NO_ARG, &get_desc_idtr, 1 },
+ { "get-lowmem", NO_ARG, &get_lowmem, 1 },
+ { "get-highmem",NO_ARG, &get_highmem, 1 },
+ { "get-efer", NO_ARG, &get_efer, 1 },
+ { "get-cr0", NO_ARG, &get_cr0, 1 },
+ { "get-cr3", NO_ARG, &get_cr3, 1 },
+ { "get-cr4", NO_ARG, &get_cr4, 1 },
+ { "get-dr7", NO_ARG, &get_dr7, 1 },
+ { "get-rsp", NO_ARG, &get_rsp, 1 },
+ { "get-rip", NO_ARG, &get_rip, 1 },
+ { "get-rax", NO_ARG, &get_rax, 1 },
+ { "get-rbx", NO_ARG, &get_rbx, 1 },
+ { "get-rcx", NO_ARG, &get_rcx, 1 },
+ { "get-rdx", NO_ARG, &get_rdx, 1 },
+ { "get-rsi", NO_ARG, &get_rsi, 1 },
+ { "get-rdi", NO_ARG, &get_rdi, 1 },
+ { "get-rbp", NO_ARG, &get_rbp, 1 },
+ { "get-r8", NO_ARG, &get_r8, 1 },
+ { "get-r9", NO_ARG, &get_r9, 1 },
+ { "get-r10", NO_ARG, &get_r10, 1 },
+ { "get-r11", NO_ARG, &get_r11, 1 },
+ { "get-r12", NO_ARG, &get_r12, 1 },
+ { "get-r13", NO_ARG, &get_r13, 1 },
+ { "get-r14", NO_ARG, &get_r14, 1 },
+ { "get-r15", NO_ARG, &get_r15, 1 },
+ { "get-rflags", NO_ARG, &get_rflags, 1 },
+ { "get-cs", NO_ARG, &get_cs, 1 },
+ { "get-ds", NO_ARG, &get_ds, 1 },
+ { "get-es", NO_ARG, &get_es, 1 },
+ { "get-fs", NO_ARG, &get_fs, 1 },
+ { "get-gs", NO_ARG, &get_gs, 1 },
+ { "get-ss", NO_ARG, &get_ss, 1 },
+ { "get-tr", NO_ARG, &get_tr, 1 },
+ { "get-ldtr", NO_ARG, &get_ldtr, 1 },
+ { "get-vmcs-pinbased-ctls",
+ NO_ARG, &get_pinbased_ctls, 1 },
+ { "get-vmcs-procbased-ctls",
+ NO_ARG, &get_procbased_ctls, 1 },
+ { "get-vmcs-procbased-ctls2",
+ NO_ARG, &get_procbased_ctls2, 1 },
+ { "get-vmcs-guest-linear-address",
+ NO_ARG, &get_vmcs_gla, 1 },
+ { "get-vmcs-guest-physical-address",
+ NO_ARG, &get_vmcs_gpa, 1 },
+ { "get-vmcs-entry-interruption-info",
+ NO_ARG, &get_vmcs_entry_interruption_info, 1},
+ { "get-vmcs-eptp", NO_ARG, &get_eptp, 1 },
+ { "get-vmcs-exception-bitmap",
+ NO_ARG, &get_exception_bitmap, 1 },
+ { "get-vmcs-io-bitmap-address",
+ NO_ARG, &get_io_bitmap, 1 },
+ { "get-vmcs-tsc-offset", NO_ARG,&get_tsc_offset, 1 },
+ { "get-vmcs-cr0-mask", NO_ARG, &get_cr0_mask, 1 },
+ { "get-vmcs-cr0-shadow", NO_ARG,&get_cr0_shadow, 1 },
+ { "get-vmcs-cr4-mask", NO_ARG, &get_cr4_mask, 1 },
+ { "get-vmcs-cr4-shadow", NO_ARG,&get_cr4_shadow, 1 },
+ { "get-vmcs-cr3-targets", NO_ARG, &get_cr3_targets, 1},
+ { "get-vmcs-apic-access-address",
+ NO_ARG, &get_apic_access_addr, 1},
+ { "get-vmcs-virtual-apic-address",
+ NO_ARG, &get_virtual_apic_addr, 1},
+ { "get-vmcs-tpr-threshold",
+ NO_ARG, &get_tpr_threshold, 1 },
+ { "get-vmcs-msr-bitmap",
+ NO_ARG, &get_msr_bitmap, 1 },
+ { "get-vmcs-msr-bitmap-address",
+ NO_ARG, &get_msr_bitmap_address, 1 },
+ { "get-vmcs-vpid", NO_ARG, &get_vpid, 1 },
+ { "get-vmcs-ple-gap", NO_ARG, &get_ple_gap, 1 },
+ { "get-vmcs-ple-window", NO_ARG,&get_ple_window,1 },
+ { "get-vmcs-instruction-error",
+ NO_ARG, &get_inst_err, 1 },
+ { "get-vmcs-exit-ctls", NO_ARG, &get_exit_ctls, 1 },
+ { "get-vmcs-entry-ctls",
+ NO_ARG, &get_entry_ctls, 1 },
+ { "get-vmcs-guest-pat", NO_ARG, &get_guest_pat, 1 },
+ { "get-vmcs-host-pat", NO_ARG, &get_host_pat, 1 },
+ { "get-vmcs-host-cr0",
+ NO_ARG, &get_host_cr0, 1 },
+ { "get-vmcs-host-cr3",
+ NO_ARG, &get_host_cr3, 1 },
+ { "get-vmcs-host-cr4",
+ NO_ARG, &get_host_cr4, 1 },
+ { "get-vmcs-host-rip",
+ NO_ARG, &get_host_rip, 1 },
+ { "get-vmcs-host-rsp",
+ NO_ARG, &get_host_rsp, 1 },
+ { "get-vmcs-guest-sysenter",
+ NO_ARG, &get_guest_sysenter, 1 },
+ { "get-vmcs-link", NO_ARG, &get_vmcs_link, 1 },
+ { "get-vmcs-exit-reason",
+ NO_ARG, &get_vmcs_exit_reason, 1 },
+ { "get-vmcs-exit-qualification",
+ NO_ARG, &get_vmcs_exit_qualification, 1 },
+ { "get-vmcs-exit-interruption-info",
+ NO_ARG, &get_vmcs_exit_interruption_info, 1},
+ { "get-vmcs-exit-interruption-error",
+ NO_ARG, &get_vmcs_exit_interruption_error, 1},
+ { "get-vmcs-interruptibility",
+ NO_ARG, &get_vmcs_interruptibility, 1 },
+ { "get-pinning",NO_ARG, &get_pinning, 1 },
+ { "get-x2apic-state",NO_ARG, &get_x2apic_state, 1 },
+ { "get-all", NO_ARG, &get_all, 1 },
+ { "run", NO_ARG, &run, 1 },
+ { "create", NO_ARG, &create, 1 },
+ { "destroy", NO_ARG, &destroy, 1 },
+ { NULL, 0, NULL, 0 }
+ };
+
+ vcpu = 0;
+ progname = basename(argv[0]);
+
+ while ((ch = getopt_long(argc, argv, "", opts, NULL)) != -1) {
+ switch (ch) {
+ case 0:
+ break;
+ case VMNAME:
+ vmname = optarg;
+ break;
+ case VCPU:
+ vcpu = atoi(optarg);
+ break;
+ case SET_LOWMEM:
+ lowmem = atoi(optarg) * MB;
+ lowmem = roundup(lowmem, 2 * MB);
+ break;
+ case SET_HIGHMEM:
+ highmem = atoi(optarg) * MB;
+ highmem = roundup(highmem, 2 * MB);
+ break;
+ case SET_EFER:
+ efer = strtoul(optarg, NULL, 0);
+ set_efer = 1;
+ break;
+ case SET_CR0:
+ cr0 = strtoul(optarg, NULL, 0);
+ set_cr0 = 1;
+ break;
+ case SET_CR3:
+ cr3 = strtoul(optarg, NULL, 0);
+ set_cr3 = 1;
+ break;
+ case SET_CR4:
+ cr4 = strtoul(optarg, NULL, 0);
+ set_cr4 = 1;
+ break;
+ case SET_DR7:
+ dr7 = strtoul(optarg, NULL, 0);
+ set_dr7 = 1;
+ break;
+ case SET_RSP:
+ rsp = strtoul(optarg, NULL, 0);
+ set_rsp = 1;
+ break;
+ case SET_RIP:
+ rip = strtoul(optarg, NULL, 0);
+ set_rip = 1;
+ break;
+ case SET_RAX:
+ rax = strtoul(optarg, NULL, 0);
+ set_rax = 1;
+ break;
+ case SET_RFLAGS:
+ rflags = strtoul(optarg, NULL, 0);
+ set_rflags = 1;
+ break;
+ case DESC_BASE:
+ desc_base = strtoul(optarg, NULL, 0);
+ break;
+ case DESC_LIMIT:
+ desc_limit = strtoul(optarg, NULL, 0);
+ break;
+ case DESC_ACCESS:
+ desc_access = strtoul(optarg, NULL, 0);
+ break;
+ case SET_CS:
+ cs = strtoul(optarg, NULL, 0);
+ set_cs = 1;
+ break;
+ case SET_DS:
+ ds = strtoul(optarg, NULL, 0);
+ set_ds = 1;
+ break;
+ case SET_ES:
+ es = strtoul(optarg, NULL, 0);
+ set_es = 1;
+ break;
+ case SET_FS:
+ fs = strtoul(optarg, NULL, 0);
+ set_fs = 1;
+ break;
+ case SET_GS:
+ gs = strtoul(optarg, NULL, 0);
+ set_gs = 1;
+ break;
+ case SET_SS:
+ ss = strtoul(optarg, NULL, 0);
+ set_ss = 1;
+ break;
+ case SET_TR:
+ tr = strtoul(optarg, NULL, 0);
+ set_tr = 1;
+ break;
+ case SET_LDTR:
+ ldtr = strtoul(optarg, NULL, 0);
+ set_ldtr = 1;
+ break;
+ case SET_PINNING:
+ pincpu = strtol(optarg, NULL, 0);
+ set_pinning = 1;
+ break;
+ case SET_X2APIC_STATE:
+ x2apic_state = strtol(optarg, NULL, 0);
+ set_x2apic_state = 1;
+ break;
+ case SET_VMCS_EXCEPTION_BITMAP:
+ exception_bitmap = strtoul(optarg, NULL, 0);
+ set_exception_bitmap = 1;
+ break;
+ case SET_VMCS_ENTRY_INTERRUPTION_INFO:
+ vmcs_entry_interruption_info = strtoul(optarg, NULL, 0);
+ set_vmcs_entry_interruption_info = 1;
+ break;
+ case SET_CAP:
+ capval = strtoul(optarg, NULL, 0);
+ setcap = 1;
+ break;
+ case CAPNAME:
+ capname = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (vmname == NULL)
+ usage();
+
+ error = 0;
+
+ if (!error && create)
+ error = vm_create(vmname);
+
+ if (!error) {
+ ctx = vm_open(vmname);
+ if (ctx == NULL)
+ error = -1;
+ }
+
+ if (!error && lowmem)
+ error = vm_setup_memory(ctx, 0, lowmem, NULL);
+
+ if (!error && highmem)
+ error = vm_setup_memory(ctx, 4 * GB, highmem, NULL);
+
+ if (!error && set_efer)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_EFER, efer);
+
+ if (!error && set_cr0)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR0, cr0);
+
+ if (!error && set_cr3)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR3, cr3);
+
+ if (!error && set_cr4)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR4, cr4);
+
+ if (!error && set_dr7)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR7, dr7);
+
+ if (!error && set_rsp)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RSP, rsp);
+
+ if (!error && set_rip)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RIP, rip);
+
+ if (!error && set_rax)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RAX, rax);
+
+ if (!error && set_rflags) {
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RFLAGS,
+ rflags);
+ }
+
+ if (!error && set_desc_ds) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_DS,
+ desc_base, desc_limit, desc_access);
+ }
+
+ if (!error && set_desc_es) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_ES,
+ desc_base, desc_limit, desc_access);
+ }
+
+ if (!error && set_desc_ss) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_SS,
+ desc_base, desc_limit, desc_access);
+ }
+
+ if (!error && set_desc_cs) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_CS,
+ desc_base, desc_limit, desc_access);
+ }
+
+ if (!error && set_desc_fs) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_FS,
+ desc_base, desc_limit, desc_access);
+ }
+
+ if (!error && set_desc_gs) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_GS,
+ desc_base, desc_limit, desc_access);
+ }
+
+ if (!error && set_desc_tr) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_TR,
+ desc_base, desc_limit, desc_access);
+ }
+
+ if (!error && set_desc_ldtr) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_LDTR,
+ desc_base, desc_limit, desc_access);
+ }
+
+ if (!error && set_desc_gdtr) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_GDTR,
+ desc_base, desc_limit, 0);
+ }
+
+ if (!error && set_desc_idtr) {
+ error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_IDTR,
+ desc_base, desc_limit, 0);
+ }
+
+ if (!error && set_cs)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CS, cs);
+
+ if (!error && set_ds)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DS, ds);
+
+ if (!error && set_es)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_ES, es);
+
+ if (!error && set_fs)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_FS, fs);
+
+ if (!error && set_gs)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_GS, gs);
+
+ if (!error && set_ss)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_SS, ss);
+
+ if (!error && set_tr)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_TR, tr);
+
+ if (!error && set_ldtr)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_LDTR, ldtr);
+
+ if (!error && set_pinning)
+ error = vm_set_pinning(ctx, vcpu, pincpu);
+
+ if (!error && set_x2apic_state)
+ error = vm_set_x2apic_state(ctx, vcpu, x2apic_state);
+
+ if (!error && set_exception_bitmap) {
+ error = vm_set_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP,
+ exception_bitmap);
+ }
+
+ if (!error && set_vmcs_entry_interruption_info) {
+ error = vm_set_vmcs_field(ctx, vcpu, VMCS_ENTRY_INTR_INFO,
+ vmcs_entry_interruption_info);
+ }
+
+ if (!error && (get_lowmem || get_all)) {
+ gpa = 0;
+ error = vm_get_memory_seg(ctx, gpa, &len);
+ if (error == 0)
+ printf("lowmem\t\t0x%016lx/%ld\n", gpa, len);
+ }
+
+ if (!error && (get_highmem || get_all)) {
+ gpa = 4 * GB;
+ error = vm_get_memory_seg(ctx, gpa, &len);
+ if (error == 0)
+ printf("highmem\t\t0x%016lx/%ld\n", gpa, len);
+ }
+
+ if (!error && (get_efer || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_EFER, &efer);
+ if (error == 0)
+ printf("efer[%d]\t\t0x%016lx\n", vcpu, efer);
+ }
+
+ if (!error && (get_cr0 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR0, &cr0);
+ if (error == 0)
+ printf("cr0[%d]\t\t0x%016lx\n", vcpu, cr0);
+ }
+
+ if (!error && (get_cr3 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR3, &cr3);
+ if (error == 0)
+ printf("cr3[%d]\t\t0x%016lx\n", vcpu, cr3);
+ }
+
+ if (!error && (get_cr4 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR4, &cr4);
+ if (error == 0)
+ printf("cr4[%d]\t\t0x%016lx\n", vcpu, cr4);
+ }
+
+ if (!error && (get_dr7 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR7, &dr7);
+ if (error == 0)
+ printf("dr7[%d]\t\t0x%016lx\n", vcpu, dr7);
+ }
+
+ if (!error && (get_rsp || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RSP, &rsp);
+ if (error == 0)
+ printf("rsp[%d]\t\t0x%016lx\n", vcpu, rsp);
+ }
+
+ if (!error && (get_rip || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RIP, &rip);
+ if (error == 0)
+ printf("rip[%d]\t\t0x%016lx\n", vcpu, rip);
+ }
+
+ if (!error && (get_rax || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RAX, &rax);
+ if (error == 0)
+ printf("rax[%d]\t\t0x%016lx\n", vcpu, rax);
+ }
+
+ if (!error && (get_rbx || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RBX, &rbx);
+ if (error == 0)
+ printf("rbx[%d]\t\t0x%016lx\n", vcpu, rbx);
+ }
+
+ if (!error && (get_rcx || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RCX, &rcx);
+ if (error == 0)
+ printf("rcx[%d]\t\t0x%016lx\n", vcpu, rcx);
+ }
+
+ if (!error && (get_rdx || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RDX, &rdx);
+ if (error == 0)
+ printf("rdx[%d]\t\t0x%016lx\n", vcpu, rdx);
+ }
+
+ if (!error && (get_rsi || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RSI, &rsi);
+ if (error == 0)
+ printf("rsi[%d]\t\t0x%016lx\n", vcpu, rsi);
+ }
+
+ if (!error && (get_rdi || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RDI, &rdi);
+ if (error == 0)
+ printf("rdi[%d]\t\t0x%016lx\n", vcpu, rdi);
+ }
+
+ if (!error && (get_rbp || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RBP, &rbp);
+ if (error == 0)
+ printf("rbp[%d]\t\t0x%016lx\n", vcpu, rbp);
+ }
+
+ if (!error && (get_r8 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R8, &r8);
+ if (error == 0)
+ printf("r8[%d]\t\t0x%016lx\n", vcpu, r8);
+ }
+
+ if (!error && (get_r9 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R9, &r9);
+ if (error == 0)
+ printf("r9[%d]\t\t0x%016lx\n", vcpu, r9);
+ }
+
+ if (!error && (get_r10 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R10, &r10);
+ if (error == 0)
+ printf("r10[%d]\t\t0x%016lx\n", vcpu, r10);
+ }
+
+ if (!error && (get_r11 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R11, &r11);
+ if (error == 0)
+ printf("r11[%d]\t\t0x%016lx\n", vcpu, r11);
+ }
+
+ if (!error && (get_r12 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R12, &r12);
+ if (error == 0)
+ printf("r12[%d]\t\t0x%016lx\n", vcpu, r12);
+ }
+
+ if (!error && (get_r13 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R13, &r13);
+ if (error == 0)
+ printf("r13[%d]\t\t0x%016lx\n", vcpu, r13);
+ }
+
+ if (!error && (get_r14 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R14, &r14);
+ if (error == 0)
+ printf("r14[%d]\t\t0x%016lx\n", vcpu, r14);
+ }
+
+ if (!error && (get_r15 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R15, &r15);
+ if (error == 0)
+ printf("r15[%d]\t\t0x%016lx\n", vcpu, r15);
+ }
+
+ if (!error && (get_rflags || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RFLAGS,
+ &rflags);
+ if (error == 0)
+ printf("rflags[%d]\t0x%016lx\n", vcpu, rflags);
+ }
+
+ if (!error && (get_stats || get_all)) {
+ int i, num_stats;
+ uint64_t *stats;
+ struct timeval tv;
+ const char *desc;
+
+ stats = vm_get_stats(ctx, vcpu, &tv, &num_stats);
+ if (stats != NULL) {
+ printf("vcpu%d\n", vcpu);
+ for (i = 0; i < num_stats; i++) {
+ desc = vm_get_stat_desc(ctx, i);
+ printf("%-32s\t%ld\n", desc, stats[i]);
+ }
+ }
+ }
+
+ if (!error && (get_desc_ds || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_DS,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("ds desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
+ vcpu, desc_base, desc_limit, desc_access);
+ }
+ }
+
+ if (!error && (get_desc_es || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_ES,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("es desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
+ vcpu, desc_base, desc_limit, desc_access);
+ }
+ }
+
+ if (!error && (get_desc_fs || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_FS,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("fs desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
+ vcpu, desc_base, desc_limit, desc_access);
+ }
+ }
+
+ if (!error && (get_desc_gs || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_GS,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("gs desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
+ vcpu, desc_base, desc_limit, desc_access);
+ }
+ }
+
+ if (!error && (get_desc_ss || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_SS,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("ss desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
+ vcpu, desc_base, desc_limit, desc_access);
+ }
+ }
+
+ if (!error && (get_desc_cs || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_CS,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("cs desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
+ vcpu, desc_base, desc_limit, desc_access);
+ }
+ }
+
+ if (!error && (get_desc_tr || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_TR,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("tr desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
+ vcpu, desc_base, desc_limit, desc_access);
+ }
+ }
+
+ if (!error && (get_desc_ldtr || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_LDTR,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("ldtr desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
+ vcpu, desc_base, desc_limit, desc_access);
+ }
+ }
+
+ if (!error && (get_desc_gdtr || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_GDTR,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("gdtr[%d]\t\t0x%016lx/0x%08x\n",
+ vcpu, desc_base, desc_limit);
+ }
+ }
+
+ if (!error && (get_desc_idtr || get_all)) {
+ error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_IDTR,
+ &desc_base, &desc_limit, &desc_access);
+ if (error == 0) {
+ printf("idtr[%d]\t\t0x%016lx/0x%08x\n",
+ vcpu, desc_base, desc_limit);
+ }
+ }
+
+ if (!error && (get_cs || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CS, &cs);
+ if (error == 0)
+ printf("cs[%d]\t\t0x%04lx\n", vcpu, cs);
+ }
+
+ if (!error && (get_ds || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DS, &ds);
+ if (error == 0)
+ printf("ds[%d]\t\t0x%04lx\n", vcpu, ds);
+ }
+
+ if (!error && (get_es || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_ES, &es);
+ if (error == 0)
+ printf("es[%d]\t\t0x%04lx\n", vcpu, es);
+ }
+
+ if (!error && (get_fs || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_FS, &fs);
+ if (error == 0)
+ printf("fs[%d]\t\t0x%04lx\n", vcpu, fs);
+ }
+
+ if (!error && (get_gs || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_GS, &gs);
+ if (error == 0)
+ printf("gs[%d]\t\t0x%04lx\n", vcpu, gs);
+ }
+
+ if (!error && (get_ss || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_SS, &ss);
+ if (error == 0)
+ printf("ss[%d]\t\t0x%04lx\n", vcpu, ss);
+ }
+
+ if (!error && (get_tr || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_TR, &tr);
+ if (error == 0)
+ printf("tr[%d]\t\t0x%04lx\n", vcpu, tr);
+ }
+
+ if (!error && (get_ldtr || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_LDTR, &ldtr);
+ if (error == 0)
+ printf("ldtr[%d]\t\t0x%04lx\n", vcpu, ldtr);
+ }
+
+ if (!error && (get_pinning || get_all)) {
+ error = vm_get_pinning(ctx, vcpu, &pincpu);
+ if (error == 0) {
+ if (pincpu < 0)
+ printf("pincpu[%d]\tunpinned\n", vcpu);
+ else
+ printf("pincpu[%d]\t%d\n", vcpu, pincpu);
+ }
+ }
+
+ if (!error && (get_x2apic_state || get_all)) {
+ error = vm_get_x2apic_state(ctx, vcpu, &x2apic_state);
+ if (error == 0)
+ printf("x2apic_state[%d]\t%d\n", vcpu, x2apic_state);
+ }
+
+ if (!error && (get_pinbased_ctls || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_PIN_BASED_CTLS, &ctl);
+ if (error == 0)
+ printf("pinbased_ctls[%d]\t0x%08lx\n", vcpu, ctl);
+ }
+
+ if (!error && (get_procbased_ctls || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_PRI_PROC_BASED_CTLS, &ctl);
+ if (error == 0)
+ printf("procbased_ctls[%d]\t0x%08lx\n", vcpu, ctl);
+ }
+
+ if (!error && (get_procbased_ctls2 || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_SEC_PROC_BASED_CTLS, &ctl);
+ if (error == 0)
+ printf("procbased_ctls2[%d]\t0x%08lx\n", vcpu, ctl);
+ }
+
+ if (!error && (get_vmcs_gla || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_GUEST_LINEAR_ADDRESS, &u64);
+ if (error == 0)
+ printf("gla[%d]\t\t0x%016lx\n", vcpu, u64);
+ }
+
+ if (!error && (get_vmcs_gpa || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_GUEST_PHYSICAL_ADDRESS, &u64);
+ if (error == 0)
+ printf("gpa[%d]\t\t0x%016lx\n", vcpu, u64);
+ }
+
+ if (!error && (get_vmcs_entry_interruption_info || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_ENTRY_INTR_INFO,&u64);
+ if (error == 0) {
+ printf("entry_interruption_info[%d]\t0x%08lx\n",
+ vcpu, u64);
+ }
+ }
+
+ if (!error && (get_eptp || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_EPTP, &eptp);
+ if (error == 0)
+ printf("eptp[%d]\t\t0x%016lx\n", vcpu, eptp);
+ }
+
+ if (!error && (get_exception_bitmap || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP,
+ &bm);
+ if (error == 0)
+ printf("exception_bitmap[%d]\t0x%08lx\n", vcpu, bm);
+ }
+
+ if (!error && (get_io_bitmap || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_IO_BITMAP_A, &bm);
+ if (error == 0)
+ printf("io_bitmap_a[%d]\t0x%08lx\n", vcpu, bm);
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_IO_BITMAP_B, &bm);
+ if (error == 0)
+ printf("io_bitmap_b[%d]\t0x%08lx\n", vcpu, bm);
+ }
+
+ if (!error && (get_tsc_offset || get_all)) {
+ uint64_t tscoff;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_TSC_OFFSET, &tscoff);
+ if (error == 0)
+ printf("tsc_offset[%d]\t0x%016lx\n", vcpu, tscoff);
+ }
+
+ if (!error && (get_cr0_mask || get_all)) {
+ uint64_t cr0mask;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR0_MASK, &cr0mask);
+ if (error == 0)
+ printf("cr0_mask[%d]\t\t0x%016lx\n", vcpu, cr0mask);
+ }
+
+ if (!error && (get_cr0_shadow || get_all)) {
+ uint64_t cr0shadow;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR0_SHADOW,
+ &cr0shadow);
+ if (error == 0)
+ printf("cr0_shadow[%d]\t\t0x%016lx\n", vcpu, cr0shadow);
+ }
+
+ if (!error && (get_cr4_mask || get_all)) {
+ uint64_t cr4mask;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR4_MASK, &cr4mask);
+ if (error == 0)
+ printf("cr4_mask[%d]\t\t0x%016lx\n", vcpu, cr4mask);
+ }
+
+ if (!error && (get_cr4_shadow || get_all)) {
+ uint64_t cr4shadow;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR4_SHADOW,
+ &cr4shadow);
+ if (error == 0)
+ printf("cr4_shadow[%d]\t\t0x%016lx\n", vcpu, cr4shadow);
+ }
+
+ if (!error && (get_cr3_targets || get_all)) {
+ uint64_t target_count, target_addr;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET_COUNT,
+ &target_count);
+ if (error == 0) {
+ printf("cr3_target_count[%d]\t0x%08lx\n",
+ vcpu, target_count);
+ }
+
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET0,
+ &target_addr);
+ if (error == 0) {
+ printf("cr3_target0[%d]\t\t0x%016lx\n",
+ vcpu, target_addr);
+ }
+
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET1,
+ &target_addr);
+ if (error == 0) {
+ printf("cr3_target1[%d]\t\t0x%016lx\n",
+ vcpu, target_addr);
+ }
+
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET2,
+ &target_addr);
+ if (error == 0) {
+ printf("cr3_target2[%d]\t\t0x%016lx\n",
+ vcpu, target_addr);
+ }
+
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET3,
+ &target_addr);
+ if (error == 0) {
+ printf("cr3_target3[%d]\t\t0x%016lx\n",
+ vcpu, target_addr);
+ }
+ }
+
+ if (!error && (get_apic_access_addr || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_APIC_ACCESS, &addr);
+ if (error == 0)
+ printf("apic_access_addr[%d]\t0x%016lx\n", vcpu, addr);
+ }
+
+ if (!error && (get_virtual_apic_addr || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_VIRTUAL_APIC, &addr);
+ if (error == 0)
+ printf("virtual_apic_addr[%d]\t0x%016lx\n", vcpu, addr);
+ }
+
+ if (!error && (get_tpr_threshold || get_all)) {
+ uint64_t threshold;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_TPR_THRESHOLD,
+ &threshold);
+ if (error == 0)
+ printf("tpr_threshold[%d]\t0x%08lx\n", vcpu, threshold);
+ }
+
+ if (!error && (get_msr_bitmap_address || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_MSR_BITMAP, &addr);
+ if (error == 0)
+ printf("msr_bitmap[%d]\t\t0x%016lx\n", vcpu, addr);
+ }
+
+ if (!error && (get_msr_bitmap || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_MSR_BITMAP, &addr);
+ if (error == 0)
+ error = dump_vmcs_msr_bitmap(vcpu, addr);
+ }
+
+ if (!error && (get_vpid || get_all)) {
+ uint64_t vpid;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_VPID, &vpid);
+ if (error == 0)
+ printf("vpid[%d]\t\t0x%04lx\n", vcpu, vpid);
+ }
+
+ if (!error && (get_ple_window || get_all)) {
+ uint64_t window;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_PLE_WINDOW, &window);
+ if (error == 0)
+ printf("ple_window[%d]\t\t0x%08lx\n", vcpu, window);
+ }
+
+ if (!error && (get_ple_gap || get_all)) {
+ uint64_t gap;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_PLE_GAP, &gap);
+ if (error == 0)
+ printf("ple_gap[%d]\t\t0x%08lx\n", vcpu, gap);
+ }
+
+ if (!error && (get_inst_err || get_all)) {
+ uint64_t insterr;
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_INSTRUCTION_ERROR,
+ &insterr);
+ if (error == 0) {
+ printf("instruction_error[%d]\t0x%08lx\n",
+ vcpu, insterr);
+ }
+ }
+
+ if (!error && (get_exit_ctls || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_CTLS, &ctl);
+ if (error == 0)
+ printf("exit_ctls[%d]\t\t0x%08lx\n", vcpu, ctl);
+ }
+
+ if (!error && (get_entry_ctls || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_ENTRY_CTLS, &ctl);
+ if (error == 0)
+ printf("entry_ctls[%d]\t\t0x%08lx\n", vcpu, ctl);
+ }
+
+ if (!error && (get_host_pat || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_IA32_PAT, &pat);
+ if (error == 0)
+ printf("host_pat[%d]\t\t0x%016lx\n", vcpu, pat);
+ }
+
+ if (!error && (get_guest_pat || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_GUEST_IA32_PAT, &pat);
+ if (error == 0)
+ printf("guest_pat[%d]\t\t0x%016lx\n", vcpu, pat);
+ }
+
+ if (!error && (get_host_cr0 || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR0, &cr0);
+ if (error == 0)
+ printf("host_cr0[%d]\t\t0x%016lx\n", vcpu, cr0);
+ }
+
+ if (!error && (get_host_cr3 || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR3, &cr3);
+ if (error == 0)
+ printf("host_cr3[%d]\t\t0x%016lx\n", vcpu, cr3);
+ }
+
+ if (!error && (get_host_cr4 || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR4, &cr4);
+ if (error == 0)
+ printf("host_cr4[%d]\t\t0x%016lx\n", vcpu, cr4);
+ }
+
+ if (!error && (get_host_rip || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_RIP, &rip);
+ if (error == 0)
+ printf("host_rip[%d]\t\t0x%016lx\n", vcpu, rip);
+ }
+
+ if (!error && (get_host_rsp || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_RSP, &rsp);
+ if (error == 0)
+ printf("host_rsp[%d]\t\t0x%016lx\n", vcpu, rsp);
+ }
+
+ if (!error && (get_guest_sysenter || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_GUEST_IA32_SYSENTER_CS, &cs);
+ if (error == 0)
+ printf("guest_sysenter_cs[%d]\t0x%08lx\n", vcpu, cs);
+
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_GUEST_IA32_SYSENTER_ESP, &rsp);
+ if (error == 0)
+ printf("guest_sysenter_sp[%d]\t0x%016lx\n", vcpu, rsp);
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_GUEST_IA32_SYSENTER_EIP, &rip);
+ if (error == 0)
+ printf("guest_sysenter_ip[%d]\t0x%016lx\n", vcpu, rip);
+ }
+
+ if (!error && (get_vmcs_link || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_LINK_POINTER, &addr);
+ if (error == 0)
+ printf("vmcs_pointer[%d]\t0x%016lx\n", vcpu, addr);
+ }
+
+ if (!error && (get_vmcs_exit_reason || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_REASON, &u64);
+ if (error == 0)
+ printf("vmcs_exit_reason[%d]\t0x%016lx\n", vcpu, u64);
+ }
+
+ if (!error && (get_vmcs_exit_qualification || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_QUALIFICATION,
+ &u64);
+ if (error == 0)
+ printf("vmcs_exit_qualification[%d]\t0x%016lx\n",
+ vcpu, u64);
+ }
+
+ if (!error && (get_vmcs_exit_interruption_info || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_EXIT_INTERRUPTION_INFO, &u64);
+ if (error == 0) {
+ printf("vmcs_exit_interruption_info[%d]\t0x%08lx\n",
+ vcpu, u64);
+ }
+ }
+
+ if (!error && (get_vmcs_exit_interruption_error || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_EXIT_INTERRUPTION_ERROR, &u64);
+ if (error == 0) {
+ printf("vmcs_exit_interruption_error[%d]\t0x%08lx\n",
+ vcpu, u64);
+ }
+ }
+
+ if (!error && (get_vmcs_interruptibility || get_all)) {
+ error = vm_get_vmcs_field(ctx, vcpu,
+ VMCS_GUEST_INTERRUPTIBILITY, &u64);
+ if (error == 0) {
+ printf("vmcs_guest_interruptibility[%d]\t0x%08lx\n",
+ vcpu, u64);
+ }
+ }
+
+ if (!error && setcap) {
+ int captype;
+ captype = vm_capability_name2type(capname);
+ error = vm_set_capability(ctx, vcpu, captype, capval);
+ if (error != 0 && errno == ENOENT)
+ printf("Capability \"%s\" is not available\n", capname);
+ }
+
+ if (!error && (getcap || get_all)) {
+ int captype, val, getcaptype;
+
+ if (getcap && capname)
+ getcaptype = vm_capability_name2type(capname);
+ else
+ getcaptype = -1;
+
+ for (captype = 0; captype < VM_CAP_MAX; captype++) {
+ if (getcaptype >= 0 && captype != getcaptype)
+ continue;
+ error = vm_get_capability(ctx, vcpu, captype, &val);
+ if (error == 0) {
+ printf("Capability \"%s\" is %s on vcpu %d\n",
+ vm_capability_type2name(captype),
+ val ? "set" : "not set", vcpu);
+ } else if (errno == ENOENT) {
+ printf("Capability \"%s\" is not available\n",
+ vm_capability_type2name(captype));
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (!error && run) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RIP, &rip);
+ assert(error == 0);
+
+ error = vm_run(ctx, vcpu, rip, &vmexit);
+ if (error == 0)
+ dump_vm_run_exitcode(&vmexit, vcpu);
+ else
+ printf("vm_run error %d\n", error);
+ }
+
+ if (error)
+ printf("errno = %d\n", errno);
+
+ if (!error && destroy)
+ vm_destroy(ctx);
+
+ exit(error);
+}
diff --git a/usr.sbin/bhyveload/Makefile b/usr.sbin/bhyveload/Makefile
new file mode 100644
index 0000000..7b00818
--- /dev/null
+++ b/usr.sbin/bhyveload/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+PROG= bhyveload
+SRCS= bhyveload.c
+MAN= bhyveload.8
+
+DPADD+= ${LIBVMMAPI}
+LDADD+= -lvmmapi
+
+WARNS?= 3
+
+CFLAGS+=-I${.CURDIR}/../../sys/boot/userboot
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bhyveload/bhyveload.8 b/usr.sbin/bhyveload/bhyveload.8
new file mode 100644
index 0000000..4a05116
--- /dev/null
+++ b/usr.sbin/bhyveload/bhyveload.8
@@ -0,0 +1,127 @@
+.\"
+.\" Copyright (c) 2012 NetApp Inc
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 7, 2012
+.Dt BHYVELOAD 8
+.Os
+.Sh NAME
+.Nm bhyveload
+.Nd load a
+.Fx
+guest inside a bhyve virtual machine
+.Sh SYNOPSIS
+.Nm
+.Op Fl m Ar lowmem
+.Op Fl M Ar highmem
+.Op Fl d Ar disk-path
+.Op Fl h Ar host-path
+.Ar vmname
+.Sh DESCRIPTION
+.Nm
+is used to load a
+.Fx
+guest inside a
+.Xr bhyve 4
+virtual machine.
+.Pp
+.Nm
+is based on
+.Xr loader 8
+and will present an interface identical to the
+.Fx
+loader on the user's terminal.
+.Pp
+The virtual machine is identified as
+.Ar vmname
+and will be created if it does not already exist.
+.Sh OPTIONS
+The following options are available:
+.Bl -tag -width indent
+.It Fl m Ar lowmem
+.Ar lowmem
+is the amount of memory allocated below 4GB in the guest's physical address
+space.
+.Pp
+The default value of
+.Ar lowmem
+is 256MB.
+.It Fl M Ar highmem
+.Ar highmem
+is the amount of memory allocated above 4GB in the guest's physical address
+space.
+.Pp
+The default value of
+.Ar highmem
+is 0MB.
+.It Fl d Ar disk-path
+The
+.Ar disk-path
+is the pathname of the guest's boot disk image.
+.It Fl h Ar host-path
+The
+.Ar host-path
+is the directory at the top of the guest's boot filesystem.
+.El
+.Sh EXAMPLES
+To create a virtual machine named
+.Ar freebsd-vm
+that boots off the ISO image
+.Pa /freebsd/release.iso
+and has 1GB memory allocated to it:
+.Pp
+.Dl "bhyveload -m 256 -M 768 -d /freebsd/release.iso freebsd-vm"
+.Pp
+In the example above the 1GB allocation is split in two segments:
+.Pp
+.Bl -dash -compact
+.It
+256MB below the 4GB boundary (0MB - 256MB)
+.It
+768MB above the 4GB boundary (4096MB - 4864MB)
+.El
+.Sh SEE ALSO
+.Xr bhyve 4 ,
+.Xr bhyve 8 ,
+.Xr loader 8 ,
+.Xr vmm 4
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 10.0 ,
+and was developed at NetApp Inc.
+.Sh AUTHORS
+.Nm
+was developed by
+.An -nosplit
+.An "Neel Natu" Aq neel@FreeBSD.org
+at NetApp Inc with a lot of help from
+.An Doug Rabson Aq dfr@FreeBSD.org
+.Sh BUGS
+.Nm
+can only load
+.Fx
+as a guest.
diff --git a/usr.sbin/bhyveload/bhyveload.c b/usr.sbin/bhyveload/bhyveload.c
new file mode 100644
index 0000000..ef12d9f
--- /dev/null
+++ b/usr.sbin/bhyveload/bhyveload.c
@@ -0,0 +1,652 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/disk.h>
+
+#include <machine/specialreg.h>
+#include <machine/vmm.h>
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <vmmapi.h>
+
+#include "userboot.h"
+
+#define MB (1024 * 1024UL)
+#define GB (1024 * 1024 * 1024UL)
+#define BSP 0
+
+static char *host_base = "/";
+static struct termios term, oldterm;
+static int disk_fd = -1;
+
+static char *vmname, *progname, *membase;
+static uint64_t lowmem, highmem;
+static struct vmctx *ctx;
+
+static uint64_t gdtbase, cr3, rsp;
+
+static void cb_exit(void *arg, int v);
+
+/*
+ * Console i/o callbacks
+ */
+
+static void
+cb_putc(void *arg, int ch)
+{
+ char c = ch;
+
+ write(1, &c, 1);
+}
+
+static int
+cb_getc(void *arg)
+{
+ char c;
+
+ if (read(0, &c, 1) == 1)
+ return (c);
+ return (-1);
+}
+
+static int
+cb_poll(void *arg)
+{
+ int n;
+
+ if (ioctl(0, FIONREAD, &n) >= 0)
+ return (n > 0);
+ return (0);
+}
+
+/*
+ * Host filesystem i/o callbacks
+ */
+
+struct cb_file {
+ int cf_isdir;
+ size_t cf_size;
+ struct stat cf_stat;
+ union {
+ int fd;
+ DIR *dir;
+ } cf_u;
+};
+
+static int
+cb_open(void *arg, const char *filename, void **hp)
+{
+ struct stat st;
+ struct cb_file *cf;
+ char path[PATH_MAX];
+
+ if (!host_base)
+ return (ENOENT);
+
+ strlcpy(path, host_base, PATH_MAX);
+ if (path[strlen(path) - 1] == '/')
+ path[strlen(path) - 1] = 0;
+ strlcat(path, filename, PATH_MAX);
+ cf = malloc(sizeof(struct cb_file));
+ if (stat(path, &cf->cf_stat) < 0) {
+ free(cf);
+ return (errno);
+ }
+
+ cf->cf_size = st.st_size;
+ if (S_ISDIR(cf->cf_stat.st_mode)) {
+ cf->cf_isdir = 1;
+ cf->cf_u.dir = opendir(path);
+ if (!cf->cf_u.dir)
+ goto out;
+ *hp = cf;
+ return (0);
+ }
+ if (S_ISREG(cf->cf_stat.st_mode)) {
+ cf->cf_isdir = 0;
+ cf->cf_u.fd = open(path, O_RDONLY);
+ if (cf->cf_u.fd < 0)
+ goto out;
+ *hp = cf;
+ return (0);
+ }
+
+out:
+ free(cf);
+ return (EINVAL);
+}
+
+static int
+cb_close(void *arg, void *h)
+{
+ struct cb_file *cf = h;
+
+ if (cf->cf_isdir)
+ closedir(cf->cf_u.dir);
+ else
+ close(cf->cf_u.fd);
+ free(cf);
+
+ return (0);
+}
+
+static int
+cb_isdir(void *arg, void *h)
+{
+ struct cb_file *cf = h;
+
+ return (cf->cf_isdir);
+}
+
+static int
+cb_read(void *arg, void *h, void *buf, size_t size, size_t *resid)
+{
+ struct cb_file *cf = h;
+ ssize_t sz;
+
+ if (cf->cf_isdir)
+ return (EINVAL);
+ sz = read(cf->cf_u.fd, buf, size);
+ if (sz < 0)
+ return (EINVAL);
+ *resid = size - sz;
+ return (0);
+}
+
+static int
+cb_readdir(void *arg, void *h, uint32_t *fileno_return, uint8_t *type_return,
+ size_t *namelen_return, char *name)
+{
+ struct cb_file *cf = h;
+ struct dirent *dp;
+
+ if (!cf->cf_isdir)
+ return (EINVAL);
+
+ dp = readdir(cf->cf_u.dir);
+ if (!dp)
+ return (ENOENT);
+
+ /*
+ * Note: d_namlen is in the range 0..255 and therefore less
+ * than PATH_MAX so we don't need to test before copying.
+ */
+ *fileno_return = dp->d_fileno;
+ *type_return = dp->d_type;
+ *namelen_return = dp->d_namlen;
+ memcpy(name, dp->d_name, dp->d_namlen);
+ name[dp->d_namlen] = 0;
+
+ return (0);
+}
+
+static int
+cb_seek(void *arg, void *h, uint64_t offset, int whence)
+{
+ struct cb_file *cf = h;
+
+ if (cf->cf_isdir)
+ return (EINVAL);
+ if (lseek(cf->cf_u.fd, offset, whence) < 0)
+ return (errno);
+ return (0);
+}
+
+static int
+cb_stat(void *arg, void *h, int *mode, int *uid, int *gid, uint64_t *size)
+{
+ struct cb_file *cf = h;
+
+ *mode = cf->cf_stat.st_mode;
+ *uid = cf->cf_stat.st_uid;
+ *gid = cf->cf_stat.st_gid;
+ *size = cf->cf_stat.st_size;
+ return (0);
+}
+
+/*
+ * Disk image i/o callbacks
+ */
+
+static int
+cb_diskread(void *arg, int unit, uint64_t from, void *to, size_t size,
+ size_t *resid)
+{
+ ssize_t n;
+
+ if (unit != 0 || disk_fd == -1)
+ return (EIO);
+ n = pread(disk_fd, to, size, from);
+ if (n < 0)
+ return (errno);
+ *resid = size - n;
+ return (0);
+}
+
+static int
+cb_diskioctl(void *arg, int unit, u_long cmd, void *data)
+{
+ struct stat sb;
+
+ if (unit != 0 || disk_fd == -1)
+ return (EBADF);
+
+ switch (cmd) {
+ case DIOCGSECTORSIZE:
+ *(u_int *)data = 512;
+ break;
+ case DIOCGMEDIASIZE:
+ if (fstat(disk_fd, &sb) == 0)
+ *(off_t *)data = sb.st_size;
+ else
+ return (ENOTTY);
+ break;
+ default:
+ return (ENOTTY);
+ }
+
+ return (0);
+}
+
+/*
+ * Guest virtual machine i/o callbacks
+ */
+static int
+cb_copyin(void *arg, const void *from, uint64_t to, size_t size)
+{
+
+ to &= 0x7fffffff;
+ if (to > lowmem)
+ return (EFAULT);
+ if (to + size > lowmem)
+ size = lowmem - to;
+
+ memcpy(&membase[to], from, size);
+
+ return (0);
+}
+
+static int
+cb_copyout(void *arg, uint64_t from, void *to, size_t size)
+{
+
+ from &= 0x7fffffff;
+ if (from > lowmem)
+ return (EFAULT);
+ if (from + size > lowmem)
+ size = lowmem - from;
+
+ memcpy(to, &membase[from], size);
+
+ return (0);
+}
+
+static void
+cb_setreg(void *arg, int r, uint64_t v)
+{
+ int error;
+ enum vm_reg_name vmreg;
+
+ vmreg = VM_REG_LAST;
+
+ switch (r) {
+ case 4:
+ vmreg = VM_REG_GUEST_RSP;
+ rsp = v;
+ break;
+ default:
+ break;
+ }
+
+ if (vmreg == VM_REG_LAST) {
+ printf("test_setreg(%d): not implemented\n", r);
+ cb_exit(NULL, USERBOOT_EXIT_QUIT);
+ }
+
+ error = vm_set_register(ctx, BSP, vmreg, v);
+ if (error) {
+ perror("vm_set_register");
+ cb_exit(NULL, USERBOOT_EXIT_QUIT);
+ }
+}
+
+static void
+cb_setmsr(void *arg, int r, uint64_t v)
+{
+ int error;
+ enum vm_reg_name vmreg;
+
+ vmreg = VM_REG_LAST;
+
+ switch (r) {
+ case MSR_EFER:
+ vmreg = VM_REG_GUEST_EFER;
+ break;
+ default:
+ break;
+ }
+
+ if (vmreg == VM_REG_LAST) {
+ printf("test_setmsr(%d): not implemented\n", r);
+ cb_exit(NULL, USERBOOT_EXIT_QUIT);
+ }
+
+ error = vm_set_register(ctx, BSP, vmreg, v);
+ if (error) {
+ perror("vm_set_msr");
+ cb_exit(NULL, USERBOOT_EXIT_QUIT);
+ }
+}
+
+static void
+cb_setcr(void *arg, int r, uint64_t v)
+{
+ int error;
+ enum vm_reg_name vmreg;
+
+ vmreg = VM_REG_LAST;
+
+ switch (r) {
+ case 0:
+ vmreg = VM_REG_GUEST_CR0;
+ break;
+ case 3:
+ vmreg = VM_REG_GUEST_CR3;
+ cr3 = v;
+ break;
+ case 4:
+ vmreg = VM_REG_GUEST_CR4;
+ break;
+ default:
+ break;
+ }
+
+ if (vmreg == VM_REG_LAST) {
+ printf("test_setcr(%d): not implemented\n", r);
+ cb_exit(NULL, USERBOOT_EXIT_QUIT);
+ }
+
+ error = vm_set_register(ctx, BSP, vmreg, v);
+ if (error) {
+ perror("vm_set_cr");
+ cb_exit(NULL, USERBOOT_EXIT_QUIT);
+ }
+}
+
+static void
+cb_setgdt(void *arg, uint64_t base, size_t size)
+{
+ int error;
+
+ error = vm_set_desc(ctx, BSP, VM_REG_GUEST_GDTR, base, size - 1, 0);
+ if (error != 0) {
+ perror("vm_set_desc(gdt)");
+ cb_exit(NULL, USERBOOT_EXIT_QUIT);
+ }
+
+ gdtbase = base;
+}
+
+static void
+cb_exec(void *arg, uint64_t rip)
+{
+ int error;
+
+ error = vm_setup_freebsd_registers(ctx, BSP, rip, cr3, gdtbase, rsp);
+ if (error) {
+ perror("vm_setup_freebsd_registers");
+ cb_exit(NULL, USERBOOT_EXIT_QUIT);
+ }
+
+ cb_exit(NULL, 0);
+}
+
+/*
+ * Misc
+ */
+
+static void
+cb_delay(void *arg, int usec)
+{
+
+ usleep(usec);
+}
+
+static void
+cb_exit(void *arg, int v)
+{
+
+ tcsetattr(0, TCSAFLUSH, &oldterm);
+ exit(v);
+}
+
+static void
+cb_getmem(void *arg, uint64_t *ret_lowmem, uint64_t *ret_highmem)
+{
+
+ *ret_lowmem = lowmem;
+ *ret_highmem = highmem;
+}
+
+static const char *
+cb_getenv(void *arg, int num)
+{
+ int max;
+
+ static const char * var[] = {
+ "smbios.bios.vendor=BHYVE",
+ "boot_serial=1",
+ NULL
+ };
+
+ max = sizeof(var) / sizeof(var[0]);
+
+ if (num < max)
+ return (var[num]);
+ else
+ return (NULL);
+}
+
+static struct loader_callbacks cb = {
+ .getc = cb_getc,
+ .putc = cb_putc,
+ .poll = cb_poll,
+
+ .open = cb_open,
+ .close = cb_close,
+ .isdir = cb_isdir,
+ .read = cb_read,
+ .readdir = cb_readdir,
+ .seek = cb_seek,
+ .stat = cb_stat,
+
+ .diskread = cb_diskread,
+ .diskioctl = cb_diskioctl,
+
+ .copyin = cb_copyin,
+ .copyout = cb_copyout,
+ .setreg = cb_setreg,
+ .setmsr = cb_setmsr,
+ .setcr = cb_setcr,
+ .setgdt = cb_setgdt,
+ .exec = cb_exec,
+
+ .delay = cb_delay,
+ .exit = cb_exit,
+ .getmem = cb_getmem,
+
+ .getenv = cb_getenv,
+};
+
+static void
+usage(void)
+{
+
+ printf("usage: %s [-d <disk image path>] [-h <host filesystem path>] "
+ "[-m <lowmem>][-M <highmem>] "
+ "<vmname>\n", progname);
+ exit(1);
+}
+
+int
+main(int argc, char** argv)
+{
+ void *h;
+ void (*func)(struct loader_callbacks *, void *, int, int);
+ int opt, error;
+ char *disk_image;
+
+ progname = argv[0];
+
+ lowmem = 128 * MB;
+ highmem = 0;
+ disk_image = NULL;
+
+ while ((opt = getopt(argc, argv, "d:h:m:M:")) != -1) {
+ switch (opt) {
+ case 'd':
+ disk_image = optarg;
+ break;
+
+ case 'h':
+ host_base = optarg;
+ break;
+
+ case 'm':
+ lowmem = strtoul(optarg, NULL, 0) * MB;
+ break;
+
+ case 'M':
+ highmem = strtoul(optarg, NULL, 0) * MB;
+ break;
+
+ case '?':
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ vmname = argv[0];
+
+ error = vm_create(vmname);
+ if (error != 0 && errno != EEXIST) {
+ perror("vm_create");
+ exit(1);
+
+ }
+
+ ctx = vm_open(vmname);
+ if (ctx == NULL) {
+ perror("vm_open");
+ exit(1);
+ }
+
+ error = vm_setup_memory(ctx, 0, lowmem, &membase);
+ if (error) {
+ perror("vm_setup_memory(lowmem)");
+ exit(1);
+ }
+
+ if (highmem != 0) {
+ error = vm_setup_memory(ctx, 4 * GB, highmem, NULL);
+ if (error) {
+ perror("vm_setup_memory(highmem)");
+ exit(1);
+ }
+ }
+
+ tcgetattr(0, &term);
+ oldterm = term;
+ term.c_lflag &= ~(ICANON|ECHO);
+ term.c_iflag &= ~ICRNL;
+ tcsetattr(0, TCSAFLUSH, &term);
+ h = dlopen("/boot/userboot.so", RTLD_LOCAL);
+ if (!h) {
+ printf("%s\n", dlerror());
+ return (1);
+ }
+ func = dlsym(h, "loader_main");
+ if (!func) {
+ printf("%s\n", dlerror());
+ return (1);
+ }
+
+ if (disk_image) {
+ disk_fd = open(disk_image, O_RDONLY);
+ }
+ func(&cb, NULL, USERBOOT_VERSION_3, disk_fd >= 0);
+}
diff --git a/usr.sbin/bsdconfig/bsdconfig b/usr.sbin/bsdconfig/bsdconfig
index 436b8a4..07b73fe 100755
--- a/usr.sbin/bsdconfig/bsdconfig
+++ b/usr.sbin/bsdconfig/bsdconfig
@@ -192,6 +192,7 @@ dialog_menu_main()
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_exit_bsdconfig\" \
--help-button \
+ --help-label \"\$msg_help\" \
${USE_XDIALOG:+--help \"\"} \
--menu \"\$prompt\" $size $menu_list \
2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
diff --git a/usr.sbin/bsdconfig/console/ttys b/usr.sbin/bsdconfig/console/ttys
index e1650da..3f9945e 100755
--- a/usr.sbin/bsdconfig/console/ttys
+++ b/usr.sbin/bsdconfig/console/ttys
@@ -192,7 +192,7 @@ while :; do
err=$( ttys_set_type "$consterm" 2>&1 )
[ "$err" ] || break
- f_show_msg "%s" "$err"
+ f_dialog_msgbox "$err"
done
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr
index f77a5e7..23ac83b 100644
--- a/usr.sbin/bsdconfig/networking/share/device.subr
+++ b/usr.sbin/bsdconfig/networking/share/device.subr
@@ -343,6 +343,7 @@ f_dialog_menu_netdev_edit()
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
--help-button \
+ --help-label \"\$msg_help\" \
${USE_XDIALOG:+--help \"\"} \
--menu \"\$prompt\" $size \
$menu_list \
@@ -455,9 +456,8 @@ f_dialog_menu_netdev_edit()
# Re/Apply the settings if desired
#
if [ ! "$dhcp" ]; then
- f_dialog_yesno "Would you like to bring the $interface" \
- "interface up right now?"
- if [ $? -eq $SUCCESS ]; then
+ if f_yesno "$msg_bring_interface_up" "$interface"
+ then
f_show_info "$msg_bring_interface_up" "$interface"
local dr="$( f_sysrc_get defaultrouter )" err
diff --git a/usr.sbin/bsdconfig/networking/share/hostname.subr b/usr.sbin/bsdconfig/networking/share/hostname.subr
index 959c7df..b276059 100644
--- a/usr.sbin/bsdconfig/networking/share/hostname.subr
+++ b/usr.sbin/bsdconfig/networking/share/hostname.subr
@@ -201,10 +201,8 @@ f_dialog_input_hostname()
f_show_msg "$msg_activate_hostname_x11warning" \
"$( hostname )" "$hostname"
else
- f_dialog_yesno "$(
- printf "$msg_activate_hostname" \
- "$( hostname )" "$hostname" \
- )" \
+ f_yesno "$msg_activate_hostname" \
+ "$( hostname )" "$hostname" \
&& hostname "$hostname"
fi
fi
diff --git a/usr.sbin/bsdconfig/networking/share/routing.subr b/usr.sbin/bsdconfig/networking/share/routing.subr
index 3990c03..4207ab2 100644
--- a/usr.sbin/bsdconfig/networking/share/routing.subr
+++ b/usr.sbin/bsdconfig/networking/share/routing.subr
@@ -129,11 +129,8 @@ f_dialog_input_defaultrouter()
#
if [ "$( f_route_get_default )" != "$defaultrouter" ]; then
f_dialog_clear
- f_dialog_yesno "$(
- printf "$msg_activate_default_router" \
- "$( f_route_get_default )" "$defaultrouter"
- )"
-
+ f_yesno "$msg_activate_default_router" \
+ "$( f_route_get_default )" "$defaultrouter"
if [ $? -eq $SUCCESS ]; then
local err
diff --git a/usr.sbin/bsdconfig/password/password b/usr.sbin/bsdconfig/password/password
index 6b9e57d..50d963d 100755
--- a/usr.sbin/bsdconfig/password/password
+++ b/usr.sbin/bsdconfig/password/password
@@ -72,7 +72,7 @@ f_mustberoot_init
if f_dialog_input_password; then
err=$( echo "$pw_password" | pw usermod $USER_ROOT -h 0 2>&1 ) ||
f_die $? "%s" "$err"
- f_show_msg "$msg_password_changed"
+ f_dialog_msgbox "$msg_password_changed"
fi
return $SUCCESS
diff --git a/usr.sbin/bsdconfig/password/share/password.subr b/usr.sbin/bsdconfig/password/share/password.subr
index bf83df7..f4ebaab9 100644
--- a/usr.sbin/bsdconfig/password/share/password.subr
+++ b/usr.sbin/bsdconfig/password/share/password.subr
@@ -108,13 +108,13 @@ f_dialog_input_password()
# Check for NULL entry
if ! [ "$_password1" -o "$_password2" ]; then
- f_show_msg "$msg_password_is_empty"
+ f_dialog_msgbox "$msg_password_is_empty"
continue
fi
# Check for password mismatch
if [ "$_password1" != "$_password2" ]; then
- f_show_msg "$msg_passwords_do_not_match"
+ f_dialog_msgbox "$msg_passwords_do_not_match"
continue
fi
diff --git a/usr.sbin/bsdconfig/security/kern_securelevel b/usr.sbin/bsdconfig/security/kern_securelevel
index 67fd1aa..42594c6 100755
--- a/usr.sbin/bsdconfig/security/kern_securelevel
+++ b/usr.sbin/bsdconfig/security/kern_securelevel
@@ -78,6 +78,7 @@ dialog_menu_main()
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
--help-button \
+ --help-label \"\$msg_help\" \
${USE_XDIALOG:+--help \"\"} \
--menu \"\$prompt\" $size \
$menu_list \
diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr
index 05531aa..c66a54f 100644
--- a/usr.sbin/bsdconfig/share/common.subr
+++ b/usr.sbin/bsdconfig/share/common.subr
@@ -214,6 +214,50 @@ f_show_msg()
fi
}
+
+# f_yesno $fmt [ $opts ... ]
+#
+# Display a message in a dialog yes/no box using printf(1) syntax.
+#
+f_yesno()
+{
+ local msg
+ msg=$( printf "$@" )
+
+ #
+ # Use f_dialog_yesno from dialog.subr if possible, otherwise fall
+ # back to dialog(1) (without options, making it obvious when using
+ # un-aided system dialog).
+ #
+ if f_have f_dialog_yesno; then
+ f_dialog_yesno "$msg"
+ else
+ dialog --yesno "$msg" 0 0
+ fi
+}
+
+# f_noyes $fmt [ $opts ... ]
+#
+# Display a message in a dialog yes/no box using printf(1) syntax.
+# NOTE: THis is just like the f_yesno function except "No" is default.
+#
+f_noyes()
+{
+ local msg
+ msg=$( printf "$@" )
+
+ #
+ # Use f_dialog_noyes from dialog.subr if possible, otherwise fall
+ # back to dialog(1) (without options, making it obvious when using
+ # un-aided system dialog).
+ #
+ if f_have f_dialog_noyes; then
+ f_dialog_noyes "$msg"
+ else
+ dialog --defaultno --yesno "$msg" 0 0
+ fi
+}
+
# f_show_help $file
#
# Display a language help-file. Automatically takes $LANG and $LC_ALL into
diff --git a/usr.sbin/bsdconfig/share/mustberoot.subr b/usr.sbin/bsdconfig/share/mustberoot.subr
index ebce9c1..2ead592 100644
--- a/usr.sbin/bsdconfig/share/mustberoot.subr
+++ b/usr.sbin/bsdconfig/share/mustberoot.subr
@@ -128,7 +128,7 @@ f_become_root_via_sudo()
1) # Always try sudo(8) when run as $user
local err
if ! err=$( touch "$checkpath" 2>&1 ); then
- f_show_msg "%s" "$err"
+ f_dialog_msgbox "$err"
else
f_show_msg "$msg_created_path" "$checkpath"
fi
diff --git a/usr.sbin/bsdconfig/share/script.subr b/usr.sbin/bsdconfig/share/script.subr
index d5a2e93..84d1cab 100644
--- a/usr.sbin/bsdconfig/share/script.subr
+++ b/usr.sbin/bsdconfig/share/script.subr
@@ -100,7 +100,7 @@ f_dispatch()
#
f_script_load()
{
- local script="$1" config_file
+ local script="$1" config_file retval=$SUCCESS
f_dprintf "f_script_load: script=[%s]" "$script"
if [ ! "$script" ]; then
@@ -113,9 +113,18 @@ f_script_load()
; do
[ -e "$script" ] && break
done
- elif [ "$script" = "-" ]; then
+ fi
+
+ local old_interactive=
+ f_getvar $VAR_NONINTERACTIVE old_interactive # save a copy
+
+ # Hint to others that we're running from a script, should they care
+ setvar $VAR_NONINTERACTIVE yes
+
+ if [ "$script" = "-" ]; then
f_dprintf "f_script_load: Loading script from stdin"
eval "$( cat )"
+ retval=$?
else
f_dprintf "f_script_load: Loading script \`%s'" "$script"
if [ ! -e "$script" ]; then
@@ -123,7 +132,13 @@ f_script_load()
return $FAILURE
fi
. "$script"
+ retval=$?
fi
+
+ [ "$old_interactive" ] &&
+ setvar $VAR_NONINTERACTIVE "$old_interactive"
+
+ return $retval
}
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/share/variable.subr b/usr.sbin/bsdconfig/share/variable.subr
index f63a5f8..235f6dc 100644
--- a/usr.sbin/bsdconfig/share/variable.subr
+++ b/usr.sbin/bsdconfig/share/variable.subr
@@ -118,7 +118,7 @@ f_variable_set_defaults()
#
# Dump a list of registered/advertised variables and their respective values to
# $VARIABLE_DUMPFILE. Returns success unless the file couldn't be written. If
-# an error occurs, it is displayed using f_show_msg() (from common.subr).
+# an error occurs, it is displayed using f_dialog_msgbox() (from dialog.subr).
#
f_dump_variables()
{
@@ -131,7 +131,7 @@ f_dump_variables()
printf "%s='%s'\n" "$var" "$value"
done > "$VARIABLE_DUMPFILE" ) 2>&1
); then
- f_show_msg "%s" "$err"
+ f_dialog_msgbox "$err"
return $FAILURE
fi
}
diff --git a/usr.sbin/bsdconfig/startup/misc b/usr.sbin/bsdconfig/startup/misc
index 626697a..37bb80f 100755
--- a/usr.sbin/bsdconfig/startup/misc
+++ b/usr.sbin/bsdconfig/startup/misc
@@ -307,14 +307,14 @@ while :; do
?" [X] "*) err=$( f_sysrc_set apm_enable NO 2>&1 ) ;;
?" [ ] "*) err=$( f_sysrc_set apm_enable YES 2>&1 ) ;;
esac
- [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+ [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;;
?" ["?"] $msg_startup_dirs")
dialog_input_value \
"$msg_startup_dirs_desc" \
"$( f_sysrc_get local_startup )"
if [ $? -eq $SUCCESS ]; then
err=$( f_sysrc_set local_startup "$value" ) ||
- f_show_msg "%s\n" "$err"
+ f_dialog_msgbox "$err\n"
fi
;;
?" ["?"] $msg_named")
@@ -322,14 +322,14 @@ while :; do
?" [X] "*) err=$( f_sysrc_set named_enable NO 2>&1 ) ;;
?" [ ] "*) err=$( f_sysrc_set named_enable YES 2>&1 ) ;;
esac
- [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+ [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;;
?" ["?"] $msg_named_flags")
dialog_input_value \
"$msg_named_flags_desc" \
"$( f_sysrc_get named_flags )"
if [ $? -eq $SUCCESS ]; then
err=$( f_sysrc_set named_flags "$value" ) ||
- f_show_msg "%s\n" "$err"
+ f_dialog_msgbox "$err\n"
fi
;;
?" ["?"] $msg_nis_client")
@@ -339,14 +339,14 @@ while :; do
err=$( f_sysrc_set nis_client_enable YES 2>&1 ) \
&& err=$( f_sysrc_set rpcbind_enable YES 2>&1 ) ;;
esac
- [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+ [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;;
?" ["?"] $msg_nis_domainname")
dialog_input_value \
"$msg_nis_domainname_desc" \
"$( f_sysrc_get nisdomainname )"
if [ $? -eq $SUCCESS ]; then
err=$( f_sysrc_set nisdomainname "$value" ) ||
- f_show_msg "%s\n" "$err"
+ f_dialog_msgbox "$err\n"
fi
;;
?" ["?"] $msg_nis_server")
@@ -356,31 +356,31 @@ while :; do
err=$( f_sysrc_set nis_server_enable YES 2>&1 ) \
&& err=$( f_sysrc_set rpcbind_enable YES 2>&1 ) ;;
esac
- [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+ [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;;
?" ["?"] $msg_accounting")
case "$mtag" in
?" [X] "*) err=$( f_sysrc_set accounting_enable NO 2>&1 ) ;;
?" [ ] "*) err=$( f_sysrc_set accounting_enable YES 2>&1 ) ;;
esac
- [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+ [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;;
?" ["?"] $msg_lpd")
case "$mtag" in
?" [X] "*) err=$( f_sysrc_set lpd_enable NO 2>&1 ) ;;
?" [ ] "*) err=$( f_sysrc_set lpd_enable YES 2>&1 ) ;;
esac
- [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+ [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;;
?" ["?"] $msg_sco")
case "$mtag" in
?" [X] "*) err=$( f_sysrc_set ibcs2_enable NO 2>&1 ) ;;
?" [ ] "*) err=$( f_sysrc_set ibcs2_enable YES 2>&1 ) ;;
esac
- [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+ [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;;
?" ["?"] $msg_svr4")
case "$mtag" in
?" [X] "*) err=$( f_sysrc_set svr4_enable NO 2>&1 ) ;;
?" [ ] "*) err=$( f_sysrc_set svr4_enable YES 2>&1 ) ;;
esac
- [ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+ [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" ;;
esac
done
diff --git a/usr.sbin/bsdconfig/startup/rcdelete b/usr.sbin/bsdconfig/startup/rcdelete
index 02ec049..578b13e 100755
--- a/usr.sbin/bsdconfig/startup/rcdelete
+++ b/usr.sbin/bsdconfig/startup/rcdelete
@@ -210,9 +210,7 @@ dialog_menu_delete()
[ $# -ge 1 ] || return $FAILURE
if [ $# -eq 1 ]; then
- msg=$( printf "$msg_are_you_sure_you_want_to_delete" \
- "$delete_vars" )
- f_dialog_noyes "$msg"
+ f_noyes "$msg_are_you_sure_you_want_to_delete" "$delete_vars"
return $?
fi
@@ -320,7 +318,7 @@ while :; do
for var in $delete_vars; do
err=$( f_sysrc_delete $var 2>&1 )
if [ $? -ne $SUCCESS ]; then
- f_show_msg "%s\n" "$err"
+ f_dialog_msgbox "$err\n"
break
fi
done
diff --git a/usr.sbin/bsdconfig/startup/rcvar b/usr.sbin/bsdconfig/startup/rcvar
index 8f27b51..d7ced9e 100755
--- a/usr.sbin/bsdconfig/startup/rcvar
+++ b/usr.sbin/bsdconfig/startup/rcvar
@@ -194,7 +194,7 @@ while :; do
esac
err=$( f_sysrc_set "$rcvar" "$value" 2>&1 ) ||
- f_show_msg "$err"
+ f_dialog_msgbox "$err"
esac
done
diff --git a/usr.sbin/bsdconfig/startup/share/rcconf.subr b/usr.sbin/bsdconfig/startup/share/rcconf.subr
index 8878d2c..12eafd9 100644
--- a/usr.sbin/bsdconfig/startup/share/rcconf.subr
+++ b/usr.sbin/bsdconfig/startup/share/rcconf.subr
@@ -432,14 +432,14 @@ f_dialog_input_rcvar()
# Check for invalid entry (1of2)
if ! echo "$_input" | grep -q "^[[:alpha:]_]"; then
- f_show_msg "$msg_rcvar_must_start_with"
+ f_dialog_msgbox "$msg_rcvar_must_start_with"
continue
fi
# Check for invalid entry (2of2)
if ! echo "$_input" | grep -q "^[[:alpha:]_][[:alnum:]_]*$"
then
- f_show_msg "$msg_rcvar_contains_invalid_chars"
+ f_dialog_msgbox "$msg_rcvar_contains_invalid_chars"
continue
fi
diff --git a/usr.sbin/bsdconfig/startup/share/rcedit.subr b/usr.sbin/bsdconfig/startup/share/rcedit.subr
index a9cba88..cb4a411 100644
--- a/usr.sbin/bsdconfig/startup/share/rcedit.subr
+++ b/usr.sbin/bsdconfig/startup/share/rcedit.subr
@@ -78,8 +78,7 @@ f_dialog_rcedit()
f_dprintf "%s: [%s]->[%s]" "$var" "$cur_val" "$_input"
- err=$( f_sysrc_set "$var" "$_input" 2>&1 ) ||
- f_show_msg "$err"
+ err=$( f_sysrc_set "$var" "$_input" 2>&1 ) || f_dialog_msgbox "$err"
}
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/usermgmt/groupinput b/usr.sbin/bsdconfig/usermgmt/groupinput
index 83d0c1d..c459224 100755
--- a/usr.sbin/bsdconfig/usermgmt/groupinput
+++ b/usr.sbin/bsdconfig/usermgmt/groupinput
@@ -63,10 +63,10 @@ save_changes()
err=$( pw groupdel "$group_name" 2>&1 )
retval=$?
if [ $retval -ne $SUCCESS ]; then
- f_show_msg "%s %s\n" "$msg_error" "$err"
+ f_dialog_msgbox "$msg_error $err\n"
return $retval
fi
- f_show_msg "$msg_group_deleted"
+ f_dialog_msgbox "$msg_group_deleted"
;;
Add)
local cmd="pw groupadd -n '$group_name'"
@@ -82,10 +82,10 @@ save_changes()
err=$( eval $cmd 2>&1 )
retval=$?
if [ $retval -ne $SUCCESS ]; then
- f_show_msg "%s %s\n" "$msg_error" "$err"
+ f_dialog_msgbox "$msg_error $err\n"
return $retval
fi
- f_show_msg "$msg_group_added"
+ f_dialog_msgbox "$msg_group_added"
;;
Edit/View)
local cmd="pw groupmod -n '$group_name'"
@@ -101,10 +101,10 @@ save_changes()
err=$( eval $cmd 2>&1 )
retval=$?
if [ $retval -ne $SUCCESS ]; then
- f_show_msg "%s %s\n" "$msg_error" "$err"
+ f_dialog_msgbox "$msg_error $err\n"
return $retval
fi
- f_show_msg "$msg_group_updated"
+ f_dialog_msgbox "$msg_group_updated"
;;
esac
diff --git a/usr.sbin/bsdconfig/usermgmt/share/group_input.subr b/usr.sbin/bsdconfig/usermgmt/share/group_input.subr
index 4b47392..278e0a4 100644
--- a/usr.sbin/bsdconfig/usermgmt/share/group_input.subr
+++ b/usr.sbin/bsdconfig/usermgmt/share/group_input.subr
@@ -134,13 +134,13 @@ f_dialog_input_group_name()
# Check for NULL entry
if [ ! "$_input" ]; then
- f_show_msg "$msg_group_is_empty"
+ f_dialog_msgbox "$msg_group_is_empty"
continue
fi
# Check for invalid entry
if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
- f_show_msg "$msg_group_must_start_with_letter"
+ f_dialog_msgbox "$msg_group_must_start_with_letter"
continue
fi
@@ -229,7 +229,7 @@ f_dialog_input_group_password()
# Check for password mismatch
if [ "$_password1" != "$_password2" ]; then
- f_show_msg "$msg_group_passwords_do_not_match"
+ f_dialog_msgbox "$msg_group_passwords_do_not_match"
continue
fi
diff --git a/usr.sbin/bsdconfig/usermgmt/share/user_input.subr b/usr.sbin/bsdconfig/usermgmt/share/user_input.subr
index d0b5fe3..e0281ed 100644
--- a/usr.sbin/bsdconfig/usermgmt/share/user_input.subr
+++ b/usr.sbin/bsdconfig/usermgmt/share/user_input.subr
@@ -239,13 +239,13 @@ f_dialog_input_name()
# Check for NULL entry
if [ ! "$_input" ]; then
- f_show_msg "$msg_login_is_empty"
+ f_dialog_msgbox "$msg_login_is_empty"
continue
fi
# Check for invalid entry
if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
- f_show_msg "$msg_login_must_start_with_letter"
+ f_dialog_msgbox "$msg_login_must_start_with_letter"
continue
fi
@@ -334,7 +334,7 @@ f_dialog_input_password()
# Check for password mismatch
if [ "$_password1" != "$_password2" ]; then
- f_show_msg "$msg_passwords_do_not_match"
+ f_dialog_msgbox "$msg_passwords_do_not_match"
continue
fi
@@ -589,7 +589,7 @@ f_dialog_input_change()
# Taint-check the user's input
if ! f_isinteger "$ret_days"; then
- f_show_msg "$msg_invalid_number_of_days"
+ f_dialog_msgbox "$msg_invalid_number_of_days"
continue
fi
@@ -616,7 +616,8 @@ f_dialog_input_change()
# Taint-check the user's input
if ! f_isinteger "${_input:-0}"; then
- f_show_msg "$msg_invalid_number_of_seconds"
+ f_dialog_msgbox \
+ "$msg_invalid_number_of_seconds"
continue
fi
@@ -773,7 +774,7 @@ f_dialog_input_expire()
# Taint-check the user's input
if ! f_isinteger "$ret_days"; then
- f_show_msg "$msg_invalid_number_of_days"
+ f_dialog_msgbox "$msg_invalid_number_of_days"
continue
fi
@@ -800,7 +801,8 @@ f_dialog_input_expire()
# Taint-check the user's input
if ! f_isinteger "${_input:-0}"; then
- f_show_msg "$msg_invalid_number_of_seconds"
+ f_dialog_msgbox \
+ "$msg_invalid_number_of_seconds"
continue
fi
diff --git a/usr.sbin/bsdconfig/usermgmt/userinput b/usr.sbin/bsdconfig/usermgmt/userinput
index 36c43e1..ad62a09 100755
--- a/usr.sbin/bsdconfig/usermgmt/userinput
+++ b/usr.sbin/bsdconfig/usermgmt/userinput
@@ -81,22 +81,22 @@ save_changes()
err=$( pw userdel -u "$pw_uid" 2>&1 )
retval=$?
if [ $retval -ne $SUCCESS ]; then
- f_show_msg "%s %s\n" "$msg_error" "$err"
+ f_dialog_msgbox "$msg_error $err\n"
return $retval
fi
- f_show_msg "$msg_login_deleted"
+ f_dialog_msgbox "$msg_login_deleted"
if [ "$pw_group_delete" = "$msg_yes" ] &&
f_quietly pw groupshow -g "$pw_gid"
then
err=$( pw groupdel -g "$pw_gid" 2>&1 ) ||
- f_show_msg "%s %s\n" "$msg_warning" "$err"
+ f_dialog_msgbox "$msg_warning $err\n"
fi
if [ "$pw_home_delete" = "$msg_yes" ]; then
f_dialog_info "$msg_deleting_home_directory"
err=$( rm -Rf "$pw_home_dir" 2>&1 ) ||
- f_show_msg "%s %s\n" "$msg_warning" "$err"
+ f_dialog_msgbox "$msg_warning $err\n"
fi
;;
Add)
@@ -119,26 +119,26 @@ save_changes()
err=$( eval $cmd 2>&1 )
retval=$?
if [ $retval -ne $SUCCESS ]; then
- f_show_msg "%s %s\n" "$msg_error" "$err"
+ f_dialog_msgbox "$msg_error $err\n"
return $retval
fi
- f_show_msg "$msg_login_added"
+ f_dialog_msgbox "$msg_login_added"
if [ "$pw_home_create" = "$msg_yes" ]; then
err=$( mkdir -p "$pw_home_dir" 2>&1 )
if [ $? -ne $SUCCESS ]; then
- f_show_msg "%s %s\n" "$msg_warning" "$err"
+ f_dialog_msgbox "$msg_warning $err\n"
elif [ -e "$pw_home_dir" ]; then
err=$( chown -R "$pw_uid:$pw_gid" \
"$pw_home_dir" 2>&1 )
- [ $? -eq $SUCCESS ] || f_show_msg \
- "%s %s\n" "$msg_warning" "$err"
+ [ $? -eq $SUCCESS ] ||
+ f_dialog_msgbox "$msg_warning $err\n"
fi
fi
if [ "$pw_dotfiles_create" = "$msg_yes" ]; then
err=$( copy_dotfiles 2>&1 ) ||
- f_show_msg "%s %s\n" "$msg_warning" "$err"
+ f_dialog_msgbox "$msg_warning $err\n"
fi
user="$pw_name"
@@ -165,26 +165,26 @@ save_changes()
err=$( eval $cmd 2>&1 )
retval=$?
if [ $retval -ne $SUCCESS ]; then
- f_show_msg "%s %s\n" "$msg_error" "$err"
+ f_dialog_msgbox "$msg_error $err\n"
return $retval
fi
- f_show_msg "$msg_login_updated"
+ f_dialog_msgbox "$msg_login_updated"
if [ "$pw_home_create" = "$msg_yes" ]; then
err=$( mkdir -p "$pw_home_dir" )
if [ $? -ne $SUCCESS ]; then
- f_show_msg "%s %s\n" "$msg_warning" "$err"
+ f_dialog_msgbox "$msg_warning $err\n"
elif [ -e "$pw_home_dir" ]; then
err=$( chown -R "$pw_uid:$pw_gid" \
"$pw_home_dir" 2>&1 )
- [ $? -eq $SUCCESS ] || f_show_msg \
- "%s %s\n" "$msg_warning" "$err"
+ [ $? -eq $SUCCESS ] ||
+ f_dialog_msgbox "$msg_warning $err\n"
fi
fi
if [ "$pw_dotfiles_create" = "$msg_yes" ]; then
err=$( copy_dotfiles 2>&1 ) ||
- f_show_msg "%s %s\n" "$msg_warning" "$err"
+ f_dialog_msgbox "$msg_warning $err\n"
fi
;;
esac
diff --git a/usr.sbin/bsdconfig/usermgmt/usermgmt b/usr.sbin/bsdconfig/usermgmt/usermgmt
index 5b69efd..5376bde 100755
--- a/usr.sbin/bsdconfig/usermgmt/usermgmt
+++ b/usr.sbin/bsdconfig/usermgmt/usermgmt
@@ -88,6 +88,7 @@ dialog_menu_main()
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
--help-button \
+ --help-label \"\$msg_help\" \
${USE_XDIALOG:+--help \"\"} \
--menu \"\" $size $menu_list \
2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
diff --git a/usr.sbin/bsdinstall/bsdinstall.8 b/usr.sbin/bsdinstall/bsdinstall.8
index 97033c9..095062f 100644
--- a/usr.sbin/bsdinstall/bsdinstall.8
+++ b/usr.sbin/bsdinstall/bsdinstall.8
@@ -1,5 +1,5 @@
.\"-
-.\" Copyright (c) 2011 Nathan Whitehorn <nwhitehorn@FreeBSD.org>
+.\" Copyright (c) 2011-2013 Nathan Whitehorn <nwhitehorn@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 11, 2011
+.Dd January 21, 2013
.Dt BSDINSTALL 8
.Os
.Sh NAME
@@ -52,9 +52,10 @@ can be invoked separately by an installation script.
.Sh TARGETS
Most of the following targets are only useful for scripting the installer.
For interactive use, most users will be interested only in the
-.Cm auto
+.Cm auto ,
+.Cm jail ,
and
-.Cm jail
+.Cm script
targets.
.Bl -tag -width ".Cm jail Ar destination"
.It Cm auto
@@ -68,6 +69,12 @@ Behavior is generally similar to
.Cm auto ,
except that disk partitioning and network setup are skipped and a kernel is
not installed into the new system.
+.It Cm script Ar script
+Runs the installation script at
+.Pa script .
+See
+.Sx SCRIPTING
+for more information on this target.
.It Cm keymap
If the current controlling TTY is a
.Xr syscons 4
@@ -104,11 +111,64 @@ partition schemes. Partitions disks, runs
.Xr newfs 8 ,
and writes the new system's
.Pa fstab .
+.It Cm scriptedpart Ar parameters
+Sets up disks like
+.Cm autopart
+and
+.Cm partedit ,
+but non-interactively according to the disk setup specified in
+.Ar parameters .
+Each disk setup is specified by a three-part argument:
+.Pp
+.Ar disk
+.Op Ar scheme
+.Op Ar {partitions}
+.Pp
+Multiple disk setups are separated by semicolons. The
+.Ar disk
+argument specifies the disk on which to operate (which will be erased),
+while the
+.Ar scheme
+argument specifies the
+.Xr gpart 8
+partition scheme to apply to the disk. If
+.Ar scheme
+is unspecified,
+.Cm scriptedpart
+will apply the default bootable scheme on your platform.
+The
+.Ar partitions
+argument is also optional and specifies how to partition
+.Ar disk .
+It consists of a comma-separated list of partitions to create enclosed in
+curly braces. Each partition declaration takes the form
+.Pp
+.Ar size
+.Ar type
+.Op Ar mount point
+.Pp
+.Ar size
+specifies the partition size to create in bytes (K, M, and G suffixes
+can be appended to specify kilobytes, megabytes, and gigabytes respectively),
+while the
+.Em auto
+keyword causes the partition to take all the remaining space on the disk. The
+.Ar type
+option chooses the
+.Xr gpart 8
+filesystem type (e.g. freebsd-ufs or freebsd-swap).
+The optional
+.Ar mount point
+argument sets where the created partition is to be mounted in the installed
+system. As an example, a typical invocation looks like:
+.Pp
+bsdinstall scriptedpart ada0 { 20G freebsd-ufs /, 4G freebsd-swap, 20G freebsd-ufs /var, auto freebsd-ufs /usr }
.It Cm mount
Mounts the file systems previously configured by
-.Cm autopart
+.Cm autopart ,
+.Cm partedit ,
or
-.Cm partedit
+.Cm scriptedpart
under
.Ev BSDINSTALL_CHROOT .
.It Cm distfetch
@@ -153,13 +213,27 @@ process. Many are used internally during installation and have reasonable
default values for most installation scenarios. Others are set by various
interactive user prompts, and can be usefully overridden when making scripted
or customized installers.
-.Bl -tag -width ".Ev BSDINSTALL_DISTDIR"
+.Bl -tag -width ".Ev BSDINSTALL_DISTSITE"
.It Ev DISTRIBUTIONS
The set of distributions to install (e.g. "base kernel ports"). Default: none
.It Ev BSDINSTALL_DISTDIR
The directory in which the distribution files can be found (or to which they
should be downloaded). Default:
.Pa /usr/freebsd-dist
+.It Ev BSDINSTALL_DISTSITE
+URL from which the distribution files should be downloaded if they are not
+already present in the directory defined by
+.Ev BSDINSTALL_DISTDIR .
+This should be a full path to the files, including architecture and release
+names. Most targets (e.g.
+.Cm auto
+and
+.Cm jail )
+that prompt for a
+.Fx
+mirror will skip that step if this variable is already defined in the
+environment. Example:
+.Pa ftp://ftp.freebsd.org/pub/FreeBSD/releases/powerpc/powerpc64/9.1-RELEASE
.It Ev BSDINSTALL_CHROOT
The directory into which the distribution files should be unpacked and the
directory at which the root file system of the new system should be mounted.
@@ -177,6 +251,67 @@ target is executed. If this directory does not already exist, it will be
created. Default:
.Pa /tmp/bsdinstall_etc
.El
+.Sh SCRIPTING
+.Nm
+scripts consist of two parts: a
+.Em preamble
+and a
+.Em setup script .
+The preamble sets up the options for the installation (how to partition the
+disk[s], which distributions to install, etc.) and the optional second part is
+a shell script run under
+.Xr chroot 8
+in the newly installed system before
+.Nm
+exits. The two parts are separated by the usual script header (#!), which
+also sets the interpreter for the setup script.
+.Pp
+A typical bsdinstall script looks like this:
+.Bd -literal -offset indent
+PARTITIONS=ada0
+DISTRIBUTIONS="kernel.txz base.txz"
+
+#!/bin/sh
+echo "ifconfig_em0=DHCP" >> /etc/rc.conf
+echo "sshd_enable=YES" >> /etc/rc.conf
+pkg install puppet
+.Ed
+.Pp
+On
+.Fx
+release media, such a script placed at
+.Pa /etc/installerconfig
+will be run at boot time and the system will be rebooted automatically after
+the installation has completed. This can be used for unattended network
+installation of new systems; see
+.Xr diskless 8
+for details.
+.Ss PREAMBLE
+The preamble consists of installer settings. These control global installation
+parameters (see
+.Sx ENVIRONMENT VARIABLES )
+as well as disk partitioning. The preamble is interpreted as a
+.Xr sh 1
+script run at the very beginning of the install. If more complicated behavior
+than setting these variables is desired, arbitrary commands can be run here
+to extend the installer. In addition to the variables in
+.Sx ENVIRONMENT VARIABLES ,
+in particular
+.Ev DISTRIBUTIONS ,
+the preamble can contain a variable
+.Ev PARTITIONS
+which is passed to the
+.Cm scriptedpart
+target to control disk setup.
+.Ss SETUP SCRIPT
+Following the preamble is an optional shell script, beginning with a #!
+declaration. This script will be run at the end of the installation process
+inside a
+.Xr chroot 8
+environment in the newly installed system and can be used to set up
+configuration files, install packages, etc. Note that newly configured
+system services (e.g. networking) have not been started in the installed
+system at this time and only installation host services are available.
.Sh HISTORY
This version of
.Nm
diff --git a/usr.sbin/bsdinstall/partedit/Makefile b/usr.sbin/bsdinstall/partedit/Makefile
index 21eaf91..b7f5097 100644
--- a/usr.sbin/bsdinstall/partedit/Makefile
+++ b/usr.sbin/bsdinstall/partedit/Makefile
@@ -2,7 +2,8 @@
BINDIR= /usr/libexec/bsdinstall
PROG= partedit
-LINKS= ${BINDIR}/partedit ${BINDIR}/autopart
+LINKS= ${BINDIR}/partedit ${BINDIR}/autopart \
+ ${BINDIR}/partedit ${BINDIR}/scriptedpart
SYMLINKS= ${BINDIR}/partedit /usr/sbin/sade
LDADD= -lgeom -lncursesw -lutil -ldialog -lm
@@ -15,7 +16,7 @@ PARTEDIT_ARCH= generic
.endif
SRCS= diskeditor.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \
- part_wizard.c
+ part_wizard.c scripted.c
WARNS?= 3
MAN= sade.8
diff --git a/usr.sbin/bsdinstall/partedit/diskeditor.c b/usr.sbin/bsdinstall/partedit/diskeditor.c
index 7933caa..9149c2b 100644
--- a/usr.sbin/bsdinstall/partedit/diskeditor.c
+++ b/usr.sbin/bsdinstall/partedit/diskeditor.c
@@ -77,7 +77,7 @@ diskeditor_show(const char *title, const char *cprompt,
int partlist_height, partlist_width;
int cur_scroll = 0;
int key, fkey;
- int cur_button = 0, cur_part = 0;
+ int cur_button = 5, cur_part = 0;
int result = DLG_EXIT_UNKNOWN;
static DLG_KEYS_BINDING binding[] = {
diff --git a/usr.sbin/bsdinstall/partedit/part_wizard.c b/usr.sbin/bsdinstall/partedit/part_wizard.c
index e840ac9..a304fb8 100644
--- a/usr.sbin/bsdinstall/partedit/part_wizard.c
+++ b/usr.sbin/bsdinstall/partedit/part_wizard.c
@@ -42,7 +42,6 @@
static char *boot_disk(struct gmesh *mesh);
static char *wizard_partition(struct gmesh *mesh, const char *disk);
-static int wizard_makeparts(struct gmesh *mesh, const char *disk);
int
part_wizard(void) {
@@ -71,7 +70,7 @@ startwizard:
dlg_put_backtitle();
error = geom_gettree(&mesh);
- error = wizard_makeparts(&mesh, schemeroot);
+ error = wizard_makeparts(&mesh, schemeroot, 1);
if (error)
goto startwizard;
free(schemeroot);
@@ -168,12 +167,6 @@ provider_for_name(struct gmesh *mesh, const char *name)
struct ggeom *gp;
LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
- if (strcmp(classp->lg_name, "DISK") != 0 &&
- strcmp(classp->lg_name, "PART") != 0 &&
- strcmp(classp->lg_name, "RAID") != 0 &&
- strcmp(classp->lg_name, "MD") != 0)
- continue;
-
LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
if (LIST_EMPTY(&gp->lg_provider))
continue;
@@ -288,8 +281,8 @@ query:
return (retval);
}
-static int
-wizard_makeparts(struct gmesh *mesh, const char *disk)
+int
+wizard_makeparts(struct gmesh *mesh, const char *disk, int interactive)
{
struct gmesh submesh;
struct gclass *classp;
@@ -310,7 +303,7 @@ wizard_makeparts(struct gmesh *mesh, const char *disk)
pp = provider_for_name(mesh, disk);
available = gpart_max_free(gp, NULL)*pp->lg_sectorsize;
- if (available < MIN_FREE_SPACE) {
+ if (interactive && available < MIN_FREE_SPACE) {
char availablestr[10], neededstr[10], message[512];
humanize_number(availablestr, 7, available, "B", HN_AUTOSCALE,
HN_DECIMAL);
diff --git a/usr.sbin/bsdinstall/partedit/partedit.c b/usr.sbin/bsdinstall/partedit/partedit.c
index d470c80..eff87fe 100644
--- a/usr.sbin/bsdinstall/partedit/partedit.c
+++ b/usr.sbin/bsdinstall/partedit/partedit.c
@@ -96,13 +96,20 @@ main(int argc, const char **argv)
prompt = "Please review the disk setup. When complete, press "
"the Finish button.";
part_wizard();
+ } else if (strcmp(basename(argv[0]), "scriptedpart") == 0) {
+ error = scripted_editor(argc, argv);
+ prompt = NULL;
+ if (error != 0) {
+ end_dialog();
+ return (error);
+ }
} else {
prompt = "Create partitions for FreeBSD. No changes will be "
"made until you select Finish.";
}
/* Show the part editor either immediately, or to confirm wizard */
- while (1) {
+ while (prompt != NULL) {
dlg_clear();
dlg_put_backtitle();
@@ -189,6 +196,15 @@ main(int argc, const char **argv)
free(items);
}
+ if (prompt == NULL) {
+ error = geom_gettree(&mesh);
+ if (validate_setup()) {
+ error = apply_changes(&mesh);
+ } else {
+ gpart_revert_all(&mesh);
+ error = -1;
+ }
+ }
geom_deletetree(&mesh);
free(items);
diff --git a/usr.sbin/bsdinstall/partedit/partedit.h b/usr.sbin/bsdinstall/partedit/partedit.h
index bffb076..121e3a2 100644
--- a/usr.sbin/bsdinstall/partedit/partedit.h
+++ b/usr.sbin/bsdinstall/partedit/partedit.h
@@ -55,6 +55,8 @@ struct partition_metadata *get_part_metadata(const char *name, int create);
void delete_part_metadata(const char *name);
int part_wizard(void);
+int scripted_editor(int argc, const char **argv);
+int wizard_makeparts(struct gmesh *mesh, const char *disk, int interactive);
/* gpart operations */
void gpart_delete(struct gprovider *pp);
diff --git a/usr.sbin/bsdinstall/partedit/sade.8 b/usr.sbin/bsdinstall/partedit/sade.8
index 8b2af49..441ddc0 100644
--- a/usr.sbin/bsdinstall/partedit/sade.8
+++ b/usr.sbin/bsdinstall/partedit/sade.8
@@ -56,7 +56,7 @@ in the post-installation environment.
A program called
.Nm
first appeared in
-.Fx 6.3
+.Fx 6.3
as a utility encapsulating features from the
.Xr sysinstall 8
installer. It was replaced in
diff --git a/usr.sbin/bsdinstall/partedit/scripted.c b/usr.sbin/bsdinstall/partedit/scripted.c
new file mode 100644
index 0000000..4ac3482
--- /dev/null
+++ b/usr.sbin/bsdinstall/partedit/scripted.c
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 2013 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 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 <sys/param.h>
+#include <errno.h>
+#include <libutil.h>
+#include <inttypes.h>
+
+#include <libgeom.h>
+#include <dialog.h>
+#include <dlg_keys.h>
+
+#include "partedit.h"
+
+static struct gprovider *
+provider_for_name(struct gmesh *mesh, const char *name)
+{
+ struct gclass *classp;
+ struct gprovider *pp = NULL;
+ struct ggeom *gp;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ if (LIST_EMPTY(&gp->lg_provider))
+ continue;
+
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider)
+ if (strcmp(pp->lg_name, name) == 0)
+ break;
+
+ if (pp != NULL) break;
+ }
+
+ if (pp != NULL) break;
+ }
+
+ return (pp);
+}
+
+static int
+part_config(char *disk, const char *scheme, char *config)
+{
+ char *partition, *ap, *size = NULL, *type = NULL, *mount = NULL;
+ struct gclass *classp;
+ struct gmesh mesh;
+ struct ggeom *gpart = NULL;
+ int error;
+
+ if (scheme == NULL)
+ scheme = default_scheme();
+
+ error = geom_gettree(&mesh);
+ if (provider_for_name(&mesh, disk) == NULL) {
+ fprintf(stderr, "GEOM provider %s not found\n", disk);
+ geom_deletetree(&mesh);
+ return (-1);
+ }
+
+ /* Remove any existing partitioning and create new scheme */
+ LIST_FOREACH(classp, &mesh.lg_class, lg_class)
+ if (strcmp(classp->lg_name, "PART") == 0)
+ break;
+ if (classp != NULL) {
+ LIST_FOREACH(gpart, &classp->lg_geom, lg_geom)
+ if (strcmp(gpart->lg_name, disk) == 0)
+ break;
+ }
+ if (gpart != NULL)
+ gpart_destroy(gpart);
+ gpart_partition(disk, scheme);
+
+ if (strcmp(scheme, "PC98") == 0 || strcmp(scheme, "MBR") == 0) {
+ struct gmesh submesh;
+ geom_gettree(&submesh);
+ gpart_create(provider_for_name(&submesh, disk),
+ "freebsd", NULL, NULL, &disk, 0);
+ geom_deletetree(&submesh);
+ } else {
+ disk= strdup(disk);
+ }
+
+ geom_deletetree(&mesh);
+ error = geom_gettree(&mesh);
+
+ /* Create partitions */
+ if (config == NULL) {
+ wizard_makeparts(&mesh, disk, 0);
+ goto finished;
+ }
+
+ while ((partition = strsep(&config, ",")) != NULL) {
+ while ((ap = strsep(&partition, " \t\n")) != NULL) {
+ if (*ap == '\0')
+ continue;
+ if (size == NULL)
+ size = ap;
+ else if (type == NULL)
+ type = ap;
+ else if (mount == NULL)
+ mount = ap;
+ }
+ if (size == NULL)
+ continue;
+ if (strcmp(size, "auto") == 0)
+ size = NULL;
+ gpart_create(provider_for_name(&mesh, disk), type, size, mount,
+ NULL, 0);
+ geom_deletetree(&mesh);
+ error = geom_gettree(&mesh);
+ size = type = mount = NULL;
+ }
+
+finished:
+ geom_deletetree(&mesh);
+ free(disk);
+
+ return (0);
+}
+
+static
+int parse_disk_config(char *input)
+{
+ char *ap;
+ char *disk = NULL, *scheme = NULL, *partconfig = NULL;
+
+ while (input != NULL && *input != 0) {
+ if (isspace(*input)) {
+ input++;
+ continue;
+ }
+
+ switch(*input) {
+ case '{':
+ input++;
+ partconfig = strchr(input, '}');
+ if (partconfig == NULL) {
+ fprintf(stderr, "Malformed partition setup "
+ "string: %s\n", input);
+ return (1);
+ }
+ *partconfig = '\0';
+ ap = partconfig+1;
+ partconfig = input;
+ input = ap;
+ break;
+ default:
+ if (disk == NULL)
+ disk = strsep(&input, " \t\n");
+ else if (scheme == NULL)
+ scheme = strsep(&input, " \t\n");
+ else {
+ fprintf(stderr, "Unknown directive: %s\n",
+ strsep(&input, " \t\n"));
+ return (1);
+ }
+ }
+ } while (input != NULL && *input != 0);
+
+ if (disk != NULL)
+ return (part_config(disk, scheme, partconfig));
+
+ return (0);
+}
+
+int
+scripted_editor(int argc, const char **argv)
+{
+ char *token;
+ int i, error = 0, len = 0;
+
+ for (i = 1; i < argc; i++)
+ len += strlen(argv[i]) + 1;
+ char inputbuf[len], *input = inputbuf;
+ strcpy(input, argv[1]);
+ for (i = 2; i < argc; i++) {
+ strcat(input, " ");
+ strcat(input, argv[i]);
+ }
+
+ while ((token = strsep(&input, ";")) != NULL) {
+ error = parse_disk_config(token);
+ if (error != 0)
+ return (error);
+ }
+
+ return (0);
+}
+
diff --git a/usr.sbin/bsdinstall/scripts/Makefile b/usr.sbin/bsdinstall/scripts/Makefile
index 5e450b7..bcfafc0 100644
--- a/usr.sbin/bsdinstall/scripts/Makefile
+++ b/usr.sbin/bsdinstall/scripts/Makefile
@@ -2,7 +2,7 @@
SCRIPTS= auto adduser checksum config docsinstall hostname jail keymap \
mirrorselect mount netconfig netconfig_ipv4 netconfig_ipv6 rootpass \
- services time umount wlanconfig
+ script services time umount wlanconfig
BINDIR= /usr/libexec/bsdinstall
NO_MAN= true
diff --git a/usr.sbin/bsdinstall/scripts/script b/usr.sbin/bsdinstall/scripts/script
new file mode 100755
index 0000000..58ae6e9
--- /dev/null
+++ b/usr.sbin/bsdinstall/scripts/script
@@ -0,0 +1,90 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013 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 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$
+
+# VARIABLES:
+# PARTITIONS
+# DISTRIBUTIONS
+# BSDINSTALL_DISTDIR
+
+error() {
+ test -f $PATH_FSTAB && bsdinstall umount
+ echo "Installation Error!"
+ cat $BSDINSTALL_LOG
+ echo "Installation Error!"
+ exit 1
+}
+
+set -e
+trap error EXIT
+
+SCRIPT="$1"
+shift
+
+echo "Begun Installation at $(date)" > $BSDINSTALL_LOG
+rm -rf $BSDINSTALL_TMPETC
+mkdir $BSDINSTALL_TMPETC
+
+split -a 2 -p '^#!.*' "$SCRIPT" /tmp/bsdinstall-installscript-
+
+. /tmp/bsdinstall-installscript-aa
+: ${DISTRIBUTIONS="kernel.txz base.txz"}; export DISTRIBUTIONS
+export BSDINSTALL_DISTDIR
+
+# Make partitions
+rm -f $PATH_FSTAB
+touch $PATH_FSTAB
+bsdinstall scriptedpart "$PARTITIONS"
+bsdinstall mount
+
+# Unpack distributions
+bsdinstall checksum
+bsdinstall distextract
+
+# Finalize install
+bsdinstall config
+
+# Make sure networking is functional, if we can arrange that
+if [ ! -f $BSDINSTALL_CHROOT/etc/resolv.conf -a -f /etc/resolv.conf ]; then
+ cp /etc/resolv.conf $BSDINSTALL_CHROOT/etc/resolv.conf
+fi
+
+# Run post-install script
+if [ -f /tmp/bsdinstall-installscript-ab ]; then
+ cp /tmp/bsdinstall-installscript-ab $BSDINSTALL_CHROOT/tmp/installscript
+ chmod a+x $BSDINSTALL_CHROOT/tmp/installscript
+ mount -t devfs devfs "$BSDINSTALL_CHROOT/dev"
+ chroot $BSDINSTALL_CHROOT /tmp/installscript $@ 2>&1
+ umount "$BSDINSTALL_CHROOT/dev"
+ rm $BSDINSTALL_CHROOT/tmp/installscript
+fi
+
+bsdinstall umount
+
+echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG
+
+trap true EXIT
diff --git a/usr.sbin/bsdinstall/scripts/services b/usr.sbin/bsdinstall/scripts/services
index 52aa57e..a4cfd46 100755
--- a/usr.sbin/bsdinstall/scripts/services
+++ b/usr.sbin/bsdinstall/scripts/services
@@ -45,7 +45,7 @@ DAEMONS=$(dialog --backtitle "FreeBSD Installer" \
sshd "Secure shell daemon" ${sshd_enable:-off} \
moused "PS/2 mouse pointer on console" ${moused_enable:-off} \
ntpd "Synchronize system and network time" ${ntpd_enable:-off} \
- powerd "Adjust CPU frequency dynamically" ${powerd_enable:-off} \
+ powerd "Adjust CPU frequency dynamically if supported" ${powerd_enable:-off} \
2>&1 1>&3)
exec 3>&-
diff --git a/usr.sbin/bsdinstall/scripts/wlanconfig b/usr.sbin/bsdinstall/scripts/wlanconfig
index 6894279..0a3599c 100755
--- a/usr.sbin/bsdinstall/scripts/wlanconfig
+++ b/usr.sbin/bsdinstall/scripts/wlanconfig
@@ -60,7 +60,7 @@ NETWORKS=`echo "$SCAN_RESULTS" | awk -F '\t' \
'/..:..:..:..:..:../ {if (length($5) > 0) printf("\"%s\"\t%s\n", $5, $4);}' |
sort | uniq`
-if [ -z $NETWORKS ]; then
+if [ -z "$NETWORKS" ]; then
dialog --backtitle "FreeBSD Installer" --title "Error" \
--yesno "No wireless networks were found. Rescan?" 0 0 && \
exec $0 $@
diff --git a/usr.sbin/bsnmpd/modules/snmp_target/Makefile b/usr.sbin/bsnmpd/modules/snmp_target/Makefile
index 10141e5..10141e5 100755..100644
--- a/usr.sbin/bsnmpd/modules/snmp_target/Makefile
+++ b/usr.sbin/bsnmpd/modules/snmp_target/Makefile
diff --git a/usr.sbin/bsnmpd/modules/snmp_usm/Makefile b/usr.sbin/bsnmpd/modules/snmp_usm/Makefile
index 4ae818a..4ae818a 100755..100644
--- a/usr.sbin/bsnmpd/modules/snmp_usm/Makefile
+++ b/usr.sbin/bsnmpd/modules/snmp_usm/Makefile
diff --git a/usr.sbin/bsnmpd/modules/snmp_vacm/Makefile b/usr.sbin/bsnmpd/modules/snmp_vacm/Makefile
index 1be8d62..1be8d62 100755..100644
--- a/usr.sbin/bsnmpd/modules/snmp_vacm/Makefile
+++ b/usr.sbin/bsnmpd/modules/snmp_vacm/Makefile
diff --git a/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c b/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c
index 52aa1a9..52aa1a9 100755..100644
--- a/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c
+++ b/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptools.c
diff --git a/usr.sbin/cpucontrol/intel.c b/usr.sbin/cpucontrol/intel.c
index 15ac939..96ab704 100644
--- a/usr.sbin/cpucontrol/intel.c
+++ b/usr.sbin/cpucontrol/intel.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -266,7 +267,9 @@ matched:
args.size = data_size;
error = ioctl(devfd, CPUCTL_UPDATE, &args);
if (error < 0) {
+ error = errno;
fprintf(stderr, "failed.\n");
+ errno = error;
WARN(0, "ioctl()");
goto fail;
}
diff --git a/usr.sbin/cpucontrol/via.c b/usr.sbin/cpucontrol/via.c
index 71ae406..d17e31f 100644
--- a/usr.sbin/cpucontrol/via.c
+++ b/usr.sbin/cpucontrol/via.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -203,7 +204,9 @@ via_update(const char *dev, const char *path)
args.size = data_size;
error = ioctl(devfd, CPUCTL_UPDATE, &args);
if (error < 0) {
+ error = errno;
fprintf(stderr, "failed.\n");
+ errno = error;
WARN(0, "ioctl()");
goto fail;
}
diff --git a/usr.sbin/crunch/crunchgen/crunchgen.c b/usr.sbin/crunch/crunchgen/crunchgen.c
index 48d6f33..0fb4906 100644
--- a/usr.sbin/crunch/crunchgen/crunchgen.c
+++ b/usr.sbin/crunch/crunchgen/crunchgen.c
@@ -105,11 +105,11 @@ int list_mode;
/* general library routines */
-void status(char *str);
+void status(const char *str);
void out_of_memory(void);
void add_string(strlst_t **listp, char *str);
-int is_dir(char *pathname);
-int is_nonempty_file(char *pathname);
+int is_dir(const char *pathname);
+int is_nonempty_file(const char *pathname);
int subtract_strlst(strlst_t **lista, strlst_t **listb);
int in_list(strlst_t **listp, char *str);
@@ -119,6 +119,8 @@ void usage(void);
void parse_conf_file(void);
void gen_outputs(void);
+extern char *crunched_skel[];
+
int
main(int argc, char **argv)
@@ -245,7 +247,7 @@ usage(void)
/* helper routines for parse_conf_file */
void parse_one_file(char *filename);
-void parse_line(char *line, int *fc, char **fv, int nf);
+void parse_line(char *pline, int *fc, char **fv, int nf);
void add_srcdirs(int argc, char **argv);
void add_progs(int argc, char **argv);
void add_link(int argc, char **argv);
@@ -340,15 +342,15 @@ parse_one_file(char *filename)
void
-parse_line(char *line, int *fc, char **fv, int nf)
+parse_line(char *pline, int *fc, char **fv, int nf)
{
char *p;
- p = line;
+ p = pline;
*fc = 0;
while (1) {
- while (isspace(*p))
+ while (isspace((unsigned char)*p))
p++;
if (*p == '\0' || *p == '#')
@@ -357,7 +359,7 @@ parse_line(char *line, int *fc, char **fv, int nf)
if (*fc < nf)
fv[(*fc)++] = p;
- while (*p && !isspace(*p) && *p != '#')
+ while (*p && !isspace((unsigned char)*p) && *p != '#')
p++;
if (*p == '\0' || *p == '#')
@@ -767,17 +769,17 @@ fillin_program_objs(prog_t *p, char *path)
}
cp = line + 6;
- while (isspace(*cp))
+ while (isspace((unsigned char)*cp))
cp++;
while(*cp) {
obj = cp;
- while (*cp && !isspace(*cp))
+ while (*cp && !isspace((unsigned char)*cp))
cp++;
if (*cp)
*cp++ = '\0';
add_string(&p->objs, obj);
- while (isspace(*cp))
+ while (isspace((unsigned char)*cp))
cp++;
}
}
@@ -887,7 +889,6 @@ gen_output_makefile(void)
void
gen_output_cfile(void)
{
- extern char *crunched_skel[];
char **cp;
FILE *outcf;
prog_t *p;
@@ -945,7 +946,7 @@ char *genident(char *str)
for (d = s = n; *s != '\0'; s++) {
if (*s == '-')
*d++ = '_';
- else if (*s == '_' || isalnum(*s))
+ else if (*s == '_' || isalnum((unsigned char)*s))
*d++ = *s;
}
*d = '\0';
@@ -1135,7 +1136,7 @@ output_strlst(FILE *outf, strlst_t *lst)
*/
void
-status(char *str)
+status(const char *str)
{
static int lastlen = 0;
int len, spaces;
@@ -1211,7 +1212,7 @@ in_list(strlst_t **listp, char *str)
}
int
-is_dir(char *pathname)
+is_dir(const char *pathname)
{
struct stat buf;
@@ -1222,7 +1223,7 @@ is_dir(char *pathname)
}
int
-is_nonempty_file(char *pathname)
+is_nonempty_file(const char *pathname)
{
struct stat buf;
diff --git a/usr.sbin/crunch/crunchide/exec_elf32.c b/usr.sbin/crunch/crunchide/exec_elf32.c
index d01fe7e..9274f89 100644
--- a/usr.sbin/crunch/crunchide/exec_elf32.c
+++ b/usr.sbin/crunch/crunchide/exec_elf32.c
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
#if 0
-__RCSID("$NetBSD: exec_elf32.c,v 1.4 1997/08/12 06:07:24 mikel Exp $");
+__RCSID("$NetBSD: exec_elf32.c,v 1.6 1999/09/20 04:12:16 christos Exp $");
#endif
#endif
__FBSDID("$FreeBSD$");
@@ -98,7 +98,7 @@ xreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn)
perror(fn);
return -1;
}
- if ((rv = read(fd, buf, size)) != size) {
+ if ((size_t)(rv = read(fd, buf, size)) != size) {
fprintf(stderr, "%s: read error: %s\n", fn,
rv == -1 ? strerror(errno) : "short read");
return -1;
@@ -115,7 +115,7 @@ xwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn)
perror(fn);
return -1;
}
- if ((rv = write(fd, buf, size)) != size) {
+ if ((size_t)(rv = write(fd, buf, size)) != size) {
fprintf(stderr, "%s: write error: %s\n", fn,
rv == -1 ? strerror(errno) : "short write");
return -1;
@@ -162,7 +162,7 @@ ELFNAMEEND(check)(int fd, const char *fn)
*/
if (fstat(fd, &sb) == -1)
return 0;
- if (sb.st_size < sizeof eh)
+ if (sb.st_size < (off_t)(sizeof eh))
return 0;
if (read(fd, &eh, sizeof eh) != sizeof eh)
return 0;
@@ -305,7 +305,7 @@ ELFNAMEEND(hide)(int fd, const char *fn)
if ((symtabp = xmalloc(xewtoh(symtabshdr->sh_size), fn, "symbol table"))
== NULL)
goto bad;
- if (xreadatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset),
+ if ((size_t)xreadatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset),
xewtoh(symtabshdr->sh_size), fn) != xewtoh(symtabshdr->sh_size))
goto bad;
@@ -313,7 +313,7 @@ ELFNAMEEND(hide)(int fd, const char *fn)
if ((strtabp = xmalloc(xewtoh(strtabshdr->sh_size), fn, "string table"))
== NULL)
goto bad;
- if (xreadatoff(fd, strtabp, xewtoh(strtabshdr->sh_offset),
+ if ((size_t)xreadatoff(fd, strtabp, xewtoh(strtabshdr->sh_offset),
xewtoh(strtabshdr->sh_size), fn) != xewtoh(strtabshdr->sh_size))
goto bad;
@@ -370,7 +370,7 @@ ELFNAMEEND(hide)(int fd, const char *fn)
if (xwriteatoff(fd, shdrp, xewtoh(ehdr.e_shoff), shdrsize, fn) !=
shdrsize)
goto bad;
- if (xwriteatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset),
+ if ((size_t)xwriteatoff(fd, symtabp, xewtoh(symtabshdr->sh_offset),
xewtoh(symtabshdr->sh_size), fn) != xewtoh(symtabshdr->sh_size))
goto bad;
/* write new symbol table strings */
@@ -385,6 +385,8 @@ out:
free(symtabp);
if (strtabp != NULL)
free(strtabp);
+ if (nstrtabp != NULL)
+ free(nstrtabp);
return (rv);
bad:
diff --git a/usr.sbin/crunch/examples/really-big.conf b/usr.sbin/crunch/examples/really-big.conf
index fbd7f03..922078a 100644
--- a/usr.sbin/crunch/examples/really-big.conf
+++ b/usr.sbin/crunch/examples/really-big.conf
@@ -72,7 +72,7 @@ progs dev_mkdb diskpart edquota flcopy gettable grfinfo hilinfo htable inetd
progs iostat iteconfig kvm_mkdb mtree named portmap pppd
progs pstat pwd_mkdb quot quotaon rarpd rbootd repquota rmt rpc.bootparamd
progs rwhod sa spray sysctl syslogd tcpdump
-progs traceroute trpt trsp update vipw vnconfig ypbind yppoll ypset
+progs traceroute trpt update vipw vnconfig ypbind yppoll ypset
special amd srcdir /usr/src/usr.sbin/amd/amd
special amd objs vers.amd.o afs_ops.o am_ops.o clock.o util.o xutil.o efs_ops.o mapc.o info_file.o info_hes.o info_ndbm.o info_passwd.o info_nis.o info_union.o map.o srvr_afs.o srvr_nfs.o mntfs.o misc_rpc.o mount_fs.o mtab.o mtab_bsd.o nfs_ops.o nfs_prot_svc.o nfs_start.o nfs_subr.o opts.o pfs_ops.o rpc_fwd.o sched.o sfs_ops.o amq_svc.o amq_subr.o umount_fs.o host_ops.o nfsx_ops.o ufs_ops.o ifs_ops.o amd.o get_args.o restart.o wire.o
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c
index 6b28764..eebcfea 100644
--- a/usr.sbin/inetd/inetd.c
+++ b/usr.sbin/inetd/inetd.c
@@ -1387,7 +1387,7 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
}
}
if (sep->se_socktype == SOCK_STREAM)
- listen(sep->se_fd, 64);
+ listen(sep->se_fd, -1);
enable(sep);
if (debug) {
warnx("registered %s on %d",
diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile
index cbc4fd9..c378455 100644
--- a/usr.sbin/mtree/Makefile
+++ b/usr.sbin/mtree/Makefile
@@ -1,10 +1,12 @@
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
+.include <bsd.own.mk>
+
.PATH: ${.CURDIR}/../../usr.bin/cksum
-PROG= mtree
-MAN= mtree.8 mtree.5
+PROG= fmtree
+MAN= fmtree.8 mtree.5
SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c verify.c
SRCS+= specspec.c
@@ -12,4 +14,14 @@ CFLAGS+= -DMD5 -DSHA1 -DRMD160 -DSHA256
DPADD= ${LIBMD}
LDADD= -lmd
+.if ${MK_NMTREE} == "no"
+LINKS= ${BINDIR}/fmtree ${BINDIR}/mtree
+MLINKS= fmtree.8 mtree.8
+.endif
+
+CLEANFILES+= fmtree.8
+
+fmtree.8: mtree.8
+ cp ${.ALLSRC} ${.TARGET}
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/ndp/ndp.8 b/usr.sbin/ndp/ndp.8
index 9eabfe4..223cfba 100644
--- a/usr.sbin/ndp/ndp.8
+++ b/usr.sbin/ndp/ndp.8
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 9, 2012
+.Dd Jan 10, 2013
.Dt NDP 8
.Os
.\"
@@ -192,6 +192,15 @@ on
This flag is set by
.Va net.inet6.ip6.auto_linklocal
sysctl variable.
+.It Ic no_prefer_iface
+The address on the outgoing interface is preferred by source addess
+selection rule.
+If this flag is set, stop treating the address on the
+.Ar interface
+as special even when the
+.Ar interface
+is outgoing interface.
+The default value of this flag is off.
.It Ic disabled
Disable IPv6 operation on the interface.
When disabled, the interface discards any IPv6 packets
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c
index b50ddb7..0449c12 100644
--- a/usr.sbin/ndp/ndp.c
+++ b/usr.sbin/ndp/ndp.c
@@ -436,9 +436,6 @@ set(argc, argv)
goto overwrite;
}
}
- /*
- * IPv4 arp command retries with sin_other = SIN_PROXY here.
- */
fprintf(stderr, "set: cannot configure a new entry\n");
return 1;
}
@@ -523,9 +520,6 @@ delete(host)
!(rtm->rtm_flags & RTF_GATEWAY)) {
goto delete;
}
- /*
- * IPv4 arp command retries with sin_other = SIN_PROXY here.
- */
fprintf(stderr, "delete: cannot delete non-NDP entry\n");
return 1;
}
@@ -982,6 +976,9 @@ ifinfo(ifname, argc, argv)
#ifdef ND6_IFF_AUTO_LINKLOCAL
SETFLAG("auto_linklocal", ND6_IFF_AUTO_LINKLOCAL);
#endif
+#ifdef ND6_IFF_NO_PREFER_IFACE
+ SETFLAG("no_prefer_iface", ND6_IFF_NO_PREFER_IFACE);
+#endif
SETVALUE("basereachable", ND.basereachable);
SETVALUE("retrans", ND.retrans);
SETVALUE("curhlim", ND.chlim);
@@ -1055,6 +1052,10 @@ ifinfo(ifname, argc, argv)
if ((ND.flags & ND6_IFF_AUTO_LINKLOCAL))
printf("auto_linklocal ");
#endif
+#ifdef ND6_IFF_NO_PREFER_IFACE
+ if ((ND.flags & ND6_IFF_NO_PREFER_IFACE))
+ printf("no_prefer_iface ");
+#endif
}
putc('\n', stdout);
#undef ND
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index 42cc013..d0ef3d3 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -179,7 +179,7 @@ struct sigwork_entry {
int sw_pidok; /* true if pid value is valid */
pid_t sw_pid; /* the process id from the PID file */
const char *sw_pidtype; /* "daemon" or "process group" */
- int run_cmd; /* run command or send PID to signal */
+ int sw_runcmd; /* run command or send PID to signal */
char sw_fname[1]; /* file the PID was read from or shell cmd */
};
@@ -1866,7 +1866,7 @@ do_sigwork(struct sigwork_entry *swork)
int kres, secs;
char *tmp;
- if (!(swork->sw_pidok) || swork->sw_pid == 0)
+ if (swork->sw_runcmd == 0 && (!(swork->sw_pidok) || swork->sw_pid == 0))
return; /* no work to do... */
/*
@@ -1900,14 +1900,19 @@ do_sigwork(struct sigwork_entry *swork)
}
if (noaction) {
- printf("\tkill -%d %d \t\t# %s\n", swork->sw_signum,
- (int)swork->sw_pid, swork->sw_fname);
- if (secs > 0)
- printf("\tsleep %d\n", secs);
+ if (swork->sw_runcmd)
+ printf("\tsh -c '%s %d'\n", swork->sw_fname,
+ swork->sw_signum);
+ else {
+ printf("\tkill -%d %d \t\t# %s\n", swork->sw_signum,
+ (int)swork->sw_pid, swork->sw_fname);
+ if (secs > 0)
+ printf("\tsleep %d\n", secs);
+ }
return;
}
- if (swork->run_cmd) {
+ if (swork->sw_runcmd) {
asprintf(&tmp, "%s %d", swork->sw_fname, swork->sw_signum);
if (tmp == NULL) {
warn("can't allocate memory to run %s",
@@ -1983,7 +1988,7 @@ do_zipwork(struct zipwork_entry *zwork)
else
pgm_name++;
- if (zwork->zw_swork != NULL && zwork->zw_swork->run_cmd == 0 &&
+ if (zwork->zw_swork != NULL && zwork->zw_swork->sw_runcmd == 0 &&
zwork->zw_swork->sw_pidok <= 0) {
warnx(
"log %s not compressed because daemon(s) not notified",
@@ -2075,10 +2080,12 @@ save_sigwork(const struct conf_entry *ent)
tmpsiz = sizeof(struct sigwork_entry) + strlen(ent->pid_cmd_file) + 1;
stmp = malloc(tmpsiz);
- stmp->run_cmd = 0;
+ stmp->sw_runcmd = 0;
/* If this is a command to run we just set the flag and run command */
if (ent->flags & CE_PID2CMD) {
- stmp->run_cmd = 1;
+ stmp->sw_pid = -1;
+ stmp->sw_pidok = 0;
+ stmp->sw_runcmd = 1;
} else {
set_swpid(stmp, ent);
}
diff --git a/usr.sbin/nmtree/Makefile b/usr.sbin/nmtree/Makefile
index 58e46ea..1b8cc01 100644
--- a/usr.sbin/nmtree/Makefile
+++ b/usr.sbin/nmtree/Makefile
@@ -20,6 +20,13 @@ LIBNETBSD= ${LIBNETBSDDIR}/libnetbsd.a
DPADD+= ${LIBNETBSD}
LDADD+= ${LIBNETBSD}
+.if ${MK_NMTREE} != "no"
+LINKS= ${BINDIR}/nmtree ${BINDIR}/mtree
+MLINKS= nmtree.8 mtree.8
+.endif
+
+CLEANFILES+= nmtree.8
+
nmtree.8: mtree.8
cp ${.ALLSRC} ${.TARGET}
diff --git a/usr.sbin/pciconf/cap.c b/usr.sbin/pciconf/cap.c
index ce184dd..1c2ab4a 100644
--- a/usr.sbin/pciconf/cap.c
+++ b/usr.sbin/pciconf/cap.c
@@ -449,24 +449,28 @@ cap_express(int fd, struct pci_conf *p, uint8_t ptr)
static void
cap_msix(int fd, struct pci_conf *p, uint8_t ptr)
{
- uint32_t val;
+ uint32_t pba_offset, table_offset, val;
+ int msgnum, pba_bar, table_bar;
uint16_t ctrl;
- int msgnum, table_bar, pba_bar;
ctrl = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_CTRL, 2);
msgnum = (ctrl & PCIM_MSIXCTRL_TABLE_SIZE) + 1;
+
val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_TABLE, 4);
table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
+ table_offset = val & ~PCIM_MSIX_BIR_MASK;
+
val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_PBA, 4);
- pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
- printf("MSI-X supports %d message%s ", msgnum,
- (msgnum == 1) ? "" : "s");
- if (table_bar == pba_bar)
- printf("in map 0x%x", table_bar);
- else
- printf("in maps 0x%x and 0x%x", table_bar, pba_bar);
- if (ctrl & PCIM_MSIXCTRL_MSIX_ENABLE)
- printf(" enabled");
+ pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
+ pba_offset = val & ~PCIM_MSIX_BIR_MASK;
+
+ printf("MSI-X supports %d message%s%s\n", msgnum,
+ (msgnum == 1) ? "" : "s",
+ (ctrl & PCIM_MSIXCTRL_MSIX_ENABLE) ? ", enabled" : "");
+
+ printf(" ");
+ printf("Table in map 0x%x[0x%x], PBA in map 0x%x[0x%x]",
+ table_bar, table_offset, pba_bar, pba_offset);
}
static void
diff --git a/usr.sbin/pkg/dns_utils.c b/usr.sbin/pkg/dns_utils.c
index e88bf98..239be90 100644
--- a/usr.sbin/pkg/dns_utils.c
+++ b/usr.sbin/pkg/dns_utils.c
@@ -66,10 +66,9 @@ dns_getsrvinfo(const char *zone)
p += len + NS_QFIXEDSZ;
}
- res = malloc(sizeof(struct dns_srvinfo) * ancount);
+ res = calloc(ancount, sizeof(struct dns_srvinfo));
if (res == NULL)
return (NULL);
- memset(res, 0, sizeof(struct dns_srvinfo) * ancount);
n = 0;
while (ancount > 0 && p < end) {
diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
index aebcc0b..77b2c71 100644
--- a/usr.sbin/pkg_install/lib/lib.h
+++ b/usr.sbin/pkg_install/lib/lib.h
@@ -99,7 +99,7 @@
* Version of the package tools - increase whenever you make a change
* in the code that is not cosmetic only.
*/
-#define PKG_INSTALL_VERSION 20121109
+#define PKG_INSTALL_VERSION 20130122
#define PKG_WRAPCONF_FNAME "/var/db/pkg_install.conf"
#define main(argc, argv) real_main(argc, argv)
diff --git a/usr.sbin/pkg_install/lib/pkgng.c b/usr.sbin/pkg_install/lib/pkgng.c
index a8731c7..3aba383 100644
--- a/usr.sbin/pkg_install/lib/pkgng.c
+++ b/usr.sbin/pkg_install/lib/pkgng.c
@@ -38,9 +38,10 @@ this system.";
void warnpkgng(void)
{
- char pkgngpath[MAXPATHLEN];
+ char pkgngpath[MAXPATHLEN + 1];
char *pkgngdir;
char *dontwarn;
+ int rc;
dontwarn = getenv("PKG_OLD_NOWARN");
if (dontwarn != NULL)
@@ -48,8 +49,12 @@ void warnpkgng(void)
pkgngdir = getenv("PKG_DBDIR");
if (pkgngdir == NULL)
pkgngdir = "/var/db/pkg";
- strcpy(pkgngpath, pkgngdir);
- strcat(pkgngpath, "/local.sqlite");
+
+ rc = snprintf(pkgngpath, sizeof(pkgngpath), "%s/local.sqlite", pkgngdir);
+ if ((size_t)rc >= sizeof(pkgngpath)) {
+ warnx("path too long: %s/local.sqlite", pkgngdir);
+ return;
+ }
if (access(pkgngpath, F_OK) == 0)
warnx(message);
diff --git a/usr.sbin/ppp/arp.c b/usr.sbin/ppp/arp.c
index e67f89b..b38b97a 100644
--- a/usr.sbin/ppp/arp.c
+++ b/usr.sbin/ppp/arp.c
@@ -91,7 +91,7 @@
*/
static struct {
struct rt_msghdr hdr;
- struct sockaddr_inarp dst;
+ struct sockaddr_in dst;
struct sockaddr_dl hwa;
char extra[128];
} arpmsg;
@@ -124,10 +124,9 @@ arp_ProxySub(struct bundle *bundle, struct in_addr addr, int add)
arpmsg.hdr.rtm_seq = ++bundle->routing_seq;
arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
arpmsg.hdr.rtm_inits = RTV_EXPIRE;
- arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
+ arpmsg.dst.sin_len = sizeof(struct sockaddr_in);
arpmsg.dst.sin_family = AF_INET;
arpmsg.dst.sin_addr.s_addr = addr.s_addr;
- arpmsg.dst.sin_other = SIN_PROXY;
arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
+ arpmsg.hwa.sdl_len;
diff --git a/usr.sbin/pw/pw_log.c b/usr.sbin/pw/pw_log.c
index f16274f..b774423 100644
--- a/usr.sbin/pw/pw_log.c
+++ b/usr.sbin/pw/pw_log.c
@@ -47,7 +47,6 @@ pw_log(struct userconf * cnf, int mode, int which, char const * fmt,...)
}
if (logfile != NULL) {
va_list argp;
- int l;
time_t now = time(NULL);
struct tm *t = localtime(&now);
char nfmt[256];
@@ -57,7 +56,6 @@ pw_log(struct userconf * cnf, int mode, int which, char const * fmt,...)
name = "unknown";
/* ISO 8601 International Standard Date format */
strftime(nfmt, sizeof nfmt, "%Y-%m-%d %T ", t);
- l = strlen(nfmt);
sprintf(nfmt + strlen(nfmt), "[%s:%s%s] %s\n", name, Which[which], Modes[mode], fmt);
va_start(argp, fmt);
vfprintf(logfile, nfmt, argp);
diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c
index 38f21ce..5f4d7a9 100644
--- a/usr.sbin/pw/pw_user.c
+++ b/usr.sbin/pw/pw_user.c
@@ -425,7 +425,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
}
grp = GETGRNAM(a_name->val);
- if (*grp->gr_mem == NULL)
+ if (grp != NULL && *grp->gr_mem == NULL)
delgrent(GETGRNAM(a_name->val));
SETGRENT();
while ((grp = GETGRENT()) != NULL) {
diff --git a/usr.sbin/rarpd/rarpd.c b/usr.sbin/rarpd/rarpd.c
index f10a7da..5386185 100644
--- a/usr.sbin/rarpd/rarpd.c
+++ b/usr.sbin/rarpd/rarpd.c
@@ -692,11 +692,10 @@ rarp_process(struct if_info *ii, u_char *pkt, u_int len)
* host (i.e. the guy running rarpd), won't try to ARP for the hardware
* address of the guy being booted (he cannot answer the ARP).
*/
-struct sockaddr_inarp sin_inarp = {
- sizeof(struct sockaddr_inarp), AF_INET, 0,
+struct sockaddr_in sin_inarp = {
+ sizeof(struct sockaddr_in), AF_INET, 0,
{0},
{0},
- 0, 0
};
struct sockaddr_dl sin_dl = {
sizeof(struct sockaddr_dl), AF_LINK, 0, IFT_ETHER, 0, 6,
@@ -712,7 +711,7 @@ update_arptab(u_char *ep, in_addr_t ipaddr)
{
struct timespec tp;
int cc;
- struct sockaddr_inarp *ar, *ar2;
+ struct sockaddr_in *ar, *ar2;
struct sockaddr_dl *ll, *ll2;
struct rt_msghdr *rt;
int xtype, xindex;
@@ -740,7 +739,7 @@ update_arptab(u_char *ep, in_addr_t ipaddr)
rt->rtm_addrs = RTA_DST;
rt->rtm_type = RTM_GET;
rt->rtm_seq = ++seq;
- ar2 = (struct sockaddr_inarp *)rtmsg.rtspace;
+ ar2 = (struct sockaddr_in *)rtmsg.rtspace;
bcopy(ar, ar2, sizeof(*ar));
rt->rtm_msglen = sizeof(*rt) + sizeof(*ar);
errno = 0;
diff --git a/usr.sbin/tcpdrop/tcpdrop.8 b/usr.sbin/tcpdrop/tcpdrop.8
index 93bfe8e..9649dec 100644
--- a/usr.sbin/tcpdrop/tcpdrop.8
+++ b/usr.sbin/tcpdrop/tcpdrop.8
@@ -17,7 +17,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 24, 2009
+.Dd January 30, 2013
.Dt TCPDROP 8
.Os
.Sh NAME
@@ -62,6 +62,9 @@ will be dropped.
.Pp
Addresses and ports may be specified by name or numeric value.
Both IPv4 and IPv6 address formats are supported.
+.Pp
+The addresses and ports may be separated by periods or colons
+instead of spaces.
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
diff --git a/usr.sbin/tcpdrop/tcpdrop.c b/usr.sbin/tcpdrop/tcpdrop.c
index dce6c6d..ef3f6bd 100644
--- a/usr.sbin/tcpdrop/tcpdrop.c
+++ b/usr.sbin/tcpdrop/tcpdrop.c
@@ -50,6 +50,7 @@ struct host_service {
static bool tcpdrop_list_commands = false;
+static char *findport(const char *);
static struct xinpgen *getxpcblist(const char *);
static void sockinfo(const struct sockaddr *, struct host_service *);
static bool tcpdrop(const struct sockaddr *, const struct sockaddr *);
@@ -65,6 +66,7 @@ static void usage(void);
int
main(int argc, char *argv[])
{
+ char *lport, *fport;
bool dropall;
int ch;
@@ -93,15 +95,43 @@ main(int argc, char *argv[])
exit(0);
}
- if (argc != 4 || tcpdrop_list_commands)
+ if ((argc != 2 && argc != 4) || tcpdrop_list_commands)
usage();
- if (!tcpdropbyname(argv[0], argv[1], argv[2], argv[3]))
+ if (argc == 2) {
+ lport = findport(argv[0]);
+ fport = findport(argv[1]);
+ if (lport == NULL || lport[1] == '\0' || fport == NULL ||
+ fport[1] == '\0')
+ usage();
+ *lport++ = '\0';
+ *fport++ = '\0';
+ if (!tcpdropbyname(argv[0], lport, argv[1], fport))
+ exit(1);
+ } else if (!tcpdropbyname(argv[0], argv[1], argv[2], argv[3]))
exit(1);
exit(0);
}
+static char *
+findport(const char *arg)
+{
+ char *dot, *colon;
+
+ /* A strrspn() or strrpbrk() would be nice. */
+ dot = strrchr(arg, '.');
+ colon = strrchr(arg, ':');
+ if (dot == NULL)
+ return (colon);
+ if (colon == NULL)
+ return (dot);
+ if (dot < colon)
+ return (colon);
+ else
+ return (dot);
+}
+
static struct xinpgen *
getxpcblist(const char *name)
{
@@ -237,7 +267,7 @@ tcpdropbyname(const char *lhost, const char *lport, const char *fhost,
error = getaddrinfo(fhost, fport, &hints, &foreign);
if (error != 0) {
freeaddrinfo(local); /* XXX gratuitous */
- errx(1, "getaddrinfo: %s port %s: %s", lhost, lport,
+ errx(1, "getaddrinfo: %s port %s: %s", fhost, fport,
gai_strerror(error));
}
@@ -318,6 +348,8 @@ usage(void)
{
fprintf(stderr,
"usage: tcpdrop local-address local-port foreign-address foreign-port\n"
+" tcpdrop local-address:local-port foreign-address:foreign-port\n"
+" tcpdrop local-address.local-port foreign-address.foreign-port\n"
" tcpdrop [-l] -a\n");
exit(1);
}
diff --git a/usr.sbin/timed/timed/acksend.c b/usr.sbin/timed/timed/acksend.c
index fde1404..8492f9e 100644
--- a/usr.sbin/timed/timed/acksend.c
+++ b/usr.sbin/timed/timed/acksend.c
@@ -42,10 +42,7 @@ struct tsp *answer;
extern u_short sequence;
void
-xmit(type, seq, addr)
- int type;
- u_int seq;
- struct sockaddr_in *addr;
+xmit(int type, u_int seq, struct sockaddr_in *addr)
{
static struct tsp msg;
@@ -68,15 +65,15 @@ xmit(type, seq, addr)
*
* Because this function calls readmsg(), none of its args may be in
* a message provided by readmsg().
+ * message this message
+ * addr to here
+ * ack look for this ack
+ * net receive from this network
+ * bad 1=losing patience
*/
struct tsp *
-acksend(message, addr, name, ack, net, bad)
- struct tsp *message; /* this message */
- struct sockaddr_in *addr; /* to here */
- char *name;
- int ack; /* look for this ack */
- struct netinfo *net; /* receive from this network */
- int bad; /* 1=losing patience */
+acksend(struct tsp *message, struct sockaddr_in *addr, char *name,
+ int ack, struct netinfo *net, int bad)
{
struct timeval twait;
int count;
diff --git a/usr.sbin/timed/timed/byteorder.c b/usr.sbin/timed/timed/byteorder.c
index a9fd151..abacbd6 100644
--- a/usr.sbin/timed/timed/byteorder.c
+++ b/usr.sbin/timed/timed/byteorder.c
@@ -42,8 +42,7 @@ static const char rcsid[] =
* messages. Protocol is defined in /usr/include/protocols/timed.h
*/
void
-bytenetorder(ptr)
- struct tsp *ptr;
+bytenetorder(struct tsp *ptr)
{
ptr->tsp_seq = htons((u_short)ptr->tsp_seq);
switch (ptr->tsp_type) {
@@ -62,8 +61,7 @@ bytenetorder(ptr)
}
void
-bytehostorder(ptr)
- struct tsp *ptr;
+bytehostorder(struct tsp *ptr)
{
ptr->tsp_seq = ntohs((u_short)ptr->tsp_seq);
switch (ptr->tsp_type) {
diff --git a/usr.sbin/timed/timed/candidate.c b/usr.sbin/timed/timed/candidate.c
index 7eae18e..c92ae70 100644
--- a/usr.sbin/timed/timed/candidate.c
+++ b/usr.sbin/timed/timed/candidate.c
@@ -44,8 +44,7 @@ static const char rcsid[] =
* candidate sends an election request, the candidature is withdrawn.
*/
int
-election(net)
- struct netinfo *net;
+election(struct netinfo *net)
{
struct tsp *resp, msg;
struct timeval then, wait;
diff --git a/usr.sbin/timed/timed/cksum.c b/usr.sbin/timed/timed/cksum.c
index 243ea38..7fa0a5e 100644
--- a/usr.sbin/timed/timed/cksum.c
+++ b/usr.sbin/timed/timed/cksum.c
@@ -49,9 +49,7 @@ static const char rcsid[] =
* worry about carries except at the end.
*/
int
-in_cksum(addr, len)
- u_short *addr;
- int len;
+in_cksum(u_short *addr, int len)
{
register int nleft = len;
register u_short *w = addr;
diff --git a/usr.sbin/timed/timed/correct.c b/usr.sbin/timed/timed/correct.c
index 0eab083..8a5b464 100644
--- a/usr.sbin/timed/timed/correct.c
+++ b/usr.sbin/timed/timed/correct.c
@@ -47,8 +47,7 @@ static void adjclock(struct timeval *);
* own
*/
void
-correct(avdelta)
- long avdelta;
+correct(long avdelta)
{
struct hosttbl *htp;
int corr;
@@ -112,8 +111,7 @@ correct(avdelta)
static void
-adjclock(corr)
- struct timeval *corr;
+adjclock(struct timeval *corr)
{
static int passes = 0;
static int smoother = 0;
@@ -176,9 +174,7 @@ adjclock(corr)
* spent in the queue
*/
void
-adj_msg_time(msg, now)
- struct tsp *msg;
- struct timeval *now;
+adj_msg_time(struct tsp *msg, struct timeval *now)
{
msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec);
msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec);
diff --git a/usr.sbin/timed/timed/master.c b/usr.sbin/timed/timed/master.c
index b64259b..9a130bf 100644
--- a/usr.sbin/timed/timed/master.c
+++ b/usr.sbin/timed/timed/master.c
@@ -63,7 +63,7 @@ static void mchgdate(struct tsp *);
* takes the appropriate action.
*/
int
-master()
+master(void)
{
struct hosttbl *htp;
long pollingtime;
@@ -339,8 +339,7 @@ loop:
* change the system date on the master
*/
static void
-mchgdate(msg)
- struct tsp *msg;
+mchgdate(struct tsp *msg)
{
char tname[MAXHOSTNAMELEN];
char olddate[32];
@@ -386,8 +385,7 @@ mchgdate(msg)
* synchronize all of the slaves
*/
void
-synch(mydelta)
- long mydelta;
+synch(long mydelta)
{
struct hosttbl *htp;
int measure_status;
@@ -460,7 +458,7 @@ synch(mydelta)
* has received the command to set the network time
*/
void
-spreadtime()
+spreadtime(void)
{
struct hosttbl *htp;
struct tsp to;
@@ -499,8 +497,7 @@ spreadtime()
}
void
-prthp(delta)
- clock_t delta;
+prthp(clock_t delta)
{
static time_t next_time;
time_t this_time;
@@ -538,8 +535,7 @@ static struct hosttbl *lasthfree = &hosttbl[0];
struct hosttbl * /* answer or 0 */
-findhost(name)
- char *name;
+findhost(char *name)
{
int i, j;
struct hosttbl *htp;
@@ -565,10 +561,7 @@ findhost(name)
* add a host to the list of controlled machines if not already there
*/
struct hosttbl *
-addmach(name, addr, ntp)
- char *name;
- struct sockaddr_in *addr;
- struct netinfo *ntp;
+addmach(char *name, struct sockaddr_in *addr, struct netinfo *ntp)
{
struct hosttbl *ret, *p, *b, *f;
@@ -654,8 +647,7 @@ addmach(name, addr, ntp)
* remove the machine with the given index in the host table.
*/
struct hosttbl *
-remmach(htp)
- struct hosttbl *htp;
+remmach(struct hosttbl *htp)
{
struct hosttbl *lprv, *hnxt, *f, *b;
@@ -706,8 +698,7 @@ remmach(htp)
* given network.
*/
void
-rmnetmachs(ntp)
- struct netinfo *ntp;
+rmnetmachs(struct netinfo *ntp)
{
struct hosttbl *htp;
@@ -722,8 +713,7 @@ rmnetmachs(ntp)
}
void
-masterup(net)
- struct netinfo *net;
+masterup(struct netinfo *net)
{
xmit(TSP_MASTERUP, 0, &net->dest_addr);
@@ -736,8 +726,7 @@ masterup(net)
}
void
-newslave(msg)
- struct tsp *msg;
+newslave(struct tsp *msg)
{
struct hosttbl *htp;
struct tsp *answer, to;
@@ -782,8 +771,7 @@ newslave(msg)
* react to a TSP_QUIT:
*/
void
-doquit(msg)
- struct tsp *msg;
+doquit(struct tsp *msg)
{
if (fromnet->status == MASTER) {
if (!good_host_name(msg->tsp_name)) {
@@ -814,7 +802,7 @@ doquit(msg)
}
void
-traceon()
+traceon(void)
{
if (!fd) {
fd = fopen(_PATH_TIMEDLOG, "w");
@@ -832,8 +820,7 @@ traceon()
void
-traceoff(msg)
- char *msg;
+traceoff(char *msg)
{
get_goodgroup(1);
setstatus();
diff --git a/usr.sbin/timed/timed/measure.c b/usr.sbin/timed/timed/measure.c
index 81ab7c4..8fe43b5 100644
--- a/usr.sbin/timed/timed/measure.c
+++ b/usr.sbin/timed/timed/measure.c
@@ -56,14 +56,12 @@ static n_short seqno = 0;
/*
* Measures the differences between machines' clocks using
* ICMP timestamp messages.
+ * maxmsec wait this many msec at most
+ * wmsec msec to wait for an answer
+ * print print complaints on stderr
*/
int /* status val defined in globals.h */
-measure(maxmsec, wmsec, hname, addr, print)
- u_long maxmsec; /* wait this many msec at most */
- u_long wmsec; /* msec to wait for an answer */
- char *hname;
- struct sockaddr_in *addr;
- int print; /* print complaints on stderr */
+measure(u_long maxmsec, u_long wmsec, char *hname, struct sockaddr_in *addr, int print)
{
int length;
int measure_status;
@@ -292,9 +290,7 @@ quit:
* round a number of milliseconds into a struct timeval
*/
void
-mstotvround(res, x)
- struct timeval *res;
- long x;
+mstotvround(struct timeval *res, long x)
{
if (x < 0)
x = -((-x + 3)/5);
@@ -310,8 +306,7 @@ mstotvround(res, x)
}
void
-timevaladd(tv1, tv2)
- struct timeval *tv1, *tv2;
+timevaladd(struct timeval *tv1, struct timeval *tv2)
{
tv1->tv_sec += tv2->tv_sec;
tv1->tv_usec += tv2->tv_usec;
@@ -326,8 +321,7 @@ timevaladd(tv1, tv2)
}
void
-timevalsub(res, tv1, tv2)
- struct timeval *res, *tv1, *tv2;
+timevalsub(struct timeval *res, struct timeval *tv1, struct timeval *tv2)
{
res->tv_sec = tv1->tv_sec - tv2->tv_sec;
res->tv_usec = tv1->tv_usec - tv2->tv_usec;
diff --git a/usr.sbin/timed/timed/networkdelta.c b/usr.sbin/timed/timed/networkdelta.c
index e9a437a..bf2a353 100644
--- a/usr.sbin/timed/timed/networkdelta.c
+++ b/usr.sbin/timed/timed/networkdelta.c
@@ -62,7 +62,7 @@ static long median(float, float *, long *, long *, unsigned int);
* bad values.
*/
long
-networkdelta()
+networkdelta(void)
{
struct hosttbl *htp;
long med;
diff --git a/usr.sbin/timed/timed/readmsg.c b/usr.sbin/timed/timed/readmsg.c
index aca2dbe..8168612 100644
--- a/usr.sbin/timed/timed/readmsg.c
+++ b/usr.sbin/timed/timed/readmsg.c
@@ -69,11 +69,7 @@ struct timeval from_when;
*/
struct tsp *
-readmsg(type, machfrom, intvl, netfrom)
- int type;
- char *machfrom;
- struct timeval *intvl;
- struct netinfo *netfrom;
+readmsg(int type, char *machfrom, struct timeval *intvl, struct netinfo *netfrom)
{
int length;
fd_set ready;
@@ -342,7 +338,7 @@ again:
* only the type ACK is to be sent by a slave
*/
void
-slaveack()
+slaveack(void)
{
switch(msgin.tsp_type) {
@@ -374,7 +370,7 @@ slaveack()
* These packets should be acknowledged.
*/
void
-ignoreack()
+ignoreack(void)
{
switch(msgin.tsp_type) {
@@ -402,7 +398,7 @@ ignoreack()
* to the messages received by a master
*/
void
-masterack()
+masterack(void)
{
struct tsp resp;
@@ -445,9 +441,7 @@ masterack()
* Print a TSP message
*/
void
-print(msg, addr)
- struct tsp *msg;
- struct sockaddr_in *addr;
+print(struct tsp *msg, struct sockaddr_in *addr)
{
char tm[26];
time_t tsp_time_sec;
diff --git a/usr.sbin/timed/timed/slave.c b/usr.sbin/timed/timed/slave.c
index 26e34f7..15c0c43 100644
--- a/usr.sbin/timed/timed/slave.c
+++ b/usr.sbin/timed/timed/slave.c
@@ -55,7 +55,7 @@ static void setmaster(struct tsp *);
static void answerdelay(void);
int
-slave()
+slave(void)
{
int tries;
long electiontime, refusetime, looktime, looptime, adjtime;
@@ -610,8 +610,7 @@ loop:
* tell the world who our master is
*/
static void
-setmaster(msg)
- struct tsp *msg;
+setmaster(struct tsp *msg)
{
if (slavenet
&& (slavenet != old_slavenet
@@ -640,9 +639,7 @@ setmaster(msg)
* handle date change request on a slave
*/
static void
-schgdate(msg, newdate)
- struct tsp *msg;
- char *newdate;
+schgdate(struct tsp *msg, char *newdate)
{
struct tsp to;
u_short seq;
@@ -680,7 +677,7 @@ schgdate(msg, newdate)
* contention and likely collisions.
*/
static void
-answerdelay()
+answerdelay(void)
{
struct timeval timeout;
diff --git a/usr.sbin/timed/timed/timed.c b/usr.sbin/timed/timed/timed.c
index 4b0030c..e178912 100644
--- a/usr.sbin/timed/timed/timed.c
+++ b/usr.sbin/timed/timed/timed.c
@@ -110,9 +110,7 @@ static void usage(void);
* overhauled at Silicon Graphics
*/
int
-main(argc, argv)
- int argc;
- char *argv[];
+main(int argc, char *argv[])
{
int on;
int ret;
@@ -434,7 +432,7 @@ main(argc, argv)
}
static void
-usage()
+usage(void)
{
#ifdef HAVENIS
fprintf(stderr,
@@ -450,10 +448,7 @@ usage()
* suppress an upstart, untrustworthy, self-appointed master
*/
void
-suppress(addr, name,net)
- struct sockaddr_in *addr;
- char *name;
- struct netinfo *net;
+suppress(struct sockaddr_in *addr, char *name, struct netinfo *net)
{
struct sockaddr_in tgt;
char tname[MAXHOSTNAMELEN];
@@ -478,8 +473,7 @@ suppress(addr, name,net)
}
void
-lookformaster(ntp)
- struct netinfo *ntp;
+lookformaster(struct netinfo *ntp)
{
struct tsp resp, conflict, *answer;
struct timeval ntime;
@@ -578,7 +572,7 @@ lookformaster(ntp)
* networks;
*/
void
-setstatus()
+setstatus(void)
{
struct netinfo *ntp;
@@ -631,8 +625,7 @@ setstatus()
}
void
-makeslave(net)
- struct netinfo *net;
+makeslave(struct netinfo *net)
{
register struct netinfo *ntp;
@@ -647,7 +640,7 @@ makeslave(net)
* Try to become master over ignored nets..
*/
static void
-checkignorednets()
+checkignorednets(void)
{
register struct netinfo *ntp;
@@ -669,8 +662,7 @@ checkignorednets()
* Take a hint about for a good network.
*/
static void
-pickslavenet(ntp)
- struct netinfo *ntp;
+pickslavenet(struct netinfo *ntp)
{
if (slavenet != 0 && slavenet->status == SLAVE) {
makeslave(slavenet); /* prune extras */
@@ -690,8 +682,7 @@ pickslavenet(ntp)
* returns a random number in the range [inf, sup]
*/
long
-casual(inf, sup)
- long inf, sup;
+casual(long inf, long sup)
{
double value;
@@ -700,7 +691,7 @@ casual(inf, sup)
}
char *
-date()
+date(void)
{
time_t tv_sec;
@@ -709,8 +700,7 @@ date()
}
void
-addnetname(name)
- char *name;
+addnetname(char *name)
{
register struct nets **netlist = &nets;
@@ -723,11 +713,11 @@ addnetname(name)
(*netlist)->name = name;
}
-/* note a host as trustworthy */
+/* note a host as trustworthy
+ * perm 1=not part of the netgroup
+ */
static void
-add_good_host(name, perm)
- char *name;
- int perm; /* 1=not part of the netgroup */
+add_good_host(char *name, int perm)
{
register struct goodhost *ghp;
register struct hostent *hentp;
@@ -753,8 +743,7 @@ add_good_host(name, perm)
/* update our image of the net-group of trustworthy hosts
*/
void
-get_goodgroup(force)
- int force;
+get_goodgroup(int force)
{
# define NG_DELAY (30*60*CLK_TCK) /* 30 minutes */
static unsigned long last_update = -NG_DELAY;
@@ -822,8 +811,7 @@ get_goodgroup(force)
/* see if a machine is trustworthy
*/
int /* 1=trust hp to change our date */
-good_host_name(name)
- char *name;
+good_host_name(char *name)
{
register struct goodhost *ghp = goodhosts;
register char c;
diff --git a/usr.sbin/timed/timedc/cmds.c b/usr.sbin/timed/timedc/cmds.c
index 84740f6..e39bf03 100644
--- a/usr.sbin/timed/timedc/cmds.c
+++ b/usr.sbin/timed/timedc/cmds.c
@@ -32,7 +32,6 @@
static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#endif
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -78,8 +77,7 @@ void bytehostorder(struct tsp *);
/* compute the difference between our date and another machine
*/
static int /* difference in days from our time */
-daydiff(hostname)
- char *hostname;
+daydiff(char *hostname)
{
int i;
int trials;
@@ -164,9 +162,7 @@ daydiff(hostname)
* measurement.
*/
void
-clockdiff(argc, argv)
- int argc;
- char *argv[];
+clockdiff(int argc, char *argv[])
{
int measure_status;
extern int measure(u_long, u_long, char *, struct sockaddr_in*, int);
@@ -263,9 +259,7 @@ clockdiff(argc, argv)
* finds location of master timedaemon
*/
void
-msite(argc, argv)
- int argc;
- char *argv[];
+msite(int argc, char *argv[])
{
ssize_t cc;
fd_set ready;
@@ -360,7 +354,7 @@ msite(argc, argv)
* quits timedc
*/
void
-quit()
+quit(void)
{
exit(0);
}
@@ -372,9 +366,7 @@ quit()
* reliability of communication channel.
*/
void
-testing(argc, argv)
- int argc;
- char *argv[];
+testing(int argc, char *argv[])
{
struct servent *srvp;
struct sockaddr_in sin;
@@ -422,9 +414,7 @@ testing(argc, argv)
* Enables or disables tracing on local timedaemon
*/
void
-tracing(argc, argv)
- int argc;
- char *argv[];
+tracing(int argc, char *argv[])
{
int onflag;
int length;
@@ -513,7 +503,7 @@ tracing(argc, argv)
}
int
-priv_resources()
+priv_resources(void)
{
int port;
struct sockaddr_in sin;
diff --git a/usr.sbin/timed/timedc/timedc.c b/usr.sbin/timed/timedc/timedc.c
index 7047f57..f81da89 100644
--- a/usr.sbin/timed/timedc/timedc.c
+++ b/usr.sbin/timed/timedc/timedc.c
@@ -62,9 +62,7 @@ jmp_buf toplevel;
static struct cmd *getcmd(char *);
int
-main(argc, argv)
- int argc;
- char *argv[];
+main(int argc, char *argv[])
{
register struct cmd *c;
@@ -131,8 +129,7 @@ main(argc, argv)
}
void
-intr(signo)
- int signo;
+intr(int signo __unused)
{
if (!fromatty)
exit(0);
@@ -141,8 +138,7 @@ intr(signo)
static struct cmd *
-getcmd(name)
- char *name;
+getcmd(char *name)
{
register char *p, *q;
register struct cmd *c, *found;
@@ -175,7 +171,7 @@ getcmd(name)
* Slice a string up into argc/argv.
*/
void
-makeargv()
+makeargv(void)
{
register char *cp;
register char **argp = margv;
@@ -203,9 +199,7 @@ makeargv()
* Help command.
*/
void
-help(argc, argv)
- int argc;
- char *argv[];
+help(int argc, char *argv[])
{
register struct cmd *c;
diff --git a/usr.sbin/watchdogd/watchdogd.c b/usr.sbin/watchdogd/watchdogd.c
index 8194f96..50bdd91 100644
--- a/usr.sbin/watchdogd/watchdogd.c
+++ b/usr.sbin/watchdogd/watchdogd.c
@@ -71,6 +71,14 @@ static int nap = 1;
static char *test_cmd = NULL;
/*
+ * Ask malloc() to map minimum-sized chunks of virtual address space at a time,
+ * so that mlockall() won't needlessly wire megabytes of unused memory into the
+ * process. This must be done using the malloc_conf string so that it gets set
+ * up before the first allocation, which happens before entry to main().
+ */
+const char * malloc_conf = "lg_chunk:0";
+
+/*
* Periodically pat the watchdog, preventing it from firing.
*/
int
@@ -188,7 +196,7 @@ watchdog_loop(void)
if (watchdog_onoff(0) == 0) {
end_program = 2;
} else {
- warnx("Could not stop the watchdog, not exitting");
+ warnx("Could not stop the watchdog, not exiting");
end_program = 0;
}
}
OpenPOWER on IntegriCloud