From owner-svn-src-stable-10@FreeBSD.ORG Thu Jul 17 02:14:28 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 6864BB5E; Thu, 17 Jul 2014 02:14:28 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 52D1E2CE6; Thu, 17 Jul 2014 02:14:28 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6H2ES9N055903; Thu, 17 Jul 2014 02:14:28 GMT (envelope-from pfg@svn.freebsd.org) Received: (from pfg@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6H2EPnQ055888; Thu, 17 Jul 2014 02:14:25 GMT (envelope-from pfg@svn.freebsd.org) Message-Id: <201407170214.s6H2EPnQ055888@svn.freebsd.org> From: "Pedro F. Giffuni" Date: Thu, 17 Jul 2014 02:14:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268782 - in stable/10/lib/libedit: . TEST X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jul 2014 02:14:28 -0000 Author: pfg Date: Thu Jul 17 02:14:25 2014 New Revision: 268782 URL: http://svnweb.freebsd.org/changeset/base/268782 Log: MFC r268502: Sync some (mostly cosmetical) changes from NetBSD Makefile,v 1.37 tc1.c v 1.3 Rename TEST/test.c tc1.c common.c,v 1.23 pass lint on _LP64. emacs.c,v 1.22 pass lint on _LP64. filecomplete.h,v 1.8 mv NetBSD ID back from 1.9 as we don't have the widecharacter support. prompt.c,v 1.14 prompt.h,v 1.9 term.h,v 1.20 read.h,v 1.6 Update NetBSD version strings sys.h,v 1.12 Misc sun stuff. tty.c 1.31 handle EINTR in the termios operations Allow a single process to control multiple ttys (for pthreads using _REENTRANT) using multiple EditLine objects. pass lint on _LP64. Don't depend on side effects inside an assert Obtained from: NetBSD Added: stable/10/lib/libedit/TEST/tc1.c - copied unchanged from r268502, head/lib/libedit/TEST/tc1.c Deleted: stable/10/lib/libedit/TEST/test.c Modified: stable/10/lib/libedit/Makefile stable/10/lib/libedit/common.c stable/10/lib/libedit/emacs.c stable/10/lib/libedit/filecomplete.h stable/10/lib/libedit/histedit.h stable/10/lib/libedit/prompt.c stable/10/lib/libedit/prompt.h stable/10/lib/libedit/read.h stable/10/lib/libedit/sys.h stable/10/lib/libedit/term.h stable/10/lib/libedit/tty.c Directory Properties: stable/10/ (props changed) Modified: stable/10/lib/libedit/Makefile ============================================================================== --- stable/10/lib/libedit/Makefile Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/Makefile Thu Jul 17 02:14:25 2014 (r268782) @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.34 2005/05/28 12:02:53 lukem Exp $ +# $NetBSD: Makefile,v 1.37 2009/01/18 12:17:49 lukem Exp $ # @(#)Makefile 8.1 (Berkeley) 6/4/93 # $FreeBSD$ @@ -70,9 +70,9 @@ editline.c: ${OSRCS} editline.o editline.po editline.So editline.ln: \ common.h emacs.h fcns.c fcns.h help.c help.h vi.h -test.o: ${.CURDIR}/TEST/test.c +tc1.o: ${.CURDIR}/TEST/tc1.c -test: test.o libedit.a ${DPADD} ${LIBTERMCAP} +test: tc1.o libedit.a ${DPADD} ${LIBTERMCAP} ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} .include Copied: stable/10/lib/libedit/TEST/tc1.c (from r268502, head/lib/libedit/TEST/tc1.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/lib/libedit/TEST/tc1.c Thu Jul 17 02:14:25 2014 (r268782, copy of r268502, head/lib/libedit/TEST/tc1.c) @@ -0,0 +1,298 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Christos Zoulas of Cornell University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ + The Regents of the University of California. All rights reserved.\n"); +#endif /* not lint */ + +#if !defined(lint) && !defined(SCCSID) +static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint && not SCCSID */ +__RCSID("$NetBSD: test.c,v 1.3 2009/07/17 12:25:52 christos Exp $"); +__FBSDID("$FreeBSD$"); + +/* + * test.c: A little test program + */ +#include "sys.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "histedit.h" + +static int continuation = 0; +volatile sig_atomic_t gotsig = 0; + +static unsigned char complete(EditLine *, int); + int main(int, char **); +static char *prompt(EditLine *); +static void sig(int); + +static char * +prompt(EditLine *el) +{ + static char a[] = "\1\e[7m\1Edit$\1\e[0m\1 "; + static char b[] = "Edit> "; + + return (continuation ? b : a); +} + +static void +sig(int i) +{ + gotsig = i; +} + +static unsigned char +complete(EditLine *el, int ch) +{ + DIR *dd = opendir("."); + struct dirent *dp; + const char* ptr; + const LineInfo *lf = el_line(el); + int len; + + /* + * Find the last word + */ + for (ptr = lf->cursor - 1; + !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--) + continue; + len = lf->cursor - ++ptr; + + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (len > strlen(dp->d_name)) + continue; + if (strncmp(dp->d_name, ptr, len) == 0) { + closedir(dd); + if (el_insertstr(el, &dp->d_name[len]) == -1) + return (CC_ERROR); + else + return (CC_REFRESH); + } + } + + closedir(dd); + return (CC_ERROR); +} + +int +main(int argc, char *argv[]) +{ + EditLine *el = NULL; + int num; + const char *buf; + Tokenizer *tok; +#if 0 + int lastevent = 0; +#endif + int ncontinuation; + History *hist; + HistEvent ev; + + (void) signal(SIGINT, sig); + (void) signal(SIGQUIT, sig); + (void) signal(SIGHUP, sig); + (void) signal(SIGTERM, sig); + + hist = history_init(); /* Init the builtin history */ + /* Remember 100 events */ + history(hist, &ev, H_SETSIZE, 100); + + tok = tok_init(NULL); /* Initialize the tokenizer */ + + /* Initialize editline */ + el = el_init(*argv, stdin, stdout, stderr); + + el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */ + el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */ + el_set(el, EL_PROMPT_ESC, prompt, '\1');/* Set the prompt function */ + + /* Tell editline to use this history interface */ + el_set(el, EL_HIST, history, hist); + + /* Add a user-defined function */ + el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); + + /* Bind tab to it */ + el_set(el, EL_BIND, "^I", "ed-complete", NULL); + + /* + * Bind j, k in vi command mode to previous and next line, instead + * of previous and next history. + */ + el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL); + el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL); + + /* + * Source the user's defaults file. + */ + el_source(el, NULL); + + while ((buf = el_gets(el, &num)) != NULL && num != 0) { + int ac, cc, co; +#ifdef DEBUG + int i; +#endif + const char **av; + const LineInfo *li; + li = el_line(el); +#ifdef DEBUG + (void) fprintf(stderr, "==> got %d %s", num, buf); + (void) fprintf(stderr, " > li `%.*s_%.*s'\n", + (li->cursor - li->buffer), li->buffer, + (li->lastchar - 1 - li->cursor), + (li->cursor >= li->lastchar) ? "" : li->cursor); + +#endif + if (gotsig) { + (void) fprintf(stderr, "Got signal %d.\n", (int)gotsig); + gotsig = 0; + el_reset(el); + } + + if (!continuation && num == 1) + continue; + + ac = cc = co = 0; + ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co); + if (ncontinuation < 0) { + (void) fprintf(stderr, "Internal error\n"); + continuation = 0; + continue; + } +#ifdef DEBUG + (void) fprintf(stderr, " > nc %d ac %d cc %d co %d\n", + ncontinuation, ac, cc, co); +#endif +#if 0 + if (continuation) { + /* + * Append to the right event in case the user + * moved around in history. + */ + if (history(hist, &ev, H_SET, lastevent) == -1) + err(1, "%d: %s", lastevent, ev.str); + history(hist, &ev, H_ADD , buf); + } else { + history(hist, &ev, H_ENTER, buf); + lastevent = ev.num; + } +#else + /* Simpler */ + history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf); +#endif + + continuation = ncontinuation; + ncontinuation = 0; + if (continuation) + continue; +#ifdef DEBUG + for (i = 0; i < ac; i++) { + (void) fprintf(stderr, " > arg# %2d ", i); + if (i != cc) + (void) fprintf(stderr, "`%s'\n", av[i]); + else + (void) fprintf(stderr, "`%.*s_%s'\n", + co, av[i], av[i] + co); + } +#endif + + if (strcmp(av[0], "history") == 0) { + int rv; + + switch (ac) { + case 1: + for (rv = history(hist, &ev, H_LAST); rv != -1; + rv = history(hist, &ev, H_PREV)) + (void) fprintf(stdout, "%4d %s", + ev.num, ev.str); + break; + + case 2: + if (strcmp(av[1], "clear") == 0) + history(hist, &ev, H_CLEAR); + else + goto badhist; + break; + + case 3: + if (strcmp(av[1], "load") == 0) + history(hist, &ev, H_LOAD, av[2]); + else if (strcmp(av[1], "save") == 0) + history(hist, &ev, H_SAVE, av[2]); + break; + + badhist: + default: + (void) fprintf(stderr, + "Bad history arguments\n"); + break; + } + } else if (el_parse(el, ac, av) == -1) { + switch (fork()) { + case 0: + execvp(av[0], __DECONST(char *const *, av)); + perror(av[0]); + _exit(1); + /*NOTREACHED*/ + break; + + case -1: + perror("fork"); + break; + + default: + if (wait(&num) == -1) + perror("wait"); + (void) fprintf(stderr, "Exit %x\n", num); + break; + } + } + + tok_reset(tok); + } + + el_end(el); + tok_end(tok); + history_end(hist); + + return (0); +} Modified: stable/10/lib/libedit/common.c ============================================================================== --- stable/10/lib/libedit/common.c Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/common.c Thu Jul 17 02:14:25 2014 (r268782) @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: common.c,v 1.19 2006/03/06 21:11:56 christos Exp $ + * $NetBSD: common.c,v 1.23 2009/02/27 04:18:45 msaitoh Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -121,7 +121,7 @@ ed_delete_prev_word(EditLine *el, int c *kp++ = *p; el->el_chared.c_kill.last = kp; - c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */ + c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */ el->el_line.cursor = cp; if (el->el_line.cursor < el->el_line.buffer) el->el_line.cursor = el->el_line.buffer; /* bounds check */ @@ -208,9 +208,6 @@ ed_move_to_end(EditLine *el, int c __unu el->el_line.cursor = el->el_line.lastchar; if (el->el_map.type == MAP_VI) { -#ifdef VI_MOVE - el->el_line.cursor--; -#endif if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); Modified: stable/10/lib/libedit/emacs.c ============================================================================== --- stable/10/lib/libedit/emacs.c Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/emacs.c Thu Jul 17 02:14:25 2014 (r268782) @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $ + * $NetBSD: emacs.c,v 1.22 2009/02/15 21:55:23 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -101,7 +101,7 @@ em_delete_next_word(EditLine *el, int c *kp++ = *p; el->el_chared.c_kill.last = kp; - c_delafter(el, cp - el->el_line.cursor); /* delete after dot */ + c_delafter(el, (int)(cp - el->el_line.cursor)); /* delete after dot */ if (el->el_line.cursor > el->el_line.lastchar) el->el_line.cursor = el->el_line.lastchar; /* bounds check */ @@ -131,7 +131,8 @@ em_yank(EditLine *el, int c __unused) cp = el->el_line.cursor; /* open the space, */ - c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf); + c_insert(el, + (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf)); /* copy the chars */ for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++) *cp++ = *kp; @@ -185,14 +186,14 @@ em_kill_region(EditLine *el, int c __unu while (cp < el->el_chared.c_kill.mark) *kp++ = *cp++; /* copy it */ el->el_chared.c_kill.last = kp; - c_delafter(el, cp - el->el_line.cursor); + c_delafter(el, (int)(cp - el->el_line.cursor)); } else { /* mark is before cursor */ cp = el->el_chared.c_kill.mark; kp = el->el_chared.c_kill.buf; while (cp < el->el_line.cursor) *kp++ = *cp++; /* copy it */ el->el_chared.c_kill.last = kp; - c_delbefore(el, cp - el->el_chared.c_kill.mark); + c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark)); el->el_line.cursor = el->el_chared.c_kill.mark; } return (CC_REFRESH); @@ -446,7 +447,7 @@ em_copy_prev_word(EditLine *el, int c __ cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, el->el_state.argument, ce__isword); - c_insert(el, oldc - cp); + c_insert(el, (int)(oldc - cp)); for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++) *dp++ = *cp; Modified: stable/10/lib/libedit/filecomplete.h ============================================================================== --- stable/10/lib/libedit/filecomplete.h Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/filecomplete.h Thu Jul 17 02:14:25 2014 (r268782) @@ -26,7 +26,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $NetBSD: filecomplete.h,v 1.9 2009/12/30 22:37:40 christos Exp $ + * $NetBSD: filecomplete.h,v 1.8 2009/02/16 00:15:45 christos Exp $ * $FreeBSD$ */ #ifndef _FILECOMPLETE_H_ Modified: stable/10/lib/libedit/histedit.h ============================================================================== --- stable/10/lib/libedit/histedit.h Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/histedit.h Thu Jul 17 02:14:25 2014 (r268782) @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)histedit.h 8.2 (Berkeley) 1/3/94 - * $NetBSD: histedit.h,v 1.32 2007/06/10 20:20:28 christos Exp $ + * $NetBSD: histedit.h,v 1.41 2009/09/07 21:24:33 christos Exp $ * $FreeBSD$ */ Modified: stable/10/lib/libedit/prompt.c ============================================================================== --- stable/10/lib/libedit/prompt.c Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/prompt.c Thu Jul 17 02:14:25 2014 (r268782) @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $ + * $NetBSD: prompt.c,v 1.14 2009/03/31 17:38:27 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) Modified: stable/10/lib/libedit/prompt.h ============================================================================== --- stable/10/lib/libedit/prompt.h Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/prompt.h Thu Jul 17 02:14:25 2014 (r268782) @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)prompt.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: prompt.h,v 1.6 2003/08/07 16:44:32 agc Exp $ + * $NetBSD: prompt.h,v 1.9 2009/03/31 17:38:27 christos Exp $ * $FreeBSD$ */ @@ -45,8 +45,8 @@ typedef char * (*el_pfunc_t)(EditLine*); typedef struct el_prompt_t { - el_pfunc_t p_func; /* Function to return the prompt */ - coord_t p_pos; /* position in the line after prompt */ + el_pfunc_t p_func; /* Function to return the prompt */ + coord_t p_pos; /* position in the line after prompt */ char p_ignore; /* character to start/end literal */ } el_prompt_t; Modified: stable/10/lib/libedit/read.h ============================================================================== --- stable/10/lib/libedit/read.h Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/read.h Thu Jul 17 02:14:25 2014 (r268782) @@ -26,7 +26,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $NetBSD: read.h,v 1.5 2006/08/21 12:45:30 christos Exp $ + * $NetBSD: read.h,v 1.6 2008/04/29 06:53:01 martin Exp $ * $FreeBSD$ */ Modified: stable/10/lib/libedit/sys.h ============================================================================== --- stable/10/lib/libedit/sys.h Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/sys.h Thu Jul 17 02:14:25 2014 (r268782) @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)sys.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: sys.h,v 1.9 2004/01/17 17:57:40 christos Exp $ + * $NetBSD: sys.h,v 1.12 2009/08/31 00:05:43 christos Exp $ * $FreeBSD$ */ @@ -70,6 +70,15 @@ typedef void *ioctl_t; #define REGEX /* Use POSIX.2 regular expression functions */ #undef REGEXP /* Use UNIX V8 regular expression functions */ +#if defined(__sun) +extern int tgetent(char *, const char *); +extern int tgetflag(char *); +extern int tgetnum(char *); +extern int tputs(const char *, int, int (*)(int)); +extern char* tgoto(const char*, int, int); +extern char* tgetstr(char*, char**); +#endif + #ifdef notdef # undef REGEX # undef REGEXP Modified: stable/10/lib/libedit/term.h ============================================================================== --- stable/10/lib/libedit/term.h Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/term.h Thu Jul 17 02:14:25 2014 (r268782) @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)term.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: term.h,v 1.18 2006/11/24 00:01:17 christos Exp $ + * $NetBSD: term.h,v 1.20 2009/03/31 17:38:27 christos Exp $ * $FreeBSD$ */ Modified: stable/10/lib/libedit/tty.c ============================================================================== --- stable/10/lib/libedit/tty.c Wed Jul 16 23:17:57 2014 (r268781) +++ stable/10/lib/libedit/tty.c Thu Jul 17 02:14:25 2014 (r268782) @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: tty.c,v 1.25 2006/03/18 09:09:41 christos Exp $ + * $NetBSD: tty.c,v 1.31 2009/07/22 15:58:09 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -443,13 +443,12 @@ private const ttymodes_t ttymodes[] = { -#define tty_getty(el, td) tcgetattr((el)->el_infd, (td)) -#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td)) - #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) #define tty__cooked_mode(td) ((td)->c_lflag & ICANON) +private int tty_getty(EditLine *, struct termios *); +private int tty_setty(EditLine *, int, const struct termios *); private int tty__getcharindex(int); private void tty__getchar(struct termios *, unsigned char *); private void tty__setchar(struct termios *, unsigned char *); @@ -458,6 +457,29 @@ private int tty_setup(EditLine *); #define t_qu t_ts +/* tty_getty(): + * Wrapper for tcgetattr to handle EINTR + */ +private int +tty_getty(EditLine *el, struct termios *t) +{ + int rv; + while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR) + continue; + return rv; +} + +/* tty_setty(): + * Wrapper for tcsetattr to handle EINTR + */ +private int +tty_setty(EditLine *el, int action, const struct termios *t) +{ + int rv; + while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR) + continue; + return rv; +} /* tty_setup(): * Get the tty parameters and initialize the editing state @@ -996,7 +1018,7 @@ tty_rawmode(EditLine *el) if (el->el_tty.t_mode == EX_IO) el->el_tty.t_ex = el->el_tty.t_ts; - if (tty_setty(el, &el->el_tty.t_ed) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n", strerror(errno)); @@ -1021,7 +1043,7 @@ tty_cookedmode(EditLine *el) if (el->el_flags & EDIT_DISABLED) return (0); - if (tty_setty(el, &el->el_tty.t_ex) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n", @@ -1057,7 +1079,7 @@ tty_quotemode(EditLine *el) el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask; el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask; - if (tty_setty(el, &el->el_tty.t_qu) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n", strerror(errno)); @@ -1078,7 +1100,7 @@ tty_noquotemode(EditLine *el) if (el->el_tty.t_mode != QU_IO) return (0); - if (tty_setty(el, &el->el_tty.t_ed) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n", strerror(errno)); @@ -1139,7 +1161,7 @@ tty_stty(EditLine *el, int argc __unused if (!argv || !*argv) { int i = -1; - int len = 0, st = 0, cu; + size_t len = 0, st = 0, cu; for (m = ttymodes; m->m_name; m++) { if (m->m_type != i) { (void) fprintf(el->el_outfile, "%s%s", @@ -1162,9 +1184,9 @@ tty_stty(EditLine *el, int argc __unused cu = strlen(m->m_name) + (x != '\0') + 1; - if (len + cu >= el->el_term.t_size.h) { + if (len + cu >= (size_t)el->el_term.t_size.h) { (void) fprintf(el->el_outfile, "\n%*s", - st, ""); + (int)st, ""); len = st + cu; } else len += cu; @@ -1208,7 +1230,8 @@ tty_stty(EditLine *el, int argc __unused int c = ffs((int)m->m_value); int v = *++p ? parse__escape((const char **) &p) : el->el_tty.t_vdisable; - assert(c-- != 0); + assert(c != 0); + c--; c = tty__getcharindex(c); assert(c != -1); tios->c_cc[c] = v; @@ -1229,6 +1252,17 @@ tty_stty(EditLine *el, int argc __unused break; } } + + if (el->el_tty.t_mode == z) { + if (tty_setty(el, TCSADRAIN, tios) == -1) { +#ifdef DEBUG_TTY + (void) fprintf(el->el_errfile, + "tty_stty: tty_setty: %s\n", strerror(errno)); +#endif /* DEBUG_TTY */ + return (-1); + } + } + return (0); } From owner-svn-src-stable-10@FreeBSD.ORG Thu Jul 17 02:33:41 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id AAAE1EB2; Thu, 17 Jul 2014 02:33:41 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 965CA2E43; Thu, 17 Jul 2014 02:33:41 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6H2Xf0f065103; Thu, 17 Jul 2014 02:33:41 GMT (envelope-from pfg@svn.freebsd.org) Received: (from pfg@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6H2Xfvx065100; Thu, 17 Jul 2014 02:33:41 GMT (envelope-from pfg@svn.freebsd.org) Message-Id: <201407170233.s6H2Xfvx065100@svn.freebsd.org> From: "Pedro F. Giffuni" Date: Thu, 17 Jul 2014 02:33:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268784 - stable/10/sbin/fsck_msdosfs X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jul 2014 02:33:41 -0000 Author: pfg Date: Thu Jul 17 02:33:40 2014 New Revision: 268784 URL: http://svnweb.freebsd.org/changeset/base/268784 Log: MFC r268628, r268631, r268635: Convert *rootDir from external to static. fsck_msdosfs: be a bit more permissive. The free space value in the FSInfo block is merely unitialized when it is 0xffffffff. This fixes a bug found in NetBSD. Respect FSFIXFAT. Fix some whitespace issues while here. Obtained from: NetBSD (CVS rev. 1.22, rev. 1.9), OpenBSD (misc) Modified: stable/10/sbin/fsck_msdosfs/check.c stable/10/sbin/fsck_msdosfs/ext.h stable/10/sbin/fsck_msdosfs/fat.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sbin/fsck_msdosfs/check.c ============================================================================== --- stable/10/sbin/fsck_msdosfs/check.c Thu Jul 17 02:22:03 2014 (r268783) +++ stable/10/sbin/fsck_msdosfs/check.c Thu Jul 17 02:33:40 2014 (r268784) @@ -142,7 +142,7 @@ checkfilesys(const char *fname) goto out; /* now write the FATs */ - if (mod & FSFATMOD) { + if (mod & (FSFATMOD|FSFIXFAT)) { if (ask(1, "Update FATs")) { mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT); if (mod & FSFATAL) Modified: stable/10/sbin/fsck_msdosfs/ext.h ============================================================================== --- stable/10/sbin/fsck_msdosfs/ext.h Thu Jul 17 02:22:03 2014 (r268783) +++ stable/10/sbin/fsck_msdosfs/ext.h Thu Jul 17 02:33:40 2014 (r268784) @@ -26,7 +26,7 @@ */ #ifndef EXT_H -#define EXT_H +#define EXT_H #include @@ -71,8 +71,8 @@ int checkfilesys(const char *); #define FSFATMOD 4 /* The FAT was modified */ #define FSERROR 8 /* Some unrecovered error remains */ #define FSFATAL 16 /* Some unrecoverable error occurred */ -#define FSDIRTY 32 /* File system is dirty */ -#define FSFIXFAT 64 /* Fix file system FAT */ +#define FSDIRTY 32 /* File system is dirty */ +#define FSFIXFAT 64 /* Fix file system FAT */ /* * read a boot block in a machine independent fashion and translate Modified: stable/10/sbin/fsck_msdosfs/fat.c ============================================================================== --- stable/10/sbin/fsck_msdosfs/fat.c Thu Jul 17 02:22:03 2014 (r268783) +++ stable/10/sbin/fsck_msdosfs/fat.c Thu Jul 17 02:33:40 2014 (r268784) @@ -242,7 +242,7 @@ readfat(int fs, struct bootblock *boot, ret |= FSDIRTY; else { /* just some odd byte sequence in FAT */ - + switch (boot->ClustMask) { case CLUST32_MASK: pwarn("%s (%02x%02x%02x%02x%02x%02x%02x%02x)\n", @@ -262,7 +262,7 @@ readfat(int fs, struct bootblock *boot, break; } - + if (ask(1, "Correct")) ret |= FSFIXFAT; } @@ -653,7 +653,7 @@ checklost(int dosfs, struct bootblock *b cl_t head; int mod = FSOK; int ret; - + for (head = CLUST_FIRST; head < boot->NumClusters; head++) { /* find next untravelled chain */ if (fat[head].head != head @@ -677,8 +677,9 @@ checklost(int dosfs, struct bootblock *b if (boot->bpbFSInfo) { ret = 0; - if (boot->FSFree != boot->NumFree) { - pwarn("Free space in FSInfo block (%d) not correct (%d)\n", + if (boot->FSFree != 0xffffffffU && + boot->FSFree != boot->NumFree) { + pwarn("Free space in FSInfo block (%u) not correct (%u)\n", boot->FSFree, boot->NumFree); if (ask(1, "Fix")) { boot->FSFree = boot->NumFree; From owner-svn-src-stable-10@FreeBSD.ORG Thu Jul 17 05:20:19 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id B334B7BF; Thu, 17 Jul 2014 05:20:19 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 955522B83; Thu, 17 Jul 2014 05:20:19 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6H5KJVt042098; Thu, 17 Jul 2014 05:20:19 GMT (envelope-from delphij@svn.freebsd.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6H5KIYd042094; Thu, 17 Jul 2014 05:20:18 GMT (envelope-from delphij@svn.freebsd.org) Message-Id: <201407170520.s6H5KIYd042094@svn.freebsd.org> From: Xin LI Date: Thu, 17 Jul 2014 05:20:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268786 - in stable/10: cddl/contrib/opensolaris/lib/libzfs/common sys/cddl/contrib/opensolaris/common/zfs sys/cddl/contrib/opensolaris/uts/common/fs/zfs X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jul 2014 05:20:19 -0000 Author: delphij Date: Thu Jul 17 05:20:18 2014 New Revision: 268786 URL: http://svnweb.freebsd.org/changeset/base/268786 Log: MFC r268116: - Fix handling of "new" style of ioctl in compatiblity mode [1]; - Reorganize code and reduce diff from upstream; - Improve forward compatibility shims for previous kernel; Reported by: sbruno [1] Modified: stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c Directory Properties: stable/10/ (props changed) Modified: stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c ============================================================================== --- stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c Thu Jul 17 02:43:53 2014 (r268785) +++ stable/10/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_compat.c Thu Jul 17 05:20:18 2014 (r268786) @@ -72,16 +72,23 @@ zcmd_ioctl(int fd, int request, zfs_cmd_ if (zfs_ioctl_version == ZFS_IOCVER_UNDEF) zfs_ioctl_version = get_zfs_ioctl_version(); - if (zfs_ioctl_version == ZFS_IOCVER_LZC) - cflag = ZFS_CMD_COMPAT_LZC; - else if (zfs_ioctl_version == ZFS_IOCVER_DEADMAN) - cflag = ZFS_CMD_COMPAT_DEADMAN; - - /* - * If vfs.zfs.version.ioctl is not defined, assume we have v28 - * compatible binaries and use vfs.zfs.version.spa to test for v15 - */ - if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) { + if (zfs_ioctl_version >= ZFS_IOCVER_DEADMAN) { + switch (zfs_ioctl_version) { + case ZFS_IOCVER_ZCMD: + cflag = ZFS_CMD_COMPAT_ZCMD; + break; + case ZFS_IOCVER_LZC: + cflag = ZFS_CMD_COMPAT_LZC; + break; + case ZFS_IOCVER_DEADMAN: + cflag = ZFS_CMD_COMPAT_DEADMAN; + break; + } + } else { + /* + * If vfs.zfs.version.ioctl is not defined, assume we have v28 + * compatible binaries and use vfs.zfs.version.spa to test for v15 + */ cflag = ZFS_CMD_COMPAT_V28; if (zfs_spa_version < 0) Modified: stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c Thu Jul 17 02:43:53 2014 (r268785) +++ stable/10/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c Thu Jul 17 05:20:18 2014 (r268786) @@ -697,6 +697,12 @@ zcmd_ioctl_compat(int fd, int request, z zp.zfs_cmd_size = sizeof(zfs_cmd_t); zp.zfs_ioctl_version = ZFS_IOCVER_CURRENT; return (ioctl(fd, ncmd, &zp)); + case ZFS_CMD_COMPAT_ZCMD: + ncmd = _IOWR('Z', request, struct zfs_iocparm); + zp.zfs_cmd = (uint64_t)zc; + zp.zfs_cmd_size = sizeof(zfs_cmd_zcmd_t); + zp.zfs_ioctl_version = ZFS_IOCVER_ZCMD; + return (ioctl(fd, ncmd, &zp)); case ZFS_CMD_COMPAT_LZC: ncmd = _IOWR('Z', request, struct zfs_cmd); return (ioctl(fd, ncmd, zc)); @@ -794,7 +800,8 @@ zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nv char *poolname, *snapname; int err; - if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC) + if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC || + cflag == ZFS_CMD_COMPAT_ZCMD) goto out; switch (vec) { @@ -945,7 +952,8 @@ zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, n { nvlist_t *tmpnvl; - if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC) + if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC || + cflag == ZFS_CMD_COMPAT_ZCMD) return (outnvl); switch (vec) { Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c Thu Jul 17 02:43:53 2014 (r268785) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c Thu Jul 17 05:20:18 2014 (r268786) @@ -24,6 +24,7 @@ * Copyright (c) 2011-2012 Pawel Jakub Dawidek . * All rights reserved. * Copyright 2013 Martin Matuska . All rights reserved. + * Copyright 2014 Xin Li . All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014, Joyent, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. @@ -5893,6 +5894,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zc zfs_iocparm_t *zc_iocparm; int cflag, cmd, oldvecnum; boolean_t newioc, compat; + void *compat_zc = NULL; cred_t *cr = td->td_ucred; #endif const zfs_ioc_vec_t *vec; @@ -5901,10 +5903,10 @@ zfsdev_ioctl(struct cdev *dev, u_long zc cflag = ZFS_CMD_COMPAT_NONE; compat = B_FALSE; - newioc = B_TRUE; + newioc = B_TRUE; /* "new" style (zfs_iocparm_t) ioctl */ len = IOCPARM_LEN(zcmd); - cmd = zcmd & 0xff; + vecnum = cmd = zcmd & 0xff; /* * Check if we are talking to supported older binaries @@ -5912,96 +5914,112 @@ zfsdev_ioctl(struct cdev *dev, u_long zc */ if (len != sizeof(zfs_iocparm_t)) { newioc = B_FALSE; - if (len == sizeof(zfs_cmd_t)) { + compat = B_TRUE; + + vecnum = cmd; + + switch (len) { + case sizeof(zfs_cmd_zcmd_t): cflag = ZFS_CMD_COMPAT_LZC; - vecnum = cmd; - } else if (len == sizeof(zfs_cmd_deadman_t)) { + break; + case sizeof(zfs_cmd_deadman_t): cflag = ZFS_CMD_COMPAT_DEADMAN; - compat = B_TRUE; - vecnum = cmd; - } else if (len == sizeof(zfs_cmd_v28_t)) { + break; + case sizeof(zfs_cmd_v28_t): cflag = ZFS_CMD_COMPAT_V28; - compat = B_TRUE; - vecnum = cmd; - } else if (len == sizeof(zfs_cmd_v15_t)) { + break; + case sizeof(zfs_cmd_v15_t): cflag = ZFS_CMD_COMPAT_V15; - compat = B_TRUE; vecnum = zfs_ioctl_v15_to_v28[cmd]; - } else + + /* + * Return without further handling + * if the command is blacklisted. + */ + if (vecnum == ZFS_IOC_COMPAT_PASS) + return (0); + else if (vecnum == ZFS_IOC_COMPAT_FAIL) + return (ENOTSUP); + break; + default: return (EINVAL); - } else - vecnum = cmd; + } + } #ifdef illumos vecnum = cmd - ZFS_IOC_FIRST; ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); #endif - if (compat) { - if (vecnum == ZFS_IOC_COMPAT_PASS) - return (0); - else if (vecnum == ZFS_IOC_COMPAT_FAIL) - return (ENOTSUP); - } - - /* - * Check if we have sufficient kernel memory allocated - * for the zfs_cmd_t request. Bail out if not so we - * will not access undefined memory region. - */ if (vecnum >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) return (SET_ERROR(EINVAL)); vec = &zfs_ioc_vec[vecnum]; -#ifdef illumos zc = kmem_zalloc(sizeof(zfs_cmd_t), KM_SLEEP); - bzero(zc, sizeof(zfs_cmd_t)); +#ifdef illumos error = ddi_copyin((void *)arg, zc, sizeof (zfs_cmd_t), flag); if (error != 0) { error = SET_ERROR(EFAULT); goto out; } #else /* !illumos */ - /* - * We don't alloc/free zc only if talking to library ioctl version 2 - */ - if (cflag != ZFS_CMD_COMPAT_LZC) { - zc = kmem_zalloc(sizeof(zfs_cmd_t), KM_SLEEP); - bzero(zc, sizeof(zfs_cmd_t)); - } else { - zc = (void *)arg; - error = 0; - } + bzero(zc, sizeof(zfs_cmd_t)); if (newioc) { zc_iocparm = (void *)arg; - if (zc_iocparm->zfs_cmd_size != sizeof(zfs_cmd_t)) { - error = SET_ERROR(EFAULT); - goto out; - } - error = ddi_copyin((void *)(uintptr_t)zc_iocparm->zfs_cmd, zc, - sizeof(zfs_cmd_t), flag); - if (error != 0) { - error = SET_ERROR(EFAULT); + + switch (zc_iocparm->zfs_ioctl_version) { + case ZFS_IOCVER_CURRENT: + if (zc_iocparm->zfs_cmd_size != sizeof(zfs_cmd_t)) { + error = SET_ERROR(EINVAL); + goto out; + } + break; + case ZFS_IOCVER_ZCMD: + if (zc_iocparm->zfs_cmd_size > sizeof(zfs_cmd_t) || + zc_iocparm->zfs_cmd_size < sizeof(zfs_cmd_zcmd_t)) { + error = SET_ERROR(EFAULT); + goto out; + } + compat = B_TRUE; + cflag = ZFS_CMD_COMPAT_ZCMD; + break; + default: + error = SET_ERROR(EINVAL); goto out; + /* NOTREACHED */ } - if (zc_iocparm->zfs_ioctl_version != ZFS_IOCVER_CURRENT) { - compat = B_TRUE; - switch (zc_iocparm->zfs_ioctl_version) { - case ZFS_IOCVER_ZCMD: - cflag = ZFS_CMD_COMPAT_ZCMD; - break; - default: - error = SET_ERROR(EINVAL); + if (compat) { + ASSERT(sizeof(zfs_cmd_t) >= zc_iocparm->zfs_cmd_size); + compat_zc = kmem_zalloc(sizeof(zfs_cmd_t), KM_SLEEP); + bzero(compat_zc, sizeof(zfs_cmd_t)); + + error = ddi_copyin((void *)(uintptr_t)zc_iocparm->zfs_cmd, + compat_zc, zc_iocparm->zfs_cmd_size, flag); + if (error != 0) { + error = SET_ERROR(EFAULT); + goto out; + } + } else { + error = ddi_copyin((void *)(uintptr_t)zc_iocparm->zfs_cmd, + zc, zc_iocparm->zfs_cmd_size, flag); + if (error != 0) { + error = SET_ERROR(EFAULT); goto out; } } } if (compat) { - zfs_cmd_compat_get(zc, arg, cflag); + if (newioc) { + ASSERT(compat_zc != NULL); + zfs_cmd_compat_get(zc, compat_zc, cflag); + } else { + ASSERT(compat_zc == NULL); + zfs_cmd_compat_get(zc, arg, cflag); + } oldvecnum = vecnum; error = zfs_ioctl_compat_pre(zc, &vecnum, cflag); if (error != 0) @@ -6097,7 +6115,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zc fnvlist_free(lognv); /* rewrite outnvl for backwards compatibility */ - if (cflag != ZFS_CMD_COMPAT_NONE && cflag != ZFS_CMD_COMPAT_LZC) + if (compat) outnvl = zfs_ioctl_compat_outnvl(zc, outnvl, vecnum, cflag); @@ -6122,17 +6140,30 @@ zfsdev_ioctl(struct cdev *dev, u_long zc out: nvlist_free(innvl); - if (compat) { - zfs_ioctl_compat_post(zc, cmd, cflag); - zfs_cmd_compat_put(zc, arg, vecnum, cflag); - } - #ifdef illumos rc = ddi_copyout(zc, (void *)arg, sizeof (zfs_cmd_t), flag); if (error == 0 && rc != 0) error = SET_ERROR(EFAULT); #else - if (newioc) { + if (compat) { + zfs_ioctl_compat_post(zc, cmd, cflag); + if (newioc) { + ASSERT(compat_zc != NULL); + ASSERT(sizeof(zfs_cmd_t) >= zc_iocparm->zfs_cmd_size); + + zfs_cmd_compat_put(zc, compat_zc, vecnum, cflag); + rc = ddi_copyout(compat_zc, + (void *)(uintptr_t)zc_iocparm->zfs_cmd, + zc_iocparm->zfs_cmd_size, flag); + if (error == 0 && rc != 0) + error = SET_ERROR(EFAULT); + kmem_free(compat_zc, sizeof (zfs_cmd_t)); + } else { + zfs_cmd_compat_put(zc, arg, vecnum, cflag); + } + } else { + ASSERT(newioc); + rc = ddi_copyout(zc, (void *)(uintptr_t)zc_iocparm->zfs_cmd, sizeof (zfs_cmd_t), flag); if (error == 0 && rc != 0) @@ -6149,15 +6180,7 @@ out: strfree(saved_poolname); } -#ifdef illumos kmem_free(zc, sizeof (zfs_cmd_t)); -#else - /* - * We don't alloc/free zc only if talking to library ioctl version 2 - */ - if (cflag != ZFS_CMD_COMPAT_LZC) - kmem_free(zc, sizeof (zfs_cmd_t)); -#endif return (error); } From owner-svn-src-stable-10@FreeBSD.ORG Thu Jul 17 06:36:23 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 395B4CD3; Thu, 17 Jul 2014 06:36:23 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0CBC12277; Thu, 17 Jul 2014 06:36:23 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6H6aM6i078685; Thu, 17 Jul 2014 06:36:22 GMT (envelope-from delphij@svn.freebsd.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6H6aMsE078681; Thu, 17 Jul 2014 06:36:22 GMT (envelope-from delphij@svn.freebsd.org) Message-Id: <201407170636.s6H6aMsE078681@svn.freebsd.org> From: Xin LI Date: Thu, 17 Jul 2014 06:36:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268791 - stable/10/usr.sbin/gstat X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jul 2014 06:36:23 -0000 Author: delphij Date: Thu Jul 17 06:36:22 2014 New Revision: 268791 URL: http://svnweb.freebsd.org/changeset/base/268791 Log: MFC r268238: Add an option, -p, which makes gstat(8) to only display physical providers (those with rank of 1). Modified: stable/10/usr.sbin/gstat/gstat.8 stable/10/usr.sbin/gstat/gstat.c Directory Properties: stable/10/ (props changed) Modified: stable/10/usr.sbin/gstat/gstat.8 ============================================================================== --- stable/10/usr.sbin/gstat/gstat.8 Thu Jul 17 06:21:58 2014 (r268790) +++ stable/10/usr.sbin/gstat/gstat.8 Thu Jul 17 06:36:22 2014 (r268791) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 17, 2014 +.Dd July 3, 2014 .Dt GSTAT 8 .Os .Sh NAME @@ -32,7 +32,7 @@ .Nd print statistics about GEOM disks .Sh SYNOPSIS .Nm -.Op Fl abcdo +.Op Fl abcdop .Op Fl f Ar filter .Op Fl I Ar interval .Sh DESCRIPTION @@ -84,6 +84,8 @@ or .Cm us (the default) indicates that the update interval is specified in seconds, milliseconds, or microseconds, respectively. +.It Fl p +Only display physical providers (those with rank of 1). .El .Sh EXIT STATUS .Ex -std Modified: stable/10/usr.sbin/gstat/gstat.c ============================================================================== --- stable/10/usr.sbin/gstat/gstat.c Thu Jul 17 06:21:58 2014 (r268790) +++ stable/10/usr.sbin/gstat/gstat.c Thu Jul 17 06:36:22 2014 (r268791) @@ -51,7 +51,7 @@ #include #include -static int flag_a, flag_b, flag_c, flag_d, flag_o; +static int flag_a, flag_b, flag_c, flag_d, flag_o, flag_p; static int flag_I = 1000000; #define PRINTMSG(...) do { \ @@ -104,7 +104,7 @@ main(int argc, char **argv) flag_b = 1; f_s[0] = '\0'; - while ((i = getopt(argc, argv, "abdcf:oI:")) != -1) { + while ((i = getopt(argc, argv, "abdcf:I:op")) != -1) { switch (i) { case 'a': flag_a = 1; @@ -143,6 +143,9 @@ main(int argc, char **argv) i *= 1; flag_I = i; break; + case 'p': + flag_p = 1; + break; case '?': default: usage(); @@ -254,6 +257,9 @@ main(int argc, char **argv) continue; if (gid->lg_what == ISCONSUMER && !flag_c) continue; + if (flag_p && gid->lg_what == ISPROVIDER && + ((struct gprovider *)(gid->lg_ptr))->lg_geom->lg_rank != 1) + continue; /* Do not print past end of window */ if (!flag_b) { getyx(stdscr, cury, curx); @@ -443,7 +449,7 @@ main(int argc, char **argv) static void usage(void) { - fprintf(stderr, "usage: gstat [-abcd] [-f filter] [-I interval]\n"); + fprintf(stderr, "usage: gstat [-abcdp] [-f filter] [-I interval]\n"); exit(EX_USAGE); /* NOTREACHED */ } From owner-svn-src-stable-10@FreeBSD.ORG Thu Jul 17 22:31:48 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 7B071399; Thu, 17 Jul 2014 22:31:48 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 6716E28BD; Thu, 17 Jul 2014 22:31:48 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6HMVmS5039568; Thu, 17 Jul 2014 22:31:48 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6HMVkt7039555; Thu, 17 Jul 2014 22:31:46 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <201407172231.s6HMVkt7039555@svn.freebsd.org> From: Warner Losh Date: Thu, 17 Jul 2014 22:31:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268813 - in stable/10: . sys/amd64/conf sys/arm/conf sys/conf sys/i386/conf sys/ia64/conf sys/sparc64/conf X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jul 2014 22:31:48 -0000 Author: imp Date: Thu Jul 17 22:31:46 2014 New Revision: 268813 URL: http://svnweb.freebsd.org/changeset/base/268813 Log: MFC r263749,267146: >r267146 | imp | 2014-06-05 22:08:55 -0600 (Thu, 05 Jun 2014) | 4 lines >Restore comments accidentally removed. >r263749 | imp | 2014-03-25 16:08:31 -0600 (Tue, 25 Mar 2014) | 18 lines >Rather than require a makeoptions DEBUG to get debug correct, >add it in kern.mk, but only if we're using clang. While this >option is supported by both clang and gcc, in the future there >may be changes to clang which change the defaults that require >a tweak to build our kernel such that other tools in our tree >will work. Set a good example by forcing -gdwarf-2 only for >clang builds, and only if the user hasn't specified another >dwarf level already. Update UPDATING to reflect the changed >state of affairs. This also keeps us from having to update >all the ARM kernels to add this, and also keeps us from >in the future having to update all the MIPS kernels and is >one less place the user will have to know to do something >special for clang and one less thing developers will need >to do when moving an architecture to clang. Modified: stable/10/UPDATING stable/10/sys/amd64/conf/GENERIC stable/10/sys/arm/conf/ZEDBOARD stable/10/sys/conf/kern.mk stable/10/sys/i386/conf/GENERIC stable/10/sys/i386/conf/XEN stable/10/sys/ia64/conf/GENERIC stable/10/sys/sparc64/conf/GENERIC Directory Properties: stable/10/ (props changed) Modified: stable/10/UPDATING ============================================================================== --- stable/10/UPDATING Thu Jul 17 22:26:24 2014 (r268812) +++ stable/10/UPDATING Thu Jul 17 22:31:46 2014 (r268813) @@ -16,6 +16,13 @@ from older versions of FreeBSD, try WITH stable/10, and then rebuild without this option. The bootstrap process from older version of current is a bit fragile. +20140717: + It is no longer necessary to include the dwarf version in your DEBUG + options in your kernel config file. The bug that required it to be + placed in the config file has bene fixed. DEBUG should now just + contain -g. The build system will automatically update things + to do the right thing. + 20140715: Several ABI breaking changes were merged to CTL and new iSCSI code. All CTL and iSCSI-related tools, such as ctladm, ctld, iscsid and Modified: stable/10/sys/amd64/conf/GENERIC ============================================================================== --- stable/10/sys/amd64/conf/GENERIC Thu Jul 17 22:26:24 2014 (r268812) +++ stable/10/sys/amd64/conf/GENERIC Thu Jul 17 22:31:46 2014 (r268813) @@ -21,7 +21,7 @@ cpu HAMMER ident GENERIC -makeoptions DEBUG=-gdwarf-2 # Build kernel with gdb(1) debug symbols +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support options SCHED_ULE # ULE scheduler Modified: stable/10/sys/arm/conf/ZEDBOARD ============================================================================== --- stable/10/sys/arm/conf/ZEDBOARD Thu Jul 17 22:26:24 2014 (r268812) +++ stable/10/sys/arm/conf/ZEDBOARD Thu Jul 17 22:31:46 2014 (r268813) @@ -59,7 +59,7 @@ options VFP # vfp/neon options SMP # Symmetric MultiProcessor Kernel # Debugging -makeoptions DEBUG=-g +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options DDB options KDB # options BREAK_TO_DEBUGGER Modified: stable/10/sys/conf/kern.mk ============================================================================== --- stable/10/sys/conf/kern.mk Thu Jul 17 22:26:24 2014 (r268812) +++ stable/10/sys/conf/kern.mk Thu Jul 17 22:31:46 2014 (r268813) @@ -159,3 +159,10 @@ CFLAGS+= -ffreestanding ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips" CFLAGS+= -fstack-protector .endif + +# +# Add -gdwarf-2 when compiling -g +# +.if ${COMPILER_TYPE} == "clang" && ${CFLAGS:M-g} != "" && ${CFLAGS:M-gdwarf} == "" +CFLAGS+= -gdwarf-2 +.endif Modified: stable/10/sys/i386/conf/GENERIC ============================================================================== --- stable/10/sys/i386/conf/GENERIC Thu Jul 17 22:26:24 2014 (r268812) +++ stable/10/sys/i386/conf/GENERIC Thu Jul 17 22:31:46 2014 (r268813) @@ -23,7 +23,7 @@ cpu I586_CPU cpu I686_CPU ident GENERIC -makeoptions DEBUG=-gdwarf-2 # Build kernel with gdb(1) debug symbols +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support options SCHED_ULE # ULE scheduler Modified: stable/10/sys/i386/conf/XEN ============================================================================== --- stable/10/sys/i386/conf/XEN Thu Jul 17 22:26:24 2014 (r268812) +++ stable/10/sys/i386/conf/XEN Thu Jul 17 22:31:46 2014 (r268813) @@ -6,7 +6,7 @@ cpu I686_CPU ident XEN -makeoptions DEBUG=-gdwarf-2 # Build kernel with gdb(1) debug symbols +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols # The following modules don't build with PAE and XEN enabled. makeoptions WITHOUT_MODULES="ctl cxgb dpt drm drm2 hptmv ida malo mwl rdma" Modified: stable/10/sys/ia64/conf/GENERIC ============================================================================== --- stable/10/sys/ia64/conf/GENERIC Thu Jul 17 22:26:24 2014 (r268812) +++ stable/10/sys/ia64/conf/GENERIC Thu Jul 17 22:31:46 2014 (r268813) @@ -23,7 +23,7 @@ cpu ITANIUM2 ident GENERIC -makeoptions DEBUG=-g # Build kernel with debug information. +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols options AUDIT # Security event auditing options CAPABILITY_MODE # Capsicum capability mode Modified: stable/10/sys/sparc64/conf/GENERIC ============================================================================== --- stable/10/sys/sparc64/conf/GENERIC Thu Jul 17 22:26:24 2014 (r268812) +++ stable/10/sys/sparc64/conf/GENERIC Thu Jul 17 22:31:46 2014 (r268813) @@ -21,7 +21,7 @@ cpu SUN4U ident GENERIC -makeoptions DEBUG=-gdwarf-2 # Build kernel with gdb(1) debug symbols +makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols # Platforms supported # At this time all platforms are supported, as-is. From owner-svn-src-stable-10@FreeBSD.ORG Thu Jul 17 22:58:06 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 711E5851; Thu, 17 Jul 2014 22:58:06 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5E0522A87; Thu, 17 Jul 2014 22:58:06 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6HMw62r050672; Thu, 17 Jul 2014 22:58:06 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6HMw6QF050671; Thu, 17 Jul 2014 22:58:06 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <201407172258.s6HMw6QF050671@svn.freebsd.org> From: Warner Losh Date: Thu, 17 Jul 2014 22:58:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268815 - stable/10/sys/cam/ata X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jul 2014 22:58:06 -0000 Author: imp Date: Thu Jul 17 22:58:05 2014 New Revision: 268815 URL: http://svnweb.freebsd.org/changeset/base/268815 Log: MFC: >r268205 | imp | 2014-07-02 23:22:13 -0600 (Wed, 02 Jul 2014) | 9 lines >Rework the BIO_DELETE code slightly. Always queue the BIO_DELETE >requests on the trim_queue, even for the CFA ERASE. This allows us, in >the future, to collapse adjacent requests. Since CFA ERASE is only for >CF cards, and it is so restrictive in what it can do, the collapse >code is not presently here. This also brings the ada driver more in >line with the da driver's treatment of BIO_DELETEs. Modified: stable/10/sys/cam/ata/ata_da.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cam/ata/ata_da.c ============================================================================== --- stable/10/sys/cam/ata/ata_da.c Thu Jul 17 22:42:18 2014 (r268814) +++ stable/10/sys/cam/ata/ata_da.c Thu Jul 17 22:58:05 2014 (r268815) @@ -727,8 +727,11 @@ adastrategy(struct bio *bp) /* * Place it in the queue of disk activities for this disk */ - if (bp->bio_cmd == BIO_DELETE && - (softc->flags & ADA_FLAG_CAN_TRIM)) { + if (bp->bio_cmd == BIO_DELETE) { + KASSERT((softc->flags & ADA_FLAG_CAN_TRIM) || + ((softc->flags & ADA_FLAG_CAN_CFA) && + !(softc->flags & ADA_FLAG_CAN_48BIT)), + ("BIO_DELETE but no supported TRIM method.")); if (ADA_SIO) bioq_disksort(&softc->trim_queue, bp); else @@ -1386,6 +1389,96 @@ adaregister(struct cam_periph *periph, v } static void +ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) +{ + struct trim_request *req = &softc->trim_req; + uint64_t lastlba = (uint64_t)-1; + int c, lastcount = 0, off, ranges = 0; + + bzero(req, sizeof(*req)); + TAILQ_INIT(&req->bps); + do { + uint64_t lba = bp->bio_pblkno; + int count = bp->bio_bcount / softc->params.secsize; + + bioq_remove(&softc->trim_queue, bp); + + /* Try to extend the previous range. */ + if (lba == lastlba) { + c = min(count, ATA_DSM_RANGE_MAX - lastcount); + lastcount += c; + off = (ranges - 1) * ATA_DSM_RANGE_SIZE; + req->data[off + 6] = lastcount & 0xff; + req->data[off + 7] = + (lastcount >> 8) & 0xff; + count -= c; + lba += c; + } + + while (count > 0) { + c = min(count, ATA_DSM_RANGE_MAX); + off = ranges * ATA_DSM_RANGE_SIZE; + req->data[off + 0] = lba & 0xff; + req->data[off + 1] = (lba >> 8) & 0xff; + req->data[off + 2] = (lba >> 16) & 0xff; + req->data[off + 3] = (lba >> 24) & 0xff; + req->data[off + 4] = (lba >> 32) & 0xff; + req->data[off + 5] = (lba >> 40) & 0xff; + req->data[off + 6] = c & 0xff; + req->data[off + 7] = (c >> 8) & 0xff; + lba += c; + count -= c; + lastcount = c; + ranges++; + /* + * Its the caller's responsibility to ensure the + * request will fit so we don't need to check for + * overrun here + */ + } + lastlba = lba; + TAILQ_INSERT_TAIL(&req->bps, bp, bio_queue); + bp = bioq_first(&softc->trim_queue); + if (bp == NULL || + bp->bio_bcount / softc->params.secsize > + (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX) + break; + } while (1); + cam_fill_ataio(ataio, + ada_retry_count, + adadone, + CAM_DIR_OUT, + 0, + req->data, + ((ranges + ATA_DSM_BLK_RANGES - 1) / + ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE, + ada_default_timeout * 1000); + ata_48bit_cmd(ataio, ATA_DATA_SET_MANAGEMENT, + ATA_DSM_TRIM, 0, (ranges + ATA_DSM_BLK_RANGES - + 1) / ATA_DSM_BLK_RANGES); +} + +static void +ada_cfaerase(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) +{ + uint64_t lba = bp->bio_pblkno; + uint16_t count = bp->bio_bcount / softc->params.secsize; + + cam_fill_ataio(ataio, + ada_retry_count, + adadone, + CAM_DIR_NONE, + 0, + NULL, + 0, + ada_default_timeout*1000); + + if (count >= 256) + count = 0; + ata_28bit_cmd(ataio, ATA_CFA_ERASE, 0, lba, count); +} + +static void adastart(struct cam_periph *periph, union ccb *start_ccb) { struct ada_softc *softc = (struct ada_softc *)periph->softc; @@ -1402,76 +1495,15 @@ adastart(struct cam_periph *periph, unio /* Run TRIM if not running yet. */ if (!softc->trim_running && (bp = bioq_first(&softc->trim_queue)) != 0) { - struct trim_request *req = &softc->trim_req; - struct bio *bp1; - uint64_t lastlba = (uint64_t)-1; - int c, lastcount = 0, off, ranges = 0; - + if (softc->flags & ADA_FLAG_CAN_TRIM) { + ada_dsmtrim(softc, bp, ataio); + } else if ((softc->flags & ADA_FLAG_CAN_CFA) && + !(softc->flags & ADA_FLAG_CAN_48BIT)) { + ada_cfaerase(softc, bp, ataio); + } else { + panic("adastart: BIO_DELETE without method, not possible."); + } softc->trim_running = 1; - bzero(req, sizeof(*req)); - TAILQ_INIT(&req->bps); - bp1 = bp; - do { - uint64_t lba = bp1->bio_pblkno; - int count = bp1->bio_bcount / - softc->params.secsize; - - bioq_remove(&softc->trim_queue, bp1); - - /* Try to extend the previous range. */ - if (lba == lastlba) { - c = min(count, ATA_DSM_RANGE_MAX - lastcount); - lastcount += c; - off = (ranges - 1) * ATA_DSM_RANGE_SIZE; - req->data[off + 6] = lastcount & 0xff; - req->data[off + 7] = - (lastcount >> 8) & 0xff; - count -= c; - lba += c; - } - - while (count > 0) { - c = min(count, ATA_DSM_RANGE_MAX); - off = ranges * ATA_DSM_RANGE_SIZE; - req->data[off + 0] = lba & 0xff; - req->data[off + 1] = (lba >> 8) & 0xff; - req->data[off + 2] = (lba >> 16) & 0xff; - req->data[off + 3] = (lba >> 24) & 0xff; - req->data[off + 4] = (lba >> 32) & 0xff; - req->data[off + 5] = (lba >> 40) & 0xff; - req->data[off + 6] = c & 0xff; - req->data[off + 7] = (c >> 8) & 0xff; - lba += c; - count -= c; - lastcount = c; - ranges++; - /* - * Its the caller's responsibility to ensure the - * request will fit so we don't need to check for - * overrun here - */ - } - lastlba = lba; - TAILQ_INSERT_TAIL(&req->bps, bp1, bio_queue); - bp1 = bioq_first(&softc->trim_queue); - if (bp1 == NULL || - bp1->bio_bcount / softc->params.secsize > - (softc->trim_max_ranges - ranges) * - ATA_DSM_RANGE_MAX) - break; - } while (1); - cam_fill_ataio(ataio, - ada_retry_count, - adadone, - CAM_DIR_OUT, - 0, - req->data, - ((ranges + ATA_DSM_BLK_RANGES - 1) / - ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE, - ada_default_timeout * 1000); - ata_48bit_cmd(ataio, ATA_DATA_SET_MANAGEMENT, - ATA_DSM_TRIM, 0, (ranges + ATA_DSM_BLK_RANGES - - 1) / ATA_DSM_BLK_RANGES); start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM; start_ccb->ccb_h.flags |= CAM_UNLOCKED; goto out; @@ -1606,25 +1638,6 @@ adastart(struct cam_periph *periph, unio } break; } - case BIO_DELETE: - { - uint64_t lba = bp->bio_pblkno; - uint16_t count = bp->bio_bcount / softc->params.secsize; - - cam_fill_ataio(ataio, - ada_retry_count, - adadone, - CAM_DIR_NONE, - 0, - NULL, - 0, - ada_default_timeout*1000); - - if (count >= 256) - count = 0; - ata_28bit_cmd(ataio, ATA_CFA_ERASE, 0, lba, count); - break; - } case BIO_FLUSH: cam_fill_ataio(ataio, 1, From owner-svn-src-stable-10@FreeBSD.ORG Thu Jul 17 23:05:21 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 3AD25AEA; Thu, 17 Jul 2014 23:05:21 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0E7E92B44; Thu, 17 Jul 2014 23:05:21 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6HN5KoC055263; Thu, 17 Jul 2014 23:05:20 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6HN5KiV055259; Thu, 17 Jul 2014 23:05:20 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <201407172305.s6HN5KiV055259@svn.freebsd.org> From: Warner Losh Date: Thu, 17 Jul 2014 23:05:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268816 - in stable/10/sys/cam: ata scsi X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jul 2014 23:05:21 -0000 Author: imp Date: Thu Jul 17 23:05:20 2014 New Revision: 268816 URL: http://svnweb.freebsd.org/changeset/base/268816 Log: MFC: >r267118 | imp | 2014-06-05 11:13:42 -0600 (Thu, 05 Jun 2014) | 9 lines >The code that combines adjacent ranges for BIO_DELETEs to optimize >trims to the device assumes the list is sorted. Don't apply the >optimization of not sorting the queue when we have SSDs to the >delete_queue, since it causes more discard traffic to the drive. While >one could argue that the higher levels should coalesce the trims, >that's not done today, so some optimization at this level is needed. >CR: https://phabric.freebsd.org/D142 Modified: stable/10/sys/cam/ata/ata_da.c stable/10/sys/cam/scsi/scsi_da.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cam/ata/ata_da.c ============================================================================== --- stable/10/sys/cam/ata/ata_da.c Thu Jul 17 22:58:05 2014 (r268815) +++ stable/10/sys/cam/ata/ata_da.c Thu Jul 17 23:05:20 2014 (r268816) @@ -732,10 +732,7 @@ adastrategy(struct bio *bp) ((softc->flags & ADA_FLAG_CAN_CFA) && !(softc->flags & ADA_FLAG_CAN_48BIT)), ("BIO_DELETE but no supported TRIM method.")); - if (ADA_SIO) - bioq_disksort(&softc->trim_queue, bp); - else - bioq_insert_tail(&softc->trim_queue, bp); + bioq_disksort(&softc->trim_queue, bp); } else { if (ADA_SIO) bioq_disksort(&softc->bio_queue, bp); Modified: stable/10/sys/cam/scsi/scsi_da.c ============================================================================== --- stable/10/sys/cam/scsi/scsi_da.c Thu Jul 17 22:58:05 2014 (r268815) +++ stable/10/sys/cam/scsi/scsi_da.c Thu Jul 17 23:05:20 2014 (r268816) @@ -1383,10 +1383,7 @@ dastrategy(struct bio *bp) * Place it in the queue of disk activities for this disk */ if (bp->bio_cmd == BIO_DELETE) { - if (DA_SIO) - bioq_disksort(&softc->delete_queue, bp); - else - bioq_insert_tail(&softc->delete_queue, bp); + bioq_disksort(&softc->delete_queue, bp); } else if (DA_SIO) { bioq_disksort(&softc->bio_queue, bp); } else { @@ -2805,16 +2802,9 @@ cmd6workaround(union ccb *ccb) da_delete_method_desc[old_method], da_delete_method_desc[softc->delete_method]); - if (DA_SIO) { - while ((bp = bioq_takefirst(&softc->delete_run_queue)) - != NULL) - bioq_disksort(&softc->delete_queue, bp); - } else { - while ((bp = bioq_takefirst(&softc->delete_run_queue)) - != NULL) - bioq_insert_tail(&softc->delete_queue, bp); - } - bioq_insert_tail(&softc->delete_queue, + while ((bp = bioq_takefirst(&softc->delete_run_queue)) != NULL) + bioq_disksort(&softc->delete_queue, bp); + bioq_disksort(&softc->delete_queue, (struct bio *)ccb->ccb_h.ccb_bp); ccb->ccb_h.ccb_bp = NULL; return (0); From owner-svn-src-stable-10@FreeBSD.ORG Thu Jul 17 23:49:02 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 723C87B0; Thu, 17 Jul 2014 23:49:02 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 53A8F2EC8; Thu, 17 Jul 2014 23:49:02 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6HNn2g2074815; Thu, 17 Jul 2014 23:49:02 GMT (envelope-from truckman@svn.freebsd.org) Received: (from truckman@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6HNn2BQ074814; Thu, 17 Jul 2014 23:49:02 GMT (envelope-from truckman@svn.freebsd.org) Message-Id: <201407172349.s6HNn2BQ074814@svn.freebsd.org> From: Don Lewis Date: Thu, 17 Jul 2014 23:49:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268821 - stable/10/sys/kern X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jul 2014 23:49:02 -0000 Author: truckman Date: Thu Jul 17 23:49:01 2014 New Revision: 268821 URL: http://svnweb.freebsd.org/changeset/base/268821 Log: MFC r268373 Declaration whitespace changes for style(9). Modified: stable/10/sys/kern/subr_rman.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/kern/subr_rman.c ============================================================================== --- stable/10/sys/kern/subr_rman.c Thu Jul 17 23:30:29 2014 (r268820) +++ stable/10/sys/kern/subr_rman.c Thu Jul 17 23:49:01 2014 (r268821) @@ -94,12 +94,12 @@ struct resource_i { u_long r_end; /* index of the last entry (inclusive) */ u_int r_flags; void *r_virtual; /* virtual address of this resource */ - struct device *r_dev; /* device which has allocated this resource */ - struct rman *r_rm; /* resource manager from whence this came */ + struct device *r_dev; /* device which has allocated this resource */ + struct rman *r_rm; /* resource manager from whence this came */ int r_rid; /* optional rid for this resource. */ }; -static int rman_debug = 0; +static int rman_debug = 0; TUNABLE_INT("debug.rman_debug", &rman_debug); SYSCTL_INT(_debug, OID_AUTO, rman_debug, CTLFLAG_RW, &rman_debug, 0, "rman debug"); @@ -108,12 +108,12 @@ SYSCTL_INT(_debug, OID_AUTO, rman_debug, static MALLOC_DEFINE(M_RMAN, "rman", "Resource manager"); -struct rman_head rman_head; -static struct mtx rman_mtx; /* mutex to protect rman_head */ -static int int_rman_activate_resource(struct rman *rm, struct resource_i *r, +struct rman_head rman_head; +static struct mtx rman_mtx; /* mutex to protect rman_head */ +static int int_rman_activate_resource(struct rman *rm, struct resource_i *r, struct resource_i **whohas); -static int int_rman_deactivate_resource(struct resource_i *r); -static int int_rman_release_resource(struct rman *rm, struct resource_i *r); +static int int_rman_deactivate_resource(struct resource_i *r); +static int int_rman_release_resource(struct rman *rm, struct resource_i *r); static __inline struct resource_i * int_alloc_resource(int malloc_flag) @@ -317,8 +317,8 @@ rman_last_free_region(struct rman *rm, u int rman_adjust_resource(struct resource *rr, u_long start, u_long end) { - struct resource_i *r, *s, *t, *new; - struct rman *rm; + struct resource_i *r, *s, *t, *new; + struct rman *rm; /* Not supported for shared resources. */ r = rr->__r_i; @@ -439,12 +439,12 @@ rman_adjust_resource(struct resource *rr struct resource * rman_reserve_resource_bound(struct rman *rm, u_long start, u_long end, - u_long count, u_long bound, u_int flags, - struct device *dev) + u_long count, u_long bound, u_int flags, + struct device *dev) { - u_int new_rflags; - struct resource_i *r, *s, *rv; - u_long rstart, rend, amask, bmask; + u_int new_rflags; + struct resource_i *r, *s, *rv; + u_long rstart, rend, amask, bmask; rv = NULL; @@ -721,9 +721,9 @@ rman_activate_resource(struct resource * int rman_await_resource(struct resource *re, int pri, int timo) { - int rv; - struct resource_i *r, *whohas; - struct rman *rm; + int rv; + struct resource_i *r, *whohas; + struct rman *rm; r = re->__r_i; rm = r->r_rm; @@ -759,7 +759,7 @@ int_rman_deactivate_resource(struct reso int rman_deactivate_resource(struct resource *r) { - struct rman *rm; + struct rman *rm; rm = r->__r_i->r_rm; mtx_lock(rm->rm_mtx); @@ -771,7 +771,7 @@ rman_deactivate_resource(struct resource static int int_rman_release_resource(struct rman *rm, struct resource_i *r) { - struct resource_i *s, *t; + struct resource_i *s, *t; if (r->r_flags & RF_ACTIVE) int_rman_deactivate_resource(r); @@ -865,9 +865,9 @@ out: int rman_release_resource(struct resource *re) { - int rv; - struct resource_i *r; - struct rman *rm; + int rv; + struct resource_i *r; + struct rman *rm; r = re->__r_i; rm = r->r_rm; @@ -880,7 +880,7 @@ rman_release_resource(struct resource *r uint32_t rman_make_alignment_flags(uint32_t size) { - int i; + int i; /* * Find the hightest bit set, and add one if more than one bit @@ -898,96 +898,112 @@ rman_make_alignment_flags(uint32_t size) void rman_set_start(struct resource *r, u_long start) { + r->__r_i->r_start = start; } u_long rman_get_start(struct resource *r) { + return (r->__r_i->r_start); } void rman_set_end(struct resource *r, u_long end) { + r->__r_i->r_end = end; } u_long rman_get_end(struct resource *r) { + return (r->__r_i->r_end); } u_long rman_get_size(struct resource *r) { + return (r->__r_i->r_end - r->__r_i->r_start + 1); } u_int rman_get_flags(struct resource *r) { + return (r->__r_i->r_flags); } void rman_set_virtual(struct resource *r, void *v) { + r->__r_i->r_virtual = v; } void * rman_get_virtual(struct resource *r) { + return (r->__r_i->r_virtual); } void rman_set_bustag(struct resource *r, bus_space_tag_t t) { + r->r_bustag = t; } bus_space_tag_t rman_get_bustag(struct resource *r) { + return (r->r_bustag); } void rman_set_bushandle(struct resource *r, bus_space_handle_t h) { + r->r_bushandle = h; } bus_space_handle_t rman_get_bushandle(struct resource *r) { + return (r->r_bushandle); } void rman_set_rid(struct resource *r, int rid) { + r->__r_i->r_rid = rid; } int rman_get_rid(struct resource *r) { + return (r->__r_i->r_rid); } void rman_set_device(struct resource *r, struct device *dev) { + r->__r_i->r_dev = dev; } struct device * rman_get_device(struct resource *r) { + return (r->__r_i->r_dev); } From owner-svn-src-stable-10@FreeBSD.ORG Fri Jul 18 00:31:07 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 6FA1C149; Fri, 18 Jul 2014 00:31:07 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5D2F92219; Fri, 18 Jul 2014 00:31:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6I0V7Rg096005; Fri, 18 Jul 2014 00:31:07 GMT (envelope-from np@svn.freebsd.org) Received: (from np@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6I0V7eE096004; Fri, 18 Jul 2014 00:31:07 GMT (envelope-from np@svn.freebsd.org) Message-Id: <201407180031.s6I0V7eE096004@svn.freebsd.org> From: Navdeep Parhar Date: Fri, 18 Jul 2014 00:31:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268823 - stable/10/sys/dev/cxgbe X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Jul 2014 00:31:07 -0000 Author: np Date: Fri Jul 18 00:31:06 2014 New Revision: 268823 URL: http://svnweb.freebsd.org/changeset/base/268823 Log: MFC r268706: cxgbe(4): Display CF facility correctly in the device log. Modified: stable/10/sys/dev/cxgbe/t4_main.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/cxgbe/t4_main.c ============================================================================== --- stable/10/sys/dev/cxgbe/t4_main.c Thu Jul 17 23:50:49 2014 (r268822) +++ stable/10/sys/dev/cxgbe/t4_main.c Fri Jul 18 00:31:06 2014 (r268823) @@ -5391,6 +5391,7 @@ const char *devlog_level_strings[] = { const char *devlog_facility_strings[] = { [FW_DEVLOG_FACILITY_CORE] = "CORE", + [FW_DEVLOG_FACILITY_CF] = "CF", [FW_DEVLOG_FACILITY_SCHED] = "SCHED", [FW_DEVLOG_FACILITY_TIMER] = "TIMER", [FW_DEVLOG_FACILITY_RES] = "RES", From owner-svn-src-stable-10@FreeBSD.ORG Sat Jul 19 15:12:38 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id B2ECD45E; Sat, 19 Jul 2014 15:12:38 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9F7672396; Sat, 19 Jul 2014 15:12:38 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JFCcP2008051; Sat, 19 Jul 2014 15:12:38 GMT (envelope-from pfg@svn.freebsd.org) Received: (from pfg@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JFCcMu008050; Sat, 19 Jul 2014 15:12:38 GMT (envelope-from pfg@svn.freebsd.org) Message-Id: <201407191512.s6JFCcMu008050@svn.freebsd.org> From: "Pedro F. Giffuni" Date: Sat, 19 Jul 2014 15:12:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268881 - stable/10/lib/libc/stdlib X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 15:12:38 -0000 Author: pfg Date: Sat Jul 19 15:12:38 2014 New Revision: 268881 URL: http://svnweb.freebsd.org/changeset/base/268881 Log: MFC r268569: strfmon: reduce unnecessary snprintf. No need for the snprintf/asprintf dance; use fixed width formats. Obtained from: NetBSD (CVS rev. 1.8) Modified: stable/10/lib/libc/stdlib/strfmon.c Directory Properties: stable/10/ (props changed) Modified: stable/10/lib/libc/stdlib/strfmon.c ============================================================================== --- stable/10/lib/libc/stdlib/strfmon.c Sat Jul 19 15:11:58 2014 (r268880) +++ stable/10/lib/libc/stdlib/strfmon.c Sat Jul 19 15:12:38 2014 (r268881) @@ -526,7 +526,6 @@ __format_grouped_double(double value, in char *rslt; char *avalue; int avalue_size; - char fmt[32]; size_t bufsize; char *bufend; @@ -567,14 +566,13 @@ __format_grouped_double(double value, in left_prec += get_groups(left_prec, grouping); /* convert to string */ - snprintf(fmt, sizeof(fmt), "%%%d.%df", left_prec + right_prec + 1, - right_prec); - avalue_size = asprintf(&avalue, fmt, value); + avalue_size = asprintf(&avalue, "%*.*f", left_prec + right_prec + 1, + right_prec, value); if (avalue_size < 0) return (NULL); /* make sure that we've enough space for result string */ - bufsize = strlen(avalue)*2+1; + bufsize = avalue_size * 2 + 1; rslt = calloc(1, bufsize); if (rslt == NULL) { free(avalue); From owner-svn-src-stable-10@FreeBSD.ORG Sat Jul 19 18:33:10 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id F1A368BE; Sat, 19 Jul 2014 18:33:09 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DE23E22A9; Sat, 19 Jul 2014 18:33:09 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JIX9ra003018; Sat, 19 Jul 2014 18:33:09 GMT (envelope-from dim@svn.freebsd.org) Received: (from dim@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JIX9WR003017; Sat, 19 Jul 2014 18:33:09 GMT (envelope-from dim@svn.freebsd.org) Message-Id: <201407191833.s6JIX9WR003017@svn.freebsd.org> From: Dimitry Andric Date: Sat, 19 Jul 2014 18:33:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268882 - in stable: 10/sys/conf 9/sys/conf X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 18:33:10 -0000 Author: dim Date: Sat Jul 19 18:33:09 2014 New Revision: 268882 URL: http://svnweb.freebsd.org/changeset/base/268882 Log: MFC r268774: After r261991, clang warnings about unused functions in the kernel were completely silenced. Make sure these warnings appear again, so there is some incentive to fix them, but do not error out the whole kernel build for them. Noticed by: steven@pyro.eu.org PR: 191867 Modified: stable/10/sys/conf/kern.mk Directory Properties: stable/10/ (props changed) Changes in other areas also in this revision: Modified: stable/9/sys/conf/kern.mk Directory Properties: stable/9/sys/ (props changed) Modified: stable/10/sys/conf/kern.mk ============================================================================== --- stable/10/sys/conf/kern.mk Sat Jul 19 15:12:38 2014 (r268881) +++ stable/10/sys/conf/kern.mk Sat Jul 19 18:33:09 2014 (r268882) @@ -29,7 +29,7 @@ NO_WSOMETIMES_UNINITIALIZED= -Wno-error- # enough to error out the whole kernel build. Display them anyway, so there is # some incentive to fix them eventually. CWARNEXTRA?= -Wno-error-tautological-compare -Wno-error-empty-body \ - -Wno-error-parentheses-equality -Wno-unused-function \ + -Wno-error-parentheses-equality -Wno-error-unused-function \ ${NO_WFORMAT} .endif From owner-svn-src-stable-10@FreeBSD.ORG Sat Jul 19 19:56:24 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id F3B2EA85; Sat, 19 Jul 2014 19:56:23 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E03442933; Sat, 19 Jul 2014 19:56:23 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JJuN9B043182; Sat, 19 Jul 2014 19:56:23 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JJuNEl043180; Sat, 19 Jul 2014 19:56:23 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201407191956.s6JJuNEl043180@svn.freebsd.org> From: Hans Petter Selasky Date: Sat, 19 Jul 2014 19:56:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268884 - stable/10/sys/dev/usb/controller X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 19:56:24 -0000 Author: hselasky Date: Sat Jul 19 19:56:23 2014 New Revision: 268884 URL: http://svnweb.freebsd.org/changeset/base/268884 Log: MFC r268735: Improve support for Intel Lynx Point USB 3.0 controllers by using the USB 2.0 port mask in addition to the USB 3.0 port mask. The hardware does not always accept when writing -1U to the port switching registers. Modified: stable/10/sys/dev/usb/controller/xhci_pci.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/usb/controller/xhci_pci.c ============================================================================== --- stable/10/sys/dev/usb/controller/xhci_pci.c Sat Jul 19 18:38:48 2014 (r268883) +++ stable/10/sys/dev/usb/controller/xhci_pci.c Sat Jul 19 19:56:23 2014 (r268884) @@ -150,6 +150,8 @@ static int xhci_pci_port_route(device_t self, uint32_t set, uint32_t clear) { uint32_t temp; + uint32_t usb3_mask; + uint32_t usb2_mask; temp = pci_read_config(self, PCI_XHCI_INTEL_USB3_PSSEN, 4) | pci_read_config(self, PCI_XHCI_INTEL_XUSB2PR, 4); @@ -158,10 +160,11 @@ xhci_pci_port_route(device_t self, uint3 temp &= ~clear; /* Don't set bits which the hardware doesn't support */ - temp &= pci_read_config(self, PCI_XHCI_INTEL_USB3PRM, 4); + usb3_mask = pci_read_config(self, PCI_XHCI_INTEL_USB3PRM, 4); + usb2_mask = pci_read_config(self, PCI_XHCI_INTEL_USB2PRM, 4); - pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp, 4); - pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp, 4); + pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp & usb3_mask, 4); + pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp & usb2_mask, 4); device_printf(self, "Port routing mask set to 0x%08x\n", temp); From owner-svn-src-stable-10@FreeBSD.ORG Sat Jul 19 20:13:02 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9E8F82BF; Sat, 19 Jul 2014 20:13:02 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8A1912AD3; Sat, 19 Jul 2014 20:13:02 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JKD2ln052728; Sat, 19 Jul 2014 20:13:02 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JKD1NE052720; Sat, 19 Jul 2014 20:13:01 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201407192013.s6JKD1NE052720@svn.freebsd.org> From: John Baldwin Date: Sat, 19 Jul 2014 20:13:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268887 - stable/10/usr.sbin/bhyve X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 20:13:02 -0000 Author: jhb Date: Sat Jul 19 20:13:01 2014 New Revision: 268887 URL: http://svnweb.freebsd.org/changeset/base/268887 Log: MFC 261904,261905,262143,262184,264921,265211,267169,267292,267294: Various PCI fixes: - Allow PCI devices to be configured on all valid bus numbers from 0 to 255. - Tweak the handling of PCI capabilities in emulated devices to remove the non-standard zero capability list terminator. - Add a check to validate that memory BARs of passthru devices are 4KB aligned. - Respect and track the enable bit in the PCI configuration address word. - Handle quad-word access to 32-bit register pairs. Modified: stable/10/usr.sbin/bhyve/acpi.c stable/10/usr.sbin/bhyve/bhyve.8 stable/10/usr.sbin/bhyve/bhyverun.c stable/10/usr.sbin/bhyve/mptbl.c stable/10/usr.sbin/bhyve/pci_emul.c stable/10/usr.sbin/bhyve/pci_emul.h stable/10/usr.sbin/bhyve/pci_lpc.c stable/10/usr.sbin/bhyve/pci_passthru.c Directory Properties: stable/10/ (props changed) Modified: stable/10/usr.sbin/bhyve/acpi.c ============================================================================== --- stable/10/usr.sbin/bhyve/acpi.c Sat Jul 19 19:58:26 2014 (r268886) +++ stable/10/usr.sbin/bhyve/acpi.c Sat Jul 19 20:13:01 2014 (r268887) @@ -713,7 +713,7 @@ basl_fwrite_dsdt(FILE *fp) pci_write_dsdt(); dsdt_line(""); - dsdt_line(" Scope (_SB.PCI0)"); + dsdt_line(" Scope (_SB.PC00)"); dsdt_line(" {"); dsdt_line(" Device (HPET)"); dsdt_line(" {"); Modified: stable/10/usr.sbin/bhyve/bhyve.8 ============================================================================== --- stable/10/usr.sbin/bhyve/bhyve.8 Sat Jul 19 19:58:26 2014 (r268886) +++ stable/10/usr.sbin/bhyve/bhyve.8 Sat Jul 19 20:13:01 2014 (r268887) @@ -100,12 +100,16 @@ There are 32 available slots, with the o per slot. .Bl -tag -width 10n .It Ar slot -.Ar pcislot Ns Op Ar :function +.Ar pcislot[:function] +.Ar bus:pcislot:function .Pp The .Ar pcislot -value is 0 to 31 and the optional function value is 0 to 7. +value is 0 to 31. The optional function value is 0 to 7. The optional +.Ar bus +value is 0 to 255. If not specified, the function value defaults to 0. +If not specified, the bus value defaults to 0. .It Ar emulation .Bl -tag -width 10n .It Li hostbridge | Li amd_hostbridge @@ -130,7 +134,8 @@ AHCI controller attached to a SATA hard- .It Li uart PCI 16550 serial device. .It Li lpc -LPC PCI-ISA bridge with COM1 and COM2 16550 serial ports. +LPC PCI-ISA bridge with COM1 and COM2 16550 serial ports. The LPC bridge +emulation can only be configured on bus 0. .El .It Op Ar conf This optional parameter describes the backend for device emulations. @@ -227,6 +232,8 @@ This is intended for debug purposes. Ignore accesses to unimplemented Model Specific Registers (MSRs). This is intended for debug purposes. .It Fl x The guest's local APIC is configured in x2APIC mode. +.It Fl Y +Disable MPtable generation. .It Fl h Print help message and exit. .It Ar vmname Modified: stable/10/usr.sbin/bhyve/bhyverun.c ============================================================================== --- stable/10/usr.sbin/bhyve/bhyverun.c Sat Jul 19 19:58:26 2014 (r268886) +++ stable/10/usr.sbin/bhyve/bhyverun.c Sat Jul 19 20:13:01 2014 (r268887) @@ -144,6 +144,7 @@ usage(int code) " -m: memory size in MB\n" " -w: ignore unimplemented MSRs\n" " -x: local apic is in x2APIC mode\n" + " -Y: disable MPtable generation\n" " -U: uuid\n", progname, (int)strlen(progname), ""); @@ -591,7 +592,7 @@ int main(int argc, char *argv[]) { int c, error, gdb_port, err, bvmcons; - int max_vcpus; + int max_vcpus, mptgen; struct vmctx *ctx; uint64_t rip; size_t memsize; @@ -601,8 +602,9 @@ main(int argc, char *argv[]) gdb_port = 0; guest_ncpus = 1; memsize = 256 * MB; + mptgen = 1; - while ((c = getopt(argc, argv, "abehwxAHIPWp:g:c:s:m:l:U:")) != -1) { + while ((c = getopt(argc, argv, "abehwxAHIPWYp:g:c:s:m:l:U:")) != -1) { switch (c) { case 'a': x2apic_mode = 0; @@ -668,6 +670,9 @@ main(int argc, char *argv[]) case 'x': x2apic_mode = 1; break; + case 'Y': + mptgen = 0; + break; case 'h': usage(0); default: @@ -727,7 +732,11 @@ main(int argc, char *argv[]) /* * build the guest tables, MP etc. */ - mptable_build(ctx, guest_ncpus); + if (mptgen) { + error = mptable_build(ctx, guest_ncpus); + if (error) + exit(1); + } error = smbios_build(ctx); assert(error == 0); Modified: stable/10/usr.sbin/bhyve/mptbl.c ============================================================================== --- stable/10/usr.sbin/bhyve/mptbl.c Sat Jul 19 19:58:26 2014 (r268886) +++ stable/10/usr.sbin/bhyve/mptbl.c Sat Jul 19 20:13:01 2014 (r268887) @@ -196,16 +196,21 @@ mpt_build_ioapic_entries(io_apic_entry_p static int mpt_count_ioint_entries(void) { + int bus, count; + + count = 0; + for (bus = 0; bus <= PCI_BUSMAX; bus++) + count += pci_count_lintr(bus); /* * Always include entries for the first 16 pins along with a entry * for each active PCI INTx pin. */ - return (16 + pci_count_lintr()); + return (16 + count); } static void -mpt_generate_pci_int(int slot, int pin, int ioapic_irq, void *arg) +mpt_generate_pci_int(int bus, int slot, int pin, int ioapic_irq, void *arg) { int_entry_ptr *mpiep, mpie; @@ -219,7 +224,7 @@ mpt_generate_pci_int(int slot, int pin, */ mpie->type = MPCT_ENTRY_INT; mpie->int_type = INTENTRY_TYPE_INT; - mpie->src_bus_id = 0; + mpie->src_bus_id = bus; mpie->src_bus_irq = slot << 2 | (pin - 1); mpie->dst_apic_id = mpie[-1].dst_apic_id; mpie->dst_apic_int = ioapic_irq; @@ -230,7 +235,7 @@ mpt_generate_pci_int(int slot, int pin, static void mpt_build_ioint_entries(int_entry_ptr mpie, int id) { - int pin; + int pin, bus; /* * The following config is taken from kernel mptable.c @@ -277,7 +282,8 @@ mpt_build_ioint_entries(int_entry_ptr mp } /* Next, generate entries for any PCI INTx interrupts. */ - pci_walk_lintr(mpt_generate_pci_int, &mpie); + for (bus = 0; bus <= PCI_BUSMAX; bus++) + pci_walk_lintr(bus, mpt_generate_pci_int, &mpie); } void @@ -297,16 +303,31 @@ mptable_build(struct vmctx *ctx, int ncp proc_entry_ptr mpep; mpfps_t mpfp; int_entry_ptr mpie; - int ioints; + int ioints, bus; char *curraddr; char *startaddr; startaddr = paddr_guest2host(ctx, MPTABLE_BASE, MPTABLE_MAX_LENGTH); if (startaddr == NULL) { - printf("mptable requires mapped mem\n"); + fprintf(stderr, "mptable requires mapped mem\n"); return (ENOMEM); } + /* + * There is no way to advertise multiple PCI hierarchies via MPtable + * so require that there is no PCI hierarchy with a non-zero bus + * number. + */ + for (bus = 1; bus <= PCI_BUSMAX; bus++) { + if (pci_bus_configured(bus)) { + fprintf(stderr, "MPtable is incompatible with " + "multiple PCI hierarchies.\r\n"); + fprintf(stderr, "MPtable generation can be disabled " + "by passing the -Y option to bhyve(8).\r\n"); + return (EINVAL); + } + } + curraddr = startaddr; mpfp = (mpfps_t)curraddr; mpt_build_mpfp(mpfp, MPTABLE_BASE); Modified: stable/10/usr.sbin/bhyve/pci_emul.c ============================================================================== --- stable/10/usr.sbin/bhyve/pci_emul.c Sat Jul 19 19:58:26 2014 (r268886) +++ stable/10/usr.sbin/bhyve/pci_emul.c Sat Jul 19 20:13:01 2014 (r268887) @@ -69,6 +69,7 @@ do { \ } \ } while (0) +#define MAXBUSES (PCI_BUSMAX + 1) #define MAXSLOTS (PCI_SLOTMAX + 1) #define MAXFUNCS (PCI_FUNCMAX + 1) @@ -86,7 +87,16 @@ struct intxinfo { struct slotinfo { struct intxinfo si_intpins[4]; struct funcinfo si_funcs[MAXFUNCS]; -} pci_slotinfo[MAXSLOTS]; +}; + +struct businfo { + uint16_t iobase, iolimit; /* I/O window */ + uint32_t membase32, memlimit32; /* mmio window below 4GB */ + uint64_t membase64, memlimit64; /* mmio window above 4GB */ + struct slotinfo slotinfo[MAXSLOTS]; +}; + +static struct businfo *pci_businfo[MAXBUSES]; SET_DECLARE(pci_devemu_set, struct pci_devemu); @@ -97,7 +107,7 @@ static uint64_t pci_emul_membase64; #define PCI_EMUL_IOBASE 0x2000 #define PCI_EMUL_IOLIMIT 0x10000 -#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */ +#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */ #define PCI_EMUL_MEMBASE64 0xD000000000UL #define PCI_EMUL_MEMLIMIT64 0xFD00000000UL @@ -105,7 +115,6 @@ static uint64_t pci_emul_membase64; static struct pci_devemu *pci_emul_finddev(char *name); static void pci_lintr_update(struct pci_devinst *pi); -static int pci_emul_devices; static struct mem_range pci_mem_hole; /* @@ -115,6 +124,7 @@ static struct mem_range pci_mem_hole; /* * Slot options are in the form: * + * ::,[,] * [:],[,] * * slot is 0..31 @@ -136,37 +146,53 @@ pci_parse_slot_usage(char *aopt) int pci_parse_slot(char *opt) { - char *slot, *func, *emul, *config; - char *str, *cpy; - int error, snum, fnum; + struct businfo *bi; + struct slotinfo *si; + char *emul, *config, *str, *cp; + int error, bnum, snum, fnum; error = -1; - str = cpy = strdup(opt); - - slot = strsep(&str, ","); - func = NULL; - if (strchr(slot, ':') != NULL) { - func = cpy; - (void) strsep(&func, ":"); - } - - emul = strsep(&str, ","); - config = str; + str = strdup(opt); - if (emul == NULL) { + emul = config = NULL; + if ((cp = strchr(str, ',')) != NULL) { + *cp = '\0'; + emul = cp + 1; + if ((cp = strchr(emul, ',')) != NULL) { + *cp = '\0'; + config = cp + 1; + } + } else { pci_parse_slot_usage(opt); goto done; } - snum = atoi(slot); - fnum = func ? atoi(func) : 0; + /* :: */ + if (sscanf(str, "%d:%d:%d", &bnum, &snum, &fnum) != 3) { + bnum = 0; + /* : */ + if (sscanf(str, "%d:%d", &snum, &fnum) != 2) { + fnum = 0; + /* */ + if (sscanf(str, "%d", &snum) != 1) { + snum = -1; + } + } + } - if (snum < 0 || snum >= MAXSLOTS || fnum < 0 || fnum >= MAXFUNCS) { + if (bnum < 0 || bnum >= MAXBUSES || snum < 0 || snum >= MAXSLOTS || + fnum < 0 || fnum >= MAXFUNCS) { pci_parse_slot_usage(opt); goto done; } - if (pci_slotinfo[snum].si_funcs[fnum].fi_name != NULL) { + if (pci_businfo[bnum] == NULL) + pci_businfo[bnum] = calloc(1, sizeof(struct businfo)); + + bi = pci_businfo[bnum]; + si = &bi->slotinfo[snum]; + + if (si->si_funcs[fnum].fi_name != NULL) { fprintf(stderr, "pci slot %d:%d already occupied!\n", snum, fnum); goto done; @@ -179,12 +205,12 @@ pci_parse_slot(char *opt) } error = 0; - pci_slotinfo[snum].si_funcs[fnum].fi_name = emul; - pci_slotinfo[snum].si_funcs[fnum].fi_param = config; + si->si_funcs[fnum].fi_name = emul; + si->si_funcs[fnum].fi_param = config; done: if (error) - free(cpy); + free(str); return (error); } @@ -346,10 +372,27 @@ pci_emul_mem_handler(struct vmctx *ctx, offset = addr - pdi->pi_bar[bidx].addr; - if (dir == MEM_F_WRITE) - (*pe->pe_barwrite)(ctx, vcpu, pdi, bidx, offset, size, *val); - else - *val = (*pe->pe_barread)(ctx, vcpu, pdi, bidx, offset, size); + if (dir == MEM_F_WRITE) { + if (size == 8) { + (*pe->pe_barwrite)(ctx, vcpu, pdi, bidx, offset, + 4, *val & 0xffffffff); + (*pe->pe_barwrite)(ctx, vcpu, pdi, bidx, offset + 4, + 4, *val >> 32); + } else { + (*pe->pe_barwrite)(ctx, vcpu, pdi, bidx, offset, + size, *val); + } + } else { + if (size == 8) { + *val = (*pe->pe_barread)(ctx, vcpu, pdi, bidx, + offset, 4); + *val |= (*pe->pe_barread)(ctx, vcpu, pdi, bidx, + offset + 4, 4) << 32; + } else { + *val = (*pe->pe_barread)(ctx, vcpu, pdi, bidx, + offset, size); + } + } return (0); } @@ -604,48 +647,39 @@ pci_emul_alloc_pbar(struct pci_devinst * static int pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen) { - int i, capoff, capid, reallen; + int i, capoff, reallen; uint16_t sts; - static u_char endofcap[4] = { - PCIY_RESERVED, 0, 0, 0 - }; - - assert(caplen > 0 && capdata[0] != PCIY_RESERVED); + assert(caplen > 0); reallen = roundup2(caplen, 4); /* dword aligned */ sts = pci_get_cfgdata16(pi, PCIR_STATUS); - if ((sts & PCIM_STATUS_CAPPRESENT) == 0) { + if ((sts & PCIM_STATUS_CAPPRESENT) == 0) capoff = CAP_START_OFFSET; - pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff); - pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT); - } else { - capoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR); - while (1) { - assert((capoff & 0x3) == 0); - capid = pci_get_cfgdata8(pi, capoff); - if (capid == PCIY_RESERVED) - break; - capoff = pci_get_cfgdata8(pi, capoff + 1); - } - } + else + capoff = pi->pi_capend + 1; /* Check if we have enough space */ - if (capoff + reallen + sizeof(endofcap) > PCI_REGMAX + 1) + if (capoff + reallen > PCI_REGMAX + 1) return (-1); + /* Set the previous capability pointer */ + if ((sts & PCIM_STATUS_CAPPRESENT) == 0) { + pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff); + pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT); + } else + pci_set_cfgdata8(pi, pi->pi_prevcap + 1, capoff); + /* Copy the capability */ for (i = 0; i < caplen; i++) pci_set_cfgdata8(pi, capoff + i, capdata[i]); /* Set the next capability pointer */ - pci_set_cfgdata8(pi, capoff + 1, capoff + reallen); - - /* Copy of the reserved capability which serves as the end marker */ - for (i = 0; i < sizeof(endofcap); i++) - pci_set_cfgdata8(pi, capoff + reallen + i, endofcap[i]); + pci_set_cfgdata8(pi, capoff + 1, 0); + pi->pi_prevcap = capoff; + pi->pi_capend = capoff + reallen - 1; return (0); } @@ -665,8 +699,8 @@ pci_emul_finddev(char *name) } static int -pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, int func, - char *params) +pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int bus, int slot, + int func, struct funcinfo *fi) { struct pci_devinst *pdi; int err; @@ -675,7 +709,7 @@ pci_emul_init(struct vmctx *ctx, struct bzero(pdi, sizeof(*pdi)); pdi->pi_vmctx = ctx; - pdi->pi_bus = 0; + pdi->pi_bus = bus; pdi->pi_slot = slot; pdi->pi_func = func; pthread_mutex_init(&pdi->pi_lintr.lock, NULL); @@ -692,13 +726,11 @@ pci_emul_init(struct vmctx *ctx, struct pci_set_cfgdata8(pdi, PCIR_COMMAND, PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); - err = (*pde->pe_init)(ctx, pdi, params); - if (err != 0) { + err = (*pde->pe_init)(ctx, pdi, fi->fi_param); + if (err == 0) + fi->fi_devi = pdi; + else free(pdi); - } else { - pci_emul_devices++; - pci_slotinfo[slot].si_funcs[func].fi_devi = pdi; - } return (err); } @@ -732,7 +764,7 @@ pci_emul_add_msicap(struct pci_devinst * static void pci_populate_msixcap(struct msixcap *msixcap, int msgnum, int barnum, - uint32_t msix_tab_size, int nextptr) + uint32_t msix_tab_size) { CTASSERT(sizeof(struct msixcap) == 12); @@ -740,7 +772,6 @@ pci_populate_msixcap(struct msixcap *msi bzero(msixcap, sizeof(struct msixcap)); msixcap->capid = PCIY_MSIX; - msixcap->nextptr = nextptr; /* * Message Control Register, all fields set to @@ -778,7 +809,6 @@ pci_msix_table_init(struct pci_devinst * int pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum) { - uint16_t pba_index; uint32_t tab_size; struct msixcap msixcap; @@ -795,14 +825,11 @@ pci_emul_add_msixcap(struct pci_devinst pi->pi_msix.table_offset = 0; pi->pi_msix.table_count = msgnum; pi->pi_msix.pba_offset = tab_size; - - /* calculate the MMIO size required for MSI-X PBA */ - pba_index = (msgnum - 1) / (PBA_TABLE_ENTRY_SIZE * 8); - pi->pi_msix.pba_size = (pba_index + 1) * PBA_TABLE_ENTRY_SIZE; + pi->pi_msix.pba_size = PBA_SIZE(msgnum); pci_msix_table_init(pi, msgnum); - pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size, 0); + pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size); /* allocate memory for MSI-X Table and PBA */ pci_emul_alloc_bar(pi, barnum, PCIBAR_MEM32, @@ -925,11 +952,9 @@ pci_emul_capwrite(struct pci_devinst *pi /* Find the capability that we want to update */ capoff = CAP_START_OFFSET; while (1) { - capid = pci_get_cfgdata8(pi, capoff); - if (capid == PCIY_RESERVED) - break; - nextoff = pci_get_cfgdata8(pi, capoff + 1); + if (nextoff == 0) + break; if (offset >= capoff && offset < nextoff) break; @@ -952,6 +977,7 @@ pci_emul_capwrite(struct pci_devinst *pi return; } + capid = pci_get_cfgdata8(pi, capoff); switch (capid) { case PCIY_MSI: msicap_cfgwrite(pi, capoff, offset, bytes, val); @@ -970,25 +996,14 @@ pci_emul_capwrite(struct pci_devinst *pi static int pci_emul_iscap(struct pci_devinst *pi, int offset) { - int found; uint16_t sts; - uint8_t capid, lastoff; - found = 0; sts = pci_get_cfgdata16(pi, PCIR_STATUS); if ((sts & PCIM_STATUS_CAPPRESENT) != 0) { - lastoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR); - while (1) { - assert((lastoff & 0x3) == 0); - capid = pci_get_cfgdata8(pi, lastoff); - if (capid == PCIY_RESERVED) - break; - lastoff = pci_get_cfgdata8(pi, lastoff + 1); - } - if (offset >= CAP_START_OFFSET && offset <= lastoff) - found = 1; + if (offset >= CAP_START_OFFSET && offset <= pi->pi_capend) + return (1); } - return (found); + return (0); } static int @@ -1006,31 +1021,68 @@ pci_emul_fallback_handler(struct vmctx * return (0); } +#define BUSIO_ROUNDUP 32 +#define BUSMEM_ROUNDUP (1024 * 1024) + int init_pci(struct vmctx *ctx) { struct pci_devemu *pde; + struct businfo *bi; + struct slotinfo *si; struct funcinfo *fi; size_t lowmem; - int slot, func; + int bus, slot, func; int error; pci_emul_iobase = PCI_EMUL_IOBASE; pci_emul_membase32 = vm_get_lowmem_limit(ctx); pci_emul_membase64 = PCI_EMUL_MEMBASE64; - for (slot = 0; slot < MAXSLOTS; slot++) { - for (func = 0; func < MAXFUNCS; func++) { - fi = &pci_slotinfo[slot].si_funcs[func]; - if (fi->fi_name != NULL) { + for (bus = 0; bus < MAXBUSES; bus++) { + if ((bi = pci_businfo[bus]) == NULL) + continue; + /* + * Keep track of the i/o and memory resources allocated to + * this bus. + */ + bi->iobase = pci_emul_iobase; + bi->membase32 = pci_emul_membase32; + bi->membase64 = pci_emul_membase64; + + for (slot = 0; slot < MAXSLOTS; slot++) { + si = &bi->slotinfo[slot]; + for (func = 0; func < MAXFUNCS; func++) { + fi = &si->si_funcs[func]; + if (fi->fi_name == NULL) + continue; pde = pci_emul_finddev(fi->fi_name); assert(pde != NULL); - error = pci_emul_init(ctx, pde, slot, func, - fi->fi_param); + error = pci_emul_init(ctx, pde, bus, slot, + func, fi); if (error) return (error); } } + + /* + * Add some slop to the I/O and memory resources decoded by + * this bus to give a guest some flexibility if it wants to + * reprogram the BARs. + */ + pci_emul_iobase += BUSIO_ROUNDUP; + pci_emul_iobase = roundup2(pci_emul_iobase, BUSIO_ROUNDUP); + bi->iolimit = pci_emul_iobase; + + pci_emul_membase32 += BUSMEM_ROUNDUP; + pci_emul_membase32 = roundup2(pci_emul_membase32, + BUSMEM_ROUNDUP); + bi->memlimit32 = pci_emul_membase32; + + pci_emul_membase64 += BUSMEM_ROUNDUP; + pci_emul_membase64 = roundup2(pci_emul_membase64, + BUSMEM_ROUNDUP); + bi->memlimit64 = pci_emul_membase64; } /* @@ -1060,7 +1112,7 @@ init_pci(struct vmctx *ctx) } static void -pci_prt_entry(int slot, int pin, int ioapic_irq, void *arg) +pci_prt_entry(int bus, int slot, int pin, int ioapic_irq, void *arg) { int *count; @@ -1075,96 +1127,165 @@ pci_prt_entry(int slot, int pin, int ioa (*count)--; } -void -pci_write_dsdt(void) +/* + * A bhyve virtual machine has a flat PCI hierarchy with a root port + * corresponding to each PCI bus. + */ +static void +pci_bus_write_dsdt(int bus) { + struct businfo *bi; + struct slotinfo *si; struct pci_devinst *pi; int count, slot, func; + /* + * If there are no devices on this 'bus' then just return. + */ + if ((bi = pci_businfo[bus]) == NULL) { + /* + * Bus 0 is special because it decodes the I/O ports used + * for PCI config space access even if there are no devices + * on it. + */ + if (bus != 0) + return; + } + dsdt_indent(1); dsdt_line("Scope (_SB)"); dsdt_line("{"); - dsdt_line(" Device (PCI0)"); + dsdt_line(" Device (PC%02X)", bus); dsdt_line(" {"); dsdt_line(" Name (_HID, EisaId (\"PNP0A03\"))"); dsdt_line(" Name (_ADR, Zero)"); + + dsdt_line(" Method (_BBN, 0, NotSerialized)"); + dsdt_line(" {"); + dsdt_line(" Return (0x%08X)", bus); + dsdt_line(" }"); dsdt_line(" Name (_CRS, ResourceTemplate ()"); dsdt_line(" {"); dsdt_line(" WordBusNumber (ResourceProducer, MinFixed, " "MaxFixed, PosDecode,"); dsdt_line(" 0x0000, // Granularity"); - dsdt_line(" 0x0000, // Range Minimum"); - dsdt_line(" 0x00FF, // Range Maximum"); + dsdt_line(" 0x%04X, // Range Minimum", bus); + dsdt_line(" 0x%04X, // Range Maximum", bus); dsdt_line(" 0x0000, // Translation Offset"); - dsdt_line(" 0x0100, // Length"); + dsdt_line(" 0x0001, // Length"); dsdt_line(" ,, )"); - dsdt_indent(3); - dsdt_fixed_ioport(0xCF8, 8); - dsdt_unindent(3); - dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, " - "PosDecode, EntireRange,"); - dsdt_line(" 0x0000, // Granularity"); - dsdt_line(" 0x0000, // Range Minimum"); - dsdt_line(" 0x0CF7, // Range Maximum"); - dsdt_line(" 0x0000, // Translation Offset"); - dsdt_line(" 0x0CF8, // Length"); - dsdt_line(" ,, , TypeStatic)"); + + if (bus == 0) { + dsdt_indent(3); + dsdt_fixed_ioport(0xCF8, 8); + dsdt_unindent(3); + + dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, " + "PosDecode, EntireRange,"); + dsdt_line(" 0x0000, // Granularity"); + dsdt_line(" 0x0000, // Range Minimum"); + dsdt_line(" 0x0CF7, // Range Maximum"); + dsdt_line(" 0x0000, // Translation Offset"); + dsdt_line(" 0x0CF8, // Length"); + dsdt_line(" ,, , TypeStatic)"); + + dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, " + "PosDecode, EntireRange,"); + dsdt_line(" 0x0000, // Granularity"); + dsdt_line(" 0x0D00, // Range Minimum"); + dsdt_line(" 0x%04X, // Range Maximum", + PCI_EMUL_IOBASE - 1); + dsdt_line(" 0x0000, // Translation Offset"); + dsdt_line(" 0x%04X, // Length", + PCI_EMUL_IOBASE - 0x0D00); + dsdt_line(" ,, , TypeStatic)"); + + if (bi == NULL) { + dsdt_line(" })"); + goto done; + } + } + assert(bi != NULL); + + /* i/o window */ dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, " "PosDecode, EntireRange,"); dsdt_line(" 0x0000, // Granularity"); - dsdt_line(" 0x0D00, // Range Minimum"); - dsdt_line(" 0xFFFF, // Range Maximum"); + dsdt_line(" 0x%04X, // Range Minimum", bi->iobase); + dsdt_line(" 0x%04X, // Range Maximum", + bi->iolimit - 1); dsdt_line(" 0x0000, // Translation Offset"); - dsdt_line(" 0xF300, // Length"); + dsdt_line(" 0x%04X, // Length", + bi->iolimit - bi->iobase); dsdt_line(" ,, , TypeStatic)"); + + /* mmio window (32-bit) */ dsdt_line(" DWordMemory (ResourceProducer, PosDecode, " "MinFixed, MaxFixed, NonCacheable, ReadWrite,"); dsdt_line(" 0x00000000, // Granularity"); - dsdt_line(" 0x%08lX, // Range Minimum\n", - pci_mem_hole.base); + dsdt_line(" 0x%08X, // Range Minimum\n", bi->membase32); dsdt_line(" 0x%08X, // Range Maximum\n", - PCI_EMUL_MEMLIMIT32 - 1); + bi->memlimit32 - 1); dsdt_line(" 0x00000000, // Translation Offset"); - dsdt_line(" 0x%08lX, // Length\n", - PCI_EMUL_MEMLIMIT32 - pci_mem_hole.base); + dsdt_line(" 0x%08X, // Length\n", + bi->memlimit32 - bi->membase32); dsdt_line(" ,, , AddressRangeMemory, TypeStatic)"); + + /* mmio window (64-bit) */ dsdt_line(" QWordMemory (ResourceProducer, PosDecode, " "MinFixed, MaxFixed, NonCacheable, ReadWrite,"); dsdt_line(" 0x0000000000000000, // Granularity"); - dsdt_line(" 0x%016lX, // Range Minimum\n", - PCI_EMUL_MEMBASE64); + dsdt_line(" 0x%016lX, // Range Minimum\n", bi->membase64); dsdt_line(" 0x%016lX, // Range Maximum\n", - PCI_EMUL_MEMLIMIT64 - 1); + bi->memlimit64 - 1); dsdt_line(" 0x0000000000000000, // Translation Offset"); dsdt_line(" 0x%016lX, // Length\n", - PCI_EMUL_MEMLIMIT64 - PCI_EMUL_MEMBASE64); + bi->memlimit64 - bi->membase64); dsdt_line(" ,, , AddressRangeMemory, TypeStatic)"); dsdt_line(" })"); - count = pci_count_lintr(); + + count = pci_count_lintr(bus); if (count != 0) { dsdt_indent(2); dsdt_line("Name (_PRT, Package (0x%02X)", count); dsdt_line("{"); - pci_walk_lintr(pci_prt_entry, &count); + pci_walk_lintr(bus, pci_prt_entry, &count); dsdt_line("})"); dsdt_unindent(2); } dsdt_indent(2); for (slot = 0; slot < MAXSLOTS; slot++) { + si = &bi->slotinfo[slot]; for (func = 0; func < MAXFUNCS; func++) { - pi = pci_slotinfo[slot].si_funcs[func].fi_devi; + pi = si->si_funcs[func].fi_devi; if (pi != NULL && pi->pi_d->pe_write_dsdt != NULL) pi->pi_d->pe_write_dsdt(pi); } } dsdt_unindent(2); - +done: dsdt_line(" }"); dsdt_line("}"); dsdt_unindent(1); } +void +pci_write_dsdt(void) +{ + int bus; + + for (bus = 0; bus < MAXBUSES; bus++) + pci_bus_write_dsdt(bus); +} + +int +pci_bus_configured(int bus) +{ + assert(bus >= 0 && bus < MAXBUSES); + return (pci_businfo[bus] != NULL); +} + int pci_msi_enabled(struct pci_devinst *pi) { @@ -1231,13 +1352,17 @@ pci_lintr_permitted(struct pci_devinst * int pci_lintr_request(struct pci_devinst *pi) { + struct businfo *bi; struct slotinfo *si; int bestpin, bestcount, irq, pin; + bi = pci_businfo[pi->pi_bus]; + assert(bi != NULL); + /* * First, allocate a pin from our slot. */ - si = &pci_slotinfo[pi->pi_slot]; + si = &bi->slotinfo[pi->pi_slot]; bestpin = 0; bestcount = si->si_intpins[0].ii_count; for (pin = 1; pin < 4; pin++) { @@ -1318,31 +1443,41 @@ pci_lintr_update(struct pci_devinst *pi) } int -pci_count_lintr(void) +pci_count_lintr(int bus) { int count, slot, pin; + struct slotinfo *slotinfo; count = 0; - for (slot = 0; slot < MAXSLOTS; slot++) { - for (pin = 0; pin < 4; pin++) { - if (pci_slotinfo[slot].si_intpins[pin].ii_count != 0) - count++; + if (pci_businfo[bus] != NULL) { + for (slot = 0; slot < MAXSLOTS; slot++) { + slotinfo = &pci_businfo[bus]->slotinfo[slot]; + for (pin = 0; pin < 4; pin++) { + if (slotinfo->si_intpins[pin].ii_count != 0) + count++; + } } } return (count); } void -pci_walk_lintr(pci_lintr_cb cb, void *arg) +pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg) { + struct businfo *bi; + struct slotinfo *si; struct intxinfo *ii; int slot, pin; + if ((bi = pci_businfo[bus]) == NULL) + return; + for (slot = 0; slot < MAXSLOTS; slot++) { + si = &bi->slotinfo[slot]; for (pin = 0; pin < 4; pin++) { - ii = &pci_slotinfo[slot].si_intpins[pin]; + ii = &si->si_intpins[pin]; if (ii->ii_count != 0) - cb(slot, pin + 1, ii->ii_ioapic_irq, arg); + cb(bus, slot, pin + 1, ii->ii_ioapic_irq, arg); } } } @@ -1352,14 +1487,19 @@ pci_walk_lintr(pci_lintr_cb cb, void *ar * Return 0 otherwise. */ static int -pci_emul_is_mfdev(int slot) +pci_emul_is_mfdev(int bus, int slot) { + struct businfo *bi; + struct slotinfo *si; int f, numfuncs; numfuncs = 0; - for (f = 0; f < MAXFUNCS; f++) { - if (pci_slotinfo[slot].si_funcs[f].fi_devi != NULL) { - numfuncs++; + if ((bi = pci_businfo[bus]) != NULL) { + si = &bi->slotinfo[slot]; + for (f = 0; f < MAXFUNCS; f++) { + if (si->si_funcs[f].fi_devi != NULL) { + numfuncs++; + } } } return (numfuncs > 1); @@ -1370,12 +1510,12 @@ pci_emul_is_mfdev(int slot) * whether or not is a multi-function being emulated in the pci 'slot'. */ static void -pci_emul_hdrtype_fixup(int slot, int off, int bytes, uint32_t *rv) +pci_emul_hdrtype_fixup(int bus, int slot, int off, int bytes, uint32_t *rv) { int mfdev; if (off <= PCIR_HDRTYPE && off + bytes > PCIR_HDRTYPE) { - mfdev = pci_emul_is_mfdev(slot); + mfdev = pci_emul_is_mfdev(bus, slot); switch (bytes) { case 1: case 2: @@ -1394,7 +1534,7 @@ pci_emul_hdrtype_fixup(int slot, int off } } -static int cfgbus, cfgslot, cfgfunc, cfgoff; +static int cfgenable, cfgbus, cfgslot, cfgfunc, cfgoff; static int pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes, @@ -1413,9 +1553,12 @@ pci_emul_cfgaddr(struct vmctx *ctx, int (cfgslot << 11) | (cfgfunc << 8) | cfgoff; - *eax = x | CONF1_ENABLE; + if (cfgenable) + x |= CONF1_ENABLE; + *eax = x; } else { x = *eax; + cfgenable = (x & CONF1_ENABLE) == CONF1_ENABLE; cfgoff = x & PCI_REGMAX; cfgfunc = (x >> 8) & PCI_FUNCMAX; cfgslot = (x >> 11) & PCI_SLOTMAX; @@ -1492,16 +1635,19 @@ static int pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes, uint32_t *eax, void *arg) { + struct businfo *bi; + struct slotinfo *si; struct pci_devinst *pi; struct pci_devemu *pe; int coff, idx, needcfg; uint64_t addr, bar, mask; assert(bytes == 1 || bytes == 2 || bytes == 4); - - if (cfgbus == 0) - pi = pci_slotinfo[cfgslot].si_funcs[cfgfunc].fi_devi; - else + + if ((bi = pci_businfo[cfgbus]) != NULL) { + si = &bi->slotinfo[cfgslot]; + pi = si->si_funcs[cfgfunc].fi_devi; + } else pi = NULL; *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-stable-10@FreeBSD.ORG Sat Jul 19 22:06:49 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 0990CFD8; Sat, 19 Jul 2014 22:06:49 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DEA0F2346; Sat, 19 Jul 2014 22:06:48 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JM6msM005676; Sat, 19 Jul 2014 22:06:48 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JM6lEv005666; Sat, 19 Jul 2014 22:06:47 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201407192206.s6JM6lEv005666@svn.freebsd.org> From: John Baldwin Date: Sat, 19 Jul 2014 22:06:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268891 - in stable/10: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/amd64/vmm/intel sys/amd64/vmm/io sys/modules/vmm usr.sbin/bhyve X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 22:06:49 -0000 Author: jhb Date: Sat Jul 19 22:06:46 2014 New Revision: 268891 URL: http://svnweb.freebsd.org/changeset/base/268891 Log: MFC 259942,262274,263035,263054,263211,263744,264179,264324,264468,264631, 264648,264650,264651,266572,267558: Flesh out the AT PIC and 8254 PIT emulations and move them into the kernel. Added: stable/10/sys/amd64/vmm/io/vatpic.c - copied, changed from r263035, head/sys/amd64/vmm/io/vatpic.c stable/10/sys/amd64/vmm/io/vatpic.h - copied, changed from r263035, head/sys/amd64/vmm/io/vatpic.h stable/10/sys/amd64/vmm/io/vatpit.c - copied, changed from r263744, head/sys/amd64/vmm/io/vatpit.c stable/10/sys/amd64/vmm/io/vatpit.h - copied, changed from r263744, head/sys/amd64/vmm/io/vatpit.h stable/10/sys/amd64/vmm/vmm_ioport.c - copied, changed from r263035, head/sys/amd64/vmm/vmm_ioport.c stable/10/sys/amd64/vmm/vmm_ioport.h - copied, changed from r263035, head/sys/amd64/vmm/vmm_ioport.h Deleted: stable/10/usr.sbin/bhyve/atpic.c stable/10/usr.sbin/bhyve/elcr.c stable/10/usr.sbin/bhyve/pit_8254.c stable/10/usr.sbin/bhyve/pit_8254.h Modified: stable/10/lib/libvmmapi/vmmapi.c stable/10/lib/libvmmapi/vmmapi.h stable/10/sys/amd64/include/vmm.h stable/10/sys/amd64/include/vmm_dev.h stable/10/sys/amd64/vmm/intel/vmx.c stable/10/sys/amd64/vmm/io/vhpet.c stable/10/sys/amd64/vmm/io/vlapic.c stable/10/sys/amd64/vmm/vmm.c stable/10/sys/amd64/vmm/vmm_dev.c stable/10/sys/modules/vmm/Makefile stable/10/usr.sbin/bhyve/Makefile stable/10/usr.sbin/bhyve/inout.c stable/10/usr.sbin/bhyve/pci_lpc.c stable/10/usr.sbin/bhyve/pm.c Directory Properties: stable/10/ (props changed) Modified: stable/10/lib/libvmmapi/vmmapi.c ============================================================================== --- stable/10/lib/libvmmapi/vmmapi.c Sat Jul 19 21:04:21 2014 (r268890) +++ stable/10/lib/libvmmapi/vmmapi.c Sat Jul 19 22:06:46 2014 (r268891) @@ -458,6 +458,41 @@ vm_ioapic_pincount(struct vmctx *ctx, in } int +vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) +{ + struct vm_isa_irq isa_irq; + + bzero(&isa_irq, sizeof(struct vm_isa_irq)); + isa_irq.atpic_irq = atpic_irq; + isa_irq.ioapic_irq = ioapic_irq; + + return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq)); +} + +int +vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) +{ + struct vm_isa_irq isa_irq; + + bzero(&isa_irq, sizeof(struct vm_isa_irq)); + isa_irq.atpic_irq = atpic_irq; + isa_irq.ioapic_irq = ioapic_irq; + + return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq)); +} + +int +vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq) +{ + struct vm_isa_irq isa_irq; + bzero(&isa_irq, sizeof(struct vm_isa_irq)); + isa_irq.atpic_irq = atpic_irq; + isa_irq.ioapic_irq = ioapic_irq; + + return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq)); +} + +int vm_inject_nmi(struct vmctx *ctx, int vcpu) { struct vm_nmi vmnmi; Modified: stable/10/lib/libvmmapi/vmmapi.h ============================================================================== --- stable/10/lib/libvmmapi/vmmapi.h Sat Jul 19 21:04:21 2014 (r268890) +++ stable/10/lib/libvmmapi/vmmapi.h Sat Jul 19 22:06:46 2014 (r268891) @@ -71,6 +71,9 @@ int vm_ioapic_assert_irq(struct vmctx *c int vm_ioapic_deassert_irq(struct vmctx *ctx, int irq); int vm_ioapic_pulse_irq(struct vmctx *ctx, int irq); int vm_ioapic_pincount(struct vmctx *ctx, int *pincount); +int vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq); +int vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq); +int vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq); int vm_inject_nmi(struct vmctx *ctx, int vcpu); int vm_capability_name2type(const char *capname); const char *vm_capability_type2name(int type); Modified: stable/10/sys/amd64/include/vmm.h ============================================================================== --- stable/10/sys/amd64/include/vmm.h Sat Jul 19 21:04:21 2014 (r268890) +++ stable/10/sys/amd64/include/vmm.h Sat Jul 19 22:06:46 2014 (r268891) @@ -117,6 +117,9 @@ int vm_run(struct vm *vm, struct vm_run int vm_inject_nmi(struct vm *vm, int vcpu); int vm_nmi_pending(struct vm *vm, int vcpuid); void vm_nmi_clear(struct vm *vm, int vcpuid); +int vm_inject_extint(struct vm *vm, int vcpu); +int vm_extint_pending(struct vm *vm, int vcpuid); +void vm_extint_clear(struct vm *vm, int vcpuid); uint64_t *vm_guest_msrs(struct vm *vm, int cpu); struct vlapic *vm_lapic(struct vm *vm, int cpu); struct vioapic *vm_ioapic(struct vm *vm); @@ -187,6 +190,8 @@ void vcpu_notify_event(struct vm *vm, in struct vmspace *vm_get_vmspace(struct vm *vm); int vm_assign_pptdev(struct vm *vm, int bus, int slot, int func); int vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); +struct vatpic *vm_atpic(struct vm *vm); +struct vatpit *vm_atpit(struct vm *vm); /* * Inject exception 'vme' into the guest vcpu. This function returns 0 on Modified: stable/10/sys/amd64/include/vmm_dev.h ============================================================================== --- stable/10/sys/amd64/include/vmm_dev.h Sat Jul 19 21:04:21 2014 (r268890) +++ stable/10/sys/amd64/include/vmm_dev.h Sat Jul 19 22:06:46 2014 (r268891) @@ -79,6 +79,11 @@ struct vm_ioapic_irq { int irq; }; +struct vm_isa_irq { + int atpic_irq; + int ioapic_irq; +}; + struct vm_capability { int cpuid; enum vm_cap_type captype; @@ -198,6 +203,11 @@ enum { IOCNUM_SET_X2APIC_STATE = 60, IOCNUM_GET_X2APIC_STATE = 61, IOCNUM_GET_HPET_CAPABILITIES = 62, + + /* legacy interrupt injection */ + IOCNUM_ISA_ASSERT_IRQ = 80, + IOCNUM_ISA_DEASSERT_IRQ = 81, + IOCNUM_ISA_PULSE_IRQ = 82, }; #define VM_RUN \ @@ -230,6 +240,12 @@ enum { _IOW('v', IOCNUM_IOAPIC_PULSE_IRQ, struct vm_ioapic_irq) #define VM_IOAPIC_PINCOUNT \ _IOR('v', IOCNUM_IOAPIC_PINCOUNT, int) +#define VM_ISA_ASSERT_IRQ \ + _IOW('v', IOCNUM_ISA_ASSERT_IRQ, struct vm_isa_irq) +#define VM_ISA_DEASSERT_IRQ \ + _IOW('v', IOCNUM_ISA_DEASSERT_IRQ, struct vm_isa_irq) +#define VM_ISA_PULSE_IRQ \ + _IOW('v', IOCNUM_ISA_PULSE_IRQ, struct vm_isa_irq) #define VM_SET_CAPABILITY \ _IOW('v', IOCNUM_SET_CAPABILITY, struct vm_capability) #define VM_GET_CAPABILITY \ Modified: stable/10/sys/amd64/vmm/intel/vmx.c ============================================================================== --- stable/10/sys/amd64/vmm/intel/vmx.c Sat Jul 19 21:04:21 2014 (r268890) +++ stable/10/sys/amd64/vmm/intel/vmx.c Sat Jul 19 22:06:46 2014 (r268891) @@ -52,10 +52,12 @@ __FBSDID("$FreeBSD$"); #include #include #include "vmm_host.h" +#include "vmm_ioport.h" #include "vmm_ipi.h" #include "vmm_msr.h" #include "vmm_ktr.h" #include "vmm_stat.h" +#include "vatpic.h" #include "vlapic.h" #include "vlapic_priv.h" @@ -1046,6 +1048,7 @@ vmx_set_pcpu_defaults(struct vmx *vmx, i invvpid_desc._res1 = 0; invvpid_desc._res2 = 0; invvpid_desc.vpid = vmxstate->vpid; + invvpid_desc.linear_addr = 0; invvpid(INVVPID_TYPE_SINGLE_CONTEXT, invvpid_desc); } else { /* @@ -1143,7 +1146,7 @@ static void vmx_inject_interrupts(struct vmx *vmx, int vcpu, struct vlapic *vlapic) { struct vm_exception exc; - int vector, need_nmi_exiting; + int vector, need_nmi_exiting, extint_pending; uint64_t rflags; uint32_t gi, info; @@ -1195,7 +1198,9 @@ vmx_inject_interrupts(struct vmx *vmx, i vmx_set_nmi_window_exiting(vmx, vcpu); } - if (virtual_interrupt_delivery) { + extint_pending = vm_extint_pending(vmx->vm, vcpu); + + if (!extint_pending && virtual_interrupt_delivery) { vmx_inject_pir(vlapic); return; } @@ -1211,11 +1216,32 @@ vmx_inject_interrupts(struct vmx *vmx, i return; } - /* Ask the local apic for a vector to inject */ - if (!vlapic_pending_intr(vlapic, &vector)) - return; + if (!extint_pending) { + /* Ask the local apic for a vector to inject */ + if (!vlapic_pending_intr(vlapic, &vector)) + return; - KASSERT(vector >= 32 && vector <= 255, ("invalid vector %d", vector)); + /* + * From the Intel SDM, Volume 3, Section "Maskable + * Hardware Interrupts": + * - maskable interrupt vectors [16,255] can be delivered + * through the local APIC. + */ + KASSERT(vector >= 16 && vector <= 255, + ("invalid vector %d from local APIC", vector)); + } else { + /* Ask the legacy pic for a vector to inject */ + vatpic_pending_intr(vmx->vm, &vector); + + /* + * From the Intel SDM, Volume 3, Section "Maskable + * Hardware Interrupts": + * - maskable interrupt vectors [0,255] can be delivered + * through the INTR pin. + */ + KASSERT(vector >= 0 && vector <= 255, + ("invalid vector %d from INTR", vector)); + } /* Check RFLAGS.IF and the interruptibility state of the guest */ rflags = vmcs_read(VMCS_GUEST_RFLAGS); @@ -1251,8 +1277,22 @@ vmx_inject_interrupts(struct vmx *vmx, i info |= vector; vmcs_write(VMCS_ENTRY_INTR_INFO, info); - /* Update the Local APIC ISR */ - vlapic_intr_accepted(vlapic, vector); + if (!extint_pending) { + /* Update the Local APIC ISR */ + vlapic_intr_accepted(vlapic, vector); + } else { + vm_extint_clear(vmx->vm, vcpu); + vatpic_intr_accepted(vmx->vm, vector); + + /* + * After we accepted the current ExtINT the PIC may + * have posted another one. If that is the case, set + * the Interrupt Window Exiting execution control so + * we can inject that one too. + */ + if (vm_extint_pending(vmx->vm, vcpu)) + vmx_set_int_window_exiting(vmx, vcpu); + } VCPU_CTR1(vmx->vm, vcpu, "Injecting hwintr at vector %d", vector); @@ -1388,6 +1428,7 @@ vmx_emulate_cr_access(struct vmx *vmx, i if (cr != 0 && cr != 4) return (UNHANDLED); + regval = 0; /* silence gcc */ vmxctx = &vmx->ctx[vcpu]; /* @@ -1882,6 +1923,11 @@ vmx_exit_process(struct vmx *vmx, int vc vmexit->u.inout.rep = (qual & 0x20) ? 1 : 0; vmexit->u.inout.port = (uint16_t)(qual >> 16); vmexit->u.inout.eax = (uint32_t)(vmxctx->guest_rax); + error = emulate_ioport(vmx->vm, vcpu, vmexit); + if (error == 0) { + handled = 1; + vmxctx->guest_rax = vmexit->u.inout.eax; + } break; case EXIT_REASON_CPUID: vmm_stat_incr(vmx->vm, vcpu, VMEXIT_CPUID, 1); @@ -2719,7 +2765,7 @@ vmx_inject_pir(struct vlapic *vlapic) struct pir_desc *pir_desc; struct LAPIC *lapic; uint64_t val, pirval; - int rvi, pirbase; + int rvi, pirbase = -1; uint16_t intr_status_old, intr_status_new; vlapic_vtx = (struct vlapic_vtx *)vlapic; @@ -2731,6 +2777,7 @@ vmx_inject_pir(struct vlapic *vlapic) } pirval = 0; + pirbase = -1; lapic = vlapic->apic_page; val = atomic_readandclear_long(&pir_desc->pir[0]); @@ -2764,11 +2811,29 @@ vmx_inject_pir(struct vlapic *vlapic) pirbase = 192; pirval = val; } + VLAPIC_CTR_IRR(vlapic, "vmx_inject_pir"); /* * Update RVI so the processor can evaluate pending virtual * interrupts on VM-entry. + * + * It is possible for pirval to be 0 here, even though the + * pending bit has been set. The scenario is: + * CPU-Y is sending a posted interrupt to CPU-X, which + * is running a guest and processing posted interrupts in h/w. + * CPU-X will eventually exit and the state seen in s/w is + * the pending bit set, but no PIR bits set. + * + * CPU-X CPU-Y + * (vm running) (host running) + * rx posted interrupt + * CLEAR pending bit + * SET PIR bit + * READ/CLEAR PIR bits + * SET pending bit + * (vm exit) + * pending bit set, PIR 0 */ if (pirval != 0) { rvi = pirbase + flsl(pirval) - 1; Copied and modified: stable/10/sys/amd64/vmm/io/vatpic.c (from r263035, head/sys/amd64/vmm/io/vatpic.c) ============================================================================== --- head/sys/amd64/vmm/io/vatpic.c Tue Mar 11 16:56:00 2014 (r263035, copy source) +++ stable/10/sys/amd64/vmm/io/vatpic.c Sat Jul 19 22:06:46 2014 (r268891) @@ -67,6 +67,7 @@ struct atpic { bool aeoi; bool poll; bool rotate; + bool sfn; /* special fully-nested mode */ int irq_base; uint8_t request; /* Interrupt Request Register (IIR) */ @@ -75,6 +76,8 @@ struct atpic { int acnt[8]; /* sum of pin asserts and deasserts */ int priority; /* current pin priority */ + + bool intr_raised; }; struct vatpic { @@ -99,6 +102,7 @@ struct vatpic { #define VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4) \ VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4) +static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate); static __inline int vatpic_get_highest_isrpin(struct atpic *atpic) @@ -120,13 +124,23 @@ vatpic_get_highest_isrpin(struct atpic * static __inline int vatpic_get_highest_irrpin(struct atpic *atpic) { + int serviced; int bit, pin; int i, j; + /* + * In 'Special Fully-Nested Mode' when an interrupt request from + * a slave is in service, the slave is not locked out from the + * master's priority logic. + */ + serviced = atpic->service; + if (atpic->sfn) + serviced &= ~(1 << 2); + for (i = 0; i <= 7; i++) { pin = ((i + 7 - atpic->priority) & 0x7); bit = (1 << pin); - if (atpic->service & bit) + if (serviced & bit) break; } @@ -148,17 +162,65 @@ vatpic_notify_intr(struct vatpic *vatpic KASSERT(VATPIC_LOCKED(vatpic), ("vatpic_notify_intr not locked")); - /* XXX master only */ - atpic = &vatpic->atpic[0]; + /* + * First check the slave. + */ + atpic = &vatpic->atpic[1]; + if (!atpic->intr_raised && + (pin = vatpic_get_highest_irrpin(atpic)) != -1) { + VATPIC_CTR4(vatpic, "atpic slave notify pin = %d " + "(imr 0x%x irr 0x%x isr 0x%x)", pin, + atpic->mask, atpic->request, atpic->service); + + /* + * Cascade the request from the slave to the master. + */ + atpic->intr_raised = true; + vatpic_set_pinstate(vatpic, 2, true); + vatpic_set_pinstate(vatpic, 2, false); + } else { + VATPIC_CTR3(vatpic, "atpic slave no eligible interrupts " + "(imr 0x%x irr 0x%x isr 0x%x)", + atpic->mask, atpic->request, atpic->service); + } - if ((pin = vatpic_get_highest_irrpin(atpic)) != -1) { - VATPIC_CTR4(vatpic, "atpic notify pin = %d " + /* + * Then check the master. + */ + atpic = &vatpic->atpic[0]; + if (!atpic->intr_raised && + (pin = vatpic_get_highest_irrpin(atpic)) != -1) { + VATPIC_CTR4(vatpic, "atpic master notify pin = %d " "(imr 0x%x irr 0x%x isr 0x%x)", pin, atpic->mask, atpic->request, atpic->service); + + /* + * PIC interrupts are routed to both the Local APIC + * and the I/O APIC to support operation in 1 of 3 + * modes. + * + * 1. Legacy PIC Mode: the PIC effectively bypasses + * all APIC components. In mode '1' the local APIC is + * disabled and LINT0 is reconfigured as INTR to + * deliver the PIC interrupt directly to the CPU. + * + * 2. Virtual Wire Mode: the APIC is treated as a + * virtual wire which delivers interrupts from the PIC + * to the CPU. In mode '2' LINT0 is programmed as + * ExtINT to indicate that the PIC is the source of + * the interrupt. + * + * 3. Symmetric I/O Mode: PIC interrupts are fielded + * by the I/O APIC and delivered to the appropriate + * CPU. In mode '3' the I/O APIC input 0 is + * programmed as ExtINT to indicate that the PIC is + * the source of the interrupt. + */ + atpic->intr_raised = true; lapic_set_local_intr(vatpic->vm, -1, APIC_LVT_LINT0); vioapic_pulse_irq(vatpic->vm, 0); } else { - VATPIC_CTR3(vatpic, "atpic no eligible interrupts " + VATPIC_CTR3(vatpic, "atpic master no eligible interrupts " "(imr 0x%x irr 0x%x isr 0x%x)", atpic->mask, atpic->request, atpic->service); } @@ -384,7 +446,7 @@ vatpic_pulse_irq(struct vm *vm, int irq) return (vatpic_set_irqstate(vm, irq, IRQSTATE_PULSE)); } -int +void vatpic_pending_intr(struct vm *vm, int *vecptr) { struct vatpic *vatpic; @@ -393,7 +455,6 @@ vatpic_pending_intr(struct vm *vm, int * vatpic = vm_atpic(vm); - /* XXX master only */ atpic = &vatpic->atpic[0]; VATPIC_LOCK(vatpic); @@ -401,37 +462,53 @@ vatpic_pending_intr(struct vm *vm, int * pin = vatpic_get_highest_irrpin(atpic); if (pin == -1) pin = 7; + if (pin == 2) { + atpic = &vatpic->atpic[1]; + pin = vatpic_get_highest_irrpin(atpic); + } *vecptr = atpic->irq_base + pin; VATPIC_UNLOCK(vatpic); +} - return (1); +static void +vatpic_pin_accepted(struct atpic *atpic, int pin) +{ + atpic->intr_raised = false; + + if (atpic->acnt[pin] == 0) + atpic->request &= ~(1 << pin); + + if (atpic->aeoi == true) { + if (atpic->rotate == true) + atpic->priority = pin; + } else { + atpic->service |= (1 << pin); + } } void vatpic_intr_accepted(struct vm *vm, int vector) { struct vatpic *vatpic; - struct atpic *atpic; int pin; vatpic = vm_atpic(vm); - /* XXX master only */ - atpic = &vatpic->atpic[0]; - VATPIC_LOCK(vatpic); - pin = vector & 0x7; - if (atpic->acnt[pin] == 0) - atpic->request &= ~(1 << pin); + pin = vector & 0x7; - if (atpic->aeoi == true) { - if (atpic->rotate == true) - atpic->priority = pin; + if ((vector & ~0x7) == vatpic->atpic[1].irq_base) { + vatpic_pin_accepted(&vatpic->atpic[1], pin); + /* + * If this vector originated from the slave, + * accept the cascaded interrupt too. + */ + vatpic_pin_accepted(&vatpic->atpic[0], 2); } else { - atpic->service |= (1 << pin); + vatpic_pin_accepted(&vatpic->atpic[0], pin); } vatpic_notify_intr(vatpic); @@ -439,51 +516,50 @@ vatpic_intr_accepted(struct vm *vm, int VATPIC_UNLOCK(vatpic); } -int -vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +static int +vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, + int bytes, uint32_t *eax) { - struct vatpic *vatpic; - struct atpic *atpic; - int error; - uint8_t val; - - vatpic = vm_atpic(vm); - atpic = &vatpic->atpic[0]; + VATPIC_LOCK(vatpic); - if (vmexit->u.inout.bytes != 1) + if (atpic->poll) { + VATPIC_CTR0(vatpic, "vatpic polled mode not supported"); + VATPIC_UNLOCK(vatpic); return (-1); - - if (vmexit->u.inout.in) { - VATPIC_LOCK(vatpic); - if (atpic->poll) { - VATPIC_CTR0(vatpic, "vatpic polled mode not " - "supported"); - VATPIC_UNLOCK(vatpic); - return (-1); + } else { + if (port & ICU_IMR_OFFSET) { + /* read interrrupt mask register */ + *eax = atpic->mask; } else { - if (vmexit->u.inout.port & ICU_IMR_OFFSET) { - /* read interrrupt mask register */ - vmexit->u.inout.eax = atpic->mask; + if (atpic->rd_cmd_reg == OCW3_RIS) { + /* read interrupt service register */ + *eax = atpic->service; } else { - if (atpic->rd_cmd_reg == OCW3_RIS) { - /* read interrupt service register */ - vmexit->u.inout.eax = atpic->service; - } else { - /* read interrupt request register */ - vmexit->u.inout.eax = atpic->request; - } + /* read interrupt request register */ + *eax = atpic->request; } } - VATPIC_UNLOCK(vatpic); - - return (0); } - val = vmexit->u.inout.eax; + VATPIC_UNLOCK(vatpic); + + return (0); + +} + +static int +vatpic_write(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, + int bytes, uint32_t *eax) +{ + int error; + uint8_t val; + + error = 0; + val = *eax; VATPIC_LOCK(vatpic); - if (vmexit->u.inout.port & ICU_IMR_OFFSET) { + if (port & ICU_IMR_OFFSET) { if (atpic->ready) { error = vatpic_ocw1(vatpic, atpic, val); } else { @@ -520,41 +596,65 @@ vatpic_master_handler(void *vm, int vcpu } int -vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpic_master_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) { - if (vmexit->u.inout.bytes != 1) + struct vatpic *vatpic; + struct atpic *atpic; + + vatpic = vm_atpic(vm); + atpic = &vatpic->atpic[0]; + + if (bytes != 1) return (-1); - if (vmexit->u.inout.in) { - if (vmexit->u.inout.port & ICU_IMR_OFFSET) { - /* all interrupts masked */ - vmexit->u.inout.eax = 0xff; - } else { - vmexit->u.inout.eax = 0x00; - } + if (in) { + return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); } - /* Pretend all accesses to the slave 8259 are alright */ - return (0); + return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); } int -vatpic_elc_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpic_slave_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) +{ + struct vatpic *vatpic; + struct atpic *atpic; + + vatpic = vm_atpic(vm); + atpic = &vatpic->atpic[1]; + + if (bytes != 1) + return (-1); + + if (in) { + return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); + } + + return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); +} + +int +vatpic_elc_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) { struct vatpic *vatpic; bool is_master; vatpic = vm_atpic(vm); - is_master = (vmexit->u.inout.port == IO_ELCR1); + is_master = (port == IO_ELCR1); - if (vmexit->u.inout.bytes != 1) + if (bytes != 1) return (-1); - if (vmexit->u.inout.in) { + VATPIC_LOCK(vatpic); + + if (in) { if (is_master) - vmexit->u.inout.eax = vatpic->elc[0]; + *eax = vatpic->elc[0]; else - vmexit->u.inout.eax = vatpic->elc[1]; + *eax = vatpic->elc[1]; } else { /* * For the master PIC the cascade channel (IRQ2), the @@ -567,11 +667,13 @@ vatpic_elc_handler(void *vm, int vcpuid, * be programmed for level mode. */ if (is_master) - vatpic->elc[0] = (vmexit->u.inout.eax & 0xf8); + vatpic->elc[0] = (*eax & 0xf8); else - vatpic->elc[1] = (vmexit->u.inout.eax & 0xde); + vatpic->elc[1] = (*eax & 0xde); } + VATPIC_UNLOCK(vatpic); + return (0); } Copied and modified: stable/10/sys/amd64/vmm/io/vatpic.h (from r263035, head/sys/amd64/vmm/io/vatpic.h) ============================================================================== --- head/sys/amd64/vmm/io/vatpic.h Tue Mar 11 16:56:00 2014 (r263035, copy source) +++ stable/10/sys/amd64/vmm/io/vatpic.h Sat Jul 19 22:06:46 2014 (r268891) @@ -39,15 +39,18 @@ struct vatpic *vatpic_init(struct vm *vm); void vatpic_cleanup(struct vatpic *vatpic); -int vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit); -int vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit); -int vatpic_elc_handler(void *vm, int vcpuid, struct vm_exit *vmexit); +int vatpic_master_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax); +int vatpic_slave_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax); +int vatpic_elc_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax); int vatpic_assert_irq(struct vm *vm, int irq); int vatpic_deassert_irq(struct vm *vm, int irq); int vatpic_pulse_irq(struct vm *vm, int irq); -int vatpic_pending_intr(struct vm *vm, int *vecptr); +void vatpic_pending_intr(struct vm *vm, int *vecptr); void vatpic_intr_accepted(struct vm *vm, int vector); #endif /* _VATPIC_H_ */ Copied and modified: stable/10/sys/amd64/vmm/io/vatpit.c (from r263744, head/sys/amd64/vmm/io/vatpit.c) ============================================================================== --- head/sys/amd64/vmm/io/vatpit.c Tue Mar 25 19:20:34 2014 (r263744, copy source) +++ stable/10/sys/amd64/vmm/io/vatpit.c Sat Jul 19 22:06:46 2014 (r268891) @@ -56,6 +56,17 @@ static MALLOC_DEFINE(M_VATPIT, "atpit", #define TIMER_MODE_MASK 0x0f #define TIMER_SEL_READBACK 0xc0 +#define TIMER_STS_OUT 0x80 +#define TIMER_STS_NULLCNT 0x40 + +#define TIMER_RB_LCTR 0x20 +#define TIMER_RB_LSTATUS 0x10 +#define TIMER_RB_CTR_2 0x08 +#define TIMER_RB_CTR_1 0x04 +#define TIMER_RB_CTR_0 0x02 + +#define TMR2_OUT_STS 0x20 + #define PIT_8254_FREQ 1193182 #define TIMER_DIV(freq, hz) (((freq) + (hz) / 2) / (hz)) @@ -71,6 +82,8 @@ struct channel { sbintime_t now_sbt; /* uptime when counter was loaded */ uint8_t cr[2]; uint8_t ol[2]; + bool slatched; /* status latched */ + uint8_t status; int crbyte; int olbyte; int frbyte; @@ -88,22 +101,29 @@ struct vatpit { struct channel channel[3]; }; -#define VATPIT_CTR0(vatpit, fmt) \ - VM_CTR0((vatpit)->vm, fmt) - -#define VATPIT_CTR1(vatpit, fmt, a1) \ - VM_CTR1((vatpit)->vm, fmt, a1) +static void pit_timer_start_cntr0(struct vatpit *vatpit); -#define VATPIT_CTR2(vatpit, fmt, a1, a2) \ - VM_CTR2((vatpit)->vm, fmt, a1, a2) +static int +vatpit_get_out(struct vatpit *vatpit, int channel) +{ + struct channel *c; + sbintime_t delta_ticks; + int out; -#define VATPIT_CTR3(vatpit, fmt, a1, a2, a3) \ - VM_CTR3((vatpit)->vm, fmt, a1, a2, a3) + c = &vatpit->channel[channel]; -#define VATPIT_CTR4(vatpit, fmt, a1, a2, a3, a4) \ - VM_CTR4((vatpit)->vm, fmt, a1, a2, a3, a4) + switch (c->mode) { + case TIMER_INTTC: + delta_ticks = (sbinuptime() - c->now_sbt) / vatpit->freq_sbt; + out = ((c->initial - delta_ticks) <= 0); + break; + default: + out = 0; + break; + } -static void pit_timer_start_cntr0(struct vatpit *vatpit); + return (out); +} static void vatpit_callout_handler(void *a) @@ -117,7 +137,7 @@ vatpit_callout_handler(void *a) c = &vatpit->channel[arg->channel_num]; callout = &c->callout; - VATPIT_CTR1(vatpit, "atpit t%d fired", arg->channel_num); + VM_CTR1(vatpit->vm, "atpit t%d fired", arg->channel_num); VATPIT_LOCK(vatpit); @@ -145,7 +165,7 @@ static void pit_timer_start_cntr0(struct vatpit *vatpit) { struct channel *c; - sbintime_t delta, precision; + sbintime_t now, delta, precision; c = &vatpit->channel[0]; if (c->initial != 0) { @@ -153,6 +173,15 @@ pit_timer_start_cntr0(struct vatpit *vat precision = delta >> tc_precexp; c->callout_sbt = c->callout_sbt + delta; + /* + * Reset 'callout_sbt' if the time that the callout + * was supposed to fire is more than 'c->initial' + * ticks in the past. + */ + now = sbinuptime(); + if (c->callout_sbt < now) + c->callout_sbt = now + delta; + callout_reset_sbt(&c->callout, c->callout_sbt, precision, vatpit_callout_handler, &c->callout_arg, C_ABSOLUTE); @@ -180,6 +209,7 @@ pit_update_counter(struct vatpit *vatpit */ c->initial = TIMER_DIV(PIT_8254_FREQ, 100); c->now_sbt = sbinuptime(); + c->status &= ~TIMER_STS_NULLCNT; } delta_ticks = (sbinuptime() - c->now_sbt) / vatpit->freq_sbt; @@ -196,6 +226,57 @@ pit_update_counter(struct vatpit *vatpit } static int +pit_readback1(struct vatpit *vatpit, int channel, uint8_t cmd) +{ + struct channel *c; + + c = &vatpit->channel[channel]; + + /* + * Latch the count/status of the timer if not already latched. + * N.B. that the count/status latch-select bits are active-low. + */ + if (!(cmd & TIMER_RB_LCTR) && !c->olbyte) { + (void) pit_update_counter(vatpit, c, true); + } + + if (!(cmd & TIMER_RB_LSTATUS) && !c->slatched) { + c->slatched = true; + /* + * For mode 0, see if the elapsed time is greater + * than the initial value - this results in the + * output pin being set to 1 in the status byte. + */ + if (c->mode == TIMER_INTTC && vatpit_get_out(vatpit, channel)) + c->status |= TIMER_STS_OUT; + else + c->status &= ~TIMER_STS_OUT; + } + + return (0); +} + +static int +pit_readback(struct vatpit *vatpit, uint8_t cmd) +{ + int error; + + /* + * The readback command can apply to all timers. + */ + error = 0; + if (cmd & TIMER_RB_CTR_0) + error = pit_readback1(vatpit, 0, cmd); + if (!error && cmd & TIMER_RB_CTR_1) + error = pit_readback1(vatpit, 1, cmd); + if (!error && cmd & TIMER_RB_CTR_2) + error = pit_readback1(vatpit, 2, cmd); + + return (error); +} + + +static int vatpit_update_mode(struct vatpit *vatpit, uint8_t val) { struct channel *c; @@ -206,7 +287,7 @@ vatpit_update_mode(struct vatpit *vatpit mode = val & TIMER_MODE_MASK; if (sel == TIMER_SEL_READBACK) - return (-1); + return (pit_readback(vatpit, val)); if (rw != TIMER_LATCH && rw != TIMER_16BIT) return (-1); @@ -229,53 +310,31 @@ vatpit_update_mode(struct vatpit *vatpit else { c->mode = mode; c->olbyte = 0; /* reset latch after reprogramming */ + c->status |= TIMER_STS_NULLCNT; } return (0); } -static int -vatpit_get_out(struct vatpit *vatpit, int channel) -{ - struct channel *c; - sbintime_t delta_ticks; - int out; - - c = &vatpit->channel[channel]; - - switch (c->mode) { - case TIMER_INTTC: - delta_ticks = (sbinuptime() - c->now_sbt) / vatpit->freq_sbt; - out = ((c->initial - delta_ticks) <= 0); - break; - default: - out = 0; - break; - } - - return (out); -} - int -vatpit_handler(void *vm, int vcpuid, struct vm_exit *vmexit) +vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) { struct vatpit *vatpit; struct channel *c; - int port; uint8_t val; int error; vatpit = vm_atpit(vm); - if (vmexit->u.inout.bytes != 1) + if (bytes != 1) return (-1); - val = vmexit->u.inout.eax; - port = vmexit->u.inout.port; + val = *eax; if (port == TIMER_MODE) { - if (vmexit->u.inout.in != 0) { - VATPIT_CTR0(vatpit, "vatpit attempt to read mode"); + if (in) { + VM_CTR0(vatpit->vm, "vatpit attempt to read mode"); return (-1); } @@ -287,12 +346,19 @@ vatpit_handler(void *vm, int vcpuid, str } /* counter ports */ - KASSERT(port >= TIMER_CNTR0 && vmexit->u.inout.port <= TIMER_CNTR2, + KASSERT(port >= TIMER_CNTR0 && port <= TIMER_CNTR2, ("invalid port 0x%x", port)); c = &vatpit->channel[port - TIMER_CNTR0]; VATPIT_LOCK(vatpit); - if (vmexit->u.inout.in) { + if (in && c->slatched) { + /* + * Return the status byte if latched + */ + *eax = c->status; + c->slatched = false; + c->status = 0; + } else if (in) { /* * The spec says that once the output latch is completely * read it should revert to "following" the counter. Use @@ -307,13 +373,14 @@ vatpit_handler(void *vm, int vcpuid, str if (c->frbyte) tmp >>= 8; tmp &= 0xff; - vmexit->u.inout.eax = tmp; + *eax = tmp; c->frbyte ^= 1; } else - vmexit->u.inout.eax = c->ol[--c->olbyte]; + *eax = c->ol[--c->olbyte]; } else { - c->cr[c->crbyte++] = vmexit->u.inout.eax; + c->cr[c->crbyte++] = *eax; if (c->crbyte == 2) { + c->status &= ~TIMER_STS_NULLCNT; c->frbyte = 0; c->crbyte = 0; c->initial = c->cr[0] | (uint16_t)c->cr[1] << 8; @@ -332,6 +399,27 @@ vatpit_handler(void *vm, int vcpuid, str return (0); } +int +vatpit_nmisc_handler(void *vm, int vcpuid, bool in, int port, int bytes, + uint32_t *eax) +{ + struct vatpit *vatpit; + + vatpit = vm_atpit(vm); + + if (in) { + VATPIT_LOCK(vatpit); + if (vatpit_get_out(vatpit, 2)) + *eax = TMR2_OUT_STS; + else *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-stable-10@FreeBSD.ORG Sat Jul 19 22:13:13 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id C03531E9; Sat, 19 Jul 2014 22:13:13 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A108823E2; Sat, 19 Jul 2014 22:13:13 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JMDD5l010081; Sat, 19 Jul 2014 22:13:13 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JMDDdH010079; Sat, 19 Jul 2014 22:13:13 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201407192213.s6JMDDdH010079@svn.freebsd.org> From: John Baldwin Date: Sat, 19 Jul 2014 22:13:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268892 - stable/10/usr.sbin/bhyve X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 22:13:13 -0000 Author: jhb Date: Sat Jul 19 22:13:12 2014 New Revision: 268892 URL: http://svnweb.freebsd.org/changeset/base/268892 Log: MFC 262884,263236,265407: Various uart fixes: - Open the uart emulation's backing tty in non-blocking mode. - Support 16-bit register access. - Disable the 'uart_drain()' callback when the emulated receive FIFO is full. Modified: stable/10/usr.sbin/bhyve/pci_lpc.c stable/10/usr.sbin/bhyve/uart_emul.c Directory Properties: stable/10/ (props changed) Modified: stable/10/usr.sbin/bhyve/pci_lpc.c ============================================================================== --- stable/10/usr.sbin/bhyve/pci_lpc.c Sat Jul 19 22:06:46 2014 (r268891) +++ stable/10/usr.sbin/bhyve/pci_lpc.c Sat Jul 19 22:13:12 2014 (r268892) @@ -130,15 +130,27 @@ lpc_uart_io_handler(struct vmctx *ctx, i int offset; struct lpc_uart_softc *sc = arg; - if (bytes != 1) - return (-1); - offset = port - sc->iobase; - if (in) - *eax = uart_read(sc->uart_softc, offset); - else - uart_write(sc->uart_softc, offset, *eax); + switch (bytes) { + case 1: + if (in) + *eax = uart_read(sc->uart_softc, offset); + else + uart_write(sc->uart_softc, offset, *eax); + break; + case 2: + if (in) { + *eax = uart_read(sc->uart_softc, offset); + *eax |= uart_read(sc->uart_softc, offset + 1) << 8; + } else { + uart_write(sc->uart_softc, offset, *eax); + uart_write(sc->uart_softc, offset + 1, *eax >> 8); + } + break; + default: + return (-1); + } return (0); } Modified: stable/10/usr.sbin/bhyve/uart_emul.c ============================================================================== --- stable/10/usr.sbin/bhyve/uart_emul.c Sat Jul 19 22:06:46 2014 (r268891) +++ stable/10/usr.sbin/bhyve/uart_emul.c Sat Jul 19 22:13:12 2014 (r268892) @@ -110,6 +110,7 @@ struct uart_softc { uint8_t dlh; /* Baudrate divisor latch MSB */ struct fifo rxfifo; + struct mevent *mev; struct ttyfd tty; bool thre_int_pending; /* THRE interrupt pending */ @@ -145,34 +146,15 @@ ttyopen(struct ttyfd *tf) } } -static bool -tty_char_available(struct ttyfd *tf) -{ - fd_set rfds; - struct timeval tv; - - FD_ZERO(&rfds); - FD_SET(tf->fd, &rfds); - tv.tv_sec = 0; - tv.tv_usec = 0; - if (select(tf->fd + 1, &rfds, NULL, NULL, &tv) > 0 ) { - return (true); - } else { - return (false); - } -} - static int ttyread(struct ttyfd *tf) { - char rb; + unsigned char rb; - if (tty_char_available(tf)) { - read(tf->fd, &rb, 1); - return (rb & 0xff); - } else { + if (read(tf->fd, &rb, 1) == 1) + return (rb); + else return (-1); - } } static void @@ -183,62 +165,111 @@ ttywrite(struct ttyfd *tf, unsigned char } static void -fifo_reset(struct fifo *fifo, int size) +rxfifo_reset(struct uart_softc *sc, int size) { + char flushbuf[32]; + struct fifo *fifo; + ssize_t nread; + int error; + fifo = &sc->rxfifo; bzero(fifo, sizeof(struct fifo)); fifo->size = size; + + if (sc->tty.opened) { + /* + * Flush any unread input from the tty buffer. + */ + while (1) { + nread = read(sc->tty.fd, flushbuf, sizeof(flushbuf)); + if (nread != sizeof(flushbuf)) + break; + } + + /* + * Enable mevent to trigger when new characters are available + * on the tty fd. + */ + error = mevent_enable(sc->mev); + assert(error == 0); + } +} + +static int +rxfifo_available(struct uart_softc *sc) +{ + struct fifo *fifo; + + fifo = &sc->rxfifo; + return (fifo->num < fifo->size); } static int -fifo_putchar(struct fifo *fifo, uint8_t ch) +rxfifo_putchar(struct uart_softc *sc, uint8_t ch) { + struct fifo *fifo; + int error; + + fifo = &sc->rxfifo; if (fifo->num < fifo->size) { fifo->buf[fifo->windex] = ch; fifo->windex = (fifo->windex + 1) % fifo->size; fifo->num++; + if (!rxfifo_available(sc)) { + if (sc->tty.opened) { + /* + * Disable mevent callback if the FIFO is full. + */ + error = mevent_disable(sc->mev); + assert(error == 0); + } + } return (0); } else return (-1); } static int -fifo_getchar(struct fifo *fifo) +rxfifo_getchar(struct uart_softc *sc) { - int c; + struct fifo *fifo; + int c, error, wasfull; + wasfull = 0; + fifo = &sc->rxfifo; if (fifo->num > 0) { + if (!rxfifo_available(sc)) + wasfull = 1; c = fifo->buf[fifo->rindex]; fifo->rindex = (fifo->rindex + 1) % fifo->size; fifo->num--; + if (wasfull) { + if (sc->tty.opened) { + error = mevent_enable(sc->mev); + assert(error == 0); + } + } return (c); } else return (-1); } static int -fifo_numchars(struct fifo *fifo) +rxfifo_numchars(struct uart_softc *sc) { + struct fifo *fifo = &sc->rxfifo; return (fifo->num); } -static int -fifo_available(struct fifo *fifo) -{ - - return (fifo->num < fifo->size); -} - static void uart_opentty(struct uart_softc *sc) { - struct mevent *mev; ttyopen(&sc->tty); - mev = mevent_add(sc->tty.fd, EVF_READ, uart_drain, sc); - assert(mev); + sc->mev = mevent_add(sc->tty.fd, EVF_READ, uart_drain, sc); + assert(sc->mev != NULL); } /* @@ -255,7 +286,7 @@ uart_intr_reason(struct uart_softc *sc) if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0) return (IIR_RLS); - else if (fifo_numchars(&sc->rxfifo) > 0 && (sc->ier & IER_ERXRDY) != 0) + else if (rxfifo_numchars(sc) > 0 && (sc->ier & IER_ERXRDY) != 0) return (IIR_RXTOUT); else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0) return (IIR_TXRDY); @@ -274,7 +305,7 @@ uart_reset(struct uart_softc *sc) sc->dll = divisor; sc->dlh = divisor >> 16; - fifo_reset(&sc->rxfifo, 1); /* no fifo until enabled by software */ + rxfifo_reset(sc, 1); /* no fifo until enabled by software */ } /* @@ -315,9 +346,9 @@ uart_drain(int fd, enum ev_type ev, void if ((sc->mcr & MCR_LOOPBACK) != 0) { (void) ttyread(&sc->tty); } else { - while (fifo_available(&sc->rxfifo) && + while (rxfifo_available(sc) && ((ch = ttyread(&sc->tty)) != -1)) { - fifo_putchar(&sc->rxfifo, ch); + rxfifo_putchar(sc, ch); } uart_toggle_intr(sc); } @@ -351,7 +382,7 @@ uart_write(struct uart_softc *sc, int of switch (offset) { case REG_DATA: if (sc->mcr & MCR_LOOPBACK) { - if (fifo_putchar(&sc->rxfifo, value) != 0) + if (rxfifo_putchar(sc, value) != 0) sc->lsr |= LSR_OE; } else if (sc->tty.opened) { ttywrite(&sc->tty, value); @@ -372,7 +403,7 @@ uart_write(struct uart_softc *sc, int of */ if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) { fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1; - fifo_reset(&sc->rxfifo, fifosz); + rxfifo_reset(sc, fifosz); } /* @@ -383,7 +414,7 @@ uart_write(struct uart_softc *sc, int of sc->fcr = 0; } else { if ((value & FCR_RCV_RST) != 0) - fifo_reset(&sc->rxfifo, FIFOSZ); + rxfifo_reset(sc, FIFOSZ); sc->fcr = value & (FCR_ENABLE | FCR_DMA | FCR_RX_MASK); @@ -480,7 +511,7 @@ uart_read(struct uart_softc *sc, int off switch (offset) { case REG_DATA: - reg = fifo_getchar(&sc->rxfifo); + reg = rxfifo_getchar(sc); break; case REG_IER: reg = sc->ier; @@ -511,7 +542,7 @@ uart_read(struct uart_softc *sc, int off sc->lsr |= LSR_TEMT | LSR_THRE; /* Check for new receive data */ - if (fifo_numchars(&sc->rxfifo) > 0) + if (rxfifo_numchars(sc) > 0) sc->lsr |= LSR_RXRDY; else sc->lsr &= ~LSR_RXRDY; @@ -585,7 +616,7 @@ uart_tty_backend(struct uart_softc *sc, retval = -1; - fd = open(opts, O_RDWR); + fd = open(opts, O_RDWR | O_NONBLOCK); if (fd > 0 && isatty(fd)) { sc->tty.fd = fd; sc->tty.opened = true; @@ -616,6 +647,10 @@ uart_set_backend(struct uart_softc *sc, retval = 0; } + /* Make the backend file descriptor non-blocking */ + if (retval == 0) + retval = fcntl(sc->tty.fd, F_SETFL, O_NONBLOCK); + if (retval == 0) uart_opentty(sc); From owner-svn-src-stable-10@FreeBSD.ORG Sat Jul 19 22:24:30 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DB56B706; Sat, 19 Jul 2014 22:24:30 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id BD60D24A9; Sat, 19 Jul 2014 22:24:30 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JMOUa5015086; Sat, 19 Jul 2014 22:24:30 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JMOTYB015081; Sat, 19 Jul 2014 22:24:29 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201407192224.s6JMOTYB015081@svn.freebsd.org> From: John Baldwin Date: Sat, 19 Jul 2014 22:24:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268894 - stable/10/usr.sbin/bhyve X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 22:24:31 -0000 Author: jhb Date: Sat Jul 19 22:24:29 2014 New Revision: 268894 URL: http://svnweb.freebsd.org/changeset/base/268894 Log: MFC 263432,265366,265376: Fixes for vcpu management in bhyve: - Use 'cpuset_t' to represent the vcpus active in a virtual machine. - Modify the "-p" option to be more flexible when associating a 'vcpu' with a 'hostcpu'. Modified: stable/10/usr.sbin/bhyve/bhyve.8 stable/10/usr.sbin/bhyve/bhyverun.c stable/10/usr.sbin/bhyve/bhyverun.h stable/10/usr.sbin/bhyve/spinup_ap.c Directory Properties: stable/10/ (props changed) Modified: stable/10/usr.sbin/bhyve/bhyve.8 ============================================================================== --- stable/10/usr.sbin/bhyve/bhyve.8 Sat Jul 19 22:13:27 2014 (r268893) +++ stable/10/usr.sbin/bhyve/bhyve.8 Sat Jul 19 22:24:29 2014 (r268894) @@ -35,7 +35,7 @@ .Op Fl aehwxAHPW .Op Fl c Ar numcpus .Op Fl g Ar gdbport -.Op Fl p Ar pinnedcpu +.Op Fl p Ar vcpu:hostcpu .Op Fl s Ar slot,emulation Ns Op , Ns Ar conf .Op Fl l Ar lpcdev Ns Op , Ns Ar conf .Ar vmname @@ -79,12 +79,11 @@ For allow a remote kernel kgdb to be relayed to the guest kernel gdb stub via a local IPv4 address and this port. This option will be deprecated in a future version. -.It Fl p Ar pinnedcpu -Force guest virtual CPUs to be pinned to host CPUs. -Virtual CPU -.Em n -is pinned to host CPU -.Em pinnedcpu+n . +.It Fl p Ar vcpu:hostcpu +Pin guest's virtual CPU +.Em vcpu +to +.Em hostcpu . .It Fl P Force the guest virtual CPU to exit when a PAUSE instruction is detected. .It Fl W Modified: stable/10/usr.sbin/bhyve/bhyverun.c ============================================================================== --- stable/10/usr.sbin/bhyve/bhyverun.c Sat Jul 19 22:13:27 2014 (r268893) +++ stable/10/usr.sbin/bhyve/bhyverun.c Sat Jul 19 22:24:29 2014 (r268894) @@ -85,7 +85,6 @@ char *vmname; int guest_ncpus; char *guest_uuid_str; -static int pincpu = -1; static int guest_vmexit_on_hlt, guest_vmexit_on_pause; static int virtio_msix = 1; static int x2apic_mode = 0; /* default is xAPIC */ @@ -98,7 +97,7 @@ static int acpi; static char *progname; static const int BSP = 0; -static int cpumask; +static cpuset_t cpumask; static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip); @@ -122,18 +121,20 @@ struct mt_vmm_info { int mt_vcpu; } mt_vmm_info[VM_MAXCPU]; +static cpuset_t *vcpumap[VM_MAXCPU] = { NULL }; + static void usage(int code) { fprintf(stderr, - "Usage: %s [-aehwAHIPW] [-g ] [-s ]\n" - " %*s [-c vcpus] [-p pincpu] [-m mem] [-l ] \n" + "Usage: %s [-aehwAHIPW] [-g ] [-s ] [-c vcpus]\n" + " %*s [-p vcpu:hostcpu] [-m mem] [-l ] \n" " -a: local apic is in xAPIC mode (deprecated)\n" " -A: create an ACPI table\n" " -g: gdb port\n" " -c: # cpus (default 1)\n" - " -p: pin vcpu 'n' to host cpu 'pincpu + n'\n" + " -p: pin 'vcpu' to 'hostcpu'\n" " -H: vmexit from the guest on hlt\n" " -P: vmexit from the guest on pause\n" " -W: force virtio to use single-vector MSI\n" @@ -151,6 +152,39 @@ usage(int code) exit(code); } +static int +pincpu_parse(const char *opt) +{ + int vcpu, pcpu; + + if (sscanf(opt, "%d:%d", &vcpu, &pcpu) != 2) { + fprintf(stderr, "invalid format: %s\n", opt); + return (-1); + } + + if (vcpu < 0 || vcpu >= VM_MAXCPU) { + fprintf(stderr, "vcpu '%d' outside valid range from 0 to %d\n", + vcpu, VM_MAXCPU - 1); + return (-1); + } + + if (pcpu < 0 || pcpu >= CPU_SETSIZE) { + fprintf(stderr, "hostcpu '%d' outside valid range from " + "0 to %d\n", pcpu, CPU_SETSIZE - 1); + return (-1); + } + + if (vcpumap[vcpu] == NULL) { + if ((vcpumap[vcpu] = malloc(sizeof(cpuset_t))) == NULL) { + perror("malloc"); + return (-1); + } + CPU_ZERO(vcpumap[vcpu]); + } + CPU_SET(pcpu, vcpumap[vcpu]); + return (0); +} + void * paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len) { @@ -200,30 +234,26 @@ fbsdrun_start_thread(void *param) } void -fbsdrun_addcpu(struct vmctx *ctx, int vcpu, uint64_t rip) +fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip) { int error; - if (cpumask & (1 << vcpu)) { - fprintf(stderr, "addcpu: attempting to add existing cpu %d\n", - vcpu); - exit(1); - } + assert(fromcpu == BSP); - atomic_set_int(&cpumask, 1 << vcpu); + CPU_SET_ATOMIC(newcpu, &cpumask); /* * Set up the vmexit struct to allow execution to start * at the given RIP */ - vmexit[vcpu].rip = rip; - vmexit[vcpu].inst_length = 0; + vmexit[newcpu].rip = rip; + vmexit[newcpu].inst_length = 0; - mt_vmm_info[vcpu].mt_ctx = ctx; - mt_vmm_info[vcpu].mt_vcpu = vcpu; + mt_vmm_info[newcpu].mt_ctx = ctx; + mt_vmm_info[newcpu].mt_vcpu = newcpu; - error = pthread_create(&mt_vmm_info[vcpu].mt_thr, NULL, - fbsdrun_start_thread, &mt_vmm_info[vcpu]); + error = pthread_create(&mt_vmm_info[newcpu].mt_thr, NULL, + fbsdrun_start_thread, &mt_vmm_info[newcpu]); assert(error == 0); } @@ -231,14 +261,13 @@ static int fbsdrun_deletecpu(struct vmctx *ctx, int vcpu) { - if ((cpumask & (1 << vcpu)) == 0) { - fprintf(stderr, "addcpu: attempting to delete unknown cpu %d\n", - vcpu); + if (!CPU_ISSET(vcpu, &cpumask)) { + fprintf(stderr, "Attempting to delete unknown cpu %d\n", vcpu); exit(1); } - atomic_clear_int(&cpumask, 1 << vcpu); - return (cpumask == 0); + CPU_CLR_ATOMIC(vcpu, &cpumask); + return (CPU_EMPTY(&cpumask)); } static int @@ -483,15 +512,12 @@ static vmexit_handler_t handler[VM_EXITC static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip) { - cpuset_t mask; int error, rc, prevcpu; enum vm_exitcode exitcode; - if (pincpu >= 0) { - CPU_ZERO(&mask); - CPU_SET(pincpu + vcpu, &mask); + if (vcpumap[vcpu] != NULL) { error = pthread_setaffinity_np(pthread_self(), - sizeof(mask), &mask); + sizeof(cpuset_t), vcpumap[vcpu]); assert(error == 0); } @@ -616,7 +642,10 @@ main(int argc, char *argv[]) bvmcons = 1; break; case 'p': - pincpu = atoi(optarg); + if (pincpu_parse(optarg) != 0) { + errx(EX_USAGE, "invalid vcpu pinning " + "configuration '%s'", optarg); + } break; case 'c': guest_ncpus = atoi(optarg); @@ -754,7 +783,7 @@ main(int argc, char *argv[]) /* * Add CPU 0 */ - fbsdrun_addcpu(ctx, BSP, rip); + fbsdrun_addcpu(ctx, BSP, BSP, rip); /* * Head off to the main event dispatch loop Modified: stable/10/usr.sbin/bhyve/bhyverun.h ============================================================================== --- stable/10/usr.sbin/bhyve/bhyverun.h Sat Jul 19 22:13:27 2014 (r268893) +++ stable/10/usr.sbin/bhyve/bhyverun.h Sat Jul 19 22:24:29 2014 (r268894) @@ -43,7 +43,7 @@ extern char *vmname; void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len); void fbsdrun_set_capabilities(struct vmctx *ctx, int cpu); -void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip); +void fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip); int fbsdrun_muxed(void); int fbsdrun_vmexit_on_hlt(void); int fbsdrun_vmexit_on_pause(void); Modified: stable/10/usr.sbin/bhyve/spinup_ap.c ============================================================================== --- stable/10/usr.sbin/bhyve/spinup_ap.c Sat Jul 19 22:13:27 2014 (r268893) +++ stable/10/usr.sbin/bhyve/spinup_ap.c Sat Jul 19 22:24:29 2014 (r268894) @@ -98,7 +98,7 @@ spinup_ap(struct vmctx *ctx, int vcpu, i spinup_ap_realmode(ctx, newcpu, &rip); - fbsdrun_addcpu(ctx, newcpu, rip); + fbsdrun_addcpu(ctx, vcpu, newcpu, rip); return (newcpu); } From owner-svn-src-stable-10@FreeBSD.ORG Sat Jul 19 23:45:00 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 371428A5; Sat, 19 Jul 2014 23:45:00 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1F61F2A21; Sat, 19 Jul 2014 23:45:00 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6JNj0vt052832; Sat, 19 Jul 2014 23:45:00 GMT (envelope-from bapt@svn.freebsd.org) Received: (from bapt@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6JNiwhg052804; Sat, 19 Jul 2014 23:44:58 GMT (envelope-from bapt@svn.freebsd.org) Message-Id: <201407192344.s6JNiwhg052804@svn.freebsd.org> From: Baptiste Daroussin Date: Sat, 19 Jul 2014 23:44:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268896 - in stable/10: contrib/libucl contrib/libucl/cmake contrib/libucl/doc contrib/libucl/include contrib/libucl/src contrib/libucl/tests contrib/libucl/tests/basic contrib/libucl/t... X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Jul 2014 23:45:00 -0000 Author: bapt Date: Sat Jul 19 23:44:57 2014 New Revision: 268896 URL: http://svnweb.freebsd.org/changeset/base/268896 Log: MFC: r263648, r264789, r266636 This brings: - schema validation - xpath-like interface for ucl objects Adapt pkg(7) to the new libucl API Added: stable/10/contrib/libucl/Makefile.am (contents, props changed) stable/10/contrib/libucl/autogen.sh (contents, props changed) stable/10/contrib/libucl/cmake/ stable/10/contrib/libucl/cmake/CMakeLists.txt (contents, props changed) stable/10/contrib/libucl/configure.ac stable/10/contrib/libucl/doc/Makefile.am (contents, props changed) stable/10/contrib/libucl/doc/libucl.3 (contents, props changed) stable/10/contrib/libucl/doc/pandoc.template stable/10/contrib/libucl/libucl.pc.in (contents, props changed) stable/10/contrib/libucl/src/Makefile.am (contents, props changed) stable/10/contrib/libucl/src/tree.h (contents, props changed) stable/10/contrib/libucl/src/ucl_schema.c (contents, props changed) stable/10/contrib/libucl/stamp-h.in (contents, props changed) stable/10/contrib/libucl/tests/.gitignore stable/10/contrib/libucl/tests/Makefile.am (contents, props changed) stable/10/contrib/libucl/tests/basic/ stable/10/contrib/libucl/tests/basic.test (contents, props changed) stable/10/contrib/libucl/tests/basic/1.in (contents, props changed) stable/10/contrib/libucl/tests/basic/1.res stable/10/contrib/libucl/tests/basic/10.in (contents, props changed) stable/10/contrib/libucl/tests/basic/2.in (contents, props changed) stable/10/contrib/libucl/tests/basic/2.res stable/10/contrib/libucl/tests/basic/3.in (contents, props changed) stable/10/contrib/libucl/tests/basic/3.res stable/10/contrib/libucl/tests/basic/4.in (contents, props changed) stable/10/contrib/libucl/tests/basic/4.res stable/10/contrib/libucl/tests/basic/6.in (contents, props changed) stable/10/contrib/libucl/tests/basic/6.res stable/10/contrib/libucl/tests/basic/8.in (contents, props changed) stable/10/contrib/libucl/tests/basic/8.res stable/10/contrib/libucl/tests/basic/9-comment.inc stable/10/contrib/libucl/tests/basic/9-empty.inc stable/10/contrib/libucl/tests/basic/9.in (contents, props changed) stable/10/contrib/libucl/tests/basic/9.inc stable/10/contrib/libucl/tests/basic/9.res stable/10/contrib/libucl/tests/generate.test (contents, props changed) stable/10/contrib/libucl/tests/schema/ stable/10/contrib/libucl/tests/schema.test (contents, props changed) stable/10/contrib/libucl/tests/schema/additionalItems.json stable/10/contrib/libucl/tests/schema/additionalProperties.json stable/10/contrib/libucl/tests/schema/allOf.json stable/10/contrib/libucl/tests/schema/anyOf.json stable/10/contrib/libucl/tests/schema/definitions.json stable/10/contrib/libucl/tests/schema/dependencies.json stable/10/contrib/libucl/tests/schema/enum.json stable/10/contrib/libucl/tests/schema/items.json stable/10/contrib/libucl/tests/schema/maxItems.json stable/10/contrib/libucl/tests/schema/maxLength.json stable/10/contrib/libucl/tests/schema/maxProperties.json stable/10/contrib/libucl/tests/schema/maximum.json stable/10/contrib/libucl/tests/schema/minItems.json stable/10/contrib/libucl/tests/schema/minLength.json stable/10/contrib/libucl/tests/schema/minProperties.json stable/10/contrib/libucl/tests/schema/minimum.json stable/10/contrib/libucl/tests/schema/multipleOf.json stable/10/contrib/libucl/tests/schema/not.json stable/10/contrib/libucl/tests/schema/oneOf.json stable/10/contrib/libucl/tests/schema/pattern.json stable/10/contrib/libucl/tests/schema/patternProperties.json stable/10/contrib/libucl/tests/schema/properties.json stable/10/contrib/libucl/tests/schema/ref.json stable/10/contrib/libucl/tests/schema/refRemote.json stable/10/contrib/libucl/tests/schema/required.json stable/10/contrib/libucl/tests/schema/type.json stable/10/contrib/libucl/tests/schema/uniqueItems.json stable/10/contrib/libucl/tests/speed.test (contents, props changed) stable/10/contrib/libucl/tests/test_schema.c (contents, props changed) stable/10/contrib/libucl/utils/Makefile.am (contents, props changed) Deleted: stable/10/contrib/libucl/.gitignore stable/10/contrib/libucl/tests/1.in stable/10/contrib/libucl/tests/1.res stable/10/contrib/libucl/tests/10.in stable/10/contrib/libucl/tests/2.in stable/10/contrib/libucl/tests/2.res stable/10/contrib/libucl/tests/3.in stable/10/contrib/libucl/tests/3.res stable/10/contrib/libucl/tests/4.in stable/10/contrib/libucl/tests/4.res stable/10/contrib/libucl/tests/5.in stable/10/contrib/libucl/tests/5.res stable/10/contrib/libucl/tests/6.in stable/10/contrib/libucl/tests/6.res stable/10/contrib/libucl/tests/7.in stable/10/contrib/libucl/tests/7.res stable/10/contrib/libucl/tests/8.in stable/10/contrib/libucl/tests/8.res stable/10/contrib/libucl/tests/9-comment.inc stable/10/contrib/libucl/tests/9-empty.inc stable/10/contrib/libucl/tests/9.in stable/10/contrib/libucl/tests/9.inc stable/10/contrib/libucl/tests/9.res Modified: stable/10/contrib/libucl/Makefile.unix stable/10/contrib/libucl/Makefile.w32 stable/10/contrib/libucl/README.md stable/10/contrib/libucl/doc/api.md stable/10/contrib/libucl/include/ucl.h stable/10/contrib/libucl/src/ucl_emitter.c stable/10/contrib/libucl/src/ucl_hash.c stable/10/contrib/libucl/src/ucl_hash.h stable/10/contrib/libucl/src/ucl_internal.h stable/10/contrib/libucl/src/ucl_parser.c stable/10/contrib/libucl/src/ucl_util.c stable/10/contrib/libucl/tests/run_tests.sh stable/10/contrib/libucl/tests/test_basic.c stable/10/contrib/libucl/tests/test_generate.c stable/10/contrib/libucl/tests/test_speed.c stable/10/contrib/libucl/utils/objdump.c stable/10/lib/libucl/Makefile stable/10/usr.sbin/pkg/config.c stable/10/usr.sbin/pkg/pkg.c Added: stable/10/contrib/libucl/Makefile.am ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libucl/Makefile.am Sat Jul 19 23:44:57 2014 (r268896) @@ -0,0 +1,7 @@ +ACLOCAL_AMFLAGS = -I m4 +EXTRA_DIST = uthash README.md + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libucl.pc + +SUBDIRS = src tests utils doc \ No newline at end of file Modified: stable/10/contrib/libucl/Makefile.unix ============================================================================== --- stable/10/contrib/libucl/Makefile.unix Sat Jul 19 23:39:17 2014 (r268895) +++ stable/10/contrib/libucl/Makefile.unix Sat Jul 19 23:44:57 2014 (r268896) @@ -4,7 +4,7 @@ LD ?= gcc C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src MAJOR_VERSION = 0 MINOR_VERSION = 2 -PATCH_VERSION = 8 +PATCH_VERSION = 9 VERSION = "$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION)" SONAME = libucl.so SONAME_FULL = $(SONAME).$(MAJOR_VERSION) @@ -21,8 +21,17 @@ LD_SHARED_FLAGS ?= -Wl,-soname,$(SONAME) LD_UCL_FLAGS ?= -L$(OBJDIR) -Wl,-rpath,$(OBJDIR) -lucl LD_ADD ?= -lrt COPT_FLAGS ?= -O2 -HDEPS = $(SRCDIR)/ucl_hash.h $(SRCDIR)/ucl_chartable.h $(SRCDIR)/ucl_internal.h $(INCLUDEDIR)/ucl.h $(SRCDIR)/xxhash.h -OBJECTS = $(OBJDIR)/ucl_hash.o $(OBJDIR)/ucl_util.o $(OBJDIR)/ucl_parser.o $(OBJDIR)/ucl_emitter.o $(OBJDIR)/xxhash.o +HDEPS = $(SRCDIR)/ucl_hash.h \ + $(SRCDIR)/ucl_chartable.h \ + $(SRCDIR)/ucl_internal.h \ + $(INCLUDEDIR)/ucl.h \ + $(SRCDIR)/xxhash.h +OBJECTS = $(OBJDIR)/ucl_hash.o \ + $(OBJDIR)/ucl_util.o \ + $(OBJDIR)/ucl_parser.o \ + $(OBJDIR)/ucl_emitter.o \ + $(OBJDIR)/ucl_schema.o \ + $(OBJDIR)/xxhash.o all: $(OBJDIR) $(OBJDIR)/$(SONAME) @@ -44,11 +53,13 @@ $(OBJDIR)/ucl_emitter.o: $(SRCDIR)/ucl_e $(CC) -o $(OBJDIR)/ucl_emitter.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_emitter.c $(OBJDIR)/ucl_hash.o: $(SRCDIR)/ucl_hash.c $(HDEPS) $(CC) -o $(OBJDIR)/ucl_hash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_hash.c +$(OBJDIR)/ucl_schema.o: $(SRCDIR)/ucl_schema.c $(HDEPS) + $(CC) -o $(OBJDIR)/ucl_schema.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_schema.c $(OBJDIR)/xxhash.o: $(SRCDIR)/xxhash.c $(HDEPS) $(CC) -o $(OBJDIR)/xxhash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/xxhash.c clean: - $(RM) $(OBJDIR)/*.o $(OBJDIR)/$(SONAME_FULL) $(OBJDIR)/$(SONAME) $(OBJDIR)/chargen $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/objdump $(OBJDIR)/test_generate + $(RM) $(OBJDIR)/*.o $(OBJDIR)/$(SONAME_FULL) $(OBJDIR)/$(SONAME) $(OBJDIR)/chargen $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/objdump $(OBJDIR)/test_generate $(OBJDIR)/test_schema || true $(RMDIR) $(OBJDIR) # Utils @@ -60,13 +71,15 @@ objdump: utils/objdump.c $(OBJDIR)/$(SON # Tests -test: $(OBJDIR) $(OBJDIR)/$(SONAME) $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/test_generate +test: $(OBJDIR) $(OBJDIR)/$(SONAME) $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/test_generate $(OBJDIR)/test_schema run-test: test - TEST_DIR=$(TESTDIR) $(TESTDIR)/run_tests.sh $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/test_generate + TEST_DIR=$(TESTDIR) $(TESTDIR)/run_tests.sh $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/test_generate $(OBJDIR)/test_schema $(OBJDIR)/test_basic: $(TESTDIR)/test_basic.c $(OBJDIR)/$(SONAME) $(CC) -o $(OBJDIR)/test_basic $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) $(TESTDIR)/test_basic.c $(LD_UCL_FLAGS) +$(OBJDIR)/test_schema: $(TESTDIR)/test_schema.c $(OBJDIR)/$(SONAME) + $(CC) -o $(OBJDIR)/test_schema $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) $(TESTDIR)/test_schema.c $(LD_UCL_FLAGS) $(OBJDIR)/test_speed: $(TESTDIR)/test_speed.c $(OBJDIR)/$(SONAME) $(CC) -o $(OBJDIR)/test_speed $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) $(TESTDIR)/test_speed.c $(LD_UCL_FLAGS) $(LD_ADD) $(OBJDIR)/test_generate: $(TESTDIR)/test_generate.c $(OBJDIR)/$(SONAME) Modified: stable/10/contrib/libucl/Makefile.w32 ============================================================================== --- stable/10/contrib/libucl/Makefile.w32 Sat Jul 19 23:39:17 2014 (r268895) +++ stable/10/contrib/libucl/Makefile.w32 Sat Jul 19 23:44:57 2014 (r268896) @@ -4,7 +4,7 @@ LD ?= gcc C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src MAJOR_VERSION = 0 MINOR_VERSION = 2 -PATCH_VERSION = 8 +PATCH_VERSION = 9 VERSION = "$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION)" SONAME = libucl.dll OBJDIR ?= .obj @@ -24,8 +24,17 @@ LD_SHARED_FLAGS ?= -Wl,-soname,$(SONAME) LD_UCL_FLAGS ?= -L$(OBJDIR) -Wl,-rpath,$(OBJDIR) -lucl LD_ADD ?= -lrt COPT_FLAGS ?= -O2 -HDEPS = $(SRCDIR)/ucl_hash.h $(SRCDIR)/ucl_chartable.h $(SRCDIR)/ucl_internal.h $(INCLUDEDIR)/ucl.h $(SRCDIR)/xxhash.h -OBJECTS = $(OBJDIR)/ucl_hash.o $(OBJDIR)/ucl_util.o $(OBJDIR)/ucl_parser.o $(OBJDIR)/ucl_emitter.o $(OBJDIR)/xxhash.o +HDEPS = $(SRCDIR)/ucl_hash.h \ + $(SRCDIR)/ucl_chartable.h \ + $(SRCDIR)/ucl_internal.h \ + $(INCLUDEDIR)/ucl.h \ + $(SRCDIR)/xxhash.h +OBJECTS = $(OBJDIR)/ucl_hash.o \ + $(OBJDIR)/ucl_util.o \ + $(OBJDIR)/ucl_parser.o \ + $(OBJDIR)/ucl_emitter.o \ + $(OBJDIR)/ucl_schema.o \ + $(OBJDIR)/xxhash.o all: $(OBJDIR) $(OBJDIR)/$(SONAME) @@ -44,6 +53,8 @@ $(OBJDIR)/ucl_emitter.o: $(SRCDIR)/ucl_e $(CC) -o $(OBJDIR)/ucl_emitter.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_emitter.c $(OBJDIR)/ucl_hash.o: $(SRCDIR)/ucl_hash.c $(HDEPS) $(CC) -o $(OBJDIR)/ucl_hash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_hash.c +$(OBJDIR)/ucl_schema.o: $(SRCDIR)/ucl_schema.c $(HDEPS) + $(CC) -o $(OBJDIR)/ucl_schema.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_schema.c $(OBJDIR)/xxhash.o: $(SRCDIR)/xxhash.c $(HDEPS) $(CC) -o $(OBJDIR)/xxhash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/xxhash.c Modified: stable/10/contrib/libucl/README.md ============================================================================== --- stable/10/contrib/libucl/README.md Sat Jul 19 23:39:17 2014 (r268895) +++ stable/10/contrib/libucl/README.md Sat Jul 19 23:44:57 2014 (r268896) @@ -1,3 +1,26 @@ +# LIBUCL + +[![Build Status](https://travis-ci.org/vstakhov/libucl.svg?branch=master)](https://travis-ci.org/vstakhov/libucl) + +**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* + +- [Introduction](#introduction) +- [Basic structure](#basic-structure) +- [Improvements to the json notation](#improvements-to-the-json-notation) + - [General syntax sugar](#general-syntax-sugar) + - [Automatic arrays creation](#automatic-arrays-creation) + - [Named keys hierarchy](#named-keys-hierarchy) + - [Convenient numbers and booleans](#convenient-numbers-and-booleans) +- [General improvements](#general-improvements) + - [Commments](#commments) + - [Macros support](#macros-support) + - [Variables support](#variables-support) + - [Multiline strings](#multiline-strings) +- [Emitter](#emitter) +- [Validation](#validation) +- [Performance](#performance) +- [Conclusion](#conclusion) + ## Introduction This document describes the main features and principles of the configuration @@ -262,6 +285,10 @@ Each UCL object can be serialized to one * `Configuration` - nginx like notation; * `YAML` - yaml inlined notation. +## Validation + +UCL allows validation of objects. It uses the same schema that is used for json: [json schema v4](http://json-schema.org). UCL supports the full set of json schema with the exception of remote references. This feature is unlikely useful for configuration objects. Of course, a schema definition can be in UCL format instead of JSON that simplifies schemas writing. Moreover, since UCL supports multiple values for keys in an object it is possible to specify generic integer constraints `maxValues` and `minValues` to define the limits of values count in a single key. UCL currently is not absolutely strict about validation schemas themselves, therefore UCL users should supply valid schemas (as it is defined in json-schema draft v4) to ensure that the input objects are validated properly. + ## Performance Are UCL parser and emitter fast enough? Well, there are some numbers. Added: stable/10/contrib/libucl/autogen.sh ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libucl/autogen.sh Sat Jul 19 23:44:57 2014 (r268896) @@ -0,0 +1,2 @@ +#!/bin/sh +autoreconf -i Added: stable/10/contrib/libucl/cmake/CMakeLists.txt ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libucl/cmake/CMakeLists.txt Sat Jul 19 23:44:57 2014 (r268896) @@ -0,0 +1,112 @@ +PROJECT(libucl C) + +SET(LIBUCL_VERSION_MAJOR 0) +SET(LIBUCL_VERSION_MINOR 2) +SET(LIBUCL_VERSION_PATCH 9) + +SET(LIBUCL_VERSION "${LIBUCL_VERSION_MAJOR}.${LIBUCL_VERSION_MINOR}.${LIBUCL_VERSION_PATCH}") + +INCLUDE(CheckCCompilerFlag) +INCLUDE(FindOpenSSL) +CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR) + +OPTION(ENABLE_URL_INCLUDE "Enable urls in ucl includes (requires libcurl or libfetch) [default: OFF]" OFF) +OPTION(ENABLE_URL_SIGN "Enable signatures check in ucl includes (requires openssl) [default: OFF]" OFF) +OPTION(BUILD_SHARED_LIBS "Build Shared Libraries [default: OFF]" OFF) + +IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") + LIST(APPEND CMAKE_REQUIRED_LIBRARIES rt) +ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") + +IF(ENABLE_URL_INCLUDE MATCHES "ON") + FIND_LIBRARY(LIBFETCH_LIBRARY NAMES fetch PATHS PATH_SUFFIXES lib64 lib + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw + /opt/local + /opt/csw + /opt + DOC "Path where the libfetch library can be found") + IF(LIBFETCH_LIBRARY) + FIND_FILE(HAVE_FETCH_H NAMES fetch.h PATHS /usr/include + /opt/include + /usr/local/include + DOC "Path to libfetch header") + ELSE(LIBFETCH_LIBRARY) + # Try to find libcurl + ProcessPackage(CURL libcurl) + IF(NOT CURL_FOUND) + MESSAGE(WARNING "Neither libcurl nor libfetch were found, no support of URL includes in configuration") + ENDIF(NOT CURL_FOUND) + ENDIF(LIBFETCH_LIBRARY) +ENDIF(ENABLE_URL_INCLUDE MATCHES "ON") + +SET(CMAKE_C_WARN_FLAGS "") +CHECK_C_COMPILER_FLAG(-Wall SUPPORT_WALL) +CHECK_C_COMPILER_FLAG(-W SUPPORT_W) +CHECK_C_COMPILER_FLAG(-Wno-unused-parameter SUPPORT_WPARAM) +CHECK_C_COMPILER_FLAG(-Wno-pointer-sign SUPPORT_WPOINTER_SIGN) +CHECK_C_COMPILER_FLAG(-Wstrict-prototypes SUPPORT_WSTRICT_PROTOTYPES) +IF(NOT "${CMAKE_C_COMPILER_ID}" MATCHES SunPro) + CHECK_C_COMPILER_FLAG("-std=c99" SUPPORT_STD_FLAG) +ENDIF(NOT "${CMAKE_C_COMPILER_ID}" MATCHES SunPro) +IF(SUPPORT_W) + SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -W") +ENDIF(SUPPORT_W) +IF(SUPPORT_WALL) + SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wall") +ENDIF(SUPPORT_WALL) +IF(SUPPORT_WPARAM) + SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wno-unused-parameter") +ENDIF(SUPPORT_WPARAM) +IF(SUPPORT_WPOINTER_SIGN) + SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wno-pointer-sign") +ENDIF(SUPPORT_WPOINTER_SIGN) +IF(SUPPORT_WSTRICT_PROTOTYPES) + SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -Wstrict-prototypes") +ENDIF(SUPPORT_WSTRICT_PROTOTYPES) +IF(SUPPORT_STD_FLAG) + SET(CMAKE_C_WARN_FLAGS "${CMAKE_C_WARN_FLAGS} -std=c99") +ENDIF(SUPPORT_STD_FLAG) + +IF(ENABLE_URL_SIGN MATCHES "ON") + IF(OPENSSL_FOUND) + SET(HAVE_OPENSSL 1) + INCLUDE_DIRECTORIES("${OPENSSL_INCLUDE_DIR}") + ENDIF(OPENSSL_FOUND) +ENDIF(ENABLE_URL_SIGN MATCHES "ON") + +INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../src") +INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../include") +INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../uthash") + +SET(UCLSRC ../src/ucl_util.c + ../src/ucl_parser.c + ../src/ucl_emitter.c + ../src/ucl_hash.c + ../src/ucl_schema.c + ../src/xxhash.c) + + +SET (LIB_TYPE STATIC) +IF (BUILD_SHARED_LIBS) + SET (LIB_TYPE SHARED) +ENDIF (BUILD_SHARED_LIBS) +ADD_LIBRARY(ucl ${LIB_TYPE} ${UCLSRC}) +SET_TARGET_PROPERTIES(ucl PROPERTIES VERSION ${LIBUCL_VERSION} SOVERSION ${LIBUCL_VERSION_MAJOR}) + +IF(HAVE_FETCH_H) + TARGET_LINK_LIBRARIES(ucl fetch) +ELSE(HAVE_FETCH_H) + IF(CURL_FOUND) + TARGET_LINK_LIBRARIES(ucl ${CURL_LIBRARIES}) + ENDIF(CURL_FOUND) +ENDIF(HAVE_FETCH_H) +IF(ENABLE_URL_SIGN MATCHES "ON") + IF(OPENSSL_FOUND) + TARGET_LINK_LIBRARIES(ucl ${OPENSSL_LIBRARIES}) + ENDIF(OPENSSL_FOUND) +ENDIF(ENABLE_URL_SIGN MATCHES "ON") Added: stable/10/contrib/libucl/configure.ac ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libucl/configure.ac Sat Jul 19 23:44:57 2014 (r268896) @@ -0,0 +1,163 @@ +m4_define([maj_ver], [0]) +m4_define([med_ver], [4]) +m4_define([min_ver], [1]) +m4_define([so_version], [1:0:0]) +m4_define([ucl_version], [maj_ver.med_ver.min_ver]) + +AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl]) +AC_CONFIG_SRCDIR([configure.ac]) +AM_INIT_AUTOMAKE([1.11 foreign silent-rules -Wall -Wportability no-dist-gzip dist-xz]) + +UCL_VERSION=ucl_version +SO_VERSION=so_version + +AC_SUBST(UCL_VERSION) +AC_SUBST(SO_VERSION) + +AC_PROG_CC_C99 +AM_PROG_CC_C_O +AM_PROG_AR +LT_INIT +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) + +AC_C_CONST +AC_TYPE_SIZE_T + +AC_CHECK_HEADERS_ONCE([fcntl.h unistd.h]) +AC_TYPE_OFF_T +AC_FUNC_MMAP +AC_CHECK_HEADERS_ONCE([fcntl.h]) +AC_CHECK_HEADERS_ONCE([sys/types.h]) +AC_CHECK_HEADERS_ONCE([sys/stat.h]) +AC_CHECK_HEADERS_ONCE([sys/param.h]) +AC_CHECK_HEADERS_ONCE([sys/mman.h]) +AC_CHECK_HEADERS_ONCE([stdlib.h]) +AC_CHECK_HEADERS_ONCE([stddef.h]) +AC_CHECK_HEADERS_ONCE([stdarg.h]) +AC_CHECK_HEADERS_ONCE([stdbool.h]) +AC_CHECK_HEADERS_ONCE([stdint.h]) +AC_CHECK_HEADERS_ONCE([string.h]) +AC_CHECK_HEADERS_ONCE([unistd.h]) +AC_CHECK_HEADERS_ONCE([ctype.h]) +AC_CHECK_HEADERS_ONCE([errno.h]) +AC_CHECK_HEADERS_ONCE([limits.h]) +AC_CHECK_HEADERS_ONCE([libgen.h]) +AC_CHECK_HEADERS_ONCE([stdio.h]) +AC_CHECK_HEADERS_ONCE([float.h]) +AC_CHECK_HEADERS_ONCE([math.h]) + +dnl Example of default-disabled feature +AC_ARG_ENABLE([urls], AS_HELP_STRING([--enable-urls], + [Enable URLs fetch (requires libfetch or libcurl) @<:@default=no@:>@]), [], + [enable_urls=no]) +AC_ARG_ENABLE([regex], AS_HELP_STRING([--enable-regex], + [Enable regex checking for schema @<:@default=yes@:>@]), [], + [enable_regex=yes]) +AC_ARG_ENABLE([signatures], AS_HELP_STRING([--enable-signatures], + [Enable signatures check (requires openssl) @<:@default=no@:>@]), [], + [enable_signatures=no]) +AC_ARG_ENABLE([utils], + AS_HELP_STRING([--enable-utils], [Build and install utils @<:@default=no@:>@]), + [case "${enableval}" in + yes) utils=true ;; + no) utils=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-utils]) ;; + esac],[utils=false]) +AM_CONDITIONAL([UTILS], [test x$utils = xtrue]) + +AS_IF([test "x$enable_signatures" = "xyes"], [ + AC_SEARCH_LIBS([EVP_MD_CTX_create], [crypto], [ + AC_DEFINE(HAVE_OPENSSL, 1, [Define to 1 if you have the 'crypto' library (-lcrypto).]) + LIBCRYPTO_LIB="-lcrypto" + LIBS_EXTRA="${LIBS_EXTRA} -lcrypto" + ], [AC_MSG_ERROR([unable to find the EVP_MD_CTX_create() function])]) +]) +AC_SUBST(LIBCRYPTO_LIB) +AC_PATH_PROG(PANDOC, pandoc, [/non/existent]) + +AC_SEARCH_LIBS([clock_gettime], [rt], [], [ + AC_CHECK_HEADER([mach/mach_time.h], [ + AC_DEFINE(HAVE_MACH_MACH_TIME_H, 1, [Define to 1 on Darwin]) + ], [AC_MSG_ERROR([unable to find clock_gettime or mach_absolute_time])]) +]) +AC_SEARCH_LIBS([remainder], [m], [], [AC_MSG_ERROR([unable to find remainder() function])]) + +AS_IF([test "x$enable_regex" = "xyes"], [ + AC_CHECK_HEADER([regex.h], [ + AC_DEFINE(HAVE_REGEX_H, 1, [Define to 1 if you have the header file.]) + AC_SEARCH_LIBS([regexec], [regex], [ + AS_IF([test "x$ac_cv_search_regexec" = "x-lregex"], [ + LIBREGEX_LIB="-lregex" + LIBS_EXTRA="${LIBS_EXTRA} -lregex" + ] + )], + [AC_MSG_ERROR([unable to find the regexec() function])])], + [AC_MSG_ERROR([unable to find the regex.h header]) + ], + [#include ]) +]) +AC_SUBST(LIBREGEX_LIB) + +AS_IF([test "x$enable_urls" = "xyes"], [ + AC_CHECK_HEADER([fetch.h], [ + AC_DEFINE(HAVE_FETCH_H, 1, [Define to 1 if you have the header file.]) + AC_CHECK_LIB(fetch, fetchXGet, [ + AC_DEFINE(HAVE_LIBFETCH, 1, [Define to 1 if you have the 'fetch' library (-lfetch).]) + LIBFETCH_LIBS="-lfetch" + have_libfetch="yes" + LIBS_EXTRA="${LIBS_EXTRA} -lfetch" + ]) + ], [],[ + #include + #ifdef HAVE_SYS_PARAM_H + #include + #endif + ]) + AC_SUBST(LIBFETCH_LIBS) + + AS_IF([ test "x$have_libfetch" != "xyes"], [ + dnl Fallback to libcurl + PKG_CHECK_MODULES([CURL], [libcurl], [ + AC_DEFINE(CURL_FOUND, 1, [Use libcurl]) + LIBS_EXTRA="${LIBS_EXTRA} -lcurl"], + [AC_MSG_ERROR([unable to find neither libfetch nor libcurl])]) + ]) + AC_SUBST(CURL_FOUND) + AC_SUBST(CURL_LIBS) + AC_SUBST(CURL_CFLAGS) +]) + +AC_SUBST(LIBS_EXTRA) + +AC_MSG_CHECKING(for GCC atomic builtins) +AC_LINK_IFELSE([ + AC_LANG_SOURCE([[ + int main() { + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); + return 0; + } + ]]) +], +[ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_ATOMIC_BUILTINS], [1], [Has gcc/MSVC atomic intrinsics]) +], +[ + AC_MSG_RESULT([no]) + AC_DEFINE([HAVE_ATOMIC_BUILTINS], [0], [Has gcc/MSVC atomic intrinsics]) + AC_MSG_WARN([Libucl references could be thread-unsafe because atomic builtins are missing]) +]) + +AC_CONFIG_FILES(Makefile \ + src/Makefile \ + tests/Makefile \ + utils/Makefile \ + doc/Makefile \ + libucl.pc) +AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) +AC_OUTPUT Added: stable/10/contrib/libucl/doc/Makefile.am ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libucl/doc/Makefile.am Sat Jul 19 23:44:57 2014 (r268896) @@ -0,0 +1,8 @@ +EXTRA_DIST = api.md + +dist_man_MANS = libucl.3 + +gen-man: @PANDOC@ + tail -n +$$(grep -n '# Synopsis' api.md | cut -d':' -f1) api.md | \ + cat pandoc.template - | sed -e 's/^# \(.*\)/# \U\1/' | \ + @PANDOC@ -s -f markdown -t man -o libucl.3 \ No newline at end of file Modified: stable/10/contrib/libucl/doc/api.md ============================================================================== --- stable/10/contrib/libucl/doc/api.md Sat Jul 19 23:39:17 2014 (r268895) +++ stable/10/contrib/libucl/doc/api.md Sat Jul 19 23:44:57 2014 (r268896) @@ -1,30 +1,75 @@ -Synopsis -======== +# API documentation + +**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* + +- [Synopsis](#synopsis) +- [Description](#description) + - [Parser functions](#parser-functions) + - [Emitting functions](#emitting-functions) + - [Conversion functions](#conversion-functions) + - [Generation functions](#generation-functions) + - [Iteration functions](#iteration-functions) + - [Validation functions](#validation-functions) + - [Utility functions](#utility-functions) +- [Parser functions](#parser-functions-1) + - [ucl_parser_new](#ucl_parser_new) + - [ucl_parser_register_macro](#ucl_parser_register_macro) + - [ucl_parser_register_variable](#ucl_parser_register_variable) + - [ucl_parser_add_chunk](#ucl_parser_add_chunk) + - [ucl_parser_add_string](#ucl_parser_add_string) + - [ucl_parser_add_file](#ucl_parser_add_file) + - [ucl_parser_get_object](#ucl_parser_get_object) + - [ucl_parser_get_error](#ucl_parser_get_error) + - [ucl_parser_free](#ucl_parser_free) + - [ucl_pubkey_add](#ucl_pubkey_add) + - [ucl_parser_set_filevars](#ucl_parser_set_filevars) + - [Parser usage example](#parser-usage-example) +- [Emitting functions](#emitting-functions-1) + - [ucl_object_emit](#ucl_object_emit) + - [ucl_object_emit_full](#ucl_object_emit_full) +- [Conversion functions](#conversion-functions-1) +- [Generation functions](#generation-functions-1) + - [ucl_object_new](#ucl_object_new) + - [ucl_object_typed_new](#ucl_object_typed_new) + - [Primitive objects generation](#primitive-objects-generation) + - [ucl_object_fromstring_common](#ucl_object_fromstring_common) +- [Iteration functions](#iteration-functions-1) + - [ucl_iterate_object](#ucl_iterate_object) +- [Validation functions](#validation-functions-1) + - [ucl_object_validate](#ucl_object_validate) + +# Synopsis `#include ` -Description -=========== +# Description Libucl is a parser and `C` API to parse and generate `ucl` objects. Libucl consist of several groups of functions: ### Parser functions -Used to parse `ucl` files and provide interface to extract `ucl` object +Used to parse `ucl` files and provide interface to extract `ucl` object. Currently, `libucl` can parse only full `ucl` documents, for instance, it is impossible to parse a part of document and therefore it is impossible to use `libucl` as a streaming parser. In future, this limitation can be removed. ### Emitting functions -Convert `ucl` objects to some textual or binary representation. +Convert `ucl` objects to some textual or binary representation. Currently, libucl supports the following exports: + +- `JSON` - valid json format (can possibly loose some original data, such as implicit arrays) +- `Config` - human-readable configuration format (losseless) +- `YAML` - embedded yaml format (has the same limitations as `json` output) ### Conversion functions -Help to convert `ucl` objects to C types +Help to convert `ucl` objects to C types. These functions are used to convert `ucl_object_t` to C primitive types, such as numbers, strings or boolean values. ### Generation functions -Allow creating of `ucl` objects from C types +Allow creating of `ucl` objects from C types and creating of complex `ucl` objects, such as hashes or arrays from primitive `ucl` objects, such as numbers or strings. ### Iteration functions -Iterate over `ucl` objects +Iterate over `ucl` complex objects or over a chain of values, for example when a key in an object has multiple values (that can be treated as implicit array or implicit consolidation). + +### Validation functions +Validation functions are used to validate some object `obj` using json-schema compatible object `schema`. Both input and schema must be UCL objects to perform validation. ### Utility functions -Provide basic utilities to manage `ucl` objects +Provide basic utilities to manage `ucl` objects: creating, removing, retaining and releasing reference count and so on. # Parser functions @@ -40,6 +85,7 @@ Creates new parser with the specified fl - `UCL_PARSER_KEY_LOWERCASE` - lowercase keys parsed - `UCL_PARSER_ZEROCOPY` - try to use zero-copy mode when reading files (in zero-copy mode text chunk being parsed without copying strings so it should exist till any object parsed is used) +- `UCL_PARSER_NO_TIME` - treat time values as strings without parsing them as floats ### ucl_parser_register_macro @@ -87,6 +133,14 @@ while this one won't be parsed correctly This limitation may possible be removed in future. +### ucl_parser_add_string +~~~C +bool ucl_parser_add_string (struct ucl_parser *parser, + const char *data, size_t len); +~~~ + +This function acts exactly like `ucl_parser_add_chunk` does but if `len` argument is zero, then the string `data` must be zero-terminated and the actual length is calculated up to `\0` character. + ### ucl_parser_add_file ~~~C @@ -228,7 +282,7 @@ Libucl provides the following functions ### ucl_object_emit ~~~C -unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); +unsigned char *ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type); ~~~ Allocate a string that is suitable to fit the underlying UCL object `obj` and fill it with the textual representation of the object `obj` according to style `emit_type`. The caller should free the returned string after using. @@ -236,7 +290,7 @@ Allocate a string that is suitable to fi ### ucl_object_emit_full ~~~C -bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, +bool ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type, struct ucl_emitter_functions *emitter); ~~~ @@ -314,19 +368,20 @@ This function is used to convert a strin - `UCL_STRING_PARSE_BOOLEAN` - parse passed string and detect boolean - `UCL_STRING_PARSE_INT` - parse passed string and detect integer number - `UCL_STRING_PARSE_DOUBLE` - parse passed string and detect integer or float number -- `UCL_STRING_PARSE_NUMBER` - parse passed string and detect number (both float or integer types) -- `UCL_STRING_PARSE` - parse passed string (and detect booleans and numbers) +- `UCL_STRING_PARSE_TIME` - parse time values as floating point numbers +- `UCL_STRING_PARSE_NUMBER` - parse passed string and detect number (both float, integer and time types) +- `UCL_STRING_PARSE` - parse passed string (and detect booleans, numbers and time values) - `UCL_STRING_PARSE_BYTES` - assume that numeric multipliers are in bytes notation, for example `10k` means `10*1024` and not `10*1000` as assumed without this flag If parsing operations fail then the resulting UCL object will be a `UCL_STRING`. A caller should always check the type of the returned object and release it after using. -# Iteration function +# Iteration functions Iteration are used to iterate over UCL compound types: arrays and objects. Moreover, iterations could be performed over the keys with multiple values (implicit arrays). To iterate over an object, an array or a key with multiple values there is a function `ucl_iterate_object`. ## ucl_iterate_object ~~~C -ucl_object_t* ucl_iterate_object (ucl_object_t *obj, +const ucl_object_t* ucl_iterate_object (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); ~~~ @@ -334,7 +389,7 @@ This function accept opaque iterator poi ~~~C ucl_object_iter_t it = NULL, it_obj = NULL; -ucl_object_t *cur, *tmp; +const ucl_object_t *cur, *tmp; /* Iterate over the object */ while ((obj = ucl_iterate_object (top, &it, true))) { @@ -345,4 +400,40 @@ while ((obj = ucl_iterate_object (top, & ucl_object_tostring_forced (cur)); } } -~~~ \ No newline at end of file +~~~ + +# Validation functions + +Currently, there is only one validation function called `ucl_object_validate`. It performs validation of object using the specified schema. This function is defined as following: + +## ucl_object_validate +~~~C +bool ucl_object_validate (const ucl_object_t *schema, + const ucl_object_t *obj, struct ucl_schema_error *err); +~~~ + +This function uses ucl object `schema`, that must be valid in terms of `json-schema` draft v4, to validate input object `obj`. If this function returns `true` then validation procedure has been succeed. Otherwise, `false` is returned and `err` is set to a specific value. If caller set `err` to NULL then this function does not set any error just returning `false`. Error is the structure defined as following: + +~~~C +struct ucl_schema_error { + enum ucl_schema_error_code code; /* error code */ + char msg[128]; /* error message */ + ucl_object_t *obj; /* object where error occured */ +}; +~~~ + +Caller may use `code` field to get a numeric error code: + +~~~C +enum ucl_schema_error_code { + UCL_SCHEMA_OK = 0, /* no error */ + UCL_SCHEMA_TYPE_MISMATCH, /* type of object is incorrect */ + UCL_SCHEMA_INVALID_SCHEMA, /* schema is invalid */ + UCL_SCHEMA_MISSING_PROPERTY,/* missing properties */ + UCL_SCHEMA_CONSTRAINT, /* constraint found */ + UCL_SCHEMA_MISSING_DEPENDENCY, /* missing dependency */ + UCL_SCHEMA_UNKNOWN /* generic error */ +}; +~~~ + +`msg` is a stiring description of an error and `obj` is an object where error has been occurred. Error object is not allocated by libucl, so there is no need to free it after validation (a static object should thus be used). \ No newline at end of file Added: stable/10/contrib/libucl/doc/libucl.3 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/contrib/libucl/doc/libucl.3 Sat Jul 19 23:44:57 2014 (r268896) @@ -0,0 +1,637 @@ +.TH LIBUCL 5 "March 20, 2014" "Libucl manual" +.SH NAME +.PP +\f[B]ucl_parser_new\f[], \f[B]ucl_parser_register_macro\f[], +\f[B]ucl_parser_register_variable\f[], \f[B]ucl_parser_add_chunk\f[], +\f[B]ucl_parser_add_string\f[], \f[B]ucl_parser_add_file\f[], +\f[B]ucl_parser_get_object\f[], \f[B]ucl_parser_get_error\f[], +\f[B]ucl_parser_free\f[], \f[B]ucl_pubkey_add\f[], +\f[B]ucl_parser_set_filevars\f[] \- universal configuration library +parser and utility functions +.SH LIBRARY +.PP +UCL library (libucl, \-lucl) +.SH SYNOPSIS +.PP +\f[C]#include\ \f[] +.SH DESCRIPTION +.PP +Libucl is a parser and \f[C]C\f[] API to parse and generate \f[C]ucl\f[] +objects. +Libucl consist of several groups of functions: +.SS Parser functions +.PP +Used to parse \f[C]ucl\f[] files and provide interface to extract +\f[C]ucl\f[] object. +Currently, \f[C]libucl\f[] can parse only full \f[C]ucl\f[] documents, +for instance, it is impossible to parse a part of document and therefore +it is impossible to use \f[C]libucl\f[] as a streaming parser. +In future, this limitation can be removed. +.SS Emitting functions +.PP +Convert \f[C]ucl\f[] objects to some textual or binary representation. +Currently, libucl supports the following exports: +.IP \[bu] 2 +\f[C]JSON\f[] \- valid json format (can possibly loose some original +data, such as implicit arrays) +.IP \[bu] 2 +\f[C]Config\f[] \- human\-readable configuration format (losseless) +.IP \[bu] 2 +\f[C]YAML\f[] \- embedded yaml format (has the same limitations as +\f[C]json\f[] output) +.SS Conversion functions +.PP +Help to convert \f[C]ucl\f[] objects to C types. +These functions are used to convert \f[C]ucl_object_t\f[] to C primitive +types, such as numbers, strings or boolean values. +.SS Generation functions +.PP +Allow creating of \f[C]ucl\f[] objects from C types and creating of +complex \f[C]ucl\f[] objects, such as hashes or arrays from primitive +\f[C]ucl\f[] objects, such as numbers or strings. +.SS Iteration functions +.PP +Iterate over \f[C]ucl\f[] complex objects or over a chain of values, for +example when a key in an object has multiple values (that can be treated +as implicit array or implicit consolidation). +.SS Validation functions +.PP +Validation functions are used to validate some object \f[C]obj\f[] using +json\-schema compatible object \f[C]schema\f[]. +Both input and schema must be UCL objects to perform validation. +.SS Utility functions +.PP +Provide basic utilities to manage \f[C]ucl\f[] objects: creating, +removing, retaining and releasing reference count and so on. +.SH PARSER FUNCTIONS +.PP +Parser functions operates with \f[C]struct\ ucl_parser\f[]. +.SS ucl_parser_new +.IP +.nf +\f[C] +struct\ ucl_parser*\ ucl_parser_new\ (int\ flags); +\f[] +.fi +.PP +Creates new parser with the specified flags: +.IP \[bu] 2 +\f[C]UCL_PARSER_KEY_LOWERCASE\f[] \- lowercase keys parsed +.IP \[bu] 2 +\f[C]UCL_PARSER_ZEROCOPY\f[] \- try to use zero\-copy mode when reading +files (in zero\-copy mode text chunk being parsed without copying +strings so it should exist till any object parsed is used) +.IP \[bu] 2 +\f[C]UCL_PARSER_NO_TIME\f[] \- treat time values as strings without +parsing them as floats +.SS ucl_parser_register_macro +.IP +.nf +\f[C] +void\ ucl_parser_register_macro\ (struct\ ucl_parser\ *parser, +\ \ \ \ const\ char\ *macro,\ ucl_macro_handler\ handler,\ void*\ ud); +\f[] +.fi +.PP +Register new macro with name .\f[C]macro\f[] parsed by handler +\f[C]handler\f[] that accepts opaque data pointer \f[C]ud\f[]. +Macro handler should be of the following type: +.IP +.nf +\f[C] +bool\ (*ucl_macro_handler)\ (const\ unsigned\ char\ *data, +\ \ \ \ size_t\ len,\ void*\ ud);` +\f[] +.fi +.PP +Handler function accepts macro text \f[C]data\f[] of length \f[C]len\f[] +and the opaque pointer \f[C]ud\f[]. +If macro is parsed successfully the handler should return \f[C]true\f[]. +\f[C]false\f[] indicates parsing failure and the parser can be +terminated. +.SS ucl_parser_register_variable +.IP +.nf +\f[C] +void\ ucl_parser_register_variable\ (struct\ ucl_parser\ *parser, +\ \ \ \ const\ char\ *var,\ const\ char\ *value); +\f[] +.fi +.PP +Register new variable $\f[C]var\f[] that should be replaced by the +parser to the \f[C]value\f[] string. +.SS ucl_parser_add_chunk +.IP +.nf +\f[C] +bool\ ucl_parser_add_chunk\ (struct\ ucl_parser\ *parser,\ +\ \ \ \ const\ unsigned\ char\ *data,\ size_t\ len); +\f[] +.fi +.PP +Add new text chunk with \f[C]data\f[] of length \f[C]len\f[] to the +parser. +At the moment, \f[C]libucl\f[] parser is not a streamlined parser and +chunk \f[I]must\f[] contain the \f[I]valid\f[] ucl object. +For example, this object should be valid: +.IP +.nf +\f[C] +{\ "var":\ "value"\ } +\f[] +.fi +.PP +while this one won\[aq]t be parsed correctly: +.IP +.nf +\f[C] +{\ "var":\ +\f[] +.fi +.PP +This limitation may possible be removed in future. +.SS ucl_parser_add_string +.IP +.nf +\f[C] +bool\ ucl_parser_add_string\ (struct\ ucl_parser\ *parser,\ +\ \ \ \ const\ char\ *data,\ size_t\ len); +\f[] +.fi +.PP +This function acts exactly like \f[C]ucl_parser_add_chunk\f[] does but +if \f[C]len\f[] argument is zero, then the string \f[C]data\f[] must be +zero\-terminated and the actual length is calculated up to \f[C]\\0\f[] +character. +.SS ucl_parser_add_file +.IP +.nf +\f[C] +bool\ ucl_parser_add_file\ (struct\ ucl_parser\ *parser,\ +\ \ \ \ const\ char\ *filename); +\f[] +.fi +.PP +Load file \f[C]filename\f[] and parse it with the specified +\f[C]parser\f[]. +This function uses \f[C]mmap\f[] call to load file, therefore, it should +not be \f[C]shrinked\f[] during parsing. +Otherwise, \f[C]libucl\f[] can cause memory corruption and terminate the +calling application. +This function is also used by the internal handler of \f[C]include\f[] +macro, hence, this macro has the same limitation. +.SS ucl_parser_get_object +.IP +.nf +\f[C] +ucl_object_t*\ ucl_parser_get_object\ (struct\ ucl_parser\ *parser); +\f[] +.fi +.PP +If the \f[C]ucl\f[] data has been parsed correctly this function returns +the top object for the parser. +Otherwise, this function returns the \f[C]NULL\f[] pointer. +The reference count for \f[C]ucl\f[] object returned is increased by +one, therefore, a caller should decrease reference by using +\f[C]ucl_object_unref\f[] to free object after usage. +.SS ucl_parser_get_error +.IP +.nf +\f[C] +const\ char\ *ucl_parser_get_error(struct\ ucl_parser\ *parser); +\f[] +.fi +.PP +Returns the constant error string for the parser object. +If no error occurred during parsing a \f[C]NULL\f[] object is returned. +A caller should not try to free or modify this string. +.SS ucl_parser_free +.IP +.nf +\f[C] +void\ ucl_parser_free\ (struct\ ucl_parser\ *parser); +\f[] +.fi +.PP +Frees memory occupied by the parser object. +The reference count for top object is decreased as well, however if the +function \f[C]ucl_parser_get_object\f[] was called previously then the +top object won\[aq]t be freed. +.SS ucl_pubkey_add +.IP +.nf +\f[C] +bool\ ucl_pubkey_add\ (struct\ ucl_parser\ *parser,\ +\ \ \ \ const\ unsigned\ char\ *key,\ size_t\ len); +\f[] +.fi +.PP +This function adds a public key from text blob \f[C]key\f[] of length +\f[C]len\f[] to the \f[C]parser\f[] object. +This public key should be in the \f[C]PEM\f[] format and can be used by +\f[C]\&.includes\f[] macro for checking signatures of files included. +\f[C]Openssl\f[] support should be enabled to make this function +working. +If a key cannot be added (e.g. +due to format error) or \f[C]openssl\f[] was not linked to +\f[C]libucl\f[] then this function returns \f[C]false\f[]. +.SS ucl_parser_set_filevars +.IP +.nf +\f[C] +bool\ ucl_parser_set_filevars\ (struct\ ucl_parser\ *parser,\ +\ \ \ \ const\ char\ *filename,\ bool\ need_expand); +\f[] +.fi +.PP +Add the standard file variables to the \f[C]parser\f[] based on the +\f[C]filename\f[] specified: +.IP \[bu] 2 +\f[C]$FILENAME\f[] \- a filename of \f[C]ucl\f[] input +.IP \[bu] 2 +\f[C]$CURDIR\f[] \- a current directory of the input +.PP +For example, if a \f[C]filename\f[] param is +\f[C]\&../something.conf\f[] then the variables will have the following +values: +.IP \[bu] 2 +\f[C]$FILENAME\f[] \- "../something.conf" +.IP \[bu] 2 +\f[C]$CURDIR\f[] \- ".." +.PP +if \f[C]need_expand\f[] parameter is \f[C]true\f[] then all relative +paths are expanded using \f[C]realpath\f[] call. +In this example if \f[C]\&..\f[] is \f[C]/etc/dir\f[] then variables +will have these values: +.IP \[bu] 2 +\f[C]$FILENAME\f[] \- "/etc/something.conf" +.IP \[bu] 2 +\f[C]$CURDIR\f[] \- "/etc" +.SS Parser usage example +.PP +The following example loads, parses and extracts \f[C]ucl\f[] object +from stdin using \f[C]libucl\f[] parser functions (the length of input +is limited to 8K): +.IP +.nf +\f[C] +char\ inbuf[8192]; +struct\ ucl_parser\ *parser\ =\ NULL; +int\ ret\ =\ 0,\ r\ =\ 0; +ucl_object_t\ *obj\ =\ NULL; +FILE\ *in; + +in\ =\ stdin; +parser\ =\ ucl_parser_new\ (0); +while\ (!feof\ (in)\ &&\ r\ <\ (int)sizeof\ (inbuf))\ { +\ \ \ \ r\ +=\ fread\ (inbuf\ +\ r,\ 1,\ sizeof\ (inbuf)\ \-\ r,\ in); +} +ucl_parser_add_chunk\ (parser,\ inbuf,\ r); +fclose\ (in); + +if\ (ucl_parser_get_error\ (parser))\ { +\ \ \ \ printf\ ("Error\ occured:\ %s\\n",\ ucl_parser_get_error\ (parser)); +\ \ \ \ ret\ =\ 1; +} +else\ { +\ \ \ \ obj\ =\ ucl_parser_get_object\ (parser); +} + +if\ (parser\ !=\ NULL)\ { +\ \ \ \ ucl_parser_free\ (parser); +} +if\ (obj\ !=\ NULL)\ { +\ \ \ \ ucl_object_unref\ (obj); +} +return\ ret; +\f[] +.fi +.SH EMITTING FUNCTIONS +.PP +Libucl can transform UCL objects to a number of tectual formats: +.IP \[bu] 2 +configuration (\f[C]UCL_EMIT_CONFIG\f[]) \- nginx like human readable +configuration file where implicit arrays are transformed to the +duplicate keys +.IP \[bu] 2 +compact json: \f[C]UCL_EMIT_JSON_COMPACT\f[] \- single line valid json +without spaces +.IP \[bu] 2 +formatted json: \f[C]UCL_EMIT_JSON\f[] \- pretty formatted JSON with +newlines and spaces +.IP \[bu] 2 +compact yaml: \f[C]UCL_EMIT_YAML\f[] \- compact YAML output +.PP +Moreover, libucl API allows to select a custom set of emitting functions +allowing efficent and zero\-copy output of libucl objects. +Libucl uses the following structure to support this feature: +.IP +.nf +\f[C] +struct\ ucl_emitter_functions\ { +\ \ \ \ /**\ Append\ a\ single\ character\ */ +\ \ \ \ int\ (*ucl_emitter_append_character)\ (unsigned\ char\ c,\ size_t\ nchars,\ void\ *ud); +\ \ \ \ /**\ Append\ a\ string\ of\ a\ specified\ length\ */ +\ \ \ \ int\ (*ucl_emitter_append_len)\ (unsigned\ const\ char\ *str,\ size_t\ len,\ void\ *ud); +\ \ \ \ /**\ Append\ a\ 64\ bit\ integer\ */ +\ \ \ \ int\ (*ucl_emitter_append_int)\ (int64_t\ elt,\ void\ *ud); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***