diff options
247 files changed, 6234 insertions, 7149 deletions
@@ -21,6 +21,7 @@ # kernel-toolchains - Build kernel-toolchain for all universe targets. # doxygen - Build API documentation of the kernel, needs doxygen. # update - Convenient way to update your source tree(s). +# checkworld - Run test suite on installed world. # check-old - List obsolete directories/files/libraries. # check-old-dirs - List obsolete directories. # check-old-files - List obsolete files. @@ -112,8 +113,8 @@ .else TGTS= all all-man buildenv buildenvvars buildkernel buildworld \ - check-old check-old-dirs check-old-files check-old-libs \ - checkdpadd clean cleandepend cleandir cleanworld \ + check check-old check-old-dirs check-old-files check-old-libs \ + checkdpadd checkworld clean cleandepend cleandir cleanworld \ delete-old delete-old-dirs delete-old-files delete-old-libs \ depend distribute distributekernel distributekernel.debug \ distributeworld distrib-dirs distribution doxygen \ @@ -121,7 +122,7 @@ TGTS= all all-man buildenv buildenvvars buildkernel buildworld \ installkernel.debug packagekernel packageworld \ reinstallkernel reinstallkernel.debug \ installworld kernel-toolchain libraries lint maninstall \ - obj objlink regress rerelease showconfig tags toolchain update \ + obj objlink rerelease showconfig tags toolchain update \ _worldtmp _legacy _bootstrap-tools _cleanobj _obj \ _build-tools _cross-tools _includes _libraries _depend \ build32 builddtb distribute32 install32 xdev xdev-build xdev-install \ @@ -330,6 +331,10 @@ bmake: .PHONY ${MMAKE} all; \ ${MMAKE} install DESTDIR=${MYMAKE:H} BINDIR= +regress: .PHONY + @echo "'make regress' has been renamed 'make check'" | /usr/bin/fmt + @false + tinderbox toolchains kernel-toolchains kernels worlds: upgrade_checks tinderbox: diff --git a/Makefile.inc1 b/Makefile.inc1 index 0030917..99f9798 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -37,6 +37,7 @@ # The intended user-driven targets are: # buildworld - rebuild *everything*, including glue to help do upgrades # installworld- install everything built by "buildworld" +# checkworld - run test suite on installed world # doxygen - build API documentation of the kernel # update - convenient way to update your source tree (eg: svn/svnup) # @@ -1121,16 +1122,14 @@ redistribute: .MAKE .PHONY DISTRIBUTION=lib32 .endif -distrib-dirs: .MAKE .PHONY - ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ - ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} - -distribution: .MAKE .PHONY +distrib-dirs distribution: .MAKE .PHONY ${_+_}cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \ ${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET} +.if make(distribution) ${_+_}cd ${.CURDIR}; ${CROSSENV} PATH=${TMPPATH} \ ${MAKE} -f Makefile.inc1 ${IMAKE_INSTALL} \ METALOG=${METALOG} installconfig +.endif # # buildkernel and installkernel @@ -1475,6 +1474,20 @@ signpackages: _pkgbootstrap @pkg -o ABI_FILE=${WSTAGEDIR}/bin/sh repo ${REPODIR}/$$(pkg -o ABI_FILE=${WSTAGEDIR}/bin/sh config ABI) ${PKGSIGNKEY} # +# +# checkworld +# +# Run test suite on installed world. +# +checkworld: .PHONY + @if [ ! -x ${LOCALBASE}/bin/kyua ]; then \ + echo "You need kyua (devel/kyua) to run the test suite." | /usr/bin/fmt; \ + exit 1; \ + fi + ${_+_}${LOCALBASE}/bin/kyua test -k ${TESTSBASE}/Kyuafile + +# +# # doxygen # # Build the API documentation with doxygen diff --git a/bin/csh/Makefile b/bin/csh/Makefile index 51ef3dd..deb6347 100644 --- a/bin/csh/Makefile +++ b/bin/csh/Makefile @@ -51,41 +51,40 @@ FILESDIR= ${SHAREDIR}/examples/tcsh FILES= complete.tcsh csh-mode.el .endif -CATALOGS= et:et_EE.ISO8859-15 \ - finnish:fi_FI.ISO8859-1 \ - french:fr_FR.ISO8859-1 \ - german:de_DE.ISO8859-1 \ - greek:el_GR.ISO8859-7 \ - italian:it_IT.ISO8859-1 \ - ja:ja_JP.eucJP \ - russian:ru_RU.KOI8-R \ - spanish:es_ES.ISO8859-1 \ - ukrainian:uk_UA.KOI8-U - -NLSLINKS_fi_FI.ISO8859-1= fi_FI.ISO8859-15 -NLSLINKS_fr_FR.ISO8859-1= fr_BE.ISO8859-1 fr_BE.ISO8859-15 \ - fr_CA.ISO8859-1 fr_CA.ISO8859-15 fr_CH.ISO8859-1 \ - fr_CH.ISO8859-15 fr_FR.ISO8859-15 -NLSLINKS_de_DE.ISO8859-1= de_AT.ISO8859-1 de_AT.ISO8859-15 de_CH.ISO8859-1 \ - de_CH.ISO8859-15 de_DE.ISO8859-15 -NLSLINKS_it_IT.ISO8859-1= it_CH.ISO8859-1 it_CH.ISO8859-15 it_IT.ISO8859-15 -NLSLINKS_es_ES.ISO8859-1= es_ES.ISO8859-15 +CATALOGS= et:et_EE.UTF-8 \ + finnish:fi_FI.UTF-8 \ + french:fr_FR.UTF-8 \ + german:de_DE.UTF-8 \ + greek:el_GR.UTF-8 \ + italian:it_IT.UTF-8 \ + ja:ja_JP.UTF-8 \ + russian:ru_RU.UTF-8 \ + spanish:es_ES.UTF-8 \ + ukrainian:uk_UA.UTF-8 + +NLSLINKS_de_DE.UTF-8 = de_AT.UTF-8 de_CH.UTF-8 +NLSLINKS_fr_FR.UTF-8 = fr_BE.UTF-8 fr_CA.UTF-8 fr_CH.UTF-8 +NLSLINKS_it_IT.UTF-8 = it_CH.UTF-8 .if ${MK_NLS_CATALOGS} == "no" || defined(RESCUE) CFLAGS+= -DNO_NLS_CATALOGS .else CFLAGS+= -DHAVE_ICONV .if ${MK_ICONV} != "no" -NLSLINKS_de_DE.ISO8859-1 += de_AT.UTF-8 de_CH.UTF-8 de_DE.UTF-8 -NLSLINKS_el_GR.ISO8859-7 = el_GR.UTF-8 -NLSLINKS_es_ES.ISO8859-1 += es_ES.UTF-8 -NLSLINKS_et_EE.ISO8859-15 = et_EE.UTF-8 -NLSLINKS_fi_FI.ISO8859-1 += fi_FI.UTF-8 -NLSLINKS_fr_FR.ISO8859-1 += fr_BE.UTF-8 fr_CA.UTF-8 fr_CH.UTF-8 fr_FR.UTF-8 -NLSLINKS_it_IT.ISO8859-1 += it_CH.UTF-8 it_IT.UTF-8 -NLSLINKS_ja_JP.eucJP = ja_JP.SJIS ja_JP.UTF-8 -NLSLINKS_ru_RU.KOI8-R = ru_RU.CP1251 ru_RU.CP866 ru_RU.ISO8859-5 ru_RU.UTF-8 -NLSLINKS_uk_UA.KOI8-U = uk_UA.ISO8859-5 uk_UA.UTF-8 +NLSLINKS_de_DE.UTF-8 += de_AT.ISO8859-1 de_AT.ISO8859-15 de_CH.ISO8859-1 \ + de_CH.ISO8859-15 de_DE.ISO8859-1 de_DE.ISO8859-15 +NLSLINKS_el_GR.UTF-8 = el_GR.ISO8859-7 +NLSLINKS_es_ES.UTF-8 = es_ES.ISO8859-1 es_ES.ISO8859-15 +NLSLINKS_et_EE.UTF-8 = et_EE.ISO8859-15 +NLSLINKS_fi_FI.UTF-8 = fi_FI.ISO8859-1 fi_FI.ISO8859-15 +NLSLINKS_fr_FR.UTF-8 += fr_BE.ISO8859-1 fr_BE.ISO8859-15 \ + fr_CA.ISO8859-1 fr_CA.ISO8859-15 fr_CH.ISO8859-1 \ + fr_CH.ISO8859-15 fr_FR.ISO8859-1 fr_FR.ISO8859-15 +NLSLINKS_it_IT.UTF-8 += it_CH.ISO8859-1 it_CH.ISO8859-15 it_IT.ISO8859-1 \ + it_IT.ISO8859-15 +NLSLINKS_ja_JP.UTF-8 = ja_JP.SJIS ja_JP.eucJP +NLSLINKS_ru_RU.UTF-8 = ru_RU.CP1251 ru_RU.CP866 ru_RU.ISO8859-5 ru_RU.KOI8-R +NLSLINKS_uk_UA.UTF-8 = uk_UA.ISO8859-5 uk_UA.KOI8-U .else # Above links can be installed from ports/shells/tcsh_nls diff --git a/bin/dd/args.c b/bin/dd/args.c index 2f197f8..1cbf3b3 100644 --- a/bin/dd/args.c +++ b/bin/dd/args.c @@ -360,6 +360,46 @@ c_conv(const void *a, const void *b) ((const struct conv *)b)->name)); } +static uintmax_t +postfix_to_mult(const char expr) +{ + uintmax_t mult; + + mult = 0; + switch (expr) { + case 'B': + case 'b': + mult = 512; + break; + case 'K': + case 'k': + mult = 1 << 10; + break; + case 'M': + case 'm': + mult = 1 << 20; + break; + case 'G': + case 'g': + mult = 1 << 30; + break; + case 'T': + case 't': + mult = (uintmax_t)1 << 40; + break; + case 'P': + case 'p': + mult = (uintmax_t)1 << 50; + break; + case 'W': + case 'w': + mult = sizeof(int); + break; + } + + return (mult); +} + /* * Convert an expression of the following forms to a uintmax_t. * 1) A positive decimal number. @@ -386,31 +426,7 @@ get_num(const char *val) if (expr == val) /* No valid digits. */ errx(1, "%s: illegal numeric value", oper); - mult = 0; - switch (*expr) { - case 'B': - case 'b': - mult = 512; - break; - case 'K': - case 'k': - mult = 1 << 10; - break; - case 'M': - case 'm': - mult = 1 << 20; - break; - case 'G': - case 'g': - mult = 1 << 30; - break; - case 'W': - case 'w': - mult = sizeof(int); - break; - default: - ; - } + mult = postfix_to_mult(*expr); if (mult != 0) { prevnum = num; @@ -460,29 +476,7 @@ get_off_t(const char *val) if (expr == val) /* No valid digits. */ errx(1, "%s: illegal numeric value", oper); - mult = 0; - switch (*expr) { - case 'B': - case 'b': - mult = 512; - break; - case 'K': - case 'k': - mult = 1 << 10; - break; - case 'M': - case 'm': - mult = 1 << 20; - break; - case 'G': - case 'g': - mult = 1 << 30; - break; - case 'W': - case 'w': - mult = sizeof(int); - break; - } + mult = postfix_to_mult(*expr); if (mult != 0) { prevnum = num; diff --git a/bin/dd/dd.1 b/bin/dd/dd.1 index 0908642..4047cdc 100644 --- a/bin/dd/dd.1 +++ b/bin/dd/dd.1 @@ -32,7 +32,7 @@ .\" @(#)dd.1 8.2 (Berkeley) 1/13/94 .\" $FreeBSD$ .\" -.Dd August 28, 2014 +.Dd February 4, 2016 .Dt DD 1 .Os .Sh NAME @@ -332,10 +332,13 @@ If the number ends with a .Dq Li k , .Dq Li m , .Dq Li g , +.Dq Li t , +.Dq Li p , or .Dq Li w , the -number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G) +number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G), +1099511627776 (1T), 1125899906842624 (1P) or the number of bytes in an integer, respectively. Two or more numbers may be separated by an .Dq Li x diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c index b62ee66..9079d1d 100644 --- a/contrib/bsnmp/snmp_mibII/mibII.c +++ b/contrib/bsnmp/snmp_mibII/mibII.c @@ -982,7 +982,7 @@ handle_rtmsg(struct rt_msghdr *rtm) { struct sockaddr *addrs[RTAX_MAX]; struct if_msghdr *ifm; - struct ifa_msghdr ifam; + struct ifa_msghdr ifam, *ifamp; struct ifma_msghdr *ifmam; #ifdef RTM_IFANNOUNCE struct if_announcemsghdr *ifan; @@ -1002,8 +1002,9 @@ handle_rtmsg(struct rt_msghdr *rtm) switch (rtm->rtm_type) { case RTM_NEWADDR: - memcpy(&ifam, rtm, sizeof(ifam)); - mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs); + ifamp = (struct ifa_msghdr *)rtm; + memcpy(&ifam, ifamp, sizeof(ifam)); + mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs); if (addrs[RTAX_IFA] == NULL || addrs[RTAX_NETMASK] == NULL) break; @@ -1029,8 +1030,9 @@ handle_rtmsg(struct rt_msghdr *rtm) break; case RTM_DELADDR: - memcpy(&ifam, rtm, sizeof(ifam)); - mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs); + ifamp = (struct ifa_msghdr *)rtm; + memcpy(&ifam, ifamp, sizeof(ifam)); + mib_extract_addrs(ifam.ifam_addrs, (u_char *)(ifamp + 1), addrs); if (addrs[RTAX_IFA] == NULL) break; diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index 6902024..a017023 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -1053,8 +1053,9 @@ static struct { static const char * r_type(unsigned int mach, unsigned int type) { + static char s_type[32]; + switch(mach) { - case EM_NONE: return ""; case EM_386: case EM_IAMCU: switch(type) { @@ -1089,8 +1090,8 @@ r_type(unsigned int mach, unsigned int type) case 35: return "R_386_TLS_DTPMOD32"; case 36: return "R_386_TLS_DTPOFF32"; case 37: return "R_386_TLS_TPOFF32"; - default: return ""; } + break; case EM_AARCH64: switch(type) { case 0: return "R_AARCH64_NONE"; @@ -1145,6 +1146,16 @@ r_type(unsigned int mach, unsigned int type) case 311: return "R_AARCH64_ADR_GOT_PAGE"; case 312: return "R_AARCH64_LD64_GOT_LO12_NC"; case 313: return "R_AARCH64_LD64_GOTPAGE_LO15"; + case 560: return "R_AARCH64_TLSDESC_LD_PREL19"; + case 561: return "R_AARCH64_TLSDESC_ADR_PREL21"; + case 562: return "R_AARCH64_TLSDESC_ADR_PAGE21"; + case 563: return "R_AARCH64_TLSDESC_LD64_LO12"; + case 564: return "R_AARCH64_TLSDESC_ADD_LO12"; + case 565: return "R_AARCH64_TLSDESC_OFF_G1"; + case 566: return "R_AARCH64_TLSDESC_OFF_G0_NC"; + case 567: return "R_AARCH64_TLSDESC_LDR"; + case 568: return "R_AARCH64_TLSDESC_ADD"; + case 569: return "R_AARCH64_TLSDESC_CALL"; case 1024: return "R_AARCH64_COPY"; case 1025: return "R_AARCH64_GLOB_DAT"; case 1026: return "R_AARCH64_JUMP_SLOT"; @@ -1154,8 +1165,8 @@ r_type(unsigned int mach, unsigned int type) case 1030: return "R_AARCH64_TLS_TPREL64"; case 1031: return "R_AARCH64_TLSDESC"; case 1032: return "R_AARCH64_IRELATIVE"; - default: return ""; } + break; case EM_ARM: switch(type) { case 0: return "R_ARM_NONE"; @@ -1206,8 +1217,8 @@ r_type(unsigned int mach, unsigned int type) case 253: return "R_ARM_RABS32"; case 254: return "R_ARM_RPC24"; case 255: return "R_ARM_RBASE"; - default: return ""; } + break; case EM_IA_64: switch(type) { case 0: return "R_IA_64_NONE"; @@ -1290,8 +1301,8 @@ r_type(unsigned int mach, unsigned int type) case 182: return "R_IA_64_DTPREL64MSB"; case 183: return "R_IA_64_DTPREL64LSB"; case 186: return "R_IA_64_LTOFF_DTPREL22"; - default: return ""; } + break; case EM_MIPS: switch(type) { case 0: return "R_MIPS_NONE"; @@ -1324,9 +1335,8 @@ r_type(unsigned int mach, unsigned int type) case 48: return "R_MIPS_TLS_TPREL64"; case 49: return "R_MIPS_TLS_TPREL_HI16"; case 50: return "R_MIPS_TLS_TPREL_LO16"; - - default: return ""; } + break; case EM_PPC: switch(type) { case 0: return "R_PPC_NONE"; @@ -1406,8 +1416,8 @@ r_type(unsigned int mach, unsigned int type) case 114: return "R_PPC_EMB_RELST_HA"; case 115: return "R_PPC_EMB_BIT_FLD"; case 116: return "R_PPC_EMB_RELSDA"; - default: return ""; } + break; case EM_RISCV: switch(type) { case 0: return "R_RISCV_NONE"; @@ -1453,6 +1463,7 @@ r_type(unsigned int mach, unsigned int type) case 44: return "R_RISCV_RVC_BRANCH"; case 45: return "R_RISCV_RVC_JUMP"; } + break; case EM_SPARC: case EM_SPARCV9: switch(type) { @@ -1536,8 +1547,8 @@ r_type(unsigned int mach, unsigned int type) case 77: return "R_SPARC_TLS_DTPOFF64"; case 78: return "R_SPARC_TLS_TPOFF32"; case 79: return "R_SPARC_TLS_TPOFF64"; - default: return ""; } + break; case EM_X86_64: switch(type) { case 0: return "R_X86_64_NONE"; @@ -1578,10 +1589,12 @@ r_type(unsigned int mach, unsigned int type) case 35: return "R_X86_64_TLSDESC_CALL"; case 36: return "R_X86_64_TLSDESC"; case 37: return "R_X86_64_IRELATIVE"; - default: return ""; } - default: return ""; + break; } + + snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type); + return (s_type); } static const char * diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index a674acb..69b6d0f 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -716,5 +716,18 @@ if [ -z "${source_rc_confs_defined}" ]; then ;; esac done + # Re-do process to pick up [possibly] redefined $rc_conf_files + for i in ${rc_conf_files}; do + case ${sourced_files} in + *:$i:*) + ;; + *) + sourced_files="${sourced_files}:$i:" + if [ -r $i ]; then + . $i + fi + ;; + esac + done } fi diff --git a/etc/periodic/daily/800.scrub-zfs b/etc/periodic/daily/800.scrub-zfs index 359be13..64eac99 100755 --- a/etc/periodic/daily/800.scrub-zfs +++ b/etc/periodic/daily/800.scrub-zfs @@ -63,6 +63,11 @@ case "$daily_scrub_zfs_enable" in _last_scrub=$(zpool history ${pool} | \ sed -ne '2s/ .*$//p') fi + if [ -z "${_last_scrub}" ]; then + echo " skipping scrubbing of pool '${pool}':" + echo " can't get last scrubbing date" + continue + fi # Now minus last scrub (both in seconds) converted to days. _scrub_diff=$(expr -e \( $(date +%s) - \ @@ -73,11 +78,14 @@ case "$daily_scrub_zfs_enable" in continue fi - _status="$(zpool status ${pool} | grep scrub:)" + _status="$(zpool status ${pool} | grep scan:)" case "${_status}" in *"scrub in progress"*) echo " scrubbing of pool '${pool}' already in progress, skipping:" ;; + *"resilver in progress"*) + echo " resilvering of pool '${pool}' is in progress, skipping:" + ;; *"none requested"*) echo " starting first scrub (since reboot) of pool '${pool}':" zpool scrub ${pool} diff --git a/etc/rc.d/jail b/etc/rc.d/jail index fa0bc46..b33f1b9 100755 --- a/etc/rc.d/jail +++ b/etc/rc.d/jail @@ -563,7 +563,7 @@ jail_warn() # To relieve confusion, show a warning message. case $_confwarn in 1) warn "Per-jail configuration via jail_* variables " \ - "is obsolete. Please consider to migrate to $jail_conf." + "is obsolete. Please consider migrating to $jail_conf." ;; esac } diff --git a/lib/libc/sys/connect.2 b/lib/libc/sys/connect.2 index e3e5783..80f4407 100644 --- a/lib/libc/sys/connect.2 +++ b/lib/libc/sys/connect.2 @@ -28,7 +28,7 @@ .\" @(#)connect.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd September 29, 2014 +.Dd February 4, 2016 .Dt CONNECT 2 .Os .Sh NAME @@ -58,6 +58,14 @@ another socket. The other socket is specified by .Fa name , which is an address in the communications space of the socket. +.Fa namelen +indicates the amount of space pointed to by +.Fa name , +in bytes; the +.Fa sa_len +member of +.Fa name +is ignored. Each communications space interprets the .Fa name argument in its own way. diff --git a/lib/libc/sys/semget.2 b/lib/libc/sys/semget.2 index 945044d..debcf11 100644 --- a/lib/libc/sys/semget.2 +++ b/lib/libc/sys/semget.2 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 12, 1995 +.Dd February 7, 2016 .Dt SEMGET 2 .Os .Sh NAME @@ -132,6 +132,17 @@ already exists. .It Bq Er EINVAL The number of semaphores requested exceeds the system imposed maximum per set. +.It Bq Er EINVAL +A semaphore set corresponding to +.Fa key +already exists and contains fewer semaphores than +.Fa nsems . +.It Bq Er EINVAL +A semaphore set corresponding to +.Fa key +does not exist and +.Fa nsems +is 0 or negative. .It Bq Er ENOSPC Insufficiently many semaphores are available. .It Bq Er ENOSPC diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3 index 1e0ff5d..05ee76e 100644 --- a/lib/libedit/editline.3 +++ b/lib/libedit/editline.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: editline.3,v 1.84 2014/12/25 13:39:41 wiz Exp $ +.\" $NetBSD: editline.3,v 1.85 2015/11/03 21:36:59 christos Exp $ .\" .\" Copyright (c) 1997-2014 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 25, 2014 +.Dd November 3, 2015 .Dt EDITLINE 3 .Os .Sh NAME @@ -191,7 +191,7 @@ counterparts. The following functions are available: .Bl -tag -width 4n .It Fn el_init -Initialise the line editor, and return a data structure +Initialize the line editor, and return a data structure to be used by all other line editing functions, or .Dv NULL on failure. @@ -521,61 +521,68 @@ are supported, along with actual type of .Fa result : .Bl -tag -width 4n .It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c" -Return a pointer to the function that displays the prompt in +Set .Fa f . +to a pointer to the function that displays the prompt. If .Fa c is not .Dv NULL , -return the start/stop literal prompt character in it. +set it to the start/stop literal prompt character. .It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c" -Return a pointer to the function that displays the prompt in +Set .Fa f . +to a pointer to the function that displays the prompt. If .Fa c is not .Dv NULL , -return the start/stop literal prompt character in it. -.It Dv EL_EDITOR , Fa "const char **" -Return the name of the editor, which will be one of +set it to the start/stop literal prompt character. +.It Dv EL_EDITOR , Fa "const char **n" +Set the name of the editor in +.Fa n , +which will be one of .Dq emacs or .Dq vi . .It Dv EL_GETTC , Fa "const char *name" , Fa "void *value" -Return non-zero if +If .Fa name is a valid .Xr termcap 5 -capability -and set +capability set .Fa value to the current value of that capability. -.It Dv EL_SIGNAL , Fa "int *" -Return non-zero if +.It Dv EL_SIGNAL , Fa "int *s" +Set +.Fa s +to non zero if .Nm has installed private signal handlers (see .Fn el_get above). -.It Dv EL_EDITMODE , Fa "int *" -Return non-zero if editing is enabled. +.It Dv EL_EDITMODE , Fa "int *c" +Set +.Fa c +to non-zero if editing is enabled. .It Dv EL_GETCFN , Fa "int (**f)(EditLine *, char *)" Return a pointer to the function that read characters, which is equal to .Dq Dv EL_BUILTIN_GETCFN in the case of the default builtin function. .It Dv EL_CLIENTDATA , Fa "void **data" -Retrieve +Set .Fa data -previously registered with the corresponding +to the previously registered client data set by an .Fn el_set call. -.It Dv EL_UNBUFFERED , Fa "int" -Return non-zero if unbuffered mode is enabled. -.It Dv EL_PREP_TERM , Fa "int" -Sets or clears terminal editing mode. +.It Dv EL_UNBUFFERED , Fa "int *c" +Set +.Fa c +to non-zero if unbuffered mode is enabled. .It Dv EL_GETFP , Fa "int fd", Fa "FILE **fp" -Return in +Set .Fa fp -the current +to the current .Nm editline file pointer for .Dq input @@ -593,7 +600,7 @@ or .Dv 2 . .El .It Fn el_source -Initialise +Initialize .Nm by reading the contents of .Fa file . @@ -671,7 +678,7 @@ and freed by The following functions are available: .Bl -tag -width 4n .It Fn history_init -Initialise the history list, and return a data structure +Initialize the history list, and return a data structure to be used by all other history list functions, or .Dv NULL on failure. @@ -810,7 +817,7 @@ and freed by The following functions are available: .Bl -tag -width 4n .It Fn tok_init -Initialise the tokenizer, and return a data structure +Initialize the tokenizer, and return a data structure to be used by all other tokenizer functions. .Fa IFS contains the Input Field Separators, which defaults to diff --git a/lib/libedit/el.c b/lib/libedit/el.c index 57ea6e5..65bd86b 100644 --- a/lib/libedit/el.c +++ b/lib/libedit/el.c @@ -1,4 +1,4 @@ -/* $NetBSD: el.c,v 1.73 2014/06/18 18:12:28 christos Exp $ */ +/* $NetBSD: el.c,v 1.74 2015/12/08 12:56:55 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; #else -__RCSID("$NetBSD: el.c,v 1.73 2014/06/18 18:12:28 christos Exp $"); +__RCSID("$NetBSD: el.c,v 1.74 2015/12/08 12:56:55 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include <sys/cdefs.h> @@ -137,7 +137,8 @@ el_end(EditLine *el) terminal_end(el); keymacro_end(el); map_end(el); - tty_end(el); + if (!(el->el_flags & NO_TTY)) + tty_end(el); ch_end(el); search_end(el); hist_end(el); diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h index 1cd7d9d..6ca6877 100644 --- a/lib/libedit/hist.h +++ b/lib/libedit/hist.h @@ -1,4 +1,4 @@ -/* $NetBSD: hist.h,v 1.14 2014/05/11 01:05:17 christos Exp $ */ +/* $NetBSD: hist.h,v 1.15 2016/01/30 15:05:27 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -47,10 +47,10 @@ typedef int (*hist_fun_t)(void *, TYPE(HistEvent) *, int, ...); typedef struct el_history_t { Char *buf; /* The history buffer */ - size_t sz; /* Size of history buffer */ + size_t sz; /* Size of history buffer */ Char *last; /* The last character */ int eventno; /* Event we are looking for */ - void * ref; /* Argument for history fcns */ + void *ref; /* Argument for history fcns */ hist_fun_t fun; /* Event access */ TYPE(HistEvent) ev; /* Event cookie */ } el_history_t; diff --git a/lib/libedit/keymacro.h b/lib/libedit/keymacro.h index 57a7a5d..139cda2 100644 --- a/lib/libedit/keymacro.h +++ b/lib/libedit/keymacro.h @@ -1,4 +1,4 @@ -/* $NetBSD: keymacro.h,v 1.2 2011/07/28 03:44:36 christos Exp $ */ +/* $NetBSD: keymacro.h,v 1.3 2016/01/29 19:59:11 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -48,7 +48,7 @@ typedef union keymacro_value_t { typedef struct keymacro_node_t keymacro_node_t; -typedef struct el_keymacromacro_t { +typedef struct el_keymacro_t { Char *buf; /* Key print buffer */ keymacro_node_t *map; /* Key map */ keymacro_value_t val; /* Local conversion buffer */ diff --git a/lib/libedit/search.c b/lib/libedit/search.c index 3cd205a..df9999c 100644 --- a/lib/libedit/search.c +++ b/lib/libedit/search.c @@ -1,4 +1,4 @@ -/* $NetBSD: search.c,v 1.30 2011/10/04 15:27:04 christos Exp $ */ +/* $NetBSD: search.c,v 1.31 2016/01/30 04:02:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: search.c,v 1.30 2011/10/04 15:27:04 christos Exp $"); +__RCSID("$NetBSD: search.c,v 1.31 2016/01/30 04:02:51 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include <sys/cdefs.h> @@ -149,7 +149,7 @@ el_match(const Char *str, const Char *pat) if (re_comp(ct_encode_string(pat, &conv)) != NULL) return 0; else - return re_exec(ct_encode_string(str, &conv) == 1); + return re_exec(ct_encode_string(str, &conv)) == 1; #endif } diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c index e61ecaf..f5171c4 100644 --- a/lib/libedit/tokenizer.c +++ b/lib/libedit/tokenizer.c @@ -1,4 +1,4 @@ -/* $NetBSD: tokenizer.c,v 1.21 2011/08/16 16:25:15 christos Exp $ */ +/* $NetBSD: tokenizer.c,v 1.22 2016/01/30 04:02:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tokenizer.c,v 1.21 2011/08/16 16:25:15 christos Exp $"); +__RCSID("$NetBSD: tokenizer.c,v 1.22 2016/01/30 04:02:51 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include <sys/cdefs.h> @@ -448,5 +448,5 @@ FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc, memset(&li, 0, sizeof(li)); li.buffer = line; li.cursor = li.lastchar = Strchr(line, '\0'); - return FUN(tok,line(tok, &li, argc, argv, NULL, NULL)); + return FUN(tok,line)(tok, &li, argc, argv, NULL, NULL); } diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c index ecf2e2a..a508e43 100644 --- a/lib/libedit/tty.c +++ b/lib/libedit/tty.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.47 2015/05/14 10:44:15 christos Exp $ */ +/* $NetBSD: tty.c,v 1.49 2015/12/08 16:53:27 gson Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tty.c,v 1.47 2015/05/14 10:44:15 christos Exp $"); +__RCSID("$NetBSD: tty.c,v 1.49 2015/12/08 16:53:27 gson Exp $"); #endif #endif /* not lint && not SCCSID */ #include <sys/cdefs.h> @@ -582,6 +582,9 @@ protected void /*ARGSUSED*/ tty_end(EditLine *el) { + if (el->el_flags & EDIT_DISABLED) + return; + if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, diff --git a/lib/libmemstat/memstat_uma.c b/lib/libmemstat/memstat_uma.c index 8e89585..20cd520 100644 --- a/lib/libmemstat/memstat_uma.c +++ b/lib/libmemstat/memstat_uma.c @@ -29,6 +29,7 @@ #include <sys/param.h> #include <sys/cpuset.h> #include <sys/sysctl.h> +#include <sys/_task.h> #include <vm/vm.h> #include <vm/vm_page.h> diff --git a/share/examples/jails/jib b/share/examples/jails/jib new file mode 100755 index 0000000..540df09 --- /dev/null +++ b/share/examples/jails/jib @@ -0,0 +1,367 @@ +#!/bin/sh +#- +# Copyright (c) 2016 Devin Teske +# 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$ +# +############################################################ IDENT(1) +# +# $Title: if_bridge(4) management script for vnet jails $ +# +############################################################ INFORMATION +# +# Use this tool with jail.conf(5) (or rc.conf(5) ``legacy'' configuration) to +# manage `vnet' interfaces. In jail.conf(5) format: +# +# ### BEGIN EXCERPT ### +# +# xxx { +# host.hostname = "xxx.yyy"; +# path = "/vm/xxx"; +# +# # +# # NB: Below 2-lines required +# # NB: The number of eNb_xxx interfaces should match the number of +# # arguments given to `jib addm xxx' in exec.prestart value. +# # +# vnet; +# vnet.interface = "e0b_xxx e1b_xxx ..."; +# +# exec.clean; +# exec.system_user = "root"; +# exec.jail_user = "root"; +# +# # +# # NB: Below 2-lines required +# # NB: The number of arguments after `jib addm xxx' should match +# # the number of eNb_xxx arguments in vnet.interface value. +# # +# exec.prestart += "jib addm xxx em0 em1 ..."; +# exec.poststop += "jib destroy xxx"; +# +# # Standard recipe +# exec.start += "/bin/sh /etc/rc"; +# exec.stop = "/bin/sh /etc/rc.shutdown"; +# exec.consolelog = "/var/log/jail_xxx_console.log"; +# mount.devfs; +# +# # Optional (default off) +# #allow.mount; +# #allow.set_hostname = 1; +# #allow.sysvipc = 1; +# #devfs_ruleset = "11"; # rule to unhide bpf for DHCP +# } +# +# ### END EXCERPT ### +# +# In rc.conf(5) ``legacy'' format (used when /etc/jail.conf does not exist): +# +# ### BEGIN EXCERPT ### +# +# jail_enable="YES" +# jail_list="xxx" +# +# # +# # Global presets for all jails +# # +# jail_devfs_enable="YES" # mount devfs +# +# # +# # Global options (default off) +# # +# #jail_mount_enable="YES" # mount /etc/fstab.{name} +# #jail_set_hostname_allow="YES" # Allow hostname to change +# #jail_sysvipc_allow="YES" # Allow SysV Interprocess Comm. +# +# # xxx +# jail_xxx_hostname="xxx.shxd.cx" # hostname +# jail_xxx_rootdir="/vm/xxx" # root directory +# jail_xxx_vnet_interfaces="e0b_xxx e1bxxx ..." # vnet interface(s) +# jail_xxx_exec_prestart0="jib addm xxx em0 em1 ..." # bridge interface(s) +# jail_xxx_exec_poststop0="jib destroy xxx" # destroy interface(s) +# #jail_xxx_mount_enable="YES" # mount /etc/fstab.xxx +# #jail_xxx_devfs_ruleset="11" # rule to unhide bpf for DHCP +# +# ### END EXCERPT ### +# +# Note that the legacy rc.conf(5) format is converted to +# /var/run/jail.{name}.conf by /etc/rc.d/jail if jail.conf(5) is missing. +# +# ASIDE: dhclient(8) inside a vnet jail... +# +# To allow dhclient(8) to work inside a vnet jail, make sure the following +# appears in /etc/devfs.rules (which should be created if it doesn't exist): +# +# [devfsrules_jail=11] +# add include $devfsrules_hide_all +# add include $devfsrules_unhide_basic +# add include $devfsrules_unhide_login +# add include $devfsrules_unhide_bpf +# +# And set ether devfs.ruleset="11" (jail.conf(5)) or +# jail_{name}_devfs_ruleset="11" (rc.conf(5)). +# +# NB: While this tool can't create every type of desirable topology, it should +# handle most setups, minus some which considered exotic or purpose-built. +# +############################################################ GLOBALS + +pgm="${0##*/}" # Program basename + +# +# Global exit status +# +SUCCESS=0 +FAILURE=1 + +############################################################ FUNCTIONS + +usage() +{ + local action usage descr + exec >&2 + echo "Usage: $pgm action [arguments]" + echo "Actions:" + for action in \ + addm \ + show \ + show1 \ + destroy \ + ; do + eval usage=\"\$jib_${action}_usage\" + [ "$usage" ] || continue + eval descr=\"\$jib_${action}_descr\" + printf "\t%s\n\t\t%s\n" "$usage" "$descr" + done + exit $FAILURE +} + +action_usage() +{ + local usage action="$1" + eval usage=\"\$jib_${action}_usage\" + echo "Usage: $pgm $usage" >&2 + exit $FAILURE +} + +mustberoot_to_continue() +{ + if [ "$( id -u )" -ne 0 ]; then + echo "Must run as root!" >&2 + exit $FAILURE + fi +} + +jib_addm_usage="addm [-b BRIDGE_NAME] NAME interface0 [interface1 ...]" +jib_addm_descr="Creates e0b_NAME [e1b_NAME ...]" +jib_addm() +{ + local OPTIND=1 OPTARG flag bridge=bridge + while getopts b: flag; do + case "$flag" in + b) bridge="${OPTARG:-bridge}" ;; + *) action_usage addm # NOTREACHED + esac + done + shift $(( $OPTIND - 1 )) + + local name="$1" + [ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -gt 1 ] || + action_usage addm # NOTREACHED + shift 1 # name + + mustberoot_to_continue + + local iface iface_devid eiface_devid_a eiface_devid_b + local new num quad i=0 + for iface in $*; do + + # 1. Make sure the interface doesn't exist already + ifconfig "e${i}a_$name" > /dev/null 2>&1 && continue + + # 2. Bring the interface up + ifconfig $iface up || return + + # 3. Make sure the interface has been bridged + if ! ifconfig "$iface$bridge" > /dev/null 2>&1; then + new=$( ifconfig bridge create ) || return + ifconfig $new addm $iface || return + ifconfig $new name "$iface$bridge" || return + fi + + # 4. Create a new interface to the bridge + new=$( ifconfig epair create ) || return + ifconfig "$iface$bridge" addm $new || return + + # 5. Rename the new interface + ifconfig $new name "e${i}a_$name" || return + ifconfig ${new%a}b name "e${i}b_$name" || return + + # + # 6. Set the MAC address of the new interface using a sensible + # algorithm to prevent conflicts on the network. + # + # The formula I'm using is ``SP:SS:SI:II:II:II'' where: + # + S denotes 16 bits of sum(1) data, split because P (below). + # + P denotes the special nibble whose value, if one of + # 2, 6, A, or E (but usually 2) denotes a privately + # administered MAC address (while remaining routable). + # + I denotes bits that are inherited from parent interface. + # + # The S bits are a CRC-16 checksum of NAME, allowing the jail + # to change the epair(4) generation order without affecting the + # MAC address. Meanwhile, if the jail NAME changes (e.g., it + # was duplicated and given a new name with no other changes), + # the underlying network interface changes, or the jail is + # moved to another host, the MAC address will be recalculated + # to a new, similarly unique value preventing conflict. + # + iface_devid=$( ifconfig $iface ether | awk '/ether/,$0=$2' ) + eiface_devid_a=${iface_devid#??:??:?} + eiface_devid_b=${iface_devid#??:??:?} + num=$( set -- `echo -n $name | sum` && echo $1 ) + quad=$(( $num & 15 )) + case "$quad" in + 10) quad=a ;; 11) quad=b ;; 12) quad=c ;; + 13) quad=d ;; 14) quad=e ;; 15) quad=f ;; + esac + eiface_devid_a=:$quad$eiface_devid_a + eiface_devid_b=:$quad$eiface_devid_b + num=$(( $num >> 4 )) + quad=$(( $num & 15 )) + case "$quad" in + 10) quad=a ;; 11) quad=b ;; 12) quad=c ;; + 13) quad=d ;; 14) quad=e ;; 15) quad=f ;; + esac + eiface_devid_a=$quad$eiface_devid_a + eiface_devid_b=$quad$eiface_devid_b + num=$(( $num >> 4 )) + quad=$(( $num & 15 )) + case "$quad" in + 10) quad=a ;; 11) quad=b ;; 12) quad=c ;; + 13) quad=d ;; 14) quad=e ;; 15) quad=f ;; + esac + eiface_devid_a=2:$quad$eiface_devid_a + eiface_devid_b=6:$quad$eiface_devid_b + num=$(( $num >> 4 )) + quad=$(( $num & 15 )) + case "$quad" in + 10) quad=a ;; 11) quad=b ;; 12) quad=c ;; + 13) quad=d ;; 14) quad=e ;; 15) quad=f ;; + esac + eiface_devid_a=$quad$eiface_devid_a + eiface_devid_b=$quad$eiface_devid_b + ifconfig "e${i}a_$name" ether $eiface_devid_a > /dev/null 2>&1 + ifconfig "e${i}b_$name" ether $eiface_devid_b > /dev/null 2>&1 + + i=$(( $i + 1 )) # on to next ng{i}_name + done # for iface +} + +jib_show_usage="show" +jib_show_descr="List possible NAME values for \`show NAME'" +jib_show1_usage="show NAME" +jib_show1_descr="Lists ng0_NAME [ng1_NAME ...]" +jib_show2_usage="show [NAME]" +jib_show() +{ + local OPTIND=1 OPTARG flag + while getopts "" flag; do + case "$flag" in + *) action_usage show2 # NOTREACHED + esac + done + shift $(( $OPTIND - 1 )) + if [ $# -eq 0 ]; then + ifconfig | awk ' + /^[^:[:space:]]+:/ { + iface = $1 + sub(/:.*/, "", iface) + next + } + $1 == "groups:" { + for (n = split($0, group); n > 1; n--) { + if (group[n] != "bridge") continue + print iface + next + } + }' | + xargs -rn1 ifconfig | + awk '$1 == "member:" && + sub(/^e[[:digit:]]+a_/, "", $2), $0 = $2' | + sort -u + return + fi + ifconfig | awk -v name="$1" ' + match($0, /^e[[:digit:]]+a_/) && sub(/:.*/, "") && + substr($1, RSTART + RLENGTH) == name + ' | sort +} + +jib_destroy_usage="destroy NAME" +jib_destroy_descr="Destroy e0b_NAME [e1b_NAME ...]" +jib_destroy() +{ + local OPTIND=1 OPTARG flag + while getopts "" flag; do + case "$flag" in + *) action_usage destroy # NOTREACHED + esac + done + shift $(( $OPTIND -1 )) + local name="$1" + [ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -eq 1 ] || + action_usage destroy # NOTREACHED + mustberoot_to_continue + jib_show "$name" | xargs -rn1 -I eiface ifconfig eiface destroy +} + +############################################################ MAIN + +# +# Command-line arguments +# +action="$1" +[ "$action" ] || usage # NOTREACHED + +# +# Validate action argument +# +if [ "$BASH_VERSION" ]; then + type="$( type -t "jib_$action" )" || usage # NOTREACHED +else + type="$( type "jib_$action" 2> /dev/null )" || usage # NOTREACHED +fi +case "$type" in +*function) + shift 1 # action + eval "jib_$action" \"\$@\" + ;; +*) usage # NOTREACHED +esac + +################################################################################ +# END +################################################################################ diff --git a/share/examples/jails/jng b/share/examples/jails/jng new file mode 100755 index 0000000..605db90 --- /dev/null +++ b/share/examples/jails/jng @@ -0,0 +1,416 @@ +#!/bin/sh +#- +# Copyright (c) 2016 Devin Teske +# 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$ +# +############################################################ IDENT(1) +# +# $Title: netgraph(4) management script for vnet jails $ +# +############################################################ INFORMATION +# +# Use this tool with jail.conf(5) (or rc.conf(5) ``legacy'' configuration) to +# manage `vnet' interfaces. In jail.conf(5) format: +# +# ### BEGIN EXCERPT ### +# +# xxx { +# host.hostname = "xxx.yyy"; +# path = "/vm/xxx"; +# +# # +# # NB: Below 2-lines required +# # NB: The number of ngN_xxx interfaces should match the number of +# # arguments given to `jng bridge xxx' in exec.prestart value. +# # +# vnet; +# vnet.interface = "ng0_xxx ng1_xxx ..."; +# +# exec.clean; +# exec.system_user = "root"; +# exec.jail_user = "root"; +# +# # +# # NB: Below 2-lines required +# # NB: The number of arguments after `jng bridge xxx' should match +# # the number of ngN_xxx arguments in vnet.interface value. +# # +# exec.prestart += "jng bridge xxx em0 em1 ..."; +# exec.poststop += "jng shutdown xxx"; +# +# # Standard recipe +# exec.start += "/bin/sh /etc/rc"; +# exec.stop = "/bin/sh /etc/rc.shutdown"; +# exec.consolelog = "/var/log/jail_xxx_console.log"; +# mount.devfs; +# +# # Optional (default off) +# #allow.mount; +# #allow.set_hostname = 1; +# #allow.sysvipc = 1; +# #devfs_ruleset = "11"; # rule to unhide bpf for DHCP +# } +# +# ### END EXCERPT ### +# +# In rc.conf(5) ``legacy'' format (used when /etc/jail.conf does not exist): +# +# ### BEGIN EXCERPT ### +# +# jail_enable="YES" +# jail_list="xxx" +# +# # +# # Global presets for all jails +# # +# jail_devfs_enable="YES" # mount devfs +# +# # +# # Global options (default off) +# # +# #jail_mount_enable="YES" # mount /etc/fstab.{name} +# #jail_set_hostname_allow="YES" # Allow hostname to change +# #jail_sysvipc_allow="YES" # Allow SysV Interprocess Comm. +# +# # xxx +# jail_xxx_hostname="xxx.shxd.cx" # hostname +# jail_xxx_rootdir="/vm/xxx" # root directory +# jail_xxx_vnet_interfaces="ng0_xxx ng1xxx ..." # vnet interface(s) +# jail_xxx_exec_prestart0="jng bridge xxx em0 em1 ..." # bridge interface(s) +# jail_xxx_exec_poststop0="jng shutdown xxx" # destroy interface(s) +# #jail_xxx_mount_enable="YES" # mount /etc/fstab.xxx +# #jail_xxx_devfs_ruleset="11" # rule to unhide bpf for DHCP +# +# ### END EXCERPT ### +# +# Note that the legacy rc.conf(5) format is converted to +# /var/run/jail.{name}.conf by /etc/rc.d/jail if jail.conf(5) is missing. +# +# ASIDE: dhclient(8) inside a vnet jail... +# +# To allow dhclient(8) to work inside a vnet jail, make sure the following +# appears in /etc/devfs.rules (which should be created if it doesn't exist): +# +# [devfsrules_jail=11] +# add include $devfsrules_hide_all +# add include $devfsrules_unhide_basic +# add include $devfsrules_unhide_login +# add include $devfsrules_unhide_bpf +# +# And set ether devfs.ruleset="11" (jail.conf(5)) or +# jail_{name}_devfs_ruleset="11" (rc.conf(5)). +# +# NB: While this tool can't create every type of desirable topology, it should +# handle most setups, minus some which considered exotic or purpose-built. +# +############################################################ GLOBALS + +pgm="${0##*/}" # Program basename + +# +# Global exit status +# +SUCCESS=0 +FAILURE=1 + +############################################################ FUNCTIONS + +usage() +{ + local action usage descr + exec >&2 + echo "Usage: $pgm action [arguments]" + echo "Actions:" + for action in \ + bridge \ + graph \ + show \ + show1 \ + shutdown \ + ; do + eval usage=\"\$jng_${action}_usage\" + [ "$usage" ] || continue + eval descr=\"\$jng_${action}_descr\" + printf "\t%s\n\t\t%s\n" "$usage" "$descr" + done + exit $FAILURE +} + +action_usage() +{ + local usage action="$1" + eval usage=\"\$jng_${action}_usage\" + echo "Usage: $pgm $usage" >&2 + exit $FAILURE +} + +mustberoot_to_continue() +{ + if [ "$( id -u )" -ne 0 ]; then + echo "Must run as root!" >&2 + exit $FAILURE + fi +} + +jng_bridge_usage="bridge [-b BRIDGE_NAME] NAME interface0 [interface1 ...]" +jng_bridge_descr="Create ng0_NAME [ng1_NAME ...]" +jng_bridge() +{ + local OPTIND=1 OPTARG flag bridge=bridge + while getopts b: flag; do + case "$flag" in + b) bridge="$OPTARG" + [ "$bridge" ] || action_usage bridge ;; # NOTREACHED + *) action_usage bridge # NOTREACHED + esac + done + shift $(( $OPTIND - 1 )) + + local name="$1" + [ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -gt 1 ] || + action_usage bridge # NOTREACHED + shift 1 # name + + mustberoot_to_continue + + local iface iface_devid eiface eiface_devid + local new num quad i=0 + for iface in $*; do + + # 0. Make sure the interface doesn't exist already + eiface=ng${i}_$name + ngctl msg "$eiface:" getifname > /dev/null 2>&1 && continue + + # 1. Bring the interface up + ifconfig $iface up || return + + # 2. Set promiscuous mode and don't overwrite src addr + ngctl msg $iface: setpromisc 1 || return + ngctl msg $iface: setautosrc 0 || return + + # 3. Make sure the interface has been bridged + if ! ngctl info ${iface}bridge: > /dev/null 2>&1; then + ngctl mkpeer $iface: bridge lower link0 || return + ngctl connect $iface: $iface:lower upper link1 || + return + ngctl name $iface:lower ${iface}bridge || return + fi + + # 3.5. Optionally create a secondary bridge + if [ "$bridge" != "bridge" ] && + ! ngctl info "$iface$bridge:" > /dev/null 2>&1 + then + num=2 + while ngctl msg ${iface}bridge: getstats $num \ + > /dev/null 2>&1 + do + num=$(( $num + 1 )) + done + ngctl mkpeer $iface:lower bridge link$num link1 || + return + ngctl name ${iface}bridge:link$num "$iface$bridge" || + return + fi + + # 4. Create a new interface to the bridge + num=2 + while ngctl msg "$iface$bridge:" getstats $num > /dev/null 2>&1 + do + num=$(( $num + 1 )) + done + ngctl mkpeer "$iface$bridge:" eiface link$num ether || return + + # 5. Rename the new interface + while [ ${#eiface} -gt 15 ]; do # OS limitation + eiface=${eiface%?} + done + new=$( set -- `ngctl show -n "$iface$bridge:link$num"` && + echo $2 ) || return + ngctl name "$iface$bridge:link$num" $eiface || return + ifconfig $new name $eiface || return + + # + # 6. Set the MAC address of the new interface using a sensible + # algorithm to prevent conflicts on the network. + # + # The formula I'm using is ``SP:SS:SI:II:II:II'' where: + # + S denotes 16 bits of sum(1) data, split because P (below). + # + P denotes the special nibble whose value, if one of + # 2, 6, A, or E (but usually 2) denotes a privately + # administered MAC address (while remaining routable). + # + I denotes bits that are inherited from parent interface. + # + # The S bits are a CRC-16 checksum of NAME, allowing the jail + # to change link numbers in ng_bridge(4) without affecting the + # MAC address. Meanwhile, if the jail NAME changes (e.g., it + # was duplicated and given a new name with no other changes), + # the underlying network interface changes, or the jail is + # moved to another host, the MAC address will be recalculated + # to a new, similarly unique value preventing conflict. + # + iface_devid=$( ifconfig $iface ether | awk '/ether/,$0=$2' ) + eiface_devid=${iface_devid#??:??:?} + num=$( set -- `echo -n $name | sum` && echo $1 ) + quad=$(( $num & 15 )) + case "$quad" in + 10) quad=a ;; 11) quad=b ;; 12) quad=c ;; + 13) quad=d ;; 14) quad=e ;; 15) quad=f ;; + esac + eiface_devid=:$quad$eiface_devid + num=$(( $num >> 4 )) + quad=$(( $num & 15 )) + case "$quad" in + 10) quad=a ;; 11) quad=b ;; 12) quad=c ;; + 13) quad=d ;; 14) quad=e ;; 15) quad=f ;; + esac + eiface_devid=$quad$eiface_devid + num=$(( $num >> 4 )) + quad=$(( $num & 15 )) + case "$quad" in + 10) quad=a ;; 11) quad=b ;; 12) quad=c ;; + 13) quad=d ;; 14) quad=e ;; 15) quad=f ;; + esac + eiface_devid=2:$quad$eiface_devid + num=$(( $num >> 4 )) + quad=$(( $num & 15 )) + case "$quad" in + 10) quad=a ;; 11) quad=b ;; 12) quad=c ;; + 13) quad=d ;; 14) quad=e ;; 15) quad=f ;; + esac + eiface_devid=$quad$eiface_devid + ifconfig $eiface ether $eiface_devid > /dev/null 2>&1 + + i=$(( $i + 1 )) # on to next ng{i}_name + done # for iface +} + +jng_graph_usage="graph [-f] [-T type] [-o output]" +jng_graph_descr="Generate network graph (default output is \`jng.svg')" +jng_graph() +{ + local OPTIND=1 OPTARG flag + local output=jng.svg output_type= force= + while getopts fo:T: flag; do + case "$flag" in + f) force=1 ;; + o) output="$OPTARG" ;; + T) output_type="$OPTARG" ;; + *) action_usage graph # NOTREACHED + esac + done + shift $(( $OPTIND - 1 )) + [ $# -eq 0 -a "$output" ] || action_usage graph # NOTREACHED + mustberoot_to_continue + if [ -e "$output" -a ! "$force" ]; then + echo "$output: Already exists (use \`-f' to overwrite)" >&2 + return $FAILURE + fi + if [ ! "$output_type" ]; then + local valid suffix + valid=$( dot -Txxx 2>&1 ) + for suffix in ${valid##*:}; do + [ "$output" != "${output%.$suffix}" ] || continue + output_type=$suffix + break + done + fi + ngctl dot | dot ${output_type:+-T "$output_type"} -o "$output" +} + +jng_show_usage="show" +jng_show_descr="List possible NAME values for \`show NAME'" +jng_show1_usage="show NAME" +jng_show1_descr="Lists ng0_NAME [ng1_NAME ...]" +jng_show2_usage="show [NAME]" +jng_show() +{ + local OPTIND=1 OPTARG flag + while getopts "" flag; do + case "$flag" in + *) action_usage show2 # NOTREACHED + esac + done + shift $(( $OPTIND - 1 )) + mustberoot_to_continue + if [ $# -eq 0 ]; then + ngctl ls | awk '$4=="bridge",$0=$2' | + xargs -rn1 -Ibridge ngctl show bridge: | + awk 'sub(/^ng[[:digit:]]+_/, "", $2), $0 = $2' | + sort -u + return + fi + ngctl ls | awk -v name="$1" ' + match($2, /^ng[[:digit:]]+_/) && + substr($2, RSTART + RLENGTH) == name && + $4 == "eiface", $0 = $2 + ' | sort +} + +jng_shutdown_usage="shutdown NAME" +jng_shutdown_descr="Shutdown ng0_NAME [ng1_NAME ...]" +jng_shutdown() +{ + local OPTIND=1 OPTARG flag + while getopts "" flag; do + case "$flag" in + *) action_usage shutdown # NOTREACHED + esac + done + shift $(( $OPTIND -1 )) + local name="$1" + [ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -eq 1 ] || + action_usage shutdown # NOTREACHED + mustberoot_to_continue + jng_show "$name" | xargs -rn1 -I eiface ngctl shutdown eiface: +} + +############################################################ MAIN + +# +# Command-line arguments +# +action="$1" +[ "$action" ] || usage # NOTREACHED + +# +# Validate action argument +# +if [ "$BASH_VERSION" ]; then + type="$( type -t "jng_$action" )" || usage # NOTREACHED +else + type="$( type "jng_$action" 2> /dev/null )" || usage # NOTREACHED +fi +case "$type" in +*function) + shift 1 # action + eval "jng_$action" \"\$@\" + ;; +*) usage # NOTREACHED +esac + +################################################################################ +# END +################################################################################ diff --git a/share/i18n/esdb/MISC/MISC.alias b/share/i18n/esdb/MISC/MISC.alias index 90e2ccd..6ffad5d 100644 --- a/share/i18n/esdb/MISC/MISC.alias +++ b/share/i18n/esdb/MISC/MISC.alias @@ -29,10 +29,10 @@ JISX0208:1990 x0208 JOHAB cp1361 -SHIFT_JIS csshiftjis -SHIFT_JIS ms_kanji -SHIFT_JIS sjis +Shift_JIS csshiftjis +Shift_JIS ms_kanji +Shift_JIS sjis -SHIFT_JIS-2004 shift_jisx0213 +Shift_JIS-2004 shift_jisx0213 TDS565 iso-ir-230 diff --git a/share/man/man4/bridge.4 b/share/man/man4/bridge.4 index cecffc5..d3410d5 100644 --- a/share/man/man4/bridge.4 +++ b/share/man/man4/bridge.4 @@ -425,8 +425,8 @@ cloned_interfaces="bridge0" ifconfig_bridge0="addm wlan0 addm fxp0 up" .Ed .Pp -For the bridge to forward packets all member interfaces and the bridge need -to be up. +For the bridge to forward packets, +all member interfaces and the bridge need to be up. The above example would also require: .Bd -literal -offset indent create_args_wlan0="wlanmode hostap" diff --git a/share/man/man4/inet.4 b/share/man/man4/inet.4 index a1d0a1c..07e7354 100644 --- a/share/man/man4/inet.4 +++ b/share/man/man4/inet.4 @@ -28,7 +28,7 @@ .\" From: @(#)inet.4 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd April 7, 2015 +.Dd Feb 4, 2016 .Dt INET 4 .Os .Sh NAME @@ -164,33 +164,11 @@ MIB. In addition to the variables supported by the transport protocols (for which the respective manual pages may be consulted), the following general variables are defined: -.Bl -tag -width IPCTL_FASTFORWARDING +.Bl -tag -width IPCTL_ACCEPTSOURCEROUTE .It Dv IPCTL_FORWARDING .Pq ip.forwarding Boolean: enable/disable forwarding of IP packets. Defaults to off. -.It Dv IPCTL_FASTFORWARDING -.Pq ip.fastforwarding -Boolean: enable/disable the use of -.Tn fast IP forwarding -code. -Defaults to off. -When -.Tn fast IP forwarding -is enabled, IP packets are forwarded directly to the appropriate network -interface with direct processing to completion, which greatly improves -the throughput. -All packets for local IP addresses, non-unicast, or with IP options are -handled by the normal IP input processing path. -All features of the normal (slow) IP forwarding path are supported -including firewall (through -.Xr pfil 9 -hooks) checking, except -.Xr ipsec 4 -tunnel brokering. -The -.Tn IP fastforwarding -path does not generate ICMP redirect or source quench messages. .It Dv IPCTL_SENDREDIRECTS .Pq ip.redirect Boolean: enable/disable sending of ICMP redirects in response to diff --git a/share/man/man7/build.7 b/share/man/man7/build.7 index be6fe09..b32d7ed 100644 --- a/share/man/man7/build.7 +++ b/share/man/man7/build.7 @@ -107,6 +107,16 @@ section below, and by the variables documented in The following list provides the names and actions for the targets supported by the build system: .Bl -tag -width ".Cm cleandepend" +.It Cm check +Run tests for a given subdirectory. +The default directory used is +.Pa ${.OBJDIR} , +but the check directory can be changed with +.Pa ${CHECKDIR} . +.It Cm checkworld +Run the +.Fx +test suite on installed world. .It Cm clean Remove any files created during the build process. .It Cm cleandepend @@ -653,6 +663,7 @@ make TARGET=sparc64 DESTDIR=/clients/sparc64 installworld .Xr mergemaster 8 , .Xr portsnap 8 , .Xr reboot 8 , -.Xr shutdown 8 +.Xr shutdown 8 , +.Xr tests 7 .Sh AUTHORS .An Mike W. Meyer Aq Mt mwm@mired.org diff --git a/share/mk/bsd.README b/share/mk/bsd.README index b1a68e8..1ae1510 100644 --- a/share/mk/bsd.README +++ b/share/mk/bsd.README @@ -448,6 +448,17 @@ It has seven targets: all: build the test programs. + check: + runs the test programs from CHECKDIR with kyua test. + + The beforecheck and aftercheck targets will be invoked, if + defined, to execute commands before and after the realcheck + target has been executed, respectively. + + The devel/kyua package must be installed before invoking this + target. + + See CHECKDIR for more details. clean: remove the test programs and any object files. cleandir: @@ -466,12 +477,6 @@ It has seven targets: run lint on the source files. tags: create a tags file for the source files. - test: - runs the test programs from the object directory; if the - Makefile does not itself define the target test, the - targets beforetest and aftertest may also be used to - cause actions immediately before and after the test - target is executed. It sets/uses the following variables, among many others: @@ -485,6 +490,10 @@ TESTSDIR Path to the installed tests. Must be a subdirectory of ${TESTSBASE}/${RELDIR:H} , e.g. /usr/tests/bin/ls when included from bin/ls/tests . +CHECKDIR The directory that 'make check' executes tests from. + + The value of CHECKDIR defaults to .OBJDIR. + KYUAFILE If 'auto' (the default), generate a Kyuafile out of the test programs defined in the Makefile. If 'yes', then a manually-crafted Kyuafile must be supplied with the diff --git a/share/mk/bsd.incs.mk b/share/mk/bsd.incs.mk index 06d04ed..05daf2f 100644 --- a/share/mk/bsd.incs.mk +++ b/share/mk/bsd.incs.mk @@ -87,8 +87,8 @@ _${group}INS: ${_${group}INCS} .if defined(INCSLINKS) && !empty(INCSLINKS) installincludes: .for s t in ${INCSLINKS} - @${ECHO} "$t -> $s" ; \ - ${INSTALL_SYMLINK} ${TAG_ARGS:D${TAG_ARGS},development} $s ${DESTDIR}$t + @${ECHO} "${DESTDIR}${t} -> ${s}" ; \ + ${INSTALL_SYMLINK} ${TAG_ARGS:D${TAG_ARGS},development} ${s} ${DESTDIR}${t} .endfor .endif .endif # !target(installincludes) diff --git a/share/mk/bsd.links.mk b/share/mk/bsd.links.mk index 87b808f..e69f3a0 100644 --- a/share/mk/bsd.links.mk +++ b/share/mk/bsd.links.mk @@ -15,10 +15,10 @@ afterinstall: _installlinks .ORDER: realinstall _installlinks _installlinks: .for s t in ${LINKS} - @${ECHO} "$t -> $s" ;\ - ${INSTALL_LINK} ${TAG_ARGS} ${DESTDIR}$s ${DESTDIR}$t + @${ECHO} "${t} -> ${s}" ;\ + ${INSTALL_LINK} ${TAG_ARGS} ${DESTDIR}${s} ${DESTDIR}${t} .endfor .for s t in ${SYMLINKS} - @${ECHO} "$t -> $s" ;\ - ${INSTALL_SYMLINK} ${TAG_ARGS} $s ${DESTDIR}/$t + @${ECHO} "${t} -> ${s}" ;\ + ${INSTALL_SYMLINK} ${TAG_ARGS} ${s} ${DESTDIR}/${t} .endfor diff --git a/share/mk/bsd.man.mk b/share/mk/bsd.man.mk index 0fee377..ee28844 100644 --- a/share/mk/bsd.man.mk +++ b/share/mk/bsd.man.mk @@ -172,6 +172,17 @@ ${__target}: ${__page} .endif # ${MK_MANCOMPRESS} == "no" +.if !defined(NO_MLINKS) && defined(MLINKS) && !empty(MLINKS) +.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/} +_MANLINKS+= ${MANDIR}${_osect}${MANSUBDIR}/${_oname} \ + ${MANDIR}${_dsect}${MANSUBDIR}/${_dname} +.if defined(MANBUILDCAT) && !empty(MANBUILDCAT) +_MANLINKS+= ${CATDIR}${_osect}${MANSUBDIR}/${_oname} \ + ${CATDIR}${_dsect}${MANSUBDIR}/${_dname} +.endif +.endfor +.endif + maninstall: _maninstall _maninstall: .if defined(MAN) && !empty(MAN) @@ -216,25 +227,10 @@ _maninstall: ${MAN} .endfor .endif # ${MK_MANCOMPRESS} == "no" .endif - -.if !defined(NO_MLINKS) && defined(MLINKS) && !empty(MLINKS) -.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/} - @l=${DESTDIR}${MANDIR}${_osect}${MANSUBDIR}/${_oname}; \ - t=${DESTDIR}${MANDIR}${_dsect}${MANSUBDIR}/${_dname}; \ - ${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \ - rm -f $${t} $${t}${MCOMPRESS_EXT}; \ - ${INSTALL_LINK} ${TAG_ARGS} $${l}${ZEXT} $${t}${ZEXT} +.for l t in ${_MANLINKS} + rm -f ${DESTDIR}${t} ${DESTDIR}${t}${MCOMPRESS_EXT}; \ + ${INSTALL_LINK} ${TAG_ARGS} ${DESTDIR}${l}${ZEXT} ${DESTDIR}${t}${ZEXT} .endfor -.if defined(MANBUILDCAT) && !empty(MANBUILDCAT) -.for _oname _osect _dname _dsect in ${MLINKS:C/\.([^.]*)$/.\1 \1/} - @l=${DESTDIR}${MANDIR}${_osect}${MANSUBDIR}/${_oname}; \ - t=${DESTDIR}${MANDIR}${_dsect}${MANSUBDIR}/${_dname}; \ - ${ECHO} $${t}${ZEXT} -\> $${l}${ZEXT}; \ - rm -f $${t} $${t}${MCOMPRESS_EXT}; \ - ${INSTALL_LINK} ${TAG_ARGS} $${l}${ZEXT} $${t}${ZEXT} -.endfor -.endif -.endif manlint: .if defined(MAN) && !empty(MAN) diff --git a/share/mk/bsd.nls.mk b/share/mk/bsd.nls.mk index c578361..d160a2b 100644 --- a/share/mk/bsd.nls.mk +++ b/share/mk/bsd.nls.mk @@ -73,6 +73,9 @@ SYMLINKS+= ${NLSSYMLINKS} .for file in ${NLS} NLSNAME_${file:T}= ${file:T:R}/${NLSNAME}.cat .if defined(NLSLINKS_${file:R}) && !empty(NLSLINKS_${file:R}) +.if !empty(NLSLINKS_${file:R}:M${file:R}) +.error NLSLINKS_${file:R} contains itself: ${file:R} +.endif NLSLINKS+= ${file:R} .endif .for dst in ${NLSLINKS_${file:R}} diff --git a/share/mk/bsd.subdir.mk b/share/mk/bsd.subdir.mk index dbe74f4..8631e65 100644 --- a/share/mk/bsd.subdir.mk +++ b/share/mk/bsd.subdir.mk @@ -43,11 +43,11 @@ SUBDIR_TARGETS+= \ checkdpadd clean cleandepend cleandir cleanilinks \ cleanobj depend distribute files includes installconfig \ installfiles installincludes realinstall lint maninstall \ - manlint obj objlink regress tags \ + manlint obj objlink tags \ # Described above. STANDALONE_SUBDIR_TARGETS+= \ - obj checkdpadd clean cleandepend cleandir \ + obj check checkdpadd clean cleandepend cleandir \ cleanilinks cleanobj installconfig \ .include <bsd.init.mk> diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk index 7ac7917..2ce5beb 100644 --- a/share/mk/bsd.sys.mk +++ b/share/mk/bsd.sys.mk @@ -178,11 +178,11 @@ CXXFLAGS+= ${CXXFLAGS.${COMPILER_TYPE}} # or expect to ever be up-to-date. PHONY_NOTMAIN = afterdepend afterinstall all beforedepend beforeinstall \ beforelinking build build-tools buildconfig buildfiles \ - buildincludes checkdpadd clean cleandepend cleandir cleanobj \ - configure depend dependall distclean distribute exe \ + buildincludes check checkdpadd clean cleandepend cleandir \ + cleanobj configure depend dependall distclean distribute exe \ files html includes install installconfig installfiles \ installincludes lint obj objlink objs objwarn realall \ - realdepend realinstall regress subdir-all subdir-depend \ + realdepend realinstall subdir-all subdir-depend \ subdir-install tags whereobj # we don't want ${PROG} to be PHONY diff --git a/share/mk/bsd.test.mk b/share/mk/bsd.test.mk index b0d4939..64a4f0d 100644 --- a/share/mk/bsd.test.mk +++ b/share/mk/bsd.test.mk @@ -61,11 +61,15 @@ _TESTS= .include <plain.test.mk> .include <tap.test.mk> +# kyua automatically descends directories; only run make check on the +# top-level directory +.if !make(check) .for ts in ${TESTS_SUBDIRS} .if empty(SUBDIR:M${ts}) SUBDIR+= ${ts} .endif .endfor +.endif # it is rare for test cases to have man pages .if !defined(MAN) @@ -80,19 +84,14 @@ PROGS_TARGETS+= install .include <suite.test.mk> .endif -.if !target(realtest) -realtest: .PHONY +.if !target(realcheck) +realcheck: .PHONY @echo "$@ not defined; skipping" .endif -test: .PHONY -.ORDER: beforetest realtest -test: beforetest realtest - -.if target(aftertest) -.ORDER: realtest aftertest -test: aftertest -.endif +beforecheck realcheck aftercheck check: .PHONY +.ORDER: beforecheck realcheck aftercheck +check: beforecheck realcheck aftercheck .ifdef PROG # we came here via bsd.progs.mk below diff --git a/share/mk/suite.test.mk b/share/mk/suite.test.mk index 2b87d7f..646d2eb 100644 --- a/share/mk/suite.test.mk +++ b/share/mk/suite.test.mk @@ -50,15 +50,12 @@ FILES+= Kyuafile FILESDIR_Kyuafile= ${TESTSDIR} .endif -.if ${KYUAFILE:tl} == "auto" -CLEANFILES+= Kyuafile Kyuafile.tmp -.endif - .for _T in ${_TESTS} _TEST_METADATA.${_T}= ${TEST_METADATA} ${TEST_METADATA.${_T}} .endfor .if ${KYUAFILE:tl} == "auto" +CLEANFILES+= Kyuafile Kyuafile.tmp Kyuafile: Makefile @{ \ echo '-- Automatically generated by bsd.test.mk.'; \ @@ -78,9 +75,11 @@ Kyuafile: Makefile @mv ${.TARGET}.tmp ${.TARGET} .endif +CHECKDIR?= ${DESTDIR}${TESTSDIR} + KYUA= ${LOCALBASE}/bin/kyua -.if exists(${KYUA}) -# Definition of the "make test" target and supporting variables. + +# Definition of the "make check" target and supporting variables. # # This target, by necessity, can only work for native builds (i.e. a FreeBSD # host building a release for the same system). The target runs Kyua, which is @@ -89,35 +88,15 @@ KYUA= ${LOCALBASE}/bin/kyua # Due to the dependencies of the binaries built by the source tree and how they # are used by tests, it is highly possible for a execution of "make test" to # report bogus results unless the new binaries are put in place. -realtest: .PHONY - @echo "*** WARNING: make test is experimental" - @echo "***" - @echo "*** Using this test does not preclude you from running the tests" - @echo "*** installed in ${TESTSBASE}. This test run may raise false" - @echo "*** positives and/or false negatives." - @echo - @${KYUA} test -k ${DESTDIR}${TESTSDIR}/Kyuafile; \ - result=0; \ - echo; \ - echo "*** Once again, note that "make test" is unsupported."; \ - test $${result} -eq 0 -.endif -beforetest: .PHONY -.if defined(TESTSDIR) -.if ${TESTSDIR} == ${TESTSBASE} -# Forbid running from ${TESTSBASE}. It can cause false positives/negatives and -# it does not cover all the tests (e.g. it misses testing software in external). - @echo "*** Sorry, you cannot use make test from src/tests. Install the" - @echo "*** tests into their final location and run them from ${TESTSBASE}" - @false -.else - @echo "*** Using this test does not preclude you from running the tests" - @echo "*** installed in ${TESTSBASE}. This test run may raise false" - @echo "*** positives and/or false negatives." -.endif -.else - @echo "*** No TESTSDIR defined; nothing to do." - @false -.endif - @echo +realcheck: .PHONY + @if [ ! -x ${KYUA} ]; then \ + echo; \ + echo "kyua binary not installed at expected location (${.TARGET})"; \ + echo; \ + echo "Please install via pkg install, or specify the path to the kyua"; \ + echo "package via the \$${LOCALBASE} variable, e.g. "; \ + echo "LOCALBASE=\"${LOCALBASE}\""; \ + false; \ + fi + @${KYUA} test -k ${CHECKDIR}/Kyuafile diff --git a/sys/amd64/amd64/uma_machdep.c b/sys/amd64/amd64/uma_machdep.c index db566ae..fc343ca 100644 --- a/sys/amd64/amd64/uma_machdep.c +++ b/sys/amd64/amd64/uma_machdep.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/systm.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/vm_page.h> #include <vm/vm_pageout.h> diff --git a/sys/arm/allwinner/a20/a20_mp.c b/sys/arm/allwinner/a20/a20_mp.c index 27cbb3d..ba9ce9a 100644 --- a/sys/arm/allwinner/a20/a20_mp.c +++ b/sys/arm/allwinner/a20/a20_mp.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/fdt.h> #include <machine/intr.h> @@ -101,8 +102,7 @@ platform_mp_start_ap(void) &cpucfg) != 0) panic("Couldn't map the CPUCFG\n"); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); bus_space_write_4(fdtbus_bs_tag, cpucfg, CPUCFG_P_REG0, pmap_kextract((vm_offset_t)mpentry)); diff --git a/sys/arm/altera/socfpga/socfpga_mp.c b/sys/arm/altera/socfpga/socfpga_mp.c index 46977f6..e057eb3 100644 --- a/sys/arm/altera/socfpga/socfpga_mp.c +++ b/sys/arm/altera/socfpga/socfpga_mp.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/fdt.h> #include <machine/intr.h> @@ -162,8 +163,7 @@ platform_mp_start_ap(void) bus_space_write_region_4(fdtbus_bs_tag, ram, 0, (uint32_t *)&socfpga_trampoline, 8); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); /* Put CPU1 out from reset */ bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, 0); diff --git a/sys/arm/amlogic/aml8726/aml8726_mp.c b/sys/arm/amlogic/aml8726/aml8726_mp.c index 779a793..c508135 100644 --- a/sys/arm/amlogic/aml8726/aml8726_mp.c +++ b/sys/arm/amlogic/aml8726/aml8726_mp.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/bus.h> #include <machine/smp.h> #include <machine/fdt.h> @@ -485,7 +486,7 @@ platform_mp_start_ap(void) value |= AML_SCU_CONTROL_ENABLE; SCU_WRITE_4(AML_SCU_CONTROL_REG, value); SCU_BARRIER(AML_SCU_CONTROL_REG); - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* Set the boot address and power on each AP. */ paddr = pmap_kextract((vm_offset_t)mpentry); diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 514a6b1..1398991 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -60,18 +60,7 @@ __FBSDID("$FreeBSD$"); #include <machine/cpuconf.h> #include <machine/cpufunc.h> -#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219) -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> -#endif - -/* - * Some definitions in i81342reg.h clash with i80321reg.h. - * This only happens for the LINT kernel. As it happens, - * we don't need anything from i81342reg.h that we already - * got from somewhere else during a LINT compile. - */ -#if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT) +#if defined(CPU_XSCALE_81342) #include <arm/xscale/i8134x/i81342reg.h> #endif @@ -99,8 +88,6 @@ u_int arm_cache_level; u_int arm_cache_type[14]; u_int arm_cache_loc; -int ctrl; - #ifdef CPU_ARM9 struct cpu_functions arm9_cpufuncs = { /* CPU functions */ @@ -121,7 +108,6 @@ struct cpu_functions arm9_cpufuncs = { /* Cache operations */ - arm9_icache_sync_all, /* icache_sync_all */ arm9_icache_sync_range, /* icache_sync_range */ arm9_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -173,7 +159,6 @@ struct cpu_functions armv5_ec_cpufuncs = { /* Cache operations */ - armv5_ec_icache_sync_all, /* icache_sync_all */ armv5_ec_icache_sync_range, /* icache_sync_range */ armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -224,7 +209,6 @@ struct cpu_functions sheeva_cpufuncs = { /* Cache operations */ - armv5_ec_icache_sync_all, /* icache_sync_all */ armv5_ec_icache_sync_range, /* icache_sync_range */ armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -275,7 +259,6 @@ struct cpu_functions pj4bv7_cpufuncs = { armv7_tlb_flushID_SE, /* tlb_flushD_SE */ /* Cache operations */ - armv7_idcache_wbinv_all, /* icache_sync_all */ armv7_icache_sync_range, /* icache_sync_range */ armv7_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -306,9 +289,7 @@ struct cpu_functions pj4bv7_cpufuncs = { }; #endif /* CPU_MV_PJ4B */ -#if defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) +#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) struct cpu_functions xscale_cpufuncs = { /* CPU functions */ @@ -329,7 +310,6 @@ struct cpu_functions xscale_cpufuncs = { /* Cache operations */ - xscale_cache_syncI, /* icache_sync_all */ xscale_cache_syncI_rng, /* icache_sync_range */ xscale_cache_purgeD, /* dcache_wbinv_all */ @@ -359,8 +339,7 @@ struct cpu_functions xscale_cpufuncs = { xscale_setup /* cpu setup */ }; #endif -/* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 - CPU_XSCALE_80219 */ +/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ #ifdef CPU_XSCALE_81342 struct cpu_functions xscalec3_cpufuncs = { @@ -382,7 +361,6 @@ struct cpu_functions xscalec3_cpufuncs = { /* Cache operations */ - xscalec3_cache_syncI, /* icache_sync_all */ xscalec3_cache_syncI_rng, /* icache_sync_range */ xscalec3_cache_purgeD, /* dcache_wbinv_all */ @@ -434,7 +412,6 @@ struct cpu_functions fa526_cpufuncs = { /* Cache operations */ - fa526_icache_sync_all, /* icache_sync_all */ fa526_icache_sync_range, /* icache_sync_range */ fa526_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -486,7 +463,6 @@ struct cpu_functions arm1176_cpufuncs = { /* Cache operations */ - arm11x6_icache_sync_all, /* icache_sync_all */ arm11x6_icache_sync_range, /* icache_sync_range */ arm11x6_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -542,7 +518,6 @@ struct cpu_functions cortexa_cpufuncs = { /* Cache operations */ - armv7_icache_sync_all, /* icache_sync_all */ armv7_icache_sync_range, /* icache_sync_range */ armv7_dcache_wbinv_all, /* dcache_wbinv_all */ @@ -588,10 +563,10 @@ u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ #if defined(CPU_ARM9) || \ defined (CPU_ARM9E) || \ - defined(CPU_ARM1176) || defined(CPU_XSCALE_80321) || \ + defined(CPU_ARM1176) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_FA526) || defined(CPU_MV_PJ4B) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \ + defined(CPU_XSCALE_81342) || \ defined(CPU_CORTEXA) || defined(CPU_KRAIT) /* Global cache line sizes, use 32 as default */ @@ -829,18 +804,6 @@ set_cpufuncs() } #endif /* CPU_FA526 */ -#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219) - if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 || - cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 || - cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) { - cpufuncs = xscale_cpufuncs; - cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ - get_cachetype_cp15(); - pmap_pte_init_xscale(); - goto out; - } -#endif /* CPU_XSCALE_80321 */ - #if defined(CPU_XSCALE_81342) if (cputype == CPU_ID_81342) { cpufuncs = xscalec3_cpufuncs; @@ -924,7 +887,6 @@ arm9_setup(void) /* Set the control register */ cpu_control(cpuctrlmask, cpuctrl); - ctrl = cpuctrl; } #endif /* CPU_ARM9 */ @@ -963,7 +925,6 @@ arm10_setup(void) cpuctrl |= CPU_CONTROL_VECRELOC; /* Set the control register */ - ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); /* And again. */ @@ -1005,47 +966,12 @@ cpu_scc_setup_ccnt(void) void arm11x6_setup(void) { - int cpuctrl, cpuctrl_wax; uint32_t auxctrl, auxctrl_wax; uint32_t tmp, tmp2; - uint32_t sbz=0; uint32_t cpuid; cpuid = cpu_ident(); - cpuctrl = - CPU_CONTROL_MMU_ENABLE | - CPU_CONTROL_DC_ENABLE | - CPU_CONTROL_WBUF_ENABLE | - CPU_CONTROL_32BP_ENABLE | - CPU_CONTROL_32BD_ENABLE | - CPU_CONTROL_LABT_ENABLE | - CPU_CONTROL_SYST_ENABLE | - CPU_CONTROL_IC_ENABLE | - CPU_CONTROL_UNAL_ENABLE; - - /* - * "write as existing" bits - * inverse of this is mask - */ - cpuctrl_wax = - (3 << 30) | /* SBZ */ - (1 << 29) | /* FA */ - (1 << 28) | /* TR */ - (3 << 26) | /* SBZ */ - (3 << 19) | /* SBZ */ - (1 << 17); /* SBZ */ - - cpuctrl |= CPU_CONTROL_BPRD_ENABLE; - cpuctrl |= CPU_CONTROL_V6_EXTPAGE; - -#ifdef __ARMEB__ - cpuctrl |= CPU_CONTROL_BEND_ENABLE; -#endif - - if (vector_page == ARM_VECTORS_HIGH) - cpuctrl |= CPU_CONTROL_VECRELOC; - auxctrl = 0; auxctrl_wax = ~0; @@ -1057,19 +983,6 @@ arm11x6_setup(void) auxctrl_wax = ~ARM1176_AUXCTL_PHD; } - /* Clear out the cache */ - cpu_idcache_wbinv_all(); - - /* Now really make sure they are clean. */ - __asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz)); - - /* Allow detection code to find the VFP if it's fitted. */ - cp15_cpacr_set(0x0fffffff); - - /* Set the control register */ - ctrl = cpuctrl; - cpu_control(~cpuctrl_wax, cpuctrl); - tmp = cp15_actlr_get(); tmp2 = tmp; tmp &= auxctrl_wax; @@ -1077,9 +990,6 @@ arm11x6_setup(void) if (tmp != tmp2) cp15_actlr_set(tmp); - /* And again. */ - cpu_idcache_wbinv_all(); - cpu_scc_setup_ccnt(); } #endif /* CPU_ARM1176 */ @@ -1088,33 +998,8 @@ arm11x6_setup(void) void pj4bv7_setup(void) { - int cpuctrl; pj4b_config(); - - cpuctrl = CPU_CONTROL_MMU_ENABLE; -#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS - cpuctrl |= CPU_CONTROL_AFLT_ENABLE; -#endif - cpuctrl |= CPU_CONTROL_DC_ENABLE; - cpuctrl |= (0xf << 3); - cpuctrl |= CPU_CONTROL_BPRD_ENABLE; - cpuctrl |= CPU_CONTROL_IC_ENABLE; - if (vector_page == ARM_VECTORS_HIGH) - cpuctrl |= CPU_CONTROL_VECRELOC; - cpuctrl |= (0x5 << 16) | (1 < 22); - cpuctrl |= CPU_CONTROL_V6_EXTPAGE; - - /* Clear out the cache */ - cpu_idcache_wbinv_all(); - - /* Set the control register */ - ctrl = cpuctrl; - cpu_control(0xFFFFFFFF, cpuctrl); - - /* And again. */ - cpu_idcache_wbinv_all(); - cpu_scc_setup_ccnt(); } #endif /* CPU_MV_PJ4B */ @@ -1124,45 +1009,6 @@ pj4bv7_setup(void) void cortexa_setup(void) { - int cpuctrl, cpuctrlmask; - - cpuctrlmask = CPU_CONTROL_MMU_ENABLE | /* MMU enable [0] */ - CPU_CONTROL_AFLT_ENABLE | /* Alignment fault [1] */ - CPU_CONTROL_DC_ENABLE | /* DCache enable [2] */ - CPU_CONTROL_BPRD_ENABLE | /* Branch prediction [11] */ - CPU_CONTROL_IC_ENABLE | /* ICache enable [12] */ - CPU_CONTROL_VECRELOC; /* Vector relocation [13] */ - - cpuctrl = CPU_CONTROL_MMU_ENABLE | - CPU_CONTROL_IC_ENABLE | - CPU_CONTROL_DC_ENABLE | - CPU_CONTROL_BPRD_ENABLE; - -#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS - cpuctrl |= CPU_CONTROL_AFLT_ENABLE; -#endif - - /* Switch to big endian */ -#ifdef __ARMEB__ - cpuctrl |= CPU_CONTROL_BEND_ENABLE; -#endif - - /* Check if the vector page is at the high address (0xffff0000) */ - if (vector_page == ARM_VECTORS_HIGH) - cpuctrl |= CPU_CONTROL_VECRELOC; - - /* Clear out the cache */ - cpu_idcache_wbinv_all(); - - /* Set the control register */ - ctrl = cpuctrl; - cpu_control(cpuctrlmask, cpuctrl); - - /* And again. */ - cpu_idcache_wbinv_all(); -#if defined(SMP) && !defined(ARM_NEW_PMAP) - armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting */ -#endif cpu_scc_setup_ccnt(); } @@ -1202,14 +1048,12 @@ fa526_setup(void) cpu_idcache_wbinv_all(); /* Set the control register */ - ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); } #endif /* CPU_FA526 */ -#if defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) +#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ + defined(CPU_XSCALE_81342) void xscale_setup(void) { @@ -1257,7 +1101,6 @@ xscale_setup(void) * Set the control register. Note that bits 6:3 must always * be set to 1. */ - ctrl = cpuctrl; /* cpu_control(cpuctrlmask, cpuctrl);*/ cpu_control(0xffffffff, cpuctrl); @@ -1276,5 +1119,4 @@ xscale_setup(void) __asm __volatile("mcr p15, 0, %0, c1, c0, 1" : : "r" (auxctl)); } -#endif /* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 - CPU_XSCALE_80219 */ +#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ diff --git a/sys/arm/arm/cpufunc_asm_arm11x6.S b/sys/arm/arm/cpufunc_asm_arm11x6.S index be6d530..793c690 100644 --- a/sys/arm/arm/cpufunc_asm_arm11x6.S +++ b/sys/arm/arm/cpufunc_asm_arm11x6.S @@ -132,12 +132,6 @@ ENTRY_NP(arm11x6_dcache_wbinv_all) RET END(arm11x6_dcache_wbinv_all) -ENTRY_NP(arm11x6_icache_sync_all) - Flush_D_cache(r0) - Invalidate_I_cache(r0, r1) - RET -END(arm11x6_icache_sync_all) - ENTRY_NP(arm11x6_icache_sync_range) add r1, r1, r0 sub r1, r1, #1 diff --git a/sys/arm/arm/cpufunc_asm_arm9.S b/sys/arm/arm/cpufunc_asm_arm9.S index 9247b0c..aaadcfe 100644 --- a/sys/arm/arm/cpufunc_asm_arm9.S +++ b/sys/arm/arm/cpufunc_asm_arm9.S @@ -85,9 +85,7 @@ ENTRY_NP(arm9_icache_sync_range) subs r1, r1, ip bhi .Larm9_sync_next mov pc, lr -END(arm9_icache_sync_range) -ENTRY_NP(arm9_icache_sync_all) .Larm9_icache_sync_all: /* * We assume that the code here can never be out of sync with the @@ -109,7 +107,7 @@ ENTRY_NP(arm9_icache_sync_all) subs s_max, s_max, s_inc bhs .Lnext_set /* Next set */ mov pc, lr -END(arm9_icache_sync_all) +END(arm9_icache_sync_range) .Larm9_line_size: .word _C_LABEL(arm_pdcache_line_size) diff --git a/sys/arm/arm/cpufunc_asm_armv5_ec.S b/sys/arm/arm/cpufunc_asm_armv5_ec.S index 31174c6..29e22b0 100644 --- a/sys/arm/arm/cpufunc_asm_armv5_ec.S +++ b/sys/arm/arm/cpufunc_asm_armv5_ec.S @@ -91,9 +91,7 @@ ENTRY_NP(armv5_ec_icache_sync_range) bpl 1b mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ RET -END(armv5_ec_icache_sync_range) -ENTRY_NP(armv5_ec_icache_sync_all) .Larmv5_ec_icache_sync_all: /* * We assume that the code here can never be out of sync with the @@ -109,7 +107,7 @@ ENTRY_NP(armv5_ec_icache_sync_all) bne 1b /* More to do? */ mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ RET -END(armv5_ec_icache_sync_all) +END(armv5_ec_icache_sync_range) .Larmv5_ec_line_size: .word _C_LABEL(arm_pdcache_line_size) diff --git a/sys/arm/arm/cpufunc_asm_armv7.S b/sys/arm/arm/cpufunc_asm_armv7.S index 42ccc6d..affd5281 100644 --- a/sys/arm/arm/cpufunc_asm_armv7.S +++ b/sys/arm/arm/cpufunc_asm_armv7.S @@ -252,16 +252,6 @@ ENTRY(armv7_idcache_wbinv_range) RET END(armv7_idcache_wbinv_range) -ENTRY_NP(armv7_icache_sync_all) -#ifdef SMP - mcr CP15_ICIALLUIS -#else - mcr CP15_ICIALLU -#endif - dsb /* data synchronization barrier */ - isb /* instruction synchronization barrier */ - RET -END(armv7_icache_sync_all) ENTRY_NP(armv7_icache_sync_range) ldr ip, .Larmv7_icache_line_size diff --git a/sys/arm/arm/cpufunc_asm_fa526.S b/sys/arm/arm/cpufunc_asm_fa526.S index 38cb11a..20530ac 100644 --- a/sys/arm/arm/cpufunc_asm_fa526.S +++ b/sys/arm/arm/cpufunc_asm_fa526.S @@ -83,12 +83,6 @@ ENTRY(fa526_idcache_wbinv_all) mov pc, lr END(fa526_idcache_wbinv_all) -ENTRY(fa526_icache_sync_all) - mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */ - mov pc, lr -END(fa526_icache_sync_all) - ENTRY(fa526_dcache_wbinv_all) mov r0, #0 mcr p15, 0, r0, c7, c14, 0 /* clean and invalidate D$ */ @@ -170,7 +164,7 @@ END(fa526_idcache_wbinv_range) ENTRY(fa526_icache_sync_range) cmp r1, #0x4000 - bhs _C_LABEL(fa526_icache_sync_all) + bhs .Lfa526_icache_sync_all and r2, r0, #(CACHELINE_SIZE - 1) add r1, r1, r2 @@ -184,6 +178,11 @@ ENTRY(fa526_icache_sync_range) 2: mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ mov pc, lr + +.Lfa526_icache_sync_all: + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ */ + mov pc, lr END(fa526_icache_sync_range) ENTRY(fa526_context_switch) diff --git a/sys/arm/arm/cpufunc_asm_xscale.S b/sys/arm/arm/cpufunc_asm_xscale.S index 3031b8c..8b9848c 100644 --- a/sys/arm/arm/cpufunc_asm_xscale.S +++ b/sys/arm/arm/cpufunc_asm_xscale.S @@ -80,9 +80,6 @@ __FBSDID("$FreeBSD$"); */ #define DCACHE_SIZE 0x00008000 -.Lblock_userspace_access: - .word _C_LABEL(block_userspace_access) - /* * CPWAIT -- Canonical method to wait for CP15 update. * From: Intel 80200 manual, section 2.3.3. @@ -137,11 +134,6 @@ ENTRY(xscale_setttb) mrs r3, cpsr orr r1, r3, #(PSR_I | PSR_F) msr cpsr_fsxc, r1 -#else - ldr r3, .Lblock_userspace_access - ldr r2, [r3] - orr r1, r2, #1 - str r1, [r3] #endif stmfd sp!, {r0-r3, lr} bl _C_LABEL(xscale_cache_cleanID) @@ -165,8 +157,6 @@ ENTRY(xscale_setttb) #ifdef CACHE_CLEAN_BLOCK_INTR msr cpsr_fsxc, r3 -#else - str r2, [r3] #endif RET END(xscale_setttb) @@ -273,14 +263,9 @@ _C_LABEL(xscale_minidata_clean_size): #define XSCALE_CACHE_CLEAN_UNBLOCK \ msr cpsr_fsxc, r3 #else -#define XSCALE_CACHE_CLEAN_BLOCK \ - ldr r3, .Lblock_userspace_access ; \ - ldr ip, [r3] ; \ - orr r0, ip, #1 ; \ - str r0, [r3] +#define XSCALE_CACHE_CLEAN_BLOCK -#define XSCALE_CACHE_CLEAN_UNBLOCK \ - str ip, [r3] +#define XSCALE_CACHE_CLEAN_UNBLOCK #endif /* CACHE_CLEAN_BLOCK_INTR */ #define XSCALE_CACHE_CLEAN_PROLOGUE \ diff --git a/sys/arm/arm/cpufunc_asm_xscale_c3.S b/sys/arm/arm/cpufunc_asm_xscale_c3.S index cb770a8..4e2c999 100644 --- a/sys/arm/arm/cpufunc_asm_xscale_c3.S +++ b/sys/arm/arm/cpufunc_asm_xscale_c3.S @@ -82,9 +82,6 @@ __FBSDID("$FreeBSD$"); */ #define DCACHE_SIZE 0x00008000 -.Lblock_userspace_access: - .word _C_LABEL(block_userspace_access) - /* * CPWAIT -- Canonical method to wait for CP15 update. * From: Intel 80200 manual, section 2.3.3. @@ -130,16 +127,8 @@ __FBSDID("$FreeBSD$"); msr cpsr_fsxc, r4 ; \ ldmfd sp!, {r4} #else -#define XSCALE_CACHE_CLEAN_BLOCK \ - stmfd sp!, {r4} ; \ - ldr r4, .Lblock_userspace_access ; \ - ldr ip, [r4] ; \ - orr r0, ip, #1 ; \ - str r0, [r4] - -#define XSCALE_CACHE_CLEAN_UNBLOCK \ - str ip, [r3] ; \ - ldmfd sp!, {r4} +#define XSCALE_CACHE_CLEAN_BLOCK +#define XSCALE_CACHE_CLEAN_UNBLOCK #endif /* CACHE_CLEAN_BLOCK_INTR */ @@ -352,11 +341,6 @@ ENTRY(xscalec3_setttb) mrs r3, cpsr orr r1, r3, #(PSR_I | PSR_F) msr cpsr_fsxc, r1 -#else - ldr r3, .Lblock_userspace_access - ldr r2, [r3] - orr r1, r2, #1 - str r1, [r3] #endif stmfd sp!, {r0-r3, lr} bl _C_LABEL(xscalec3_cache_cleanID) diff --git a/sys/arm/arm/cpuinfo.c b/sys/arm/arm/cpuinfo.c index 5e96cae..b2d96a7 100644 --- a/sys/arm/arm/cpuinfo.c +++ b/sys/arm/arm/cpuinfo.c @@ -31,8 +31,8 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <machine/cpu.h> #include <machine/cpuinfo.h> -#include <machine/cpu-v6.h> struct cpuinfo cpuinfo = { @@ -83,14 +83,16 @@ cpuinfo_init(void) /* CP15 c0,c0 regs 0-7 exist on all CPUs (although aliased with MIDR) */ cpuinfo.ctr = cp15_ctr_get(); cpuinfo.tcmtr = cp15_tcmtr_get(); +#if __ARM_ARCH >= 6 cpuinfo.tlbtr = cp15_tlbtr_get(); cpuinfo.mpidr = cp15_mpidr_get(); cpuinfo.revidr = cp15_revidr_get(); +#endif /* if CPU is not v7 cpu id scheme */ if (cpuinfo.architecture != 0xF) return; - +#if __ARM_ARCH >= 6 cpuinfo.id_pfr0 = cp15_id_pfr0_get(); cpuinfo.id_pfr1 = cp15_id_pfr1_get(); cpuinfo.id_dfr0 = cp15_id_dfr0_get(); @@ -144,6 +146,7 @@ cpuinfo_init(void) } cpuinfo.dcache_line_mask = cpuinfo.dcache_line_size - 1; cpuinfo.icache_line_mask = cpuinfo.icache_line_size - 1; +#endif } /* diff --git a/sys/arm/arm/db_interface.c b/sys/arm/arm/db_interface.c index 613dc08..bc49dc6 100644 --- a/sys/arm/arm/db_interface.c +++ b/sys/arm/arm/db_interface.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include <sys/param.h> +#include <sys/cons.h> #include <sys/proc.h> #include <sys/reboot.h> #include <sys/systm.h> /* just for boothowto */ @@ -53,9 +54,9 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_extern.h> #include <machine/db_machdep.h> +#include <machine/cpu.h> #include <machine/machdep.h> #include <machine/vmparam.h> -#include <machine/cpu.h> #include <ddb/ddb.h> #include <ddb/db_access.h> @@ -63,7 +64,7 @@ __FBSDID("$FreeBSD$"); #include <ddb/db_output.h> #include <ddb/db_variables.h> #include <ddb/db_sym.h> -#include <sys/cons.h> + static int nil = 0; @@ -245,11 +246,10 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data) } /* make sure the caches and memory are in sync */ - cpu_icache_sync_range(addr, size); + icache_sync(addr, size); /* In case the current page tables have been modified ... */ - cpu_tlb_flushID(); - cpu_cpwait(); + tlb_flush_all(); return (0); } diff --git a/sys/arm/arm/debug_monitor.c b/sys/arm/arm/debug_monitor.c index e216e34..eaf88e9 100644 --- a/sys/arm/arm/debug_monitor.c +++ b/sys/arm/arm/debug_monitor.c @@ -845,8 +845,10 @@ dbg_arch_supported(void) { switch (dbg_model) { +#ifdef not_yet case ID_DFR0_CP_DEBUG_M_V6: case ID_DFR0_CP_DEBUG_M_V6_1: +#endif case ID_DFR0_CP_DEBUG_M_V7: case ID_DFR0_CP_DEBUG_M_V7_1: /* fall through */ return (TRUE); diff --git a/sys/arm/arm/devmap.c b/sys/arm/arm/devmap.c index 380e129..011b579 100644 --- a/sys/arm/arm/devmap.c +++ b/sys/arm/arm/devmap.c @@ -40,7 +40,9 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/pmap.h> +#ifdef __arm__ #include <machine/acle-compat.h> +#endif #include <machine/armreg.h> #include <machine/devmap.h> #include <machine/vmparam.h> @@ -53,9 +55,6 @@ static boolean_t devmap_bootstrap_done = false; #define PTE_DEVICE VM_MEMATTR_DEVICE #elif defined(__arm__) #define MAX_VADDR ARM_VECTORS_HIGH -#if __ARM_ARCH >= 6 -#define PTE_DEVICE VM_MEMATTR_DEVICE -#endif #endif /* diff --git a/sys/arm/arm/dump_machdep.c b/sys/arm/arm/dump_machdep.c index e87d3e7..2c11141 100644 --- a/sys/arm/arm/dump_machdep.c +++ b/sys/arm/arm/dump_machdep.c @@ -59,8 +59,7 @@ dumpsys_wbinv_all(void) * have already been stopped, and their flush/invalidate was done as * part of stopping. */ - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); #ifdef __XSCALE__ xscale_cache_clean_minidata(); #endif diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c index 7dbdc91..2ec659a 100644 --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -282,7 +282,7 @@ elf_cpu_load_file(linker_file_t lf) #else cpu_dcache_wb_range((vm_offset_t)lf->address, (vm_size_t)lf->size); cpu_l2cache_wb_range((vm_offset_t)lf->address, (vm_size_t)lf->size); - cpu_icache_sync_all(); + cpu_icache_sync_range((vm_offset_t)lf->address, (vm_size_t)lf->size); #endif return (0); } diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c index 6c086ea..22f0f44 100644 --- a/sys/arm/arm/elf_trampoline.c +++ b/sys/arm/arm/elf_trampoline.c @@ -67,9 +67,7 @@ extern void fa526_idcache_wbinv_all(void); extern void armv5_ec_idcache_wbinv_all(void); #elif defined(CPU_ARM1176) #define cpu_idcache_wbinv_all armv6_idcache_wbinv_all -#elif defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) +#elif defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) #define cpu_idcache_wbinv_all xscale_cache_purgeID extern void xscale_cache_purgeID(void); #elif defined(CPU_XSCALE_81342) @@ -127,7 +125,6 @@ static int arm_dcache_l2_assoc; static int arm_dcache_l2_linesize; -int block_userspace_access = 0; extern int arm9_dcache_sets_inc; extern int arm9_dcache_sets_max; extern int arm9_dcache_index_max; diff --git a/sys/arm/arm/fiq.c b/sys/arm/arm/fiq.c index 94231de..f475a30 100644 --- a/sys/arm/arm/fiq.c +++ b/sys/arm/arm/fiq.c @@ -81,8 +81,8 @@ fiq_installhandler(void *func, size_t size) #if !defined(__ARM_FIQ_INDIRECT) vector_page_setprot(VM_PROT_READ); - cpu_icache_sync_range((vm_offset_t) fiqvector, size); #endif + icache_sync((vm_offset_t) fiqvector, size); } /* diff --git a/sys/arm/arm/fusu.S b/sys/arm/arm/fusu.S index 54d263c..ba50e67 100644 --- a/sys/arm/arm/fusu.S +++ b/sys/arm/arm/fusu.S @@ -183,51 +183,10 @@ END(fusword) */ ENTRY(fuswintr) - ldr r3, =(VM_MAXUSER_ADDRESS-1) - cmp r0, r3 - mvncs r0, #0 - RETc(cs) - - ldr r2, Lblock_userspace_access - ldr r2, [r2] - teq r2, #0 - mvnne r0, #0x00000000 - RETne - - GET_PCB(r2) - ldr r2, [r2] - -#ifdef DIAGNOSTIC - teq r2, #0x00000000 - beq .Lfusupcbfault -#endif - - adr r1, _C_LABEL(fusubailout) - str r1, [r2, #PCB_ONFAULT] - - ldrbt r3, [r0], #1 - ldrbt ip, [r0] -#ifdef __ARMEB__ - orr r0, ip, r3, asl #8 -#else - orr r0, r3, ip, asl #8 -#endif - - mov r1, #0x00000000 - str r1, [r2, #PCB_ONFAULT] + mov r0, #-1 RET END(fuswintr) -Lblock_userspace_access: - .word _C_LABEL(block_userspace_access) - - .data - .align 2 - .global _C_LABEL(block_userspace_access) -_C_LABEL(block_userspace_access): - .word 0 - .text - /* * fubyte(caddr_t uaddr); * Fetch a byte from the user's address space. @@ -268,20 +227,6 @@ END(fubyte) mvn r0, #0x00000000 RET -/* - * Handle faults from [fs]u*(). Clean up and return -1. This differs from - * fusufault() in that trap() will recognise it and return immediately rather - * than trying to page fault. - */ - -/* label must be global as fault.c references it */ - .global _C_LABEL(fusubailout) -_C_LABEL(fusubailout): - mov r0, #0x00000000 - str r0, [r2, #PCB_ONFAULT] - mvn r0, #0x00000000 - RET - #ifdef DIAGNOSTIC /* * Handle earlier faults from [fs]u*(), due to no pcb @@ -335,39 +280,7 @@ END(suword) */ ENTRY(suswintr) - ldr r3, =(VM_MAXUSER_ADDRESS-1) - cmp r0, r3 - mvncs r0, #0 - RETc(cs) - - ldr r2, Lblock_userspace_access - ldr r2, [r2] - teq r2, #0 - mvnne r0, #0x00000000 - RETne - - GET_PCB(r2) - ldr r2, [r2] - -#ifdef DIAGNOSTIC - teq r2, #0x00000000 - beq .Lfusupcbfault -#endif - - adr r3, _C_LABEL(fusubailout) - str r3, [r2, #PCB_ONFAULT] - -#ifdef __ARMEB__ - mov ip, r1, lsr #8 - strbt ip, [r0], #1 -#else - strbt r1, [r0], #1 - mov r1, r1, lsr #8 -#endif - strbt r1, [r0] - - mov r0, #0x00000000 - str r0, [r2, #PCB_ONFAULT] + mov r0, #-1 RET END(suswintr) diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c index eb4e51b..4149771 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$"); #include <machine/frame.h> #include <machine/pcb.h> #include <machine/cpu.h> -#include <machine/cpu-v6.h> #include <machine/proc.h> #include <machine/cpufunc.h> #include <machine/cpuinfo.h> @@ -59,7 +58,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_var.h> ASSYM(KERNBASE, KERNBASE); -ASSYM(PCB_NOALIGNFLT, PCB_NOALIGNFLT); #if __ARM_ARCH >= 6 ASSYM(CPU_ASID_KERNEL,CPU_ASID_KERNEL); #endif @@ -67,7 +65,6 @@ ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); #if __ARM_ARCH < 6 ASSYM(PCB_DACR, offsetof(struct pcb, pcb_dacr)); #endif -ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(PCB_PAGEDIR, offsetof(struct pcb, pcb_pagedir)); #if __ARM_ARCH < 6 ASSYM(PCB_L1VEC, offsetof(struct pcb, pcb_l1vec)); @@ -93,24 +90,15 @@ ASSYM(M_DATA, offsetof(struct mbuf, m_data)); ASSYM(M_NEXT, offsetof(struct mbuf, m_next)); ASSYM(IP_SRC, offsetof(struct ip, ip_src)); ASSYM(IP_DST, offsetof(struct ip, ip_dst)); -ASSYM(CF_SETTTB, offsetof(struct cpu_functions, cf_setttb)); -ASSYM(CF_CONTROL, offsetof(struct cpu_functions, cf_control)); ASSYM(CF_CONTEXT_SWITCH, offsetof(struct cpu_functions, cf_context_switch)); ASSYM(CF_DCACHE_WB_RANGE, offsetof(struct cpu_functions, cf_dcache_wb_range)); -ASSYM(CF_L2CACHE_WB_RANGE, offsetof(struct cpu_functions, cf_l2cache_wb_range)); ASSYM(CF_IDCACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_idcache_wbinv_all)); ASSYM(CF_L2CACHE_WBINV_ALL, offsetof(struct cpu_functions, cf_l2cache_wbinv_all)); ASSYM(CF_TLB_FLUSHID_SE, offsetof(struct cpu_functions, cf_tlb_flushID_SE)); -ASSYM(CF_ICACHE_SYNC, offsetof(struct cpu_functions, cf_icache_sync_all)); - -ASSYM(V_TRAP, offsetof(struct vmmeter, v_trap)); -ASSYM(V_SOFT, offsetof(struct vmmeter, v_soft)); -ASSYM(V_INTR, offsetof(struct vmmeter, v_intr)); ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); ASSYM(TD_FLAGS, offsetof(struct thread, td_flags)); ASSYM(TD_PROC, offsetof(struct thread, td_proc)); -ASSYM(TD_FRAME, offsetof(struct thread, td_frame)); ASSYM(TD_MD, offsetof(struct thread, td_md)); ASSYM(TD_LOCK, offsetof(struct thread, td_lock)); ASSYM(MD_TP, offsetof(struct mdthread, md_tp)); @@ -147,10 +135,6 @@ ASSYM(PMAP_INCLUDE_PTE_SYNC, 1); #endif ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); -ASSYM(P_TRACED, P_TRACED); -ASSYM(P_SIGEVENT, P_SIGEVENT); -ASSYM(P_PROFIL, P_PROFIL); -ASSYM(TRAPFRAMESIZE, sizeof(struct trapframe)); ASSYM(MAXCOMLEN, MAXCOMLEN); ASSYM(MAXCPU, MAXCPU); diff --git a/sys/arm/arm/identcpu.c b/sys/arm/arm/identcpu.c index 6c5764c..2b7fec4 100644 --- a/sys/arm/arm/identcpu.c +++ b/sys/arm/arm/identcpu.c @@ -321,7 +321,6 @@ print_enadis(int enadis, char *s) printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en"); } -extern int ctrl; enum cpu_class cpu_class = CPU_CLASS_NONE; u_int cpu_pfr(int num) @@ -388,9 +387,10 @@ void identify_arm_cpu(void) { u_int cpuid, reg, size, sets, ways; - u_int8_t type, linesize; + u_int8_t type, linesize, ctrl; int i; + ctrl = cpu_get_control(); cpuid = cpu_ident(); if (cpuid == 0) { diff --git a/sys/arm/arm/locore-v6.S b/sys/arm/arm/locore-v6.S index eda6014..b93af2c 100644 --- a/sys/arm/arm/locore-v6.S +++ b/sys/arm/arm/locore-v6.S @@ -132,9 +132,9 @@ ASENTRY_NP(_start) bic r7, #CPU_CONTROL_DC_ENABLE bic r7, #CPU_CONTROL_MMU_ENABLE bic r7, #CPU_CONTROL_IC_ENABLE - bic r7, #CPU_CONTROL_UNAL_ENABLE bic r7, #CPU_CONTROL_BPRD_ENABLE bic r7, #CPU_CONTROL_SW_ENABLE + orr r7, #CPU_CONTROL_UNAL_ENABLE orr r7, #CPU_CONTROL_AFLT_ENABLE orr r7, #CPU_CONTROL_VECRELOC mcr CP15_SCTLR(r7) @@ -456,9 +456,9 @@ ASENTRY_NP(mpentry) bic r0, #CPU_CONTROL_MMU_ENABLE bic r0, #CPU_CONTROL_DC_ENABLE bic r0, #CPU_CONTROL_IC_ENABLE - bic r0, #CPU_CONTROL_UNAL_ENABLE bic r0, #CPU_CONTROL_BPRD_ENABLE bic r0, #CPU_CONTROL_SW_ENABLE + orr r0, #CPU_CONTROL_UNAL_ENABLE orr r0, #CPU_CONTROL_AFLT_ENABLE orr r0, #CPU_CONTROL_VECRELOC mcr CP15_SCTLR(r0) diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 8d7c39c..4e7cb70 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -123,7 +123,6 @@ __FBSDID("$FreeBSD$"); #include <ddb/ddb.h> #if __ARM_ARCH >= 6 -#include <machine/cpu-v6.h> DB_SHOW_COMMAND(cp15, db_show_cp15) { @@ -397,7 +396,7 @@ arm_vector_init(vm_offset_t va, int which) } /* Now sync the vectors. */ - cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); + icache_sync(va, (ARM_NVEC * 2) * sizeof(u_int)); vector_page = va; @@ -479,12 +478,7 @@ void cpu_flush_dcache(void *ptr, size_t len) { - cpu_dcache_wb_range((uintptr_t)ptr, len); -#ifdef ARM_L2_PIPT - cpu_l2cache_wb_range((uintptr_t)vtophys(ptr), len); -#else - cpu_l2cache_wb_range((uintptr_t)ptr, len); -#endif + dcache_wb_poc((vm_offset_t)ptr, (vm_paddr_t)vtophys(ptr), len); } /* Get current clock frequency for the given cpu id. */ @@ -1622,7 +1616,7 @@ initarm(struct arm_boot_params *abp) cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT); pmap_pa = kernel_l1pt.pv_pa; - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)); @@ -1675,7 +1669,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. @@ -1867,7 +1861,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/arm/minidump_machdep.c b/sys/arm/arm/minidump_machdep.c index a351fb7..2eb4bfd 100644 --- a/sys/arm/arm/minidump_machdep.c +++ b/sys/arm/arm/minidump_machdep.c @@ -45,11 +45,11 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> #include <machine/atomic.h> +#include <machine/cpu.h> #include <machine/elf.h> #include <machine/md_var.h> -#include <machine/vmparam.h> #include <machine/minidump.h> -#include <machine/cpufunc.h> +#include <machine/vmparam.h> CTASSERT(sizeof(struct kerneldumpheader) == 512); @@ -203,8 +203,7 @@ minidumpsys(struct dumperinfo *di) * by time we get to here, all that remains is to flush the L1 for the * current CPU, then the L2. */ - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); counter = 0; /* Walk page table pages, set bits in vm_page_dump */ diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c index 6cedd46..8643860 100644 --- a/sys/arm/arm/mp_machdep.c +++ b/sys/arm/arm/mp_machdep.c @@ -123,9 +123,7 @@ cpu_mp_start(void) dpcpu[i] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE, M_WAITOK | M_ZERO); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* Initialize boot code and start up processors */ platform_mp_start_ap(); @@ -283,7 +281,7 @@ ipi_stop(void *dummy __unused) * stop will do the l2 cache flush after all other cores * have done their l1 flushes and stopped. */ - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* Indicate we are stopped */ CPU_SET_ATOMIC(cpu, &stopped_cpus); @@ -381,7 +379,7 @@ ipi_handler(void *arg) * stop will do the l2 cache flush after all other cores * have done their l1 flushes and stopped. */ - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* Indicate we are stopped */ CPU_SET_ATOMIC(cpu, &stopped_cpus); diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index d4ab930..525280c 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -3,8 +3,8 @@ * Copyright (c) 1994 John S. Dyson * Copyright (c) 1994 David Greenman * Copyright (c) 2005-2010 Alan L. Cox <alc@cs.rice.edu> - * Copyright (c) 2014 Svatopluk Kraus <onwahe@gmail.com> - * Copyright (c) 2014 Michal Meloun <meloun@miracle.cz> + * Copyright (c) 2014-2016 Svatopluk Kraus <skra@FreeBSD.org> + * Copyright (c) 2014-2016 Michal Meloun <mmel@FreeBSD.org> * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -141,7 +141,6 @@ __FBSDID("$FreeBSD$"); #include <machine/md_var.h> #include <machine/pmap_var.h> #include <machine/cpu.h> -#include <machine/cpu-v6.h> #include <machine/pcb.h> #include <machine/sf_buf.h> #ifdef SMP @@ -223,11 +222,14 @@ int pmap_debug_level = 1; /* * PTE2 descriptors creation macros. */ -#define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, pt_memattr) -#define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, pt_memattr) +#define PTE2_ATTR_DEFAULT vm_memattr_to_pte2(VM_MEMATTR_DEFAULT) +#define PTE2_ATTR_PT vm_memattr_to_pte2(pt_memattr) -#define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_NORMAL) -#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_ATTR_NORMAL) +#define PTE2_KPT(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_PT) +#define PTE2_KPT_NG(pa) PTE2_KERN_NG(pa, PTE2_AP_KRW, PTE2_ATTR_PT) + +#define PTE2_KRW(pa) PTE2_KERN(pa, PTE2_AP_KRW, PTE2_ATTR_DEFAULT) +#define PTE2_KRO(pa) PTE2_KERN(pa, PTE2_AP_KR, PTE2_ATTR_DEFAULT) #define PV_STATS #ifdef PV_STATS @@ -262,10 +264,6 @@ static uint32_t ttb_flags; static vm_memattr_t pt_memattr; ttb_entry_t pmap_kern_ttb; -/* XXX use converion function*/ -#define PTE2_ATTR_NORMAL VM_MEMATTR_DEFAULT -#define PTE1_ATTR_NORMAL ATTR_TO_L1(PTE2_ATTR_NORMAL) - struct pmap kernel_pmap_store; LIST_HEAD(pmaplist, pmap); static struct pmaplist allpmaps; @@ -399,6 +397,37 @@ static uint32_t tex_class[8] = { }; #undef TEX +static uint32_t pte2_attr_tab[8] = { + PTE2_ATTR_WB_WA, /* 0 - VM_MEMATTR_WB_WA */ + PTE2_ATTR_NOCACHE, /* 1 - VM_MEMATTR_NOCACHE */ + PTE2_ATTR_DEVICE, /* 2 - VM_MEMATTR_DEVICE */ + PTE2_ATTR_SO, /* 3 - VM_MEMATTR_SO */ + PTE2_ATTR_WT, /* 4 - VM_MEMATTR_WRITE_THROUGH */ + 0, /* 5 - NOT USED YET */ + 0, /* 6 - NOT USED YET */ + 0 /* 7 - NOT USED YET */ +}; +CTASSERT(VM_MEMATTR_WB_WA == 0); +CTASSERT(VM_MEMATTR_NOCACHE == 1); +CTASSERT(VM_MEMATTR_DEVICE == 2); +CTASSERT(VM_MEMATTR_SO == 3); +CTASSERT(VM_MEMATTR_WRITE_THROUGH == 4); + +static inline uint32_t +vm_memattr_to_pte2(vm_memattr_t ma) +{ + + KASSERT((u_int)ma < 5, ("%s: bad vm_memattr_t %d", __func__, ma)); + return (pte2_attr_tab[(u_int)ma]); +} + +static inline uint32_t +vm_page_pte2_attr(vm_page_t m) +{ + + return (vm_memattr_to_pte2(m->md.pat_mode)); +} + /* * Convert TEX definition entry to TTB flags. */ @@ -713,7 +742,7 @@ pmap_bootstrap_prepare(vm_paddr_t last) pt1_entry_t *pte1p; pt2_entry_t *pte2p; u_int i; - uint32_t actlr_mask, actlr_set; + uint32_t actlr_mask, actlr_set, l1_attr; /* * Now, we are going to make real kernel mapping. Note that we are @@ -776,10 +805,10 @@ pmap_bootstrap_prepare(vm_paddr_t last) pte1_store(pte1p++, PTE1_LINK(pa)); /* Make section mappings for kernel. */ + l1_attr = ATTR_TO_L1(PTE2_ATTR_DEFAULT); pte1p = kern_pte1(KERNBASE); for (pa = KERNEL_V2P(KERNBASE); pa < last; pa += PTE1_SIZE) - pte1_store(pte1p++, PTE1_KERN(pa, PTE1_AP_KRW, - ATTR_TO_L1(PTE2_ATTR_WB_WA))); + pte1_store(pte1p++, PTE1_KERN(pa, PTE1_AP_KRW, l1_attr)); /* * Get free and aligned space for PT2MAP and make L1 page table links @@ -988,13 +1017,14 @@ pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, vm_prot_t prot, vm_memattr_t attr) { u_int num; - u_int l1_attr, l1_prot, l2_prot; + u_int l1_attr, l1_prot, l2_prot, l2_attr; pt1_entry_t *pte1p; pt2_entry_t *pte2p; l2_prot = prot & VM_PROT_WRITE ? PTE2_AP_KRW : PTE2_AP_KR; + l2_attr = vm_memattr_to_pte2(attr); l1_prot = ATTR_TO_L1(l2_prot); - l1_attr = ATTR_TO_L1(attr); + l1_attr = ATTR_TO_L1(l2_attr); /* Map all the pages. */ num = round_page(size); @@ -1007,7 +1037,7 @@ pmap_preboot_map_attr(vm_paddr_t pa, vm_offset_t va, vm_size_t size, num -= PTE1_SIZE; } else { pte2p = pmap_preboot_vtopte2(va); - pte2_store(pte2p, PTE2_KERN(pa, l2_prot, attr)); + pte2_store(pte2p, PTE2_KERN(pa, l2_prot, l2_attr)); va += PAGE_SIZE; pa += PAGE_SIZE; num -= PAGE_SIZE; @@ -1247,7 +1277,7 @@ PMAP_INLINE void pmap_kenter(vm_offset_t va, vm_paddr_t pa) { - pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_NORMAL); + pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_DEFAULT); } /* @@ -1320,7 +1350,8 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) vm_offset_t va, sva; vm_paddr_t pte1_offset; pt1_entry_t npte1; - u_int l1prot,l2prot; + uint32_t l1prot, l2prot; + uint32_t l1attr, l2attr; PDEBUG(1, printf("%s: virt = %#x, start = %#x, end = %#x (size = %#x)," " prot = %d\n", __func__, *virt, start, end, end - start, prot)); @@ -1329,6 +1360,9 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) l2prot |= (prot & VM_PROT_EXECUTE) ? PTE2_X : PTE2_NX; l1prot = ATTR_TO_L1(l2prot); + l2attr = PTE2_ATTR_DEFAULT; + l1attr = ATTR_TO_L1(l2attr); + va = *virt; /* * Does the physical address range's size and alignment permit at @@ -1351,13 +1385,12 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) if ((start & PTE1_OFFSET) == 0 && end - start >= PTE1_SIZE) { KASSERT((va & PTE1_OFFSET) == 0, ("%s: misaligned va %#x", __func__, va)); - npte1 = PTE1_KERN(start, l1prot, PTE1_ATTR_NORMAL); + npte1 = PTE1_KERN(start, l1prot, l1attr); pmap_kenter_pte1(va, npte1); va += PTE1_SIZE; start += PTE1_SIZE; } else { - pmap_kenter_prot_attr(va, start, l2prot, - PTE2_ATTR_NORMAL); + pmap_kenter_prot_attr(va, start, l2prot, l2attr); va += PAGE_SIZE; start += PAGE_SIZE; } @@ -1527,7 +1560,7 @@ pmap_page_init(vm_page_t m) TAILQ_INIT(&m->md.pv_list); pt2_wirecount_init(m); - m->md.pat_mode = PTE2_ATTR_NORMAL; + m->md.pat_mode = VM_MEMATTR_DEFAULT; } /* @@ -1562,7 +1595,7 @@ pmap_pt2pg_zero(vm_page_t m) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, - m->md.pat_mode)); + vm_page_pte2_attr(m))); /* Even VM_ALLOC_ZERO request is only advisory. */ if ((m->flags & PG_ZERO) == 0) pagezero(sysmaps->CADDR2); @@ -1586,7 +1619,7 @@ pmap_pt2pg_init(pmap_t pmap, vm_offset_t va, vm_page_t m) pt2_entry_t *pte2p; /* Check page attributes. */ - if (pmap_page_get_memattr(m) != pt_memattr) + if (m->md.pat_mode != pt_memattr) pmap_page_set_memattr(m, pt_memattr); /* Zero page and init wire counts. */ @@ -1717,10 +1750,10 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) pa = VM_PAGE_TO_PHYS(m); pte2 = pte2_load(pte2p); if ((pte2_pa(pte2) != pa) || - (pte2_attr(pte2) != m->md.pat_mode)) { + (pte2_attr(pte2) != vm_page_pte2_attr(m))) { anychanged++; pte2_store(pte2p, PTE2_KERN(pa, PTE2_AP_KRW, - m->md.pat_mode)); + vm_page_pte2_attr(m))); } pte2p++; } @@ -3770,7 +3803,7 @@ validate: /* * Now validate mapping with desired protection/wiring. */ - npte2 = PTE2(pa, PTE2_NM, m->md.pat_mode); + npte2 = PTE2(pa, PTE2_NM, vm_page_pte2_attr(m)); if (prot & VM_PROT_WRITE) { if (pte2_is_managed(npte2)) vm_page_aflag_set(m, PGA_WRITEABLE); @@ -3795,7 +3828,7 @@ validate: */ if ((opte2 & ~(PTE2_NM | PTE2_A)) != (npte2 & ~(PTE2_NM | PTE2_A))) { /* - * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA + * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA * is set. Do it now, before the mapping is stored and made * valid for hardware table walk. If done later, there is a race * for other threads of current process in lazy loading case. @@ -3810,7 +3843,7 @@ validate: * (2) Now, we do it on a page basis. */ if ((prot & VM_PROT_EXECUTE) && pmap != kernel_pmap && - m->md.pat_mode == PTE2_ATTR_WB_WA && + m->md.pat_mode == VM_MEMATTR_WB_WA && (opa != pa || (opte2 & PTE2_NX))) cache_icache_sync_fresh(va, pa, PAGE_SIZE); @@ -4410,14 +4443,14 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, l2prot |= PTE2_U | PTE2_NG; if ((prot & VM_PROT_EXECUTE) == 0) l2prot |= PTE2_NX; - else if (m->md.pat_mode == PTE2_ATTR_WB_WA && pmap != kernel_pmap) { + else if (m->md.pat_mode == VM_MEMATTR_WB_WA && pmap != kernel_pmap) { /* - * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA + * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA * is set. QQQ: For more info, see comments in pmap_enter(). */ cache_icache_sync_fresh(va, pa, PAGE_SIZE); } - pte2_store(pte2p, PTE2(pa, l2prot, m->md.pat_mode)); + pte2_store(pte2p, PTE2(pa, l2prot, vm_page_pte2_attr(m))); return (mpt2pg); } @@ -4481,14 +4514,14 @@ pmap_enter_pte1(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) l1prot |= PTE1_U | PTE1_NG; if ((prot & VM_PROT_EXECUTE) == 0) l1prot |= PTE1_NX; - else if (m->md.pat_mode == PTE2_ATTR_WB_WA && pmap != kernel_pmap) { + else if (m->md.pat_mode == VM_MEMATTR_WB_WA && pmap != kernel_pmap) { /* - * Sync icache if exec permission and attribute PTE2_ATTR_WB_WA + * Sync icache if exec permission and attribute VM_MEMATTR_WB_WA * is set. QQQ: For more info, see comments in pmap_enter(). */ cache_icache_sync_fresh(va, pa, PTE1_SIZE); } - pte1_store(pte1p, PTE1(pa, l1prot, ATTR_TO_L1(m->md.pat_mode))); + pte1_store(pte1p, PTE1(pa, l1prot, ATTR_TO_L1(vm_page_pte2_attr(m)))); pmap_pte1_mappings++; CTR3(KTR_PMAP, "%s: success for va %#lx in pmap %p", __func__, va, @@ -4552,7 +4585,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, pt1_entry_t *pte1p; vm_paddr_t pa, pte2_pa; vm_page_t p; - int pat_mode; + vm_memattr_t pat_mode; u_int l1attr, l1prot; VM_OBJECT_ASSERT_WLOCKED(object); @@ -4598,7 +4631,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, * is done here, so readonly mapping must be done elsewhere. */ l1prot = PTE1_U | PTE1_NG | PTE1_RW | PTE1_M | PTE1_A; - l1attr = ATTR_TO_L1(pat_mode); + l1attr = ATTR_TO_L1(vm_memattr_to_pte2(pat_mode)); PMAP_LOCK(pmap); for (pa = pte2_pa; pa < pte2_pa + size; pa += PTE1_SIZE) { pte1p = pmap_pte1(pmap, addr); @@ -5492,7 +5525,8 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) mtx_lock(&sysmaps->lock); if (*sysmaps->CMAP2) panic("%s: CMAP2 busy", __func__); - pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, ma)); + pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(pa, PTE2_AP_KRW, + vm_memattr_to_pte2(ma))); dcache_wbinv_poc((vm_offset_t)sysmaps->CADDR2, pa, PAGE_SIZE); pte2_clear(sysmaps->CMAP2); tlb_flush((vm_offset_t)sysmaps->CADDR2); @@ -5583,7 +5617,7 @@ pmap_zero_page(vm_page_t m) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - m->md.pat_mode)); + vm_page_pte2_attr(m))); pagezero(sysmaps->CADDR2); pte2_clear(sysmaps->CMAP2); tlb_flush((vm_offset_t)sysmaps->CADDR2); @@ -5608,7 +5642,7 @@ pmap_zero_page_area(vm_page_t m, int off, int size) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - m->md.pat_mode)); + vm_page_pte2_attr(m))); if (off == 0 && size == PAGE_SIZE) pagezero(sysmaps->CADDR2); else @@ -5633,7 +5667,7 @@ pmap_zero_page_idle(vm_page_t m) panic("%s: CMAP3 busy", __func__); sched_pin(); pte2_store(CMAP3, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - m->md.pat_mode)); + vm_page_pte2_attr(m))); pagezero(CADDR3); pte2_clear(CMAP3); tlb_flush((vm_offset_t)CADDR3); @@ -5659,9 +5693,9 @@ pmap_copy_page(vm_page_t src, vm_page_t dst) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(src), - PTE2_AP_KR | PTE2_NM, src->md.pat_mode)); + PTE2_AP_KR | PTE2_NM, vm_page_pte2_attr(src))); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(dst), - PTE2_AP_KRW, dst->md.pat_mode)); + PTE2_AP_KRW, vm_page_pte2_attr(dst))); bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE); pte2_clear(sysmaps->CMAP1); tlb_flush((vm_offset_t)sysmaps->CADDR1); @@ -5698,10 +5732,10 @@ pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[], b_pg_offset = b_offset & PAGE_MASK; cnt = min(cnt, PAGE_SIZE - b_pg_offset); pte2_store(sysmaps->CMAP1, PTE2_KERN_NG(VM_PAGE_TO_PHYS(a_pg), - PTE2_AP_KR | PTE2_NM, a_pg->md.pat_mode)); + PTE2_AP_KR | PTE2_NM, vm_page_pte2_attr(a_pg))); tlb_flush_local((vm_offset_t)sysmaps->CADDR1); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(b_pg), - PTE2_AP_KRW, b_pg->md.pat_mode)); + PTE2_AP_KRW, vm_page_pte2_attr(b_pg))); tlb_flush_local((vm_offset_t)sysmaps->CADDR2); a_cp = sysmaps->CADDR1 + a_pg_offset; b_cp = sysmaps->CADDR2 + b_pg_offset; @@ -5731,7 +5765,7 @@ pmap_quick_enter_page(vm_page_t m) KASSERT(pte2_load(pte2p) == 0, ("%s: PTE2 busy", __func__)); pte2_store(pte2p, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - pmap_page_get_memattr(m))); + vm_page_pte2_attr(m))); return (qmap_addr); } @@ -5993,13 +6027,15 @@ void pmap_kenter_device(vm_offset_t va, vm_size_t size, vm_paddr_t pa) { vm_offset_t sva; + uint32_t l2attr; KASSERT((size & PAGE_MASK) == 0, ("%s: device mapping not page-sized", __func__)); sva = va; + l2attr = vm_memattr_to_pte2(VM_MEMATTR_DEVICE); while (size != 0) { - pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, PTE2_ATTR_DEVICE); + pmap_kenter_prot_attr(va, pa, PTE2_AP_KRW, l2attr); va += PAGE_SIZE; pa += PAGE_SIZE; size -= PAGE_SIZE; @@ -6037,7 +6073,7 @@ pmap_set_pcb_pagedir(pmap_t pmap, struct pcb *pcb) * The range must be within a single page. */ static void -pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, vm_memattr_t ma) +pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, uint32_t attr) { struct sysmaps *sysmaps; @@ -6049,7 +6085,7 @@ pmap_dcache_wb_pou(vm_paddr_t pa, vm_size_t size, vm_memattr_t ma) mtx_lock(&sysmaps->lock); if (*sysmaps->CMAP3) panic("%s: CMAP3 busy", __func__); - pte2_store(sysmaps->CMAP3, PTE2_KERN_NG(pa, PTE2_AP_KRW, ma)); + pte2_store(sysmaps->CMAP3, PTE2_KERN_NG(pa, PTE2_AP_KRW, attr)); dcache_wb_pou((vm_offset_t)sysmaps->CADDR3 + (pa & PAGE_MASK), size); pte2_clear(sysmaps->CMAP3); tlb_flush((vm_offset_t)sysmaps->CADDR3); @@ -6073,7 +6109,7 @@ cache_icache_sync_fresh(vm_offset_t va, vm_paddr_t pa, vm_size_t size) m = PHYS_TO_VM_PAGE(pa); KASSERT(m != NULL, ("%s: vm_page_t is null for %#x", __func__, pa)); - pmap_dcache_wb_pou(pa, len, m->md.pat_mode); + pmap_dcache_wb_pou(pa, len, vm_page_pte2_attr(m)); } /* * I-cache is VIPT. Only way how to flush all virtual mappings @@ -6101,7 +6137,7 @@ pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t size) m = PHYS_TO_VM_PAGE(pa); KASSERT(m != NULL, ("%s: vm_page_t is null for %#x", __func__, pa)); - pmap_dcache_wb_pou(pa, len, m->md.pat_mode); + pmap_dcache_wb_pou(pa, len, vm_page_pte2_attr(m)); } } /* @@ -6298,7 +6334,7 @@ pmap_zero_page_check(vm_page_t m) if (pte2_load(sysmaps->CMAP2) != 0) panic("%s: CMAP2 busy", __func__); pte2_store(sysmaps->CMAP2, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m), PTE2_AP_KRW, - m->md.pat_mode)); + vm_page_pte2_attr(m))); end = (uint32_t*)(sysmaps->CADDR2 + PAGE_SIZE); for (p = (uint32_t*)sysmaps->CADDR2; p < end; p++) if (*p != 0) diff --git a/sys/arm/arm/sys_machdep.c b/sys/arm/arm/sys_machdep.c index efebda3..b893a90 100644 --- a/sys/arm/arm/sys_machdep.c +++ b/sys/arm/arm/sys_machdep.c @@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_extern.h> #include <machine/acle-compat.h> -#include <machine/cpu-v6.h> +#include <machine/cpu.h> #include <machine/sysarch.h> #include <machine/vmparam.h> @@ -153,8 +153,13 @@ arm32_drain_writebuf(struct thread *td, void *args) { /* No args. */ - td->td_retval[0] = 0; +#if __ARM_ARCH < 6 cpu_drain_writebuf(); +#else + dsb(); + cpu_l2cache_drain_writebuf(); +#endif + td->td_retval[0] = 0; return (0); } diff --git a/sys/arm/arm/trap-v6.c b/sys/arm/arm/trap-v6.c index adc29c6..81a6ee4 100644 --- a/sys/arm/arm/trap-v6.c +++ b/sys/arm/arm/trap-v6.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include <machine/acle-compat.h> #include <machine/cpu.h> -#include <machine/cpu-v6.h> #include <machine/frame.h> #include <machine/machdep.h> #include <machine/pcb.h> @@ -70,7 +69,6 @@ __FBSDID("$FreeBSD$"); #include <sys/dtrace_bsd.h> #endif -extern char fusubailout[]; extern char cachebailout[]; #ifdef DEBUG @@ -293,7 +291,10 @@ abort_handler(struct trapframe *tf, int prefetch) #ifdef INVARIANTS void *onfault; #endif + + PCPU_INC(cnt.v_trap); td = curthread; + fsr = (prefetch) ? cp15_ifsr_get(): cp15_dfsr_get(); #if __ARM_ARCH >= 7 far = (prefetch) ? cp15_ifar_get() : cp15_dfar_get(); @@ -334,24 +335,23 @@ abort_handler(struct trapframe *tf, int prefetch) * they are not from KVA space. Thus, no action is needed here. */ + /* + * (1) Handle access and R/W hardware emulation aborts. + * (2) Check that abort is not on pmap essential address ranges. + * There is no way how to fix it, so we don't even try. + */ rv = pmap_fault(PCPU_GET(curpmap), far, fsr, idx, usermode); if (rv == KERN_SUCCESS) return; - if (rv == KERN_INVALID_ADDRESS) - goto nogo; - /* - * Now, when we handled imprecise and debug aborts, the rest of - * aborts should be really related to mapping. - */ - - PCPU_INC(cnt.v_trap); - #ifdef KDB if (kdb_active) { kdb_reenter(); goto out; } #endif + if (rv == KERN_INVALID_ADDRESS) + goto nogo; + if (__predict_false((td->td_pflags & TDP_NOFAULTING) != 0)) { /* * Due to both processor errata and lazy TLB invalidation when @@ -418,6 +418,14 @@ abort_handler(struct trapframe *tf, int prefetch) } /* + * At this point, we're dealing with one of the following aborts: + * + * FAULT_ICACHE - I-cache maintenance + * FAULT_TRAN_xx - Translation + * FAULT_PERM_xx - Permission + */ + + /* * Don't pass faulting cache operation to vm_fault(). We don't want * to handle all vm stuff at this moment. */ @@ -435,23 +443,6 @@ abort_handler(struct trapframe *tf, int prefetch) goto out; } - /* - * At this point, we're dealing with one of the following aborts: - * - * FAULT_TRAN_xx - Translation - * FAULT_PERM_xx - Permission - * - * These are the main virtual memory-related faults signalled by - * the MMU. - */ - - /* fusubailout is used by [fs]uswintr to avoid page faulting. */ - if (__predict_false(pcb->pcb_onfault == fusubailout)) { - tf->tf_r0 = EFAULT; - tf->tf_pc = (register_t)pcb->pcb_onfault; - return; - } - va = trunc_page(far); if (va >= KERNBASE) { /* diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c index e43ec8e..eb4d683 100644 --- a/sys/arm/arm/trap.c +++ b/sys/arm/arm/trap.c @@ -111,8 +111,6 @@ __FBSDID("$FreeBSD$"); #define ReadWord(a) (*((volatile unsigned int *)(a))) -extern char fusubailout[]; - #ifdef DEBUG int last_fault_code; /* For the benefit of pmap_fault_fixup() */ #endif @@ -255,13 +253,6 @@ abort_handler(struct trapframe *tf, int type) * the MMU. */ - /* fusubailout is used by [fs]uswintr to avoid page faulting */ - if (__predict_false(pcb->pcb_onfault == fusubailout)) { - tf->tf_r0 = EFAULT; - tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault; - return; - } - /* * Make sure the Program Counter is sane. We could fall foul of * someone executing Thumb code, in which case the PC might not diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c index 6a70cbf..601be07 100644 --- a/sys/arm/arm/vm_machdep.c +++ b/sys/arm/arm/vm_machdep.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/sysent.h> #include <sys/unistd.h> +#include <sys/taskqueue.h> #include <machine/acle-compat.h> #include <machine/cpu.h> diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c index 936f145..e904780 100644 --- a/sys/arm/at91/at91_machdep.c +++ b/sys/arm/at91/at91_machdep.c @@ -566,7 +566,7 @@ initarm(struct arm_boot_params *abp) arm_devmap_bootstrap(l1pagetable, at91_devmap); cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)); @@ -612,7 +612,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/broadcom/bcm2835/bcm2836_mp.c b/sys/arm/broadcom/bcm2835/bcm2836_mp.c index 93cc0d8..d6c84cb 100644 --- a/sys/arm/broadcom/bcm2835/bcm2836_mp.c +++ b/sys/arm/broadcom/bcm2835/bcm2836_mp.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/bus.h> #include <machine/fdt.h> @@ -123,8 +124,7 @@ platform_mp_start_ap(void) BSWR4(MBOX3CLR_CORE(i), 0xffffffff); } wmb(); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); /* boot secondary CPUs */ for (i = 1; i < mp_ncpus; i++) { diff --git a/sys/arm/cavium/cns11xx/econa_machdep.c b/sys/arm/cavium/cns11xx/econa_machdep.c index 1591053..e212a10 100644 --- a/sys/arm/cavium/cns11xx/econa_machdep.c +++ b/sys/arm/cavium/cns11xx/econa_machdep.c @@ -275,7 +275,7 @@ initarm(struct arm_boot_params *abp) arm_devmap_bootstrap(l1pagetable, econa_devmap); cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); cninit(); @@ -297,7 +297,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES index f4259f2..db64f8e 100644 --- a/sys/arm/conf/NOTES +++ b/sys/arm/conf/NOTES @@ -5,8 +5,6 @@ machine arm cpu CPU_ARM9 cpu CPU_ARM9E cpu CPU_FA526 -cpu CPU_XSCALE_80219 -cpu CPU_XSCALE_80321 cpu CPU_XSCALE_81342 cpu CPU_XSCALE_IXP425 cpu CPU_XSCALE_IXP435 diff --git a/sys/arm/freescale/imx/imx6_mp.c b/sys/arm/freescale/imx/imx6_mp.c index 3208f67..7aa9aab 100644 --- a/sys/arm/freescale/imx/imx6_mp.c +++ b/sys/arm/freescale/imx/imx6_mp.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/fdt.h> #include <machine/intr.h> @@ -149,7 +150,7 @@ platform_mp_start_ap(void) val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG); bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG, val | SCU_CONTROL_ENABLE); - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); /* * For each AP core, set the entry point address and argument registers, diff --git a/sys/arm/include/cpu-v4.h b/sys/arm/include/cpu-v4.h new file mode 100644 index 0000000..0d66dee --- /dev/null +++ b/sys/arm/include/cpu-v4.h @@ -0,0 +1,186 @@ +/*- + * Copyright 2016 Svatopluk Kraus <skra@FreeBSD.org> + * Copyright 2016 Michal Meloun <mmel@FreeBSD.org> + * 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 MACHINE_CPU_V4_H +#define MACHINE_CPU_V4_H + +/* There are no user serviceable parts here, they may change without notice */ +#ifndef _KERNEL +#error Only include this file in the kernel +#endif + +#include <machine/acle-compat.h> +#include <machine/atomic.h> +#include <machine/cpufunc.h> +#include <machine/cpuinfo.h> +#include <machine/sysreg.h> + +#if __ARM_ARCH >= 6 +#error Never include this file for ARMv6 +#else + +#define CPU_ASID_KERNEL 0 + +/* + * Macros to generate CP15 (system control processor) read/write functions. + */ +#define _FX(s...) #s + +#define _RF0(fname, aname...) \ +static __inline register_t \ +fname(void) \ +{ \ + register_t reg; \ + __asm __volatile("mrc\t" _FX(aname): "=r" (reg)); \ + return(reg); \ +} + +#define _R64F0(fname, aname) \ +static __inline uint64_t \ +fname(void) \ +{ \ + uint64_t reg; \ + __asm __volatile("mrrc\t" _FX(aname): "=r" (reg)); \ + return(reg); \ +} + +#define _WF0(fname, aname...) \ +static __inline void \ +fname(void) \ +{ \ + __asm __volatile("mcr\t" _FX(aname)); \ +} + +#define _WF1(fname, aname...) \ +static __inline void \ +fname(register_t reg) \ +{ \ + __asm __volatile("mcr\t" _FX(aname):: "r" (reg)); \ +} + + +/* + * Publicly accessible functions + */ + + +/* Various control registers */ + +_RF0(cp15_cpacr_get, CP15_CPACR(%0)) +_WF1(cp15_cpacr_set, CP15_CPACR(%0)) +_RF0(cp15_dfsr_get, CP15_DFSR(%0)) +_RF0(cp15_ttbr_get, CP15_TTBR0(%0)) +_RF0(cp15_dfar_get, CP15_DFAR(%0)) +/* XScale */ +_RF0(cp15_actlr_get, CP15_ACTLR(%0)) +_WF1(cp15_actlr_set, CP15_ACTLR(%0)) + +/*CPU id registers */ +_RF0(cp15_midr_get, CP15_MIDR(%0)) +_RF0(cp15_ctr_get, CP15_CTR(%0)) +_RF0(cp15_tcmtr_get, CP15_TCMTR(%0)) +_RF0(cp15_tlbtr_get, CP15_TLBTR(%0)) + +#undef _FX +#undef _RF0 +#undef _WF0 +#undef _WF1 + + +/* + * armv4/5 compatibility shims. + * + * These functions provide armv4 cache maintenance using the new armv6 names. + * Included here are just the functions actually used now in common code; it may + * be necessary to add things here over time. + * + * The callers of the dcache functions expect these routines to handle address + * and size values which are not aligned to cacheline boundaries; the armv4 and + * armv5 asm code handles that. + */ + +static __inline void +tlb_flush_all(void) +{ + cpu_tlb_flushID(); + cpu_cpwait(); +} + +static __inline void +icache_sync(vm_offset_t va, vm_size_t size) +{ + cpu_icache_sync_range(va, size); +} + +static __inline void +dcache_inv_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) +{ + + cpu_dcache_inv_range(va, size); +#ifdef ARM_L2_PIPT + cpu_l2cache_inv_range(pa, size); +#else + cpu_l2cache_inv_range(va, size); +#endif +} + +static __inline void +dcache_inv_poc_dma(vm_offset_t va, vm_paddr_t pa, vm_size_t size) +{ + + /* See armv6 code, above, for why we do L2 before L1 in this case. */ +#ifdef ARM_L2_PIPT + cpu_l2cache_inv_range(pa, size); +#else + cpu_l2cache_inv_range(va, size); +#endif + cpu_dcache_inv_range(va, size); +} + +static __inline void +dcache_wb_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) +{ + + cpu_dcache_wb_range(va, size); +#ifdef ARM_L2_PIPT + cpu_l2cache_wb_range(pa, size); +#else + cpu_l2cache_wb_range(va, size); +#endif +} + +static __inline void +dcache_wbinv_poc_all(void) +{ + cpu_idcache_wbinv_all(); + cpu_l2cache_wbinv_all(); +} + +#endif /* _KERNEL */ + +#endif /* MACHINE_CPU_V4_H */ diff --git a/sys/arm/include/cpu-v6.h b/sys/arm/include/cpu-v6.h index bb8649a..e537c10 100644 --- a/sys/arm/include/cpu-v6.h +++ b/sys/arm/include/cpu-v6.h @@ -32,19 +32,32 @@ /* There are no user serviceable parts here, they may change without notice */ #ifndef _KERNEL #error Only include this file in the kernel -#else +#endif #include <machine/acle-compat.h> -#include "machine/atomic.h" -#include "machine/cpufunc.h" -#include "machine/cpuinfo.h" -#include "machine/sysreg.h" +#include <machine/atomic.h> +#include <machine/cpufunc.h> +#include <machine/cpuinfo.h> +#include <machine/sysreg.h> + +#if __ARM_ARCH < 6 +#error Only include this file for ARMv6 +#else #define CPU_ASID_KERNEL 0 +void dcache_wbinv_poc_all(void); /* !!! NOT SMP coherent function !!! */ vm_offset_t dcache_wb_pou_checked(vm_offset_t, vm_size_t); vm_offset_t icache_inv_pou_checked(vm_offset_t, vm_size_t); +#ifdef DEV_PMU +#include <sys/pcpu.h> +#define PMU_OVSR_C 0x80000000 /* Cycle Counter */ +extern uint32_t ccnt_hi[MAXCPU]; +extern int pmu_attched; +#endif /* DEV_PMU */ + + /* * Macros to generate CP15 (system control processor) read/write functions. */ @@ -277,12 +290,6 @@ _W64F1(cp15_cnthp_cval_set, CP15_CNTHP_CVAL(%Q0, %R0)) #undef _WF0 #undef _WF1 -#if __ARM_ARCH >= 6 -/* - * Cache and TLB maintenance operations for armv6+ code. The #else block - * provides armv4/v5 implementations for a few of these used in common code. - */ - /* * TLB maintenance operations. */ @@ -577,48 +584,6 @@ cp15_ttbr_set(uint32_t reg) isb(); tlb_flush_all_ng_local(); } - -#else /* ! __ARM_ARCH >= 6 */ - -/* - * armv4/5 compatibility shims. - * - * These functions provide armv4 cache maintenance using the new armv6 names. - * Included here are just the functions actually used now in common code; it may - * be necessary to add things here over time. - * - * The callers of the dcache functions expect these routines to handle address - * and size values which are not aligned to cacheline boundaries; the armv4 and - * armv5 asm code handles that. - */ - -static __inline void -dcache_inv_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) -{ - - cpu_dcache_inv_range(va, size); - cpu_l2cache_inv_range(va, size); -} - -static __inline void -dcache_inv_poc_dma(vm_offset_t va, vm_paddr_t pa, vm_size_t size) -{ - - /* See armv6 code, above, for why we do L2 before L1 in this case. */ - cpu_l2cache_inv_range(va, size); - cpu_dcache_inv_range(va, size); -} - -static __inline void -dcache_wb_poc(vm_offset_t va, vm_paddr_t pa, vm_size_t size) -{ - - cpu_dcache_wb_range(va, size); - cpu_l2cache_wb_range(va, size); -} - -#endif /* __ARM_ARCH >= 6 */ - #endif /* _KERNEL */ #endif /* !MACHINE_CPU_V6_H */ diff --git a/sys/arm/include/cpu.h b/sys/arm/include/cpu.h index 782471e..0d79e68 100644 --- a/sys/arm/include/cpu.h +++ b/sys/arm/include/cpu.h @@ -14,12 +14,8 @@ void swi_vm(void *); #ifdef _KERNEL #if __ARM_ARCH >= 6 #include <machine/cpu-v6.h> -#ifdef DEV_PMU -#include <sys/pcpu.h> -#define PMU_OVSR_C 0x80000000 /* Cycle Counter */ -extern uint32_t ccnt_hi[MAXCPU]; -extern int pmu_attched; -#endif /* DEV_PMU */ +#else +#include <machine/cpu-v4.h> #endif /* __ARM_ARCH >= 6 */ static __inline uint64_t diff --git a/sys/arm/include/cpuconf.h b/sys/arm/include/cpuconf.h index ecee280..24a3b8f 100644 --- a/sys/arm/include/cpuconf.h +++ b/sys/arm/include/cpuconf.h @@ -53,7 +53,6 @@ #define CPU_NTYPES (defined(CPU_ARM9) + \ defined(CPU_ARM9E) + \ defined(CPU_ARM1176) + \ - defined(CPU_XSCALE_80321) + \ defined(CPU_XSCALE_PXA2X0) + \ defined(CPU_FA526) + \ defined(CPU_XSCALE_IXP425)) + \ @@ -71,8 +70,7 @@ #endif #if (defined(CPU_ARM9E) || \ - defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \ + defined(CPU_XSCALE_81342) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425)) #define ARM_ARCH_5 1 #else @@ -163,9 +161,8 @@ #define ARM_MMU_V7 0 #endif -#if (defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)) +#if (defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ + defined(CPU_XSCALE_81342)) #define ARM_MMU_XSCALE 1 #else #define ARM_MMU_XSCALE 0 @@ -180,11 +177,10 @@ /* * Step 4: Define features that may be present on a subset of CPUs * - * ARM_XSCALE_PMU Performance Monitoring Unit on 80200 and 80321 + * ARM_XSCALE_PMU Performance Monitoring Unit on 81342 */ -#if (defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)) +#if (defined(CPU_XSCALE_81342)) #define ARM_XSCALE_PMU 1 #else #define ARM_XSCALE_PMU 0 diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index aad0feb..eb445b4 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -79,7 +79,6 @@ struct cpu_functions { * * We define the following primitives: * - * icache_sync_all Synchronize I-cache * icache_sync_range Synchronize I-cache range * * dcache_wbinv_all Write-back and Invalidate D-cache @@ -104,7 +103,7 @@ struct cpu_functions { * state (such as when it may have lines tagged as valid * that belong to a previous set of mappings). * - * I-cache Synch (all or range): + * I-cache Sync range: * The goal is to synchronize the instruction stream, * so you may beed to write-back dirty D-cache blocks * first. If a range is requested, and you can't @@ -130,7 +129,6 @@ struct cpu_functions { * Valid virtual addresses must be passed to each * cache operation. */ - void (*cf_icache_sync_all) (void); void (*cf_icache_sync_range) (vm_offset_t, vm_size_t); void (*cf_dcache_wbinv_all) (void); @@ -163,9 +161,12 @@ struct cpu_functions { extern struct cpu_functions cpufuncs; extern u_int cputype; +#if __ARM_ARCH < 6 #define cpu_cpwait() cpufuncs.cf_cpwait() +#endif #define cpu_control(c, e) cpufuncs.cf_control(c, e) +#if __ARM_ARCH < 6 #define cpu_setttb(t) cpufuncs.cf_setttb(t) #define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID() @@ -173,7 +174,6 @@ extern u_int cputype; #define cpu_tlb_flushD() cpufuncs.cf_tlb_flushD() #define cpu_tlb_flushD_SE(e) cpufuncs.cf_tlb_flushD_SE(e) -#define cpu_icache_sync_all() cpufuncs.cf_icache_sync_all() #define cpu_icache_sync_range(a, s) cpufuncs.cf_icache_sync_range((a), (s)) #define cpu_dcache_wbinv_all() cpufuncs.cf_dcache_wbinv_all() @@ -184,13 +184,16 @@ extern u_int cputype; #define cpu_idcache_inv_all() cpufuncs.cf_idcache_inv_all() #define cpu_idcache_wbinv_all() cpufuncs.cf_idcache_wbinv_all() #define cpu_idcache_wbinv_range(a, s) cpufuncs.cf_idcache_wbinv_range((a), (s)) +#endif #define cpu_l2cache_wbinv_all() cpufuncs.cf_l2cache_wbinv_all() #define cpu_l2cache_wb_range(a, s) cpufuncs.cf_l2cache_wb_range((a), (s)) #define cpu_l2cache_inv_range(a, s) cpufuncs.cf_l2cache_inv_range((a), (s)) #define cpu_l2cache_wbinv_range(a, s) cpufuncs.cf_l2cache_wbinv_range((a), (s)) #define cpu_l2cache_drain_writebuf() cpufuncs.cf_l2cache_drain_writebuf() +#if __ARM_ARCH < 6 #define cpu_drain_writebuf() cpufuncs.cf_drain_writebuf() +#endif #define cpu_sleep(m) cpufuncs.cf_sleep(m) #define cpu_setup() cpufuncs.cf_setup() @@ -205,6 +208,7 @@ u_int cpufunc_control (u_int clear, u_int bic); void cpu_domains (u_int domains); u_int cpu_faultstatus (void); u_int cpu_faultaddress (void); +u_int cpu_get_control (void); u_int cpu_pfr (int); #if defined(CPU_FA526) @@ -214,7 +218,6 @@ void fa526_context_switch (void); void fa526_cpu_sleep (int); void fa526_tlb_flushID_SE (u_int); -void fa526_icache_sync_all (void); void fa526_icache_sync_range(vm_offset_t start, vm_size_t end); void fa526_dcache_wbinv_all (void); void fa526_dcache_wbinv_range(vm_offset_t start, vm_size_t end); @@ -231,8 +234,7 @@ void arm9_tlb_flushID_SE (u_int va); void arm9_context_switch (void); #endif -#if defined(CPU_ARM9) -void arm9_icache_sync_all (void); +#if defined(CPU_ARM9) void arm9_icache_sync_range (vm_offset_t, vm_size_t); void arm9_dcache_wbinv_all (void); @@ -275,7 +277,6 @@ void armv6_idcache_wbinv_all (void); void armv7_setttb (u_int); void armv7_tlb_flushID (void); void armv7_tlb_flushID_SE (u_int); -void armv7_icache_sync_all (void); void armv7_icache_sync_range (vm_offset_t, vm_size_t); void armv7_idcache_wbinv_range (vm_offset_t, vm_size_t); void armv7_idcache_inv_all (void); @@ -319,7 +320,6 @@ void armv6_idcache_inv_all (void); void arm11x6_setttb (u_int); void arm11x6_idcache_wbinv_all (void); void arm11x6_dcache_wbinv_all (void); -void arm11x6_icache_sync_all (void); void arm11x6_icache_sync_range (vm_offset_t, vm_size_t); void arm11x6_idcache_wbinv_range (vm_offset_t, vm_size_t); void arm11x6_setup (void); @@ -329,7 +329,6 @@ void arm11x6_sleep (int); /* no ref. for errata */ #if defined(CPU_ARM9E) void armv5_ec_setttb(u_int); -void armv5_ec_icache_sync_all(void); void armv5_ec_icache_sync_range(vm_offset_t, vm_size_t); void armv5_ec_dcache_wbinv_all(void); @@ -342,10 +341,9 @@ void armv5_ec_idcache_wbinv_range(vm_offset_t, vm_size_t); #endif #if defined(CPU_ARM9) || defined(CPU_ARM9E) || \ - defined(CPU_XSCALE_80321) || \ defined(CPU_FA526) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) + defined(CPU_XSCALE_81342) void armv4_tlb_flushID (void); void armv4_tlb_flushD (void); @@ -355,9 +353,8 @@ void armv4_drain_writebuf (void); void armv4_idcache_inv_all (void); #endif -#if defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) +#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ + defined(CPU_XSCALE_81342) void xscale_cpwait (void); void xscale_cpu_sleep (int mode); @@ -395,8 +392,7 @@ void xscale_cache_flushD_rng (vm_offset_t start, vm_size_t end); void xscale_context_switch (void); void xscale_setup (void); -#endif /* CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 - CPU_XSCALE_80219 */ +#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ #ifdef CPU_XSCALE_81342 @@ -423,9 +419,6 @@ void xscalec3_context_switch (void); #endif /* CPU_XSCALE_81342 */ -#define setttb cpu_setttb -#define drain_writebuf cpu_drain_writebuf - /* * Macros for manipulating CPU interrupts */ diff --git a/sys/arm/include/kdb.h b/sys/arm/include/kdb.h index fb50c78..c7968ab 100644 --- a/sys/arm/include/kdb.h +++ b/sys/arm/include/kdb.h @@ -29,10 +29,10 @@ #ifndef _MACHINE_KDB_H_ #define _MACHINE_KDB_H_ +#include <machine/cpu.h> +#include <machine/db_machdep.h> #include <machine/frame.h> #include <machine/psl.h> -#include <machine/cpufunc.h> -#include <machine/db_machdep.h> #define KDB_STOPPEDPCB(pc) &stoppcbs[pc->pc_cpuid] @@ -56,7 +56,7 @@ static __inline void kdb_cpu_sync_icache(unsigned char *addr, size_t size) { - cpu_icache_sync_range((vm_offset_t)addr, size); + icache_sync((vm_offset_t)addr, size); } static __inline void diff --git a/sys/arm/include/pmap-v6.h b/sys/arm/include/pmap-v6.h index d522384..0678977 100644 --- a/sys/arm/include/pmap-v6.h +++ b/sys/arm/include/pmap-v6.h @@ -115,7 +115,7 @@ struct pv_chunk; struct md_page { TAILQ_HEAD(,pv_entry) pv_list; uint16_t pt2_wirecount[4]; - int pat_mode; + vm_memattr_t pat_mode; }; struct pmap { @@ -173,7 +173,7 @@ struct pv_chunk { struct pcb; extern ttb_entry_t pmap_kern_ttb; /* TTB for kernel pmap */ -#define pmap_page_get_memattr(m) ((vm_memattr_t)(m)->md.pat_mode) +#define pmap_page_get_memattr(m) ((m)->md.pat_mode) #define pmap_page_is_write_mapped(m) (((m)->aflags & PGA_WRITEABLE) != 0) /* @@ -250,6 +250,8 @@ void pmap_preboot_map_attr(vm_paddr_t, vm_offset_t, vm_size_t, vm_prot_t, */ void vector_page_setprot(int); +#define PTE_DEVICE VM_MEMATTR_DEVICE + #endif /* _KERNEL */ // ----------------------------------------------------------------------------- diff --git a/sys/arm/include/vm.h b/sys/arm/include/vm.h index 552460e..eb67025 100644 --- a/sys/arm/include/vm.h +++ b/sys/arm/include/vm.h @@ -34,11 +34,11 @@ #if __ARM_ARCH >= 6 #include <machine/pte-v6.h> -#define VM_MEMATTR_WB_WA ((vm_memattr_t)PTE2_ATTR_WB_WA) -#define VM_MEMATTR_NOCACHE ((vm_memattr_t)PTE2_ATTR_NOCACHE) -#define VM_MEMATTR_DEVICE ((vm_memattr_t)PTE2_ATTR_DEVICE) -#define VM_MEMATTR_SO ((vm_memattr_t)PTE2_ATTR_SO) -#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PTE2_ATTR_WT) +#define VM_MEMATTR_WB_WA ((vm_memattr_t)0) +#define VM_MEMATTR_NOCACHE ((vm_memattr_t)1) +#define VM_MEMATTR_DEVICE ((vm_memattr_t)2) +#define VM_MEMATTR_SO ((vm_memattr_t)3) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)4) #define VM_MEMATTR_DEFAULT VM_MEMATTR_WB_WA #define VM_MEMATTR_UNCACHEABLE VM_MEMATTR_SO /* misused by DMA */ diff --git a/sys/arm/mv/armada38x/pmsu.c b/sys/arm/mv/armada38x/pmsu.c index a84ede0..110278b 100644 --- a/sys/arm/mv/armada38x/pmsu.c +++ b/sys/arm/mv/armada38x/pmsu.c @@ -36,10 +36,12 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/module.h> #include <sys/resource.h> +#include <sys/systm.h> #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/fdt.h> #include <machine/smp.h> @@ -143,8 +145,7 @@ pmsu_boot_secondary_cpu(void) bus_space_write_4(fdtbus_bs_tag, vaddr, PMSU_BOOT_ADDR_REDIRECT_OFFSET(1), pmap_kextract((vm_offset_t)mpentry)); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, vaddr, MV_PMSU_REGS_LEN); diff --git a/sys/arm/mv/armadaxp/armadaxp_mp.c b/sys/arm/mv/armadaxp/armadaxp_mp.c index 4ccf7e3..52f3508 100644 --- a/sys/arm/mv/armadaxp/armadaxp_mp.c +++ b/sys/arm/mv/armadaxp/armadaxp_mp.c @@ -40,6 +40,7 @@ #include <dev/fdt/fdt_common.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/fdt.h> #include <machine/armreg.h> @@ -174,7 +175,7 @@ platform_mp_start_ap(void) bus_space_write_4(fdtbus_bs_tag, CPU_PMU(cpu_num), CPU_PMU_BOOT, pmap_kextract((vm_offset_t)mpentry)); - cpu_idcache_wbinv_all(); + dcache_wbinv_poc_all(); for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) bus_space_write_4(fdtbus_bs_tag, MP, MP_SW_RESET(cpu_num), 0); diff --git a/sys/arm/rockchip/rk30xx_mp.c b/sys/arm/rockchip/rk30xx_mp.c index 38b6b41..5de2eff 100644 --- a/sys/arm/rockchip/rk30xx_mp.c +++ b/sys/arm/rockchip/rk30xx_mp.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/fdt.h> #include <machine/intr.h> @@ -171,8 +172,7 @@ platform_mp_start_ap(void) bus_space_write_region_4(fdtbus_bs_tag, imem, 0, (uint32_t *)&rk30xx_boot2, 8); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); /* Start all cores */ val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON); diff --git a/sys/arm/samsung/exynos/exynos5_mp.c b/sys/arm/samsung/exynos/exynos5_mp.c index 8eb0d29..44b2844 100644 --- a/sys/arm/samsung/exynos/exynos5_mp.c +++ b/sys/arm/samsung/exynos/exynos5_mp.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/fdt.h> #include <machine/intr.h> @@ -135,8 +136,7 @@ platform_mp_start_ap(void) bus_space_write_4(fdtbus_bs_tag, sysram, 0x0, pmap_kextract((vm_offset_t)mpentry)); - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); armv7_sev(); bus_space_unmap(fdtbus_bs_tag, sysram, 0x100); diff --git a/sys/arm/ti/omap4/omap4_mp.c b/sys/arm/ti/omap4/omap4_mp.c index 1a095ab..6cea1cc 100644 --- a/sys/arm/ti/omap4/omap4_mp.c +++ b/sys/arm/ti/omap4/omap4_mp.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/fdt.h> #include <machine/intr.h> @@ -72,8 +73,8 @@ platform_mp_start_ap(void) /* Enable the SCU */ *(volatile unsigned int *)scu_addr |= 1; //*(volatile unsigned int *)(scu_addr + 0x30) |= 1; - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); + ti_smc0(0x200, 0xfffffdff, MODIFY_AUX_CORE_0); ti_smc0(pmap_kextract((vm_offset_t)mpentry), 0, WRITE_AUX_CORE_1); armv7_sev(); diff --git a/sys/arm/xilinx/zy7_mp.c b/sys/arm/xilinx/zy7_mp.c index f71740c..74528ef 100644 --- a/sys/arm/xilinx/zy7_mp.c +++ b/sys/arm/xilinx/zy7_mp.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <machine/cpu.h> #include <machine/smp.h> #include <machine/fdt.h> #include <machine/intr.h> @@ -104,8 +105,7 @@ platform_mp_start_ap(void) * magic location, 0xfffffff0, isn't in the SCU's filtering range so it * needs a write-back too. */ - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); + dcache_wbinv_poc_all(); /* Wake up CPU1. */ armv7_sev(); diff --git a/sys/arm/xscale/i80321/ep80219_machdep.c b/sys/arm/xscale/i80321/ep80219_machdep.c deleted file mode 100644 index 6c0d1f5..0000000 --- a/sys/arm/xscale/i80321/ep80219_machdep.c +++ /dev/null @@ -1,402 +0,0 @@ -/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */ - -/*- - * Copyright (c) 1994-1998 Mark Brinicombe. - * Copyright (c) 1994 Brini. - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Brini. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. - * - * RiscBSD kernel project - * - * machdep.c - * - * Machine dependant functions for kernel setup - * - * This file needs a lot of work. - * - * Created : 17/09/94 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_kstack_pages.h" - -#define _ARM32_BUS_DMA_PRIVATE -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sysproto.h> -#include <sys/signalvar.h> -#include <sys/imgact.h> -#include <sys/kernel.h> -#include <sys/ktr.h> -#include <sys/linker.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/pcpu.h> -#include <sys/proc.h> -#include <sys/ptrace.h> -#include <sys/cons.h> -#include <sys/bio.h> -#include <sys/bus.h> -#include <sys/buf.h> -#include <sys/exec.h> -#include <sys/kdb.h> -#include <sys/msgbuf.h> -#include <machine/reg.h> -#include <machine/cpu.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_object.h> -#include <vm/vm_page.h> -#include <vm/vm_map.h> -#include <machine/devmap.h> -#include <machine/vmparam.h> -#include <machine/pcb.h> -#include <machine/undefined.h> -#include <machine/machdep.h> -#include <machine/metadata.h> -#include <machine/armreg.h> -#include <machine/bus.h> -#include <machine/physmem.h> -#include <sys/reboot.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> -#include <arm/xscale/i80321/iq80321reg.h> -#include <arm/xscale/i80321/obiovar.h> - -#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ -#define KERNEL_PT_IOPXS 1 -#define KERNEL_PT_BEFOREKERN 2 -#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */ -#define KERNEL_PT_AFKERNEL_NUM 9 - -/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ -#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) - -struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; - -/* Physical and virtual addresses for some global pages */ - -struct pv_addr systempage; -struct pv_addr msgbufpv; -struct pv_addr irqstack; -struct pv_addr undstack; -struct pv_addr abtstack; -struct pv_addr kernelstack; -struct pv_addr minidataclean; - - -/* #define IQ80321_OBIO_BASE 0xfe800000UL */ -/* #define IQ80321_OBIO_SIZE 0x00100000UL */ - -/* Static device mappings. */ -static const struct arm_devmap_entry ep80219_devmap[] = { - /* - * Map the on-board devices VA == PA so that we can access them - * with the MMU on or off. - */ - { - IQ80321_OBIO_BASE, - IQ80321_OBIO_BASE, - IQ80321_OBIO_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - IQ80321_IOW_VBASE, - VERDE_OUT_XLATE_IO_WIN0_BASE, - VERDE_OUT_XLATE_IO_WIN_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - IQ80321_80321_VBASE, - VERDE_PMMR_BASE, - VERDE_PMMR_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - 0, - 0, - 0, - 0, - 0, - } -}; - -extern vm_offset_t xscale_cache_clean_addr; - -void * -initarm(struct arm_boot_params *abp) -{ - struct pv_addr kernel_l1pt; - struct pv_addr dpcpu; - int loop, i; - u_int l1pagetable; - vm_offset_t freemempos; - vm_offset_t freemem_pt; - vm_offset_t afterkern; - vm_offset_t freemem_after; - vm_offset_t lastaddr; - uint32_t memsize, memstart; - - lastaddr = parse_boot_param(abp); - arm_physmem_kernaddr = abp->abp_physaddr; - set_cpufuncs(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); - PCPU_SET(curthread, &thread0); - - /* Do basic tuning, hz etc */ - init_param1(); - - freemempos = 0xa0200000; - /* Define a macro to simplify memory allocation */ -#define valloc_pages(var, np) \ - alloc_pages((var).pv_pa, (np)); \ - (var).pv_va = (var).pv_pa + 0x20000000; - -#define alloc_pages(var, np) \ - freemempos -= (np * PAGE_SIZE); \ - (var) = freemempos; \ - memset((char *)(var), 0, ((np) * PAGE_SIZE)); - - while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) - freemempos -= PAGE_SIZE; - valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); - for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { - if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { - valloc_pages(kernel_pt_table[loop], - L2_TABLE_SIZE / PAGE_SIZE); - } else { - kernel_pt_table[loop].pv_pa = freemempos + - (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * - L2_TABLE_SIZE_REAL; - kernel_pt_table[loop].pv_va = - kernel_pt_table[loop].pv_pa + 0x20000000; - } - } - freemem_pt = freemempos; - freemempos = 0xa0100000; - /* - * Allocate a page for the system page mapped to V0x00000000 - * This page will just contain the system vectors and can be - * shared by all processes. - */ - valloc_pages(systempage, 1); - - /* Allocate dynamic per-cpu area. */ - valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); - dpcpu_init((void *)dpcpu.pv_va, 0); - - /* Allocate stacks for all modes */ - valloc_pages(irqstack, IRQ_STACK_SIZE); - valloc_pages(abtstack, ABT_STACK_SIZE); - valloc_pages(undstack, UND_STACK_SIZE); - valloc_pages(kernelstack, kstack_pages); - alloc_pages(minidataclean.pv_pa, 1); - valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); - /* - * Allocate memory for the l1 and l2 page tables. The scheme to avoid - * wasting memory by allocating the l1pt on the first 16k memory was - * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for - * this to work (which is supposed to be the case). - */ - - /* - * Now we start construction of the L1 page table - * We start by mapping the L2 page tables into the L1. - * This means that we can replace L1 mappings later on if necessary - */ - l1pagetable = kernel_l1pt.pv_va; - - /* Map the L2 pages tables in the L1 page table */ - pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1), - &kernel_pt_table[KERNEL_PT_SYS]); - pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE, - &kernel_pt_table[KERNEL_PT_IOPXS]); - pmap_link_l2pt(l1pagetable, KERNBASE, - &kernel_pt_table[KERNEL_PT_BEFOREKERN]); - pmap_map_chunk(l1pagetable, KERNBASE, IQ80321_SDRAM_START, 0x100000, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, IQ80321_SDRAM_START + 0x100000, - 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); - pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, IQ80321_SDRAM_START + 0x200000, - (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1), - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1); - afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE - - 1)); - for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { - pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000, - &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); - } - pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - - - /* Map the Mini-Data cache clean area. */ - xscale_setup_minidata(l1pagetable, afterkern, - minidataclean.pv_pa); - - /* Map the vector page. */ - pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - arm_devmap_bootstrap(l1pagetable, ep80219_devmap); - /* - * Give the XScale global cache clean code an appropriately - * sized chunk of unmapped VA space starting at 0xff000000 - * (our device mappings end before this address). - */ - xscale_cache_clean_addr = 0xff000000U; - - cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); - cpu_tlb_flushID(); - cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); - /* - * Pages were allocated during the secondary bootstrap for the - * stacks for different CPU modes. - * We must now set the r13 registers in the different CPU modes to - * point to these stacks. - * Since the ARM stacks use STMFD etc. we must set r13 to the top end - * of the stack memory. - */ - set_stackptrs(0); - - /* - * We must now clean the cache again.... - * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() - * but since we are boot strapping the addresses used for the read - * may have just been remapped and thus the cache could be out - * of sync. A re-clean after the switch will cure this. - * After booting there are no gross relocations of the kernel thus - * this problem will not occur after initarm(). - */ - cpu_idcache_wbinv_all(); - cpu_setup(); - - /* - * Fetch the SDRAM start/size from the i80321 SDRAM configration - * registers. - */ - i80321_calibrate_delay(); - i80321_sdram_bounds(obio_bs_tag, IQ80321_80321_VBASE + VERDE_MCU_BASE, - &memstart, &memsize); - physmem = memsize / PAGE_SIZE; - cninit(); - - undefined_init(); - - init_proc0(kernelstack.pv_va); - - /* Enable MMU, I-cache, D-cache, write buffer. */ - - arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); - vm_max_kernel_address = 0xe0000000; - pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); - msgbufp = (void*)msgbufpv.pv_va; - msgbufinit(msgbufp, msgbufsize); - mutex_init(); - - /* - * Add the physical ram we have available. - * - * Exclude the kernel (and all the things we allocated which immediately - * follow the kernel) from the VM allocation pool but not from crash - * dumps. virtual_avail is a global variable which tracks the kva we've - * "allocated" while setting up pmaps. - * - * Prepare the list of physical memory available to the vm subsystem. - */ - arm_physmem_hardware_region(IQ80321_SDRAM_START, memsize); - arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr - - freemem_pt, EXFLAG_NOALLOC); - arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 - - freemempos, EXFLAG_NOALLOC); - arm_physmem_exclude_region(abp->abp_physaddr, - virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC); - arm_physmem_init_kernel_globals(); - - init_param2(physmem); - kdb_init(); - return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - - sizeof(struct pcb))); -} - -extern int -machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin) -{ - int bus; - int device; - int func; - uint32_t busno; - struct i80321_pci_softc *sc = device_get_softc(pcib); - bus = pci_get_bus(dev); - device = pci_get_slot(dev); - func = pci_get_function(dev); - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - if (bus != busno) - goto no_mapping; - switch (device) { - /* EP80219 PCI */ - case 1: /* Ethernet i82555 10/100 */ - printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(0)); - return (ICU_INT_XINT(0)); - case 2: /* UART */ - printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(1)); - return (ICU_INT_XINT(1)); - case 3: - /* - * The S-ATA chips are behind the bridge, and all of - * the S-ATA interrupts are wired together. - */ - printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(2)); - return (ICU_INT_XINT(2)); - case 4: /* MINI-PIC_INT */ - printf("Device %d routed to irq %d\n", device, ICU_INT_XINT(3)); - return( ICU_INT_XINT(3)); - default: -no_mapping: - printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin); - - } - return (0); - -} diff --git a/sys/arm/xscale/i80321/files.ep80219 b/sys/arm/xscale/i80321/files.ep80219 deleted file mode 100644 index 0eaf9db..0000000 --- a/sys/arm/xscale/i80321/files.ep80219 +++ /dev/null @@ -1,11 +0,0 @@ -#$FreeBSD$ -# -# -# EP80219 Board Specific -# -arm/xscale/i80321/iq80321.c standard -arm/xscale/i80321/ep80219_machdep.c standard -arm/xscale/i80321/obio.c standard -arm/xscale/i80321/uart_cpu_i80321.c optional uart -arm/xscale/i80321/uart_bus_i80321.c optional uart -dev/uart/uart_dev_ns8250.c optional uart diff --git a/sys/arm/xscale/i80321/files.i80219 b/sys/arm/xscale/i80321/files.i80219 deleted file mode 100644 index 306376b..0000000 --- a/sys/arm/xscale/i80321/files.i80219 +++ /dev/null @@ -1,11 +0,0 @@ -#$FreeBSD$ -# -# IOP Specific -# -arm/xscale/i80321/i80321.c standard -arm/xscale/i80321/i80321_dma.c optional dma -arm/xscale/i80321/i80321_mcu.c standard -arm/xscale/i80321/i80321_pci.c optional pci -arm/xscale/i80321/i80321_space.c standard -arm/xscale/i80321/i80321_timer.c standard -arm/xscale/i80321/i80321_wdog.c optional iopwdog diff --git a/sys/arm/xscale/i80321/files.i80321 b/sys/arm/xscale/i80321/files.i80321 deleted file mode 100644 index bd318af..0000000 --- a/sys/arm/xscale/i80321/files.i80321 +++ /dev/null @@ -1,9 +0,0 @@ -#$FreeBSD$ -arm/xscale/i80321/i80321.c standard -arm/xscale/i80321/i80321_aau.c optional aau -arm/xscale/i80321/i80321_dma.c optional dma -arm/xscale/i80321/i80321_mcu.c standard -arm/xscale/i80321/i80321_pci.c optional pci -arm/xscale/i80321/i80321_space.c standard -arm/xscale/i80321/i80321_timer.c standard -arm/xscale/i80321/i80321_wdog.c optional iopwdog diff --git a/sys/arm/xscale/i80321/files.iq31244 b/sys/arm/xscale/i80321/files.iq31244 deleted file mode 100644 index d28d49b..0000000 --- a/sys/arm/xscale/i80321/files.iq31244 +++ /dev/null @@ -1,8 +0,0 @@ -#$FreeBSD$ -arm/xscale/i80321/iq80321.c standard -arm/xscale/i80321/iq31244_machdep.c standard -arm/xscale/i80321/iq31244_7seg.c optional iq31244_7seg -arm/xscale/i80321/obio.c standard -arm/xscale/i80321/uart_cpu_i80321.c optional uart -arm/xscale/i80321/uart_bus_i80321.c optional uart -dev/uart/uart_dev_ns8250.c optional uart diff --git a/sys/arm/xscale/i80321/i80321.c b/sys/arm/xscale/i80321/i80321.c deleted file mode 100644 index e65f38d..0000000 --- a/sys/arm/xscale/i80321/i80321.c +++ /dev/null @@ -1,250 +0,0 @@ -/* $NetBSD: i80321.c,v 1.15 2003/10/06 16:06:05 thorpej Exp $ */ - -/*- - * Copyright (c) 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * Autoconfiguration support for the Intel i80321 I/O Processor. - */ - -#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> - -#define _ARM32_BUS_DMA_PRIVATE -#include <machine/bus.h> -#include <machine/intr.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> -#include <arm/xscale/i80321/i80321_intr.h> - -#include <dev/pci/pcireg.h> - -volatile uint32_t intr_enabled; -uint32_t intr_steer = 0; -/* - * Statically-allocated bus_space stucture used to access the - * i80321's own registers. - */ -struct bus_space i80321_bs_tag; - -/* - * There can be only one i80321, so we keep a global pointer to - * the softc, so board-specific code can use features of the - * i80321 without having to have a handle on the softc itself. - */ -struct i80321_softc *i80321_softc; - -#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) -/* - * i80321_attach: - * - * Board-independent attach routine for the i80321. - */ -void -i80321_attach(struct i80321_softc *sc) -{ - - i80321_softc = sc; - uint32_t preg; - - /* We expect the Memory Controller to be already sliced off. */ - - /* - * Program the Inbound windows. - */ - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, - (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0, - sc->sc_iwin[0].iwin_xlate); - if (sc->sc_is_host) { - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS, sc->sc_iwin[0].iwin_base_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x04, sc->sc_iwin[0].iwin_base_hi); - } else { - sc->sc_iwin[0].iwin_base_lo = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS); - sc->sc_iwin[0].iwin_base_hi = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x04); - sc->sc_iwin[0].iwin_base_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[0].iwin_base_lo); - } - - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, - (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0); - - /* no xlate for window 1 */ - if (sc->sc_is_host) { - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x08, sc->sc_iwin[1].iwin_base_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x0c, sc->sc_iwin[1].iwin_base_hi); - } else { - sc->sc_iwin[1].iwin_base_lo = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x08); - sc->sc_iwin[1].iwin_base_hi = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x0c); - sc->sc_iwin[1].iwin_base_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); - } - - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, - (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2, - sc->sc_iwin[2].iwin_xlate); - - if (sc->sc_is_host) { - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x10, sc->sc_iwin[2].iwin_base_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_BARS + 0x14, sc->sc_iwin[2].iwin_base_hi); - } else { - sc->sc_iwin[2].iwin_base_lo = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x10); - sc->sc_iwin[2].iwin_base_hi = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, PCIR_BARS + 0x14); - sc->sc_iwin[2].iwin_base_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); - } - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3, - (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3, - sc->sc_iwin[3].iwin_xlate); - - if (sc->sc_is_host) { - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi); - } else { - sc->sc_iwin[3].iwin_base_lo = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, ATU_IABAR3); - sc->sc_iwin[3].iwin_base_hi = bus_space_read_4(sc->sc_st, - sc->sc_atu_sh, ATU_IAUBAR3); - sc->sc_iwin[3].iwin_base_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[3].iwin_base_lo); - } - /* - * Mask (disable) the ATU interrupt sources. - * XXX May want to revisit this if we encounter - * XXX an application that wants it. - */ - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_ATUIMR, - ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST| - ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM| - ATUIMR_PTAT|ATUIMR_PMPE); - - /* - * Program the outbound windows. - */ - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OIOWTVR, sc->sc_ioout_xlate); - - if (!sc->sc_is_host) { - sc->sc_owin[0].owin_xlate_lo = sc->sc_iwin[1].iwin_base_lo; - sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; - } - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi); - - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi); - - /* - * Set up the ATU configuration register. All we do - * right now is enable Outbound Windows. - */ - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR, - ATUCR_OUT_EN); - - /* - * Enable bus mastering, memory access, SERR, and parity - * checking on the ATU. - */ - if (sc->sc_is_host) { - preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, - PCIR_COMMAND); - preg |= PCIM_CMD_MEMEN | - PCIM_CMD_BUSMASTEREN | PCIM_CMD_PERRESPEN | - PCIM_CMD_SERRESPEN; - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, - PCIR_COMMAND, preg); - } - /* Initialize the bus space tags. */ - i80321_io_bs_init(&sc->sc_pci_iot, sc); - i80321_mem_bs_init(&sc->sc_pci_memt, sc); - intr_enabled = 0; - i80321_set_intrmask(); - i80321_set_intrsteer(); -} - - -static __inline uint32_t -i80321_iintsrc_read(void) -{ - uint32_t iintsrc; - - __asm __volatile("mrc p6, 0, %0, c8, c0, 0" - : "=r" (iintsrc)); - - /* - * The IINTSRC register shows bits that are active even - * if they are masked in INTCTL, so we have to mask them - * off with the interrupts we consider enabled. - */ - return (iintsrc & intr_enabled); -} - -int -arm_get_next_irq(int last __unused) -{ - int irq; - - if ((irq = i80321_iintsrc_read())) - return (ffs(irq) - 1); - return (-1); -} diff --git a/sys/arm/xscale/i80321/i80321_aau.c b/sys/arm/xscale/i80321/i80321_aau.c deleted file mode 100644 index 288411b..0000000 --- a/sys/arm/xscale/i80321/i80321_aau.c +++ /dev/null @@ -1,292 +0,0 @@ -/*- - * Copyright (c) 2005 Olivier Houchard. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <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/lock.h> -#include <sys/mutex.h> -#include <sys/proc.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_map.h> -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/md_var.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> -#include <arm/xscale/i80321/iq80321reg.h> -#include <arm/xscale/i80321/iq80321var.h> -#include <arm/xscale/i80321/i80321_intr.h> - -typedef struct i80321_aaudesc_s { - vm_paddr_t next_desc; - uint32_t sar[4]; - vm_paddr_t local_addr; - vm_size_t count; - uint32_t descr_ctrl; -} __packed i80321_aaudesc_t; - -typedef struct i80321_aauring_s { - i80321_aaudesc_t *desc; - vm_paddr_t phys_addr; - bus_dmamap_t map; -} i80321_aauring_t; - -#define AAU_RING_SIZE 64 - -struct i80321_aau_softc { - bus_space_tag_t sc_st; - bus_space_handle_t sc_aau_sh; - bus_dma_tag_t dmatag; - i80321_aauring_t aauring[AAU_RING_SIZE]; - int flags; -#define BUSY 0x1 - int unit; - struct mtx mtx; -}; - -static int -i80321_aau_probe(device_t dev) -{ - device_set_desc(dev, "I80321 AAU"); - return (0); -} - -static struct i80321_aau_softc *aau_softc; - -static void -i80321_mapphys(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - vm_paddr_t *addr = (vm_paddr_t *)arg; - - *addr = segs->ds_addr; -} - -#define AAU_REG_WRITE(softc, reg, val) \ - bus_space_write_4((softc)->sc_st, (softc)->sc_aau_sh, \ - (reg), (val)) -#define AAU_REG_READ(softc, reg) \ - bus_space_read_4((softc)->sc_st, (softc)->sc_aau_sh, \ - (reg)) - -static int aau_bzero(void *, int, int); - -static int -i80321_aau_attach(device_t dev) -{ - struct i80321_aau_softc *softc = device_get_softc(dev); - struct i80321_softc *sc = device_get_softc(device_get_parent(dev)); - struct i80321_aaudesc_s *aaudescs; - - mtx_init(&softc->mtx, "AAU mtx", NULL, MTX_SPIN); - softc->sc_st = sc->sc_st; - if (bus_space_subregion(softc->sc_st, sc->sc_sh, VERDE_AAU_BASE, - VERDE_AAU_SIZE, &softc->sc_aau_sh) != 0) - panic("%s: unable to subregion AAU registers", - device_get_name(dev)); - if (bus_dma_tag_create(NULL, sizeof(i80321_aaudesc_t), 0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, - AAU_RING_SIZE * sizeof(i80321_aaudesc_t), - 1, sizeof(i80321_aaudesc_t), BUS_DMA_ALLOCNOW, busdma_lock_mutex, - &Giant, &softc->dmatag)) - panic("Couldn't create a dma tag"); - if (bus_dmamem_alloc(softc->dmatag, (void **)&aaudescs, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &softc->aauring[0].map)) - panic("Couldn't alloc dma memory"); - - for (int i = 0; i < AAU_RING_SIZE; i++) { - if (i > 0) - if (bus_dmamap_create(softc->dmatag, 0, - &softc->aauring[i].map)) - panic("Couldn't create dma map"); - softc->aauring[i].desc = &aaudescs[i]; - bus_dmamap_load(softc->dmatag, softc->aauring[i].map, - softc->aauring[i].desc, sizeof(i80321_aaudesc_t), - i80321_mapphys, &softc->aauring[i].phys_addr, 0); - bzero(softc->aauring[i].desc, sizeof(i80321_aaudesc_t)); - } - aau_softc = softc; - _arm_bzero = aau_bzero; - _min_bzero_size = 1024; - return (0); -} - -static __inline void -test_virt_addr(void *addr, int len) -{ - int to_nextpage; - - while (len > 0) { - *(char *)addr = 0; - to_nextpage = ((vm_offset_t)addr & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)addr; - if (to_nextpage >= len) - break; - len -= to_nextpage; - addr = (void *)((vm_offset_t)addr + to_nextpage); - } -} - -static int -aau_bzero(void *dst, int len, int flags) -{ - struct i80321_aau_softc *sc = aau_softc; - i80321_aaudesc_t *desc; - int ret; - int csr; - int descnb = 0; - int tmplen = len; - int to_nextpagedst; - int min_hop; - vm_paddr_t pa, tmppa; - - if (!sc) - return (-1); - mtx_lock_spin(&sc->mtx); - if (sc->flags & BUSY) { - mtx_unlock_spin(&sc->mtx); - return (-1); - } - sc->flags |= BUSY; - mtx_unlock_spin(&sc->mtx); - desc = sc->aauring[0].desc; - if (flags & IS_PHYSICAL) { - desc->local_addr = (vm_paddr_t)dst; - desc->next_desc = 0; - desc->count = len; - desc->descr_ctrl = 2 << 1 | 1 << 31; /* Fill, enable dest write */ - bus_dmamap_sync(sc->dmatag, sc->aauring[0].map, - BUS_DMASYNC_PREWRITE); - } else { - test_virt_addr(dst, len); - if ((vm_offset_t)dst & (31)) - cpu_dcache_wb_range((vm_offset_t)dst & ~31, 32); - if (((vm_offset_t)dst + len) & 31) - cpu_dcache_wb_range(((vm_offset_t)dst + len) & ~31, - 32); - cpu_dcache_inv_range((vm_offset_t)dst, len); - while (tmplen > 0) { - pa = vtophys(dst); - to_nextpagedst = ((vm_offset_t)dst & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)dst; - while (to_nextpagedst < tmplen) { - tmppa = vtophys((vm_offset_t)dst + - to_nextpagedst); - if (tmppa != pa + to_nextpagedst) - break; - to_nextpagedst += PAGE_SIZE; - } - min_hop = to_nextpagedst; - if (min_hop < 64) { - tmplen -= min_hop; - bzero(dst, min_hop); - cpu_dcache_wbinv_range((vm_offset_t)dst, - min_hop); - - dst = (void *)((vm_offset_t)dst + min_hop); - if (tmplen <= 0 && descnb > 0) { - sc->aauring[descnb - 1].desc->next_desc - = 0; - bus_dmamap_sync(sc->dmatag, - sc->aauring[descnb - 1].map, - BUS_DMASYNC_PREWRITE); - } - continue; - } - desc->local_addr = pa; - desc->count = tmplen > min_hop ? min_hop : tmplen; - desc->descr_ctrl = 2 << 1 | 1 << 31; /* Fill, enable dest write */; - if (min_hop < tmplen) { - tmplen -= min_hop; - dst = (void *)((vm_offset_t)dst + min_hop); - } else - tmplen = 0; - if (descnb + 1 >= AAU_RING_SIZE) { - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (-1); - } - if (tmplen > 0) { - desc->next_desc = sc->aauring[descnb + 1]. - phys_addr; - bus_dmamap_sync(sc->dmatag, - sc->aauring[descnb].map, - BUS_DMASYNC_PREWRITE); - desc = sc->aauring[descnb + 1].desc; - descnb++; - } else { - desc->next_desc = 0; - bus_dmamap_sync(sc->dmatag, - sc->aauring[descnb].map, - BUS_DMASYNC_PREWRITE); - } - - } - - } - AAU_REG_WRITE(sc, 0x0c /* Descriptor addr */, - sc->aauring[0].phys_addr); - AAU_REG_WRITE(sc, 0 /* Control register */, 1 << 0/* Start transfer */); - while ((csr = AAU_REG_READ(sc, 0x4)) & (1 << 10)); - /* Wait until it's done. */ - if (csr & (1 << 5)) /* error */ - ret = -1; - else - ret = 0; - /* Clear the interrupt. */ - AAU_REG_WRITE(sc, 0x4, csr); - /* Stop the AAU. */ - AAU_REG_WRITE(sc, 0, 0); - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (ret); -} - -static device_method_t i80321_aau_methods[] = { - DEVMETHOD(device_probe, i80321_aau_probe), - DEVMETHOD(device_attach, i80321_aau_attach), - {0, 0}, -}; - -static driver_t i80321_aau_driver = { - "i80321_aau", - i80321_aau_methods, - sizeof(struct i80321_aau_softc), -}; - -static devclass_t i80321_aau_devclass; - -DRIVER_MODULE(i80321_aau, iq, i80321_aau_driver, i80321_aau_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/i80321_dma.c b/sys/arm/xscale/i80321/i80321_dma.c deleted file mode 100644 index abf7dcc..0000000 --- a/sys/arm/xscale/i80321/i80321_dma.c +++ /dev/null @@ -1,351 +0,0 @@ -/*- - * Copyright (c) 2005 Olivier Houchard. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <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/lock.h> -#include <sys/mutex.h> -#include <sys/proc.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_map.h> -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/md_var.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> -#include <arm/xscale/i80321/iq80321reg.h> -#include <arm/xscale/i80321/iq80321var.h> -#include <arm/xscale/i80321/i80321_intr.h> - -typedef struct i80321_dmadesc_s { - vm_paddr_t next_desc; - vm_paddr_t low_pciaddr; - vm_paddr_t high_pciaddr; - vm_paddr_t local_addr; - vm_size_t count; - uint32_t descr_ctrl; - uint64_t unused; -} __packed i80321_dmadesc_t; - -typedef struct i80321_dmaring_s { - i80321_dmadesc_t *desc; - vm_paddr_t phys_addr; - bus_dmamap_t map; -} i80321_dmaring_t; - -#define DMA_RING_SIZE 64 - -struct i80321_dma_softc { - bus_space_tag_t sc_st; - bus_space_handle_t sc_dma_sh; - bus_dma_tag_t dmatag; - i80321_dmaring_t dmaring[DMA_RING_SIZE]; - int flags; -#define BUSY 0x1 - int unit; - struct mtx mtx; -}; - -static int -i80321_dma_probe(device_t dev) -{ - device_set_desc(dev, "I80321 DMA Unit"); - return (0); -} - -static struct i80321_dma_softc *softcs[2]; /* XXX */ - -static void -i80321_mapphys(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - vm_paddr_t *addr = (vm_paddr_t *)arg; - - *addr = segs->ds_addr; -} - -#define DMA_REG_WRITE(softc, reg, val) \ - bus_space_write_4((softc)->sc_st, (softc)->sc_dma_sh, \ - (reg), (val)) -#define DMA_REG_READ(softc, reg) \ - bus_space_read_4((softc)->sc_st, (softc)->sc_dma_sh, \ - (reg)) - -#define DMA_CLEAN_MASK (0x2|0x4|0x8|0x20|0x100|0x200) -static int dma_memcpy(void *, void *, int, int); - -static int -i80321_dma_attach(device_t dev) -{ - struct i80321_dma_softc *softc = device_get_softc(dev); - struct i80321_softc *sc = device_get_softc(device_get_parent(dev)); - int unit = device_get_unit(dev); - i80321_dmadesc_t *dmadescs; - - mtx_init(&softc->mtx, "DMA engine mtx", NULL, MTX_SPIN); - softc->sc_st = sc->sc_st; - if (bus_space_subregion(softc->sc_st, sc->sc_sh, unit == 0 ? - VERDE_DMA_BASE0 : VERDE_DMA_BASE1, VERDE_DMA_SIZE, - &softc->sc_dma_sh) != 0) - panic("%s: unable to subregion DMA registers", - device_get_name(dev)); - if (bus_dma_tag_create(NULL, sizeof(i80321_dmadesc_t), - 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, - DMA_RING_SIZE * sizeof(i80321_dmadesc_t), 1, - sizeof(i80321_dmadesc_t), BUS_DMA_ALLOCNOW, busdma_lock_mutex, - &Giant, &softc->dmatag)) - panic("Couldn't create a dma tag"); - DMA_REG_WRITE(softc, 0, 0); - if (bus_dmamem_alloc(softc->dmatag, (void **)&dmadescs, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &softc->dmaring[0].map)) - panic("Couldn't alloc dma memory"); - for (int i = 0; i < DMA_RING_SIZE; i++) { - if (i > 0) - if (bus_dmamap_create(softc->dmatag, 0, - &softc->dmaring[i].map)) - panic("Couldn't alloc dmamap"); - softc->dmaring[i].desc = &dmadescs[i]; - bus_dmamap_load(softc->dmatag, softc->dmaring[i].map, - softc->dmaring[i].desc, sizeof(i80321_dmadesc_t), - i80321_mapphys, &softc->dmaring[i].phys_addr, 0); - } - softc->unit = unit; - softcs[unit] = softc; - _arm_memcpy = dma_memcpy; - _min_memcpy_size = 1024; - return (0); -} - -static __inline int -virt_addr_is_valid(void *addr, int len, int write, int is_kernel) -{ - int to_nextpage; - char tmp = 0; - - while (len > 0) { - if (write) { - if (is_kernel) - *(char *)addr = 0; - else if (subyte(addr, 0) != 0) { - return (0); - } - } else { - if (is_kernel) - badaddr_read(addr, 1, &tmp); - else if (fubyte(addr) == -1) { - return (0); - } - } - to_nextpage = ((vm_offset_t)addr & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)addr; - if (to_nextpage >= len) - break; - len -= to_nextpage; - addr = (void *)((vm_offset_t)addr + to_nextpage); - } - return (1); -} - -static int -dma_memcpy(void *dst, void *src, int len, int flags) -{ - struct i80321_dma_softc *sc; - i80321_dmadesc_t *desc; - int ret; - int csr; - int descnb = 0; - int tmplen = len; - int to_nextpagesrc, to_nextpagedst; - int min_hop; - vm_paddr_t pa, pa2, tmppa; - pmap_t pmap = vmspace_pmap(curthread->td_proc->p_vmspace); - - if (!softcs[0] || !softcs[1]) - return (-1); - mtx_lock_spin(&softcs[0]->mtx); - if (softcs[0]->flags & BUSY) { - mtx_unlock_spin(&softcs[0]->mtx); - mtx_lock_spin(&softcs[1]->mtx); - if (softcs[1]->flags & BUSY) { - mtx_unlock(&softcs[1]->mtx); - return (-1); - } - sc = softcs[1]; - } else - sc = softcs[0]; - sc->flags |= BUSY; - mtx_unlock_spin(&sc->mtx); - desc = sc->dmaring[0].desc; - if (flags & IS_PHYSICAL) { - desc->next_desc = 0; - desc->low_pciaddr = (vm_paddr_t)src; - desc->high_pciaddr = 0; - desc->local_addr = (vm_paddr_t)dst; - desc->count = len; - desc->descr_ctrl = 1 << 6; /* Local memory to local memory. */ - bus_dmamap_sync(sc->dmatag, - sc->dmaring[0].map, - BUS_DMASYNC_PREWRITE); - } else { - if (!virt_addr_is_valid(dst, len, 1, !(flags & DST_IS_USER)) || - !virt_addr_is_valid(src, len, 0, !(flags & SRC_IS_USER))) { - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (-1); - } - cpu_dcache_wb_range((vm_offset_t)src, len); - if ((vm_offset_t)dst & (31)) - cpu_dcache_wb_range((vm_offset_t)dst & ~31, 32); - if (((vm_offset_t)dst + len) & 31) - cpu_dcache_wb_range(((vm_offset_t)dst + len) & ~31, - 32); - cpu_dcache_inv_range((vm_offset_t)dst, len); - while (tmplen > 0) { - pa = (flags & SRC_IS_USER) ? - pmap_extract(pmap, (vm_offset_t)src) : - vtophys(src); - pa2 = (flags & DST_IS_USER) ? - pmap_extract(pmap, (vm_offset_t)dst) : - vtophys(dst); - to_nextpagesrc = ((vm_offset_t)src & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)src; - to_nextpagedst = ((vm_offset_t)dst & ~PAGE_MASK) + - PAGE_SIZE - (vm_offset_t)dst; - while (to_nextpagesrc < tmplen) { - tmppa = (flags & SRC_IS_USER) ? - pmap_extract(pmap, (vm_offset_t)src + - to_nextpagesrc) : - vtophys((vm_offset_t)src + - to_nextpagesrc); - if (tmppa != pa + to_nextpagesrc) - break; - to_nextpagesrc += PAGE_SIZE; - } - while (to_nextpagedst < tmplen) { - tmppa = (flags & DST_IS_USER) ? - pmap_extract(pmap, (vm_offset_t)dst + - to_nextpagedst) : - vtophys((vm_offset_t)dst + - to_nextpagedst); - if (tmppa != pa2 + to_nextpagedst) - break; - to_nextpagedst += PAGE_SIZE; - } - min_hop = to_nextpagedst > to_nextpagesrc ? - to_nextpagesrc : to_nextpagedst; - if (min_hop < 64) { - tmplen -= min_hop; - memcpy(dst, src, min_hop); - cpu_dcache_wbinv_range((vm_offset_t)dst, - min_hop); - - src = (void *)((vm_offset_t)src + min_hop); - dst = (void *)((vm_offset_t)dst + min_hop); - if (tmplen <= 0 && descnb > 0) { - sc->dmaring[descnb - 1].desc->next_desc - = 0; - bus_dmamap_sync(sc->dmatag, - sc->dmaring[descnb - 1].map, - BUS_DMASYNC_PREWRITE); - } - continue; - } - desc->low_pciaddr = pa; - desc->high_pciaddr = 0; - desc->local_addr = pa2; - desc->count = tmplen > min_hop ? min_hop : tmplen; - desc->descr_ctrl = 1 << 6; - if (min_hop < tmplen) { - tmplen -= min_hop; - src = (void *)((vm_offset_t)src + min_hop); - dst = (void *)((vm_offset_t)dst + min_hop); - } else - tmplen = 0; - if (descnb + 1 >= DMA_RING_SIZE) { - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (-1); - } - if (tmplen > 0) { - desc->next_desc = sc->dmaring[descnb + 1]. - phys_addr; - bus_dmamap_sync(sc->dmatag, - sc->dmaring[descnb].map, - BUS_DMASYNC_PREWRITE); - desc = sc->dmaring[descnb + 1].desc; - descnb++; - } else { - desc->next_desc = 0; - bus_dmamap_sync(sc->dmatag, - sc->dmaring[descnb].map, - BUS_DMASYNC_PREWRITE); - } - - } - - } - DMA_REG_WRITE(sc, 4 /* Status register */, - DMA_REG_READ(sc, 4) | DMA_CLEAN_MASK); - DMA_REG_WRITE(sc, 0x10 /* Descriptor addr */, - sc->dmaring[0].phys_addr); - DMA_REG_WRITE(sc, 0 /* Control register */, 1 | 2/* Start transfer */); - while ((csr = DMA_REG_READ(sc, 0x4)) & (1 << 10)); - /* Wait until it's done. */ - if (csr & 0x2e) /* error */ - ret = -1; - else - ret = 0; - DMA_REG_WRITE(sc, 0, 0); - mtx_lock_spin(&sc->mtx); - sc->flags &= ~BUSY; - mtx_unlock_spin(&sc->mtx); - return (ret); -} - -static device_method_t i80321_dma_methods[] = { - DEVMETHOD(device_probe, i80321_dma_probe), - DEVMETHOD(device_attach, i80321_dma_attach), - {0, 0}, -}; - -static driver_t i80321_dma_driver = { - "i80321_dma", - i80321_dma_methods, - sizeof(struct i80321_dma_softc), -}; - -static devclass_t i80321_dma_devclass; - -DRIVER_MODULE(i80321_dma, iq, i80321_dma_driver, i80321_dma_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/i80321_intr.h b/sys/arm/xscale/i80321/i80321_intr.h deleted file mode 100644 index 29003a0..0000000 --- a/sys/arm/xscale/i80321/i80321_intr.h +++ /dev/null @@ -1,165 +0,0 @@ -/* $NetBSD: i80321_intr.h,v 1.5 2004/01/12 10:25:06 scw Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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 _I80321_INTR_H_ -#define _I80321_INTR_H_ - -#define ARM_IRQ_HANDLER _C_LABEL(i80321_intr_dispatch) - -#ifndef _LOCORE - -#include <machine/armreg.h> -#include <machine/cpufunc.h> - -#include <arm/xscale/i80321/i80321reg.h> - -void i80321_do_pending(void); - -extern __volatile uint32_t intr_enabled; -extern uint32_t intr_steer; - -static __inline void __attribute__((__unused__)) -i80321_set_intrmask(void) -{ - - __asm __volatile("mcr p6, 0, %0, c0, c0, 0" - : - : "r" (intr_enabled & ICU_INT_HWMASK)); -} - -static __inline void -i80321_set_intrsteer(void) -{ - - __asm __volatile("mcr p6, 0, %0, c4, c0, 0" - : - : "r" (intr_steer & ICU_INT_HWMASK)); -} - -#if defined ( CPU_XSCALE_80219 ) -#define INT_SWMASK \ - ((1U << ICU_INT_bit26) | \ - (1U << ICU_INT_bit25) | \ - (1U << ICU_INT_bit23) | \ - (1U << ICU_INT_bit22) | \ - (1U << ICU_INT_bit7) | \ - (1U << ICU_INT_bit6) | \ - (1U << ICU_INT_bit5) | \ - (1U << ICU_INT_bit4)) -#else -#define INT_SWMASK \ - ((1U << ICU_INT_bit26) | (1U << ICU_INT_bit22) | \ - (1U << ICU_INT_bit5) | (1U << ICU_INT_bit4)) -#endif - -#if 0 -static __inline void __attribute__((__unused__)) -i80321_splx(int new) -{ - extern __volatile uint32_t intr_enabled; - extern __volatile int current_spl_level; - extern __volatile int i80321_ipending; - extern void i80321_do_pending(void); - int oldirqstate, hwpend; - - /* Don't let the compiler re-order this code with preceding code */ - __insn_barrier(); - - current_spl_level = new; - - hwpend = (i80321_ipending & ICU_INT_HWMASK) & ~new; - if (hwpend != 0) { - oldirqstate = disable_interrupts(PSR_I); - intr_enabled |= hwpend; - i80321_set_intrmask(); - restore_interrupts(oldirqstate); - } - - if ((i80321_ipending & INT_SWMASK) & ~new) - i80321_do_pending(); -} - -static __inline int __attribute__((__unused__)) -i80321_splraise(int ipl) -{ - extern __volatile int current_spl_level; - extern int i80321_imask[]; - int old; - - old = current_spl_level; - current_spl_level |= i80321_imask[ipl]; - - /* Don't let the compiler re-order this code with subsequent code */ - __insn_barrier(); - - return (old); -} - -static __inline int __attribute__((__unused__)) -i80321_spllower(int ipl) -{ - extern __volatile int current_spl_level; - extern int i80321_imask[]; - int old = current_spl_level; - - i80321_splx(i80321_imask[ipl]); - return(old); -} - -#endif -#if !defined(EVBARM_SPL_NOINLINE) - -#define splx(new) i80321_splx(new) -#define _spllower(ipl) i80321_spllower(ipl) -#define _splraise(ipl) i80321_splraise(ipl) -void _setsoftintr(int); - -#else - -int _splraise(int); -int _spllower(int); -void splx(int); -void _setsoftintr(int); - -#endif /* ! EVBARM_SPL_NOINLINE */ - -#endif /* _LOCORE */ - -#endif /* _I80321_INTR_H_ */ diff --git a/sys/arm/xscale/i80321/i80321_mcu.c b/sys/arm/xscale/i80321/i80321_mcu.c deleted file mode 100644 index a51a433..0000000 --- a/sys/arm/xscale/i80321/i80321_mcu.c +++ /dev/null @@ -1,90 +0,0 @@ -/* $NetBSD: i80321_mcu.c,v 1.2 2003/07/15 00:24:54 lukem Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * Intel i80321 I/O Processor memory controller support. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> - -#include <machine/bus.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> - -/* - * i80321_sdram_bounds: - * - * Retrieve the start and size of SDRAM. - */ -void -i80321_sdram_bounds(bus_space_tag_t st, bus_space_handle_t sh, - vm_paddr_t *start, vm_size_t *size) -{ - uint32_t sdbr, sbr0, sbr1; - uint32_t bank0, bank1; - - sdbr = bus_space_read_4(st, sh, MCU_SDBR); - sbr0 = bus_space_read_4(st, sh, MCU_SBR0); - sbr1 = bus_space_read_4(st, sh, MCU_SBR1); - -#ifdef VERBOSE_INIT_ARM - printf("i80321: SBDR = 0x%08x SBR0 = 0x%08x SBR1 = 0x%08x\n", - sdbr, sbr0, sbr1); -#endif - - *start = sdbr; - - sdbr = (sdbr >> 25) & 0x1f; - - sbr0 &= 0x3f; - sbr1 &= 0x3f; - - bank0 = (sbr0 - sdbr) << 25; - bank1 = (sbr1 - sbr0) << 25; - -#ifdef VERBOSE_INIT_ARM - printf("i80321: BANK0 = 0x%08x BANK1 = 0x%08x\n", bank0, bank1); -#endif - - *size = bank0 + bank1; -} diff --git a/sys/arm/xscale/i80321/i80321_pci.c b/sys/arm/xscale/i80321/i80321_pci.c deleted file mode 100644 index 5f78577..0000000 --- a/sys/arm/xscale/i80321/i80321_pci.c +++ /dev/null @@ -1,401 +0,0 @@ -/* $NetBSD: i80321_pci.c,v 1.4 2003/07/15 00:24:54 lukem Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * PCI configuration support for i80321 I/O Processor chip. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/rman.h> - -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/pcb.h> -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_extern.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> -#include <arm/xscale/i80321/i80321_intr.h> - -#include <dev/pci/pcib_private.h> -#include "pcib_if.h" - -#include <dev/pci/pcireg.h> -extern struct i80321_softc *i80321_softc; - -static int -i80321_pci_probe(device_t dev) -{ - device_set_desc(dev, "i80321 PCI bus"); - return (0); -} - -static int -i80321_pci_attach(device_t dev) -{ - - uint32_t busno; - struct i80321_pci_softc *sc = device_get_softc(dev); - - sc->sc_st = i80321_softc->sc_st; - sc->sc_atu_sh = i80321_softc->sc_atu_sh; - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - sc->sc_dev = dev; - sc->sc_busno = busno; - sc->sc_pciio = &i80321_softc->sc_pci_iot; - sc->sc_pcimem = &i80321_softc->sc_pci_memt; - sc->sc_mem = i80321_softc->sc_owin[0].owin_xlate_lo + - VERDE_OUT_XLATE_MEM_WIN_SIZE; - - sc->sc_io = i80321_softc->sc_iow_vaddr; - /* Initialize memory and i/o rmans. */ - sc->sc_io_rman.rm_type = RMAN_ARRAY; - sc->sc_io_rman.rm_descr = "I80321 PCI I/O Ports"; - if (rman_init(&sc->sc_io_rman) != 0 || - rman_manage_region(&sc->sc_io_rman, - sc->sc_io, - sc->sc_io + - VERDE_OUT_XLATE_IO_WIN_SIZE) != 0) { - panic("i80321_pci_probe: failed to set up I/O rman"); - } - sc->sc_mem_rman.rm_type = RMAN_ARRAY; - sc->sc_mem_rman.rm_descr = "I80321 PCI Memory"; - if (rman_init(&sc->sc_mem_rman) != 0 || - rman_manage_region(&sc->sc_mem_rman, - 0, VERDE_OUT_XLATE_MEM_WIN_SIZE) != 0) { - panic("i80321_pci_probe: failed to set up memory rman"); - } - sc->sc_irq_rman.rm_type = RMAN_ARRAY; - sc->sc_irq_rman.rm_descr = "i80321 PCI IRQs"; - if (rman_init(&sc->sc_irq_rman) != 0 || - rman_manage_region(&sc->sc_irq_rman, 26, 32) != 0) - panic("i80321_pci_probe: failed to set up IRQ rman"); - device_add_child(dev, "pci", -1); - return (bus_generic_attach(dev)); -} - -static int -i80321_pci_maxslots(device_t dev) -{ - return (PCI_SLOTMAX); -} - - - -static int -i80321_pci_conf_setup(struct i80321_pci_softc *sc, int bus, int slot, int func, - int reg, uint32_t *addr) -{ - uint32_t busno; - - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - - /* - * If the bus # is the same as our own, then use Type 0 cycles, - * else use Type 1. - * - * XXX We should filter out all non-private devices here! - * XXX How does private space interact with PCI-PCI bridges? - */ - if (bus == busno) { - if (slot > (31 - 16)) - return (1); - /* - * NOTE: PCI-X requires that that devices updated their - * PCIXSR on every config write with the device number - * specified in AD[15:11]. If we don't set this field, - * each device could end of thinking it is at device 0, - * which can cause a number of problems. Doing this - * unconditionally should be OK when only PCI devices - * are present. - */ - bus &= 0xff; - slot &= 0x1f; - func &= 0x07; - - *addr = (1U << (slot + 16)) | - (slot << 11) | (func << 8) | reg; - } else { - *addr = (bus << 16) | (slot << 11) | (func << 8) | reg | 1; - } - - return (0); -} - -static u_int32_t -i80321_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, int bytes) -{ - struct i80321_pci_softc *sc = device_get_softc(dev); - uint32_t isr; - uint32_t addr; - u_int32_t ret = 0; - vm_offset_t va; - int err = 0; - if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) - return (-1); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR, - addr); - - va = sc->sc_atu_sh; - switch (bytes) { - case 1: - err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 1, &ret); - break; - case 2: - err = badaddr_read((void*)(va + ATU_OCCDR + (reg & 3)), 2, &ret); - break; - case 4: - err = badaddr_read((void *)(va + ATU_OCCDR), 4, &ret); - break; - default: - printf("i80321_read_config: invalid size %d\n", bytes); - ret = -1; - } - if (err) { - - isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR); - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR, - isr & (ATUISR_P_SERR_DET|ATUISR_PMA|ATUISR_PTAM| - ATUISR_PTAT|ATUISR_PMPE)); - return (-1); - } - return (ret); -} - -static void -i80321_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, u_int32_t data, int bytes) -{ - struct i80321_pci_softc *sc = device_get_softc(dev); - uint32_t addr; - - if (i80321_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) - return; - - - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR, - addr); - switch (bytes) { - case 1: - bus_space_write_1(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR + - (reg & 3), data); - break; - case 2: - bus_space_write_2(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR + - (reg & 3), data); - break; - case 4: - bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR, data); - break; - default: - printf("i80321_pci_write_config: Invalid size : %d\n", bytes); - } - -} - -static int -i80321_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct i80321_pci_softc *sc = device_get_softc(dev); - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = 0; - return (0); - case PCIB_IVAR_BUS: - *result = sc->sc_busno; - return (0); - - } - return (ENOENT); -} - -static int -i80321_write_ivar(device_t dev, device_t child, int which, uintptr_t result) -{ - struct i80321_pci_softc * sc = device_get_softc(dev); - - switch (which) { - case PCIB_IVAR_DOMAIN: - return (EINVAL); - case PCIB_IVAR_BUS: - sc->sc_busno = result; - return (0); - } - return (ENOENT); -} - -static struct resource * -i80321_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct i80321_pci_softc *sc = device_get_softc(bus); - struct resource *rv; - struct rman *rm; - bus_space_tag_t bt = NULL; - bus_space_handle_t bh = 0; - - switch (type) { - case SYS_RES_IRQ: - rm = &sc->sc_irq_rman; - break; - case SYS_RES_MEMORY: - rm = &sc->sc_mem_rman; - bt = sc->sc_pcimem; - bh = (start >= 0x80000000 && start < 0x84000000) ? 0x80000000 : - sc->sc_mem; - start &= (0x1000000 - 1); - end &= (0x1000000 - 1); - break; - case SYS_RES_IOPORT: - rm = &sc->sc_io_rman; - bt = sc->sc_pciio; - bh = sc->sc_io; - if (start < sc->sc_io) { - start = start - 0x90000000 + sc->sc_io; - end = end - 0x90000000 + sc->sc_io; - } - break; - default: - return (NULL); - } - - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == NULL) - return (NULL); - rman_set_rid(rv, *rid); - if (type != SYS_RES_IRQ) { - if (type == SYS_RES_MEMORY) - bh += (rman_get_start(rv)); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - if (flags & RF_ACTIVE) { - if (bus_activate_resource(child, type, *rid, rv)) { - rman_release_resource(rv); - return (NULL); - } - } - } - return (rv); -} - -static int -i80321_pci_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - u_long p; - int error; - - if (type == SYS_RES_MEMORY) { - error = bus_space_map(rman_get_bustag(r), - rman_get_bushandle(r), rman_get_size(r), 0, &p); - if (error) - return (error); - rman_set_bushandle(r, p); - - } - return (rman_activate_resource(r)); -} - -static int -i80321_pci_setup_intr(device_t dev, device_t child, - struct resource *ires, int flags, driver_filter_t *filt, - driver_intr_t *intr, void *arg, void **cookiep) -{ - return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, - filt, intr, arg, cookiep)); -} - -static int -i80321_pci_teardown_intr(device_t dev, device_t child, struct resource *res, - void *cookie) -{ - return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); -} - -static device_method_t i80321_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, i80321_pci_probe), - DEVMETHOD(device_attach, i80321_pci_attach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_read_ivar, i80321_read_ivar), - DEVMETHOD(bus_write_ivar, i80321_write_ivar), - DEVMETHOD(bus_alloc_resource, i80321_pci_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, i80321_pci_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, i80321_pci_setup_intr), - DEVMETHOD(bus_teardown_intr, i80321_pci_teardown_intr), - - /* pcib interface */ - DEVMETHOD(pcib_maxslots, i80321_pci_maxslots), - DEVMETHOD(pcib_read_config, i80321_pci_read_config), - DEVMETHOD(pcib_write_config, i80321_pci_write_config), - DEVMETHOD(pcib_route_interrupt, machdep_pci_route_interrupt), - - DEVMETHOD_END -}; - -static driver_t i80321_pci_driver = { - "pcib", - i80321_pci_methods, - sizeof(struct i80321_pci_softc), -}; - -static devclass_t i80321_pci_devclass; - -DRIVER_MODULE(ipci, iq, i80321_pci_driver, i80321_pci_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/i80321_space.c b/sys/arm/xscale/i80321/i80321_space.c deleted file mode 100644 index 64c2225..0000000 --- a/sys/arm/xscale/i80321/i80321_space.c +++ /dev/null @@ -1,209 +0,0 @@ -/* $NetBSD: i80321_space.c,v 1.6 2003/10/06 15:43:35 thorpej Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * bus_space functions for i80321 I/O Processor. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> - -#include <machine/pcb.h> - -#include <vm/vm.h> -#include <vm/vm_kern.h> -#include <vm/pmap.h> -#include <vm/vm_page.h> -#include <vm/vm_extern.h> - -#include <machine/bus.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> - -/* Prototypes for all the bus_space structure functions */ -bs_protos(i80321); -bs_protos(i80321_io); -bs_protos(i80321_mem); - -void -i80321_bs_init(bus_space_tag_t bs, void *cookie) -{ - - *bs = *arm_base_bs_tag; - bs->bs_privdata = cookie; -} - -void -i80321_io_bs_init(bus_space_tag_t bs, void *cookie) -{ - - *bs = *arm_base_bs_tag; - bs->bs_privdata = cookie; - - bs->bs_map = i80321_io_bs_map; - bs->bs_unmap = i80321_io_bs_unmap; - bs->bs_alloc = i80321_io_bs_alloc; - bs->bs_free = i80321_io_bs_free; - -} - -void -i80321_mem_bs_init(bus_space_tag_t bs, void *cookie) -{ - - *bs = *arm_base_bs_tag; - bs->bs_privdata = cookie; - - bs->bs_map = i80321_mem_bs_map; - bs->bs_unmap = i80321_mem_bs_unmap; - bs->bs_alloc = i80321_mem_bs_alloc; - bs->bs_free = i80321_mem_bs_free; - -} - -/* *** Routines shared by i80321, PCI IO, and PCI MEM. *** */ - -int -i80321_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, - bus_size_t size, bus_space_handle_t *nbshp) -{ - - *nbshp = bsh + offset; - return (0); -} - -void -i80321_bs_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset, - bus_size_t len, int flags) -{ - - /* Nothing to do. */ -} - -/* *** Routines for PCI IO. *** */ - -extern struct i80321_softc *i80321_softc; -int -i80321_io_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags, - bus_space_handle_t *bshp) -{ - struct i80321_softc *sc = i80321_softc; - vm_offset_t winvaddr; - uint32_t busbase; - - if (bpa >= sc->sc_ioout_xlate && - bpa < (sc->sc_ioout_xlate + VERDE_OUT_XLATE_IO_WIN_SIZE)) { - busbase = sc->sc_ioout_xlate; - winvaddr = sc->sc_iow_vaddr; - } else - return (EINVAL); - - if ((bpa + size) >= (busbase + VERDE_OUT_XLATE_IO_WIN_SIZE)) - return (EINVAL); - - /* - * Found the window -- PCI I/O space is mapped at a fixed - * virtual address by board-specific code. Translate the - * bus address to the virtual address. - */ - *bshp = winvaddr + (bpa - busbase); - - return (0); -} - -void -i80321_io_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size) -{ - - /* Nothing to do. */ -} - -int -i80321_io_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend, - bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, - bus_addr_t *bpap, bus_space_handle_t *bshp) -{ - - panic("i80321_io_bs_alloc(): not implemented"); -} - -void -i80321_io_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size) -{ - - panic("i80321_io_bs_free(): not implemented"); -} - - -/* *** Routines for PCI MEM. *** */ -extern int badaddr_read(void *, int, void *); -int -i80321_mem_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags, - bus_space_handle_t *bshp) -{ - - *bshp = (vm_offset_t)pmap_mapdev(bpa, size); - return (0); -} - -void -i80321_mem_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size) -{ - - pmap_unmapdev((vm_offset_t)h, size); -} - -int -i80321_mem_bs_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend, - bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, - bus_addr_t *bpap, bus_space_handle_t *bshp) -{ - - panic("i80321_mem_bs_alloc(): not implemented"); -} - -void -i80321_mem_bs_free(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size) -{ - - panic("i80321_mem_bs_free(): not implemented"); -} diff --git a/sys/arm/xscale/i80321/iq31244_7seg.c b/sys/arm/xscale/i80321/iq31244_7seg.c deleted file mode 100644 index 3737094..0000000 --- a/sys/arm/xscale/i80321/iq31244_7seg.c +++ /dev/null @@ -1,390 +0,0 @@ -/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */ - -/*- - * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * Support for the 7-segment display on the Intel IQ31244. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/sysctl.h> - -#include <machine/bus.h> - -#include <arm/xscale/i80321/iq80321reg.h> -#include <arm/xscale/i80321/iq80321var.h> - -#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v) - -static int snakestate; - -/* - * The 7-segment display looks like so: - * - * A - * +-----+ - * | | - * F | | B - * | G | - * +-----+ - * | | - * E | | C - * | D | - * +-----+ o DP - * - * Setting a bit clears the corresponding segment on the - * display. - */ -#define SEG_A (1 << 0) -#define SEG_B (1 << 1) -#define SEG_C (1 << 2) -#define SEG_D (1 << 3) -#define SEG_E (1 << 4) -#define SEG_F (1 << 5) -#define SEG_G (1 << 6) -#define SEG_DP (1 << 7) - -static const uint8_t digitmap[] = { -/* +#####+ - * # # - * # # - * # # - * +-----+ - * # # - * # # - * # # - * +#####+ - */ - SEG_G, - -/* +-----+ - * | # - * | # - * | # - * +-----+ - * | # - * | # - * | # - * +-----+ - */ - SEG_A|SEG_D|SEG_E|SEG_F|SEG_G, - -/* +#####+ - * | # - * | # - * | # - * +#####+ - * # | - * # | - * # | - * +#####+ - */ - SEG_C|SEG_F, - -/* +#####+ - * | # - * | # - * | # - * +#####+ - * | # - * | # - * | # - * +#####+ - */ - SEG_E|SEG_F, - -/* +-----+ - * # # - * # # - * # # - * +#####+ - * | # - * | # - * | # - * +-----+ - */ - SEG_A|SEG_D|SEG_E, - -/* +#####+ - * # | - * # | - * # | - * +#####+ - * | # - * | # - * | # - * +#####+ - */ - SEG_B|SEG_E, - -/* +#####+ - * # | - * # | - * # | - * +#####+ - * # # - * # # - * # # - * +#####+ - */ - SEG_B, - -/* +#####+ - * | # - * | # - * | # - * +-----+ - * | # - * | # - * | # - * +-----+ - */ - SEG_D|SEG_E|SEG_F, - -/* +#####+ - * # # - * # # - * # # - * +#####+ - * # # - * # # - * # # - * +#####+ - */ - 0, - -/* +#####+ - * # # - * # # - * # # - * +#####+ - * | # - * | # - * | # - * +-----+ - */ - SEG_D|SEG_E, -}; - -static uint8_t -iq80321_7seg_xlate(char c) -{ - uint8_t rv; - - if (c >= '0' && c <= '9') - rv = digitmap[c - '0']; - else if (c == '.') - rv = (uint8_t) ~SEG_DP; - else - rv = 0xff; - - return (rv); -} - -void -iq80321_7seg(char a, char b) -{ - uint8_t msb, lsb; - - msb = iq80321_7seg_xlate(a); - lsb = iq80321_7seg_xlate(b); - - snakestate = 0; - - WRITE(IQ80321_7SEG_MSB, msb); - WRITE(IQ80321_7SEG_LSB, lsb); -} - -static const uint8_t snakemap[][2] = { - -/* +#####+ +#####+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_A, ~SEG_A }, - -/* +-----+ +-----+ - * # | | # - * # | | # - * # | | # - * +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_F, ~SEG_B }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +#####+ +#####+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_G, ~SEG_G }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - * | # # | - * | # # | - * | # # | - * +-----+ +-----+ - */ - { ~SEG_C, ~SEG_E }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +#####+ +#####+ - */ - { ~SEG_D, ~SEG_D }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - * # | | # - * # | | # - * # | | # - * +-----+ +-----+ - */ - { ~SEG_E, ~SEG_C }, - -/* +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +#####+ +#####+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_G, ~SEG_G }, - -/* +-----+ +-----+ - * | # # | - * | # # | - * | # # | - * +-----+ +-----+ - * | | | | - * | | | | - * | | | | - * +-----+ +-----+ - */ - { ~SEG_B, ~SEG_F }, -}; - -static SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg"); -static int freq = 20; -SYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0, - "7 Seg update frequency"); -static void -iq31244_7seg_snake(void) -{ - static int snakefreq; - int cur = snakestate; - - snakefreq++; - if ((snakefreq % freq)) - return; - WRITE(IQ80321_7SEG_MSB, snakemap[cur][0]); - WRITE(IQ80321_7SEG_LSB, snakemap[cur][1]); - - snakestate = (cur + 1) & 7; -} - -struct iq31244_7seg_softc { - device_t dev; -}; - -static int -iq31244_7seg_probe(device_t dev) -{ - - device_set_desc(dev, "IQ31244 7seg"); - return (0); -} - -extern void (*i80321_hardclock_hook)(void); -static int -iq31244_7seg_attach(device_t dev) -{ - - i80321_hardclock_hook = iq31244_7seg_snake; - return (0); -} - -static device_method_t iq31244_7seg_methods[] = { - DEVMETHOD(device_probe, iq31244_7seg_probe), - DEVMETHOD(device_attach, iq31244_7seg_attach), - {0, 0}, -}; - -static driver_t iq31244_7seg_driver = { - "iqseg", - iq31244_7seg_methods, - sizeof(struct iq31244_7seg_softc), -}; -static devclass_t iq31244_7seg_devclass; - -DRIVER_MODULE(iqseg, iq, iq31244_7seg_driver, iq31244_7seg_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/iq31244_machdep.c b/sys/arm/xscale/i80321/iq31244_machdep.c deleted file mode 100644 index eb19f78..0000000 --- a/sys/arm/xscale/i80321/iq31244_machdep.c +++ /dev/null @@ -1,416 +0,0 @@ -/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */ - -/*- - * Copyright (c) 1994-1998 Mark Brinicombe. - * Copyright (c) 1994 Brini. - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Brini. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. - * - * RiscBSD kernel project - * - * machdep.c - * - * Machine dependant functions for kernel setup - * - * This file needs a lot of work. - * - * Created : 17/09/94 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_kstack_pages.h" - -#define _ARM32_BUS_DMA_PRIVATE -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sysproto.h> -#include <sys/signalvar.h> -#include <sys/imgact.h> -#include <sys/kernel.h> -#include <sys/ktr.h> -#include <sys/linker.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/pcpu.h> -#include <sys/proc.h> -#include <sys/ptrace.h> -#include <sys/cons.h> -#include <sys/bio.h> -#include <sys/bus.h> -#include <sys/buf.h> -#include <sys/exec.h> -#include <sys/kdb.h> -#include <sys/msgbuf.h> -#include <machine/reg.h> -#include <machine/cpu.h> -#include <machine/physmem.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_object.h> -#include <vm/vm_page.h> -#include <vm/vm_map.h> -#include <machine/devmap.h> -#include <machine/vmparam.h> -#include <machine/pcb.h> -#include <machine/undefined.h> -#include <machine/machdep.h> -#include <machine/metadata.h> -#include <machine/armreg.h> -#include <machine/bus.h> -#include <sys/reboot.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> -#include <arm/xscale/i80321/iq80321reg.h> -#include <arm/xscale/i80321/obiovar.h> - -#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ -#define KERNEL_PT_IOPXS 1 -#define KERNEL_PT_BEFOREKERN 2 -#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */ -#define KERNEL_PT_AFKERNEL_NUM 9 - -/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ -#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) - -struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; - -/* Physical and virtual addresses for some global pages */ - -struct pv_addr systempage; -struct pv_addr msgbufpv; -struct pv_addr irqstack; -struct pv_addr undstack; -struct pv_addr abtstack; -struct pv_addr kernelstack; -struct pv_addr minidataclean; - -#define IQ80321_OBIO_BASE 0xfe800000UL -#define IQ80321_OBIO_SIZE 0x00100000UL -/* Static device mappings. */ -static const struct arm_devmap_entry iq80321_devmap[] = { - /* - * Map the on-board devices VA == PA so that we can access them - * with the MMU on or off. - */ - { - IQ80321_OBIO_BASE, - IQ80321_OBIO_BASE, - IQ80321_OBIO_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - IQ80321_IOW_VBASE, - VERDE_OUT_XLATE_IO_WIN0_BASE, - VERDE_OUT_XLATE_IO_WIN_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - - { - IQ80321_80321_VBASE, - VERDE_PMMR_BASE, - VERDE_PMMR_SIZE, - VM_PROT_READ|VM_PROT_WRITE, - PTE_DEVICE, - }, - { - 0, - 0, - 0, - 0, - 0, - } -}; - -#define SDRAM_START 0xa0000000 - -extern vm_offset_t xscale_cache_clean_addr; - -void * -initarm(struct arm_boot_params *abp) -{ - struct pv_addr kernel_l1pt; - struct pv_addr dpcpu; - int loop, i; - u_int l1pagetable; - vm_offset_t freemempos; - vm_offset_t freemem_pt; - vm_offset_t afterkern; - vm_offset_t freemem_after; - vm_offset_t lastaddr; - uint32_t memsize, memstart; - - lastaddr = parse_boot_param(abp); - arm_physmem_kernaddr = abp->abp_physaddr; - set_cpufuncs(); - pcpu_init(pcpup, 0, sizeof(struct pcpu)); - PCPU_SET(curthread, &thread0); - - /* Do basic tuning, hz etc */ - init_param1(); - - freemempos = 0xa0200000; - /* Define a macro to simplify memory allocation */ -#define valloc_pages(var, np) \ - alloc_pages((var).pv_pa, (np)); \ - (var).pv_va = (var).pv_pa + 0x20000000; - -#define alloc_pages(var, np) \ - freemempos -= (np * PAGE_SIZE); \ - (var) = freemempos; \ - memset((char *)(var), 0, ((np) * PAGE_SIZE)); - - while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) - freemempos -= PAGE_SIZE; - valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); - for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { - if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { - valloc_pages(kernel_pt_table[loop], - L2_TABLE_SIZE / PAGE_SIZE); - } else { - kernel_pt_table[loop].pv_pa = freemempos + - (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * - L2_TABLE_SIZE_REAL; - kernel_pt_table[loop].pv_va = - kernel_pt_table[loop].pv_pa + 0x20000000; - } - } - freemem_pt = freemempos; - freemempos = 0xa0100000; - /* - * Allocate a page for the system page mapped to V0x00000000 - * This page will just contain the system vectors and can be - * shared by all processes. - */ - valloc_pages(systempage, 1); - - /* Allocate dynamic per-cpu area. */ - valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); - dpcpu_init((void *)dpcpu.pv_va, 0); - - /* Allocate stacks for all modes */ - valloc_pages(irqstack, IRQ_STACK_SIZE); - valloc_pages(abtstack, ABT_STACK_SIZE); - valloc_pages(undstack, UND_STACK_SIZE); - valloc_pages(kernelstack, kstack_pages); - alloc_pages(minidataclean.pv_pa, 1); - valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); - /* - * Allocate memory for the l1 and l2 page tables. The scheme to avoid - * wasting memory by allocating the l1pt on the first 16k memory was - * taken from NetBSD rpc_machdep.c. NKPT should be greater than 12 for - * this to work (which is supposed to be the case). - */ - - /* - * Now we start construction of the L1 page table - * We start by mapping the L2 page tables into the L1. - * This means that we can replace L1 mappings later on if necessary - */ - l1pagetable = kernel_l1pt.pv_va; - - /* Map the L2 pages tables in the L1 page table */ - pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1), - &kernel_pt_table[KERNEL_PT_SYS]); - pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE, - &kernel_pt_table[KERNEL_PT_IOPXS]); - pmap_link_l2pt(l1pagetable, KERNBASE, - &kernel_pt_table[KERNEL_PT_BEFOREKERN]); - pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000, - 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); - pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000, - (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1), - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1); - afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE - - 1)); - for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { - pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000, - &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); - } - pmap_map_entry(l1pagetable, afterkern, minidataclean.pv_pa, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - - - /* Map the Mini-Data cache clean area. */ - xscale_setup_minidata(l1pagetable, afterkern, - minidataclean.pv_pa); - - /* Map the vector page. */ - pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, - VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - arm_devmap_bootstrap(l1pagetable, iq80321_devmap); - /* - * Give the XScale global cache clean code an appropriately - * sized chunk of unmapped VA space starting at 0xff000000 - * (our device mappings end before this address). - */ - xscale_cache_clean_addr = 0xff000000U; - - cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); - cpu_tlb_flushID(); - cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); - /* - * Pages were allocated during the secondary bootstrap for the - * stacks for different CPU modes. - * We must now set the r13 registers in the different CPU modes to - * point to these stacks. - * Since the ARM stacks use STMFD etc. we must set r13 to the top end - * of the stack memory. - */ - set_stackptrs(0); - - /* - * We must now clean the cache again.... - * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() - * but since we are boot strapping the addresses used for the read - * may have just been remapped and thus the cache could be out - * of sync. A re-clean after the switch will cure this. - * After booting there are no gross relocations of the kernel thus - * this problem will not occur after initarm(). - */ - cpu_idcache_wbinv_all(); - cpu_setup(); - - /* - * Fetch the SDRAM start/size from the i80321 SDRAM configration - * registers. - */ - i80321_calibrate_delay(); - i80321_sdram_bounds(obio_bs_tag, IQ80321_80321_VBASE + VERDE_MCU_BASE, - &memstart, &memsize); - physmem = memsize / PAGE_SIZE; - cninit(); - - undefined_init(); - - init_proc0(kernelstack.pv_va); - - /* Enable MMU, I-cache, D-cache, write buffer. */ - - arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); - pmap_curmaxkvaddr = afterkern + PAGE_SIZE; - vm_max_kernel_address = 0xe0000000; - pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); - msgbufp = (void*)msgbufpv.pv_va; - msgbufinit(msgbufp, msgbufsize); - mutex_init(); - - /* - * Add the physical ram we have available. - * - * Exclude the kernel (and all the things we allocated which immediately - * follow the kernel) from the VM allocation pool but not from crash - * dumps. virtual_avail is a global variable which tracks the kva we've - * "allocated" while setting up pmaps. - * - * Prepare the list of physical memory available to the vm subsystem. - */ - arm_physmem_hardware_region(SDRAM_START, memsize); - arm_physmem_exclude_region(freemem_pt, abp->abp_physaddr - - freemem_pt, EXFLAG_NOALLOC); - arm_physmem_exclude_region(freemempos, abp->abp_physaddr - 0x100000 - - freemempos, EXFLAG_NOALLOC); - arm_physmem_exclude_region(abp->abp_physaddr, - virtual_avail - KERNVIRTADDR, EXFLAG_NOALLOC); - arm_physmem_init_kernel_globals(); - - init_param2(physmem); - kdb_init(); - return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - - sizeof(struct pcb))); -} - -extern int -machdep_pci_route_interrupt(device_t pcib, device_t dev, int pin) -{ - int bus; - int device; - int func; - uint32_t busno; - struct i80321_pci_softc *sc = device_get_softc(pcib); - bus = pci_get_bus(dev); - device = pci_get_slot(dev); - func = pci_get_function(dev); - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - if (bus != busno) - goto no_mapping; - switch (device) { - /* IQ31244 PCI */ - case 1: /* PCIX-PCIX bridge */ - /* - * The S-ATA chips are behind the bridge, and all of - * the S-ATA interrupts are wired together. - */ - return (ICU_INT_XINT(2)); - case 2: /* PCI slot */ - /* All pins are wired together. */ - return (ICU_INT_XINT(3)); - case 3: /* i82546 dual Gig-E */ - if (pin == 1 || pin == 2) - return (ICU_INT_XINT(0)); - goto no_mapping; - /* IQ80321 PCI */ - case 4: /* i82544 Gig-E */ - case 8: /* - * Apparently you can set the device for the ethernet adapter - * to 8 with a jumper, so handle that as well - */ - if (pin == 1) - return (ICU_INT_XINT(0)); - goto no_mapping; - case 6: /* S-PCI-X slot */ - if (pin == 1) - return (ICU_INT_XINT(2)); - if (pin == 2) - return (ICU_INT_XINT(3)); - goto no_mapping; - default: -no_mapping: - printf("No mapping for %d/%d/%d/%c\n", bus, device, func, pin); - - } - return (0); - -} diff --git a/sys/arm/xscale/i80321/iq80321.c b/sys/arm/xscale/i80321/iq80321.c deleted file mode 100644 index fb34455..0000000 --- a/sys/arm/xscale/i80321/iq80321.c +++ /dev/null @@ -1,394 +0,0 @@ -/* $NetBSD: i80321_mainbus.c,v 1.13 2003/12/17 22:03:24 abs Exp $ */ - -/*- - * Copyright (c) 2001, 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * IQ80321 front-end for the i80321 I/O Processor. We take care - * of setting up the i80321 memory map, PCI interrupt routing, etc., - * which are all specific to the board the i80321 is wired up to. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define _ARM32_BUS_DMA_PRIVATE -#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 <machine/armreg.h> -#include <machine/bus.h> -#include <machine/intr.h> - -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> -#include <arm/xscale/i80321/iq80321reg.h> -#include <arm/xscale/i80321/iq80321var.h> -#include <arm/xscale/i80321/i80321_intr.h> - -#include <dev/pci/pcireg.h> - - -int iq80321_probe(device_t); -void iq80321_identify(driver_t *, device_t); -int iq80321_attach(device_t); - -int -iq80321_probe(device_t dev) -{ - device_set_desc(dev, "Intel 80321"); - return (BUS_PROBE_NOWILDCARD); -} - -void -iq80321_identify(driver_t *driver, device_t parent) -{ - - BUS_ADD_CHILD(parent, 0, "iq", 0); -} - -static struct arm32_dma_range i80321_dr; -static int dma_range_init = 0; - -struct arm32_dma_range * -bus_dma_get_range(void) -{ - if (dma_range_init == 0) - return (NULL); - return (&i80321_dr); -} - -int -bus_dma_get_range_nb(void) -{ - if (dma_range_init == 0) - return (0); - return (1); -} - -#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008 -#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004 - -int -iq80321_attach(device_t dev) -{ - struct i80321_softc *sc = device_get_softc(dev); - int b0u, b0l, b1u, b1l; - vm_paddr_t memstart = 0; - vm_size_t memsize = 0; - int busno; - - /* - * Fill in the space tag for the i80321's own devices, - * and hand-craft the space handle for it (the device - * was mapped during early bootstrap). - */ - i80321_bs_init(&i80321_bs_tag, sc); - sc->sc_st = &i80321_bs_tag; - sc->sc_sh = IQ80321_80321_VBASE; - sc->dev = dev; - sc->sc_is_host = 1; - - /* - * Slice off a subregion for the Memory Controller -- we need it - * here in order read the memory size. - */ - if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE, - VERDE_MCU_SIZE, &sc->sc_mcu_sh)) - panic("%s: unable to subregion MCU registers", - device_get_name(dev)); - - if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE, - VERDE_ATU_SIZE, &sc->sc_atu_sh)) - panic("%s: unable to subregion ATU registers", - device_get_name(dev)); - - /* - * We have mapped the PCI I/O windows in the early - * bootstrap phase. - */ - sc->sc_iow_vaddr = IQ80321_IOW_VBASE; - - /* - * Check the configuration of the ATU to see if another BIOS - * has configured us. If a PC BIOS didn't configure us, then: - * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c. - * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c. - * If a BIOS has configured us, at least one of those should be - * different. This is pretty fragile, but it's not clear what - * would work better. - */ - b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0); - b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4); - b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8); - b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc); - -#ifdef VERBOSE_INIT_ARM - printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n", - b0l,b0u, b1l, b1u ); -#endif - -#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0 - b0l &= PCI_MAPREG_MEM_ADDR_MASK; - b0u &= PCI_MAPREG_MEM_ADDR_MASK; - b1l &= PCI_MAPREG_MEM_ADDR_MASK; - b1u &= PCI_MAPREG_MEM_ADDR_MASK; - -#ifdef VERBOSE_INIT_ARM - printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n", - b0l,b0u, b1l, b1u ); -#endif - - if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0)) - sc->sc_is_host = 0; - else - sc->sc_is_host = 1; - - /* FIXME: i force it's */ - -#ifdef CPU_XSCALE_80219 - sc->sc_is_host = 1; -#endif - - i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize); - /* - * We set up the Inbound Windows as follows: - * - * 0 Access to i80321 PMMRs - * - * 1 Reserve space for private devices - * - * 2 RAM access - * - * 3 Unused. - * - * This chunk needs to be customized for each IOP321 application. - */ -#if 0 - sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE; - sc->sc_iwin[0].iwin_base_hi = 0; - sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE; - sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE; -#endif - if (sc->sc_is_host) { - - /* Map PCI:Local 1:1. */ - sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE | - PCI_MAPREG_MEM_PREFETCHABLE_MASK | - PCI_MAPREG_MEM_TYPE_64BIT; - sc->sc_iwin[1].iwin_base_hi = 0; - } else { - - sc->sc_iwin[1].iwin_base_lo = 0; - sc->sc_iwin[1].iwin_base_hi = 0; - } - sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE; - sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE; - - if (sc->sc_is_host) { - sc->sc_iwin[2].iwin_base_lo = memstart | - PCI_MAPREG_MEM_PREFETCHABLE_MASK | - PCI_MAPREG_MEM_TYPE_64BIT; - sc->sc_iwin[2].iwin_base_hi = 0; - } else { - sc->sc_iwin[2].iwin_base_lo = 0; - sc->sc_iwin[2].iwin_base_hi = 0; - } - sc->sc_iwin[2].iwin_xlate = memstart; - sc->sc_iwin[2].iwin_size = memsize; - - if (sc->sc_is_host) { - sc->sc_iwin[3].iwin_base_lo = 0 | - PCI_MAPREG_MEM_PREFETCHABLE_MASK | - PCI_MAPREG_MEM_TYPE_64BIT; - } else { - sc->sc_iwin[3].iwin_base_lo = 0; - } - sc->sc_iwin[3].iwin_base_hi = 0; - sc->sc_iwin[3].iwin_xlate = 0; - sc->sc_iwin[3].iwin_size = 0; - -#ifdef VERBOSE_INIT_ARM - printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n", - sc->sc_iwin[1].iwin_base_hi, - sc->sc_iwin[1].iwin_base_lo, - sc->sc_iwin[1].iwin_xlate, - sc->sc_iwin[1].iwin_size - ); - printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n", - sc->sc_iwin[2].iwin_base_hi, - sc->sc_iwin[2].iwin_base_lo, - sc->sc_iwin[2].iwin_xlate, - sc->sc_iwin[2].iwin_size - ); -#endif - - /* - * We set up the Outbound Windows as follows: - * - * 0 Access to private PCI space. - * - * 1 Unused. - */ -#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0) - sc->sc_owin[0].owin_xlate_lo = - PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo); - sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi; - /* - * Set the Secondary Outbound I/O window to map - * to PCI address 0 for all 64K of the I/O space. - */ - sc->sc_ioout_xlate = 0; - i80321_attach(sc); - i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate; - i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); - i80321_dr.dr_len = sc->sc_iwin[2].iwin_size; - dma_range_init = 1; - busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); - busno = PCIXSR_BUSNO(busno); - if (busno == 0xff) - busno = 0; - sc->sc_irq_rman.rm_type = RMAN_ARRAY; - sc->sc_irq_rman.rm_descr = "i80321 IRQs"; - if (rman_init(&sc->sc_irq_rman) != 0 || - rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0) - panic("i80321_attach: failed to set up IRQ rman"); - - device_add_child(dev, "obio", 0); - device_add_child(dev, "itimer", 0); - device_add_child(dev, "iopwdog", 0); -#ifndef CPU_XSCALE_80219 - device_add_child(dev, "iqseg", 0); -#endif - device_add_child(dev, "pcib", busno); - device_add_child(dev, "i80321_dma", 0); - device_add_child(dev, "i80321_dma", 1); -#ifndef CPU_XSCALE_80219 - device_add_child(dev, "i80321_aau", 0); -#endif - bus_generic_probe(dev); - bus_generic_attach(dev); - - return (0); -} - -void -arm_mask_irq(uintptr_t nb) -{ - intr_enabled &= ~(1 << nb); - i80321_set_intrmask(); -} - -void -arm_unmask_irq(uintptr_t nb) -{ - intr_enabled |= (1 << nb); - i80321_set_intrmask(); -} - - -void -cpu_reset() -{ - (void) disable_interrupts(PSR_I|PSR_F); - *(__volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE + - ATU_PCSR) = PCSR_RIB | PCSR_RPB; - printf("Reset failed!\n"); - for(;;); -} - -static struct resource * -iq80321_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct i80321_softc *sc = device_get_softc(dev); - struct resource *rv; - - if (type == SYS_RES_IRQ) { - rv = rman_reserve_resource(&sc->sc_irq_rman, - start, end, count, flags, child); - if (rv != NULL) - rman_set_rid(rv, *rid); - return (rv); - } - return (NULL); -} - -static int -iq80321_setup_intr(device_t dev, device_t child, - struct resource *ires, int flags, driver_filter_t *filt, - driver_intr_t *intr, void *arg, void **cookiep) -{ - int error; - - error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, - filt, intr, arg, cookiep); - if (error) - return (error); - intr_enabled |= 1 << rman_get_start(ires); - i80321_set_intrmask(); - - return (0); -} - -static int -iq80321_teardown_intr(device_t dev, device_t child, struct resource *res, - void *cookie) -{ - return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); -} - -static device_method_t iq80321_methods[] = { - DEVMETHOD(device_probe, iq80321_probe), - DEVMETHOD(device_attach, iq80321_attach), - DEVMETHOD(device_identify, iq80321_identify), - DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource), - DEVMETHOD(bus_setup_intr, iq80321_setup_intr), - DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr), - {0, 0}, -}; - -static driver_t iq80321_driver = { - "iq", - iq80321_methods, - sizeof(struct i80321_softc), -}; -static devclass_t iq80321_devclass; - -DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/iq80321reg.h b/sys/arm/xscale/i80321/iq80321reg.h deleted file mode 100644 index d887fcd..0000000 --- a/sys/arm/xscale/i80321/iq80321reg.h +++ /dev/null @@ -1,111 +0,0 @@ -/* $NetBSD: iq80321reg.h,v 1.4 2003/05/14 19:46:39 thorpej Exp $ */ - -/*- - * Copyright (c) 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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 _IQ80321REG_H_ -#define _IQ80321REG_H_ - -/* - * Memory map and register definitions for the Intel IQ80321 - * Evaluation Board. - */ - -/* - * The memory map of the IQ80321 looks like so: - * - * ------------------------------ - * Intel 80321 IOP Reserved - * FFFF E900 ------------------------------ - * Peripheral Memory Mapped - * Registers - * FFFF E000 ------------------------------ - * On-board devices - * FE80 0000 ------------------------------ - * SDRAM - * A000 0000 ------------------------------ - * Reserved - * 9100 0000 ------------------------------ - * Flash - * 9080 0000 ------------------------------ - * Reserved - * 9002 0000 ------------------------------ - * ATU Outbound Transaction - * Windows - * 8000 0000 ------------------------------ - * ATU Outbound Direct - * Addressing Windows - * 0000 1000 ------------------------------ - * Initialization Boot Code - * from Flash - * 0000 0000 ------------------------------ - */ - -/* - * We allocate a page table for VA 0xfe400000 (4MB) and map the - * PCI I/O space (64K) and i80321 memory-mapped registers (4K) there. - */ -#define IQ80321_IOPXS_VBASE 0xfe400000UL -#define IQ80321_IOW_VBASE IQ80321_IOPXS_VBASE -#define IQ80321_80321_VBASE (IQ80321_IOW_VBASE + \ - VERDE_OUT_XLATE_IO_WIN_SIZE) - -#define IQ80321_SDRAM_START 0xa0000000 -/* - * The IQ80321 on-board devices are mapped VA==PA during bootstrap. - * Conveniently, the size of the on-board register space is 1 section - * mapping. - */ -#define IQ80321_OBIO_BASE 0xfe800000UL -#define IQ80321_OBIO_SIZE 0x00100000UL /* 1MB */ - -#define IQ80321_UART1 0xfe800000UL /* TI 16550 */ - -#if defined( CPU_XSCALE_80321 ) -#define IQ80321_7SEG_MSB 0xfe840000UL -#define IQ80321_7SEG_LSB 0xfe850000UL - -#define IQ80321_ROT_SWITCH 0xfe8d0000UL - -#define IQ80321_BATTERY_STAT 0xfe8f0000UL -#define BATTERY_STAT_PRES (1U << 0) -#define BATTERY_STAT_CHRG (1U << 1) -#define BATTERY_STAT_DISCHRG (1U << 2) -#endif /* CPU_XSCALE_80321 */ - -#endif /* _IQ80321REG_H_ */ diff --git a/sys/arm/xscale/i80321/iq80321var.h b/sys/arm/xscale/i80321/iq80321var.h deleted file mode 100644 index 4a03500..0000000 --- a/sys/arm/xscale/i80321/iq80321var.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $NetBSD: iq80321var.h,v 1.1 2002/03/27 21:51:30 thorpej Exp $ */ - -/*- - * Copyright (c) 2002 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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 _IQ80321_IQ80321VAR_H_ -#define _IQ80321_IQ80321VAR_H_ - -#include <dev/pci/pcivar.h> - -void iq80321_7seg(char, char); -void iq80321_7seg_snake(void); - -#if 0 -void iq80321_pci_init(pci_chipset_tag_t, void *); -#endif - -#endif /* _IQ80321_IQ80321VAR_H_ */ diff --git a/sys/arm/xscale/i80321/obio.c b/sys/arm/xscale/i80321/obio.c deleted file mode 100644 index 55218cc..0000000 --- a/sys/arm/xscale/i80321/obio.c +++ /dev/null @@ -1,163 +0,0 @@ -/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */ - -/*- - * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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. - */ - -/* - * On-board device autoconfiguration support for Intel IQ80321 - * evaluation boards. - */ - -#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/rman.h> -#include <sys/malloc.h> - -#include <machine/bus.h> - -#include <arm/xscale/i80321/i80321reg.h> - -#include <arm/xscale/i80321/iq80321reg.h> -#include <arm/xscale/i80321/obiovar.h> - -bus_space_tag_t obio_bs_tag; - -int obio_probe(device_t); -int obio_attach(device_t); - -int -obio_probe(device_t dev) -{ - return (0); -} - -int -obio_attach(device_t dev) -{ - struct obio_softc *sc = device_get_softc(dev); - - obio_bs_tag = arm_base_bs_tag; - sc->oba_st = obio_bs_tag; - sc->oba_addr = IQ80321_OBIO_BASE; - sc->oba_size = IQ80321_OBIO_SIZE; - sc->oba_rman.rm_type = RMAN_ARRAY; - sc->oba_rman.rm_descr = "OBIO I/O"; - if (rman_init(&sc->oba_rman) != 0 || - rman_manage_region(&sc->oba_rman, - sc->oba_addr, sc->oba_addr + sc->oba_size) != 0) - panic("obio_attach: failed to set up I/O rman"); - sc->oba_irq_rman.rm_type = RMAN_ARRAY; - sc->oba_irq_rman.rm_descr = "OBIO IRQ"; - if (rman_init(&sc->oba_irq_rman) != 0 || - rman_manage_region(&sc->oba_irq_rman, 28, 28) != 0) - panic("obio_attach: failed to set up IRQ rman"); - device_add_child(dev, "uart", 0); - bus_generic_probe(dev); - bus_generic_attach(dev); - return (0); -} - -static struct resource * -obio_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct resource *rv; - struct rman *rm; - bus_space_tag_t bt = NULL; - bus_space_handle_t bh = 0; - struct obio_softc *sc = device_get_softc(bus); - - switch (type) { - case SYS_RES_IRQ: - rm = &sc->oba_irq_rman; - break; - case SYS_RES_MEMORY: - return (NULL); - case SYS_RES_IOPORT: - rm = &sc->oba_rman; - bt = sc->oba_st; - bh = sc->oba_addr; - start = bh; - break; - default: - return (NULL); - } - - - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == NULL) - return (NULL); - if (type == SYS_RES_IRQ) - return (rv); - rman_set_rid(rv, *rid); - rman_set_bustag(rv, bt); - rman_set_bushandle(rv, bh); - - return (rv); - -} - -static int -obio_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *r) -{ - return (0); -} -static device_method_t obio_methods[] = { - DEVMETHOD(device_probe, obio_probe), - DEVMETHOD(device_attach, obio_attach), - - DEVMETHOD(bus_alloc_resource, obio_alloc_resource), - DEVMETHOD(bus_activate_resource, obio_activate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - {0, 0}, -}; - -static driver_t obio_driver = { - "obio", - obio_methods, - sizeof(struct obio_softc), -}; -static devclass_t obio_devclass; - -DRIVER_MODULE(obio, iq, obio_driver, obio_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/obiovar.h b/sys/arm/xscale/i80321/obiovar.h deleted file mode 100644 index 182b52f..0000000 --- a/sys/arm/xscale/i80321/obiovar.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */ - -/*- - * Copyright (c) 2002, 2003 Wasabi Systems, Inc. - * All rights reserved. - * - * Written by Jason R. Thorpe for Wasabi Systems, 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project by - * Wasabi Systems, Inc. - * 4. The name of Wasabi Systems, Inc. may not be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, 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 WASABI SYSTEMS, INC - * 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 _IQ80321_OBIOVAR_H_ -#define _IQ80321_OBIOVAR_H_ - -#include <sys/rman.h> - -struct obio_softc { - bus_space_tag_t oba_st; /* bus space tag */ - bus_addr_t oba_addr; /* address of device */ - bus_size_t oba_size; /* size of device */ - int oba_width; /* bus width */ - int oba_irq; /* XINT interrupt bit # */ - struct rman oba_rman; - struct rman oba_irq_rman; - -}; -extern bus_space_tag_t obio_bs_tag; - -#endif /* _IQ80321_OBIOVAR_H_ */ diff --git a/sys/arm/xscale/i80321/std.ep80219 b/sys/arm/xscale/i80321/std.ep80219 deleted file mode 100644 index 9f5cbb7..0000000 --- a/sys/arm/xscale/i80321/std.ep80219 +++ /dev/null @@ -1,7 +0,0 @@ -#EP80219 board configuration -#$FreeBSD$ -include "../xscale/i80321/std.i80219" -files "../xscale/i80321/files.ep80219" -makeoptions KERNPHYSADDR=0xa0200000 -makeoptions KERNVIRTADDR=0xc0200000 -options COUNTS_PER_SEC=198000000 diff --git a/sys/arm/xscale/i80321/std.i80219 b/sys/arm/xscale/i80321/std.i80219 deleted file mode 100644 index 7cc8f37..0000000 --- a/sys/arm/xscale/i80321/std.i80219 +++ /dev/null @@ -1,5 +0,0 @@ -#XScale i80219 generic configuration -#$FreeBSD$ -files "../xscale/i80321/files.i80219" -include "../xscale/std.xscale-be" -cpu CPU_XSCALE_80219 diff --git a/sys/arm/xscale/i80321/std.i80321 b/sys/arm/xscale/i80321/std.i80321 deleted file mode 100644 index 8142bdf..0000000 --- a/sys/arm/xscale/i80321/std.i80321 +++ /dev/null @@ -1,5 +0,0 @@ -#XScale i80321 generic configuration -#$FreeBSD$ -files "../xscale/i80321/files.i80321" -include "../xscale/std.xscale-be" -cpu CPU_XSCALE_80321 diff --git a/sys/arm/xscale/i80321/std.iq31244 b/sys/arm/xscale/i80321/std.iq31244 deleted file mode 100644 index c4c23bf..0000000 --- a/sys/arm/xscale/i80321/std.iq31244 +++ /dev/null @@ -1,7 +0,0 @@ -#IQ31244 board configuration -#$FreeBSD$ -include "../xscale/i80321/std.i80321" -files "../xscale/i80321/files.iq31244" -makeoptions KERNPHYSADDR=0xa0200000 -makeoptions KERNVIRTADDR=0xc0200000 -options COUNTS_PER_SEC=198000000 diff --git a/sys/arm/xscale/i80321/uart_bus_i80321.c b/sys/arm/xscale/i80321/uart_bus_i80321.c deleted file mode 100644 index 5bb903d..0000000 --- a/sys/arm/xscale/i80321/uart_bus_i80321.c +++ /dev/null @@ -1,76 +0,0 @@ -/*- - * Copyright (c) 2004 Olivier Houchard. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <machine/resource.h> - -#include <dev/pci/pcivar.h> - -#include <dev/uart/uart.h> -#include <dev/uart/uart_bus.h> -#include <dev/uart/uart_cpu.h> - -#include "uart_if.h" - -static int uart_i80321_probe(device_t dev); - -static device_method_t uart_i80321_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uart_i80321_probe), - DEVMETHOD(device_attach, uart_bus_attach), - DEVMETHOD(device_detach, uart_bus_detach), - { 0, 0 } -}; - -static driver_t uart_i80321_driver = { - uart_driver_name, - uart_i80321_methods, - sizeof(struct uart_softc), -}; - -extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; -static int -uart_i80321_probe(device_t dev) -{ - struct uart_softc *sc; - - sc = device_get_softc(dev); - sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); - sc->sc_class = &uart_ns8250_class; - bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); - return(uart_bus_probe(dev, 0, 0, 0, 0)); -} - - -DRIVER_MODULE(uart, obio, uart_i80321_driver, uart_devclass, 0, 0); diff --git a/sys/arm/xscale/i80321/uart_cpu_i80321.c b/sys/arm/xscale/i80321/uart_cpu_i80321.c deleted file mode 100644 index a3faec7..0000000 --- a/sys/arm/xscale/i80321/uart_cpu_i80321.c +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * Copyright (c) 2003 Marcel Moolenaar - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/cons.h> -#include <machine/bus.h> - -#include <dev/uart/uart.h> -#include <dev/uart/uart_cpu.h> - -#include <arm/xscale/i80321/i80321var.h> -#include <arm/xscale/i80321/obiovar.h> - -bus_space_tag_t uart_bus_space_io; -bus_space_tag_t uart_bus_space_mem; - -int -uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) -{ - return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0); -} - -int -uart_cpu_getdev(int devtype, struct uart_devinfo *di) -{ - di->ops = uart_getops(&uart_ns8250_class); - di->bas.chan = 0; - di->bas.bst = obio_bs_tag; - di->bas.regshft = 0; - di->bas.rclk = 0; - di->baudrate = 115200; - di->databits = 8; - di->stopbits = 1; - di->parity = UART_PARITY_NONE; - uart_bus_space_io = obio_bs_tag; - uart_bus_space_mem = NULL; - di->bas.bsh = 0xfe800000; - return (0); -} diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c index 2bd77a5..2936963 100644 --- a/sys/arm/xscale/i8134x/crb_machdep.c +++ b/sys/arm/xscale/i8134x/crb_machdep.c @@ -92,7 +92,7 @@ __FBSDID("$FreeBSD$"); #include <sys/reboot.h> -#include <arm/xscale/i80321/i80321var.h> /* For i80321_calibrate_delay() */ +#include <arm/xscale/i8134x/i80321var.h> /* For i80321_calibrate_delay() */ #include <arm/xscale/i8134x/i81342reg.h> #include <arm/xscale/i8134x/i81342var.h> @@ -267,7 +267,7 @@ initarm(struct arm_boot_params *abp) xscale_cache_clean_addr = 0xff000000U; cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); /* @@ -284,7 +284,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/xscale/i8134x/files.i81342 b/sys/arm/xscale/i8134x/files.i81342 index ed93e6b..63c715c 100644 --- a/sys/arm/xscale/i8134x/files.i81342 +++ b/sys/arm/xscale/i8134x/files.i81342 @@ -1,7 +1,7 @@ # $FreeBSD$ arm/arm/bus_space_base.c standard -arm/xscale/i80321/i80321_timer.c standard -arm/xscale/i80321/i80321_wdog.c optional iopwdog +arm/xscale/i8134x/i80321_timer.c standard +arm/xscale/i8134x/i80321_wdog.c optional iopwdog arm/xscale/i8134x/i81342.c standard arm/xscale/i8134x/i81342_mcu.c standard arm/xscale/i8134x/i81342_pci.c optional pci diff --git a/sys/arm/xscale/i80321/i80321_timer.c b/sys/arm/xscale/i8134x/i80321_timer.c index 3b4e5a1..ea15d92 100644 --- a/sys/arm/xscale/i80321/i80321_timer.c +++ b/sys/arm/xscale/i8134x/i80321_timer.c @@ -59,8 +59,8 @@ __FBSDID("$FreeBSD$"); #include <machine/frame.h> #include <machine/resource.h> #include <machine/intr.h> -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> +#include <arm/xscale/i8134x/i80321reg.h> +#include <arm/xscale/i8134x/i80321var.h> #ifdef CPU_XSCALE_81342 #define ICU_INT_TIMER0 (8) /* XXX: Can't include i81342reg.h because diff --git a/sys/arm/xscale/i80321/i80321_wdog.c b/sys/arm/xscale/i8134x/i80321_wdog.c index 9be98d2..c11c78a 100644 --- a/sys/arm/xscale/i80321/i80321_wdog.c +++ b/sys/arm/xscale/i8134x/i80321_wdog.c @@ -54,8 +54,8 @@ __FBSDID("$FreeBSD$"); #include <machine/cpufunc.h> #include <machine/machdep.h> -#include <arm/xscale/i80321/i80321reg.h> -#include <arm/xscale/i80321/i80321var.h> +#include <arm/xscale/i8134x/i80321reg.h> +#include <arm/xscale/i8134x/i80321var.h> struct iopwdog_softc { diff --git a/sys/arm/xscale/i80321/i80321reg.h b/sys/arm/xscale/i8134x/i80321reg.h index 53617f9..b6dd4fe 100644 --- a/sys/arm/xscale/i80321/i80321reg.h +++ b/sys/arm/xscale/i8134x/i80321reg.h @@ -91,19 +91,9 @@ #define VERDE_MCU_BASE 0x0500 #define VERDE_MCU_SIZE 0x0100 -#if defined(CPU_XSCALE_80321) -#define VERDE_SSP_BASE 0x0600 -#define VERDE_SSP_SIZE 0x0080 -#endif - #define VERDE_PBIU_BASE 0x0680 #define VERDE_PBIU_SIZE 0x0080 -#if defined(CPU_XSCALE_80321) -#define VERDE_AAU_BASE 0x0800 -#define VERDE_AAU_SIZE 0x0100 -#endif - #define VERDE_I2C_BASE 0x1680 #define VERDE_I2C_BASE0 (VERDE_I2C_BASE + 0x00) #define VERDE_I2C_BASE1 (VERDE_I2C_BASE + 0x20) @@ -340,21 +330,13 @@ #define ICU_INT_XINT(x) ((x) + ICU_INT_XINT0) #define ICU_INT_bit26 26 -#if defined (CPU_XSCALE_80219) -#define ICU_INT_bit25 25 /* reserved */ -#else /* CPU_XSCALE_80321 */ #define ICU_INT_SSP 25 /* SSP serial port */ -#endif #define ICU_INT_MUE 24 /* msg unit error */ -#if defined (CPU_XSCALE_80219) -#define ICU_INT_bit23 23 /* reserved */ -#else /* CPU_XSCALE_80321 */ #define ICU_INT_AAUE 23 /* AAU error */ -#endif #define ICU_INT_bit22 22 #define ICU_INT_DMA1E 21 /* DMA Ch 1 error */ @@ -372,14 +354,9 @@ #define ICU_INT_TMR0 9 /* timer 0 */ #define ICU_INT_CPPM 8 /* core processor PMU */ -#if defined(CPU_XSCALE_80219) -#define ICU_INT_bit7 7 /* reserved */ -#define ICU_INT_bit6 6 /* reserved */ -#else /* CPU_XSCALE_80321 */ #define ICU_INT_AAU_EOC 7 /* AAU end-of-chain */ #define ICU_INT_AAU_EOT 6 /* AAU end-of-transfer */ -#endif #define ICU_INT_bit5 5 #define ICU_INT_bit4 4 @@ -388,81 +365,12 @@ #define ICU_INT_DMA0_EOC 1 /* DMA0 end-of-chain */ #define ICU_INT_DMA0_EOT 0 /* DMA0 end-of-transfer */ -#if defined (CPU_XSCALE_80219) -#define ICU_INT_HWMASK (0xffffffff & \ - ~((1 << ICU_INT_bit26) | \ - (1 << ICU_INT_bit25) | \ - (1 << ICU_INT_bit23) | \ - (1 << ICU_INT_bit22) | \ - (1 << ICU_INT_bit7) | \ - (1 << ICU_INT_bit6) | \ - (1 << ICU_INT_bit5) | \ - (1 << ICU_INT_bit4))) - -#else /* CPU_XSCALE_80321 */ #define ICU_INT_HWMASK (0xffffffff & \ ~((1 << ICU_INT_bit26) | \ (1 << ICU_INT_bit22) | \ (1 << ICU_INT_bit5) | \ (1 << ICU_INT_bit4))) -#endif - -/* - * SSP Serial Port - */ -#if defined (CPU_XSCALE_80321) - -#define SSP_SSCR0 0x00 /* SSC control 0 */ -#define SSP_SSCR1 0x04 /* SSC control 1 */ -#define SSP_SSSR 0x08 /* SSP status */ -#define SSP_SSITR 0x0c /* SSP interrupt test */ -#define SSP_SSDR 0x10 /* SSP data */ - -#define SSP_SSCR0_DSIZE(x) ((x) - 1)/* data size: 4..16 */ -#define SSP_SSCR0_FRF_SPI (0 << 4) /* Motorola Serial Periph Iface */ -#define SSP_SSCR0_FRF_SSP (1U << 4)/* TI Sync. Serial Protocol */ -#define SSP_SSCR0_FRF_UWIRE (2U << 4)/* NatSemi Microwire */ -#define SSP_SSCR0_FRF_rsvd (3U << 4)/* reserved */ -#define SSP_SSCR0_ECS (1U << 6)/* external clock select */ -#define SSP_SSCR0_SSE (1U << 7)/* sync. serial port enable */ -#define SSP_SSCR0_SCR(x) ((x) << 8)/* serial clock rate */ - /* bit rate = 3.6864 * 10e6 / - (2 * (SCR + 1)) */ - -#define SSP_SSCR1_RIE (1U << 0)/* Rx FIFO interrupt enable */ -#define SSP_SSCR1_TIE (1U << 1)/* Tx FIFO interrupt enable */ -#define SSP_SSCR1_LBM (1U << 2)/* loopback mode enable */ -#define SSP_SSCR1_SPO (1U << 3)/* Moto SPI SSCLK pol. (1 = high) */ -#define SSP_SSCR1_SPH (1U << 4)/* Moto SPI SSCLK phase: - 0 = inactive full at start, - 1/2 at end of frame - 1 = inactive 1/2 at start, - full at end of frame */ -#define SSP_SSCR1_MWDS (1U << 5)/* Microwire data size: - 0 = 8 bit - 1 = 16 bit */ -#define SSP_SSCR1_TFT (((x) - 1) << 6) /* Tx FIFO threshold */ -#define SSP_SSCR1_RFT (((x) - 1) << 10)/* Rx FIFO threshold */ -#define SSP_SSCR1_EFWR (1U << 14)/* enab. FIFO write/read */ -#define SSP_SSCR1_STRF (1U << 15)/* FIFO write/read FIFO select: - 0 = Tx FIFO - 1 = Rx FIFO */ - -#define SSP_SSSR_TNF (1U << 2)/* Tx FIFO not full */ -#define SSP_SSSR_RNE (1U << 3)/* Rx FIFO not empty */ -#define SSP_SSSR_BSY (1U << 4)/* SSP is busy */ -#define SSP_SSSR_TFS (1U << 5)/* Tx FIFO service request */ -#define SSP_SSSR_RFS (1U << 6)/* Rx FIFO service request */ -#define SSP_SSSR_ROR (1U << 7)/* Rx FIFO overrun */ -#define SSP_SSSR_TFL(x) (((x) >> 8) & 0xf) /* Tx FIFO level */ -#define SSP_SSSR_RFL(x) (((x) >> 12) & 0xf)/* Rx FIFO level */ - -#define SSP_SSITR_TTFS (1U << 5)/* Test Tx FIFO service */ -#define SSP_SSITR_TRFS (1U << 6)/* Test Rx FIFO service */ -#define SSP_SSITR_TROR (1U << 7)/* Test Rx overrun */ - -#endif /* CPU_XSCALE_80321 */ /* * Peripheral Bus Interface Unit diff --git a/sys/arm/xscale/i80321/i80321var.h b/sys/arm/xscale/i8134x/i80321var.h index 0fead25..0fead25 100644 --- a/sys/arm/xscale/i80321/i80321var.h +++ b/sys/arm/xscale/i8134x/i80321var.h diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c index e033e13..f8632e1 100644 --- a/sys/arm/xscale/ixp425/avila_machdep.c +++ b/sys/arm/xscale/ixp425/avila_machdep.c @@ -353,7 +353,7 @@ initarm(struct arm_boot_params *abp) xscale_cache_clean_addr = 0xff000000U; cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); @@ -370,7 +370,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c index 5cc8d46..2bbb835 100644 --- a/sys/arm/xscale/pxa/pxa_machdep.c +++ b/sys/arm/xscale/pxa/pxa_machdep.c @@ -267,7 +267,7 @@ initarm(struct arm_boot_params *abp) xscale_cache_clean_addr = 0xff000000U; cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - setttb(kernel_l1pt.pv_pa); + cpu_setttb(kernel_l1pt.pv_pa); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); @@ -284,7 +284,7 @@ initarm(struct arm_boot_params *abp) /* * We must now clean the cache again.... * Cleaning may be done by reading new data to displace any - * dirty data in the cache. This will have happened in setttb() + * dirty data in the cache. This will have happened in cpu_setttb() * but since we are boot strapping the addresses used for the read * may have just been remapped and thus the cache could be out * of sync. A re-clean after the switch will cure this. diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S index 9909a42..87abee1 100644 --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -628,11 +628,11 @@ tcr_early: sctlr_set: /* Bits to set */ .quad (SCTLR_UCI | SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | SCTLR_DZE | \ - SCTLR_I | SCTLR_SED | SCTLR_C | SCTLR_M) + SCTLR_I | SCTLR_SED | SCTLR_SA0 | SCTLR_SA | SCTLR_C | SCTLR_M) sctlr_clear: /* Bits to clear */ .quad (SCTLR_EE | SCTLR_EOE | SCTLR_WXN | SCTLR_UMA | SCTLR_ITD | \ - SCTLR_THEE | SCTLR_CP15BEN | SCTLR_SA0 | SCTLR_SA | SCTLR_A) + SCTLR_THEE | SCTLR_CP15BEN | SCTLR_A) .globl abort abort: diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index 89d6d0c..10e3f41 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -374,6 +374,10 @@ do_el0_sync(struct trapframe *frame) case EXCP_UNKNOWN: el0_excp_unknown(frame); break; + case EXCP_SP_ALIGN: + call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_sp); + userret(td, frame); + break; case EXCP_PC_ALIGN: call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr); userret(td, frame); diff --git a/sys/arm64/arm64/uma_machdep.c b/sys/arm64/arm64/uma_machdep.c index 9b9df5c..a9dae0f 100644 --- a/sys/arm64/arm64/uma_machdep.c +++ b/sys/arm64/arm64/uma_machdep.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/systm.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/vm_page.h> #include <vm/vm_pageout.h> diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c index 6794b1b4..3b68914 100644 --- a/sys/arm64/arm64/vm_machdep.c +++ b/sys/arm64/arm64/vm_machdep.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sf_buf.h> #include <sys/signal.h> #include <sys/unistd.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/vm_page.h> diff --git a/sys/arm64/include/kdb.h b/sys/arm64/include/kdb.h index e4f4f70..2f7306e 100644 --- a/sys/arm64/include/kdb.h +++ b/sys/arm64/include/kdb.h @@ -43,6 +43,8 @@ void kdb_cpu_set_singlestep(void); static __inline void kdb_cpu_sync_icache(unsigned char *addr, size_t size) { + + cpu_icache_sync_range((vm_offset_t)addr, size); } static __inline void diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index 0ff1a15..3207f73 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -886,7 +886,7 @@ __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef, error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md)); if (error == EOPNOTSUPP) { md.md_cval += ef->off; - md.md_data = (void *)((uintptr_t)md.md_data + ef->off); + md.md_data = (void *)((uintptr_t)md.md_data + (uintptr_t)ef->off); } else if (error != 0) return (error); #endif diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c index c326c79..1161b0a 100644 --- a/sys/boot/efi/boot1/boot1.c +++ b/sys/boot/efi/boot1/boot1.c @@ -50,9 +50,6 @@ static const boot_module_t *boot_modules[] = void putchar(int c); EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab); -static void try_load(const boot_module_t* mod); -static EFI_STATUS probe_handle(EFI_HANDLE h); - EFI_SYSTEM_TABLE *systab; EFI_BOOT_SERVICES *bs; static EFI_HANDLE *image; @@ -85,20 +82,300 @@ Free(void *buf, const char *file __unused, int line __unused) } /* - * This function only returns if it fails to load the kernel. If it - * succeeds, it simply boots the kernel. + * nodes_match returns TRUE if the imgpath isn't NULL and the nodes match, + * FALSE otherwise. */ -void -try_load(const boot_module_t *mod) +static BOOLEAN +nodes_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) +{ + int len; + + if (imgpath == NULL || imgpath->Type != devpath->Type || + imgpath->SubType != devpath->SubType) + return (FALSE); + + len = DevicePathNodeLength(imgpath); + if (len != DevicePathNodeLength(devpath)) + return (FALSE); + + return (memcmp(imgpath, devpath, (size_t)len) == 0); +} + +/* + * device_paths_match returns TRUE if the imgpath isn't NULL and all nodes + * in imgpath and devpath match up to their respect occurances of a media + * node, FALSE otherwise. + */ +static BOOLEAN +device_paths_match(EFI_DEVICE_PATH *imgpath, EFI_DEVICE_PATH *devpath) +{ + + if (imgpath == NULL) + return (FALSE); + + while (!IsDevicePathEnd(imgpath) && !IsDevicePathEnd(devpath)) { + if (IsDevicePathType(imgpath, MEDIA_DEVICE_PATH) && + IsDevicePathType(devpath, MEDIA_DEVICE_PATH)) + return (TRUE); + + if (!nodes_match(imgpath, devpath)) + return (FALSE); + + imgpath = NextDevicePathNode(imgpath); + devpath = NextDevicePathNode(devpath); + } + + return (FALSE); +} + +/* + * devpath_last returns the last non-path end node in devpath. + */ +static EFI_DEVICE_PATH * +devpath_last(EFI_DEVICE_PATH *devpath) +{ + + while (!IsDevicePathEnd(NextDevicePathNode(devpath))) + devpath = NextDevicePathNode(devpath); + + return (devpath); +} + +/* + * devpath_node_str is a basic output method for a devpath node which + * only understands a subset of the available sub types. + * + * If we switch to UEFI 2.x then we should update it to use: + * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. + */ +static int +devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath) +{ + + switch (devpath->Type) { + case MESSAGING_DEVICE_PATH: + switch (devpath->SubType) { + case MSG_ATAPI_DP: { + ATAPI_DEVICE_PATH *atapi; + + atapi = (ATAPI_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "ata(%s,%s,0x%x)", + (atapi->PrimarySecondary == 1) ? "Sec" : "Pri", + (atapi->SlaveMaster == 1) ? "Slave" : "Master", + atapi->Lun); + } + case MSG_USB_DP: { + USB_DEVICE_PATH *usb; + + usb = (USB_DEVICE_PATH *)devpath; + return snprintf(buf, size, "usb(0x%02x,0x%02x)", + usb->ParentPortNumber, usb->InterfaceNumber); + } + case MSG_SCSI_DP: { + SCSI_DEVICE_PATH *scsi; + + scsi = (SCSI_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "scsi(0x%02x,0x%02x)", + scsi->Pun, scsi->Lun); + } + case MSG_SATA_DP: { + SATA_DEVICE_PATH *sata; + + sata = (SATA_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)", + sata->HBAPortNumber, sata->PortMultiplierPortNumber, + sata->Lun); + } + default: + return snprintf(buf, size, "msg(0x%02x)", + devpath->SubType); + } + break; + case HARDWARE_DEVICE_PATH: + switch (devpath->SubType) { + case HW_PCI_DP: { + PCI_DEVICE_PATH *pci; + + pci = (PCI_DEVICE_PATH *)devpath; + return snprintf(buf, size, "pci(0x%02x,0x%02x)", + pci->Device, pci->Function); + } + default: + return snprintf(buf, size, "hw(0x%02x)", + devpath->SubType); + } + break; + case ACPI_DEVICE_PATH: { + ACPI_HID_DEVICE_PATH *acpi; + + acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath; + if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + switch (EISA_ID_TO_NUM(acpi->HID)) { + case 0x0a03: + return snprintf(buf, size, "pciroot(0x%x)", + acpi->UID); + case 0x0a08: + return snprintf(buf, size, "pcieroot(0x%x)", + acpi->UID); + case 0x0604: + return snprintf(buf, size, "floppy(0x%x)", + acpi->UID); + case 0x0301: + return snprintf(buf, size, "keyboard(0x%x)", + acpi->UID); + case 0x0501: + return snprintf(buf, size, "serial(0x%x)", + acpi->UID); + case 0x0401: + return snprintf(buf, size, "parallelport(0x%x)", + acpi->UID); + default: + return snprintf(buf, size, "acpi(pnp%04x,0x%x)", + EISA_ID_TO_NUM(acpi->HID), acpi->UID); + } + } + + return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID, + acpi->UID); + } + case MEDIA_DEVICE_PATH: + switch (devpath->SubType) { + case MEDIA_CDROM_DP: { + CDROM_DEVICE_PATH *cdrom; + + cdrom = (CDROM_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "cdrom(%x)", + cdrom->BootEntry); + } + case MEDIA_HARDDRIVE_DP: { + HARDDRIVE_DEVICE_PATH *hd; + + hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath; + return snprintf(buf, size, "hd(%x)", + hd->PartitionNumber); + } + default: + return snprintf(buf, size, "media(0x%02x)", + devpath->SubType); + } + case BBS_DEVICE_PATH: + return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType); + case END_DEVICE_PATH_TYPE: + return (0); + } + + return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type, + devpath->SubType); +} + +/* + * devpath_strlcat appends a text description of devpath to buf but not more + * than size - 1 characters followed by NUL-terminator. + */ +int +devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath) +{ + size_t len, used; + const char *sep; + + sep = ""; + used = 0; + while (!IsDevicePathEnd(devpath)) { + len = snprintf(buf, size - used, "%s", sep); + used += len; + if (used > size) + return (used); + buf += len; + + len = devpath_node_str(buf, size - used, devpath); + used += len; + if (used > size) + return (used); + buf += len; + devpath = NextDevicePathNode(devpath); + sep = ":"; + } + + return (used); +} + +/* + * devpath_str is convenience method which returns the text description of + * devpath using a static buffer, so it isn't thread safe! + */ +char * +devpath_str(EFI_DEVICE_PATH *devpath) +{ + static char buf[256]; + + devpath_strlcat(buf, sizeof(buf), devpath); + + return buf; +} + +/* + * load_loader attempts to load the loader image data. + * + * It tries each module and its respective devices, identified by mod->probe, + * in order until a successful load occurs at which point it returns EFI_SUCCESS + * and EFI_NOT_FOUND otherwise. + * + * Only devices which have preferred matching the preferred parameter are tried. + */ +static EFI_STATUS +load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp, + size_t *bufsize, BOOLEAN preferred) { - size_t bufsize, cmdsize; - void *buf; + UINTN i; + dev_info_t *dev; + const boot_module_t *mod; + + for (i = 0; i < NUM_BOOT_MODULES; i++) { + if (boot_modules[i] == NULL) + continue; + mod = boot_modules[i]; + for (dev = mod->devices(); dev != NULL; dev = dev->next) { + if (dev->preferred != preferred) + continue; + + if (mod->load(PATH_LOADER_EFI, dev, bufp, bufsize) == + EFI_SUCCESS) { + *devinfop = dev; + *modp = mod; + return (EFI_SUCCESS); + } + } + } + + return (EFI_NOT_FOUND); +} + +/* + * try_boot only returns if it fails to load the loader. If it succeeds + * it simply boots, otherwise it returns the status of last EFI call. + */ +static EFI_STATUS +try_boot() +{ + size_t bufsize, loadersize, cmdsize; + void *buf, *loaderbuf; char *cmd; dev_info_t *dev; + const boot_module_t *mod; EFI_HANDLE loaderhandle; EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; + status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE); + if (status != EFI_SUCCESS) { + status = load_loader(&mod, &dev, &loaderbuf, &loadersize, + FALSE); + if (status != EFI_SUCCESS) { + printf("Failed to load '%s'\n", PATH_LOADER_EFI); + return (status); + } + } + /* * Read in and parse the command line from /boot.config or /boot/config, * if present. We'll pass it the next stage via a simple ASCII @@ -111,67 +388,183 @@ try_load(const boot_module_t *mod) */ cmd = NULL; cmdsize = 0; - status = mod->load(PATH_DOTCONFIG, &dev, &buf, &bufsize); + status = mod->load(PATH_DOTCONFIG, dev, &buf, &bufsize); if (status == EFI_NOT_FOUND) - status = mod->load(PATH_CONFIG, &dev, &buf, &bufsize); + status = mod->load(PATH_CONFIG, dev, &buf, &bufsize); if (status == EFI_SUCCESS) { cmdsize = bufsize + 1; cmd = malloc(cmdsize); - if (cmd == NULL) { - free(buf); - return; - } + if (cmd == NULL) + goto errout; memcpy(cmd, buf, bufsize); cmd[bufsize] = '\0'; free(buf); + buf = NULL; } - status = mod->load(PATH_LOADER_EFI, &dev, &buf, &bufsize); - if (status == EFI_NOT_FOUND) - return; - - if (status != EFI_SUCCESS) { - printf("%s failed to load %s (%lu)\n", mod->name, - PATH_LOADER_EFI, EFI_ERROR_CODE(status)); - return; - } - - if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize, - &loaderhandle)) != EFI_SUCCESS) { + if ((status = bs->LoadImage(TRUE, image, devpath_last(dev->devpath), + loaderbuf, loadersize, &loaderhandle)) != EFI_SUCCESS) { printf("Failed to load image provided by %s, size: %zu, (%lu)\n", mod->name, bufsize, EFI_ERROR_CODE(status)); - return; + goto errout; } - if (cmd != NULL) - printf(" command args: %s\n", cmd); - if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID, (VOID**)&loaded_image)) != EFI_SUCCESS) { printf("Failed to query LoadedImage provided by %s (%lu)\n", mod->name, EFI_ERROR_CODE(status)); - return; + goto errout; } + if (cmd != NULL) + printf(" command args: %s\n", cmd); + loaded_image->DeviceHandle = dev->devhandle; loaded_image->LoadOptionsSize = cmdsize; loaded_image->LoadOptions = cmd; + DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF("."); + DSTALL(1000000); + DPRINTF(".\n"); + if ((status = bs->StartImage(loaderhandle, NULL, NULL)) != EFI_SUCCESS) { printf("Failed to start image provided by %s (%lu)\n", mod->name, EFI_ERROR_CODE(status)); - free(cmd); loaded_image->LoadOptionsSize = 0; loaded_image->LoadOptions = NULL; - return; } + +errout: + if (cmd != NULL) + free(cmd); + if (buf != NULL) + free(buf); + if (loaderbuf != NULL) + free(loaderbuf); + + return (status); +} + +/* + * probe_handle determines if the passed handle represents a logical partition + * if it does it uses each module in order to probe it and if successful it + * returns EFI_SUCCESS. + */ +static EFI_STATUS +probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, BOOLEAN *preferred) +{ + dev_info_t *devinfo; + EFI_BLOCK_IO *blkio; + EFI_DEVICE_PATH *devpath; + EFI_STATUS status; + UINTN i; + + /* Figure out if we're dealing with an actual partition. */ + status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); + if (status == EFI_UNSUPPORTED) + return (status); + + if (status != EFI_SUCCESS) { + DPRINTF("\nFailed to query DevicePath (%lu)\n", + EFI_ERROR_CODE(status)); + return (status); + } + + DPRINTF("probing: %s\n", devpath_str(devpath)); + + status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); + if (status == EFI_UNSUPPORTED) + return (status); + + if (status != EFI_SUCCESS) { + DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", + EFI_ERROR_CODE(status)); + return (status); + } + + if (!blkio->Media->LogicalPartition) + return (EFI_UNSUPPORTED); + + *preferred = device_paths_match(imgpath, devpath); + + /* Run through each module, see if it can load this partition */ + for (i = 0; i < NUM_BOOT_MODULES; i++) { + if (boot_modules[i] == NULL) + continue; + + if ((status = bs->AllocatePool(EfiLoaderData, + sizeof(*devinfo), (void **)&devinfo)) != + EFI_SUCCESS) { + DPRINTF("\nFailed to allocate devinfo (%lu)\n", + EFI_ERROR_CODE(status)); + continue; + } + devinfo->dev = blkio; + devinfo->devpath = devpath; + devinfo->devhandle = h; + devinfo->devdata = NULL; + devinfo->preferred = *preferred; + devinfo->next = NULL; + + status = boot_modules[i]->probe(devinfo); + if (status == EFI_SUCCESS) + return (EFI_SUCCESS); + (void)bs->FreePool(devinfo); + } + + return (EFI_UNSUPPORTED); +} + +/* + * probe_handle_status calls probe_handle and outputs the returned status + * of the call. + */ +static void +probe_handle_status(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath) +{ + EFI_STATUS status; + BOOLEAN preferred; + + status = probe_handle(h, imgpath, &preferred); + + DPRINTF("probe: "); + switch (status) { + case EFI_UNSUPPORTED: + printf("."); + DPRINTF(" not supported\n"); + break; + case EFI_SUCCESS: + if (preferred) { + printf("%c", '*'); + DPRINTF(" supported (preferred)\n"); + } else { + printf("%c", '+'); + DPRINTF(" supported\n"); + } + break; + default: + printf("x"); + DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status)); + break; + } + DSTALL(500000); } EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) { EFI_HANDLE *handles; + EFI_LOADED_IMAGE *img; + EFI_DEVICE_PATH *imgpath; EFI_STATUS status; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; @@ -254,20 +647,22 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) /* Scan all partitions, probing with all modules. */ nhandles = hsize / sizeof(*handles); printf(" Probing %zu block devices...", nhandles); - for (i = 0; i < nhandles; i++) { - status = probe_handle(handles[i]); - switch (status) { - case EFI_UNSUPPORTED: - printf("."); - break; - case EFI_SUCCESS: - printf("+"); - break; - default: - printf("x"); - break; - } + DPRINTF("\n"); + + /* Determine the devpath of our image so we can prefer it. */ + status = bs->HandleProtocol(image, &LoadedImageGUID, (VOID**)&img); + imgpath = NULL; + if (status == EFI_SUCCESS) { + status = bs->HandleProtocol(img->DeviceHandle, &DevicePathGUID, + (void **)&imgpath); + if (status != EFI_SUCCESS) + DPRINTF("Failed to get image DevicePath (%lu)\n", + EFI_ERROR_CODE(status)); + DPRINTF("boot1 imagepath: %s\n", devpath_str(imgpath)); } + + for (i = 0; i < nhandles; i++) + probe_handle_status(handles[i], imgpath); printf(" done\n"); /* Status summary. */ @@ -278,78 +673,15 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) } } - /* Select a partition to boot by trying each module in order. */ - for (i = 0; i < NUM_BOOT_MODULES; i++) - if (boot_modules[i] != NULL) - try_load(boot_modules[i]); + try_boot(); /* If we get here, we're out of luck... */ panic("No bootable partitions found!"); } -static EFI_STATUS -probe_handle(EFI_HANDLE h) -{ - dev_info_t *devinfo; - EFI_BLOCK_IO *blkio; - EFI_DEVICE_PATH *devpath; - EFI_STATUS status; - UINTN i; - - /* Figure out if we're dealing with an actual partition. */ - status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath); - if (status == EFI_UNSUPPORTED) - return (status); - - if (status != EFI_SUCCESS) { - DPRINTF("\nFailed to query DevicePath (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); - } - - while (!IsDevicePathEnd(NextDevicePathNode(devpath))) - devpath = NextDevicePathNode(devpath); - - status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio); - if (status == EFI_UNSUPPORTED) - return (status); - - if (status != EFI_SUCCESS) { - DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n", - EFI_ERROR_CODE(status)); - return (status); - } - - if (!blkio->Media->LogicalPartition) - return (EFI_UNSUPPORTED); - - /* Run through each module, see if it can load this partition */ - for (i = 0; i < NUM_BOOT_MODULES; i++) { - if (boot_modules[i] == NULL) - continue; - - if ((status = bs->AllocatePool(EfiLoaderData, - sizeof(*devinfo), (void **)&devinfo)) != - EFI_SUCCESS) { - DPRINTF("\nFailed to allocate devinfo (%lu)\n", - EFI_ERROR_CODE(status)); - continue; - } - devinfo->dev = blkio; - devinfo->devpath = devpath; - devinfo->devhandle = h; - devinfo->devdata = NULL; - devinfo->next = NULL; - - status = boot_modules[i]->probe(devinfo); - if (status == EFI_SUCCESS) - return (EFI_SUCCESS); - (void)bs->FreePool(devinfo); - } - - return (EFI_UNSUPPORTED); -} - +/* + * add_device adds a device to the passed devinfo list. + */ void add_device(dev_info_t **devinfop, dev_info_t *devinfo) { diff --git a/sys/boot/efi/boot1/boot_module.h b/sys/boot/efi/boot1/boot_module.h index 2c158f6..296d5a6 100644 --- a/sys/boot/efi/boot1/boot_module.h +++ b/sys/boot/efi/boot1/boot_module.h @@ -36,9 +36,11 @@ #include <eficonsctl.h> #ifdef EFI_DEBUG -#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__) +#define DPRINTF(fmt, args...) printf(fmt, ##args) +#define DSTALL(d) bs->Stall(d) #else #define DPRINTF(fmt, ...) {} +#define DSTALL(d) {} #endif /* EFI device info */ @@ -48,6 +50,7 @@ typedef struct dev_info EFI_DEVICE_PATH *devpath; EFI_HANDLE *devhandle; void *devdata; + BOOLEAN preferred; struct dev_info *next; } dev_info_t; @@ -75,19 +78,21 @@ typedef struct boot_module_t /* * load should select the best out of a set of devices that probe - * indicated were loadable and load it. + * indicated were loadable and load the specified file. * * Return codes: * EFI_SUCCESS = The module can handle the device. * EFI_NOT_FOUND = The module can not handle the device. * Other = The module encountered an error. */ - EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo, + EFI_STATUS (*load)(const char *filepath, dev_info_t *devinfo, void **buf, size_t *bufsize); /* status outputs information about the probed devices. */ void (*status)(); + /* valid devices as found by probe. */ + dev_info_t *(*devices)(); } boot_module_t; /* Standard boot modules. */ @@ -107,4 +112,6 @@ extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); extern EFI_SYSTEM_TABLE *systab; extern EFI_BOOT_SERVICES *bs; +extern int devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath); +extern char *devpath_str(EFI_DEVICE_PATH *devpath); #endif diff --git a/sys/boot/efi/boot1/ufs_module.c b/sys/boot/efi/boot1/ufs_module.c index 07c7152..63087ea 100644 --- a/sys/boot/efi/boot1/ufs_module.c +++ b/sys/boot/efi/boot1/ufs_module.c @@ -93,7 +93,7 @@ probe(dev_info_t* dev) } static EFI_STATUS -try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize) +load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize) { ufs_ino_t ino; EFI_STATUS status; @@ -101,59 +101,46 @@ try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize) ssize_t read; void *buf; - if (init_dev(dev) < 0) + DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath)); + + if (init_dev(dev) < 0) { + DPRINTF("Failed to init device\n"); return (EFI_UNSUPPORTED); + } - if ((ino = lookup(loader_path)) == 0) + if ((ino = lookup(filepath)) == 0) { + DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath); return (EFI_NOT_FOUND); + } if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) { - printf("Failed to read size of '%s' ino: %d\n", loader_path, - ino); + printf("Failed to read size of '%s' ino: %d\n", filepath, ino); return (EFI_INVALID_PARAMETER); } if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) != EFI_SUCCESS) { - printf("Failed to allocate read buffer (%lu)\n", - EFI_ERROR_CODE(status)); + printf("Failed to allocate read buffer %zu for '%s' (%lu)\n", + size, filepath, EFI_ERROR_CODE(status)); return (status); } read = fsread(ino, buf, size); if ((size_t)read != size) { - printf("Failed to read '%s' (%zd != %zu)\n", loader_path, read, + printf("Failed to read '%s' (%zd != %zu)\n", filepath, read, size); (void)bs->FreePool(buf); return (EFI_INVALID_PARAMETER); } + DPRINTF("Load complete\n"); + *bufp = buf; *bufsize = size; return (EFI_SUCCESS); } -static EFI_STATUS -load(const char *loader_path, dev_info_t **devinfop, void **buf, - size_t *bufsize) -{ - dev_info_t *dev; - EFI_STATUS status; - - for (dev = devices; dev != NULL; dev = dev->next) { - status = try_load(dev, loader_path, buf, bufsize); - if (status == EFI_SUCCESS) { - *devinfop = dev; - return (EFI_SUCCESS); - } else if (status != EFI_NOT_FOUND) { - return (status); - } - } - - return (EFI_NOT_FOUND); -} - static void status() { @@ -176,10 +163,18 @@ status() } } +static dev_info_t * +_devices() +{ + + return (devices); +} + const boot_module_t ufs_module = { .name = "UFS", .probe = probe, .load = load, - .status = status + .status = status, + .devices = _devices }; diff --git a/sys/boot/efi/boot1/zfs_module.c b/sys/boot/efi/boot1/zfs_module.c index 96eec33..925f0b2 100644 --- a/sys/boot/efi/boot1/zfs_module.c +++ b/sys/boot/efi/boot1/zfs_module.c @@ -91,7 +91,7 @@ probe(dev_info_t *dev) } static EFI_STATUS -try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize) +load(const char *filepath, dev_info_t *devinfo, void **bufp, size_t *bufsize) { spa_t *spa; struct zfsmount zfsmount; @@ -102,32 +102,41 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs EFI_STATUS status; spa = devinfo->devdata; - if (zfs_spa_init(spa) != 0) { - /* Init failed, don't report this loudly. */ + + DPRINTF("load: '%s' spa: '%s', devpath: %s\n", filepath, spa->spa_name, + devpath_str(devinfo->devpath)); + + if ((err = zfs_spa_init(spa)) != 0) { + DPRINTF("Failed to load pool '%s' (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } - if (zfs_mount(spa, 0, &zfsmount) != 0) { - /* Mount failed, don't report this loudly. */ + if ((err = zfs_mount(spa, 0, &zfsmount)) != 0) { + DPRINTF("Failed to mount pool '%s' (%d)\n", spa->spa_name, err); return (EFI_NOT_FOUND); } - if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) { - printf("Failed to lookup %s on pool %s (%d)\n", loader_path, + if ((err = zfs_lookup(&zfsmount, filepath, &dn)) != 0) { + if (err == ENOENT) { + DPRINTF("Failed to find '%s' on pool '%s' (%d)\n", + filepath, spa->spa_name, err); + return (EFI_NOT_FOUND); + } + printf("Failed to lookup '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) { - printf("Failed to lookup %s on pool %s (%d)\n", loader_path, + printf("Failed to stat '%s' on pool '%s' (%d)\n", filepath, spa->spa_name, err); return (EFI_INVALID_PARAMETER); } if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf)) != EFI_SUCCESS) { - printf("Failed to allocate load buffer for pool %s (%lu)\n", - spa->spa_name, EFI_ERROR_CODE(status)); + printf("Failed to allocate load buffer %zd for pool '%s' for '%s' " + "(%lu)\n", st.st_size, spa->spa_name, filepath, EFI_ERROR_CODE(status)); return (EFI_INVALID_PARAMETER); } @@ -144,26 +153,6 @@ try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufs return (EFI_SUCCESS); } -static EFI_STATUS -load(const char *loader_path, dev_info_t **devinfop, void **bufp, - size_t *bufsize) -{ - dev_info_t *devinfo; - EFI_STATUS status; - - for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) { - status = try_load(devinfo, loader_path, bufp, bufsize); - if (status == EFI_SUCCESS) { - *devinfop = devinfo; - return (EFI_SUCCESS); - } else if (status != EFI_NOT_FOUND) { - return (status); - } - } - - return (EFI_NOT_FOUND); -} - static void status() { @@ -189,11 +178,19 @@ init() zfs_init(); } +static dev_info_t * +_devices() +{ + + return (devices); +} + const boot_module_t zfs_module = { .name = "ZFS", .init = init, .probe = probe, .load = load, - .status = status + .status = status, + .devices = _devices }; diff --git a/sys/boot/efi/include/efidevp.h b/sys/boot/efi/include/efidevp.h index f0f49ef..dda79de7 100644 --- a/sys/boot/efi/include/efidevp.h +++ b/sys/boot/efi/include/efidevp.h @@ -40,9 +40,7 @@ typedef struct _EFI_DEVICE_PATH { #define EFI_DP_TYPE_MASK 0x7F #define EFI_DP_TYPE_UNPACKED 0x80 -//#define END_DEVICE_PATH_TYPE 0xff #define END_DEVICE_PATH_TYPE 0x7f -//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff #define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 @@ -56,8 +54,8 @@ typedef struct _EFI_DEVICE_PATH { #define DevicePathSubType(a) ( (a)->SubType ) #define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) ) #define NextDevicePathNode(a) ( (EFI_DEVICE_PATH *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a))) -//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED ) -#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE ) +#define IsDevicePathType(a, t) ( DevicePathType(a) == t ) +#define IsDevicePathEndType(a) IsDevicePathType(a, END_DEVICE_PATH_TYPE) #define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) #define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) ) #define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED ) @@ -285,6 +283,13 @@ typedef struct _UART_DEVICE_PATH { #define DEVICE_PATH_MESSAGING_VT_UTF8 \ { 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} } +#define MSG_SATA_DP 0x12 +typedef struct _SATA_DEVICE_PATH { + EFI_DEVICE_PATH Header; + UINT16 HBAPortNumber; + UINT16 PortMultiplierPortNumber; + UINT16 Lun; +} SATA_DEVICE_PATH; #define MEDIA_DEVICE_PATH 0x04 diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c index d9ecdcc..b7888aa 100644 --- a/sys/boot/efi/libefi/efinet.c +++ b/sys/boot/efi/libefi/efinet.c @@ -309,8 +309,8 @@ efinet_dev_init() status = BS->OpenProtocol(h, &sn_guid, (void **)&net, IH, 0, EFI_OPEN_PROTOCOL_EXCLUSIVE); if (status != EFI_SUCCESS) { - printf("Unable to open network interface %d\n", i); - continue; + printf("Unable to open network interface %d for " + "exclusive access\n", i); } dif->dif_unit = i; diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c index 8e6d420..bf2fc6f8 100644 --- a/sys/boot/zfs/zfs.c +++ b/sys/boot/zfs/zfs.c @@ -722,8 +722,6 @@ init_zfs_bootenv(char *currdev) currdev[strlen(currdev) - 1] = '\0'; setenv("zfs_be_active", currdev, 1); setenv("zfs_be_currpage", "1", 1); - /* Do not overwrite if already set */ - setenv("vfs.root.mountfrom", currdev, 0); /* Forward past zfs: */ currdev = strchr(currdev, ':'); currdev++; diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c index d836e42..d5220e8 100644 --- a/sys/cam/ata/ata_all.c +++ b/sys/cam/ata/ata_all.c @@ -75,13 +75,18 @@ ata_op_string(struct ata_cmd *cmd) if (cmd->control & 0x04) return ("SOFT_RESET"); switch (cmd->command) { - case 0x00: return ("NOP"); + case 0x00: + switch (cmd->features) { + case 0x00: return ("NOP FLUSHQUEUE"); + case 0x01: return ("NOP AUTOPOLL"); + } + return ("NOP"); case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR"); case 0x06: switch (cmd->features) { - case 0x01: return ("DSM TRIM"); - } - return "DSM"; + case 0x01: return ("DSM TRIM"); + } + return "DSM"; case 0x08: return ("DEVICE_RESET"); case 0x20: return ("READ"); case 0x24: return ("READ48"); @@ -105,6 +110,12 @@ ata_op_string(struct ata_cmd *cmd) case 0x3f: return ("WRITE_LOG_EXT"); case 0x40: return ("READ_VERIFY"); case 0x42: return ("READ_VERIFY48"); + case 0x45: + switch (cmd->features) { + case 0x55: return ("WRITE_UNCORRECTABLE48 PSEUDO"); + case 0xaa: return ("WRITE_UNCORRECTABLE48 FLAGGED"); + } + return "WRITE_UNCORRECTABLE48"; case 0x51: return ("CONFIGURE_STREAM"); case 0x60: return ("READ_FPDMA_QUEUED"); case 0x61: return ("WRITE_FPDMA_QUEUED"); @@ -128,7 +139,18 @@ ata_op_string(struct ata_cmd *cmd) case 0xa0: return ("PACKET"); case 0xa1: return ("ATAPI_IDENTIFY"); case 0xa2: return ("SERVICE"); - case 0xb0: return ("SMART"); + case 0xb0: + switch(cmd->features) { + case 0xd0: return ("SMART READ ATTR VALUES"); + case 0xd1: return ("SMART READ ATTR THRESHOLDS"); + case 0xd3: return ("SMART SAVE ATTR VALUES"); + case 0xd4: return ("SMART EXECUTE OFFLINE IMMEDIATE"); + case 0xd5: return ("SMART READ LOG DATA"); + case 0xd8: return ("SMART ENABLE OPERATION"); + case 0xd9: return ("SMART DISABLE OPERATION"); + case 0xda: return ("SMART RETURN STATUS"); + } + return ("SMART"); case 0xb1: return ("DEVICE CONFIGURATION"); case 0xc0: return ("CFA_ERASE"); case 0xc4: return ("READ_MUL"); @@ -158,18 +180,22 @@ ata_op_string(struct ata_cmd *cmd) case 0xed: return ("MEDIA_EJECT"); case 0xef: switch (cmd->features) { - case 0x03: return ("SETFEATURES SET TRANSFER MODE"); - case 0x02: return ("SETFEATURES ENABLE WCACHE"); - case 0x82: return ("SETFEATURES DISABLE WCACHE"); - case 0x06: return ("SETFEATURES ENABLE PUIS"); - case 0x86: return ("SETFEATURES DISABLE PUIS"); - case 0x07: return ("SETFEATURES SPIN-UP"); - case 0x10: return ("SETFEATURES ENABLE SATA FEATURE"); - case 0x90: return ("SETFEATURES DISABLE SATA FEATURE"); - case 0xaa: return ("SETFEATURES ENABLE RCACHE"); - case 0x55: return ("SETFEATURES DISABLE RCACHE"); - } - return "SETFEATURES"; + case 0x03: return ("SETFEATURES SET TRANSFER MODE"); + case 0x02: return ("SETFEATURES ENABLE WCACHE"); + case 0x82: return ("SETFEATURES DISABLE WCACHE"); + case 0x06: return ("SETFEATURES ENABLE PUIS"); + case 0x86: return ("SETFEATURES DISABLE PUIS"); + case 0x07: return ("SETFEATURES SPIN-UP"); + case 0x10: return ("SETFEATURES ENABLE SATA FEATURE"); + case 0x90: return ("SETFEATURES DISABLE SATA FEATURE"); + case 0xaa: return ("SETFEATURES ENABLE RCACHE"); + case 0x55: return ("SETFEATURES DISABLE RCACHE"); + case 0x5d: return ("SETFEATURES ENABLE RELIRQ"); + case 0xdd: return ("SETFEATURES DISABLE RELIRQ"); + case 0x5e: return ("SETFEATURES ENABLE SRVIRQ"); + case 0xde: return ("SETFEATURES DISABLE SRVIRQ"); + } + return "SETFEATURES"; case 0xf1: return ("SECURITY_SET_PASSWORD"); case 0xf2: return ("SECURITY_UNLOCK"); case 0xf3: return ("SECURITY_ERASE_PREPARE"); diff --git a/sys/cddl/dev/fbt/arm/fbt_isa.c b/sys/cddl/dev/fbt/arm/fbt_isa.c index 0e948dd..2e0e5a5 100644 --- a/sys/cddl/dev/fbt/arm/fbt_isa.c +++ b/sys/cddl/dev/fbt/arm/fbt_isa.c @@ -83,7 +83,7 @@ fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val) { *fbt->fbtp_patchpoint = val; - cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, sizeof(val)); + icache_sync((vm_offset_t)fbt->fbtp_patchpoint, sizeof(val)); } int diff --git a/sys/compat/cloudabi/cloudabi_proc.c b/sys/compat/cloudabi/cloudabi_proc.c index d917337..8d0b6e7 100644 --- a/sys/compat/cloudabi/cloudabi_proc.c +++ b/sys/compat/cloudabi/cloudabi_proc.c @@ -75,12 +75,16 @@ int cloudabi_sys_proc_fork(struct thread *td, struct cloudabi_sys_proc_fork_args *uap) { + struct fork_req fr; struct filecaps fcaps = {}; - struct proc *p2; int error, fd; cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_EVENT); - error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0, &fcaps); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; + fr.fr_pd_fd = &fd; + fr.fr_pd_fcaps = &fcaps; + error = fork1(td, &fr); if (error != 0) return (error); /* Return the file descriptor to the parent process. */ diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c index d0f73ad..c12f198 100644 --- a/sys/compat/linux/linux_fork.c +++ b/sys/compat/linux/linux_fork.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); int linux_fork(struct thread *td, struct linux_fork_args *args) { + struct fork_req fr; int error; struct proc *p2; struct thread *td2; @@ -73,8 +74,10 @@ linux_fork(struct thread *td, struct linux_fork_args *args) printf(ARGS(fork, "")); #endif - if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0, - NULL)) != 0) + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFSTOPPED; + fr.fr_procp = &p2; + if ((error = fork1(td, &fr)) != 0) return (error); td2 = FIRST_THREAD_IN_PROC(p2); @@ -97,6 +100,7 @@ linux_fork(struct thread *td, struct linux_fork_args *args) int linux_vfork(struct thread *td, struct linux_vfork_args *args) { + struct fork_req fr; int error; struct proc *p2; struct thread *td2; @@ -106,8 +110,10 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args) printf(ARGS(vfork, "")); #endif - if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED, - 0, &p2, NULL, 0, NULL)) != 0) + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED; + fr.fr_procp = &p2; + if ((error = fork1(td, &fr)) != 0) return (error); td2 = FIRST_THREAD_IN_PROC(p2); @@ -130,6 +136,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args) static int linux_clone_proc(struct thread *td, struct linux_clone_args *args) { + struct fork_req fr; int error, ff = RFPROC | RFSTOPPED; struct proc *p2; struct thread *td2; @@ -170,7 +177,10 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args) if (args->flags & LINUX_CLONE_VFORK) ff |= RFPPWAIT; - error = fork1(td, ff, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = ff; + fr.fr_procp = &p2; + error = fork1(td, &fr); if (error) return (error); diff --git a/sys/conf/files.arm b/sys/conf/files.arm index 9f3a6bf..bc5d8a3 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -14,14 +14,14 @@ arm/arm/cpufunc_asm.S standard arm/arm/cpufunc_asm_arm9.S optional cpu_arm9 | cpu_arm9e arm/arm/cpufunc_asm_arm11.S optional cpu_arm1176 arm/arm/cpufunc_asm_arm11x6.S optional cpu_arm1176 -arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342 +arm/arm/cpufunc_asm_armv4.S optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_81342 arm/arm/cpufunc_asm_armv5_ec.S optional cpu_arm9e arm/arm/cpufunc_asm_armv6.S optional cpu_arm1176 arm/arm/cpufunc_asm_armv7.S optional cpu_cortexa | cpu_krait | cpu_mv_pj4b arm/arm/cpufunc_asm_fa526.S optional cpu_fa526 arm/arm/cpufunc_asm_pj4b.S optional cpu_mv_pj4b arm/arm/cpufunc_asm_sheeva.S optional cpu_arm9e -arm/arm/cpufunc_asm_xscale.S optional cpu_xscale_80321 | cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_80219 | cpu_xscale_81342 +arm/arm/cpufunc_asm_xscale.S optional cpu_xscale_pxa2x0 | cpu_xscale_ixp425 | cpu_xscale_81342 arm/arm/cpufunc_asm_xscale_c3.S optional cpu_xscale_81342 arm/arm/cpuinfo.c standard arm/arm/cpu_asm-v6.S optional armv6 diff --git a/sys/conf/options b/sys/conf/options index c7cd5818..f1b2af4 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -918,6 +918,7 @@ VNET_DEBUG opt_global.h # Common Flash Interface (CFI) options CFI_SUPPORT_STRATAFLASH opt_cfi.h CFI_ARMEDANDDANGEROUS opt_cfi.h +CFI_HARDWAREBYTESWAP opt_cfi.h # Sound options SND_DEBUG opt_snd.h diff --git a/sys/conf/options.arm b/sys/conf/options.arm index ef66413..7beae5b 100644 --- a/sys/conf/options.arm +++ b/sys/conf/options.arm @@ -15,8 +15,6 @@ CPU_CORTEXA opt_global.h CPU_KRAIT opt_global.h CPU_FA526 opt_global.h CPU_MV_PJ4B opt_global.h -CPU_XSCALE_80219 opt_global.h -CPU_XSCALE_80321 opt_global.h CPU_XSCALE_81342 opt_global.h CPU_XSCALE_IXP425 opt_global.h CPU_XSCALE_IXP435 opt_global.h diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c index 753e8e5..e325f6e 100644 --- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c +++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c @@ -48,6 +48,7 @@ #include <vm/vm_phys.h> #include <machine/bus.h> +#include <machine/cpu.h> #include <arm/broadcom/bcm2835/bcm2835_mbox.h> #include <arm/broadcom/bcm2835/bcm2835_vcbus.h> @@ -411,6 +412,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, int run, addridx, actual_pages; int err; vm_paddr_t pagelist_phys; + vm_paddr_t pa; offset = (vm_offset_t)buf & (PAGE_SIZE - 1); num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE; @@ -533,7 +535,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, (fragments - g_fragments_base)/g_fragment_size; } - cpu_dcache_wbinv_range((vm_offset_t)buf, count); + pa = pmap_extract(PCPU_GET(curpmap), (vm_offset_t)buf); + dcache_wbinv_poc((vm_offset_t)buf, pa, count); bus_dmamap_sync(bi->pagelist_dma_tag, bi->pagelist_dma_map, BUS_DMASYNC_PREWRITE); diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 118e38e..8cefa9e 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -496,7 +496,18 @@ ata_cmd2str(struct ata_request *request) } } else { switch (request->u.ata.command) { - case 0x00: return ("NOP"); + case 0x00: + switch (request->u.ata.feature) { + case 0x00: return ("NOP FLUSHQUEUE"); + case 0x01: return ("NOP AUTOPOLL"); + } + return ("NOP"); + case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR"); + case 0x06: + switch (request->u.ata.feature) { + case 0x01: return ("DSM TRIM"); + } + return "DSM"; case 0x08: return ("DEVICE_RESET"); case 0x20: return ("READ"); case 0x24: return ("READ48"); @@ -504,18 +515,65 @@ ata_cmd2str(struct ata_request *request) case 0x26: return ("READ_DMA_QUEUED48"); case 0x27: return ("READ_NATIVE_MAX_ADDRESS48"); case 0x29: return ("READ_MUL48"); + case 0x2a: return ("READ_STREAM_DMA48"); + case 0x2b: return ("READ_STREAM48"); + case 0x2f: return ("READ_LOG_EXT"); case 0x30: return ("WRITE"); case 0x34: return ("WRITE48"); case 0x35: return ("WRITE_DMA48"); case 0x36: return ("WRITE_DMA_QUEUED48"); case 0x37: return ("SET_MAX_ADDRESS48"); case 0x39: return ("WRITE_MUL48"); + case 0x3a: return ("WRITE_STREAM_DMA48"); + case 0x3b: return ("WRITE_STREAM48"); + case 0x3d: return ("WRITE_DMA_FUA48"); + case 0x3e: return ("WRITE_DMA_QUEUED_FUA48"); + case 0x3f: return ("WRITE_LOG_EXT"); + case 0x40: return ("READ_VERIFY"); + case 0x42: return ("READ_VERIFY48"); + case 0x45: + switch (request->u.ata.feature) { + case 0x55: return ("WRITE_UNCORRECTABLE48 PSEUDO"); + case 0xaa: return ("WRITE_UNCORRECTABLE48 FLAGGED"); + } + return "WRITE_UNCORRECTABLE48"; + case 0x51: return ("CONFIGURE_STREAM"); + case 0x60: return ("READ_FPDMA_QUEUED"); + case 0x61: return ("WRITE_FPDMA_QUEUED"); + case 0x63: return ("NCQ_NON_DATA"); + case 0x64: return ("SEND_FPDMA_QUEUED"); + case 0x65: return ("RECEIVE_FPDMA_QUEUED"); + case 0x67: + if (request->u.ata.feature == 0xec) + return ("SEP_ATTN IDENTIFY"); + switch (request->u.ata.lba) { + case 0x00: return ("SEP_ATTN READ BUFFER"); + case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS"); + case 0x80: return ("SEP_ATTN WRITE BUFFER"); + case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC"); + } + return ("SEP_ATTN"); case 0x70: return ("SEEK"); - case 0xa0: return ("PACKET_CMD"); + case 0x87: return ("CFA_TRANSLATE_SECTOR"); + case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC"); + case 0x92: return ("DOWNLOAD_MICROCODE"); + case 0xa0: return ("PACKET"); case 0xa1: return ("ATAPI_IDENTIFY"); case 0xa2: return ("SERVICE"); - case 0xb0: return ("SMART"); - case 0xc0: return ("CFA ERASE"); + case 0xb0: + switch(request->u.ata.feature) { + case 0xd0: return ("SMART READ ATTR VALUES"); + case 0xd1: return ("SMART READ ATTR THRESHOLDS"); + case 0xd3: return ("SMART SAVE ATTR VALUES"); + case 0xd4: return ("SMART EXECUTE OFFLINE IMMEDIATE"); + case 0xd5: return ("SMART READ LOG DATA"); + case 0xd8: return ("SMART ENABLE OPERATION"); + case 0xd9: return ("SMART DISABLE OPERATION"); + case 0xda: return ("SMART RETURN STATUS"); + } + return ("SMART"); + case 0xb1: return ("DEVICE CONFIGURATION"); + case 0xc0: return ("CFA_ERASE"); case 0xc4: return ("READ_MUL"); case 0xc5: return ("WRITE_MUL"); case 0xc6: return ("SET_MULTI"); @@ -523,22 +581,48 @@ ata_cmd2str(struct ata_request *request) case 0xc8: return ("READ_DMA"); case 0xca: return ("WRITE_DMA"); case 0xcc: return ("WRITE_DMA_QUEUED"); + case 0xcd: return ("CFA_WRITE_MULTIPLE_WITHOUT_ERASE"); + case 0xce: return ("WRITE_MUL_FUA48"); + case 0xd1: return ("CHECK_MEDIA_CARD_TYPE"); + case 0xda: return ("GET_MEDIA_STATUS"); + case 0xde: return ("MEDIA_LOCK"); + case 0xdf: return ("MEDIA_UNLOCK"); + case 0xe0: return ("STANDBY_IMMEDIATE"); + case 0xe1: return ("IDLE_IMMEDIATE"); + case 0xe2: return ("STANDBY"); + case 0xe3: return ("IDLE"); + case 0xe4: return ("READ_BUFFER/PM"); + case 0xe5: return ("CHECK_POWER_MODE"); case 0xe6: return ("SLEEP"); case 0xe7: return ("FLUSHCACHE"); + case 0xe8: return ("WRITE_PM"); case 0xea: return ("FLUSHCACHE48"); case 0xec: return ("ATA_IDENTIFY"); + case 0xed: return ("MEDIA_EJECT"); case 0xef: switch (request->u.ata.feature) { case 0x03: return ("SETFEATURES SET TRANSFER MODE"); case 0x02: return ("SETFEATURES ENABLE WCACHE"); case 0x82: return ("SETFEATURES DISABLE WCACHE"); + case 0x06: return ("SETFEATURES ENABLE PUIS"); + case 0x86: return ("SETFEATURES DISABLE PUIS"); + case 0x07: return ("SETFEATURES SPIN-UP"); + case 0x10: return ("SETFEATURES ENABLE SATA FEATURE"); + case 0x90: return ("SETFEATURES DISABLE SATA FEATURE"); case 0xaa: return ("SETFEATURES ENABLE RCACHE"); case 0x55: return ("SETFEATURES DISABLE RCACHE"); + case 0x5d: return ("SETFEATURES ENABLE RELIRQ"); + case 0xdd: return ("SETFEATURES DISABLE RELIRQ"); + case 0x5e: return ("SETFEATURES ENABLE SRVIRQ"); + case 0xde: return ("SETFEATURES DISABLE SRVIRQ"); } - sprintf(buffer, "SETFEATURES 0x%02x", - request->u.ata.feature); - return (buffer); - case 0xf5: return ("SECURITY_FREE_LOCK"); + return "SETFEATURES"; + case 0xf1: return ("SECURITY_SET_PASSWORD"); + case 0xf2: return ("SECURITY_UNLOCK"); + case 0xf3: return ("SECURITY_ERASE_PREPARE"); + case 0xf4: return ("SECURITY_ERASE_UNIT"); + case 0xf5: return ("SECURITY_FREEZE_LOCK"); + case 0xf6: return ("SECURITY_DISABLE_PASSWORD"); case 0xf8: return ("READ_NATIVE_MAX_ADDRESS"); case 0xf9: return ("SET_MAX_ADDRESS"); } diff --git a/sys/dev/cfi/cfi_core.c b/sys/dev/cfi/cfi_core.c index 5150b77..d292e1a 100644 --- a/sys/dev/cfi/cfi_core.c +++ b/sys/dev/cfi/cfi_core.c @@ -99,11 +99,17 @@ cfi_read(struct cfi_softc *sc, u_int ofs) break; case 2: sval = bus_space_read_2(sc->sc_tag, sc->sc_handle, ofs); +#ifdef CFI_HARDWAREBYTESWAP + val = sval; +#else val = le16toh(sval); +#endif break; case 4: val = bus_space_read_4(sc->sc_tag, sc->sc_handle, ofs); +#ifndef CFI_HARDWAREBYTESWAP val = le32toh(val); +#endif break; default: val = ~0; @@ -122,10 +128,19 @@ cfi_write(struct cfi_softc *sc, u_int ofs, u_int val) bus_space_write_1(sc->sc_tag, sc->sc_handle, ofs, val); break; case 2: +#ifdef CFI_HARDWAREBYTESWAP + bus_space_write_2(sc->sc_tag, sc->sc_handle, ofs, val); +#else bus_space_write_2(sc->sc_tag, sc->sc_handle, ofs, htole16(val)); + +#endif break; case 4: +#ifdef CFI_HARDWAREBYTESWAP + bus_space_write_4(sc->sc_tag, sc->sc_handle, ofs, val); +#else bus_space_write_4(sc->sc_tag, sc->sc_handle, ofs, htole32(val)); +#endif break; } } diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c index d70a948..2cfad26 100644 --- a/sys/dev/cxgb/cxgb_sge.c +++ b/sys/dev/cxgb/cxgb_sge.c @@ -738,7 +738,7 @@ refill_fl(adapter_t *sc, struct sge_fl *q, int n) cl, q->buf_size, refill_fl_cb, &cb_arg, 0); if (err != 0 || cb_arg.error) { - if (q->zone == zone_pack) + if (q->zone != zone_pack) uma_zfree(q->zone, cl); m_free(m); goto done; diff --git a/sys/dev/e1000/e1000_80003es2lan.c b/sys/dev/e1000/e1000_80003es2lan.c index b948bb4..e7c42d5 100644 --- a/sys/dev/e1000/e1000_80003es2lan.c +++ b/sys/dev/e1000/e1000_80003es2lan.c @@ -851,11 +851,17 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) e1000_release_phy_80003es2lan(hw); /* Disable IBIST slave mode (far-end loopback) */ - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); + ret_val = e1000_read_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data); + if (!ret_val) { + kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_INBAND_PARAM, + kum_reg_data); + if (ret_val) + DEBUGOUT("Error disabling far-end loopback\n"); + } else + DEBUGOUT("Error disabling far-end loopback\n"); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) @@ -911,11 +917,18 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) return ret_val; /* Disable IBIST slave mode (far-end loopback) */ - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); + ret_val = + e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, + &kum_reg_data); + if (!ret_val) { + kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_INBAND_PARAM, + kum_reg_data); + if (ret_val) + DEBUGOUT("Error disabling far-end loopback\n"); + } else + DEBUGOUT("Error disabling far-end loopback\n"); /* Set the transmit descriptor write-back policy */ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0)); diff --git a/sys/dev/e1000/e1000_82540.c b/sys/dev/e1000/e1000_82540.c index 68f92c6..2d03b8f 100644 --- a/sys/dev/e1000/e1000_82540.c +++ b/sys/dev/e1000/e1000_82540.c @@ -66,7 +66,7 @@ static s32 e1000_read_mac_addr_82540(struct e1000_hw *hw); static s32 e1000_init_phy_params_82540(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; @@ -329,7 +329,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 txdctl, ctrl_ext; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 i; DEBUGFUNC("e1000_init_hw_82540"); @@ -411,7 +411,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw) static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw) { u32 ctrl; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 data; DEBUGFUNC("e1000_setup_copper_link_82540"); @@ -498,7 +498,7 @@ out: **/ static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 nvm_data; DEBUGFUNC("e1000_adjust_serdes_amplitude_82540"); @@ -528,7 +528,7 @@ out: **/ static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 default_page = 0; u16 phy_data; diff --git a/sys/dev/e1000/e1000_82541.c b/sys/dev/e1000/e1000_82541.c index 5961555..55d51087 100644 --- a/sys/dev/e1000/e1000_82541.c +++ b/sys/dev/e1000/e1000_82541.c @@ -85,7 +85,7 @@ static const u16 e1000_igp_cable_length_table[] = { static s32 e1000_init_phy_params_82541(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_init_phy_params_82541"); @@ -295,7 +295,7 @@ void e1000_init_function_pointers_82541(struct e1000_hw *hw) **/ static s32 e1000_reset_hw_82541(struct e1000_hw *hw) { - u32 ledctl, ctrl, icr, manc; + u32 ledctl, ctrl, manc; DEBUGFUNC("e1000_reset_hw_82541"); @@ -317,6 +317,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw) /* Must reset the Phy before resetting the MAC */ if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST)); + E1000_WRITE_FLUSH(hw); msec_delay(5); } @@ -359,7 +360,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); /* Clear any pending interrupt events. */ - icr = E1000_READ_REG(hw, E1000_ICR); + E1000_READ_REG(hw, E1000_ICR); return E1000_SUCCESS; } diff --git a/sys/dev/e1000/e1000_82542.c b/sys/dev/e1000/e1000_82542.c index b2d676e..4cca9b2 100644 --- a/sys/dev/e1000/e1000_82542.c +++ b/sys/dev/e1000/e1000_82542.c @@ -317,7 +317,7 @@ static s32 e1000_init_hw_82542(struct e1000_hw *hw) static s32 e1000_setup_link_82542(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_setup_link_82542"); @@ -565,7 +565,7 @@ static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw) * * Reads the device MAC address from the EEPROM and stores the value. **/ -static s32 e1000_read_mac_addr_82542(struct e1000_hw *hw) +s32 e1000_read_mac_addr_82542(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 offset, nvm_data, i; diff --git a/sys/dev/e1000/e1000_82543.c b/sys/dev/e1000/e1000_82543.c index b9a53bd..474387d 100644 --- a/sys/dev/e1000/e1000_82543.c +++ b/sys/dev/e1000/e1000_82543.c @@ -900,7 +900,7 @@ static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw) **/ static s32 e1000_reset_hw_82543(struct e1000_hw *hw) { - u32 ctrl, icr; + u32 ctrl; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_reset_hw_82543"); @@ -942,7 +942,7 @@ static s32 e1000_reset_hw_82543(struct e1000_hw *hw) /* Masking off and clearing any pending interrupts */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - icr = E1000_READ_REG(hw, E1000_ICR); + E1000_READ_REG(hw, E1000_ICR); return ret_val; } diff --git a/sys/dev/e1000/e1000_82571.h b/sys/dev/e1000/e1000_82571.h index 1d7718e..8e5ca56 100644 --- a/sys/dev/e1000/e1000_82571.h +++ b/sys/dev/e1000/e1000_82571.h @@ -50,9 +50,10 @@ #define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */ #define E1000_EIAC_MASK_82574 0x01F00000 -#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */ +#define E1000_IVAR_INT_ALLOC_VALID 0x8 -#define E1000_RXCFGL 0x0B634 /* TimeSync Rx EtherType & Msg Type Reg - RW */ +/* Manageability Operation Mode mask */ +#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 #define E1000_BASE1000T_STATUS 10 #define E1000_IDLE_ERROR_COUNT_MASK 0xFF diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c index 10653f8..38770a3 100644 --- a/sys/dev/e1000/e1000_82575.c +++ b/sys/dev/e1000/e1000_82575.c @@ -278,6 +278,11 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) if (ret_val) goto out; } + if (phy->id == M88E1543_E_PHY_ID) { + ret_val = e1000_initialize_M88E1543_phy(hw); + if (ret_val) + goto out; + } break; case IGP03E1000_E_PHY_ID: case IGP04E1000_E_PHY_ID: @@ -1235,7 +1240,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) DEBUGFUNC("e1000_check_for_link_media_swap"); - /* Check the copper medium. */ + /* Check for copper. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); if (ret_val) return ret_val; @@ -1247,7 +1252,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_COPPER; - /* Check the other medium. */ + /* Check for other. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); if (ret_val) return ret_val; @@ -1256,11 +1261,6 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) if (ret_val) return ret_val; - /* reset page to 0 */ - ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); - if (ret_val) - return ret_val; - if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_OTHER; @@ -1268,8 +1268,20 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) if (port && (hw->dev_spec._82575.media_port != port)) { hw->dev_spec._82575.media_port = port; hw->dev_spec._82575.media_changed = TRUE; + } + + if (port == E1000_MEDIA_PORT_COPPER) { + /* reset page to 0 */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; + e1000_check_for_link_82575(hw); } else { - ret_val = e1000_check_for_link_82575(hw); + e1000_check_for_link_82575(hw); + /* reset page to 0 */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); + if (ret_val) + return ret_val; } return E1000_SUCCESS; @@ -2136,7 +2148,13 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; int i, ms_wait; - DEBUGFUNC("e1000_rx_fifo_workaround_82575"); + DEBUGFUNC("e1000_rx_fifo_flush_82575"); + + /* disable IPv6 options as per hardware errata */ + rfctl = E1000_READ_REG(hw, E1000_RFCTL); + rfctl |= E1000_RFCTL_IPV6_EX_DIS; + E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); + if (hw->mac.type != e1000_82575 || !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) return; @@ -2164,7 +2182,6 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) * incoming packets are rejected. Set enable and wait 2ms so that * any packet that was coming in as RCTL.EN was set is flushed */ - rfctl = E1000_READ_REG(hw, E1000_RFCTL); E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); rlpml = E1000_READ_REG(hw, E1000_RLPML); @@ -2806,7 +2823,7 @@ s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) * e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY * @hw: pointer to the HW structure * - * Initialize Marverl 1512 to work correctly with Avoton. + * Initialize Marvell 1512 to work correctly with Avoton. **/ s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw) { @@ -2892,13 +2909,114 @@ out: } /** + * e1000_initialize_M88E1543_phy - Initialize M88E1543 PHY + * @hw: pointer to the HW structure + * + * Initialize Marvell 1543 to work correctly with Avoton. + **/ +s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("e1000_initialize_M88E1543_phy"); + + /* Check if this is correct PHY. */ + if (phy->id != M88E1543_E_PHY_ID) + goto out; + + /* Switch to PHY page 0xFF. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xDC0C); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159); + if (ret_val) + goto out; + + /* Switch to PHY page 0xFB. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB); + if (ret_val) + goto out; + + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0xC00D); + if (ret_val) + goto out; + + /* Switch to PHY page 0x12. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12); + if (ret_val) + goto out; + + /* Change mode to SGMII-to-Copper */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001); + if (ret_val) + goto out; + + /* Switch to PHY page 1. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x1); + if (ret_val) + goto out; + + /* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_FIBER_CTRL, 0x9140); + if (ret_val) + goto out; + + /* Return the PHY to page 0. */ + ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); + if (ret_val) + goto out; + + ret_val = phy->ops.commit(hw); + if (ret_val) { + DEBUGOUT("Error committing the PHY changes\n"); + return ret_val; + } + + msec_delay(1000); +out: + return ret_val; +} + +/** * e1000_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure + * @adv1g: boolean flag enabling 1G EEE advertisement + * @adv100m: boolean flag enabling 100M EEE advertisement * * Enable/disable EEE based on setting in dev_spec structure. * **/ -s32 e1000_set_eee_i350(struct e1000_hw *hw) +s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M) { u32 ipcnfg, eeer; @@ -2914,7 +3032,16 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw) if (!(hw->dev_spec._82575.eee_disable)) { u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); - ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); + if (adv100M) + ipcnfg |= E1000_IPCNFG_EEE_100M_AN; + else + ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN; + + if (adv1G) + ipcnfg |= E1000_IPCNFG_EEE_1G_AN; + else + ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN; + eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); @@ -2938,11 +3065,13 @@ out: /** * e1000_set_eee_i354 - Enable/disable EEE support * @hw: pointer to the HW structure + * @adv1g: boolean flag enabling 1G EEE advertisement + * @adv100m: boolean flag enabling 100M EEE advertisement * * Enable/disable EEE legacy mode based on setting in dev_spec structure. * **/ -s32 e1000_set_eee_i354(struct e1000_hw *hw) +s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; @@ -2984,8 +3113,16 @@ s32 e1000_set_eee_i354(struct e1000_hw *hw) if (ret_val) goto out; - phy_data |= E1000_EEE_ADV_100_SUPPORTED | - E1000_EEE_ADV_1000_SUPPORTED; + if (adv100M) + phy_data |= E1000_EEE_ADV_100_SUPPORTED; + else + phy_data &= ~E1000_EEE_ADV_100_SUPPORTED; + + if (adv1G) + phy_data |= E1000_EEE_ADV_1000_SUPPORTED; + else + phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED; + ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, phy_data); diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h index 503fdce..45fe132 100644 --- a/sys/dev/e1000/e1000_82575.h +++ b/sys/dev/e1000/e1000_82575.h @@ -495,10 +495,11 @@ void e1000_rlpml_set_vf(struct e1000_hw *, u16); s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type); u16 e1000_rxpbs_adjust_82580(u32 data); s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data); -s32 e1000_set_eee_i350(struct e1000_hw *); -s32 e1000_set_eee_i354(struct e1000_hw *); +s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M); +s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M); s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *); s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw); +s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw); /* I2C SDA and SCL timing parameters for standard mode */ #define E1000_I2C_T_HD_STA 4 diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c index 5db22db..28379cc 100644 --- a/sys/dev/e1000/e1000_api.c +++ b/sys/dev/e1000/e1000_api.c @@ -299,6 +299,13 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_PCH_I218_V3: mac->type = e1000_pch_lpt; break; + case E1000_DEV_ID_PCH_SPT_I219_LM: + case E1000_DEV_ID_PCH_SPT_I219_V: + case E1000_DEV_ID_PCH_SPT_I219_LM2: + case E1000_DEV_ID_PCH_SPT_I219_V2: + case E1000_DEV_ID_PCH_LBG_I219_LM3: + mac->type = e1000_pch_spt; + break; case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: @@ -449,6 +456,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: e1000_init_function_pointers_ich8lan(hw); break; case e1000_82575: diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h index 9472ca4..e33fe0f 100644 --- a/sys/dev/e1000/e1000_defines.h +++ b/sys/dev/e1000/e1000_defines.h @@ -197,6 +197,8 @@ #define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ #define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */ +#define E1000_RCTL_RDMTS_HEX 0x00010000 +#define E1000_RCTL_RDMTS1_HEX E1000_RCTL_RDMTS_HEX #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ #define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ #define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ @@ -753,6 +755,12 @@ #define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ +/* HH Time Sync */ +#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */ +#define E1000_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */ +#define E1000_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */ +#define E1000_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */ + #define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ #define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ #define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 @@ -849,6 +857,7 @@ #define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */ #define E1000_M88E1543_EEE_CTRL_1 0x0 #define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */ +#define E1000_M88E1543_FIBER_CTRL 0x0 /* Fiber Control Register */ #define E1000_EEE_ADV_DEV_I354 7 #define E1000_EEE_ADV_ADDR_I354 60 #define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */ @@ -1020,9 +1029,7 @@ /* NVM Addressing bits based on type 0=small, 1=large */ #define E1000_EECD_ADDR_BITS 0x00000400 #define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */ -#ifndef E1000_NVM_GRANT_ATTEMPTS #define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ -#endif #define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ #define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ #define E1000_EECD_SIZE_EX_SHIFT 11 diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h index 8ae4b20..1792e14 100644 --- a/sys/dev/e1000/e1000_hw.h +++ b/sys/dev/e1000/e1000_hw.h @@ -137,6 +137,11 @@ struct e1000_hw; #define E1000_DEV_ID_PCH_I218_V2 0x15A1 #define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */ #define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_LM 0x156F /* Sunrise Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_V 0x1570 /* Sunrise Point PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* Sunrise Point-H PCH */ +#define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* Sunrise Point-H PCH */ +#define E1000_DEV_ID_PCH_LBG_I219_LM3 0x15B9 /* LEWISBURG PCH */ #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 @@ -222,6 +227,7 @@ enum e1000_mac_type { e1000_pchlan, e1000_pch2lan, e1000_pch_lpt, + e1000_pch_spt, e1000_82575, e1000_82576, e1000_82580, @@ -805,7 +811,7 @@ struct e1000_mac_info { enum e1000_serdes_link_state serdes_link_state; bool serdes_has_link; bool tx_pkt_filtering; - u32 max_frame_size; + u32 max_frame_size; }; struct e1000_phy_info { diff --git a/sys/dev/e1000/e1000_i210.c b/sys/dev/e1000/e1000_i210.c index 563f11a..cd8d7c7 100644 --- a/sys/dev/e1000/e1000_i210.c +++ b/sys/dev/e1000/e1000_i210.c @@ -883,6 +883,35 @@ static s32 e1000_pll_workaround_i210(struct e1000_hw *hw) } /** + * e1000_get_cfg_done_i210 - Read config done bit + * @hw: pointer to the HW structure + * + * Read the management control register for the config done bit for + * completion status. NOTE: silicon which is EEPROM-less will fail trying + * to read the config done bit, so an error is *ONLY* logged and returns + * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon + * would not be able to be reset or change link. + **/ +static s32 e1000_get_cfg_done_i210(struct e1000_hw *hw) +{ + s32 timeout = PHY_CFG_TIMEOUT; + u32 mask = E1000_NVM_CFG_DONE_PORT_0; + + DEBUGFUNC("e1000_get_cfg_done_i210"); + + while (timeout) { + if (E1000_READ_REG(hw, E1000_EEMNGCTL_I210) & mask) + break; + msec_delay(1); + timeout--; + } + if (!timeout) + DEBUGOUT("MNG configuration cycle has not completed.\n"); + + return E1000_SUCCESS; +} + +/** * e1000_init_hw_i210 - Init hw for I210/I211 * @hw: pointer to the HW structure * @@ -899,6 +928,7 @@ s32 e1000_init_hw_i210(struct e1000_hw *hw) if (ret_val != E1000_SUCCESS) return ret_val; } + hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i210; ret_val = e1000_init_hw_82575(hw); return ret_val; } diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c index 75fcade..9b9a090 100644 --- a/sys/dev/e1000/e1000_ich8lan.c +++ b/sys/dev/e1000/e1000_ich8lan.c @@ -92,10 +92,13 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active); static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); +static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data); static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw); +static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw); static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data); static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw); @@ -123,6 +126,14 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 *data); static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, u8 size, u16 *data); +static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, + u32 *data); +static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 *data); +static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, + u32 offset, u32 data); +static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 dword); static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data); static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, @@ -232,16 +243,21 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) if (ret_val) return FALSE; out: - if (hw->mac.type == e1000_pch_lpt) { - /* Unforce SMBus mode in PHY */ - hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg); - phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; - hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg); + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { + /* Only unforce SMBus if ME is not active */ + if (!(E1000_READ_REG(hw, E1000_FWSM) & + E1000_ICH_FWSM_FW_VALID)) { + /* Unforce SMBus mode in PHY */ + hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg); + phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; + hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg); - /* Unforce SMBus mode in MAC */ - mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); - mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + /* Unforce SMBus mode in MAC */ + mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + } } return TRUE; @@ -328,6 +344,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) */ switch (hw->mac.type) { case e1000_pch_lpt: + case e1000_pch_spt: if (e1000_phy_is_accessible_pchlan(hw)) break; @@ -475,6 +492,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) /* fall-through */ case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ @@ -617,36 +635,57 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 gfpreg, sector_base_addr, sector_end_addr; u16 i; + u32 nvm_size; DEBUGFUNC("e1000_init_nvm_params_ich8lan"); - /* Can't read flash registers if the register set isn't mapped. */ nvm->type = e1000_nvm_flash_sw; - if (!hw->flash_address) { - DEBUGOUT("ERROR: Flash registers not mapped\n"); - return -E1000_ERR_CONFIG; - } - gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); + if (hw->mac.type == e1000_pch_spt) { + /* in SPT, gfpreg doesn't exist. NVM size is taken from the + * STRAP register. This is because in SPT the GbE Flash region + * is no longer accessed through the flash registers. Instead, + * the mechanism has changed, and the Flash region access + * registers are now implemented in GbE memory space. + */ + nvm->flash_base_addr = 0; + nvm_size = + (((E1000_READ_REG(hw, E1000_STRAP) >> 1) & 0x1F) + 1) + * NVM_SIZE_MULTIPLIER; + nvm->flash_bank_size = nvm_size / 2; + /* Adjust to word count */ + nvm->flash_bank_size /= sizeof(u16); + /* Set the base address for flash register access */ + hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR; + } else { + /* Can't read flash registers if register set isn't mapped. */ + if (!hw->flash_address) { + DEBUGOUT("ERROR: Flash registers not mapped\n"); + return -E1000_ERR_CONFIG; + } - /* sector_X_addr is a "sector"-aligned address (4096 bytes) - * Add 1 to sector_end_addr since this sector is included in - * the overall size. - */ - sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; - sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; + gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); - /* flash_base_addr is byte-aligned */ - nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; + /* sector_X_addr is a "sector"-aligned address (4096 bytes) + * Add 1 to sector_end_addr since this sector is included in + * the overall size. + */ + sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; + sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; - /* find total size of the NVM, then cut in half since the total - * size represents two separate NVM banks. - */ - nvm->flash_bank_size = ((sector_end_addr - sector_base_addr) - << FLASH_SECTOR_ADDR_SHIFT); - nvm->flash_bank_size /= 2; - /* Adjust to word count */ - nvm->flash_bank_size /= sizeof(u16); + /* flash_base_addr is byte-aligned */ + nvm->flash_base_addr = sector_base_addr + << FLASH_SECTOR_ADDR_SHIFT; + + /* find total size of the NVM, then cut in half since the total + * size represents two separate NVM banks. + */ + nvm->flash_bank_size = ((sector_end_addr - sector_base_addr) + << FLASH_SECTOR_ADDR_SHIFT); + nvm->flash_bank_size /= 2; + /* Adjust to word count */ + nvm->flash_bank_size /= sizeof(u16); + } nvm->word_size = E1000_SHADOW_RAM_WORDS; @@ -662,8 +701,13 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_ich8lan; nvm->ops.release = e1000_release_nvm_ich8lan; - nvm->ops.read = e1000_read_nvm_ich8lan; - nvm->ops.update = e1000_update_nvm_checksum_ich8lan; + if (hw->mac.type == e1000_pch_spt) { + nvm->ops.read = e1000_read_nvm_spt; + nvm->ops.update = e1000_update_nvm_checksum_spt; + } else { + nvm->ops.read = e1000_read_nvm_ich8lan; + nvm->ops.update = e1000_update_nvm_checksum_ich8lan; + } nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan; nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; nvm->ops.write = e1000_write_nvm_ich8lan; @@ -681,9 +725,6 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; -#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) - u16 pci_cfg; -#endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */ DEBUGFUNC("e1000_init_mac_params_ich8lan"); @@ -752,15 +793,12 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) mac->ops.rar_set = e1000_rar_set_pch2lan; /* fall-through */ case e1000_pch_lpt: + case e1000_pch_spt: /* multicast address update for pch2 */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_pch2lan; + /* fall-through */ case e1000_pchlan: -#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) - /* save PCH revision_id */ - e1000_read_pci_cfg(hw, E1000_PCI_REVISION_ID_REG, &pci_cfg); - hw->revision_id = (u8)(pci_cfg &= 0x000F); -#endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */ /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; /* ID LED init */ @@ -777,7 +815,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) break; } - if (mac->type == e1000_pch_lpt) { + if ((mac->type == e1000_pch_lpt) || + (mac->type == e1000_pch_spt)) { mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES; mac->ops.rar_set = e1000_rar_set_pch_lpt; mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt; @@ -1007,8 +1046,9 @@ release: /* clear FEXTNVM6 bit 8 on link down or 10/100 */ fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK; - if (!link || ((status & E1000_STATUS_SPEED_100) && - (status & E1000_STATUS_FD))) + if ((hw->phy.revision > 5) || !link || + ((status & E1000_STATUS_SPEED_100) && + (status & E1000_STATUS_FD))) goto update_fextnvm6; ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, ®); @@ -1221,6 +1261,7 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) u32 mac_reg; s32 ret_val = E1000_SUCCESS; u16 phy_reg; + u16 oem_reg = 0; if ((hw->mac.type < e1000_pch_lpt) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) || @@ -1276,6 +1317,25 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable + * LPLU and disable Gig speed when entering ULP + */ + if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) { + ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS, + &oem_reg); + if (ret_val) + goto release; + + phy_reg = oem_reg; + phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS; + + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, + phy_reg); + + if (ret_val) + goto release; + } + /* Set Inband ULP Exit, Reset to SMBus mode and * Disable SMBus Release on PERST# in PHY */ @@ -1287,10 +1347,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) if (to_sx) { if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC) phy_reg |= I218_ULP_CONFIG1_WOL_HOST; + else + phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST; phy_reg |= I218_ULP_CONFIG1_STICKY_ULP; + phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT; } else { phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT; + phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP; + phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST; } e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); @@ -1302,6 +1367,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) /* Commit ULP changes in PHY by starting auto ULP configuration */ phy_reg |= I218_ULP_CONFIG1_START; e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); + + if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) && + to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, + oem_reg); + if (ret_val) + goto release; + } + release: hw->phy.ops.release(hw); out: @@ -1352,10 +1426,10 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) E1000_WRITE_REG(hw, E1000_H2ME, mac_reg); } - /* Poll up to 100msec for ME to clear ULP_CFG_DONE */ + /* Poll up to 300msec for ME to clear ULP_CFG_DONE. */ while (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_ULP_CFG_DONE) { - if (i++ == 10) { + if (i++ == 30) { ret_val = -E1000_ERR_PHY; goto out; } @@ -1429,6 +1503,8 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) I218_ULP_CONFIG1_RESET_TO_SMBUS | I218_ULP_CONFIG1_WOL_HOST | I218_ULP_CONFIG1_INBAND_EXIT | + I218_ULP_CONFIG1_EN_ULP_LANPHYPC | + I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST | I218_ULP_CONFIG1_DISABLE_SMB_PERST); e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); @@ -1467,7 +1543,8 @@ out: static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; + s32 ret_val, tipg_reg = 0; + u16 emi_addr, emi_val = 0; bool link; u16 phy_reg; @@ -1500,35 +1577,119 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) * the IPG and reduce Rx latency in the PHY. */ if (((hw->mac.type == e1000_pch2lan) || - (hw->mac.type == e1000_pch_lpt)) && link) { - u32 reg; - reg = E1000_READ_REG(hw, E1000_STATUS); - if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { - u16 emi_addr; + (hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) && link) { + u16 speed, duplex; - reg = E1000_READ_REG(hw, E1000_TIPG); - reg &= ~E1000_TIPG_IPGT_MASK; - reg |= 0xFF; - E1000_WRITE_REG(hw, E1000_TIPG, reg); + e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex); + tipg_reg = E1000_READ_REG(hw, E1000_TIPG); + tipg_reg &= ~E1000_TIPG_IPGT_MASK; + if (duplex == HALF_DUPLEX && speed == SPEED_10) { + tipg_reg |= 0xFF; /* Reduce Rx latency in analog PHY */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; + emi_val = 0; + } else if (hw->mac.type == e1000_pch_spt && + duplex == FULL_DUPLEX && speed != SPEED_1000) { + tipg_reg |= 0xC; + emi_val = 1; + } else { + /* Roll back the default values */ + tipg_reg |= 0x08; + emi_val = 1; + } + + E1000_WRITE_REG(hw, E1000_TIPG, tipg_reg); - if (hw->mac.type == e1000_pch2lan) - emi_addr = I82579_RX_CONFIG; + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + if (hw->mac.type == e1000_pch2lan) + emi_addr = I82579_RX_CONFIG; + else + emi_addr = I217_RX_CONFIG; + ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val); + + if (hw->mac.type == e1000_pch_lpt || + hw->mac.type == e1000_pch_spt) { + u16 phy_reg; + + hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG, + &phy_reg); + phy_reg &= ~I217_PLL_CLOCK_GATE_MASK; + if (speed == SPEED_100 || speed == SPEED_10) + phy_reg |= 0x3E8; else - emi_addr = I217_RX_CONFIG; - ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0); + phy_reg |= 0xFA; + hw->phy.ops.write_reg_locked(hw, + I217_PLL_CLOCK_GATE_REG, + phy_reg); + } + hw->phy.ops.release(hw); - hw->phy.ops.release(hw); + if (ret_val) + return ret_val; - if (ret_val) - return ret_val; + if (hw->mac.type == e1000_pch_spt) { + u16 data; + u16 ptr_gap; + + if (speed == SPEED_1000) { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + ret_val = hw->phy.ops.read_reg_locked(hw, + PHY_REG(776, 20), + &data); + if (ret_val) { + hw->phy.ops.release(hw); + return ret_val; + } + + ptr_gap = (data & (0x3FF << 2)) >> 2; + if (ptr_gap < 0x18) { + data &= ~(0x3FF << 2); + data |= (0x18 << 2); + ret_val = + hw->phy.ops.write_reg_locked(hw, + PHY_REG(776, 20), data); + } + hw->phy.ops.release(hw); + if (ret_val) + return ret_val; + } else { + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + ret_val = hw->phy.ops.write_reg_locked(hw, + PHY_REG(776, 20), + 0xC023); + hw->phy.ops.release(hw); + if (ret_val) + return ret_val; + + } } } + /* I217 Packet Loss issue: + * ensure that FEXTNVM4 Beacon Duration is set correctly + * on power up. + * Set the Beacon Duration for I217 to 8 usec + */ + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { + u32 mac_reg; + + mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4); + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; + E1000_WRITE_REG(hw, E1000_FEXTNVM4, mac_reg); + } + /* Work-around I218 hang issue */ if ((hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || (hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) || @@ -1538,7 +1699,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; } - if (hw->mac.type == e1000_pch_lpt) { + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { /* Set platform power management values for * Latency Tolerance Reporting (LTR) * Optimized Buffer Flush/Fill (OBFF) @@ -1551,6 +1713,19 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) /* Clear link partner's EEE ability */ hw->dev_spec.ich8lan.eee_lp_ability = 0; + /* FEXTNVM6 K1-off workaround */ + if (hw->mac.type == e1000_pch_spt) { + u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG); + u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); + + if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) + fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE; + else + fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE; + + E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6); + } + if (!link) return E1000_SUCCESS; /* No link detected */ @@ -1644,6 +1819,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: hw->phy.ops.init_params = e1000_init_phy_params_pchlan; break; default: @@ -2026,7 +2202,7 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) continue; } blocked = FALSE; - } while (blocked && (i++ < 10)); + } while (blocked && (i++ < 30)); return blocked ? E1000_BLK_PHY_RESET : E1000_SUCCESS; } @@ -2107,6 +2283,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; break; default: @@ -3216,12 +3393,47 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) struct e1000_nvm_info *nvm = &hw->nvm; u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; + u32 nvm_dword = 0; u8 sig_byte = 0; s32 ret_val; DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan"); switch (hw->mac.type) { + case e1000_pch_spt: + bank1_offset = nvm->flash_bank_size; + act_offset = E1000_ICH_NVM_SIG_WORD; + + /* set bank to 0 in case flash read fails */ + *bank = 0; + + /* Check bank 0 */ + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, + &nvm_dword); + if (ret_val) + return ret_val; + sig_byte = (u8)((nvm_dword & 0xFF00) >> 8); + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == + E1000_ICH_NVM_SIG_VALUE) { + *bank = 0; + return E1000_SUCCESS; + } + + /* Check bank 1 */ + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset + + bank1_offset, + &nvm_dword); + if (ret_val) + return ret_val; + sig_byte = (u8)((nvm_dword & 0xFF00) >> 8); + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == + E1000_ICH_NVM_SIG_VALUE) { + *bank = 1; + return E1000_SUCCESS; + } + + DEBUGOUT("ERROR: No valid NVM bank present\n"); + return -E1000_ERR_NVM; case e1000_ich8lan: case e1000_ich9lan: eecd = E1000_READ_REG(hw, E1000_EECD); @@ -3269,6 +3481,99 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) } /** + * e1000_read_nvm_spt - NVM access for SPT + * @hw: pointer to the HW structure + * @offset: The offset (in bytes) of the word(s) to read. + * @words: Size of data to read in words. + * @data: pointer to the word(s) to read at offset. + * + * Reads a word(s) from the NVM + **/ +static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, + u16 *data) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + u32 act_offset; + s32 ret_val = E1000_SUCCESS; + u32 bank = 0; + u32 dword = 0; + u16 offset_to_read; + u16 i; + + DEBUGFUNC("e1000_read_nvm_spt"); + + if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || + (words == 0)) { + DEBUGOUT("nvm parameter(s) out of bounds\n"); + ret_val = -E1000_ERR_NVM; + goto out; + } + + nvm->ops.acquire(hw); + + ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); + if (ret_val != E1000_SUCCESS) { + DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); + bank = 0; + } + + act_offset = (bank) ? nvm->flash_bank_size : 0; + act_offset += offset; + + ret_val = E1000_SUCCESS; + + for (i = 0; i < words; i += 2) { + if (words - i == 1) { + if (dev_spec->shadow_ram[offset+i].modified) { + data[i] = dev_spec->shadow_ram[offset+i].value; + } else { + offset_to_read = act_offset + i - + ((act_offset + i) % 2); + ret_val = + e1000_read_flash_dword_ich8lan(hw, + offset_to_read, + &dword); + if (ret_val) + break; + if ((act_offset + i) % 2 == 0) + data[i] = (u16)(dword & 0xFFFF); + else + data[i] = (u16)((dword >> 16) & 0xFFFF); + } + } else { + offset_to_read = act_offset + i; + if (!(dev_spec->shadow_ram[offset+i].modified) || + !(dev_spec->shadow_ram[offset+i+1].modified)) { + ret_val = + e1000_read_flash_dword_ich8lan(hw, + offset_to_read, + &dword); + if (ret_val) + break; + } + if (dev_spec->shadow_ram[offset+i].modified) + data[i] = dev_spec->shadow_ram[offset+i].value; + else + data[i] = (u16) (dword & 0xFFFF); + if (dev_spec->shadow_ram[offset+i].modified) + data[i+1] = + dev_spec->shadow_ram[offset+i+1].value; + else + data[i+1] = (u16) (dword >> 16 & 0xFFFF); + } + } + + nvm->ops.release(hw); + +out: + if (ret_val) + DEBUGOUT1("NVM read error: %d\n", ret_val); + + return ret_val; +} + +/** * e1000_read_nvm_ich8lan - Read word(s) from the NVM * @hw: pointer to the HW structure * @offset: The offset (in bytes) of the word(s) to read. @@ -3355,7 +3660,11 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) /* Clear FCERR and DAEL in hw status by writing 1 */ hsfsts.hsf_status.flcerr = 1; hsfsts.hsf_status.dael = 1; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsfsts.regval & 0xFFFF); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); /* Either we should have a hardware SPI cycle in progress * bit to check against, in order to start a new cycle or @@ -3371,7 +3680,12 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) * Begin by setting Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsfsts.regval & 0xFFFF); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, + hsfsts.regval); ret_val = E1000_SUCCESS; } else { s32 i; @@ -3393,8 +3707,12 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) * now set the Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, - hsfsts.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsfsts.regval & 0xFFFF); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, + hsfsts.regval); } else { DEBUGOUT("Flash controller busy, cannot get access\n"); } @@ -3419,10 +3737,17 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) DEBUGFUNC("e1000_flash_cycle_ich8lan"); /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ - hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; + else + hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcgo = 1; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* wait till FDONE bit is set to 1 */ do { @@ -3439,6 +3764,29 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) } /** + * e1000_read_flash_dword_ich8lan - Read dword from flash + * @hw: pointer to the HW structure + * @offset: offset to data location + * @data: pointer to the location for storing the data + * + * Reads the flash dword at offset into data. Offset is converted + * to bytes before read. + **/ +static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset, + u32 *data) +{ + DEBUGFUNC("e1000_read_flash_dword_ich8lan"); + + if (!data) + return -E1000_ERR_NVM; + + /* Must convert word offset into bytes. */ + offset <<= 1; + + return e1000_read_flash_data32_ich8lan(hw, offset, data); +} + +/** * e1000_read_flash_word_ich8lan - Read word from flash * @hw: pointer to the HW structure * @offset: offset to data location @@ -3475,7 +3823,13 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, s32 ret_val; u16 word = 0; - ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); + /* In SPT, only 32 bits access is supported, + * so this function should not be called. + */ + if (hw->mac.type == e1000_pch_spt) + return -E1000_ERR_NVM; + else + ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); if (ret_val) return ret_val; @@ -3561,6 +3915,83 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, return ret_val; } +/** + * e1000_read_flash_data32_ich8lan - Read dword from NVM + * @hw: pointer to the HW structure + * @offset: The offset (in bytes) of the dword to read. + * @data: Pointer to the dword to store the value read. + * + * Reads a byte or word from the NVM using the flash access registers. + **/ +static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, + u32 *data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + u32 flash_linear_addr; + s32 ret_val = -E1000_ERR_NVM; + u8 count = 0; + + DEBUGFUNC("e1000_read_flash_data_ich8lan"); + + if (offset > ICH_FLASH_LINEAR_ADDR_MASK || + hw->mac.type != e1000_pch_spt) + return -E1000_ERR_NVM; + flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + + hw->nvm.flash_base_addr); + + do { + usec_delay(1); + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val != E1000_SUCCESS) + break; + /* In SPT, This register is in Lan memory space, not flash. + * Therefore, only 32 bit access is supported + */ + hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; + + /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ + hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1; + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; + /* In SPT, This register is in Lan memory space, not flash. + * Therefore, only 32 bit access is supported + */ + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + (u32)hsflctl.regval << 16); + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); + + ret_val = e1000_flash_cycle_ich8lan(hw, + ICH_FLASH_READ_COMMAND_TIMEOUT); + + /* Check if FCERR is set to 1, if set to 1, clear it + * and try the whole sequence a few more times, else + * read in (shift in) the Flash Data0, the order is + * least significant byte first msb to lsb + */ + if (ret_val == E1000_SUCCESS) { + *data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0); + break; + } else { + /* If we've gotten here, then things are probably + * completely hosed, but if the error condition is + * detected, it won't hurt to give it another try... + * ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFSTS); + if (hsfsts.hsf_status.flcerr) { + /* Repeat for some time before giving up. */ + continue; + } else if (!hsfsts.hsf_status.flcdone) { + DEBUGOUT("Timeout error - flash cycle did not complete.\n"); + break; + } + } + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); + + return ret_val; +} /** * e1000_write_nvm_ich8lan - Write word(s) to the NVM @@ -3599,6 +4030,175 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, } /** + * e1000_update_nvm_checksum_spt - Update the checksum for NVM + * @hw: pointer to the HW structure + * + * The NVM checksum is updated by calling the generic update_nvm_checksum, + * which writes the checksum to the shadow ram. The changes in the shadow + * ram are then committed to the EEPROM by processing each bank at a time + * checking for the modified bit and writing only the pending changes. + * After a successful commit, the shadow ram is cleared and is ready for + * future writes. + **/ +static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw) +{ + struct e1000_nvm_info *nvm = &hw->nvm; + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + u32 i, act_offset, new_bank_offset, old_bank_offset, bank; + s32 ret_val; + u32 dword = 0; + + DEBUGFUNC("e1000_update_nvm_checksum_spt"); + + ret_val = e1000_update_nvm_checksum_generic(hw); + if (ret_val) + goto out; + + if (nvm->type != e1000_nvm_flash_sw) + goto out; + + nvm->ops.acquire(hw); + + /* We're writing to the opposite bank so if we're on bank 1, + * write to bank 0 etc. We also need to erase the segment that + * is going to be written + */ + ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); + if (ret_val != E1000_SUCCESS) { + DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); + bank = 0; + } + + if (bank == 0) { + new_bank_offset = nvm->flash_bank_size; + old_bank_offset = 0; + ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); + if (ret_val) + goto release; + } else { + old_bank_offset = nvm->flash_bank_size; + new_bank_offset = 0; + ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); + if (ret_val) + goto release; + } + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i += 2) { + /* Determine whether to write the value stored + * in the other NVM bank or a modified value stored + * in the shadow RAM + */ + ret_val = e1000_read_flash_dword_ich8lan(hw, + i + old_bank_offset, + &dword); + + if (dev_spec->shadow_ram[i].modified) { + dword &= 0xffff0000; + dword |= (dev_spec->shadow_ram[i].value & 0xffff); + } + if (dev_spec->shadow_ram[i + 1].modified) { + dword &= 0x0000ffff; + dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff) + << 16); + } + if (ret_val) + break; + + /* If the word is 0x13, then make sure the signature bits + * (15:14) are 11b until the commit has completed. + * This will allow us to write 10b which indicates the + * signature is valid. We want to do this after the write + * has completed so that we don't mark the segment valid + * while the write is still in progress + */ + if (i == E1000_ICH_NVM_SIG_WORD - 1) + dword |= E1000_ICH_NVM_SIG_MASK << 16; + + /* Convert offset to bytes. */ + act_offset = (i + new_bank_offset) << 1; + + usec_delay(100); + + /* Write the data to the new bank. Offset in words*/ + act_offset = i + new_bank_offset; + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, + dword); + if (ret_val) + break; + } + + /* Don't bother writing the segment valid bits if sector + * programming failed. + */ + if (ret_val) { + DEBUGOUT("Flash commit failed.\n"); + goto release; + } + + /* Finally validate the new segment by setting bit 15:14 + * to 10b in word 0x13 , this can be done without an + * erase as well since these bits are 11 to start with + * and we need to change bit 14 to 0b + */ + act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; + + /*offset in words but we read dword*/ + --act_offset; + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword); + + if (ret_val) + goto release; + + dword &= 0xBFFFFFFF; + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword); + + if (ret_val) + goto release; + + /* And invalidate the previously valid segment by setting + * its signature word (0x13) high_byte to 0b. This can be + * done without an erase because flash erase sets all bits + * to 1's. We can write 1's to 0's without an erase + */ + act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; + + /* offset in words but we read dword*/ + act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1; + ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword); + + if (ret_val) + goto release; + + dword &= 0x00FFFFFF; + ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword); + + if (ret_val) + goto release; + + /* Great! Everything worked, we can now clear the cached entries. */ + for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { + dev_spec->shadow_ram[i].modified = FALSE; + dev_spec->shadow_ram[i].value = 0xFFFF; + } + +release: + nvm->ops.release(hw); + + /* Reload the EEPROM, or else modifications will not appear + * until after the next adapter reset. + */ + if (!ret_val) { + nvm->ops.reload(hw); + msec_delay(10); + } + +out: + if (ret_val) + DEBUGOUT1("NVM update error: %d\n", ret_val); + + return ret_val; +} + +/** * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM * @hw: pointer to the HW structure * @@ -3775,6 +4375,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) */ switch (hw->mac.type) { case e1000_pch_lpt: + case e1000_pch_spt: word = NVM_COMPAT; valid_csum_mask = NVM_COMPAT_VALID_CSUM; break; @@ -3822,8 +4423,13 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, DEBUGFUNC("e1000_write_ich8_data"); - if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) - return -E1000_ERR_NVM; + if (hw->mac.type == e1000_pch_spt) { + if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK) + return -E1000_ERR_NVM; + } else { + if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) + return -E1000_ERR_NVM; + } flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + hw->nvm.flash_base_addr); @@ -3834,12 +4440,29 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val != E1000_SUCCESS) break; - hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + /* In SPT, This register is in Lan memory space, not + * flash. Therefore, only 32 bit access is supported + */ + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = + E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16; + else + hsflctl.regval = + E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size - 1; hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); + /* In SPT, This register is in Lan memory space, + * not flash. Therefore, only 32 bit access is + * supported + */ + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, + hsflctl.regval); E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); @@ -3877,6 +4500,94 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, return ret_val; } +/** +* e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM +* @hw: pointer to the HW structure +* @offset: The offset (in bytes) of the dwords to read. +* @data: The 4 bytes to write to the NVM. +* +* Writes one/two/four bytes to the NVM using the flash access registers. +**/ +static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, + u32 data) +{ + union ich8_hws_flash_status hsfsts; + union ich8_hws_flash_ctrl hsflctl; + u32 flash_linear_addr; + s32 ret_val; + u8 count = 0; + + DEBUGFUNC("e1000_write_flash_data32_ich8lan"); + + if (hw->mac.type == e1000_pch_spt) { + if (offset > ICH_FLASH_LINEAR_ADDR_MASK) + return -E1000_ERR_NVM; + } + flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + + hw->nvm.flash_base_addr); + do { + usec_delay(1); + /* Steps */ + ret_val = e1000_flash_cycle_init_ich8lan(hw); + if (ret_val != E1000_SUCCESS) + break; + + /* In SPT, This register is in Lan memory space, not + * flash. Therefore, only 32 bit access is supported + */ + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = E1000_READ_FLASH_REG(hw, + ICH_FLASH_HSFSTS) + >> 16; + else + hsflctl.regval = E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFCTL); + + hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1; + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; + + /* In SPT, This register is in Lan memory space, + * not flash. Therefore, only 32 bit access is + * supported + */ + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, + hsflctl.regval); + + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); + + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, data); + + /* check if FCERR is set to 1 , if set to 1, clear it + * and try the whole sequence a few more times else done + */ + ret_val = e1000_flash_cycle_ich8lan(hw, + ICH_FLASH_WRITE_COMMAND_TIMEOUT); + + if (ret_val == E1000_SUCCESS) + break; + + /* If we're here, then things are most likely + * completely hosed, but if the error condition + * is detected, it won't hurt to give it another + * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. + */ + hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); + + if (hsfsts.hsf_status.flcerr) + /* Repeat for some time before giving up. */ + continue; + if (!hsfsts.hsf_status.flcdone) { + DEBUGOUT("Timeout error - flash cycle did not complete.\n"); + break; + } + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); + + return ret_val; +} /** * e1000_write_flash_byte_ich8lan - Write a single byte to NVM @@ -3896,7 +4607,42 @@ static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, return e1000_write_flash_data_ich8lan(hw, offset, 1, word); } +/** +* e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM +* @hw: pointer to the HW structure +* @offset: The offset of the word to write. +* @dword: The dword to write to the NVM. +* +* Writes a single dword to the NVM using the flash access registers. +* Goes through a retry algorithm before giving up. +**/ +static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, + u32 offset, u32 dword) +{ + s32 ret_val; + u16 program_retries; + + DEBUGFUNC("e1000_retry_write_flash_dword_ich8lan"); + + /* Must convert word offset into bytes. */ + offset <<= 1; + + ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); + if (!ret_val) + return ret_val; + for (program_retries = 0; program_retries < 100; program_retries++) { + DEBUGOUT2("Retrying Byte %8.8X at offset %u\n", dword, offset); + usec_delay(100); + ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); + if (ret_val == E1000_SUCCESS) + break; + } + if (program_retries == 100) + return -E1000_ERR_NVM; + + return E1000_SUCCESS; +} /** * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM @@ -4006,12 +4752,22 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) /* Write a value 11 (block Erase) in Flash * Cycle field in hw flash control */ - hsflctl.regval = - E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + if (hw->mac.type == e1000_pch_spt) + hsflctl.regval = + E1000_READ_FLASH_REG(hw, + ICH_FLASH_HSFSTS)>>16; + else + hsflctl.regval = + E1000_READ_FLASH_REG16(hw, + ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; - E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, - hsflctl.regval); + if (hw->mac.type == e1000_pch_spt) + E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS, + hsflctl.regval << 16); + else + E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, + hsflctl.regval); /* Write the last 24 bits of an index within the * block into Flash Linear address field in Flash @@ -4444,7 +5200,8 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_RFCTL, reg); /* Enable ECC on Lynxpoint */ - if (hw->mac.type == e1000_pch_lpt) { + if ((hw->mac.type == e1000_pch_lpt) || + (hw->mac.type == e1000_pch_spt)) { reg = E1000_READ_REG(hw, E1000_PBECCSTS); reg |= E1000_PBECCSTS_ECC_ENABLE; E1000_WRITE_REG(hw, E1000_PBECCSTS, reg); @@ -4876,7 +5633,8 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) || (device_id == E1000_DEV_ID_PCH_I218_LM3) || - (device_id == E1000_DEV_ID_PCH_I218_V3)) { + (device_id == E1000_DEV_ID_PCH_I218_V3) || + (hw->mac.type == e1000_pch_spt)) { u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); E1000_WRITE_REG(hw, E1000_FEXTNVM6, @@ -4992,18 +5750,18 @@ out: * the PHY. * On i217, setup Intel Rapid Start Technology. **/ -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) +u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_resume_workarounds_pchlan"); if (hw->mac.type < e1000_pch2lan) - return; + return E1000_SUCCESS; ret_val = e1000_init_phy_workarounds_pchlan(hw); if (ret_val) { DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val); - return; + return ret_val; } /* For i217 Intel Rapid Start Technology support when the system @@ -5017,7 +5775,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire(hw); if (ret_val) { DEBUGOUT("Failed to setup iRST\n"); - return; + return ret_val; } /* Clear Auto Enable LPI after link up */ @@ -5051,7 +5809,9 @@ release: if (ret_val) DEBUGOUT1("Error %d in resume workarounds\n", ret_val); hw->phy.ops.release(hw); + return ret_val; } + return E1000_SUCCESS; } /** diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h index 9cb79c0..edc1dd1 100644 --- a/sys/dev/e1000/e1000_ich8lan.h +++ b/sys/dev/e1000/e1000_ich8lan.h @@ -107,9 +107,23 @@ #define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 #define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200 - +#define E1000_FEXTNVM6_K1_OFF_ENABLE 0x80000000 +/* bit for disabling packet buffer read */ +#define E1000_FEXTNVM7_DISABLE_PB_READ 0x00040000 +#define E1000_FEXTNVM7_SIDE_CLK_UNGATE 0x00000004 #define E1000_FEXTNVM7_DISABLE_SMB_PERST 0x00000020 - +#define E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS 0x00000800 +#define E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS 0x00001000 +#define E1000_FEXTNVM11_DISABLE_PB_READ 0x00000200 +#define E1000_FEXTNVM11_DISABLE_MULR_FIX 0x00002000 + +/* bit24: RXDCTL thresholds granularity: 0 - cache lines, 1 - descriptors */ +#define E1000_RXDCTL_THRESH_UNIT_DESC 0x01000000 + +#define NVM_SIZE_MULTIPLIER 4096 /*multiplier for NVMS field*/ +#define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs*/ +#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */ +#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29) #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 @@ -171,6 +185,8 @@ #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ +#define K1_ENTRY_LATENCY 0 +#define K1_MIN_TIME 1 /* SMBus Control Phy Register */ #define CV_SMB_CTRL PHY_REG(769, 23) @@ -184,6 +200,10 @@ #define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */ #define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */ #define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */ +/* enable ULP even if when phy powered down via lanphypc */ +#define I218_ULP_CONFIG1_EN_ULP_LANPHYPC 0x0400 +/* disable clear of sticky ULP on PERST */ +#define I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST 0x0800 #define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */ /* SMBus Address Phy Register */ @@ -222,6 +242,9 @@ #define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 #define HV_PM_CTRL_K1_ENABLE 0x4000 +#define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28) +#define I217_PLL_CLOCK_GATE_MASK 0x07FF + #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ /* Inband Control */ @@ -302,15 +325,12 @@ #define E1000_SVCR_OFF_TIMER_SHIFT 16 #define E1000_SVT_OFF_HWM_MASK 0x0000001F -#if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) -#define E1000_PCI_REVISION_ID_REG 0x08 -#endif /* defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) */ void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, bool state); void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); +u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw); s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h index 1daed9b..ef9789b 100644 --- a/sys/dev/e1000/e1000_mac.h +++ b/sys/dev/e1000/e1000_mac.h @@ -36,9 +36,7 @@ #define _E1000_MAC_H_ void e1000_init_mac_ops_generic(struct e1000_hw *hw); -#ifndef E1000_REMOVED #define E1000_REMOVED(a) (0) -#endif /* E1000_REMOVED */ void e1000_null_mac_generic(struct e1000_hw *hw); s32 e1000_null_ops_generic(struct e1000_hw *hw); s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d); diff --git a/sys/dev/e1000/e1000_mbx.c b/sys/dev/e1000/e1000_mbx.c index d9fb9ac..1de19a4 100644 --- a/sys/dev/e1000/e1000_mbx.c +++ b/sys/dev/e1000/e1000_mbx.c @@ -426,15 +426,21 @@ static s32 e1000_check_for_rst_vf(struct e1000_hw *hw, static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw) { s32 ret_val = -E1000_ERR_MBX; + int count = 10; DEBUGFUNC("e1000_obtain_mbx_lock_vf"); - /* Take ownership of the buffer */ - E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU); + do { + /* Take ownership of the buffer */ + E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU); - /* reserve mailbox for vf use */ - if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) - ret_val = E1000_SUCCESS; + /* reserve mailbox for vf use */ + if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) { + ret_val = E1000_SUCCESS; + break; + } + usec_delay(1000); + } while (count-- > 0); return ret_val; } @@ -639,18 +645,26 @@ static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) { s32 ret_val = -E1000_ERR_MBX; u32 p2v_mailbox; + int count = 10; DEBUGFUNC("e1000_obtain_mbx_lock_pf"); - /* Take ownership of the buffer */ - E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); + do { + /* Take ownership of the buffer */ + E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), + E1000_P2VMAILBOX_PFU); - /* reserve mailbox for vf use */ - p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number)); - if (p2v_mailbox & E1000_P2VMAILBOX_PFU) - ret_val = E1000_SUCCESS; + /* reserve mailbox for pf use */ + p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number)); + if (p2v_mailbox & E1000_P2VMAILBOX_PFU) { + ret_val = E1000_SUCCESS; + break; + } + usec_delay(1000); + } while (count-- > 0); return ret_val; + } /** diff --git a/sys/dev/e1000/e1000_nvm.h b/sys/dev/e1000/e1000_nvm.h index 31f2180..64a4083 100644 --- a/sys/dev/e1000/e1000_nvm.h +++ b/sys/dev/e1000/e1000_nvm.h @@ -35,12 +35,10 @@ #ifndef _E1000_NVM_H_ #define _E1000_NVM_H_ -#if !defined(NO_READ_PBA_RAW) || !defined(NO_WRITE_PBA_RAW) struct e1000_pba { u16 word[2]; u16 *pba_block; }; -#endif void e1000_init_nvm_ops_generic(struct e1000_hw *hw); diff --git a/sys/dev/e1000/e1000_osdep.h b/sys/dev/e1000/e1000_osdep.h index fc46f48..c0bf418 100644 --- a/sys/dev/e1000/e1000_osdep.h +++ b/sys/dev/e1000/e1000_osdep.h @@ -60,24 +60,24 @@ #define ASSERT(x) if(!(x)) panic("EM: x") #define usec_delay(x) DELAY(x) -#define usec_delay_irq(x) DELAY(x) +#define usec_delay_irq(x) usec_delay(x) #define msec_delay(x) DELAY(1000*(x)) #define msec_delay_irq(x) DELAY(1000*(x)) -#define DEBUGFUNC(F) DEBUGOUT(F); -#define DEBUGOUT(S) do {} while (0) -#define DEBUGOUT1(S,A) do {} while (0) -#define DEBUGOUT2(S,A,B) do {} while (0) -#define DEBUGOUT3(S,A,B,C) do {} while (0) -#define DEBUGOUT7(S,A,B,C,D,E,F,G) do {} while (0) +/* Enable/disable debugging statements in shared code */ +#define DBG 0 + +#define DEBUGOUT(...) \ + do { if (DBG) printf(__VA_ARGS__); } while (0) +#define DEBUGOUT1(...) DEBUGOUT(__VA_ARGS__) +#define DEBUGOUT2(...) DEBUGOUT(__VA_ARGS__) +#define DEBUGOUT3(...) DEBUGOUT(__VA_ARGS__) +#define DEBUGOUT7(...) DEBUGOUT(__VA_ARGS__) +#define DEBUGFUNC(F) DEBUGOUT(F "\n") #define STATIC static #define FALSE 0 #define TRUE 1 -#ifndef __bool_true_false_are_defined -#define false FALSE -#define true TRUE -#endif #define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */ #define PCI_COMMAND_REGISTER PCIR_COMMAND @@ -99,9 +99,6 @@ typedef int64_t s64; typedef int32_t s32; typedef int16_t s16; typedef int8_t s8; -#ifndef __bool_true_false_are_defined -typedef boolean_t bool; -#endif #define __le16 u16 #define __le32 u32 diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c index 0c8ccd2..b2bec3e 100644 --- a/sys/dev/e1000/e1000_phy.c +++ b/sys/dev/e1000/e1000_phy.c @@ -1827,9 +1827,9 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) phy_data); if (ret_val) return ret_val; - } - DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); + DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); + } ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) @@ -3429,14 +3429,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read, bool page_set) { s32 ret_val; - u16 reg, page; + u16 reg = BM_PHY_REG_NUM(offset); + u16 page = BM_PHY_REG_PAGE(offset); u16 phy_reg = 0; DEBUGFUNC("e1000_access_phy_wakeup_reg_bm"); - reg = BM_PHY_REG_NUM(offset); - page = BM_PHY_REG_PAGE(offset); - /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */ if ((hw->mac.type == e1000_pchlan) && (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h index 7c81a89..37d7017 100644 --- a/sys/dev/e1000/e1000_regs.h +++ b/sys/dev/e1000/e1000_regs.h @@ -65,6 +65,9 @@ #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ #define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ +#define E1000_FEXTNVM9 0x5BB4 /* Future Extended NVM 9 - RW */ +#define E1000_FEXTNVM11 0x5BBC /* Future Extended NVM 11 - RW */ +#define E1000_PCIEANACFG 0x00F18 /* PCIE Analog Config */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ @@ -107,7 +110,9 @@ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ #define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ +#define E1000_IOSFPC 0x00F28 /* TX corrupted data */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ +#define E1000_EEMNGCTL_I210 0x01010 /* i210 MNG EEprom Mode Control */ #define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ #define E1000_EEARBC_I210 0x12024 /* EEPROM Auto Read Bus Control */ #define E1000_FLASHT 0x01028 /* FLASH Timer Register */ @@ -588,6 +593,10 @@ #define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */ #define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */ #define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ +#define E1000_SYSSTMPL 0x0B648 /* HH Timesync system stamp low register */ +#define E1000_SYSSTMPH 0x0B64C /* HH Timesync system stamp hi register */ +#define E1000_PLTSTMPL 0x0B640 /* HH Timesync platform stamp low register */ +#define E1000_PLTSTMPH 0x0B644 /* HH Timesync platform stamp hi register */ #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ #define E1000_TSICR 0x0B66C /* Interrupt Cause Register */ #define E1000_TSIM 0x0B674 /* Interrupt Mask Register */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index b6c98b1..1f6746c 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -96,14 +96,9 @@ #include "if_em.h" /********************************************************************* - * Set this to one to display debug statistics - *********************************************************************/ -int em_display_debug_stats = 0; - -/********************************************************************* * Driver version: *********************************************************************/ -char em_driver_version[] = "7.4.2"; +char em_driver_version[] = "7.6.1-k"; /********************************************************************* * PCI Device ID Table @@ -191,6 +186,13 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_PCH_I218_V2, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH_I218_LM3, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH_I218_V3, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM2, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V2, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_LBG_I219_LM3, + PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; @@ -238,6 +240,7 @@ static void em_free_pci_resources(struct adapter *); static void em_local_timer(void *); static void em_reset(struct adapter *); static int em_setup_interface(device_t, struct adapter *); +static void em_flush_desc_rings(struct adapter *); static void em_setup_transmit_structures(struct adapter *); static void em_initialize_transmit_unit(struct adapter *); @@ -577,10 +580,25 @@ em_attach(device_t dev) adapter->osdep.flash_bus_space_handle = rman_get_bushandle(adapter->flash); } + /* + ** In the new SPT device flash is not a + ** seperate BAR, rather it is also in BAR0, + ** so use the same tag and an offset handle for the + ** FLASH read/write macros in the shared code. + */ + else if (hw->mac.type == e1000_pch_spt) { + adapter->osdep.flash_bus_space_tag = + adapter->osdep.mem_bus_space_tag; + adapter->osdep.flash_bus_space_handle = + adapter->osdep.mem_bus_space_handle + + E1000_FLASH_BASE_ADDR; + } /* Do Shared Code initialization */ - if (e1000_setup_init_funcs(hw, TRUE)) { - device_printf(dev, "Setup of Shared code failed\n"); + error = e1000_setup_init_funcs(hw, TRUE); + if (error) { + device_printf(dev, "Setup of Shared code failed, error %d\n", + error); error = ENXIO; goto err_pci; } @@ -1170,6 +1188,7 @@ em_ioctl(if_t ifp, u_long command, caddr_t data) case e1000_ich10lan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: case e1000_82574: case e1000_82583: case e1000_80003es2lan: /* 9K Jumbo Frame size */ @@ -2359,6 +2378,8 @@ em_update_link_status(struct adapter *adapter) switch (hw->phy.media_type) { case e1000_media_type_copper: if (hw->mac.get_link_status) { + if (hw->mac.type == e1000_pch_spt) + msec_delay(50); /* Do the work to read phy */ e1000_check_for_link(hw); link_check = !hw->mac.get_link_status; @@ -2450,6 +2471,10 @@ em_stop(void *arg) EM_TX_UNLOCK(txr); } + /* I219 needs some special flushing to avoid hangs */ + if (adapter->hw.mac.type == e1000_pch_spt) + em_flush_desc_rings(adapter); + e1000_reset_hw(&adapter->hw); E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0); @@ -2869,6 +2894,116 @@ msi: } +/* +** The 3 following flush routines are used as a workaround in the +** I219 client parts and only for them. +** +** em_flush_tx_ring - remove all descriptors from the tx_ring +** +** We want to clear all pending descriptors from the TX ring. +** zeroing happens when the HW reads the regs. We assign the ring itself as +** the data of the next descriptor. We don't care about the data we are about +** to reset the HW. +*/ +static void +em_flush_tx_ring(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + struct tx_ring *txr = adapter->tx_rings; + struct e1000_tx_desc *txd; + u32 tctl, txd_lower = E1000_TXD_CMD_IFCS; + u16 size = 512; + + tctl = E1000_READ_REG(hw, E1000_TCTL); + E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN); + + txd = &txr->tx_base[txr->next_avail_desc++]; + if (txr->next_avail_desc == adapter->num_tx_desc) + txr->next_avail_desc = 0; + + /* Just use the ring as a dummy buffer addr */ + txd->buffer_addr = txr->txdma.dma_paddr; + txd->lower.data = htole32(txd_lower | size); + txd->upper.data = 0; + + /* flush descriptors to memory before notifying the HW */ + wmb(); + + E1000_WRITE_REG(hw, E1000_TDT(0), txr->next_avail_desc); + mb(); + usec_delay(250); +} + +/* +** em_flush_rx_ring - remove all descriptors from the rx_ring +** +** Mark all descriptors in the RX ring as consumed and disable the rx ring +*/ +static void +em_flush_rx_ring(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 rctl, rxdctl; + + rctl = E1000_READ_REG(hw, E1000_RCTL); + E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); + E1000_WRITE_FLUSH(hw); + usec_delay(150); + + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); + /* zero the lower 14 bits (prefetch and host thresholds) */ + rxdctl &= 0xffffc000; + /* + * update thresholds: prefetch threshold to 31, host threshold to 1 + * and make sure the granularity is "descriptors" and not "cache lines" + */ + rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC); + E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl); + + /* momentarily enable the RX ring for the changes to take effect */ + E1000_WRITE_REG(hw, E1000_RCTL, rctl | E1000_RCTL_EN); + E1000_WRITE_FLUSH(hw); + usec_delay(150); + E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); +} + +/* +** em_flush_desc_rings - remove all descriptors from the descriptor rings +** +** In i219, the descriptor rings must be emptied before resetting the HW +** or before changing the device state to D3 during runtime (runtime PM). +** +** Failure to do this will cause the HW to enter a unit hang state which can +** only be released by PCI reset on the device +** +*/ +static void +em_flush_desc_rings(struct adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + device_t dev = adapter->dev; + u16 hang_state; + u32 fext_nvm11, tdlen; + + /* First, disable MULR fix in FEXTNVM11 */ + fext_nvm11 = E1000_READ_REG(hw, E1000_FEXTNVM11); + fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX; + E1000_WRITE_REG(hw, E1000_FEXTNVM11, fext_nvm11); + + /* do nothing if we're not in faulty state, or if the queue is empty */ + tdlen = E1000_READ_REG(hw, E1000_TDLEN(0)); + hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2); + if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen) + return; + em_flush_tx_ring(adapter); + + /* recheck, maybe the fault is caused by the rx ring */ + hang_state = pci_read_config(dev, PCICFG_DESC_RING_STATUS, 2); + if (hang_state & FLUSH_DESC_REQUIRED) + em_flush_rx_ring(adapter); +} + + /********************************************************************* * * Initialize the hardware to a configuration @@ -2930,6 +3065,7 @@ em_reset(struct adapter *adapter) case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: pba = E1000_PBA_26K; break; default: @@ -2988,6 +3124,7 @@ em_reset(struct adapter *adapter) break; case e1000_pch2lan: case e1000_pch_lpt: + case e1000_pch_spt: hw->fc.high_water = 0x5C20; hw->fc.low_water = 0x5048; hw->fc.pause_time = 0x0650; @@ -3012,6 +3149,10 @@ em_reset(struct adapter *adapter) break; } + /* I219 needs some special flushing to avoid hangs */ + if (hw->mac.type == e1000_pch_spt) + em_flush_desc_rings(adapter); + /* Issue a global reset */ e1000_reset_hw(hw); E1000_WRITE_REG(hw, E1000_WUC, 0); @@ -3608,6 +3749,15 @@ em_initialize_transmit_unit(struct adapter *adapter) /* This write will effectively turn on the transmit unit. */ E1000_WRITE_REG(&adapter->hw, E1000_TCTL, tctl); + if (hw->mac.type == e1000_pch_spt) { + u32 reg; + reg = E1000_READ_REG(hw, E1000_IOSFPC); + reg |= E1000_RCTL_RDMTS_HEX; + E1000_WRITE_REG(hw, E1000_IOSFPC, reg); + reg = E1000_READ_REG(hw, E1000_TARC(0)); + reg |= E1000_TARC0_CB_MULTIQ_3_REQ; + E1000_WRITE_REG(hw, E1000_TARC(0), reg); + } } diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index 362df49..3b280b3 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -218,6 +218,9 @@ #define EM_TX_HUNG 0x80000000 #define EM_TX_MAXTRIES 10 +#define PCICFG_DESC_RING_STATUS 0xe4 +#define FLUSH_DESC_REQUIRED 0x100 + /* * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 5be7836..c84dfc2 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -47,7 +47,7 @@ /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] = "2.5.2"; +char igb_driver_version[] = "2.5.3-k"; /********************************************************************* @@ -551,9 +551,9 @@ igb_attach(device_t dev) "Disable Energy Efficient Ethernet"); if (adapter->hw.phy.media_type == e1000_media_type_copper) { if (adapter->hw.mac.type == e1000_i354) - e1000_set_eee_i354(&adapter->hw); + e1000_set_eee_i354(&adapter->hw, TRUE, TRUE); else - e1000_set_eee_i350(&adapter->hw); + e1000_set_eee_i350(&adapter->hw, TRUE, TRUE); } } @@ -1277,6 +1277,9 @@ igb_init_locked(struct adapter *adapter) if (ifp->if_capenable & IFCAP_TSO) ifp->if_hwassist |= CSUM_TSO; + /* Clear bad data from Rx FIFOs */ + e1000_rx_fifo_flush_82575(&adapter->hw); + /* Configure for OS presence */ igb_init_manageability(adapter); @@ -1304,7 +1307,6 @@ igb_init_locked(struct adapter *adapter) return; } igb_initialize_receive_units(adapter); - e1000_rx_fifo_flush_82575(&adapter->hw); /* Enable VLAN support */ if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) @@ -1341,9 +1343,9 @@ igb_init_locked(struct adapter *adapter) /* Set Energy Efficient Ethernet */ if (adapter->hw.phy.media_type == e1000_media_type_copper) { if (adapter->hw.mac.type == e1000_i354) - e1000_set_eee_i354(&adapter->hw); + e1000_set_eee_i354(&adapter->hw, TRUE, TRUE); else - e1000_set_eee_i350(&adapter->hw); + e1000_set_eee_i350(&adapter->hw, TRUE, TRUE); } } diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index 7f46573..3f56f12 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -1009,14 +1009,14 @@ pmc_attach_one_process(struct proc *p, struct pmc *pm) /* issue an attach event to a configured log file */ if (pm->pm_owner->po_flags & PMC_PO_OWNS_LOGFILE) { - pmc_getfilename(p->p_textvp, &fullpath, &freepath); if (p->p_flag & P_KTHREAD) { fullpath = kernelname; freepath = NULL; - } else + } else { + pmc_getfilename(p->p_textvp, &fullpath, &freepath); pmclog_process_pmcattach(pm, p->p_pid, fullpath); - if (freepath) - free(freepath, M_TEMP); + } + free(freepath, M_TEMP); if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) pmc_log_process_mappings(pm->pm_owner, p); } diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 852e14e..8e2ca57 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -908,30 +908,6 @@ int hv_vmbus_channel_teardown_gpdal( struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary); -/* - * Work abstraction defines - */ -typedef struct hv_work_queue { - struct taskqueue* queue; - struct proc* proc; - struct sema* work_sema; -} hv_work_queue; - -typedef struct hv_work_item { - struct task work; - void (*callback)(void *); - void* context; - hv_work_queue* wq; -} hv_work_item; - -struct hv_work_queue* hv_work_queue_create(char* name); - -void hv_work_queue_close(struct hv_work_queue* wq); - -int hv_queue_work_item( - hv_work_queue* wq, - void (*callback)(void *), - void* context); /** * @brief Get physical address from virtual */ @@ -952,8 +928,8 @@ typedef struct hv_vmbus_service { hv_guid guid; /* Hyper-V GUID */ char *name; /* name of service */ boolean_t enabled; /* service enabled */ - hv_work_queue *work_queue; /* background work queue */ - + void* context; + struct task task; /* * function to initialize service */ @@ -963,6 +939,11 @@ typedef struct hv_vmbus_service { * function to process Hyper-V messages */ void (*callback)(void *); + + /* + * function to uninitilize service + */ + int (*uninit)(struct hv_vmbus_service *); } hv_vmbus_service; extern uint8_t* receive_buffer[]; diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 8bf34a8..cd60b4969 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -74,10 +74,7 @@ hv_nv_alloc_net_device(struct hv_device *device) netvsc_dev *net_dev; hn_softc_t *sc = device_get_softc(device->device); - net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_NOWAIT | M_ZERO); - if (net_dev == NULL) { - return (NULL); - } + net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO); net_dev->dev = device; net_dev->destroy = FALSE; @@ -136,15 +133,15 @@ hv_nv_get_next_send_section(netvsc_dev *net_dev) int i; for (i = 0; i < bitsmap_words; i++) { - idx = ffs(~bitsmap[i]); + idx = ffsl(~bitsmap[i]); if (0 == idx) continue; idx--; - if (i * BITS_PER_LONG + idx >= net_dev->send_section_count) - return (ret); + KASSERT(i * BITS_PER_LONG + idx < net_dev->send_section_count, + ("invalid i %d and idx %lu", i, idx)); - if (synch_test_and_set_bit(idx, &bitsmap[i])) + if (atomic_testandset_long(&bitsmap[i], idx)) continue; ret = i * BITS_PER_LONG + idx; @@ -224,11 +221,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hv_device *device) init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections; net_dev->rx_sections = malloc(net_dev->rx_section_count * - sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_NOWAIT); - if (net_dev->rx_sections == NULL) { - ret = EINVAL; - goto cleanup; - } + sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_WAITOK); memcpy(net_dev->rx_sections, init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections, net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section)); @@ -326,11 +319,7 @@ hv_nv_init_send_buffer_with_net_vsp(struct hv_device *device) BITS_PER_LONG); net_dev->send_section_bitsmap = malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC, - M_NOWAIT | M_ZERO); - if (NULL == net_dev->send_section_bitsmap) { - ret = ENOMEM; - goto cleanup; - } + M_WAITOK | M_ZERO); goto exit; @@ -789,8 +778,27 @@ hv_nv_on_send_completion(netvsc_dev *net_dev, if (NULL != net_vsc_pkt) { if (net_vsc_pkt->send_buf_section_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { - synch_change_bit(net_vsc_pkt->send_buf_section_idx, - net_dev->send_section_bitsmap); + u_long mask; + int idx; + + idx = net_vsc_pkt->send_buf_section_idx / + BITS_PER_LONG; + KASSERT(idx < net_dev->bitsmap_words, + ("invalid section index %u", + net_vsc_pkt->send_buf_section_idx)); + mask = 1UL << + (net_vsc_pkt->send_buf_section_idx % + BITS_PER_LONG); + + KASSERT(net_dev->send_section_bitsmap[idx] & + mask, + ("index bitmap 0x%lx, section index %u, " + "bitmap idx %d, bitmask 0x%lx", + net_dev->send_section_bitsmap[idx], + net_vsc_pkt->send_buf_section_idx, + idx, mask)); + atomic_clear_long( + &net_dev->send_section_bitsmap[idx], mask); } /* Notify the layer above us */ diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index c190340..4f52e0d 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -1015,6 +1015,7 @@ typedef struct hn_softc { bus_dma_tag_t hn_tx_rndis_dtag; int hn_tx_chimney_size; int hn_tx_chimney_max; + uint64_t hn_csum_assist; struct mtx hn_txlist_spin; struct hn_txdesc_list hn_txlist; @@ -1022,6 +1023,7 @@ typedef struct hn_softc { int hn_txdesc_avail; int hn_txeof; + int hn_sched_tx; int hn_direct_tx_size; struct taskqueue *hn_tx_taskq; struct task hn_start_task; @@ -1030,11 +1032,12 @@ typedef struct hn_softc { struct lro_ctrl hn_lro; int hn_lro_hiwat; - /* Trust tcp segments verification on host side */ - int hn_trust_hosttcp; + /* Trust csum verification on host side */ + int hn_trust_hcsum; /* HN_TRUST_HCSUM_ */ u_long hn_csum_ip; u_long hn_csum_tcp; + u_long hn_csum_udp; u_long hn_csum_trusted; u_long hn_lro_tried; u_long hn_small_pkts; @@ -1045,6 +1048,9 @@ typedef struct hn_softc { u_long hn_tx_chimney; } hn_softc_t; +#define HN_TRUST_HCSUM_IP 0x0001 +#define HN_TRUST_HCSUM_TCP 0x0002 +#define HN_TRUST_HCSUM_UDP 0x0004 /* * Externs diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index ab88e36..be43bf4 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -132,6 +132,8 @@ __FBSDID("$FreeBSD$"); /* YYY should get it from the underlying channel */ #define HN_TX_DESC_CNT 512 +#define HN_LROENT_CNT_DEF 128 + #define HN_RNDIS_MSG_LEN \ (sizeof(rndis_msg) + \ RNDIS_VLAN_PPI_SIZE + \ @@ -167,14 +169,12 @@ struct hn_txdesc { #define HN_TXD_FLAG_DMAMAP 0x2 /* - * A unified flag for all outbound check sum flags is useful, - * and it helps avoiding unnecessary check sum calculation in - * network forwarding scenario. + * Only enable UDP checksum offloading when it is on 2012R2 or + * later. UDP checksum offloading doesn't work on earlier + * Windows releases. */ -#define HV_CSUM_FOR_OUTBOUND \ - (CSUM_IP|CSUM_IP_UDP|CSUM_IP_TCP|CSUM_IP_SCTP|CSUM_IP_TSO| \ - CSUM_IP_ISCSI|CSUM_IP6_UDP|CSUM_IP6_TCP|CSUM_IP6_SCTP| \ - CSUM_IP6_TSO|CSUM_IP6_ISCSI) +#define HN_CSUM_ASSIST_WIN8 (CSUM_TCP) +#define HN_CSUM_ASSIST (CSUM_IP | CSUM_UDP | CSUM_TCP) /* XXX move to netinet/tcp_lro.h */ #define HN_LRO_HIWAT_MAX 65535 @@ -212,6 +212,14 @@ int hv_promisc_mode = 0; /* normal mode by default */ static int hn_trust_hosttcp = 1; TUNABLE_INT("dev.hn.trust_hosttcp", &hn_trust_hosttcp); +/* Trust udp datagrams verification on host side. */ +static int hn_trust_hostudp = 1; +TUNABLE_INT("dev.hn.trust_hostudp", &hn_trust_hostudp); + +/* Trust ip packets verification on host side. */ +static int hn_trust_hostip = 1; +TUNABLE_INT("dev.hn.trust_hostip", &hn_trust_hostip); + #if __FreeBSD_version >= 1100045 /* Limit TSO burst size */ static int hn_tso_maxlen = 0; @@ -226,6 +234,13 @@ TUNABLE_INT("dev.hn.tx_chimney_size", &hn_tx_chimney_size); static int hn_direct_tx_size = HN_DIRECT_TX_SIZE_DEF; TUNABLE_INT("dev.hn.direct_tx_size", &hn_direct_tx_size); +#if defined(INET) || defined(INET6) +#if __FreeBSD_version >= 1100095 +static int hn_lro_entry_count = HN_LROENT_CNT_DEF; +TUNABLE_INT("dev.hn.lro_entry_count", &hn_lro_entry_count); +#endif +#endif + /* * Forward declarations */ @@ -241,12 +256,14 @@ static void hn_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); #ifdef HN_LRO_HIWAT static int hn_lro_hiwat_sysctl(SYSCTL_HANDLER_ARGS); #endif +static int hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS); static int hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS); static int hn_check_iplen(const struct mbuf *, int); static int hn_create_tx_ring(struct hn_softc *sc); static void hn_destroy_tx_ring(struct hn_softc *sc); static void hn_start_taskfunc(void *xsc, int pending); static void hn_txeof_taskfunc(void *xsc, int pending); +static int hn_encap(struct hn_softc *, struct hn_txdesc *, struct mbuf **); static __inline void hn_set_lro_hiwat(struct hn_softc *sc, int hiwat) @@ -257,62 +274,6 @@ hn_set_lro_hiwat(struct hn_softc *sc, int hiwat) #endif } -/* - * NetVsc get message transport protocol type - */ -static uint32_t get_transport_proto_type(struct mbuf *m_head) -{ - uint32_t ret_val = TRANSPORT_TYPE_NOT_IP; - uint16_t ether_type = 0; - int ether_len = 0; - struct ether_vlan_header *eh; -#ifdef INET - struct ip *iph; -#endif -#ifdef INET6 - struct ip6_hdr *ip6; -#endif - - eh = mtod(m_head, struct ether_vlan_header*); - if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { - ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; - ether_type = eh->evl_proto; - } else { - ether_len = ETHER_HDR_LEN; - ether_type = eh->evl_encap_proto; - } - - switch (ntohs(ether_type)) { -#ifdef INET6 - case ETHERTYPE_IPV6: - ip6 = (struct ip6_hdr *)(m_head->m_data + ether_len); - - if (IPPROTO_TCP == ip6->ip6_nxt) { - ret_val = TRANSPORT_TYPE_IPV6_TCP; - } else if (IPPROTO_UDP == ip6->ip6_nxt) { - ret_val = TRANSPORT_TYPE_IPV6_UDP; - } - break; -#endif -#ifdef INET - case ETHERTYPE_IP: - iph = (struct ip *)(m_head->m_data + ether_len); - - if (IPPROTO_TCP == iph->ip_p) { - ret_val = TRANSPORT_TYPE_IPV4_TCP; - } else if (IPPROTO_UDP == iph->ip_p) { - ret_val = TRANSPORT_TYPE_IPV4_UDP; - } - break; -#endif - default: - ret_val = TRANSPORT_TYPE_NOT_IP; - break; - } - - return (ret_val); -} - static int hn_ifmedia_upd(struct ifnet *ifp __unused) { @@ -383,6 +344,11 @@ netvsc_attach(device_t dev) #if __FreeBSD_version >= 1100045 int tso_maxlen; #endif +#if defined(INET) || defined(INET6) +#if __FreeBSD_version >= 1100095 + int lroent_cnt; +#endif +#endif sc = device_get_softc(dev); if (sc == NULL) { @@ -393,8 +359,13 @@ netvsc_attach(device_t dev) sc->hn_unit = unit; sc->hn_dev = dev; sc->hn_lro_hiwat = HN_LRO_HIWAT_DEF; - sc->hn_trust_hosttcp = hn_trust_hosttcp; sc->hn_direct_tx_size = hn_direct_tx_size; + if (hn_trust_hosttcp) + sc->hn_trust_hcsum |= HN_TRUST_HCSUM_TCP; + if (hn_trust_hostudp) + sc->hn_trust_hcsum |= HN_TRUST_HCSUM_UDP; + if (hn_trust_hostip) + sc->hn_trust_hcsum |= HN_TRUST_HCSUM_IP; sc->hn_tx_taskq = taskqueue_create_fast("hn_tx", M_WAITOK, taskqueue_thread_enqueue, &sc->hn_tx_taskq); @@ -444,15 +415,12 @@ netvsc_attach(device_t dev) ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_TSO | IFCAP_LRO; - /* - * Only enable UDP checksum offloading when it is on 2012R2 or - * later. UDP checksum offloading doesn't work on earlier - * Windows releases. - */ + if (hv_vmbus_protocal_version >= HV_VMBUS_VERSION_WIN8_1) - ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_TSO; + sc->hn_csum_assist = HN_CSUM_ASSIST; else - ifp->if_hwassist = CSUM_TCP | CSUM_TSO; + sc->hn_csum_assist = HN_CSUM_ASSIST_WIN8; + ifp->if_hwassist = sc->hn_csum_assist | CSUM_TSO; error = hv_rf_on_device_add(device_ctx, &device_info); if (error) @@ -463,9 +431,17 @@ netvsc_attach(device_t dev) } #if defined(INET) || defined(INET6) +#if __FreeBSD_version >= 1100095 + lroent_cnt = hn_lro_entry_count; + if (lroent_cnt < TCP_LRO_ENTRIES) + lroent_cnt = TCP_LRO_ENTRIES; + tcp_lro_init_args(&sc->hn_lro, ifp, lroent_cnt, 0); + device_printf(dev, "LRO: entry count %d\n", lroent_cnt); +#else tcp_lro_init(&sc->hn_lro); /* Driver private LRO settings */ sc->hn_lro.ifp = ifp; +#endif #ifdef HN_LRO_HIWAT sc->hn_lro.lro_hiwat = sc->hn_lro_hiwat; #endif @@ -509,17 +485,30 @@ netvsc_attach(device_t dev) CTLTYPE_INT | CTLFLAG_RW, sc, 0, hn_lro_hiwat_sysctl, "I", "LRO high watermark"); #endif - SYSCTL_ADD_INT(ctx, child, OID_AUTO, "trust_hosttcp", - CTLFLAG_RW, &sc->hn_trust_hosttcp, 0, + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hosttcp", + CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_TCP, + hn_trust_hcsum_sysctl, "I", "Trust tcp segement verification on host side, " "when csum info is missing"); + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hostudp", + CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_UDP, + hn_trust_hcsum_sysctl, "I", + "Trust udp datagram verification on host side, " + "when csum info is missing"); + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "trust_hostip", + CTLTYPE_INT | CTLFLAG_RW, sc, HN_TRUST_HCSUM_IP, + hn_trust_hcsum_sysctl, "I", + "Trust ip packet verification on host side, " + "when csum info is missing"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_ip", CTLFLAG_RW, &sc->hn_csum_ip, "RXCSUM IP"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_tcp", CTLFLAG_RW, &sc->hn_csum_tcp, "RXCSUM TCP"); + SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_udp", + CTLFLAG_RW, &sc->hn_csum_udp, "RXCSUM UDP"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "csum_trusted", CTLFLAG_RW, &sc->hn_csum_trusted, - "# of TCP segements that we trust host's csum verification"); + "# of packets that we trust host's csum verification"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "small_pkts", CTLFLAG_RW, &sc->hn_small_pkts, "# of small packets received"); SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "no_txdescs", @@ -545,6 +534,10 @@ netvsc_attach(device_t dev) SYSCTL_ADD_INT(ctx, child, OID_AUTO, "direct_tx_size", CTLFLAG_RW, &sc->hn_direct_tx_size, 0, "Size of the packet for direct transmission"); + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "sched_tx", + CTLFLAG_RW, &sc->hn_sched_tx, 0, + "Always schedule transmission " + "instead of doing direct transmission"); if (unit == 0) { struct sysctl_ctx_list *dc_ctx; @@ -562,6 +555,14 @@ netvsc_attach(device_t dev) CTLFLAG_RD, &hn_trust_hosttcp, 0, "Trust tcp segement verification on host side, " "when csum info is missing (global setting)"); + SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "trust_hostudp", + CTLFLAG_RD, &hn_trust_hostudp, 0, + "Trust udp datagram verification on host side, " + "when csum info is missing (global setting)"); + SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "trust_hostip", + CTLFLAG_RD, &hn_trust_hostip, 0, + "Trust ip packet verification on host side, " + "when csum info is missing (global setting)"); SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "tx_chimney_size", CTLFLAG_RD, &hn_tx_chimney_size, 0, "Chimney send packet size limit"); @@ -572,6 +573,12 @@ netvsc_attach(device_t dev) SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "direct_tx_size", CTLFLAG_RD, &hn_direct_tx_size, 0, "Size of the packet for direct transmission"); +#if defined(INET) || defined(INET6) +#if __FreeBSD_version >= 1100095 + SYSCTL_ADD_INT(dc_ctx, dc_child, OID_AUTO, "lro_entry_count", + CTLFLAG_RD, &hn_lro_entry_count, 0, "LRO entry count"); +#endif +#endif } return (0); @@ -761,6 +768,15 @@ void netvsc_channel_rollup(struct hv_device *device_ctx) { struct hn_softc *sc = device_get_softc(device_ctx->device); +#if defined(INET) || defined(INET6) + struct lro_ctrl *lro = &sc->hn_lro; + struct lro_entry *queued; + + while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) { + SLIST_REMOVE_HEAD(&lro->lro_active, next); + tcp_lro_flush(lro, queued); + } +#endif if (!sc->hn_txeof) return; @@ -770,177 +786,94 @@ netvsc_channel_rollup(struct hv_device *device_ctx) } /* - * Start a transmit of one or more packets + * NOTE: + * This this function fails, then both txd and m_head0 will be freed */ static int -hn_start_locked(struct ifnet *ifp, int len) +hn_encap(struct hn_softc *sc, struct hn_txdesc *txd, struct mbuf **m_head0) { - hn_softc_t *sc = ifp->if_softc; - struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); - netvsc_dev *net_dev = sc->net_dev; - struct ether_vlan_header *eh; + bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX]; + int error, nsegs, i; + struct mbuf *m_head = *m_head0; + netvsc_packet *packet; rndis_msg *rndis_mesg; rndis_packet *rndis_pkt; rndis_per_packet_info *rppi; - ndis_8021q_info *rppi_vlan_info; - rndis_tcp_ip_csum_info *csum_info; - rndis_tcp_tso_info *tso_info; - int ether_len; - uint32_t rndis_msg_size = 0; - uint32_t trans_proto_type; + uint32_t rndis_msg_size; - if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING) - return 0; + packet = &txd->netvsc_pkt; + packet->is_data_pkt = TRUE; + packet->tot_data_buf_len = m_head->m_pkthdr.len; - while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { - bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX]; - int error, nsegs, i, send_failed = 0; - struct hn_txdesc *txd; - netvsc_packet *packet; - struct mbuf *m_head; - - IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) - break; + /* + * extension points to the area reserved for the + * rndis_filter_packet, which is placed just after + * the netvsc_packet (and rppi struct, if present; + * length is updated later). + */ + rndis_mesg = txd->rndis_msg; + /* XXX not necessary */ + memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN); + rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; - if (len > 0 && m_head->m_pkthdr.len > len) { - /* - * This sending could be time consuming; let callers - * dispatch this packet sending (and sending of any - * following up packets) to tx taskqueue. - */ - IF_PREPEND(&ifp->if_snd, m_head); - return 1; - } + rndis_pkt = &rndis_mesg->msg.packet; + rndis_pkt->data_offset = sizeof(rndis_packet); + rndis_pkt->data_length = packet->tot_data_buf_len; + rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet); - txd = hn_txdesc_get(sc); - if (txd == NULL) { - sc->hn_no_txdescs++; - IF_PREPEND(&ifp->if_snd, m_head); - atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); - break; - } + rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet); - packet = &txd->netvsc_pkt; - packet->is_data_pkt = TRUE; - /* Initialize it from the mbuf */ - packet->tot_data_buf_len = m_head->m_pkthdr.len; + if (m_head->m_flags & M_VLANTAG) { + ndis_8021q_info *rppi_vlan_info; - /* - * extension points to the area reserved for the - * rndis_filter_packet, which is placed just after - * the netvsc_packet (and rppi struct, if present; - * length is updated later). - */ - rndis_mesg = txd->rndis_msg; - /* XXX not necessary */ - memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN); - rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; + rndis_msg_size += RNDIS_VLAN_PPI_SIZE; + rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE, + ieee_8021q_info); - rndis_pkt = &rndis_mesg->msg.packet; - rndis_pkt->data_offset = sizeof(rndis_packet); - rndis_pkt->data_length = packet->tot_data_buf_len; - rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet); + rppi_vlan_info = (ndis_8021q_info *)((uint8_t *)rppi + + rppi->per_packet_info_offset); + rppi_vlan_info->u1.s1.vlan_id = + m_head->m_pkthdr.ether_vtag & 0xfff; + } - rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet); + if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { + rndis_tcp_tso_info *tso_info; + struct ether_vlan_header *eh; + int ether_len; /* - * If the Hyper-V infrastructure needs to embed a VLAN tag, - * initialize netvsc_packet and rppi struct values as needed. + * XXX need m_pullup and use mtodo */ - if (m_head->m_flags & M_VLANTAG) { - /* - * set up some additional fields so the Hyper-V infrastructure will stuff the VLAN tag - * into the frame. - */ - rndis_msg_size += RNDIS_VLAN_PPI_SIZE; - - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE, - ieee_8021q_info); - - /* VLAN info immediately follows rppi struct */ - rppi_vlan_info = (ndis_8021q_info *)((char*)rppi + - rppi->per_packet_info_offset); - /* FreeBSD does not support CFI or priority */ - rppi_vlan_info->u1.s1.vlan_id = - m_head->m_pkthdr.ether_vtag & 0xfff; - } - - /* Only check the flags for outbound and ignore the ones for inbound */ - if (0 == (m_head->m_pkthdr.csum_flags & HV_CSUM_FOR_OUTBOUND)) { - goto pre_send; - } - eh = mtod(m_head, struct ether_vlan_header*); - if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { + if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) ether_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; - } else { + else ether_len = ETHER_HDR_LEN; - } - - trans_proto_type = get_transport_proto_type(m_head); - if (TRANSPORT_TYPE_NOT_IP == trans_proto_type) { - goto pre_send; - } - /* - * TSO packet needless to setup the send side checksum - * offload. - */ - if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { - goto do_tso; - } - - /* setup checksum offload */ - rndis_msg_size += RNDIS_CSUM_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE, - tcpip_chksum_info); - csum_info = (rndis_tcp_ip_csum_info *)((char*)rppi + - rppi->per_packet_info_offset); - - if (trans_proto_type & (TYPE_IPV4 << 16)) { - csum_info->xmit.is_ipv4 = 1; - } else { - csum_info->xmit.is_ipv6 = 1; - } - - if (trans_proto_type & TYPE_TCP) { - csum_info->xmit.tcp_csum = 1; - csum_info->xmit.tcp_header_offset = 0; - } else if (trans_proto_type & TYPE_UDP) { - csum_info->xmit.udp_csum = 1; - } - - goto pre_send; - -do_tso: - /* setup TCP segmentation offload */ rndis_msg_size += RNDIS_TSO_PPI_SIZE; rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE, tcp_large_send_info); - - tso_info = (rndis_tcp_tso_info *)((char *)rppi + + + tso_info = (rndis_tcp_tso_info *)((uint8_t *)rppi + rppi->per_packet_info_offset); tso_info->lso_v2_xmit.type = RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; - + #ifdef INET - if (trans_proto_type & (TYPE_IPV4 << 16)) { + if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) { struct ip *ip = (struct ip *)(m_head->m_data + ether_len); unsigned long iph_len = ip->ip_hl << 2; struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + iph_len); - + tso_info->lso_v2_xmit.ip_version = RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4; ip->ip_len = 0; ip->ip_sum = 0; - + th->th_sum = in_pseudo(ip->ip_src.s_addr, - ip->ip_dst.s_addr, - htons(IPPROTO_TCP)); + ip->ip_dst.s_addr, htons(IPPROTO_TCP)); } #endif #if defined(INET6) && defined(INET) @@ -948,8 +881,8 @@ do_tso: #endif #ifdef INET6 { - struct ip6_hdr *ip6 = - (struct ip6_hdr *)(m_head->m_data + ether_len); + struct ip6_hdr *ip6 = (struct ip6_hdr *) + (m_head->m_data + ether_len); struct tcphdr *th = (struct tcphdr *)(ip6 + 1); tso_info->lso_v2_xmit.ip_version = @@ -960,98 +893,163 @@ do_tso: #endif tso_info->lso_v2_xmit.tcp_header_offset = 0; tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz; + } else if (m_head->m_pkthdr.csum_flags & sc->hn_csum_assist) { + rndis_tcp_ip_csum_info *csum_info; -pre_send: - rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size; - packet->tot_data_buf_len = rndis_mesg->msg_len; - - /* send packet with send buffer */ - if (packet->tot_data_buf_len < sc->hn_tx_chimney_size) { - uint32_t send_buf_section_idx; - - send_buf_section_idx = - hv_nv_get_next_send_section(net_dev); - if (send_buf_section_idx != - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { - uint8_t *dest = ((uint8_t *)net_dev->send_buf + - (send_buf_section_idx * - net_dev->send_section_size)); - - memcpy(dest, rndis_mesg, rndis_msg_size); - dest += rndis_msg_size; - - m_copydata(m_head, 0, m_head->m_pkthdr.len, - dest); - - packet->send_buf_section_idx = - send_buf_section_idx; - packet->send_buf_section_size = - packet->tot_data_buf_len; - packet->page_buf_count = 0; - sc->hn_tx_chimney++; - goto do_send; - } - } - - error = hn_txdesc_dmamap_load(sc, txd, &m_head, segs, &nsegs); - if (error) { - int freed; + rndis_msg_size += RNDIS_CSUM_PPI_SIZE; + rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE, + tcpip_chksum_info); + csum_info = (rndis_tcp_ip_csum_info *)((uint8_t *)rppi + + rppi->per_packet_info_offset); - /* - * This mbuf is not linked w/ the txd yet, so free - * it now. - */ - m_freem(m_head); - freed = hn_txdesc_put(sc, txd); - KASSERT(freed != 0, - ("fail to free txd upon txdma error")); + csum_info->xmit.is_ipv4 = 1; + if (m_head->m_pkthdr.csum_flags & CSUM_IP) + csum_info->xmit.ip_header_csum = 1; - sc->hn_txdma_failed++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - continue; + if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { + csum_info->xmit.tcp_csum = 1; + csum_info->xmit.tcp_header_offset = 0; + } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) { + csum_info->xmit.udp_csum = 1; } + } + + rndis_mesg->msg_len = packet->tot_data_buf_len + rndis_msg_size; + packet->tot_data_buf_len = rndis_mesg->msg_len; - packet->page_buf_count = nsegs + - HV_RF_NUM_TX_RESERVED_PAGE_BUFS; + /* + * Chimney send, if the packet could fit into one chimney buffer. + */ + if (packet->tot_data_buf_len < sc->hn_tx_chimney_size) { + netvsc_dev *net_dev = sc->net_dev; + uint32_t send_buf_section_idx; + + send_buf_section_idx = + hv_nv_get_next_send_section(net_dev); + if (send_buf_section_idx != + NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { + uint8_t *dest = ((uint8_t *)net_dev->send_buf + + (send_buf_section_idx * + net_dev->send_section_size)); + + memcpy(dest, rndis_mesg, rndis_msg_size); + dest += rndis_msg_size; + m_copydata(m_head, 0, m_head->m_pkthdr.len, dest); + + packet->send_buf_section_idx = send_buf_section_idx; + packet->send_buf_section_size = + packet->tot_data_buf_len; + packet->page_buf_count = 0; + sc->hn_tx_chimney++; + goto done; + } + } - /* send packet with page buffer */ - packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr); - packet->page_buffers[0].offset = - txd->rndis_msg_paddr & PAGE_MASK; - packet->page_buffers[0].length = rndis_msg_size; + error = hn_txdesc_dmamap_load(sc, txd, &m_head, segs, &nsegs); + if (error) { + int freed; /* - * Fill the page buffers with mbuf info starting at index - * HV_RF_NUM_TX_RESERVED_PAGE_BUFS. + * This mbuf is not linked w/ the txd yet, so free it now. */ - for (i = 0; i < nsegs; ++i) { - hv_vmbus_page_buffer *pb = &packet->page_buffers[ - i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS]; + m_freem(m_head); + *m_head0 = NULL; - pb->pfn = atop(segs[i].ds_addr); - pb->offset = segs[i].ds_addr & PAGE_MASK; - pb->length = segs[i].ds_len; - } + freed = hn_txdesc_put(sc, txd); + KASSERT(freed != 0, + ("fail to free txd upon txdma error")); - packet->send_buf_section_idx = - NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; - packet->send_buf_section_size = 0; + sc->hn_txdma_failed++; + if_inc_counter(sc->hn_ifp, IFCOUNTER_OERRORS, 1); + return error; + } + *m_head0 = m_head; + + packet->page_buf_count = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS; + + /* send packet with page buffer */ + packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr); + packet->page_buffers[0].offset = txd->rndis_msg_paddr & PAGE_MASK; + packet->page_buffers[0].length = rndis_msg_size; -do_send: - txd->m = m_head; + /* + * Fill the page buffers with mbuf info starting at index + * HV_RF_NUM_TX_RESERVED_PAGE_BUFS. + */ + for (i = 0; i < nsegs; ++i) { + hv_vmbus_page_buffer *pb = &packet->page_buffers[ + i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS]; + + pb->pfn = atop(segs[i].ds_addr); + pb->offset = segs[i].ds_addr & PAGE_MASK; + pb->length = segs[i].ds_len; + } + + packet->send_buf_section_idx = + NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; + packet->send_buf_section_size = 0; +done: + txd->m = m_head; + + /* Set the completion routine */ + packet->compl.send.on_send_completion = netvsc_xmit_completion; + packet->compl.send.send_completion_context = packet; + packet->compl.send.send_completion_tid = (uint64_t)(uintptr_t)txd; + + return 0; +} + +/* + * Start a transmit of one or more packets + */ +static int +hn_start_locked(struct ifnet *ifp, int len) +{ + struct hn_softc *sc = ifp->if_softc; + struct hv_device *device_ctx = vmbus_get_devctx(sc->hn_dev); + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return 0; + + while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { + int error, send_failed = 0; + struct hn_txdesc *txd; + struct mbuf *m_head; + + IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); + if (m_head == NULL) + break; + + if (len > 0 && m_head->m_pkthdr.len > len) { + /* + * This sending could be time consuming; let callers + * dispatch this packet sending (and sending of any + * following up packets) to tx taskqueue. + */ + IF_PREPEND(&ifp->if_snd, m_head); + return 1; + } - /* Set the completion routine */ - packet->compl.send.on_send_completion = netvsc_xmit_completion; - packet->compl.send.send_completion_context = packet; - packet->compl.send.send_completion_tid = - (uint64_t)(uintptr_t)txd; + txd = hn_txdesc_get(sc); + if (txd == NULL) { + sc->hn_no_txdescs++; + IF_PREPEND(&ifp->if_snd, m_head); + atomic_set_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); + break; + } + error = hn_encap(sc, txd, &m_head); + if (error) { + /* Both txd and m_head are freed */ + continue; + } again: /* * Make sure that txd is not freed before ETHER_BPF_MTAP. */ hn_txdesc_hold(txd); - error = hv_nv_on_send(device_ctx, packet); + error = hv_nv_on_send(device_ctx, &txd->netvsc_pkt); if (!error) { ETHER_BPF_MTAP(ifp, m_head); if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); @@ -1191,7 +1189,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, struct mbuf *m_new; struct ifnet *ifp; device_t dev = device_ctx->device; - int size, do_lro = 0; + int size, do_lro = 0, do_csum = 1; if (sc == NULL) { return (0); /* TODO: KYS how can this be! */ @@ -1239,21 +1237,28 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, } m_new->m_pkthdr.rcvif = ifp; + if (__predict_false((ifp->if_capenable & IFCAP_RXCSUM) == 0)) + do_csum = 0; + /* receive side checksum offload */ - if (NULL != csum_info) { + if (csum_info != NULL) { /* IP csum offload */ - if (csum_info->receive.ip_csum_succeeded) { + if (csum_info->receive.ip_csum_succeeded && do_csum) { m_new->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID); sc->hn_csum_ip++; } - /* TCP csum offload */ - if (csum_info->receive.tcp_csum_succeeded) { + /* TCP/UDP csum offload */ + if ((csum_info->receive.tcp_csum_succeeded || + csum_info->receive.udp_csum_succeeded) && do_csum) { m_new->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); m_new->m_pkthdr.csum_data = 0xffff; - sc->hn_csum_tcp++; + if (csum_info->receive.tcp_csum_succeeded) + sc->hn_csum_tcp++; + else + sc->hn_csum_udp++; } if (csum_info->receive.ip_csum_succeeded && @@ -1284,7 +1289,8 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, pr = hn_check_iplen(m_new, hoff); if (pr == IPPROTO_TCP) { - if (sc->hn_trust_hosttcp) { + if (do_csum && + (sc->hn_trust_hcsum & HN_TRUST_HCSUM_TCP)) { sc->hn_csum_trusted++; m_new->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID | @@ -1293,6 +1299,20 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet, } /* Rely on SW csum verification though... */ do_lro = 1; + } else if (pr == IPPROTO_UDP) { + if (do_csum && + (sc->hn_trust_hcsum & HN_TRUST_HCSUM_UDP)) { + sc->hn_csum_trusted++; + m_new->m_pkthdr.csum_flags |= + (CSUM_IP_CHECKED | CSUM_IP_VALID | + CSUM_DATA_VALID | CSUM_PSEUDO_HDR); + m_new->m_pkthdr.csum_data = 0xffff; + } + } else if (pr != IPPROTO_DONE && do_csum && + (sc->hn_trust_hcsum & HN_TRUST_HCSUM_IP)) { + sc->hn_csum_trusted++; + m_new->m_pkthdr.csum_flags |= + (CSUM_IP_CHECKED | CSUM_IP_VALID); } } } @@ -1331,18 +1351,8 @@ skip: } void -netvsc_recv_rollup(struct hv_device *device_ctx) +netvsc_recv_rollup(struct hv_device *device_ctx __unused) { -#if defined(INET) || defined(INET6) - hn_softc_t *sc = device_get_softc(device_ctx->device); - struct lro_ctrl *lro = &sc->hn_lro; - struct lro_entry *queued; - - while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) { - SLIST_REMOVE_HEAD(&lro->lro_active, next); - tcp_lro_flush(lro, queued); - } -#endif } /* @@ -1506,47 +1516,40 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = 0; break; case SIOCSIFCAP: + NV_LOCK(sc); + mask = ifr->ifr_reqcap ^ ifp->if_capenable; if (mask & IFCAP_TXCSUM) { - if (IFCAP_TXCSUM & ifp->if_capenable) { - ifp->if_capenable &= ~IFCAP_TXCSUM; - ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP); - } else { - ifp->if_capenable |= IFCAP_TXCSUM; - /* - * Only enable UDP checksum offloading on - * Windows Server 2012R2 or later releases. - */ - if (hv_vmbus_protocal_version >= - HV_VMBUS_VERSION_WIN8_1) { - ifp->if_hwassist |= - (CSUM_TCP | CSUM_UDP); - } else { - ifp->if_hwassist |= CSUM_TCP; - } - } + ifp->if_capenable ^= IFCAP_TXCSUM; + if (ifp->if_capenable & IFCAP_TXCSUM) + ifp->if_hwassist |= sc->hn_csum_assist; + else + ifp->if_hwassist &= ~sc->hn_csum_assist; } - if (mask & IFCAP_RXCSUM) { - if (IFCAP_RXCSUM & ifp->if_capenable) { - ifp->if_capenable &= ~IFCAP_RXCSUM; - } else { - ifp->if_capenable |= IFCAP_RXCSUM; - } - } + if (mask & IFCAP_RXCSUM) + ifp->if_capenable ^= IFCAP_RXCSUM; + if (mask & IFCAP_LRO) ifp->if_capenable ^= IFCAP_LRO; if (mask & IFCAP_TSO4) { ifp->if_capenable ^= IFCAP_TSO4; - ifp->if_hwassist ^= CSUM_IP_TSO; + if (ifp->if_capenable & IFCAP_TSO4) + ifp->if_hwassist |= CSUM_IP_TSO; + else + ifp->if_hwassist &= ~CSUM_IP_TSO; } if (mask & IFCAP_TSO6) { ifp->if_capenable ^= IFCAP_TSO6; - ifp->if_hwassist ^= CSUM_IP6_TSO; + if (ifp->if_capenable & IFCAP_TSO6) + ifp->if_hwassist |= CSUM_IP6_TSO; + else + ifp->if_hwassist &= ~CSUM_IP6_TSO; } + NV_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: @@ -1603,9 +1606,11 @@ hn_stop(hn_softc_t *sc) static void hn_start(struct ifnet *ifp) { - hn_softc_t *sc; + struct hn_softc *sc = ifp->if_softc; + + if (sc->hn_sched_tx) + goto do_sched; - sc = ifp->if_softc; if (NV_TRYLOCK(sc)) { int sched; @@ -1614,15 +1619,18 @@ hn_start(struct ifnet *ifp) if (!sched) return; } +do_sched: taskqueue_enqueue_fast(sc->hn_tx_taskq, &sc->hn_start_task); } static void hn_start_txeof(struct ifnet *ifp) { - hn_softc_t *sc; + struct hn_softc *sc = ifp->if_softc; + + if (sc->hn_sched_tx) + goto do_sched; - sc = ifp->if_softc; if (NV_TRYLOCK(sc)) { int sched; @@ -1634,6 +1642,7 @@ hn_start_txeof(struct ifnet *ifp) &sc->hn_start_task); } } else { +do_sched: /* * Release the OACTIVE earlier, with the hope, that * others could catch up. The task will clear the @@ -1735,6 +1744,30 @@ hn_lro_hiwat_sysctl(SYSCTL_HANDLER_ARGS) #endif /* HN_LRO_HIWAT */ static int +hn_trust_hcsum_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct hn_softc *sc = arg1; + int hcsum = arg2; + int on, error; + + on = 0; + if (sc->hn_trust_hcsum & hcsum) + on = 1; + + error = sysctl_handle_int(oidp, &on, 0, req); + if (error || req->newptr == NULL) + return error; + + NV_LOCK(sc); + if (on) + sc->hn_trust_hcsum |= hcsum; + else + sc->hn_trust_hcsum &= ~hcsum; + NV_UNLOCK(sc); + return 0; +} + +static int hn_tx_chimney_size_sysctl(SYSCTL_HANDLER_ARGS) { struct hn_softc *sc = arg1; diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index dfd0b47..9fb78ee 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -135,12 +135,9 @@ hv_get_rndis_device(void) { rndis_device *device; - device = malloc(sizeof(rndis_device), M_NETVSC, M_NOWAIT | M_ZERO); - if (device == NULL) { - return (NULL); - } + device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO); - mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_SPIN | MTX_RECURSE); + mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF); /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */ STAILQ_INIT(&device->myrequest_list); @@ -171,10 +168,7 @@ hv_rndis_request(rndis_device *device, uint32_t message_type, rndis_msg *rndis_mesg; rndis_set_request *set; - request = malloc(sizeof(rndis_request), M_NETVSC, M_NOWAIT | M_ZERO); - if (request == NULL) { - return (NULL); - } + request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO); sema_init(&request->wait_sema, 0, "rndis sema"); @@ -193,9 +187,9 @@ hv_rndis_request(rndis_device *device, uint32_t message_type, set->request_id += 1; /* Add to the request list */ - mtx_lock_spin(&device->req_lock); + mtx_lock(&device->req_lock); STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry); - mtx_unlock_spin(&device->req_lock); + mtx_unlock(&device->req_lock); return (request); } @@ -206,14 +200,14 @@ hv_rndis_request(rndis_device *device, uint32_t message_type, static inline void hv_put_rndis_request(rndis_device *device, rndis_request *request) { - mtx_lock_spin(&device->req_lock); + mtx_lock(&device->req_lock); /* Fixme: Has O(n) performance */ /* * XXXKYS: Use Doubly linked lists. */ STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_, mylist_entry); - mtx_unlock_spin(&device->req_lock); + mtx_unlock(&device->req_lock); sema_destroy(&request->wait_sema); free(request, M_NETVSC); @@ -270,7 +264,7 @@ hv_rf_receive_response(rndis_device *device, rndis_msg *response) rndis_request *next_request; boolean_t found = FALSE; - mtx_lock_spin(&device->req_lock); + mtx_lock(&device->req_lock); request = STAILQ_FIRST(&device->myrequest_list); while (request != NULL) { /* @@ -285,7 +279,7 @@ hv_rf_receive_response(rndis_device *device, rndis_msg *response) next_request = STAILQ_NEXT(request, mylist_entry); request = next_request; } - mtx_unlock_spin(&device->req_lock); + mtx_unlock(&device->req_lock); if (found) { if (response->msg_len <= sizeof(rndis_msg)) { diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c index 098c8c9..9683ad8 100644 --- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -1524,13 +1524,12 @@ static void storvsc_destroy_bounce_buffer(struct sglist *sgl) { struct hv_sgl_node *sgl_node = NULL; - - sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.in_use_sgl_list); - LIST_REMOVE(sgl_node, link); - if (NULL == sgl_node) { + if (LIST_EMPTY(&g_hv_sgl_page_pool.in_use_sgl_list)) { printf("storvsc error: not enough in use sgl\n"); return; } + sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.in_use_sgl_list); + LIST_REMOVE(sgl_node, link); sgl_node->sgl_data = sgl; LIST_INSERT_HEAD(&g_hv_sgl_page_pool.free_sgl_list, sgl_node, link); } @@ -1556,12 +1555,12 @@ storvsc_create_bounce_buffer(uint16_t seg_count, int write) struct hv_sgl_node *sgl_node = NULL; /* get struct sglist from free_sgl_list */ - sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list); - LIST_REMOVE(sgl_node, link); - if (NULL == sgl_node) { + if (LIST_EMPTY(&g_hv_sgl_page_pool.free_sgl_list)) { printf("storvsc error: not enough free sgl\n"); return NULL; } + sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list); + LIST_REMOVE(sgl_node, link); bounce_sgl = sgl_node->sgl_data; LIST_INSERT_HEAD(&g_hv_sgl_page_pool.in_use_sgl_list, sgl_node, link); diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c index 58d565c4..86e037a 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -98,7 +98,7 @@ static d_poll_t hv_kvp_dev_daemon_poll; static int hv_kvp_req_in_progress(void); static void hv_kvp_transaction_init(uint32_t, hv_vmbus_channel *, uint64_t, uint8_t *); static void hv_kvp_send_msg_to_daemon(void); -static void hv_kvp_process_request(void *context); +static void hv_kvp_process_request(void *context, int pending); /* hv_kvp character device structure */ static struct cdevsw hv_kvp_cdevsw = @@ -123,9 +123,6 @@ static struct selinfo hv_kvp_selinfo; */ static struct { - /* Pre-allocated work item for queue */ - hv_work_item work_item; - /* Unless specified the pending mutex should be * used to alter the values of the following paramters: * 1. req_in_progress @@ -642,7 +639,7 @@ hv_kvp_send_msg_to_daemon(void) * and interact with daemon */ static void -hv_kvp_process_request(void *context) +hv_kvp_process_request(void *context, int pending) { uint8_t *kvp_buf; hv_vmbus_channel *channel = context; @@ -756,23 +753,18 @@ hv_kvp_callback(void *context) uint64_t pending_cnt = 0; if (kvp_globals.register_done == false) { - kvp_globals.channelp = context; + TASK_INIT(&service_table[HV_KVP].task, 0, hv_kvp_process_request, context); } else { - mtx_lock(&kvp_globals.pending_mutex); kvp_globals.pending_reqs = kvp_globals.pending_reqs + 1; pending_cnt = kvp_globals.pending_reqs; mtx_unlock(&kvp_globals.pending_mutex); if (pending_cnt == 1) { hv_kvp_log_info("%s: Queuing work item\n", __func__); - hv_queue_work_item( - service_table[HV_KVP].work_queue, - hv_kvp_process_request, - context - ); + taskqueue_enqueue(taskqueue_thread, &service_table[HV_KVP].task); } - } + } } @@ -977,26 +969,13 @@ int hv_kvp_init(hv_vmbus_service *srv) { int error = 0; - hv_work_queue *work_queue = NULL; - - memset(&kvp_globals, 0, sizeof(kvp_globals)); - work_queue = hv_work_queue_create("KVP Service"); - if (work_queue == NULL) { - hv_kvp_log_info("%s: Work queue alloc failed\n", __func__); - error = ENOMEM; - hv_kvp_log_error("%s: ENOMEM\n", __func__); - goto Finish; - } - srv->work_queue = work_queue; + memset(&kvp_globals, 0, sizeof(kvp_globals)); error = hv_kvp_dev_init(); mtx_init(&kvp_globals.pending_mutex, "hv-kvp pending mutex", - NULL, MTX_DEF); - kvp_globals.pending_reqs = 0; - + NULL, MTX_DEF); -Finish: return (error); } diff --git a/sys/dev/hyperv/utilities/hv_util.c b/sys/dev/hyperv/utilities/hv_util.c index dc4b1e2..38054ca 100644 --- a/sys/dev/hyperv/utilities/hv_util.c +++ b/sys/dev/hyperv/utilities/hv_util.c @@ -52,6 +52,8 @@ static void hv_heartbeat_cb(void *context); static void hv_timesync_cb(void *context); static int hv_timesync_init(hv_vmbus_service *serv); +static int hv_timesync_uninit(hv_vmbus_service *serv); +static void hv_set_host_time(void *context, int pending); /* * Note: GUID codes below are predefined by the host hypervisor @@ -73,6 +75,7 @@ hv_vmbus_service service_table[] = { .enabled = TRUE, .init = hv_timesync_init, .callback = hv_timesync_cb, + .uninit = hv_timesync_uninit, }, /* Heartbeat Service */ @@ -111,10 +114,16 @@ struct hv_ictimesync_data { static int hv_timesync_init(hv_vmbus_service *serv) { + void *time_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_WAITOK); + TASK_INIT(&serv->task, 1, hv_set_host_time, time_msg); + return (0); +} - serv->work_queue = hv_work_queue_create("Time Sync"); - if (serv->work_queue == NULL) - return (ENOMEM); +static int +hv_timesync_uninit(hv_vmbus_service *serv) +{ + taskqueue_drain(taskqueue_thread, &serv->task); + free(serv->task.ta_context, M_DEVBUF); return (0); } @@ -152,9 +161,9 @@ hv_negotiate_version( * Set host time based on time sync message from host */ static void -hv_set_host_time(void *context) +hv_set_host_time(void *context, int pending) { - time_sync_data* time_msg = (time_sync_data*) context; + time_sync_data* time_msg = (time_sync_data*) context; uint64_t hosttime = time_msg->data; struct timespec guest_ts, host_ts; uint64_t host_tns; @@ -166,7 +175,7 @@ hv_set_host_time(void *context) host_ts.tv_nsec = (long)(host_tns%HV_NANO_SEC_PER_SEC); nanotime(&guest_ts); - + diff = (int64_t)host_ts.tv_sec - (int64_t)guest_ts.tv_sec; /* @@ -175,12 +184,7 @@ hv_set_host_time(void *context) if (diff > 5 || diff < -5) { error = kern_clock_settime(curthread, CLOCK_REALTIME, &host_ts); - } - - /* - * Free the hosttime that was allocated in hv_adj_guesttime() - */ - free(time_msg, M_DEVBUF); + } } /** @@ -197,23 +201,13 @@ hv_set_host_time(void *context) static inline void hv_adj_guesttime(uint64_t hosttime, uint8_t flags) { - time_sync_data* time_msg; - - time_msg = malloc(sizeof(time_sync_data), M_DEVBUF, M_NOWAIT); + time_sync_data* time_msg = service_table[HV_TIME_SYNCH].task.ta_context; - if (time_msg == NULL) - return; - time_msg->data = hosttime; - if ((flags & HV_ICTIMESYNCFLAG_SYNC) != 0) { - hv_queue_work_item(service_table[HV_TIME_SYNCH].work_queue, - hv_set_host_time, time_msg); - } else if ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0) { - hv_queue_work_item(service_table[HV_TIME_SYNCH].work_queue, - hv_set_host_time, time_msg); - } else { - free(time_msg, M_DEVBUF); + if (((flags & HV_ICTIMESYNCFLAG_SYNC) != 0) || + ((flags & HV_ICTIMESYNCFLAG_SAMPLE) != 0)) { + taskqueue_enqueue(taskqueue_thread, &service_table[HV_TIME_SYNCH].task); } } @@ -452,19 +446,14 @@ hv_util_detach(device_t dev) service = device_get_softc(dev); receive_buffer_offset = service - &service_table[0]; - if (service->work_queue != NULL) - hv_work_queue_close(service->work_queue); + if (service->uninit != NULL) + service->uninit(service); free(receive_buffer[receive_buffer_offset], M_DEVBUF); receive_buffer[receive_buffer_offset] = NULL; return (0); } -static void -hv_util_init(void) -{ -} - static int hv_util_modevent(module_t mod, int event, void *arg) { @@ -495,6 +484,3 @@ static devclass_t util_devclass; DRIVER_MODULE(hv_utils, vmbus, util_driver, util_devclass, hv_util_modevent, 0); MODULE_VERSION(hv_utils, 1); MODULE_DEPEND(hv_utils, vmbus, 1, 1, 1); - -SYSINIT(hv_util_initx, SI_SUB_KTHREAD_IDLE, SI_ORDER_MIDDLE + 1, - hv_util_init, NULL); diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c index 762ace4..af7395b 100644 --- a/sys/dev/hyperv/vmbus/hv_channel.c +++ b/sys/dev/hyperv/vmbus/hv_channel.c @@ -68,9 +68,7 @@ vmbus_channel_set_event(hv_vmbus_channel *channel) + ((channel->offer_msg.child_rel_id >> 5)))); monitor_page = (hv_vmbus_monitor_page *) - hv_vmbus_g_connection.monitor_pages; - - monitor_page++; /* Get the child to parent monitor page */ + hv_vmbus_g_connection.monitor_page_2; synch_set_bit(channel->monitor_bit, (uint32_t *)&monitor_page-> diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c index 93008aa..21f7d95 100644 --- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c +++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c @@ -36,8 +36,10 @@ */ static void vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr); +static void vmbus_channel_on_offer_internal(void* context); static void vmbus_channel_on_open_result(hv_vmbus_channel_msg_header* hdr); static void vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr); +static void vmbus_channel_on_offer_rescind_internal(void* context); static void vmbus_channel_on_gpadl_created(hv_vmbus_channel_msg_header* hdr); static void vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr); static void vmbus_channel_on_offers_delivered(hv_vmbus_channel_msg_header* hdr); @@ -49,41 +51,46 @@ static void vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr); hv_vmbus_channel_msg_table_entry g_channel_message_table[HV_CHANNEL_MESSAGE_COUNT] = { { HV_CHANNEL_MESSAGE_INVALID, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_OFFER_CHANNEL, - 0, vmbus_channel_on_offer }, + vmbus_channel_on_offer }, { HV_CHANNEL_MESSAGE_RESCIND_CHANNEL_OFFER, - 0, vmbus_channel_on_offer_rescind }, + vmbus_channel_on_offer_rescind }, { HV_CHANNEL_MESSAGE_REQUEST_OFFERS, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_ALL_OFFERS_DELIVERED, - 1, vmbus_channel_on_offers_delivered }, + vmbus_channel_on_offers_delivered }, { HV_CHANNEL_MESSAGE_OPEN_CHANNEL, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_OPEN_CHANNEL_RESULT, - 1, vmbus_channel_on_open_result }, + vmbus_channel_on_open_result }, { HV_CHANNEL_MESSAGE_CLOSE_CHANNEL, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGEL_GPADL_HEADER, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_GPADL_BODY, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_GPADL_CREATED, - 1, vmbus_channel_on_gpadl_created }, + vmbus_channel_on_gpadl_created }, { HV_CHANNEL_MESSAGE_GPADL_TEARDOWN, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_GPADL_TORNDOWN, - 1, vmbus_channel_on_gpadl_torndown }, + vmbus_channel_on_gpadl_torndown }, { HV_CHANNEL_MESSAGE_REL_ID_RELEASED, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_INITIATED_CONTACT, - 0, NULL }, + NULL }, { HV_CHANNEL_MESSAGE_VERSION_RESPONSE, - 1, vmbus_channel_on_version_response }, + vmbus_channel_on_version_response }, { HV_CHANNEL_MESSAGE_UNLOAD, - 0, NULL } + NULL } }; +typedef struct hv_work_item { + struct task work; + void (*callback)(void *); + void* context; +} hv_work_item; /** * Implementation of the work abstraction. @@ -93,120 +100,30 @@ work_item_callback(void *work, int pending) { struct hv_work_item *w = (struct hv_work_item *)work; - /* - * Serialize work execution. - */ - if (w->wq->work_sema != NULL) { - sema_wait(w->wq->work_sema); - } - w->callback(w->context); - if (w->wq->work_sema != NULL) { - sema_post(w->wq->work_sema); - } - free(w, M_DEVBUF); } -struct hv_work_queue* -hv_work_queue_create(char* name) -{ - static unsigned int qid = 0; - char qname[64]; - int pri; - struct hv_work_queue* wq; - - wq = malloc(sizeof(struct hv_work_queue), M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(wq != NULL, ("Error VMBUS: Failed to allocate work_queue\n")); - if (wq == NULL) - return (NULL); - - /* - * We use work abstraction to handle messages - * coming from the host and these are typically offers. - * Some FreeBsd drivers appear to have a concurrency issue - * where probe/attach needs to be serialized. We ensure that - * by having only one thread process work elements in a - * specific queue by serializing work execution. - * - */ - if (strcmp(name, "vmbusQ") == 0) { - pri = PI_DISK; - } else { /* control */ - pri = PI_NET; - /* - * Initialize semaphore for this queue by pointing - * to the globale semaphore used for synchronizing all - * control messages. - */ - wq->work_sema = &hv_vmbus_g_connection.control_sema; - } - - sprintf(qname, "hv_%s_%u", name, qid); - - /* - * Fixme: FreeBSD 8.2 has a different prototype for - * taskqueue_create(), and for certain other taskqueue functions. - * We need to research the implications of these changes. - * Fixme: Not sure when the changes were introduced. - */ - wq->queue = taskqueue_create(qname, M_NOWAIT, taskqueue_thread_enqueue, - &wq->queue - #if __FreeBSD_version < 800000 - , &wq->proc - #endif - ); - - if (wq->queue == NULL) { - free(wq, M_DEVBUF); - return (NULL); - } - - if (taskqueue_start_threads(&wq->queue, 1, pri, "%s taskq", qname)) { - taskqueue_free(wq->queue); - free(wq, M_DEVBUF); - return (NULL); - } - - qid++; - - return (wq); -} - -void -hv_work_queue_close(struct hv_work_queue *wq) -{ - /* - * KYS: Need to drain the taskqueue - * before we close the hv_work_queue. - */ - /*KYS: taskqueue_drain(wq->tq, ); */ - taskqueue_free(wq->queue); - free(wq, M_DEVBUF); -} - /** * @brief Create work item */ -int +static int hv_queue_work_item( - struct hv_work_queue *wq, void (*callback)(void *), void *context) { struct hv_work_item *w = malloc(sizeof(struct hv_work_item), - M_DEVBUF, M_NOWAIT | M_ZERO); + M_DEVBUF, M_NOWAIT); KASSERT(w != NULL, ("Error VMBUS: Failed to allocate WorkItem\n")); if (w == NULL) return (ENOMEM); w->callback = callback; w->context = context; - w->wq = wq; TASK_INIT(&w->work, 0, work_item_callback, w); - return (taskqueue_enqueue(wq->queue, &w->work)); + return (taskqueue_enqueue(taskqueue_thread, &w->work)); } @@ -221,10 +138,7 @@ hv_vmbus_allocate_channel(void) channel = (hv_vmbus_channel*) malloc( sizeof(hv_vmbus_channel), M_DEVBUF, - M_NOWAIT | M_ZERO); - KASSERT(channel != NULL, ("Error VMBUS: Failed to allocate channel!")); - if (channel == NULL) - return (NULL); + M_WAITOK | M_ZERO); mtx_init(&channel->inbound_lock, "channel inbound", NULL, MTX_DEF); mtx_init(&channel->sc_lock, "vmbus multi channel", NULL, MTX_DEF); @@ -235,16 +149,6 @@ hv_vmbus_allocate_channel(void) } /** - * @brief Release the vmbus channel object itself - */ -static inline void -ReleaseVmbusChannel(void *context) -{ - hv_vmbus_channel* channel = (hv_vmbus_channel*) context; - free(channel, M_DEVBUF); -} - -/** * @brief Release the resources used by the vmbus channel object */ void @@ -252,13 +156,8 @@ hv_vmbus_free_vmbus_channel(hv_vmbus_channel* channel) { mtx_destroy(&channel->sc_lock); mtx_destroy(&channel->inbound_lock); - /* - * We have to release the channel's workqueue/thread in - * the vmbus's workqueue/thread context - * ie we can't destroy ourselves - */ - hv_queue_work_item(hv_vmbus_g_connection.work_queue, - ReleaseVmbusChannel, (void *) channel); + + free(channel, M_DEVBUF); } /** @@ -456,7 +355,7 @@ static void vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr) { hv_vmbus_channel_offer_channel* offer; - hv_vmbus_channel* new_channel; + hv_vmbus_channel_offer_channel* copied; offer = (hv_vmbus_channel_offer_channel*) hdr; @@ -466,10 +365,25 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr) guidType = &offer->offer.interface_type; guidInstance = &offer->offer.interface_instance; + // copy offer data + copied = malloc(sizeof(*copied), M_DEVBUF, M_NOWAIT); + if (copied == NULL) { + printf("fail to allocate memory\n"); + return; + } + + memcpy(copied, hdr, sizeof(*copied)); + hv_queue_work_item(vmbus_channel_on_offer_internal, copied); +} + +static void +vmbus_channel_on_offer_internal(void* context) +{ + hv_vmbus_channel* new_channel; + + hv_vmbus_channel_offer_channel* offer = (hv_vmbus_channel_offer_channel*)context; /* Allocate the channel object and save this offer */ new_channel = hv_vmbus_allocate_channel(); - if (new_channel == NULL) - return; /* * By default we setup state to enable batched @@ -509,6 +423,8 @@ vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr) new_channel->monitor_bit = (uint8_t) offer->monitor_id % 32; vmbus_channel_process_offer(new_channel); + + free(offer, M_DEVBUF); } /** @@ -526,13 +442,20 @@ vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr) rescind = (hv_vmbus_channel_rescind_offer*) hdr; channel = hv_vmbus_g_connection.channels[rescind->child_rel_id]; - if (channel == NULL) + if (channel == NULL) return; - hv_vmbus_child_device_unregister(channel->device); - mtx_lock(&hv_vmbus_g_connection.channel_lock); + hv_queue_work_item(vmbus_channel_on_offer_rescind_internal, channel); hv_vmbus_g_connection.channels[rescind->child_rel_id] = NULL; - mtx_unlock(&hv_vmbus_g_connection.channel_lock); +} + +static void +vmbus_channel_on_offer_rescind_internal(void *context) +{ + hv_vmbus_channel* channel; + + channel = (hv_vmbus_channel*)context; + hv_vmbus_child_device_unregister(channel->device); } /** @@ -709,35 +632,6 @@ vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr) } /** - * @brief Handler for channel protocol messages. - * - * This is invoked in the vmbus worker thread context. - */ -void -hv_vmbus_on_channel_message(void *context) -{ - hv_vmbus_message* msg; - hv_vmbus_channel_msg_header* hdr; - int size; - - msg = (hv_vmbus_message*) context; - hdr = (hv_vmbus_channel_msg_header*) msg->u.payload; - size = msg->header.payload_size; - - if (hdr->message_type >= HV_CHANNEL_MESSAGE_COUNT) { - free(msg, M_DEVBUF); - return; - } - - if (g_channel_message_table[hdr->message_type].messageHandler) { - g_channel_message_table[hdr->message_type].messageHandler(hdr); - } - - /* Free the msg that was allocated in VmbusOnMsgDPC() */ - free(msg, M_DEVBUF); -} - -/** * @brief Send a request to get all our pending offers. */ int @@ -762,8 +656,7 @@ hv_vmbus_request_channel_offers(void) ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_msg_header)); - if (msg_info) - free(msg_info, M_DEVBUF); + free(msg_info, M_DEVBUF); return (ret); } diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c index 05b1612..e60c557 100644 --- a/sys/dev/hyperv/vmbus/hv_connection.c +++ b/sys/dev/hyperv/vmbus/hv_connection.c @@ -86,12 +86,10 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info, hv_vmbus_g_connection.interrupt_page); msg->monitor_page_1 = hv_get_phys_addr( - hv_vmbus_g_connection.monitor_pages); + hv_vmbus_g_connection.monitor_page_1); - msg->monitor_page_2 = - hv_get_phys_addr( - ((uint8_t *) hv_vmbus_g_connection.monitor_pages - + PAGE_SIZE)); + msg->monitor_page_2 = hv_get_phys_addr( + hv_vmbus_g_connection.monitor_page_2); /** * Add to list before we send the request since we may receive the @@ -164,8 +162,6 @@ hv_vmbus_connect(void) { * Initialize the vmbus connection */ hv_vmbus_g_connection.connect_state = HV_CONNECTING; - hv_vmbus_g_connection.work_queue = hv_work_queue_create("vmbusQ"); - sema_init(&hv_vmbus_g_connection.control_sema, 1, "control_sema"); TAILQ_INIT(&hv_vmbus_g_connection.channel_msg_anchor); mtx_init(&hv_vmbus_g_connection.channel_msg_lock, "vmbus channel msg", @@ -179,18 +175,9 @@ hv_vmbus_connect(void) { * Setup the vmbus event connection for channel interrupt abstraction * stuff */ - hv_vmbus_g_connection.interrupt_page = contigmalloc( + hv_vmbus_g_connection.interrupt_page = malloc( PAGE_SIZE, M_DEVBUF, - M_NOWAIT | M_ZERO, 0UL, - BUS_SPACE_MAXADDR, - PAGE_SIZE, 0); - KASSERT(hv_vmbus_g_connection.interrupt_page != NULL, - ("Error VMBUS: malloc failed to allocate Channel" - " Request Event message!")); - if (hv_vmbus_g_connection.interrupt_page == NULL) { - ret = ENOMEM; - goto cleanup; - } + M_WAITOK | M_ZERO); hv_vmbus_g_connection.recv_interrupt_page = hv_vmbus_g_connection.interrupt_page; @@ -203,31 +190,19 @@ hv_vmbus_connect(void) { * Set up the monitor notification facility. The 1st page for * parent->child and the 2nd page for child->parent */ - hv_vmbus_g_connection.monitor_pages = contigmalloc( - 2 * PAGE_SIZE, + hv_vmbus_g_connection.monitor_page_1 = malloc( + PAGE_SIZE, M_DEVBUF, - M_NOWAIT | M_ZERO, - 0UL, - BUS_SPACE_MAXADDR, + M_WAITOK | M_ZERO); + hv_vmbus_g_connection.monitor_page_2 = malloc( PAGE_SIZE, - 0); - KASSERT(hv_vmbus_g_connection.monitor_pages != NULL, - ("Error VMBUS: malloc failed to allocate Monitor Pages!")); - if (hv_vmbus_g_connection.monitor_pages == NULL) { - ret = ENOMEM; - goto cleanup; - } + M_DEVBUF, + M_WAITOK | M_ZERO); msg_info = (hv_vmbus_channel_msg_info*) malloc(sizeof(hv_vmbus_channel_msg_info) + sizeof(hv_vmbus_channel_initiate_contact), - M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(msg_info != NULL, - ("Error VMBUS: malloc failed for Initiate Contact message!")); - if (msg_info == NULL) { - ret = ENOMEM; - goto cleanup; - } + M_DEVBUF, M_WAITOK | M_ZERO); hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) * HV_CHANNEL_MAX_COUNT, @@ -269,8 +244,6 @@ hv_vmbus_connect(void) { hv_vmbus_g_connection.connect_state = HV_DISCONNECTED; - hv_work_queue_close(hv_vmbus_g_connection.work_queue); - sema_destroy(&hv_vmbus_g_connection.control_sema); mtx_destroy(&hv_vmbus_g_connection.channel_lock); mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock); @@ -282,13 +255,8 @@ hv_vmbus_connect(void) { hv_vmbus_g_connection.interrupt_page = NULL; } - if (hv_vmbus_g_connection.monitor_pages != NULL) { - contigfree( - hv_vmbus_g_connection.monitor_pages, - 2 * PAGE_SIZE, - M_DEVBUF); - hv_vmbus_g_connection.monitor_pages = NULL; - } + free(hv_vmbus_g_connection.monitor_page_1, M_DEVBUF); + free(hv_vmbus_g_connection.monitor_page_2, M_DEVBUF); if (msg_info) { sema_destroy(&msg_info->wait_sema); @@ -305,32 +273,19 @@ hv_vmbus_connect(void) { int hv_vmbus_disconnect(void) { int ret = 0; - hv_vmbus_channel_unload* msg; - - msg = malloc(sizeof(hv_vmbus_channel_unload), - M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(msg != NULL, - ("Error VMBUS: malloc failed to allocate Channel Unload Msg!")); - if (msg == NULL) - return (ENOMEM); + hv_vmbus_channel_unload msg; - msg->message_type = HV_CHANNEL_MESSAGE_UNLOAD; - - ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_unload)); + msg.message_type = HV_CHANNEL_MESSAGE_UNLOAD; + ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload)); contigfree(hv_vmbus_g_connection.interrupt_page, PAGE_SIZE, M_DEVBUF); mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock); - hv_work_queue_close(hv_vmbus_g_connection.work_queue); - sema_destroy(&hv_vmbus_g_connection.control_sema); - free(hv_vmbus_g_connection.channels, M_DEVBUF); hv_vmbus_g_connection.connect_state = HV_DISCONNECTED; - free(msg, M_DEVBUF); - return (ret); } diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hv_hv.c index ca5641f..6afc2b8 100644 --- a/sys/dev/hyperv/vmbus/hv_hv.c +++ b/sys/dev/hyperv/vmbus/hv_hv.c @@ -189,11 +189,7 @@ hv_vmbus_init(void) * See if the hypercall page is already set */ hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL); - virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(virt_addr != NULL, - ("Error VMBUS: malloc failed to allocate page during init!")); - if (virt_addr == NULL) - goto cleanup; + virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); hypercall_msr.u.enable = 1; hypercall_msr.u.guest_physical_address = diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c index 7eac116..8a1e412 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -83,8 +83,6 @@ vmbus_msg_swintr(void *arg) hv_vmbus_channel_msg_table_entry *entry; hv_vmbus_channel_msg_type msg_type; hv_vmbus_message* msg; - hv_vmbus_message* copied; - static bool warned = false; cpu = (int)(long)arg; KASSERT(cpu <= mp_maxid, ("VMBUS: vmbus_msg_swintr: " @@ -100,31 +98,15 @@ vmbus_msg_swintr(void *arg) hdr = (hv_vmbus_channel_msg_header *)msg->u.payload; msg_type = hdr->message_type; - if (msg_type >= HV_CHANNEL_MESSAGE_COUNT && !warned) { - warned = true; + if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) { printf("VMBUS: unknown message type = %d\n", msg_type); goto handled; } entry = &g_channel_message_table[msg_type]; - if (entry->handler_no_sleep) + if (entry->messageHandler) entry->messageHandler(hdr); - else { - - copied = malloc(sizeof(hv_vmbus_message), - M_DEVBUF, M_NOWAIT); - KASSERT(copied != NULL, - ("Error VMBUS: malloc failed to allocate" - " hv_vmbus_message!")); - if (copied == NULL) - continue; - - memcpy(copied, msg, sizeof(hv_vmbus_message)); - hv_queue_work_item(hv_vmbus_g_connection.work_queue, - hv_vmbus_on_channel_message, - copied); - } handled: msg->header.message_type = HV_MESSAGE_TYPE_NONE; @@ -309,12 +291,7 @@ hv_vmbus_child_device_create( * Allocate the new child device */ child_dev = malloc(sizeof(hv_device), M_DEVBUF, - M_NOWAIT | M_ZERO); - KASSERT(child_dev != NULL, - ("Error VMBUS: malloc failed to allocate hv_device!")); - - if (child_dev == NULL) - return (NULL); + M_WAITOK | M_ZERO); child_dev->channel = channel; memcpy(&child_dev->class_id, &type, sizeof(hv_guid)); @@ -566,12 +543,7 @@ vmbus_bus_init(void) */ for(i = 0; i < 2; i++) { setup_args.page_buffers[2 * j + i] = - malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); - if (setup_args.page_buffers[2 * j + i] == NULL) { - KASSERT(setup_args.page_buffers[2 * j + i] != NULL, - ("Error VMBUS: malloc failed!")); - goto cleanup1; - } + malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); } } diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h index 538ab1e..5f62072 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -350,7 +350,8 @@ typedef struct { * notification and 2nd is child->parent * notification */ - void *monitor_pages; + void *monitor_page_1; + void *monitor_page_2; TAILQ_HEAD(, hv_vmbus_channel_msg_info) channel_msg_anchor; struct mtx channel_msg_lock; /** @@ -362,10 +363,8 @@ typedef struct { /** * channel table for fast lookup through id. - */ + */ hv_vmbus_channel **channels; - hv_vmbus_handle work_queue; - struct sema control_sema; } hv_vmbus_connection; typedef union { @@ -632,7 +631,6 @@ typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg); typedef struct hv_vmbus_channel_msg_table_entry { hv_vmbus_channel_msg_type messageType; - bool handler_no_sleep; /* true: the handler doesn't sleep */ vmbus_msg_handler messageHandler; } hv_vmbus_channel_msg_table_entry; @@ -682,7 +680,6 @@ uint32_t hv_ring_buffer_read_end( hv_vmbus_channel* hv_vmbus_allocate_channel(void); void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel); -void hv_vmbus_on_channel_message(void *context); int hv_vmbus_request_channel_offers(void); void hv_vmbus_release_unattached_channels(void); int hv_vmbus_init(void); diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index c6a5084..f0e218f 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -1017,6 +1017,7 @@ static void ixgbe_set_if_hwassist(struct adapter *adapter) { struct ifnet *ifp = adapter->ifp; + struct ixgbe_hw *hw = &adapter->hw; ifp->if_hwassist = 0; #if __FreeBSD_version >= 1000000 @@ -1024,18 +1025,21 @@ ixgbe_set_if_hwassist(struct adapter *adapter) ifp->if_hwassist |= CSUM_IP_TSO; if (ifp->if_capenable & IFCAP_TSO6) ifp->if_hwassist |= CSUM_IP6_TSO; - if (ifp->if_capenable & IFCAP_TXCSUM) - ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP | - CSUM_IP_SCTP); - if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) - ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP | - CSUM_IP6_SCTP); + if (ifp->if_capenable & IFCAP_TXCSUM) { + ifp->if_hwassist |= (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP); + if (hw->mac.type != ixgbe_mac_82598EB) + ifp->if_hwassist |= CSUM_IP_SCTP; + } + if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) { + ifp->if_hwassist |= (CSUM_IP6_UDP | CSUM_IP6_TCP); + if (hw->mac.type != ixgbe_mac_82598EB) + ifp->if_hwassist |= CSUM_IP6_SCTP; + } #else if (ifp->if_capenable & IFCAP_TSO) ifp->if_hwassist |= CSUM_TSO; if (ifp->if_capenable & IFCAP_TXCSUM) { ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); - struct ixgbe_hw *hw = &adapter->hw; if (hw->mac.type != ixgbe_mac_82598EB) ifp->if_hwassist |= CSUM_SCTP; } diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index 4080fc6..5f18341 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -1476,6 +1476,14 @@ mps_setup_sysctl(struct mps_softc *sc) OID_AUTO, "spinup_wait_time", CTLFLAG_RD, &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for " "spinup after SATA ID error"); + + SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "mapping_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, + mps_mapping_dump, "A", "Mapping Table Dump"); + + SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), + OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, + mps_mapping_encl_dump, "A", "Enclosure Table Dump"); } int diff --git a/sys/dev/mps/mps_mapping.c b/sys/dev/mps/mps_mapping.c index d96f33c..351625b 100644 --- a/sys/dev/mps/mps_mapping.c +++ b/sys/dev/mps/mps_mapping.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/endian.h> #include <sys/sysctl.h> +#include <sys/sbuf.h> #include <sys/eventhandler.h> #include <sys/uio.h> #include <machine/bus.h> @@ -2263,3 +2264,61 @@ out: if (sc->pending_map_events) sc->pending_map_events--; } + +int +mps_mapping_dump(SYSCTL_HANDLER_ARGS) +{ + struct mps_softc *sc; + struct dev_mapping_table *mt_entry; + struct sbuf sbuf; + int i, error; + + sc = (struct mps_softc *)arg1; + + error = sysctl_wire_old_buffer(req, 0); + if (error != 0) + return (error); + sbuf_new_for_sysctl(&sbuf, NULL, 128, req); + + sbuf_printf(&sbuf, "\nindex physical_id handle id\n"); + for (i = 0; i < sc->max_devices; i++) { + mt_entry = &sc->mapping_table[i]; + if (mt_entry->physical_id == 0) + continue; + sbuf_printf(&sbuf, "%4d %jx %04x %hd\n", + i, mt_entry->physical_id, mt_entry->dev_handle, + mt_entry->id); + } + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + return (error); +} + +int +mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS) +{ + struct mps_softc *sc; + struct enc_mapping_table *enc_entry; + struct sbuf sbuf; + int i, error; + + sc = (struct mps_softc *)arg1; + + error = sysctl_wire_old_buffer(req, 0); + if (error != 0) + return (error); + sbuf_new_for_sysctl(&sbuf, NULL, 128, req); + + sbuf_printf(&sbuf, "\nindex enclosure_id handle map_index\n"); + for (i = 0; i < sc->max_enclosures; i++) { + enc_entry = &sc->enclosure_table[i]; + if (enc_entry->enclosure_id == 0) + continue; + sbuf_printf(&sbuf, "%4d %jx %04x %d\n", + i, enc_entry->enclosure_id, enc_entry->enc_handle, + enc_entry->start_index); + } + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + return (error); +} diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index 96bb4e1..0cb51a0 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -756,6 +756,8 @@ void mps_mapping_enclosure_dev_status_change_event(struct mps_softc *, Mpi2EventDataSasEnclDevStatusChange_t *event_data); void mps_mapping_ir_config_change_event(struct mps_softc *sc, Mpi2EventDataIrConfigChangeList_t *event_data); +int mps_mapping_dump(SYSCTL_HANDLER_ARGS); +int mps_mapping_encl_dump(SYSCTL_HANDLER_ARGS); void mpssas_evt_handler(struct mps_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *event); diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index a1f8780..983b869 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -741,8 +741,7 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir) if (off + isonum_711(isodir->length) > imp->logical_block_size) { vput(vp); - if (bp != 0) - brelse(bp); + brelse(bp); printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n", off +isonum_711(isodir->length), off, isonum_711(isodir->length)); diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c index 78679cf..d62e9ba 100644 --- a/sys/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/fs/ext2fs/ext2_inode_cnv.c @@ -149,11 +149,13 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei) ei->e2di_atime = ip->i_atime; ei->e2di_mtime = ip->i_mtime; ei->e2di_ctime = ip->i_ctime; - ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec); - ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec); - ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec); - ei->e2di_crtime = ip->i_birthtime; - ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec); + if (E2DI_HAS_XTIME(ip)) { + ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec); + ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec); + ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec); + ei->e2di_crtime = ip->i_birthtime; + ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec); + } ei->e2di_flags = 0; ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0; ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0; diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index 5a2a6a9..74a7e32 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -941,14 +941,10 @@ msdosfs_rename(struct vop_rename_args *ap) int error; u_long cn, pcl; daddr_t bn; - struct denode *fddep; /* from file's parent directory */ struct msdosfsmount *pmp; struct direntry *dotdotp; struct buf *bp; - fddep = VTODE(ap->a_fdvp); - pmp = fddep->de_pmp; - pmp = VFSTOMSDOSFS(fdvp->v_mount); #ifdef DIAGNOSTIC diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 8a7a11a..43d4800 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -258,7 +258,7 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, int interp_name_len, int32_t *osrel) { const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; - Elf_Brandinfo *bi; + Elf_Brandinfo *bi, *bi_m; boolean_t ret; int i; @@ -270,6 +270,7 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, */ /* Look for an ".note.ABI-tag" ELF section */ + bi_m = NULL; for (i = 0; i < MAX_BRANDS; i++) { bi = elf_brand_list[i]; if (bi == NULL) @@ -280,10 +281,28 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, /* Give brand a chance to veto check_note's guess */ if (ret && bi->header_supported) ret = bi->header_supported(imgp); + /* + * If note checker claimed the binary, but the + * interpreter path in the image does not + * match default one for the brand, try to + * search for other brands with the same + * interpreter. Either there is better brand + * with the right interpreter, or, failing + * this, we return first brand which accepted + * our note and, optionally, header. + */ + if (ret && bi_m == NULL && (strlen(bi->interp_path) + + 1 != interp_name_len || strncmp(interp, + bi->interp_path, interp_name_len) != 0)) { + bi_m = bi; + ret = 0; + } if (ret) return (bi); } } + if (bi_m != NULL) + return (bi_m); /* If the executable has a brand, search for it in the brand list. */ for (i = 0; i < MAX_BRANDS; i++) { diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 8d5580b..d5f8f4d 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -828,12 +828,15 @@ start_init(void *dummy) static void create_init(const void *udata __unused) { + struct fork_req fr; struct ucred *newcred, *oldcred; struct thread *td; int error; - error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc, - NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFSTOPPED; + fr.fr_procp = &initproc; + error = fork1(&thread0, &fr); if (error) panic("cannot fork init: %d\n", error); KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1")); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index e7d7276..9abe08c 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -101,12 +101,15 @@ struct fork_args { int sys_fork(struct thread *td, struct fork_args *uap) { - int error; - struct proc *p2; + struct fork_req fr; + int error, pid; - error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC; + fr.fr_pidp = &pid; + error = fork1(td, &fr); if (error == 0) { - td->td_retval[0] = p2->p_pid; + td->td_retval[0] = pid; td->td_retval[1] = 0; } return (error); @@ -114,22 +117,24 @@ sys_fork(struct thread *td, struct fork_args *uap) /* ARGUSED */ int -sys_pdfork(td, uap) - struct thread *td; - struct pdfork_args *uap; +sys_pdfork(struct thread *td, struct pdfork_args *uap) { - int error, fd; - struct proc *p2; - + struct fork_req fr; + int error, fd, pid; + + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; + fr.fr_pidp = &pid; + fr.fr_pd_fd = &fd; + fr.fr_pd_flags = uap->flags; /* * It is necessary to return fd by reference because 0 is a valid file * descriptor number, and the child needs to be able to distinguish * itself from the parent using the return value. */ - error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, - &fd, uap->flags, NULL); + error = fork1(td, &fr); if (error == 0) { - td->td_retval[0] = p2->p_pid; + td->td_retval[0] = pid; td->td_retval[1] = 0; error = copyout(&fd, uap->fdp, sizeof(fd)); } @@ -140,13 +145,15 @@ sys_pdfork(td, uap) int sys_vfork(struct thread *td, struct vfork_args *uap) { - int error, flags; - struct proc *p2; + struct fork_req fr; + int error, pid; - flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; - error = fork1(td, flags, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; + fr.fr_pidp = &pid; + error = fork1(td, &fr); if (error == 0) { - td->td_retval[0] = p2->p_pid; + td->td_retval[0] = pid; td->td_retval[1] = 0; } return (error); @@ -155,17 +162,20 @@ sys_vfork(struct thread *td, struct vfork_args *uap) int sys_rfork(struct thread *td, struct rfork_args *uap) { - struct proc *p2; - int error; + struct fork_req fr; + int error, pid; /* Don't allow kernel-only flags. */ if ((uap->flags & RFKERNELONLY) != 0) return (EINVAL); AUDIT_ARG_FFLAGS(uap->flags); - error = fork1(td, uap->flags, 0, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = uap->flags; + fr.fr_pidp = &pid; + error = fork1(td, &fr); if (error == 0) { - td->td_retval[0] = p2 ? p2->p_pid : 0; + td->td_retval[0] = pid; td->td_retval[1] = 0; } return (error); @@ -366,11 +376,11 @@ fail: } static void -do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, - struct vmspace *vm2, int pdflags) +do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *td2, + struct vmspace *vm2, struct file *fp_procdesc) { struct proc *p1, *pptr; - int p2_held, trypid; + int trypid; struct filedesc *fd; struct filedesc_to_leader *fdtol; struct sigacts *newsigacts; @@ -378,10 +388,9 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, sx_assert(&proctree_lock, SX_SLOCKED); sx_assert(&allproc_lock, SX_XLOCKED); - p2_held = 0; p1 = td->td_proc; - trypid = fork_findpid(flags); + trypid = fork_findpid(fr->fr_flags); sx_sunlock(&proctree_lock); @@ -414,7 +423,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, /* * Malloc things while we don't hold any locks. */ - if (flags & RFSIGSHARE) + if (fr->fr_flags & RFSIGSHARE) newsigacts = NULL; else newsigacts = sigacts_alloc(); @@ -422,10 +431,10 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, /* * Copy filedesc. */ - if (flags & RFCFDG) { + if (fr->fr_flags & RFCFDG) { fd = fdinit(p1->p_fd, false); fdtol = NULL; - } else if (flags & RFFDG) { + } else if (fr->fr_flags & RFFDG) { fd = fdcopy(p1->p_fd); fdtol = NULL; } else { @@ -433,7 +442,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, if (p1->p_fdtol == NULL) p1->p_fdtol = filedesc_to_leader_alloc(NULL, NULL, p1->p_leader); - if ((flags & RFTHREAD) != 0) { + if ((fr->fr_flags & RFTHREAD) != 0) { /* * Shared file descriptor table, and shared * process leaders. @@ -501,16 +510,16 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, vm_domain_policy_localcopy(&p2->p_vm_dom_policy, &p1->p_vm_dom_policy); - if (flags & RFSIGSHARE) { + if (fr->fr_flags & RFSIGSHARE) { p2->p_sigacts = sigacts_hold(p1->p_sigacts); } else { sigacts_copy(newsigacts, p1->p_sigacts); p2->p_sigacts = newsigacts; } - if (flags & RFTSIGZMB) - p2->p_sigparent = RFTSIGNUM(flags); - else if (flags & RFLINUXTHPN) + if (fr->fr_flags & RFTSIGZMB) + p2->p_sigparent = RFTSIGNUM(fr->fr_flags); + else if (fr->fr_flags & RFLINUXTHPN) p2->p_sigparent = SIGUSR1; else p2->p_sigparent = SIGCHLD; @@ -543,7 +552,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, /* * Set up linkage for kernel based threading. */ - if ((flags & RFTHREAD) != 0) { + if ((fr->fr_flags & RFTHREAD) != 0) { mtx_lock(&ppeers_lock); p2->p_peers = p1->p_peers; p1->p_peers = p2; @@ -590,7 +599,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) p2->p_flag |= P_CONTROLT; SESS_UNLOCK(p1->p_session); - if (flags & RFPPWAIT) + if (fr->fr_flags & RFPPWAIT) p2->p_flag |= P_PPWAIT; p2->p_pgrp = p1->p_pgrp; @@ -624,7 +633,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * of init. This effectively disassociates the child from the * parent. */ - if ((flags & RFNOWAIT) != 0) { + if ((fr->fr_flags & RFNOWAIT) != 0) { pptr = p1->p_reaper; p2->p_reaper = pptr; } else { @@ -652,13 +661,13 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * Finish creating the child process. It will return via a different * execution path later. (ie: directly into user mode) */ - vm_forkproc(td, p2, td2, vm2, flags); + vm_forkproc(td, p2, td2, vm2, fr->fr_flags); - if (flags == (RFFDG | RFPROC)) { + if (fr->fr_flags == (RFFDG | RFPROC)) { PCPU_INC(cnt.v_forks); PCPU_ADD(cnt.v_forkpages, p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize); - } else if (flags == (RFFDG | RFPROC | RFPPWAIT | RFMEM)) { + } else if (fr->fr_flags == (RFFDG | RFPROC | RFPPWAIT | RFMEM)) { PCPU_INC(cnt.v_vforks); PCPU_ADD(cnt.v_vforkpages, p2->p_vmspace->vm_dsize + p2->p_vmspace->vm_ssize); @@ -677,14 +686,14 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * can happen that might cause that process to need the descriptor. * However, don't do this until after fork(2) can no longer fail. */ - if (flags & RFPROCDESC) - procdesc_new(p2, pdflags); + if (fr->fr_flags & RFPROCDESC) + procdesc_new(p2, fr->fr_pd_flags); /* * Both processes are set up, now check if any loadable modules want * to adjust anything. */ - EVENTHANDLER_INVOKE(process_fork, p1, p2, flags); + EVENTHANDLER_INVOKE(process_fork, p1, p2, fr->fr_flags); /* * Set the child start time and mark the process as being complete. @@ -703,9 +712,14 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * this only after p_state is PRS_NORMAL since the fasttrap module will * use pfind() later on. */ - if ((flags & RFMEM) == 0 && dtrace_fasttrap_fork) + if ((fr->fr_flags & RFMEM) == 0 && dtrace_fasttrap_fork) dtrace_fasttrap_fork(p1, p2); #endif + /* + * Hold the process so that it cannot exit after we make it runnable, + * but before we wait for the debugger. + */ + _PHOLD(p2); if ((p1->p_flag & (P_TRACED | P_FOLLOWFORK)) == (P_TRACED | P_FOLLOWFORK)) { /* @@ -718,24 +732,12 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, td->td_dbgflags |= TDB_FORK; td->td_dbg_forked = p2->p_pid; td2->td_dbgflags |= TDB_STOPATFORK; - _PHOLD(p2); - p2_held = 1; } - if (flags & RFPPWAIT) { + if (fr->fr_flags & RFPPWAIT) { td->td_pflags |= TDP_RFPPWAIT; td->td_rfppwait_p = p2; } PROC_UNLOCK(p2); - if ((flags & RFSTOPPED) == 0) { - /* - * If RFSTOPPED not requested, make child runnable and - * add to run queue. - */ - thread_lock(td2); - TD_SET_CAN_RUN(td2); - sched_add(td2, SRQ_BORING); - thread_unlock(td2); - } /* * Now can be swapped. @@ -747,22 +749,41 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * Tell any interested parties about the new process. */ knote_fork(&p1->p_klist, p2->p_pid); - SDT_PROBE3(proc, , , create, p2, p1, flags); + SDT_PROBE3(proc, , , create, p2, p1, fr->fr_flags); + if (fr->fr_flags & RFPROCDESC) { + procdesc_finit(p2->p_procdesc, fp_procdesc); + fdrop(fp_procdesc, td); + } + + if ((fr->fr_flags & RFSTOPPED) == 0) { + /* + * If RFSTOPPED not requested, make child runnable and + * add to run queue. + */ + thread_lock(td2); + TD_SET_CAN_RUN(td2); + sched_add(td2, SRQ_BORING); + thread_unlock(td2); + if (fr->fr_pidp != NULL) + *fr->fr_pidp = p2->p_pid; + } else { + *fr->fr_procp = p2; + } + + PROC_LOCK(p2); /* * Wait until debugger is attached to child. */ - PROC_LOCK(p2); - while ((td2->td_dbgflags & TDB_STOPATFORK) != 0) + while (td2->td_proc == p2 && (td2->td_dbgflags & TDB_STOPATFORK) != 0) cv_wait(&p2->p_dbgwait, &p2->p_mtx); - if (p2_held) - _PRELE(p2); + _PRELE(p2); + racct_proc_fork_done(p2); PROC_UNLOCK(p2); } int -fork1(struct thread *td, int flags, int pages, struct proc **procp, - int *procdescp, int pdflags, struct filecaps *fcaps) +fork1(struct thread *td, struct fork_req *fr) { struct proc *p1, *newproc; struct thread *td2; @@ -772,6 +793,15 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, int error, nprocs_new, ok; static int curfail; static struct timeval lastfail; + int flags, pages; + + flags = fr->fr_flags; + pages = fr->fr_pages; + + if ((flags & RFSTOPPED) != 0) + MPASS(fr->fr_procp != NULL && fr->fr_pidp == NULL); + else + MPASS(fr->fr_procp == NULL); /* Check for the undefined or unimplemented flags. */ if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0) @@ -795,7 +825,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, return (EINVAL); /* Must provide a place to put a procdesc if creating one. */ - if (procdescp == NULL) + if (fr->fr_pd_fd == NULL) return (EINVAL); } @@ -806,7 +836,10 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, * certain parts of a process from itself. */ if ((flags & RFPROC) == 0) { - *procp = NULL; + if (fr->fr_procp != NULL) + *fr->fr_procp = NULL; + else if (fr->fr_pidp != NULL) + *fr->fr_pidp = 0; return (fork_norfproc(td, flags)); } @@ -845,7 +878,8 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, * later. */ if (flags & RFPROCDESC) { - error = falloc_caps(td, &fp_procdesc, procdescp, 0, fcaps); + error = falloc_caps(td, &fp_procdesc, fr->fr_pd_fd, 0, + fr->fr_pd_fcaps); if (error != 0) goto fail2; } @@ -933,17 +967,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, lim_cur(td, RLIMIT_NPROC)); } if (ok) { - do_fork(td, flags, newproc, td2, vm2, pdflags); - - /* - * Return child proc pointer to parent. - */ - *procp = newproc; - if (flags & RFPROCDESC) { - procdesc_finit(newproc->p_procdesc, fp_procdesc); - fdrop(fp_procdesc, td); - } - racct_proc_fork_done(newproc); + do_fork(td, fr, newproc, td2, vm2, fp_procdesc); return (0); } @@ -962,7 +986,7 @@ fail2: vmspace_free(vm2); uma_zfree(proc_zone, newproc); if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) { - fdclose(td, fp_procdesc, *procdescp); + fdclose(td, fp_procdesc, *fr->fr_pd_fd); fdrop(fp_procdesc, td); } atomic_add_int(&nprocs, -1); diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index 2072dc7..9cca255 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -80,6 +80,7 @@ int kproc_create(void (*func)(void *), void *arg, struct proc **newpp, int flags, int pages, const char *fmt, ...) { + struct fork_req fr; int error; va_list ap; struct thread *td; @@ -88,8 +89,11 @@ kproc_create(void (*func)(void *), void *arg, if (!proc0.p_stats) panic("kproc_create called too soon"); - error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags, - pages, &p2, NULL, 0, NULL); + bzero(&fr, sizeof(fr)); + fr.fr_flags = RFMEM | RFFDG | RFPROC | RFSTOPPED | flags; + fr.fr_pages = pages; + fr.fr_procp = &p2; + error = fork1(&thread0, &fr); if (error) return error; diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index e7c81d6..f7c67f2 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/sbuf.h> #include <sys/sysctl.h> +#include <sys/taskqueue.h> #include <sys/time.h> #include <sys/vmem.h> diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index a864c94..5596439 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_map.h> #include <vm/uma.h> -#include <vm/uma_int.h> #include <vm/uma_dbg.h> /* @@ -275,12 +274,6 @@ uma_zone_t zone_jumbo16; uma_zone_t zone_ext_refcnt; /* - * Callout to assist us in freeing mbufs. - */ -static struct callout mb_reclaim_callout; -static struct mtx mb_reclaim_callout_mtx; - -/* * Local prototypes. */ static int mb_ctor_mbuf(void *, int, void *, int); @@ -292,9 +285,8 @@ static void mb_dtor_pack(void *, int, void *); static int mb_zinit_pack(void *, int, int); static void mb_zfini_pack(void *, int); -static void mb_reclaim(void *); +static void mb_reclaim(uma_zone_t, int); static void *mbuf_jumbo_alloc(uma_zone_t, vm_size_t, uint8_t *, int); -static void mb_maxaction(uma_zone_t); /* Ensure that MSIZE is a power of 2. */ CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE); @@ -320,7 +312,7 @@ mbuf_init(void *dummy) if (nmbufs > 0) nmbufs = uma_zone_set_max(zone_mbuf, nmbufs); uma_zone_set_warning(zone_mbuf, "kern.ipc.nmbufs limit reached"); - uma_zone_set_maxaction(zone_mbuf, mb_maxaction); + uma_zone_set_maxaction(zone_mbuf, mb_reclaim); zone_clust = uma_zcreate(MBUF_CLUSTER_MEM_NAME, MCLBYTES, mb_ctor_clust, mb_dtor_clust, @@ -333,7 +325,7 @@ mbuf_init(void *dummy) if (nmbclusters > 0) nmbclusters = uma_zone_set_max(zone_clust, nmbclusters); uma_zone_set_warning(zone_clust, "kern.ipc.nmbclusters limit reached"); - uma_zone_set_maxaction(zone_clust, mb_maxaction); + uma_zone_set_maxaction(zone_clust, mb_reclaim); zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack, mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf); @@ -350,7 +342,7 @@ mbuf_init(void *dummy) if (nmbjumbop > 0) nmbjumbop = uma_zone_set_max(zone_jumbop, nmbjumbop); uma_zone_set_warning(zone_jumbop, "kern.ipc.nmbjumbop limit reached"); - uma_zone_set_maxaction(zone_jumbop, mb_maxaction); + uma_zone_set_maxaction(zone_jumbop, mb_reclaim); zone_jumbo9 = uma_zcreate(MBUF_JUMBO9_MEM_NAME, MJUM9BYTES, mb_ctor_clust, mb_dtor_clust, @@ -364,7 +356,7 @@ mbuf_init(void *dummy) if (nmbjumbo9 > 0) nmbjumbo9 = uma_zone_set_max(zone_jumbo9, nmbjumbo9); uma_zone_set_warning(zone_jumbo9, "kern.ipc.nmbjumbo9 limit reached"); - uma_zone_set_maxaction(zone_jumbo9, mb_maxaction); + uma_zone_set_maxaction(zone_jumbo9, mb_reclaim); zone_jumbo16 = uma_zcreate(MBUF_JUMBO16_MEM_NAME, MJUM16BYTES, mb_ctor_clust, mb_dtor_clust, @@ -378,20 +370,13 @@ mbuf_init(void *dummy) if (nmbjumbo16 > 0) nmbjumbo16 = uma_zone_set_max(zone_jumbo16, nmbjumbo16); uma_zone_set_warning(zone_jumbo16, "kern.ipc.nmbjumbo16 limit reached"); - uma_zone_set_maxaction(zone_jumbo16, mb_maxaction); + uma_zone_set_maxaction(zone_jumbo16, mb_reclaim); zone_ext_refcnt = uma_zcreate(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_ZINIT); - /* uma_prealloc() goes here... */ - - /* Initialize the mb_reclaim() callout. */ - mtx_init(&mb_reclaim_callout_mtx, "mb_reclaim_callout_mtx", NULL, - MTX_DEF); - callout_init(&mb_reclaim_callout, 1); - /* * Hook event handler for low-memory situation, used to * drain protocols and push data back to the caches (UMA @@ -678,81 +663,23 @@ m_pkthdr_init(struct mbuf *m, int how) } /* - * This is the protocol drain routine. + * This is the protocol drain routine. Called by UMA whenever any of the + * mbuf zones is closed to its limit. * * No locks should be held when this is called. The drain routines have to * presently acquire some locks which raises the possibility of lock order * reversal. */ static void -mb_reclaim(void *junk) +mb_reclaim(uma_zone_t zone __unused, int pending __unused) { struct domain *dp; struct protosw *pr; - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL, - "mb_reclaim()"); + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL, __func__); for (dp = domains; dp != NULL; dp = dp->dom_next) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_drain != NULL) (*pr->pr_drain)(); } - -/* - * This is the function called by the mb_reclaim_callout, which is - * used when we hit the maximum for a zone. - * - * (See mb_maxaction() below.) - */ -static void -mb_reclaim_timer(void *junk __unused) -{ - - mtx_lock(&mb_reclaim_callout_mtx); - - /* - * Avoid running this function extra times by skipping this invocation - * if the callout has already been rescheduled. - */ - if (callout_pending(&mb_reclaim_callout) || - !callout_active(&mb_reclaim_callout)) { - mtx_unlock(&mb_reclaim_callout_mtx); - return; - } - mtx_unlock(&mb_reclaim_callout_mtx); - - mb_reclaim(NULL); - - mtx_lock(&mb_reclaim_callout_mtx); - callout_deactivate(&mb_reclaim_callout); - mtx_unlock(&mb_reclaim_callout_mtx); -} - -/* - * This function is called when we hit the maximum for a zone. - * - * At that point, we want to call the protocol drain routine to free up some - * mbufs. However, we will use the callout routines to schedule this to - * occur in another thread. (The thread calling this function holds the - * zone lock.) - */ -static void -mb_maxaction(uma_zone_t zone __unused) -{ - - /* - * If we can't immediately obtain the lock, either the callout - * is currently running, or another thread is scheduling the - * callout. - */ - if (!mtx_trylock(&mb_reclaim_callout_mtx)) - return; - - /* If not already scheduled/running, schedule the callout. */ - if (!callout_active(&mb_reclaim_callout)) { - callout_reset(&mb_reclaim_callout, 1, mb_reclaim_timer, NULL); - } - - mtx_unlock(&mb_reclaim_callout_mtx); -} diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index a4f8576..729d7f0 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2983,6 +2983,12 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_SIGTRAMP, sigtramp, CTLFLAG_RD | int allproc_gen; +/* + * stop_all_proc() purpose is to stop all process which have usermode, + * except current process for obvious reasons. This makes it somewhat + * unreliable when invoked from multithreaded process. The service + * must not be user-callable anyway. + */ void stop_all_proc(void) { @@ -2991,17 +2997,6 @@ stop_all_proc(void) bool restart, seen_stopped, seen_exiting, stopped_some; cp = curproc; - /* - * stop_all_proc() assumes that all process which have - * usermode must be stopped, except current process, for - * obvious reasons. Since other threads in the process - * establishing global stop could unstop something, disable - * calls from multithreaded processes as precaution. The - * service must not be user-callable anyway. - */ - KASSERT((cp->p_flag & P_HADTHREADS) == 0 || - (cp->p_flag & P_KTHREAD) != 0, ("mt stop_all_proc")); - allproc_loop: sx_xlock(&allproc_lock); gen = allproc_gen; @@ -3088,7 +3083,7 @@ resume_all_proc(void) sx_xunlock(&allproc_lock); } -#define TOTAL_STOP_DEBUG 1 +/* #define TOTAL_STOP_DEBUG 1 */ #ifdef TOTAL_STOP_DEBUG volatile static int ap_resume; #include <sys/mount.h> diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c index 0c7c0c4..ce7e2a4 100644 --- a/sys/kern/kern_racct.c +++ b/sys/kern/kern_racct.c @@ -957,16 +957,15 @@ void racct_proc_fork_done(struct proc *child) { + PROC_LOCK_ASSERT(child, MA_OWNED); #ifdef RCTL if (!racct_enable) return; - PROC_LOCK(child); mtx_lock(&racct_lock); rctl_enforce(child, RACCT_NPROC, 0); rctl_enforce(child, RACCT_NTHR, 0); mtx_unlock(&racct_lock); - PROC_UNLOCK(child); #endif } diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index d9324f4..22616b9 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -867,6 +867,11 @@ sys_semget(struct thread *td, struct semget_args *uap) } if (semid < seminfo.semmni) { DPRINTF(("found public key\n")); + if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) { + DPRINTF(("not exclusive\n")); + error = EEXIST; + goto done2; + } if ((error = ipcperm(td, &sema[semid].u.sem_perm, semflg & 0700))) { goto done2; @@ -876,11 +881,6 @@ sys_semget(struct thread *td, struct semget_args *uap) error = EINVAL; goto done2; } - if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) { - DPRINTF(("not exclusive\n")); - error = EEXIST; - goto done2; - } #ifdef MAC error = mac_sysvsem_check_semget(cred, &sema[semid]); if (error != 0) diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 14a66c3..5b2083c 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -196,7 +196,7 @@ typedef struct oaiocb { } oaiocb_t; /* - * Below is a key of locks used to protect each member of struct aiocblist + * Below is a key of locks used to protect each member of struct kaiocb * aioliojob and kaioinfo and any backends. * * * - need not protected @@ -219,10 +219,10 @@ typedef struct oaiocb { * daemons. */ -struct aiocblist { - TAILQ_ENTRY(aiocblist) list; /* (b) internal list of for backend */ - TAILQ_ENTRY(aiocblist) plist; /* (a) list of jobs for each backend */ - TAILQ_ENTRY(aiocblist) allist; /* (a) list of all jobs in proc */ +struct kaiocb { + TAILQ_ENTRY(kaiocb) list; /* (b) internal list of for backend */ + TAILQ_ENTRY(kaiocb) plist; /* (a) list of jobs for each backend */ + TAILQ_ENTRY(kaiocb) allist; /* (a) list of all jobs in proc */ int jobflags; /* (a) job flags */ int jobstate; /* (b) job state */ int inputcharge; /* (*) input blockes */ @@ -235,7 +235,7 @@ struct aiocblist { struct ucred *cred; /* (*) active credential when created */ struct file *fd_file; /* (*) pointer to file structure */ struct aioliojob *lio; /* (*) optional lio job */ - struct aiocb *uuaiocb; /* (*) pointer in userspace of aiocb */ + struct aiocb *ujob; /* (*) pointer in userspace of aiocb */ struct knlist klist; /* (a) list of knotes */ struct aiocb uaiocb; /* (*) kernel I/O control block */ ksiginfo_t ksi; /* (a) realtime signal info */ @@ -244,10 +244,10 @@ struct aiocblist { }; /* jobflags */ -#define AIOCBLIST_DONE 0x01 -#define AIOCBLIST_BUFDONE 0x02 -#define AIOCBLIST_RUNDOWN 0x04 -#define AIOCBLIST_CHECKSYNC 0x08 +#define KAIOCB_DONE 0x01 +#define KAIOCB_BUFDONE 0x02 +#define KAIOCB_RUNDOWN 0x04 +#define KAIOCB_CHECKSYNC 0x08 /* * AIO process info @@ -289,12 +289,12 @@ struct kaioinfo { int kaio_count; /* (a) size of AIO queue */ int kaio_ballowed_count; /* (*) maximum number of buffers */ int kaio_buffer_count; /* (a) number of physio buffers */ - TAILQ_HEAD(,aiocblist) kaio_all; /* (a) all AIOs in a process */ - TAILQ_HEAD(,aiocblist) kaio_done; /* (a) done queue for process */ + TAILQ_HEAD(,kaiocb) kaio_all; /* (a) all AIOs in a process */ + TAILQ_HEAD(,kaiocb) kaio_done; /* (a) done queue for process */ TAILQ_HEAD(,aioliojob) kaio_liojoblist; /* (a) list of lio jobs */ - TAILQ_HEAD(,aiocblist) kaio_jobqueue; /* (a) job queue for process */ - TAILQ_HEAD(,aiocblist) kaio_bufqueue; /* (a) buffer job queue */ - TAILQ_HEAD(,aiocblist) kaio_syncqueue; /* (a) queue for aio_fsync */ + TAILQ_HEAD(,kaiocb) kaio_jobqueue; /* (a) job queue for process */ + TAILQ_HEAD(,kaiocb) kaio_bufqueue; /* (a) buffer job queue */ + TAILQ_HEAD(,kaiocb) kaio_syncqueue; /* (a) queue for aio_fsync */ struct task kaio_task; /* (*) task to kick aio processes */ }; @@ -323,28 +323,28 @@ struct aiocb_ops { static TAILQ_HEAD(,aioproc) aio_freeproc; /* (c) Idle daemons */ static struct sema aio_newproc_sem; static struct mtx aio_job_mtx; -static TAILQ_HEAD(,aiocblist) aio_jobs; /* (c) Async job list */ +static TAILQ_HEAD(,kaiocb) aio_jobs; /* (c) Async job list */ static struct unrhdr *aiod_unr; void aio_init_aioinfo(struct proc *p); static int aio_onceonly(void); -static int aio_free_entry(struct aiocblist *aiocbe); -static void aio_process_rw(struct aiocblist *aiocbe); -static void aio_process_sync(struct aiocblist *aiocbe); -static void aio_process_mlock(struct aiocblist *aiocbe); +static int aio_free_entry(struct kaiocb *job); +static void aio_process_rw(struct kaiocb *job); +static void aio_process_sync(struct kaiocb *job); +static void aio_process_mlock(struct kaiocb *job); static int aio_newproc(int *); -int aio_aqueue(struct thread *td, struct aiocb *job, +int aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lio, int type, struct aiocb_ops *ops); static void aio_physwakeup(struct bio *bp); static void aio_proc_rundown(void *arg, struct proc *p); static void aio_proc_rundown_exec(void *arg, struct proc *p, struct image_params *imgp); -static int aio_qphysio(struct proc *p, struct aiocblist *iocb); +static int aio_qphysio(struct proc *p, struct kaiocb *job); static void aio_daemon(void *param); static void aio_swake_cb(struct socket *, struct sockbuf *); static int aio_unload(void); -static void aio_bio_done_notify(struct proc *userp, - struct aiocblist *aiocbe, int type); +static void aio_bio_done_notify(struct proc *userp, struct kaiocb *job, + int type); #define DONE_BUF 1 #define DONE_QUEUE 2 static int aio_kick(struct proc *userp); @@ -488,7 +488,7 @@ aio_onceonly(void) NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiop_zone = uma_zcreate("AIOP", sizeof(struct aioproc), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); - aiocb_zone = uma_zcreate("AIOCB", sizeof(struct aiocblist), NULL, NULL, + aiocb_zone = uma_zcreate("AIOCB", sizeof(struct kaiocb), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); aiol_zone = uma_zcreate("AIOL", AIO_LISTIO_MAX*sizeof(intptr_t) , NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); @@ -625,29 +625,29 @@ aio_sendsig(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi) * restart the queue scan. */ static int -aio_free_entry(struct aiocblist *aiocbe) +aio_free_entry(struct kaiocb *job) { struct kaioinfo *ki; struct aioliojob *lj; struct proc *p; - p = aiocbe->userproc; + p = job->userproc; MPASS(curproc == p); ki = p->p_aioinfo; MPASS(ki != NULL); AIO_LOCK_ASSERT(ki, MA_OWNED); - MPASS(aiocbe->jobstate == JOBST_JOBFINISHED); + MPASS(job->jobstate == JOBST_JOBFINISHED); atomic_subtract_int(&num_queue_count, 1); ki->kaio_count--; MPASS(ki->kaio_count >= 0); - TAILQ_REMOVE(&ki->kaio_done, aiocbe, plist); - TAILQ_REMOVE(&ki->kaio_all, aiocbe, allist); + TAILQ_REMOVE(&ki->kaio_done, job, plist); + TAILQ_REMOVE(&ki->kaio_all, job, allist); - lj = aiocbe->lio; + lj = job->lio; if (lj) { lj->lioj_count--; lj->lioj_finished_count--; @@ -663,14 +663,14 @@ aio_free_entry(struct aiocblist *aiocbe) } } - /* aiocbe is going away, we need to destroy any knotes */ - knlist_delete(&aiocbe->klist, curthread, 1); + /* job is going away, we need to destroy any knotes */ + knlist_delete(&job->klist, curthread, 1); PROC_LOCK(p); - sigqueue_take(&aiocbe->ksi); + sigqueue_take(&job->ksi); PROC_UNLOCK(p); - MPASS(aiocbe->bp == NULL); - aiocbe->jobstate = JOBST_NULL; + MPASS(job->bp == NULL); + job->jobstate = JOBST_NULL; AIO_UNLOCK(ki); /* @@ -682,7 +682,7 @@ aio_free_entry(struct aiocblist *aiocbe) * another process. * * Currently, all the callers of this function call it to remove - * an aiocblist from the current process' job list either via a + * a kaiocb from the current process' job list either via a * syscall or due to the current process calling exit() or * execve(). Thus, we know that p == curproc. We also know that * curthread can't exit since we are curthread. @@ -693,10 +693,10 @@ aio_free_entry(struct aiocblist *aiocbe) * at open time, but this is already true of file descriptors in * a multithreaded process. */ - if (aiocbe->fd_file) - fdrop(aiocbe->fd_file, curthread); - crfree(aiocbe->cred); - uma_zfree(aiocb_zone, aiocbe); + if (job->fd_file) + fdrop(job->fd_file, curthread); + crfree(job->cred); + uma_zfree(aiocb_zone, job); AIO_LOCK(ki); return (0); @@ -717,7 +717,7 @@ aio_proc_rundown(void *arg, struct proc *p) { struct kaioinfo *ki; struct aioliojob *lj; - struct aiocblist *cbe, *cbn; + struct kaiocb *job, *jobn; struct file *fp; struct socket *so; int remove; @@ -737,30 +737,30 @@ restart: * Try to cancel all pending requests. This code simulates * aio_cancel on all pending I/O requests. */ - TAILQ_FOREACH_SAFE(cbe, &ki->kaio_jobqueue, plist, cbn) { + TAILQ_FOREACH_SAFE(job, &ki->kaio_jobqueue, plist, jobn) { remove = 0; mtx_lock(&aio_job_mtx); - if (cbe->jobstate == JOBST_JOBQGLOBAL) { - TAILQ_REMOVE(&aio_jobs, cbe, list); + if (job->jobstate == JOBST_JOBQGLOBAL) { + TAILQ_REMOVE(&aio_jobs, job, list); remove = 1; - } else if (cbe->jobstate == JOBST_JOBQSOCK) { - fp = cbe->fd_file; + } else if (job->jobstate == JOBST_JOBQSOCK) { + fp = job->fd_file; MPASS(fp->f_type == DTYPE_SOCKET); so = fp->f_data; - TAILQ_REMOVE(&so->so_aiojobq, cbe, list); + TAILQ_REMOVE(&so->so_aiojobq, job, list); remove = 1; - } else if (cbe->jobstate == JOBST_JOBQSYNC) { - TAILQ_REMOVE(&ki->kaio_syncqueue, cbe, list); + } else if (job->jobstate == JOBST_JOBQSYNC) { + TAILQ_REMOVE(&ki->kaio_syncqueue, job, list); remove = 1; } mtx_unlock(&aio_job_mtx); if (remove) { - cbe->jobstate = JOBST_JOBFINISHED; - cbe->uaiocb._aiocb_private.status = -1; - cbe->uaiocb._aiocb_private.error = ECANCELED; - TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist); - aio_bio_done_notify(p, cbe, DONE_QUEUE); + job->jobstate = JOBST_JOBFINISHED; + job->uaiocb._aiocb_private.status = -1; + job->uaiocb._aiocb_private.error = ECANCELED; + TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist); + aio_bio_done_notify(p, job, DONE_QUEUE); } } @@ -773,8 +773,8 @@ restart: } /* Free all completed I/O requests. */ - while ((cbe = TAILQ_FIRST(&ki->kaio_done)) != NULL) - aio_free_entry(cbe); + while ((job = TAILQ_FIRST(&ki->kaio_done)) != NULL) + aio_free_entry(job); while ((lj = TAILQ_FIRST(&ki->kaio_liojoblist)) != NULL) { if (lj->lioj_count == 0) { @@ -799,27 +799,27 @@ restart: /* * Select a job to run (called by an AIO daemon). */ -static struct aiocblist * +static struct kaiocb * aio_selectjob(struct aioproc *aiop) { - struct aiocblist *aiocbe; + struct kaiocb *job; struct kaioinfo *ki; struct proc *userp; mtx_assert(&aio_job_mtx, MA_OWNED); - TAILQ_FOREACH(aiocbe, &aio_jobs, list) { - userp = aiocbe->userproc; + TAILQ_FOREACH(job, &aio_jobs, list) { + userp = job->userproc; ki = userp->p_aioinfo; if (ki->kaio_active_count < ki->kaio_maxactive_count) { - TAILQ_REMOVE(&aio_jobs, aiocbe, list); + TAILQ_REMOVE(&aio_jobs, job, list); /* Account for currently active jobs. */ ki->kaio_active_count++; - aiocbe->jobstate = JOBST_JOBRUNNING; + job->jobstate = JOBST_JOBRUNNING; break; } } - return (aiocbe); + return (job); } /* @@ -857,7 +857,7 @@ drop: * XXX I don't think it works well for socket, pipe, and fifo. */ static void -aio_process_rw(struct aiocblist *aiocbe) +aio_process_rw(struct kaiocb *job) { struct ucred *td_savedcred; struct thread *td; @@ -871,15 +871,15 @@ aio_process_rw(struct aiocblist *aiocbe) int oublock_st, oublock_end; int inblock_st, inblock_end; - KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_READ || - aiocbe->uaiocb.aio_lio_opcode == LIO_WRITE, - ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode)); + KASSERT(job->uaiocb.aio_lio_opcode == LIO_READ || + job->uaiocb.aio_lio_opcode == LIO_WRITE, + ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); td = curthread; td_savedcred = td->td_ucred; - td->td_ucred = aiocbe->cred; - cb = &aiocbe->uaiocb; - fp = aiocbe->fd_file; + td->td_ucred = job->cred; + cb = &job->uaiocb; + fp = job->fd_file; aiov.iov_base = (void *)(uintptr_t)cb->aio_buf; aiov.iov_len = cb->aio_nbytes; @@ -913,8 +913,8 @@ aio_process_rw(struct aiocblist *aiocbe) inblock_end = td->td_ru.ru_inblock; oublock_end = td->td_ru.ru_oublock; - aiocbe->inputcharge = inblock_end - inblock_st; - aiocbe->outputcharge = oublock_end - oublock_st; + job->inputcharge = inblock_end - inblock_st; + job->outputcharge = oublock_end - oublock_st; if ((error) && (auio.uio_resid != cnt)) { if (error == ERESTART || error == EINTR || error == EWOULDBLOCK) @@ -927,9 +927,9 @@ aio_process_rw(struct aiocblist *aiocbe) sigpipe = 0; } if (sigpipe) { - PROC_LOCK(aiocbe->userproc); - kern_psignal(aiocbe->userproc, SIGPIPE); - PROC_UNLOCK(aiocbe->userproc); + PROC_LOCK(job->userproc); + kern_psignal(job->userproc, SIGPIPE); + PROC_UNLOCK(job->userproc); } } } @@ -941,18 +941,18 @@ aio_process_rw(struct aiocblist *aiocbe) } static void -aio_process_sync(struct aiocblist *aiocbe) +aio_process_sync(struct kaiocb *job) { struct thread *td = curthread; struct ucred *td_savedcred = td->td_ucred; - struct aiocb *cb = &aiocbe->uaiocb; - struct file *fp = aiocbe->fd_file; + struct aiocb *cb = &job->uaiocb; + struct file *fp = job->fd_file; int error = 0; - KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_SYNC, - ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode)); + KASSERT(job->uaiocb.aio_lio_opcode == LIO_SYNC, + ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); - td->td_ucred = aiocbe->cred; + td->td_ucred = job->cred; if (fp->f_vnode != NULL) error = aio_fsync_vnode(td, fp->f_vnode); cb->_aiocb_private.error = error; @@ -961,31 +961,31 @@ aio_process_sync(struct aiocblist *aiocbe) } static void -aio_process_mlock(struct aiocblist *aiocbe) +aio_process_mlock(struct kaiocb *job) { - struct aiocb *cb = &aiocbe->uaiocb; + struct aiocb *cb = &job->uaiocb; int error; - KASSERT(aiocbe->uaiocb.aio_lio_opcode == LIO_MLOCK, - ("%s: opcode %d", __func__, aiocbe->uaiocb.aio_lio_opcode)); + KASSERT(job->uaiocb.aio_lio_opcode == LIO_MLOCK, + ("%s: opcode %d", __func__, job->uaiocb.aio_lio_opcode)); - error = vm_mlock(aiocbe->userproc, aiocbe->cred, + error = vm_mlock(job->userproc, job->cred, __DEVOLATILE(void *, cb->aio_buf), cb->aio_nbytes); cb->_aiocb_private.error = error; cb->_aiocb_private.status = 0; } static void -aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) +aio_bio_done_notify(struct proc *userp, struct kaiocb *job, int type) { struct aioliojob *lj; struct kaioinfo *ki; - struct aiocblist *scb, *scbn; + struct kaiocb *sjob, *sjobn; int lj_done; ki = userp->p_aioinfo; AIO_LOCK_ASSERT(ki, MA_OWNED); - lj = aiocbe->lio; + lj = job->lio; lj_done = 0; if (lj) { lj->lioj_finished_count++; @@ -993,21 +993,21 @@ aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) lj_done = 1; } if (type == DONE_QUEUE) { - aiocbe->jobflags |= AIOCBLIST_DONE; + job->jobflags |= KAIOCB_DONE; } else { - aiocbe->jobflags |= AIOCBLIST_BUFDONE; + job->jobflags |= KAIOCB_BUFDONE; } - TAILQ_INSERT_TAIL(&ki->kaio_done, aiocbe, plist); - aiocbe->jobstate = JOBST_JOBFINISHED; + TAILQ_INSERT_TAIL(&ki->kaio_done, job, plist); + job->jobstate = JOBST_JOBFINISHED; if (ki->kaio_flags & KAIO_RUNDOWN) goto notification_done; - if (aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || - aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) - aio_sendsig(userp, &aiocbe->uaiocb.aio_sigevent, &aiocbe->ksi); + if (job->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || + job->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) + aio_sendsig(userp, &job->uaiocb.aio_sigevent, &job->ksi); - KNOTE_LOCKED(&aiocbe->klist, 1); + KNOTE_LOCKED(&job->klist, 1); if (lj_done) { if (lj->lioj_signal.sigev_notify == SIGEV_KEVENT) { @@ -1024,16 +1024,16 @@ aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) } notification_done: - if (aiocbe->jobflags & AIOCBLIST_CHECKSYNC) { - TAILQ_FOREACH_SAFE(scb, &ki->kaio_syncqueue, list, scbn) { - if (aiocbe->fd_file == scb->fd_file && - aiocbe->seqno < scb->seqno) { - if (--scb->pending == 0) { + if (job->jobflags & KAIOCB_CHECKSYNC) { + TAILQ_FOREACH_SAFE(sjob, &ki->kaio_syncqueue, list, sjobn) { + if (job->fd_file == sjob->fd_file && + job->seqno < sjob->seqno) { + if (--sjob->pending == 0) { mtx_lock(&aio_job_mtx); - scb->jobstate = JOBST_JOBQGLOBAL; - TAILQ_REMOVE(&ki->kaio_syncqueue, scb, + sjob->jobstate = JOBST_JOBQGLOBAL; + TAILQ_REMOVE(&ki->kaio_syncqueue, sjob, list); - TAILQ_INSERT_TAIL(&aio_jobs, scb, list); + TAILQ_INSERT_TAIL(&aio_jobs, sjob, list); aio_kick_nowait(userp); mtx_unlock(&aio_job_mtx); } @@ -1047,10 +1047,10 @@ notification_done: } static void -aio_switch_vmspace(struct aiocblist *aiocbe) +aio_switch_vmspace(struct kaiocb *job) { - vmspace_switch_aio(aiocbe->userproc->p_vmspace); + vmspace_switch_aio(job->userproc->p_vmspace); } /* @@ -1060,7 +1060,7 @@ aio_switch_vmspace(struct aiocblist *aiocbe) static void aio_daemon(void *_id) { - struct aiocblist *aiocbe; + struct kaiocb *job; struct aioproc *aiop; struct kaioinfo *ki; struct proc *p, *userp; @@ -1105,28 +1105,28 @@ aio_daemon(void *_id) /* * Check for jobs. */ - while ((aiocbe = aio_selectjob(aiop)) != NULL) { + while ((job = aio_selectjob(aiop)) != NULL) { mtx_unlock(&aio_job_mtx); - userp = aiocbe->userproc; + userp = job->userproc; /* * Connect to process address space for user program. */ - aio_switch_vmspace(aiocbe); + aio_switch_vmspace(job); ki = userp->p_aioinfo; /* Do the I/O function. */ - switch(aiocbe->uaiocb.aio_lio_opcode) { + switch(job->uaiocb.aio_lio_opcode) { case LIO_READ: case LIO_WRITE: - aio_process_rw(aiocbe); + aio_process_rw(job); break; case LIO_SYNC: - aio_process_sync(aiocbe); + aio_process_sync(job); break; case LIO_MLOCK: - aio_process_mlock(aiocbe); + aio_process_mlock(job); break; } @@ -1136,8 +1136,8 @@ aio_daemon(void *_id) mtx_unlock(&aio_job_mtx); AIO_LOCK(ki); - TAILQ_REMOVE(&ki->kaio_jobqueue, aiocbe, plist); - aio_bio_done_notify(userp, aiocbe, DONE_QUEUE); + TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist); + aio_bio_done_notify(userp, job, DONE_QUEUE); AIO_UNLOCK(ki); mtx_lock(&aio_job_mtx); @@ -1226,7 +1226,7 @@ aio_newproc(int *start) * duration of this call. */ static int -aio_qphysio(struct proc *p, struct aiocblist *aiocbe) +aio_qphysio(struct proc *p, struct kaiocb *job) { struct aiocb *cb; struct file *fp; @@ -1240,8 +1240,8 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) int error, ref, unmap, poff; vm_prot_t prot; - cb = &aiocbe->uaiocb; - fp = aiocbe->fd_file; + cb = &job->uaiocb; + fp = job->fd_file; if (fp == NULL || fp->f_type != DTYPE_VNODE) return (-1); @@ -1286,9 +1286,9 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) goto unref; } } - aiocbe->bp = bp = g_alloc_bio(); + job->bp = bp = g_alloc_bio(); if (!unmap) { - aiocbe->pbuf = pbuf = (struct buf *)getpbuf(NULL); + job->pbuf = pbuf = (struct buf *)getpbuf(NULL); BUF_KERNPROC(pbuf); } @@ -1296,12 +1296,12 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) ki->kaio_count++; if (!unmap) ki->kaio_buffer_count++; - lj = aiocbe->lio; + lj = job->lio; if (lj) lj->lioj_count++; - TAILQ_INSERT_TAIL(&ki->kaio_bufqueue, aiocbe, plist); - TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); - aiocbe->jobstate = JOBST_JOBQBUF; + TAILQ_INSERT_TAIL(&ki->kaio_bufqueue, job, plist); + TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist); + job->jobstate = JOBST_JOBQBUF; cb->_aiocb_private.status = cb->aio_nbytes; AIO_UNLOCK(ki); @@ -1312,25 +1312,25 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) bp->bio_offset = cb->aio_offset; bp->bio_cmd = cb->aio_lio_opcode == LIO_WRITE ? BIO_WRITE : BIO_READ; bp->bio_dev = dev; - bp->bio_caller1 = (void *)aiocbe; + bp->bio_caller1 = (void *)job; prot = VM_PROT_READ; if (cb->aio_lio_opcode == LIO_READ) prot |= VM_PROT_WRITE; /* Less backwards than it looks */ - if ((aiocbe->npages = vm_fault_quick_hold_pages( + if ((job->npages = vm_fault_quick_hold_pages( &curproc->p_vmspace->vm_map, - (vm_offset_t)bp->bio_data, bp->bio_length, prot, aiocbe->pages, - sizeof(aiocbe->pages)/sizeof(aiocbe->pages[0]))) < 0) { + (vm_offset_t)bp->bio_data, bp->bio_length, prot, job->pages, + sizeof(job->pages)/sizeof(job->pages[0]))) < 0) { error = EFAULT; goto doerror; } if (!unmap) { pmap_qenter((vm_offset_t)pbuf->b_data, - aiocbe->pages, aiocbe->npages); + job->pages, job->npages); bp->bio_data = pbuf->b_data + poff; } else { - bp->bio_ma = aiocbe->pages; - bp->bio_ma_n = aiocbe->npages; + bp->bio_ma = job->pages; + bp->bio_ma_n = job->npages; bp->bio_ma_offset = poff; bp->bio_data = unmapped_buf; bp->bio_flags |= BIO_UNMAPPED; @@ -1347,9 +1347,9 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe) doerror: AIO_LOCK(ki); - aiocbe->jobstate = JOBST_NULL; - TAILQ_REMOVE(&ki->kaio_bufqueue, aiocbe, plist); - TAILQ_REMOVE(&ki->kaio_all, aiocbe, allist); + job->jobstate = JOBST_NULL; + TAILQ_REMOVE(&ki->kaio_bufqueue, job, plist); + TAILQ_REMOVE(&ki->kaio_all, job, allist); ki->kaio_count--; if (!unmap) ki->kaio_buffer_count--; @@ -1358,10 +1358,10 @@ doerror: AIO_UNLOCK(ki); if (pbuf) { relpbuf(pbuf, NULL); - aiocbe->pbuf = NULL; + job->pbuf = NULL; } g_destroy_bio(bp); - aiocbe->bp = NULL; + job->bp = NULL; unref: dev_relthread(dev, ref); return (error); @@ -1373,7 +1373,7 @@ unref: static void aio_swake_cb(struct socket *so, struct sockbuf *sb) { - struct aiocblist *cb, *cbn; + struct kaiocb *job, *jobn; int opcode; SOCKBUF_LOCK_ASSERT(sb); @@ -1384,18 +1384,18 @@ aio_swake_cb(struct socket *so, struct sockbuf *sb) sb->sb_flags &= ~SB_AIO; mtx_lock(&aio_job_mtx); - TAILQ_FOREACH_SAFE(cb, &so->so_aiojobq, list, cbn) { - if (opcode == cb->uaiocb.aio_lio_opcode) { - if (cb->jobstate != JOBST_JOBQSOCK) + TAILQ_FOREACH_SAFE(job, &so->so_aiojobq, list, jobn) { + if (opcode == job->uaiocb.aio_lio_opcode) { + if (job->jobstate != JOBST_JOBQSOCK) panic("invalid queue value"); /* XXX * We don't have actual sockets backend yet, * so we simply move the requests to the generic * file I/O backend. */ - TAILQ_REMOVE(&so->so_aiojobq, cb, list); - TAILQ_INSERT_TAIL(&aio_jobs, cb, list); - aio_kick_nowait(cb->userproc); + TAILQ_REMOVE(&so->so_aiojobq, job, list); + TAILQ_INSERT_TAIL(&aio_jobs, job, list); + aio_kick_nowait(job->userproc); } } mtx_unlock(&aio_job_mtx); @@ -1515,14 +1515,14 @@ static struct aiocb_ops aiocb_ops_osigevent = { * technique is done in this code. */ int -aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, +aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj, int type, struct aiocb_ops *ops) { struct proc *p = td->td_proc; cap_rights_t rights; struct file *fp; struct socket *so; - struct aiocblist *aiocbe, *cb; + struct kaiocb *job, *job2; struct kaioinfo *ki; struct kevent kev; struct sockbuf *sb; @@ -1537,57 +1537,57 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, ki = p->p_aioinfo; - ops->store_status(job, -1); - ops->store_error(job, 0); - ops->store_kernelinfo(job, -1); + ops->store_status(ujob, -1); + ops->store_error(ujob, 0); + ops->store_kernelinfo(ujob, -1); if (num_queue_count >= max_queue_count || ki->kaio_count >= ki->kaio_qallowed_count) { - ops->store_error(job, EAGAIN); + ops->store_error(ujob, EAGAIN); return (EAGAIN); } - aiocbe = uma_zalloc(aiocb_zone, M_WAITOK | M_ZERO); - knlist_init_mtx(&aiocbe->klist, AIO_MTX(ki)); + job = uma_zalloc(aiocb_zone, M_WAITOK | M_ZERO); + knlist_init_mtx(&job->klist, AIO_MTX(ki)); - error = ops->copyin(job, &aiocbe->uaiocb); + error = ops->copyin(ujob, &job->uaiocb); if (error) { - ops->store_error(job, error); - uma_zfree(aiocb_zone, aiocbe); + ops->store_error(ujob, error); + uma_zfree(aiocb_zone, job); return (error); } /* XXX: aio_nbytes is later casted to signed types. */ - if (aiocbe->uaiocb.aio_nbytes > INT_MAX) { - uma_zfree(aiocb_zone, aiocbe); + if (job->uaiocb.aio_nbytes > INT_MAX) { + uma_zfree(aiocb_zone, job); return (EINVAL); } - if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT && - aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_SIGNAL && - aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_THREAD_ID && - aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_NONE) { - ops->store_error(job, EINVAL); - uma_zfree(aiocb_zone, aiocbe); + if (job->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT && + job->uaiocb.aio_sigevent.sigev_notify != SIGEV_SIGNAL && + job->uaiocb.aio_sigevent.sigev_notify != SIGEV_THREAD_ID && + job->uaiocb.aio_sigevent.sigev_notify != SIGEV_NONE) { + ops->store_error(ujob, EINVAL); + uma_zfree(aiocb_zone, job); return (EINVAL); } - if ((aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || - aiocbe->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) && - !_SIG_VALID(aiocbe->uaiocb.aio_sigevent.sigev_signo)) { - uma_zfree(aiocb_zone, aiocbe); + if ((job->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL || + job->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID) && + !_SIG_VALID(job->uaiocb.aio_sigevent.sigev_signo)) { + uma_zfree(aiocb_zone, job); return (EINVAL); } - ksiginfo_init(&aiocbe->ksi); + ksiginfo_init(&job->ksi); /* Save userspace address of the job info. */ - aiocbe->uuaiocb = job; + job->ujob = ujob; /* Get the opcode. */ if (type != LIO_NOP) - aiocbe->uaiocb.aio_lio_opcode = type; - opcode = aiocbe->uaiocb.aio_lio_opcode; + job->uaiocb.aio_lio_opcode = type; + opcode = job->uaiocb.aio_lio_opcode; /* * Validate the opcode and fetch the file object for the specified @@ -1597,7 +1597,7 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, * retrieve a file descriptor without knowing what the capabiltity * should be. */ - fd = aiocbe->uaiocb.aio_fildes; + fd = job->uaiocb.aio_fildes; switch (opcode) { case LIO_WRITE: error = fget_write(td, fd, @@ -1620,8 +1620,8 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, error = EINVAL; } if (error) { - uma_zfree(aiocb_zone, aiocbe); - ops->store_error(job, error); + uma_zfree(aiocb_zone, job); + ops->store_error(ujob, error); return (error); } @@ -1630,60 +1630,60 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, goto aqueue_fail; } - if (opcode != LIO_SYNC && aiocbe->uaiocb.aio_offset == -1LL) { + if (opcode != LIO_SYNC && job->uaiocb.aio_offset == -1LL) { error = EINVAL; goto aqueue_fail; } - aiocbe->fd_file = fp; + job->fd_file = fp; mtx_lock(&aio_job_mtx); jid = jobrefid++; - aiocbe->seqno = jobseqno++; + job->seqno = jobseqno++; mtx_unlock(&aio_job_mtx); - error = ops->store_kernelinfo(job, jid); + error = ops->store_kernelinfo(ujob, jid); if (error) { error = EINVAL; goto aqueue_fail; } - aiocbe->uaiocb._aiocb_private.kernelinfo = (void *)(intptr_t)jid; + job->uaiocb._aiocb_private.kernelinfo = (void *)(intptr_t)jid; if (opcode == LIO_NOP) { fdrop(fp, td); - uma_zfree(aiocb_zone, aiocbe); + uma_zfree(aiocb_zone, job); return (0); } - if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT) + if (job->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT) goto no_kqueue; - evflags = aiocbe->uaiocb.aio_sigevent.sigev_notify_kevent_flags; + evflags = job->uaiocb.aio_sigevent.sigev_notify_kevent_flags; if ((evflags & ~(EV_CLEAR | EV_DISPATCH | EV_ONESHOT)) != 0) { error = EINVAL; goto aqueue_fail; } - kqfd = aiocbe->uaiocb.aio_sigevent.sigev_notify_kqueue; - kev.ident = (uintptr_t)aiocbe->uuaiocb; + kqfd = job->uaiocb.aio_sigevent.sigev_notify_kqueue; + kev.ident = (uintptr_t)job->ujob; kev.filter = EVFILT_AIO; kev.flags = EV_ADD | EV_ENABLE | EV_FLAG1 | evflags; - kev.data = (intptr_t)aiocbe; - kev.udata = aiocbe->uaiocb.aio_sigevent.sigev_value.sival_ptr; + kev.data = (intptr_t)job; + kev.udata = job->uaiocb.aio_sigevent.sigev_value.sival_ptr; error = kqfd_register(kqfd, &kev, td, 1); aqueue_fail: if (error) { if (fp) fdrop(fp, td); - uma_zfree(aiocb_zone, aiocbe); - ops->store_error(job, error); + uma_zfree(aiocb_zone, job); + ops->store_error(ujob, error); goto done; } no_kqueue: - ops->store_error(job, EINPROGRESS); - aiocbe->uaiocb._aiocb_private.error = EINPROGRESS; - aiocbe->userproc = p; - aiocbe->cred = crhold(td->td_ucred); - aiocbe->jobflags = 0; - aiocbe->lio = lj; + ops->store_error(ujob, EINPROGRESS); + job->uaiocb._aiocb_private.error = EINPROGRESS; + job->userproc = p; + job->cred = crhold(td->td_ucred); + job->jobflags = 0; + job->lio = lj; if (opcode == LIO_SYNC) goto queueit; @@ -1695,7 +1695,7 @@ no_kqueue: * socket is ready to be read or written (based on the requested * operation). * - * If it is not ready for io, then queue the aiocbe on the + * If it is not ready for io, then queue the job on the * socket, and set the flags so we get a call when sbnotify() * happens. * @@ -1710,13 +1710,13 @@ no_kqueue: sb->sb_flags |= SB_AIO; mtx_lock(&aio_job_mtx); - TAILQ_INSERT_TAIL(&so->so_aiojobq, aiocbe, list); + TAILQ_INSERT_TAIL(&so->so_aiojobq, job, list); mtx_unlock(&aio_job_mtx); AIO_LOCK(ki); - TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); - TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist); - aiocbe->jobstate = JOBST_JOBQSOCK; + TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist); + TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, job, plist); + job->jobstate = JOBST_JOBQSOCK; ki->kaio_count++; if (lj) lj->lioj_count++; @@ -1729,12 +1729,12 @@ no_kqueue: SOCKBUF_UNLOCK(sb); } - if ((error = aio_qphysio(p, aiocbe)) == 0) + if ((error = aio_qphysio(p, job)) == 0) goto done; #if 0 if (error > 0) { - aiocbe->uaiocb._aiocb_private.error = error; - ops->store_error(job, error); + job->uaiocb._aiocb_private.error = error; + ops->store_error(ujob, error); goto done; } #endif @@ -1745,35 +1745,35 @@ queueit: ki->kaio_count++; if (lj) lj->lioj_count++; - TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist); - TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); + TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, job, plist); + TAILQ_INSERT_TAIL(&ki->kaio_all, job, allist); if (opcode == LIO_SYNC) { - TAILQ_FOREACH(cb, &ki->kaio_jobqueue, plist) { - if (cb->fd_file == aiocbe->fd_file && - cb->uaiocb.aio_lio_opcode != LIO_SYNC && - cb->seqno < aiocbe->seqno) { - cb->jobflags |= AIOCBLIST_CHECKSYNC; - aiocbe->pending++; + TAILQ_FOREACH(job2, &ki->kaio_jobqueue, plist) { + if (job2->fd_file == job->fd_file && + job2->uaiocb.aio_lio_opcode != LIO_SYNC && + job2->seqno < job->seqno) { + job2->jobflags |= KAIOCB_CHECKSYNC; + job->pending++; } } - TAILQ_FOREACH(cb, &ki->kaio_bufqueue, plist) { - if (cb->fd_file == aiocbe->fd_file && - cb->uaiocb.aio_lio_opcode != LIO_SYNC && - cb->seqno < aiocbe->seqno) { - cb->jobflags |= AIOCBLIST_CHECKSYNC; - aiocbe->pending++; + TAILQ_FOREACH(job2, &ki->kaio_bufqueue, plist) { + if (job2->fd_file == job->fd_file && + job2->uaiocb.aio_lio_opcode != LIO_SYNC && + job2->seqno < job->seqno) { + job2->jobflags |= KAIOCB_CHECKSYNC; + job->pending++; } } - if (aiocbe->pending != 0) { - TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, aiocbe, list); - aiocbe->jobstate = JOBST_JOBQSYNC; + if (job->pending != 0) { + TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, job, list); + job->jobstate = JOBST_JOBQSYNC; AIO_UNLOCK(ki); goto done; } } mtx_lock(&aio_job_mtx); - TAILQ_INSERT_TAIL(&aio_jobs, aiocbe, list); - aiocbe->jobstate = JOBST_JOBQGLOBAL; + TAILQ_INSERT_TAIL(&aio_jobs, job, list); + job->jobstate = JOBST_JOBQGLOBAL; aio_kick_nowait(p); mtx_unlock(&aio_job_mtx); AIO_UNLOCK(ki); @@ -1848,10 +1848,10 @@ aio_kick_helper(void *context, int pending) * released. */ static int -kern_aio_return(struct thread *td, struct aiocb *uaiocb, struct aiocb_ops *ops) +kern_aio_return(struct thread *td, struct aiocb *ujob, struct aiocb_ops *ops) { struct proc *p = td->td_proc; - struct aiocblist *cb; + struct kaiocb *job; struct kaioinfo *ki; int status, error; @@ -1859,26 +1859,26 @@ kern_aio_return(struct thread *td, struct aiocb *uaiocb, struct aiocb_ops *ops) if (ki == NULL) return (EINVAL); AIO_LOCK(ki); - TAILQ_FOREACH(cb, &ki->kaio_done, plist) { - if (cb->uuaiocb == uaiocb) + TAILQ_FOREACH(job, &ki->kaio_done, plist) { + if (job->ujob == ujob) break; } - if (cb != NULL) { - MPASS(cb->jobstate == JOBST_JOBFINISHED); - status = cb->uaiocb._aiocb_private.status; - error = cb->uaiocb._aiocb_private.error; + if (job != NULL) { + MPASS(job->jobstate == JOBST_JOBFINISHED); + status = job->uaiocb._aiocb_private.status; + error = job->uaiocb._aiocb_private.error; td->td_retval[0] = status; - if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) { - td->td_ru.ru_oublock += cb->outputcharge; - cb->outputcharge = 0; - } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) { - td->td_ru.ru_inblock += cb->inputcharge; - cb->inputcharge = 0; + if (job->uaiocb.aio_lio_opcode == LIO_WRITE) { + td->td_ru.ru_oublock += job->outputcharge; + job->outputcharge = 0; + } else if (job->uaiocb.aio_lio_opcode == LIO_READ) { + td->td_ru.ru_inblock += job->inputcharge; + job->inputcharge = 0; } - aio_free_entry(cb); + aio_free_entry(job); AIO_UNLOCK(ki); - ops->store_error(uaiocb, error); - ops->store_status(uaiocb, status); + ops->store_error(ujob, error); + ops->store_status(ujob, status); } else { error = EINVAL; AIO_UNLOCK(ki); @@ -1903,7 +1903,7 @@ kern_aio_suspend(struct thread *td, int njoblist, struct aiocb **ujoblist, struct proc *p = td->td_proc; struct timeval atv; struct kaioinfo *ki; - struct aiocblist *cb, *cbfirst; + struct kaiocb *firstjob, *job; int error, i, timo; timo = 0; @@ -1926,20 +1926,20 @@ kern_aio_suspend(struct thread *td, int njoblist, struct aiocb **ujoblist, AIO_LOCK(ki); for (;;) { - cbfirst = NULL; + firstjob = NULL; error = 0; - TAILQ_FOREACH(cb, &ki->kaio_all, allist) { + TAILQ_FOREACH(job, &ki->kaio_all, allist) { for (i = 0; i < njoblist; i++) { - if (cb->uuaiocb == ujoblist[i]) { - if (cbfirst == NULL) - cbfirst = cb; - if (cb->jobstate == JOBST_JOBFINISHED) + if (job->ujob == ujoblist[i]) { + if (firstjob == NULL) + firstjob = job; + if (job->jobstate == JOBST_JOBFINISHED) goto RETURN; } } } /* All tasks were finished. */ - if (cbfirst == NULL) + if (firstjob == NULL) break; ki->kaio_flags |= KAIO_WAKEUP; @@ -1990,7 +1990,7 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap) { struct proc *p = td->td_proc; struct kaioinfo *ki; - struct aiocblist *cbe, *cbn; + struct kaiocb *job, *jobn; struct file *fp; struct socket *so; cap_rights_t rights; @@ -2019,32 +2019,32 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap) } AIO_LOCK(ki); - TAILQ_FOREACH_SAFE(cbe, &ki->kaio_jobqueue, plist, cbn) { - if ((uap->fd == cbe->uaiocb.aio_fildes) && + TAILQ_FOREACH_SAFE(job, &ki->kaio_jobqueue, plist, jobn) { + if ((uap->fd == job->uaiocb.aio_fildes) && ((uap->aiocbp == NULL) || - (uap->aiocbp == cbe->uuaiocb))) { + (uap->aiocbp == job->ujob))) { remove = 0; mtx_lock(&aio_job_mtx); - if (cbe->jobstate == JOBST_JOBQGLOBAL) { - TAILQ_REMOVE(&aio_jobs, cbe, list); + if (job->jobstate == JOBST_JOBQGLOBAL) { + TAILQ_REMOVE(&aio_jobs, job, list); remove = 1; - } else if (cbe->jobstate == JOBST_JOBQSOCK) { + } else if (job->jobstate == JOBST_JOBQSOCK) { MPASS(fp->f_type == DTYPE_SOCKET); so = fp->f_data; - TAILQ_REMOVE(&so->so_aiojobq, cbe, list); + TAILQ_REMOVE(&so->so_aiojobq, job, list); remove = 1; - } else if (cbe->jobstate == JOBST_JOBQSYNC) { - TAILQ_REMOVE(&ki->kaio_syncqueue, cbe, list); + } else if (job->jobstate == JOBST_JOBQSYNC) { + TAILQ_REMOVE(&ki->kaio_syncqueue, job, list); remove = 1; } mtx_unlock(&aio_job_mtx); if (remove) { - TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist); - cbe->uaiocb._aiocb_private.status = -1; - cbe->uaiocb._aiocb_private.error = ECANCELED; - aio_bio_done_notify(p, cbe, DONE_QUEUE); + TAILQ_REMOVE(&ki->kaio_jobqueue, job, plist); + job->uaiocb._aiocb_private.status = -1; + job->uaiocb._aiocb_private.error = ECANCELED; + aio_bio_done_notify(p, job, DONE_QUEUE); cancelled++; } else { notcancelled++; @@ -2086,10 +2086,10 @@ done: * a userland subroutine. */ static int -kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops) +kern_aio_error(struct thread *td, struct aiocb *ujob, struct aiocb_ops *ops) { struct proc *p = td->td_proc; - struct aiocblist *cb; + struct kaiocb *job; struct kaioinfo *ki; int status; @@ -2100,11 +2100,11 @@ kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops) } AIO_LOCK(ki); - TAILQ_FOREACH(cb, &ki->kaio_all, allist) { - if (cb->uuaiocb == aiocbp) { - if (cb->jobstate == JOBST_JOBFINISHED) + TAILQ_FOREACH(job, &ki->kaio_all, allist) { + if (job->ujob == ujob) { + if (job->jobstate == JOBST_JOBFINISHED) td->td_retval[0] = - cb->uaiocb._aiocb_private.error; + job->uaiocb._aiocb_private.error; else td->td_retval[0] = EINPROGRESS; AIO_UNLOCK(ki); @@ -2116,9 +2116,9 @@ kern_aio_error(struct thread *td, struct aiocb *aiocbp, struct aiocb_ops *ops) /* * Hack for failure of aio_aqueue. */ - status = ops->fetch_status(aiocbp); + status = ops->fetch_status(ujob); if (status == -1) { - td->td_retval[0] = ops->fetch_error(aiocbp); + td->td_retval[0] = ops->fetch_error(ujob); return (0); } @@ -2178,7 +2178,7 @@ kern_lio_listio(struct thread *td, int mode, struct aiocb * const *uacb_list, struct aiocb_ops *ops) { struct proc *p = td->td_proc; - struct aiocb *iocb; + struct aiocb *job; struct kaioinfo *ki; struct aioliojob *lj; struct kevent kev; @@ -2254,9 +2254,9 @@ kern_lio_listio(struct thread *td, int mode, struct aiocb * const *uacb_list, */ nerror = 0; for (i = 0; i < nent; i++) { - iocb = acb_list[i]; - if (iocb != NULL) { - error = aio_aqueue(td, iocb, lj, LIO_NOP, ops); + job = acb_list[i]; + if (job != NULL) { + error = aio_aqueue(td, job, lj, LIO_NOP, ops); if (error != 0) nerror++; } @@ -2379,37 +2379,37 @@ sys_lio_listio(struct thread *td, struct lio_listio_args *uap) static void aio_physwakeup(struct bio *bp) { - struct aiocblist *aiocbe = (struct aiocblist *)bp->bio_caller1; + struct kaiocb *job = (struct kaiocb *)bp->bio_caller1; struct proc *userp; struct kaioinfo *ki; int nblks; /* Release mapping into kernel space. */ - if (aiocbe->pbuf) { - pmap_qremove((vm_offset_t)aiocbe->pbuf->b_data, aiocbe->npages); - relpbuf(aiocbe->pbuf, NULL); - aiocbe->pbuf = NULL; + if (job->pbuf) { + pmap_qremove((vm_offset_t)job->pbuf->b_data, job->npages); + relpbuf(job->pbuf, NULL); + job->pbuf = NULL; atomic_subtract_int(&num_buf_aio, 1); } - vm_page_unhold_pages(aiocbe->pages, aiocbe->npages); + vm_page_unhold_pages(job->pages, job->npages); - bp = aiocbe->bp; - aiocbe->bp = NULL; - userp = aiocbe->userproc; + bp = job->bp; + job->bp = NULL; + userp = job->userproc; ki = userp->p_aioinfo; AIO_LOCK(ki); - aiocbe->uaiocb._aiocb_private.status -= bp->bio_resid; - aiocbe->uaiocb._aiocb_private.error = 0; + job->uaiocb._aiocb_private.status -= bp->bio_resid; + job->uaiocb._aiocb_private.error = 0; if (bp->bio_flags & BIO_ERROR) - aiocbe->uaiocb._aiocb_private.error = bp->bio_error; - nblks = btodb(aiocbe->uaiocb.aio_nbytes); - if (aiocbe->uaiocb.aio_lio_opcode == LIO_WRITE) - aiocbe->outputcharge += nblks; + job->uaiocb._aiocb_private.error = bp->bio_error; + nblks = btodb(job->uaiocb.aio_nbytes); + if (job->uaiocb.aio_lio_opcode == LIO_WRITE) + job->outputcharge += nblks; else - aiocbe->inputcharge += nblks; - TAILQ_REMOVE(&userp->p_aioinfo->kaio_bufqueue, aiocbe, plist); + job->inputcharge += nblks; + TAILQ_REMOVE(&userp->p_aioinfo->kaio_bufqueue, job, plist); ki->kaio_buffer_count--; - aio_bio_done_notify(userp, aiocbe, DONE_BUF); + aio_bio_done_notify(userp, job, DONE_BUF); AIO_UNLOCK(ki); g_destroy_bio(bp); @@ -2417,17 +2417,17 @@ aio_physwakeup(struct bio *bp) /* syscall - wait for the next completion of an aio request */ static int -kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp, +kern_aio_waitcomplete(struct thread *td, struct aiocb **ujobp, struct timespec *ts, struct aiocb_ops *ops) { struct proc *p = td->td_proc; struct timeval atv; struct kaioinfo *ki; - struct aiocblist *cb; - struct aiocb *uuaiocb; + struct kaiocb *job; + struct aiocb *ujob; int error, status, timo; - ops->store_aiocb(aiocbp, NULL); + ops->store_aiocb(ujobp, NULL); if (ts == NULL) { timo = 0; @@ -2448,9 +2448,9 @@ kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp, ki = p->p_aioinfo; error = 0; - cb = NULL; + job = NULL; AIO_LOCK(ki); - while ((cb = TAILQ_FIRST(&ki->kaio_done)) == NULL) { + while ((job = TAILQ_FIRST(&ki->kaio_done)) == NULL) { if (timo == -1) { error = EWOULDBLOCK; break; @@ -2464,24 +2464,24 @@ kern_aio_waitcomplete(struct thread *td, struct aiocb **aiocbp, break; } - if (cb != NULL) { - MPASS(cb->jobstate == JOBST_JOBFINISHED); - uuaiocb = cb->uuaiocb; - status = cb->uaiocb._aiocb_private.status; - error = cb->uaiocb._aiocb_private.error; + if (job != NULL) { + MPASS(job->jobstate == JOBST_JOBFINISHED); + ujob = job->ujob; + status = job->uaiocb._aiocb_private.status; + error = job->uaiocb._aiocb_private.error; td->td_retval[0] = status; - if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) { - td->td_ru.ru_oublock += cb->outputcharge; - cb->outputcharge = 0; - } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) { - td->td_ru.ru_inblock += cb->inputcharge; - cb->inputcharge = 0; + if (job->uaiocb.aio_lio_opcode == LIO_WRITE) { + td->td_ru.ru_oublock += job->outputcharge; + job->outputcharge = 0; + } else if (job->uaiocb.aio_lio_opcode == LIO_READ) { + td->td_ru.ru_inblock += job->inputcharge; + job->inputcharge = 0; } - aio_free_entry(cb); + aio_free_entry(job); AIO_UNLOCK(ki); - ops->store_aiocb(aiocbp, uuaiocb); - ops->store_error(uuaiocb, error); - ops->store_status(uuaiocb, status); + ops->store_aiocb(ujobp, ujob); + ops->store_error(ujob, error); + ops->store_status(ujob, status); } else AIO_UNLOCK(ki); @@ -2507,7 +2507,7 @@ sys_aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap) } static int -kern_aio_fsync(struct thread *td, int op, struct aiocb *aiocbp, +kern_aio_fsync(struct thread *td, int op, struct aiocb *ujob, struct aiocb_ops *ops) { struct proc *p = td->td_proc; @@ -2518,7 +2518,7 @@ kern_aio_fsync(struct thread *td, int op, struct aiocb *aiocbp, ki = p->p_aioinfo; if (ki == NULL) aio_init_aioinfo(p); - return (aio_aqueue(td, aiocbp, NULL, LIO_SYNC, ops)); + return (aio_aqueue(td, ujob, NULL, LIO_SYNC, ops)); } int @@ -2532,19 +2532,19 @@ sys_aio_fsync(struct thread *td, struct aio_fsync_args *uap) static int filt_aioattach(struct knote *kn) { - struct aiocblist *aiocbe = (struct aiocblist *)kn->kn_sdata; + struct kaiocb *job = (struct kaiocb *)kn->kn_sdata; /* - * The aiocbe pointer must be validated before using it, so + * The job pointer must be validated before using it, so * registration is restricted to the kernel; the user cannot * set EV_FLAG1. */ if ((kn->kn_flags & EV_FLAG1) == 0) return (EPERM); - kn->kn_ptr.p_aio = aiocbe; + kn->kn_ptr.p_aio = job; kn->kn_flags &= ~EV_FLAG1; - knlist_add(&aiocbe->klist, kn, 0); + knlist_add(&job->klist, kn, 0); return (0); } @@ -2567,10 +2567,10 @@ filt_aiodetach(struct knote *kn) static int filt_aio(struct knote *kn, long hint) { - struct aiocblist *aiocbe = kn->kn_ptr.p_aio; + struct kaiocb *job = kn->kn_ptr.p_aio; - kn->kn_data = aiocbe->uaiocb._aiocb_private.error; - if (aiocbe->jobstate != JOBST_JOBFINISHED) + kn->kn_data = job->uaiocb._aiocb_private.error; + if (job->jobstate != JOBST_JOBFINISHED) return (0); kn->kn_flags |= EV_EOF; return (1); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index eb392cb..e272f9d 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -2245,7 +2245,7 @@ brelse(struct buf *bp) int qindex; /* - * Many function erroneously call brelse with a NULL bp under rare + * Many functions erroneously call brelse with a NULL bp under rare * error conditions. Simply return when called with a NULL bp. */ if (bp == NULL) diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 3ca995f..505da75 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -880,10 +880,10 @@ vfs_domount_update( struct vfsoptlist **optlist /* Options local to the filesystem. */ ) { - struct oexport_args oexport; struct export_args export; + void *bufp; struct mount *mp; - int error, export_error; + int error, export_error, len; uint64_t flag; ASSERT_VOP_ELOCKED(vp, __func__); @@ -951,23 +951,21 @@ vfs_domount_update( error = VFS_MOUNT(mp); export_error = 0; - if (error == 0) { - /* Process the export option. */ - if (vfs_copyopt(mp->mnt_optnew, "export", &export, - sizeof(export)) == 0) { - export_error = vfs_export(mp, &export); - } else if (vfs_copyopt(mp->mnt_optnew, "export", &oexport, - sizeof(oexport)) == 0) { - export.ex_flags = oexport.ex_flags; - export.ex_root = oexport.ex_root; - export.ex_anon = oexport.ex_anon; - export.ex_addr = oexport.ex_addr; - export.ex_addrlen = oexport.ex_addrlen; - export.ex_mask = oexport.ex_mask; - export.ex_masklen = oexport.ex_masklen; - export.ex_indexfile = oexport.ex_indexfile; - export.ex_numsecflavors = 0; + /* Process the export option. */ + if (error == 0 && vfs_getopt(mp->mnt_optnew, "export", &bufp, + &len) == 0) { + /* Assume that there is only 1 ABI for each length. */ + switch (len) { + case (sizeof(struct oexport_args)): + bzero(&export, sizeof(export)); + /* FALLTHROUGH */ + case (sizeof(export)): + bcopy(bufp, &export, len); export_error = vfs_export(mp, &export); + break; + default: + export_error = EINVAL; + break; } } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index c246b9e..0762ca7a 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -987,7 +987,8 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, } /* - * Allocate the file descriptor, but don't install a descriptor yet. + * Allocate a file structure. The descriptor to reference it + * is allocated and set by finstall() below. */ error = falloc_noinstall(td, &fp); if (error != 0) diff --git a/sys/mips/mips/uma_machdep.c b/sys/mips/mips/uma_machdep.c index b4006e1..7014703 100644 --- a/sys/mips/mips/uma_machdep.c +++ b/sys/mips/mips/uma_machdep.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/systm.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/vm_page.h> #include <vm/vm_pageout.h> diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c index f952ecc..03fc60e 100644 --- a/sys/mips/mips/vm_machdep.c +++ b/sys/mips/mips/vm_machdep.c @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/unistd.h> +#include <sys/taskqueue.h> #include <machine/cache.h> #include <machine/clock.h> diff --git a/sys/powerpc/fpu/fpu_emu.c b/sys/powerpc/fpu/fpu_emu.c index 9056dca..011b999 100644 --- a/sys/powerpc/fpu/fpu_emu.c +++ b/sys/powerpc/fpu/fpu_emu.c @@ -275,7 +275,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) vm_offset_t addr; int ra, rb, rc, rt, type, mask, fsr, cx, bf, setcr; unsigned int cond; - struct fpreg *fs; + struct fpu *fs; /* Setup work. */ fp = NULL; @@ -335,7 +335,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) if (ra != 0) addr += tf->fixreg[ra]; rt = instr.i_x.i_rt; - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; DPRINTF(FPE_INSN, ("fpu_execute: Store INT %x at %p\n", a[1], (void *)addr)); @@ -402,7 +402,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) DPRINTF(FPE_INSN, ("fpu_execute: Store DBL at %p\n", (void *)addr)); - if (copyout(&fs->fpreg[rt].fpr, (void *)addr, + if (copyout(&fs->fpr[rt].fpr, (void *)addr, size)) return (FAULT); } @@ -411,13 +411,13 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) FPU_EMU_EVCNT_INCR(fpload); DPRINTF(FPE_INSN, ("fpu_execute: Load from %p\n", (void *)addr)); - if (copyin((const void *)addr, &fs->fpreg[rt].fpr, + if (copyin((const void *)addr, &fs->fpr[rt].fpr, size)) return (FAULT); if (type != FTYPE_DBL) { fpu_explode(fe, fp = &fe->fe_f1, type, rt); fpu_implode(fe, fp, FTYPE_DBL, - (u_int *)&fs->fpreg[rt].fpr); + (u_int *)&fs->fpr[rt].fpr); } } if (update) @@ -470,7 +470,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) DPRINTF(FPE_INSN, ("fpu_execute: FRSP\n")); fpu_explode(fe, fp = &fe->fe_f1, FTYPE_DBL, rb); fpu_implode(fe, fp, FTYPE_SNG, - (u_int *)&fs->fpreg[rt].fpr); + (u_int *)&fs->fpr[rt].fpr); fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt); type = FTYPE_DBL; break; @@ -503,9 +503,9 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) case OPC63_FNEG: FPU_EMU_EVCNT_INCR(fnegabs); DPRINTF(FPE_INSN, ("fpu_execute: FNEGABS\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr, sizeof(double)); - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; *a ^= (1U << 31); break; case OPC63_MCRFS: @@ -533,7 +533,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) case OPC63_FMR: FPU_EMU_EVCNT_INCR(fmr); DPRINTF(FPE_INSN, ("fpu_execute: FMR\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr, sizeof(double)); break; case OPC63_MTFSFI: @@ -550,23 +550,23 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) case OPC63_FNABS: FPU_EMU_EVCNT_INCR(fnabs); DPRINTF(FPE_INSN, ("fpu_execute: FABS\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr, sizeof(double)); - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; *a |= (1U << 31); break; case OPC63_FABS: FPU_EMU_EVCNT_INCR(fabs); DPRINTF(FPE_INSN, ("fpu_execute: FABS\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rb].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rb].fpr, sizeof(double)); - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; *a &= ~(1U << 31); break; case OPC63_MFFS: FPU_EMU_EVCNT_INCR(mffs); DPRINTF(FPE_INSN, ("fpu_execute: MFFS\n")); - memcpy(&fs->fpreg[rt].fpr, &fs->fpscr, + memcpy(&fs->fpr[rt].fpr, &fs->fpscr, sizeof(fs->fpscr)); break; case OPC63_MTFSF: @@ -581,7 +581,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) if (rt & (1<<ra)) mask |= (0xf<<(4*ra)); } - a = (int *)&fs->fpreg[rt].fpr; + a = (int *)&fs->fpr[rt].fpr; fe->fe_cx = mask & a[1]; fe->fe_fpscr = (fe->fe_fpscr&~mask) | (fe->fe_cx); @@ -648,12 +648,12 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) case OPC63M_FSEL: FPU_EMU_EVCNT_INCR(fsel); DPRINTF(FPE_INSN, ("fpu_execute: FSEL\n")); - a = (int *)&fe->fe_fpstate->fpreg[ra].fpr; + a = (int *)&fe->fe_fpstate->fpr[ra].fpr; if ((*a & 0x80000000) && (*a & 0x7fffffff)) /* fra < 0 */ rc = rb; DPRINTF(FPE_INSN, ("f%d => f%d\n", rc, rt)); - memcpy(&fs->fpreg[rt].fpr, &fs->fpreg[rc].fpr, + memcpy(&fs->fpr[rt].fpr, &fs->fpr[rc].fpr, sizeof(double)); break; case OPC59_FRES: @@ -662,7 +662,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) fpu_explode(fe, &fe->fe_f1, type, rb); fp = fpu_sqrt(fe); /* now we've gotta overwrite the dest reg */ - *((int *)&fe->fe_fpstate->fpreg[rt].fpr) = 1; + *((int *)&fe->fe_fpstate->fpr[rt].fpr) = 1; fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt); fpu_div(fe); break; @@ -681,7 +681,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) fp = fpu_sqrt(fe); fe->fe_f2 = *fp; /* now we've gotta overwrite the dest reg */ - *((int *)&fe->fe_fpstate->fpreg[rt].fpr) = 1; + *((int *)&fe->fe_fpstate->fpr[rt].fpr) = 1; fpu_explode(fe, &fe->fe_f1, FTYPE_INT, rt); fpu_div(fe); break; @@ -737,7 +737,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) /* If the instruction was single precision, round */ if (!(instr.i_any.i_opcd & 0x4)) { fpu_implode(fe, fp, FTYPE_SNG, - (u_int *)&fs->fpreg[rt].fpr); + (u_int *)&fs->fpr[rt].fpr); fpu_explode(fe, fp = &fe->fe_f1, FTYPE_SNG, rt); } } @@ -752,7 +752,7 @@ fpu_execute(struct trapframe *tf, struct fpemu *fe, union instr *insn) * Otherwise set new current exceptions and accrue. */ if (fp) - fpu_implode(fe, fp, type, (u_int *)&fs->fpreg[rt].fpr); + fpu_implode(fe, fp, type, (u_int *)&fs->fpr[rt].fpr); cx = fe->fe_cx; fsr = fe->fe_fpscr; if (cx != 0) { diff --git a/sys/powerpc/fpu/fpu_explode.c b/sys/powerpc/fpu/fpu_explode.c index 1ebd96e..84073a4 100644 --- a/sys/powerpc/fpu/fpu_explode.c +++ b/sys/powerpc/fpu/fpu_explode.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); #include <machine/fpu.h> #include <machine/ieee.h> -#include <machine/reg.h> +#include <machine/pcb.h> #include <powerpc/fpu/fpu_arith.h> #include <powerpc/fpu/fpu_emu.h> @@ -211,9 +211,9 @@ fpu_explode(struct fpemu *fe, struct fpn *fp, int type, int reg) u_int s, *space; u_int64_t l, *xspace; - xspace = (u_int64_t *)&fe->fe_fpstate->fpreg[reg].fpr; + xspace = (u_int64_t *)&fe->fe_fpstate->fpr[reg].fpr; l = xspace[0]; - space = (u_int *)&fe->fe_fpstate->fpreg[reg].fpr; + space = (u_int *)&fe->fe_fpstate->fpr[reg].fpr; s = space[0]; fp->fp_sign = s >> 31; fp->fp_sticky = 0; diff --git a/sys/powerpc/powerpc/uma_machdep.c b/sys/powerpc/powerpc/uma_machdep.c index d5a458f..2e02396 100644 --- a/sys/powerpc/powerpc/uma_machdep.c +++ b/sys/powerpc/powerpc/uma_machdep.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/systm.h> #include <sys/sysctl.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/vm_page.h> #include <vm/vm_kern.h> diff --git a/sys/riscv/include/asm.h b/sys/riscv/include/asm.h index fb0c844..adcc23a 100644 --- a/sys/riscv/include/asm.h +++ b/sys/riscv/include/asm.h @@ -59,9 +59,7 @@ .set alias,sym #define SET_FAULT_HANDLER(handler, tmp) \ - la tmp, pcpup; \ - ld tmp, 0(tmp); \ - ld tmp, PC_CURTHREAD(tmp); \ + ld tmp, PC_CURTHREAD(gp); \ ld tmp, TD_PCB(tmp); /* Load the pcb */ \ sd handler, PCB_ONFAULT(tmp) /* Set the handler */ diff --git a/sys/riscv/include/pcpu.h b/sys/riscv/include/pcpu.h index c60a954..7dfe23d 100644 --- a/sys/riscv/include/pcpu.h +++ b/sys/riscv/include/pcpu.h @@ -47,8 +47,11 @@ extern struct pcpu *pcpup; static inline struct pcpu * get_pcpu(void) { + struct pcpu *pcpu; - return (pcpup); + __asm __volatile("mv %0, gp" : "=&r"(pcpu)); + + return (pcpu); } static inline struct thread * @@ -56,7 +59,7 @@ get_curthread(void) { struct thread *td; - td = (struct thread *)*(uint64_t *)pcpup; + __asm __volatile("ld %0, 0(gp)" : "=&r"(td)); return (td); } diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S index 07fcfc5..814fcf6 100644 --- a/sys/riscv/riscv/exception.S +++ b/sys/riscv/riscv/exception.S @@ -41,12 +41,16 @@ __FBSDID("$FreeBSD$"); #include <machine/riscvreg.h> .macro save_registers el - addi sp, sp, -280 + addi sp, sp, -(TF_SIZE) sd ra, (TF_RA)(sp) - sd gp, (TF_GP)(sp) sd tp, (TF_TP)(sp) +.if \el == 0 /* We came from userspace. Load our pcpu */ + sd gp, (TF_GP)(sp) + ld gp, (TF_SIZE)(sp) +.endif + sd t0, (TF_T + 0 * 8)(sp) sd t1, (TF_T + 1 * 8)(sp) sd t2, (TF_T + 2 * 8)(sp) @@ -127,13 +131,16 @@ __FBSDID("$FreeBSD$"); csrw sepc, t0 .if \el == 0 - /* Load user sp */ + /* We go to userspace. Load user sp */ ld t0, (TF_SP)(sp) csrw sscratch, t0 + + /* And store our pcpu */ + sd gp, (TF_SIZE)(sp) + ld gp, (TF_GP)(sp) .endif ld ra, (TF_RA)(sp) - ld gp, (TF_GP)(sp) ld tp, (TF_TP)(sp) ld t0, (TF_T + 0 * 8)(sp) @@ -166,7 +173,7 @@ __FBSDID("$FreeBSD$"); ld a6, (TF_A + 6 * 8)(sp) ld a7, (TF_A + 7 * 8)(sp) - addi sp, sp, 280 + addi sp, sp, (TF_SIZE) .endm .macro do_ast @@ -175,9 +182,7 @@ __FBSDID("$FreeBSD$"); 1: csrci sstatus, SSTATUS_IE - la a1, pcpup - ld a1, 0(a1) - ld a1, PC_CURTHREAD(a1) + ld a1, PC_CURTHREAD(gp) lw a2, TD_FLAGS(a1) li a3, (TDF_ASTPENDING|TDF_NEEDRESCHED) diff --git a/sys/riscv/riscv/genassym.c b/sys/riscv/riscv/genassym.c index f5c971d..bf6c8fb 100644 --- a/sys/riscv/riscv/genassym.c +++ b/sys/riscv/riscv/genassym.c @@ -85,6 +85,7 @@ ASSYM(TD_FRAME, offsetof(struct thread, td_frame)); ASSYM(TD_MD, offsetof(struct thread, td_md)); ASSYM(TD_LOCK, offsetof(struct thread, td_lock)); +ASSYM(TF_SIZE, sizeof(struct trapframe)); ASSYM(TF_RA, offsetof(struct trapframe, tf_ra)); ASSYM(TF_SP, offsetof(struct trapframe, tf_sp)); ASSYM(TF_GP, offsetof(struct trapframe, tf_gp)); diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 5f9bd1f..79688e6 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -256,7 +256,9 @@ ptrace_clear_single_step(struct thread *td) void exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) { - struct trapframe *tf = td->td_frame; + struct trapframe *tf; + + tf = td->td_frame; memset(tf, 0, sizeof(struct trapframe)); @@ -563,6 +565,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) static void init_proc0(vm_offset_t kstack) { + pcpup = &__pcpu[0]; proc_linkup0(&proc0, &thread0); @@ -760,11 +763,7 @@ initriscv(struct riscv_bootparams *rvbp) pcpu_init(pcpup, 0, sizeof(struct pcpu)); /* Set the pcpu pointer */ -#if 0 - /* SMP TODO: try re-use gp for pcpu pointer */ - __asm __volatile( - "mv gp, %0" :: "r"(pcpup)); -#endif + __asm __volatile("mv gp, %0" :: "r"(pcpup)); PCPU_SET(curthread, &thread0); diff --git a/sys/riscv/riscv/swtch.S b/sys/riscv/riscv/swtch.S index 945fce3..c6336a9 100644 --- a/sys/riscv/riscv/swtch.S +++ b/sys/riscv/riscv/swtch.S @@ -46,14 +46,11 @@ __FBSDID("$FreeBSD$"); * void cpu_throw(struct thread *old, struct thread *new) */ ENTRY(cpu_throw) - /* Load pcpu */ - la x14, pcpup - ld x14, 0(x14) /* Store the new curthread */ - sd a1, PC_CURTHREAD(x14) + sd a1, PC_CURTHREAD(gp) /* And the new pcb */ ld x13, TD_PCB(a1) - sd x13, PC_CURPCB(x14) + sd x13, PC_CURPCB(gp) sfence.vm @@ -74,8 +71,6 @@ ENTRY(cpu_throw) /* Load registers */ ld ra, (PCB_RA)(x13) ld sp, (PCB_SP)(x13) - ld gp, (PCB_GP)(x13) - ld tp, (PCB_TP)(x13) /* s[0-11] */ ld s0, (PCB_S + 0 * 8)(x13) @@ -105,14 +100,11 @@ END(cpu_throw) * x3 to x7, x16 and x17 are caller saved */ ENTRY(cpu_switch) - /* Load pcpu */ - la x14, pcpup - ld x14, 0(x14) /* Store the new curthread */ - sd a1, PC_CURTHREAD(x14) + sd a1, PC_CURTHREAD(gp) /* And the new pcb */ ld x13, TD_PCB(a1) - sd x13, PC_CURPCB(x14) + sd x13, PC_CURPCB(gp) /* Save the old context. */ ld x13, TD_PCB(a0) @@ -120,8 +112,6 @@ ENTRY(cpu_switch) /* Store the callee-saved registers */ sd ra, (PCB_RA)(x13) sd sp, (PCB_SP)(x13) - sd gp, (PCB_GP)(x13) - sd tp, (PCB_TP)(x13) /* We use these in fork_trampoline */ sd t0, (PCB_T + 0 * 8)(x13) @@ -176,8 +166,6 @@ ENTRY(cpu_switch) /* Restore the registers */ ld ra, (PCB_RA)(x13) ld sp, (PCB_SP)(x13) - ld gp, (PCB_GP)(x13) - ld tp, (PCB_TP)(x13) /* We use these in fork_trampoline */ ld t0, (PCB_T + 0 * 8)(x13) @@ -254,12 +242,23 @@ ENTRY(fork_trampoline) ld a6, (TF_A + 6 * 8)(sp) ld a7, (TF_A + 7 * 8)(sp) + /* Load user ra and sp */ + ld tp, (TF_TP)(sp) + ld ra, (TF_RA)(sp) + + /* + * Store our pcpup on stack, we will load it back + * on kernel mode trap. + */ + sd gp, (TF_SIZE)(sp) + ld gp, (TF_GP)(sp) + /* Save kernel stack so we can use it doing a user trap */ + addi sp, sp, TF_SIZE csrw sscratch, sp - /* Load user ra and sp */ - ld ra, (TF_RA)(sp) - ld sp, (TF_SP)(sp) + /* Load user stack */ + ld sp, (TF_SP - TF_SIZE)(sp) eret END(fork_trampoline) diff --git a/sys/riscv/riscv/uma_machdep.c b/sys/riscv/riscv/uma_machdep.c index ba48071..b3f2d82 100644 --- a/sys/riscv/riscv/uma_machdep.c +++ b/sys/riscv/riscv/uma_machdep.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mutex.h> #include <sys/systm.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/vm_page.h> #include <vm/vm_pageout.h> diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c index 62e466f..fef626b 100644 --- a/sys/riscv/riscv/vm_machdep.c +++ b/sys/riscv/riscv/vm_machdep.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sf_buf.h> #include <sys/signal.h> #include <sys/unistd.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/vm_page.h> @@ -217,7 +218,7 @@ cpu_thread_alloc(struct thread *td) td->td_pcb = (struct pcb *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE) - 1; td->td_frame = (struct trapframe *)STACKALIGN( - td->td_pcb - 1); + (caddr_t)td->td_pcb - 8 - sizeof(struct trapframe)); } void diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c index df8be0b..9780406 100644 --- a/sys/sparc64/sparc64/vm_machdep.c +++ b/sys/sparc64/sparc64/vm_machdep.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/unistd.h> #include <sys/vmmeter.h> +#include <sys/taskqueue.h> #include <dev/ofw/openfirm.h> diff --git a/sys/sys/ata.h b/sys/sys/ata.h index 272b46a..5df610e 100644 --- a/sys/sys/ata.h +++ b/sys/sys/ata.h @@ -368,6 +368,9 @@ struct ata_params { #define ATA_WRITE_LOG_EXT 0x3f #define ATA_READ_VERIFY 0x40 #define ATA_READ_VERIFY48 0x42 +#define ATA_WRITE_UNCORRECTABLE48 0x45 /* write uncorrectable 48bit LBA */ +#define ATA_WU_PSEUDO 0x55 /* pseudo-uncorrectable error */ +#define ATA_WU_FLAGGED 0xaa /* flagged-uncorrectable error */ #define ATA_READ_LOG_DMA_EXT 0x47 /* read log DMA ext - PIO Data-In */ #define ATA_READ_FPDMA_QUEUED 0x60 /* read DMA NCQ */ #define ATA_WRITE_FPDMA_QUEUED 0x61 /* write DMA NCQ */ diff --git a/sys/sys/event.h b/sys/sys/event.h index 35aad99..7897c81 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -222,7 +222,7 @@ struct knote { union { struct file *p_fp; /* file data pointer */ struct proc *p_proc; /* proc pointer */ - struct aiocblist *p_aio; /* AIO job pointer */ + struct kaiocb *p_aio; /* AIO job pointer */ struct aioliojob *p_lio; /* LIO job pointer */ sbintime_t *p_nexttime; /* next timer event fires at */ void *p_v; /* generic other pointer */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index f2f4a9d..039fd39 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -907,6 +907,16 @@ struct proc *pfind_locked(pid_t pid); struct pgrp *pgfind(pid_t); /* Find process group by id. */ struct proc *zpfind(pid_t); /* Find zombie process by id. */ +struct fork_req { + int fr_flags; + int fr_pages; + int *fr_pidp; + struct proc **fr_procp; + int *fr_pd_fd; + int fr_pd_flags; + struct filecaps *fr_pd_fcaps; +}; + /* * pget() flags. */ @@ -930,8 +940,7 @@ int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp, int enterthispgrp(struct proc *p, struct pgrp *pgrp); void faultin(struct proc *p); void fixjobc(struct proc *p, struct pgrp *pgrp, int entering); -int fork1(struct thread *, int, int, struct proc **, int *, int, - struct filecaps *); +int fork1(struct thread *, struct fork_req *); void fork_exit(void (*)(void *, struct trapframe *), void *, struct trapframe *); void fork_return(struct thread *, struct trapframe *); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 55a7950..f101849 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -104,7 +104,7 @@ struct socket { struct sigio *so_sigio; /* [sg] information for async I/O or out of band data (SIGURG) */ u_long so_oobmark; /* (c) chars to oob mark */ - TAILQ_HEAD(, aiocblist) so_aiojobq; /* AIO ops waiting on socket */ + TAILQ_HEAD(, kaiocb) so_aiojobq; /* AIO ops waiting on socket */ struct sockbuf so_rcv, so_snd; diff --git a/sys/vm/memguard.c b/sys/vm/memguard.c index d4efc2b..fb70a41 100644 --- a/sys/vm/memguard.c +++ b/sys/vm/memguard.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/malloc.h> #include <sys/sysctl.h> +#include <sys/taskqueue.h> #include <sys/vmem.h> #include <vm/vm.h> diff --git a/sys/vm/sg_pager.c b/sys/vm/sg_pager.c index 84bfa49..2cccb7ea 100644 --- a/sys/vm/sg_pager.c +++ b/sys/vm/sg_pager.c @@ -189,6 +189,9 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind, VM_OBJECT_WLOCK(object); TAILQ_INSERT_TAIL(&object->un_pager.sgp.sgp_pglist, page, plinks.q); vm_page_replace_checked(page, object, offset, m[0]); + vm_page_lock(m[0]); + vm_page_free(m[0]); + vm_page_unlock(m[0]); m[0] = page; page->valid = VM_PAGE_BITS_ALL; diff --git a/sys/vm/uma.h b/sys/vm/uma.h index d218e60..21c6121 100644 --- a/sys/vm/uma.h +++ b/sys/vm/uma.h @@ -530,7 +530,7 @@ void uma_zone_set_warning(uma_zone_t zone, const char *warning); * Returns: * Nothing */ -typedef void (*uma_maxaction_t)(uma_zone_t); +typedef void (*uma_maxaction_t)(uma_zone_t, int); void uma_zone_set_maxaction(uma_zone_t zone, uma_maxaction_t); /* diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 4600589..0d45046 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sbuf.h> #include <sys/sched.h> #include <sys/smp.h> +#include <sys/taskqueue.h> #include <sys/vmmeter.h> #include <vm/vm.h> @@ -275,6 +276,11 @@ void uma_print_stats(void); static int sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS); static int sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS); +#ifdef INVARIANTS +static void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item); +static void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item); +#endif + SYSINIT(uma_startup3, SI_SUB_VM_CONF, SI_ORDER_SECOND, uma_startup3, NULL); SYSCTL_PROC(_vm, OID_AUTO, zone_count, CTLFLAG_RD|CTLTYPE_INT, @@ -434,8 +440,9 @@ zone_log_warning(uma_zone_t zone) static inline void zone_maxaction(uma_zone_t zone) { - if (zone->uz_maxaction) - (*zone->uz_maxaction)(zone); + + if (zone->uz_maxaction.ta_func != NULL) + taskqueue_enqueue(taskqueue_thread, &zone->uz_maxaction); } static void @@ -1585,7 +1592,6 @@ zone_ctor(void *mem, int size, void *udata, int flags) zone->uz_flags = 0; zone->uz_warning = NULL; timevalclear(&zone->uz_ratecheck); - zone->uz_maxaction = NULL; keg = arg->keg; ZONE_LOCK_INIT(zone, (arg->flags & UMA_ZONE_MTXCLASS)); @@ -3022,7 +3028,7 @@ uma_zone_set_maxaction(uma_zone_t zone, uma_maxaction_t maxaction) { ZONE_LOCK(zone); - zone->uz_maxaction = maxaction; + TASK_INIT(&zone->uz_maxaction, 0, (task_fn_t *)maxaction, zone); ZONE_UNLOCK(zone); } @@ -3607,6 +3613,102 @@ sysctl_handle_uma_zone_cur(SYSCTL_HANDLER_ARGS) return (sysctl_handle_int(oidp, &cur, 0, req)); } +#ifdef INVARIANTS +static uma_slab_t +uma_dbg_getslab(uma_zone_t zone, void *item) +{ + uma_slab_t slab; + uma_keg_t keg; + uint8_t *mem; + + mem = (uint8_t *)((uintptr_t)item & (~UMA_SLAB_MASK)); + if (zone->uz_flags & UMA_ZONE_VTOSLAB) { + slab = vtoslab((vm_offset_t)mem); + } else { + /* + * It is safe to return the slab here even though the + * zone is unlocked because the item's allocation state + * essentially holds a reference. + */ + ZONE_LOCK(zone); + keg = LIST_FIRST(&zone->uz_kegs)->kl_keg; + if (keg->uk_flags & UMA_ZONE_HASH) + slab = hash_sfind(&keg->uk_hash, mem); + else + slab = (uma_slab_t)(mem + keg->uk_pgoff); + ZONE_UNLOCK(zone); + } + + return (slab); +} + +/* + * Set up the slab's freei data such that uma_dbg_free can function. + * + */ +static void +uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item) +{ + uma_keg_t keg; + int freei; + + if (zone_first_keg(zone) == NULL) + return; + if (slab == NULL) { + slab = uma_dbg_getslab(zone, item); + if (slab == NULL) + panic("uma: item %p did not belong to zone %s\n", + item, zone->uz_name); + } + keg = slab->us_keg; + freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; + + if (BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree)) + panic("Duplicate alloc of %p from zone %p(%s) slab %p(%d)\n", + item, zone, zone->uz_name, slab, freei); + BIT_SET_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree); + + return; +} + +/* + * Verifies freed addresses. Checks for alignment, valid slab membership + * and duplicate frees. + * + */ +static void +uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item) +{ + uma_keg_t keg; + int freei; + + if (zone_first_keg(zone) == NULL) + return; + if (slab == NULL) { + slab = uma_dbg_getslab(zone, item); + if (slab == NULL) + panic("uma: Freed item %p did not belong to zone %s\n", + item, zone->uz_name); + } + keg = slab->us_keg; + freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; + + if (freei >= keg->uk_ipers) + panic("Invalid free of %p from zone %p(%s) slab %p(%d)\n", + item, zone, zone->uz_name, slab, freei); + + if (((freei * keg->uk_rsize) + slab->us_data) != item) + panic("Unaligned free of %p from zone %p(%s) slab %p(%d)\n", + item, zone, zone->uz_name, slab, freei); + + if (!BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree)) + panic("Duplicate free of %p from zone %p(%s) slab %p(%d)\n", + item, zone, zone->uz_name, slab, freei); + + BIT_CLR_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree); +} +#endif /* INVARIANTS */ + #ifdef DDB DB_SHOW_COMMAND(uma, db_show_uma) { @@ -3664,4 +3766,4 @@ DB_SHOW_COMMAND(umacache, db_show_umacache) return; } } -#endif +#endif /* DDB */ diff --git a/sys/vm/uma_dbg.c b/sys/vm/uma_dbg.c index 3fbd29b..7bf06d3 100644 --- a/sys/vm/uma_dbg.c +++ b/sys/vm/uma_dbg.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/mutex.h> #include <sys/malloc.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/vm_object.h> @@ -196,100 +197,3 @@ mtrash_fini(void *mem, int size) { (void)mtrash_ctor(mem, size, NULL, 0); } - -#ifdef INVARIANTS -static uma_slab_t -uma_dbg_getslab(uma_zone_t zone, void *item) -{ - uma_slab_t slab; - uma_keg_t keg; - uint8_t *mem; - - mem = (uint8_t *)((uintptr_t)item & (~UMA_SLAB_MASK)); - if (zone->uz_flags & UMA_ZONE_VTOSLAB) { - slab = vtoslab((vm_offset_t)mem); - } else { - /* - * It is safe to return the slab here even though the - * zone is unlocked because the item's allocation state - * essentially holds a reference. - */ - ZONE_LOCK(zone); - keg = LIST_FIRST(&zone->uz_kegs)->kl_keg; - if (keg->uk_flags & UMA_ZONE_HASH) - slab = hash_sfind(&keg->uk_hash, mem); - else - slab = (uma_slab_t)(mem + keg->uk_pgoff); - ZONE_UNLOCK(zone); - } - - return (slab); -} - -/* - * Set up the slab's freei data such that uma_dbg_free can function. - * - */ -void -uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item) -{ - uma_keg_t keg; - int freei; - - if (zone_first_keg(zone) == NULL) - return; - if (slab == NULL) { - slab = uma_dbg_getslab(zone, item); - if (slab == NULL) - panic("uma: item %p did not belong to zone %s\n", - item, zone->uz_name); - } - keg = slab->us_keg; - freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; - - if (BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree)) - panic("Duplicate alloc of %p from zone %p(%s) slab %p(%d)\n", - item, zone, zone->uz_name, slab, freei); - BIT_SET_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree); - - return; -} - -/* - * Verifies freed addresses. Checks for alignment, valid slab membership - * and duplicate frees. - * - */ -void -uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item) -{ - uma_keg_t keg; - int freei; - - if (zone_first_keg(zone) == NULL) - return; - if (slab == NULL) { - slab = uma_dbg_getslab(zone, item); - if (slab == NULL) - panic("uma: Freed item %p did not belong to zone %s\n", - item, zone->uz_name); - } - keg = slab->us_keg; - freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; - - if (freei >= keg->uk_ipers) - panic("Invalid free of %p from zone %p(%s) slab %p(%d)\n", - item, zone, zone->uz_name, slab, freei); - - if (((freei * keg->uk_rsize) + slab->us_data) != item) - panic("Unaligned free of %p from zone %p(%s) slab %p(%d)\n", - item, zone, zone->uz_name, slab, freei); - - if (!BIT_ISSET(SLAB_SETSIZE, freei, &slab->us_debugfree)) - panic("Duplicate free of %p from zone %p(%s) slab %p(%d)\n", - item, zone, zone->uz_name, slab, freei); - - BIT_CLR_ATOMIC(SLAB_SETSIZE, freei, &slab->us_debugfree); -} - -#endif /* INVARIANTS */ diff --git a/sys/vm/uma_dbg.h b/sys/vm/uma_dbg.h index 341cecb..e3c9df0 100644 --- a/sys/vm/uma_dbg.h +++ b/sys/vm/uma_dbg.h @@ -49,7 +49,4 @@ void mtrash_dtor(void *mem, int size, void *arg); int mtrash_init(void *mem, int size, int flags); void mtrash_fini(void *mem, int size); -void uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item); -void uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item); - #endif /* VM_UMA_DBG_H */ diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h index 5d7ecd3..1b0d5d5 100644 --- a/sys/vm/uma_int.h +++ b/sys/vm/uma_int.h @@ -307,7 +307,7 @@ struct uma_zone { const char *uz_warning; /* Warning to print on failure */ struct timeval uz_ratecheck; /* Warnings rate-limiting */ - uma_maxaction_t uz_maxaction; /* Function to run when at limit */ + struct task uz_maxaction; /* Task to run when at limit */ /* * This HAS to be the last item because we adjust the zone size diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index d27eb2d..b510696 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -102,6 +102,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/vmmeter.h> #include <sys/vnode.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/pmap.h> diff --git a/tests/sys/acl/Makefile b/tests/sys/acl/Makefile index b85cf00..7db6682 100644 --- a/tests/sys/acl/Makefile +++ b/tests/sys/acl/Makefile @@ -25,8 +25,14 @@ TAP_TESTS_SH+= 04 TEST_METADATA.$t+= required_user="root" .endfor +_ACL_PROGS= getfacl setfacl + .for t in 01 03 04 -TEST_METADATA.$t+= required_programs="/sbin/zpool" +TEST_METADATA.$t+= required_programs="zpool ${_ACL_PROGS}" +.endfor + +.for t in 00 02 +TEST_METADATA.$t+= required_programs="${_ACL_PROGS}" .endfor .include <bsd.test.mk> diff --git a/tools/regression/sysvsem/semtest.c b/tools/regression/sysvsem/semtest.c index 8a997d0..39c4164 100644 --- a/tools/regression/sysvsem/semtest.c +++ b/tools/regression/sysvsem/semtest.c @@ -152,6 +152,15 @@ main(int argc, char *argv[]) print_semid_ds(&s_ds, 0600); + errno = 0; + if (semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0600) != -1 || + errno != EEXIST) + err(1, "semget IPC_EXCL 1 did not fail with [EEXIST]"); + errno = 0; + if (semget(semkey, 2, IPC_CREAT | IPC_EXCL | 0600) != -1 || + errno != EEXIST) + err(1, "semget IPC_EXCL 2 did not fail with [EEXIST]"); + for (child_count = 0; child_count < 5; child_count++) { switch ((child_pid = fork())) { case -1: diff --git a/tools/tools/ath/athaggrstats/main.c b/tools/tools/ath/athaggrstats/main.c index 95e7917..6a0de98 100644 --- a/tools/tools/ath/athaggrstats/main.c +++ b/tools/tools/ath/athaggrstats/main.c @@ -89,7 +89,7 @@ main(int argc, char *argv[]) ifname = getenv("ATH"); if (ifname == NULL) - ifname = "ath0"; + ifname = ATH_DEFAULT; wf = athaggrstats_new(ifname, getfmt("default")); while ((c = getopt(argc, argv, "bi:lo:z")) != -1) { switch (c) { diff --git a/tools/tools/ath/athdebug/athdebug.c b/tools/tools/ath/athdebug/athdebug.c index bcdbcc8..b28f043 100644 --- a/tools/tools/ath/athdebug/athdebug.c +++ b/tools/tools/ath/athdebug/athdebug.c @@ -31,7 +31,7 @@ /* * athdebug [-i interface] flags - * (default interface is ath0). + * (default interface is wlan0). */ #include <sys/param.h> @@ -156,7 +156,7 @@ main(int argc, char *argv[]) ifname = getenv("ATH"); if (ifname == NULL) - ifname = "ath0"; + ifname = ATH_DEFAULT; progname = argv[0]; if (argc > 1) { if (strcmp(argv[1], "-i") == 0) { diff --git a/tools/tools/ath/athradar/athradar.c b/tools/tools/ath/athradar/athradar.c index f40e1bd..69f4416 100644 --- a/tools/tools/ath/athradar/athradar.c +++ b/tools/tools/ath/athradar/athradar.c @@ -30,10 +30,6 @@ #include "ah.h" #include "ah_internal.h" -#ifndef ATH_DEFAULT -#define ATH_DEFAULT "ath0" -#endif - #include <getopt.h> #include <errno.h> #include <err.h> diff --git a/tools/tools/ath/athratestats/main.c b/tools/tools/ath/athratestats/main.c index 3881e85..b3f85f7 100644 --- a/tools/tools/ath/athratestats/main.c +++ b/tools/tools/ath/athratestats/main.c @@ -310,7 +310,7 @@ main(int argc, char *argv[]) ifname = getenv("ATH"); if (ifname == NULL) - ifname = "ath0"; + ifname = ATH_DEFAULT; while ((c = getopt(argc, argv, "ahi:m:s:")) != -1) { switch (c) { diff --git a/tools/tools/ath/athregs/dumpregs.c b/tools/tools/ath/athregs/dumpregs.c index 4a50726..472df05 100644 --- a/tools/tools/ath/athregs/dumpregs.c +++ b/tools/tools/ath/athregs/dumpregs.c @@ -155,7 +155,7 @@ main(int argc, char *argv[]) atd.ad_out_data = (caddr_t) &state.revs; atd.ad_out_size = sizeof(state.revs); if (ioctl(s, SIOCGATHDIAG, &atd) < 0) - err(1, atd.ad_name); + err(1, "%s", atd.ad_name); if (ath_hal_setupregs(&atd, what) == 0) errx(-1, "no registers are known for this part " @@ -173,7 +173,7 @@ main(int argc, char *argv[]) } atd.ad_id = HAL_DIAG_REGS | ATH_DIAG_IN | ATH_DIAG_DYN; if (ioctl(s, SIOCGATHDIAG, &atd) < 0) - err(1, atd.ad_name); + err(1, "%s", atd.ad_name); /* * Expand register data into global space that can be diff --git a/tools/tools/ath/athspectral/athspectral.c b/tools/tools/ath/athspectral/athspectral.c index 1ec9085..91045d0 100644 --- a/tools/tools/ath/athspectral/athspectral.c +++ b/tools/tools/ath/athspectral/athspectral.c @@ -30,10 +30,6 @@ #include "ah.h" #include "ah_internal.h" -#ifndef ATH_DEFAULT -#define ATH_DEFAULT "ath0" -#endif - #include <getopt.h> #include <errno.h> #include <err.h> diff --git a/tools/tools/ath/athstats/main.c b/tools/tools/ath/athstats/main.c index bf0323d..29e8636 100644 --- a/tools/tools/ath/athstats/main.c +++ b/tools/tools/ath/athstats/main.c @@ -94,7 +94,7 @@ main(int argc, char *argv[]) ifname = getenv("ATH"); if (ifname == NULL) - ifname = "ath0"; + ifname = ATH_DEFAULT; wf = athstats_new(ifname, getfmt("default")); while ((c = getopt(argc, argv, "bi:lo:z")) != -1) { switch (c) { diff --git a/tools/tools/nanobsd/defaults.sh b/tools/tools/nanobsd/defaults.sh index a0e6be5..9a5c5cb 100755 --- a/tools/tools/nanobsd/defaults.sh +++ b/tools/tools/nanobsd/defaults.sh @@ -356,7 +356,7 @@ clean_world ( ) ( rm -r ${NANO_OBJ}/ fi mkdir -p "${NANO_OBJ}" "${NANO_WORLDDIR}" - printenv > ${NANO_OBJ}/_.env + printenv > ${NANO_LOG}/_.env else pprint 2 "Clean and create world directory (${NANO_WORLDDIR})" if ! rm -rf "${NANO_WORLDDIR}/" > /dev/null 2>&1 ; then @@ -385,7 +385,7 @@ make_conf_install ( ) ( install_world ( ) ( pprint 2 "installworld" - pprint 3 "log: ${NANO_OBJ}/_.iw" + pprint 3 "log: ${NANO_LOG}/_.iw" ( nano_make_install_env @@ -393,13 +393,13 @@ install_world ( ) ( cd "${NANO_SRC}" ${NANO_MAKE} installworld DESTDIR="${NANO_WORLDDIR}" chflags -R noschg "${NANO_WORLDDIR}" - ) > ${NANO_OBJ}/_.iw 2>&1 + ) > ${NANO_LOG}/_.iw 2>&1 ) install_etc ( ) ( pprint 2 "install /etc" - pprint 3 "log: ${NANO_OBJ}/_.etc" + pprint 3 "log: ${NANO_LOG}/_.etc" ( nano_make_install_env @@ -409,14 +409,14 @@ install_etc ( ) ( # make.conf doesn't get created by default, but some ports need it # so they can spam it. cp /dev/null "${NANO_WORLDDIR}"/etc/make.conf - ) > ${NANO_OBJ}/_.etc 2>&1 + ) > ${NANO_LOG}/_.etc 2>&1 ) install_kernel ( ) ( local extra pprint 2 "install kernel ($NANO_KERNEL)" - pprint 3 "log: ${NANO_OBJ}/_.ik" + pprint 3 "log: ${NANO_LOG}/_.ik" ( @@ -432,12 +432,12 @@ install_kernel ( ) ( cd "${NANO_SRC}" ${NANO_MAKE} installkernel DESTDIR="${NANO_WORLDDIR}" - ) > ${NANO_OBJ}/_.ik 2>&1 + ) > ${NANO_LOG}/_.ik 2>&1 ) native_xtools ( ) ( print 2 "Installing the optimized native build tools for cross env" - pprint 3 "log: ${NANO_OBJ}/_.native_xtools" + pprint 3 "log: ${NANO_LOG}/_.native_xtools" ( @@ -446,7 +446,7 @@ native_xtools ( ) ( cd "${NANO_SRC}" ${NANO_MAKE} native-xtools DESTDIR="${NANO_WORLDDIR}" - ) > ${NANO_OBJ}/_.native_xtools 2>&1 + ) > ${NANO_LOG}/_.native_xtools 2>&1 ) # @@ -460,9 +460,9 @@ run_customize ( ) ( for c in $NANO_CUSTOMIZE do pprint 2 "customize \"$c\"" - pprint 3 "log: ${NANO_OBJ}/_.cust.$c" + pprint 3 "log: ${NANO_LOG}/_.cust.$c" pprint 4 "`type $c`" - ( set -x ; $c ) > ${NANO_OBJ}/_.cust.$c 2>&1 + ( set -x ; $c ) > ${NANO_LOG}/_.cust.$c 2>&1 done ) @@ -476,9 +476,9 @@ run_late_customize ( ) ( for c in $NANO_LATE_CUSTOMIZE do pprint 2 "late customize \"$c\"" - pprint 3 "log: ${NANO_OBJ}/_.late_cust.$c" + pprint 3 "log: ${NANO_LOG}/_.late_cust.$c" pprint 4 "`type $c`" - ( set -x ; $c ) > ${NANO_OBJ}/_.late_cust.$c 2>&1 + ( set -x ; $c ) > ${NANO_LOG}/_.late_cust.$c 2>&1 done ) @@ -510,7 +510,7 @@ fixup_before_diskimage ( ) ( setup_nanobsd ( ) ( pprint 2 "configure nanobsd setup" - pprint 3 "log: ${NANO_OBJ}/_.dl" + pprint 3 "log: ${NANO_LOG}/_.dl" ( cd "${NANO_WORLDDIR}" @@ -547,7 +547,7 @@ setup_nanobsd ( ) ( # Put /tmp on the /var ramdisk (could be symlink already) tgt_dir2symlink tmp var/tmp - ) > ${NANO_OBJ}/_.dl 2>&1 + ) > ${NANO_LOG}/_.dl 2>&1 ) setup_nanobsd_etc ( ) ( @@ -630,7 +630,7 @@ populate_data_slice ( ) ( create_diskimage ( ) ( pprint 2 "build diskimage" - pprint 3 "log: ${NANO_OBJ}/_.di" + pprint 3 "log: ${NANO_LOG}/_.di" ( echo $NANO_MEDIASIZE $NANO_IMAGES \ @@ -699,7 +699,7 @@ create_diskimage ( ) ( # for booting the image from a USB device to work. print "a 1" } - ' > ${NANO_OBJ}/_.fdisk + ' > ${NANO_LOG}/_.fdisk IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} MNT=${NANO_OBJ}/_.mnt @@ -718,7 +718,7 @@ create_diskimage ( ) ( trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT - fdisk -i -f ${NANO_OBJ}/_.fdisk ${MD} + fdisk -i -f ${NANO_LOG}/_.fdisk ${MD} fdisk ${MD} # XXX: params # XXX: pick up cached boot* files, they may not be in image anymore. @@ -736,8 +736,8 @@ create_diskimage ( ) ( populate_slice /dev/${MD}${NANO_ROOT} ${NANO_WORLDDIR} ${MNT} "${NANO_ROOT}" mount /dev/${MD}${NANO_ROOT} ${MNT} echo "Generating mtree..." - ( cd "${MNT}" && mtree -c ) > ${NANO_OBJ}/_.mtree - ( cd "${MNT}" && du -k ) > ${NANO_OBJ}/_.du + ( cd "${MNT}" && mtree -c ) > ${NANO_LOG}/_.mtree + ( cd "${MNT}" && du -k ) > ${NANO_LOG}/_.du nano_umount "${MNT}" if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then @@ -792,7 +792,7 @@ create_diskimage ( ) ( trap - 1 2 15 trap nano_cleanup EXIT - ) > ${NANO_OBJ}/_.di 2>&1 + ) > ${NANO_LOG}/_.di 2>&1 ) last_orders ( ) ( @@ -1026,7 +1026,8 @@ set_defaults_and_export ( ) { : ${NANO_OBJ:=/usr/obj/nanobsd.${NANO_NAME}} : ${MAKEOBJDIRPREFIX:=${NANO_OBJ}} : ${NANO_DISKIMGDIR:=${NANO_OBJ}} - NANO_WORLDDIR=${NANO_OBJ}/_.w + : ${NANO_WORLDDIR:=${NANO_OBJ}/_.w} + : ${NANO_LOG:=${NANO_OBJ}} NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install @@ -1070,6 +1071,7 @@ set_defaults_and_export ( ) { export_var NANO_MODULES export_var NANO_NOPRIV_BUILD export_var NANO_METALOG + export_var NANO_LOG export_var SRCCONF export_var SRC_ENV_CONF } diff --git a/tools/tools/nanobsd/embedded/common b/tools/tools/nanobsd/embedded/common index bbac162..50e507f 100644 --- a/tools/tools/nanobsd/embedded/common +++ b/tools/tools/nanobsd/embedded/common @@ -76,7 +76,7 @@ fi NANO_SLICE_FAT_SIZE=32m NANO_SLICE_CFG_SIZE=32m -NANO_BOOT2CFG="-D -h -S115200 comconsole_port=0x3e8" +NANO_BOOT2CFG="-P -S115200" NANO_RAM_ETCSIZE=8192 NANO_RAM_TMPVARSIZE=8192 @@ -88,23 +88,32 @@ NANO_CFG_BASE=$(pwd) NANO_CFG_BASE=$(realpath ${NANO_CFG_BASE}/..) NANO_SRC=$(realpath ${NANO_CFG_BASE}/../../..) #### XXX share obj -NANO_OBJ=${NANO_SRC}/../$NANO_NAME/obj -# Where cust_pkg() finds packages to install -#XXX: Is this the right place? -#NANO_PORTS=$(realpath ${NANO_SRC}/../ports) -NANO_PORTS=/usr/ports -NANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg +if [ -z ${NANO_CPUTYPE} ]; then + NANO_OBJ=${NANO_SRC}/../embedded/obj +else + # Alas, I can't set OBJTREE to ${MACHINE}.${MACHINE_ARCH}.${CPUTYPE} + # so this will have to do until I can. + NANO_OBJ=${NANO_SRC}/../embedded/obj.${NANO_CPUTYPE} +fi +NANO_LOG=${NANO_OBJ}/../${NANO_NAME} +NANO_DISKIMGDIR=${NANO_OBJ}/../images +NANO_WORLDDIR=${NANO_LOG}/_.w NANO_INIT_IMG2=0 NANO_NOPRIV_BUILD=t unset MAKEOBJDIRPREFIX -# this to go into nanobsd.sh -NANO_PORTS=${NANO_PORTS:-/usr/ports} - mkdir -p ${NANO_OBJ} NANO_OBJ=$(realpath ${NANO_OBJ}) +mkdir -p ${NANO_LOG} +NANO_LOG=$(realpath ${NANO_LOG}) +mkdir -p ${NANO_IMAGES} +NANO_IMAGES=$(realpath ${NANO_IMAGES}) +mkdir -p ${NANO_WORLDDIR} +NANO_WORLDDIR=$(realpath ${NANO_WORLDDIR}) +mkdir -p ${NANO_DISKIMGDIR} +NANO_DISKIMGDIR=$(realpath ${NANO_DISKIMGDIR}) -NANO_FAT_DIR=${NANO_OBJ}/_.fat +NANO_FAT_DIR=${NANO_LOG}/_.fat customize_cmd cust_allow_ssh_root @@ -180,109 +189,18 @@ WITHOUT_RCS=true NANO_PACKAGE_ONLY=1 -# install a package from a pre-built binary -do_add_pkg ( ) ( - # Need to create ${NANO_OBJ}/ports in this add_pkg_${port} function - set -x - mkdir -p ${NANO_OBJ}/ports/distfiles - mkdir -p ${NANO_OBJ}/ports/packages - mkdir -p ${NANO_WORLDDIR}/usr/ports/packages - mkdir -p ${NANO_WORLDDIR}/usr/ports/distfiles - mount -t nullfs -o noatime ${NANO_OBJ}/ports/packages \ - ${NANO_WORLDDIR}/usr/ports/packages - mount -t nullfs -o noatime ${NANO_OBJ}/ports/distfiles \ - ${NANO_WORLDDIR}/usr/ports/distfiles - CR env ASSUME_ALWAYS_YES=YES SIGNATURE_TYPE=none /usr/sbin/pkg add /usr/ports/packages/All/$1.txz - umount ${NANO_WORLDDIR}/usr/ports/distfiles - umount ${NANO_WORLDDIR}/usr/ports/packages - rmdir ${NANO_WORLDDIR}/usr/ports/packages - rmdir ${NANO_WORLDDIR}/usr/ports/distfiles - rmdir ${NANO_WORLDDIR}/usr/ports - set +x -) +# Creates images for all the formats that use MBR / GPT +# split later if the #ifdef soup gets too bad. +create_diskimage_gpt ( ) ( + pprint 2 "build diskimage gpt ${NANO_NAME}" -# Build a port (with the side effect of creating a package) -do_add_port ( ) ( - local port_path - port_path=$1 - shift - set -x - # Need to create ${NANO_OBJ}/ports in this add_port_${port} function - mkdir -p ${NANO_OBJ}/ports/distfiles - mkdir -p ${NANO_OBJ}/ports/packages - mkdir -p ${NANO_PORTS}/packages - mkdir -p ${NANO_PORTS}/distfiles - mkdir -p ${NANO_WORLDDIR}/usr/src - mkdir -p ${NANO_WORLDDIR}/usr/ports - mount -t nullfs -o noatime ${NANO_SRC} ${NANO_WORLDDIR}/usr/src - mount -t nullfs -o noatime ${NANO_PORTS} ${NANO_WORLDDIR}/usr/ports - mount -t nullfs -o noatime ${NANO_OBJ}/ports/packages \ - ${NANO_WORLDDIR}/usr/ports/packages - mount -t nullfs -o noatime ${NANO_OBJ}/ports/distfiles \ - ${NANO_WORLDDIR}/usr/ports/distfiles - mkdir -p ${NANO_WORLDDIR}/dev - mount -t devfs devfs ${NANO_WORLDDIR}/dev - mkdir -p ${NANO_WORLDDIR}/usr/workdir - cp /etc/resolv.conf ${NANO_WORLDDIR}/etc/resolv.conf - # OK, a little inefficient, but likely not enough to worry about. - CR ldconfig /lib /usr/lib /usr/local/lib - CR ldconfig -R - CR ldconfig -r -# Improvement: Don't know why package-recursive don't works here - CR "env UNAME_p=${NANO_ARCH} TARGET=${NANO_ARCH} \ - TARGET_ARCH=${NANO_ARCH} PORTSDIR=${NANO_PORTS} make \ - __MAKE_CONF=${NANO_MAKE_CONF_BUILD} \ - WRKDIRPREFIX=/usr/workdir -C /usr/ports/$port_path \ - package-recursive BATCH=yes $* clean FORCE_PKG_REGISTER=t" - rm ${NANO_WORLDDIR}/etc/resolv.conf - rm -rf ${NANO_WORLDDIR}/usr/obj - rm -rf ${NANO_WORLDDIR}/usr/workdir - umount ${NANO_WORLDDIR}/dev - umount ${NANO_WORLDDIR}/usr/ports/packages - umount ${NANO_WORLDDIR}/usr/ports/distfiles - umount ${NANO_WORLDDIR}/usr/ports - umount ${NANO_WORLDDIR}/usr/src - set +x + create_diskimage_mbr $* ) -# Need to check if this function works with cross-compiling architecture!!!! -# Recursive complex fonction: Generate one function for each ports -# writes shell functions called later, so don't do in subshell. -add_port ( ) { - local port_path=$1 - local port=`echo $1 | sed -e 's/\//_/'` - shift - # Check if package allready exist - # Need to: - # 1. check ARCH of this package! - # 2. Add a trap - cd ${NANO_PORTS}/${port_path} - PKG_NAME=`env PORTSDIR=${NANO_PORTS} make __MAKE_CONF=${NANO_MAKE_CONF_BUILD} package-name` - if [ -f ${NANO_OBJ}/ports/packages/All/${PKG_NAME}.txz ]; then - # Pkg file found: Generate add_pkg_NAME function - eval " - add_pkg_${port} ( ) { - do_add_pkg ${PKG_NAME} - } - customize_cmd add_pkg_${port} - " - else - # No pkg file: Generate add_port_NAME function - eval " - add_port_${port} ( ) { - do_add_port ${port_path} $* - } - customize_cmd add_port_${port} - " - NANO_PACKAGE_ONLY=0 - fi -} - -# Creates images for all the formats that use MBR create_diskimage_mbr ( ) ( pprint 2 "build diskimage ${NANO_NAME}" - pprint 3 "log: ${NANO_OBJ}/_.di" + pprint 3 "log: ${NANO_LOG}/_.di" ( local extra i sz fmt fmtarg bootmbr bootbsd skiparg @@ -295,44 +213,54 @@ create_diskimage_mbr ( ) ( skiparg=${NANO_MBR_FIRST_SKIP:+-S ${NANO_MBR_FIRST_SKIP}} for i in s1 s2 s3 s4 p1 p2 p3 p4 p5 empty; do - rm -fr ${NANO_OBJ}/_.${i}* + rm -fr ${NANO_LOG}/_.${i}* done # Populate the FAT partition, if needed if [ -n "${NANO_SLICE_FAT}" ]; then echo Creating MSDOS partition for kernel newfs_msdos -C ${NANO_SLICE_FAT_SIZE} -F 16 -L ${NANO_NAME} \ - ${NANO_OBJ}/_.${NANO_SLICE_FAT} + ${NANO_LOG}/_.${NANO_SLICE_FAT} if [ -d ${NANO_FAT_DIR} ]; then # Need to copy files from ${NANO_FATDIR} with mtools, or use # makefs -t msdos once that's supported - mcopy -i ${NANO_OBJ}/_.${NANO_SLICE_FAT} ${NANO_FAT_DIR}/* :: + mcopy -i ${NANO_LOG}/_.${NANO_SLICE_FAT} ${NANO_FAT_DIR}/* :: fi fi # Populate the Powerpc boot image, if needed if [ "${NANO_LAYOUT}" = powerpc64-ibm ]; then - dd if=${NANO_WORLDDIR}/boot/boot1.elf of=${NANO_OBJ}/_.s1 bs=800k count=1 conv=sync + dd if=${NANO_WORLDDIR}/boot/boot1.elf of=${NANO_LOG}/_.s1 bs=800k count=1 conv=sync fi # Populate the / partition, and place it into a slice with a # bsd label [ -z ${NANO_NOPRIV_BUILD} ] || extra="-F ${NANO_METALOG}" sz=${NANO_SLICE_ROOT_SIZE:+-s ${NANO_SLICE_ROOT_SIZE}} - eval "${NANO_MAKEFS_UFS}" ${extra} $sz "${NANO_OBJ}/_.${NANO_SLICE_ROOT}" \ + eval "${NANO_MAKEFS_UFS}" ${extra} $sz "${NANO_LOG}/_.${NANO_ROOT}" \ "${NANO_WORLDDIR}" -# mkimg -s bsd ${bootbsd} -p freebsd-ufs:=${NANO_OBJ}/_.${NANO_SLICE_ROOT} \ -# -o ${NANO_OBJ}/_.${NANO_SLICE_ROOT} + case ${NANO_DISK_SCHEME} in + mbr) + mkimg -s bsd ${bootbsd} -p freebsd-ufs:=${NANO_LOG}/_.${NANO_ROOT} \ + -o ${NANO_LOG}/_.${NANO_SLICE_ROOT} + eval $NANO_SLICE_CFG=freebsd + eval $NANO_SLICE_ROOT=freebsd + ;; + gpt) + eval $NANO_SLICE_CFG=freebsd-ufs + eval $NANO_SLICE_ROOT=freebsd-ufs + ;; + esac # Populate the /cfg partition, empty if none given if [ -z "${NANO_CFGDIR}" ]; then echo "Faking cfg dir, it's empty" - NANO_CFGDIR=${NANO_OBJ}/_.empty + NANO_CFGDIR=${NANO_LOG}/_.empty mkdir -p ${NANO_CFGDIR} fi # XXX -F cfg-mtree eval "${NANO_MAKEFS_UFS}" -s ${NANO_SLICE_CFG_SIZE} \ - "${NANO_OBJ}/_.${NANO_SLICE_CFG}" "${NANO_CFGDIR}" + "${NANO_LOG}/_.${NANO_SLICE_CFG}" "${NANO_CFGDIR}" # data slice not supported since we need the part for FAT for # booting @@ -341,43 +269,33 @@ create_diskimage_mbr ( ) ( if [ -n "$NANO_SLICE_FAT" ]; then eval $NANO_SLICE_FAT=fat16b fi - case ${NANO_SLICE_CFG} in - s*) - echo slice - eval $NANO_SLICE_CFG=freebsd - eval $NANO_SLICE_ROOT=freebsd - ;; - p*) - echo part - eval $NANO_SLICE_CFG=freebsd-ufs - eval $NANO_SLICE_ROOT=freebsd-ufs - ;; - esac + + out=${NANO_DISKIMGDIR}/_.disk.image.${NANO_NAME}${fmt} # below depends on https://reviews.freebsd.org/D4403 not yet in the tree # but there's problems: it marks all partitions as active, so you have to # boot off parittion 3 or 2 by hand if you're playing around with this WIP case ${NANO_LAYOUT} in std-embedded) - mkimg -a 3 ${skiparg} ${fmtarg} ${bootmbr} -s mbr -p ${s1}:=${NANO_OBJ}/_.s1 \ - -p ${s2}:=${NANO_OBJ}/_.s2 \ - -p ${s3}:=${NANO_OBJ}/_.s3 \ - -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt} + mkimg -a 3 ${skiparg} ${fmtarg} ${bootmbr} -s mbr -p ${s1}:=${NANO_LOG}/_.s1 \ + -p ${s2}:=${NANO_LOG}/_.s2 \ + -p ${s3}:=${NANO_LOG}/_.s3 \ + -o ${out} ;; std-x86) # s1 is cfg, s2 is /, not sure how to make that # boot (marked as active) with mkimg yet - mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr -p ${s1}:=${NANO_OBJ}/_.s1 \ - -p ${s2}:=${NANO_OBJ}/_.s2 \ - -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt} + mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr -p ${s1}:=${NANO_LOG}/_.s1 \ + -p ${s2}:=${NANO_LOG}/_.s2 \ + -o ${out} ;; std-uefi) # s1 is boot, s2 is cfg, s3 is /, not sure how to make that # boot (marked as active) with mkimg yet mkimg -a 2 ${fmtarg} ${bootmbr} -s mbr \ -p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \ - -p ${s2}:=${NANO_OBJ}/_.s2 \ - -p ${s3}:=${NANO_OBJ}/_.s3 \ - -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt} + -p ${s2}:=${NANO_LOG}/_.s2 \ + -p ${s3}:=${NANO_LOG}/_.s3 \ + -o ${out} ;; std-uefi-bios) # p1 is boot for uefi, p2 is boot for gpt, p3 is cfg, p4 is / @@ -385,9 +303,9 @@ create_diskimage_mbr ( ) ( mkimg -a 2 ${fmtarg} ${bootmbr} -s gpt \ -p efi:=${NANO_WORLDDIR}/boot/boot1.efifat \ -p freebsd-boot:=${NAANO_WORLDDIR}/boot/gptboot \ - -p ${p3}:=${NANO_OBJ}/_.p3 \ - -p ${p4}:=${NANO_OBJ}/_.p4 \ - -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt} + -p ${p3}:=${NANO_LOG}/_.p3 \ + -p ${p4}:=${NANO_LOG}/_.p4 \ + -o ${out} ;; powerpc64-ibm) # A lie to make the boot loader work, it boots the first BSD partition @@ -396,13 +314,14 @@ create_diskimage_mbr ( ) ( # boot image is on a special partition, ala std-embedded, but that # partition isn't FAT with special files, but a copy of the boot # loader itself. - mkimg -a 1 ${fmtarg} -s mbr -p prepboot:=${NANO_OBJ}/_.s1 \ - -p ${s2}:=${NANO_OBJ}/_.s2 \ - -p ${s3}:=${NANO_OBJ}/_.s3a \ - -o ${NANO_OBJ}/_.disk.image.${NANO_NAME}${fmt} + mkimg -a 1 ${fmtarg} -s mbr -p prepboot:=${NANO_LOG}/_.s1 \ + -p ${s2}:=${NANO_LOG}/_.s2 \ + -p ${s3}:=${NANO_LOG}/_.s3a \ + -o ${out} ;; esac - ) > ${NANO_OBJ}/_.di 2>&1 + xz -9 --keep ${out} + ) > ${NANO_LOG}/_.di 2>&1 ) die( ) { @@ -662,11 +581,21 @@ eval std_${NANO_ARCH} # off the top. We also resize the 'a' partion on first boot # to the size of the partition for the ping/pong upgrade. # This feature needs support in the rc.d bootup script. +# +# Ideally, we'd not put BSD labels on the MBR disks. +# However, we can't boot off raw MBR disks. First, +# boot2 defaults to 'a' partition, and freaks out +# unless you tell it to use 'c'. But even if we +# hack that, then /boot/loader wants to load off +# of 'c' partition. If you fix that, then we'll +# try to mount root, but sanity checks prevent +# slices from working. +# : ${NANO_ENDIAN:=little} # make -V something to figure it out? : ${NANO_LAYOUT:=std-embedded} : ${NANO_MAKEFS_UFS:=makefs -t ffs -B ${NANO_ENDIAN}} -: ${NANO_DISK_SCHEME:=mbr} # No others really supported ATM +: ${NANO_DISK_SCHEME:=mbr} # No others really supported ATM (well, gpt) case ${NANO_LAYOUT} in std-embedded) NANO_SLICE_FAT=s1 @@ -696,11 +625,15 @@ std-uefi) NANO_SLICE_ALTROOT=s4 ;; std-uefi-bios) + NANO_DISK_SCHEME=gpt NANO_SLICE_UEFI=p1 NANO_SLICE_BOOT=p2 NANO_SLICE_CFG=p3 NANO_SLICE_ROOT=p4 NANO_SLICE_ALTROOT=p5 + # override root name + NANO_ROOT=${NANO_SLICE_ROOT} + NANO_ALTROOT=${NANO_SLICE_ALTROOT} ;; *) echo Unknown Layout ${NANO_LAYOUT} @@ -708,10 +641,6 @@ std-uefi-bios) ;; esac -# For this config, no BSD labels so NANO_ROOT and NANO_ALTROOT need to be -# adjusted -NANO_ROOT=${NANO_SLICE_ROOT} -NANO_ALTROOT=${NANO_SLICE_ALTROOT} NANO_SLICE_DATA= # Not included diff --git a/tools/tools/nanobsd/embedded/i386.cfg b/tools/tools/nanobsd/embedded/i386.cfg new file mode 100644 index 0000000..7fd9a528 --- /dev/null +++ b/tools/tools/nanobsd/embedded/i386.cfg @@ -0,0 +1,34 @@ +# $FreeBSD$ + +#- +# Copyright (c) 2015 Warner Losh. All Rights Reserved. +# Copyright (c) 2010-2011 iXsystems, 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 iXsystems, 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. +# + +NANO_ARCH=i386 +NANO_KERNEL=GENERIC +NANO_DRIVE=ada0 +NANO_NAME=i386 + +. common # Pull in common definitions, keep last diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr index 5996446..2b911fc 100644 --- a/usr.sbin/bsdconfig/share/common.subr +++ b/usr.sbin/bsdconfig/share/common.subr @@ -1,7 +1,7 @@ if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1 # # Copyright (c) 2012 Ron McDowell -# Copyright (c) 2012-2015 Devin Teske +# Copyright (c) 2012-2016 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -1015,10 +1015,9 @@ f_count_ifs() # # Trap signals so we can recover gracefully # -trap 'f_interrupt' SIGINT -trap 'f_die' SIGTERM SIGPIPE SIGXCPU SIGXFSZ \ - SIGFPE SIGTRAP SIGABRT SIGSEGV -trap '' SIGALRM SIGPROF SIGUSR1 SIGUSR2 SIGHUP SIGVTALRM +trap 'f_interrupt' INT +trap 'f_die' TERM PIPE XCPU XFSZ FPE TRAP ABRT SEGV +trap '' ALRM PROF USR1 USR2 HUP VTALRM # # Clone terminal stdout/stderr so we can redirect to it from within sub-shells diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index f1dbbd7..f33f4df 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -65,54 +65,60 @@ f_isinteger() # f_substr [-v $var_to_set] $string $start [$length] # # Similar to awk(1)'s substr(), return length substring of string that begins -# at start position counted from 1. +# at start position counted from 1. # -f_substr() -{ - local OPTIND=1 OPTARG __flag __var_to_set= - while getopts v: __flag; do - case "$__flag" in - v) __var_to_set="$OPTARG" ;; +case "$BASH_VERSION" in +*?*) + f_substr() + { + local __var_to_set= + case "$1" in + -v) __var_to_set="$2"; shift 2 ;; + -v?*) __var_to_set="${2#-v}"; shift 1 ;; esac - done - shift $(( $OPTIND - 1 )) - - local __tmp="$1" __start="${2:-1}" __size="$3" - local __tbuf __tbuf_len __trim __trimq - - if [ ! "$__tmp" ]; then - [ "$__var_to_set" ] && setvar "$__var_to_set" "" - return ${SUCCESS:-0} - fi - [ "$__start" -ge 1 ] 2> /dev/null || __start=1 - if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then - [ "$__var_to_set" ] && setvar "$__var_to_set" "" - return ${FAILURE:-1} - fi - - __trim=$(( $__start - 1 )) - while [ $__trim -gt 0 ]; do - __tbuf="?" - __tbuf_len=1 - while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]; do - __tbuf="$__tbuf?" - __tbuf_len=$(( $__tbuf_len + 1 )) - done - __trimq=$(( $__trim / $__tbuf_len )) - __trim=$(( $__trim - $__tbuf_len * $__trimq )) - while [ $__trimq -gt 0 ]; do - __tmp="${__tmp#$__tbuf}" - __trimq=$(( $__trimq - 1 )) + local __tmp="$1" __start="${2:-1}" __len="$3" + [ "$__start" -gt 0 ] 2> /dev/null && + __start=$(( $__start - 1 )) + if [ ! "$__var_to_set" ]; then + eval echo \"\${__tmp:\$__start${__len:+:\$__len}}\" + return $? + fi + if [ "$__len" ]; then + eval $__var_to_set=\"\${__tmp:\$__start:\$__len}\" + else + eval $__var_to_set=\"\${__tmp:\$__start}\" + fi + } + ;; +*) + # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above + f_substr() + { + local OPTIND=1 OPTARG __flag __var_to_set= + while getopts v: __flag; do + case "$__flag" in + v) __var_to_set="$OPTARG" ;; + esac done - done + shift $(( $OPTIND - 1 )) + + local __tmp="$1" __start="${2:-1}" __size="$3" + local __tbuf __tbuf_len __trim __trimq + + if [ ! "$__tmp" ]; then + [ "$__var_to_set" ] && setvar "$__var_to_set" "" + return ${SUCCESS:-0} + fi + [ "$__start" -ge 1 ] 2> /dev/null || __start=1 + if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then + [ "$__var_to_set" ] && setvar "$__var_to_set" "" + return ${FAILURE:-1} + fi - local __tmp_size=${#__tmp} - local __mask __mask_len - __trim=$(( $__tmp_size - ${__size:-$__tmp_size} )) - while [ $__trim -gt 0 ]; do - __tbuf="?" - __tbuf_len=1 - if [ $__trim -le $__size ]; then + __trim=$(( $__start - 1 )) + while [ $__trim -gt 0 ]; do + __tbuf="?" + __tbuf_len=1 while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ] do __tbuf="$__tbuf?" @@ -121,33 +127,66 @@ f_substr() __trimq=$(( $__trim / $__tbuf_len )) __trim=$(( $__trim - $__tbuf_len * $__trimq )) while [ $__trimq -gt 0 ]; do - __tmp="${__tmp%$__tbuf}" + __tmp="${__tmp#$__tbuf}" __trimq=$(( $__trimq - 1 )) done - else - __mask="$__tmp" - while [ $__tbuf_len -lt $(( $__size / $__tbuf_len )) ] - do - __tbuf="$__tbuf?" - __tbuf_len=$(( $__tbuf_len + 1 )) - done - __trimq=$(( $__size / $__tbuf_len )) - if [ $(( $__trimq * $__tbuf_len )) -ne $__size ]; then - __tbuf="$__tbuf?" - __tbuf_len=$(( $__tbuf_len + 1 )) + done + + local __tmp_size=${#__tmp} + local __mask __mask_len + __trim=$(( $__tmp_size - ${__size:-$__tmp_size} )) + while [ $__trim -gt 0 ]; do + __tbuf="?" + __tbuf_len=1 + if [ $__trim -le $__size ]; then + while [ $__tbuf_len -lt $(( + $__trim / $__tbuf_len + )) ]; do + __tbuf="$__tbuf?" + __tbuf_len=$(( $__tbuf_len + 1 )) + done + __trimq=$(( $__trim / $__tbuf_len )) + __trim=$(( $__trim - $__tbuf_len * $__trimq )) + while [ $__trimq -gt 0 ]; do + __tmp="${__tmp%$__tbuf}" + __trimq=$(( $__trimq - 1 )) + done + else + __mask="$__tmp" + while [ $__tbuf_len -lt $(( + $__size / $__tbuf_len + )) ]; do + __tbuf="$__tbuf?" + __tbuf_len=$(( $__tbuf_len + 1 )) + done + __trimq=$(( $__size / $__tbuf_len )) + if [ $__size -ne $(( + $__trimq * $__tbuf_len + )) ]; then + __tbuf="$__tbuf?" + __tbuf_len=$(( $__tbuf_len + 1 )) + fi + __mask_len=$(( + $__tmp_size - $__tbuf_len * $__trimq + )) + __trim=$(( + $__tmp_size - $__mask_len - $__size + )) + while [ $__trimq -gt 0 ]; do + __mask="${__mask#$__tbuf}" + __trimq=$(( $__trimq - 1 )) + done + __tmp="${__tmp%"$__mask"}" fi - __mask_len=$(( $__tmp_size - $__tbuf_len * $__trimq )) - __trim=$(( $__tmp_size - $__mask_len - $__size )) - while [ $__trimq -gt 0 ]; do - __mask="${__mask#$__tbuf}" - __trimq=$(( $__trimq - 1 )) - done - __tmp="${__tmp%"$__mask"}" - fi - done + done - setvar "$__var_to_set" "$__tmp" -} + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__tmp" + else + echo "$__tmp" + fi + } +esac # f_sprintf $var_to_set $format [$arguments ...] # diff --git a/usr.sbin/ctld/Makefile b/usr.sbin/ctld/Makefile index 6169d30..664dc22 100644 --- a/usr.sbin/ctld/Makefile +++ b/usr.sbin/ctld/Makefile @@ -1,8 +1,11 @@ # $FreeBSD$ +CFLAGS+=-I${.CURDIR}/../../contrib/libucl/include +.PATH: ${.CURDIR}/../../contrib/libucl/include + PROG= ctld SRCS= chap.c ctld.c discovery.c isns.c kernel.c keys.c log.c -SRCS+= login.c parse.y pdu.c token.l y.tab.h +SRCS+= login.c parse.y pdu.c token.l y.tab.h uclparse.c CFLAGS+= -I${.CURDIR} CFLAGS+= -I${.CURDIR}/../../sys CFLAGS+= -I${.CURDIR}/../../sys/cam/ctl @@ -10,7 +13,7 @@ CFLAGS+= -I${.CURDIR}/../../sys/dev/iscsi #CFLAGS+= -DICL_KERNEL_PROXY MAN= ctld.8 ctl.conf.5 -LIBADD= bsdxml l md sbuf util +LIBADD= bsdxml l md sbuf util ucl m YFLAGS+= -v CLEANFILES= y.tab.c y.tab.h y.output diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c index 92fa553..6c8b4a8 100644 --- a/usr.sbin/ctld/ctld.c +++ b/usr.sbin/ctld/ctld.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> +#include <sys/stat.h> #include <sys/wait.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -2491,6 +2492,104 @@ register_signals(void) log_err(1, "sigaction"); } +static void +check_perms(const char *path) +{ + struct stat sb; + int error; + + error = stat(path, &sb); + if (error != 0) { + log_warn("stat"); + return; + } + if (sb.st_mode & S_IWOTH) { + log_warnx("%s is world-writable", path); + } else if (sb.st_mode & S_IROTH) { + log_warnx("%s is world-readable", path); + } else if (sb.st_mode & S_IXOTH) { + /* + * Ok, this one doesn't matter, but still do it, + * just for consistency. + */ + log_warnx("%s is world-executable", path); + } + + /* + * XXX: Should we also check for owner != 0? + */ +} + +static struct conf * +conf_new_from_file(const char *path, struct conf *oldconf, bool ucl) +{ + struct conf *conf; + struct auth_group *ag; + struct portal_group *pg; + struct pport *pp; + int error; + + log_debugx("obtaining configuration from %s", path); + + conf = conf_new(); + + TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next) + pport_copy(pp, conf); + + ag = auth_group_new(conf, "default"); + assert(ag != NULL); + + ag = auth_group_new(conf, "no-authentication"); + assert(ag != NULL); + ag->ag_type = AG_TYPE_NO_AUTHENTICATION; + + ag = auth_group_new(conf, "no-access"); + assert(ag != NULL); + ag->ag_type = AG_TYPE_DENY; + + pg = portal_group_new(conf, "default"); + assert(pg != NULL); + + if (ucl) + error = uclparse_conf(conf, path); + else + error = parse_conf(conf, path); + + if (error != 0) { + conf_delete(conf); + return (NULL); + } + + check_perms(path); + + if (conf->conf_default_ag_defined == false) { + log_debugx("auth-group \"default\" not defined; " + "going with defaults"); + ag = auth_group_find(conf, "default"); + assert(ag != NULL); + ag->ag_type = AG_TYPE_DENY; + } + + if (conf->conf_default_pg_defined == false) { + log_debugx("portal-group \"default\" not defined; " + "going with defaults"); + pg = portal_group_find(conf, "default"); + assert(pg != NULL); + portal_group_add_listen(pg, "0.0.0.0:3260", false); + portal_group_add_listen(pg, "[::]:3260", false); + } + + conf->conf_kernel_port_on = true; + + error = conf_verify(conf); + if (error != 0) { + conf_delete(conf); + return (NULL); + } + + return (conf); +} + int main(int argc, char **argv) { @@ -2499,13 +2598,17 @@ main(int argc, char **argv) const char *config_path = DEFAULT_CONFIG_PATH; int debug = 0, ch, error; bool dont_daemonize = false; + bool use_ucl = false; - while ((ch = getopt(argc, argv, "df:R")) != -1) { + while ((ch = getopt(argc, argv, "duf:R")) != -1) { switch (ch) { case 'd': dont_daemonize = true; debug++; break; + case 'u': + use_ucl = true; + break; case 'f': config_path = optarg; break; @@ -2529,7 +2632,8 @@ main(int argc, char **argv) kernel_init(); oldconf = conf_new_from_kernel(); - newconf = conf_new_from_file(config_path, oldconf); + newconf = conf_new_from_file(config_path, oldconf, use_ucl); + if (newconf == NULL) log_errx(1, "configuration error; exiting"); if (debug > 0) { @@ -2564,7 +2668,9 @@ main(int argc, char **argv) if (sighup_received) { sighup_received = false; log_debugx("received SIGHUP, reloading configuration"); - tmpconf = conf_new_from_file(config_path, newconf); + tmpconf = conf_new_from_file(config_path, newconf, + use_ucl); + if (tmpconf == NULL) { log_warnx("configuration error, " "continuing with old configuration"); diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h index 808b722..e9152329 100644 --- a/usr.sbin/ctld/ctld.h +++ b/usr.sbin/ctld/ctld.h @@ -297,8 +297,10 @@ int rchap_receive(struct rchap *rchap, char *rchap_get_response(struct rchap *rchap); void rchap_delete(struct rchap *rchap); +int parse_conf(struct conf *conf, const char *path); +int uclparse_conf(struct conf *conf, const char *path); + struct conf *conf_new(void); -struct conf *conf_new_from_file(const char *path, struct conf *old); struct conf *conf_new_from_kernel(void); void conf_delete(struct conf *conf); int conf_verify(struct conf *conf); diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y index afbf315..820b4c7 100644 --- a/usr.sbin/ctld/parse.y +++ b/usr.sbin/ctld/parse.y @@ -1044,70 +1044,18 @@ yyerror(const char *str) lineno, yytext, str); } -static void -check_perms(const char *path) +int +parse_conf(struct conf *newconf, const char *path) { - struct stat sb; int error; - error = stat(path, &sb); - if (error != 0) { - log_warn("stat"); - return; - } - if (sb.st_mode & S_IWOTH) { - log_warnx("%s is world-writable", path); - } else if (sb.st_mode & S_IROTH) { - log_warnx("%s is world-readable", path); - } else if (sb.st_mode & S_IXOTH) { - /* - * Ok, this one doesn't matter, but still do it, - * just for consistency. - */ - log_warnx("%s is world-executable", path); - } - - /* - * XXX: Should we also check for owner != 0? - */ -} - -struct conf * -conf_new_from_file(const char *path, struct conf *oldconf) -{ - struct auth_group *ag; - struct portal_group *pg; - struct pport *pp; - int error; - - log_debugx("obtaining configuration from %s", path); - - conf = conf_new(); - - TAILQ_FOREACH(pp, &oldconf->conf_pports, pp_next) - pport_copy(pp, conf); - - ag = auth_group_new(conf, "default"); - assert(ag != NULL); - - ag = auth_group_new(conf, "no-authentication"); - assert(ag != NULL); - ag->ag_type = AG_TYPE_NO_AUTHENTICATION; - - ag = auth_group_new(conf, "no-access"); - assert(ag != NULL); - ag->ag_type = AG_TYPE_DENY; - - pg = portal_group_new(conf, "default"); - assert(pg != NULL); - + conf = newconf; yyin = fopen(path, "r"); if (yyin == NULL) { log_warn("unable to open configuration file %s", path); - conf_delete(conf); - return (NULL); + return (1); } - check_perms(path); + lineno = 1; yyrestart(yyin); error = yyparse(); @@ -1116,35 +1064,6 @@ conf_new_from_file(const char *path, struct conf *oldconf) target = NULL; lun = NULL; fclose(yyin); - if (error != 0) { - conf_delete(conf); - return (NULL); - } - - if (conf->conf_default_ag_defined == false) { - log_debugx("auth-group \"default\" not defined; " - "going with defaults"); - ag = auth_group_find(conf, "default"); - assert(ag != NULL); - ag->ag_type = AG_TYPE_DENY; - } - - if (conf->conf_default_pg_defined == false) { - log_debugx("portal-group \"default\" not defined; " - "going with defaults"); - pg = portal_group_find(conf, "default"); - assert(pg != NULL); - portal_group_add_listen(pg, "0.0.0.0:3260", false); - portal_group_add_listen(pg, "[::]:3260", false); - } - - conf->conf_kernel_port_on = true; - - error = conf_verify(conf); - if (error != 0) { - conf_delete(conf); - return (NULL); - } - return (conf); + return (error); } diff --git a/usr.sbin/ctld/uclparse.c b/usr.sbin/ctld/uclparse.c new file mode 100644 index 0000000..fb2cce0 --- /dev/null +++ b/usr.sbin/ctld/uclparse.c @@ -0,0 +1,900 @@ +/*- + * Copyright (c) 2015 iXsystems Inc. + * All rights reserved. + * + * This software was developed by Jakub Klama <jceel@FreeBSD.org> + * under sponsorship from iXsystems 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 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/queue.h> +#include <sys/types.h> +#include <assert.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <ucl.h> + +#include "ctld.h" + +static struct conf *conf = NULL; + +static int uclparse_toplevel(const ucl_object_t *); +static int uclparse_chap(struct auth_group *, const ucl_object_t *); +static int uclparse_chap_mutual(struct auth_group *, const ucl_object_t *); +static int uclparse_lun(const char *, const ucl_object_t *); +static int uclparse_auth_group(const char *, const ucl_object_t *); +static int uclparse_portal_group(const char *, const ucl_object_t *); +static int uclparse_target(const char *, const ucl_object_t *); +static int uclparse_target_portal_group(struct target *, const ucl_object_t *); +static int uclparse_target_lun(struct target *, const ucl_object_t *); + +static int +uclparse_chap(struct auth_group *auth_group, const ucl_object_t *obj) +{ + const struct auth *ca; + const ucl_object_t *user, *secret; + + user = ucl_object_find_key(obj, "user"); + if (!user || user->type != UCL_STRING) { + log_warnx("chap section in auth-group \"%s\" is missing " + "\"user\" string key", auth_group->ag_name); + return (1); + } + + secret = ucl_object_find_key(obj, "secret"); + if (!secret || secret->type != UCL_STRING) { + log_warnx("chap section in auth-group \"%s\" is missing " + "\"secret\" string key", auth_group->ag_name); + } + + ca = auth_new_chap(auth_group, + ucl_object_tostring(user), + ucl_object_tostring(secret)); + + if (ca == NULL) + return (1); + + return (0); +} + +static int +uclparse_chap_mutual(struct auth_group *auth_group, const ucl_object_t *obj) +{ + const struct auth *ca; + const ucl_object_t *user, *secret, *mutual_user; + const ucl_object_t *mutual_secret; + + user = ucl_object_find_key(obj, "user"); + if (!user || user->type != UCL_STRING) { + log_warnx("chap-mutual section in auth-group \"%s\" is missing " + "\"user\" string key", auth_group->ag_name); + return (1); + } + + secret = ucl_object_find_key(obj, "secret"); + if (!secret || secret->type != UCL_STRING) { + log_warnx("chap-mutual section in auth-group \"%s\" is missing " + "\"secret\" string key", auth_group->ag_name); + return (1); + } + + mutual_user = ucl_object_find_key(obj, "mutual-user"); + if (!user || user->type != UCL_STRING) { + log_warnx("chap-mutual section in auth-group \"%s\" is missing " + "\"mutual-user\" string key", auth_group->ag_name); + return (1); + } + + mutual_secret = ucl_object_find_key(obj, "mutual-secret"); + if (!secret || secret->type != UCL_STRING) { + log_warnx("chap-mutual section in auth-group \"%s\" is missing " + "\"mutual-secret\" string key", auth_group->ag_name); + return (1); + } + + ca = auth_new_chap_mutual(auth_group, + ucl_object_tostring(user), + ucl_object_tostring(secret), + ucl_object_tostring(mutual_user), + ucl_object_tostring(mutual_secret)); + + if (ca == NULL) + return (1); + + return (0); +} + +static int +uclparse_target_portal_group(struct target *target, const ucl_object_t *obj) +{ + struct portal_group *tpg; + struct auth_group *tag = NULL; + struct port *tp; + const ucl_object_t *portal_group, *auth_group; + + portal_group = ucl_object_find_key(obj, "name"); + if (!portal_group || portal_group->type != UCL_STRING) { + log_warnx("portal-group section in target \"%s\" is missing " + "\"name\" string key", target->t_name); + return (1); + } + + auth_group = ucl_object_find_key(obj, "auth-group-name"); + if (auth_group && auth_group->type != UCL_STRING) { + log_warnx("portal-group section in target \"%s\" is missing " + "\"auth-group-name\" string key", target->t_name); + return (1); + } + + + tpg = portal_group_find(conf, ucl_object_tostring(portal_group)); + if (tpg == NULL) { + log_warnx("unknown portal-group \"%s\" for target " + "\"%s\"", ucl_object_tostring(portal_group), target->t_name); + return (1); + } + + if (auth_group) { + tag = auth_group_find(conf, ucl_object_tostring(auth_group)); + if (tag == NULL) { + log_warnx("unknown auth-group \"%s\" for target " + "\"%s\"", ucl_object_tostring(auth_group), + target->t_name); + return (1); + } + } + + tp = port_new(conf, target, tpg); + if (tp == NULL) { + log_warnx("can't link portal-group \"%s\" to target " + "\"%s\"", ucl_object_tostring(portal_group), target->t_name); + return (1); + } + tp->p_auth_group = tag; + + return (0); +} + +static int +uclparse_target_lun(struct target *target, const ucl_object_t *obj) +{ + struct lun *lun; + + if (obj->type == UCL_INT) { + char *name; + + asprintf(&name, "%s,lun,%ju", target->t_name, + ucl_object_toint(obj)); + lun = lun_new(conf, name); + if (lun == NULL) + return (1); + + lun_set_scsiname(lun, name); + target->t_luns[ucl_object_toint(obj)] = lun; + return (0); + } + + if (obj->type == UCL_OBJECT) { + const ucl_object_t *num = ucl_object_find_key(obj, "number"); + const ucl_object_t *name = ucl_object_find_key(obj, "name"); + + if (num == NULL || num->type != UCL_INT) { + log_warnx("lun section in target \"%s\" is missing " + "\"number\" integer property", target->t_name); + return (1); + } + + if (name == NULL || name->type != UCL_STRING) { + log_warnx("lun section in target \"%s\" is missing " + "\"name\" string property", target->t_name); + return (1); + } + + lun = lun_find(conf, ucl_object_tostring(name)); + if (lun == NULL) + return (1); + + target->t_luns[ucl_object_toint(num)] = lun; + } + + return (0); +} + +static int +uclparse_toplevel(const ucl_object_t *top) +{ + ucl_object_iter_t it = NULL, iter = NULL; + const ucl_object_t *obj = NULL, *child = NULL; + int err = 0; + + /* Pass 1 - everything except targets */ + while ((obj = ucl_iterate_object(top, &it, true))) { + const char *key = ucl_object_key(obj); + + if (!strcmp(key, "debug")) { + if (obj->type == UCL_INT) + conf->conf_debug = ucl_object_toint(obj); + else { + log_warnx("\"debug\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "timeout")) { + if (obj->type == UCL_INT) + conf->conf_timeout = ucl_object_toint(obj); + else { + log_warnx("\"timeout\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "maxproc")) { + if (obj->type == UCL_INT) + conf->conf_maxproc = ucl_object_toint(obj); + else { + log_warnx("\"maxproc\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "pidfile")) { + if (obj->type == UCL_STRING) + conf->conf_pidfile_path = strdup( + ucl_object_tostring(obj)); + else { + log_warnx("\"pidfile\" property value is not string"); + return (1); + } + } + + if (!strcmp(key, "isns-server")) { + if (obj->type == UCL_ARRAY) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, + true))) { + if (child->type != UCL_STRING) + return (1); + + err = isns_new(conf, + ucl_object_tostring(child)); + if (err != 0) { + return (1); + } + } + } else { + log_warnx("\"isns-server\" property value is " + "not an array"); + return (1); + } + } + + if (!strcmp(key, "isns-period")) { + if (obj->type == UCL_INT) + conf->conf_timeout = ucl_object_toint(obj); + else { + log_warnx("\"isns-period\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "isns-timeout")) { + if (obj->type == UCL_INT) + conf->conf_timeout = ucl_object_toint(obj); + else { + log_warnx("\"isns-timeout\" property value is not integer"); + return (1); + } + } + + if (!strcmp(key, "auth-group")) { + if (obj->type == UCL_OBJECT) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, true))) { + uclparse_auth_group(ucl_object_key(child), child); + } + } else { + log_warnx("\"auth-group\" section is not an object"); + return (1); + } + } + + if (!strcmp(key, "portal-group")) { + if (obj->type == UCL_OBJECT) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, true))) { + uclparse_portal_group(ucl_object_key(child), child); + } + } else { + log_warnx("\"portal-group\" section is not an object"); + return (1); + } + } + + if (!strcmp(key, "lun")) { + if (obj->type == UCL_OBJECT) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, true))) { + uclparse_lun(ucl_object_key(child), child); + } + } else { + log_warnx("\"lun\" section is not an object"); + return (1); + } + } + } + + /* Pass 2 - targets */ + it = NULL; + while ((obj = ucl_iterate_object(top, &it, true))) { + const char *key = ucl_object_key(obj); + + if (!strcmp(key, "target")) { + if (obj->type == UCL_OBJECT) { + iter = NULL; + while ((child = ucl_iterate_object(obj, &iter, + true))) { + uclparse_target(ucl_object_key(child), + child); + } + } else { + log_warnx("\"target\" section is not an object"); + return (1); + } + } + } + + return (0); +} + +static int +uclparse_auth_group(const char *name, const ucl_object_t *top) +{ + struct auth_group *auth_group; + const struct auth_name *an; + const struct auth_portal *ap; + ucl_object_iter_t it = NULL, it2 = NULL; + const ucl_object_t *obj = NULL, *tmp = NULL; + const char *key; + int err; + + if (!strcmp(name, "default") && + conf->conf_default_ag_defined == false) { + auth_group = auth_group_find(conf, name); + conf->conf_default_ag_defined = true; + } else { + auth_group = auth_group_new(conf, name); + } + + if (auth_group == NULL) + return (1); + + while ((obj = ucl_iterate_object(top, &it, true))) { + key = ucl_object_key(obj); + + if (!strcmp(key, "auth-type")) { + const char *value = ucl_object_tostring(obj); + + err = auth_group_set_type(auth_group, value); + if (err) + return (1); + } + + if (!strcmp(key, "chap")) { + if (obj->type != UCL_ARRAY) { + log_warnx("\"chap\" property of " + "auth-group \"%s\" is not an array", + name); + return (1); + } + + it2 = NULL; + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + if (uclparse_chap(auth_group, tmp) != 0) + return (1); + } + } + + if (!strcmp(key, "chap-mutual")) { + if (obj->type != UCL_ARRAY) { + log_warnx("\"chap-mutual\" property of " + "auth-group \"%s\" is not an array", + name); + return (1); + } + + it2 = NULL; + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + if (uclparse_chap_mutual(auth_group, tmp) != 0) + return (1); + } + } + + if (!strcmp(key, "initiator-name")) { + if (obj->type != UCL_ARRAY) { + log_warnx("\"initiator-name\" property of " + "auth-group \"%s\" is not an array", + name); + return (1); + } + + it2 = NULL; + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + const char *value = ucl_object_tostring(tmp); + + an = auth_name_new(auth_group, value); + if (an == NULL) + return (1); + } + } + + if (!strcmp(key, "initiator-portal")) { + if (obj->type != UCL_ARRAY) { + log_warnx("\"initiator-portal\" property of " + "auth-group \"%s\" is not an array", + name); + return (1); + } + + it2 = NULL; + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + const char *value = ucl_object_tostring(tmp); + + ap = auth_portal_new(auth_group, value); + if (ap == NULL) + return (1); + } + } + } + + return (0); +} + +static int +uclparse_portal_group(const char *name, const ucl_object_t *top) +{ + struct portal_group *portal_group; + ucl_object_iter_t it = NULL, it2 = NULL; + const ucl_object_t *obj = NULL, *tmp = NULL; + const char *key; + + if (strcmp(name, "default") == 0 && + conf->conf_default_pg_defined == false) { + portal_group = portal_group_find(conf, name); + conf->conf_default_pg_defined = true; + } else { + portal_group = portal_group_new(conf, name); + } + + if (portal_group == NULL) + return (1); + + while ((obj = ucl_iterate_object(top, &it, true))) { + key = ucl_object_key(obj); + + if (!strcmp(key, "discovery-auth-group")) { + portal_group->pg_discovery_auth_group = + auth_group_find(conf, ucl_object_tostring(obj)); + if (portal_group->pg_discovery_auth_group == NULL) { + log_warnx("unknown discovery-auth-group \"%s\" " + "for portal-group \"%s\"", + ucl_object_tostring(obj), + portal_group->pg_name); + return (1); + } + } + + if (!strcmp(key, "discovery-filter")) { + if (obj->type != UCL_STRING) { + log_warnx("\"discovery-filter\" property of " + "portal-group \"%s\" is not a string", + portal_group->pg_name); + return (1); + } + + if (portal_group_set_filter(portal_group, + ucl_object_tostring(obj)) != 0) + return (1); + } + + if (!strcmp(key, "listen")) { + if (obj->type == UCL_STRING) { + if (portal_group_add_listen(portal_group, + ucl_object_tostring(obj), false) != 0) + return (1); + } else if (obj->type == UCL_ARRAY) { + while ((tmp = ucl_iterate_object(obj, &it2, + true))) { + if (portal_group_add_listen( + portal_group, + ucl_object_tostring(tmp), + false) != 0) + return (1); + } + } else { + log_warnx("\"listen\" property of " + "portal-group \"%s\" is not a string", + portal_group->pg_name); + return (1); + } + } + + if (!strcmp(key, "listen-iser")) { + if (obj->type == UCL_STRING) { + if (portal_group_add_listen(portal_group, + ucl_object_tostring(obj), true) != 0) + return (1); + } else if (obj->type == UCL_ARRAY) { + while ((tmp = ucl_iterate_object(obj, &it2, + true))) { + if (portal_group_add_listen( + portal_group, + ucl_object_tostring(tmp), + true) != 0) + return (1); + } + } else { + log_warnx("\"listen\" property of " + "portal-group \"%s\" is not a string", + portal_group->pg_name); + return (1); + } + } + + if (!strcmp(key, "redirect")) { + if (obj->type != UCL_STRING) { + log_warnx("\"listen\" property of " + "portal-group \"%s\" is not a string", + portal_group->pg_name); + return (1); + } + + if (portal_group_set_redirection(portal_group, + ucl_object_tostring(obj)) != 0) + return (1); + } + + if (!strcmp(key, "options")) { + if (obj->type != UCL_OBJECT) { + log_warnx("\"options\" property of portal group " + "\"%s\" is not an object", portal_group->pg_name); + return (1); + } + + while ((tmp = ucl_iterate_object(obj, &it2, + true))) { + option_new(&portal_group->pg_options, + ucl_object_key(tmp), + ucl_object_tostring_forced(tmp)); + } + } + } + + return (0); +} + +static int +uclparse_target(const char *name, const ucl_object_t *top) +{ + struct target *target; + ucl_object_iter_t it = NULL, it2 = NULL; + const ucl_object_t *obj = NULL, *tmp = NULL; + const char *key; + + target = target_new(conf, name); + + while ((obj = ucl_iterate_object(top, &it, true))) { + key = ucl_object_key(obj); + + if (!strcmp(key, "alias")) { + if (obj->type != UCL_STRING) { + log_warnx("\"alias\" property of target " + "\"%s\" is not a string", target->t_name); + return (1); + } + + target->t_alias = strdup(ucl_object_tostring(obj)); + } + + if (!strcmp(key, "auth-group")) { + if (target->t_auth_group != NULL) { + if (target->t_auth_group->ag_name != NULL) + log_warnx("auth-group for target \"%s\" " + "specified more than once", + target->t_name); + else + log_warnx("cannot use both auth-group " + "and explicit authorisations for " + "target \"%s\"", target->t_name); + return (1); + } + target->t_auth_group = auth_group_find(conf, + ucl_object_tostring(obj)); + if (target->t_auth_group == NULL) { + log_warnx("unknown auth-group \"%s\" for target " + "\"%s\"", ucl_object_tostring(obj), + target->t_name); + return (1); + } + } + + if (!strcmp(key, "auth-type")) { + int error; + + if (target->t_auth_group != NULL) { + if (target->t_auth_group->ag_name != NULL) { + log_warnx("cannot use both auth-group and " + "auth-type for target \"%s\"", + target->t_name); + return (1); + } + } else { + target->t_auth_group = auth_group_new(conf, NULL); + if (target->t_auth_group == NULL) + return (1); + + target->t_auth_group->ag_target = target; + } + error = auth_group_set_type(target->t_auth_group, + ucl_object_tostring(obj)); + if (error != 0) + return (1); + } + + if (!strcmp(key, "chap")) { + if (uclparse_chap(target->t_auth_group, obj) != 0) + return (1); + } + + if (!strcmp(key, "chap-mutual")) { + if (uclparse_chap_mutual(target->t_auth_group, obj) != 0) + return (1); + } + + if (!strcmp(key, "initiator-name")) { + const struct auth_name *an; + + if (target->t_auth_group != NULL) { + if (target->t_auth_group->ag_name != NULL) { + log_warnx("cannot use both auth-group and " + "initiator-name for target \"%s\"", + target->t_name); + return (1); + } + } else { + target->t_auth_group = auth_group_new(conf, NULL); + if (target->t_auth_group == NULL) + return (1); + + target->t_auth_group->ag_target = target; + } + an = auth_name_new(target->t_auth_group, + ucl_object_tostring(obj)); + if (an == NULL) + return (1); + } + + if (!strcmp(key, "initiator-portal")) { + const struct auth_portal *ap; + + if (target->t_auth_group != NULL) { + if (target->t_auth_group->ag_name != NULL) { + log_warnx("cannot use both auth-group and " + "initiator-portal for target \"%s\"", + target->t_name); + return (1); + } + } else { + target->t_auth_group = auth_group_new(conf, NULL); + if (target->t_auth_group == NULL) + return (1); + + target->t_auth_group->ag_target = target; + } + ap = auth_portal_new(target->t_auth_group, + ucl_object_tostring(obj)); + if (ap == NULL) + return (1); + } + + if (!strcmp(key, "portal-group")) { + if (obj->type == UCL_OBJECT) { + if (uclparse_target_portal_group(target, obj) != 0) + return (1); + } + + if (obj->type == UCL_ARRAY) { + while ((tmp = ucl_iterate_object(obj, &it2, + true))) { + if (uclparse_target_portal_group(target, + tmp) != 0) + return (1); + } + } + } + + if (!strcmp(key, "port")) { + struct pport *pp; + struct port *tp; + const char *value = ucl_object_tostring(obj); + + pp = pport_find(conf, value); + if (pp == NULL) { + log_warnx("unknown port \"%s\" for target \"%s\"", + value, target->t_name); + return (1); + } + if (!TAILQ_EMPTY(&pp->pp_ports)) { + log_warnx("can't link port \"%s\" to target \"%s\", " + "port already linked to some target", + value, target->t_name); + return (1); + } + tp = port_new_pp(conf, target, pp); + if (tp == NULL) { + log_warnx("can't link port \"%s\" to target \"%s\"", + value, target->t_name); + return (1); + } + } + + if (!strcmp(key, "redirect")) { + if (obj->type != UCL_STRING) { + log_warnx("\"redirect\" property of target " + "\"%s\" is not a string", target->t_name); + return (1); + } + + if (target_set_redirection(target, + ucl_object_tostring(obj)) != 0) + return (1); + } + + if (!strcmp(key, "lun")) { + while ((tmp = ucl_iterate_object(obj, &it2, true))) { + if (uclparse_target_lun(target, tmp) != 0) + return (1); + } + } + } + + return (0); +} + +static int +uclparse_lun(const char *name, const ucl_object_t *top) +{ + struct lun *lun; + ucl_object_iter_t it = NULL, child_it = NULL; + const ucl_object_t *obj = NULL, *child = NULL; + const char *key; + + lun = lun_new(conf, name); + + while ((obj = ucl_iterate_object(top, &it, true))) { + key = ucl_object_key(obj); + + if (!strcmp(key, "backend")) { + if (obj->type != UCL_STRING) { + log_warnx("\"backend\" property of lun " + "\"%s\" is not a string", + lun->l_name); + return (1); + } + + lun_set_backend(lun, ucl_object_tostring(obj)); + } + + if (!strcmp(key, "blocksize")) { + if (obj->type != UCL_INT) { + log_warnx("\"blocksize\" property of lun " + "\"%s\" is not an integer", lun->l_name); + return (1); + } + + lun_set_blocksize(lun, ucl_object_toint(obj)); + } + + if (!strcmp(key, "device-id")) { + if (obj->type != UCL_STRING) { + log_warnx("\"device-id\" property of lun " + "\"%s\" is not an integer", lun->l_name); + return (1); + } + + lun_set_device_id(lun, ucl_object_tostring(obj)); + } + + if (!strcmp(key, "options")) { + if (obj->type != UCL_OBJECT) { + log_warnx("\"options\" property of lun " + "\"%s\" is not an object", lun->l_name); + return (1); + } + + while ((child = ucl_iterate_object(obj, &child_it, + true))) { + option_new(&lun->l_options, + ucl_object_key(child), + ucl_object_tostring_forced(child)); + } + } + + if (!strcmp(key, "path")) { + if (obj->type != UCL_STRING) { + log_warnx("\"path\" property of lun " + "\"%s\" is not a string", lun->l_name); + return (1); + } + + lun_set_path(lun, ucl_object_tostring(obj)); + } + + if (!strcmp(key, "serial")) { + if (obj->type != UCL_STRING) { + log_warnx("\"serial\" property of lun " + "\"%s\" is not a string", lun->l_name); + return (1); + } + + lun_set_serial(lun, ucl_object_tostring(obj)); + } + + if (!strcmp(key, "size")) { + if (obj->type != UCL_INT) { + log_warnx("\"size\" property of lun " + "\"%s\" is not an integer", lun->l_name); + return (1); + } + + lun_set_size(lun, ucl_object_toint(obj)); + } + } + + return (0); +} + +int +uclparse_conf(struct conf *newconf, const char *path) +{ + struct ucl_parser *parser; + int error; + + conf = newconf; + parser = ucl_parser_new(0); + ucl_parser_add_file(parser, path); + + if (ucl_parser_get_error(parser)) { + log_warn("unable to parse configuration file %s: %s", path, + ucl_parser_get_error(parser)); + return (1); + } + + error = uclparse_toplevel(ucl_parser_get_object(parser)); + + return (error); +} diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh index cce2af5..feb8db6 100644 --- a/usr.sbin/freebsd-update/freebsd-update.sh +++ b/usr.sbin/freebsd-update/freebsd-update.sh @@ -45,7 +45,7 @@ Options: (default: /etc/freebsd-update.conf) -F -- Force a fetch operation to proceed -k KEY -- Trust an RSA key with SHA256 hash of KEY - -r release -- Target for upgrade (e.g., 6.2-RELEASE) + -r release -- Target for upgrade (e.g., 11.1-RELEASE) -s server -- Server from which to fetch updates (default: update.FreeBSD.org) -t address -- Mail output of cron command, if any, to address |