From owner-svn-src-stable-7@FreeBSD.ORG Mon Aug 31 00:52:10 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DD2EE106568B; Mon, 31 Aug 2009 00:52:10 +0000 (UTC) (envelope-from mlaier@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id CB4AF8FC17; Mon, 31 Aug 2009 00:52:10 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n7V0qApB011359; Mon, 31 Aug 2009 00:52:10 GMT (envelope-from mlaier@svn.freebsd.org) Received: (from mlaier@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n7V0qA6P011357; Mon, 31 Aug 2009 00:52:10 GMT (envelope-from mlaier@svn.freebsd.org) Message-Id: <200908310052.n7V0qA6P011357@svn.freebsd.org> From: Max Laier Date: Mon, 31 Aug 2009 00:52:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196680 - in stable/7/sys: . contrib/pf contrib/pf/net X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Aug 2009 00:52:11 -0000 Author: mlaier Date: Mon Aug 31 00:52:10 2009 New Revision: 196680 URL: http://svn.freebsd.org/changeset/base/196680 Log: MFC r196551: Fix argument ordering to memcpy as well as the size of the copy in the (theoretical) case that pfi_buffer_cnt should be greater than ~_max. Submitted by: pjd Reviewed by: {krw,sthen,markus}@openbsd.org Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/contrib/pf/net/pf_if.c Modified: stable/7/sys/contrib/pf/net/pf_if.c ============================================================================== --- stable/7/sys/contrib/pf/net/pf_if.c Mon Aug 31 00:18:17 2009 (r196679) +++ stable/7/sys/contrib/pf/net/pf_if.c Mon Aug 31 00:52:10 2009 (r196680) @@ -660,7 +660,7 @@ pfi_address_add(struct sockaddr *sa, int "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX); return; } - memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer)); + memcpy(p, pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer)); /* no need to zero buffer */ free(pfi_buffer, PFI_MTYPE); pfi_buffer = p; From owner-svn-src-stable-7@FreeBSD.ORG Mon Aug 31 00:54:14 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E46A7106566C; Mon, 31 Aug 2009 00:54:14 +0000 (UTC) (envelope-from mlaier@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D29478FC13; Mon, 31 Aug 2009 00:54:14 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n7V0sEkg011437; Mon, 31 Aug 2009 00:54:14 GMT (envelope-from mlaier@svn.freebsd.org) Received: (from mlaier@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n7V0sEKO011434; Mon, 31 Aug 2009 00:54:14 GMT (envelope-from mlaier@svn.freebsd.org) Message-Id: <200908310054.n7V0sEKO011434@svn.freebsd.org> From: Max Laier Date: Mon, 31 Aug 2009 00:54:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196681 - in stable/7/sys: . contrib/pf contrib/pf/net X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Aug 2009 00:54:15 -0000 Author: mlaier Date: Mon Aug 31 00:54:14 2009 New Revision: 196681 URL: http://svn.freebsd.org/changeset/base/196681 Log: MFC r196372: If we cannot immediately get the pf_consistency_lock in the purge thread, restart the scan after acquiring the lock the hard way. Otherwise we might end up with a dead reference. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/contrib/pf/net/pf.c stable/7/sys/contrib/pf/net/pfvar.h Modified: stable/7/sys/contrib/pf/net/pf.c ============================================================================== --- stable/7/sys/contrib/pf/net/pf.c Mon Aug 31 00:52:10 2009 (r196680) +++ stable/7/sys/contrib/pf/net/pf.c Mon Aug 31 00:54:14 2009 (r196681) @@ -972,6 +972,9 @@ void pf_purge_thread(void *v) { int nloops = 0, s; +#ifdef __FreeBSD__ + int locked; +#endif for (;;) { tsleep(pf_purge_thread, PWAIT, "pftm", 1 * hz); @@ -979,14 +982,19 @@ pf_purge_thread(void *v) #ifdef __FreeBSD__ sx_slock(&pf_consistency_lock); PF_LOCK(); + locked = 0; if (pf_end_threads) { - pf_purge_expired_states(pf_status.states); + PF_UNLOCK(); + sx_sunlock(&pf_consistency_lock); + sx_xlock(&pf_consistency_lock); + PF_LOCK(); + pf_purge_expired_states(pf_status.states, 1); pf_purge_expired_fragments(); - pf_purge_expired_src_nodes(0); + pf_purge_expired_src_nodes(1); pf_end_threads++; - sx_sunlock(&pf_consistency_lock); + sx_xunlock(&pf_consistency_lock); PF_UNLOCK(); wakeup(pf_purge_thread); kthread_exit(0); @@ -995,20 +1003,44 @@ pf_purge_thread(void *v) s = splsoftnet(); /* process a fraction of the state table every second */ +#ifdef __FreeBSD__ + if(!pf_purge_expired_states(1 + (pf_status.states + / pf_default_rule.timeout[PFTM_INTERVAL]), 0)) { + PF_UNLOCK(); + sx_sunlock(&pf_consistency_lock); + sx_xlock(&pf_consistency_lock); + PF_LOCK(); + locked = 1; + + pf_purge_expired_states(1 + (pf_status.states + / pf_default_rule.timeout[PFTM_INTERVAL]), 1); + } +#else pf_purge_expired_states(1 + (pf_status.states / pf_default_rule.timeout[PFTM_INTERVAL])); +#endif /* purge other expired types every PFTM_INTERVAL seconds */ if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) { pf_purge_expired_fragments(); - pf_purge_expired_src_nodes(0); + if (!pf_purge_expired_src_nodes(locked)) { + PF_UNLOCK(); + sx_sunlock(&pf_consistency_lock); + sx_xlock(&pf_consistency_lock); + PF_LOCK(); + locked = 1; + pf_purge_expired_src_nodes(1); + } nloops = 0; } splx(s); #ifdef __FreeBSD__ PF_UNLOCK(); - sx_sunlock(&pf_consistency_lock); + if (locked) + sx_xunlock(&pf_consistency_lock); + else + sx_sunlock(&pf_consistency_lock); #endif } } @@ -1057,8 +1089,13 @@ pf_state_expires(const struct pf_state * return (state->expire + timeout); } +#ifdef __FreeBSD__ +int +pf_purge_expired_src_nodes(int waslocked) +#else void pf_purge_expired_src_nodes(int waslocked) +#endif { struct pf_src_node *cur, *next; int locked = waslocked; @@ -1069,12 +1106,8 @@ pf_purge_expired_src_nodes(int waslocked if (cur->states <= 0 && cur->expire <= time_second) { if (! locked) { #ifdef __FreeBSD__ - if (!sx_try_upgrade(&pf_consistency_lock)) { - PF_UNLOCK(); - sx_sunlock(&pf_consistency_lock); - sx_xlock(&pf_consistency_lock); - PF_LOCK(); - } + if (!sx_try_upgrade(&pf_consistency_lock)) + return (0); #else rw_enter_write(&pf_consistency_lock); #endif @@ -1101,6 +1134,10 @@ pf_purge_expired_src_nodes(int waslocked #else rw_exit_write(&pf_consistency_lock); #endif + +#ifdef __FreeBSD__ + return (1); +#endif } void @@ -1203,12 +1240,21 @@ pf_free_state(struct pf_state *cur) pf_status.states--; } +#ifdef __FreeBSD__ +int +pf_purge_expired_states(u_int32_t maxcheck, int waslocked) +#else void pf_purge_expired_states(u_int32_t maxcheck) +#endif { static struct pf_state *cur = NULL; struct pf_state *next; +#ifdef __FreeBSD__ + int locked = waslocked; +#else int locked = 0; +#endif while (maxcheck--) { /* wrap to start of list when we hit the end */ @@ -1225,12 +1271,8 @@ pf_purge_expired_states(u_int32_t maxche /* free unlinked state */ if (! locked) { #ifdef __FreeBSD__ - if (!sx_try_upgrade(&pf_consistency_lock)) { - PF_UNLOCK(); - sx_sunlock(&pf_consistency_lock); - sx_xlock(&pf_consistency_lock); - PF_LOCK(); - } + if (!sx_try_upgrade(&pf_consistency_lock)) + return (0); #else rw_enter_write(&pf_consistency_lock); #endif @@ -1242,12 +1284,8 @@ pf_purge_expired_states(u_int32_t maxche pf_unlink_state(cur); if (! locked) { #ifdef __FreeBSD__ - if (!sx_try_upgrade(&pf_consistency_lock)) { - PF_UNLOCK(); - sx_sunlock(&pf_consistency_lock); - sx_xlock(&pf_consistency_lock); - PF_LOCK(); - } + if (!sx_try_upgrade(&pf_consistency_lock)) + return (0); #else rw_enter_write(&pf_consistency_lock); #endif @@ -1258,10 +1296,13 @@ pf_purge_expired_states(u_int32_t maxche cur = next; } - if (locked) #ifdef __FreeBSD__ + if (!waslocked && locked) sx_downgrade(&pf_consistency_lock); + + return (1); #else + if (locked) rw_exit_write(&pf_consistency_lock); #endif } Modified: stable/7/sys/contrib/pf/net/pfvar.h ============================================================================== --- stable/7/sys/contrib/pf/net/pfvar.h Mon Aug 31 00:52:10 2009 (r196680) +++ stable/7/sys/contrib/pf/net/pfvar.h Mon Aug 31 00:54:14 2009 (r196681) @@ -1593,8 +1593,13 @@ extern struct pool pf_state_pl, pf_alt extern struct pool pf_state_scrub_pl; #endif extern void pf_purge_thread(void *); +#ifdef __FreeBSD__ +extern int pf_purge_expired_src_nodes(int); +extern int pf_purge_expired_states(u_int32_t, int); +#else extern void pf_purge_expired_src_nodes(int); extern void pf_purge_expired_states(u_int32_t); +#endif extern void pf_unlink_state(struct pf_state *); extern void pf_free_state(struct pf_state *); extern int pf_insert_state(struct pfi_kif *, From owner-svn-src-stable-7@FreeBSD.ORG Mon Aug 31 02:22:20 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 247D0106568F; Mon, 31 Aug 2009 02:22:20 +0000 (UTC) (envelope-from edwin@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 110458FC0A; Mon, 31 Aug 2009 02:22:20 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n7V2MI5r013283; Mon, 31 Aug 2009 02:22:18 GMT (envelope-from edwin@svn.freebsd.org) Received: (from edwin@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n7V2MISr013278; Mon, 31 Aug 2009 02:22:18 GMT (envelope-from edwin@svn.freebsd.org) Message-Id: <200908310222.n7V2MISr013278@svn.freebsd.org> From: Edwin Groothuis Date: Mon, 31 Aug 2009 02:22:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196683 - in stable/7: lib/libc lib/libc/stdtime usr.sbin/zic X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Aug 2009 02:22:20 -0000 Author: edwin Date: Mon Aug 31 02:22:18 2009 New Revision: 196683 URL: http://svn.freebsd.org/changeset/base/196683 Log: MFC of r192625, r192890, r194783, r196587: r192625: MFC of tzcode2009e: Upgrade of the tzcode from 2004a to 2009e. Changes are numerous, but include... - New format of the output of zic, which supports both 32 and 64 bit time_t formats. - zdump on 64 bit platforms will actually produce some output instead of doing nothing for a looooooooong time. - linux_base-fX, with X >= at least 8, will work without problems related to the local time again. The original patch, based on the 2008e, has been running for a long time on both my laptop and desktop machine and have been tested by other people. After the installation of this code and the running of zic(8), you need to run tzsetup(8) again to install the new datafile. r192890: MFC of tzcode2009h - Clarify the license for the tzcode: public domain r194783: Remove duplicate if-statement on gmt_is_set in gmtsub(). r196587: MFC of tzcode2009k zic.c: Do not end a binary file with a POSIX-style time zone string for locations that end up in permanent DST (thanks to Andreas Schwab). Deleted: stable/7/usr.sbin/zic/Arts.htm stable/7/usr.sbin/zic/tz-art.htm stable/7/usr.sbin/zic/tz-link.htm Modified: stable/7/lib/libc/ (props changed) stable/7/lib/libc/stdtime/asctime.c stable/7/lib/libc/stdtime/difftime.c stable/7/lib/libc/stdtime/localtime.c stable/7/lib/libc/stdtime/private.h stable/7/lib/libc/stdtime/strftime.c stable/7/lib/libc/stdtime/time2posix.3 stable/7/lib/libc/stdtime/tzfile.5 stable/7/lib/libc/stdtime/tzfile.h stable/7/usr.sbin/zic/ (props changed) stable/7/usr.sbin/zic/README stable/7/usr.sbin/zic/Theory stable/7/usr.sbin/zic/ialloc.c stable/7/usr.sbin/zic/private.h stable/7/usr.sbin/zic/scheck.c stable/7/usr.sbin/zic/zdump.8 stable/7/usr.sbin/zic/zdump.c stable/7/usr.sbin/zic/zic.8 stable/7/usr.sbin/zic/zic.c Modified: stable/7/lib/libc/stdtime/asctime.c ============================================================================== --- stable/7/lib/libc/stdtime/asctime.c Mon Aug 31 00:56:06 2009 (r196682) +++ stable/7/lib/libc/stdtime/asctime.c Mon Aug 31 02:22:18 2009 (r196683) @@ -1,12 +1,18 @@ /* ** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. +*/ + +/* +** Avoid the temptation to punt entirely to strftime; +** the output of strftime is supposed to be locale specific +** whereas the output of asctime is supposed to be constant. */ #include #ifndef lint #ifndef NOID -static char elsieid[] __unused = "@(#)asctime.c 7.9"; +static char elsieid[] __unused = "@(#)asctime.c 8.2"; #endif /* !defined NOID */ #endif /* !defined lint */ __FBSDID("$FreeBSD$"); @@ -19,7 +25,57 @@ __FBSDID("$FreeBSD$"); #include "tzfile.h" /* -** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12. +** Some systems only handle "%.2d"; others only handle "%02d"; +** "%02.2d" makes (most) everybody happy. +** At least some versions of gcc warn about the %02.2d; +** we conditionalize below to avoid the warning. +*/ +/* +** All years associated with 32-bit time_t values are exactly four digits long; +** some years associated with 64-bit time_t values are not. +** Vintage programs are coded for years that are always four digits long +** and may assume that the newline always lands in the same place. +** For years that are less than four digits, we pad the output with +** leading zeroes to get the newline in the traditional place. +** The -4 ensures that we get four characters of output even if +** we call a strftime variant that produces fewer characters for some years. +** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year, +** but many implementations pad anyway; most likely the standards are buggy. +*/ +#ifdef __GNUC__ +#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n" +#else /* !defined __GNUC__ */ +#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n" +#endif /* !defined __GNUC__ */ +/* +** For years that are more than four digits we put extra spaces before the year +** so that code trying to overwrite the newline won't end up overwriting +** a digit within a year and truncating the year (operating on the assumption +** that no output is better than wrong output). +*/ +#ifdef __GNUC__ +#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n" +#else /* !defined __GNUC__ */ +#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n" +#endif /* !defined __GNUC__ */ + +#define STD_ASCTIME_BUF_SIZE 26 +/* +** Big enough for something such as +** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n +** (two three-character abbreviations, five strings denoting integers, +** seven explicit spaces, two explicit colons, a newline, +** and a trailing ASCII nul). +** The values above are for systems where an int is 32 bits and are provided +** as an example; the define below calculates the maximum for the system at +** hand. +*/ +#define MAX_ASCTIME_BUF_SIZE (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1) + +static char buf_asctime[MAX_ASCTIME_BUF_SIZE]; + +/* +** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition. */ char * @@ -36,6 +92,8 @@ char * buf; }; const char * wn; const char * mn; + char year[INT_STRLEN_MAXIMUM(int) + 2]; + char result[MAX_ASCTIME_BUF_SIZE]; if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK) wn = "???"; @@ -44,35 +102,41 @@ char * buf; mn = "???"; else mn = mon_name[timeptr->tm_mon]; /* - ** The X3J11-suggested format is - ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n" - ** Since the .2 in 02.2d is ignored, we drop it. + ** Use strftime's %Y to generate the year, to avoid overflow problems + ** when computing timeptr->tm_year + TM_YEAR_BASE. + ** Assume that strftime is unaffected by other out-of-range members + ** (e.g., timeptr->tm_mday) when processing "%Y". */ - (void) sprintf(buf, "%.3s %.3s%3d %02d:%02d:%02d %d\n", + (void) strftime(year, sizeof year, "%Y", timeptr); + /* + ** We avoid using snprintf since it's not available on all systems. + */ + (void) sprintf(result, + ((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B), wn, mn, timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, - TM_YEAR_BASE + timeptr->tm_year); - return buf; + year); + if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime) { + (void) strcpy(buf, result); + return buf; + } else { +#ifdef EOVERFLOW + errno = EOVERFLOW; +#else /* !defined EOVERFLOW */ + errno = EINVAL; +#endif /* !defined EOVERFLOW */ + return NULL; + } } /* -** A la X3J11, with core dump avoidance. +** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition. */ char * asctime(timeptr) const struct tm * timeptr; { - /* - ** Big enough for something such as - ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n - ** (two three-character abbreviations, five strings denoting integers, - ** three explicit spaces, two explicit colons, a newline, - ** and a trailing ASCII nul). - */ - static char result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) + - 3 + 2 + 1 + 1]; - - return asctime_r(timeptr, result); + return asctime_r(timeptr, buf_asctime); } Modified: stable/7/lib/libc/stdtime/difftime.c ============================================================================== --- stable/7/lib/libc/stdtime/difftime.c Mon Aug 31 00:56:06 2009 (r196682) +++ stable/7/lib/libc/stdtime/difftime.c Mon Aug 31 02:22:18 2009 (r196683) @@ -1,12 +1,12 @@ /* ** This file is in the public domain, so clarified as of -** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. */ #include #ifndef lint #ifndef NOID -static char elsieid[] __unused = "@(#)difftime.c 7.9"; +static char elsieid[] __unused = "@(#)difftime.c 8.1"; #endif /* !defined NOID */ #endif /* !defined lint */ __FBSDID("$FreeBSD$"); @@ -14,74 +14,56 @@ __FBSDID("$FreeBSD$"); /*LINTLIBRARY*/ #include "namespace.h" -#include "private.h" +#include "private.h" /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */ #include "un-namespace.h" -/* -** Algorithm courtesy Paul Eggert (eggert@twinsun.com). -*/ - -#ifdef HAVE_LONG_DOUBLE -#define long_double long double -#endif /* defined HAVE_LONG_DOUBLE */ -#ifndef HAVE_LONG_DOUBLE -#define long_double double -#endif /* !defined HAVE_LONG_DOUBLE */ - double difftime(time1, time0) const time_t time1; const time_t time0; { - time_t delta; - time_t hibit; - - { - time_t tt; - double d; - long_double ld; - - if (sizeof tt < sizeof d) - return (double) time1 - (double) time0; - if (sizeof tt < sizeof ld) - return (long_double) time1 - (long_double) time0; + /* + ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract + ** (assuming that the larger type has more precision). + ** This is the common real-world case circa 2004. + */ + if (sizeof (double) > sizeof (time_t)) + return (double) time1 - (double) time0; + if (!TYPE_INTEGRAL(time_t)) { + /* + ** time_t is floating. + */ + return time1 - time0; + } + if (!TYPE_SIGNED(time_t)) { + /* + ** time_t is integral and unsigned. + ** The difference of two unsigned values can't overflow + ** if the minuend is greater than or equal to the subtrahend. + */ + if (time1 >= time0) + return time1 - time0; + else return -((double) (time0 - time1)); } - if (time1 < time0) - return -difftime(time0, time1); /* - ** As much as possible, avoid loss of precision - ** by computing the difference before converting to double. + ** time_t is integral and signed. + ** Handle cases where both time1 and time0 have the same sign + ** (meaning that their difference cannot overflow). */ - delta = time1 - time0; - if (delta >= 0) - return delta; + if ((time1 < 0) == (time0 < 0)) + return time1 - time0; /* - ** Repair delta overflow. + ** time1 and time0 have opposite signs. + ** Punt if unsigned long is too narrow. */ - hibit = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1); + if (sizeof (unsigned long) < sizeof (time_t)) + return (double) time1 - (double) time0; /* - ** The following expression rounds twice, which means - ** the result may not be the closest to the true answer. - ** For example, suppose time_t is 64-bit signed int, - ** long_double is IEEE 754 double with default rounding, - ** time1 = 9223372036854775807 and time0 = -1536. - ** Then the true difference is 9223372036854777343, - ** which rounds to 9223372036854777856 - ** with a total error of 513. - ** But delta overflows to -9223372036854774273, - ** which rounds to -9223372036854774784, and correcting - ** this by subtracting 2 * (long_double) hibit - ** (i.e. by adding 2**64 = 18446744073709551616) - ** yields 9223372036854776832, which - ** rounds to 9223372036854775808 - ** with a total error of 1535 instead. - ** This problem occurs only with very large differences. - ** It's too painful to fix this portably. - ** We are not alone in this problem; - ** some C compilers round twice when converting - ** large unsigned types to small floating types, - ** so if time_t is unsigned the "return delta" above - ** has the same double-rounding problem with those compilers. + ** Stay calm...decent optimizers will eliminate the complexity below. */ - return delta - 2 * (long_double) hibit; + if (time1 >= 0 /* && time0 < 0 */) + return (unsigned long) time1 + + (unsigned long) (-(time0 + 1)) + 1; + return -(double) ((unsigned long) time0 + + (unsigned long) (-(time1 + 1)) + 1); } Modified: stable/7/lib/libc/stdtime/localtime.c ============================================================================== --- stable/7/lib/libc/stdtime/localtime.c Mon Aug 31 00:56:06 2009 (r196682) +++ stable/7/lib/libc/stdtime/localtime.c Mon Aug 31 02:22:18 2009 (r196683) @@ -1,20 +1,19 @@ /* ** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. */ #include #ifndef lint #ifndef NOID -static char elsieid[] __unused = "@(#)localtime.c 7.78"; +static char elsieid[] __unused = "@(#)localtime.c 8.9"; #endif /* !defined NOID */ #endif /* !defined lint */ __FBSDID("$FreeBSD$"); /* -** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu). -** POSIX-style TZ environment variable handling from Guy Harris -** (guy@auspex.com). +** Leap second handling from Bradley White. +** POSIX-style TZ environment variable handling from Guy Harris. */ /*LINTLIBRARY*/ @@ -28,6 +27,20 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "tzfile.h" +#include "float.h" /* for FLT_MAX and DBL_MAX */ + +#ifndef TZ_ABBR_MAX_LEN +#define TZ_ABBR_MAX_LEN 16 +#endif /* !defined TZ_ABBR_MAX_LEN */ + +#ifndef TZ_ABBR_CHAR_SET +#define TZ_ABBR_CHAR_SET \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" +#endif /* !defined TZ_ABBR_CHAR_SET */ + +#ifndef TZ_ABBR_ERR_CHAR +#define TZ_ABBR_ERR_CHAR '_' +#endif /* !defined TZ_ABBR_ERR_CHAR */ #include "libc_private.h" @@ -74,16 +87,16 @@ __FBSDID("$FreeBSD$"); ** 5. They might reference tm.TM_ZONE after calling offtime. ** What's best to do in the above cases is open to debate; ** for now, we just set things up so that in any of the five cases -** WILDABBR is used. Another possibility: initialize tzname[0] to the +** WILDABBR is used. Another possibility: initialize tzname[0] to the ** string "tzname[0] used before set", and similarly for the other cases. -** And another: initialize tzname[0] to "ERA", with an explanation in the +** And another: initialize tzname[0] to "ERA", with an explanation in the ** manual page of what this "time zone abbreviation" means (doing this so ** that tzname[0] has the "normal" length of three characters). */ #define WILDABBR " " #endif /* !defined WILDABBR */ -static char wildabbr[] = "WILDABBR"; +static char wildabbr[] = WILDABBR; /* * In June 2004 it was decided UTC was a more appropriate default time @@ -130,6 +143,8 @@ struct state { int timecnt; int typecnt; int charcnt; + int goback; + int goahead; time_t ats[TZ_MAX_TIMES]; unsigned char types[TZ_MAX_TIMES]; struct ttinfo ttis[TZ_MAX_TYPES]; @@ -155,40 +170,49 @@ struct rule { */ static long detzcode(const char * codep); +static time_t detzcode64(const char * codep); +static int differ_by_repeat(time_t t1, time_t t0); static const char * getzname(const char * strp); +static const char * getqzname(const char * strp, const int delim); static const char * getnum(const char * strp, int * nump, int min, int max); static const char * getsecs(const char * strp, long * secsp); static const char * getoffset(const char * strp, long * offsetp); static const char * getrule(const char * strp, struct rule * rulep); static void gmtload(struct state * sp); -static void gmtsub(const time_t * timep, long offset, +static struct tm * gmtsub(const time_t * timep, long offset, struct tm * tmp); -static void localsub(const time_t * timep, long offset, +static struct tm * localsub(const time_t * timep, long offset, struct tm * tmp); static int increment_overflow(int * number, int delta); +static int leaps_thru_end_of(int y); +static int long_increment_overflow(long * number, int delta); +static int long_normalize_overflow(long * tensptr, + int * unitsptr, int base); static int normalize_overflow(int * tensptr, int * unitsptr, int base); static void settzname(void); static time_t time1(struct tm * tmp, - void(*funcp) (const time_t *, + struct tm * (*funcp)(const time_t *, long, struct tm *), long offset); static time_t time2(struct tm *tmp, - void(*funcp) (const time_t *, + struct tm * (*funcp)(const time_t *, long, struct tm*), long offset, int * okayp); static time_t time2sub(struct tm *tmp, - void(*funcp) (const time_t *, + struct tm * (*funcp)(const time_t *, long, struct tm*), long offset, int * okayp, int do_norm_secs); -static void timesub(const time_t * timep, long offset, +static struct tm * timesub(const time_t * timep, long offset, const struct state * sp, struct tm * tmp); static int tmcomp(const struct tm * atmp, const struct tm * btmp); static time_t transtime(time_t janfirst, int year, const struct rule * rulep, long offset); -static int tzload(const char * name, struct state * sp); +static int typesequiv(const struct state * sp, int a, int b); +static int tzload(const char * name, struct state * sp, + int doextend); static int tzparse(const char * name, struct state * sp, int lastditch); @@ -224,7 +248,7 @@ char * tzname[2] = { ** Except for the strftime function, these functions [asctime, ** ctime, gmtime, localtime] return values in one of two static ** objects: a broken-down time structure and an array of char. -** Thanks to Paul Eggert (eggert@twinsun.com) for noting this. +** Thanks to Paul Eggert for noting this. */ static struct tm tm; @@ -245,12 +269,25 @@ const char * const codep; long result; int i; - result = (codep[0] & 0x80) ? ~0L : 0L; + result = (codep[0] & 0x80) ? ~0L : 0; for (i = 0; i < 4; ++i) result = (result << 8) | (codep[i] & 0xff); return result; } +static time_t +detzcode64(codep) +const char * const codep; +{ + register time_t result; + register int i; + + result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; + for (i = 0; i < 8; ++i) + result = result * 256 + (codep[i] & 0xff); + return result; +} + static void settzname(void) { @@ -299,16 +336,58 @@ settzname(void) tzname[ttisp->tt_isdst] = &sp->chars[ttisp->tt_abbrind]; } + /* + ** Finally, scrub the abbreviations. + ** First, replace bogus characters. + */ + for (i = 0; i < sp->charcnt; ++i) + if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL) + sp->chars[i] = TZ_ABBR_ERR_CHAR; + /* + ** Second, truncate long abbreviations. + */ + for (i = 0; i < sp->typecnt; ++i) { + register const struct ttinfo * const ttisp = &sp->ttis[i]; + register char * cp = &sp->chars[ttisp->tt_abbrind]; + + if (strlen(cp) > TZ_ABBR_MAX_LEN && + strcmp(cp, GRANDPARENTED) != 0) + *(cp + TZ_ABBR_MAX_LEN) = '\0'; + } +} + +static int +differ_by_repeat(t1, t0) +const time_t t1; +const time_t t0; +{ + int_fast64_t _t0 = t0; + int_fast64_t _t1 = t1; + + if (TYPE_INTEGRAL(time_t) && + TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) + return 0; + //turn ((int_fast64_t)(t1 - t0) == SECSPERREPEAT); + return _t1 - _t0 == SECSPERREPEAT; } static int -tzload(name, sp) +tzload(name, sp, doextend) const char * name; struct state * const sp; +register const int doextend; { const char * p; int i; int fid; + int stored; + int nread; + union { + struct tzhead tzhead; + char buf[2 * sizeof(struct tzhead) + + 2 * sizeof *sp + + 4 * TZ_MAX_TIMES]; + } u; /* XXX The following is from OpenBSD, and I'm not sure it is correct */ if (name != NULL && issetugid() != 0) @@ -356,18 +435,13 @@ struct state * const sp; return -1; } } - { - struct tzhead * tzhp; - union { - struct tzhead tzhead; - char buf[sizeof *sp + sizeof *tzhp]; - } u; + nread = _read(fid, u.buf, sizeof u.buf); + if (_close(fid) < 0 || nread <= 0) + return -1; + for (stored = 4; stored <= 8; stored *= 2) { int ttisstdcnt; int ttisgmtcnt; - i = _read(fid, u.buf, sizeof u.buf); - if (_close(fid) != 0) - return -1; ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); @@ -382,17 +456,19 @@ struct state * const sp; (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) return -1; - if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */ + if (nread - (p - u.buf) < + sp->timecnt * stored + /* ats */ sp->timecnt + /* types */ - sp->typecnt * (4 + 2) + /* ttinfos */ + sp->typecnt * 6 + /* ttinfos */ sp->charcnt + /* chars */ - sp->leapcnt * (4 + 4) + /* lsinfos */ + sp->leapcnt * (stored + 4) + /* lsinfos */ ttisstdcnt + /* ttisstds */ ttisgmtcnt) /* ttisgmts */ return -1; for (i = 0; i < sp->timecnt; ++i) { - sp->ats[i] = detzcode(p); - p += 4; + sp->ats[i] = (stored == 4) ? + detzcode(p) : detzcode64(p); + p += stored; } for (i = 0; i < sp->timecnt; ++i) { sp->types[i] = (unsigned char) *p++; @@ -420,8 +496,9 @@ struct state * const sp; struct lsinfo * lsisp; lsisp = &sp->lsis[i]; - lsisp->ls_trans = detzcode(p); - p += 4; + lsisp->ls_trans = (stored == 4) ? + detzcode(p) : detzcode64(p); + p += stored; lsisp->ls_corr = detzcode(p); p += 4; } @@ -451,10 +528,127 @@ struct state * const sp; return -1; } } + /* + ** Out-of-sort ats should mean we're running on a + ** signed time_t system but using a data file with + ** unsigned values (or vice versa). + */ + for (i = 0; i < sp->timecnt - 2; ++i) + if (sp->ats[i] > sp->ats[i + 1]) { + ++i; + if (TYPE_SIGNED(time_t)) { + /* + ** Ignore the end (easy). + */ + sp->timecnt = i; + } else { + /* + ** Ignore the beginning (harder). + */ + register int j; + + for (j = 0; j + i < sp->timecnt; ++j) { + sp->ats[j] = sp->ats[j + i]; + sp->types[j] = sp->types[j + i]; + } + sp->timecnt = j; + } + break; + } + /* + ** If this is an old file, we're done. + */ + if (u.tzhead.tzh_version[0] == '\0') + break; + nread -= p - u.buf; + for (i = 0; i < nread; ++i) + u.buf[i] = p[i]; + /* + ** If this is a narrow integer time_t system, we're done. + */ + if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) + break; + } + if (doextend && nread > 2 && + u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && + sp->typecnt + 2 <= TZ_MAX_TYPES) { + struct state ts; + register int result; + + u.buf[nread - 1] = '\0'; + result = tzparse(&u.buf[1], &ts, FALSE); + if (result == 0 && ts.typecnt == 2 && + sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { + for (i = 0; i < 2; ++i) + ts.ttis[i].tt_abbrind += + sp->charcnt; + for (i = 0; i < ts.charcnt; ++i) + sp->chars[sp->charcnt++] = + ts.chars[i]; + i = 0; + while (i < ts.timecnt && + ts.ats[i] <= + sp->ats[sp->timecnt - 1]) + ++i; + while (i < ts.timecnt && + sp->timecnt < TZ_MAX_TIMES) { + sp->ats[sp->timecnt] = + ts.ats[i]; + sp->types[sp->timecnt] = + sp->typecnt + + ts.types[i]; + ++sp->timecnt; + ++i; + } + sp->ttis[sp->typecnt++] = ts.ttis[0]; + sp->ttis[sp->typecnt++] = ts.ttis[1]; + } + } + sp->goback = sp->goahead = FALSE; + if (sp->timecnt > 1) { + for (i = 1; i < sp->timecnt; ++i) + if (typesequiv(sp, sp->types[i], sp->types[0]) && + differ_by_repeat(sp->ats[i], sp->ats[0])) { + sp->goback = TRUE; + break; + } + for (i = sp->timecnt - 2; i >= 0; --i) + if (typesequiv(sp, sp->types[sp->timecnt - 1], + sp->types[i]) && + differ_by_repeat(sp->ats[sp->timecnt - 1], + sp->ats[i])) { + sp->goahead = TRUE; + break; + } } return 0; } +static int +typesequiv(sp, a, b) +const struct state * const sp; +const int a; +const int b; +{ + register int result; + + if (sp == NULL || + a < 0 || a >= sp->typecnt || + b < 0 || b >= sp->typecnt) + result = FALSE; + else { + register const struct ttinfo * ap = &sp->ttis[a]; + register const struct ttinfo * bp = &sp->ttis[b]; + result = ap->tt_gmtoff == bp->tt_gmtoff && + ap->tt_isdst == bp->tt_isdst && + ap->tt_ttisstd == bp->tt_ttisstd && + ap->tt_ttisgmt == bp->tt_ttisgmt && + strcmp(&sp->chars[ap->tt_abbrind], + &sp->chars[bp->tt_abbrind]) == 0; + } + return result; +} + static const int mon_lengths[2][MONSPERYEAR] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } @@ -466,7 +660,7 @@ static const int year_lengths[2] = { /* ** Given a pointer into a time zone string, scan until a character that is not -** a valid character in a zone name is found. Return a pointer to that +** a valid character in a zone name is found. Return a pointer to that ** character. */ @@ -483,6 +677,25 @@ const char * strp; } /* +** Given a pointer into an extended time zone string, scan until the ending +** delimiter of the zone name is located. Return a pointer to the delimiter. +** +** As with getzname above, the legal character set is actually quite +** restricted, with other characters producing undefined results. +** We don't do any checking here; checking is done later in common-case code. +*/ + +static const char * +getqzname(register const char *strp, const int delim) +{ + register int c; + + while ((c = *strp) != '\0' && c != delim) + ++strp; + return strp; +} + +/* ** Given a pointer into a time zone string, extract a number from that string. ** Check that the number is within a specified range; if it is not, return ** NULL. @@ -547,7 +760,7 @@ long * const secsp; *secsp += num * SECSPERMIN; if (*strp == ':') { ++strp; - /* `SECSPERMIN' allows for leap seconds. */ + /* `SECSPERMIN' allows for leap seconds. */ strp = getnum(strp, &num, 0, SECSPERMIN); if (strp == NULL) return NULL; @@ -586,7 +799,7 @@ long * const offsetp; /* ** Given a pointer into a time zone string, extract a rule in the form -** date[/time]. See POSIX section 8 for the format of "date" and "time". +** date[/time]. See POSIX section 8 for the format of "date" and "time". ** If a valid rule is not found, return NULL. ** Otherwise, return a pointer to the first character not part of the rule. */ @@ -705,7 +918,7 @@ const long offset; dow += DAYSPERWEEK; /* - ** "dow" is the day-of-week of the first day of the month. Get + ** "dow" is the day-of-week of the first day of the month. Get ** the day-of-month (zero-origin) of the first "dow" day of the ** month. */ @@ -728,7 +941,7 @@ const long offset; /* ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in - ** question. To get the Epoch-relative time of the specified local + ** question. To get the Epoch-relative time of the specified local ** time on that day, add the transition time and the current offset ** from UTC. */ @@ -766,10 +979,18 @@ const int lastditch; stdlen = (sizeof sp->chars) - 1; stdoffset = 0; } else { - name = getzname(name); - stdlen = name - stdname; - if (stdlen < 3) - return -1; + if (*name == '<') { + name++; + stdname = name; + name = getqzname(name, '>'); + if (*name != '>') + return (-1); + stdlen = name - stdname; + name++; + } else { + name = getzname(name); + stdlen = name - stdname; + } if (*name == '\0') return -1; /* was "stdoffset = 0;" */ else { @@ -778,15 +999,22 @@ const int lastditch; return -1; } } - load_result = tzload(TZDEFRULES, sp); + load_result = tzload(TZDEFRULES, sp, FALSE); if (load_result != 0) sp->leapcnt = 0; /* so, we're off a little */ if (*name != '\0') { - dstname = name; - name = getzname(name); - dstlen = name - dstname; /* length of DST zone name */ - if (dstlen < 3) - return -1; + if (*name == '<') { + dstname = ++name; + name = getqzname(name, '>'); + if (*name != '>') + return -1; + dstlen = name - dstname; + name++; + } else { + dstname = name; + name = getzname(name); + dstlen = name - dstname; /* length of DST zone name */ + } if (*name != '\0' && *name != ',' && *name != ';') { name = getoffset(name, &dstoffset); if (name == NULL) @@ -813,11 +1041,8 @@ const int lastditch; return -1; sp->typecnt = 2; /* standard time and DST */ /* - ** Two transitions per year, from EPOCH_YEAR to 2037. + ** Two transitions per year, from EPOCH_YEAR forward. */ - sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); - if (sp->timecnt > TZ_MAX_TIMES) - return -1; sp->ttis[0].tt_gmtoff = -dstoffset; sp->ttis[0].tt_isdst = 1; sp->ttis[0].tt_abbrind = stdlen + 1; @@ -827,7 +1052,12 @@ const int lastditch; atp = sp->ats; typep = sp->types; janfirst = 0; - for (year = EPOCH_YEAR; year <= 2037; ++year) { + sp->timecnt = 0; + for (year = EPOCH_YEAR; + sp->timecnt + 2 <= TZ_MAX_TIMES; + ++year) { + time_t newfirst; + starttime = transtime(janfirst, year, &start, stdoffset); endtime = transtime(janfirst, year, &end, @@ -843,8 +1073,13 @@ const int lastditch; *atp++ = endtime; *typep++ = 1; /* DST ends */ } - janfirst += year_lengths[isleap(year)] * + sp->timecnt += 2; + newfirst = janfirst; + newfirst += year_lengths[isleap(year)] * SECSPERDAY; + if (newfirst <= janfirst) + break; + janfirst = newfirst; } } else { long theirstdoffset; @@ -959,7 +1194,7 @@ static void gmtload(sp) struct state * const sp; { - if (tzload(gmt, sp) != 0) + if (tzload(gmt, sp, TRUE) != 0) (void) tzparse(gmt, sp, TRUE); } @@ -990,7 +1225,7 @@ tzsetwall_basic(int rdlocked) } } #endif /* defined ALL_STATE */ - if (tzload((char *) NULL, lclptr) != 0) + if (tzload((char *) NULL, lclptr, TRUE) != 0) gmtload(lclptr); settzname(); _RWLOCK_UNLOCK(&lcl_rwlock); @@ -1053,7 +1288,7 @@ tzset_basic(int rdlocked) lclptr->ttis[0].tt_gmtoff = 0; lclptr->ttis[0].tt_abbrind = 0; (void) strcpy(lclptr->chars, gmt); - } else if (tzload(name, lclptr) != 0) + } else if (tzload(name, lclptr, TRUE) != 0) if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) (void) gmtload(lclptr); settzname(); @@ -1072,14 +1307,14 @@ tzset(void) /* ** The easy way to behave "as if no library function calls" localtime ** is to not call it--so we drop its guts into "localsub", which can be -** freely called. (And no, the PANS doesn't require the above behavior-- +** freely called. (And no, the PANS doesn't require the above behavior-- ** but it *is* desirable.) ** ** The unused offset argument is for the benefit of mktime variants. */ /*ARGSUSED*/ -static void +static struct tm * localsub(timep, offset, tmp) const time_t * const timep; const long offset; @@ -1088,15 +1323,53 @@ struct tm * const tmp; struct state * sp; const struct ttinfo * ttisp; int i; - const time_t t = *timep; + struct tm * result; + const time_t t = *timep; sp = lclptr; #ifdef ALL_STATE - if (sp == NULL) { - gmtsub(timep, offset, tmp); - return; - } + if (sp == NULL) + return gmtsub(timep, offset, tmp); #endif /* defined ALL_STATE */ + if ((sp->goback && t < sp->ats[0]) || + (sp->goahead && t > sp->ats[sp->timecnt - 1])) { + time_t newt = t; + register time_t seconds; + register time_t tcycles; + register int_fast64_t icycles; + + if (t < sp->ats[0]) + seconds = sp->ats[0] - t; + else seconds = t - sp->ats[sp->timecnt - 1]; + --seconds; + tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; + ++tcycles; + icycles = tcycles; + if (tcycles - icycles >= 1 || icycles - tcycles >= 1) + return NULL; + seconds = icycles; + seconds *= YEARSPERREPEAT; + seconds *= AVGSECSPERYEAR; + if (t < sp->ats[0]) + newt += seconds; + else newt -= seconds; + if (newt < sp->ats[0] || + newt > sp->ats[sp->timecnt - 1]) + return NULL; /* "cannot happen" */ + result = localsub(&newt, offset, tmp); + if (result == tmp) { + register time_t newy; + + newy = tmp->tm_year; + if (t < sp->ats[0]) + newy -= icycles * YEARSPERREPEAT; + else newy += icycles * YEARSPERREPEAT; + tmp->tm_year = newy; + if (tmp->tm_year != newy) + return NULL; + } + return result; + } if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; while (sp->ttis[i].tt_isdst) @@ -1105,10 +1378,17 @@ struct tm * const tmp; break; } } else { - for (i = 1; i < sp->timecnt; ++i) - if (t < sp->ats[i]) - break; - i = sp->types[i - 1]; + register int lo = 1; + register int hi = sp->timecnt; + + while (lo < hi) { + register int mid = (lo + hi) >> 1; + + if (t < sp->ats[mid]) + hi = mid; + else lo = mid + 1; + } + i = (int) sp->types[lo - 1]; } ttisp = &sp->ttis[i]; /* @@ -1117,12 +1397,13 @@ struct tm * const tmp; ** t += ttisp->tt_gmtoff; ** timesub(&t, 0L, sp, tmp); */ - timesub(&t, ttisp->tt_gmtoff, sp, tmp); + result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); tmp->tm_isdst = ttisp->tt_isdst; tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; #ifdef TM_ZONE tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; #endif /* defined TM_ZONE */ *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-stable-7@FreeBSD.ORG Mon Aug 31 02:45:47 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D321A106566C; Mon, 31 Aug 2009 02:45:47 +0000 (UTC) (envelope-from edwin@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C22048FC1D; Mon, 31 Aug 2009 02:45:47 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n7V2jl0O013839; Mon, 31 Aug 2009 02:45:47 GMT (envelope-from edwin@svn.freebsd.org) Received: (from edwin@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n7V2jliD013837; Mon, 31 Aug 2009 02:45:47 GMT (envelope-from edwin@svn.freebsd.org) Message-Id: <200908310245.n7V2jliD013837@svn.freebsd.org> From: Edwin Groothuis Date: Mon, 31 Aug 2009 02:45:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196684 - stable/7 X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Aug 2009 02:45:47 -0000 Author: edwin Date: Mon Aug 31 02:45:47 2009 New Revision: 196684 URL: http://svn.freebsd.org/changeset/base/196684 Log: MFC of r192625: Throw alert about the newly generated format of zic(8) and the necessarity to run tzsetup(8). Modified: stable/7/UPDATING (contents, props changed) Modified: stable/7/UPDATING ============================================================================== --- stable/7/UPDATING Mon Aug 31 02:22:18 2009 (r196683) +++ stable/7/UPDATING Mon Aug 31 02:45:47 2009 (r196684) @@ -8,6 +8,11 @@ Items affecting the ports and packages s /usr/ports/UPDATING. Please read that file before running portupgrade. +20090831: + The newly imported zic(8) produces a new format in the + output. Please run tzsetup(8) to install the newly created + data to /etc/localtime. + 20090731: The ABI of various structures related to the SYSV IPC API have been changed. Bump __FreeBSD_version to 702105. From owner-svn-src-stable-7@FreeBSD.ORG Mon Aug 31 09:20:37 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E3868106568D; Mon, 31 Aug 2009 09:20:37 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D1EBC8FC1C; Mon, 31 Aug 2009 09:20:37 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n7V9KbQQ022095; Mon, 31 Aug 2009 09:20:37 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n7V9Kb31022093; Mon, 31 Aug 2009 09:20:37 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200908310920.n7V9Kb31022093@svn.freebsd.org> From: Konstantin Belousov Date: Mon, 31 Aug 2009 09:20:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196688 - in stable/7/sys: . contrib/pf kern X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Aug 2009 09:20:38 -0000 Author: kib Date: Mon Aug 31 09:20:37 2009 New Revision: 196688 URL: http://svn.freebsd.org/changeset/base/196688 Log: MFC r196560: Honor the vfs.timestamp_precision sysctl settings for utimes(path, NULL) and similar calls. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/kern/vfs_syscalls.c Modified: stable/7/sys/kern/vfs_syscalls.c ============================================================================== --- stable/7/sys/kern/vfs_syscalls.c Mon Aug 31 09:08:14 2009 (r196687) +++ stable/7/sys/kern/vfs_syscalls.c Mon Aug 31 09:20:37 2009 (r196688) @@ -2843,8 +2843,7 @@ getutimes(usrtvp, tvpseg, tsp) int error; if (usrtvp == NULL) { - microtime(&tv[0]); - TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); + vfs_timestamp(&tsp[0]); tsp[1] = tsp[0]; } else { if (tvpseg == UIO_SYSSPACE) { From owner-svn-src-stable-7@FreeBSD.ORG Mon Aug 31 11:54:14 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1E8451065672; Mon, 31 Aug 2009 11:54:14 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0D9B98FC0C; Mon, 31 Aug 2009 11:54:14 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n7VBsDK3026598; Mon, 31 Aug 2009 11:54:13 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n7VBsDMP026596; Mon, 31 Aug 2009 11:54:13 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200908311154.n7VBsDMP026596@svn.freebsd.org> From: John Baldwin Date: Mon, 31 Aug 2009 11:54:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196693 - stable/7/sys/ufs/ufs X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Aug 2009 11:54:14 -0000 Author: jhb Date: Mon Aug 31 11:54:13 2009 New Revision: 196693 URL: http://svn.freebsd.org/changeset/base/196693 Log: MFC a part of 191990: Fix compile of UFS_EXTATTR without UFS_EXTATTR_AUTOSTART. PR: kern/138350 Modified: stable/7/sys/ufs/ufs/ufs_extattr.c Modified: stable/7/sys/ufs/ufs/ufs_extattr.c ============================================================================== --- stable/7/sys/ufs/ufs/ufs_extattr.c Mon Aug 31 10:20:52 2009 (r196692) +++ stable/7/sys/ufs/ufs/ufs_extattr.c Mon Aug 31 11:54:13 2009 (r196693) @@ -93,8 +93,10 @@ static int ufs_extattr_set(struct vnode struct thread *td); static int ufs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name, struct ucred *cred, struct thread *td); +#ifdef UFS_EXTATTR_AUTOSTART static int ufs_extattr_autostart_locked(struct mount *mp, struct thread *td); +#endif static int ufs_extattr_start_locked(struct ufsmount *ump, struct thread *td); From owner-svn-src-stable-7@FreeBSD.ORG Mon Aug 31 19:07:20 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F36BD106566B; Mon, 31 Aug 2009 19:07:19 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id DF8718FC12; Mon, 31 Aug 2009 19:07:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n7VJ7JHo036302; Mon, 31 Aug 2009 19:07:19 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n7VJ7J9Z036296; Mon, 31 Aug 2009 19:07:19 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200908311907.n7VJ7J9Z036296@svn.freebsd.org> From: John Baldwin Date: Mon, 31 Aug 2009 19:07:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196708 - in stable/7: share/man/man9 sys sys/conf sys/contrib/pf sys/kern sys/sys X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Aug 2009 19:07:20 -0000 Author: jhb Date: Mon Aug 31 19:07:19 2009 New Revision: 196708 URL: http://svn.freebsd.org/changeset/base/196708 Log: MFC 193260 and 196417: Add a simple API to manage scatter/gather lists of phyiscal addresses. Each list describes a logical memory object that is backed by one or more physical address ranges. To minimize locking, the sglist objects themselves are immutable once they are shared. Added: stable/7/share/man/man9/sglist.9 - copied, changed from r193260, head/share/man/man9/sglist.9 stable/7/sys/kern/subr_sglist.c - copied, changed from r193260, head/sys/kern/subr_sglist.c stable/7/sys/sys/sglist.h - copied unchanged from r193260, head/sys/sys/sglist.h Modified: stable/7/share/man/man9/ (props changed) stable/7/share/man/man9/Makefile stable/7/sys/ (props changed) stable/7/sys/conf/files stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/share/man/man9/Makefile ============================================================================== --- stable/7/share/man/man9/Makefile Mon Aug 31 18:41:13 2009 (r196707) +++ stable/7/share/man/man9/Makefile Mon Aug 31 19:07:19 2009 (r196708) @@ -210,6 +210,7 @@ MAN= accept_filter.9 \ selrecord.9 \ sema.9 \ sf_buf.9 \ + sglist.9 \ signal.9 \ sleep.9 \ sleepqueue.9 \ @@ -983,6 +984,24 @@ MLINKS+=sf_buf.9 sf_buf_alloc.9 \ sf_buf.9 sf_buf_free.9 \ sf_buf.9 sf_buf_kva.9 \ sf_buf.9 sf_buf_page.9 +MLINKS+=sglist.9 sglist_alloc.9 \ + sglist.9 sglist_append.9 \ + sglist.9 sglist_append_mbuf.9 \ + sglist.9 sglist_append_phys.9 \ + sglist.9 sglist_append_uio.9 \ + sglist.9 sglist_append_user.9 \ + sglist.9 sglist_build.9 \ + sglist.9 sglist_clone.9 \ + sglist.9 sglist_consume_uio.9 \ + sglist.9 sglist_count.9 \ + sglist.9 sglist_free.9 \ + sglist.9 sglist_hold.9 \ + sglist.9 sglist_init.9 \ + sglist.9 sglist_join.9 \ + sglist.9 sglist_length.9 \ + sglist.9 sglist_reset.9 \ + sglist.9 sglist_slice.9 \ + sglist.9 sglist_split.9 MLINKS+=signal.9 cursig.9 \ signal.9 execsigs.9 \ signal.9 issignal.9 \ Copied and modified: stable/7/share/man/man9/sglist.9 (from r193260, head/share/man/man9/sglist.9) ============================================================================== --- head/share/man/man9/sglist.9 Mon Jun 1 20:35:39 2009 (r193260, copy source) +++ stable/7/share/man/man9/sglist.9 Mon Aug 31 19:07:19 2009 (r196708) @@ -191,6 +191,8 @@ Specifically, the family of routines can be used to append the physical address ranges described by an object to the end of a scatter/gather list. All of these routines return 0 on success or an error on failure. +If a request to append an address range to a scatter/gather list fails, +the scatter/gather list will remain unchanged. .Pp The .Nm sglist_append @@ -445,6 +447,7 @@ There are not enough available segments to append the physical address ranges from .Fa second . .El +.Pp The .Nm sglist_slice function returns the following errors on failure: @@ -470,6 +473,7 @@ list in .Fa *slice to describe the requested physical address ranges. .El +.Pp The .Nm sglist_split function returns the following errors on failure: Modified: stable/7/sys/conf/files ============================================================================== --- stable/7/sys/conf/files Mon Aug 31 18:41:13 2009 (r196707) +++ stable/7/sys/conf/files Mon Aug 31 19:07:19 2009 (r196708) @@ -1630,6 +1630,7 @@ kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_rwlock.c standard +kern/kern_sdt.c optional kdtrace_hooks kern/kern_sema.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard @@ -1683,7 +1684,7 @@ kern/subr_rman.c standard kern/subr_rtc.c optional genclock kern/subr_sbuf.c standard kern/subr_scanf.c standard -kern/kern_sdt.c optional kdtrace_hooks +kern/subr_sglist.c standard kern/subr_sleepqueue.c standard kern/subr_smp.c standard kern/subr_stack.c optional ddb | stack Copied and modified: stable/7/sys/kern/subr_sglist.c (from r193260, head/sys/kern/subr_sglist.c) ============================================================================== --- head/sys/kern/subr_sglist.c Mon Jun 1 20:35:39 2009 (r193260, copy source) +++ stable/7/sys/kern/subr_sglist.c Mon Aug 31 19:07:19 2009 (r196708) @@ -48,6 +48,32 @@ __FBSDID("$FreeBSD$"); static MALLOC_DEFINE(M_SGLIST, "sglist", "scatter/gather lists"); /* + * Convenience macros to save the state of an sglist so it can be restored + * if an append attempt fails. Since sglist's only grow we only need to + * save the current count of segments and the length of the ending segment. + * Earlier segments will not be changed by an append, and the only change + * that can occur to the ending segment is that it can be extended. + */ +struct sgsave { + u_short sg_nseg; + size_t ss_len; +}; + +#define SGLIST_SAVE(sg, sgsave) do { \ + (sgsave).sg_nseg = (sg)->sg_nseg; \ + if ((sgsave).sg_nseg > 0) \ + (sgsave).ss_len = (sg)->sg_segs[(sgsave).sg_nseg - 1].ss_len; \ + else \ + (sgsave).ss_len = 0; \ +} while (0) + +#define SGLIST_RESTORE(sg, sgsave) do { \ + (sg)->sg_nseg = (sgsave).sg_nseg; \ + if ((sgsave).sg_nseg > 0) \ + (sg)->sg_segs[(sgsave).sg_nseg - 1].ss_len = (sgsave).ss_len; \ +} while (0) + +/* * Append a single (paddr, len) to a sglist. sg is the list and ss is * the current segment in the list. If we run out of segments then * EFBIG will be returned. @@ -62,10 +88,8 @@ _sglist_append_range(struct sglist *sg, if (ss->ss_paddr + ss->ss_len == paddr) ss->ss_len += len; else { - if (sg->sg_nseg == sg->sg_maxseg) { - sg->sg_nseg = 0; + if (sg->sg_nseg == sg->sg_maxseg) return (EFBIG); - } ss++; ss->ss_paddr = paddr; ss->ss_len = len; @@ -107,26 +131,33 @@ _sglist_append_buf(struct sglist *sg, vo ss->ss_paddr = paddr; ss->ss_len = seglen; sg->sg_nseg = 1; - error = 0; } else { ss = &sg->sg_segs[sg->sg_nseg - 1]; error = _sglist_append_range(sg, &ss, paddr, seglen); + if (error) + return (error); } + vaddr += seglen; + len -= seglen; + if (donep) + *donep += seglen; - while (error == 0 && len > seglen) { - vaddr += seglen; - len -= seglen; - if (donep) - *donep += seglen; + while (len > 0) { seglen = MIN(len, PAGE_SIZE); if (pmap != NULL) paddr = pmap_extract(pmap, vaddr); else paddr = pmap_kextract(vaddr); error = _sglist_append_range(sg, &ss, paddr, seglen); + if (error) + return (error); + vaddr += seglen; + len -= seglen; + if (donep) + *donep += seglen; } - return (error); + return (0); } /* @@ -195,10 +226,16 @@ sglist_free(struct sglist *sg) int sglist_append(struct sglist *sg, void *buf, size_t len) { + struct sgsave save; + int error; if (sg->sg_maxseg == 0) return (EINVAL); - return (_sglist_append_buf(sg, buf, len, NULL, NULL)); + SGLIST_SAVE(sg, save); + error = _sglist_append_buf(sg, buf, len, NULL, NULL); + if (error) + SGLIST_RESTORE(sg, save); + return (error); } /* @@ -209,6 +246,8 @@ int sglist_append_phys(struct sglist *sg, vm_paddr_t paddr, size_t len) { struct sglist_seg *ss; + struct sgsave save; + int error; if (sg->sg_maxseg == 0) return (EINVAL); @@ -222,7 +261,11 @@ sglist_append_phys(struct sglist *sg, vm return (0); } ss = &sg->sg_segs[sg->sg_nseg - 1]; - return (_sglist_append_range(sg, &ss, paddr, len)); + SGLIST_SAVE(sg, save); + error = _sglist_append_range(sg, &ss, paddr, len); + if (error) + SGLIST_RESTORE(sg, save); + return (error); } /* @@ -233,6 +276,7 @@ sglist_append_phys(struct sglist *sg, vm int sglist_append_mbuf(struct sglist *sg, struct mbuf *m0) { + struct sgsave save; struct mbuf *m; int error; @@ -240,11 +284,14 @@ sglist_append_mbuf(struct sglist *sg, st return (EINVAL); error = 0; + SGLIST_SAVE(sg, save); for (m = m0; m != NULL; m = m->m_next) { if (m->m_len > 0) { error = sglist_append(sg, m->m_data, m->m_len); - if (error) + if (error) { + SGLIST_RESTORE(sg, save); return (error); + } } } return (0); @@ -258,11 +305,17 @@ sglist_append_mbuf(struct sglist *sg, st int sglist_append_user(struct sglist *sg, void *buf, size_t len, struct thread *td) { + struct sgsave save; + int error; if (sg->sg_maxseg == 0) return (EINVAL); - return (_sglist_append_buf(sg, buf, len, - vmspace_pmap(td->td_proc->p_vmspace), NULL)); + SGLIST_SAVE(sg, save); + error = _sglist_append_buf(sg, buf, len, + vmspace_pmap(td->td_proc->p_vmspace), NULL); + if (error) + SGLIST_RESTORE(sg, save); + return (error); } /* @@ -274,6 +327,7 @@ int sglist_append_uio(struct sglist *sg, struct uio *uio) { struct iovec *iov; + struct sgsave save; size_t resid, minlen; pmap_t pmap; int error, i; @@ -292,6 +346,7 @@ sglist_append_uio(struct sglist *sg, str pmap = NULL; error = 0; + SGLIST_SAVE(sg, save); for (i = 0; i < uio->uio_iovcnt && resid != 0; i++) { /* * Now at the first iovec to load. Load each iovec @@ -301,8 +356,10 @@ sglist_append_uio(struct sglist *sg, str if (minlen > 0) { error = _sglist_append_buf(sg, iov[i].iov_base, minlen, pmap, NULL); - if (error) + if (error) { + SGLIST_RESTORE(sg, save); return (error); + } resid -= minlen; } } @@ -397,6 +454,7 @@ sglist_clone(struct sglist *sg, int mfla new = sglist_alloc(sg->sg_maxseg, mflags); if (new == NULL) return (NULL); + new->sg_nseg = sg->sg_nseg; bcopy(sg->sg_segs, new->sg_segs, sizeof(struct sglist_seg) * sg->sg_nseg); return (new); Copied: stable/7/sys/sys/sglist.h (from r193260, head/sys/sys/sglist.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/7/sys/sys/sglist.h Mon Aug 31 19:07:19 2009 (r196708, copy of r193260, head/sys/sys/sglist.h) @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2008 Yahoo!, Inc. + * All rights reserved. + * Written by: John Baldwin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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$ + */ + +/* + * A scatter/gather list describes a group of physical address ranges. + * Each physical address range consists of a starting address and a + * length. + */ + +#ifndef __SGLIST_H__ +#define __SGLIST_H__ + +#include + +struct sglist_seg { + vm_paddr_t ss_paddr; + size_t ss_len; +}; + +struct sglist { + struct sglist_seg *sg_segs; + int sg_refs; + u_short sg_nseg; + u_short sg_maxseg; +}; + +struct mbuf; +struct uio; + +static __inline void +sglist_init(struct sglist *sg, u_short maxsegs, struct sglist_seg *segs) +{ + + sg->sg_segs = segs; + sg->sg_nseg = 0; + sg->sg_maxseg = maxsegs; + refcount_init(&sg->sg_refs, 1); +} + +static __inline void +sglist_reset(struct sglist *sg) +{ + + sg->sg_nseg = 0; +} + +static __inline struct sglist * +sglist_hold(struct sglist *sg) +{ + + refcount_acquire(&sg->sg_refs); + return (sg); +} + +struct sglist *sglist_alloc(int nsegs, int mflags); +int sglist_append(struct sglist *sg, void *buf, size_t len); +int sglist_append_mbuf(struct sglist *sg, struct mbuf *m0); +int sglist_append_phys(struct sglist *sg, vm_paddr_t paddr, + size_t len); +int sglist_append_uio(struct sglist *sg, struct uio *uio); +int sglist_append_user(struct sglist *sg, void *buf, size_t len, + struct thread *td); +struct sglist *sglist_build(void *buf, size_t len, int mflags); +struct sglist *sglist_clone(struct sglist *sg, int mflags); +int sglist_consume_uio(struct sglist *sg, struct uio *uio, int resid); +int sglist_count(void *buf, size_t len); +void sglist_free(struct sglist *sg); +int sglist_join(struct sglist *first, struct sglist *second); +size_t sglist_length(struct sglist *sg); +int sglist_slice(struct sglist *original, struct sglist **slice, + size_t offset, size_t length, int mflags); +int sglist_split(struct sglist *original, struct sglist **head, + size_t length, int mflags); + +#endif /* !__SGLIST_H__ */ From owner-svn-src-stable-7@FreeBSD.ORG Tue Sep 1 16:56:20 2009 Return-Path: Delivered-To: svn-src-stable-7@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 797DF1065679 for ; Tue, 1 Sep 2009 16:56:20 +0000 (UTC) (envelope-from njm@njm.me.uk) Received: from smtp004.apm-internet.net (smtp004.apm-internet.net [85.119.248.54]) by mx1.freebsd.org (Postfix) with SMTP id E1F7E8FC16 for ; Tue, 1 Sep 2009 16:56:19 +0000 (UTC) Received: (qmail 99074 invoked from network); 1 Sep 2009 16:29:39 -0000 Received: from unknown (HELO titania.njm.me.uk) (86.138.89.107) by smtp004.apm-internet.net with SMTP; 1 Sep 2009 16:29:39 -0000 Received: from titania.njm.me.uk (localhost [127.0.0.1]) by titania.njm.me.uk (8.14.3/8.14.3) with ESMTP id n81GTdid002402; Tue, 1 Sep 2009 17:29:39 +0100 (BST) (envelope-from njm@njm.me.uk) Received: (from njm@localhost) by titania.njm.me.uk (8.14.3/8.14.3/Submit) id n81GTdVU002401; Tue, 1 Sep 2009 17:29:39 +0100 (BST) (envelope-from njm@njm.me.uk) Date: Tue, 1 Sep 2009 17:29:39 +0100 From: "N.J. Mann" To: Edwin Groothuis Message-ID: <20090901162939.GA2371@titania.njm.me.uk> Mail-Followup-To: Edwin Groothuis , src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org References: <200908310245.n7V2jliD013837@svn.freebsd.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200908310245.n7V2jliD013837@svn.freebsd.org> X-Operating-System: FreeBSD 7.2-STABLE User-Agent: mutt-NJM (2009-07-16) Cc: svn-src-stable@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org, svn-src-stable-7@FreeBSD.org Subject: Re: svn commit: r196684 - stable/7 X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Sep 2009 16:56:20 -0000 In message <200908310245.n7V2jliD013837@svn.freebsd.org>, Edwin Groothuis (edwin@FreeBSD.org) wrote: > Author: edwin > Date: Mon Aug 31 02:45:47 2009 > New Revision: 196684 > URL: http://svn.freebsd.org/changeset/base/196684 > > Log: > MFC of r192625: > > Throw alert about the newly generated format of zic(8) and the > necessarity to run tzsetup(8). > > Modified: > stable/7/UPDATING (contents, props changed) > > Modified: stable/7/UPDATING > ============================================================================== > --- stable/7/UPDATING Mon Aug 31 02:22:18 2009 (r196683) > +++ stable/7/UPDATING Mon Aug 31 02:45:47 2009 (r196684) > @@ -8,6 +8,11 @@ Items affecting the ports and packages s > /usr/ports/UPDATING. Please read that file before running > portupgrade. > > +20090831: > + The newly imported zic(8) produces a new format in the > + output. Please run tzsetup(8) to install the newly created > + data to /etc/localtime. > + > 20090731: > The ABI of various structures related to the SYSV IPC API have > been changed. Bump __FreeBSD_version to 702105. I have just updated one of my machines that runs 7-STABLE and having done so I followed the above instructions. Having read the instructions I was expecting the new version of /etc/localtime to be different from the old one. However, the new one is identical to the old one. Is this to be expected? Cheers, Nick. -- From owner-svn-src-stable-7@FreeBSD.ORG Thu Sep 3 13:56:19 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 455E6106566C; Thu, 3 Sep 2009 13:56:19 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 326BC8FC19; Thu, 3 Sep 2009 13:56:19 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n83DuJMq034511; Thu, 3 Sep 2009 13:56:19 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n83DuJ7P034506; Thu, 3 Sep 2009 13:56:19 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200909031356.n83DuJ7P034506@svn.freebsd.org> From: John Baldwin Date: Thu, 3 Sep 2009 13:56:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196781 - in stable/7/sys: . amd64/amd64 amd64/include contrib/pf i386/i386 i386/include vm X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Sep 2009 13:56:19 -0000 Author: jhb Date: Thu Sep 3 13:56:18 2009 New Revision: 196781 URL: http://svn.freebsd.org/changeset/base/196781 Log: MFC 180430, 180483, 180485, 180601, 180845, 180871-180873, 181043, 181077, 181151, 181284, 181356, 181456, 189454, 194209, 195416, 195836, 196318, 196705, and 196707: Various fixes and enhancements to the amd64 and i386 pmaps to support PAT. - Extend pmap_demote_pde() to include the ability to instantiate a new page table page where none existed before. - Enhance pmap_change_attr() to fully support large (2/4MB) pages by breaking demoting them to 4KB page mappings when needed. - Enhance pmap_change_attr() to avoid page demotions, cache mode changes, and cache and TLB invalidation when some or all of the specified range is already mapped with the specified cache mode. - Enhance pmap_change_attr() to adjust the direct map automatically when changing the cache mode of a kernel virtual address range. - Fix pmap_object_init_pt() to not assume that the pages of a OBJT_DEVICE object are always physically contiguous. - Correct a critical accounting error in pmap_demote_pde(). Reviewed by: alc Modified: stable/7/sys/ (props changed) stable/7/sys/amd64/amd64/pmap.c stable/7/sys/amd64/include/pmap.h stable/7/sys/contrib/pf/ (props changed) stable/7/sys/i386/i386/pmap.c stable/7/sys/i386/include/pmap.h stable/7/sys/vm/vm_object.c stable/7/sys/vm/vm_object.h Modified: stable/7/sys/amd64/amd64/pmap.c ============================================================================== --- stable/7/sys/amd64/amd64/pmap.c Thu Sep 3 13:54:58 2009 (r196780) +++ stable/7/sys/amd64/amd64/pmap.c Thu Sep 3 13:56:18 2009 (r196781) @@ -220,17 +220,22 @@ static void pmap_pvh_free(struct md_page static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va); +static int pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode); static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); static boolean_t pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot); static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte); +static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte); static void pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); static boolean_t pmap_is_modified_pvh(struct md_page *pvh); +static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode); static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va); +static void pmap_pde_attr(pd_entry_t *pde, int cache_bits); static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); static boolean_t pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot); +static void pmap_pte_attr(pt_entry_t *pte, int cache_bits); static int pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, vm_page_t *free); static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, @@ -461,11 +466,12 @@ create_pagetables(vm_paddr_t *firstaddr) ((pdp_entry_t *)KPDPphys)[i + KPDPI] |= PG_RW | PG_V | PG_U; } - /* Now set up the direct map space using 2MB pages */ + /* Preset PG_M and PG_A because demotion expects it */ for (i = 0; i < NPDEPG * ndmpdp; i++) { ((pd_entry_t *)DMPDphys)[i] = (vm_paddr_t)i << PDRSHIFT; - ((pd_entry_t *)DMPDphys)[i] |= PG_RW | PG_V | PG_PS | PG_G; + ((pd_entry_t *)DMPDphys)[i] |= PG_RW | PG_V | PG_PS | PG_G | + PG_M | PG_A; } /* And the direct map space's PDP */ @@ -1068,7 +1074,7 @@ pmap_kenter(vm_offset_t va, vm_paddr_t p pte_store(pte, pa | PG_RW | PG_V | PG_G); } -PMAP_INLINE void +static __inline void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode) { pt_entry_t *pte; @@ -2192,58 +2198,98 @@ pmap_pv_insert_pde(pmap_t pmap, vm_offse } /* - * Tries to demote a 2MB page mapping. + * Fills a page table page with mappings to consecutive physical pages. + */ +static void +pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte) +{ + pt_entry_t *pte; + + for (pte = firstpte; pte < firstpte + NPTEPG; pte++) { + *pte = newpte; + newpte += PAGE_SIZE; + } +} + +/* + * Tries to demote a 2MB page mapping. If demotion fails, the 2MB page + * mapping is invalidated. */ static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) { pd_entry_t newpde, oldpde; - pt_entry_t *firstpte, newpte, *pte; + pt_entry_t *firstpte, newpte; vm_paddr_t mptepa; vm_page_t free, mpte; PMAP_LOCK_ASSERT(pmap, MA_OWNED); + oldpde = *pde; + KASSERT((oldpde & (PG_PS | PG_V)) == (PG_PS | PG_V), + ("pmap_demote_pde: oldpde is missing PG_PS and/or PG_V")); mpte = pmap_lookup_pt_page(pmap, va); if (mpte != NULL) pmap_remove_pt_page(pmap, mpte); else { - KASSERT((*pde & PG_W) == 0, + KASSERT((oldpde & PG_W) == 0, ("pmap_demote_pde: page table page for a wired mapping" " is missing")); - free = NULL; - pmap_remove_pde(pmap, pde, trunc_2mpage(va), &free); - pmap_invalidate_page(pmap, trunc_2mpage(va)); - pmap_free_zero_pages(free); - CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#lx" - " in pmap %p", va, pmap); - return (FALSE); + + /* + * Invalidate the 2MB page mapping and return "failure" if the + * mapping was never accessed or the allocation of the new + * page table page fails. If the 2MB page mapping belongs to + * the direct map region of the kernel's address space, then + * the page allocation request specifies the highest possible + * priority (VM_ALLOC_INTERRUPT). Otherwise, the priority is + * normal. Page table pages are preallocated for every other + * part of the kernel address space, so the direct map region + * is the only part of the kernel address space that must be + * handled here. + */ + if ((oldpde & PG_A) == 0 || (mpte = vm_page_alloc(NULL, + pmap_pde_pindex(va), (va >= DMAP_MIN_ADDRESS && va < + DMAP_MAX_ADDRESS ? VM_ALLOC_INTERRUPT : VM_ALLOC_NORMAL) | + VM_ALLOC_NOOBJ | VM_ALLOC_WIRED)) == NULL) { + free = NULL; + pmap_remove_pde(pmap, pde, trunc_2mpage(va), &free); + pmap_invalidate_page(pmap, trunc_2mpage(va)); + pmap_free_zero_pages(free); + CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#lx" + " in pmap %p", va, pmap); + return (FALSE); + } + if (va < VM_MAXUSER_ADDRESS) + pmap->pm_stats.resident_count++; } mptepa = VM_PAGE_TO_PHYS(mpte); firstpte = (pt_entry_t *)PHYS_TO_DMAP(mptepa); - oldpde = *pde; newpde = mptepa | PG_M | PG_A | (oldpde & PG_U) | PG_RW | PG_V; - KASSERT((oldpde & (PG_A | PG_V)) == (PG_A | PG_V), - ("pmap_demote_pde: oldpde is missing PG_A and/or PG_V")); + KASSERT((oldpde & PG_A) != 0, + ("pmap_demote_pde: oldpde is missing PG_A")); KASSERT((oldpde & (PG_M | PG_RW)) != PG_RW, ("pmap_demote_pde: oldpde is missing PG_M")); - KASSERT((oldpde & PG_PS) != 0, - ("pmap_demote_pde: oldpde is missing PG_PS")); newpte = oldpde & ~PG_PS; if ((newpte & PG_PDE_PAT) != 0) newpte ^= PG_PDE_PAT | PG_PTE_PAT; /* - * If the mapping has changed attributes, update the page table - * entries. + * If the page table page is new, initialize it. */ + if (mpte->wire_count == 1) { + mpte->wire_count = NPTEPG; + pmap_fill_ptp(firstpte, newpte); + } KASSERT((*firstpte & PG_FRAME) == (newpte & PG_FRAME), ("pmap_demote_pde: firstpte and newpte map different physical" " addresses")); + + /* + * If the mapping has changed attributes, update the page table + * entries. + */ if ((*firstpte & PG_PTE_PROMOTE) != (newpte & PG_PTE_PROMOTE)) - for (pte = firstpte; pte < firstpte + NPTEPG; pte++) { - *pte = newpte; - newpte += PAGE_SIZE; - } + pmap_fill_ptp(firstpte, newpte); /* * Demote the mapping. This pmap is locked. The old PDE has @@ -3310,78 +3356,74 @@ void pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, vm_pindex_t pindex, vm_size_t size) { - vm_offset_t va; + pd_entry_t *pde; + vm_paddr_t pa, ptepa; vm_page_t p, pdpg; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); KASSERT(object->type == OBJT_DEVICE, ("pmap_object_init_pt: non-device object")); - if (((addr & (NBPDR - 1)) == 0) && ((size & (NBPDR - 1)) == 0)) { - vm_page_t m[1]; - pd_entry_t ptepa, *pde; - - PMAP_LOCK(pmap); - pde = pmap_pde(pmap, addr); - if (pde != 0 && (*pde & PG_V) != 0) - goto out; - PMAP_UNLOCK(pmap); -retry: + if ((addr & (NBPDR - 1)) == 0 && (size & (NBPDR - 1)) == 0) { + if (!vm_object_populate(object, pindex, pindex + atop(size))) + return; p = vm_page_lookup(object, pindex); - if (p != NULL) { - if (vm_page_sleep_if_busy(p, FALSE, "init4p")) - goto retry; - } else { - p = vm_page_alloc(object, pindex, VM_ALLOC_NORMAL); - if (p == NULL) - return; - m[0] = p; - - if (vm_pager_get_pages(object, m, 1, 0) != VM_PAGER_OK) { - vm_page_lock_queues(); - vm_page_free(p); - vm_page_unlock_queues(); - return; - } - - p = vm_page_lookup(object, pindex); - vm_page_wakeup(p); - } + KASSERT(p->valid == VM_PAGE_BITS_ALL, + ("pmap_object_init_pt: invalid page %p", p)); + /* + * Abort the mapping if the first page is not physically + * aligned to a 2MB page boundary. + */ ptepa = VM_PAGE_TO_PHYS(p); if (ptepa & (NBPDR - 1)) return; - p->valid = VM_PAGE_BITS_ALL; + /* + * Skip the first page. Abort the mapping if the rest of + * the pages are not physically contiguous. + */ + p = TAILQ_NEXT(p, listq); + for (pa = ptepa + PAGE_SIZE; pa < ptepa + size; + pa += PAGE_SIZE) { + KASSERT(p->valid == VM_PAGE_BITS_ALL, + ("pmap_object_init_pt: invalid page %p", p)); + if (pa != VM_PAGE_TO_PHYS(p)) + return; + p = TAILQ_NEXT(p, listq); + } + /* Map using 2MB pages. */ PMAP_LOCK(pmap); - for (va = addr; va < addr + size; va += NBPDR) { - while ((pdpg = - pmap_allocpde(pmap, va, M_NOWAIT)) == NULL) { - PMAP_UNLOCK(pmap); - vm_page_busy(p); - VM_OBJECT_UNLOCK(object); - VM_WAIT; - VM_OBJECT_LOCK(object); - vm_page_wakeup(p); - PMAP_LOCK(pmap); + for (pa = ptepa; pa < ptepa + size; pa += NBPDR) { + pdpg = pmap_allocpde(pmap, addr, M_NOWAIT); + if (pdpg == NULL) { + /* + * The creation of mappings below is only an + * optimization. If a page directory page + * cannot be allocated without blocking, + * continue on to the next mapping rather than + * blocking. + */ + addr += NBPDR; + continue; } pde = (pd_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pdpg)); - pde = &pde[pmap_pde_index(va)]; + pde = &pde[pmap_pde_index(addr)]; if ((*pde & PG_V) == 0) { - pde_store(pde, ptepa | PG_PS | PG_M | PG_A | + pde_store(pde, pa | PG_PS | PG_M | PG_A | PG_U | PG_RW | PG_V); - pmap->pm_stats.resident_count += - NBPDR / PAGE_SIZE; + pmap->pm_stats.resident_count += NBPDR / + PAGE_SIZE; + pmap_pde_mappings++; } else { + /* Continue on if the PDE is already valid. */ pdpg->wire_count--; KASSERT(pdpg->wire_count > 0, ("pmap_object_init_pt: missing reference " - "to page directory page, va: 0x%lx", va)); + "to page directory page, va: 0x%lx", addr)); } - ptepa += NBPDR; + addr += NBPDR; } - pmap_invalidate_all(pmap); -out: PMAP_UNLOCK(pmap); } } @@ -3739,7 +3781,9 @@ pmap_remove_pages(pmap_t pmap) if ((tpte & PG_PS) != 0) pte = pde; else { - pte = vtopte(pv->pv_va); + pte = (pt_entry_t *)PHYS_TO_DMAP(tpte & + PG_FRAME); + pte = &pte[pmap_pte_index(pv->pv_va)]; tpte = *pte & ~PG_PTE_PAT; } @@ -4160,41 +4204,35 @@ pmap_clear_reference(vm_page_t m) /* Adjust the cache mode for a 4KB page mapped via a PTE. */ static __inline void -pmap_pte_attr(vm_offset_t va, int mode) +pmap_pte_attr(pt_entry_t *pte, int cache_bits) { - pt_entry_t *pte; u_int opte, npte; - pte = vtopte(va); - /* * The cache mode bits are all in the low 32-bits of the * PTE, so we can just spin on updating the low 32-bits. */ do { opte = *(u_int *)pte; - npte = opte & ~(PG_PTE_PAT | PG_NC_PCD | PG_NC_PWT); - npte |= pmap_cache_bits(mode, 0); + npte = opte & ~PG_PTE_CACHE; + npte |= cache_bits; } while (npte != opte && !atomic_cmpset_int((u_int *)pte, opte, npte)); } /* Adjust the cache mode for a 2MB page mapped via a PDE. */ static __inline void -pmap_pde_attr(vm_offset_t va, int mode) +pmap_pde_attr(pd_entry_t *pde, int cache_bits) { - pd_entry_t *pde; u_int opde, npde; - pde = pmap_pde(kernel_pmap, va); - /* * The cache mode bits are all in the low 32-bits of the * PDE, so we can just spin on updating the low 32-bits. */ do { opde = *(u_int *)pde; - npde = opde & ~(PG_PDE_PAT | PG_NC_PCD | PG_NC_PWT); - npde |= pmap_cache_bits(mode, 1); + npde = opde & ~PG_PDE_CACHE; + npde |= cache_bits; } while (npde != opde && !atomic_cmpset_int((u_int *)pde, opde, npde)); } @@ -4210,11 +4248,14 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_ vm_offset_t va, tmpva, offset; /* - * If this fits within the direct map window and use WB caching - * mode, use the direct map. + * If the specified range of physical addresses fits within the direct + * map window, use the direct map. */ - if (pa < dmaplimit && (pa + size) < dmaplimit && mode == PAT_WRITE_BACK) - return ((void *)PHYS_TO_DMAP(pa)); + if (pa < dmaplimit && pa + size < dmaplimit) { + va = PHYS_TO_DMAP(pa); + if (!pmap_change_attr(va, size, mode)) + return ((void *)va); + } offset = pa & PAGE_MASK; size = roundup(offset + size, PAGE_SIZE); va = kmem_alloc_nofault(kernel_map, size); @@ -4263,68 +4304,174 @@ pmap_unmapdev(vm_offset_t va, vm_size_t kmem_free(kernel_map, base, size); } +/* + * Changes the specified virtual address range's memory type to that given by + * the parameter "mode". The specified virtual address range must be + * completely contained within either the direct map or the kernel map. If + * the virtual address range is contained within the kernel map, then the + * memory type for each of the corresponding ranges of the direct map is also + * changed. (The corresponding ranges of the direct map are those ranges that + * map the same physical pages as the specified virtual address range.) These + * changes to the direct map are necessary because Intel describes the + * behavior of their processors as "undefined" if two or more mappings to the + * same physical page have different memory types. + * + * Returns zero if the change completed successfully, and either EINVAL or + * ENOMEM if the change failed. Specifically, EINVAL is returned if some part + * of the virtual address range was not mapped, and ENOMEM is returned if + * there was insufficient memory available to complete the change. In the + * latter case, the memory type may have been changed on some part of the + * virtual address range or the direct map. + */ int pmap_change_attr(vm_offset_t va, vm_size_t size, int mode) { + int error; + + PMAP_LOCK(kernel_pmap); + error = pmap_change_attr_locked(va, size, mode); + PMAP_UNLOCK(kernel_pmap); + return (error); +} + +static int +pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode) +{ vm_offset_t base, offset, tmpva; + vm_paddr_t pa_start, pa_end; pd_entry_t *pde; pt_entry_t *pte; + int cache_bits_pte, cache_bits_pde, error; + boolean_t changed; + PMAP_LOCK_ASSERT(kernel_pmap, MA_OWNED); base = trunc_page(va); offset = va & PAGE_MASK; size = roundup(offset + size, PAGE_SIZE); - /* Only supported on kernel virtual addresses. */ - if (base <= VM_MAXUSER_ADDRESS) + /* + * Only supported on kernel virtual addresses, including the direct + * map but excluding the recursive map. + */ + if (base < DMAP_MIN_ADDRESS) return (EINVAL); + cache_bits_pde = pmap_cache_bits(mode, 1); + cache_bits_pte = pmap_cache_bits(mode, 0); + changed = FALSE; + /* - * XXX: We have to support tearing 2MB pages down into 4k pages if - * needed here. + * Pages that aren't mapped aren't supported. Also break down 2MB pages + * into 4KB pages if required. */ - /* Pages that aren't mapped aren't supported. */ - for (tmpva = base; tmpva < (base + size); ) { + for (tmpva = base; tmpva < base + size; ) { pde = pmap_pde(kernel_pmap, tmpva); if (*pde == 0) return (EINVAL); if (*pde & PG_PS) { - /* Handle 2MB pages that are completely contained. */ - if (size >= NBPDR) { + /* + * If the current 2MB page already has the required + * memory type, then we need not demote this page. Just + * increment tmpva to the next 2MB page frame. + */ + if ((*pde & PG_PDE_CACHE) == cache_bits_pde) { + tmpva = trunc_2mpage(tmpva) + NBPDR; + continue; + } + + /* + * If the current offset aligns with a 2MB page frame + * and there is at least 2MB left within the range, then + * we need not break down this page into 4KB pages. + */ + if ((tmpva & PDRMASK) == 0 && + tmpva + PDRMASK < base + size) { tmpva += NBPDR; continue; } - return (EINVAL); + if (!pmap_demote_pde(kernel_pmap, pde, tmpva)) + return (ENOMEM); } - pte = vtopte(va); + pte = pmap_pde_to_pte(pde, tmpva); if (*pte == 0) return (EINVAL); tmpva += PAGE_SIZE; } + error = 0; /* * Ok, all the pages exist, so run through them updating their - * cache mode. + * cache mode if required. */ - for (tmpva = base; size > 0; ) { + pa_start = pa_end = 0; + for (tmpva = base; tmpva < base + size; ) { pde = pmap_pde(kernel_pmap, tmpva); if (*pde & PG_PS) { - pmap_pde_attr(tmpva, mode); - tmpva += NBPDR; - size -= NBPDR; + if ((*pde & PG_PDE_CACHE) != cache_bits_pde) { + pmap_pde_attr(pde, cache_bits_pde); + changed = TRUE; + } + if (tmpva >= VM_MIN_KERNEL_ADDRESS) { + if (pa_start == pa_end) { + /* Start physical address run. */ + pa_start = *pde & PG_PS_FRAME; + pa_end = pa_start + NBPDR; + } else if (pa_end == (*pde & PG_PS_FRAME)) + pa_end += NBPDR; + else { + /* Run ended, update direct map. */ + error = pmap_change_attr_locked( + PHYS_TO_DMAP(pa_start), + pa_end - pa_start, mode); + if (error != 0) + break; + /* Start physical address run. */ + pa_start = *pde & PG_PS_FRAME; + pa_end = pa_start + NBPDR; + } + } + tmpva = trunc_2mpage(tmpva) + NBPDR; } else { - pmap_pte_attr(tmpva, mode); + pte = pmap_pde_to_pte(pde, tmpva); + if ((*pte & PG_PTE_CACHE) != cache_bits_pte) { + pmap_pte_attr(pte, cache_bits_pte); + changed = TRUE; + } + if (tmpva >= VM_MIN_KERNEL_ADDRESS) { + if (pa_start == pa_end) { + /* Start physical address run. */ + pa_start = *pte & PG_FRAME; + pa_end = pa_start + PAGE_SIZE; + } else if (pa_end == (*pte & PG_FRAME)) + pa_end += PAGE_SIZE; + else { + /* Run ended, update direct map. */ + error = pmap_change_attr_locked( + PHYS_TO_DMAP(pa_start), + pa_end - pa_start, mode); + if (error != 0) + break; + /* Start physical address run. */ + pa_start = *pte & PG_FRAME; + pa_end = pa_start + PAGE_SIZE; + } + } tmpva += PAGE_SIZE; - size -= PAGE_SIZE; } } + if (error == 0 && pa_start != pa_end) + error = pmap_change_attr_locked(PHYS_TO_DMAP(pa_start), + pa_end - pa_start, mode); /* - * Flush CPU caches to make sure any data isn't cached that shouldn't - * be, etc. - */ - pmap_invalidate_range(kernel_pmap, base, tmpva); - pmap_invalidate_cache(); - return (0); + * Flush CPU caches if required to make sure any data isn't cached that + * shouldn't be, etc. + */ + if (changed) { + pmap_invalidate_range(kernel_pmap, base, tmpva); + pmap_invalidate_cache(); + } + return (error); } /* Modified: stable/7/sys/amd64/include/pmap.h ============================================================================== --- stable/7/sys/amd64/include/pmap.h Thu Sep 3 13:54:58 2009 (r196780) +++ stable/7/sys/amd64/include/pmap.h Thu Sep 3 13:56:18 2009 (r196781) @@ -75,6 +75,10 @@ #define PG_PROT (PG_RW|PG_U) /* all protection bits . */ #define PG_N (PG_NC_PWT|PG_NC_PCD) /* Non-cacheable */ +/* Page level cache control fields used to determine the PAT type */ +#define PG_PDE_CACHE (PG_PDE_PAT | PG_NC_PWT | PG_NC_PCD) +#define PG_PTE_CACHE (PG_PTE_PAT | PG_NC_PWT | PG_NC_PCD) + /* * Promotion to a 2MB (PDE) page mapping requires that the corresponding 4KB * (PTE) page mappings have identical settings for the following fields: @@ -308,7 +312,6 @@ void pmap_bootstrap(vm_paddr_t *); int pmap_change_attr(vm_offset_t, vm_size_t, int); void pmap_init_pat(void); void pmap_kenter(vm_offset_t va, vm_paddr_t pa); -void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode); void *pmap_kenter_temporary(vm_paddr_t pa, int i); vm_paddr_t pmap_kextract(vm_offset_t); void pmap_kremove(vm_offset_t); Modified: stable/7/sys/i386/i386/pmap.c ============================================================================== --- stable/7/sys/i386/i386/pmap.c Thu Sep 3 13:54:58 2009 (r196780) +++ stable/7/sys/i386/i386/pmap.c Thu Sep 3 13:56:18 2009 (r196781) @@ -284,11 +284,15 @@ static boolean_t pmap_enter_pde(pmap_t p static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte); static void pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); +static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte); static boolean_t pmap_is_modified_pvh(struct md_page *pvh); +static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode); static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va); +static void pmap_pde_attr(pd_entry_t *pde, int cache_bits); static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); static boolean_t pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot); +static void pmap_pte_attr(pt_entry_t *pte, int cache_bits); static void pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, vm_page_t *free); static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t sva, @@ -1132,7 +1136,7 @@ pmap_kenter(vm_offset_t va, vm_paddr_t p pte_store(pte, pa | PG_RW | PG_V | pgeflag); } -PMAP_INLINE void +static __inline void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode) { pt_entry_t *pte; @@ -2245,32 +2249,62 @@ pmap_pv_insert_pde(pmap_t pmap, vm_offse } /* - * Tries to demote a 2- or 4MB page mapping. + * Fills a page table page with mappings to consecutive physical pages. + */ +static void +pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte) +{ + pt_entry_t *pte; + + for (pte = firstpte; pte < firstpte + NPTEPG; pte++) { + *pte = newpte; + newpte += PAGE_SIZE; + } +} + +/* + * Tries to demote a 2- or 4MB page mapping. If demotion fails, the + * 2- or 4MB page mapping is invalidated. */ static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) { pd_entry_t newpde, oldpde; pmap_t allpmaps_entry; - pt_entry_t *firstpte, newpte, *pte; + pt_entry_t *firstpte, newpte; vm_paddr_t mptepa; vm_page_t free, mpte; PMAP_LOCK_ASSERT(pmap, MA_OWNED); + oldpde = *pde; + KASSERT((oldpde & (PG_PS | PG_V)) == (PG_PS | PG_V), + ("pmap_demote_pde: oldpde is missing PG_PS and/or PG_V")); mpte = pmap_lookup_pt_page(pmap, va); if (mpte != NULL) pmap_remove_pt_page(pmap, mpte); else { - KASSERT((*pde & PG_W) == 0, + KASSERT((oldpde & PG_W) == 0, ("pmap_demote_pde: page table page for a wired mapping" " is missing")); - free = NULL; - pmap_remove_pde(pmap, pde, trunc_4mpage(va), &free); - pmap_invalidate_page(pmap, trunc_4mpage(va)); - pmap_free_zero_pages(free); - CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#x" - " in pmap %p", va, pmap); - return (FALSE); + + /* + * Invalidate the 2- or 4MB page mapping and return + * "failure" if the mapping was never accessed or the + * allocation of the new page table page fails. + */ + if ((oldpde & PG_A) == 0 || (mpte = vm_page_alloc(NULL, + va >> PDRSHIFT, VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL | + VM_ALLOC_WIRED)) == NULL) { + free = NULL; + pmap_remove_pde(pmap, pde, trunc_4mpage(va), &free); + pmap_invalidate_page(pmap, trunc_4mpage(va)); + pmap_free_zero_pages(free); + CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#x" + " in pmap %p", va, pmap); + return (FALSE); + } + if (va < VM_MAXUSER_ADDRESS) + pmap->pm_stats.resident_count++; } mptepa = VM_PAGE_TO_PHYS(mpte); @@ -2304,30 +2338,32 @@ pmap_demote_pde(pmap_t pmap, pd_entry_t } firstpte = PADDR2; } - oldpde = *pde; newpde = mptepa | PG_M | PG_A | (oldpde & PG_U) | PG_RW | PG_V; - KASSERT((oldpde & (PG_A | PG_V)) == (PG_A | PG_V), - ("pmap_demote_pde: oldpde is missing PG_A and/or PG_V")); + KASSERT((oldpde & PG_A) != 0, + ("pmap_demote_pde: oldpde is missing PG_A")); KASSERT((oldpde & (PG_M | PG_RW)) != PG_RW, ("pmap_demote_pde: oldpde is missing PG_M")); - KASSERT((oldpde & PG_PS) != 0, - ("pmap_demote_pde: oldpde is missing PG_PS")); newpte = oldpde & ~PG_PS; if ((newpte & PG_PDE_PAT) != 0) newpte ^= PG_PDE_PAT | PG_PTE_PAT; /* - * If the mapping has changed attributes, update the page table - * entries. - */ + * If the page table page is new, initialize it. + */ + if (mpte->wire_count == 1) { + mpte->wire_count = NPTEPG; + pmap_fill_ptp(firstpte, newpte); + } KASSERT((*firstpte & PG_FRAME) == (newpte & PG_FRAME), ("pmap_demote_pde: firstpte and newpte map different physical" " addresses")); + + /* + * If the mapping has changed attributes, update the page table + * entries. + */ if ((*firstpte & PG_PTE_PROMOTE) != (newpte & PG_PTE_PROMOTE)) - for (pte = firstpte; pte < firstpte + NPTEPG; pte++) { - *pte = newpte; - newpte += PAGE_SIZE; - } + pmap_fill_ptp(firstpte, newpte); /* * Demote the mapping. This pmap is locked. The old PDE has @@ -3432,62 +3468,57 @@ void pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, vm_pindex_t pindex, vm_size_t size) { + pd_entry_t *pde; + vm_paddr_t pa, ptepa; vm_page_t p; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); KASSERT(object->type == OBJT_DEVICE, ("pmap_object_init_pt: non-device object")); if (pseflag && - ((addr & (NBPDR - 1)) == 0) && ((size & (NBPDR - 1)) == 0)) { - int i; - vm_page_t m[1]; - unsigned int ptepindex; - int npdes; - pd_entry_t ptepa; - - PMAP_LOCK(pmap); - if (pmap->pm_pdir[ptepindex = (addr >> PDRSHIFT)]) - goto out; - PMAP_UNLOCK(pmap); -retry: + (addr & (NBPDR - 1)) == 0 && (size & (NBPDR - 1)) == 0) { + if (!vm_object_populate(object, pindex, pindex + atop(size))) + return; p = vm_page_lookup(object, pindex); - if (p != NULL) { - if (vm_page_sleep_if_busy(p, FALSE, "init4p")) - goto retry; - } else { - p = vm_page_alloc(object, pindex, VM_ALLOC_NORMAL); - if (p == NULL) - return; - m[0] = p; - - if (vm_pager_get_pages(object, m, 1, 0) != VM_PAGER_OK) { - vm_page_lock_queues(); - vm_page_free(p); - vm_page_unlock_queues(); - return; - } - - p = vm_page_lookup(object, pindex); - vm_page_wakeup(p); - } + KASSERT(p->valid == VM_PAGE_BITS_ALL, + ("pmap_object_init_pt: invalid page %p", p)); + /* + * Abort the mapping if the first page is not physically + * aligned to a 2/4MB page boundary. + */ ptepa = VM_PAGE_TO_PHYS(p); if (ptepa & (NBPDR - 1)) return; - p->valid = VM_PAGE_BITS_ALL; + /* + * Skip the first page. Abort the mapping if the rest of + * the pages are not physically contiguous. + */ + p = TAILQ_NEXT(p, listq); + for (pa = ptepa + PAGE_SIZE; pa < ptepa + size; + pa += PAGE_SIZE) { + KASSERT(p->valid == VM_PAGE_BITS_ALL, + ("pmap_object_init_pt: invalid page %p", p)); + if (pa != VM_PAGE_TO_PHYS(p)) + return; + p = TAILQ_NEXT(p, listq); + } + /* Map using 2/4MB pages. */ PMAP_LOCK(pmap); - pmap->pm_stats.resident_count += size >> PAGE_SHIFT; - npdes = size >> PDRSHIFT; - for(i = 0; i < npdes; i++) { - pde_store(&pmap->pm_pdir[ptepindex], - ptepa | PG_U | PG_RW | PG_V | PG_PS); - ptepa += NBPDR; - ptepindex += 1; + for (pa = ptepa; pa < ptepa + size; pa += NBPDR) { + pde = pmap_pde(pmap, addr); + if (*pde == 0) { + pde_store(pde, pa | PG_PS | PG_M | PG_A | + PG_U | PG_RW | PG_V); + pmap->pm_stats.resident_count += NBPDR / + PAGE_SIZE; + pmap_pde_mappings++; + } + /* Else continue on if the PDE is already valid. */ + addr += NBPDR; } - pmap_invalidate_all(pmap); -out: PMAP_UNLOCK(pmap); } } @@ -4326,6 +4357,40 @@ pmap_clear_reference(vm_page_t m) * Miscellaneous support routines follow */ +/* Adjust the cache mode for a 4KB page mapped via a PTE. */ +static __inline void +pmap_pte_attr(pt_entry_t *pte, int cache_bits) +{ + u_int opte, npte; + + /* + * The cache mode bits are all in the low 32-bits of the + * PTE, so we can just spin on updating the low 32-bits. + */ + do { + opte = *(u_int *)pte; + npte = opte & ~PG_PTE_CACHE; + npte |= cache_bits; + } while (npte != opte && !atomic_cmpset_int((u_int *)pte, opte, npte)); +} + +/* Adjust the cache mode for a 2/4MB page mapped via a PDE. */ +static __inline void +pmap_pde_attr(pd_entry_t *pde, int cache_bits) +{ + u_int opde, npde; + + /* + * The cache mode bits are all in the low 32-bits of the + * PDE, so we can just spin on updating the low 32-bits. + */ + do { + opde = *(u_int *)pde; + npde = opde & ~PG_PDE_CACHE; + npde |= cache_bits; + } while (npde != opde && !atomic_cmpset_int((u_int *)pde, opde, npde)); +} + /* * Map a set of physical memory pages into the kernel virtual * address space. Return a pointer to where it is mapped. This @@ -4389,61 +4454,117 @@ pmap_unmapdev(vm_offset_t va, vm_size_t kmem_free(kernel_map, base, size); } +/* + * Changes the specified virtual address range's memory type to that given by + * the parameter "mode". The specified virtual address range must be + * completely contained within either the kernel map. + * + * Returns zero if the change completed successfully, and either EINVAL or + * ENOMEM if the change failed. Specifically, EINVAL is returned if some part + * of the virtual address range was not mapped, and ENOMEM is returned if + * there was insufficient memory available to complete the change. + */ int pmap_change_attr(vm_offset_t va, vm_size_t size, int mode) { vm_offset_t base, offset, tmpva; - pt_entry_t *pte; - u_int opte, npte; pd_entry_t *pde; + pt_entry_t *pte; + int cache_bits_pte, cache_bits_pde; + boolean_t changed; base = trunc_page(va); offset = va & PAGE_MASK; size = roundup(offset + size, PAGE_SIZE); - /* Only supported on kernel virtual addresses. */ - if (base <= VM_MAXUSER_ADDRESS) + /* + * Only supported on kernel virtual addresses above the recursive map. + */ + if (base < VM_MIN_KERNEL_ADDRESS) return (EINVAL); - /* 4MB pages and pages that aren't mapped aren't supported. */ - for (tmpva = base; tmpva < (base + size); tmpva += PAGE_SIZE) { + cache_bits_pde = pmap_cache_bits(mode, 1); + cache_bits_pte = pmap_cache_bits(mode, 0); + changed = FALSE; + + /* + * Pages that aren't mapped aren't supported. Also break down + * 2/4MB pages into 4KB pages if required. + */ + PMAP_LOCK(kernel_pmap); + for (tmpva = base; tmpva < base + size; ) { pde = pmap_pde(kernel_pmap, tmpva); - if (*pde & PG_PS) - return (EINVAL); - if (*pde == 0) + if (*pde == 0) { + PMAP_UNLOCK(kernel_pmap); return (EINVAL); - pte = vtopte(va); - if (*pte == 0) + } + if (*pde & PG_PS) { + /* + * If the current 2/4MB page already has + * the required memory type, then we need not + * demote this page. Just increment tmpva to + * the next 2/4MB page frame. + */ + if ((*pde & PG_PDE_CACHE) == cache_bits_pde) { + tmpva = trunc_4mpage(tmpva) + NBPDR; + continue; + } + + /* + * If the current offset aligns with a 2/4MB + * page frame and there is at least 2/4MB left + * within the range, then we need not break + * down this page into 4KB pages. + */ + if ((tmpva & PDRMASK) == 0 && + tmpva + PDRMASK < base + size) { + tmpva += NBPDR; + continue; + } + if (!pmap_demote_pde(kernel_pmap, pde, tmpva)) { + PMAP_UNLOCK(kernel_pmap); + return (ENOMEM); + } + } + pte = vtopte(tmpva); + if (*pte == 0) { + PMAP_UNLOCK(kernel_pmap); return (EINVAL); + } + tmpva += PAGE_SIZE; } + PMAP_UNLOCK(kernel_pmap); /* - * Ok, all the pages exist and are 4k, so run through them updating - * their cache mode. + * Ok, all the pages exist, so run through them updating their + * cache mode if required. */ - for (tmpva = base; size > 0; ) { - pte = vtopte(tmpva); - - /* - * The cache mode bits are all in the low 32-bits of the - * PTE, so we can just spin on updating the low 32-bits. - */ - do { - opte = *(u_int *)pte; - npte = opte & ~(PG_PTE_PAT | PG_NC_PCD | PG_NC_PWT); - npte |= pmap_cache_bits(mode, 0); - } while (npte != opte && - !atomic_cmpset_int((u_int *)pte, opte, npte)); - tmpva += PAGE_SIZE; - size -= PAGE_SIZE; + for (tmpva = base; tmpva < base + size; ) { + pde = pmap_pde(kernel_pmap, tmpva); + if (*pde & PG_PS) { + if ((*pde & PG_PDE_CACHE) != cache_bits_pde) { + pmap_pde_attr(pde, cache_bits_pde); + changed = TRUE; + } + tmpva = trunc_4mpage(tmpva) + NBPDR; *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-stable-7@FreeBSD.ORG Thu Sep 3 14:23:51 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7DA3A106566C; Thu, 3 Sep 2009 14:23:51 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6B03F8FC19; Thu, 3 Sep 2009 14:23:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n83ENpso035319; Thu, 3 Sep 2009 14:23:51 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n83ENpUW035318; Thu, 3 Sep 2009 14:23:51 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200909031423.n83ENpUW035318@svn.freebsd.org> From: John Baldwin Date: Thu, 3 Sep 2009 14:23:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196782 - in stable/7/sys: . contrib/pf kern sys vm X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Sep 2009 14:23:51 -0000 Author: jhb Date: Thu Sep 3 14:23:50 2009 New Revision: 196782 URL: http://svn.freebsd.org/changeset/base/196782 Log: MFC 193275 and 194989: Add an extension to the character device interface that allows character device drivers to use arbitrary VM objects to satisfy individual mmap() requests. - A new d_mmap_single(cdev, &foff, objsize, &object, prot) callback is added to cdevsw. This function is called for each mmap() request. If it returns ENODEV, then the mmap() request will fall back to using the device's device pager object and d_mmap(). Otherwise, the method can return a VM object to satisfy this entire mmap() request via *object. It can also modify the starting offset into this object via *foff. This allows device drivers to use the file offset as a cookie to identify specific VM objects. - vm_mmap_vnode() has been changed to call vm_mmap_cdev() directly when mapping V_CHR vnodes. This avoids duplicating all the cdev mmap handling code and simplifies some of vm_mmap_vnode(). - D_VERSION has been bumped to D_VERSION_02. Older device drivers using D_VERSION_01 are still supported. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/kern/kern_conf.c stable/7/sys/sys/conf.h stable/7/sys/vm/vm_mmap.c Modified: stable/7/sys/kern/kern_conf.c ============================================================================== --- stable/7/sys/kern/kern_conf.c Thu Sep 3 13:56:18 2009 (r196781) +++ stable/7/sys/kern/kern_conf.c Thu Sep 3 14:23:50 2009 (r196782) @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include static MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage"); @@ -276,6 +277,7 @@ dead_strategy(struct bio *bp) #define dead_dump (dumper_t *)enxio #define dead_kqfilter (d_kqfilter_t *)enxio +#define dead_mmap_single (d_mmap_single_t *)enodev static struct cdevsw dead_cdevsw = { .d_version = D_VERSION, @@ -290,7 +292,8 @@ static struct cdevsw dead_cdevsw = { .d_strategy = dead_strategy, .d_name = "dead", .d_dump = dead_dump, - .d_kqfilter = dead_kqfilter + .d_kqfilter = dead_kqfilter, + .d_mmap_single = dead_mmap_single }; /* Default methods if driver does not specify method */ @@ -302,6 +305,7 @@ static struct cdevsw dead_cdevsw = { #define no_ioctl (d_ioctl_t *)enodev #define no_mmap (d_mmap_t *)enodev #define no_kqfilter (d_kqfilter_t *)enodev +#define no_mmap_single (d_mmap_single_t *)enodev static void no_strategy(struct bio *bp) @@ -481,6 +485,23 @@ giant_mmap(struct cdev *dev, vm_offset_t return (retval); } +static int +giant_mmap_single(struct cdev *dev, vm_ooffset_t *offset, vm_size_t size, + vm_object_t *object, int nprot) +{ + struct cdevsw *dsw; + int retval; + + dsw = dev_refthread(dev); + if (dsw == NULL) + return (ENXIO); + mtx_lock(&Giant); + retval = dsw->d_gianttrick->d_mmap_single(dev, offset, size, object, + nprot); + mtx_unlock(&Giant); + dev_relthread(dev); + return (retval); +} /* * struct cdev * and u_dev_t primitives @@ -616,7 +637,8 @@ prep_cdevsw(struct cdevsw *devsw) return; } - if (devsw->d_version != D_VERSION_01) { + if (devsw->d_version != D_VERSION_01 && + devsw->d_version != D_VERSION_02) { printf( "WARNING: Device driver \"%s\" has wrong version %s\n", devsw->d_name == NULL ? "???" : devsw->d_name, @@ -632,6 +654,8 @@ prep_cdevsw(struct cdevsw *devsw) devsw->d_dump = dead_dump; devsw->d_kqfilter = dead_kqfilter; } + if (devsw->d_version == D_VERSION_01) + devsw->d_mmap_single = NULL; if (devsw->d_flags & D_TTY) { if (devsw->d_ioctl == NULL) devsw->d_ioctl = ttyioctl; @@ -668,6 +692,7 @@ prep_cdevsw(struct cdevsw *devsw) FIXUP(d_mmap, no_mmap, giant_mmap); FIXUP(d_strategy, no_strategy, giant_strategy); FIXUP(d_kqfilter, no_kqfilter, giant_kqfilter); + FIXUP(d_mmap_single, no_mmap_single, giant_mmap_single); if (devsw->d_dump == NULL) devsw->d_dump = no_dump; Modified: stable/7/sys/sys/conf.h ============================================================================== --- stable/7/sys/sys/conf.h Thu Sep 3 13:56:18 2009 (r196781) +++ stable/7/sys/sys/conf.h Thu Sep 3 14:23:50 2009 (r196782) @@ -106,6 +106,7 @@ struct thread; struct uio; struct knote; struct clonedevs; +struct vm_object; struct vnode; /* @@ -139,10 +140,10 @@ typedef int d_poll_t(struct cdev *dev, i typedef int d_kqfilter_t(struct cdev *dev, struct knote *kn); typedef int d_mmap_t(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot); +typedef int d_mmap_single_t(struct cdev *cdev, vm_ooffset_t *offset, + vm_size_t size, struct vm_object **object, int nprot); typedef void d_purge_t(struct cdev *dev); -typedef int d_spare2_t(struct cdev *dev); - typedef int dumper_t( void *priv, /* Private to the driver. */ void *virtual, /* Virtual (mapped) address. */ @@ -177,7 +178,8 @@ typedef int dumper_t( */ #define D_VERSION_00 0x20011966 #define D_VERSION_01 0x17032005 /* Add d_uid,gid,mode & kind */ -#define D_VERSION D_VERSION_01 +#define D_VERSION_02 0x28042009 /* Add d_mmap_single */ +#define D_VERSION D_VERSION_02 /* * Flags used for internal housekeeping @@ -203,7 +205,7 @@ struct cdevsw { dumper_t *d_dump; d_kqfilter_t *d_kqfilter; d_purge_t *d_purge; - d_spare2_t *d_spare2; + d_mmap_single_t *d_mmap_single; uid_t d_uid; gid_t d_gid; mode_t d_mode; Modified: stable/7/sys/vm/vm_mmap.c ============================================================================== --- stable/7/sys/vm/vm_mmap.c Thu Sep 3 13:56:18 2009 (r196781) +++ stable/7/sys/vm/vm_mmap.c Thu Sep 3 14:23:50 2009 (r196782) @@ -116,9 +116,9 @@ vmmapentry_rsrc_init(dummy) } static int vm_mmap_vnode(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *, - int *, struct vnode *, vm_ooffset_t, vm_object_t *); + int *, struct vnode *, vm_ooffset_t *, vm_object_t *); static int vm_mmap_cdev(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *, - int *, struct cdev *, vm_ooffset_t, vm_object_t *); + int *, struct cdev *, vm_ooffset_t *, vm_object_t *); /* * MPSAFE @@ -1132,14 +1132,13 @@ munlock(td, uap) int vm_mmap_vnode(struct thread *td, vm_size_t objsize, vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp, - struct vnode *vp, vm_ooffset_t foff, vm_object_t *objp) + struct vnode *vp, vm_ooffset_t *foffp, vm_object_t *objp) { struct vattr va; - void *handle; vm_object_t obj; + vm_offset_t foff; struct mount *mp; - struct cdevsw *dsw; - int error, flags, type; + int error, flags; int vfslocked; mp = vp->v_mount; @@ -1148,6 +1147,7 @@ vm_mmap_vnode(struct thread *td, vm_size VFS_UNLOCK_GIANT(vfslocked); return (error); } + foff = *foffp; flags = *flagsp; obj = vp->v_object; if (vp->v_type == VREG) { @@ -1163,41 +1163,12 @@ vm_mmap_vnode(struct thread *td, vm_size vp = (struct vnode*)obj->handle; vget(vp, LK_EXCLUSIVE, td); } - type = OBJT_VNODE; - handle = vp; } else if (vp->v_type == VCHR) { - type = OBJT_DEVICE; - handle = vp->v_rdev; - - dsw = dev_refthread(handle); - if (dsw == NULL) { - error = ENXIO; - goto done; - } - if (dsw->d_flags & D_MMAP_ANON) { - dev_relthread(handle); - *maxprotp = VM_PROT_ALL; - *flagsp |= MAP_ANON; - error = 0; - goto done; - } - dev_relthread(handle); - /* - * cdevs does not provide private mappings of any kind. - */ - if ((*maxprotp & VM_PROT_WRITE) == 0 && - (prot & PROT_WRITE) != 0) { - error = EACCES; - goto done; - } - if (flags & (MAP_PRIVATE|MAP_COPY)) { - error = EINVAL; - goto done; - } - /* - * Force device mappings to be shared. - */ - flags |= MAP_SHARED; + error = vm_mmap_cdev(td, objsize, prot, maxprotp, flagsp, + vp->v_rdev, foffp, objp); + if (error == 0) + goto mark_atime; + goto done; } else { error = EINVAL; goto done; @@ -1224,18 +1195,18 @@ vm_mmap_vnode(struct thread *td, vm_size * we do not need to sync it. * Adjust object size to be the size of actual file. */ - if (vp->v_type == VREG) { - objsize = round_page(va.va_size); - if (va.va_nlink == 0) - flags |= MAP_NOSYNC; - } - obj = vm_pager_allocate(type, handle, objsize, prot, foff); + objsize = round_page(va.va_size); + if (va.va_nlink == 0) + flags |= MAP_NOSYNC; + obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff); if (obj == NULL) { - error = (type == OBJT_DEVICE ? EINVAL : ENOMEM); + error = ENOMEM; goto done; } *objp = obj; *flagsp = flags; + +mark_atime: vfs_mark_atime(vp, td); done: @@ -1255,11 +1226,11 @@ done: int vm_mmap_cdev(struct thread *td, vm_size_t objsize, vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp, - struct cdev *cdev, vm_ooffset_t foff, vm_object_t *objp) + struct cdev *cdev, vm_ooffset_t *foff, vm_object_t *objp) { vm_object_t obj; struct cdevsw *dsw; - int flags; + int error, flags; flags = *flagsp; @@ -1272,25 +1243,43 @@ vm_mmap_cdev(struct thread *td, vm_size_ *flagsp |= MAP_ANON; return (0); } - dev_relthread(cdev); /* - * cdevs does not provide private mappings of any kind. + * cdevs do not provide private mappings of any kind. */ if ((*maxprotp & VM_PROT_WRITE) == 0 && - (prot & PROT_WRITE) != 0) + (prot & PROT_WRITE) != 0) { + dev_relthread(cdev); return (EACCES); - if (flags & (MAP_PRIVATE|MAP_COPY)) + } + if (flags & (MAP_PRIVATE|MAP_COPY)) { + dev_relthread(cdev); return (EINVAL); + } /* * Force device mappings to be shared. */ flags |= MAP_SHARED; #ifdef MAC_XXX - error = mac_check_cdev_mmap(td->td_ucred, cdev, prot); - if (error != 0) + error = mac_cdev_check_mmap(td->td_ucred, cdev, prot); + if (error != 0) { + dev_relthread(cdev); return (error); + } #endif - obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, foff); + /* + * First, try d_mmap_single(). If that is not implemented + * (returns ENODEV), fall back to using the device pager. + * Note that d_mmap_single() must return a reference to the + * object (it needs to bump the reference count of the object + * it returns somehow). + * + * XXX assumes VM_PROT_* == PROT_* + */ + error = dsw->d_mmap_single(cdev, foff, objsize, objp, (int)prot); + dev_relthread(cdev); + if (error != ENODEV) + return (error); + obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff); if (obj == NULL) return (EINVAL); *objp = obj; @@ -1356,11 +1345,11 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, switch (handle_type) { case OBJT_DEVICE: error = vm_mmap_cdev(td, size, prot, &maxprot, &flags, - handle, foff, &object); + handle, &foff, &object); break; case OBJT_VNODE: error = vm_mmap_vnode(td, size, prot, &maxprot, &flags, - handle, foff, &object); + handle, &foff, &object); break; case OBJT_DEFAULT: if (handle == NULL) { From owner-svn-src-stable-7@FreeBSD.ORG Thu Sep 3 18:16:03 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8DE81106566B; Thu, 3 Sep 2009 18:16:03 +0000 (UTC) (envelope-from brian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7ADB08FC17; Thu, 3 Sep 2009 18:16:03 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n83IG3nh041108; Thu, 3 Sep 2009 18:16:03 GMT (envelope-from brian@svn.freebsd.org) Received: (from brian@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n83IG3jB041106; Thu, 3 Sep 2009 18:16:03 GMT (envelope-from brian@svn.freebsd.org) Message-Id: <200909031816.n83IG3jB041106@svn.freebsd.org> From: Brian Somers Date: Thu, 3 Sep 2009 18:16:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196793 - stable/7/usr.sbin/ppp X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Sep 2009 18:16:03 -0000 Author: brian Date: Thu Sep 3 18:16:03 2009 New Revision: 196793 URL: http://svn.freebsd.org/changeset/base/196793 Log: MFC r196530: Document that ppp handles pipe(2) descriptors specially in -direct mode. Modified: stable/7/usr.sbin/ppp/ (props changed) stable/7/usr.sbin/ppp/ppp.8.m4 Modified: stable/7/usr.sbin/ppp/ppp.8.m4 ============================================================================== --- stable/7/usr.sbin/ppp/ppp.8.m4 Thu Sep 3 17:37:23 2009 (r196792) +++ stable/7/usr.sbin/ppp/ppp.8.m4 Thu Sep 3 18:16:03 2009 (r196793) @@ -27,7 +27,7 @@ changecom(,)dnl .\" .\" $FreeBSD$ .\" -.Dd May 24, 2007 +.Dd August 25, 2009 .Dt PPP 8 .Os .Sh NAME @@ -171,6 +171,17 @@ If callback is configured, will use the .Dq set device information when dialing back. +.Pp +When run in +.Fl direct +mode, +.Nm +will behave slightly differently if descriptor 0 was created by +.Xr pipe 2 . +As pipes are not bi-directional, ppp will redirect all writes to descriptor +1 (standard output), leaving only reads acting on descriptor 0. +No special action is taken if descriptor 0 was created by +.Xr socketpair 2 . .It Fl dedicated This option is designed for machines connected with a dedicated wire. @@ -6070,6 +6081,8 @@ This socket is used to pass links betwee .Xr tcpdump 1 , .Xr telnet 1 , .Xr kldload 2 , +.Xr pipe 2 , +.Xr socketpair 2 , ifdef({LOCALNAT},{},{.Xr libalias 3 , })dnl ifdef({LOCALRAD},{},{.Xr libradius 3 , From owner-svn-src-stable-7@FreeBSD.ORG Fri Sep 4 04:48:12 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 74D2E106566C; Fri, 4 Sep 2009 04:48:12 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4941B8FC12; Fri, 4 Sep 2009 04:48:12 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n844mC2U054065; Fri, 4 Sep 2009 04:48:12 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n844mCdq054063; Fri, 4 Sep 2009 04:48:12 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <200909040448.n844mCdq054063@svn.freebsd.org> From: Alan Cox Date: Fri, 4 Sep 2009 04:48:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196807 - in stable/7/sys: . contrib/pf vm X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Sep 2009 04:48:12 -0000 Author: alc Date: Fri Sep 4 04:48:12 2009 New Revision: 196807 URL: http://svn.freebsd.org/changeset/base/196807 Log: MFC r190912 Previously, when vm_page_free_toq() was performed on a page belonging to a reservation, unless all of the reservation's pages were free, the reservation was moved to the head of the partially-populated reservations queue, where it would be the next reservation to be broken in case the free page queues were emptied. Now, instead, I am moving it to the tail. Very likely this reservation is in the process of being freed in its entirety, so placing it at the tail of the queue makes it more likely that the underlying physical memory will be returned to the free page queues as one contiguous chunk. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/vm/vm_reserv.c Modified: stable/7/sys/vm/vm_reserv.c ============================================================================== --- stable/7/sys/vm/vm_reserv.c Fri Sep 4 01:44:31 2009 (r196806) +++ stable/7/sys/vm/vm_reserv.c Fri Sep 4 04:48:12 2009 (r196807) @@ -138,8 +138,8 @@ static vm_reserv_t vm_reserv_array; * The partially-populated reservation queue * * This queue enables the fast recovery of an unused cached or free small page - * from a partially-populated reservation. The head of this queue is either - * the least-recently-populated or most-recently-depopulated reservation. + * from a partially-populated reservation. The reservation at the head of + * this queue is the least-recently-changed, partially-populated reservation. * * Access to this queue is synchronized by the free page queue lock. */ @@ -209,7 +209,7 @@ sysctl_vm_reserv_partpopq(SYSCTL_HANDLER /* * Reduces the given reservation's population count. If the population count * becomes zero, the reservation is destroyed. Additionally, moves the - * reservation to the head of the partially-populated reservations queue if the + * reservation to the tail of the partially-populated reservations queue if the * population count is non-zero. * * The free page queue lock must be held. @@ -235,7 +235,7 @@ vm_reserv_depopulate(vm_reserv_t rv) vm_reserv_freed++; } else { rv->inpartpopq = TRUE; - TAILQ_INSERT_HEAD(&vm_rvq_partpop, rv, partpopq); + TAILQ_INSERT_TAIL(&vm_rvq_partpop, rv, partpopq); } } From owner-svn-src-stable-7@FreeBSD.ORG Fri Sep 4 05:06:15 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 693B6106566B; Fri, 4 Sep 2009 05:06:15 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 57C978FC14; Fri, 4 Sep 2009 05:06:15 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n8456FnX054464; Fri, 4 Sep 2009 05:06:15 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n8456FjI054462; Fri, 4 Sep 2009 05:06:15 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <200909040506.n8456FjI054462@svn.freebsd.org> From: Alan Cox Date: Fri, 4 Sep 2009 05:06:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196808 - in stable/7/sys: . amd64/include contrib/pf X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Sep 2009 05:06:15 -0000 Author: alc Date: Fri Sep 4 05:06:15 2009 New Revision: 196808 URL: http://svn.freebsd.org/changeset/base/196808 Log: MFC r193729 Now that amd64's kernel map is 512GB (r192469), there is no reason to cap its buffer map at 400MB. Modified: stable/7/sys/ (props changed) stable/7/sys/amd64/include/param.h stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/amd64/include/param.h ============================================================================== --- stable/7/sys/amd64/include/param.h Fri Sep 4 04:48:12 2009 (r196807) +++ stable/7/sys/amd64/include/param.h Fri Sep 4 05:06:15 2009 (r196808) @@ -131,15 +131,6 @@ #endif /* - * Ceiling on size of buffer cache (really only effects write queueing, - * the VM page cache is not effected), can be changed via - * the kern.maxbcache /boot/loader.conf variable. - */ -#ifndef VM_BCACHE_SIZE_MAX -#define VM_BCACHE_SIZE_MAX (400 * 1024 * 1024) -#endif - -/* * Mach derived conversion macros */ #define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) From owner-svn-src-stable-7@FreeBSD.ORG Fri Sep 4 19:59:33 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 383CD106566C; Fri, 4 Sep 2009 19:59:33 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2286C8FC13; Fri, 4 Sep 2009 19:59:33 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n84JxXcn009878; Fri, 4 Sep 2009 19:59:33 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n84JxWGA009848; Fri, 4 Sep 2009 19:59:32 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200909041959.n84JxWGA009848@svn.freebsd.org> From: John Baldwin Date: Fri, 4 Sep 2009 19:59:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196838 - in stable/7/sys: . amd64/amd64 amd64/include arm/include contrib/pf dev/iir i386/i386 i386/include ia64/include kern powerpc/include sparc64/include sun4v/include sun4v/sun4v vm X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Sep 2009 19:59:33 -0000 Author: jhb Date: Fri Sep 4 19:59:32 2009 New Revision: 196838 URL: http://svn.freebsd.org/changeset/base/196838 Log: MFC 193396, 193521, 194331, 194337, 194376, 194454, 194562, 194642, 195033, 195385, 195649, 195660, 195749, and 195774: Add support to the virtual memory system for configuring machine- dependent memory attributes: - Refactor contigmalloc() into two functions: a simple front-end that deals with the malloc tag and calls a new back-end, kmem_alloc_contig(), that allocates the pages and maps them. - Use kmem_alloc_contig() to implement the UMA back-end allocator for jumbo frame zones. - Use kmem_alloc_contig() to allocate the top-level page tables for PAE. - Introduce vm_memattr_t to as a type to hold memory attributes. - Introduce vm_object_set_memattr() for setting the default memory attributes that will be given to an object's pages. - Introduce and use pmap_page_{get,set}_memattr() for getting and setting a page's machine-dependent memory attributes. Add full support for these functions on amd64 and i386 and stubs for them on the other architectures. The function pmap_page_set_memattr() is also responsible for any other machine-dependent aspects of changing a page's memory attributes, such as flushing the cache or updating the direct map. The uses include kmem_alloc_contig(), vm_page_alloc(), and the device pager: kmem_alloc_contig() can now be used to allocate kernel memory with non-default memory attributes on amd64 and i386. vm_page_alloc() and the device pager will set the memory attributes for the real or fictitious page according to the object's default memory attributes. - Update the various pmap functions on amd64 and i386 that map pages to incorporate each page's memory attributes in the mapping. Reviewed by: alc Added: stable/7/sys/amd64/include/vm.h - copied, changed from r195033, head/sys/amd64/include/vm.h stable/7/sys/arm/include/vm.h - copied, changed from r195033, head/sys/arm/include/vm.h stable/7/sys/i386/include/vm.h - copied, changed from r195033, head/sys/i386/include/vm.h stable/7/sys/ia64/include/vm.h - copied, changed from r195033, head/sys/ia64/include/vm.h stable/7/sys/powerpc/include/vm.h - copied, changed from r195033, head/sys/powerpc/include/vm.h stable/7/sys/sparc64/include/vm.h - copied, changed from r195033, head/sys/sparc64/include/vm.h stable/7/sys/sun4v/include/vm.h - copied, changed from r195033, head/sys/sun4v/include/vm.h Modified: stable/7/sys/ (props changed) stable/7/sys/amd64/amd64/pmap.c stable/7/sys/amd64/include/pmap.h stable/7/sys/arm/include/pmap.h stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/iir/iir.c stable/7/sys/dev/iir/iir_ctrl.c stable/7/sys/i386/i386/pmap.c stable/7/sys/i386/include/pmap.h stable/7/sys/ia64/include/pmap.h stable/7/sys/kern/kern_mbuf.c stable/7/sys/powerpc/include/pmap.h stable/7/sys/sparc64/include/pmap.h stable/7/sys/sun4v/include/pmap.h stable/7/sys/sun4v/sun4v/pmap.c stable/7/sys/vm/device_pager.c stable/7/sys/vm/pmap.h stable/7/sys/vm/vm.h stable/7/sys/vm/vm_contig.c stable/7/sys/vm/vm_extern.h stable/7/sys/vm/vm_object.c stable/7/sys/vm/vm_object.h stable/7/sys/vm/vm_page.c stable/7/sys/vm/vm_phys.c Modified: stable/7/sys/amd64/amd64/pmap.c ============================================================================== --- stable/7/sys/amd64/amd64/pmap.c Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/amd64/amd64/pmap.c Fri Sep 4 19:59:32 2009 (r196838) @@ -618,6 +618,7 @@ pmap_page_init(vm_page_t m) { TAILQ_INIT(&m->md.pv_list); + m->md.pat_mode = PAT_WRITE_BACK; } /* @@ -748,21 +749,6 @@ pmap_cache_bits(int mode, boolean_t is_p /* The PAT bit is different for PTE's and PDE's. */ pat_flag = is_pde ? PG_PDE_PAT : PG_PTE_PAT; - /* If we don't support PAT, map extended modes to older ones. */ - if (!(cpu_feature & CPUID_PAT)) { - switch (mode) { - case PAT_UNCACHEABLE: - case PAT_WRITE_THROUGH: - case PAT_WRITE_BACK: - break; - case PAT_UNCACHED: - case PAT_WRITE_COMBINING: - case PAT_WRITE_PROTECTED: - mode = PAT_UNCACHEABLE; - break; - } - } - /* Map the caching mode to a PAT index. */ switch (mode) { #ifdef PAT_WORKS @@ -1134,7 +1120,8 @@ pmap_qenter(vm_offset_t sva, vm_page_t * endpte = pte + count; while (pte < endpte) { oldpte |= *pte; - pte_store(pte, VM_PAGE_TO_PHYS(*ma) | PG_G | PG_RW | PG_V); + pte_store(pte, VM_PAGE_TO_PHYS(*ma) | PG_G | + pmap_cache_bits((*ma)->md.pat_mode, 0) | PG_RW | PG_V); pte++; ma++; } @@ -3046,7 +3033,7 @@ validate: /* * Now validate mapping with desired protection/wiring. */ - newpte = (pt_entry_t)(pa | PG_V); + newpte = (pt_entry_t)(pa | pmap_cache_bits(m->md.pat_mode, 0) | PG_V); if ((prot & VM_PROT_WRITE) != 0) { newpte |= PG_RW; vm_page_flag_set(m, PG_WRITEABLE); @@ -3131,7 +3118,8 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t " in pmap %p", va, pmap); return (FALSE); } - newpde = VM_PAGE_TO_PHYS(m) | PG_PS | PG_V; + newpde = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 1) | + PG_PS | PG_V; if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) { newpde |= PG_MANAGED; @@ -3318,7 +3306,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_ */ pmap->pm_stats.resident_count++; - pa = VM_PAGE_TO_PHYS(m); + pa = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 0); if ((prot & VM_PROT_EXECUTE) == 0) pa |= pg_nx; @@ -3359,6 +3347,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offs pd_entry_t *pde; vm_paddr_t pa, ptepa; vm_page_t p, pdpg; + int pat_mode; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); KASSERT(object->type == OBJT_DEVICE, @@ -3369,6 +3358,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offs p = vm_page_lookup(object, pindex); KASSERT(p->valid == VM_PAGE_BITS_ALL, ("pmap_object_init_pt: invalid page %p", p)); + pat_mode = p->md.pat_mode; /* * Abort the mapping if the first page is not physically @@ -3380,21 +3370,28 @@ pmap_object_init_pt(pmap_t pmap, vm_offs /* * Skip the first page. Abort the mapping if the rest of - * the pages are not physically contiguous. + * the pages are not physically contiguous or have differing + * memory attributes. */ p = TAILQ_NEXT(p, listq); for (pa = ptepa + PAGE_SIZE; pa < ptepa + size; pa += PAGE_SIZE) { KASSERT(p->valid == VM_PAGE_BITS_ALL, ("pmap_object_init_pt: invalid page %p", p)); - if (pa != VM_PAGE_TO_PHYS(p)) + if (pa != VM_PAGE_TO_PHYS(p) || + pat_mode != p->md.pat_mode) return; p = TAILQ_NEXT(p, listq); } - /* Map using 2MB pages. */ + /* + * Map using 2MB pages. Since "ptepa" is 2M aligned and + * "size" is a multiple of 2M, adding the PAT setting to "pa" + * will not affect the termination of this loop. + */ PMAP_LOCK(pmap); - for (pa = ptepa; pa < ptepa + size; pa += NBPDR) { + for (pa = ptepa | pmap_cache_bits(pat_mode, 1); pa < ptepa + + size; pa += NBPDR) { pdpg = pmap_allocpde(pmap, addr, M_NOWAIT); if (pdpg == NULL) { /* @@ -4305,6 +4302,26 @@ pmap_unmapdev(vm_offset_t va, vm_size_t } /* + * Sets the memory attribute for the specified page. + */ +void +pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) +{ + + m->md.pat_mode = ma; + + /* + * If "m" is a normal page, update its direct mapping. This update + * can be relied upon to perform any cache operations that are + * required for data coherence. + */ + if ((m->flags & PG_FICTITIOUS) == 0 && + pmap_change_attr(PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)), PAGE_SIZE, + m->md.pat_mode)) + panic("memory attribute change on the direct map failed"); +} + +/* * Changes the specified virtual address range's memory type to that given by * the parameter "mode". The specified virtual address range must be * completely contained within either the direct map or the kernel map. If Modified: stable/7/sys/amd64/include/pmap.h ============================================================================== --- stable/7/sys/amd64/include/pmap.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/amd64/include/pmap.h Fri Sep 4 19:59:32 2009 (r196838) @@ -234,7 +234,7 @@ struct pv_entry; struct pv_chunk; struct md_page { - int pv_unused; + int pat_mode; TAILQ_HEAD(,pv_entry) pv_list; }; @@ -306,6 +306,7 @@ extern vm_paddr_t dump_avail[]; extern vm_offset_t virtual_avail; extern vm_offset_t virtual_end; +#define pmap_page_get_memattr(m) ((vm_memattr_t)(m)->md.pat_mode) #define pmap_unmapbios(va, sz) pmap_unmapdev((va), (sz)) void pmap_bootstrap(vm_paddr_t *); @@ -319,6 +320,7 @@ void *pmap_mapbios(vm_paddr_t, vm_size_t void *pmap_mapdev(vm_paddr_t, vm_size_t); void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int); boolean_t pmap_page_is_mapped(vm_page_t m); +void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); void pmap_unmapdev(vm_offset_t, vm_size_t); void pmap_invalidate_page(pmap_t, vm_offset_t); void pmap_invalidate_range(pmap_t, vm_offset_t, vm_offset_t); Copied and modified: stable/7/sys/amd64/include/vm.h (from r195033, head/sys/amd64/include/vm.h) ============================================================================== --- head/sys/amd64/include/vm.h Fri Jun 26 04:47:43 2009 (r195033, copy source) +++ stable/7/sys/amd64/include/vm.h Fri Sep 4 19:59:32 2009 (r196838) @@ -32,14 +32,14 @@ #include -/* Cache control options. */ -#define VM_CACHE_UNCACHEABLE ((vm_cache_mode_t)PAT_UNCACHEABLE) -#define VM_CACHE_WRITE_COMBINING ((vm_cache_mode_t)PAT_WRITE_COMBINING) -#define VM_CACHE_WRITE_THROUGH ((vm_cache_mode_t)PAT_WRITE_THROUGH) -#define VM_CACHE_WRITE_PROTECTED ((vm_cache_mode_t)PAT_WRITE_PROTECTED) -#define VM_CACHE_WRITE_BACK ((vm_cache_mode_t)PAT_WRITE_BACK) -#define VM_CACHE_UNCACHED ((vm_cache_mode_t)PAT_UNCACHED) +/* Memory attributes. */ +#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHEABLE) +#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PAT_WRITE_COMBINING) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PAT_WRITE_THROUGH) +#define VM_MEMATTR_WRITE_PROTECTED ((vm_memattr_t)PAT_WRITE_PROTECTED) +#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PAT_WRITE_BACK) +#define VM_MEMATTR_UNCACHED ((vm_memattr_t)PAT_UNCACHED) -#define VM_CACHE_DEFAULT VM_CACHE_WRITE_BACK +#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK #endif /* !_MACHINE_PMAP_H_ */ Modified: stable/7/sys/arm/include/pmap.h ============================================================================== --- stable/7/sys/arm/include/pmap.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/arm/include/pmap.h Fri Sep 4 19:59:32 2009 (r196838) @@ -75,7 +75,10 @@ #endif +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) +#define pmap_page_set_memattr(m, ma) (void)0 + /* * Pmap stuff */ Copied and modified: stable/7/sys/arm/include/vm.h (from r195033, head/sys/arm/include/vm.h) ============================================================================== --- head/sys/arm/include/vm.h Fri Jun 26 04:47:43 2009 (r195033, copy source) +++ stable/7/sys/arm/include/vm.h Fri Sep 4 19:59:32 2009 (r196838) @@ -29,7 +29,7 @@ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ -/* Cache control is not (yet) implemented. */ -#define VM_CACHE_DEFAULT 0 +/* Memory attribute configuration is not (yet) implemented. */ +#define VM_MEMATTR_DEFAULT 0 #endif /* !_MACHINE_PMAP_H_ */ Modified: stable/7/sys/dev/iir/iir.c ============================================================================== --- stable/7/sys/dev/iir/iir.c Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/dev/iir/iir.c Fri Sep 4 19:59:32 2009 (r196838) @@ -67,9 +67,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include - #include MALLOC_DEFINE(M_GDTBUF, "iirbuf", "iir driver buffer"); Modified: stable/7/sys/dev/iir/iir_ctrl.c ============================================================================== --- stable/7/sys/dev/iir/iir_ctrl.c Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/dev/iir/iir_ctrl.c Fri Sep 4 19:59:32 2009 (r196838) @@ -52,10 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include -#include -#include #include Modified: stable/7/sys/i386/i386/pmap.c ============================================================================== --- stable/7/sys/i386/i386/pmap.c Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/i386/i386/pmap.c Fri Sep 4 19:59:32 2009 (r196838) @@ -556,20 +556,18 @@ pmap_page_init(vm_page_t m) { TAILQ_INIT(&m->md.pv_list); + m->md.pat_mode = PAT_WRITE_BACK; } #ifdef PAE - -static MALLOC_DEFINE(M_PMAPPDPT, "pmap", "pmap pdpt"); - static void * pmap_pdpt_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) { /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; - return (contigmalloc(PAGE_SIZE, M_PMAPPDPT, 0, 0x0ULL, 0xffffffffULL, - 1, 0)); + return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, 0x0ULL, + 0xffffffffULL, 1, 0, VM_MEMATTR_DEFAULT)); } #endif @@ -1206,7 +1204,8 @@ pmap_qenter(vm_offset_t sva, vm_page_t * endpte = pte + count; while (pte < endpte) { oldpte |= *pte; - pte_store(pte, VM_PAGE_TO_PHYS(*ma) | pgeflag | PG_RW | PG_V); + pte_store(pte, VM_PAGE_TO_PHYS(*ma) | pgeflag | + pmap_cache_bits((*ma)->md.pat_mode, 0) | PG_RW | PG_V); pte++; ma++; } @@ -3161,7 +3160,7 @@ validate: /* * Now validate mapping with desired protection/wiring. */ - newpte = (pt_entry_t)(pa | PG_V); + newpte = (pt_entry_t)(pa | pmap_cache_bits(m->md.pat_mode, 0) | PG_V); if ((prot & VM_PROT_WRITE) != 0) { newpte |= PG_RW; vm_page_flag_set(m, PG_WRITEABLE); @@ -3243,7 +3242,8 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t " in pmap %p", va, pmap); return (FALSE); } - newpde = VM_PAGE_TO_PHYS(m) | PG_PS | PG_V; + newpde = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 1) | + PG_PS | PG_V; if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) { newpde |= PG_MANAGED; @@ -3428,7 +3428,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_ */ pmap->pm_stats.resident_count++; - pa = VM_PAGE_TO_PHYS(m); + pa = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 0); #ifdef PAE if ((prot & VM_PROT_EXECUTE) == 0) pa |= pg_nx; @@ -3471,6 +3471,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offs pd_entry_t *pde; vm_paddr_t pa, ptepa; vm_page_t p; + int pat_mode; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); KASSERT(object->type == OBJT_DEVICE, @@ -3482,6 +3483,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offs p = vm_page_lookup(object, pindex); KASSERT(p->valid == VM_PAGE_BITS_ALL, ("pmap_object_init_pt: invalid page %p", p)); + pat_mode = p->md.pat_mode; /* * Abort the mapping if the first page is not physically @@ -3493,21 +3495,28 @@ pmap_object_init_pt(pmap_t pmap, vm_offs /* * Skip the first page. Abort the mapping if the rest of - * the pages are not physically contiguous. + * the pages are not physically contiguous or have differing + * memory attributes. */ p = TAILQ_NEXT(p, listq); for (pa = ptepa + PAGE_SIZE; pa < ptepa + size; pa += PAGE_SIZE) { KASSERT(p->valid == VM_PAGE_BITS_ALL, ("pmap_object_init_pt: invalid page %p", p)); - if (pa != VM_PAGE_TO_PHYS(p)) + if (pa != VM_PAGE_TO_PHYS(p) || + pat_mode != p->md.pat_mode) return; p = TAILQ_NEXT(p, listq); } - /* Map using 2/4MB pages. */ + /* + * Map using 2/4MB pages. Since "ptepa" is 2/4M aligned and + * "size" is a multiple of 2/4M, adding the PAT setting to + * "pa" will not affect the termination of this loop. + */ PMAP_LOCK(pmap); - for (pa = ptepa; pa < ptepa + size; pa += NBPDR) { + for (pa = ptepa | pmap_cache_bits(pat_mode, 1); pa < ptepa + + size; pa += NBPDR) { pde = pmap_pde(pmap, addr); if (*pde == 0) { pde_store(pde, pa | PG_PS | PG_M | PG_A | @@ -3723,7 +3732,8 @@ pmap_zero_page(vm_page_t m) if (*sysmaps->CMAP2) panic("pmap_zero_page: CMAP2 busy"); sched_pin(); - *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M; + *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | + pmap_cache_bits(m->md.pat_mode, 0); invlcaddr(sysmaps->CADDR2); pagezero(sysmaps->CADDR2); *sysmaps->CMAP2 = 0; @@ -3745,9 +3755,10 @@ pmap_zero_page_area(vm_page_t m, int off sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; mtx_lock(&sysmaps->lock); if (*sysmaps->CMAP2) - panic("pmap_zero_page: CMAP2 busy"); + panic("pmap_zero_page_area: CMAP2 busy"); sched_pin(); - *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M; + *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | + pmap_cache_bits(m->md.pat_mode, 0); invlcaddr(sysmaps->CADDR2); if (off == 0 && size == PAGE_SIZE) pagezero(sysmaps->CADDR2); @@ -3769,9 +3780,10 @@ pmap_zero_page_idle(vm_page_t m) { if (*CMAP3) - panic("pmap_zero_page: CMAP3 busy"); + panic("pmap_zero_page_idle: CMAP3 busy"); sched_pin(); - *CMAP3 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M; + *CMAP3 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | + pmap_cache_bits(m->md.pat_mode, 0); invlcaddr(CADDR3); pagezero(CADDR3); *CMAP3 = 0; @@ -3798,8 +3810,10 @@ pmap_copy_page(vm_page_t src, vm_page_t sched_pin(); invlpg((u_int)sysmaps->CADDR1); invlpg((u_int)sysmaps->CADDR2); - *sysmaps->CMAP1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A; - *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M; + *sysmaps->CMAP1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A | + pmap_cache_bits(src->md.pat_mode, 0); + *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M | + pmap_cache_bits(dst->md.pat_mode, 0); bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE); *sysmaps->CMAP1 = 0; *sysmaps->CMAP2 = 0; @@ -4420,7 +4434,9 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_ pa += PAGE_SIZE; } pmap_invalidate_range(kernel_pmap, va, tmpva); - pmap_invalidate_cache(); + /* If "Self Snoop" is supported, do nothing. */ + if (!(cpu_feature & CPUID_SS)) + pmap_invalidate_cache(); return ((void *)(va + offset)); } @@ -4455,6 +4471,25 @@ pmap_unmapdev(vm_offset_t va, vm_size_t } /* + * Sets the memory attribute for the specified page. + */ +void +pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) +{ + + m->md.pat_mode = ma; + + /* + * If "m" is a normal page, flush it from the cache. + */ + if ((m->flags & PG_FICTITIOUS) == 0) { + /* If "Self Snoop" is supported, do nothing. */ + if (!(cpu_feature & CPUID_SS)) + pmap_invalidate_cache(); + } +} + +/* * Changes the specified virtual address range's memory type to that given by * the parameter "mode". The specified virtual address range must be * completely contained within either the kernel map. Modified: stable/7/sys/i386/include/pmap.h ============================================================================== --- stable/7/sys/i386/include/pmap.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/i386/include/pmap.h Fri Sep 4 19:59:32 2009 (r196838) @@ -332,7 +332,7 @@ struct pv_entry; struct pv_chunk; struct md_page { - int pv_unused; + int pat_mode; TAILQ_HEAD(,pv_entry) pv_list; }; @@ -411,6 +411,7 @@ extern char *ptvmmap; /* poor name! */ extern vm_offset_t virtual_avail; extern vm_offset_t virtual_end; +#define pmap_page_get_memattr(m) ((vm_memattr_t)(m)->md.pat_mode) #define pmap_unmapbios(va, sz) pmap_unmapdev((va), (sz)) void pmap_bootstrap(vm_paddr_t); @@ -423,6 +424,7 @@ void *pmap_mapbios(vm_paddr_t, vm_size_t void *pmap_mapdev(vm_paddr_t, vm_size_t); void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int); boolean_t pmap_page_is_mapped(vm_page_t m); +void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); void pmap_unmapdev(vm_offset_t, vm_size_t); pt_entry_t *pmap_pte(pmap_t, vm_offset_t) __pure2; void pmap_set_pg(void); Copied and modified: stable/7/sys/i386/include/vm.h (from r195033, head/sys/i386/include/vm.h) ============================================================================== --- head/sys/i386/include/vm.h Fri Jun 26 04:47:43 2009 (r195033, copy source) +++ stable/7/sys/i386/include/vm.h Fri Sep 4 19:59:32 2009 (r196838) @@ -32,14 +32,14 @@ #include -/* Cache control options. */ -#define VM_CACHE_UNCACHEABLE ((vm_cache_mode_t)PAT_UNCACHEABLE) -#define VM_CACHE_WRITE_COMBINING ((vm_cache_mode_t)PAT_WRITE_COMBINING) -#define VM_CACHE_WRITE_THROUGH ((vm_cache_mode_t)PAT_WRITE_THROUGH) -#define VM_CACHE_WRITE_PROTECTED ((vm_cache_mode_t)PAT_WRITE_PROTECTED) -#define VM_CACHE_WRITE_BACK ((vm_cache_mode_t)PAT_WRITE_BACK) -#define VM_CACHE_UNCACHED ((vm_cache_mode_t)PAT_UNCACHED) +/* Memory attributes. */ +#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHEABLE) +#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PAT_WRITE_COMBINING) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PAT_WRITE_THROUGH) +#define VM_MEMATTR_WRITE_PROTECTED ((vm_memattr_t)PAT_WRITE_PROTECTED) +#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PAT_WRITE_BACK) +#define VM_MEMATTR_UNCACHED ((vm_memattr_t)PAT_UNCACHED) -#define VM_CACHE_DEFAULT VM_CACHE_WRITE_BACK +#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK #endif /* !_MACHINE_PMAP_H_ */ Modified: stable/7/sys/ia64/include/pmap.h ============================================================================== --- stable/7/sys/ia64/include/pmap.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/ia64/include/pmap.h Fri Sep 4 19:59:32 2009 (r196838) @@ -118,7 +118,9 @@ extern vm_offset_t virtual_end; extern uint64_t pmap_vhpt_base[]; extern int pmap_vhpt_log2size; +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) +#define pmap_page_set_memattr(m, ma) (void)0 #define pmap_mapbios(pa, sz) pmap_mapdev(pa, sz) #define pmap_unmapbios(va, sz) pmap_unmapdev(va, sz) Copied and modified: stable/7/sys/ia64/include/vm.h (from r195033, head/sys/ia64/include/vm.h) ============================================================================== --- head/sys/ia64/include/vm.h Fri Jun 26 04:47:43 2009 (r195033, copy source) +++ stable/7/sys/ia64/include/vm.h Fri Sep 4 19:59:32 2009 (r196838) @@ -32,13 +32,13 @@ #include #include -/* Cache control options. */ -#define VM_CACHE_WRITE_BACK ((vm_cache_mode_t)PTE_MA_WB) -#define VM_CACHE_UNCACHEABLE ((vm_cache_mode_t)PTE_MA_UC) -#define VM_CACHE_UNCACHEABLE_EXPORTED ((vm_cache_mode_t)PTE_MA_UCE) -#define VM_CACHE_WRITE_COMBINING ((vm_cache_mode_t)PTE_MA_WC) -#define VM_CACHE_NATPAGE ((vm_cache_mode_t)PTE_MA_NATPAGE) +/* Memory attributes. */ +#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PTE_MA_WB) +#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PTE_MA_UC) +#define VM_MEMATTR_UNCACHEABLE_EXPORTED ((vm_memattr_t)PTE_MA_UCE) +#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PTE_MA_WC) +#define VM_MEMATTR_NATPAGE ((vm_memattr_t)PTE_MA_NATPAGE) -#define VM_CACHE_DEFAULT VM_CACHE_WRITE_BACK +#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK #endif /* !_MACHINE_PMAP_H_ */ Modified: stable/7/sys/kern/kern_mbuf.c ============================================================================== --- stable/7/sys/kern/kern_mbuf.c Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/kern/kern_mbuf.c Fri Sep 4 19:59:32 2009 (r196838) @@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include #include #include @@ -233,9 +235,6 @@ static void mb_zfini_pack(void *, int); static void mb_reclaim(void *); static void mbuf_init(void *); static void *mbuf_jumbo_alloc(uma_zone_t, int, u_int8_t *, int); -static void mbuf_jumbo_free(void *, int, u_int8_t); - -static MALLOC_DEFINE(M_JUMBOFRAME, "jumboframes", "mbuf jumbo frame buffers"); /* Ensure that MSIZE doesn't break dtom() - it must be a power of 2 */ CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE); @@ -297,7 +296,6 @@ mbuf_init(void *dummy) if (nmbjumbo9 > 0) uma_zone_set_max(zone_jumbo9, nmbjumbo9); uma_zone_set_allocf(zone_jumbo9, mbuf_jumbo_alloc); - uma_zone_set_freef(zone_jumbo9, mbuf_jumbo_free); zone_jumbo16 = uma_zcreate(MBUF_JUMBO16_MEM_NAME, MJUM16BYTES, mb_ctor_clust, mb_dtor_clust, @@ -310,7 +308,6 @@ mbuf_init(void *dummy) if (nmbjumbo16 > 0) uma_zone_set_max(zone_jumbo16, nmbjumbo16); uma_zone_set_allocf(zone_jumbo16, mbuf_jumbo_alloc); - uma_zone_set_freef(zone_jumbo16, mbuf_jumbo_free); zone_ext_refcnt = uma_zcreate(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int), NULL, NULL, @@ -359,18 +356,8 @@ mbuf_jumbo_alloc(uma_zone_t zone, int by /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; - return (contigmalloc(bytes, M_JUMBOFRAME, wait, (vm_paddr_t)0, - ~(vm_paddr_t)0, 1, 0)); -} - -/* - * UMA backend page deallocator for the jumbo frame zones. - */ -static void -mbuf_jumbo_free(void *mem, int size, u_int8_t flags) -{ - - contigfree(mem, size, M_JUMBOFRAME); + return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, + (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0, VM_MEMATTR_DEFAULT)); } /* Modified: stable/7/sys/powerpc/include/pmap.h ============================================================================== --- stable/7/sys/powerpc/include/pmap.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/powerpc/include/pmap.h Fri Sep 4 19:59:32 2009 (r196838) @@ -72,7 +72,9 @@ struct md_page { extern struct pmap kernel_pmap_store; #define kernel_pmap (&kernel_pmap_store) +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!LIST_EMPTY(&(m)->md.mdpg_pvoh)) +#define pmap_page_set_memattr(m, ma) (void)0 #ifdef _KERNEL Copied and modified: stable/7/sys/powerpc/include/vm.h (from r195033, head/sys/powerpc/include/vm.h) ============================================================================== --- head/sys/powerpc/include/vm.h Fri Jun 26 04:47:43 2009 (r195033, copy source) +++ stable/7/sys/powerpc/include/vm.h Fri Sep 4 19:59:32 2009 (r196838) @@ -31,10 +31,12 @@ #include -/* Cache control options. */ -#define VM_CACHE_INHIBIT ((vm_cache_mode_t)PTE_I) -#define VM_CACHE_WRITE_THROUGH ((vm_cache_mode_t)PTE_W) +/* Memory attributes. */ +#define VM_MEMATTR_CACHING_INHIBIT ((vm_memattr_t)PTE_I) +#define VM_MEMATTR_GUARD ((vm_memattr_t)PTE_G) +#define VM_MEMATTR_MEMORY_COHERENCE ((vm_memattr_t)PTE_M) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PTE_W) -#define VM_CACHE_DEFAULT 0 +#define VM_MEMATTR_DEFAULT 0 #endif /* !_MACHINE_PMAP_H_ */ Modified: stable/7/sys/sparc64/include/pmap.h ============================================================================== --- stable/7/sys/sparc64/include/pmap.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/sparc64/include/pmap.h Fri Sep 4 19:59:32 2009 (r196838) @@ -77,6 +77,9 @@ struct pmap { #define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx) #define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx) +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT +#define pmap_page_set_memattr(m, ma) (void)0 + void pmap_bootstrap(vm_offset_t ekva); vm_paddr_t pmap_kextract(vm_offset_t va); void pmap_kenter(vm_offset_t va, vm_page_t m); Copied and modified: stable/7/sys/sparc64/include/vm.h (from r195033, head/sys/sparc64/include/vm.h) ============================================================================== --- head/sys/sparc64/include/vm.h Fri Jun 26 04:47:43 2009 (r195033, copy source) +++ stable/7/sys/sparc64/include/vm.h Fri Sep 4 19:59:32 2009 (r196838) @@ -29,7 +29,7 @@ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ -/* Cache control is not (yet) implemented. */ -#define VM_CACHE_DEFAULT 0 +/* Memory attribute configuration is not (yet) implemented. */ +#define VM_MEMATTR_DEFAULT 0 #endif /* !_MACHINE_PMAP_H_ */ Modified: stable/7/sys/sun4v/include/pmap.h ============================================================================== --- stable/7/sys/sun4v/include/pmap.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/sun4v/include/pmap.h Fri Sep 4 19:59:32 2009 (r196838) @@ -106,7 +106,9 @@ typedef struct pv_entry { TAILQ_ENTRY(pv_entry) pv_plist; } *pv_entry_t; +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) +#define pmap_page_set_memattr(m, ma) (void)0 void pmap_bootstrap(vm_offset_t ekva); vm_paddr_t pmap_kextract(vm_offset_t va); Copied and modified: stable/7/sys/sun4v/include/vm.h (from r195033, head/sys/sun4v/include/vm.h) ============================================================================== --- head/sys/sun4v/include/vm.h Fri Jun 26 04:47:43 2009 (r195033, copy source) +++ stable/7/sys/sun4v/include/vm.h Fri Sep 4 19:59:32 2009 (r196838) @@ -29,7 +29,7 @@ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ -/* Cache control is not (yet) implemented. */ -#define VM_CACHE_DEFAULT 0 +/* Memory attribute configuration is not (yet) implemented. */ +#define VM_MEMATTR_DEFAULT 0 #endif /* !_MACHINE_PMAP_H_ */ Modified: stable/7/sys/sun4v/sun4v/pmap.c ============================================================================== --- stable/7/sys/sun4v/sun4v/pmap.c Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/sun4v/sun4v/pmap.c Fri Sep 4 19:59:32 2009 (r196838) @@ -1298,7 +1298,7 @@ pmap_alloc_zeroed_contig_pages(int npage while (m == NULL) { for (i = 0; phys_avail[i + 1] != 0; i += 2) { m = vm_phys_alloc_contig(npages, phys_avail[i], - phys_avail[i + 1], alignment, (1UL<<34)); + phys_avail[i + 1], alignment, (1UL<<34)); if (m) goto found; } Modified: stable/7/sys/vm/device_pager.c ============================================================================== --- stable/7/sys/vm/device_pager.c Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/vm/device_pager.c Fri Sep 4 19:59:32 2009 (r196838) @@ -70,9 +70,9 @@ static struct mtx dev_pager_mtx; static uma_zone_t fakepg_zone; -static vm_page_t dev_pager_getfake(vm_paddr_t); +static vm_page_t dev_pager_getfake(vm_paddr_t, vm_memattr_t); static void dev_pager_putfake(vm_page_t); -static void dev_pager_updatefake(vm_page_t, vm_paddr_t); +static void dev_pager_updatefake(vm_page_t, vm_paddr_t, vm_memattr_t); struct pagerops devicepagerops = { .pgo_init = dev_pager_init, @@ -194,7 +194,7 @@ dev_pager_dealloc(object) /* * Free up our fake pages. */ - while ((m = TAILQ_FIRST(&object->un_pager.devp.devp_pglist)) != 0) { + while ((m = TAILQ_FIRST(&object->un_pager.devp.devp_pglist)) != NULL) { TAILQ_REMOVE(&object->un_pager.devp.devp_pglist, m, pageq); dev_pager_putfake(m); } @@ -209,7 +209,8 @@ dev_pager_getpages(object, m, count, req { vm_pindex_t offset; vm_paddr_t paddr; - vm_page_t page; + vm_page_t m_paddr, page; + vm_memattr_t memattr; struct cdev *dev; int i, ret; int prot; @@ -219,7 +220,9 @@ dev_pager_getpages(object, m, count, req VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); dev = object->handle; - offset = m[reqpage]->pindex; + page = m[reqpage]; + offset = page->pindex; + memattr = object->memattr; VM_OBJECT_UNLOCK(object); csw = dev_refthread(dev); if (csw == NULL) @@ -233,14 +236,20 @@ dev_pager_getpages(object, m, count, req KASSERT(ret == 0, ("dev_pager_getpage: map function returns error")); td->td_fpop = fpop; dev_relthread(dev); - - if ((m[reqpage]->flags & PG_FICTITIOUS) != 0) { + /* If "paddr" is a real page, perform a sanity check on "memattr". */ + if ((m_paddr = vm_phys_paddr_to_vm_page(paddr)) != NULL && + pmap_page_get_memattr(m_paddr) != memattr) { + memattr = pmap_page_get_memattr(m_paddr); + printf( + "WARNING: A device driver has set \"memattr\" inconsistently.\n"); + } + if ((page->flags & PG_FICTITIOUS) != 0) { /* * If the passed in reqpage page is a fake page, update it with * the new physical address. */ VM_OBJECT_LOCK(object); - dev_pager_updatefake(m[reqpage], paddr); + dev_pager_updatefake(page, paddr, memattr); if (count > 1) { vm_page_lock_queues(); for (i = 0; i < count; i++) { @@ -254,7 +263,7 @@ dev_pager_getpages(object, m, count, req * Replace the passed in reqpage page with our own fake page and * free up the all of the original pages. */ - page = dev_pager_getfake(paddr); + page = dev_pager_getfake(paddr, memattr); VM_OBJECT_LOCK(object); TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist, page, pageq); vm_page_lock_queues(); @@ -264,7 +273,7 @@ dev_pager_getpages(object, m, count, req vm_page_insert(page, object, offset); m[reqpage] = page; } - + page->valid = VM_PAGE_BITS_ALL; return (VM_PAGER_OK); } @@ -294,48 +303,48 @@ dev_pager_haspage(object, pindex, before } /* - * Instantiate a fictitious page. Unlike physical memory pages, only - * the machine-independent fields must be initialized. + * Create a fictitious page with the specified physical address and memory + * attribute. The memory attribute is the only the machine-dependent aspect + * of a fictitious page that must be initialized. */ static vm_page_t -dev_pager_getfake(paddr) - vm_paddr_t paddr; +dev_pager_getfake(vm_paddr_t paddr, vm_memattr_t memattr) { vm_page_t m; - m = uma_zalloc(fakepg_zone, M_WAITOK); - + m = uma_zalloc(fakepg_zone, M_WAITOK | M_ZERO); + m->phys_addr = paddr; + /* Fictitious pages don't use "segind". */ m->flags = PG_FICTITIOUS; + /* Fictitious pages don't use "order" or "pool". */ m->oflags = VPO_BUSY; - m->valid = VM_PAGE_BITS_ALL; - m->dirty = 0; - m->busy = 0; - m->queue = PQ_NONE; - m->object = NULL; - m->wire_count = 1; - m->hold_count = 0; - m->phys_addr = paddr; - + pmap_page_set_memattr(m, memattr); return (m); } +/* + * Release a fictitious page. + */ static void -dev_pager_putfake(m) - vm_page_t m; +dev_pager_putfake(vm_page_t m) { + if (!(m->flags & PG_FICTITIOUS)) panic("dev_pager_putfake: bad page"); uma_zfree(fakepg_zone, m); } +/* + * Update the given fictitious page to the specified physical address and + * memory attribute. + */ static void -dev_pager_updatefake(m, paddr) - vm_page_t m; - vm_paddr_t paddr; +dev_pager_updatefake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr) { + if (!(m->flags & PG_FICTITIOUS)) panic("dev_pager_updatefake: bad page"); m->phys_addr = paddr; - m->valid = VM_PAGE_BITS_ALL; + pmap_page_set_memattr(m, memattr); } Modified: stable/7/sys/vm/pmap.h ============================================================================== --- stable/7/sys/vm/pmap.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/vm/pmap.h Fri Sep 4 19:59:32 2009 (r196838) @@ -79,10 +79,16 @@ struct pmap_statistics { }; typedef struct pmap_statistics *pmap_statistics_t; +/* + * Each machine dependent implementation is expected to provide: + * + * vm_memattr_t pmap_page_get_memattr(vm_page_t); + * boolean_t pmap_page_is_mapped(vm_page_t); + * void pmap_page_set_memattr(vm_page_t, vm_memattr_t); + */ #include #ifdef _KERNEL -struct proc; struct thread; /* Modified: stable/7/sys/vm/vm.h ============================================================================== --- stable/7/sys/vm/vm.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/vm/vm.h Fri Sep 4 19:59:32 2009 (r196838) @@ -61,6 +61,14 @@ #ifndef VM_H #define VM_H +#include + +/* + * The exact set of memory attributes is machine dependent. However, every + * machine is required to define VM_MEMATTR_DEFAULT. + */ +typedef char vm_memattr_t; /* memory attribute codes */ + typedef char vm_inherit_t; /* inheritance codes */ #define VM_INHERIT_SHARE ((vm_inherit_t) 0) Modified: stable/7/sys/vm/vm_contig.c ============================================================================== --- stable/7/sys/vm/vm_contig.c Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/vm/vm_contig.c Fri Sep 4 19:59:32 2009 (r196838) @@ -193,37 +193,37 @@ vm_page_release_contig(vm_page_t m, vm_p * specified through the given flags, then the pages are zeroed * before they are mapped. */ -static void * -contigmapping(vm_page_t m, vm_pindex_t npages, int flags) +static vm_offset_t +contigmapping(vm_map_t map, vm_size_t size, vm_page_t m, vm_memattr_t memattr, + int flags) { vm_object_t object = kernel_object; - vm_map_t map = kernel_map; vm_offset_t addr, tmp_addr; - vm_pindex_t i; vm_map_lock(map); - if (vm_map_findspace(map, vm_map_min(map), npages << PAGE_SHIFT, &addr) - != KERN_SUCCESS) { + if (vm_map_findspace(map, vm_map_min(map), size, &addr)) { vm_map_unlock(map); - return (NULL); + return (0); } vm_object_reference(object); vm_map_insert(map, object, addr - VM_MIN_KERNEL_ADDRESS, - addr, addr + (npages << PAGE_SHIFT), VM_PROT_ALL, VM_PROT_ALL, 0); + addr, addr + size, VM_PROT_ALL, VM_PROT_ALL, 0); vm_map_unlock(map); - tmp_addr = addr; VM_OBJECT_LOCK(object); - for (i = 0; i < npages; i++) { - vm_page_insert(&m[i], object, + for (tmp_addr = addr; tmp_addr < addr + size; tmp_addr += PAGE_SIZE) { + if (memattr != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, memattr); + vm_page_insert(m, object, OFF_TO_IDX(tmp_addr - VM_MIN_KERNEL_ADDRESS)); - if ((flags & M_ZERO) && !(m[i].flags & PG_ZERO)) - pmap_zero_page(&m[i]); - tmp_addr += PAGE_SIZE; + if ((flags & M_ZERO) && (m->flags & PG_ZERO) == 0) + pmap_zero_page(m); + m->valid = VM_PAGE_BITS_ALL; + m++; } VM_OBJECT_UNLOCK(object); - vm_map_wire(map, addr, addr + (npages << PAGE_SHIFT), + vm_map_wire(map, addr, addr + size, VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES); - return ((void *)addr); + return (addr); } void * @@ -237,11 +237,26 @@ contigmalloc( unsigned long boundary) { void *ret; + + ret = (void *)kmem_alloc_contig(kernel_map, size, flags, low, high, + alignment, boundary, VM_MEMATTR_DEFAULT); + if (ret != NULL) + malloc_type_allocated(type, round_page(size)); + return (ret); +} + +vm_offset_t +kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low, + vm_paddr_t high, unsigned long alignment, unsigned long boundary, + vm_memattr_t memattr) +{ + vm_offset_t ret; vm_page_t pages; unsigned long npgs; int actl, actmax, inactl, inactmax, tries; - npgs = round_page(size) >> PAGE_SHIFT; + size = round_page(size); + npgs = size >> PAGE_SHIFT; tries = 0; retry: pages = vm_phys_alloc_contig(npgs, low, high, alignment, boundary); @@ -267,13 +282,11 @@ again: tries++; goto retry; } - ret = NULL; + ret = 0; } else { - ret = contigmapping(pages, npgs, flags); - if (ret == NULL) + ret = contigmapping(map, size, pages, memattr, flags); + if (ret == 0) vm_page_release_contig(pages, npgs); - else - malloc_type_allocated(type, npgs << PAGE_SHIFT); } return (ret); } @@ -281,9 +294,7 @@ again: void contigfree(void *addr, unsigned long size, struct malloc_type *type) { - vm_pindex_t npgs; - npgs = round_page(size) >> PAGE_SHIFT; kmem_free(kernel_map, (vm_offset_t)addr, size); - malloc_type_freed(type, npgs << PAGE_SHIFT); + malloc_type_freed(type, round_page(size)); } Modified: stable/7/sys/vm/vm_extern.h ============================================================================== --- stable/7/sys/vm/vm_extern.h Fri Sep 4 19:20:46 2009 (r196837) +++ stable/7/sys/vm/vm_extern.h Fri Sep 4 19:59:32 2009 (r196838) @@ -57,6 +57,9 @@ int swapon(struct thread *, void *, int int kernacc(void *, int, int); vm_offset_t kmem_alloc(vm_map_t, vm_size_t); +vm_offset_t kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, + vm_paddr_t low, vm_paddr_t high, unsigned long alignment, + unsigned long boundary, vm_memattr_t memattr); vm_offset_t kmem_alloc_nofault(vm_map_t, vm_size_t); vm_offset_t kmem_alloc_wait(vm_map_t, vm_size_t); void kmem_free(vm_map_t, vm_offset_t, vm_size_t); Modified: stable/7/sys/vm/vm_object.c ============================================================================== --- stable/7/sys/vm/vm_object.c Fri Sep 4 19:20:46 2009 (r196837) *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-stable-7@FreeBSD.ORG Sat Sep 5 05:28:07 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BEB561065679; Sat, 5 Sep 2009 05:28:07 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id AC1848FC0C; Sat, 5 Sep 2009 05:28:07 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n855S7ZY038176; Sat, 5 Sep 2009 05:28:07 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n855S7M0038174; Sat, 5 Sep 2009 05:28:07 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <200909050528.n855S7M0038174@svn.freebsd.org> From: Alan Cox Date: Sat, 5 Sep 2009 05:28:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196852 - in stable/7/sys: . contrib/pf pc98/include X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Sep 2009 05:28:07 -0000 Author: alc Date: Sat Sep 5 05:28:07 2009 New Revision: 196852 URL: http://svn.freebsd.org/changeset/base/196852 Log: MFC r195089 Add stub vm.h for pc98. Added: stable/7/sys/pc98/include/vm.h - copied unchanged from r195089, head/sys/pc98/include/vm.h Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) Copied: stable/7/sys/pc98/include/vm.h (from r195089, head/sys/pc98/include/vm.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/7/sys/pc98/include/vm.h Sat Sep 5 05:28:07 2009 (r196852, copy of r195089, head/sys/pc98/include/vm.h) @@ -0,0 +1,6 @@ +/*- + * This file is in the public domain. + */ +/* $FreeBSD$ */ + +#include From owner-svn-src-stable-7@FreeBSD.ORG Sat Sep 5 05:57:44 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8FD6E106566C; Sat, 5 Sep 2009 05:57:44 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 63A948FC0A; Sat, 5 Sep 2009 05:57:44 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n855vius038789; Sat, 5 Sep 2009 05:57:44 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n855viT4038786; Sat, 5 Sep 2009 05:57:44 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <200909050557.n855viT4038786@svn.freebsd.org> From: Alan Cox Date: Sat, 5 Sep 2009 05:57:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196853 - in stable/7/sys: . contrib/pf i386/include X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Sep 2009 05:57:44 -0000 Author: alc Date: Sat Sep 5 05:57:44 2009 New Revision: 196853 URL: http://svn.freebsd.org/changeset/base/196853 Log: MFC r194295 Move (read|write)_cyrix_reg() inlines from specialreg.h to cpufunc.h. specialreg.h now consists solely of register-related macros. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/i386/include/cpufunc.h stable/7/sys/i386/include/specialreg.h Modified: stable/7/sys/i386/include/cpufunc.h ============================================================================== --- stable/7/sys/i386/include/cpufunc.h Sat Sep 5 05:28:07 2009 (r196852) +++ stable/7/sys/i386/include/cpufunc.h Sat Sep 5 05:57:44 2009 (r196853) @@ -646,6 +646,20 @@ load_dr7(u_int dr7) __asm __volatile("movl %0,%%dr7" : : "r" (dr7)); } +static __inline u_char +read_cyrix_reg(u_char reg) +{ + outb(0x22, reg); + return inb(0x23); +} + +static __inline void +write_cyrix_reg(u_char reg, u_char data) +{ + outb(0x22, reg); + outb(0x23, data); +} + static __inline register_t intr_disable(void) { @@ -720,6 +734,7 @@ u_int rdr5(void); u_int rdr6(void); u_int rdr7(void); uint64_t rdtsc(void); +u_char read_cyrix_reg(u_char reg); u_int read_eflags(void); u_int rfs(void); uint64_t rgdt(void); @@ -728,6 +743,7 @@ uint64_t ridt(void); u_short rldt(void); u_short rtr(void); void wbinvd(void); +void write_cyrix_reg(u_char reg, u_char data); void write_eflags(u_int ef); void wrmsr(u_int msr, uint64_t newval); Modified: stable/7/sys/i386/include/specialreg.h ============================================================================== --- stable/7/sys/i386/include/specialreg.h Sat Sep 5 05:28:07 2009 (r196852) +++ stable/7/sys/i386/include/specialreg.h Sat Sep 5 05:57:44 2009 (r196853) @@ -540,20 +540,4 @@ #define VIA_CRYPT_CWLO_KEY192 0x0000040c /* 192bit, 12 rds */ #define VIA_CRYPT_CWLO_KEY256 0x0000080e /* 256bit, 15 rds */ -#ifndef LOCORE -static __inline u_char -read_cyrix_reg(u_char reg) -{ - outb(0x22, reg); - return inb(0x23); -} - -static __inline void -write_cyrix_reg(u_char reg, u_char data) -{ - outb(0x22, reg); - outb(0x23, data); -} -#endif - #endif /* !_MACHINE_SPECIALREG_H_ */ From owner-svn-src-stable-7@FreeBSD.ORG Sat Sep 5 13:31:16 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6EF25106568F; Sat, 5 Sep 2009 13:31:16 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 5D6808FC14; Sat, 5 Sep 2009 13:31:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n85DVGdh054246; Sat, 5 Sep 2009 13:31:16 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n85DVGPb054244; Sat, 5 Sep 2009 13:31:16 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200909051331.n85DVGPb054244@svn.freebsd.org> From: Konstantin Belousov Date: Sat, 5 Sep 2009 13:31:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196860 - in stable/7/sys: . contrib/pf fs/pseudofs X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Sep 2009 13:31:16 -0000 Author: kib Date: Sat Sep 5 13:31:16 2009 New Revision: 196860 URL: http://svn.freebsd.org/changeset/base/196860 Log: MFC r196689: Remove spurious pfs_unlock(). Approved by: re (rwatson) Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/fs/pseudofs/pseudofs_vnops.c Modified: stable/7/sys/fs/pseudofs/pseudofs_vnops.c ============================================================================== --- stable/7/sys/fs/pseudofs/pseudofs_vnops.c Sat Sep 5 13:10:54 2009 (r196859) +++ stable/7/sys/fs/pseudofs/pseudofs_vnops.c Sat Sep 5 13:31:16 2009 (r196860) @@ -339,7 +339,6 @@ pfs_getextattr(struct vop_getextattr_arg if (proc != NULL) PROC_UNLOCK(proc); - pfs_unlock(pn); PFS_RETURN (error); } From owner-svn-src-stable-7@FreeBSD.ORG Sat Sep 5 18:44:36 2009 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D15C11065672; Sat, 5 Sep 2009 18:44:36 +0000 (UTC) (envelope-from rodrigc@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C036C8FC0A; Sat, 5 Sep 2009 18:44:36 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n85Iiajq061375; Sat, 5 Sep 2009 18:44:36 GMT (envelope-from rodrigc@svn.freebsd.org) Received: (from rodrigc@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n85IiaNs061373; Sat, 5 Sep 2009 18:44:36 GMT (envelope-from rodrigc@svn.freebsd.org) Message-Id: <200909051844.n85IiaNs061373@svn.freebsd.org> From: Craig Rodrigues Date: Sat, 5 Sep 2009 18:44:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196870 - stable/7/etc/rc.d X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Sep 2009 18:44:36 -0000 Author: rodrigc Date: Sat Sep 5 18:44:36 2009 New Revision: 196870 URL: http://svn.freebsd.org/changeset/base/196870 Log: This set of MFC's brings savecore closer to the trunk version. Now, crashinfo will only be run if the following conditions are true: - savecore -C determines that a crash dump exists - crashinfo_enable="YES" MFC: 182460 Add the ability to run /usr/sbin/crashinfo on a new core dump automatically during boot. MFC: 180318 Remove the $DUMPDIR variable. It's redundant and the rest of the script uses $dumpdir directly. MFC: 180317 Make checking for the availability of core dumps work in the case that $dumpdev is not set to "AUTO". Modified: stable/7/etc/rc.d/savecore Modified: stable/7/etc/rc.d/savecore ============================================================================== --- stable/7/etc/rc.d/savecore Sat Sep 5 17:40:27 2009 (r196869) +++ stable/7/etc/rc.d/savecore Sat Sep 5 18:44:36 2009 (r196870) @@ -52,10 +52,25 @@ savecore_prestart() savecore_start() { + local dev + + case "${dumpdev}" in + [Aa][Uu][Tt][Oo]) + dev= + ;; + *) + dev="${dumpdev}" + ;; + esac + echo "Checking for core dump on ${dumpdev}..." - savecore ${savecore_flags} ${dumpdir} ${dumpdev} - if checkyesno crashinfo_enable; then - ${crashinfo_program} -d ${dumpdir} + if savecore -C "${dumpdir}" "${dev}" >/dev/null; then + savecore ${savecore_flags} ${dumpdir} ${dumpdev} + if checkyesno crashinfo_enable; then + ${crashinfo_program} -d ${dumpdir} + fi + else + [ -z "${rc_quiet}" ] && echo "No core dumps found" fi }