diff --git a/Makefile b/Makefile index 6fd823111c10..a22e04389de5 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ # check-old-dirs - List obsolete directories. # check-old-files - List obsolete files. # check-old-libs - List obsolete libraries. -# delete-old - Delete obsolete directories/files/libraries. +# delete-old - Delete obsolete directories/files. # delete-old-dirs - Delete obsolete directories. # delete-old-files - Delete obsolete files. # delete-old-libs - Delete obsolete libraries. diff --git a/UPDATING b/UPDATING index 9a7699be854d..9da1e29ed092 100644 --- a/UPDATING +++ b/UPDATING @@ -22,6 +22,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW: machines to maximize performance. (To disable malloc debugging, run ln -s aj /etc/malloc.conf.) +20120211: + The getifaddrs upgrade path broken with 20111215 has been restored. + If you have upgraded in between 20111215 and 20120209 you need to + recompile libc again with your kernel. You still need to recompile + world to be able to configure CARP but this restriction already + comes from 20111215. + 20120114: The set_rcvar() function has been removed from /etc/rc.subr. All base and ports rc.d scripts have been updated, so if you have a diff --git a/bin/sh/eval.c b/bin/sh/eval.c index a5f0aff21b3b..2d90921aa206 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -921,6 +921,15 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) if (pipe(pip) < 0) error("Pipe call failed: %s", strerror(errno)); } + if (cmdentry.cmdtype == CMDNORMAL && + cmd->ncmd.redirect == NULL && + varlist.list == NULL && + (mode == FORK_FG || mode == FORK_NOJOB) && + !disvforkset() && !iflag && !mflag) { + vforkexecshell(jp, argv, environment(), path, + cmdentry.u.index, flags & EV_BACKCMD ? pip : NULL); + goto parent; + } if (forkshell(jp, cmd, mode) != 0) goto parent; /* at end of routine */ if (flags & EV_BACKCMD) { diff --git a/bin/sh/exec.c b/bin/sh/exec.c index 82cb3ac9e1a3..f2e4c1db75ec 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -231,7 +231,9 @@ hashcmd(int argc __unused, char **argv __unused) int verbose; struct cmdentry entry; char *name; + int errors; + errors = 0; verbose = 0; while ((c = nextopt("rv")) != '\0') { if (c == 'r') { @@ -254,19 +256,21 @@ hashcmd(int argc __unused, char **argv __unused) && cmdp->cmdtype == CMDNORMAL) delete_cmd_entry(); find_command(name, &entry, DO_ERR, pathval()); - if (verbose) { - if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */ - cmdp = cmdlookup(name, 0); - if (cmdp != NULL) - printentry(cmdp, verbose); - else - outfmt(out2, "%s: not found\n", name); + if (entry.cmdtype == CMDUNKNOWN) + errors = 1; + else if (verbose) { + cmdp = cmdlookup(name, 0); + if (cmdp != NULL) + printentry(cmdp, verbose); + else { + outfmt(out2, "%s: not found\n", name); + errors = 1; } flushall(); } argptr++; } - return 0; + return errors; } diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 232be8bf959f..335d2caf80c6 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #undef CEOF /* syntax.h redefines this */ #endif #include "redir.h" +#include "exec.h" #include "show.h" #include "main.h" #include "parser.h" @@ -885,6 +886,54 @@ forkshell(struct job *jp, union node *n, int mode) } +pid_t +vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int idx, int pip[2]) +{ + pid_t pid; + struct jmploc jmploc; + struct jmploc *savehandler; + + TRACE(("vforkexecshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n, + mode)); + INTOFF; + flushall(); + savehandler = handler; + pid = vfork(); + if (pid == -1) { + TRACE(("Vfork failed, errno=%d\n", errno)); + INTON; + error("Cannot fork: %s", strerror(errno)); + } + if (pid == 0) { + TRACE(("Child shell %d\n", (int)getpid())); + if (setjmp(jmploc.loc)) + _exit(exception == EXEXEC ? exerrno : 2); + if (pip != NULL) { + close(pip[0]); + if (pip[1] != 1) { + dup2(pip[1], 1); + close(pip[1]); + } + } + handler = &jmploc; + shellexec(argv, envp, path, idx); + } + handler = savehandler; + if (jp) { + struct procstat *ps = &jp->ps[jp->nprocs++]; + ps->pid = pid; + ps->status = -1; + ps->cmd = nullstr; + jp->foreground = 1; +#if JOBS + setcurjob(jp); +#endif + } + INTON; + TRACE(("In parent shell: child = %d\n", (int)pid)); + return pid; +} + /* * Wait for job to finish. diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h index 5e9d70db0434..e741b2c0dfb1 100644 --- a/bin/sh/jobs.h +++ b/bin/sh/jobs.h @@ -91,6 +91,7 @@ void setjobctl(int); void showjobs(int, int); struct job *makejob(union node *, int); pid_t forkshell(struct job *, union node *, int); +pid_t vforkexecshell(struct job *, char **, char **, const char *, int, int []); int waitforjob(struct job *, int *); int stoppedjobs(void); int backgndpidset(void); diff --git a/bin/sh/var.c b/bin/sh/var.c index b3bc6f7fdf8f..6041459e6864 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -94,6 +94,7 @@ struct var vps2; struct var vps4; struct var vvers; static struct var voptind; +struct var vdisvfork; int forcelocal; @@ -125,6 +126,8 @@ static const struct varinit varinit[] = { #endif { &voptind, 0, "OPTIND=1", getoptsreset }, + { &vdisvfork, VUNSET, "SH_DISABLE_VFORK=", + NULL }, { NULL, 0, NULL, NULL } }; @@ -600,7 +603,7 @@ showvarscmd(int argc __unused, char **argv __unused) } } - INTON; + INTOFF; vars = ckmalloc(n * sizeof(*vars)); i = 0; for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) { @@ -625,7 +628,7 @@ showvarscmd(int argc __unused, char **argv __unused) out1c('\n'); } ckfree(vars); - INTOFF; + INTON; return 0; } diff --git a/bin/sh/var.h b/bin/sh/var.h index 347c3777c36d..6cdfbfec9841 100644 --- a/bin/sh/var.h +++ b/bin/sh/var.h @@ -79,6 +79,7 @@ extern struct var vppid; extern struct var vps1; extern struct var vps2; extern struct var vps4; +extern struct var vdisvfork; #ifndef NO_HISTORY extern struct var vhistsize; extern struct var vterm; @@ -109,6 +110,7 @@ extern int initial_localeisutf8; #endif #define mpathset() ((vmpath.flags & VUNSET) == 0) +#define disvforkset() ((vdisvfork.flags & VUNSET) == 0) void initvar(void); void setvar(const char *, const char *, int); diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c index 27d882e1cc4f..30434cc67fd7 100644 --- a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c +++ b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c @@ -590,7 +590,7 @@ zfs_do_clone(int argc, char **argv) zfs_handle_t *zhp = NULL; boolean_t parents = B_FALSE; nvlist_t *props; - int ret; + int ret = 0; int c; if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) @@ -1052,7 +1052,7 @@ destroy_print_cb(zfs_handle_t *zhp, void *arg) static int destroy_print_snapshots(zfs_handle_t *fs_zhp, destroy_cbdata_t *cb) { - int err; + int err = 0; assert(cb->cb_firstsnap == NULL); assert(cb->cb_prevsnap == NULL); err = zfs_iter_snapshots_sorted(fs_zhp, destroy_print_cb, cb); @@ -1130,7 +1130,7 @@ destroy_clones(destroy_cbdata_t *cb) ZFS_TYPE_SNAPSHOT); if (zhp != NULL) { boolean_t defer = cb->cb_defer_destroy; - int err; + int err = 0; /* * We can't defer destroy non-snapshots, so set it to @@ -1207,7 +1207,7 @@ zfs_do_destroy(int argc, char **argv) at = strchr(argv[0], '@'); if (at != NULL) { - int err; + int err = 0; /* Build the list of snaps to destroy in cb_nvl. */ if (nvlist_alloc(&cb.cb_nvl, NV_UNIQUE_NAME, 0) != 0) @@ -1474,7 +1474,7 @@ zfs_do_get(int argc, char **argv) zprop_get_cbdata_t cb = { 0 }; int i, c, flags = ZFS_ITER_ARGS_CAN_BE_PATHS; char *value, *fields; - int ret; + int ret = 0; int limit = 0; zprop_list_t fake_name = { 0 }; @@ -1711,7 +1711,7 @@ zfs_do_inherit(int argc, char **argv) zfs_prop_t prop; inherit_cbdata_t cb = { 0 }; char *propname; - int ret; + int ret = 0; int flags = 0; boolean_t received = B_FALSE; @@ -1917,7 +1917,7 @@ zfs_do_upgrade(int argc, char **argv) { boolean_t all = B_FALSE; boolean_t showversions = B_FALSE; - int ret; + int ret = 0; upgrade_cbdata_t cb = { 0 }; char c; int flags = ZFS_ITER_ARGS_CAN_BE_PATHS; @@ -2206,7 +2206,7 @@ userspace_cb(void *arg, const char *domain, uid_t rid, uint64_t space) uid_t id; uint64_t classes; #ifdef sun - int err; + int err = 0; directory_error_t e; #endif @@ -2562,7 +2562,7 @@ zfs_do_userspace(int argc, char **argv) boolean_t prtnum = B_FALSE; boolean_t parseable = B_FALSE; boolean_t sid2posix = B_FALSE; - int error; + int error = 0; int c; zfs_sort_column_t *default_sortcol = NULL; zfs_sort_column_t *sortcol = NULL; @@ -2925,7 +2925,7 @@ zfs_do_list(int argc, char **argv) list_cbdata_t cb = { 0 }; char *value; int limit = 0; - int ret; + int ret = 0; zfs_sort_column_t *sortcol = NULL; int flags = ZFS_ITER_PROP_LISTSNAPS | ZFS_ITER_ARGS_CAN_BE_PATHS; @@ -3062,7 +3062,9 @@ zfs_do_rename(int argc, char **argv) { zfs_handle_t *zhp; renameflags_t flags = { 0 }; - int c, ret, types; + int c; + int ret = 0; + int types; boolean_t parents = B_FALSE; /* check options */ @@ -3155,7 +3157,7 @@ static int zfs_do_promote(int argc, char **argv) { zfs_handle_t *zhp; - int ret; + int ret = 0; /* check options */ if (argc > 1 && argv[1][0] == '-') { @@ -3276,7 +3278,7 @@ rollback_check(zfs_handle_t *zhp, void *data) static int zfs_do_rollback(int argc, char **argv) { - int ret; + int ret = 0; int c; boolean_t force = B_FALSE; rollback_cbdata_t cb = { 0 }; @@ -3394,7 +3396,7 @@ static int zfs_do_set(int argc, char **argv) { set_cbdata_t cb; - int ret; + int ret = 0; /* check for options */ if (argc > 1 && argv[1][0] == '-') { @@ -3448,7 +3450,7 @@ static int zfs_do_snapshot(int argc, char **argv) { boolean_t recursive = B_FALSE; - int ret; + int ret = 0; char c; nvlist_t *props; @@ -5286,7 +5288,7 @@ zfs_do_holds(int argc, char **argv) holds_cbdata_t cb = { 0 }; int limit = 0; - int ret; + int ret = 0; int flags = 0; /* check options */ @@ -5863,7 +5865,7 @@ static int unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual) { zfs_handle_t *zhp; - int ret; + int ret = 0; struct stat64 statbuf; struct extmnttab entry; const char *cmdname = (op == OP_SHARE) ? "unshare" : "unmount"; @@ -6331,7 +6333,7 @@ manual_mount(int argc, char **argv) zfs_handle_t *zhp; char mountpoint[ZFS_MAXPROPLEN]; char mntopts[MNT_LINE_MAX] = { '\0' }; - int ret; + int ret = 0; int c; int flags = 0; char *dataset, *path; @@ -6481,7 +6483,7 @@ zfs_do_diff(int argc, char **argv) char *tosnap = NULL; char *fromsnap = NULL; char *atp, *copy; - int err; + int err = 0; int c; while ((c = getopt(argc, argv, "FHt")) != -1) { @@ -6551,7 +6553,7 @@ zfs_do_diff(int argc, char **argv) int main(int argc, char **argv) { - int ret; + int ret = 0; int i; char *progname; char *cmdname; diff --git a/contrib/gcc/gcc.c b/contrib/gcc/gcc.c index ddf2f49205e6..e88dc53a855b 100644 --- a/contrib/gcc/gcc.c +++ b/contrib/gcc/gcc.c @@ -2696,6 +2696,17 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode, return xstrdup (DEFAULT_LINKER); #endif +#ifdef FREEBSD_NATIVE + if (! strcmp(name, "include")) + { +#ifdef CROSS_INCLUDE_DIR + return xstrdup(CROSS_INCLUDE_DIR); +#else + return xstrdup(STANDARD_INCLUDE_DIR); +#endif + } +#endif + /* Determine the filename to execute (special case for absolute paths). */ if (IS_ABSOLUTE_PATH (name)) diff --git a/contrib/llvm/tools/bugpoint/BugDriver.cpp b/contrib/llvm/tools/bugpoint/BugDriver.cpp new file mode 100644 index 000000000000..677d17887f40 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/BugDriver.cpp @@ -0,0 +1,247 @@ +//===- BugDriver.cpp - Top-Level BugPoint class implementation ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class contains all of the shared state and information that is used by +// the BugPoint tool to track down errors in optimizations. This class is the +// main driver class that invokes all sub-functionality. +// +//===----------------------------------------------------------------------===// + +#include "BugDriver.h" +#include "ToolRunner.h" +#include "llvm/Linker.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/IRReader.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Host.h" +#include +using namespace llvm; + +namespace llvm { + Triple TargetTriple; +} + +// Anonymous namespace to define command line options for debugging. +// +namespace { + // Output - The user can specify a file containing the expected output of the + // program. If this filename is set, it is used as the reference diff source, + // otherwise the raw input run through an interpreter is used as the reference + // source. + // + cl::opt + OutputFile("output", cl::desc("Specify a reference program output " + "(for miscompilation detection)")); +} + +/// setNewProgram - If we reduce or update the program somehow, call this method +/// to update bugdriver with it. This deletes the old module and sets the +/// specified one as the current program. +void BugDriver::setNewProgram(Module *M) { + delete Program; + Program = M; +} + + +/// getPassesString - Turn a list of passes into a string which indicates the +/// command line options that must be passed to add the passes. +/// +std::string llvm::getPassesString(const std::vector &Passes) { + std::string Result; + for (unsigned i = 0, e = Passes.size(); i != e; ++i) { + if (i) Result += " "; + Result += "-"; + Result += Passes[i]; + } + return Result; +} + +BugDriver::BugDriver(const char *toolname, bool find_bugs, + unsigned timeout, unsigned memlimit, bool use_valgrind, + LLVMContext& ctxt) + : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), + Program(0), Interpreter(0), SafeInterpreter(0), gcc(0), + run_find_bugs(find_bugs), Timeout(timeout), + MemoryLimit(memlimit), UseValgrind(use_valgrind) {} + +BugDriver::~BugDriver() { + delete Program; +} + + +/// ParseInputFile - Given a bitcode or assembly input filename, parse and +/// return it, or return null if not possible. +/// +Module *llvm::ParseInputFile(const std::string &Filename, + LLVMContext& Ctxt) { + SMDiagnostic Err; + Module *Result = ParseIRFile(Filename, Err, Ctxt); + if (!Result) + Err.Print("bugpoint", errs()); + + // If we don't have an override triple, use the first one to configure + // bugpoint, or use the host triple if none provided. + if (Result) { + if (TargetTriple.getTriple().empty()) { + Triple TheTriple(Result->getTargetTriple()); + + if (TheTriple.getTriple().empty()) + TheTriple.setTriple(sys::getHostTriple()); + + TargetTriple.setTriple(TheTriple.getTriple()); + } + + Result->setTargetTriple(TargetTriple.getTriple()); // override the triple + } + return Result; +} + +// This method takes the specified list of LLVM input files, attempts to load +// them, either as assembly or bitcode, then link them together. It returns +// true on failure (if, for example, an input bitcode file could not be +// parsed), and false on success. +// +bool BugDriver::addSources(const std::vector &Filenames) { + assert(Program == 0 && "Cannot call addSources multiple times!"); + assert(!Filenames.empty() && "Must specify at least on input filename!"); + + // Load the first input file. + Program = ParseInputFile(Filenames[0], Context); + if (Program == 0) return true; + + outs() << "Read input file : '" << Filenames[0] << "'\n"; + + for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { + std::auto_ptr M(ParseInputFile(Filenames[i], Context)); + if (M.get() == 0) return true; + + outs() << "Linking in input file: '" << Filenames[i] << "'\n"; + std::string ErrorMessage; + if (Linker::LinkModules(Program, M.get(), Linker::DestroySource, + &ErrorMessage)) { + errs() << ToolName << ": error linking in '" << Filenames[i] << "': " + << ErrorMessage << '\n'; + return true; + } + } + + outs() << "*** All input ok\n"; + + // All input files read successfully! + return false; +} + + + +/// run - The top level method that is invoked after all of the instance +/// variables are set up from command line arguments. +/// +bool BugDriver::run(std::string &ErrMsg) { + if (run_find_bugs) { + // Rearrange the passes and apply them to the program. Repeat this process + // until the user kills the program or we find a bug. + return runManyPasses(PassesToRun, ErrMsg); + } + + // If we're not running as a child, the first thing that we must do is + // determine what the problem is. Does the optimization series crash the + // compiler, or does it produce illegal code? We make the top-level + // decision by trying to run all of the passes on the the input program, + // which should generate a bitcode file. If it does generate a bitcode + // file, then we know the compiler didn't crash, so try to diagnose a + // miscompilation. + if (!PassesToRun.empty()) { + outs() << "Running selected passes on program to test for crash: "; + if (runPasses(Program, PassesToRun)) + return debugOptimizerCrash(); + } + + // Set up the execution environment, selecting a method to run LLVM bitcode. + if (initializeExecutionEnvironment()) return true; + + // Test to see if we have a code generator crash. + outs() << "Running the code generator to test for a crash: "; + std::string Error; + compileProgram(Program, &Error); + if (!Error.empty()) { + outs() << Error; + return debugCodeGeneratorCrash(ErrMsg); + } + outs() << '\n'; + + // Run the raw input to see where we are coming from. If a reference output + // was specified, make sure that the raw output matches it. If not, it's a + // problem in the front-end or the code generator. + // + bool CreatedOutput = false; + if (ReferenceOutputFile.empty()) { + outs() << "Generating reference output from raw program: "; + if (!createReferenceFile(Program)) { + return debugCodeGeneratorCrash(ErrMsg); + } + CreatedOutput = true; + } + + // Make sure the reference output file gets deleted on exit from this + // function, if appropriate. + sys::Path ROF(ReferenceOutputFile); + FileRemover RemoverInstance(ROF.str(), CreatedOutput && !SaveTemps); + + // Diff the output of the raw program against the reference output. If it + // matches, then we assume there is a miscompilation bug and try to + // diagnose it. + outs() << "*** Checking the code generator...\n"; + bool Diff = diffProgram(Program, "", "", false, &Error); + if (!Error.empty()) { + errs() << Error; + return debugCodeGeneratorCrash(ErrMsg); + } + if (!Diff) { + outs() << "\n*** Output matches: Debugging miscompilation!\n"; + debugMiscompilation(&Error); + if (!Error.empty()) { + errs() << Error; + return debugCodeGeneratorCrash(ErrMsg); + } + return false; + } + + outs() << "\n*** Input program does not match reference diff!\n"; + outs() << "Debugging code generator problem!\n"; + bool Failure = debugCodeGenerator(&Error); + if (!Error.empty()) { + errs() << Error; + return debugCodeGeneratorCrash(ErrMsg); + } + return Failure; +} + +void llvm::PrintFunctionList(const std::vector &Funcs) { + unsigned NumPrint = Funcs.size(); + if (NumPrint > 10) NumPrint = 10; + for (unsigned i = 0; i != NumPrint; ++i) + outs() << " " << Funcs[i]->getName(); + if (NumPrint < Funcs.size()) + outs() << "... <" << Funcs.size() << " total>"; + outs().flush(); +} + +void llvm::PrintGlobalVariableList(const std::vector &GVs) { + unsigned NumPrint = GVs.size(); + if (NumPrint > 10) NumPrint = 10; + for (unsigned i = 0; i != NumPrint; ++i) + outs() << " " << GVs[i]->getName(); + if (NumPrint < GVs.size()) + outs() << "... <" << GVs.size() << " total>"; + outs().flush(); +} diff --git a/contrib/llvm/tools/bugpoint/BugDriver.h b/contrib/llvm/tools/bugpoint/BugDriver.h new file mode 100644 index 000000000000..cc78489e3d90 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/BugDriver.h @@ -0,0 +1,330 @@ +//===- BugDriver.h - Top-Level BugPoint class -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class contains all of the shared state and information that is used by +// the BugPoint tool to track down errors in optimizations. This class is the +// main driver class that invokes all sub-functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef BUGDRIVER_H +#define BUGDRIVER_H + +#include "llvm/ADT/ValueMap.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +#include +#include + +namespace llvm { + +class Value; +class PassInfo; +class Module; +class GlobalVariable; +class Function; +class BasicBlock; +class AbstractInterpreter; +class Instruction; +class LLVMContext; + +class DebugCrashes; + +class GCC; + +extern bool DisableSimplifyCFG; + +/// BugpointIsInterrupted - Set to true when the user presses ctrl-c. +/// +extern bool BugpointIsInterrupted; + +class BugDriver { + LLVMContext& Context; + const char *ToolName; // argv[0] of bugpoint + std::string ReferenceOutputFile; // Name of `good' output file + Module *Program; // The raw program, linked together + std::vector PassesToRun; + AbstractInterpreter *Interpreter; // How to run the program + AbstractInterpreter *SafeInterpreter; // To generate reference output, etc. + GCC *gcc; + bool run_find_bugs; + unsigned Timeout; + unsigned MemoryLimit; + bool UseValgrind; + + // FIXME: sort out public/private distinctions... + friend class ReducePassList; + friend class ReduceMisCodegenFunctions; + +public: + BugDriver(const char *toolname, bool find_bugs, + unsigned timeout, unsigned memlimit, bool use_valgrind, + LLVMContext& ctxt); + ~BugDriver(); + + const char *getToolName() const { return ToolName; } + + LLVMContext& getContext() const { return Context; } + + // Set up methods... these methods are used to copy information about the + // command line arguments into instance variables of BugDriver. + // + bool addSources(const std::vector &FileNames); + void addPass(std::string p) { PassesToRun.push_back(p); } + void setPassesToRun(const std::vector &PTR) { + PassesToRun = PTR; + } + const std::vector &getPassesToRun() const { + return PassesToRun; + } + + /// run - The top level method that is invoked after all of the instance + /// variables are set up from command line arguments. The \p as_child argument + /// indicates whether the driver is to run in parent mode or child mode. + /// + bool run(std::string &ErrMsg); + + /// debugOptimizerCrash - This method is called when some optimizer pass + /// crashes on input. It attempts to prune down the testcase to something + /// reasonable, and figure out exactly which pass is crashing. + /// + bool debugOptimizerCrash(const std::string &ID = "passes"); + + /// debugCodeGeneratorCrash - This method is called when the code generator + /// crashes on an input. It attempts to reduce the input as much as possible + /// while still causing the code generator to crash. + bool debugCodeGeneratorCrash(std::string &Error); + + /// debugMiscompilation - This method is used when the passes selected are not + /// crashing, but the generated output is semantically different from the + /// input. + void debugMiscompilation(std::string *Error); + + /// debugPassMiscompilation - This method is called when the specified pass + /// miscompiles Program as input. It tries to reduce the testcase to + /// something that smaller that still miscompiles the program. + /// ReferenceOutput contains the filename of the file containing the output we + /// are to match. + /// + bool debugPassMiscompilation(const PassInfo *ThePass, + const std::string &ReferenceOutput); + + /// compileSharedObject - This method creates a SharedObject from a given + /// BitcodeFile for debugging a code generator. + /// + std::string compileSharedObject(const std::string &BitcodeFile, + std::string &Error); + + /// debugCodeGenerator - This method narrows down a module to a function or + /// set of functions, using the CBE as a ``safe'' code generator for other + /// functions that are not under consideration. + bool debugCodeGenerator(std::string *Error); + + /// isExecutingJIT - Returns true if bugpoint is currently testing the JIT + /// + bool isExecutingJIT(); + + /// runPasses - Run all of the passes in the "PassesToRun" list, discard the + /// output, and return true if any of the passes crashed. + bool runPasses(Module *M) const { + return runPasses(M, PassesToRun); + } + + Module *getProgram() const { return Program; } + + /// swapProgramIn - Set the current module to the specified module, returning + /// the old one. + Module *swapProgramIn(Module *M) { + Module *OldProgram = Program; + Program = M; + return OldProgram; + } + + AbstractInterpreter *switchToSafeInterpreter() { + AbstractInterpreter *Old = Interpreter; + Interpreter = (AbstractInterpreter*)SafeInterpreter; + return Old; + } + + void switchToInterpreter(AbstractInterpreter *AI) { + Interpreter = AI; + } + + /// setNewProgram - If we reduce or update the program somehow, call this + /// method to update bugdriver with it. This deletes the old module and sets + /// the specified one as the current program. + void setNewProgram(Module *M); + + /// compileProgram - Try to compile the specified module, returning false and + /// setting Error if an error occurs. This is used for code generation + /// crash testing. + /// + void compileProgram(Module *M, std::string *Error) const; + + /// executeProgram - This method runs "Program", capturing the output of the + /// program to a file. A recommended filename may be optionally specified. + /// + std::string executeProgram(const Module *Program, + std::string OutputFilename, + std::string Bitcode, + const std::string &SharedObjects, + AbstractInterpreter *AI, + std::string *Error) const; + + /// executeProgramSafely - Used to create reference output with the "safe" + /// backend, if reference output is not provided. If there is a problem with + /// the code generator (e.g., llc crashes), this will return false and set + /// Error. + /// + std::string executeProgramSafely(const Module *Program, + std::string OutputFile, + std::string *Error) const; + + /// createReferenceFile - calls compileProgram and then records the output + /// into ReferenceOutputFile. Returns true if reference file created, false + /// otherwise. Note: initializeExecutionEnvironment should be called BEFORE + /// this function. + /// + bool createReferenceFile(Module *M, const std::string &Filename + = "bugpoint.reference.out"); + + /// diffProgram - This method executes the specified module and diffs the + /// output against the file specified by ReferenceOutputFile. If the output + /// is different, 1 is returned. If there is a problem with the code + /// generator (e.g., llc crashes), this will return -1 and set Error. + /// + bool diffProgram(const Module *Program, + const std::string &BitcodeFile = "", + const std::string &SharedObj = "", + bool RemoveBitcode = false, + std::string *Error = 0) const; + + /// EmitProgressBitcode - This function is used to output M to a file named + /// "bugpoint-ID.bc". + /// + void EmitProgressBitcode(const Module *M, const std::string &ID, + bool NoFlyer = false) const; + + /// deleteInstructionFromProgram - This method clones the current Program and + /// deletes the specified instruction from the cloned module. It then runs a + /// series of cleanup passes (ADCE and SimplifyCFG) to eliminate any code + /// which depends on the value. The modified module is then returned. + /// + Module *deleteInstructionFromProgram(const Instruction *I, unsigned Simp); + + /// performFinalCleanups - This method clones the current Program and performs + /// a series of cleanups intended to get rid of extra cruft on the module. If + /// the MayModifySemantics argument is true, then the cleanups is allowed to + /// modify how the code behaves. + /// + Module *performFinalCleanups(Module *M, bool MayModifySemantics = false); + + /// ExtractLoop - Given a module, extract up to one loop from it into a new + /// function. This returns null if there are no extractable loops in the + /// program or if the loop extractor crashes. + Module *ExtractLoop(Module *M); + + /// ExtractMappedBlocksFromModule - Extract all but the specified basic blocks + /// into their own functions. The only detail is that M is actually a module + /// cloned from the one the BBs are in, so some mapping needs to be performed. + /// If this operation fails for some reason (ie the implementation is buggy), + /// this function should return null, otherwise it returns a new Module. + Module *ExtractMappedBlocksFromModule(const std::vector &BBs, + Module *M); + + /// runPassesOn - Carefully run the specified set of pass on the specified + /// module, returning the transformed module on success, or a null pointer on + /// failure. If AutoDebugCrashes is set to true, then bugpoint will + /// automatically attempt to track down a crashing pass if one exists, and + /// this method will never return null. + Module *runPassesOn(Module *M, const std::vector &Passes, + bool AutoDebugCrashes = false, unsigned NumExtraArgs = 0, + const char * const *ExtraArgs = NULL); + + /// runPasses - Run the specified passes on Program, outputting a bitcode + /// file and writting the filename into OutputFile if successful. If the + /// optimizations fail for some reason (optimizer crashes), return true, + /// otherwise return false. If DeleteOutput is set to true, the bitcode is + /// deleted on success, and the filename string is undefined. This prints to + /// outs() a single line message indicating whether compilation was successful + /// or failed, unless Quiet is set. ExtraArgs specifies additional arguments + /// to pass to the child bugpoint instance. + /// + bool runPasses(Module *Program, + const std::vector &PassesToRun, + std::string &OutputFilename, bool DeleteOutput = false, + bool Quiet = false, unsigned NumExtraArgs = 0, + const char * const *ExtraArgs = NULL) const; + + /// runManyPasses - Take the specified pass list and create different + /// combinations of passes to compile the program with. Compile the program with + /// each set and mark test to see if it compiled correctly. If the passes + /// compiled correctly output nothing and rearrange the passes into a new order. + /// If the passes did not compile correctly, output the command required to + /// recreate the failure. This returns true if a compiler error is found. + /// + bool runManyPasses(const std::vector &AllPasses, + std::string &ErrMsg); + + /// writeProgramToFile - This writes the current "Program" to the named + /// bitcode file. If an error occurs, true is returned. + /// + bool writeProgramToFile(const std::string &Filename, const Module *M) const; + +private: + /// runPasses - Just like the method above, but this just returns true or + /// false indicating whether or not the optimizer crashed on the specified + /// input (true = crashed). + /// + bool runPasses(Module *M, + const std::vector &PassesToRun, + bool DeleteOutput = true) const { + std::string Filename; + return runPasses(M, PassesToRun, Filename, DeleteOutput); + } + + /// initializeExecutionEnvironment - This method is used to set up the + /// environment for executing LLVM programs. + /// + bool initializeExecutionEnvironment(); +}; + +/// ParseInputFile - Given a bitcode or assembly input filename, parse and +/// return it, or return null if not possible. +/// +Module *ParseInputFile(const std::string &InputFilename, + LLVMContext& ctxt); + + +/// getPassesString - Turn a list of passes into a string which indicates the +/// command line options that must be passed to add the passes. +/// +std::string getPassesString(const std::vector &Passes); + +/// PrintFunctionList - prints out list of problematic functions +/// +void PrintFunctionList(const std::vector &Funcs); + +/// PrintGlobalVariableList - prints out list of problematic global variables +/// +void PrintGlobalVariableList(const std::vector &GVs); + +// DeleteFunctionBody - "Remove" the function by deleting all of it's basic +// blocks, making it external. +// +void DeleteFunctionBody(Function *F); + +/// SplitFunctionsOutOfModule - Given a module and a list of functions in the +/// module, split the functions OUT of the specified module, and place them in +/// the new module. +Module *SplitFunctionsOutOfModule(Module *M, const std::vector &F, + ValueToValueMapTy &VMap); + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/tools/bugpoint/CMakeLists.txt b/contrib/llvm/tools/bugpoint/CMakeLists.txt new file mode 100644 index 000000000000..e06feb100312 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS asmparser instrumentation scalaropts ipo + linker bitreader bitwriter) + +add_llvm_tool(bugpoint + BugDriver.cpp + CrashDebugger.cpp + ExecutionDriver.cpp + ExtractFunction.cpp + FindBugs.cpp + Miscompilation.cpp + OptimizerDriver.cpp + ToolRunner.cpp + bugpoint.cpp + ) diff --git a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp new file mode 100644 index 000000000000..f19ef6222f56 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp @@ -0,0 +1,667 @@ +//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the bugpoint internals that narrow down compilation crashes +// +//===----------------------------------------------------------------------===// + +#include "BugDriver.h" +#include "ToolRunner.h" +#include "ListReducer.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/PassManager.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Support/CFG.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/CommandLine.h" +#include +using namespace llvm; + +namespace { + cl::opt + KeepMain("keep-main", + cl::desc("Force function reduction to keep main"), + cl::init(false)); + cl::opt + NoGlobalRM ("disable-global-remove", + cl::desc("Do not remove global variables"), + cl::init(false)); +} + +namespace llvm { + class ReducePassList : public ListReducer { + BugDriver &BD; + public: + ReducePassList(BugDriver &bd) : BD(bd) {} + + // doTest - Return true iff running the "removed" passes succeeds, and + // running the "Kept" passes fail when run on the output of the "removed" + // passes. If we return true, we update the current module of bugpoint. + // + virtual TestResult doTest(std::vector &Removed, + std::vector &Kept, + std::string &Error); + }; +} + +ReducePassList::TestResult +ReducePassList::doTest(std::vector &Prefix, + std::vector &Suffix, + std::string &Error) { + sys::Path PrefixOutput; + Module *OrigProgram = 0; + if (!Prefix.empty()) { + outs() << "Checking to see if these passes crash: " + << getPassesString(Prefix) << ": "; + std::string PfxOutput; + if (BD.runPasses(BD.getProgram(), Prefix, PfxOutput)) + return KeepPrefix; + + PrefixOutput.set(PfxOutput); + OrigProgram = BD.Program; + + BD.Program = ParseInputFile(PrefixOutput.str(), BD.getContext()); + if (BD.Program == 0) { + errs() << BD.getToolName() << ": Error reading bitcode file '" + << PrefixOutput.str() << "'!\n"; + exit(1); + } + PrefixOutput.eraseFromDisk(); + } + + outs() << "Checking to see if these passes crash: " + << getPassesString(Suffix) << ": "; + + if (BD.runPasses(BD.getProgram(), Suffix)) { + delete OrigProgram; // The suffix crashes alone... + return KeepSuffix; + } + + // Nothing failed, restore state... + if (OrigProgram) { + delete BD.Program; + BD.Program = OrigProgram; + } + return NoFailure; +} + +namespace { + /// ReduceCrashingGlobalVariables - This works by removing the global + /// variable's initializer and seeing if the program still crashes. If it + /// does, then we keep that program and try again. + /// + class ReduceCrashingGlobalVariables : public ListReducer { + BugDriver &BD; + bool (*TestFn)(const BugDriver &, Module *); + public: + ReduceCrashingGlobalVariables(BugDriver &bd, + bool (*testFn)(const BugDriver &, Module *)) + : BD(bd), TestFn(testFn) {} + + virtual TestResult doTest(std::vector &Prefix, + std::vector &Kept, + std::string &Error) { + if (!Kept.empty() && TestGlobalVariables(Kept)) + return KeepSuffix; + if (!Prefix.empty() && TestGlobalVariables(Prefix)) + return KeepPrefix; + return NoFailure; + } + + bool TestGlobalVariables(std::vector &GVs); + }; +} + +bool +ReduceCrashingGlobalVariables::TestGlobalVariables( + std::vector &GVs) { + // Clone the program to try hacking it apart... + ValueToValueMapTy VMap; + Module *M = CloneModule(BD.getProgram(), VMap); + + // Convert list to set for fast lookup... + std::set GVSet; + + for (unsigned i = 0, e = GVs.size(); i != e; ++i) { + GlobalVariable* CMGV = cast(VMap[GVs[i]]); + assert(CMGV && "Global Variable not in module?!"); + GVSet.insert(CMGV); + } + + outs() << "Checking for crash with only these global variables: "; + PrintGlobalVariableList(GVs); + outs() << ": "; + + // Loop over and delete any global variables which we aren't supposed to be + // playing with... + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) + if (I->hasInitializer() && !GVSet.count(I)) { + I->setInitializer(0); + I->setLinkage(GlobalValue::ExternalLinkage); + } + + // Try running the hacked up program... + if (TestFn(BD, M)) { + BD.setNewProgram(M); // It crashed, keep the trimmed version... + + // Make sure to use global variable pointers that point into the now-current + // module. + GVs.assign(GVSet.begin(), GVSet.end()); + return true; + } + + delete M; + return false; +} + +namespace llvm { + /// ReduceCrashingFunctions reducer - This works by removing functions and + /// seeing if the program still crashes. If it does, then keep the newer, + /// smaller program. + /// + class ReduceCrashingFunctions : public ListReducer { + BugDriver &BD; + bool (*TestFn)(const BugDriver &, Module *); + public: + ReduceCrashingFunctions(BugDriver &bd, + bool (*testFn)(const BugDriver &, Module *)) + : BD(bd), TestFn(testFn) {} + + virtual TestResult doTest(std::vector &Prefix, + std::vector &Kept, + std::string &Error) { + if (!Kept.empty() && TestFuncs(Kept)) + return KeepSuffix; + if (!Prefix.empty() && TestFuncs(Prefix)) + return KeepPrefix; + return NoFailure; + } + + bool TestFuncs(std::vector &Prefix); + }; +} + +bool ReduceCrashingFunctions::TestFuncs(std::vector &Funcs) { + + //if main isn't present, claim there is no problem + if (KeepMain && find(Funcs.begin(), Funcs.end(), + BD.getProgram()->getFunction("main")) == Funcs.end()) + return false; + + // Clone the program to try hacking it apart... + ValueToValueMapTy VMap; + Module *M = CloneModule(BD.getProgram(), VMap); + + // Convert list to set for fast lookup... + std::set Functions; + for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { + Function *CMF = cast(VMap[Funcs[i]]); + assert(CMF && "Function not in module?!"); + assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty"); + assert(CMF->getName() == Funcs[i]->getName() && "wrong name"); + Functions.insert(CMF); + } + + outs() << "Checking for crash with only these functions: "; + PrintFunctionList(Funcs); + outs() << ": "; + + // Loop over and delete any functions which we aren't supposed to be playing + // with... + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + if (!I->isDeclaration() && !Functions.count(I)) + DeleteFunctionBody(I); + + // Try running the hacked up program... + if (TestFn(BD, M)) { + BD.setNewProgram(M); // It crashed, keep the trimmed version... + + // Make sure to use function pointers that point into the now-current + // module. + Funcs.assign(Functions.begin(), Functions.end()); + return true; + } + delete M; + return false; +} + + +namespace { + /// ReduceCrashingBlocks reducer - This works by setting the terminators of + /// all terminators except the specified basic blocks to a 'ret' instruction, + /// then running the simplify-cfg pass. This has the effect of chopping up + /// the CFG really fast which can reduce large functions quickly. + /// + class ReduceCrashingBlocks : public ListReducer { + BugDriver &BD; + bool (*TestFn)(const BugDriver &, Module *); + public: + ReduceCrashingBlocks(BugDriver &bd, + bool (*testFn)(const BugDriver &, Module *)) + : BD(bd), TestFn(testFn) {} + + virtual TestResult doTest(std::vector &Prefix, + std::vector &Kept, + std::string &Error) { + if (!Kept.empty() && TestBlocks(Kept)) + return KeepSuffix; + if (!Prefix.empty() && TestBlocks(Prefix)) + return KeepPrefix; + return NoFailure; + } + + bool TestBlocks(std::vector &Prefix); + }; +} + +bool ReduceCrashingBlocks::TestBlocks(std::vector &BBs) { + // Clone the program to try hacking it apart... + ValueToValueMapTy VMap; + Module *M = CloneModule(BD.getProgram(), VMap); + + // Convert list to set for fast lookup... + SmallPtrSet Blocks; + for (unsigned i = 0, e = BBs.size(); i != e; ++i) + Blocks.insert(cast(VMap[BBs[i]])); + + outs() << "Checking for crash with only these blocks:"; + unsigned NumPrint = Blocks.size(); + if (NumPrint > 10) NumPrint = 10; + for (unsigned i = 0, e = NumPrint; i != e; ++i) + outs() << " " << BBs[i]->getName(); + if (NumPrint < Blocks.size()) + outs() << "... <" << Blocks.size() << " total>"; + outs() << ": "; + + // Loop over and delete any hack up any blocks that are not listed... + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) + if (!Blocks.count(BB) && BB->getTerminator()->getNumSuccessors()) { + // Loop over all of the successors of this block, deleting any PHI nodes + // that might include it. + for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) + (*SI)->removePredecessor(BB); + + TerminatorInst *BBTerm = BB->getTerminator(); + + if (!BB->getTerminator()->getType()->isVoidTy()) + BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType())); + + // Replace the old terminator instruction. + BB->getInstList().pop_back(); + new UnreachableInst(BB->getContext(), BB); + } + + // The CFG Simplifier pass may delete one of the basic blocks we are + // interested in. If it does we need to take the block out of the list. Make + // a "persistent mapping" by turning basic blocks into pairs. + // This won't work well if blocks are unnamed, but that is just the risk we + // have to take. + std::vector > BlockInfo; + + for (SmallPtrSet::iterator I = Blocks.begin(), + E = Blocks.end(); I != E; ++I) + BlockInfo.push_back(std::make_pair((*I)->getParent()->getName(), + (*I)->getName())); + + // Now run the CFG simplify pass on the function... + std::vector Passes; + Passes.push_back("simplifycfg"); + Passes.push_back("verify"); + Module *New = BD.runPassesOn(M, Passes); + delete M; + if (!New) { + errs() << "simplifycfg failed!\n"; + exit(1); + } + M = New; + + // Try running on the hacked up program... + if (TestFn(BD, M)) { + BD.setNewProgram(M); // It crashed, keep the trimmed version... + + // Make sure to use basic block pointers that point into the now-current + // module, and that they don't include any deleted blocks. + BBs.clear(); + const ValueSymbolTable &GST = M->getValueSymbolTable(); + for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { + Function *F = cast(GST.lookup(BlockInfo[i].first)); + ValueSymbolTable &ST = F->getValueSymbolTable(); + Value* V = ST.lookup(BlockInfo[i].second); + if (V && V->getType() == Type::getLabelTy(V->getContext())) + BBs.push_back(cast(V)); + } + return true; + } + delete M; // It didn't crash, try something else. + return false; +} + +namespace { + /// ReduceCrashingInstructions reducer - This works by removing the specified + /// non-terminator instructions and replacing them with undef. + /// + class ReduceCrashingInstructions : public ListReducer { + BugDriver &BD; + bool (*TestFn)(const BugDriver &, Module *); + public: + ReduceCrashingInstructions(BugDriver &bd, + bool (*testFn)(const BugDriver &, Module *)) + : BD(bd), TestFn(testFn) {} + + virtual TestResult doTest(std::vector &Prefix, + std::vector &Kept, + std::string &Error) { + if (!Kept.empty() && TestInsts(Kept)) + return KeepSuffix; + if (!Prefix.empty() && TestInsts(Prefix)) + return KeepPrefix; + return NoFailure; + } + + bool TestInsts(std::vector &Prefix); + }; +} + +bool ReduceCrashingInstructions::TestInsts(std::vector + &Insts) { + // Clone the program to try hacking it apart... + ValueToValueMapTy VMap; + Module *M = CloneModule(BD.getProgram(), VMap); + + // Convert list to set for fast lookup... + SmallPtrSet Instructions; + for (unsigned i = 0, e = Insts.size(); i != e; ++i) { + assert(!isa(Insts[i])); + Instructions.insert(cast(VMap[Insts[i]])); + } + + outs() << "Checking for crash with only " << Instructions.size(); + if (Instructions.size() == 1) + outs() << " instruction: "; + else + outs() << " instructions: "; + + for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) + for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) + for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { + Instruction *Inst = I++; + if (!Instructions.count(Inst) && !isa(Inst)) { + if (!Inst->getType()->isVoidTy()) + Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); + Inst->eraseFromParent(); + } + } + + // Verify that this is still valid. + PassManager Passes; + Passes.add(createVerifierPass()); + Passes.run(*M); + + // Try running on the hacked up program... + if (TestFn(BD, M)) { + BD.setNewProgram(M); // It crashed, keep the trimmed version... + + // Make sure to use instruction pointers that point into the now-current + // module, and that they don't include any deleted blocks. + Insts.clear(); + for (SmallPtrSet::const_iterator I = Instructions.begin(), + E = Instructions.end(); I != E; ++I) + Insts.push_back(*I); + return true; + } + delete M; // It didn't crash, try something else. + return false; +} + +/// DebugACrash - Given a predicate that determines whether a component crashes +/// on a program, try to destructively reduce the program while still keeping +/// the predicate true. +static bool DebugACrash(BugDriver &BD, + bool (*TestFn)(const BugDriver &, Module *), + std::string &Error) { + // See if we can get away with nuking some of the global variable initializers + // in the program... + if (!NoGlobalRM && + BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { + // Now try to reduce the number of global variable initializers in the + // module to something small. + Module *M = CloneModule(BD.getProgram()); + bool DeletedInit = false; + + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) + if (I->hasInitializer()) { + I->setInitializer(0); + I->setLinkage(GlobalValue::ExternalLinkage); + DeletedInit = true; + } + + if (!DeletedInit) { + delete M; // No change made... + } else { + // See if the program still causes a crash... + outs() << "\nChecking to see if we can delete global inits: "; + + if (TestFn(BD, M)) { // Still crashes? + BD.setNewProgram(M); + outs() << "\n*** Able to remove all global initializers!\n"; + } else { // No longer crashes? + outs() << " - Removing all global inits hides problem!\n"; + delete M; + + std::vector GVs; + + for (Module::global_iterator I = BD.getProgram()->global_begin(), + E = BD.getProgram()->global_end(); I != E; ++I) + if (I->hasInitializer()) + GVs.push_back(I); + + if (GVs.size() > 1 && !BugpointIsInterrupted) { + outs() << "\n*** Attempting to reduce the number of global " + << "variables in the testcase\n"; + + unsigned OldSize = GVs.size(); + ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs, Error); + if (!Error.empty()) + return true; + + if (GVs.size() < OldSize) + BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables"); + } + } + } + } + + // Now try to reduce the number of functions in the module to something small. + std::vector Functions; + for (Module::iterator I = BD.getProgram()->begin(), + E = BD.getProgram()->end(); I != E; ++I) + if (!I->isDeclaration()) + Functions.push_back(I); + + if (Functions.size() > 1 && !BugpointIsInterrupted) { + outs() << "\n*** Attempting to reduce the number of functions " + "in the testcase\n"; + + unsigned OldSize = Functions.size(); + ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error); + + if (Functions.size() < OldSize) + BD.EmitProgressBitcode(BD.getProgram(), "reduced-function"); + } + + // Attempt to delete entire basic blocks at a time to speed up + // convergence... this actually works by setting the terminator of the blocks + // to a return instruction then running simplifycfg, which can potentially + // shrinks the code dramatically quickly + // + if (!DisableSimplifyCFG && !BugpointIsInterrupted) { + std::vector Blocks; + for (Module::const_iterator I = BD.getProgram()->begin(), + E = BD.getProgram()->end(); I != E; ++I) + for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI) + Blocks.push_back(FI); + unsigned OldSize = Blocks.size(); + ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error); + if (Blocks.size() < OldSize) + BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks"); + } + + // Attempt to delete instructions using bisection. This should help out nasty + // cases with large basic blocks where the problem is at one end. + if (!BugpointIsInterrupted) { + std::vector Insts; + for (Module::const_iterator MI = BD.getProgram()->begin(), + ME = BD.getProgram()->end(); MI != ME; ++MI) + for (Function::const_iterator FI = MI->begin(), FE = MI->end(); FI != FE; + ++FI) + for (BasicBlock::const_iterator I = FI->begin(), E = FI->end(); + I != E; ++I) + if (!isa(I)) + Insts.push_back(I); + + ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error); + } + + // FIXME: This should use the list reducer to converge faster by deleting + // larger chunks of instructions at a time! + unsigned Simplification = 2; + do { + if (BugpointIsInterrupted) break; + --Simplification; + outs() << "\n*** Attempting to reduce testcase by deleting instruc" + << "tions: Simplification Level #" << Simplification << '\n'; + + // Now that we have deleted the functions that are unnecessary for the + // program, try to remove instructions that are not necessary to cause the + // crash. To do this, we loop through all of the instructions in the + // remaining functions, deleting them (replacing any values produced with + // nulls), and then running ADCE and SimplifyCFG. If the transformed input + // still triggers failure, keep deleting until we cannot trigger failure + // anymore. + // + unsigned InstructionsToSkipBeforeDeleting = 0; + TryAgain: + + // Loop over all of the (non-terminator) instructions remaining in the + // function, attempting to delete them. + unsigned CurInstructionNum = 0; + for (Module::const_iterator FI = BD.getProgram()->begin(), + E = BD.getProgram()->end(); FI != E; ++FI) + if (!FI->isDeclaration()) + for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E; + ++BI) + for (BasicBlock::const_iterator I = BI->begin(), E = --BI->end(); + I != E; ++I, ++CurInstructionNum) + if (InstructionsToSkipBeforeDeleting) { + --InstructionsToSkipBeforeDeleting; + } else { + if (BugpointIsInterrupted) goto ExitLoops; + + outs() << "Checking instruction: " << *I; + Module *M = BD.deleteInstructionFromProgram(I, Simplification); + + // Find out if the pass still crashes on this pass... + if (TestFn(BD, M)) { + // Yup, it does, we delete the old module, and continue trying + // to reduce the testcase... + BD.setNewProgram(M); + InstructionsToSkipBeforeDeleting = CurInstructionNum; + goto TryAgain; // I wish I had a multi-level break here! + } + + // This pass didn't crash without this instruction, try the next + // one. + delete M; + } + + if (InstructionsToSkipBeforeDeleting) { + InstructionsToSkipBeforeDeleting = 0; + goto TryAgain; + } + + } while (Simplification); +ExitLoops: + + // Try to clean up the testcase by running funcresolve and globaldce... + if (!BugpointIsInterrupted) { + outs() << "\n*** Attempting to perform final cleanups: "; + Module *M = CloneModule(BD.getProgram()); + M = BD.performFinalCleanups(M, true); + + // Find out if the pass still crashes on the cleaned up program... + if (TestFn(BD, M)) { + BD.setNewProgram(M); // Yup, it does, keep the reduced version... + } else { + delete M; + } + } + + BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplified"); + + return false; +} + +static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) { + return BD.runPasses(M); +} + +/// debugOptimizerCrash - This method is called when some pass crashes on input. +/// It attempts to prune down the testcase to something reasonable, and figure +/// out exactly which pass is crashing. +/// +bool BugDriver::debugOptimizerCrash(const std::string &ID) { + outs() << "\n*** Debugging optimizer crash!\n"; + + std::string Error; + // Reduce the list of passes which causes the optimizer to crash... + if (!BugpointIsInterrupted) + ReducePassList(*this).reduceList(PassesToRun, Error); + assert(Error.empty()); + + outs() << "\n*** Found crashing pass" + << (PassesToRun.size() == 1 ? ": " : "es: ") + << getPassesString(PassesToRun) << '\n'; + + EmitProgressBitcode(Program, ID); + + bool Success = DebugACrash(*this, TestForOptimizerCrash, Error); + assert(Error.empty()); + return Success; +} + +static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) { + std::string Error; + BD.compileProgram(M, &Error); + if (!Error.empty()) { + errs() << "\n"; + return true; // Tool is still crashing. + } + errs() << '\n'; + return false; +} + +/// debugCodeGeneratorCrash - This method is called when the code generator +/// crashes on an input. It attempts to reduce the input as much as possible +/// while still causing the code generator to crash. +bool BugDriver::debugCodeGeneratorCrash(std::string &Error) { + errs() << "*** Debugging code generator crash!\n"; + + return DebugACrash(*this, TestForCodeGenCrash, Error); +} diff --git a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp new file mode 100644 index 000000000000..77c01ac552b3 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp @@ -0,0 +1,516 @@ +//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code used to execute the program utilizing one of the +// various ways of running LLVM bitcode. +// +//===----------------------------------------------------------------------===// + +#include "BugDriver.h" +#include "ToolRunner.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +namespace { + // OutputType - Allow the user to specify the way code should be run, to test + // for miscompilation. + // + enum OutputType { + AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe, + CompileCustom, Custom + }; + + cl::opt + AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"), + cl::init(0.0)); + cl::opt + RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"), + cl::init(0.0)); + + cl::opt + InterpreterSel(cl::desc("Specify the \"test\" i.e. suspect back-end:"), + cl::values(clEnumValN(AutoPick, "auto", "Use best guess"), + clEnumValN(RunLLI, "run-int", + "Execute with the interpreter"), + clEnumValN(RunJIT, "run-jit", "Execute with JIT"), + clEnumValN(RunLLC, "run-llc", "Compile with LLC"), + clEnumValN(RunLLCIA, "run-llc-ia", + "Compile with LLC with integrated assembler"), + clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), + clEnumValN(CBE_bug,"cbe-bug", "Find CBE bugs"), + clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"), + clEnumValN(CompileCustom, "compile-custom", + "Use -compile-command to define a command to " + "compile the bitcode. Useful to avoid linking."), + clEnumValN(Custom, "run-custom", + "Use -exec-command to define a command to execute " + "the bitcode. Useful for cross-compilation."), + clEnumValEnd), + cl::init(AutoPick)); + + cl::opt + SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"), + cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"), + clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"), + clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"), + clEnumValN(Custom, "safe-run-custom", + "Use -exec-command to define a command to execute " + "the bitcode. Useful for cross-compilation."), + clEnumValEnd), + cl::init(AutoPick)); + + cl::opt + SafeInterpreterPath("safe-path", + cl::desc("Specify the path to the \"safe\" backend program"), + cl::init("")); + + cl::opt + AppendProgramExitCode("append-exit-code", + cl::desc("Append the exit code to the output so it gets diff'd too"), + cl::init(false)); + + cl::opt + InputFile("input", cl::init("/dev/null"), + cl::desc("Filename to pipe in as stdin (default: /dev/null)")); + + cl::list + AdditionalSOs("additional-so", + cl::desc("Additional shared objects to load " + "into executing programs")); + + cl::list + AdditionalLinkerArgs("Xlinker", + cl::desc("Additional arguments to pass to the linker")); + + cl::opt + CustomCompileCommand("compile-command", cl::init("llc"), + cl::desc("Command to compile the bitcode (use with -compile-custom) " + "(default: llc)")); + + cl::opt + CustomExecCommand("exec-command", cl::init("simulate"), + cl::desc("Command to execute the bitcode (use with -run-custom) " + "(default: simulate)")); +} + +namespace llvm { + // Anything specified after the --args option are taken as arguments to the + // program being debugged. + cl::list + InputArgv("args", cl::Positional, cl::desc("..."), + cl::ZeroOrMore, cl::PositionalEatsArgs); + + cl::opt + OutputPrefix("output-prefix", cl::init("bugpoint"), + cl::desc("Prefix to use for outputs (default: 'bugpoint')")); +} + +namespace { + cl::list + ToolArgv("tool-args", cl::Positional, cl::desc("..."), + cl::ZeroOrMore, cl::PositionalEatsArgs); + + cl::list + SafeToolArgv("safe-tool-args", cl::Positional, + cl::desc("..."), + cl::ZeroOrMore, cl::PositionalEatsArgs); + + cl::opt + GCCBinary("gcc", cl::init("gcc"), + cl::desc("The gcc binary to use. (default 'gcc')")); + + cl::list + GCCToolArgv("gcc-tool-args", cl::Positional, + cl::desc("..."), + cl::ZeroOrMore, cl::PositionalEatsArgs); +} + +//===----------------------------------------------------------------------===// +// BugDriver method implementation +// + +/// initializeExecutionEnvironment - This method is used to set up the +/// environment for executing LLVM programs. +/// +bool BugDriver::initializeExecutionEnvironment() { + outs() << "Initializing execution environment: "; + + // Create an instance of the AbstractInterpreter interface as specified on + // the command line + SafeInterpreter = 0; + std::string Message; + + switch (InterpreterSel) { + case AutoPick: + InterpreterSel = RunCBE; + Interpreter = + AbstractInterpreter::createCBE(getToolName(), Message, GCCBinary, + &ToolArgv, &GCCToolArgv); + if (!Interpreter) { + InterpreterSel = RunJIT; + Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, + &ToolArgv); + } + if (!Interpreter) { + InterpreterSel = RunLLC; + Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, + GCCBinary, &ToolArgv, + &GCCToolArgv); + } + if (!Interpreter) { + InterpreterSel = RunLLI; + Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, + &ToolArgv); + } + if (!Interpreter) { + InterpreterSel = AutoPick; + Message = "Sorry, I can't automatically select an interpreter!\n"; + } + break; + case RunLLI: + Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, + &ToolArgv); + break; + case RunLLC: + case RunLLCIA: + case LLC_Safe: + Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, + GCCBinary, &ToolArgv, + &GCCToolArgv, + InterpreterSel == RunLLCIA); + break; + case RunJIT: + Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, + &ToolArgv); + break; + case RunCBE: + case CBE_bug: + Interpreter = AbstractInterpreter::createCBE(getToolName(), Message, + GCCBinary, &ToolArgv, + &GCCToolArgv); + break; + case CompileCustom: + Interpreter = + AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand); + break; + case Custom: + Interpreter = + AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); + break; + default: + Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; + break; + } + if (!Interpreter) + errs() << Message; + else // Display informational messages on stdout instead of stderr + outs() << Message; + + std::string Path = SafeInterpreterPath; + if (Path.empty()) + Path = getToolName(); + std::vector SafeToolArgs = SafeToolArgv; + switch (SafeInterpreterSel) { + case AutoPick: + // In "cbe-bug" mode, default to using LLC as the "safe" backend. + if (!SafeInterpreter && + InterpreterSel == CBE_bug) { + SafeInterpreterSel = RunLLC; + SafeToolArgs.push_back("--relocation-model=pic"); + SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, + GCCBinary, + &SafeToolArgs, + &GCCToolArgv); + } + + // In "llc-safe" mode, default to using LLC as the "safe" backend. + if (!SafeInterpreter && + InterpreterSel == LLC_Safe) { + SafeInterpreterSel = RunLLC; + SafeToolArgs.push_back("--relocation-model=pic"); + SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, + GCCBinary, + &SafeToolArgs, + &GCCToolArgv); + } + + // Pick a backend that's different from the test backend. The JIT and + // LLC backends share a lot of code, so prefer to use the CBE as the + // safe back-end when testing them. + if (!SafeInterpreter && + InterpreterSel != RunCBE) { + SafeInterpreterSel = RunCBE; + SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, + GCCBinary, + &SafeToolArgs, + &GCCToolArgv); + } + if (!SafeInterpreter && + InterpreterSel != RunLLC && + InterpreterSel != RunJIT) { + SafeInterpreterSel = RunLLC; + SafeToolArgs.push_back("--relocation-model=pic"); + SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, + GCCBinary, + &SafeToolArgs, + &GCCToolArgv); + } + if (!SafeInterpreter) { + SafeInterpreterSel = AutoPick; + Message = "Sorry, I can't automatically select an interpreter!\n"; + } + break; + case RunLLC: + case RunLLCIA: + SafeToolArgs.push_back("--relocation-model=pic"); + SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, + GCCBinary, &SafeToolArgs, + &GCCToolArgv, + SafeInterpreterSel == RunLLCIA); + break; + case RunCBE: + SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, + GCCBinary, &SafeToolArgs, + &GCCToolArgv); + break; + case Custom: + SafeInterpreter = + AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); + break; + default: + Message = "Sorry, this back-end is not supported by bugpoint as the " + "\"safe\" backend right now!\n"; + break; + } + if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); } + + gcc = GCC::create(Message, GCCBinary, &GCCToolArgv); + if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } + + // If there was an error creating the selected interpreter, quit with error. + return Interpreter == 0; +} + +/// compileProgram - Try to compile the specified module, returning false and +/// setting Error if an error occurs. This is used for code generation +/// crash testing. +/// +void BugDriver::compileProgram(Module *M, std::string *Error) const { + // Emit the program to a bitcode file... + sys::Path BitcodeFile (OutputPrefix + "-test-program.bc"); + std::string ErrMsg; + if (BitcodeFile.makeUnique(true, &ErrMsg)) { + errs() << ToolName << ": Error making unique filename: " << ErrMsg + << "\n"; + exit(1); + } + if (writeProgramToFile(BitcodeFile.str(), M)) { + errs() << ToolName << ": Error emitting bitcode to file '" + << BitcodeFile.str() << "'!\n"; + exit(1); + } + + // Remove the temporary bitcode file when we are done. + FileRemover BitcodeFileRemover(BitcodeFile.str(), !SaveTemps); + + // Actually compile the program! + Interpreter->compileProgram(BitcodeFile.str(), Error, Timeout, MemoryLimit); +} + + +/// executeProgram - This method runs "Program", capturing the output of the +/// program to a file, returning the filename of the file. A recommended +/// filename may be optionally specified. +/// +std::string BugDriver::executeProgram(const Module *Program, + std::string OutputFile, + std::string BitcodeFile, + const std::string &SharedObj, + AbstractInterpreter *AI, + std::string *Error) const { + if (AI == 0) AI = Interpreter; + assert(AI && "Interpreter should have been created already!"); + bool CreatedBitcode = false; + std::string ErrMsg; + if (BitcodeFile.empty()) { + // Emit the program to a bitcode file... + sys::Path uniqueFilename(OutputPrefix + "-test-program.bc"); + if (uniqueFilename.makeUnique(true, &ErrMsg)) { + errs() << ToolName << ": Error making unique filename: " + << ErrMsg << "!\n"; + exit(1); + } + BitcodeFile = uniqueFilename.str(); + + if (writeProgramToFile(BitcodeFile, Program)) { + errs() << ToolName << ": Error emitting bitcode to file '" + << BitcodeFile << "'!\n"; + exit(1); + } + CreatedBitcode = true; + } + + // Remove the temporary bitcode file when we are done. + sys::Path BitcodePath(BitcodeFile); + FileRemover BitcodeFileRemover(BitcodePath.str(), + CreatedBitcode && !SaveTemps); + + if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output"; + + // Check to see if this is a valid output filename... + sys::Path uniqueFile(OutputFile); + if (uniqueFile.makeUnique(true, &ErrMsg)) { + errs() << ToolName << ": Error making unique filename: " + << ErrMsg << "\n"; + exit(1); + } + OutputFile = uniqueFile.str(); + + // Figure out which shared objects to run, if any. + std::vector SharedObjs(AdditionalSOs); + if (!SharedObj.empty()) + SharedObjs.push_back(SharedObj); + + int RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, OutputFile, + Error, AdditionalLinkerArgs, SharedObjs, + Timeout, MemoryLimit); + if (!Error->empty()) + return OutputFile; + + if (RetVal == -1) { + errs() << ""; + static bool FirstTimeout = true; + if (FirstTimeout) { + outs() << "\n" + "*** Program execution timed out! This mechanism is designed to handle\n" + " programs stuck in infinite loops gracefully. The -timeout option\n" + " can be used to change the timeout threshold or disable it completely\n" + " (with -timeout=0). This message is only displayed once.\n"; + FirstTimeout = false; + } + } + + if (AppendProgramExitCode) { + std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); + outFile << "exit " << RetVal << '\n'; + outFile.close(); + } + + // Return the filename we captured the output to. + return OutputFile; +} + +/// executeProgramSafely - Used to create reference output with the "safe" +/// backend, if reference output is not provided. +/// +std::string BugDriver::executeProgramSafely(const Module *Program, + std::string OutputFile, + std::string *Error) const { + return executeProgram(Program, OutputFile, "", "", SafeInterpreter, Error); +} + +std::string BugDriver::compileSharedObject(const std::string &BitcodeFile, + std::string &Error) { + assert(Interpreter && "Interpreter should have been created already!"); + sys::Path OutputFile; + + // Using the known-good backend. + GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile, + Error); + if (!Error.empty()) + return ""; + + std::string SharedObjectFile; + bool Failure = gcc->MakeSharedObject(OutputFile.str(), FT, SharedObjectFile, + AdditionalLinkerArgs, Error); + if (!Error.empty()) + return ""; + if (Failure) + exit(1); + + // Remove the intermediate C file + OutputFile.eraseFromDisk(); + + return "./" + SharedObjectFile; +} + +/// createReferenceFile - calls compileProgram and then records the output +/// into ReferenceOutputFile. Returns true if reference file created, false +/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE +/// this function. +/// +bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) { + std::string Error; + compileProgram(Program, &Error); + if (!Error.empty()) + return false; + + ReferenceOutputFile = executeProgramSafely(Program, Filename, &Error); + if (!Error.empty()) { + errs() << Error; + if (Interpreter != SafeInterpreter) { + errs() << "*** There is a bug running the \"safe\" backend. Either" + << " debug it (for example with the -run-cbe bugpoint option," + << " if CBE is being used as the \"safe\" backend), or fix the" + << " error some other way.\n"; + } + return false; + } + outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; + return true; +} + +/// diffProgram - This method executes the specified module and diffs the +/// output against the file specified by ReferenceOutputFile. If the output +/// is different, 1 is returned. If there is a problem with the code +/// generator (e.g., llc crashes), this will set ErrMsg. +/// +bool BugDriver::diffProgram(const Module *Program, + const std::string &BitcodeFile, + const std::string &SharedObject, + bool RemoveBitcode, + std::string *ErrMsg) const { + // Execute the program, generating an output file... + sys::Path Output(executeProgram(Program, "", BitcodeFile, SharedObject, 0, + ErrMsg)); + if (!ErrMsg->empty()) + return false; + + std::string Error; + bool FilesDifferent = false; + if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile), + sys::Path(Output.str()), + AbsTolerance, RelTolerance, &Error)) { + if (Diff == 2) { + errs() << "While diffing output: " << Error << '\n'; + exit(1); + } + FilesDifferent = true; + } + else { + // Remove the generated output if there are no differences. + Output.eraseFromDisk(); + } + + // Remove the bitcode file if we are supposed to. + if (RemoveBitcode) + sys::Path(BitcodeFile).eraseFromDisk(); + return FilesDifferent; +} + +bool BugDriver::isExecutingJIT() { + return InterpreterSel == RunJIT; +} + diff --git a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp new file mode 100644 index 000000000000..73b65ca94f70 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp @@ -0,0 +1,370 @@ +//===- ExtractFunction.cpp - Extract a function from Program --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements several methods that are used to extract functions, +// loops, or portions of a module from the rest of the module. +// +//===----------------------------------------------------------------------===// + +#include "BugDriver.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/FunctionUtils.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Signals.h" +#include +using namespace llvm; + +namespace llvm { + bool DisableSimplifyCFG = false; + extern cl::opt OutputPrefix; +} // End llvm namespace + +namespace { + cl::opt + NoDCE ("disable-dce", + cl::desc("Do not use the -dce pass to reduce testcases")); + cl::opt + NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG), + cl::desc("Do not use the -simplifycfg pass to reduce testcases")); +} + +/// deleteInstructionFromProgram - This method clones the current Program and +/// deletes the specified instruction from the cloned module. It then runs a +/// series of cleanup passes (ADCE and SimplifyCFG) to eliminate any code which +/// depends on the value. The modified module is then returned. +/// +Module *BugDriver::deleteInstructionFromProgram(const Instruction *I, + unsigned Simplification) { + // FIXME, use vmap? + Module *Clone = CloneModule(Program); + + const BasicBlock *PBB = I->getParent(); + const Function *PF = PBB->getParent(); + + Module::iterator RFI = Clone->begin(); // Get iterator to corresponding fn + std::advance(RFI, std::distance(PF->getParent()->begin(), + Module::const_iterator(PF))); + + Function::iterator RBI = RFI->begin(); // Get iterator to corresponding BB + std::advance(RBI, std::distance(PF->begin(), Function::const_iterator(PBB))); + + BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst + std::advance(RI, std::distance(PBB->begin(), BasicBlock::const_iterator(I))); + Instruction *TheInst = RI; // Got the corresponding instruction! + + // If this instruction produces a value, replace any users with null values + if (!TheInst->getType()->isVoidTy()) + TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType())); + + // Remove the instruction from the program. + TheInst->getParent()->getInstList().erase(TheInst); + + // Spiff up the output a little bit. + std::vector Passes; + + /// Can we get rid of the -disable-* options? + if (Simplification > 1 && !NoDCE) + Passes.push_back("dce"); + if (Simplification && !DisableSimplifyCFG) + Passes.push_back("simplifycfg"); // Delete dead control flow + + Passes.push_back("verify"); + Module *New = runPassesOn(Clone, Passes); + delete Clone; + if (!New) { + errs() << "Instruction removal failed. Sorry. :( Please report a bug!\n"; + exit(1); + } + return New; +} + +/// performFinalCleanups - This method clones the current Program and performs +/// a series of cleanups intended to get rid of extra cruft on the module +/// before handing it to the user. +/// +Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) { + // Make all functions external, so GlobalDCE doesn't delete them... + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + I->setLinkage(GlobalValue::ExternalLinkage); + + std::vector CleanupPasses; + CleanupPasses.push_back("globaldce"); + + if (MayModifySemantics) + CleanupPasses.push_back("deadarghaX0r"); + else + CleanupPasses.push_back("deadargelim"); + + Module *New = runPassesOn(M, CleanupPasses); + if (New == 0) { + errs() << "Final cleanups failed. Sorry. :( Please report a bug!\n"; + return M; + } + delete M; + return New; +} + + +/// ExtractLoop - Given a module, extract up to one loop from it into a new +/// function. This returns null if there are no extractable loops in the +/// program or if the loop extractor crashes. +Module *BugDriver::ExtractLoop(Module *M) { + std::vector LoopExtractPasses; + LoopExtractPasses.push_back("loop-extract-single"); + + Module *NewM = runPassesOn(M, LoopExtractPasses); + if (NewM == 0) { + outs() << "*** Loop extraction failed: "; + EmitProgressBitcode(M, "loopextraction", true); + outs() << "*** Sorry. :( Please report a bug!\n"; + return 0; + } + + // Check to see if we created any new functions. If not, no loops were + // extracted and we should return null. Limit the number of loops we extract + // to avoid taking forever. + static unsigned NumExtracted = 32; + if (M->size() == NewM->size() || --NumExtracted == 0) { + delete NewM; + return 0; + } else { + assert(M->size() < NewM->size() && "Loop extract removed functions?"); + Module::iterator MI = NewM->begin(); + for (unsigned i = 0, e = M->size(); i != e; ++i) + ++MI; + } + + return NewM; +} + + +// DeleteFunctionBody - "Remove" the function by deleting all of its basic +// blocks, making it external. +// +void llvm::DeleteFunctionBody(Function *F) { + // delete the body of the function... + F->deleteBody(); + assert(F->isDeclaration() && "This didn't make the function external!"); +} + +/// GetTorInit - Given a list of entries for static ctors/dtors, return them +/// as a constant array. +static Constant *GetTorInit(std::vector > &TorList) { + assert(!TorList.empty() && "Don't create empty tor list!"); + std::vector ArrayElts; + Type *Int32Ty = Type::getInt32Ty(TorList[0].first->getContext()); + + StructType *STy = + StructType::get(Int32Ty, TorList[0].first->getType(), NULL); + for (unsigned i = 0, e = TorList.size(); i != e; ++i) { + Constant *Elts[] = { + ConstantInt::get(Int32Ty, TorList[i].second), + TorList[i].first + }; + ArrayElts.push_back(ConstantStruct::get(STy, Elts)); + } + return ConstantArray::get(ArrayType::get(ArrayElts[0]->getType(), + ArrayElts.size()), + ArrayElts); +} + +/// SplitStaticCtorDtor - A module was recently split into two parts, M1/M2, and +/// M1 has all of the global variables. If M2 contains any functions that are +/// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and +/// prune appropriate entries out of M1s list. +static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2, + ValueToValueMapTy &VMap) { + GlobalVariable *GV = M1->getNamedGlobal(GlobalName); + if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || + !GV->use_empty()) return; + + std::vector > M1Tors, M2Tors; + ConstantArray *InitList = dyn_cast(GV->getInitializer()); + if (!InitList) return; + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + + if (CS->getOperand(1)->isNullValue()) + break; // Found a null terminator, stop here. + + ConstantInt *CI = dyn_cast(CS->getOperand(0)); + int Priority = CI ? CI->getSExtValue() : 0; + + Constant *FP = CS->getOperand(1); + if (ConstantExpr *CE = dyn_cast(FP)) + if (CE->isCast()) + FP = CE->getOperand(0); + if (Function *F = dyn_cast(FP)) { + if (!F->isDeclaration()) + M1Tors.push_back(std::make_pair(F, Priority)); + else { + // Map to M2's version of the function. + F = cast(VMap[F]); + M2Tors.push_back(std::make_pair(F, Priority)); + } + } + } + } + + GV->eraseFromParent(); + if (!M1Tors.empty()) { + Constant *M1Init = GetTorInit(M1Tors); + new GlobalVariable(*M1, M1Init->getType(), false, + GlobalValue::AppendingLinkage, + M1Init, GlobalName); + } + + GV = M2->getNamedGlobal(GlobalName); + assert(GV && "Not a clone of M1?"); + assert(GV->use_empty() && "llvm.ctors shouldn't have uses!"); + + GV->eraseFromParent(); + if (!M2Tors.empty()) { + Constant *M2Init = GetTorInit(M2Tors); + new GlobalVariable(*M2, M2Init->getType(), false, + GlobalValue::AppendingLinkage, + M2Init, GlobalName); + } +} + + +/// SplitFunctionsOutOfModule - Given a module and a list of functions in the +/// module, split the functions OUT of the specified module, and place them in +/// the new module. +Module * +llvm::SplitFunctionsOutOfModule(Module *M, + const std::vector &F, + ValueToValueMapTy &VMap) { + // Make sure functions & globals are all external so that linkage + // between the two modules will work. + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + I->setLinkage(GlobalValue::ExternalLinkage); + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + if (I->hasName() && I->getName()[0] == '\01') + I->setName(I->getName().substr(1)); + I->setLinkage(GlobalValue::ExternalLinkage); + } + + ValueToValueMapTy NewVMap; + Module *New = CloneModule(M, NewVMap); + + // Make sure global initializers exist only in the safe module (CBE->.so) + for (Module::global_iterator I = New->global_begin(), E = New->global_end(); + I != E; ++I) + I->setInitializer(0); // Delete the initializer to make it external + + // Remove the Test functions from the Safe module + std::set TestFunctions; + for (unsigned i = 0, e = F.size(); i != e; ++i) { + Function *TNOF = cast(VMap[F[i]]); + DEBUG(errs() << "Removing function "); + DEBUG(WriteAsOperand(errs(), TNOF, false)); + DEBUG(errs() << "\n"); + TestFunctions.insert(cast(NewVMap[TNOF])); + DeleteFunctionBody(TNOF); // Function is now external in this module! + } + + + // Remove the Safe functions from the Test module + for (Module::iterator I = New->begin(), E = New->end(); I != E; ++I) + if (!TestFunctions.count(I)) + DeleteFunctionBody(I); + + + // Make sure that there is a global ctor/dtor array in both halves of the + // module if they both have static ctor/dtor functions. + SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap); + SplitStaticCtorDtor("llvm.global_dtors", M, New, NewVMap); + + return New; +} + +//===----------------------------------------------------------------------===// +// Basic Block Extraction Code +//===----------------------------------------------------------------------===// + +/// ExtractMappedBlocksFromModule - Extract all but the specified basic blocks +/// into their own functions. The only detail is that M is actually a module +/// cloned from the one the BBs are in, so some mapping needs to be performed. +/// If this operation fails for some reason (ie the implementation is buggy), +/// this function should return null, otherwise it returns a new Module. +Module *BugDriver::ExtractMappedBlocksFromModule(const + std::vector &BBs, + Module *M) { + sys::Path uniqueFilename(OutputPrefix + "-extractblocks"); + std::string ErrMsg; + if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) { + outs() << "*** Basic Block extraction failed!\n"; + errs() << "Error creating temporary file: " << ErrMsg << "\n"; + EmitProgressBitcode(M, "basicblockextractfail", true); + return 0; + } + sys::RemoveFileOnSignal(uniqueFilename); + + std::string ErrorInfo; + tool_output_file BlocksToNotExtractFile(uniqueFilename.c_str(), ErrorInfo); + if (!ErrorInfo.empty()) { + outs() << "*** Basic Block extraction failed!\n"; + errs() << "Error writing list of blocks to not extract: " << ErrorInfo + << "\n"; + EmitProgressBitcode(M, "basicblockextractfail", true); + return 0; + } + for (std::vector::const_iterator I = BBs.begin(), E = BBs.end(); + I != E; ++I) { + BasicBlock *BB = *I; + // If the BB doesn't have a name, give it one so we have something to key + // off of. + if (!BB->hasName()) BB->setName("tmpbb"); + BlocksToNotExtractFile.os() << BB->getParent()->getNameStr() << " " + << BB->getName() << "\n"; + } + BlocksToNotExtractFile.os().close(); + if (BlocksToNotExtractFile.os().has_error()) { + errs() << "Error writing list of blocks to not extract: " << ErrorInfo + << "\n"; + EmitProgressBitcode(M, "basicblockextractfail", true); + BlocksToNotExtractFile.os().clear_error(); + return 0; + } + BlocksToNotExtractFile.keep(); + + std::string uniqueFN = "--extract-blocks-file=" + uniqueFilename.str(); + const char *ExtraArg = uniqueFN.c_str(); + + std::vector PI; + PI.push_back("extract-blocks"); + Module *Ret = runPassesOn(M, PI, false, 1, &ExtraArg); + + uniqueFilename.eraseFromDisk(); // Free disk space + + if (Ret == 0) { + outs() << "*** Basic Block extraction failed, please report a bug!\n"; + EmitProgressBitcode(M, "basicblockextractfail", true); + } + return Ret; +} diff --git a/contrib/llvm/tools/bugpoint/FindBugs.cpp b/contrib/llvm/tools/bugpoint/FindBugs.cpp new file mode 100644 index 000000000000..a291f9fb0f99 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/FindBugs.cpp @@ -0,0 +1,113 @@ +//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an interface that allows bugpoint to choose different +// combinations of optimizations to run on the selected input. Bugpoint will +// run these optimizations and record the success/failure of each. This way +// we can hopefully spot bugs in the optimizations. +// +//===----------------------------------------------------------------------===// + +#include "BugDriver.h" +#include "ToolRunner.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; + +/// runManyPasses - Take the specified pass list and create different +/// combinations of passes to compile the program with. Compile the program with +/// each set and mark test to see if it compiled correctly. If the passes +/// compiled correctly output nothing and rearrange the passes into a new order. +/// If the passes did not compile correctly, output the command required to +/// recreate the failure. This returns true if a compiler error is found. +/// +bool BugDriver::runManyPasses(const std::vector &AllPasses, + std::string &ErrMsg) { + setPassesToRun(AllPasses); + outs() << "Starting bug finding procedure...\n\n"; + + // Creating a reference output if necessary + if (initializeExecutionEnvironment()) return false; + + outs() << "\n"; + if (ReferenceOutputFile.empty()) { + outs() << "Generating reference output from raw program: \n"; + if (!createReferenceFile(Program)) + return false; + } + + srand(time(NULL)); + + unsigned num = 1; + while(1) { + // + // Step 1: Randomize the order of the optimizer passes. + // + std::random_shuffle(PassesToRun.begin(), PassesToRun.end()); + + // + // Step 2: Run optimizer passes on the program and check for success. + // + outs() << "Running selected passes on program to test for crash: "; + for(int i = 0, e = PassesToRun.size(); i != e; i++) { + outs() << "-" << PassesToRun[i] << " "; + } + + std::string Filename; + if(runPasses(Program, PassesToRun, Filename, false)) { + outs() << "\n"; + outs() << "Optimizer passes caused failure!\n\n"; + debugOptimizerCrash(); + return true; + } else { + outs() << "Combination " << num << " optimized successfully!\n"; + } + + // + // Step 3: Compile the optimized code. + // + outs() << "Running the code generator to test for a crash: "; + std::string Error; + compileProgram(Program, &Error); + if (!Error.empty()) { + outs() << "\n*** compileProgram threw an exception: "; + outs() << Error; + return debugCodeGeneratorCrash(ErrMsg); + } + outs() << '\n'; + + // + // Step 4: Run the program and compare its output to the reference + // output (created above). + // + outs() << "*** Checking if passes caused miscompliation:\n"; + bool Diff = diffProgram(Program, Filename, "", false, &Error); + if (Error.empty() && Diff) { + outs() << "\n*** diffProgram returned true!\n"; + debugMiscompilation(&Error); + if (Error.empty()) + return true; + } + if (!Error.empty()) { + errs() << Error; + debugCodeGeneratorCrash(ErrMsg); + return true; + } + outs() << "\n*** diff'd output matches!\n"; + + sys::Path(Filename).eraseFromDisk(); + + outs() << "\n\n"; + num++; + } //end while + + // Unreachable. +} diff --git a/contrib/llvm/tools/bugpoint/ListReducer.h b/contrib/llvm/tools/bugpoint/ListReducer.h new file mode 100644 index 000000000000..bd1c5da65c8f --- /dev/null +++ b/contrib/llvm/tools/bugpoint/ListReducer.h @@ -0,0 +1,201 @@ +//===- ListReducer.h - Trim down list while retaining property --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class is to be used as a base class for operations that want to zero in +// on a subset of the input which still causes the bug we are tracking. +// +//===----------------------------------------------------------------------===// + +#ifndef BUGPOINT_LIST_REDUCER_H +#define BUGPOINT_LIST_REDUCER_H + +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include +#include + +namespace llvm { + + extern bool BugpointIsInterrupted; + +template +struct ListReducer { + enum TestResult { + NoFailure, // No failure of the predicate was detected + KeepSuffix, // The suffix alone satisfies the predicate + KeepPrefix, // The prefix alone satisfies the predicate + InternalError // Encountered an error trying to run the predicate + }; + + virtual ~ListReducer() {} + + // doTest - This virtual function should be overriden by subclasses to + // implement the test desired. The testcase is only required to test to see + // if the Kept list still satisfies the property, but if it is going to check + // the prefix anyway, it can. + // + virtual TestResult doTest(std::vector &Prefix, + std::vector &Kept, + std::string &Error) = 0; + + // reduceList - This function attempts to reduce the length of the specified + // list while still maintaining the "test" property. This is the core of the + // "work" that bugpoint does. + // + bool reduceList(std::vector &TheList, std::string &Error) { + std::vector empty; + std::srand(0x6e5ea738); // Seed the random number generator + switch (doTest(TheList, empty, Error)) { + case KeepPrefix: + if (TheList.size() == 1) // we are done, it's the base case and it fails + return true; + else + break; // there's definitely an error, but we need to narrow it down + + case KeepSuffix: + // cannot be reached! + llvm_unreachable("bugpoint ListReducer internal error: " + "selected empty set."); + + case NoFailure: + return false; // there is no failure with the full set of passes/funcs! + + case InternalError: + assert(!Error.empty()); + return true; + } + + // Maximal number of allowed splitting iterations, + // before the elements are randomly shuffled. + const unsigned MaxIterationsWithoutProgress = 3; + bool ShufflingEnabled = true; + +Backjump: + unsigned MidTop = TheList.size(); + unsigned MaxIterations = MaxIterationsWithoutProgress; + unsigned NumOfIterationsWithoutProgress = 0; + while (MidTop > 1) { // Binary split reduction loop + // Halt if the user presses ctrl-c. + if (BugpointIsInterrupted) { + errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n"; + return true; + } + + // If the loop doesn't make satisfying progress, try shuffling. + // The purpose of shuffling is to avoid the heavy tails of the + // distribution (improving the speed of convergence). + if (ShufflingEnabled && + NumOfIterationsWithoutProgress > MaxIterations) { + std::vector ShuffledList(TheList); + std::random_shuffle(ShuffledList.begin(), ShuffledList.end()); + errs() << "\n\n*** Testing shuffled set...\n\n"; + // Check that random shuffle doesn't loose the bug + if (doTest(ShuffledList, empty, Error) == KeepPrefix) { + // If the bug is still here, use the shuffled list. + TheList.swap(ShuffledList); + MidTop = TheList.size(); + // Must increase the shuffling treshold to avoid the small + // probability of inifinite looping without making progress. + MaxIterations += 2; + errs() << "\n\n*** Shuffling does not hide the bug...\n\n"; + } else { + ShufflingEnabled = false; // Disable shuffling further on + errs() << "\n\n*** Shuffling hides the bug...\n\n"; + } + NumOfIterationsWithoutProgress = 0; + } + + unsigned Mid = MidTop / 2; + std::vector Prefix(TheList.begin(), TheList.begin()+Mid); + std::vector Suffix(TheList.begin()+Mid, TheList.end()); + + switch (doTest(Prefix, Suffix, Error)) { + case KeepSuffix: + // The property still holds. We can just drop the prefix elements, and + // shorten the list to the "kept" elements. + TheList.swap(Suffix); + MidTop = TheList.size(); + // Reset progress treshold and progress counter + MaxIterations = MaxIterationsWithoutProgress; + NumOfIterationsWithoutProgress = 0; + break; + case KeepPrefix: + // The predicate still holds, shorten the list to the prefix elements. + TheList.swap(Prefix); + MidTop = TheList.size(); + // Reset progress treshold and progress counter + MaxIterations = MaxIterationsWithoutProgress; + NumOfIterationsWithoutProgress = 0; + break; + case NoFailure: + // Otherwise the property doesn't hold. Some of the elements we removed + // must be necessary to maintain the property. + MidTop = Mid; + NumOfIterationsWithoutProgress++; + break; + case InternalError: + return true; // Error was set by doTest. + } + assert(Error.empty() && "doTest did not return InternalError for error"); + } + + // Probability of backjumping from the trimming loop back to the binary + // split reduction loop. + const int BackjumpProbability = 10; + + // Okay, we trimmed as much off the top and the bottom of the list as we + // could. If there is more than two elements in the list, try deleting + // interior elements and testing that. + // + if (TheList.size() > 2) { + bool Changed = true; + std::vector EmptyList; + while (Changed) { // Trimming loop. + Changed = false; + + // If the binary split reduction loop made an unfortunate sequence of + // splits, the trimming loop might be left off with a huge number of + // remaining elements (large search space). Backjumping out of that + // search space and attempting a different split can significantly + // improve the convergence speed. + if (std::rand() % 100 < BackjumpProbability) + goto Backjump; + + for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts + if (BugpointIsInterrupted) { + errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n"; + return true; + } + + std::vector TestList(TheList); + TestList.erase(TestList.begin()+i); + + if (doTest(EmptyList, TestList, Error) == KeepSuffix) { + // We can trim down the list! + TheList.swap(TestList); + --i; // Don't skip an element of the list + Changed = true; + } + if (!Error.empty()) + return true; + } + // This can take a long time if left uncontrolled. For now, don't + // iterate. + break; + } + } + + return true; // there are some failure and we've narrowed them down + } +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/tools/bugpoint/Makefile b/contrib/llvm/tools/bugpoint/Makefile new file mode 100644 index 000000000000..5d287ef188ae --- /dev/null +++ b/contrib/llvm/tools/bugpoint/Makefile @@ -0,0 +1,16 @@ +##===- tools/bugpoint/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. + +TOOLNAME = bugpoint + +LINK_COMPONENTS := asmparser instrumentation scalaropts ipo \ + linker bitreader bitwriter + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/bugpoint/Miscompilation.cpp b/contrib/llvm/tools/bugpoint/Miscompilation.cpp new file mode 100644 index 000000000000..7ff16dbf958b --- /dev/null +++ b/contrib/llvm/tools/bugpoint/Miscompilation.cpp @@ -0,0 +1,1078 @@ +//===- Miscompilation.cpp - Debug program miscompilations -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements optimizer and code generation miscompilation debugging +// support. +// +//===----------------------------------------------------------------------===// + +#include "BugDriver.h" +#include "ListReducer.h" +#include "ToolRunner.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Linker.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Config/config.h" // for HAVE_LINK_R +using namespace llvm; + +namespace llvm { + extern cl::opt OutputPrefix; + extern cl::list InputArgv; +} + +namespace { + static llvm::cl::opt + DisableLoopExtraction("disable-loop-extraction", + cl::desc("Don't extract loops when searching for miscompilations"), + cl::init(false)); + static llvm::cl::opt + DisableBlockExtraction("disable-block-extraction", + cl::desc("Don't extract blocks when searching for miscompilations"), + cl::init(false)); + + class ReduceMiscompilingPasses : public ListReducer { + BugDriver &BD; + public: + ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {} + + virtual TestResult doTest(std::vector &Prefix, + std::vector &Suffix, + std::string &Error); + }; +} + +/// TestResult - After passes have been split into a test group and a control +/// group, see if they still break the program. +/// +ReduceMiscompilingPasses::TestResult +ReduceMiscompilingPasses::doTest(std::vector &Prefix, + std::vector &Suffix, + std::string &Error) { + // First, run the program with just the Suffix passes. If it is still broken + // with JUST the kept passes, discard the prefix passes. + outs() << "Checking to see if '" << getPassesString(Suffix) + << "' compiles correctly: "; + + std::string BitcodeResult; + if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/, + true/*quiet*/)) { + errs() << " Error running this sequence of passes" + << " on the input program!\n"; + BD.setPassesToRun(Suffix); + BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); + exit(BD.debugOptimizerCrash()); + } + + // Check to see if the finished program matches the reference output... + bool Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", + true /*delete bitcode*/, &Error); + if (!Error.empty()) + return InternalError; + if (Diff) { + outs() << " nope.\n"; + if (Suffix.empty()) { + errs() << BD.getToolName() << ": I'm confused: the test fails when " + << "no passes are run, nondeterministic program?\n"; + exit(1); + } + return KeepSuffix; // Miscompilation detected! + } + outs() << " yup.\n"; // No miscompilation! + + if (Prefix.empty()) return NoFailure; + + // Next, see if the program is broken if we run the "prefix" passes first, + // then separately run the "kept" passes. + outs() << "Checking to see if '" << getPassesString(Prefix) + << "' compiles correctly: "; + + // If it is not broken with the kept passes, it's possible that the prefix + // passes must be run before the kept passes to break it. If the program + // WORKS after the prefix passes, but then fails if running the prefix AND + // kept passes, we can update our bitcode file to include the result of the + // prefix passes, then discard the prefix passes. + // + if (BD.runPasses(BD.getProgram(), Prefix, BitcodeResult, false/*delete*/, + true/*quiet*/)) { + errs() << " Error running this sequence of passes" + << " on the input program!\n"; + BD.setPassesToRun(Prefix); + BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); + exit(BD.debugOptimizerCrash()); + } + + // If the prefix maintains the predicate by itself, only keep the prefix! + Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", false, &Error); + if (!Error.empty()) + return InternalError; + if (Diff) { + outs() << " nope.\n"; + sys::Path(BitcodeResult).eraseFromDisk(); + return KeepPrefix; + } + outs() << " yup.\n"; // No miscompilation! + + // Ok, so now we know that the prefix passes work, try running the suffix + // passes on the result of the prefix passes. + // + OwningPtr PrefixOutput(ParseInputFile(BitcodeResult, + BD.getContext())); + if (PrefixOutput == 0) { + errs() << BD.getToolName() << ": Error reading bitcode file '" + << BitcodeResult << "'!\n"; + exit(1); + } + sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk + + // Don't check if there are no passes in the suffix. + if (Suffix.empty()) + return NoFailure; + + outs() << "Checking to see if '" << getPassesString(Suffix) + << "' passes compile correctly after the '" + << getPassesString(Prefix) << "' passes: "; + + OwningPtr OriginalInput(BD.swapProgramIn(PrefixOutput.take())); + if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/, + true/*quiet*/)) { + errs() << " Error running this sequence of passes" + << " on the input program!\n"; + BD.setPassesToRun(Suffix); + BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); + exit(BD.debugOptimizerCrash()); + } + + // Run the result... + Diff = BD.diffProgram(BD.getProgram(), BitcodeResult, "", + true /*delete bitcode*/, &Error); + if (!Error.empty()) + return InternalError; + if (Diff) { + outs() << " nope.\n"; + return KeepSuffix; + } + + // Otherwise, we must not be running the bad pass anymore. + outs() << " yup.\n"; // No miscompilation! + // Restore orig program & free test. + delete BD.swapProgramIn(OriginalInput.take()); + return NoFailure; +} + +namespace { + class ReduceMiscompilingFunctions : public ListReducer { + BugDriver &BD; + bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); + public: + ReduceMiscompilingFunctions(BugDriver &bd, + bool (*F)(BugDriver &, Module *, Module *, + std::string &)) + : BD(bd), TestFn(F) {} + + virtual TestResult doTest(std::vector &Prefix, + std::vector &Suffix, + std::string &Error) { + if (!Suffix.empty()) { + bool Ret = TestFuncs(Suffix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepSuffix; + } + if (!Prefix.empty()) { + bool Ret = TestFuncs(Prefix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepPrefix; + } + return NoFailure; + } + + bool TestFuncs(const std::vector &Prefix, std::string &Error); + }; +} + +/// TestMergedProgram - Given two modules, link them together and run the +/// program, checking to see if the program matches the diff. If there is +/// an error, return NULL. If not, return the merged module. The Broken argument +/// will be set to true if the output is different. If the DeleteInputs +/// argument is set to true then this function deletes both input +/// modules before it returns. +/// +static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2, + bool DeleteInputs, std::string &Error, + bool &Broken) { + // Link the two portions of the program back to together. + std::string ErrorMsg; + if (!DeleteInputs) { + M1 = CloneModule(M1); + M2 = CloneModule(M2); + } + if (Linker::LinkModules(M1, M2, Linker::DestroySource, &ErrorMsg)) { + errs() << BD.getToolName() << ": Error linking modules together:" + << ErrorMsg << '\n'; + exit(1); + } + delete M2; // We are done with this module. + + // Execute the program. + Broken = BD.diffProgram(M1, "", "", false, &Error); + if (!Error.empty()) { + // Delete the linked module + delete M1; + return NULL; + } + return M1; +} + +/// TestFuncs - split functions in a Module into two groups: those that are +/// under consideration for miscompilation vs. those that are not, and test +/// accordingly. Each group of functions becomes a separate Module. +/// +bool ReduceMiscompilingFunctions::TestFuncs(const std::vector &Funcs, + std::string &Error) { + // Test to see if the function is misoptimized if we ONLY run it on the + // functions listed in Funcs. + outs() << "Checking to see if the program is misoptimized when " + << (Funcs.size()==1 ? "this function is" : "these functions are") + << " run through the pass" + << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":"; + PrintFunctionList(Funcs); + outs() << '\n'; + + // Create a clone for two reasons: + // * If the optimization passes delete any function, the deleted function + // will be in the clone and Funcs will still point to valid memory + // * If the optimization passes use interprocedural information to break + // a function, we want to continue with the original function. Otherwise + // we can conclude that a function triggers the bug when in fact one + // needs a larger set of original functions to do so. + ValueToValueMapTy VMap; + Module *Clone = CloneModule(BD.getProgram(), VMap); + Module *Orig = BD.swapProgramIn(Clone); + + std::vector FuncsOnClone; + for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { + Function *F = cast(VMap[Funcs[i]]); + FuncsOnClone.push_back(F); + } + + // Split the module into the two halves of the program we want. + VMap.clear(); + Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); + Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone, + VMap); + + // Run the predicate, note that the predicate will delete both input modules. + bool Broken = TestFn(BD, ToOptimize, ToNotOptimize, Error); + + delete BD.swapProgramIn(Orig); + + return Broken; +} + +/// DisambiguateGlobalSymbols - Give anonymous global values names. +/// +static void DisambiguateGlobalSymbols(Module *M) { + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) + if (!I->hasName()) + I->setName("anon_global"); + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + if (!I->hasName()) + I->setName("anon_fn"); +} + +/// ExtractLoops - Given a reduced list of functions that still exposed the bug, +/// check to see if we can extract the loops in the region without obscuring the +/// bug. If so, it reduces the amount of code identified. +/// +static bool ExtractLoops(BugDriver &BD, + bool (*TestFn)(BugDriver &, Module *, Module *, + std::string &), + std::vector &MiscompiledFunctions, + std::string &Error) { + bool MadeChange = false; + while (1) { + if (BugpointIsInterrupted) return MadeChange; + + ValueToValueMapTy VMap; + Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); + Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, + MiscompiledFunctions, + VMap); + Module *ToOptimizeLoopExtracted = BD.ExtractLoop(ToOptimize); + if (!ToOptimizeLoopExtracted) { + // If the loop extractor crashed or if there were no extractible loops, + // then this chapter of our odyssey is over with. + delete ToNotOptimize; + delete ToOptimize; + return MadeChange; + } + + errs() << "Extracted a loop from the breaking portion of the program.\n"; + + // Bugpoint is intentionally not very trusting of LLVM transformations. In + // particular, we're not going to assume that the loop extractor works, so + // we're going to test the newly loop extracted program to make sure nothing + // has broken. If something broke, then we'll inform the user and stop + // extraction. + AbstractInterpreter *AI = BD.switchToSafeInterpreter(); + bool Failure; + Module *New = TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, + false, Error, Failure); + if (!New) + return false; + // Delete the original and set the new program. + delete BD.swapProgramIn(New); + if (Failure) { + BD.switchToInterpreter(AI); + + // Merged program doesn't work anymore! + errs() << " *** ERROR: Loop extraction broke the program. :(" + << " Please report a bug!\n"; + errs() << " Continuing on with un-loop-extracted version.\n"; + + BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc", + ToNotOptimize); + BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc", + ToOptimize); + BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc", + ToOptimizeLoopExtracted); + + errs() << "Please submit the " + << OutputPrefix << "-loop-extract-fail-*.bc files.\n"; + delete ToOptimize; + delete ToNotOptimize; + delete ToOptimizeLoopExtracted; + return MadeChange; + } + delete ToOptimize; + BD.switchToInterpreter(AI); + + outs() << " Testing after loop extraction:\n"; + // Clone modules, the tester function will free them. + Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted); + Module *TNOBackup = CloneModule(ToNotOptimize); + Failure = TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize, Error); + if (!Error.empty()) + return false; + if (!Failure) { + outs() << "*** Loop extraction masked the problem. Undoing.\n"; + // If the program is not still broken, then loop extraction did something + // that masked the error. Stop loop extraction now. + delete TOLEBackup; + delete TNOBackup; + return MadeChange; + } + ToOptimizeLoopExtracted = TOLEBackup; + ToNotOptimize = TNOBackup; + + outs() << "*** Loop extraction successful!\n"; + + std::vector > MisCompFunctions; + for (Module::iterator I = ToOptimizeLoopExtracted->begin(), + E = ToOptimizeLoopExtracted->end(); I != E; ++I) + if (!I->isDeclaration()) + MisCompFunctions.push_back(std::make_pair(I->getName(), + I->getFunctionType())); + + // Okay, great! Now we know that we extracted a loop and that loop + // extraction both didn't break the program, and didn't mask the problem. + // Replace the current program with the loop extracted version, and try to + // extract another loop. + std::string ErrorMsg; + if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, + Linker::DestroySource, &ErrorMsg)){ + errs() << BD.getToolName() << ": Error linking modules together:" + << ErrorMsg << '\n'; + exit(1); + } + delete ToOptimizeLoopExtracted; + + // All of the Function*'s in the MiscompiledFunctions list are in the old + // module. Update this list to include all of the functions in the + // optimized and loop extracted module. + MiscompiledFunctions.clear(); + for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { + Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first); + + assert(NewF && "Function not found??"); + MiscompiledFunctions.push_back(NewF); + } + + BD.setNewProgram(ToNotOptimize); + MadeChange = true; + } +} + +namespace { + class ReduceMiscompiledBlocks : public ListReducer { + BugDriver &BD; + bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); + std::vector FunctionsBeingTested; + public: + ReduceMiscompiledBlocks(BugDriver &bd, + bool (*F)(BugDriver &, Module *, Module *, + std::string &), + const std::vector &Fns) + : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {} + + virtual TestResult doTest(std::vector &Prefix, + std::vector &Suffix, + std::string &Error) { + if (!Suffix.empty()) { + bool Ret = TestFuncs(Suffix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepSuffix; + } + if (!Prefix.empty()) { + bool Ret = TestFuncs(Prefix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepPrefix; + } + return NoFailure; + } + + bool TestFuncs(const std::vector &BBs, std::string &Error); + }; +} + +/// TestFuncs - Extract all blocks for the miscompiled functions except for the +/// specified blocks. If the problem still exists, return true. +/// +bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, + std::string &Error) { + // Test to see if the function is misoptimized if we ONLY run it on the + // functions listed in Funcs. + outs() << "Checking to see if the program is misoptimized when all "; + if (!BBs.empty()) { + outs() << "but these " << BBs.size() << " blocks are extracted: "; + for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i) + outs() << BBs[i]->getName() << " "; + if (BBs.size() > 10) outs() << "..."; + } else { + outs() << "blocks are extracted."; + } + outs() << '\n'; + + // Split the module into the two halves of the program we want. + ValueToValueMapTy VMap; + Module *Clone = CloneModule(BD.getProgram(), VMap); + Module *Orig = BD.swapProgramIn(Clone); + std::vector FuncsOnClone; + std::vector BBsOnClone; + for (unsigned i = 0, e = FunctionsBeingTested.size(); i != e; ++i) { + Function *F = cast(VMap[FunctionsBeingTested[i]]); + FuncsOnClone.push_back(F); + } + for (unsigned i = 0, e = BBs.size(); i != e; ++i) { + BasicBlock *BB = cast(VMap[BBs[i]]); + BBsOnClone.push_back(BB); + } + VMap.clear(); + + Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); + Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, + FuncsOnClone, + VMap); + + // Try the extraction. If it doesn't work, then the block extractor crashed + // or something, in which case bugpoint can't chase down this possibility. + if (Module *New = BD.ExtractMappedBlocksFromModule(BBsOnClone, ToOptimize)) { + delete ToOptimize; + // Run the predicate, + // note that the predicate will delete both input modules. + bool Ret = TestFn(BD, New, ToNotOptimize, Error); + delete BD.swapProgramIn(Orig); + return Ret; + } + delete BD.swapProgramIn(Orig); + delete ToOptimize; + delete ToNotOptimize; + return false; +} + + +/// ExtractBlocks - Given a reduced list of functions that still expose the bug, +/// extract as many basic blocks from the region as possible without obscuring +/// the bug. +/// +static bool ExtractBlocks(BugDriver &BD, + bool (*TestFn)(BugDriver &, Module *, Module *, + std::string &), + std::vector &MiscompiledFunctions, + std::string &Error) { + if (BugpointIsInterrupted) return false; + + std::vector Blocks; + for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) + for (Function::iterator I = MiscompiledFunctions[i]->begin(), + E = MiscompiledFunctions[i]->end(); I != E; ++I) + Blocks.push_back(I); + + // Use the list reducer to identify blocks that can be extracted without + // obscuring the bug. The Blocks list will end up containing blocks that must + // be retained from the original program. + unsigned OldSize = Blocks.size(); + + // Check to see if all blocks are extractible first. + bool Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions) + .TestFuncs(std::vector(), Error); + if (!Error.empty()) + return false; + if (Ret) { + Blocks.clear(); + } else { + ReduceMiscompiledBlocks(BD, TestFn, + MiscompiledFunctions).reduceList(Blocks, Error); + if (!Error.empty()) + return false; + if (Blocks.size() == OldSize) + return false; + } + + ValueToValueMapTy VMap; + Module *ProgClone = CloneModule(BD.getProgram(), VMap); + Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, + MiscompiledFunctions, + VMap); + Module *Extracted = BD.ExtractMappedBlocksFromModule(Blocks, ToExtract); + if (Extracted == 0) { + // Weird, extraction should have worked. + errs() << "Nondeterministic problem extracting blocks??\n"; + delete ProgClone; + delete ToExtract; + return false; + } + + // Otherwise, block extraction succeeded. Link the two program fragments back + // together. + delete ToExtract; + + std::vector > MisCompFunctions; + for (Module::iterator I = Extracted->begin(), E = Extracted->end(); + I != E; ++I) + if (!I->isDeclaration()) + MisCompFunctions.push_back(std::make_pair(I->getName(), + I->getFunctionType())); + + std::string ErrorMsg; + if (Linker::LinkModules(ProgClone, Extracted, Linker::DestroySource, + &ErrorMsg)) { + errs() << BD.getToolName() << ": Error linking modules together:" + << ErrorMsg << '\n'; + exit(1); + } + delete Extracted; + + // Set the new program and delete the old one. + BD.setNewProgram(ProgClone); + + // Update the list of miscompiled functions. + MiscompiledFunctions.clear(); + + for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { + Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first); + assert(NewF && "Function not found??"); + MiscompiledFunctions.push_back(NewF); + } + + return true; +} + + +/// DebugAMiscompilation - This is a generic driver to narrow down +/// miscompilations, either in an optimization or a code generator. +/// +static std::vector +DebugAMiscompilation(BugDriver &BD, + bool (*TestFn)(BugDriver &, Module *, Module *, + std::string &), + std::string &Error) { + // Okay, now that we have reduced the list of passes which are causing the + // failure, see if we can pin down which functions are being + // miscompiled... first build a list of all of the non-external functions in + // the program. + std::vector MiscompiledFunctions; + Module *Prog = BD.getProgram(); + for (Module::iterator I = Prog->begin(), E = Prog->end(); I != E; ++I) + if (!I->isDeclaration()) + MiscompiledFunctions.push_back(I); + + // Do the reduction... + if (!BugpointIsInterrupted) + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, + Error); + if (!Error.empty()) { + errs() << "\n***Cannot reduce functions: "; + return MiscompiledFunctions; + } + outs() << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; + PrintFunctionList(MiscompiledFunctions); + outs() << '\n'; + + // See if we can rip any loops out of the miscompiled functions and still + // trigger the problem. + + if (!BugpointIsInterrupted && !DisableLoopExtraction) { + bool Ret = ExtractLoops(BD, TestFn, MiscompiledFunctions, Error); + if (!Error.empty()) + return MiscompiledFunctions; + if (Ret) { + // Okay, we extracted some loops and the problem still appears. See if + // we can eliminate some of the created functions from being candidates. + DisambiguateGlobalSymbols(BD.getProgram()); + + // Do the reduction... + if (!BugpointIsInterrupted) + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, + Error); + if (!Error.empty()) + return MiscompiledFunctions; + + outs() << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; + PrintFunctionList(MiscompiledFunctions); + outs() << '\n'; + } + } + + if (!BugpointIsInterrupted && !DisableBlockExtraction) { + bool Ret = ExtractBlocks(BD, TestFn, MiscompiledFunctions, Error); + if (!Error.empty()) + return MiscompiledFunctions; + if (Ret) { + // Okay, we extracted some blocks and the problem still appears. See if + // we can eliminate some of the created functions from being candidates. + DisambiguateGlobalSymbols(BD.getProgram()); + + // Do the reduction... + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, + Error); + if (!Error.empty()) + return MiscompiledFunctions; + + outs() << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; + PrintFunctionList(MiscompiledFunctions); + outs() << '\n'; + } + } + + return MiscompiledFunctions; +} + +/// TestOptimizer - This is the predicate function used to check to see if the +/// "Test" portion of the program is misoptimized. If so, return true. In any +/// case, both module arguments are deleted. +/// +static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe, + std::string &Error) { + // Run the optimization passes on ToOptimize, producing a transformed version + // of the functions being tested. + outs() << " Optimizing functions being tested: "; + Module *Optimized = BD.runPassesOn(Test, BD.getPassesToRun(), + /*AutoDebugCrashes*/true); + outs() << "done.\n"; + delete Test; + + outs() << " Checking to see if the merged program executes correctly: "; + bool Broken; + Module *New = TestMergedProgram(BD, Optimized, Safe, true, Error, Broken); + if (New) { + outs() << (Broken ? " nope.\n" : " yup.\n"); + // Delete the original and set the new program. + delete BD.swapProgramIn(New); + } + return Broken; +} + + +/// debugMiscompilation - This method is used when the passes selected are not +/// crashing, but the generated output is semantically different from the +/// input. +/// +void BugDriver::debugMiscompilation(std::string *Error) { + // Make sure something was miscompiled... + if (!BugpointIsInterrupted) + if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun, *Error)) { + if (Error->empty()) + errs() << "*** Optimized program matches reference output! No problem" + << " detected...\nbugpoint can't help you with your problem!\n"; + return; + } + + outs() << "\n*** Found miscompiling pass" + << (getPassesToRun().size() == 1 ? "" : "es") << ": " + << getPassesString(getPassesToRun()) << '\n'; + EmitProgressBitcode(Program, "passinput"); + + std::vector MiscompiledFunctions = + DebugAMiscompilation(*this, TestOptimizer, *Error); + if (!Error->empty()) + return; + + // Output a bunch of bitcode files for the user... + outs() << "Outputting reduced bitcode files which expose the problem:\n"; + ValueToValueMapTy VMap; + Module *ToNotOptimize = CloneModule(getProgram(), VMap); + Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, + MiscompiledFunctions, + VMap); + + outs() << " Non-optimized portion: "; + EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true); + delete ToNotOptimize; // Delete hacked module. + + outs() << " Portion that is input to optimizer: "; + EmitProgressBitcode(ToOptimize, "tooptimize"); + delete ToOptimize; // Delete hacked module. + + return; +} + +/// CleanupAndPrepareModules - Get the specified modules ready for code +/// generator testing. +/// +static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, + Module *Safe) { + // Clean up the modules, removing extra cruft that we don't need anymore... + Test = BD.performFinalCleanups(Test); + + // If we are executing the JIT, we have several nasty issues to take care of. + if (!BD.isExecutingJIT()) return; + + // First, if the main function is in the Safe module, we must add a stub to + // the Test module to call into it. Thus, we create a new function `main' + // which just calls the old one. + if (Function *oldMain = Safe->getFunction("main")) + if (!oldMain->isDeclaration()) { + // Rename it + oldMain->setName("llvm_bugpoint_old_main"); + // Create a NEW `main' function with same type in the test module. + Function *newMain = Function::Create(oldMain->getFunctionType(), + GlobalValue::ExternalLinkage, + "main", Test); + // Create an `oldmain' prototype in the test module, which will + // corresponds to the real main function in the same module. + Function *oldMainProto = Function::Create(oldMain->getFunctionType(), + GlobalValue::ExternalLinkage, + oldMain->getName(), Test); + // Set up and remember the argument list for the main function. + std::vector args; + for (Function::arg_iterator + I = newMain->arg_begin(), E = newMain->arg_end(), + OI = oldMain->arg_begin(); I != E; ++I, ++OI) { + I->setName(OI->getName()); // Copy argument names from oldMain + args.push_back(I); + } + + // Call the old main function and return its result + BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain); + CallInst *call = CallInst::Create(oldMainProto, args, "", BB); + + // If the type of old function wasn't void, return value of call + ReturnInst::Create(Safe->getContext(), call, BB); + } + + // The second nasty issue we must deal with in the JIT is that the Safe + // module cannot directly reference any functions defined in the test + // module. Instead, we use a JIT API call to dynamically resolve the + // symbol. + + // Add the resolver to the Safe module. + // Prototype: void *getPointerToNamedFunction(const char* Name) + Constant *resolverFunc = + Safe->getOrInsertFunction("getPointerToNamedFunction", + Type::getInt8PtrTy(Safe->getContext()), + Type::getInt8PtrTy(Safe->getContext()), + (Type *)0); + + // Use the function we just added to get addresses of functions we need. + for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { + if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc && + !F->isIntrinsic() /* ignore intrinsics */) { + Function *TestFn = Test->getFunction(F->getName()); + + // Don't forward functions which are external in the test module too. + if (TestFn && !TestFn->isDeclaration()) { + // 1. Add a string constant with its name to the global file + Constant *InitArray = ConstantArray::get(F->getContext(), F->getName()); + GlobalVariable *funcName = + new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, + GlobalValue::InternalLinkage, InitArray, + F->getName() + "_name"); + + // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an + // sbyte* so it matches the signature of the resolver function. + + // GetElementPtr *funcName, ulong 0, ulong 0 + std::vector GEPargs(2, + Constant::getNullValue(Type::getInt32Ty(F->getContext()))); + Value *GEP = ConstantExpr::getGetElementPtr(funcName, GEPargs); + std::vector ResolverArgs; + ResolverArgs.push_back(GEP); + + // Rewrite uses of F in global initializers, etc. to uses of a wrapper + // function that dynamically resolves the calls to F via our JIT API + if (!F->use_empty()) { + // Create a new global to hold the cached function pointer. + Constant *NullPtr = ConstantPointerNull::get(F->getType()); + GlobalVariable *Cache = + new GlobalVariable(*F->getParent(), F->getType(), + false, GlobalValue::InternalLinkage, + NullPtr,F->getName()+".fpcache"); + + // Construct a new stub function that will re-route calls to F + FunctionType *FuncTy = F->getFunctionType(); + Function *FuncWrapper = Function::Create(FuncTy, + GlobalValue::InternalLinkage, + F->getName() + "_wrapper", + F->getParent()); + BasicBlock *EntryBB = BasicBlock::Create(F->getContext(), + "entry", FuncWrapper); + BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(), + "usecache", FuncWrapper); + BasicBlock *LookupBB = BasicBlock::Create(F->getContext(), + "lookupfp", FuncWrapper); + + // Check to see if we already looked up the value. + Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB); + Value *IsNull = new ICmpInst(*EntryBB, ICmpInst::ICMP_EQ, CachedVal, + NullPtr, "isNull"); + BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB); + + // Resolve the call to function F via the JIT API: + // + // call resolver(GetElementPtr...) + CallInst *Resolver = + CallInst::Create(resolverFunc, ResolverArgs, "resolver", LookupBB); + + // Cast the result from the resolver to correctly-typed function. + CastInst *CastedResolver = + new BitCastInst(Resolver, + PointerType::getUnqual(F->getFunctionType()), + "resolverCast", LookupBB); + + // Save the value in our cache. + new StoreInst(CastedResolver, Cache, LookupBB); + BranchInst::Create(DoCallBB, LookupBB); + + PHINode *FuncPtr = PHINode::Create(NullPtr->getType(), 2, + "fp", DoCallBB); + FuncPtr->addIncoming(CastedResolver, LookupBB); + FuncPtr->addIncoming(CachedVal, EntryBB); + + // Save the argument list. + std::vector Args; + for (Function::arg_iterator i = FuncWrapper->arg_begin(), + e = FuncWrapper->arg_end(); i != e; ++i) + Args.push_back(i); + + // Pass on the arguments to the real function, return its result + if (F->getReturnType()->isVoidTy()) { + CallInst::Create(FuncPtr, Args, "", DoCallBB); + ReturnInst::Create(F->getContext(), DoCallBB); + } else { + CallInst *Call = CallInst::Create(FuncPtr, Args, + "retval", DoCallBB); + ReturnInst::Create(F->getContext(),Call, DoCallBB); + } + + // Use the wrapper function instead of the old function + F->replaceAllUsesWith(FuncWrapper); + } + } + } + } + + if (verifyModule(*Test) || verifyModule(*Safe)) { + errs() << "Bugpoint has a bug, which corrupted a module!!\n"; + abort(); + } +} + + + +/// TestCodeGenerator - This is the predicate function used to check to see if +/// the "Test" portion of the program is miscompiled by the code generator under +/// test. If so, return true. In any case, both module arguments are deleted. +/// +static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, + std::string &Error) { + CleanupAndPrepareModules(BD, Test, Safe); + + sys::Path TestModuleBC("bugpoint.test.bc"); + std::string ErrMsg; + if (TestModuleBC.makeUnique(true, &ErrMsg)) { + errs() << BD.getToolName() << "Error making unique filename: " + << ErrMsg << "\n"; + exit(1); + } + if (BD.writeProgramToFile(TestModuleBC.str(), Test)) { + errs() << "Error writing bitcode to `" << TestModuleBC.str() + << "'\nExiting."; + exit(1); + } + delete Test; + + FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps); + + // Make the shared library + sys::Path SafeModuleBC("bugpoint.safe.bc"); + if (SafeModuleBC.makeUnique(true, &ErrMsg)) { + errs() << BD.getToolName() << "Error making unique filename: " + << ErrMsg << "\n"; + exit(1); + } + + if (BD.writeProgramToFile(SafeModuleBC.str(), Safe)) { + errs() << "Error writing bitcode to `" << SafeModuleBC.str() + << "'\nExiting."; + exit(1); + } + + FileRemover SafeModuleBCRemover(SafeModuleBC.str(), !SaveTemps); + + std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error); + if (!Error.empty()) + return false; + delete Safe; + + FileRemover SharedObjectRemover(SharedObject, !SaveTemps); + + // Run the code generator on the `Test' code, loading the shared library. + // The function returns whether or not the new output differs from reference. + bool Result = BD.diffProgram(BD.getProgram(), TestModuleBC.str(), + SharedObject, false, &Error); + if (!Error.empty()) + return false; + + if (Result) + errs() << ": still failing!\n"; + else + errs() << ": didn't fail.\n"; + + return Result; +} + + +/// debugCodeGenerator - debug errors in LLC, LLI, or CBE. +/// +bool BugDriver::debugCodeGenerator(std::string *Error) { + if ((void*)SafeInterpreter == (void*)Interpreter) { + std::string Result = executeProgramSafely(Program, "bugpoint.safe.out", + Error); + if (Error->empty()) { + outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match " + << "the reference diff. This may be due to a\n front-end " + << "bug or a bug in the original program, but this can also " + << "happen if bugpoint isn't running the program with the " + << "right flags or input.\n I left the result of executing " + << "the program with the \"safe\" backend in this file for " + << "you: '" + << Result << "'.\n"; + } + return true; + } + + DisambiguateGlobalSymbols(Program); + + std::vector Funcs = DebugAMiscompilation(*this, TestCodeGenerator, + *Error); + if (!Error->empty()) + return true; + + // Split the module into the two halves of the program we want. + ValueToValueMapTy VMap; + Module *ToNotCodeGen = CloneModule(getProgram(), VMap); + Module *ToCodeGen = SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, VMap); + + // Condition the modules + CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen); + + sys::Path TestModuleBC("bugpoint.test.bc"); + std::string ErrMsg; + if (TestModuleBC.makeUnique(true, &ErrMsg)) { + errs() << getToolName() << "Error making unique filename: " + << ErrMsg << "\n"; + exit(1); + } + + if (writeProgramToFile(TestModuleBC.str(), ToCodeGen)) { + errs() << "Error writing bitcode to `" << TestModuleBC.str() + << "'\nExiting."; + exit(1); + } + delete ToCodeGen; + + // Make the shared library + sys::Path SafeModuleBC("bugpoint.safe.bc"); + if (SafeModuleBC.makeUnique(true, &ErrMsg)) { + errs() << getToolName() << "Error making unique filename: " + << ErrMsg << "\n"; + exit(1); + } + + if (writeProgramToFile(SafeModuleBC.str(), ToNotCodeGen)) { + errs() << "Error writing bitcode to `" << SafeModuleBC.str() + << "'\nExiting."; + exit(1); + } + std::string SharedObject = compileSharedObject(SafeModuleBC.str(), *Error); + if (!Error->empty()) + return true; + delete ToNotCodeGen; + + outs() << "You can reproduce the problem with the command line: \n"; + if (isExecutingJIT()) { + outs() << " lli -load " << SharedObject << " " << TestModuleBC.str(); + } else { + outs() << " llc " << TestModuleBC.str() << " -o " << TestModuleBC.str() + << ".s\n"; + outs() << " gcc " << SharedObject << " " << TestModuleBC.str() + << ".s -o " << TestModuleBC.str() << ".exe"; +#if defined (HAVE_LINK_R) + outs() << " -Wl,-R."; +#endif + outs() << "\n"; + outs() << " " << TestModuleBC.str() << ".exe"; + } + for (unsigned i = 0, e = InputArgv.size(); i != e; ++i) + outs() << " " << InputArgv[i]; + outs() << '\n'; + outs() << "The shared object was created with:\n llc -march=c " + << SafeModuleBC.str() << " -o temporary.c\n" + << " gcc -xc temporary.c -O2 -o " << SharedObject; + if (TargetTriple.getArch() == Triple::sparc) + outs() << " -G"; // Compile a shared library, `-G' for Sparc + else + outs() << " -fPIC -shared"; // `-shared' for Linux/X86, maybe others + + outs() << " -fno-strict-aliasing\n"; + + return false; +} diff --git a/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp b/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp new file mode 100644 index 000000000000..336c83d7b1f3 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp @@ -0,0 +1,265 @@ +//===- OptimizerDriver.cpp - Allow BugPoint to run passes safely ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an interface that allows bugpoint to run various passes +// without the threat of a buggy pass corrupting bugpoint (of course, bugpoint +// may have its own bugs, but that's another story...). It achieves this by +// forking a copy of itself and having the child process do the optimizations. +// If this client dies, we can always fork a new one. :) +// +//===----------------------------------------------------------------------===// + +#include "BugDriver.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" + +#define DONT_GET_PLUGIN_LOADER_OPTION +#include "llvm/Support/PluginLoader.h" + +#include +using namespace llvm; + +namespace llvm { + extern cl::opt OutputPrefix; +} + +namespace { + // ChildOutput - This option captures the name of the child output file that + // is set up by the parent bugpoint process + cl::opt ChildOutput("child-output", cl::ReallyHidden); +} + +/// writeProgramToFile - This writes the current "Program" to the named bitcode +/// file. If an error occurs, true is returned. +/// +bool BugDriver::writeProgramToFile(const std::string &Filename, + const Module *M) const { + std::string ErrInfo; + tool_output_file Out(Filename.c_str(), ErrInfo, + raw_fd_ostream::F_Binary); + if (ErrInfo.empty()) { + WriteBitcodeToFile(M, Out.os()); + Out.os().close(); + if (!Out.os().has_error()) { + Out.keep(); + return false; + } + } + Out.os().clear_error(); + return true; +} + + +/// EmitProgressBitcode - This function is used to output the current Program +/// to a file named "bugpoint-ID.bc". +/// +void BugDriver::EmitProgressBitcode(const Module *M, + const std::string &ID, + bool NoFlyer) const { + // Output the input to the current pass to a bitcode file, emit a message + // telling the user how to reproduce it: opt -foo blah.bc + // + std::string Filename = OutputPrefix + "-" + ID + ".bc"; + if (writeProgramToFile(Filename, M)) { + errs() << "Error opening file '" << Filename << "' for writing!\n"; + return; + } + + outs() << "Emitted bitcode to '" << Filename << "'\n"; + if (NoFlyer || PassesToRun.empty()) return; + outs() << "\n*** You can reproduce the problem with: "; + if (UseValgrind) outs() << "valgrind "; + outs() << "opt " << Filename << " "; + outs() << getPassesString(PassesToRun) << "\n"; +} + +cl::opt SilencePasses("silence-passes", + cl::desc("Suppress output of running passes (both stdout and stderr)")); + +static cl::list OptArgs("opt-args", cl::Positional, + cl::desc("..."), + cl::ZeroOrMore, cl::PositionalEatsArgs); + +/// runPasses - Run the specified passes on Program, outputting a bitcode file +/// and writing the filename into OutputFile if successful. If the +/// optimizations fail for some reason (optimizer crashes), return true, +/// otherwise return false. If DeleteOutput is set to true, the bitcode is +/// deleted on success, and the filename string is undefined. This prints to +/// outs() a single line message indicating whether compilation was successful +/// or failed. +/// +bool BugDriver::runPasses(Module *Program, + const std::vector &Passes, + std::string &OutputFilename, bool DeleteOutput, + bool Quiet, unsigned NumExtraArgs, + const char * const *ExtraArgs) const { + // setup the output file name + outs().flush(); + sys::Path uniqueFilename(OutputPrefix + "-output.bc"); + std::string ErrMsg; + if (uniqueFilename.makeUnique(true, &ErrMsg)) { + errs() << getToolName() << ": Error making unique filename: " + << ErrMsg << "\n"; + return(1); + } + OutputFilename = uniqueFilename.str(); + + // set up the input file name + sys::Path inputFilename(OutputPrefix + "-input.bc"); + if (inputFilename.makeUnique(true, &ErrMsg)) { + errs() << getToolName() << ": Error making unique filename: " + << ErrMsg << "\n"; + return(1); + } + + std::string ErrInfo; + tool_output_file InFile(inputFilename.c_str(), ErrInfo, + raw_fd_ostream::F_Binary); + + + if (!ErrInfo.empty()) { + errs() << "Error opening bitcode file: " << inputFilename.str() << "\n"; + return 1; + } + WriteBitcodeToFile(Program, InFile.os()); + InFile.os().close(); + if (InFile.os().has_error()) { + errs() << "Error writing bitcode file: " << inputFilename.str() << "\n"; + InFile.os().clear_error(); + return 1; + } + + sys::Path tool = PrependMainExecutablePath("opt", getToolName(), + (void*)"opt"); + if (tool.empty()) { + errs() << "Cannot find `opt' in executable directory!\n"; + return 1; + } + + // Ok, everything that could go wrong before running opt is done. + InFile.keep(); + + // setup the child process' arguments + SmallVector Args; + std::string Opt = tool.str(); + if (UseValgrind) { + Args.push_back("valgrind"); + Args.push_back("--error-exitcode=1"); + Args.push_back("-q"); + Args.push_back(tool.c_str()); + } else + Args.push_back(Opt.c_str()); + + Args.push_back("-o"); + Args.push_back(OutputFilename.c_str()); + for (unsigned i = 0, e = OptArgs.size(); i != e; ++i) + Args.push_back(OptArgs[i].c_str()); + std::vector pass_args; + for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { + pass_args.push_back( std::string("-load")); + pass_args.push_back( PluginLoader::getPlugin(i)); + } + for (std::vector::const_iterator I = Passes.begin(), + E = Passes.end(); I != E; ++I ) + pass_args.push_back( std::string("-") + (*I) ); + for (std::vector::const_iterator I = pass_args.begin(), + E = pass_args.end(); I != E; ++I ) + Args.push_back(I->c_str()); + Args.push_back(inputFilename.c_str()); + for (unsigned i = 0; i < NumExtraArgs; ++i) + Args.push_back(*ExtraArgs); + Args.push_back(0); + + DEBUG(errs() << "\nAbout to run:\t"; + for (unsigned i = 0, e = Args.size()-1; i != e; ++i) + errs() << " " << Args[i]; + errs() << "\n"; + ); + + sys::Path prog; + if (UseValgrind) + prog = sys::Program::FindProgramByName("valgrind"); + else + prog = tool; + + // Redirect stdout and stderr to nowhere if SilencePasses is given + sys::Path Nowhere; + const sys::Path *Redirects[3] = {0, &Nowhere, &Nowhere}; + + int result = sys::Program::ExecuteAndWait(prog, Args.data(), 0, + (SilencePasses ? Redirects : 0), + Timeout, MemoryLimit, &ErrMsg); + + // If we are supposed to delete the bitcode file or if the passes crashed, + // remove it now. This may fail if the file was never created, but that's ok. + if (DeleteOutput || result != 0) + sys::Path(OutputFilename).eraseFromDisk(); + + // Remove the temporary input file as well + inputFilename.eraseFromDisk(); + + if (!Quiet) { + if (result == 0) + outs() << "Success!\n"; + else if (result > 0) + outs() << "Exited with error code '" << result << "'\n"; + else if (result < 0) { + if (result == -1) + outs() << "Execute failed: " << ErrMsg << "\n"; + else + outs() << "Crashed: " << ErrMsg << "\n"; + } + if (result & 0x01000000) + outs() << "Dumped core\n"; + } + + // Was the child successful? + return result != 0; +} + + +/// runPassesOn - Carefully run the specified set of pass on the specified +/// module, returning the transformed module on success, or a null pointer on +/// failure. +Module *BugDriver::runPassesOn(Module *M, + const std::vector &Passes, + bool AutoDebugCrashes, unsigned NumExtraArgs, + const char * const *ExtraArgs) { + std::string BitcodeResult; + if (runPasses(M, Passes, BitcodeResult, false/*delete*/, true/*quiet*/, + NumExtraArgs, ExtraArgs)) { + if (AutoDebugCrashes) { + errs() << " Error running this sequence of passes" + << " on the input program!\n"; + delete swapProgramIn(M); + EmitProgressBitcode(M, "pass-error", false); + exit(debugOptimizerCrash()); + } + return 0; + } + + Module *Ret = ParseInputFile(BitcodeResult, Context); + if (Ret == 0) { + errs() << getToolName() << ": Error reading bitcode file '" + << BitcodeResult << "'!\n"; + exit(1); + } + sys::Path(BitcodeResult).eraseFromDisk(); // No longer need the file on disk + return Ret; +} diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.cpp b/contrib/llvm/tools/bugpoint/ToolRunner.cpp new file mode 100644 index 000000000000..0d98262b4310 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/ToolRunner.cpp @@ -0,0 +1,977 @@ +//===-- ToolRunner.cpp ----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the interfaces described in the ToolRunner.h file. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "toolrunner" +#include "ToolRunner.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Config/config.h" // for HAVE_LINK_R +#include +#include +using namespace llvm; + +namespace llvm { + cl::opt + SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); +} + +namespace { + cl::opt + RemoteClient("remote-client", + cl::desc("Remote execution client (rsh/ssh)")); + + cl::opt + RemoteHost("remote-host", + cl::desc("Remote execution (rsh/ssh) host")); + + cl::opt + RemotePort("remote-port", + cl::desc("Remote execution (rsh/ssh) port")); + + cl::opt + RemoteUser("remote-user", + cl::desc("Remote execution (rsh/ssh) user id")); + + cl::opt + RemoteExtra("remote-extra-options", + cl::desc("Remote execution (rsh/ssh) extra options")); +} + +/// RunProgramWithTimeout - This function provides an alternate interface +/// to the sys::Program::ExecuteAndWait interface. +/// @see sys::Program::ExecuteAndWait +static int RunProgramWithTimeout(const sys::Path &ProgramPath, + const char **Args, + const sys::Path &StdInFile, + const sys::Path &StdOutFile, + const sys::Path &StdErrFile, + unsigned NumSeconds = 0, + unsigned MemoryLimit = 0, + std::string *ErrMsg = 0) { + const sys::Path* redirects[3]; + redirects[0] = &StdInFile; + redirects[1] = &StdOutFile; + redirects[2] = &StdErrFile; + +#if 0 // For debug purposes + { + errs() << "RUN:"; + for (unsigned i = 0; Args[i]; ++i) + errs() << " " << Args[i]; + errs() << "\n"; + } +#endif + + return + sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, + NumSeconds, MemoryLimit, ErrMsg); +} + +/// RunProgramRemotelyWithTimeout - This function runs the given program +/// remotely using the given remote client and the sys::Program::ExecuteAndWait. +/// Returns the remote program exit code or reports a remote client error if it +/// fails. Remote client is required to return 255 if it failed or program exit +/// code otherwise. +/// @see sys::Program::ExecuteAndWait +static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, + const char **Args, + const sys::Path &StdInFile, + const sys::Path &StdOutFile, + const sys::Path &StdErrFile, + unsigned NumSeconds = 0, + unsigned MemoryLimit = 0) { + const sys::Path* redirects[3]; + redirects[0] = &StdInFile; + redirects[1] = &StdOutFile; + redirects[2] = &StdErrFile; + +#if 0 // For debug purposes + { + errs() << "RUN:"; + for (unsigned i = 0; Args[i]; ++i) + errs() << " " << Args[i]; + errs() << "\n"; + } +#endif + + // Run the program remotely with the remote client + int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, + 0, redirects, NumSeconds, MemoryLimit); + + // Has the remote client fail? + if (255 == ReturnCode) { + std::ostringstream OS; + OS << "\nError running remote client:\n "; + for (const char **Arg = Args; *Arg; ++Arg) + OS << " " << *Arg; + OS << "\n"; + + // The error message is in the output file, let's print it out from there. + std::ifstream ErrorFile(StdOutFile.c_str()); + if (ErrorFile) { + std::copy(std::istreambuf_iterator(ErrorFile), + std::istreambuf_iterator(), + std::ostreambuf_iterator(OS)); + ErrorFile.close(); + } + + errs() << OS; + } + + return ReturnCode; +} + +static std::string ProcessFailure(sys::Path ProgPath, const char** Args, + unsigned Timeout = 0, + unsigned MemoryLimit = 0) { + std::ostringstream OS; + OS << "\nError running tool:\n "; + for (const char **Arg = Args; *Arg; ++Arg) + OS << " " << *Arg; + OS << "\n"; + + // Rerun the compiler, capturing any error messages to print them. + sys::Path ErrorFilename("bugpoint.program_error_messages"); + std::string ErrMsg; + if (ErrorFilename.makeUnique(true, &ErrMsg)) { + errs() << "Error making unique filename: " << ErrMsg << "\n"; + exit(1); + } + RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, + ErrorFilename, Timeout, MemoryLimit); + // FIXME: check return code ? + + // Print out the error messages generated by GCC if possible... + std::ifstream ErrorFile(ErrorFilename.c_str()); + if (ErrorFile) { + std::copy(std::istreambuf_iterator(ErrorFile), + std::istreambuf_iterator(), + std::ostreambuf_iterator(OS)); + ErrorFile.close(); + } + + ErrorFilename.eraseFromDisk(); + return OS.str(); +} + +//===---------------------------------------------------------------------===// +// LLI Implementation of AbstractIntepreter interface +// +namespace { + class LLI : public AbstractInterpreter { + std::string LLIPath; // The path to the LLI executable + std::vector ToolArgs; // Args to pass to LLI + public: + LLI(const std::string &Path, const std::vector *Args) + : LLIPath(Path) { + ToolArgs.clear (); + if (Args) { ToolArgs = *Args; } + } + + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs, + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + }; +} + +int LLI::ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs, + const std::vector &SharedLibs, + unsigned Timeout, + unsigned MemoryLimit) { + std::vector LLIArgs; + LLIArgs.push_back(LLIPath.c_str()); + LLIArgs.push_back("-force-interpreter=true"); + + for (std::vector::const_iterator i = SharedLibs.begin(), + e = SharedLibs.end(); i != e; ++i) { + LLIArgs.push_back("-load"); + LLIArgs.push_back((*i).c_str()); + } + + // Add any extra LLI args. + for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) + LLIArgs.push_back(ToolArgs[i].c_str()); + + LLIArgs.push_back(Bitcode.c_str()); + // Add optional parameters to the running program from Argv + for (unsigned i=0, e = Args.size(); i != e; ++i) + LLIArgs.push_back(Args[i].c_str()); + LLIArgs.push_back(0); + + outs() << ""; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; + for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) + errs() << " " << LLIArgs[i]; + errs() << "\n"; + ); + return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], + sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), + Timeout, MemoryLimit, Error); +} + +// LLI create method - Try to find the LLI executable +AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, + std::string &Message, + const std::vector *ToolArgs) { + std::string LLIPath = + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI).str(); + if (!LLIPath.empty()) { + Message = "Found lli: " + LLIPath + "\n"; + return new LLI(LLIPath, ToolArgs); + } + + Message = "Cannot find `lli' in executable directory!\n"; + return 0; +} + +//===---------------------------------------------------------------------===// +// Custom compiler command implementation of AbstractIntepreter interface +// +// Allows using a custom command for compiling the bitcode, thus allows, for +// example, to compile a bitcode fragment without linking or executing, then +// using a custom wrapper script to check for compiler errors. +namespace { + class CustomCompiler : public AbstractInterpreter { + std::string CompilerCommand; + std::vector CompilerArgs; + public: + CustomCompiler( + const std::string &CompilerCmd, std::vector CompArgs) : + CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} + + virtual void compileProgram(const std::string &Bitcode, + std::string *Error, + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = + std::vector(), + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0) { + *Error = "Execution not supported with -compile-custom"; + return -1; + } + }; +} + +void CustomCompiler::compileProgram(const std::string &Bitcode, + std::string *Error, + unsigned Timeout, + unsigned MemoryLimit) { + + std::vector ProgramArgs; + ProgramArgs.push_back(CompilerCommand.c_str()); + + for (std::size_t i = 0; i < CompilerArgs.size(); ++i) + ProgramArgs.push_back(CompilerArgs.at(i).c_str()); + ProgramArgs.push_back(Bitcode.c_str()); + ProgramArgs.push_back(0); + + // Add optional parameters to the running program from Argv + for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) + ProgramArgs.push_back(CompilerArgs[i].c_str()); + + if (RunProgramWithTimeout( sys::Path(CompilerCommand), &ProgramArgs[0], + sys::Path(), sys::Path(), sys::Path(), + Timeout, MemoryLimit, Error)) + *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0], + Timeout, MemoryLimit); +} + +//===---------------------------------------------------------------------===// +// Custom execution command implementation of AbstractIntepreter interface +// +// Allows using a custom command for executing the bitcode, thus allows, +// for example, to invoke a cross compiler for code generation followed by +// a simulator that executes the generated binary. +namespace { + class CustomExecutor : public AbstractInterpreter { + std::string ExecutionCommand; + std::vector ExecutorArgs; + public: + CustomExecutor( + const std::string &ExecutionCmd, std::vector ExecArgs) : + ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} + + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs, + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + }; +} + +int CustomExecutor::ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs, + const std::vector &SharedLibs, + unsigned Timeout, + unsigned MemoryLimit) { + + std::vector ProgramArgs; + ProgramArgs.push_back(ExecutionCommand.c_str()); + + for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) + ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); + ProgramArgs.push_back(Bitcode.c_str()); + ProgramArgs.push_back(0); + + // Add optional parameters to the running program from Argv + for (unsigned i = 0, e = Args.size(); i != e; ++i) + ProgramArgs.push_back(Args[i].c_str()); + + return RunProgramWithTimeout( + sys::Path(ExecutionCommand), + &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), + sys::Path(OutputFile), Timeout, MemoryLimit, Error); +} + +// Tokenize the CommandLine to the command and the args to allow +// defining a full command line as the command instead of just the +// executed program. We cannot just pass the whole string after the command +// as a single argument because then program sees only a single +// command line argument (with spaces in it: "foo bar" instead +// of "foo" and "bar"). +// +// code borrowed from: +// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html +static void lexCommand(std::string &Message, const std::string &CommandLine, + std::string &CmdPath, std::vector Args) { + + std::string Command = ""; + std::string delimiters = " "; + + std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0); + std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos); + + while (std::string::npos != pos || std::string::npos != lastPos) { + std::string token = CommandLine.substr(lastPos, pos - lastPos); + if (Command == "") + Command = token; + else + Args.push_back(token); + // Skip delimiters. Note the "not_of" + lastPos = CommandLine.find_first_not_of(delimiters, pos); + // Find next "non-delimiter" + pos = CommandLine.find_first_of(delimiters, lastPos); + } + + CmdPath = sys::Program::FindProgramByName(Command).str(); + if (CmdPath.empty()) { + Message = + std::string("Cannot find '") + Command + + "' in PATH!\n"; + return; + } + + Message = "Found command in: " + CmdPath + "\n"; +} + +// Custom execution environment create method, takes the execution command +// as arguments +AbstractInterpreter *AbstractInterpreter::createCustomCompiler( + std::string &Message, + const std::string &CompileCommandLine) { + + std::string CmdPath; + std::vector Args; + lexCommand(Message, CompileCommandLine, CmdPath, Args); + if (CmdPath.empty()) + return 0; + + return new CustomCompiler(CmdPath, Args); +} + +// Custom execution environment create method, takes the execution command +// as arguments +AbstractInterpreter *AbstractInterpreter::createCustomExecutor( + std::string &Message, + const std::string &ExecCommandLine) { + + + std::string CmdPath; + std::vector Args; + lexCommand(Message, ExecCommandLine, CmdPath, Args); + if (CmdPath.empty()) + return 0; + + return new CustomExecutor(CmdPath, Args); +} + +//===----------------------------------------------------------------------===// +// LLC Implementation of AbstractIntepreter interface +// +GCC::FileType LLC::OutputCode(const std::string &Bitcode, + sys::Path &OutputAsmFile, std::string &Error, + unsigned Timeout, unsigned MemoryLimit) { + const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); + sys::Path uniqueFile(Bitcode + Suffix); + std::string ErrMsg; + if (uniqueFile.makeUnique(true, &ErrMsg)) { + errs() << "Error making unique filename: " << ErrMsg << "\n"; + exit(1); + } + OutputAsmFile = uniqueFile; + std::vector LLCArgs; + LLCArgs.push_back(LLCPath.c_str()); + + // Add any extra LLC args. + for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) + LLCArgs.push_back(ToolArgs[i].c_str()); + + LLCArgs.push_back("-o"); + LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file + LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode + + if (UseIntegratedAssembler) + LLCArgs.push_back("-filetype=obj"); + + LLCArgs.push_back (0); + + outs() << (UseIntegratedAssembler ? "" : ""); + outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; + for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) + errs() << " " << LLCArgs[i]; + errs() << "\n"; + ); + if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], + sys::Path(), sys::Path(), sys::Path(), + Timeout, MemoryLimit)) + Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], + Timeout, MemoryLimit); + return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; +} + +void LLC::compileProgram(const std::string &Bitcode, std::string *Error, + unsigned Timeout, unsigned MemoryLimit) { + sys::Path OutputAsmFile; + OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); + OutputAsmFile.eraseFromDisk(); +} + +int LLC::ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &ArgsForGCC, + const std::vector &SharedLibs, + unsigned Timeout, + unsigned MemoryLimit) { + + sys::Path OutputAsmFile; + GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, + MemoryLimit); + FileRemover OutFileRemover(OutputAsmFile.str(), !SaveTemps); + + std::vector GCCArgs(ArgsForGCC); + GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); + + // Assuming LLC worked, compile the result with GCC and run it. + return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, + InputFile, OutputFile, Error, GCCArgs, + Timeout, MemoryLimit); +} + +/// createLLC - Try to find the LLC executable +/// +LLC *AbstractInterpreter::createLLC(const char *Argv0, + std::string &Message, + const std::string &GCCBinary, + const std::vector *Args, + const std::vector *GCCArgs, + bool UseIntegratedAssembler) { + std::string LLCPath = + PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str(); + if (LLCPath.empty()) { + Message = "Cannot find `llc' in executable directory!\n"; + return 0; + } + + Message = "Found llc: " + LLCPath + "\n"; + GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); + if (!gcc) { + errs() << Message << "\n"; + exit(1); + } + return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); +} + +//===---------------------------------------------------------------------===// +// JIT Implementation of AbstractIntepreter interface +// +namespace { + class JIT : public AbstractInterpreter { + std::string LLIPath; // The path to the LLI executable + std::vector ToolArgs; // Args to pass to LLI + public: + JIT(const std::string &Path, const std::vector *Args) + : LLIPath(Path) { + ToolArgs.clear (); + if (Args) { ToolArgs = *Args; } + } + + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = + std::vector(), + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + }; +} + +int JIT::ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs, + const std::vector &SharedLibs, + unsigned Timeout, + unsigned MemoryLimit) { + // Construct a vector of parameters, incorporating those from the command-line + std::vector JITArgs; + JITArgs.push_back(LLIPath.c_str()); + JITArgs.push_back("-force-interpreter=false"); + + // Add any extra LLI args. + for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) + JITArgs.push_back(ToolArgs[i].c_str()); + + for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { + JITArgs.push_back("-load"); + JITArgs.push_back(SharedLibs[i].c_str()); + } + JITArgs.push_back(Bitcode.c_str()); + // Add optional parameters to the running program from Argv + for (unsigned i=0, e = Args.size(); i != e; ++i) + JITArgs.push_back(Args[i].c_str()); + JITArgs.push_back(0); + + outs() << ""; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; + for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) + errs() << " " << JITArgs[i]; + errs() << "\n"; + ); + DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); + return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], + sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), + Timeout, MemoryLimit, Error); +} + +/// createJIT - Try to find the LLI executable +/// +AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, + std::string &Message, const std::vector *Args) { + std::string LLIPath = + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT).str(); + if (!LLIPath.empty()) { + Message = "Found lli: " + LLIPath + "\n"; + return new JIT(LLIPath, Args); + } + + Message = "Cannot find `lli' in executable directory!\n"; + return 0; +} + +GCC::FileType CBE::OutputCode(const std::string &Bitcode, + sys::Path &OutputCFile, std::string &Error, + unsigned Timeout, unsigned MemoryLimit) { + sys::Path uniqueFile(Bitcode+".cbe.c"); + std::string ErrMsg; + if (uniqueFile.makeUnique(true, &ErrMsg)) { + errs() << "Error making unique filename: " << ErrMsg << "\n"; + exit(1); + } + OutputCFile = uniqueFile; + std::vector LLCArgs; + LLCArgs.push_back(LLCPath.c_str()); + + // Add any extra LLC args. + for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) + LLCArgs.push_back(ToolArgs[i].c_str()); + + LLCArgs.push_back("-o"); + LLCArgs.push_back(OutputCFile.c_str()); // Output to the C file + LLCArgs.push_back("-march=c"); // Output C language + LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode + LLCArgs.push_back(0); + + outs() << ""; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; + for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) + errs() << " " << LLCArgs[i]; + errs() << "\n"; + ); + if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), + sys::Path(), Timeout, MemoryLimit)) + Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); + return GCC::CFile; +} + +void CBE::compileProgram(const std::string &Bitcode, std::string *Error, + unsigned Timeout, unsigned MemoryLimit) { + sys::Path OutputCFile; + OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); + OutputCFile.eraseFromDisk(); +} + +int CBE::ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &ArgsForGCC, + const std::vector &SharedLibs, + unsigned Timeout, + unsigned MemoryLimit) { + sys::Path OutputCFile; + OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); + + FileRemover CFileRemove(OutputCFile.str(), !SaveTemps); + + std::vector GCCArgs(ArgsForGCC); + GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); + + return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, + InputFile, OutputFile, Error, GCCArgs, + Timeout, MemoryLimit); +} + +/// createCBE - Try to find the 'llc' executable +/// +CBE *AbstractInterpreter::createCBE(const char *Argv0, + std::string &Message, + const std::string &GCCBinary, + const std::vector *Args, + const std::vector *GCCArgs) { + sys::Path LLCPath = + PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createCBE); + if (LLCPath.isEmpty()) { + Message = + "Cannot find `llc' in executable directory!\n"; + return 0; + } + + Message = "Found llc: " + LLCPath.str() + "\n"; + GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); + if (!gcc) { + errs() << Message << "\n"; + exit(1); + } + return new CBE(LLCPath, gcc, Args); +} + +//===---------------------------------------------------------------------===// +// GCC abstraction +// + +static bool IsARMArchitecture(std::vector Args) { + for (std::vector::const_iterator + I = Args.begin(), E = Args.end(); I != E; ++I) { + if (StringRef(*I).equals_lower("-arch")) { + ++I; + if (I != E && StringRef(*I).substr(0, strlen("arm")).equals_lower("arm")) + return true; + } + } + + return false; +} + +int GCC::ExecuteProgram(const std::string &ProgramFile, + const std::vector &Args, + FileType fileType, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &ArgsForGCC, + unsigned Timeout, + unsigned MemoryLimit) { + std::vector GCCArgs; + + GCCArgs.push_back(GCCPath.c_str()); + + if (TargetTriple.getArch() == Triple::x86) + GCCArgs.push_back("-m32"); + + for (std::vector::const_iterator + I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) + GCCArgs.push_back(I->c_str()); + + // Specify -x explicitly in case the extension is wonky + if (fileType != ObjectFile) { + GCCArgs.push_back("-x"); + if (fileType == CFile) { + GCCArgs.push_back("c"); + GCCArgs.push_back("-fno-strict-aliasing"); + } else { + GCCArgs.push_back("assembler"); + + // For ARM architectures we don't want this flag. bugpoint isn't + // explicitly told what architecture it is working on, so we get + // it from gcc flags + if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs)) + GCCArgs.push_back("-force_cpusubtype_ALL"); + } + } + + GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. + + GCCArgs.push_back("-x"); + GCCArgs.push_back("none"); + GCCArgs.push_back("-o"); + sys::Path OutputBinary (ProgramFile+".gcc.exe"); + std::string ErrMsg; + if (OutputBinary.makeUnique(true, &ErrMsg)) { + errs() << "Error making unique filename: " << ErrMsg << "\n"; + exit(1); + } + GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... + + // Add any arguments intended for GCC. We locate them here because this is + // most likely -L and -l options that need to come before other libraries but + // after the source. Other options won't be sensitive to placement on the + // command line, so this should be safe. + for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) + GCCArgs.push_back(ArgsForGCC[i].c_str()); + + GCCArgs.push_back("-lm"); // Hard-code the math library... + GCCArgs.push_back("-O2"); // Optimize the program a bit... +#if defined (HAVE_LINK_R) + GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files +#endif + if (TargetTriple.getArch() == Triple::sparc) + GCCArgs.push_back("-mcpu=v9"); + GCCArgs.push_back(0); // NULL terminator + + outs() << ""; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; + for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) + errs() << " " << GCCArgs[i]; + errs() << "\n"; + ); + if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), + sys::Path())) { + *Error = ProcessFailure(GCCPath, &GCCArgs[0]); + return -1; + } + + std::vector ProgramArgs; + + // Declared here so that the destructor only runs after + // ProgramArgs is used. + std::string Exec; + + if (RemoteClientPath.isEmpty()) + ProgramArgs.push_back(OutputBinary.c_str()); + else { + ProgramArgs.push_back(RemoteClientPath.c_str()); + ProgramArgs.push_back(RemoteHost.c_str()); + if (!RemoteUser.empty()) { + ProgramArgs.push_back("-l"); + ProgramArgs.push_back(RemoteUser.c_str()); + } + if (!RemotePort.empty()) { + ProgramArgs.push_back("-p"); + ProgramArgs.push_back(RemotePort.c_str()); + } + if (!RemoteExtra.empty()) { + ProgramArgs.push_back(RemoteExtra.c_str()); + } + + // Full path to the binary. We need to cd to the exec directory because + // there is a dylib there that the exec expects to find in the CWD + char* env_pwd = getenv("PWD"); + Exec = "cd "; + Exec += env_pwd; + Exec += "; ./"; + Exec += OutputBinary.c_str(); + ProgramArgs.push_back(Exec.c_str()); + } + + // Add optional parameters to the running program from Argv + for (unsigned i = 0, e = Args.size(); i != e; ++i) + ProgramArgs.push_back(Args[i].c_str()); + ProgramArgs.push_back(0); // NULL terminator + + // Now that we have a binary, run it! + outs() << ""; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; + for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) + errs() << " " << ProgramArgs[i]; + errs() << "\n"; + ); + + FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); + + if (RemoteClientPath.isEmpty()) { + DEBUG(errs() << ""); + int ExitCode = RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], + sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), + Timeout, MemoryLimit, Error); + // Treat a signal (usually SIGSEGV) or timeout as part of the program output + // so that crash-causing miscompilation is handled seamlessly. + if (ExitCode < -1) { + std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); + outFile << *Error << '\n'; + outFile.close(); + Error->clear(); + } + return ExitCode; + } else { + outs() << ""; outs().flush(); + return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), + &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), + sys::Path(OutputFile), Timeout, MemoryLimit); + } +} + +int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, + std::string &OutputFile, + const std::vector &ArgsForGCC, + std::string &Error) { + sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); + std::string ErrMsg; + if (uniqueFilename.makeUnique(true, &ErrMsg)) { + errs() << "Error making unique filename: " << ErrMsg << "\n"; + exit(1); + } + OutputFile = uniqueFilename.str(); + + std::vector GCCArgs; + + GCCArgs.push_back(GCCPath.c_str()); + + if (TargetTriple.getArch() == Triple::x86) + GCCArgs.push_back("-m32"); + + for (std::vector::const_iterator + I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) + GCCArgs.push_back(I->c_str()); + + // Compile the C/asm file into a shared object + if (fileType != ObjectFile) { + GCCArgs.push_back("-x"); + GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); + } + GCCArgs.push_back("-fno-strict-aliasing"); + GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. + GCCArgs.push_back("-x"); + GCCArgs.push_back("none"); + if (TargetTriple.getArch() == Triple::sparc) + GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc + else if (TargetTriple.isOSDarwin()) { + // link all source files into a single module in data segment, rather than + // generating blocks. dynamic_lookup requires that you set + // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for + // bugpoint to just pass that in the environment of GCC. + GCCArgs.push_back("-single_module"); + GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC + GCCArgs.push_back("-undefined"); + GCCArgs.push_back("dynamic_lookup"); + } else + GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others + + if ((TargetTriple.getArch() == Triple::alpha) || + (TargetTriple.getArch() == Triple::x86_64)) + GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC + + if (TargetTriple.getArch() == Triple::sparc) + GCCArgs.push_back("-mcpu=v9"); + + GCCArgs.push_back("-o"); + GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. + GCCArgs.push_back("-O2"); // Optimize the program a bit. + + + + // Add any arguments intended for GCC. We locate them here because this is + // most likely -L and -l options that need to come before other libraries but + // after the source. Other options won't be sensitive to placement on the + // command line, so this should be safe. + for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) + GCCArgs.push_back(ArgsForGCC[i].c_str()); + GCCArgs.push_back(0); // NULL terminator + + + + outs() << ""; outs().flush(); + DEBUG(errs() << "\nAbout to run:\t"; + for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) + errs() << " " << GCCArgs[i]; + errs() << "\n"; + ); + if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), + sys::Path())) { + Error = ProcessFailure(GCCPath, &GCCArgs[0]); + return 1; + } + return 0; +} + +/// create - Try to find the `gcc' executable +/// +GCC *GCC::create(std::string &Message, + const std::string &GCCBinary, + const std::vector *Args) { + sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); + if (GCCPath.isEmpty()) { + Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; + return 0; + } + + sys::Path RemoteClientPath; + if (!RemoteClient.empty()) + RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); + + Message = "Found gcc: " + GCCPath.str() + "\n"; + return new GCC(GCCPath, RemoteClientPath, Args); +} diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.h b/contrib/llvm/tools/bugpoint/ToolRunner.h new file mode 100644 index 000000000000..cfa8acf6b240 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/ToolRunner.h @@ -0,0 +1,247 @@ +//===-- tools/bugpoint/ToolRunner.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an abstraction around a platform C compiler, used to +// compile C and assembly code. It also exposes an "AbstractIntepreter" +// interface, which is used to execute code using one of the LLVM execution +// engines. +// +//===----------------------------------------------------------------------===// + +#ifndef BUGPOINT_TOOLRUNNER_H +#define BUGPOINT_TOOLRUNNER_H + +#include "llvm/ADT/Triple.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/Path.h" +#include +#include + +namespace llvm { + +extern cl::opt SaveTemps; +extern Triple TargetTriple; + +class CBE; +class LLC; + +//===---------------------------------------------------------------------===// +// GCC abstraction +// +class GCC { + sys::Path GCCPath; // The path to the gcc executable. + sys::Path RemoteClientPath; // The path to the rsh / ssh executable. + std::vector gccArgs; // GCC-specific arguments. + GCC(const sys::Path &gccPath, const sys::Path &RemotePath, + const std::vector *GCCArgs) + : GCCPath(gccPath), RemoteClientPath(RemotePath) { + if (GCCArgs) gccArgs = *GCCArgs; + } +public: + enum FileType { AsmFile, ObjectFile, CFile }; + + static GCC *create(std::string &Message, + const std::string &GCCBinary, + const std::vector *Args); + + /// ExecuteProgram - Execute the program specified by "ProgramFile" (which is + /// either a .s file, or a .c file, specified by FileType), with the specified + /// arguments. Standard input is specified with InputFile, and standard + /// Output is captured to the specified OutputFile location. The SharedLibs + /// option specifies optional native shared objects that can be loaded into + /// the program for execution. + /// + int ExecuteProgram(const std::string &ProgramFile, + const std::vector &Args, + FileType fileType, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error = 0, + const std::vector &GCCArgs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + + /// MakeSharedObject - This compiles the specified file (which is either a .c + /// file or a .s file) into a shared object. + /// + int MakeSharedObject(const std::string &InputFile, FileType fileType, + std::string &OutputFile, + const std::vector &ArgsForGCC, + std::string &Error); +}; + + +//===---------------------------------------------------------------------===// +/// AbstractInterpreter Class - Subclasses of this class are used to execute +/// LLVM bitcode in a variety of ways. This abstract interface hides this +/// complexity behind a simple interface. +/// +class AbstractInterpreter { +public: + static CBE *createCBE(const char *Argv0, std::string &Message, + const std::string &GCCBinary, + const std::vector *Args = 0, + const std::vector *GCCArgs = 0); + static LLC *createLLC(const char *Argv0, std::string &Message, + const std::string &GCCBinary, + const std::vector *Args = 0, + const std::vector *GCCArgs = 0, + bool UseIntegratedAssembler = false); + + static AbstractInterpreter* createLLI(const char *Argv0, std::string &Message, + const std::vector *Args=0); + + static AbstractInterpreter* createJIT(const char *Argv0, std::string &Message, + const std::vector *Args=0); + + static AbstractInterpreter* + createCustomCompiler(std::string &Message, + const std::string &CompileCommandLine); + + static AbstractInterpreter* + createCustomExecutor(std::string &Message, + const std::string &ExecCommandLine); + + + virtual ~AbstractInterpreter() {} + + /// compileProgram - Compile the specified program from bitcode to executable + /// code. This does not produce any output, it is only used when debugging + /// the code generator. It returns false if the code generator fails. + virtual void compileProgram(const std::string &Bitcode, std::string *Error, + unsigned Timeout = 0, unsigned MemoryLimit = 0) {} + + /// OutputCode - Compile the specified program from bitcode to code + /// understood by the GCC driver (either C or asm). If the code generator + /// fails, it sets Error, otherwise, this function returns the type of code + /// emitted. + virtual GCC::FileType OutputCode(const std::string &Bitcode, + sys::Path &OutFile, std::string &Error, + unsigned Timeout = 0, + unsigned MemoryLimit = 0) { + Error = "OutputCode not supported by this AbstractInterpreter!"; + return GCC::AsmFile; + } + + /// ExecuteProgram - Run the specified bitcode file, emitting output to the + /// specified filename. This sets RetVal to the exit code of the program or + /// returns false if a problem was encountered that prevented execution of + /// the program. + /// + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = + std::vector(), + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0) = 0; +}; + +//===---------------------------------------------------------------------===// +// CBE Implementation of AbstractIntepreter interface +// +class CBE : public AbstractInterpreter { + sys::Path LLCPath; // The path to the `llc' executable. + std::vector ToolArgs; // Extra args to pass to LLC. + GCC *gcc; +public: + CBE(const sys::Path &llcPath, GCC *Gcc, + const std::vector *Args) + : LLCPath(llcPath), gcc(Gcc) { + ToolArgs.clear (); + if (Args) ToolArgs = *Args; + } + ~CBE() { delete gcc; } + + /// compileProgram - Compile the specified program from bitcode to executable + /// code. This does not produce any output, it is only used when debugging + /// the code generator. Returns false if the code generator fails. + virtual void compileProgram(const std::string &Bitcode, std::string *Error, + unsigned Timeout = 0, unsigned MemoryLimit = 0); + + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = + std::vector(), + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + + /// OutputCode - Compile the specified program from bitcode to code + /// understood by the GCC driver (either C or asm). If the code generator + /// fails, it sets Error, otherwise, this function returns the type of code + /// emitted. + virtual GCC::FileType OutputCode(const std::string &Bitcode, + sys::Path &OutFile, std::string &Error, + unsigned Timeout = 0, + unsigned MemoryLimit = 0); +}; + + +//===---------------------------------------------------------------------===// +// LLC Implementation of AbstractIntepreter interface +// +class LLC : public AbstractInterpreter { + std::string LLCPath; // The path to the LLC executable. + std::vector ToolArgs; // Extra args to pass to LLC. + GCC *gcc; + bool UseIntegratedAssembler; +public: + LLC(const std::string &llcPath, GCC *Gcc, + const std::vector *Args, + bool useIntegratedAssembler) + : LLCPath(llcPath), gcc(Gcc), + UseIntegratedAssembler(useIntegratedAssembler) { + ToolArgs.clear(); + if (Args) ToolArgs = *Args; + } + ~LLC() { delete gcc; } + + /// compileProgram - Compile the specified program from bitcode to executable + /// code. This does not produce any output, it is only used when debugging + /// the code generator. Returns false if the code generator fails. + virtual void compileProgram(const std::string &Bitcode, std::string *Error, + unsigned Timeout = 0, unsigned MemoryLimit = 0); + + virtual int ExecuteProgram(const std::string &Bitcode, + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = + std::vector(), + const std::vector &SharedLibs = + std::vector(), + unsigned Timeout = 0, + unsigned MemoryLimit = 0); + + /// OutputCode - Compile the specified program from bitcode to code + /// understood by the GCC driver (either C or asm). If the code generator + /// fails, it sets Error, otherwise, this function returns the type of code + /// emitted. + virtual GCC::FileType OutputCode(const std::string &Bitcode, + sys::Path &OutFile, std::string &Error, + unsigned Timeout = 0, + unsigned MemoryLimit = 0); +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/tools/bugpoint/bugpoint.cpp b/contrib/llvm/tools/bugpoint/bugpoint.cpp new file mode 100644 index 000000000000..6a87521a17b6 --- /dev/null +++ b/contrib/llvm/tools/bugpoint/bugpoint.cpp @@ -0,0 +1,209 @@ +//===- bugpoint.cpp - The LLVM Bugpoint utility ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program is an automated compiler debugger tool. It is used to narrow +// down miscompilations and crash problems to a specific pass in the compiler, +// and the specific Module or Function input that is causing the problem. +// +//===----------------------------------------------------------------------===// + +#include "BugDriver.h" +#include "ToolRunner.h" +#include "llvm/LinkAllPasses.h" +#include "llvm/LLVMContext.h" +#include "llvm/PassManager.h" +#include "llvm/Support/PassNameParser.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Valgrind.h" +#include "llvm/LinkAllVMCore.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" + +//Enable this macro to debug bugpoint itself. +//#define DEBUG_BUGPOINT 1 + +using namespace llvm; + +static cl::opt +FindBugs("find-bugs", cl::desc("Run many different optimization sequences " + "on program to find bugs"), cl::init(false)); + +static cl::list +InputFilenames(cl::Positional, cl::OneOrMore, + cl::desc("")); + +static cl::opt +TimeoutValue("timeout", cl::init(300), cl::value_desc("seconds"), + cl::desc("Number of seconds program is allowed to run before it " + "is killed (default is 300s), 0 disables timeout")); + +static cl::opt +MemoryLimit("mlimit", cl::init(-1), cl::value_desc("MBytes"), + cl::desc("Maximum amount of memory to use. 0 disables check." + " Defaults to 100MB (800MB under valgrind).")); + +static cl::opt +UseValgrind("enable-valgrind", + cl::desc("Run optimizations through valgrind")); + +// The AnalysesList is automatically populated with registered Passes by the +// PassNameParser. +// +static cl::list +PassList(cl::desc("Passes available:"), cl::ZeroOrMore); + +static cl::opt +StandardCompileOpts("std-compile-opts", + cl::desc("Include the standard compile time optimizations")); + +static cl::opt +StandardLinkOpts("std-link-opts", + cl::desc("Include the standard link time optimizations")); + +static cl::opt +OptLevelO1("O1", + cl::desc("Optimization level 1. Similar to llvm-gcc -O1")); + +static cl::opt +OptLevelO2("O2", + cl::desc("Optimization level 2. Similar to llvm-gcc -O2")); + +static cl::opt +OptLevelO3("O3", + cl::desc("Optimization level 3. Similar to llvm-gcc -O3")); + +static cl::opt +OverrideTriple("mtriple", cl::desc("Override target triple for module")); + +/// BugpointIsInterrupted - Set to true when the user presses ctrl-c. +bool llvm::BugpointIsInterrupted = false; + +#ifndef DEBUG_BUGPOINT +static void BugpointInterruptFunction() { + BugpointIsInterrupted = true; +} +#endif + +// Hack to capture a pass list. +namespace { + class AddToDriver : public FunctionPassManager { + BugDriver &D; + public: + AddToDriver(BugDriver &_D) : FunctionPassManager(0), D(_D) {} + + virtual void add(Pass *P) { + const void *ID = P->getPassID(); + const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID); + D.addPass(PI->getPassArgument()); + } + }; +} + +int main(int argc, char **argv) { +#ifndef DEBUG_BUGPOINT + llvm::sys::PrintStackTraceOnErrorSignal(); + llvm::PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. +#endif + + // Initialize passes + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeScalarOpts(Registry); + initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + initializeInstrumentation(Registry); + initializeTarget(Registry); + + cl::ParseCommandLineOptions(argc, argv, + "LLVM automatic testcase reducer. See\nhttp://" + "llvm.org/cmds/bugpoint.html" + " for more information.\n"); +#ifndef DEBUG_BUGPOINT + sys::SetInterruptFunction(BugpointInterruptFunction); +#endif + + LLVMContext& Context = getGlobalContext(); + // If we have an override, set it and then track the triple we want Modules + // to use. + if (!OverrideTriple.empty()) { + TargetTriple.setTriple(Triple::normalize(OverrideTriple)); + outs() << "Override triple set to '" << TargetTriple.getTriple() << "'\n"; + } + + if (MemoryLimit < 0) { + // Set the default MemoryLimit. Be sure to update the flag's description if + // you change this. + if (sys::RunningOnValgrind() || UseValgrind) + MemoryLimit = 800; + else + MemoryLimit = 100; + } + + BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, + UseValgrind, Context); + if (D.addSources(InputFilenames)) return 1; + + AddToDriver PM(D); + if (StandardCompileOpts) { + PassManagerBuilder Builder; + Builder.OptLevel = 3; + Builder.Inliner = createFunctionInliningPass(); + Builder.populateModulePassManager(PM); + } + + if (StandardLinkOpts) { + PassManagerBuilder Builder; + Builder.populateLTOPassManager(PM, /*Internalize=*/true, + /*RunInliner=*/true); + } + + if (OptLevelO1 || OptLevelO2 || OptLevelO3) { + PassManagerBuilder Builder; + if (OptLevelO1) + Builder.Inliner = createAlwaysInlinerPass(); + else if (OptLevelO2) + Builder.Inliner = createFunctionInliningPass(225); + else + Builder.Inliner = createFunctionInliningPass(275); + + // Note that although clang/llvm-gcc use two separate passmanagers + // here, it shouldn't normally make a difference. + Builder.populateFunctionPassManager(PM); + Builder.populateModulePassManager(PM); + } + + for (std::vector::iterator I = PassList.begin(), + E = PassList.end(); + I != E; ++I) { + const PassInfo* PI = *I; + D.addPass(PI->getPassArgument()); + } + + // Bugpoint has the ability of generating a plethora of core files, so to + // avoid filling up the disk, we prevent it +#ifndef DEBUG_BUGPOINT + sys::Process::PreventCoreFiles(); +#endif + + std::string Error; + bool Failure = D.run(Error); + if (!Error.empty()) { + errs() << Error; + return 1; + } + return Failure; +} diff --git a/contrib/llvm/tools/llc/CMakeLists.txt b/contrib/llvm/tools/llc/CMakeLists.txt new file mode 100644 index 000000000000..683f29862d5c --- /dev/null +++ b/contrib/llvm/tools/llc/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser) + +add_llvm_tool(llc + llc.cpp + ) diff --git a/contrib/llvm/tools/llc/Makefile b/contrib/llvm/tools/llc/Makefile new file mode 100644 index 000000000000..7319aada489e --- /dev/null +++ b/contrib/llvm/tools/llc/Makefile @@ -0,0 +1,21 @@ +#===- tools/llc/Makefile -----------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = llc + +# Include this here so we can get the configuration of the targets +# that have been configured for construction. We have to do this +# early so we can set up LINK_COMPONENTS before including Makefile.rules +include $(LEVEL)/Makefile.config + +LINK_COMPONENTS := $(TARGETS_TO_BUILD) bitreader asmparser + +include $(LLVM_SRC_ROOT)/Makefile.rules + diff --git a/contrib/llvm/tools/llc/llc.cpp b/contrib/llvm/tools/llc/llc.cpp new file mode 100644 index 000000000000..d29bd9bc69a9 --- /dev/null +++ b/contrib/llvm/tools/llc/llc.cpp @@ -0,0 +1,381 @@ +//===-- llc.cpp - Implement the LLVM Native Code Generator ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the llc code generator driver. It provides a convenient +// command-line interface for generating native assembly-language code +// or C code, given LLVM bitcode. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Pass.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/IRReader.h" +#include "llvm/CodeGen/LinkAllAsmWriterComponents.h" +#include "llvm/CodeGen/LinkAllCodegenComponents.h" +#include "llvm/Config/config.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include +using namespace llvm; + +// General options for llc. Other pass-specific options are specified +// within the corresponding llc passes, and target-specific options +// and back-end code generation options are specified with the target machine. +// +static cl::opt +InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); + +// Determine optimization level. +static cl::opt +OptLevel("O", + cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " + "(default = '-O2')"), + cl::Prefix, + cl::ZeroOrMore, + cl::init(' ')); + +static cl::opt +TargetTriple("mtriple", cl::desc("Override target triple for module")); + +static cl::opt +MArch("march", cl::desc("Architecture to generate code for (see --version)")); + +static cl::opt +MCPU("mcpu", + cl::desc("Target a specific cpu type (-mcpu=help for details)"), + cl::value_desc("cpu-name"), + cl::init("")); + +static cl::list +MAttrs("mattr", + cl::CommaSeparated, + cl::desc("Target specific attributes (-mattr=help for details)"), + cl::value_desc("a1,+a2,-a3,...")); + +static cl::opt +RelocModel("relocation-model", + cl::desc("Choose relocation model"), + cl::init(Reloc::Default), + cl::values( + clEnumValN(Reloc::Default, "default", + "Target default relocation model"), + clEnumValN(Reloc::Static, "static", + "Non-relocatable code"), + clEnumValN(Reloc::PIC_, "pic", + "Fully relocatable, position independent code"), + clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic", + "Relocatable external references, non-relocatable code"), + clEnumValEnd)); + +static cl::opt +CMModel("code-model", + cl::desc("Choose code model"), + cl::init(CodeModel::Default), + cl::values(clEnumValN(CodeModel::Default, "default", + "Target default code model"), + clEnumValN(CodeModel::Small, "small", + "Small code model"), + clEnumValN(CodeModel::Kernel, "kernel", + "Kernel code model"), + clEnumValN(CodeModel::Medium, "medium", + "Medium code model"), + clEnumValN(CodeModel::Large, "large", + "Large code model"), + clEnumValEnd)); + +static cl::opt +RelaxAll("mc-relax-all", + cl::desc("When used with filetype=obj, " + "relax all fixups in the emitted object file")); + +cl::opt +FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), + cl::desc("Choose a file type (not all types are supported by all targets):"), + cl::values( + clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm", + "Emit an assembly ('.s') file"), + clEnumValN(TargetMachine::CGFT_ObjectFile, "obj", + "Emit a native object ('.o') file [experimental]"), + clEnumValN(TargetMachine::CGFT_Null, "null", + "Emit nothing, for performance testing"), + clEnumValEnd)); + +cl::opt NoVerify("disable-verify", cl::Hidden, + cl::desc("Do not verify input module")); + +cl::opt DisableDotLoc("disable-dot-loc", cl::Hidden, + cl::desc("Do not use .loc entries")); + +cl::opt DisableCFI("disable-cfi", cl::Hidden, + cl::desc("Do not use .cfi_* directives")); + +static cl::opt +DisableRedZone("disable-red-zone", + cl::desc("Do not emit code that uses the red zone."), + cl::init(false)); + +// GetFileNameRoot - Helper function to get the basename of a filename. +static inline std::string +GetFileNameRoot(const std::string &InputFilename) { + std::string IFN = InputFilename; + std::string outputFilename; + int Len = IFN.length(); + if ((Len > 2) && + IFN[Len-3] == '.' && + ((IFN[Len-2] == 'b' && IFN[Len-1] == 'c') || + (IFN[Len-2] == 'l' && IFN[Len-1] == 'l'))) { + outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ + } else { + outputFilename = IFN; + } + return outputFilename; +} + +static tool_output_file *GetOutputStream(const char *TargetName, + Triple::OSType OS, + const char *ProgName) { + // If we don't yet have an output filename, make one. + if (OutputFilename.empty()) { + if (InputFilename == "-") + OutputFilename = "-"; + else { + OutputFilename = GetFileNameRoot(InputFilename); + + switch (FileType) { + default: assert(0 && "Unknown file type"); + case TargetMachine::CGFT_AssemblyFile: + if (TargetName[0] == 'c') { + if (TargetName[1] == 0) + OutputFilename += ".cbe.c"; + else if (TargetName[1] == 'p' && TargetName[2] == 'p') + OutputFilename += ".cpp"; + else + OutputFilename += ".s"; + } else + OutputFilename += ".s"; + break; + case TargetMachine::CGFT_ObjectFile: + if (OS == Triple::Win32) + OutputFilename += ".obj"; + else + OutputFilename += ".o"; + break; + case TargetMachine::CGFT_Null: + OutputFilename += ".null"; + break; + } + } + } + + // Decide if we need "binary" output. + bool Binary = false; + switch (FileType) { + default: assert(0 && "Unknown file type"); + case TargetMachine::CGFT_AssemblyFile: + break; + case TargetMachine::CGFT_ObjectFile: + case TargetMachine::CGFT_Null: + Binary = true; + break; + } + + // Open the file. + std::string error; + unsigned OpenFlags = 0; + if (Binary) OpenFlags |= raw_fd_ostream::F_Binary; + tool_output_file *FDOut = new tool_output_file(OutputFilename.c_str(), error, + OpenFlags); + if (!error.empty()) { + errs() << error << '\n'; + delete FDOut; + return 0; + } + + return FDOut; +} + +// main - Entry point for the llc compiler. +// +int main(int argc, char **argv) { + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + // Enable debug stream buffering. + EnableDebugBuffering = true; + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize targets first, so that --version shows registered targets. + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); + + // Register the target printer for --version. + cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); + + cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); + + // Load the module to be compiled... + SMDiagnostic Err; + std::auto_ptr M; + + M.reset(ParseIRFile(InputFilename, Err, Context)); + if (M.get() == 0) { + Err.Print(argv[0], errs()); + return 1; + } + Module &mod = *M.get(); + + // If we are supposed to override the target triple, do so now. + if (!TargetTriple.empty()) + mod.setTargetTriple(Triple::normalize(TargetTriple)); + + Triple TheTriple(mod.getTargetTriple()); + if (TheTriple.getTriple().empty()) + TheTriple.setTriple(sys::getHostTriple()); + + // Allocate target machine. First, check whether the user has explicitly + // specified an architecture to compile for. If so we have to look it up by + // name, because it might be a backend that has no mapping to a target triple. + const Target *TheTarget = 0; + if (!MArch.empty()) { + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + if (MArch == it->getName()) { + TheTarget = &*it; + break; + } + } + + if (!TheTarget) { + errs() << argv[0] << ": error: invalid target '" << MArch << "'.\n"; + return 1; + } + + // Adjust the triple to match (if known), otherwise stick with the + // module/host triple. + Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); + if (Type != Triple::UnknownArch) + TheTriple.setArch(Type); + } else { + std::string Err; + TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Err); + if (TheTarget == 0) { + errs() << argv[0] << ": error auto-selecting target for module '" + << Err << "'. Please use the -march option to explicitly " + << "pick a target.\n"; + return 1; + } + } + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (MAttrs.size()) { + SubtargetFeatures Features; + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + std::auto_ptr + target(TheTarget->createTargetMachine(TheTriple.getTriple(), + MCPU, FeaturesStr, + RelocModel, CMModel)); + assert(target.get() && "Could not allocate target machine!"); + TargetMachine &Target = *target.get(); + + if (DisableDotLoc) + Target.setMCUseLoc(false); + + if (DisableCFI) + Target.setMCUseCFI(false); + + // Disable .loc support for older OS X versions. + if (TheTriple.isMacOSX() && + TheTriple.isMacOSXVersionLT(10, 6)) + Target.setMCUseLoc(false); + + // Figure out where we are going to send the output... + OwningPtr Out + (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); + if (!Out) return 1; + + CodeGenOpt::Level OLvl = CodeGenOpt::Default; + switch (OptLevel) { + default: + errs() << argv[0] << ": invalid optimization level.\n"; + return 1; + case ' ': break; + case '0': OLvl = CodeGenOpt::None; break; + case '1': OLvl = CodeGenOpt::Less; break; + case '2': OLvl = CodeGenOpt::Default; break; + case '3': OLvl = CodeGenOpt::Aggressive; break; + } + + // Build up all of the passes that we want to do to the module. + PassManager PM; + + // Add the target data from the target machine, if it exists, or the module. + if (const TargetData *TD = Target.getTargetData()) + PM.add(new TargetData(*TD)); + else + PM.add(new TargetData(&mod)); + + // Override default to generate verbose assembly. + Target.setAsmVerbosityDefault(true); + + if (RelaxAll) { + if (FileType != TargetMachine::CGFT_ObjectFile) + errs() << argv[0] + << ": warning: ignoring -mc-relax-all because filetype != obj"; + else + Target.setMCRelaxAll(true); + } + + { + formatted_raw_ostream FOS(Out->os()); + + // Ask the target to add backend passes as necessary. + if (Target.addPassesToEmitFile(PM, FOS, FileType, OLvl, NoVerify)) { + errs() << argv[0] << ": target does not support generation of this" + << " file type!\n"; + return 1; + } + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + PM.run(mod); + } + + // Declare success. + Out->keep(); + + return 0; +} diff --git a/contrib/llvm/tools/lli/CMakeLists.txt b/contrib/llvm/tools/lli/CMakeLists.txt new file mode 100644 index 000000000000..9378ef255466 --- /dev/null +++ b/contrib/llvm/tools/lli/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser selectiondag) + +add_llvm_tool(lli + lli.cpp + ) diff --git a/contrib/llvm/tools/lli/Makefile b/contrib/llvm/tools/lli/Makefile new file mode 100644 index 000000000000..80aa82b4d681 --- /dev/null +++ b/contrib/llvm/tools/lli/Makefile @@ -0,0 +1,15 @@ +##===- tools/lli/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../.. +TOOLNAME := lli +LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selectiondag + +# Enable JIT support +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/lli/lli.cpp b/contrib/llvm/tools/lli/lli.cpp new file mode 100644 index 000000000000..50c7a498f1cd --- /dev/null +++ b/contrib/llvm/tools/lli/lli.cpp @@ -0,0 +1,305 @@ +//===- lli.cpp - LLVM Interpreter / Dynamic compiler ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This utility provides a simple wrapper around the LLVM Execution Engines, +// which allow the direct execution of LLVM programs through a Just-In-Time +// compiler, or through an interpreter if no JIT is available for this platform. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/LinkAllCodegenComponents.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/IRReader.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TargetSelect.h" +#include + +#ifdef __CYGWIN__ +#include +#if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 +#define DO_NOTHING_ATEXIT 1 +#endif +#endif + +using namespace llvm; + +namespace { + cl::opt + InputFile(cl::desc(""), cl::Positional, cl::init("-")); + + cl::list + InputArgv(cl::ConsumeAfter, cl::desc("...")); + + cl::opt ForceInterpreter("force-interpreter", + cl::desc("Force interpretation: disable JIT"), + cl::init(false)); + + cl::opt UseMCJIT( + "use-mcjit", cl::desc("Enable use of the MC-based JIT (if available)"), + cl::init(false)); + + // Determine optimization level. + cl::opt + OptLevel("O", + cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " + "(default = '-O2')"), + cl::Prefix, + cl::ZeroOrMore, + cl::init(' ')); + + cl::opt + TargetTriple("mtriple", cl::desc("Override target triple for module")); + + cl::opt + MArch("march", + cl::desc("Architecture to generate assembly for (see --version)")); + + cl::opt + MCPU("mcpu", + cl::desc("Target a specific cpu type (-mcpu=help for details)"), + cl::value_desc("cpu-name"), + cl::init("")); + + cl::list + MAttrs("mattr", + cl::CommaSeparated, + cl::desc("Target specific attributes (-mattr=help for details)"), + cl::value_desc("a1,+a2,-a3,...")); + + cl::opt + EntryFunc("entry-function", + cl::desc("Specify the entry function (default = 'main') " + "of the executable"), + cl::value_desc("function"), + cl::init("main")); + + cl::opt + FakeArgv0("fake-argv0", + cl::desc("Override the 'argv[0]' value passed into the executing" + " program"), cl::value_desc("executable")); + + cl::opt + DisableCoreFiles("disable-core-files", cl::Hidden, + cl::desc("Disable emission of core files if possible")); + + cl::opt + NoLazyCompilation("disable-lazy-compilation", + cl::desc("Disable JIT lazy compilation"), + cl::init(false)); + + cl::opt + RelocModel("relocation-model", + cl::desc("Choose relocation model"), + cl::init(Reloc::Default), + cl::values( + clEnumValN(Reloc::Default, "default", + "Target default relocation model"), + clEnumValN(Reloc::Static, "static", + "Non-relocatable code"), + clEnumValN(Reloc::PIC_, "pic", + "Fully relocatable, position independent code"), + clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic", + "Relocatable external references, non-relocatable code"), + clEnumValEnd)); + + cl::opt + CMModel("code-model", + cl::desc("Choose code model"), + cl::init(CodeModel::JITDefault), + cl::values(clEnumValN(CodeModel::JITDefault, "default", + "Target default JIT code model"), + clEnumValN(CodeModel::Small, "small", + "Small code model"), + clEnumValN(CodeModel::Kernel, "kernel", + "Kernel code model"), + clEnumValN(CodeModel::Medium, "medium", + "Medium code model"), + clEnumValN(CodeModel::Large, "large", + "Large code model"), + clEnumValEnd)); + +} + +static ExecutionEngine *EE = 0; + +static void do_shutdown() { + // Cygwin-1.5 invokes DLL's dtors before atexit handler. +#ifndef DO_NOTHING_ATEXIT + delete EE; + llvm_shutdown(); +#endif +} + +//===----------------------------------------------------------------------===// +// main Driver function +// +int main(int argc, char **argv, char * const *envp) { + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + LLVMContext &Context = getGlobalContext(); + atexit(do_shutdown); // Call llvm_shutdown() on exit. + + // If we have a native target, initialize it to ensure it is linked in and + // usable by the JIT. + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + + cl::ParseCommandLineOptions(argc, argv, + "llvm interpreter & dynamic compiler\n"); + + // If the user doesn't want core files, disable them. + if (DisableCoreFiles) + sys::Process::PreventCoreFiles(); + + // Load the bitcode... + SMDiagnostic Err; + Module *Mod = ParseIRFile(InputFile, Err, Context); + if (!Mod) { + Err.Print(argv[0], errs()); + return 1; + } + + // If not jitting lazily, load the whole bitcode file eagerly too. + std::string ErrorMsg; + if (NoLazyCompilation) { + if (Mod->MaterializeAllPermanently(&ErrorMsg)) { + errs() << argv[0] << ": bitcode didn't read correctly.\n"; + errs() << "Reason: " << ErrorMsg << "\n"; + exit(1); + } + } + + EngineBuilder builder(Mod); + builder.setMArch(MArch); + builder.setMCPU(MCPU); + builder.setMAttrs(MAttrs); + builder.setRelocationModel(RelocModel); + builder.setCodeModel(CMModel); + builder.setErrorStr(&ErrorMsg); + builder.setEngineKind(ForceInterpreter + ? EngineKind::Interpreter + : EngineKind::JIT); + + // If we are supposed to override the target triple, do so now. + if (!TargetTriple.empty()) + Mod->setTargetTriple(Triple::normalize(TargetTriple)); + + // Enable MCJIT, if desired. + if (UseMCJIT) + builder.setUseMCJIT(true); + + CodeGenOpt::Level OLvl = CodeGenOpt::Default; + switch (OptLevel) { + default: + errs() << argv[0] << ": invalid optimization level.\n"; + return 1; + case ' ': break; + case '0': OLvl = CodeGenOpt::None; break; + case '1': OLvl = CodeGenOpt::Less; break; + case '2': OLvl = CodeGenOpt::Default; break; + case '3': OLvl = CodeGenOpt::Aggressive; break; + } + builder.setOptLevel(OLvl); + + EE = builder.create(); + if (!EE) { + if (!ErrorMsg.empty()) + errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n"; + else + errs() << argv[0] << ": unknown error creating EE!\n"; + exit(1); + } + + EE->RegisterJITEventListener(createOProfileJITEventListener()); + + EE->DisableLazyCompilation(NoLazyCompilation); + + // If the user specifically requested an argv[0] to pass into the program, + // do it now. + if (!FakeArgv0.empty()) { + InputFile = FakeArgv0; + } else { + // Otherwise, if there is a .bc suffix on the executable strip it off, it + // might confuse the program. + if (StringRef(InputFile).endswith(".bc")) + InputFile.erase(InputFile.length() - 3); + } + + // Add the module's name to the start of the vector of arguments to main(). + InputArgv.insert(InputArgv.begin(), InputFile); + + // Call the main function from M as if its signature were: + // int main (int argc, char **argv, const char **envp) + // using the contents of Args to determine argc & argv, and the contents of + // EnvVars to determine envp. + // + Function *EntryFn = Mod->getFunction(EntryFunc); + if (!EntryFn) { + errs() << '\'' << EntryFunc << "\' function not found in module.\n"; + return -1; + } + + // If the program doesn't explicitly call exit, we will need the Exit + // function later on to make an explicit call, so get the function now. + Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context), + Type::getInt32Ty(Context), + NULL); + + // Reset errno to zero on entry to main. + errno = 0; + + // Run static constructors. + EE->runStaticConstructorsDestructors(false); + + if (NoLazyCompilation) { + for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { + Function *Fn = &*I; + if (Fn != EntryFn && !Fn->isDeclaration()) + EE->getPointerToFunction(Fn); + } + } + + // Run main. + int Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp); + + // Run static destructors. + EE->runStaticConstructorsDestructors(true); + + // If the program didn't call exit explicitly, we should call it now. + // This ensures that any atexit handlers get called correctly. + if (Function *ExitF = dyn_cast(Exit)) { + std::vector Args; + GenericValue ResultGV; + ResultGV.IntVal = APInt(32, Result); + Args.push_back(ResultGV); + EE->runFunction(ExitF, Args); + errs() << "ERROR: exit(" << Result << ") returned!\n"; + abort(); + } else { + errs() << "ERROR: exit defined with wrong prototype!\n"; + abort(); + } +} diff --git a/contrib/llvm/tools/llvm-ar/CMakeLists.txt b/contrib/llvm/tools/llvm-ar/CMakeLists.txt new file mode 100644 index 000000000000..c8b0b725d83c --- /dev/null +++ b/contrib/llvm/tools/llvm-ar/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_LINK_COMPONENTS archive) +set(LLVM_REQUIRES_EH 1) + +add_llvm_tool(llvm-ar + llvm-ar.cpp + ) + +# TODO: Support check-local. diff --git a/contrib/llvm/tools/llvm-ar/Makefile b/contrib/llvm/tools/llvm-ar/Makefile new file mode 100644 index 000000000000..e4fe4e8ca39a --- /dev/null +++ b/contrib/llvm/tools/llvm-ar/Makefile @@ -0,0 +1,25 @@ +##===- tools/llvm-ar/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. + +TOOLNAME = llvm-ar +LINK_COMPONENTS = archive +REQUIRES_EH := 1 + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common + +check-local:: + $(Echo) Checking llvm-ar + $(Verb) $(ToolDir)/llvm-ar zRrS nada.a . + $(Verb) $(ToolDir)/llvm-ar tv nada.a | \ + grep Debug/llvm-ar.d >/dev/null 2>&1 + $(Verb) $(RM) -f nada.a diff --git a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp new file mode 100644 index 000000000000..c1c8b2474e79 --- /dev/null +++ b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp @@ -0,0 +1,781 @@ +//===-- llvm-ar.cpp - LLVM archive librarian utility ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Builds up (relatively) standard unix archive files (.a) containing LLVM +// bitcode or other files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Bitcode/Archive.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Signals.h" +#include +#include +#include +using namespace llvm; + +// Option for compatibility with AIX, not used but must allow it to be present. +static cl::opt +X32Option ("X32_64", cl::Hidden, + cl::desc("Ignored option for compatibility with AIX")); + +// llvm-ar operation code and modifier flags. This must come first. +static cl::opt +Options(cl::Positional, cl::Required, cl::desc("{operation}[modifiers]...")); + +// llvm-ar remaining positional arguments. +static cl::list +RestOfArgs(cl::Positional, cl::OneOrMore, + cl::desc("[relpos] [count] [members]...")); + +// MoreHelp - Provide additional help output explaining the operations and +// modifiers of llvm-ar. This object instructs the CommandLine library +// to print the text of the constructor when the --help option is given. +static cl::extrahelp MoreHelp( + "\nOPERATIONS:\n" + " d[NsS] - delete file(s) from the archive\n" + " m[abiSs] - move file(s) in the archive\n" + " p[kN] - print file(s) found in the archive\n" + " q[ufsS] - quick append file(s) to the archive\n" + " r[abfiuzRsS] - replace or insert file(s) into the archive\n" + " t - display contents of archive\n" + " x[No] - extract file(s) from the archive\n" + "\nMODIFIERS (operation specific):\n" + " [a] - put file(s) after [relpos]\n" + " [b] - put file(s) before [relpos] (same as [i])\n" + " [f] - truncate inserted file names\n" + " [i] - put file(s) before [relpos] (same as [b])\n" + " [k] - always print bitcode files (default is to skip them)\n" + " [N] - use instance [count] of name\n" + " [o] - preserve original dates\n" + " [P] - use full path names when matching\n" + " [R] - recurse through directories when inserting\n" + " [s] - create an archive index (cf. ranlib)\n" + " [S] - do not build a symbol table\n" + " [u] - update only files newer than archive contents\n" + " [z] - compress files before inserting/extracting\n" + "\nMODIFIERS (generic):\n" + " [c] - do not warn if the library had to be created\n" + " [v] - be verbose about actions taken\n" + " [V] - be *really* verbose about actions taken\n" +); + +// This enumeration delineates the kinds of operations on an archive +// that are permitted. +enum ArchiveOperation { + NoOperation, ///< An operation hasn't been specified + Print, ///< Print the contents of the archive + Delete, ///< Delete the specified members + Move, ///< Move members to end or as given by {a,b,i} modifiers + QuickAppend, ///< Quickly append to end of archive + ReplaceOrInsert, ///< Replace or Insert members + DisplayTable, ///< Display the table of contents + Extract ///< Extract files back to file system +}; + +// Modifiers to follow operation to vary behavior +bool AddAfter = false; ///< 'a' modifier +bool AddBefore = false; ///< 'b' modifier +bool Create = false; ///< 'c' modifier +bool TruncateNames = false; ///< 'f' modifier +bool InsertBefore = false; ///< 'i' modifier +bool DontSkipBitcode = false; ///< 'k' modifier +bool UseCount = false; ///< 'N' modifier +bool OriginalDates = false; ///< 'o' modifier +bool FullPath = false; ///< 'P' modifier +bool RecurseDirectories = false; ///< 'R' modifier +bool SymTable = true; ///< 's' & 'S' modifiers +bool OnlyUpdate = false; ///< 'u' modifier +bool Verbose = false; ///< 'v' modifier +bool ReallyVerbose = false; ///< 'V' modifier +bool Compression = false; ///< 'z' modifier + +// Relative Positional Argument (for insert/move). This variable holds +// the name of the archive member to which the 'a', 'b' or 'i' modifier +// refers. Only one of 'a', 'b' or 'i' can be specified so we only need +// one variable. +std::string RelPos; + +// Select which of multiple entries in the archive with the same name should be +// used (specified with -N) for the delete and extract operations. +int Count = 1; + +// This variable holds the name of the archive file as given on the +// command line. +std::string ArchiveName; + +// This variable holds the list of member files to proecess, as given +// on the command line. +std::vector Members; + +// This variable holds the (possibly expanded) list of path objects that +// correspond to files we will +std::set Paths; + +// The Archive object to which all the editing operations will be sent. +Archive* TheArchive = 0; + +// getRelPos - Extract the member filename from the command line for +// the [relpos] argument associated with a, b, and i modifiers +void getRelPos() { + if(RestOfArgs.size() > 0) { + RelPos = RestOfArgs[0]; + RestOfArgs.erase(RestOfArgs.begin()); + } + else + throw "Expected [relpos] for a, b, or i modifier"; +} + +// getCount - Extract the [count] argument associated with the N modifier +// from the command line and check its value. +void getCount() { + if(RestOfArgs.size() > 0) { + Count = atoi(RestOfArgs[0].c_str()); + RestOfArgs.erase(RestOfArgs.begin()); + } + else + throw "Expected [count] value with N modifier"; + + // Non-positive counts are not allowed + if (Count < 1) + throw "Invalid [count] value (not a positive integer)"; +} + +// getArchive - Get the archive file name from the command line +void getArchive() { + if(RestOfArgs.size() > 0) { + ArchiveName = RestOfArgs[0]; + RestOfArgs.erase(RestOfArgs.begin()); + } + else + throw "An archive name must be specified."; +} + +// getMembers - Copy over remaining items in RestOfArgs to our Members vector +// This is just for clarity. +void getMembers() { + if(RestOfArgs.size() > 0) + Members = std::vector(RestOfArgs); +} + +// parseCommandLine - Parse the command line options as presented and return the +// operation specified. Process all modifiers and check to make sure that +// constraints on modifier/operation pairs have not been violated. +ArchiveOperation parseCommandLine() { + + // Keep track of number of operations. We can only specify one + // per execution. + unsigned NumOperations = 0; + + // Keep track of the number of positional modifiers (a,b,i). Only + // one can be specified. + unsigned NumPositional = 0; + + // Keep track of which operation was requested + ArchiveOperation Operation = NoOperation; + + for(unsigned i=0; i 1) + throw "Only one operation may be specified"; + if (NumPositional > 1) + throw "You may only specify one of a, b, and i modifiers"; + if (AddAfter || AddBefore || InsertBefore) + if (Operation != Move && Operation != ReplaceOrInsert) + throw "The 'a', 'b' and 'i' modifiers can only be specified with " + "the 'm' or 'r' operations"; + if (RecurseDirectories && Operation != ReplaceOrInsert) + throw "The 'R' modifiers is only applicabe to the 'r' operation"; + if (OriginalDates && Operation != Extract) + throw "The 'o' modifier is only applicable to the 'x' operation"; + if (TruncateNames && Operation!=QuickAppend && Operation!=ReplaceOrInsert) + throw "The 'f' modifier is only applicable to the 'q' and 'r' operations"; + if (OnlyUpdate && Operation != ReplaceOrInsert) + throw "The 'u' modifier is only applicable to the 'r' operation"; + if (Compression && Operation!=ReplaceOrInsert && Operation!=Extract) + throw "The 'z' modifier is only applicable to the 'r' and 'x' operations"; + if (Count > 1 && Members.size() > 1) + throw "Only one member name may be specified with the 'N' modifier"; + + // Return the parsed operation to the caller + return Operation; +} + +// recurseDirectories - Implements the "R" modifier. This function scans through +// the Paths vector (built by buildPaths, below) and replaces any directories it +// finds with all the files in that directory (recursively). It uses the +// sys::Path::getDirectoryContent method to perform the actual directory scans. +bool +recurseDirectories(const sys::Path& path, + std::set& result, std::string* ErrMsg) { + result.clear(); + if (RecurseDirectories) { + std::set content; + if (path.getDirectoryContents(content, ErrMsg)) + return true; + + for (std::set::iterator I = content.begin(), E = content.end(); + I != E; ++I) { + // Make sure it exists and is a directory + sys::PathWithStatus PwS(*I); + const sys::FileStatus *Status = PwS.getFileStatus(false, ErrMsg); + if (!Status) + return true; + if (Status->isDir) { + std::set moreResults; + if (recurseDirectories(*I, moreResults, ErrMsg)) + return true; + result.insert(moreResults.begin(), moreResults.end()); + } else { + result.insert(*I); + } + } + } + return false; +} + +// buildPaths - Convert the strings in the Members vector to sys::Path objects +// and make sure they are valid and exist exist. This check is only needed for +// the operations that add/replace files to the archive ('q' and 'r') +bool buildPaths(bool checkExistence, std::string* ErrMsg) { + for (unsigned i = 0; i < Members.size(); i++) { + sys::Path aPath; + if (!aPath.set(Members[i])) + throw std::string("File member name invalid: ") + Members[i]; + if (checkExistence) { + bool Exists; + if (sys::fs::exists(aPath.str(), Exists) || !Exists) + throw std::string("File does not exist: ") + Members[i]; + std::string Err; + sys::PathWithStatus PwS(aPath); + const sys::FileStatus *si = PwS.getFileStatus(false, &Err); + if (!si) + throw Err; + if (si->isDir) { + std::set dirpaths; + if (recurseDirectories(aPath, dirpaths, ErrMsg)) + return true; + Paths.insert(dirpaths.begin(),dirpaths.end()); + } else { + Paths.insert(aPath); + } + } else { + Paths.insert(aPath); + } + } + return false; +} + +// printSymbolTable - print out the archive's symbol table. +void printSymbolTable() { + outs() << "\nArchive Symbol Table:\n"; + const Archive::SymTabType& symtab = TheArchive->getSymbolTable(); + for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end(); + I != E; ++I ) { + unsigned offset = TheArchive->getFirstFileOffset() + I->second; + outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n"; + } +} + +// doPrint - Implements the 'p' operation. This function traverses the archive +// looking for members that match the path list. It is careful to uncompress +// things that should be and to skip bitcode files unless the 'k' modifier was +// given. +bool doPrint(std::string* ErrMsg) { + if (buildPaths(false, ErrMsg)) + return true; + unsigned countDown = Count; + for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); + I != E; ++I ) { + if (Paths.empty() || + (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { + if (countDown == 1) { + const char* data = reinterpret_cast(I->getData()); + + // Skip things that don't make sense to print + if (I->isLLVMSymbolTable() || I->isSVR4SymbolTable() || + I->isBSD4SymbolTable() || (!DontSkipBitcode && I->isBitcode())) + continue; + + if (Verbose) + outs() << "Printing " << I->getPath().str() << "\n"; + + unsigned len = I->getSize(); + outs().write(data, len); + } else { + countDown--; + } + } + } + return false; +} + +// putMode - utility function for printing out the file mode when the 't' +// operation is in verbose mode. +void +printMode(unsigned mode) { + if (mode & 004) + outs() << "r"; + else + outs() << "-"; + if (mode & 002) + outs() << "w"; + else + outs() << "-"; + if (mode & 001) + outs() << "x"; + else + outs() << "-"; +} + +// doDisplayTable - Implement the 't' operation. This function prints out just +// the file names of each of the members. However, if verbose mode is requested +// ('v' modifier) then the file type, permission mode, user, group, size, and +// modification time are also printed. +bool +doDisplayTable(std::string* ErrMsg) { + if (buildPaths(false, ErrMsg)) + return true; + for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); + I != E; ++I ) { + if (Paths.empty() || + (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { + if (Verbose) { + // FIXME: Output should be this format: + // Zrw-r--r-- 500/ 500 525 Nov 8 17:42 2004 Makefile + if (I->isBitcode()) + outs() << "b"; + else if (I->isCompressed()) + outs() << "Z"; + else + outs() << " "; + unsigned mode = I->getMode(); + printMode((mode >> 6) & 007); + printMode((mode >> 3) & 007); + printMode(mode & 007); + outs() << " " << format("%4u", I->getUser()); + outs() << "/" << format("%4u", I->getGroup()); + outs() << " " << format("%8u", I->getSize()); + outs() << " " << format("%20s", I->getModTime().str().substr(4).c_str()); + outs() << " " << I->getPath().str() << "\n"; + } else { + outs() << I->getPath().str() << "\n"; + } + } + } + if (ReallyVerbose) + printSymbolTable(); + return false; +} + +// doExtract - Implement the 'x' operation. This function extracts files back to +// the file system, making sure to uncompress any that were compressed +bool +doExtract(std::string* ErrMsg) { + if (buildPaths(false, ErrMsg)) + return true; + for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); + I != E; ++I ) { + if (Paths.empty() || + (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end())) { + + // Make sure the intervening directories are created + if (I->hasPath()) { + sys::Path dirs(I->getPath()); + dirs.eraseComponent(); + if (dirs.createDirectoryOnDisk(/*create_parents=*/true, ErrMsg)) + return true; + } + + // Open up a file stream for writing + std::ios::openmode io_mode = std::ios::out | std::ios::trunc | + std::ios::binary; + std::ofstream file(I->getPath().c_str(), io_mode); + + // Get the data and its length + const char* data = reinterpret_cast(I->getData()); + unsigned len = I->getSize(); + + // Write the data. + file.write(data,len); + file.close(); + + // If we're supposed to retain the original modification times, etc. do so + // now. + if (OriginalDates) + I->getPath().setStatusInfoOnDisk(I->getFileStatus()); + } + } + return false; +} + +// doDelete - Implement the delete operation. This function deletes zero or more +// members from the archive. Note that if the count is specified, there should +// be no more than one path in the Paths list or else this algorithm breaks. +// That check is enforced in parseCommandLine (above). +bool +doDelete(std::string* ErrMsg) { + if (buildPaths(false, ErrMsg)) + return true; + if (Paths.empty()) + return false; + unsigned countDown = Count; + for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); + I != E; ) { + if (std::find(Paths.begin(), Paths.end(), I->getPath()) != Paths.end()) { + if (countDown == 1) { + Archive::iterator J = I; + ++I; + TheArchive->erase(J); + } else + countDown--; + } else { + ++I; + } + } + + // We're done editting, reconstruct the archive. + if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) + return true; + if (ReallyVerbose) + printSymbolTable(); + return false; +} + +// doMore - Implement the move operation. This function re-arranges just the +// order of the archive members so that when the archive is written the move +// of the members is accomplished. Note the use of the RelPos variable to +// determine where the items should be moved to. +bool +doMove(std::string* ErrMsg) { + if (buildPaths(false, ErrMsg)) + return true; + + // By default and convention the place to move members to is the end of the + // archive. + Archive::iterator moveto_spot = TheArchive->end(); + + // However, if the relative positioning modifiers were used, we need to scan + // the archive to find the member in question. If we don't find it, its no + // crime, we just move to the end. + if (AddBefore || InsertBefore || AddAfter) { + for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); + I != E; ++I ) { + if (RelPos == I->getPath().str()) { + if (AddAfter) { + moveto_spot = I; + moveto_spot++; + } else { + moveto_spot = I; + } + break; + } + } + } + + // Keep a list of the paths remaining to be moved + std::set remaining(Paths); + + // Scan the archive again, this time looking for the members to move to the + // moveto_spot. + for (Archive::iterator I = TheArchive->begin(), E= TheArchive->end(); + I != E && !remaining.empty(); ++I ) { + std::set::iterator found = + std::find(remaining.begin(),remaining.end(),I->getPath()); + if (found != remaining.end()) { + if (I != moveto_spot) + TheArchive->splice(moveto_spot,*TheArchive,I); + remaining.erase(found); + } + } + + // We're done editting, reconstruct the archive. + if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) + return true; + if (ReallyVerbose) + printSymbolTable(); + return false; +} + +// doQuickAppend - Implements the 'q' operation. This function just +// indiscriminantly adds the members to the archive and rebuilds it. +bool +doQuickAppend(std::string* ErrMsg) { + // Get the list of paths to append. + if (buildPaths(true, ErrMsg)) + return true; + if (Paths.empty()) + return false; + + // Append them quickly. + for (std::set::iterator PI = Paths.begin(), PE = Paths.end(); + PI != PE; ++PI) { + if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg)) + return true; + } + + // We're done editting, reconstruct the archive. + if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) + return true; + if (ReallyVerbose) + printSymbolTable(); + return false; +} + +// doReplaceOrInsert - Implements the 'r' operation. This function will replace +// any existing files or insert new ones into the archive. +bool +doReplaceOrInsert(std::string* ErrMsg) { + + // Build the list of files to be added/replaced. + if (buildPaths(true, ErrMsg)) + return true; + if (Paths.empty()) + return false; + + // Keep track of the paths that remain to be inserted. + std::set remaining(Paths); + + // Default the insertion spot to the end of the archive + Archive::iterator insert_spot = TheArchive->end(); + + // Iterate over the archive contents + for (Archive::iterator I = TheArchive->begin(), E = TheArchive->end(); + I != E && !remaining.empty(); ++I ) { + + // Determine if this archive member matches one of the paths we're trying + // to replace. + + std::set::iterator found = remaining.end(); + for (std::set::iterator RI = remaining.begin(), + RE = remaining.end(); RI != RE; ++RI ) { + std::string compare(RI->str()); + if (TruncateNames && compare.length() > 15) { + const char* nm = compare.c_str(); + unsigned len = compare.length(); + size_t slashpos = compare.rfind('/'); + if (slashpos != std::string::npos) { + nm += slashpos + 1; + len -= slashpos +1; + } + if (len > 15) + len = 15; + compare.assign(nm,len); + } + if (compare == I->getPath().str()) { + found = RI; + break; + } + } + + if (found != remaining.end()) { + std::string Err; + sys::PathWithStatus PwS(*found); + const sys::FileStatus *si = PwS.getFileStatus(false, &Err); + if (!si) + return true; + if (!si->isDir) { + if (OnlyUpdate) { + // Replace the item only if it is newer. + if (si->modTime > I->getModTime()) + if (I->replaceWith(*found, ErrMsg)) + return true; + } else { + // Replace the item regardless of time stamp + if (I->replaceWith(*found, ErrMsg)) + return true; + } + } else { + // We purposefully ignore directories. + } + + // Remove it from our "to do" list + remaining.erase(found); + } + + // Determine if this is the place where we should insert + if ((AddBefore || InsertBefore) && RelPos == I->getPath().str()) + insert_spot = I; + else if (AddAfter && RelPos == I->getPath().str()) { + insert_spot = I; + insert_spot++; + } + } + + // If we didn't replace all the members, some will remain and need to be + // inserted at the previously computed insert-spot. + if (!remaining.empty()) { + for (std::set::iterator PI = remaining.begin(), + PE = remaining.end(); PI != PE; ++PI) { + if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg)) + return true; + } + } + + // We're done editting, reconstruct the archive. + if (TheArchive->writeToDisk(SymTable,TruncateNames,Compression,ErrMsg)) + return true; + if (ReallyVerbose) + printSymbolTable(); + return false; +} + +// main - main program for llvm-ar .. see comments in the code +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Have the command line options parsed and handle things + // like --help and --version. + cl::ParseCommandLineOptions(argc, argv, + "LLVM Archiver (llvm-ar)\n\n" + " This program archives bitcode files into single libraries\n" + ); + + int exitCode = 0; + + // Make sure we don't exit with "unhandled exception". + try { + // Do our own parsing of the command line because the CommandLine utility + // can't handle the grouped positional parameters without a dash. + ArchiveOperation Operation = parseCommandLine(); + + // Check the path name of the archive + sys::Path ArchivePath; + if (!ArchivePath.set(ArchiveName)) + throw std::string("Archive name invalid: ") + ArchiveName; + + // Create or open the archive object. + bool Exists; + if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) { + // Produce a warning if we should and we're creating the archive + if (!Create) + errs() << argv[0] << ": creating " << ArchivePath.str() << "\n"; + TheArchive = Archive::CreateEmpty(ArchivePath, Context); + TheArchive->writeToDisk(); + } else { + std::string Error; + TheArchive = Archive::OpenAndLoad(ArchivePath, Context, &Error); + if (TheArchive == 0) { + errs() << argv[0] << ": error loading '" << ArchivePath.str() << "': " + << Error << "!\n"; + return 1; + } + } + + // Make sure we're not fooling ourselves. + assert(TheArchive && "Unable to instantiate the archive"); + + // Make sure we clean up the archive even on failure. + std::auto_ptr AutoArchive(TheArchive); + + // Perform the operation + std::string ErrMsg; + bool haveError = false; + switch (Operation) { + case Print: haveError = doPrint(&ErrMsg); break; + case Delete: haveError = doDelete(&ErrMsg); break; + case Move: haveError = doMove(&ErrMsg); break; + case QuickAppend: haveError = doQuickAppend(&ErrMsg); break; + case ReplaceOrInsert: haveError = doReplaceOrInsert(&ErrMsg); break; + case DisplayTable: haveError = doDisplayTable(&ErrMsg); break; + case Extract: haveError = doExtract(&ErrMsg); break; + case NoOperation: + errs() << argv[0] << ": No operation was selected.\n"; + break; + } + if (haveError) { + errs() << argv[0] << ": " << ErrMsg << "\n"; + return 1; + } + } catch (const char*msg) { + // These errors are usage errors, thrown only by the various checks in the + // code above. + errs() << argv[0] << ": " << msg << "\n\n"; + cl::PrintHelpMessage(); + exitCode = 1; + } catch (const std::string& msg) { + // These errors are thrown by LLVM libraries (e.g. lib System) and represent + // a more serious error so we bump the exitCode and don't print the usage. + errs() << argv[0] << ": " << msg << "\n"; + exitCode = 2; + } catch (...) { + // This really shouldn't happen, but just in case .... + errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; + exitCode = 3; + } + + // Return result code back to operating system. + return exitCode; +} diff --git a/contrib/llvm/tools/llvm-as/CMakeLists.txt b/contrib/llvm/tools/llvm-as/CMakeLists.txt new file mode 100644 index 000000000000..eef4a13e29dc --- /dev/null +++ b/contrib/llvm/tools/llvm-as/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS asmparser bitwriter) +set(LLVM_REQUIRES_EH 1) + +add_llvm_tool(llvm-as + llvm-as.cpp + ) diff --git a/contrib/llvm/tools/llvm-as/Makefile b/contrib/llvm/tools/llvm-as/Makefile new file mode 100644 index 000000000000..e1e5853a7b6a --- /dev/null +++ b/contrib/llvm/tools/llvm-as/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-as/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = llvm-as +LINK_COMPONENTS := asmparser bitwriter + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-as/llvm-as.cpp b/contrib/llvm/tools/llvm-as/llvm-as.cpp new file mode 100644 index 000000000000..c1661cdcb196 --- /dev/null +++ b/contrib/llvm/tools/llvm-as/llvm-as.cpp @@ -0,0 +1,119 @@ +//===--- llvm-as.cpp - The low-level LLVM assembler -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This utility may be invoked in the following manner: +// llvm-as --help - Output information about command line switches +// llvm-as [options] - Read LLVM asm from stdin, write bitcode to stdout +// llvm-as [options] x.ll - Read LLVM asm from the x.ll file, write bitcode +// to the x.bc file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Parser.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Signals.h" +#include +using namespace llvm; + +static cl::opt +InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +OutputFilename("o", cl::desc("Override output filename"), + cl::value_desc("filename")); + +static cl::opt +Force("f", cl::desc("Enable binary output on terminals")); + +static cl::opt +DisableOutput("disable-output", cl::desc("Disable output"), cl::init(false)); + +static cl::opt +DumpAsm("d", cl::desc("Print assembly as parsed"), cl::Hidden); + +static cl::opt +DisableVerify("disable-verify", cl::Hidden, + cl::desc("Do not run verifier on input LLVM (dangerous!)")); + +static void WriteOutputFile(const Module *M) { + // Infer the output filename if needed. + if (OutputFilename.empty()) { + if (InputFilename == "-") { + OutputFilename = "-"; + } else { + std::string IFN = InputFilename; + int Len = IFN.length(); + if (IFN[Len-3] == '.' && IFN[Len-2] == 'l' && IFN[Len-1] == 'l') { + // Source ends in .ll + OutputFilename = std::string(IFN.begin(), IFN.end()-3); + } else { + OutputFilename = IFN; // Append a .bc to it + } + OutputFilename += ".bc"; + } + } + + std::string ErrorInfo; + OwningPtr Out + (new tool_output_file(OutputFilename.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary)); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << '\n'; + exit(1); + } + + if (Force || !CheckBitcodeOutputToConsole(Out->os(), true)) + WriteBitcodeToFile(M, Out->os()); + + // Declare success. + Out->keep(); +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n"); + + // Parse the file now... + SMDiagnostic Err; + std::auto_ptr M(ParseAssemblyFile(InputFilename, Err, Context)); + if (M.get() == 0) { + Err.Print(argv[0], errs()); + return 1; + } + + if (!DisableVerify) { + std::string Err; + if (verifyModule(*M.get(), ReturnStatusAction, &Err)) { + errs() << argv[0] + << ": assembly parsed, but does not verify as correct!\n"; + errs() << Err; + return 1; + } + } + + if (DumpAsm) errs() << "Here's the assembly:\n" << *M.get(); + + if (!DisableOutput) + WriteOutputFile(M.get()); + + return 0; +} diff --git a/contrib/llvm/tools/llvm-bcanalyzer/CMakeLists.txt b/contrib/llvm/tools/llvm-bcanalyzer/CMakeLists.txt new file mode 100644 index 000000000000..732bc3296f2c --- /dev/null +++ b/contrib/llvm/tools/llvm-bcanalyzer/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS bitreader) +set(LLVM_REQUIRES_EH 1) + +add_llvm_tool(llvm-bcanalyzer + llvm-bcanalyzer.cpp + ) diff --git a/contrib/llvm/tools/llvm-bcanalyzer/Makefile b/contrib/llvm/tools/llvm-bcanalyzer/Makefile new file mode 100644 index 000000000000..488387d5da24 --- /dev/null +++ b/contrib/llvm/tools/llvm-bcanalyzer/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-bcanalyzer/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. + +TOOLNAME = llvm-bcanalyzer +LINK_COMPONENTS := bitreader + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp new file mode 100644 index 000000000000..4ada64a5285f --- /dev/null +++ b/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -0,0 +1,629 @@ +//===-- llvm-bcanalyzer.cpp - Bitcode Analyzer --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tool may be invoked in the following manner: +// llvm-bcanalyzer [options] - Read LLVM bitcode from stdin +// llvm-bcanalyzer [options] x.bc - Read LLVM bitcode from the x.bc file +// +// Options: +// --help - Output information about command line switches +// --dump - Dump low-level bitcode structure in readable format +// +// This tool provides analytical information about a bitcode file. It is +// intended as an aid to developers of bitcode reading and writing software. It +// produces on std::out a summary of the bitcode file that shows various +// statistics about the contents of the file. By default this information is +// detailed and contains information about individual bitcode blocks and the +// functions in the module. +// The tool is also able to print a bitcode file in a straight forward text +// format that shows the containment and relationships of the information in +// the bitcode file (-dump option). +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Bitcode/LLVMBitCodes.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" +#include +#include +#include +using namespace llvm; + +static cl::opt + InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt Dump("dump", cl::desc("Dump low level bitcode trace")); + +//===----------------------------------------------------------------------===// +// Bitcode specific analysis. +//===----------------------------------------------------------------------===// + +static cl::opt NoHistogram("disable-histogram", + cl::desc("Do not print per-code histogram")); + +static cl::opt +NonSymbolic("non-symbolic", + cl::desc("Emit numeric info in dump even if" + " symbolic info is available")); + +namespace { + +/// CurStreamTypeType - A type for CurStreamType +enum CurStreamTypeType { + UnknownBitstream, + LLVMIRBitstream +}; + +} + +/// CurStreamType - If we can sniff the flavor of this stream, we can produce +/// better dump info. +static CurStreamTypeType CurStreamType; + + +/// GetBlockName - Return a symbolic block name if known, otherwise return +/// null. +static const char *GetBlockName(unsigned BlockID, + const BitstreamReader &StreamFile) { + // Standard blocks for all bitcode files. + if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { + if (BlockID == bitc::BLOCKINFO_BLOCK_ID) + return "BLOCKINFO_BLOCK"; + return 0; + } + + // Check to see if we have a blockinfo record for this block, with a name. + if (const BitstreamReader::BlockInfo *Info = + StreamFile.getBlockInfo(BlockID)) { + if (!Info->Name.empty()) + return Info->Name.c_str(); + } + + + if (CurStreamType != LLVMIRBitstream) return 0; + + switch (BlockID) { + default: return 0; + case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK"; + case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK"; + case bitc::TYPE_BLOCK_ID_OLD: return "TYPE_BLOCK_ID_OLD"; + case bitc::TYPE_BLOCK_ID_NEW: return "TYPE_BLOCK_ID"; + case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK"; + case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK"; + case bitc::TYPE_SYMTAB_BLOCK_ID_OLD: return "TYPE_SYMTAB_OLD"; + case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB"; + case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK"; + case bitc::METADATA_ATTACHMENT_ID: return "METADATA_ATTACHMENT_BLOCK"; + } +} + +/// GetCodeName - Return a symbolic code name if known, otherwise return +/// null. +static const char *GetCodeName(unsigned CodeID, unsigned BlockID, + const BitstreamReader &StreamFile) { + // Standard blocks for all bitcode files. + if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) { + if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { + switch (CodeID) { + default: return 0; + case bitc::BLOCKINFO_CODE_SETBID: return "SETBID"; + case bitc::BLOCKINFO_CODE_BLOCKNAME: return "BLOCKNAME"; + case bitc::BLOCKINFO_CODE_SETRECORDNAME: return "SETRECORDNAME"; + } + } + return 0; + } + + // Check to see if we have a blockinfo record for this record, with a name. + if (const BitstreamReader::BlockInfo *Info = + StreamFile.getBlockInfo(BlockID)) { + for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i) + if (Info->RecordNames[i].first == CodeID) + return Info->RecordNames[i].second.c_str(); + } + + + if (CurStreamType != LLVMIRBitstream) return 0; + + switch (BlockID) { + default: return 0; + case bitc::MODULE_BLOCK_ID: + switch (CodeID) { + default: return 0; + case bitc::MODULE_CODE_VERSION: return "VERSION"; + case bitc::MODULE_CODE_TRIPLE: return "TRIPLE"; + case bitc::MODULE_CODE_DATALAYOUT: return "DATALAYOUT"; + case bitc::MODULE_CODE_ASM: return "ASM"; + case bitc::MODULE_CODE_SECTIONNAME: return "SECTIONNAME"; + case bitc::MODULE_CODE_DEPLIB: return "DEPLIB"; + case bitc::MODULE_CODE_GLOBALVAR: return "GLOBALVAR"; + case bitc::MODULE_CODE_FUNCTION: return "FUNCTION"; + case bitc::MODULE_CODE_ALIAS: return "ALIAS"; + case bitc::MODULE_CODE_PURGEVALS: return "PURGEVALS"; + case bitc::MODULE_CODE_GCNAME: return "GCNAME"; + } + case bitc::PARAMATTR_BLOCK_ID: + switch (CodeID) { + default: return 0; + case bitc::PARAMATTR_CODE_ENTRY: return "ENTRY"; + } + case bitc::TYPE_BLOCK_ID_OLD: + case bitc::TYPE_BLOCK_ID_NEW: + switch (CodeID) { + default: return 0; + case bitc::TYPE_CODE_NUMENTRY: return "NUMENTRY"; + case bitc::TYPE_CODE_VOID: return "VOID"; + case bitc::TYPE_CODE_FLOAT: return "FLOAT"; + case bitc::TYPE_CODE_DOUBLE: return "DOUBLE"; + case bitc::TYPE_CODE_LABEL: return "LABEL"; + case bitc::TYPE_CODE_OPAQUE: return "OPAQUE"; + case bitc::TYPE_CODE_INTEGER: return "INTEGER"; + case bitc::TYPE_CODE_POINTER: return "POINTER"; + case bitc::TYPE_CODE_FUNCTION: return "FUNCTION"; + case bitc::TYPE_CODE_STRUCT_OLD: return "STRUCT_OLD"; + case bitc::TYPE_CODE_ARRAY: return "ARRAY"; + case bitc::TYPE_CODE_VECTOR: return "VECTOR"; + case bitc::TYPE_CODE_X86_FP80: return "X86_FP80"; + case bitc::TYPE_CODE_FP128: return "FP128"; + case bitc::TYPE_CODE_PPC_FP128: return "PPC_FP128"; + case bitc::TYPE_CODE_METADATA: return "METADATA"; + case bitc::TYPE_CODE_STRUCT_ANON: return "STRUCT_ANON"; + case bitc::TYPE_CODE_STRUCT_NAME: return "STRUCT_NAME"; + case bitc::TYPE_CODE_STRUCT_NAMED: return "STRUCT_NAMED"; + } + + case bitc::CONSTANTS_BLOCK_ID: + switch (CodeID) { + default: return 0; + case bitc::CST_CODE_SETTYPE: return "SETTYPE"; + case bitc::CST_CODE_NULL: return "NULL"; + case bitc::CST_CODE_UNDEF: return "UNDEF"; + case bitc::CST_CODE_INTEGER: return "INTEGER"; + case bitc::CST_CODE_WIDE_INTEGER: return "WIDE_INTEGER"; + case bitc::CST_CODE_FLOAT: return "FLOAT"; + case bitc::CST_CODE_AGGREGATE: return "AGGREGATE"; + case bitc::CST_CODE_STRING: return "STRING"; + case bitc::CST_CODE_CSTRING: return "CSTRING"; + case bitc::CST_CODE_CE_BINOP: return "CE_BINOP"; + case bitc::CST_CODE_CE_CAST: return "CE_CAST"; + case bitc::CST_CODE_CE_GEP: return "CE_GEP"; + case bitc::CST_CODE_CE_INBOUNDS_GEP: return "CE_INBOUNDS_GEP"; + case bitc::CST_CODE_CE_SELECT: return "CE_SELECT"; + case bitc::CST_CODE_CE_EXTRACTELT: return "CE_EXTRACTELT"; + case bitc::CST_CODE_CE_INSERTELT: return "CE_INSERTELT"; + case bitc::CST_CODE_CE_SHUFFLEVEC: return "CE_SHUFFLEVEC"; + case bitc::CST_CODE_CE_CMP: return "CE_CMP"; + case bitc::CST_CODE_INLINEASM: return "INLINEASM"; + case bitc::CST_CODE_CE_SHUFVEC_EX: return "CE_SHUFVEC_EX"; + } + case bitc::FUNCTION_BLOCK_ID: + switch (CodeID) { + default: return 0; + case bitc::FUNC_CODE_DECLAREBLOCKS: return "DECLAREBLOCKS"; + + case bitc::FUNC_CODE_INST_BINOP: return "INST_BINOP"; + case bitc::FUNC_CODE_INST_CAST: return "INST_CAST"; + case bitc::FUNC_CODE_INST_GEP: return "INST_GEP"; + case bitc::FUNC_CODE_INST_INBOUNDS_GEP: return "INST_INBOUNDS_GEP"; + case bitc::FUNC_CODE_INST_SELECT: return "INST_SELECT"; + case bitc::FUNC_CODE_INST_EXTRACTELT: return "INST_EXTRACTELT"; + case bitc::FUNC_CODE_INST_INSERTELT: return "INST_INSERTELT"; + case bitc::FUNC_CODE_INST_SHUFFLEVEC: return "INST_SHUFFLEVEC"; + case bitc::FUNC_CODE_INST_CMP: return "INST_CMP"; + + case bitc::FUNC_CODE_INST_RET: return "INST_RET"; + case bitc::FUNC_CODE_INST_BR: return "INST_BR"; + case bitc::FUNC_CODE_INST_SWITCH: return "INST_SWITCH"; + case bitc::FUNC_CODE_INST_INVOKE: return "INST_INVOKE"; + case bitc::FUNC_CODE_INST_UNWIND: return "INST_UNWIND"; + case bitc::FUNC_CODE_INST_UNREACHABLE: return "INST_UNREACHABLE"; + + case bitc::FUNC_CODE_INST_PHI: return "INST_PHI"; + case bitc::FUNC_CODE_INST_ALLOCA: return "INST_ALLOCA"; + case bitc::FUNC_CODE_INST_LOAD: return "INST_LOAD"; + case bitc::FUNC_CODE_INST_VAARG: return "INST_VAARG"; + case bitc::FUNC_CODE_INST_STORE: return "INST_STORE"; + case bitc::FUNC_CODE_INST_EXTRACTVAL: return "INST_EXTRACTVAL"; + case bitc::FUNC_CODE_INST_INSERTVAL: return "INST_INSERTVAL"; + case bitc::FUNC_CODE_INST_CMP2: return "INST_CMP2"; + case bitc::FUNC_CODE_INST_VSELECT: return "INST_VSELECT"; + case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: return "DEBUG_LOC_AGAIN"; + case bitc::FUNC_CODE_INST_CALL: return "INST_CALL"; + case bitc::FUNC_CODE_DEBUG_LOC: return "DEBUG_LOC"; + } + case bitc::TYPE_SYMTAB_BLOCK_ID_OLD: + switch (CodeID) { + default: return 0; + case bitc::TST_CODE_ENTRY: return "ENTRY"; + } + case bitc::VALUE_SYMTAB_BLOCK_ID: + switch (CodeID) { + default: return 0; + case bitc::VST_CODE_ENTRY: return "ENTRY"; + case bitc::VST_CODE_BBENTRY: return "BBENTRY"; + } + case bitc::METADATA_ATTACHMENT_ID: + switch(CodeID) { + default:return 0; + case bitc::METADATA_ATTACHMENT: return "METADATA_ATTACHMENT"; + } + case bitc::METADATA_BLOCK_ID: + switch(CodeID) { + default:return 0; + case bitc::METADATA_STRING: return "METADATA_STRING"; + case bitc::METADATA_NAME: return "METADATA_NAME"; + case bitc::METADATA_KIND: return "METADATA_KIND"; + case bitc::METADATA_NODE: return "METADATA_NODE"; + case bitc::METADATA_FN_NODE: return "METADATA_FN_NODE"; + case bitc::METADATA_NAMED_NODE: return "METADATA_NAMED_NODE"; + } + } +} + +struct PerRecordStats { + unsigned NumInstances; + unsigned NumAbbrev; + uint64_t TotalBits; + + PerRecordStats() : NumInstances(0), NumAbbrev(0), TotalBits(0) {} +}; + +struct PerBlockIDStats { + /// NumInstances - This the number of times this block ID has been seen. + unsigned NumInstances; + + /// NumBits - The total size in bits of all of these blocks. + uint64_t NumBits; + + /// NumSubBlocks - The total number of blocks these blocks contain. + unsigned NumSubBlocks; + + /// NumAbbrevs - The total number of abbreviations. + unsigned NumAbbrevs; + + /// NumRecords - The total number of records these blocks contain, and the + /// number that are abbreviated. + unsigned NumRecords, NumAbbreviatedRecords; + + /// CodeFreq - Keep track of the number of times we see each code. + std::vector CodeFreq; + + PerBlockIDStats() + : NumInstances(0), NumBits(0), + NumSubBlocks(0), NumAbbrevs(0), NumRecords(0), NumAbbreviatedRecords(0) {} +}; + +static std::map BlockIDStats; + + + +/// Error - All bitcode analysis errors go through this function, making this a +/// good place to breakpoint if debugging. +static bool Error(const std::string &Err) { + errs() << Err << "\n"; + return true; +} + +/// ParseBlock - Read a block, updating statistics, etc. +static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { + std::string Indent(IndentLevel*2, ' '); + uint64_t BlockBitStart = Stream.GetCurrentBitNo(); + unsigned BlockID = Stream.ReadSubBlockID(); + + // Get the statistics for this BlockID. + PerBlockIDStats &BlockStats = BlockIDStats[BlockID]; + + BlockStats.NumInstances++; + + // BLOCKINFO is a special part of the stream. + if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { + if (Dump) errs() << Indent << "\n"; + if (Stream.ReadBlockInfoBlock()) + return Error("Malformed BlockInfoBlock"); + uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); + BlockStats.NumBits += BlockBitEnd-BlockBitStart; + return false; + } + + unsigned NumWords = 0; + if (Stream.EnterSubBlock(BlockID, &NumWords)) + return Error("Malformed block record"); + + const char *BlockName = 0; + if (Dump) { + errs() << Indent << "<"; + if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader()))) + errs() << BlockName; + else + errs() << "UnknownBlock" << BlockID; + + if (NonSymbolic && BlockName) + errs() << " BlockID=" << BlockID; + + errs() << " NumWords=" << NumWords + << " BlockCodeSize=" << Stream.GetAbbrevIDWidth() << ">\n"; + } + + SmallVector Record; + + // Read all the records for this block. + while (1) { + if (Stream.AtEndOfStream()) + return Error("Premature end of bitstream"); + + uint64_t RecordStartBit = Stream.GetCurrentBitNo(); + + // Read the code for this record. + unsigned AbbrevID = Stream.ReadCode(); + switch (AbbrevID) { + case bitc::END_BLOCK: { + if (Stream.ReadBlockEnd()) + return Error("Error at end of block"); + uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); + BlockStats.NumBits += BlockBitEnd-BlockBitStart; + if (Dump) { + errs() << Indent << "\n"; + else + errs() << "UnknownBlock" << BlockID << ">\n"; + } + return false; + } + case bitc::ENTER_SUBBLOCK: { + uint64_t SubBlockBitStart = Stream.GetCurrentBitNo(); + if (ParseBlock(Stream, IndentLevel+1)) + return true; + ++BlockStats.NumSubBlocks; + uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo(); + + // Don't include subblock sizes in the size of this block. + BlockBitStart += SubBlockBitEnd-SubBlockBitStart; + break; + } + case bitc::DEFINE_ABBREV: + Stream.ReadAbbrevRecord(); + ++BlockStats.NumAbbrevs; + break; + default: + Record.clear(); + + ++BlockStats.NumRecords; + if (AbbrevID != bitc::UNABBREV_RECORD) + ++BlockStats.NumAbbreviatedRecords; + + const char *BlobStart = 0; + unsigned BlobLen = 0; + unsigned Code = Stream.ReadRecord(AbbrevID, Record, BlobStart, BlobLen); + + + + // Increment the # occurrences of this code. + if (BlockStats.CodeFreq.size() <= Code) + BlockStats.CodeFreq.resize(Code+1); + BlockStats.CodeFreq[Code].NumInstances++; + BlockStats.CodeFreq[Code].TotalBits += + Stream.GetCurrentBitNo()-RecordStartBit; + if (AbbrevID != bitc::UNABBREV_RECORD) + BlockStats.CodeFreq[Code].NumAbbrev++; + + if (Dump) { + errs() << Indent << " <"; + if (const char *CodeName = + GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) + errs() << CodeName; + else + errs() << "UnknownCode" << Code; + if (NonSymbolic && + GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) + errs() << " codeid=" << Code; + if (AbbrevID != bitc::UNABBREV_RECORD) + errs() << " abbrevid=" << AbbrevID; + + for (unsigned i = 0, e = Record.size(); i != e; ++i) + errs() << " op" << i << "=" << (int64_t)Record[i]; + + errs() << "/>"; + + if (BlobStart) { + errs() << " blob data = "; + bool BlobIsPrintable = true; + for (unsigned i = 0; i != BlobLen; ++i) + if (!isprint(BlobStart[i])) { + BlobIsPrintable = false; + break; + } + + if (BlobIsPrintable) + errs() << "'" << std::string(BlobStart, BlobStart+BlobLen) <<"'"; + else + errs() << "unprintable, " << BlobLen << " bytes."; + } + + errs() << "\n"; + } + + break; + } + } +} + +static void PrintSize(double Bits) { + fprintf(stderr, "%.2f/%.2fB/%luW", Bits, Bits/8,(unsigned long)(Bits/32)); +} +static void PrintSize(uint64_t Bits) { + fprintf(stderr, "%lub/%.2fB/%luW", (unsigned long)Bits, + (double)Bits/8, (unsigned long)(Bits/32)); +} + + +/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename. +static int AnalyzeBitcode() { + // Read the input file. + OwningPtr MemBuf; + + if (error_code ec = + MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), MemBuf)) + return Error("Error reading '" + InputFilename + "': " + ec.message()); + + if (MemBuf->getBufferSize() & 3) + return Error("Bitcode stream should be a multiple of 4 bytes in length"); + + unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart(); + unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize(); + + // If we have a wrapper header, parse it and ignore the non-bc file contents. + // The magic number is 0x0B17C0DE stored in little endian. + if (isBitcodeWrapper(BufPtr, EndBufPtr)) + if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr)) + return Error("Invalid bitcode wrapper header"); + + BitstreamReader StreamFile(BufPtr, EndBufPtr); + BitstreamCursor Stream(StreamFile); + StreamFile.CollectBlockInfoNames(); + + // Read the stream signature. + char Signature[6]; + Signature[0] = Stream.Read(8); + Signature[1] = Stream.Read(8); + Signature[2] = Stream.Read(4); + Signature[3] = Stream.Read(4); + Signature[4] = Stream.Read(4); + Signature[5] = Stream.Read(4); + + // Autodetect the file contents, if it is one we know. + CurStreamType = UnknownBitstream; + if (Signature[0] == 'B' && Signature[1] == 'C' && + Signature[2] == 0x0 && Signature[3] == 0xC && + Signature[4] == 0xE && Signature[5] == 0xD) + CurStreamType = LLVMIRBitstream; + + unsigned NumTopBlocks = 0; + + // Parse the top-level structure. We only allow blocks at the top-level. + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + if (Code != bitc::ENTER_SUBBLOCK) + return Error("Invalid record at top-level"); + + if (ParseBlock(Stream, 0)) + return true; + ++NumTopBlocks; + } + + if (Dump) errs() << "\n\n"; + + uint64_t BufferSizeBits = (EndBufPtr-BufPtr)*CHAR_BIT; + // Print a summary of the read file. + errs() << "Summary of " << InputFilename << ":\n"; + errs() << " Total size: "; + PrintSize(BufferSizeBits); + errs() << "\n"; + errs() << " Stream type: "; + switch (CurStreamType) { + default: assert(0 && "Unknown bitstream type"); + case UnknownBitstream: errs() << "unknown\n"; break; + case LLVMIRBitstream: errs() << "LLVM IR\n"; break; + } + errs() << " # Toplevel Blocks: " << NumTopBlocks << "\n"; + errs() << "\n"; + + // Emit per-block stats. + errs() << "Per-block Summary:\n"; + for (std::map::iterator I = BlockIDStats.begin(), + E = BlockIDStats.end(); I != E; ++I) { + errs() << " Block ID #" << I->first; + if (const char *BlockName = GetBlockName(I->first, StreamFile)) + errs() << " (" << BlockName << ")"; + errs() << ":\n"; + + const PerBlockIDStats &Stats = I->second; + errs() << " Num Instances: " << Stats.NumInstances << "\n"; + errs() << " Total Size: "; + PrintSize(Stats.NumBits); + errs() << "\n"; + double pct = (Stats.NumBits * 100.0) / BufferSizeBits; + errs() << " Percent of file: " << format("%2.4f%%", pct) << "\n"; + if (Stats.NumInstances > 1) { + errs() << " Average Size: "; + PrintSize(Stats.NumBits/(double)Stats.NumInstances); + errs() << "\n"; + errs() << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/" + << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n"; + errs() << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/" + << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n"; + errs() << " Tot/Avg Records: " << Stats.NumRecords << "/" + << Stats.NumRecords/(double)Stats.NumInstances << "\n"; + } else { + errs() << " Num SubBlocks: " << Stats.NumSubBlocks << "\n"; + errs() << " Num Abbrevs: " << Stats.NumAbbrevs << "\n"; + errs() << " Num Records: " << Stats.NumRecords << "\n"; + } + if (Stats.NumRecords) { + double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords; + errs() << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n"; + } + errs() << "\n"; + + // Print a histogram of the codes we see. + if (!NoHistogram && !Stats.CodeFreq.empty()) { + std::vector > FreqPairs; // + for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i) + if (unsigned Freq = Stats.CodeFreq[i].NumInstances) + FreqPairs.push_back(std::make_pair(Freq, i)); + std::stable_sort(FreqPairs.begin(), FreqPairs.end()); + std::reverse(FreqPairs.begin(), FreqPairs.end()); + + errs() << "\tRecord Histogram:\n"; + fprintf(stderr, "\t\t Count # Bits %% Abv Record Kind\n"); + for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) { + const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second]; + + fprintf(stderr, "\t\t%7d %9lu ", RecStats.NumInstances, + (unsigned long)RecStats.TotalBits); + + if (RecStats.NumAbbrev) + fprintf(stderr, "%7.2f ", + (double)RecStats.NumAbbrev/RecStats.NumInstances*100); + else + fprintf(stderr, " "); + + if (const char *CodeName = + GetCodeName(FreqPairs[i].second, I->first, StreamFile)) + fprintf(stderr, "%s\n", CodeName); + else + fprintf(stderr, "UnknownCode%d\n", FreqPairs[i].second); + } + errs() << "\n"; + + } + } + return 0; +} + + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n"); + + return AnalyzeBitcode(); +} diff --git a/contrib/llvm/tools/llvm-diff/CMakeLists.txt b/contrib/llvm/tools/llvm-diff/CMakeLists.txt new file mode 100644 index 000000000000..c59d69ea0d45 --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_LINK_COMPONENTS support asmparser bitreader) + +add_llvm_tool(llvm-diff + llvm-diff.cpp + DiffConsumer.cpp + DiffLog.cpp + DifferenceEngine.cpp + ) diff --git a/contrib/llvm/tools/llvm-diff/DiffConsumer.cpp b/contrib/llvm/tools/llvm-diff/DiffConsumer.cpp new file mode 100644 index 000000000000..c23e8fb91a1b --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/DiffConsumer.cpp @@ -0,0 +1,209 @@ +//===-- DiffConsumer.cpp - Difference Consumer ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files implements the the LLVM difference Consumer +// +//===----------------------------------------------------------------------===// + +#include "DiffConsumer.h" + +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +static void ComputeNumbering(Function *F, DenseMap &Numbering){ + unsigned IN = 0; + + // Arguments get the first numbers. + for (Function::arg_iterator + AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) + if (!AI->hasName()) + Numbering[&*AI] = IN++; + + // Walk the basic blocks in order. + for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) { + if (!FI->hasName()) + Numbering[&*FI] = IN++; + + // Walk the instructions in order. + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) + // void instructions don't get numbers. + if (!BI->hasName() && !BI->getType()->isVoidTy()) + Numbering[&*BI] = IN++; + } + + assert(!Numbering.empty() && "asked for numbering but numbering was no-op"); +} + + +void DiffConsumer::printValue(Value *V, bool isL) { + if (V->hasName()) { + out << (isa(V) ? '@' : '%') << V->getName(); + return; + } + if (V->getType()->isVoidTy()) { + if (isa(V)) { + out << "store to "; + printValue(cast(V)->getPointerOperand(), isL); + } else if (isa(V)) { + out << "call to "; + printValue(cast(V)->getCalledValue(), isL); + } else if (isa(V)) { + out << "invoke to "; + printValue(cast(V)->getCalledValue(), isL); + } else { + out << *V; + } + return; + } + + unsigned N = contexts.size(); + while (N > 0) { + --N; + DiffContext &ctxt = contexts[N]; + if (!ctxt.IsFunction) continue; + if (isL) { + if (ctxt.LNumbering.empty()) + ComputeNumbering(cast(ctxt.L), ctxt.LNumbering); + out << '%' << ctxt.LNumbering[V]; + return; + } else { + if (ctxt.RNumbering.empty()) + ComputeNumbering(cast(ctxt.R), ctxt.RNumbering); + out << '%' << ctxt.RNumbering[V]; + return; + } + } + + out << ""; +} + +void DiffConsumer::header() { + if (contexts.empty()) return; + for (SmallVectorImpl::iterator + I = contexts.begin(), E = contexts.end(); I != E; ++I) { + if (I->Differences) continue; + if (isa(I->L)) { + // Extra newline between functions. + if (Differences) out << "\n"; + + Function *L = cast(I->L); + Function *R = cast(I->R); + if (L->getName() != R->getName()) + out << "in function " << L->getName() + << " / " << R->getName() << ":\n"; + else + out << "in function " << L->getName() << ":\n"; + } else if (isa(I->L)) { + BasicBlock *L = cast(I->L); + BasicBlock *R = cast(I->R); + if (L->hasName() && R->hasName() && L->getName() == R->getName()) + out << " in block %" << L->getName() << ":\n"; + else { + out << " in block "; + printValue(L, true); + out << " / "; + printValue(R, false); + out << ":\n"; + } + } else if (isa(I->L)) { + out << " in instruction "; + printValue(I->L, true); + out << " / "; + printValue(I->R, false); + out << ":\n"; + } + + I->Differences = true; + } +} + +void DiffConsumer::indent() { + unsigned N = Indent; + while (N--) out << ' '; +} + +bool DiffConsumer::hadDifferences() const { + return Differences; +} + +void DiffConsumer::enterContext(Value *L, Value *R) { + contexts.push_back(DiffContext(L, R)); + Indent += 2; +} + +void DiffConsumer::exitContext() { + Differences |= contexts.back().Differences; + contexts.pop_back(); + Indent -= 2; +} + +void DiffConsumer::log(StringRef text) { + header(); + indent(); + out << text << '\n'; +} + +void DiffConsumer::logf(const LogBuilder &Log) { + header(); + indent(); + + unsigned arg = 0; + + StringRef format = Log.getFormat(); + while (true) { + size_t percent = format.find('%'); + if (percent == StringRef::npos) { + out << format; + break; + } + assert(format[percent] == '%'); + + if (percent > 0) out << format.substr(0, percent); + + switch (format[percent+1]) { + case '%': out << '%'; break; + case 'l': printValue(Log.getArgument(arg++), true); break; + case 'r': printValue(Log.getArgument(arg++), false); break; + default: llvm_unreachable("unknown format character"); + } + + format = format.substr(percent+2); + } + + out << '\n'; +} + +void DiffConsumer::logd(const DiffLogBuilder &Log) { + header(); + + for (unsigned I = 0, E = Log.getNumLines(); I != E; ++I) { + indent(); + switch (Log.getLineKind(I)) { + case DC_match: + out << " "; + Log.getLeft(I)->dump(); + //printValue(Log.getLeft(I), true); + break; + case DC_left: + out << "< "; + Log.getLeft(I)->dump(); + //printValue(Log.getLeft(I), true); + break; + case DC_right: + out << "> "; + Log.getRight(I)->dump(); + //printValue(Log.getRight(I), false); + break; + } + //out << "\n"; + } +} diff --git a/contrib/llvm/tools/llvm-diff/DiffConsumer.h b/contrib/llvm/tools/llvm-diff/DiffConsumer.h new file mode 100644 index 000000000000..b95d42713a64 --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/DiffConsumer.h @@ -0,0 +1,92 @@ +//===-- DiffConsumer.h - Difference Consumer --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference Consumer +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_DIFFCONSUMER_H_ +#define _LLVM_DIFFCONSUMER_H_ + +#include "DiffLog.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + class Module; + class Value; + class Function; + + /// The interface for consumers of difference data. + class Consumer { + public: + /// Record that a local context has been entered. Left and + /// Right are IR "containers" of some sort which are being + /// considered for structural equivalence: global variables, + /// functions, blocks, instructions, etc. + virtual void enterContext(Value *Left, Value *Right) = 0; + + /// Record that a local context has been exited. + virtual void exitContext() = 0; + + /// Record a difference within the current context. + virtual void log(StringRef Text) = 0; + + /// Record a formatted difference within the current context. + virtual void logf(const LogBuilder &Log) = 0; + + /// Record a line-by-line instruction diff. + virtual void logd(const DiffLogBuilder &Log) = 0; + + protected: + virtual ~Consumer() {} + }; + + class DiffConsumer : public Consumer { + private: + struct DiffContext { + DiffContext(Value *L, Value *R) + : L(L), R(R), Differences(false), IsFunction(isa(L)) {} + Value *L; + Value *R; + bool Differences; + bool IsFunction; + DenseMap LNumbering; + DenseMap RNumbering; + }; + + raw_ostream &out; + Module *LModule; + Module *RModule; + SmallVector contexts; + bool Differences; + unsigned Indent; + + void printValue(Value *V, bool isL); + void header(); + void indent(); + + public: + DiffConsumer(Module *L, Module *R) + : out(errs()), LModule(L), RModule(R), Differences(false), Indent(0) {} + + bool hadDifferences() const; + void enterContext(Value *L, Value *R); + void exitContext(); + void log(StringRef text); + void logf(const LogBuilder &Log); + void logd(const DiffLogBuilder &Log); + }; +} + +#endif diff --git a/contrib/llvm/tools/llvm-diff/DiffLog.cpp b/contrib/llvm/tools/llvm-diff/DiffLog.cpp new file mode 100644 index 000000000000..9cc0c889fd1f --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/DiffLog.cpp @@ -0,0 +1,53 @@ +//===-- DiffLog.h - Difference Log Builder and accessories ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference log builder. +// +//===----------------------------------------------------------------------===// + +#include "DiffLog.h" +#include "DiffConsumer.h" + +#include "llvm/Instructions.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +using namespace llvm; + +LogBuilder::~LogBuilder() { + consumer.logf(*this); +} + +StringRef LogBuilder::getFormat() const { return Format; } + +unsigned LogBuilder::getNumArguments() const { return Arguments.size(); } +Value *LogBuilder::getArgument(unsigned I) const { return Arguments[I]; } + +DiffLogBuilder::~DiffLogBuilder() { consumer.logd(*this); } + +void DiffLogBuilder::addMatch(Instruction *L, Instruction *R) { + Diff.push_back(DiffRecord(L, R)); +} +void DiffLogBuilder::addLeft(Instruction *L) { + // HACK: VS 2010 has a bug in the stdlib that requires this. + Diff.push_back(DiffRecord(L, DiffRecord::second_type(0))); +} +void DiffLogBuilder::addRight(Instruction *R) { + // HACK: VS 2010 has a bug in the stdlib that requires this. + Diff.push_back(DiffRecord(DiffRecord::first_type(0), R)); +} + +unsigned DiffLogBuilder::getNumLines() const { return Diff.size(); } + +DiffChange DiffLogBuilder::getLineKind(unsigned I) const { + return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left) + : DC_right); +} +Instruction *DiffLogBuilder::getLeft(unsigned I) const { return Diff[I].first; } +Instruction *DiffLogBuilder::getRight(unsigned I) const { return Diff[I].second; } diff --git a/contrib/llvm/tools/llvm-diff/DiffLog.h b/contrib/llvm/tools/llvm-diff/DiffLog.h new file mode 100644 index 000000000000..43e318ac4e9f --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/DiffLog.h @@ -0,0 +1,80 @@ +//===-- DiffLog.h - Difference Log Builder and accessories ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference log builder. +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_DIFFLOG_H_ +#define _LLVM_DIFFLOG_H_ + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class Instruction; + class Value; + class Consumer; + + /// Trichotomy assumption + enum DiffChange { DC_match, DC_left, DC_right }; + + /// A temporary-object class for building up log messages. + class LogBuilder { + Consumer &consumer; + + /// The use of a stored StringRef here is okay because + /// LogBuilder should be used only as a temporary, and as a + /// temporary it will be destructed before whatever temporary + /// might be initializing this format. + StringRef Format; + + SmallVector Arguments; + + public: + LogBuilder(Consumer &c, StringRef Format) + : consumer(c), Format(Format) {} + + LogBuilder &operator<<(Value *V) { + Arguments.push_back(V); + return *this; + } + + ~LogBuilder(); + + StringRef getFormat() const; + unsigned getNumArguments() const; + Value *getArgument(unsigned I) const; + }; + + /// A temporary-object class for building up diff messages. + class DiffLogBuilder { + typedef std::pair DiffRecord; + SmallVector Diff; + + Consumer &consumer; + + public: + DiffLogBuilder(Consumer &c) : consumer(c) {} + ~DiffLogBuilder(); + + void addMatch(Instruction *L, Instruction *R); + // HACK: VS 2010 has a bug in the stdlib that requires this. + void addLeft(Instruction *L); + void addRight(Instruction *R); + + unsigned getNumLines() const; + DiffChange getLineKind(unsigned I) const; + Instruction *getLeft(unsigned I) const; + Instruction *getRight(unsigned I) const; + }; + +} + +#endif diff --git a/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp b/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp new file mode 100644 index 000000000000..b240d8c5da5d --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/DifferenceEngine.cpp @@ -0,0 +1,677 @@ +//===-- DifferenceEngine.cpp - Structural function/module comparison ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the implementation of the LLVM difference +// engine, which structurally compares global values within a module. +// +//===----------------------------------------------------------------------===// + +#include "DifferenceEngine.h" + +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/type_traits.h" + +#include + +using namespace llvm; + +namespace { + +/// A priority queue, implemented as a heap. +template +class PriorityQueue { + Sorter Precedes; + llvm::SmallVector Storage; + +public: + PriorityQueue(const Sorter &Precedes) : Precedes(Precedes) {} + + /// Checks whether the heap is empty. + bool empty() const { return Storage.empty(); } + + /// Insert a new value on the heap. + void insert(const T &V) { + unsigned Index = Storage.size(); + Storage.push_back(V); + if (Index == 0) return; + + T *data = Storage.data(); + while (true) { + unsigned Target = (Index + 1) / 2 - 1; + if (!Precedes(data[Index], data[Target])) return; + std::swap(data[Index], data[Target]); + if (Target == 0) return; + Index = Target; + } + } + + /// Remove the minimum value in the heap. Only valid on a non-empty heap. + T remove_min() { + assert(!empty()); + T tmp = Storage[0]; + + unsigned NewSize = Storage.size() - 1; + if (NewSize) { + // Move the slot at the end to the beginning. + if (isPodLike::value) + Storage[0] = Storage[NewSize]; + else + std::swap(Storage[0], Storage[NewSize]); + + // Bubble the root up as necessary. + unsigned Index = 0; + while (true) { + // With a 1-based index, the children would be Index*2 and Index*2+1. + unsigned R = (Index + 1) * 2; + unsigned L = R - 1; + + // If R is out of bounds, we're done after this in any case. + if (R >= NewSize) { + // If L is also out of bounds, we're done immediately. + if (L >= NewSize) break; + + // Otherwise, test whether we should swap L and Index. + if (Precedes(Storage[L], Storage[Index])) + std::swap(Storage[L], Storage[Index]); + break; + } + + // Otherwise, we need to compare with the smaller of L and R. + // Prefer R because it's closer to the end of the array. + unsigned IndexToTest = (Precedes(Storage[L], Storage[R]) ? L : R); + + // If Index is >= the min of L and R, then heap ordering is restored. + if (!Precedes(Storage[IndexToTest], Storage[Index])) + break; + + // Otherwise, keep bubbling up. + std::swap(Storage[IndexToTest], Storage[Index]); + Index = IndexToTest; + } + } + Storage.pop_back(); + + return tmp; + } +}; + +/// A function-scope difference engine. +class FunctionDifferenceEngine { + DifferenceEngine &Engine; + + /// The current mapping from old local values to new local values. + DenseMap Values; + + /// The current mapping from old blocks to new blocks. + DenseMap Blocks; + + DenseSet > TentativeValues; + + unsigned getUnprocPredCount(BasicBlock *Block) const { + unsigned Count = 0; + for (pred_iterator I = pred_begin(Block), E = pred_end(Block); I != E; ++I) + if (!Blocks.count(*I)) Count++; + return Count; + } + + typedef std::pair BlockPair; + + /// A type which sorts a priority queue by the number of unprocessed + /// predecessor blocks it has remaining. + /// + /// This is actually really expensive to calculate. + struct QueueSorter { + const FunctionDifferenceEngine &fde; + explicit QueueSorter(const FunctionDifferenceEngine &fde) : fde(fde) {} + + bool operator()(const BlockPair &Old, const BlockPair &New) { + return fde.getUnprocPredCount(Old.first) + < fde.getUnprocPredCount(New.first); + } + }; + + /// A queue of unified blocks to process. + PriorityQueue Queue; + + /// Try to unify the given two blocks. Enqueues them for processing + /// if they haven't already been processed. + /// + /// Returns true if there was a problem unifying them. + bool tryUnify(BasicBlock *L, BasicBlock *R) { + BasicBlock *&Ref = Blocks[L]; + + if (Ref) { + if (Ref == R) return false; + + Engine.logf("successor %l cannot be equivalent to %r; " + "it's already equivalent to %r") + << L << R << Ref; + return true; + } + + Ref = R; + Queue.insert(BlockPair(L, R)); + return false; + } + + /// Unifies two instructions, given that they're known not to have + /// structural differences. + void unify(Instruction *L, Instruction *R) { + DifferenceEngine::Context C(Engine, L, R); + + bool Result = diff(L, R, true, true); + assert(!Result && "structural differences second time around?"); + (void) Result; + if (!L->use_empty()) + Values[L] = R; + } + + void processQueue() { + while (!Queue.empty()) { + BlockPair Pair = Queue.remove_min(); + diff(Pair.first, Pair.second); + } + } + + void diff(BasicBlock *L, BasicBlock *R) { + DifferenceEngine::Context C(Engine, L, R); + + BasicBlock::iterator LI = L->begin(), LE = L->end(); + BasicBlock::iterator RI = R->begin(); + + llvm::SmallVector, 20> TentativePairs; + + do { + assert(LI != LE && RI != R->end()); + Instruction *LeftI = &*LI, *RightI = &*RI; + + // If the instructions differ, start the more sophisticated diff + // algorithm at the start of the block. + if (diff(LeftI, RightI, false, false)) { + TentativeValues.clear(); + return runBlockDiff(L->begin(), R->begin()); + } + + // Otherwise, tentatively unify them. + if (!LeftI->use_empty()) + TentativeValues.insert(std::make_pair(LeftI, RightI)); + + ++LI, ++RI; + } while (LI != LE); // This is sufficient: we can't get equality of + // terminators if there are residual instructions. + + // Unify everything in the block, non-tentatively this time. + TentativeValues.clear(); + for (LI = L->begin(), RI = R->begin(); LI != LE; ++LI, ++RI) + unify(&*LI, &*RI); + } + + bool matchForBlockDiff(Instruction *L, Instruction *R); + void runBlockDiff(BasicBlock::iterator LI, BasicBlock::iterator RI); + + bool diffCallSites(CallSite L, CallSite R, bool Complain) { + // FIXME: call attributes + if (!equivalentAsOperands(L.getCalledValue(), R.getCalledValue())) { + if (Complain) Engine.log("called functions differ"); + return true; + } + if (L.arg_size() != R.arg_size()) { + if (Complain) Engine.log("argument counts differ"); + return true; + } + for (unsigned I = 0, E = L.arg_size(); I != E; ++I) + if (!equivalentAsOperands(L.getArgument(I), R.getArgument(I))) { + if (Complain) + Engine.logf("arguments %l and %r differ") + << L.getArgument(I) << R.getArgument(I); + return true; + } + return false; + } + + bool diff(Instruction *L, Instruction *R, bool Complain, bool TryUnify) { + // FIXME: metadata (if Complain is set) + + // Different opcodes always imply different operations. + if (L->getOpcode() != R->getOpcode()) { + if (Complain) Engine.log("different instruction types"); + return true; + } + + if (isa(L)) { + if (cast(L)->getPredicate() + != cast(R)->getPredicate()) { + if (Complain) Engine.log("different predicates"); + return true; + } + } else if (isa(L)) { + return diffCallSites(CallSite(L), CallSite(R), Complain); + } else if (isa(L)) { + // FIXME: implement. + + // This is really weird; type uniquing is broken? + if (L->getType() != R->getType()) { + if (!L->getType()->isPointerTy() || !R->getType()->isPointerTy()) { + if (Complain) Engine.log("different phi types"); + return true; + } + } + return false; + + // Terminators. + } else if (isa(L)) { + InvokeInst *LI = cast(L); + InvokeInst *RI = cast(R); + if (diffCallSites(CallSite(LI), CallSite(RI), Complain)) + return true; + + if (TryUnify) { + tryUnify(LI->getNormalDest(), RI->getNormalDest()); + tryUnify(LI->getUnwindDest(), RI->getUnwindDest()); + } + return false; + + } else if (isa(L)) { + BranchInst *LI = cast(L); + BranchInst *RI = cast(R); + if (LI->isConditional() != RI->isConditional()) { + if (Complain) Engine.log("branch conditionality differs"); + return true; + } + + if (LI->isConditional()) { + if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) { + if (Complain) Engine.log("branch conditions differ"); + return true; + } + if (TryUnify) tryUnify(LI->getSuccessor(1), RI->getSuccessor(1)); + } + if (TryUnify) tryUnify(LI->getSuccessor(0), RI->getSuccessor(0)); + return false; + + } else if (isa(L)) { + SwitchInst *LI = cast(L); + SwitchInst *RI = cast(R); + if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) { + if (Complain) Engine.log("switch conditions differ"); + return true; + } + if (TryUnify) tryUnify(LI->getDefaultDest(), RI->getDefaultDest()); + + bool Difference = false; + + DenseMap LCases; + for (unsigned I = 1, E = LI->getNumCases(); I != E; ++I) + LCases[LI->getCaseValue(I)] = LI->getSuccessor(I); + for (unsigned I = 1, E = RI->getNumCases(); I != E; ++I) { + ConstantInt *CaseValue = RI->getCaseValue(I); + BasicBlock *LCase = LCases[CaseValue]; + if (LCase) { + if (TryUnify) tryUnify(LCase, RI->getSuccessor(I)); + LCases.erase(CaseValue); + } else if (!Difference) { + if (Complain) + Engine.logf("right switch has extra case %r") << CaseValue; + Difference = true; + } + } + if (!Difference) + for (DenseMap::iterator + I = LCases.begin(), E = LCases.end(); I != E; ++I) { + if (Complain) + Engine.logf("left switch has extra case %l") << I->first; + Difference = true; + } + return Difference; + } else if (isa(L)) { + return false; + } + + if (L->getNumOperands() != R->getNumOperands()) { + if (Complain) Engine.log("instructions have different operand counts"); + return true; + } + + for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I) { + Value *LO = L->getOperand(I), *RO = R->getOperand(I); + if (!equivalentAsOperands(LO, RO)) { + if (Complain) Engine.logf("operands %l and %r differ") << LO << RO; + return true; + } + } + + return false; + } + + bool equivalentAsOperands(Constant *L, Constant *R) { + // Use equality as a preliminary filter. + if (L == R) + return true; + + if (L->getValueID() != R->getValueID()) + return false; + + // Ask the engine about global values. + if (isa(L)) + return Engine.equivalentAsOperands(cast(L), + cast(R)); + + // Compare constant expressions structurally. + if (isa(L)) + return equivalentAsOperands(cast(L), + cast(R)); + + // Nulls of the "same type" don't always actually have the same + // type; I don't know why. Just white-list them. + if (isa(L)) + return true; + + // Block addresses only match if we've already encountered the + // block. FIXME: tentative matches? + if (isa(L)) + return Blocks[cast(L)->getBasicBlock()] + == cast(R)->getBasicBlock(); + + return false; + } + + bool equivalentAsOperands(ConstantExpr *L, ConstantExpr *R) { + if (L == R) + return true; + if (L->getOpcode() != R->getOpcode()) + return false; + + switch (L->getOpcode()) { + case Instruction::ICmp: + case Instruction::FCmp: + if (L->getPredicate() != R->getPredicate()) + return false; + break; + + case Instruction::GetElementPtr: + // FIXME: inbounds? + break; + + default: + break; + } + + if (L->getNumOperands() != R->getNumOperands()) + return false; + + for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I) + if (!equivalentAsOperands(L->getOperand(I), R->getOperand(I))) + return false; + + return true; + } + + bool equivalentAsOperands(Value *L, Value *R) { + // Fall out if the values have different kind. + // This possibly shouldn't take priority over oracles. + if (L->getValueID() != R->getValueID()) + return false; + + // Value subtypes: Argument, Constant, Instruction, BasicBlock, + // InlineAsm, MDNode, MDString, PseudoSourceValue + + if (isa(L)) + return equivalentAsOperands(cast(L), cast(R)); + + if (isa(L)) + return Values[L] == R || TentativeValues.count(std::make_pair(L, R)); + + if (isa(L)) + return Values[L] == R; + + if (isa(L)) + return Blocks[cast(L)] != R; + + // Pretend everything else is identical. + return true; + } + + // Avoid a gcc warning about accessing 'this' in an initializer. + FunctionDifferenceEngine *this_() { return this; } + +public: + FunctionDifferenceEngine(DifferenceEngine &Engine) : + Engine(Engine), Queue(QueueSorter(*this_())) {} + + void diff(Function *L, Function *R) { + if (L->arg_size() != R->arg_size()) + Engine.log("different argument counts"); + + // Map the arguments. + for (Function::arg_iterator + LI = L->arg_begin(), LE = L->arg_end(), + RI = R->arg_begin(), RE = R->arg_end(); + LI != LE && RI != RE; ++LI, ++RI) + Values[&*LI] = &*RI; + + tryUnify(&*L->begin(), &*R->begin()); + processQueue(); + } +}; + +struct DiffEntry { + DiffEntry() : Cost(0) {} + + unsigned Cost; + llvm::SmallVector Path; // actually of DifferenceEngine::DiffChange +}; + +bool FunctionDifferenceEngine::matchForBlockDiff(Instruction *L, + Instruction *R) { + return !diff(L, R, false, false); +} + +void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart, + BasicBlock::iterator RStart) { + BasicBlock::iterator LE = LStart->getParent()->end(); + BasicBlock::iterator RE = RStart->getParent()->end(); + + unsigned NL = std::distance(LStart, LE); + + SmallVector Paths1(NL+1); + SmallVector Paths2(NL+1); + + DiffEntry *Cur = Paths1.data(); + DiffEntry *Next = Paths2.data(); + + const unsigned LeftCost = 2; + const unsigned RightCost = 2; + const unsigned MatchCost = 0; + + assert(TentativeValues.empty()); + + // Initialize the first column. + for (unsigned I = 0; I != NL+1; ++I) { + Cur[I].Cost = I * LeftCost; + for (unsigned J = 0; J != I; ++J) + Cur[I].Path.push_back(DC_left); + } + + for (BasicBlock::iterator RI = RStart; RI != RE; ++RI) { + // Initialize the first row. + Next[0] = Cur[0]; + Next[0].Cost += RightCost; + Next[0].Path.push_back(DC_right); + + unsigned Index = 1; + for (BasicBlock::iterator LI = LStart; LI != LE; ++LI, ++Index) { + if (matchForBlockDiff(&*LI, &*RI)) { + Next[Index] = Cur[Index-1]; + Next[Index].Cost += MatchCost; + Next[Index].Path.push_back(DC_match); + TentativeValues.insert(std::make_pair(&*LI, &*RI)); + } else if (Next[Index-1].Cost <= Cur[Index].Cost) { + Next[Index] = Next[Index-1]; + Next[Index].Cost += LeftCost; + Next[Index].Path.push_back(DC_left); + } else { + Next[Index] = Cur[Index]; + Next[Index].Cost += RightCost; + Next[Index].Path.push_back(DC_right); + } + } + + std::swap(Cur, Next); + } + + // We don't need the tentative values anymore; everything from here + // on out should be non-tentative. + TentativeValues.clear(); + + SmallVectorImpl &Path = Cur[NL].Path; + BasicBlock::iterator LI = LStart, RI = RStart; + + DiffLogBuilder Diff(Engine.getConsumer()); + + // Drop trailing matches. + while (Path.back() == DC_match) + Path.pop_back(); + + // Skip leading matches. + SmallVectorImpl::iterator + PI = Path.begin(), PE = Path.end(); + while (PI != PE && *PI == DC_match) { + unify(&*LI, &*RI); + ++PI, ++LI, ++RI; + } + + for (; PI != PE; ++PI) { + switch (static_cast(*PI)) { + case DC_match: + assert(LI != LE && RI != RE); + { + Instruction *L = &*LI, *R = &*RI; + unify(L, R); + Diff.addMatch(L, R); + } + ++LI; ++RI; + break; + + case DC_left: + assert(LI != LE); + Diff.addLeft(&*LI); + ++LI; + break; + + case DC_right: + assert(RI != RE); + Diff.addRight(&*RI); + ++RI; + break; + } + } + + // Finishing unifying and complaining about the tails of the block, + // which should be matches all the way through. + while (LI != LE) { + assert(RI != RE); + unify(&*LI, &*RI); + ++LI, ++RI; + } + + // If the terminators have different kinds, but one is an invoke and the + // other is an unconditional branch immediately following a call, unify + // the results and the destinations. + TerminatorInst *LTerm = LStart->getParent()->getTerminator(); + TerminatorInst *RTerm = RStart->getParent()->getTerminator(); + if (isa(LTerm) && isa(RTerm)) { + if (cast(LTerm)->isConditional()) return; + BasicBlock::iterator I = LTerm; + if (I == LStart->getParent()->begin()) return; + --I; + if (!isa(*I)) return; + CallInst *LCall = cast(&*I); + InvokeInst *RInvoke = cast(RTerm); + if (!equivalentAsOperands(LCall->getCalledValue(), RInvoke->getCalledValue())) + return; + if (!LCall->use_empty()) + Values[LCall] = RInvoke; + tryUnify(LTerm->getSuccessor(0), RInvoke->getNormalDest()); + } else if (isa(LTerm) && isa(RTerm)) { + if (cast(RTerm)->isConditional()) return; + BasicBlock::iterator I = RTerm; + if (I == RStart->getParent()->begin()) return; + --I; + if (!isa(*I)) return; + CallInst *RCall = cast(I); + InvokeInst *LInvoke = cast(LTerm); + if (!equivalentAsOperands(LInvoke->getCalledValue(), RCall->getCalledValue())) + return; + if (!LInvoke->use_empty()) + Values[LInvoke] = RCall; + tryUnify(LInvoke->getNormalDest(), RTerm->getSuccessor(0)); + } +} + +} + +void DifferenceEngine::diff(Function *L, Function *R) { + Context C(*this, L, R); + + // FIXME: types + // FIXME: attributes and CC + // FIXME: parameter attributes + + // If both are declarations, we're done. + if (L->empty() && R->empty()) + return; + else if (L->empty()) + log("left function is declaration, right function is definition"); + else if (R->empty()) + log("right function is declaration, left function is definition"); + else + FunctionDifferenceEngine(*this).diff(L, R); +} + +void DifferenceEngine::diff(Module *L, Module *R) { + StringSet<> LNames; + SmallVector, 20> Queue; + + for (Module::iterator I = L->begin(), E = L->end(); I != E; ++I) { + Function *LFn = &*I; + LNames.insert(LFn->getName()); + + if (Function *RFn = R->getFunction(LFn->getName())) + Queue.push_back(std::make_pair(LFn, RFn)); + else + logf("function %l exists only in left module") << LFn; + } + + for (Module::iterator I = R->begin(), E = R->end(); I != E; ++I) { + Function *RFn = &*I; + if (!LNames.count(RFn->getName())) + logf("function %r exists only in right module") << RFn; + } + + for (SmallVectorImpl >::iterator + I = Queue.begin(), E = Queue.end(); I != E; ++I) + diff(I->first, I->second); +} + +bool DifferenceEngine::equivalentAsOperands(GlobalValue *L, GlobalValue *R) { + if (globalValueOracle) return (*globalValueOracle)(L, R); + return L->getName() == R->getName(); +} diff --git a/contrib/llvm/tools/llvm-diff/DifferenceEngine.h b/contrib/llvm/tools/llvm-diff/DifferenceEngine.h new file mode 100644 index 000000000000..5b4f80b99e55 --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/DifferenceEngine.h @@ -0,0 +1,91 @@ +//===-- DifferenceEngine.h - Module comparator ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the interface to the LLVM difference engine, +// which structurally compares functions within a module. +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_DIFFERENCE_ENGINE_H_ +#define _LLVM_DIFFERENCE_ENGINE_H_ + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "DiffLog.h" +#include "DiffConsumer.h" + +#include + +namespace llvm { + class Function; + class GlobalValue; + class Instruction; + class LLVMContext; + class Module; + class Twine; + class Value; + + /// A class for performing structural comparisons of LLVM assembly. + class DifferenceEngine { + public: + /// A RAII object for recording the current context. + struct Context { + Context(DifferenceEngine &Engine, Value *L, Value *R) : Engine(Engine) { + Engine.consumer.enterContext(L, R); + } + + ~Context() { + Engine.consumer.exitContext(); + } + + private: + DifferenceEngine &Engine; + }; + + /// An oracle for answering whether two values are equivalent as + /// operands. + struct Oracle { + virtual bool operator()(Value *L, Value *R) = 0; + + protected: + virtual ~Oracle() {} + }; + + DifferenceEngine(LLVMContext &context, Consumer &consumer) + : context(context), consumer(consumer), globalValueOracle(0) {} + + void diff(Module *L, Module *R); + void diff(Function *L, Function *R); + void log(StringRef text) { + consumer.log(text); + } + LogBuilder logf(StringRef text) { + return LogBuilder(consumer, text); + } + Consumer& getConsumer() const { return consumer; } + + /// Installs an oracle to decide whether two global values are + /// equivalent as operands. Without an oracle, global values are + /// considered equivalent as operands precisely when they have the + /// same name. + void setGlobalValueOracle(Oracle *oracle) { + globalValueOracle = oracle; + } + + /// Determines whether two global values are equivalent. + bool equivalentAsOperands(GlobalValue *L, GlobalValue *R); + + private: + LLVMContext &context; + Consumer &consumer; + Oracle *globalValueOracle; + }; +} + +#endif diff --git a/contrib/llvm/tools/llvm-diff/Makefile b/contrib/llvm/tools/llvm-diff/Makefile new file mode 100644 index 000000000000..58e49fa95962 --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-diff/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = llvm-diff +LINK_COMPONENTS := asmparser bitreader + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-diff/llvm-diff.cpp b/contrib/llvm/tools/llvm-diff/llvm-diff.cpp new file mode 100644 index 000000000000..76853f1e4330 --- /dev/null +++ b/contrib/llvm/tools/llvm-diff/llvm-diff.cpp @@ -0,0 +1,98 @@ +//===-- llvm-diff.cpp - Module comparator command-line driver ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the command-line driver for the difference engine. +// +//===----------------------------------------------------------------------===// + +#include "DiffLog.h" +#include "DifferenceEngine.h" + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/IRReader.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" + +#include +#include + + +using namespace llvm; + +/// Reads a module from a file. On error, messages are written to stderr +/// and null is returned. +static Module *ReadModule(LLVMContext &Context, StringRef Name) { + SMDiagnostic Diag; + Module *M = ParseIRFile(Name, Diag, Context); + if (!M) + Diag.Print("llvmdiff", errs()); + return M; +} + +static void diffGlobal(DifferenceEngine &Engine, Module *L, Module *R, + StringRef Name) { + // Drop leading sigils from the global name. + if (Name.startswith("@")) Name = Name.substr(1); + + Function *LFn = L->getFunction(Name); + Function *RFn = R->getFunction(Name); + if (LFn && RFn) + Engine.diff(LFn, RFn); + else if (!LFn && !RFn) + errs() << "No function named @" << Name << " in either module\n"; + else if (!LFn) + errs() << "No function named @" << Name << " in left module\n"; + else + errs() << "No function named @" << Name << " in right module\n"; +} + +static cl::opt LeftFilename(cl::Positional, + cl::desc(""), + cl::Required); +static cl::opt RightFilename(cl::Positional, + cl::desc(""), + cl::Required); +static cl::list GlobalsToCompare(cl::Positional, + cl::desc("")); + +int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv); + + LLVMContext Context; + + // Load both modules. Die if that fails. + Module *LModule = ReadModule(Context, LeftFilename); + Module *RModule = ReadModule(Context, RightFilename); + if (!LModule || !RModule) return 1; + + DiffConsumer Consumer(LModule, RModule); + DifferenceEngine Engine(Context, Consumer); + + // If any global names were given, just diff those. + if (!GlobalsToCompare.empty()) { + for (unsigned I = 0, E = GlobalsToCompare.size(); I != E; ++I) + diffGlobal(Engine, LModule, RModule, GlobalsToCompare[I]); + + // Otherwise, diff everything in the module. + } else { + Engine.diff(LModule, RModule); + } + + delete LModule; + delete RModule; + + return Consumer.hadDifferences(); +} diff --git a/contrib/llvm/tools/llvm-dis/CMakeLists.txt b/contrib/llvm/tools/llvm-dis/CMakeLists.txt new file mode 100644 index 000000000000..3125f8a5c6bb --- /dev/null +++ b/contrib/llvm/tools/llvm-dis/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS bitreader analysis) +set(LLVM_REQUIRES_EH 1) + +add_llvm_tool(llvm-dis + llvm-dis.cpp + ) diff --git a/contrib/llvm/tools/llvm-dis/Makefile b/contrib/llvm/tools/llvm-dis/Makefile new file mode 100644 index 000000000000..be711000861d --- /dev/null +++ b/contrib/llvm/tools/llvm-dis/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-dis/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. + +TOOLNAME = llvm-dis +LINK_COMPONENTS := bitreader analysis + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-dis/llvm-dis.cpp b/contrib/llvm/tools/llvm-dis/llvm-dis.cpp new file mode 100644 index 000000000000..9020a527866c --- /dev/null +++ b/contrib/llvm/tools/llvm-dis/llvm-dis.cpp @@ -0,0 +1,186 @@ +//===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This utility may be invoked in the following manner: +// llvm-dis [options] - Read LLVM bitcode from stdin, write asm to stdout +// llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm +// to the x.ll file. +// Options: +// --help - Output information about command line switches +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Assembly/AssemblyAnnotationWriter.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" +using namespace llvm; + +static cl::opt +InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +OutputFilename("o", cl::desc("Override output filename"), + cl::value_desc("filename")); + +static cl::opt +Force("f", cl::desc("Enable binary output on terminals")); + +static cl::opt +DontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden); + +static cl::opt +ShowAnnotations("show-annotations", + cl::desc("Add informational comments to the .ll file")); + +namespace { + +static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { + OS << DL.getLine() << ":" << DL.getCol(); + if (MDNode *N = DL.getInlinedAt(getGlobalContext())) { + DebugLoc IDL = DebugLoc::getFromDILocation(N); + if (!IDL.isUnknown()) { + OS << "@"; + printDebugLoc(IDL,OS); + } + } +} +class CommentWriter : public AssemblyAnnotationWriter { +public: + void emitFunctionAnnot(const Function *F, + formatted_raw_ostream &OS) { + OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses + OS << '\n'; + } + void printInfoComment(const Value &V, formatted_raw_ostream &OS) { + bool Padded = false; + if (!V.getType()->isVoidTy()) { + OS.PadToColumn(50); + Padded = true; + OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]"; // Output # uses and type + } + if (const Instruction *I = dyn_cast(&V)) { + const DebugLoc &DL = I->getDebugLoc(); + if (!DL.isUnknown()) { + if (!Padded) { + OS.PadToColumn(50); + Padded = true; + OS << ";"; + } + OS << " [debug line = "; + printDebugLoc(DL,OS); + OS << "]"; + } + if (const DbgDeclareInst *DDI = dyn_cast(I)) { + DIVariable Var(DDI->getVariable()); + if (!Padded) { + OS.PadToColumn(50); + Padded = true; + OS << ";"; + } + OS << " [debug variable = " << Var.getName() << "]"; + } + else if (const DbgValueInst *DVI = dyn_cast(I)) { + DIVariable Var(DVI->getVariable()); + if (!Padded) { + OS.PadToColumn(50); + Padded = true; + OS << ";"; + } + OS << " [debug variable = " << Var.getName() << "]"; + } + } + } +}; + +} // end anon namespace + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + + cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); + + std::string ErrorMessage; + std::auto_ptr M; + + { + OwningPtr BufferPtr; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) + ErrorMessage = ec.message(); + else + M.reset(ParseBitcodeFile(BufferPtr.get(), Context, &ErrorMessage)); + } + + if (M.get() == 0) { + errs() << argv[0] << ": "; + if (ErrorMessage.size()) + errs() << ErrorMessage << "\n"; + else + errs() << "bitcode didn't read correctly.\n"; + return 1; + } + + // Just use stdout. We won't actually print anything on it. + if (DontPrint) + OutputFilename = "-"; + + if (OutputFilename.empty()) { // Unspecified output, infer it. + if (InputFilename == "-") { + OutputFilename = "-"; + } else { + const std::string &IFN = InputFilename; + int Len = IFN.length(); + // If the source ends in .bc, strip it off. + if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') + OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll"; + else + OutputFilename = IFN+".ll"; + } + } + + std::string ErrorInfo; + OwningPtr + Out(new tool_output_file(OutputFilename.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary)); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << '\n'; + return 1; + } + + OwningPtr Annotator; + if (ShowAnnotations) + Annotator.reset(new CommentWriter()); + + // All that llvm-dis does is write the assembly to a file. + if (!DontPrint) + M->print(Out->os(), Annotator.get()); + + // Declare success. + Out->keep(); + + return 0; +} + diff --git a/contrib/llvm/tools/llvm-extract/CMakeLists.txt b/contrib/llvm/tools/llvm-extract/CMakeLists.txt new file mode 100644 index 000000000000..a4e3266e3532 --- /dev/null +++ b/contrib/llvm/tools/llvm-extract/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS asmparser ipo bitreader bitwriter) + +add_llvm_tool(llvm-extract + llvm-extract.cpp + ) diff --git a/contrib/llvm/tools/llvm-extract/Makefile b/contrib/llvm/tools/llvm-extract/Makefile new file mode 100644 index 000000000000..5672aa3299a2 --- /dev/null +++ b/contrib/llvm/tools/llvm-extract/Makefile @@ -0,0 +1,18 @@ +##===- tools/llvm-extract/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. + +TOOLNAME = llvm-extract +LINK_COMPONENTS := ipo bitreader bitwriter asmparser + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-extract/llvm-extract.cpp b/contrib/llvm/tools/llvm-extract/llvm-extract.cpp new file mode 100644 index 000000000000..f6227ee25553 --- /dev/null +++ b/contrib/llvm/tools/llvm-extract/llvm-extract.cpp @@ -0,0 +1,238 @@ +//===- llvm-extract.cpp - LLVM function extraction utility ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This utility changes the input module to only contain a single function, +// which is primarily used for debugging transformations. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/IRReader.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Regex.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SetVector.h" +#include +using namespace llvm; + +// InputFilename - The filename to read from. +static cl::opt +InputFilename(cl::Positional, cl::desc(""), + cl::init("-"), cl::value_desc("filename")); + +static cl::opt +OutputFilename("o", cl::desc("Specify output filename"), + cl::value_desc("filename"), cl::init("-")); + +static cl::opt +Force("f", cl::desc("Enable binary output on terminals")); + +static cl::opt +DeleteFn("delete", cl::desc("Delete specified Globals from Module")); + +// ExtractFuncs - The functions to extract from the module. +static cl::list +ExtractFuncs("func", cl::desc("Specify function to extract"), + cl::ZeroOrMore, cl::value_desc("function")); + +// ExtractRegExpFuncs - The functions, matched via regular expression, to +// extract from the module. +static cl::list +ExtractRegExpFuncs("rfunc", cl::desc("Specify function(s) to extract using a " + "regular expression"), + cl::ZeroOrMore, cl::value_desc("rfunction")); + +// ExtractGlobals - The globals to extract from the module. +static cl::list +ExtractGlobals("glob", cl::desc("Specify global to extract"), + cl::ZeroOrMore, cl::value_desc("global")); + +// ExtractRegExpGlobals - The globals, matched via regular expression, to +// extract from the module... +static cl::list +ExtractRegExpGlobals("rglob", cl::desc("Specify global(s) to extract using a " + "regular expression"), + cl::ZeroOrMore, cl::value_desc("rglobal")); + +static cl::opt +OutputAssembly("S", + cl::desc("Write output as LLVM assembly"), cl::Hidden); + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); + + // Use lazy loading, since we only care about selected global values. + SMDiagnostic Err; + std::auto_ptr M; + M.reset(getLazyIRFileModule(InputFilename, Err, Context)); + + if (M.get() == 0) { + Err.Print(argv[0], errs()); + return 1; + } + + // Use SetVector to avoid duplicates. + SetVector GVs; + + // Figure out which globals we should extract. + for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { + GlobalValue *GV = M.get()->getNamedGlobal(ExtractGlobals[i]); + if (!GV) { + errs() << argv[0] << ": program doesn't contain global named '" + << ExtractGlobals[i] << "'!\n"; + return 1; + } + GVs.insert(GV); + } + + // Extract globals via regular expression matching. + for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { + std::string Error; + Regex RegEx(ExtractRegExpGlobals[i]); + if (!RegEx.isValid(Error)) { + errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " + "invalid regex: " << Error; + } + bool match = false; + for (Module::global_iterator GV = M.get()->global_begin(), + E = M.get()->global_end(); GV != E; GV++) { + if (RegEx.match(GV->getName())) { + GVs.insert(&*GV); + match = true; + } + } + if (!match) { + errs() << argv[0] << ": program doesn't contain global named '" + << ExtractRegExpGlobals[i] << "'!\n"; + return 1; + } + } + + // Figure out which functions we should extract. + for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { + GlobalValue *GV = M.get()->getFunction(ExtractFuncs[i]); + if (!GV) { + errs() << argv[0] << ": program doesn't contain function named '" + << ExtractFuncs[i] << "'!\n"; + return 1; + } + GVs.insert(GV); + } + // Extract functions via regular expression matching. + for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { + std::string Error; + StringRef RegExStr = ExtractRegExpFuncs[i]; + Regex RegEx(RegExStr); + if (!RegEx.isValid(Error)) { + errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " + "invalid regex: " << Error; + } + bool match = false; + for (Module::iterator F = M.get()->begin(), E = M.get()->end(); F != E; + F++) { + if (RegEx.match(F->getName())) { + GVs.insert(&*F); + match = true; + } + } + if (!match) { + errs() << argv[0] << ": program doesn't contain global named '" + << ExtractRegExpFuncs[i] << "'!\n"; + return 1; + } + } + + // Materialize requisite global values. + if (!DeleteFn) + for (size_t i = 0, e = GVs.size(); i != e; ++i) { + GlobalValue *GV = GVs[i]; + if (GV->isMaterializable()) { + std::string ErrInfo; + if (GV->Materialize(&ErrInfo)) { + errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; + return 1; + } + } + } + else { + // Deleting. Materialize every GV that's *not* in GVs. + SmallPtrSet GVSet(GVs.begin(), GVs.end()); + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + GlobalVariable *G = I; + if (!GVSet.count(G) && G->isMaterializable()) { + std::string ErrInfo; + if (G->Materialize(&ErrInfo)) { + errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; + return 1; + } + } + } + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { + Function *F = I; + if (!GVSet.count(F) && F->isMaterializable()) { + std::string ErrInfo; + if (F->Materialize(&ErrInfo)) { + errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; + return 1; + } + } + } + } + + // In addition to deleting all other functions, we also want to spiff it + // up a little bit. Do this now. + PassManager Passes; + Passes.add(new TargetData(M.get())); // Use correct TargetData + + std::vector Gvs(GVs.begin(), GVs.end()); + + Passes.add(createGVExtractionPass(Gvs, DeleteFn)); + if (!DeleteFn) + Passes.add(createGlobalDCEPass()); // Delete unreachable globals + Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info + Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls + + std::string ErrorInfo; + tool_output_file Out(OutputFilename.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << '\n'; + return 1; + } + + if (OutputAssembly) + Passes.add(createPrintModulePass(&Out.os())); + else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) + Passes.add(createBitcodeWriterPass(Out.os())); + + Passes.run(*M.get()); + + // Declare success. + Out.keep(); + + return 0; +} diff --git a/contrib/llvm/tools/llvm-ld/CMakeLists.txt b/contrib/llvm/tools/llvm-ld/CMakeLists.txt new file mode 100644 index 000000000000..370bcb4abf52 --- /dev/null +++ b/contrib/llvm/tools/llvm-ld/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_LINK_COMPONENTS ipo scalaropts linker archive bitwriter) + +add_llvm_tool(llvm-ld + Optimize.cpp + llvm-ld.cpp + ) + +add_dependencies(llvm-ld llvm-stub) diff --git a/contrib/llvm/tools/llvm-ld/Makefile b/contrib/llvm/tools/llvm-ld/Makefile new file mode 100644 index 000000000000..1ef9bf117450 --- /dev/null +++ b/contrib/llvm/tools/llvm-ld/Makefile @@ -0,0 +1,15 @@ +##===- tools/llvm-ld/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. + +TOOLNAME = llvm-ld +LINK_COMPONENTS = ipo scalaropts linker archive bitwriter + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-ld/Optimize.cpp b/contrib/llvm/tools/llvm-ld/Optimize.cpp new file mode 100644 index 000000000000..7f3f90014fc2 --- /dev/null +++ b/contrib/llvm/tools/llvm-ld/Optimize.cpp @@ -0,0 +1,130 @@ +//===- Optimize.cpp - Optimize a complete program -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements all optimization of the linked module for llvm-ld. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/PassNameParser.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Scalar.h" +using namespace llvm; + +// Pass Name Options as generated by the PassNameParser +static cl::list + OptimizationList(cl::desc("Optimizations available:")); + +//Don't verify at the end +static cl::opt DontVerify("disable-verify", cl::ReallyHidden); + +static cl::opt DisableInline("disable-inlining", + cl::desc("Do not run the inliner pass")); + +static cl::opt +DisableOptimizations("disable-opt", + cl::desc("Do not run any optimization passes")); + +static cl::opt DisableInternalize("disable-internalize", + cl::desc("Do not mark all symbols as internal")); + +static cl::opt VerifyEach("verify-each", + cl::desc("Verify intermediate results of all passes")); + +static cl::alias ExportDynamic("export-dynamic", + cl::aliasopt(DisableInternalize), + cl::desc("Alias for -disable-internalize")); + +static cl::opt Strip("strip-all", + cl::desc("Strip all symbol info from executable")); + +static cl::alias A0("s", cl::desc("Alias for --strip-all"), + cl::aliasopt(Strip)); + +static cl::opt StripDebug("strip-debug", + cl::desc("Strip debugger symbol info from executable")); + +static cl::alias A1("S", cl::desc("Alias for --strip-debug"), + cl::aliasopt(StripDebug)); + +// A utility function that adds a pass to the pass manager but will also add +// a verifier pass after if we're supposed to verify. +static inline void addPass(PassManager &PM, Pass *P) { + // Add the pass to the pass manager... + PM.add(P); + + // If we are verifying all of the intermediate steps, add the verifier... + if (VerifyEach) + PM.add(createVerifierPass()); +} + +namespace llvm { +/// Optimize - Perform link time optimizations. This will run the scalar +/// optimizations, any loaded plugin-optimization modules, and then the +/// inter-procedural optimizations if applicable. +void Optimize(Module *M) { + + // Instantiate the pass manager to organize the passes. + PassManager Passes; + + // If we're verifying, start off with a verification pass. + if (VerifyEach) + Passes.add(createVerifierPass()); + + // Add an appropriate TargetData instance for this module... + addPass(Passes, new TargetData(M)); + + if (!DisableOptimizations) + PassManagerBuilder().populateLTOPassManager(Passes, !DisableInternalize, + !DisableInline); + + // If the -s or -S command line options were specified, strip the symbols out + // of the resulting program to make it smaller. -s and -S are GNU ld options + // that we are supporting; they alias -strip-all and -strip-debug. + if (Strip || StripDebug) + addPass(Passes, createStripSymbolsPass(StripDebug && !Strip)); + + // Create a new optimization pass for each one specified on the command line + std::auto_ptr target; + for (unsigned i = 0; i < OptimizationList.size(); ++i) { + const PassInfo *Opt = OptimizationList[i]; + if (Opt->getNormalCtor()) + addPass(Passes, Opt->getNormalCtor()()); + else + errs() << "llvm-ld: cannot create pass: " << Opt->getPassName() + << "\n"; + } + + // The user's passes may leave cruft around. Clean up after them them but + // only if we haven't got DisableOptimizations set + if (!DisableOptimizations) { + addPass(Passes, createInstructionCombiningPass()); + addPass(Passes, createCFGSimplificationPass()); + addPass(Passes, createAggressiveDCEPass()); + addPass(Passes, createGlobalDCEPass()); + } + + // Make sure everything is still good. + if (!DontVerify) + Passes.add(createVerifierPass()); + + // Run our queue of passes all at once now, efficiently. + Passes.run(*M); +} + +} diff --git a/contrib/llvm/tools/llvm-ld/llvm-ld.cpp b/contrib/llvm/tools/llvm-ld/llvm-ld.cpp new file mode 100644 index 000000000000..6b4c3c7728e5 --- /dev/null +++ b/contrib/llvm/tools/llvm-ld/llvm-ld.cpp @@ -0,0 +1,732 @@ +//===- llvm-ld.cpp - LLVM 'ld' compatible linker --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This utility is intended to be compatible with GCC, and follows standard +// system 'ld' conventions. As such, the default output file is ./a.out. +// Additionally, this program outputs a shell script that is used to invoke LLI +// to execute the program. In this manner, the generated executable (a.out for +// example), is directly executable, whereas the bitcode file actually lives in +// the a.out.bc file generated by this program. +// +// Note that if someone (or a script) deletes the executable program generated, +// the .bc file will be left around. Considering that this is a temporary hack, +// I'm not too worried about this. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LinkAllVMCore.h" +#include "llvm/Linker.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/Program.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Signals.h" +#include "llvm/Config/config.h" +#include +#include +using namespace llvm; + +// Rightly this should go in a header file but it just seems such a waste. +namespace llvm { +extern void Optimize(Module*); +} + +// Input/Output Options +static cl::list InputFilenames(cl::Positional, cl::OneOrMore, + cl::desc("")); + +static cl::opt OutputFilename("o", cl::init("a.out"), + cl::desc("Override output filename"), + cl::value_desc("filename")); + +static cl::opt BitcodeOutputFilename("b", cl::init(""), + cl::desc("Override bitcode output filename"), + cl::value_desc("filename")); + +static cl::opt Verbose("v", + cl::desc("Print information about actions taken")); + +static cl::list LibPaths("L", cl::Prefix, + cl::desc("Specify a library search path"), + cl::value_desc("directory")); + +static cl::list FrameworkPaths("F", cl::Prefix, + cl::desc("Specify a framework search path"), + cl::value_desc("directory")); + +static cl::list Libraries("l", cl::Prefix, + cl::desc("Specify libraries to link to"), + cl::value_desc("library prefix")); + +static cl::list Frameworks("framework", + cl::desc("Specify frameworks to link to"), + cl::value_desc("framework")); + +// Options to control the linking, optimization, and code gen processes +static cl::opt LinkAsLibrary("link-as-library", + cl::desc("Link the .bc files together as a library, not an executable")); + +static cl::alias Relink("r", cl::aliasopt(LinkAsLibrary), + cl::desc("Alias for -link-as-library")); + +static cl::opt Native("native", + cl::desc("Generate a native binary instead of a shell script")); + +static cl::optNativeCBE("native-cbe", + cl::desc("Generate a native binary with the C backend and GCC")); + +static cl::list PostLinkOpts("post-link-opts", + cl::value_desc("path"), + cl::desc("Run one or more optimization programs after linking")); + +static cl::list XLinker("Xlinker", cl::value_desc("option"), + cl::desc("Pass options to the system linker")); + +// Compatibility options that llvm-ld ignores but are supported for +// compatibility with LD +static cl::opt CO3("soname", cl::Hidden, + cl::desc("Compatibility option: ignored")); + +static cl::opt CO4("version-script", cl::Hidden, + cl::desc("Compatibility option: ignored")); + +static cl::opt CO5("eh-frame-hdr", cl::Hidden, + cl::desc("Compatibility option: ignored")); + +static cl::opt CO6("h", cl::Hidden, + cl::desc("Compatibility option: ignored")); + +static cl::opt CO7("start-group", cl::Hidden, + cl::desc("Compatibility option: ignored")); + +static cl::opt CO8("end-group", cl::Hidden, + cl::desc("Compatibility option: ignored")); + +static cl::opt CO9("m", cl::Hidden, + cl::desc("Compatibility option: ignored")); + +/// This is just for convenience so it doesn't have to be passed around +/// everywhere. +static std::string progname; + +/// FileRemover objects to clean up output files in the event of an error. +static FileRemover OutputRemover; +static FileRemover BitcodeOutputRemover; + +/// PrintAndExit - Prints a message to standard error and exits with error code +/// +/// Inputs: +/// Message - The message to print to standard error. +/// +static void PrintAndExit(const std::string &Message, Module *M, int errcode = 1) { + errs() << progname << ": " << Message << "\n"; + delete M; + llvm_shutdown(); + exit(errcode); +} + +static void PrintCommand(const std::vector &args) { + std::vector::const_iterator I = args.begin(), E = args.end(); + for (; I != E; ++I) + if (*I) + errs() << "'" << *I << "'" << " "; + errs() << "\n"; +} + +/// CopyEnv - This function takes an array of environment variables and makes a +/// copy of it. This copy can then be manipulated any way the caller likes +/// without affecting the process's real environment. +/// +/// Inputs: +/// envp - An array of C strings containing an environment. +/// +/// Return value: +/// NULL - An error occurred. +/// +/// Otherwise, a pointer to a new array of C strings is returned. Every string +/// in the array is a duplicate of the one in the original array (i.e. we do +/// not copy the char *'s from one array to another). +/// +static char ** CopyEnv(char ** const envp) { + // Count the number of entries in the old list; + unsigned entries; // The number of entries in the old environment list + for (entries = 0; envp[entries] != NULL; entries++) + /*empty*/; + + // Add one more entry for the NULL pointer that ends the list. + ++entries; + + // If there are no entries at all, just return NULL. + if (entries == 0) + return NULL; + + // Allocate a new environment list. + char **newenv = new char* [entries]; + if (newenv == NULL) + return NULL; + + // Make a copy of the list. Don't forget the NULL that ends the list. + entries = 0; + while (envp[entries] != NULL) { + size_t len = strlen(envp[entries]) + 1; + newenv[entries] = new char[len]; + memcpy(newenv[entries], envp[entries], len); + ++entries; + } + newenv[entries] = NULL; + + return newenv; +} + + +/// RemoveEnv - Remove the specified environment variable from the environment +/// array. +/// +/// Inputs: +/// name - The name of the variable to remove. It cannot be NULL. +/// envp - The array of environment variables. It cannot be NULL. +/// +/// Notes: +/// This is mainly done because functions to remove items from the environment +/// are not available across all platforms. In particular, Solaris does not +/// seem to have an unsetenv() function or a setenv() function (or they are +/// undocumented if they do exist). +/// +static void RemoveEnv(const char * name, char ** const envp) { + for (unsigned index=0; envp[index] != NULL; index++) { + // Find the first equals sign in the array and make it an EOS character. + char *p = strchr (envp[index], '='); + if (p == NULL) + continue; + else + *p = '\0'; + + // Compare the two strings. If they are equal, zap this string. + // Otherwise, restore it. + if (!strcmp(name, envp[index])) + *envp[index] = '\0'; + else + *p = '='; + } + + return; +} + +/// GenerateBitcode - generates a bitcode file from the module provided +void GenerateBitcode(Module* M, const std::string& FileName) { + + if (Verbose) + errs() << "Generating Bitcode To " << FileName << '\n'; + + // Create the output file. + std::string ErrorInfo; + tool_output_file Out(FileName.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary); + if (!ErrorInfo.empty()) { + PrintAndExit(ErrorInfo, M); + return; + } + + // Write it out + WriteBitcodeToFile(M, Out.os()); + Out.keep(); +} + +/// GenerateAssembly - generates a native assembly language source file from the +/// specified bitcode file. +/// +/// Inputs: +/// InputFilename - The name of the input bitcode file. +/// OutputFilename - The name of the file to generate. +/// llc - The pathname to use for LLC. +/// envp - The environment to use when running LLC. +/// +/// Return non-zero value on error. +/// +static int GenerateAssembly(const std::string &OutputFilename, + const std::string &InputFilename, + const sys::Path &llc, + std::string &ErrMsg ) { + // Run LLC to convert the bitcode file into assembly code. + std::vector args; + args.push_back(llc.c_str()); + // We will use GCC to assemble the program so set the assembly syntax to AT&T, + // regardless of what the target in the bitcode file is. + args.push_back("-x86-asm-syntax=att"); + args.push_back("-o"); + args.push_back(OutputFilename.c_str()); + args.push_back(InputFilename.c_str()); + args.push_back(0); + + if (Verbose) { + errs() << "Generating Assembly With: \n"; + PrintCommand(args); + } + + return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg); +} + +/// GenerateCFile - generates a C source file from the specified bitcode file. +static int GenerateCFile(const std::string &OutputFile, + const std::string &InputFile, + const sys::Path &llc, + std::string& ErrMsg) { + // Run LLC to convert the bitcode file into C. + std::vector args; + args.push_back(llc.c_str()); + args.push_back("-march=c"); + args.push_back("-o"); + args.push_back(OutputFile.c_str()); + args.push_back(InputFile.c_str()); + args.push_back(0); + + if (Verbose) { + errs() << "Generating C Source With: \n"; + PrintCommand(args); + } + + return sys::Program::ExecuteAndWait(llc, &args[0], 0, 0, 0, 0, &ErrMsg); +} + +/// GenerateNative - generates a native object file from the +/// specified bitcode file. +/// +/// Inputs: +/// InputFilename - The name of the input bitcode file. +/// OutputFilename - The name of the file to generate. +/// NativeLinkItems - The native libraries, files, code with which to link +/// LibPaths - The list of directories in which to find libraries. +/// FrameworksPaths - The list of directories in which to find frameworks. +/// Frameworks - The list of frameworks (dynamic libraries) +/// gcc - The pathname to use for GGC. +/// envp - A copy of the process's current environment. +/// +/// Outputs: +/// None. +/// +/// Returns non-zero value on error. +/// +static int GenerateNative(const std::string &OutputFilename, + const std::string &InputFilename, + const Linker::ItemList &LinkItems, + const sys::Path &gcc, char ** const envp, + std::string& ErrMsg) { + // Remove these environment variables from the environment of the + // programs that we will execute. It appears that GCC sets these + // environment variables so that the programs it uses can configure + // themselves identically. + // + // However, when we invoke GCC below, we want it to use its normal + // configuration. Hence, we must sanitize its environment. + char ** clean_env = CopyEnv(envp); + if (clean_env == NULL) + return 1; + RemoveEnv("LIBRARY_PATH", clean_env); + RemoveEnv("COLLECT_GCC_OPTIONS", clean_env); + RemoveEnv("GCC_EXEC_PREFIX", clean_env); + RemoveEnv("COMPILER_PATH", clean_env); + RemoveEnv("COLLECT_GCC", clean_env); + + + // Run GCC to assemble and link the program into native code. + // + // Note: + // We can't just assemble and link the file with the system assembler + // and linker because we don't know where to put the _start symbol. + // GCC mysteriously knows how to do it. + std::vector args; + args.push_back(gcc.c_str()); + args.push_back("-fno-strict-aliasing"); + args.push_back("-O3"); + args.push_back("-o"); + args.push_back(OutputFilename); + args.push_back(InputFilename); + + // Add in the library and framework paths + for (unsigned index = 0; index < LibPaths.size(); index++) { + args.push_back("-L" + LibPaths[index]); + } + for (unsigned index = 0; index < FrameworkPaths.size(); index++) { + args.push_back("-F" + FrameworkPaths[index]); + } + + // Add the requested options + for (unsigned index = 0; index < XLinker.size(); index++) + args.push_back(XLinker[index]); + + // Add in the libraries to link. + for (unsigned index = 0; index < LinkItems.size(); index++) + if (LinkItems[index].first != "crtend") { + if (LinkItems[index].second) + args.push_back("-l" + LinkItems[index].first); + else + args.push_back(LinkItems[index].first); + } + + // Add in frameworks to link. + for (unsigned index = 0; index < Frameworks.size(); index++) { + args.push_back("-framework"); + args.push_back(Frameworks[index]); + } + + // Now that "args" owns all the std::strings for the arguments, call the c_str + // method to get the underlying string array. We do this game so that the + // std::string array is guaranteed to outlive the const char* array. + std::vector Args; + for (unsigned i = 0, e = args.size(); i != e; ++i) + Args.push_back(args[i].c_str()); + Args.push_back(0); + + if (Verbose) { + errs() << "Generating Native Executable With:\n"; + PrintCommand(Args); + } + + // Run the compiler to assembly and link together the program. + int R = sys::Program::ExecuteAndWait( + gcc, &Args[0], const_cast(clean_env), 0, 0, 0, &ErrMsg); + delete [] clean_env; + return R; +} + +/// EmitShellScript - Output the wrapper file that invokes the JIT on the LLVM +/// bitcode file for the program. +static void EmitShellScript(char **argv, Module *M) { + if (Verbose) + errs() << "Emitting Shell Script\n"; +#if defined(_WIN32) + // Windows doesn't support #!/bin/sh style shell scripts in .exe files. To + // support windows systems, we copy the llvm-stub.exe executable from the + // build tree to the destination file. + std::string ErrMsg; + sys::Path llvmstub = PrependMainExecutablePath("llvm-stub", argv[0], + (void *)(intptr_t)&Optimize); + if (llvmstub.isEmpty()) + PrintAndExit("Could not find llvm-stub.exe executable!", M); + + if (0 != sys::CopyFile(sys::Path(OutputFilename), llvmstub, &ErrMsg)) + PrintAndExit(ErrMsg, M); + + return; +#endif + + // Output the script to start the program... + std::string ErrorInfo; + tool_output_file Out2(OutputFilename.c_str(), ErrorInfo); + if (!ErrorInfo.empty()) + PrintAndExit(ErrorInfo, M); + + Out2.os() << "#!/bin/sh\n"; + // Allow user to setenv LLVMINTERP if lli is not in their PATH. + Out2.os() << "lli=${LLVMINTERP-lli}\n"; + Out2.os() << "exec $lli \\\n"; + // gcc accepts -l and implicitly searches /lib and /usr/lib. + LibPaths.push_back("/lib"); + LibPaths.push_back("/usr/lib"); + LibPaths.push_back("/usr/X11R6/lib"); + // We don't need to link in libc! In fact, /usr/lib/libc.so may not be a + // shared object at all! See RH 8: plain text. + std::vector::iterator libc = + std::find(Libraries.begin(), Libraries.end(), "c"); + if (libc != Libraries.end()) Libraries.erase(libc); + // List all the shared object (native) libraries this executable will need + // on the command line, so that we don't have to do this manually! + for (std::vector::iterator i = Libraries.begin(), + e = Libraries.end(); i != e; ++i) { + // try explicit -L arguments first: + sys::Path FullLibraryPath; + for (cl::list::const_iterator P = LibPaths.begin(), + E = LibPaths.end(); P != E; ++P) { + FullLibraryPath = *P; + FullLibraryPath.appendComponent("lib" + *i); + FullLibraryPath.appendSuffix(sys::Path::GetDLLSuffix()); + if (!FullLibraryPath.isEmpty()) { + if (!FullLibraryPath.isDynamicLibrary()) { + // Not a native shared library; mark as invalid + FullLibraryPath = sys::Path(); + } else break; + } + } + if (FullLibraryPath.isEmpty()) + FullLibraryPath = sys::Path::FindLibrary(*i); + if (!FullLibraryPath.isEmpty()) + Out2.os() << " -load=" << FullLibraryPath.str() << " \\\n"; + } + Out2.os() << " " << BitcodeOutputFilename << " ${1+\"$@\"}\n"; + Out2.keep(); +} + +// BuildLinkItems -- This function generates a LinkItemList for the LinkItems +// linker function by combining the Files and Libraries in the order they were +// declared on the command line. +static void BuildLinkItems( + Linker::ItemList& Items, + const cl::list& Files, + const cl::list& Libraries) { + + // Build the list of linkage items for LinkItems. + + cl::list::const_iterator fileIt = Files.begin(); + cl::list::const_iterator libIt = Libraries.begin(); + + int libPos = -1, filePos = -1; + while ( libIt != Libraries.end() || fileIt != Files.end() ) { + if (libIt != Libraries.end()) + libPos = Libraries.getPosition(libIt - Libraries.begin()); + else + libPos = -1; + if (fileIt != Files.end()) + filePos = Files.getPosition(fileIt - Files.begin()); + else + filePos = -1; + + if (filePos != -1 && (libPos == -1 || filePos < libPos)) { + // Add a source file + Items.push_back(std::make_pair(*fileIt++, false)); + } else if (libPos != -1 && (filePos == -1 || libPos < filePos)) { + // Add a library + Items.push_back(std::make_pair(*libIt++, true)); + } + } +} + +int main(int argc, char **argv, char **envp) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize passes + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeScalarOpts(Registry); + initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + initializeTarget(Registry); + + // Initial global variable above for convenience printing of program name. + progname = sys::path::stem(argv[0]); + + // Parse the command line options + cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); + +#if defined(_WIN32) || defined(__CYGWIN__) + if (!LinkAsLibrary) { + // Default to "a.exe" instead of "a.out". + if (OutputFilename.getNumOccurrences() == 0) + OutputFilename = "a.exe"; + + // If there is no suffix add an "exe" one. + if (sys::path::extension(OutputFilename).empty()) + OutputFilename.append(".exe"); + } +#endif + + // Generate the bitcode for the optimized module. + // If -b wasn't specified, use the name specified + // with -o to construct BitcodeOutputFilename. + if (BitcodeOutputFilename.empty()) { + BitcodeOutputFilename = OutputFilename; + if (!LinkAsLibrary) BitcodeOutputFilename += ".bc"; + } + + // Arrange for the bitcode output file to be deleted on any errors. + BitcodeOutputRemover.setFile(BitcodeOutputFilename); + sys::RemoveFileOnSignal(sys::Path(BitcodeOutputFilename)); + + // Arrange for the output file to be deleted on any errors. + if (!LinkAsLibrary) { + OutputRemover.setFile(OutputFilename); + sys::RemoveFileOnSignal(sys::Path(OutputFilename)); + } + + // Construct a Linker (now that Verbose is set) + Linker TheLinker(progname, OutputFilename, Context, Verbose); + + // Keep track of the native link items (versus the bitcode items) + Linker::ItemList NativeLinkItems; + + // Add library paths to the linker + TheLinker.addPaths(LibPaths); + TheLinker.addSystemPaths(); + + // Remove any consecutive duplicates of the same library... + Libraries.erase(std::unique(Libraries.begin(), Libraries.end()), + Libraries.end()); + + if (LinkAsLibrary) { + std::vector Files; + for (unsigned i = 0; i < InputFilenames.size(); ++i ) + Files.push_back(sys::Path(InputFilenames[i])); + if (TheLinker.LinkInFiles(Files)) + return 1; // Error already printed + + // The libraries aren't linked in but are noted as "dependent" in the + // module. + for (cl::list::const_iterator I = Libraries.begin(), + E = Libraries.end(); I != E ; ++I) { + TheLinker.getModule()->addLibrary(*I); + } + } else { + // Build a list of the items from our command line + Linker::ItemList Items; + BuildLinkItems(Items, InputFilenames, Libraries); + + // Link all the items together + if (TheLinker.LinkInItems(Items, NativeLinkItems) ) + return 1; // Error already printed + } + + std::auto_ptr Composite(TheLinker.releaseModule()); + + // Optimize the module + Optimize(Composite.get()); + + // Generate the bitcode output. + GenerateBitcode(Composite.get(), BitcodeOutputFilename); + + // If we are not linking a library, generate either a native executable + // or a JIT shell script, depending upon what the user wants. + if (!LinkAsLibrary) { + // If the user wants to run a post-link optimization, run it now. + if (!PostLinkOpts.empty()) { + std::vector opts = PostLinkOpts; + for (std::vector::iterator I = opts.begin(), + E = opts.end(); I != E; ++I) { + sys::Path prog(*I); + if (!prog.canExecute()) { + prog = sys::Program::FindProgramByName(*I); + if (prog.isEmpty()) + PrintAndExit(std::string("Optimization program '") + *I + + "' is not found or not executable.", Composite.get()); + } + // Get the program arguments + sys::Path tmp_output("opt_result"); + std::string ErrMsg; + if (tmp_output.createTemporaryFileOnDisk(true, &ErrMsg)) + PrintAndExit(ErrMsg, Composite.get()); + + const char* args[4]; + args[0] = I->c_str(); + args[1] = BitcodeOutputFilename.c_str(); + args[2] = tmp_output.c_str(); + args[3] = 0; + if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0,0, &ErrMsg)) { + if (tmp_output.isBitcodeFile()) { + sys::Path target(BitcodeOutputFilename); + target.eraseFromDisk(); + if (tmp_output.renamePathOnDisk(target, &ErrMsg)) + PrintAndExit(ErrMsg, Composite.get(), 2); + } else + PrintAndExit("Post-link optimization output is not bitcode", + Composite.get()); + } else { + PrintAndExit(ErrMsg, Composite.get()); + } + } + } + + // If the user wants to generate a native executable, compile it from the + // bitcode file. + // + // Otherwise, create a script that will run the bitcode through the JIT. + if (Native) { + // Name of the Assembly Language output file + sys::Path AssemblyFile ( OutputFilename); + AssemblyFile.appendSuffix("s"); + + // Mark the output files for removal. + FileRemover AssemblyFileRemover(AssemblyFile.str()); + sys::RemoveFileOnSignal(AssemblyFile); + + // Determine the locations of the llc and gcc programs. + sys::Path llc = PrependMainExecutablePath("llc", argv[0], + (void *)(intptr_t)&Optimize); + if (llc.isEmpty()) + PrintAndExit("Failed to find llc", Composite.get()); + + sys::Path gcc = sys::Program::FindProgramByName("gcc"); + if (gcc.isEmpty()) + PrintAndExit("Failed to find gcc", Composite.get()); + + // Generate an assembly language file for the bitcode. + std::string ErrMsg; + if (0 != GenerateAssembly(AssemblyFile.str(), BitcodeOutputFilename, + llc, ErrMsg)) + PrintAndExit(ErrMsg, Composite.get()); + + if (0 != GenerateNative(OutputFilename, AssemblyFile.str(), + NativeLinkItems, gcc, envp, ErrMsg)) + PrintAndExit(ErrMsg, Composite.get()); + } else if (NativeCBE) { + sys::Path CFile (OutputFilename); + CFile.appendSuffix("cbe.c"); + + // Mark the output files for removal. + FileRemover CFileRemover(CFile.str()); + sys::RemoveFileOnSignal(CFile); + + // Determine the locations of the llc and gcc programs. + sys::Path llc = PrependMainExecutablePath("llc", argv[0], + (void *)(intptr_t)&Optimize); + if (llc.isEmpty()) + PrintAndExit("Failed to find llc", Composite.get()); + + sys::Path gcc = sys::Program::FindProgramByName("gcc"); + if (gcc.isEmpty()) + PrintAndExit("Failed to find gcc", Composite.get()); + + // Generate an assembly language file for the bitcode. + std::string ErrMsg; + if (GenerateCFile(CFile.str(), BitcodeOutputFilename, llc, ErrMsg)) + PrintAndExit(ErrMsg, Composite.get()); + + if (GenerateNative(OutputFilename, CFile.str(), + NativeLinkItems, gcc, envp, ErrMsg)) + PrintAndExit(ErrMsg, Composite.get()); + } else { + EmitShellScript(argv, Composite.get()); + } + + // Make the script executable... + std::string ErrMsg; + if (sys::Path(OutputFilename).makeExecutableOnDisk(&ErrMsg)) + PrintAndExit(ErrMsg, Composite.get()); + + // Make the bitcode file readable and directly executable in LLEE as well + if (sys::Path(BitcodeOutputFilename).makeExecutableOnDisk(&ErrMsg)) + PrintAndExit(ErrMsg, Composite.get()); + + if (sys::Path(BitcodeOutputFilename).makeReadableOnDisk(&ErrMsg)) + PrintAndExit(ErrMsg, Composite.get()); + } + + // Operations which may fail are now complete. + BitcodeOutputRemover.releaseFile(); + if (!LinkAsLibrary) + OutputRemover.releaseFile(); + + // Graceful exit + return 0; +} diff --git a/contrib/llvm/tools/llvm-link/CMakeLists.txt b/contrib/llvm/tools/llvm-link/CMakeLists.txt new file mode 100644 index 000000000000..11933f7f959e --- /dev/null +++ b/contrib/llvm/tools/llvm-link/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS linker bitreader bitwriter asmparser) + +add_llvm_tool(llvm-link + llvm-link.cpp + ) diff --git a/contrib/llvm/tools/llvm-link/Makefile b/contrib/llvm/tools/llvm-link/Makefile new file mode 100644 index 000000000000..26370187c55f --- /dev/null +++ b/contrib/llvm/tools/llvm-link/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-link/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. + +TOOLNAME = llvm-link +LINK_COMPONENTS = linker bitreader bitwriter asmparser + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-link/llvm-link.cpp b/contrib/llvm/tools/llvm-link/llvm-link.cpp new file mode 100644 index 000000000000..95ad1ca5a17e --- /dev/null +++ b/contrib/llvm/tools/llvm-link/llvm-link.cpp @@ -0,0 +1,142 @@ +//===- llvm-link.cpp - Low-level LLVM linker ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This utility may be invoked in the following manner: +// llvm-link a.bc b.bc c.bc -o x.bc +// +//===----------------------------------------------------------------------===// + +#include "llvm/Linker.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/IRReader.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Path.h" +#include +using namespace llvm; + +static cl::list +InputFilenames(cl::Positional, cl::OneOrMore, + cl::desc("")); + +static cl::opt +OutputFilename("o", cl::desc("Override output filename"), cl::init("-"), + cl::value_desc("filename")); + +static cl::opt +Force("f", cl::desc("Enable binary output on terminals")); + +static cl::opt +OutputAssembly("S", + cl::desc("Write output as LLVM assembly"), cl::Hidden); + +static cl::opt +Verbose("v", cl::desc("Print information about actions taken")); + +static cl::opt +DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden); + +// LoadFile - Read the specified bitcode file in and return it. This routine +// searches the link path for the specified file to try to find it... +// +static inline std::auto_ptr LoadFile(const char *argv0, + const std::string &FN, + LLVMContext& Context) { + sys::Path Filename; + if (!Filename.set(FN)) { + errs() << "Invalid file name: '" << FN << "'\n"; + return std::auto_ptr(); + } + + SMDiagnostic Err; + if (Verbose) errs() << "Loading '" << Filename.c_str() << "'\n"; + Module* Result = 0; + + const std::string &FNStr = Filename.str(); + Result = ParseIRFile(FNStr, Err, Context); + if (Result) return std::auto_ptr(Result); // Load successful! + + Err.Print(argv0, errs()); + return std::auto_ptr(); +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); + + unsigned BaseArg = 0; + std::string ErrorMessage; + + std::auto_ptr Composite(LoadFile(argv[0], + InputFilenames[BaseArg], Context)); + if (Composite.get() == 0) { + errs() << argv[0] << ": error loading file '" + << InputFilenames[BaseArg] << "'\n"; + return 1; + } + + for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) { + std::auto_ptr M(LoadFile(argv[0], + InputFilenames[i], Context)); + if (M.get() == 0) { + errs() << argv[0] << ": error loading file '" < > ByteArrayTy; + +namespace { +class VectorMemoryObject : public MemoryObject { +private: + const ByteArrayTy &Bytes; +public: + VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {} + + uint64_t getBase() const { return 0; } + uint64_t getExtent() const { return Bytes.size(); } + + int readByte(uint64_t Addr, uint8_t *Byte) const { + if (Addr >= getExtent()) + return -1; + *Byte = Bytes[Addr].first; + return 0; + } +}; +} + +static bool PrintInsts(const MCDisassembler &DisAsm, + MCInstPrinter &Printer, const ByteArrayTy &Bytes, + SourceMgr &SM, raw_ostream &Out) { + // Wrap the vector in a MemoryObject. + VectorMemoryObject memoryObject(Bytes); + + // Disassemble it to strings. + uint64_t Size; + uint64_t Index; + + for (Index = 0; Index < Bytes.size(); Index += Size) { + MCInst Inst; + + MCDisassembler::DecodeStatus S; + S = DisAsm.getInstruction(Inst, Size, memoryObject, Index, + /*REMOVE*/ nulls(), nulls()); + switch (S) { + case MCDisassembler::Fail: + SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), + "invalid instruction encoding", "warning"); + if (Size == 0) + Size = 1; // skip illegible bytes + break; + + case MCDisassembler::SoftFail: + SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), + "potentially undefined instruction encoding", "warning"); + // Fall through + + case MCDisassembler::Success: + Printer.printInst(&Inst, Out, ""); + Out << "\n"; + break; + } + } + + return false; +} + +static bool ByteArrayFromString(ByteArrayTy &ByteArray, + StringRef &Str, + SourceMgr &SM) { + while (!Str.empty()) { + // Strip horizontal whitespace. + if (size_t Pos = Str.find_first_not_of(" \t\r")) { + Str = Str.substr(Pos); + continue; + } + + // If this is the end of a line or start of a comment, remove the rest of + // the line. + if (Str[0] == '\n' || Str[0] == '#') { + // Strip to the end of line if we already processed any bytes on this + // line. This strips the comment and/or the \n. + if (Str[0] == '\n') { + Str = Str.substr(1); + } else { + Str = Str.substr(Str.find_first_of('\n')); + if (!Str.empty()) + Str = Str.substr(1); + } + continue; + } + + // Get the current token. + size_t Next = Str.find_first_of(" \t\n\r#"); + StringRef Value = Str.substr(0, Next); + + // Convert to a byte and add to the byte vector. + unsigned ByteVal; + if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) { + // If we have an error, print it and skip to the end of line. + SM.PrintMessage(SMLoc::getFromPointer(Value.data()), + "invalid input token", "error"); + Str = Str.substr(Str.find('\n')); + ByteArray.clear(); + continue; + } + + ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data())); + Str = Str.substr(Next); + } + + return false; +} + +int Disassembler::disassemble(const Target &T, + const std::string &Triple, + const std::string &Cpu, + const std::string &FeaturesStr, + MemoryBuffer &Buffer, + raw_ostream &Out) { + // Set up disassembler. + OwningPtr AsmInfo(T.createMCAsmInfo(Triple)); + + if (!AsmInfo) { + errs() << "error: no assembly info for target " << Triple << "\n"; + return -1; + } + + OwningPtr STI(T.createMCSubtargetInfo(Triple, Cpu, FeaturesStr)); + if (!STI) { + errs() << "error: no subtarget info for target " << Triple << "\n"; + return -1; + } + + OwningPtr DisAsm(T.createMCDisassembler(*STI)); + if (!DisAsm) { + errs() << "error: no disassembler for target " << Triple << "\n"; + return -1; + } + + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + OwningPtr IP(T.createMCInstPrinter(AsmPrinterVariant, + *AsmInfo, *STI)); + if (!IP) { + errs() << "error: no instruction printer for target " << Triple << '\n'; + return -1; + } + + bool ErrorOccurred = false; + + SourceMgr SM; + SM.AddNewSourceBuffer(&Buffer, SMLoc()); + + // Convert the input to a vector for disassembly. + ByteArrayTy ByteArray; + StringRef Str = Buffer.getBuffer(); + + ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); + + if (!ByteArray.empty()) + ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM, Out); + + return ErrorOccurred; +} + +static int byteArrayReader(uint8_t *B, uint64_t A, void *Arg) { + ByteArrayTy &ByteArray = *((ByteArrayTy*)Arg); + + if (A >= ByteArray.size()) + return -1; + + *B = ByteArray[A].first; + + return 0; +} + +static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) { + EDDisassembler &disassembler = *(EDDisassembler *)((void **)Arg)[0]; + raw_ostream &Out = *(raw_ostream *)((void **)Arg)[1]; + + if (const char *regName = disassembler.nameWithRegisterID(R)) + Out << "[" << regName << "/" << R << "]"; + + if (disassembler.registerIsStackPointer(R)) + Out << "(sp)"; + if (disassembler.registerIsProgramCounter(R)) + Out << "(pc)"; + + *V = 0; + return 0; +} + +int Disassembler::disassembleEnhanced(const std::string &TS, + MemoryBuffer &Buffer, + raw_ostream &Out) { + ByteArrayTy ByteArray; + StringRef Str = Buffer.getBuffer(); + SourceMgr SM; + + SM.AddNewSourceBuffer(&Buffer, SMLoc()); + + if (ByteArrayFromString(ByteArray, Str, SM)) { + return -1; + } + + Triple T(TS); + EDDisassembler::AssemblySyntax AS; + + switch (T.getArch()) { + default: + errs() << "error: no default assembly syntax for " << TS.c_str() << "\n"; + return -1; + case Triple::arm: + case Triple::thumb: + AS = EDDisassembler::kEDAssemblySyntaxARMUAL; + break; + case Triple::x86: + case Triple::x86_64: + AS = EDDisassembler::kEDAssemblySyntaxX86ATT; + break; + } + + EDDisassembler::initialize(); + OwningPtr + disassembler(EDDisassembler::getDisassembler(TS.c_str(), AS)); + + if (disassembler == 0) { + errs() << "error: couldn't get disassembler for " << TS << '\n'; + return -1; + } + + while (ByteArray.size()) { + OwningPtr + inst(disassembler->createInst(byteArrayReader, 0, &ByteArray)); + + if (inst == 0) { + errs() << "error: Didn't get an instruction\n"; + return -1; + } + + ByteArray.erase (ByteArray.begin(), ByteArray.begin() + inst->byteSize()); + + unsigned numTokens = inst->numTokens(); + if ((int)numTokens < 0) { + errs() << "error: couldn't count the instruction's tokens\n"; + return -1; + } + + for (unsigned tokenIndex = 0; tokenIndex != numTokens; ++tokenIndex) { + EDToken *token; + + if (inst->getToken(token, tokenIndex)) { + errs() << "error: Couldn't get token\n"; + return -1; + } + + const char *buf; + if (token->getString(buf)) { + errs() << "error: Couldn't get string for token\n"; + return -1; + } + + Out << '['; + int operandIndex = token->operandID(); + + if (operandIndex >= 0) + Out << operandIndex << "-"; + + switch (token->type()) { + default: Out << "?"; break; + case EDToken::kTokenWhitespace: Out << "w"; break; + case EDToken::kTokenPunctuation: Out << "p"; break; + case EDToken::kTokenOpcode: Out << "o"; break; + case EDToken::kTokenLiteral: Out << "l"; break; + case EDToken::kTokenRegister: Out << "r"; break; + } + + Out << ":" << buf; + + if (token->type() == EDToken::kTokenLiteral) { + Out << "="; + if (token->literalSign()) + Out << "-"; + uint64_t absoluteValue; + if (token->literalAbsoluteValue(absoluteValue)) { + errs() << "error: Couldn't get the value of a literal token\n"; + return -1; + } + Out << absoluteValue; + } else if (token->type() == EDToken::kTokenRegister) { + Out << "="; + unsigned regID; + if (token->registerID(regID)) { + errs() << "error: Couldn't get the ID of a register token\n"; + return -1; + } + Out << "r" << regID; + } + + Out << "]"; + } + + Out << " "; + + if (inst->isBranch()) + Out << "
"; + if (inst->isMove()) + Out << " "; + + unsigned numOperands = inst->numOperands(); + + if ((int)numOperands < 0) { + errs() << "error: Couldn't count operands\n"; + return -1; + } + + for (unsigned operandIndex = 0; operandIndex != numOperands; + ++operandIndex) { + Out << operandIndex << ":"; + + EDOperand *operand; + if (inst->getOperand(operand, operandIndex)) { + errs() << "error: couldn't get operand\n"; + return -1; + } + + uint64_t evaluatedResult; + void *Arg[] = { disassembler.get(), &Out }; + if (operand->evaluate(evaluatedResult, verboseEvaluator, Arg)) { + errs() << "error: Couldn't evaluate an operand\n"; + return -1; + } + Out << "=" << evaluatedResult << " "; + } + + Out << '\n'; + } + + return 0; +} + diff --git a/contrib/llvm/tools/llvm-mc/Disassembler.h b/contrib/llvm/tools/llvm-mc/Disassembler.h new file mode 100644 index 000000000000..e8cd92db030a --- /dev/null +++ b/contrib/llvm/tools/llvm-mc/Disassembler.h @@ -0,0 +1,42 @@ +//===- Disassembler.h - Text File Disassembler ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the disassembler of strings of bytes written in +// hexadecimal, from standard input or from a file. +// +//===----------------------------------------------------------------------===// + +#ifndef DISASSEMBLER_H +#define DISASSEMBLER_H + +#include + +namespace llvm { + +class MemoryBuffer; +class Target; +class raw_ostream; + +class Disassembler { +public: + static int disassemble(const Target &target, + const std::string &tripleString, + const std::string &Cpu, + const std::string &FeaturesStr, + MemoryBuffer &buffer, + raw_ostream &Out); + + static int disassembleEnhanced(const std::string &tripleString, + MemoryBuffer &buffer, + raw_ostream &Out); +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/tools/llvm-mc/Makefile b/contrib/llvm/tools/llvm-mc/Makefile new file mode 100644 index 000000000000..934a6e4dd081 --- /dev/null +++ b/contrib/llvm/tools/llvm-mc/Makefile @@ -0,0 +1,24 @@ +##===- tools/llvm-mc/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = llvm-mc + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +# Include this here so we can get the configuration of the targets +# that have been configured for construction. We have to do this +# early so we can set up LINK_COMPONENTS before including Makefile.rules +include $(LEVEL)/Makefile.config + +LINK_COMPONENTS := $(TARGETS_TO_BUILD) MCDisassembler MCParser MC support + +include $(LLVM_SRC_ROOT)/Makefile.rules + diff --git a/contrib/llvm/tools/llvm-mc/llvm-mc.cpp b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp new file mode 100644 index 000000000000..5fb3fdf5b5f1 --- /dev/null +++ b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp @@ -0,0 +1,517 @@ +//===-- llvm-mc.cpp - Machine Code Hacking Driver -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This utility is a simple driver that allows command line hacking on machine +// code. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/system_error.h" +#include "Disassembler.h" +using namespace llvm; + +static cl::opt +InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +OutputFilename("o", cl::desc("Output filename"), + cl::value_desc("filename")); + +static cl::opt +ShowEncoding("show-encoding", cl::desc("Show instruction encodings")); + +static cl::opt +ShowInst("show-inst", cl::desc("Show internal instruction representation")); + +static cl::opt +ShowInstOperands("show-inst-operands", + cl::desc("Show instructions operands as parsed")); + +static cl::opt +OutputAsmVariant("output-asm-variant", + cl::desc("Syntax variant to use for output printing")); + +static cl::opt +RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); + +static cl::opt +NoExecStack("mc-no-exec-stack", cl::desc("File doesn't need an exec stack")); + +static cl::opt +EnableLogging("enable-api-logging", cl::desc("Enable MC API logging")); + +enum OutputFileType { + OFT_Null, + OFT_AssemblyFile, + OFT_ObjectFile +}; +static cl::opt +FileType("filetype", cl::init(OFT_AssemblyFile), + cl::desc("Choose an output file type:"), + cl::values( + clEnumValN(OFT_AssemblyFile, "asm", + "Emit an assembly ('.s') file"), + clEnumValN(OFT_Null, "null", + "Don't emit anything (for timing purposes)"), + clEnumValN(OFT_ObjectFile, "obj", + "Emit a native object ('.o') file"), + clEnumValEnd)); + +static cl::list +IncludeDirs("I", cl::desc("Directory of include files"), + cl::value_desc("directory"), cl::Prefix); + +static cl::opt +ArchName("arch", cl::desc("Target arch to assemble for, " + "see -version for available targets")); + +static cl::opt +TripleName("triple", cl::desc("Target triple to assemble for, " + "see -version for available targets")); + +static cl::opt +MCPU("mcpu", + cl::desc("Target a specific cpu type (-mcpu=help for details)"), + cl::value_desc("cpu-name"), + cl::init("")); + +static cl::list +MAttrs("mattr", + cl::CommaSeparated, + cl::desc("Target specific attributes (-mattr=help for details)"), + cl::value_desc("a1,+a2,-a3,...")); + +static cl::opt +RelocModel("relocation-model", + cl::desc("Choose relocation model"), + cl::init(Reloc::Default), + cl::values( + clEnumValN(Reloc::Default, "default", + "Target default relocation model"), + clEnumValN(Reloc::Static, "static", + "Non-relocatable code"), + clEnumValN(Reloc::PIC_, "pic", + "Fully relocatable, position independent code"), + clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic", + "Relocatable external references, non-relocatable code"), + clEnumValEnd)); + +static cl::opt +CMModel("code-model", + cl::desc("Choose code model"), + cl::init(CodeModel::Default), + cl::values(clEnumValN(CodeModel::Default, "default", + "Target default code model"), + clEnumValN(CodeModel::Small, "small", + "Small code model"), + clEnumValN(CodeModel::Kernel, "kernel", + "Kernel code model"), + clEnumValN(CodeModel::Medium, "medium", + "Medium code model"), + clEnumValN(CodeModel::Large, "large", + "Large code model"), + clEnumValEnd)); + +static cl::opt +NoInitialTextSection("n", cl::desc("Don't assume assembly file starts " + "in the text section")); + +static cl::opt +SaveTempLabels("L", cl::desc("Don't discard temporary labels")); + +enum ActionType { + AC_AsLex, + AC_Assemble, + AC_Disassemble, + AC_EDisassemble +}; + +static cl::opt +Action(cl::desc("Action to perform:"), + cl::init(AC_Assemble), + cl::values(clEnumValN(AC_AsLex, "as-lex", + "Lex tokens from a .s file"), + clEnumValN(AC_Assemble, "assemble", + "Assemble a .s file (default)"), + clEnumValN(AC_Disassemble, "disassemble", + "Disassemble strings of hex bytes"), + clEnumValN(AC_EDisassemble, "edis", + "Enhanced disassembly of strings of hex bytes"), + clEnumValEnd)); + +static const Target *GetTarget(const char *ProgName) { + // Figure out the target triple. + if (TripleName.empty()) + TripleName = sys::getHostTriple(); + Triple TheTriple(Triple::normalize(TripleName)); + + const Target *TheTarget = 0; + if (!ArchName.empty()) { + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + if (ArchName == it->getName()) { + TheTarget = &*it; + break; + } + } + + if (!TheTarget) { + errs() << ProgName << ": error: invalid target '" << ArchName << "'.\n"; + return 0; + } + + // Adjust the triple to match (if known), otherwise stick with the + // module/host triple. + Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); + if (Type != Triple::UnknownArch) + TheTriple.setArch(Type); + } else { + // Get the target specific parser. + std::string Error; + TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error); + if (TheTarget == 0) { + errs() << ProgName << ": error: unable to get target for '" + << TheTriple.getTriple() + << "', see --version and --triple.\n"; + return 0; + } + } + + TripleName = TheTriple.getTriple(); + return TheTarget; +} + +static tool_output_file *GetOutputStream() { + if (OutputFilename == "") + OutputFilename = "-"; + + std::string Err; + tool_output_file *Out = new tool_output_file(OutputFilename.c_str(), Err, + raw_fd_ostream::F_Binary); + if (!Err.empty()) { + errs() << Err << '\n'; + delete Out; + return 0; + } + + return Out; +} + +static int AsLexInput(const char *ProgName) { + OwningPtr BufferPtr; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { + errs() << ProgName << ": " << ec.message() << '\n'; + return 1; + } + MemoryBuffer *Buffer = BufferPtr.take(); + + SourceMgr SrcMgr; + + // Tell SrcMgr about this buffer, which is what TGParser will pick up. + SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); + + // Record the location of the include directories so that the lexer can find + // it later. + SrcMgr.setIncludeDirs(IncludeDirs); + + const Target *TheTarget = GetTarget(ProgName); + if (!TheTarget) + return 1; + + llvm::OwningPtr MAI(TheTarget->createMCAsmInfo(TripleName)); + assert(MAI && "Unable to create target asm info!"); + + AsmLexer Lexer(*MAI); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); + + OwningPtr Out(GetOutputStream()); + if (!Out) + return 1; + + bool Error = false; + while (Lexer.Lex().isNot(AsmToken::Eof)) { + AsmToken Tok = Lexer.getTok(); + + switch (Tok.getKind()) { + default: + SrcMgr.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); + Error = true; + break; + case AsmToken::Error: + Error = true; // error already printed. + break; + case AsmToken::Identifier: + Out->os() << "identifier: " << Lexer.getTok().getString(); + break; + case AsmToken::Integer: + Out->os() << "int: " << Lexer.getTok().getString(); + break; + case AsmToken::Real: + Out->os() << "real: " << Lexer.getTok().getString(); + break; + case AsmToken::Register: + Out->os() << "register: " << Lexer.getTok().getRegVal(); + break; + case AsmToken::String: + Out->os() << "string: " << Lexer.getTok().getString(); + break; + + case AsmToken::Amp: Out->os() << "Amp"; break; + case AsmToken::AmpAmp: Out->os() << "AmpAmp"; break; + case AsmToken::At: Out->os() << "At"; break; + case AsmToken::Caret: Out->os() << "Caret"; break; + case AsmToken::Colon: Out->os() << "Colon"; break; + case AsmToken::Comma: Out->os() << "Comma"; break; + case AsmToken::Dollar: Out->os() << "Dollar"; break; + case AsmToken::Dot: Out->os() << "Dot"; break; + case AsmToken::EndOfStatement: Out->os() << "EndOfStatement"; break; + case AsmToken::Eof: Out->os() << "Eof"; break; + case AsmToken::Equal: Out->os() << "Equal"; break; + case AsmToken::EqualEqual: Out->os() << "EqualEqual"; break; + case AsmToken::Exclaim: Out->os() << "Exclaim"; break; + case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual"; break; + case AsmToken::Greater: Out->os() << "Greater"; break; + case AsmToken::GreaterEqual: Out->os() << "GreaterEqual"; break; + case AsmToken::GreaterGreater: Out->os() << "GreaterGreater"; break; + case AsmToken::Hash: Out->os() << "Hash"; break; + case AsmToken::LBrac: Out->os() << "LBrac"; break; + case AsmToken::LCurly: Out->os() << "LCurly"; break; + case AsmToken::LParen: Out->os() << "LParen"; break; + case AsmToken::Less: Out->os() << "Less"; break; + case AsmToken::LessEqual: Out->os() << "LessEqual"; break; + case AsmToken::LessGreater: Out->os() << "LessGreater"; break; + case AsmToken::LessLess: Out->os() << "LessLess"; break; + case AsmToken::Minus: Out->os() << "Minus"; break; + case AsmToken::Percent: Out->os() << "Percent"; break; + case AsmToken::Pipe: Out->os() << "Pipe"; break; + case AsmToken::PipePipe: Out->os() << "PipePipe"; break; + case AsmToken::Plus: Out->os() << "Plus"; break; + case AsmToken::RBrac: Out->os() << "RBrac"; break; + case AsmToken::RCurly: Out->os() << "RCurly"; break; + case AsmToken::RParen: Out->os() << "RParen"; break; + case AsmToken::Slash: Out->os() << "Slash"; break; + case AsmToken::Star: Out->os() << "Star"; break; + case AsmToken::Tilde: Out->os() << "Tilde"; break; + } + + // Print the token string. + Out->os() << " (\""; + Out->os().write_escaped(Tok.getString()); + Out->os() << "\")\n"; + } + + // Keep output if no errors. + if (Error == 0) Out->keep(); + + return Error; +} + +static int AssembleInput(const char *ProgName) { + const Target *TheTarget = GetTarget(ProgName); + if (!TheTarget) + return 1; + + OwningPtr BufferPtr; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { + errs() << ProgName << ": " << ec.message() << '\n'; + return 1; + } + MemoryBuffer *Buffer = BufferPtr.take(); + + SourceMgr SrcMgr; + + // Tell SrcMgr about this buffer, which is what the parser will pick up. + SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); + + // Record the location of the include directories so that the lexer can find + // it later. + SrcMgr.setIncludeDirs(IncludeDirs); + + + llvm::OwningPtr MAI(TheTarget->createMCAsmInfo(TripleName)); + assert(MAI && "Unable to create target asm info!"); + + llvm::OwningPtr MRI(TheTarget->createMCRegInfo(TripleName)); + assert(MRI && "Unable to create target register info!"); + + // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and + // MCObjectFileInfo needs a MCContext reference in order to initialize itself. + OwningPtr MOFI(new MCObjectFileInfo()); + MCContext Ctx(*MAI, *MRI, MOFI.get()); + MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx); + + if (SaveTempLabels) + Ctx.setAllowTemporaryLabels(false); + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (MAttrs.size()) { + SubtargetFeatures Features; + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + OwningPtr Out(GetOutputStream()); + if (!Out) + return 1; + + formatted_raw_ostream FOS(Out->os()); + OwningPtr Str; + + OwningPtr MCII(TheTarget->createMCInstrInfo()); + OwningPtr + STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); + + // FIXME: There is a bit of code duplication with addPassesToEmitFile. + if (FileType == OFT_AssemblyFile) { + MCInstPrinter *IP = + TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *STI); + MCCodeEmitter *CE = 0; + MCAsmBackend *MAB = 0; + if (ShowEncoding) { + CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx); + MAB = TheTarget->createMCAsmBackend(TripleName); + } + Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/true, + /*useLoc*/ true, + /*useCFI*/ true, IP, CE, MAB, + ShowInst)); + } else if (FileType == OFT_Null) { + Str.reset(createNullStreamer(Ctx)); + } else { + assert(FileType == OFT_ObjectFile && "Invalid file type!"); + MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *STI, Ctx); + MCAsmBackend *MAB = TheTarget->createMCAsmBackend(TripleName); + Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB, + FOS, CE, RelaxAll, + NoExecStack)); + } + + if (EnableLogging) { + Str.reset(createLoggingStreamer(Str.take(), errs())); + } + + OwningPtr Parser(createMCAsmParser(SrcMgr, Ctx, + *Str.get(), *MAI)); + OwningPtr TAP(TheTarget->createMCAsmParser(*STI, *Parser)); + if (!TAP) { + errs() << ProgName + << ": error: this target does not support assembly parsing.\n"; + return 1; + } + + Parser->setShowParsedOperands(ShowInstOperands); + Parser->setTargetParser(*TAP.get()); + + int Res = Parser->Run(NoInitialTextSection); + + // Keep output if no errors. + if (Res == 0) Out->keep(); + + return Res; +} + +static int DisassembleInput(const char *ProgName, bool Enhanced) { + const Target *TheTarget = GetTarget(ProgName); + if (!TheTarget) + return 0; + + OwningPtr Buffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, Buffer)) { + errs() << ProgName << ": " << ec.message() << '\n'; + return 1; + } + + OwningPtr Out(GetOutputStream()); + if (!Out) + return 1; + + int Res; + if (Enhanced) { + Res = + Disassembler::disassembleEnhanced(TripleName, *Buffer.take(), Out->os()); + } else { + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (MAttrs.size()) { + SubtargetFeatures Features; + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + Res = Disassembler::disassemble(*TheTarget, TripleName, MCPU, FeaturesStr, + *Buffer.take(), Out->os()); + } + + // Keep output if no errors. + if (Res == 0) Out->keep(); + + return Res; +} + + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmParsers(); + llvm::InitializeAllDisassemblers(); + + cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); + TripleName = Triple::normalize(TripleName); + + switch (Action) { + default: + case AC_AsLex: + return AsLexInput(argv[0]); + case AC_Assemble: + return AssembleInput(argv[0]); + case AC_Disassemble: + return DisassembleInput(argv[0], false); + case AC_EDisassemble: + return DisassembleInput(argv[0], true); + } + + return 0; +} + diff --git a/contrib/llvm/tools/llvm-nm/CMakeLists.txt b/contrib/llvm/tools/llvm-nm/CMakeLists.txt new file mode 100644 index 000000000000..b6cd80b477a9 --- /dev/null +++ b/contrib/llvm/tools/llvm-nm/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS archive bitreader object) + +add_llvm_tool(llvm-nm + llvm-nm.cpp + ) diff --git a/contrib/llvm/tools/llvm-nm/Makefile b/contrib/llvm/tools/llvm-nm/Makefile new file mode 100644 index 000000000000..6bb4cd4acc23 --- /dev/null +++ b/contrib/llvm/tools/llvm-nm/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-nm/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. + +TOOLNAME = llvm-nm +LINK_COMPONENTS = archive bitreader object + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp new file mode 100644 index 000000000000..e79d72d1933c --- /dev/null +++ b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp @@ -0,0 +1,392 @@ +//===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program is a utility that works like traditional Unix "nm", +// that is, it prints out the names of symbols in a bitcode file, +// along with some information about each symbol. +// +// This "nm" does not print symbols' addresses. It supports many of +// the features of GNU "nm", including its different output formats. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Bitcode/Archive.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/system_error.h" +#include +#include +#include +#include +#include +using namespace llvm; +using namespace object; + +namespace { + enum OutputFormatTy { bsd, sysv, posix }; + cl::opt + OutputFormat("format", + cl::desc("Specify output format"), + cl::values(clEnumVal(bsd, "BSD format"), + clEnumVal(sysv, "System V format"), + clEnumVal(posix, "POSIX.2 format"), + clEnumValEnd), cl::init(bsd)); + cl::alias OutputFormat2("f", cl::desc("Alias for --format"), + cl::aliasopt(OutputFormat)); + + cl::list + InputFilenames(cl::Positional, cl::desc(""), + cl::ZeroOrMore); + + cl::opt UndefinedOnly("undefined-only", + cl::desc("Show only undefined symbols")); + cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), + cl::aliasopt(UndefinedOnly)); + + cl::opt DefinedOnly("defined-only", + cl::desc("Show only defined symbols")); + + cl::opt ExternalOnly("extern-only", + cl::desc("Show only external symbols")); + cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), + cl::aliasopt(ExternalOnly)); + + cl::opt BSDFormat("B", cl::desc("Alias for --format=bsd")); + cl::opt POSIXFormat("P", cl::desc("Alias for --format=posix")); + + cl::opt PrintFileName("print-file-name", + cl::desc("Precede each symbol with the object file it came from")); + + cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"), + cl::aliasopt(PrintFileName)); + cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"), + cl::aliasopt(PrintFileName)); + + cl::opt DebugSyms("debug-syms", + cl::desc("Show all symbols, even debugger only")); + cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"), + cl::aliasopt(DebugSyms)); + + cl::opt NumericSort("numeric-sort", + cl::desc("Sort symbols by address")); + cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"), + cl::aliasopt(NumericSort)); + cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"), + cl::aliasopt(NumericSort)); + + cl::opt NoSort("no-sort", + cl::desc("Show symbols in order encountered")); + cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), + cl::aliasopt(NoSort)); + + cl::opt PrintSize("print-size", + cl::desc("Show symbol size instead of address")); + cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"), + cl::aliasopt(PrintSize)); + + cl::opt SizeSort("size-sort", cl::desc("Sort symbols by size")); + + bool PrintAddress = true; + + bool MultipleFiles = false; + + std::string ToolName; +} + +namespace { + struct NMSymbol { + uint64_t Address; + uint64_t Size; + char TypeChar; + StringRef Name; + }; + + static bool CompareSymbolAddress(const NMSymbol &a, const NMSymbol &b) { + if (a.Address < b.Address) + return true; + else if (a.Address == b.Address && a.Name < b.Name) + return true; + else + return false; + + } + + static bool CompareSymbolSize(const NMSymbol &a, const NMSymbol &b) { + if (a.Size < b.Size) + return true; + else if (a.Size == b.Size && a.Name < b.Name) + return true; + else + return false; + } + + static bool CompareSymbolName(const NMSymbol &a, const NMSymbol &b) { + return a.Name < b.Name; + } + + StringRef CurrentFilename; + typedef std::vector SymbolListT; + SymbolListT SymbolList; + + bool error(error_code ec) { + if (!ec) return false; + + outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; + outs().flush(); + return true; + } +} + +static void SortAndPrintSymbolList() { + if (!NoSort) { + if (NumericSort) + std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolAddress); + else if (SizeSort) + std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolSize); + else + std::sort(SymbolList.begin(), SymbolList.end(), CompareSymbolName); + } + + if (OutputFormat == posix && MultipleFiles) { + outs() << '\n' << CurrentFilename << ":\n"; + } else if (OutputFormat == bsd && MultipleFiles) { + outs() << "\n" << CurrentFilename << ":\n"; + } else if (OutputFormat == sysv) { + outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n" + << "Name Value Class Type" + << " Size Line Section\n"; + } + + for (SymbolListT::iterator i = SymbolList.begin(), + e = SymbolList.end(); i != e; ++i) { + if ((i->TypeChar != 'U') && UndefinedOnly) + continue; + if ((i->TypeChar == 'U') && DefinedOnly) + continue; + if (SizeSort && !PrintAddress && i->Size == UnknownAddressOrSize) + continue; + + char SymbolAddrStr[10] = ""; + char SymbolSizeStr[10] = ""; + + if (OutputFormat == sysv || i->Address == object::UnknownAddressOrSize) + strcpy(SymbolAddrStr, " "); + if (OutputFormat == sysv) + strcpy(SymbolSizeStr, " "); + + if (i->Address != object::UnknownAddressOrSize) + format("%08"PRIx64, i->Address).print(SymbolAddrStr, sizeof(SymbolAddrStr)); + if (i->Size != object::UnknownAddressOrSize) + format("%08"PRIx64, i->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); + + if (OutputFormat == posix) { + outs() << i->Name << " " << i->TypeChar << " " + << SymbolAddrStr << SymbolSizeStr << "\n"; + } else if (OutputFormat == bsd) { + if (PrintAddress) + outs() << SymbolAddrStr << ' '; + if (PrintSize) { + outs() << SymbolSizeStr; + if (i->Size != object::UnknownAddressOrSize) + outs() << ' '; + } + outs() << i->TypeChar << " " << i->Name << "\n"; + } else if (OutputFormat == sysv) { + std::string PaddedName (i->Name); + while (PaddedName.length () < 20) + PaddedName += " "; + outs() << PaddedName << "|" << SymbolAddrStr << "| " + << i->TypeChar + << " | |" << SymbolSizeStr << "| |\n"; + } + } + + SymbolList.clear(); +} + +static char TypeCharForSymbol(GlobalValue &GV) { + if (GV.isDeclaration()) return 'U'; + if (GV.hasLinkOnceLinkage()) return 'C'; + if (GV.hasCommonLinkage()) return 'C'; + if (GV.hasWeakLinkage()) return 'W'; + if (isa(GV) && GV.hasInternalLinkage()) return 't'; + if (isa(GV)) return 'T'; + if (isa(GV) && GV.hasInternalLinkage()) return 'd'; + if (isa(GV)) return 'D'; + if (const GlobalAlias *GA = dyn_cast(&GV)) { + const GlobalValue *AliasedGV = GA->getAliasedGlobal(); + if (isa(AliasedGV)) return 'T'; + if (isa(AliasedGV)) return 'D'; + } + return '?'; +} + +static void DumpSymbolNameForGlobalValue(GlobalValue &GV) { + // Private linkage and available_externally linkage don't exist in symtab. + if (GV.hasPrivateLinkage() || + GV.hasLinkerPrivateLinkage() || + GV.hasLinkerPrivateWeakLinkage() || + GV.hasLinkerPrivateWeakDefAutoLinkage() || + GV.hasAvailableExternallyLinkage()) + return; + char TypeChar = TypeCharForSymbol(GV); + if (GV.hasLocalLinkage () && ExternalOnly) + return; + + NMSymbol s; + s.Address = object::UnknownAddressOrSize; + s.Size = object::UnknownAddressOrSize; + s.TypeChar = TypeChar; + s.Name = GV.getName(); + SymbolList.push_back(s); +} + +static void DumpSymbolNamesFromModule(Module *M) { + CurrentFilename = M->getModuleIdentifier(); + std::for_each (M->begin(), M->end(), DumpSymbolNameForGlobalValue); + std::for_each (M->global_begin(), M->global_end(), + DumpSymbolNameForGlobalValue); + std::for_each (M->alias_begin(), M->alias_end(), + DumpSymbolNameForGlobalValue); + + SortAndPrintSymbolList(); +} + +static void DumpSymbolNamesFromObject(ObjectFile *obj) { + error_code ec; + for (symbol_iterator i = obj->begin_symbols(), + e = obj->end_symbols(); + i != e; i.increment(ec)) { + if (error(ec)) break; + bool internal; + if (error(i->isInternal(internal))) break; + if (!DebugSyms && internal) + continue; + NMSymbol s; + s.Size = object::UnknownAddressOrSize; + s.Address = object::UnknownAddressOrSize; + if (PrintSize || SizeSort) { + if (error(i->getSize(s.Size))) break; + } + if (PrintAddress) + if (error(i->getOffset(s.Address))) break; + if (error(i->getNMTypeChar(s.TypeChar))) break; + if (error(i->getName(s.Name))) break; + SymbolList.push_back(s); + } + + CurrentFilename = obj->getFileName(); + SortAndPrintSymbolList(); +} + +static void DumpSymbolNamesFromFile(std::string &Filename) { + LLVMContext &Context = getGlobalContext(); + std::string ErrorMessage; + sys::Path aPath(Filename); + bool exists; + if (sys::fs::exists(aPath.str(), exists) || !exists) + errs() << ToolName << ": '" << Filename << "': " << "No such file\n"; + // Note: Currently we do not support reading an archive from stdin. + if (Filename == "-" || aPath.isBitcodeFile()) { + OwningPtr Buffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buffer)) + ErrorMessage = ec.message(); + Module *Result = 0; + if (Buffer.get()) + Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); + + if (Result) { + DumpSymbolNamesFromModule(Result); + delete Result; + } else + errs() << ToolName << ": " << Filename << ": " << ErrorMessage << "\n"; + + } else if (aPath.isArchive()) { + OwningPtr arch; + if (error_code ec = object::createBinary(aPath.str(), arch)) { + errs() << ToolName << ": " << Filename << ": " << ec.message() << ".\n"; + return; + } + if (object::Archive *a = dyn_cast(arch.get())) { + for (object::Archive::child_iterator i = a->begin_children(), + e = a->end_children(); i != e; ++i) { + OwningPtr child; + if (error_code ec = i->getAsBinary(child)) { + // Try opening it as a bitcode file. + OwningPtr buff(i->getBuffer()); + Module *Result = 0; + if (buff) + Result = ParseBitcodeFile(buff.get(), Context, &ErrorMessage); + + if (Result) { + DumpSymbolNamesFromModule(Result); + delete Result; + } + continue; + } + if (object::ObjectFile *o = dyn_cast(child.get())) { + outs() << o->getFileName() << ":\n"; + DumpSymbolNamesFromObject(o); + } + } + } + } else if (aPath.isObjectFile()) { + OwningPtr obj; + if (error_code ec = object::createBinary(aPath.str(), obj)) { + errs() << ToolName << ": " << Filename << ": " << ec.message() << ".\n"; + return; + } + if (object::ObjectFile *o = dyn_cast(obj.get())) + DumpSymbolNamesFromObject(o); + } else { + errs() << ToolName << ": " << Filename << ": " + << "unrecognizable file type\n"; + return; + } +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n"); + + ToolName = argv[0]; + if (BSDFormat) OutputFormat = bsd; + if (POSIXFormat) OutputFormat = posix; + + // The relative order of these is important. If you pass --size-sort it should + // only print out the size. However, if you pass -S --size-sort, it should + // print out both the size and address. + if (SizeSort && !PrintSize) PrintAddress = false; + if (OutputFormat == sysv || SizeSort) PrintSize = true; + + switch (InputFilenames.size()) { + case 0: InputFilenames.push_back("-"); + case 1: break; + default: MultipleFiles = true; + } + + std::for_each(InputFilenames.begin(), InputFilenames.end(), + DumpSymbolNamesFromFile); + return 0; +} diff --git a/contrib/llvm/tools/llvm-objdump/CMakeLists.txt b/contrib/llvm/tools/llvm-objdump/CMakeLists.txt new file mode 100644 index 000000000000..f3b2e1fe4196 --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + DebugInfo + MC + MCParser + MCDisassembler + Object + ) + +add_llvm_tool(llvm-objdump + llvm-objdump.cpp + MachODump.cpp + MCFunction.cpp + ) diff --git a/contrib/llvm/tools/llvm-objdump/MCFunction.cpp b/contrib/llvm/tools/llvm-objdump/MCFunction.cpp new file mode 100644 index 000000000000..5c67f1b70a9a --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/MCFunction.cpp @@ -0,0 +1,138 @@ +//===-- MCFunction.cpp ----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the algorithm to break down a region of machine code +// into basic blocks and try to reconstruct a CFG from it. +// +//===----------------------------------------------------------------------===// + +#include "MCFunction.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrAnalysis.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include +using namespace llvm; + +MCFunction +MCFunction::createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm, + const MemoryObject &Region, uint64_t Start, + uint64_t End, const MCInstrAnalysis *Ana, + raw_ostream &DebugOut, + SmallVectorImpl &Calls) { + std::vector Instructions; + std::set Splits; + Splits.insert(Start); + uint64_t Size; + + MCFunction f(Name); + + { + DenseSet VisitedInsts; + SmallVector WorkList; + WorkList.push_back(Start); + // Disassemble code and gather basic block split points. + while (!WorkList.empty()) { + uint64_t Index = WorkList.pop_back_val(); + if (VisitedInsts.find(Index) != VisitedInsts.end()) + continue; // Already visited this location. + + for (;Index < End; Index += Size) { + VisitedInsts.insert(Index); + + MCInst Inst; + if (DisAsm->getInstruction(Inst, Size, Region, Index, DebugOut, nulls())){ + Instructions.push_back(MCDecodedInst(Index, Size, Inst)); + if (Ana->isBranch(Inst)) { + uint64_t targ = Ana->evaluateBranch(Inst, Index, Size); + if (targ != -1ULL && targ == Index+Size) + continue; // Skip nop jumps. + + // If we could determine the branch target, make a note to start a + // new basic block there and add the target to the worklist. + if (targ != -1ULL) { + Splits.insert(targ); + WorkList.push_back(targ); + WorkList.push_back(Index+Size); + } + Splits.insert(Index+Size); + break; + } else if (Ana->isReturn(Inst)) { + // Return instruction. This basic block ends here. + Splits.insert(Index+Size); + break; + } else if (Ana->isCall(Inst)) { + uint64_t targ = Ana->evaluateBranch(Inst, Index, Size); + // Add the call to the call list if the destination is known. + if (targ != -1ULL && targ != Index+Size) + Calls.push_back(targ); + } + } else { + errs().write_hex(Index) << ": warning: invalid instruction encoding\n"; + if (Size == 0) + Size = 1; // skip illegible bytes + } + } + } + } + + // Make sure the instruction list is sorted. + std::sort(Instructions.begin(), Instructions.end()); + + // Create basic blocks. + unsigned ii = 0, ie = Instructions.size(); + for (std::set::iterator spi = Splits.begin(), + spe = llvm::prior(Splits.end()); spi != spe; ++spi) { + MCBasicBlock BB; + uint64_t BlockEnd = *llvm::next(spi); + // Add instructions to the BB. + for (; ii != ie; ++ii) { + if (Instructions[ii].Address < *spi || + Instructions[ii].Address >= BlockEnd) + break; + BB.addInst(Instructions[ii]); + } + f.addBlock(*spi, BB); + } + + std::sort(f.Blocks.begin(), f.Blocks.end()); + + // Calculate successors of each block. + for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) { + MCBasicBlock &BB = const_cast(i->second); + if (BB.getInsts().empty()) continue; + const MCDecodedInst &Inst = BB.getInsts().back(); + + if (Ana->isBranch(Inst.Inst)) { + uint64_t targ = Ana->evaluateBranch(Inst.Inst, Inst.Address, Inst.Size); + if (targ == -1ULL) { + // Indirect branch. Bail and add all blocks of the function as a + // successor. + for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) + BB.addSucc(i->first); + } else if (targ != Inst.Address+Inst.Size) + BB.addSucc(targ); + // Conditional branches can also fall through to the next block. + if (Ana->isConditionalBranch(Inst.Inst) && llvm::next(i) != e) + BB.addSucc(llvm::next(i)->first); + } else { + // No branch. Fall through to the next block. + if (!Ana->isReturn(Inst.Inst) && llvm::next(i) != e) + BB.addSucc(llvm::next(i)->first); + } + } + + return f; +} diff --git a/contrib/llvm/tools/llvm-objdump/MCFunction.h b/contrib/llvm/tools/llvm-objdump/MCFunction.h new file mode 100644 index 000000000000..6d3a548d48e8 --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/MCFunction.h @@ -0,0 +1,100 @@ +//===-- MCFunction.h ------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the data structures to hold a CFG reconstructed from +// machine code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECTDUMP_MCFUNCTION_H +#define LLVM_OBJECTDUMP_MCFUNCTION_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/MC/MCInst.h" +#include + +namespace llvm { + +class MCDisassembler; +class MCInstrAnalysis; +class MemoryObject; +class raw_ostream; + +/// MCDecodedInst - Small container to hold an MCInst and associated info like +/// address and size. +struct MCDecodedInst { + uint64_t Address; + uint64_t Size; + MCInst Inst; + + MCDecodedInst() {} + MCDecodedInst(uint64_t Address, uint64_t Size, MCInst Inst) + : Address(Address), Size(Size), Inst(Inst) {} + + bool operator<(const MCDecodedInst &RHS) const { + return Address < RHS.Address; + } +}; + +/// MCBasicBlock - Consists of multiple MCDecodedInsts and a list of successing +/// MCBasicBlocks. +class MCBasicBlock { + std::vector Insts; + typedef DenseSet SetTy; + SetTy Succs; +public: + ArrayRef getInsts() const { return Insts; } + + typedef SetTy::const_iterator succ_iterator; + succ_iterator succ_begin() const { return Succs.begin(); } + succ_iterator succ_end() const { return Succs.end(); } + + bool contains(uint64_t Addr) const { return Succs.count(Addr); } + + void addInst(const MCDecodedInst &Inst) { Insts.push_back(Inst); } + void addSucc(uint64_t Addr) { Succs.insert(Addr); } + + bool operator<(const MCBasicBlock &RHS) const { + return Insts.size() < RHS.Insts.size(); + } +}; + +/// MCFunction - Represents a named function in machine code, containing +/// multiple MCBasicBlocks. +class MCFunction { + const StringRef Name; + // Keep BBs sorted by address. + typedef std::vector > MapTy; + MapTy Blocks; +public: + MCFunction(StringRef Name) : Name(Name) {} + + // Create an MCFunction from a region of binary machine code. + static MCFunction + createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm, + const MemoryObject &Region, uint64_t Start, uint64_t End, + const MCInstrAnalysis *Ana, raw_ostream &DebugOut, + SmallVectorImpl &Calls); + + typedef MapTy::const_iterator iterator; + iterator begin() const { return Blocks.begin(); } + iterator end() const { return Blocks.end(); } + + StringRef getName() const { return Name; } + + MCBasicBlock &addBlock(uint64_t Address, const MCBasicBlock &BB) { + Blocks.push_back(std::make_pair(Address, BB)); + return Blocks.back().second; + } +}; + +} + +#endif diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp new file mode 100644 index 000000000000..3f44b295d32c --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp @@ -0,0 +1,617 @@ +//===-- MachODump.cpp - Object file dumping utility for llvm --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MachO-specific dumper for llvm-objdump. +// +//===----------------------------------------------------------------------===// + +#include "llvm-objdump.h" +#include "MCFunction.h" +#include "llvm/Support/MachO.h" +#include "llvm/Object/MachOObject.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrAnalysis.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include +#include +using namespace llvm; +using namespace object; + +static cl::opt + CFG("cfg", cl::desc("Create a CFG for every symbol in the object file and" + "write it to a graphviz file (MachO-only)")); + +static cl::opt + UseDbg("g", cl::desc("Print line information from debug info if available")); + +static cl::opt + DSYMFile("dsym", cl::desc("Use .dSYM file for debug info")); + +static const Target *GetTarget(const MachOObject *MachOObj) { + // Figure out the target triple. + llvm::Triple TT("unknown-unknown-unknown"); + switch (MachOObj->getHeader().CPUType) { + case llvm::MachO::CPUTypeI386: + TT.setArch(Triple::ArchType(Triple::x86)); + break; + case llvm::MachO::CPUTypeX86_64: + TT.setArch(Triple::ArchType(Triple::x86_64)); + break; + case llvm::MachO::CPUTypeARM: + TT.setArch(Triple::ArchType(Triple::arm)); + break; + case llvm::MachO::CPUTypePowerPC: + TT.setArch(Triple::ArchType(Triple::ppc)); + break; + case llvm::MachO::CPUTypePowerPC64: + TT.setArch(Triple::ArchType(Triple::ppc64)); + break; + } + + TripleName = TT.str(); + + // Get the target specific parser. + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); + if (TheTarget) + return TheTarget; + + errs() << "llvm-objdump: error: unable to get target for '" << TripleName + << "', see --version and --triple.\n"; + return 0; +} + +struct Section { + char Name[16]; + uint64_t Address; + uint64_t Size; + uint32_t Offset; + uint32_t NumRelocs; + uint64_t RelocTableOffset; +}; + +struct Symbol { + uint64_t Value; + uint32_t StringIndex; + uint8_t SectionIndex; + bool operator<(const Symbol &RHS) const { return Value < RHS.Value; } +}; + +template +static Section copySection(const T &Sect) { + Section S; + memcpy(S.Name, Sect->Name, 16); + S.Address = Sect->Address; + S.Size = Sect->Size; + S.Offset = Sect->Offset; + S.NumRelocs = Sect->NumRelocationTableEntries; + S.RelocTableOffset = Sect->RelocationTableOffset; + return S; +} + +template +static Symbol copySymbol(const T &STE) { + Symbol S; + S.StringIndex = STE->StringIndex; + S.SectionIndex = STE->SectionIndex; + S.Value = STE->Value; + return S; +} + +// Print additional information about an address, if available. +static void DumpAddress(uint64_t Address, ArrayRef
Sections, + MachOObject *MachOObj, raw_ostream &OS) { + for (unsigned i = 0; i != Sections.size(); ++i) { + uint64_t addr = Address-Sections[i].Address; + if (Sections[i].Address <= Address && + Sections[i].Address + Sections[i].Size > Address) { + StringRef bytes = MachOObj->getData(Sections[i].Offset, + Sections[i].Size); + // Print constant strings. + if (!strcmp(Sections[i].Name, "__cstring")) + OS << '"' << bytes.substr(addr, bytes.find('\0', addr)) << '"'; + // Print constant CFStrings. + if (!strcmp(Sections[i].Name, "__cfstring")) + OS << "@\"" << bytes.substr(addr, bytes.find('\0', addr)) << '"'; + } + } +} + +typedef std::map FunctionMapTy; +typedef SmallVector FunctionListTy; +static void createMCFunctionAndSaveCalls(StringRef Name, + const MCDisassembler *DisAsm, + MemoryObject &Object, uint64_t Start, + uint64_t End, + MCInstrAnalysis *InstrAnalysis, + uint64_t Address, + raw_ostream &DebugOut, + FunctionMapTy &FunctionMap, + FunctionListTy &Functions) { + SmallVector Calls; + MCFunction f = + MCFunction::createFunctionFromMC(Name, DisAsm, Object, Start, End, + InstrAnalysis, DebugOut, Calls); + Functions.push_back(f); + FunctionMap[Address] = &Functions.back(); + + // Add the gathered callees to the map. + for (unsigned i = 0, e = Calls.size(); i != e; ++i) + FunctionMap.insert(std::make_pair(Calls[i], (MCFunction*)0)); +} + +// Write a graphviz file for the CFG inside an MCFunction. +static void emitDOTFile(const char *FileName, const MCFunction &f, + MCInstPrinter *IP) { + // Start a new dot file. + std::string Error; + raw_fd_ostream Out(FileName, Error); + if (!Error.empty()) { + errs() << "llvm-objdump: warning: " << Error << '\n'; + return; + } + + Out << "digraph " << f.getName() << " {\n"; + Out << "graph [ rankdir = \"LR\" ];\n"; + for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) { + bool hasPreds = false; + // Only print blocks that have predecessors. + // FIXME: Slow. + for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe; + ++pi) + if (pi->second.contains(i->first)) { + hasPreds = true; + break; + } + + if (!hasPreds && i != f.begin()) + continue; + + Out << '"' << i->first << "\" [ label=\""; + // Print instructions. + for (unsigned ii = 0, ie = i->second.getInsts().size(); ii != ie; + ++ii) { + // Escape special chars and print the instruction in mnemonic form. + std::string Str; + raw_string_ostream OS(Str); + IP->printInst(&i->second.getInsts()[ii].Inst, OS, ""); + Out << DOT::EscapeString(OS.str()) << '|'; + } + Out << "\" shape=\"record\" ];\n"; + + // Add edges. + for (MCBasicBlock::succ_iterator si = i->second.succ_begin(), + se = i->second.succ_end(); si != se; ++si) + Out << i->first << ":o -> " << *si <<":a\n"; + } + Out << "}\n"; +} + +static void getSectionsAndSymbols(const macho::Header &Header, + MachOObject *MachOObj, + InMemoryStruct *SymtabLC, + std::vector
&Sections, + std::vector &Symbols, + SmallVectorImpl &FoundFns) { + // Make a list of all symbols in the object file. + for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); + if (LCI.Command.Type == macho::LCT_Segment) { + InMemoryStruct SegmentLC; + MachOObj->ReadSegmentLoadCommand(LCI, SegmentLC); + + // Store the sections in this segment. + for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) { + InMemoryStruct Sect; + MachOObj->ReadSection(LCI, SectNum, Sect); + Sections.push_back(copySection(Sect)); + + } + } else if (LCI.Command.Type == macho::LCT_Segment64) { + InMemoryStruct Segment64LC; + MachOObj->ReadSegment64LoadCommand(LCI, Segment64LC); + + // Store the sections in this segment. + for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections; + ++SectNum) { + InMemoryStruct Sect64; + MachOObj->ReadSection64(LCI, SectNum, Sect64); + Sections.push_back(copySection(Sect64)); + } + } else if (LCI.Command.Type == macho::LCT_FunctionStarts) { + // We found a function starts segment, parse the addresses for later + // consumption. + InMemoryStruct LLC; + MachOObj->ReadLinkeditDataLoadCommand(LCI, LLC); + + MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); + } + } + // Store the symbols. + if (SymtabLC) { + for (unsigned i = 0; i != (*SymtabLC)->NumSymbolTableEntries; ++i) { + if (MachOObj->is64Bit()) { + InMemoryStruct STE; + MachOObj->ReadSymbol64TableEntry((*SymtabLC)->SymbolTableOffset, i, + STE); + Symbols.push_back(copySymbol(STE)); + } else { + InMemoryStruct STE; + MachOObj->ReadSymbolTableEntry((*SymtabLC)->SymbolTableOffset, i, + STE); + Symbols.push_back(copySymbol(STE)); + } + } + } +} + +void llvm::DisassembleInputMachO(StringRef Filename) { + OwningPtr Buff; + + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) { + errs() << "llvm-objdump: " << Filename << ": " << ec.message() << "\n"; + return; + } + + OwningPtr MachOObj(MachOObject::LoadFromBuffer(Buff.take())); + + const Target *TheTarget = GetTarget(MachOObj.get()); + if (!TheTarget) { + // GetTarget prints out stuff. + return; + } + OwningPtr InstrInfo(TheTarget->createMCInstrInfo()); + OwningPtr + InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get())); + + // Set up disassembler. + OwningPtr AsmInfo(TheTarget->createMCAsmInfo(TripleName)); + OwningPtr + STI(TheTarget->createMCSubtargetInfo(TripleName, "", "")); + OwningPtr DisAsm(TheTarget->createMCDisassembler(*STI)); + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + OwningPtr IP(TheTarget->createMCInstPrinter( + AsmPrinterVariant, *AsmInfo, *STI)); + + if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) { + errs() << "error: couldn't initialize disassembler for target " + << TripleName << '\n'; + return; + } + + outs() << '\n' << Filename << ":\n\n"; + + const macho::Header &Header = MachOObj->getHeader(); + + const MachOObject::LoadCommandInfo *SymtabLCI = 0; + // First, find the symbol table segment. + for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); + if (LCI.Command.Type == macho::LCT_Symtab) { + SymtabLCI = &LCI; + break; + } + } + + // Read and register the symbol table data. + InMemoryStruct SymtabLC; + MachOObj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC); + MachOObj->RegisterStringTable(*SymtabLC); + + std::vector
Sections; + std::vector Symbols; + SmallVector FoundFns; + + getSectionsAndSymbols(Header, MachOObj.get(), &SymtabLC, Sections, Symbols, + FoundFns); + + // Make a copy of the unsorted symbol list. FIXME: duplication + std::vector UnsortedSymbols(Symbols); + // Sort the symbols by address, just in case they didn't come in that way. + array_pod_sort(Symbols.begin(), Symbols.end()); + +#ifndef NDEBUG + raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); +#else + raw_ostream &DebugOut = nulls(); +#endif + + StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection, + DebugLineSection, DebugStrSection; + OwningPtr diContext; + OwningPtr DSYMObj; + MachOObject *DbgInfoObj = MachOObj.get(); + // Try to find debug info and set up the DIContext for it. + if (UseDbg) { + ArrayRef
DebugSections = Sections; + std::vector
DSYMSections; + + // A separate DSym file path was specified, parse it as a macho file, + // get the sections and supply it to the section name parsing machinery. + if (!DSYMFile.empty()) { + OwningPtr Buf; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile.c_str(), Buf)) { + errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n'; + return; + } + DSYMObj.reset(MachOObject::LoadFromBuffer(Buf.take())); + const macho::Header &Header = DSYMObj->getHeader(); + + std::vector Symbols; + SmallVector FoundFns; + getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols, + FoundFns); + DebugSections = DSYMSections; + DbgInfoObj = DSYMObj.get(); + } + + // Find the named debug info sections. + for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) { + if (!strcmp(DebugSections[SectIdx].Name, "__debug_abbrev")) + DebugAbbrevSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + else if (!strcmp(DebugSections[SectIdx].Name, "__debug_info")) + DebugInfoSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + else if (!strcmp(DebugSections[SectIdx].Name, "__debug_aranges")) + DebugArangesSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + else if (!strcmp(DebugSections[SectIdx].Name, "__debug_line")) + DebugLineSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + else if (!strcmp(DebugSections[SectIdx].Name, "__debug_str")) + DebugStrSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + } + + // Setup the DIContext. + diContext.reset(DIContext::getDWARFContext(DbgInfoObj->isLittleEndian(), + DebugInfoSection, + DebugAbbrevSection, + DebugArangesSection, + DebugLineSection, + DebugStrSection)); + } + + FunctionMapTy FunctionMap; + FunctionListTy Functions; + + for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { + if (strcmp(Sections[SectIdx].Name, "__text")) + continue; // Skip non-text sections + + // Insert the functions from the function starts segment into our map. + uint64_t VMAddr = Sections[SectIdx].Address - Sections[SectIdx].Offset; + for (unsigned i = 0, e = FoundFns.size(); i != e; ++i) + FunctionMap.insert(std::make_pair(FoundFns[i]+VMAddr, (MCFunction*)0)); + + StringRef Bytes = MachOObj->getData(Sections[SectIdx].Offset, + Sections[SectIdx].Size); + StringRefMemoryObject memoryObject(Bytes); + bool symbolTableWorked = false; + + // Parse relocations. + std::vector > Relocs; + for (unsigned j = 0; j != Sections[SectIdx].NumRelocs; ++j) { + InMemoryStruct RE; + MachOObj->ReadRelocationEntry(Sections[SectIdx].RelocTableOffset, j, RE); + Relocs.push_back(std::make_pair(RE->Word0, RE->Word1 & 0xffffff)); + } + array_pod_sort(Relocs.begin(), Relocs.end()); + + // Disassemble symbol by symbol. + for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { + // Make sure the symbol is defined in this section. + if ((unsigned)Symbols[SymIdx].SectionIndex - 1 != SectIdx) + continue; + + // Start at the address of the symbol relative to the section's address. + uint64_t Start = Symbols[SymIdx].Value - Sections[SectIdx].Address; + // Stop disassembling either at the beginning of the next symbol or at + // the end of the section. + uint64_t End = (SymIdx+1 == Symbols.size() || + Symbols[SymIdx].SectionIndex != Symbols[SymIdx+1].SectionIndex) ? + Sections[SectIdx].Size : + Symbols[SymIdx+1].Value - Sections[SectIdx].Address; + uint64_t Size; + + if (Start >= End) + continue; + + symbolTableWorked = true; + + if (!CFG) { + // Normal disassembly, print addresses, bytes and mnemonic form. + outs() << MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex) + << ":\n"; + DILineInfo lastLine; + for (uint64_t Index = Start; Index < End; Index += Size) { + MCInst Inst; + + if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, + DebugOut, nulls())) { + outs() << format("%8llx:\t", Sections[SectIdx].Address + Index); + DumpBytes(StringRef(Bytes.data() + Index, Size)); + IP->printInst(&Inst, outs(), ""); + + // Print debug info. + if (diContext) { + DILineInfo dli = + diContext->getLineInfoForAddress(Sections[SectIdx].Address + + Index); + // Print valid line info if it changed. + if (dli != lastLine && dli.getLine() != 0) + outs() << "\t## " << dli.getFileName() << ':' + << dli.getLine() << ':' << dli.getColumn(); + lastLine = dli; + } + outs() << "\n"; + } else { + errs() << "llvm-objdump: warning: invalid instruction encoding\n"; + if (Size == 0) + Size = 1; // skip illegible bytes + } + } + } else { + // Create CFG and use it for disassembly. + createMCFunctionAndSaveCalls( + MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex), + DisAsm.get(), memoryObject, Start, End, InstrAnalysis.get(), + Start, DebugOut, FunctionMap, Functions); + } + } + + if (CFG) { + if (!symbolTableWorked) { + // Reading the symbol table didn't work, create a big __TEXT symbol. + createMCFunctionAndSaveCalls("__TEXT", DisAsm.get(), memoryObject, + 0, Sections[SectIdx].Size, + InstrAnalysis.get(), + Sections[SectIdx].Offset, DebugOut, + FunctionMap, Functions); + } + for (std::map::iterator mi = FunctionMap.begin(), + me = FunctionMap.end(); mi != me; ++mi) + if (mi->second == 0) { + // Create functions for the remaining callees we have gathered, + // but we didn't find a name for them. + SmallVector Calls; + MCFunction f = + MCFunction::createFunctionFromMC("unknown", DisAsm.get(), + memoryObject, mi->first, + Sections[SectIdx].Size, + InstrAnalysis.get(), DebugOut, + Calls); + Functions.push_back(f); + mi->second = &Functions.back(); + for (unsigned i = 0, e = Calls.size(); i != e; ++i) { + std::pair p(Calls[i], (MCFunction*)0); + if (FunctionMap.insert(p).second) + mi = FunctionMap.begin(); + } + } + + DenseSet PrintedBlocks; + for (unsigned ffi = 0, ffe = Functions.size(); ffi != ffe; ++ffi) { + MCFunction &f = Functions[ffi]; + for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){ + if (!PrintedBlocks.insert(fi->first).second) + continue; // We already printed this block. + + // We assume a block has predecessors when it's the first block after + // a symbol. + bool hasPreds = FunctionMap.find(fi->first) != FunctionMap.end(); + + // See if this block has predecessors. + // FIXME: Slow. + for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe; + ++pi) + if (pi->second.contains(fi->first)) { + hasPreds = true; + break; + } + + // No predecessors, this is a data block. Print as .byte directives. + if (!hasPreds) { + uint64_t End = llvm::next(fi) == fe ? Sections[SectIdx].Size : + llvm::next(fi)->first; + outs() << "# " << End-fi->first << " bytes of data:\n"; + for (unsigned pos = fi->first; pos != End; ++pos) { + outs() << format("%8x:\t", Sections[SectIdx].Address + pos); + DumpBytes(StringRef(Bytes.data() + pos, 1)); + outs() << format("\t.byte 0x%02x\n", (uint8_t)Bytes[pos]); + } + continue; + } + + if (fi->second.contains(fi->first)) // Print a header for simple loops + outs() << "# Loop begin:\n"; + + DILineInfo lastLine; + // Walk over the instructions and print them. + for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie; + ++ii) { + const MCDecodedInst &Inst = fi->second.getInsts()[ii]; + + // If there's a symbol at this address, print its name. + if (FunctionMap.find(Sections[SectIdx].Address + Inst.Address) != + FunctionMap.end()) + outs() << FunctionMap[Sections[SectIdx].Address + Inst.Address]-> + getName() << ":\n"; + + outs() << format("%8llx:\t", Sections[SectIdx].Address + + Inst.Address); + DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size)); + + if (fi->second.contains(fi->first)) // Indent simple loops. + outs() << '\t'; + + IP->printInst(&Inst.Inst, outs(), ""); + + // Look for relocations inside this instructions, if there is one + // print its target and additional information if available. + for (unsigned j = 0; j != Relocs.size(); ++j) + if (Relocs[j].first >= Sections[SectIdx].Address + Inst.Address && + Relocs[j].first < Sections[SectIdx].Address + Inst.Address + + Inst.Size) { + outs() << "\t# " + << MachOObj->getStringAtIndex( + UnsortedSymbols[Relocs[j].second].StringIndex) + << ' '; + DumpAddress(UnsortedSymbols[Relocs[j].second].Value, Sections, + MachOObj.get(), outs()); + } + + // If this instructions contains an address, see if we can evaluate + // it and print additional information. + uint64_t targ = InstrAnalysis->evaluateBranch(Inst.Inst, + Inst.Address, + Inst.Size); + if (targ != -1ULL) + DumpAddress(targ, Sections, MachOObj.get(), outs()); + + // Print debug info. + if (diContext) { + DILineInfo dli = + diContext->getLineInfoForAddress(Sections[SectIdx].Address + + Inst.Address); + // Print valid line info if it changed. + if (dli != lastLine && dli.getLine() != 0) + outs() << "\t## " << dli.getFileName() << ':' + << dli.getLine() << ':' << dli.getColumn(); + lastLine = dli; + } + + outs() << '\n'; + } + } + + emitDOTFile((f.getName().str() + ".dot").c_str(), f, IP.get()); + } + } + } +} diff --git a/contrib/llvm/tools/llvm-objdump/Makefile b/contrib/llvm/tools/llvm-objdump/Makefile new file mode 100644 index 000000000000..703bf6c8a4f1 --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/Makefile @@ -0,0 +1,18 @@ +##===- tools/llvm-objdump/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. + +TOOLNAME = llvm-objdump +LINK_COMPONENTS = $(TARGETS_TO_BUILD) DebugInfo MC MCParser MCDisassembler \ + Object + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp new file mode 100644 index 000000000000..40c59bd8c369 --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -0,0 +1,459 @@ +//===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program is a utility that works like binutils "objdump", that is, it +// dumps out a plethora of information about an object file depending on the +// flags. +// +//===----------------------------------------------------------------------===// + +#include "llvm-objdump.h" +#include "MCFunction.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include +#include +using namespace llvm; +using namespace object; + +static cl::list +InputFilenames(cl::Positional, cl::desc(""),cl::ZeroOrMore); + +static cl::opt +Disassemble("disassemble", + cl::desc("Display assembler mnemonics for the machine instructions")); +static cl::alias +Disassembled("d", cl::desc("Alias for --disassemble"), + cl::aliasopt(Disassemble)); + +static cl::opt +Relocations("r", cl::desc("Display the relocation entries in the file")); + +static cl::opt +MachO("macho", cl::desc("Use MachO specific object file parser")); +static cl::alias +MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachO)); + +cl::opt +llvm::TripleName("triple", cl::desc("Target triple to disassemble for, " + "see -version for available targets")); + +cl::opt +llvm::ArchName("arch", cl::desc("Target arch to disassemble for, " + "see -version for available targets")); + +static cl::opt +SectionHeaders("section-headers", cl::desc("Display summaries of the headers " + "for each section.")); +static cl::alias +SectionHeadersShort("headers", cl::desc("Alias for --section-headers"), + cl::aliasopt(SectionHeaders)); +static cl::alias +SectionHeadersShorter("h", cl::desc("Alias for --section-headers"), + cl::aliasopt(SectionHeaders)); + +static StringRef ToolName; + +static bool error(error_code ec) { + if (!ec) return false; + + outs() << ToolName << ": error reading file: " << ec.message() << ".\n"; + outs().flush(); + return true; +} + +static const Target *GetTarget(const ObjectFile *Obj = NULL) { + // Figure out the target triple. + llvm::Triple TT("unknown-unknown-unknown"); + if (TripleName.empty()) { + if (Obj) + TT.setArch(Triple::ArchType(Obj->getArch())); + } else + TT.setTriple(Triple::normalize(TripleName)); + + if (!ArchName.empty()) + TT.setArchName(ArchName); + + TripleName = TT.str(); + + // Get the target specific parser. + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); + if (TheTarget) + return TheTarget; + + errs() << ToolName << ": error: unable to get target for '" << TripleName + << "', see --version and --triple.\n"; + return 0; +} + +void llvm::DumpBytes(StringRef bytes) { + static const char hex_rep[] = "0123456789abcdef"; + // FIXME: The real way to do this is to figure out the longest instruction + // and align to that size before printing. I'll fix this when I get + // around to outputting relocations. + // 15 is the longest x86 instruction + // 3 is for the hex rep of a byte + a space. + // 1 is for the null terminator. + enum { OutputSize = (15 * 3) + 1 }; + char output[OutputSize]; + + assert(bytes.size() <= 15 + && "DumpBytes only supports instructions of up to 15 bytes"); + memset(output, ' ', sizeof(output)); + unsigned index = 0; + for (StringRef::iterator i = bytes.begin(), + e = bytes.end(); i != e; ++i) { + output[index] = hex_rep[(*i & 0xF0) >> 4]; + output[index + 1] = hex_rep[*i & 0xF]; + index += 3; + } + + output[sizeof(output) - 1] = 0; + outs() << output; +} + +static bool RelocAddressLess(RelocationRef a, RelocationRef b) { + uint64_t a_addr, b_addr; + if (error(a.getAddress(a_addr))) return false; + if (error(b.getAddress(b_addr))) return false; + return a_addr < b_addr; +} + +static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { + const Target *TheTarget = GetTarget(Obj); + if (!TheTarget) { + // GetTarget prints out stuff. + return; + } + + outs() << '\n'; + outs() << Obj->getFileName() + << ":\tfile format " << Obj->getFileFormatName() << "\n\n"; + + error_code ec; + for (section_iterator i = Obj->begin_sections(), + e = Obj->end_sections(); + i != e; i.increment(ec)) { + if (error(ec)) break; + bool text; + if (error(i->isText(text))) break; + if (!text) continue; + + uint64_t SectionAddr; + if (error(i->getAddress(SectionAddr))) break; + + // Make a list of all the symbols in this section. + std::vector > Symbols; + for (symbol_iterator si = Obj->begin_symbols(), + se = Obj->end_symbols(); + si != se; si.increment(ec)) { + bool contains; + if (!error(i->containsSymbol(*si, contains)) && contains) { + uint64_t Address; + if (error(si->getOffset(Address))) break; + StringRef Name; + if (error(si->getName(Name))) break; + Symbols.push_back(std::make_pair(Address, Name)); + } + } + + // Sort the symbols by address, just in case they didn't come in that way. + array_pod_sort(Symbols.begin(), Symbols.end()); + + // Make a list of all the relocations for this section. + std::vector Rels; + if (InlineRelocs) { + for (relocation_iterator ri = i->begin_relocations(), + re = i->end_relocations(); + ri != re; ri.increment(ec)) { + if (error(ec)) break; + Rels.push_back(*ri); + } + } + + // Sort relocations by address. + std::sort(Rels.begin(), Rels.end(), RelocAddressLess); + + StringRef name; + if (error(i->getName(name))) break; + outs() << "Disassembly of section " << name << ':'; + + // If the section has no symbols just insert a dummy one and disassemble + // the whole section. + if (Symbols.empty()) + Symbols.push_back(std::make_pair(0, name)); + + // Set up disassembler. + OwningPtr AsmInfo(TheTarget->createMCAsmInfo(TripleName)); + + if (!AsmInfo) { + errs() << "error: no assembly info for target " << TripleName << "\n"; + return; + } + + OwningPtr STI( + TheTarget->createMCSubtargetInfo(TripleName, "", "")); + + if (!STI) { + errs() << "error: no subtarget info for target " << TripleName << "\n"; + return; + } + + OwningPtr DisAsm( + TheTarget->createMCDisassembler(*STI)); + if (!DisAsm) { + errs() << "error: no disassembler for target " << TripleName << "\n"; + return; + } + + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + OwningPtr IP(TheTarget->createMCInstPrinter( + AsmPrinterVariant, *AsmInfo, *STI)); + if (!IP) { + errs() << "error: no instruction printer for target " << TripleName + << '\n'; + return; + } + + StringRef Bytes; + if (error(i->getContents(Bytes))) break; + StringRefMemoryObject memoryObject(Bytes); + uint64_t Size; + uint64_t Index; + uint64_t SectSize; + if (error(i->getSize(SectSize))) break; + + std::vector::const_iterator rel_cur = Rels.begin(); + std::vector::const_iterator rel_end = Rels.end(); + // Disassemble symbol by symbol. + for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { + uint64_t Start = Symbols[si].first; + uint64_t End; + // The end is either the size of the section or the beginning of the next + // symbol. + if (si == se - 1) + End = SectSize; + // Make sure this symbol takes up space. + else if (Symbols[si + 1].first != Start) + End = Symbols[si + 1].first - 1; + else + // This symbol has the same address as the next symbol. Skip it. + continue; + + outs() << '\n' << Symbols[si].second << ":\n"; + +#ifndef NDEBUG + raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); +#else + raw_ostream &DebugOut = nulls(); +#endif + + for (Index = Start; Index < End; Index += Size) { + MCInst Inst; + + if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, + DebugOut, nulls())) { + outs() << format("%8"PRIx64":\t", SectionAddr + Index); + DumpBytes(StringRef(Bytes.data() + Index, Size)); + IP->printInst(&Inst, outs(), ""); + outs() << "\n"; + } else { + errs() << ToolName << ": warning: invalid instruction encoding\n"; + if (Size == 0) + Size = 1; // skip illegible bytes + } + + // Print relocation for instruction. + while (rel_cur != rel_end) { + uint64_t addr; + SmallString<16> name; + SmallString<32> val; + if (error(rel_cur->getAddress(addr))) goto skip_print_rel; + // Stop when rel_cur's address is past the current instruction. + if (addr > Index + Size) break; + if (error(rel_cur->getTypeName(name))) goto skip_print_rel; + if (error(rel_cur->getValueString(val))) goto skip_print_rel; + + outs() << format("\t\t\t%8"PRIx64": ", SectionAddr + addr) << name << "\t" + << val << "\n"; + + skip_print_rel: + ++rel_cur; + } + } + } + } +} + +static void PrintRelocations(const ObjectFile *o) { + error_code ec; + for (section_iterator si = o->begin_sections(), se = o->end_sections(); + si != se; si.increment(ec)){ + if (error(ec)) return; + if (si->begin_relocations() == si->end_relocations()) + continue; + StringRef secname; + if (error(si->getName(secname))) continue; + outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n"; + for (relocation_iterator ri = si->begin_relocations(), + re = si->end_relocations(); + ri != re; ri.increment(ec)) { + if (error(ec)) return; + + uint64_t address; + SmallString<32> relocname; + SmallString<32> valuestr; + if (error(ri->getTypeName(relocname))) continue; + if (error(ri->getAddress(address))) continue; + if (error(ri->getValueString(valuestr))) continue; + outs() << address << " " << relocname << " " << valuestr << "\n"; + } + outs() << "\n"; + } +} + +static void PrintSectionHeaders(const ObjectFile *o) { + outs() << "Sections:\n" + "Idx Name Size Address Type\n"; + error_code ec; + unsigned i = 0; + for (section_iterator si = o->begin_sections(), se = o->end_sections(); + si != se; si.increment(ec)) { + if (error(ec)) return; + StringRef Name; + if (error(si->getName(Name))) return; + uint64_t Address; + if (error(si->getAddress(Address))) return; + uint64_t Size; + if (error(si->getSize(Size))) return; + bool Text, Data, BSS; + if (error(si->isText(Text))) return; + if (error(si->isData(Data))) return; + if (error(si->isBSS(BSS))) return; + std::string Type = (std::string(Text ? "TEXT " : "") + + (Data ? "DATA " : "") + (BSS ? "BSS" : "")); + outs() << format("%3d %-13s %09"PRIx64" %017"PRIx64" %s\n", i, Name.str().c_str(), Size, + Address, Type.c_str()); + ++i; + } +} + +static void DumpObject(const ObjectFile *o) { + if (Disassemble) + DisassembleObject(o, Relocations); + if (Relocations && !Disassemble) + PrintRelocations(o); + if (SectionHeaders) + PrintSectionHeaders(o); +} + +/// @brief Dump each object file in \a a; +static void DumpArchive(const Archive *a) { + for (Archive::child_iterator i = a->begin_children(), + e = a->end_children(); i != e; ++i) { + OwningPtr child; + if (error_code ec = i->getAsBinary(child)) { + errs() << ToolName << ": '" << a->getFileName() << "': " << ec.message() + << ".\n"; + continue; + } + if (ObjectFile *o = dyn_cast(child.get())) + DumpObject(o); + else + errs() << ToolName << ": '" << a->getFileName() << "': " + << "Unrecognized file type.\n"; + } +} + +/// @brief Open file and figure out how to dump it. +static void DumpInput(StringRef file) { + // If file isn't stdin, check that it exists. + if (file != "-" && !sys::fs::exists(file)) { + errs() << ToolName << ": '" << file << "': " << "No such file\n"; + return; + } + + if (MachO && Disassemble) { + DisassembleInputMachO(file); + return; + } + + // Attempt to open the binary. + OwningPtr binary; + if (error_code ec = createBinary(file, binary)) { + errs() << ToolName << ": '" << file << "': " << ec.message() << ".\n"; + return; + } + + if (Archive *a = dyn_cast(binary.get())) { + DumpArchive(a); + } else if (ObjectFile *o = dyn_cast(binary.get())) { + DumpObject(o); + } else { + errs() << ToolName << ": '" << file << "': " << "Unrecognized file type.\n"; + } +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmParsers(); + llvm::InitializeAllDisassemblers(); + + cl::ParseCommandLineOptions(argc, argv, "llvm object file dumper\n"); + TripleName = Triple::normalize(TripleName); + + ToolName = argv[0]; + + // Defaults to a.out if no filenames specified. + if (InputFilenames.size() == 0) + InputFilenames.push_back("a.out"); + + if (!Disassemble && !Relocations && !SectionHeaders) { + cl::PrintHelpMessage(); + return 2; + } + + std::for_each(InputFilenames.begin(), InputFilenames.end(), + DumpInput); + + return 0; +} diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h new file mode 100644 index 000000000000..75f852afbc7e --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h @@ -0,0 +1,46 @@ +//===-- llvm-objdump.h ----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJDUMP_H +#define LLVM_OBJDUMP_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryObject.h" + +namespace llvm { + +extern cl::opt TripleName; +extern cl::opt ArchName; + +// Various helper functions. +void DumpBytes(StringRef bytes); +void DisassembleInputMachO(StringRef Filename); + +class StringRefMemoryObject : public MemoryObject { +private: + StringRef Bytes; +public: + StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {} + + uint64_t getBase() const { return 0; } + uint64_t getExtent() const { return Bytes.size(); } + + int readByte(uint64_t Addr, uint8_t *Byte) const { + if (Addr >= getExtent()) + return -1; + *Byte = Bytes[Addr]; + return 0; + } +}; + +} + +#endif diff --git a/contrib/llvm/tools/llvm-prof/CMakeLists.txt b/contrib/llvm/tools/llvm-prof/CMakeLists.txt new file mode 100644 index 000000000000..442112bc88ed --- /dev/null +++ b/contrib/llvm/tools/llvm-prof/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS bitreader analysis) + +add_llvm_tool(llvm-prof + llvm-prof.cpp + ) diff --git a/contrib/llvm/tools/llvm-prof/Makefile b/contrib/llvm/tools/llvm-prof/Makefile new file mode 100644 index 000000000000..86eb54d51bf4 --- /dev/null +++ b/contrib/llvm/tools/llvm-prof/Makefile @@ -0,0 +1,17 @@ +##===- tools/llvm-prof/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. + +TOOLNAME = llvm-prof +LINK_COMPONENTS = bitreader analysis + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-prof/llvm-prof.cpp b/contrib/llvm/tools/llvm-prof/llvm-prof.cpp new file mode 100644 index 000000000000..9d0b46833bef --- /dev/null +++ b/contrib/llvm/tools/llvm-prof/llvm-prof.cpp @@ -0,0 +1,293 @@ +//===- llvm-prof.cpp - Read in and process llvmprof.out data files --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tools is meant for use with the various LLVM profiling instrumentation +// passes. It reads in the data file produced by executing an instrumented +// program, and outputs a nice report. +// +//===----------------------------------------------------------------------===// + +#include "llvm/InstrTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Assembly/AssemblyAnnotationWriter.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Analysis/ProfileInfoLoader.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" +#include +#include +#include +#include + +using namespace llvm; + +namespace { + cl::opt + BitcodeFile(cl::Positional, cl::desc(""), + cl::Required); + + cl::opt + ProfileDataFile(cl::Positional, cl::desc(""), + cl::Optional, cl::init("llvmprof.out")); + + cl::opt + PrintAnnotatedLLVM("annotated-llvm", + cl::desc("Print LLVM code with frequency annotations")); + cl::alias PrintAnnotated2("A", cl::desc("Alias for --annotated-llvm"), + cl::aliasopt(PrintAnnotatedLLVM)); + cl::opt + PrintAllCode("print-all-code", + cl::desc("Print annotated code for the entire program")); +} + +// PairSecondSort - A sorting predicate to sort by the second element of a pair. +template +struct PairSecondSortReverse + : public std::binary_function, + std::pair, bool> { + bool operator()(const std::pair &LHS, + const std::pair &RHS) const { + return LHS.second > RHS.second; + } +}; + +static double ignoreMissing(double w) { + if (w == ProfileInfo::MissingValue) return 0; + return w; +} + +namespace { + class ProfileAnnotator : public AssemblyAnnotationWriter { + ProfileInfo &PI; + public: + ProfileAnnotator(ProfileInfo &pi) : PI(pi) {} + + virtual void emitFunctionAnnot(const Function *F, + formatted_raw_ostream &OS) { + double w = PI.getExecutionCount(F); + if (w != ProfileInfo::MissingValue) { + OS << ";;; %" << F->getName() << " called "<<(unsigned)w + <<" times.\n;;;\n"; + } + } + virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, + formatted_raw_ostream &OS) { + double w = PI.getExecutionCount(BB); + if (w != ProfileInfo::MissingValue) { + if (w != 0) { + OS << "\t;;; Basic block executed " << (unsigned)w << " times.\n"; + } else { + OS << "\t;;; Never executed!\n"; + } + } + } + + virtual void emitBasicBlockEndAnnot(const BasicBlock *BB, + formatted_raw_ostream &OS) { + // Figure out how many times each successor executed. + std::vector > SuccCounts; + + const TerminatorInst *TI = BB->getTerminator(); + for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { + BasicBlock* Succ = TI->getSuccessor(s); + double w = ignoreMissing(PI.getEdgeWeight(std::make_pair(BB, Succ))); + if (w != 0) + SuccCounts.push_back(std::make_pair(std::make_pair(BB, Succ), w)); + } + if (!SuccCounts.empty()) { + OS << "\t;;; Out-edge counts:"; + for (unsigned i = 0, e = SuccCounts.size(); i != e; ++i) + OS << " [" << (SuccCounts[i]).second << " -> " + << (SuccCounts[i]).first.second->getName() << "]"; + OS << "\n"; + } + } + }; +} + +namespace { + /// ProfileInfoPrinterPass - Helper pass to dump the profile information for + /// a module. + // + // FIXME: This should move elsewhere. + class ProfileInfoPrinterPass : public ModulePass { + ProfileInfoLoader &PIL; + public: + static char ID; // Class identification, replacement for typeinfo. + explicit ProfileInfoPrinterPass(ProfileInfoLoader &_PIL) + : ModulePass(ID), PIL(_PIL) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + bool runOnModule(Module &M); + }; +} + +char ProfileInfoPrinterPass::ID = 0; + +bool ProfileInfoPrinterPass::runOnModule(Module &M) { + ProfileInfo &PI = getAnalysis(); + std::map FuncFreqs; + std::map BlockFreqs; + std::map EdgeFreqs; + + // Output a report. Eventually, there will be multiple reports selectable on + // the command line, for now, just keep things simple. + + // Emit the most frequent function table... + std::vector > FunctionCounts; + std::vector > Counts; + for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) { + if (FI->isDeclaration()) continue; + double w = ignoreMissing(PI.getExecutionCount(FI)); + FunctionCounts.push_back(std::make_pair(FI, w)); + for (Function::iterator BB = FI->begin(), BBE = FI->end(); + BB != BBE; ++BB) { + double w = ignoreMissing(PI.getExecutionCount(BB)); + Counts.push_back(std::make_pair(BB, w)); + } + } + + // Sort by the frequency, backwards. + sort(FunctionCounts.begin(), FunctionCounts.end(), + PairSecondSortReverse()); + + double TotalExecutions = 0; + for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) + TotalExecutions += FunctionCounts[i].second; + + outs() << "===" << std::string(73, '-') << "===\n" + << "LLVM profiling output for execution"; + if (PIL.getNumExecutions() != 1) outs() << "s"; + outs() << ":\n"; + + for (unsigned i = 0, e = PIL.getNumExecutions(); i != e; ++i) { + outs() << " "; + if (e != 1) outs() << i+1 << ". "; + outs() << PIL.getExecution(i) << "\n"; + } + + outs() << "\n===" << std::string(73, '-') << "===\n"; + outs() << "Function execution frequencies:\n\n"; + + // Print out the function frequencies... + outs() << " ## Frequency\n"; + for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) { + if (FunctionCounts[i].second == 0) { + outs() << "\n NOTE: " << e-i << " function" + << (e-i-1 ? "s were" : " was") << " never executed!\n"; + break; + } + + outs() << format("%3d", i+1) << ". " + << format("%5.2g", FunctionCounts[i].second) << "/" + << format("%g", TotalExecutions) << " " + << FunctionCounts[i].first->getNameStr() << "\n"; + } + + std::set FunctionsToPrint; + + TotalExecutions = 0; + for (unsigned i = 0, e = Counts.size(); i != e; ++i) + TotalExecutions += Counts[i].second; + + // Sort by the frequency, backwards. + sort(Counts.begin(), Counts.end(), + PairSecondSortReverse()); + + outs() << "\n===" << std::string(73, '-') << "===\n"; + outs() << "Top 20 most frequently executed basic blocks:\n\n"; + + // Print out the function frequencies... + outs() <<" ## %% \tFrequency\n"; + unsigned BlocksToPrint = Counts.size(); + if (BlocksToPrint > 20) BlocksToPrint = 20; + for (unsigned i = 0; i != BlocksToPrint; ++i) { + if (Counts[i].second == 0) break; + Function *F = Counts[i].first->getParent(); + outs() << format("%3d", i+1) << ". " + << format("%5g", Counts[i].second/(double)TotalExecutions*100) << "% " + << format("%5.0f", Counts[i].second) << "/" + << format("%g", TotalExecutions) << "\t" + << F->getNameStr() << "() - " + << Counts[i].first->getNameStr() << "\n"; + FunctionsToPrint.insert(F); + } + + if (PrintAnnotatedLLVM || PrintAllCode) { + outs() << "\n===" << std::string(73, '-') << "===\n"; + outs() << "Annotated LLVM code for the module:\n\n"; + + ProfileAnnotator PA(PI); + + if (FunctionsToPrint.empty() || PrintAllCode) + M.print(outs(), &PA); + else + // Print just a subset of the functions. + for (std::set::iterator I = FunctionsToPrint.begin(), + E = FunctionsToPrint.end(); I != E; ++I) + (*I)->print(outs(), &PA); + } + + return false; +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + cl::ParseCommandLineOptions(argc, argv, "llvm profile dump decoder\n"); + + // Read in the bitcode file... + std::string ErrorMessage; + OwningPtr Buffer; + error_code ec; + Module *M = 0; + if (!(ec = MemoryBuffer::getFileOrSTDIN(BitcodeFile, Buffer))) { + M = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage); + } else + ErrorMessage = ec.message(); + if (M == 0) { + errs() << argv[0] << ": " << BitcodeFile << ": " + << ErrorMessage << "\n"; + return 1; + } + + // Read the profiling information. This is redundant since we load it again + // using the standard profile info provider pass, but for now this gives us + // access to additional information not exposed via the ProfileInfo + // interface. + ProfileInfoLoader PIL(argv[0], ProfileDataFile, *M); + + // Run the printer pass. + PassManager PassMgr; + PassMgr.add(createProfileLoaderPass(ProfileDataFile)); + PassMgr.add(new ProfileInfoPrinterPass(PIL)); + PassMgr.run(*M); + + return 0; +} diff --git a/contrib/llvm/tools/llvm-ranlib/CMakeLists.txt b/contrib/llvm/tools/llvm-ranlib/CMakeLists.txt new file mode 100644 index 000000000000..3116d2e4ff79 --- /dev/null +++ b/contrib/llvm/tools/llvm-ranlib/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS archive) +set(LLVM_REQUIRES_EH 1) + +add_llvm_tool(llvm-ranlib + llvm-ranlib.cpp + ) diff --git a/contrib/llvm/tools/llvm-ranlib/Makefile b/contrib/llvm/tools/llvm-ranlib/Makefile new file mode 100644 index 000000000000..46a10e644662 --- /dev/null +++ b/contrib/llvm/tools/llvm-ranlib/Makefile @@ -0,0 +1,18 @@ +##===- tools/llvm-ranlib/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = llvm-ranlib +LINK_COMPONENTS = archive +REQUIRES_EH := 1 + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/llvm-ranlib/llvm-ranlib.cpp b/contrib/llvm/tools/llvm-ranlib/llvm-ranlib.cpp new file mode 100644 index 000000000000..64f795f7f63d --- /dev/null +++ b/contrib/llvm/tools/llvm-ranlib/llvm-ranlib.cpp @@ -0,0 +1,101 @@ +//===-- llvm-ranlib.cpp - LLVM archive index generator --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Adds or updates an index (symbol table) for an LLVM archive file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Bitcode/Archive.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Signals.h" +#include +using namespace llvm; + +// llvm-ar operation code and modifier flags +static cl::opt +ArchiveName(cl::Positional, cl::Optional, cl::desc("")); + +static cl::opt +Verbose("verbose",cl::Optional,cl::init(false), + cl::desc("Print the symbol table")); + +// printSymbolTable - print out the archive's symbol table. +void printSymbolTable(Archive* TheArchive) { + outs() << "\nArchive Symbol Table:\n"; + const Archive::SymTabType& symtab = TheArchive->getSymbolTable(); + for (Archive::SymTabType::const_iterator I=symtab.begin(), E=symtab.end(); + I != E; ++I ) { + unsigned offset = TheArchive->getFirstFileOffset() + I->second; + outs() << " " << format("%9u", offset) << "\t" << I->first <<"\n"; + } +} + +int main(int argc, char **argv) { + // Print a stack trace if we signal out. + llvm::sys::PrintStackTraceOnErrorSignal(); + llvm::PrettyStackTraceProgram X(argc, argv); + + LLVMContext &Context = getGlobalContext(); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Have the command line options parsed and handle things + // like --help and --version. + cl::ParseCommandLineOptions(argc, argv, + "LLVM Archive Index Generator (llvm-ranlib)\n\n" + " This program adds or updates an index of bitcode symbols\n" + " to an LLVM archive file." + ); + + int exitCode = 0; + + // Make sure we don't exit with "unhandled exception". + try { + + // Check the path name of the archive + sys::Path ArchivePath; + if (!ArchivePath.set(ArchiveName)) + throw std::string("Archive name invalid: ") + ArchiveName; + + // Make sure it exists, we don't create empty archives + bool Exists; + if (llvm::sys::fs::exists(ArchivePath.str(), Exists) || !Exists) + throw std::string("Archive file does not exist"); + + std::string err_msg; + std::auto_ptr + AutoArchive(Archive::OpenAndLoad(ArchivePath, Context, &err_msg)); + Archive* TheArchive = AutoArchive.get(); + if (!TheArchive) + throw err_msg; + + if (TheArchive->writeToDisk(true, false, false, &err_msg )) + throw err_msg; + + if (Verbose) + printSymbolTable(TheArchive); + + } catch (const char* msg) { + errs() << argv[0] << ": " << msg << "\n\n"; + exitCode = 1; + } catch (const std::string& msg) { + errs() << argv[0] << ": " << msg << "\n"; + exitCode = 2; + } catch (...) { + errs() << argv[0] << ": An unexpected unknown exception occurred.\n"; + exitCode = 3; + } + return exitCode; +} diff --git a/contrib/llvm/tools/llvm-rtdyld/CMakeLists.txt b/contrib/llvm/tools/llvm-rtdyld/CMakeLists.txt new file mode 100644 index 000000000000..17e2c3e2d5bd --- /dev/null +++ b/contrib/llvm/tools/llvm-rtdyld/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT) + +add_llvm_tool(llvm-rtdyld + llvm-rtdyld.cpp + ) diff --git a/contrib/llvm/tools/llvm-rtdyld/Makefile b/contrib/llvm/tools/llvm-rtdyld/Makefile new file mode 100644 index 000000000000..0d57277f08d8 --- /dev/null +++ b/contrib/llvm/tools/llvm-rtdyld/Makefile @@ -0,0 +1,23 @@ +##===- tools/llvm-rtdyld/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = llvm-rtdyld + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +# Include this here so we can get the configuration of the targets +# that have been configured for construction. We have to do this +# early so we can set up LINK_COMPONENTS before including Makefile.rules +include $(LEVEL)/Makefile.config + +LINK_COMPONENTS := $(TARGETS_TO_BUILD) support MC object RuntimeDyld JIT + +include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp new file mode 100644 index 000000000000..ec9d6526ece1 --- /dev/null +++ b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -0,0 +1,151 @@ +//===-- llvm-rtdyld.cpp - MCJIT Testing Tool ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a testing tool for use with the MC-JIT LLVM components. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/Object/MachOObject.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +using namespace llvm; +using namespace llvm::object; + +static cl::list +InputFileList(cl::Positional, cl::ZeroOrMore, + cl::desc("")); + +enum ActionType { + AC_Execute +}; + +static cl::opt +Action(cl::desc("Action to perform:"), + cl::init(AC_Execute), + cl::values(clEnumValN(AC_Execute, "execute", + "Load, link, and execute the inputs."), + clEnumValEnd)); + +static cl::opt +EntryPoint("entry", + cl::desc("Function to call as entry point."), + cl::init("_main")); + +/* *** */ + +// A trivial memory manager that doesn't do anything fancy, just uses the +// support library allocation routines directly. +class TrivialMemoryManager : public RTDyldMemoryManager { +public: + SmallVector FunctionMemory; + + uint8_t *startFunctionBody(const char *Name, uintptr_t &Size); + void endFunctionBody(const char *Name, uint8_t *FunctionStart, + uint8_t *FunctionEnd); +}; + +uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name, + uintptr_t &Size) { + return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); +} + +void TrivialMemoryManager::endFunctionBody(const char *Name, + uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + uintptr_t Size = FunctionEnd - FunctionStart + 1; + FunctionMemory.push_back(sys::MemoryBlock(FunctionStart, Size)); +} + +static const char *ProgramName; + +static void Message(const char *Type, const Twine &Msg) { + errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; +} + +static int Error(const Twine &Msg) { + Message("error", Msg); + return 1; +} + +/* *** */ + +static int executeInput() { + // Instantiate a dynamic linker. + TrivialMemoryManager *MemMgr = new TrivialMemoryManager; + RuntimeDyld Dyld(MemMgr); + + // If we don't have any input files, read from stdin. + if (!InputFileList.size()) + InputFileList.push_back("-"); + for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { + // Load the input memory buffer. + OwningPtr InputBuffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], + InputBuffer)) + return Error("unable to read input: '" + ec.message() + "'"); + + // Load the object file into it. + if (Dyld.loadObject(InputBuffer.take())) { + return Error(Dyld.getErrorString()); + } + } + + // Resolve all the relocations we can. + Dyld.resolveRelocations(); + + // FIXME: Error out if there are unresolved relocations. + + // Get the address of the entry point (_main by default). + void *MainAddress = Dyld.getSymbolAddress(EntryPoint); + if (MainAddress == 0) + return Error("no definition for '" + EntryPoint + "'"); + + // Invalidate the instruction cache for each loaded function. + for (unsigned i = 0, e = MemMgr->FunctionMemory.size(); i != e; ++i) { + sys::MemoryBlock &Data = MemMgr->FunctionMemory[i]; + // Make sure the memory is executable. + std::string ErrorStr; + sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); + if (!sys::Memory::setExecutable(Data, &ErrorStr)) + return Error("unable to mark function executable: '" + ErrorStr + "'"); + } + + // Dispatch to _main(). + errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n"; + + int (*Main)(int, const char**) = + (int(*)(int,const char**)) uintptr_t(MainAddress); + const char **Argv = new const char*[2]; + // Use the name of the first input object module as argv[0] for the target. + Argv[0] = InputFileList[0].c_str(); + Argv[1] = 0; + return Main(1, Argv); +} + +int main(int argc, char **argv) { + ProgramName = argv[0]; + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n"); + + switch (Action) { + default: + case AC_Execute: + return executeInput(); + } + + return 0; +} diff --git a/contrib/llvm/tools/llvm-stub/CMakeLists.txt b/contrib/llvm/tools/llvm-stub/CMakeLists.txt new file mode 100644 index 000000000000..a98dc9ed49a9 --- /dev/null +++ b/contrib/llvm/tools/llvm-stub/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_tool(llvm-stub + llvm-stub.c + ) diff --git a/contrib/llvm/tools/llvm-stub/Makefile b/contrib/llvm/tools/llvm-stub/Makefile new file mode 100644 index 000000000000..7ffe14976bb5 --- /dev/null +++ b/contrib/llvm/tools/llvm-stub/Makefile @@ -0,0 +1,13 @@ +##===- tools/llvm-stub/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = llvm-stub +include $(LEVEL)/Makefile.common + diff --git a/contrib/llvm/tools/llvm-stub/llvm-stub.c b/contrib/llvm/tools/llvm-stub/llvm-stub.c new file mode 100644 index 000000000000..69cd6edbec57 --- /dev/null +++ b/contrib/llvm/tools/llvm-stub/llvm-stub.c @@ -0,0 +1,77 @@ +/*===- llvm-stub.c - Stub executable to run llvm bitcode files ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tool is used by the gccld program to enable transparent execution of +// bitcode files by the user. Specifically, gccld outputs two files when asked +// to compile a file: +// 1. It outputs the LLVM bitcode file to .bc +// 2. It outputs a stub executable that runs lli on .bc +// +// This allows the end user to just say ./ and have the JIT executed +// automatically. On unix, the stub executable emitted is actually a bourne +// shell script that does the forwarding. Windows does not like #!/bin/sh +// programs in .exe files, so we make it an actual program, defined here. +// +//===----------------------------------------------------------------------===*/ + +#include +#include +#include + +#include "llvm/Config/config.h" + +#if defined(HAVE_UNISTD_H) && !defined(_MSC_VER) +#include +#endif + +#ifdef _WIN32 +#include +#include +#endif + +int main(int argc, char** argv) { + const char *Interp = getenv("LLVMINTERP"); + const char **Args; + if (Interp == 0) Interp = "lli"; + + /* Set up the command line options to pass to the JIT. */ + Args = (const char**)malloc(sizeof(char*) * (argc+2)); + /* argv[0] is the JIT */ + Args[0] = Interp; + +#ifdef LLVM_ON_WIN32 + { + int len = strlen(argv[0]); + if (len < 4 || strcmp(argv[0] + len - 4, ".exe") != 0) { + /* .exe suffix is stripped off of argv[0] if the executable was run on the + * command line without one. Put it back on. + */ + argv[0] = strcat(strcpy((char*)malloc(len + 5), argv[0]), ".exe"); + } + } +#endif + + /* argv[1] is argv[0] + ".bc". */ + Args[1] = strcat(strcpy((char*)malloc(strlen(argv[0])+4), argv[0]), ".bc"); + + /* The rest of the args are as before. */ + memcpy((char **)Args+2, argv+1, sizeof(char*)*argc); + + /* Run the JIT. */ +#if !defined(_WIN32) || defined(__MINGW64__) + execvp(Interp, (char **)Args); /* POSIX execvp takes a char *const[]. */ +#else + execvp(Interp, Args); /* windows execvp takes a const char *const *. */ +#endif + /* if _execv returns, the JIT could not be started. */ + fprintf(stderr, "Could not execute the LLVM JIT. Either add 'lli' to your" + " path, or set the\ninterpreter you want to use in the LLVMINTERP " + "environment variable.\n"); + return 1; +} diff --git a/contrib/llvm/tools/macho-dump/CMakeLists.txt b/contrib/llvm/tools/macho-dump/CMakeLists.txt new file mode 100644 index 000000000000..d55e1d5c4139 --- /dev/null +++ b/contrib/llvm/tools/macho-dump/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support object) + +add_llvm_tool(macho-dump + macho-dump.cpp + ) diff --git a/contrib/llvm/tools/macho-dump/Makefile b/contrib/llvm/tools/macho-dump/Makefile new file mode 100644 index 000000000000..638015e9289a --- /dev/null +++ b/contrib/llvm/tools/macho-dump/Makefile @@ -0,0 +1,23 @@ +##===- tools/macho-dump/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = macho-dump + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +# Include this here so we can get the configuration of the targets +# that have been configured for construction. We have to do this +# early so we can set up LINK_COMPONENTS before including Makefile.rules +include $(LEVEL)/Makefile.config + +LINK_COMPONENTS := support object + +include $(LLVM_SRC_ROOT)/Makefile.rules diff --git a/contrib/llvm/tools/macho-dump/macho-dump.cpp b/contrib/llvm/tools/macho-dump/macho-dump.cpp new file mode 100644 index 000000000000..2b22c3b0fd91 --- /dev/null +++ b/contrib/llvm/tools/macho-dump/macho-dump.cpp @@ -0,0 +1,400 @@ +//===-- macho-dump.cpp - Mach Object Dumping Tool -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a testing tool for use with the MC/Mach-O LLVM components. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/MachOObject.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +using namespace llvm; +using namespace llvm::object; + +static cl::opt +InputFile(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +ShowSectionData("dump-section-data", cl::desc("Dump the contents of sections"), + cl::init(false)); + +/// + +static const char *ProgramName; + +static void Message(const char *Type, const Twine &Msg) { + errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; +} + +static int Error(const Twine &Msg) { + Message("error", Msg); + return 1; +} + +static void Warning(const Twine &Msg) { + Message("warning", Msg); +} + +/// + +static void DumpSegmentCommandData(StringRef Name, + uint64_t VMAddr, uint64_t VMSize, + uint64_t FileOffset, uint64_t FileSize, + uint32_t MaxProt, uint32_t InitProt, + uint32_t NumSections, uint32_t Flags) { + outs() << " ('segment_name', '"; + outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; + outs() << " ('vm_addr', " << VMAddr << ")\n"; + outs() << " ('vm_size', " << VMSize << ")\n"; + outs() << " ('file_offset', " << FileOffset << ")\n"; + outs() << " ('file_size', " << FileSize << ")\n"; + outs() << " ('maxprot', " << MaxProt << ")\n"; + outs() << " ('initprot', " << InitProt << ")\n"; + outs() << " ('num_sections', " << NumSections << ")\n"; + outs() << " ('flags', " << Flags << ")\n"; +} + +static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, + StringRef SegmentName, uint64_t Address, + uint64_t Size, uint32_t Offset, + uint32_t Align, uint32_t RelocationTableOffset, + uint32_t NumRelocationTableEntries, + uint32_t Flags, uint32_t Reserved1, + uint32_t Reserved2, uint64_t Reserved3 = ~0ULL) { + outs() << " # Section " << Index << "\n"; + outs() << " (('section_name', '"; + outs().write_escaped(Name, /*UseHexEscapes=*/true) << "')\n"; + outs() << " ('segment_name', '"; + outs().write_escaped(SegmentName, /*UseHexEscapes=*/true) << "')\n"; + outs() << " ('address', " << Address << ")\n"; + outs() << " ('size', " << Size << ")\n"; + outs() << " ('offset', " << Offset << ")\n"; + outs() << " ('alignment', " << Align << ")\n"; + outs() << " ('reloc_offset', " << RelocationTableOffset << ")\n"; + outs() << " ('num_reloc', " << NumRelocationTableEntries << ")\n"; + outs() << " ('flags', " << format("0x%x", Flags) << ")\n"; + outs() << " ('reserved1', " << Reserved1 << ")\n"; + outs() << " ('reserved2', " << Reserved2 << ")\n"; + if (Reserved3 != ~0ULL) + outs() << " ('reserved3', " << Reserved3 << ")\n"; + outs() << " ),\n"; + + // Dump the relocation entries. + int Res = 0; + outs() << " ('_relocations', [\n"; + for (unsigned i = 0; i != NumRelocationTableEntries; ++i) { + InMemoryStruct RE; + Obj.ReadRelocationEntry(RelocationTableOffset, i, RE); + if (!RE) { + Res = Error("unable to read relocation table entry '" + Twine(i) + "'"); + break; + } + + outs() << " # Relocation " << i << "\n"; + outs() << " (('word-0', " << format("0x%x", RE->Word0) << "),\n"; + outs() << " ('word-1', " << format("0x%x", RE->Word1) << ")),\n"; + } + outs() << " ])\n"; + + // Dump the section data, if requested. + if (ShowSectionData) { + outs() << " ('_section_data', '"; + StringRef Data = Obj.getData(Offset, Size); + for (unsigned i = 0; i != Data.size(); ++i) { + if (i && (i % 4) == 0) + outs() << ' '; + outs() << hexdigit((Data[i] >> 4) & 0xF, /*LowerCase=*/true); + outs() << hexdigit((Data[i] >> 0) & 0xF, /*LowerCase=*/true); + } + outs() << "')\n"; + } + + return Res; +} + +static int DumpSegmentCommand(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct SLC; + Obj.ReadSegmentLoadCommand(LCI, SLC); + if (!SLC) + return Error("unable to read segment load command"); + + DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, + SLC->VMSize, SLC->FileOffset, SLC->FileSize, + SLC->MaxVMProtection, SLC->InitialVMProtection, + SLC->NumSections, SLC->Flags); + + // Dump the sections. + int Res = 0; + outs() << " ('sections', [\n"; + for (unsigned i = 0; i != SLC->NumSections; ++i) { + InMemoryStruct Sect; + Obj.ReadSection(LCI, i, Sect); + if (!SLC) { + Res = Error("unable to read section '" + Twine(i) + "'"); + break; + } + + if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), + StringRef(Sect->SegmentName, 16), Sect->Address, + Sect->Size, Sect->Offset, Sect->Align, + Sect->RelocationTableOffset, + Sect->NumRelocationTableEntries, Sect->Flags, + Sect->Reserved1, Sect->Reserved2))) + break; + } + outs() << " ])\n"; + + return Res; +} + +static int DumpSegment64Command(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct SLC; + Obj.ReadSegment64LoadCommand(LCI, SLC); + if (!SLC) + return Error("unable to read segment load command"); + + DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, + SLC->VMSize, SLC->FileOffset, SLC->FileSize, + SLC->MaxVMProtection, SLC->InitialVMProtection, + SLC->NumSections, SLC->Flags); + + // Dump the sections. + int Res = 0; + outs() << " ('sections', [\n"; + for (unsigned i = 0; i != SLC->NumSections; ++i) { + InMemoryStruct Sect; + Obj.ReadSection64(LCI, i, Sect); + if (!SLC) { + Res = Error("unable to read section '" + Twine(i) + "'"); + break; + } + + if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), + StringRef(Sect->SegmentName, 16), Sect->Address, + Sect->Size, Sect->Offset, Sect->Align, + Sect->RelocationTableOffset, + Sect->NumRelocationTableEntries, Sect->Flags, + Sect->Reserved1, Sect->Reserved2, + Sect->Reserved3))) + break; + } + outs() << " ])\n"; + + return 0; +} + +static void DumpSymbolTableEntryData(MachOObject &Obj, + unsigned Index, uint32_t StringIndex, + uint8_t Type, uint8_t SectionIndex, + uint16_t Flags, uint64_t Value) { + outs() << " # Symbol " << Index << "\n"; + outs() << " (('n_strx', " << StringIndex << ")\n"; + outs() << " ('n_type', " << format("0x%x", Type) << ")\n"; + outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n"; + outs() << " ('n_desc', " << Flags << ")\n"; + outs() << " ('n_value', " << Value << ")\n"; + outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n"; + outs() << " ),\n"; +} + +static int DumpSymtabCommand(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct SLC; + Obj.ReadSymtabLoadCommand(LCI, SLC); + if (!SLC) + return Error("unable to read segment load command"); + + outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n"; + outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n"; + outs() << " ('stroff', " << SLC->StringTableOffset << ")\n"; + outs() << " ('strsize', " << SLC->StringTableSize << ")\n"; + + // Cache the string table data. + Obj.RegisterStringTable(*SLC); + + // Dump the string data. + outs() << " ('_string_data', '"; + outs().write_escaped(Obj.getStringTableData(), + /*UseHexEscapes=*/true) << "')\n"; + + // Dump the symbol table. + int Res = 0; + outs() << " ('_symbols', [\n"; + for (unsigned i = 0; i != SLC->NumSymbolTableEntries; ++i) { + if (Obj.is64Bit()) { + InMemoryStruct STE; + Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE); + if (!STE) { + Res = Error("unable to read symbol: '" + Twine(i) + "'"); + break; + } + + DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, + STE->SectionIndex, STE->Flags, STE->Value); + } else { + InMemoryStruct STE; + Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE); + if (!SLC) { + Res = Error("unable to read symbol: '" + Twine(i) + "'"); + break; + } + + DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, + STE->SectionIndex, STE->Flags, STE->Value); + } + } + outs() << " ])\n"; + + return Res; +} + +static int DumpDysymtabCommand(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct DLC; + Obj.ReadDysymtabLoadCommand(LCI, DLC); + if (!DLC) + return Error("unable to read segment load command"); + + outs() << " ('ilocalsym', " << DLC->LocalSymbolsIndex << ")\n"; + outs() << " ('nlocalsym', " << DLC->NumLocalSymbols << ")\n"; + outs() << " ('iextdefsym', " << DLC->ExternalSymbolsIndex << ")\n"; + outs() << " ('nextdefsym', " << DLC->NumExternalSymbols << ")\n"; + outs() << " ('iundefsym', " << DLC->UndefinedSymbolsIndex << ")\n"; + outs() << " ('nundefsym', " << DLC->NumUndefinedSymbols << ")\n"; + outs() << " ('tocoff', " << DLC->TOCOffset << ")\n"; + outs() << " ('ntoc', " << DLC->NumTOCEntries << ")\n"; + outs() << " ('modtaboff', " << DLC->ModuleTableOffset << ")\n"; + outs() << " ('nmodtab', " << DLC->NumModuleTableEntries << ")\n"; + outs() << " ('extrefsymoff', " << DLC->ReferenceSymbolTableOffset << ")\n"; + outs() << " ('nextrefsyms', " + << DLC->NumReferencedSymbolTableEntries << ")\n"; + outs() << " ('indirectsymoff', " << DLC->IndirectSymbolTableOffset << ")\n"; + outs() << " ('nindirectsyms', " + << DLC->NumIndirectSymbolTableEntries << ")\n"; + outs() << " ('extreloff', " << DLC->ExternalRelocationTableOffset << ")\n"; + outs() << " ('nextrel', " << DLC->NumExternalRelocationTableEntries << ")\n"; + outs() << " ('locreloff', " << DLC->LocalRelocationTableOffset << ")\n"; + outs() << " ('nlocrel', " << DLC->NumLocalRelocationTableEntries << ")\n"; + + // Dump the indirect symbol table. + int Res = 0; + outs() << " ('_indirect_symbols', [\n"; + for (unsigned i = 0; i != DLC->NumIndirectSymbolTableEntries; ++i) { + InMemoryStruct ISTE; + Obj.ReadIndirectSymbolTableEntry(*DLC, i, ISTE); + if (!ISTE) { + Res = Error("unable to read segment load command"); + break; + } + + outs() << " # Indirect Symbol " << i << "\n"; + outs() << " (('symbol_index', " + << format("0x%x", ISTE->Index) << "),),\n"; + } + outs() << " ])\n"; + + return Res; +} + +static int DumpLinkeditDataCommand(MachOObject &Obj, + const MachOObject::LoadCommandInfo &LCI) { + InMemoryStruct LLC; + Obj.ReadLinkeditDataLoadCommand(LCI, LLC); + if (!LLC) + return Error("unable to read segment load command"); + + outs() << " ('dataoff', " << LLC->DataOffset << ")\n" + << " ('datasize', " << LLC->DataSize << ")\n" + << " ('_addresses', [\n"; + + SmallVector Addresses; + Obj.ReadULEB128s(LLC->DataOffset, Addresses); + for (unsigned i = 0, e = Addresses.size(); i != e; ++i) + outs() << " # Address " << i << '\n' + << " ('address', " << format("0x%x", Addresses[i]) << "),\n"; + + outs() << " ])\n"; + + return 0; +} + + +static int DumpLoadCommand(MachOObject &Obj, unsigned Index) { + const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index); + int Res = 0; + + outs() << " # Load Command " << Index << "\n" + << " (('command', " << LCI.Command.Type << ")\n" + << " ('size', " << LCI.Command.Size << ")\n"; + switch (LCI.Command.Type) { + case macho::LCT_Segment: + Res = DumpSegmentCommand(Obj, LCI); + break; + case macho::LCT_Segment64: + Res = DumpSegment64Command(Obj, LCI); + break; + case macho::LCT_Symtab: + Res = DumpSymtabCommand(Obj, LCI); + break; + case macho::LCT_Dysymtab: + Res = DumpDysymtabCommand(Obj, LCI); + break; + case macho::LCT_CodeSignature: + case macho::LCT_SegmentSplitInfo: + case macho::LCT_FunctionStarts: + Res = DumpLinkeditDataCommand(Obj, LCI); + break; + default: + Warning("unknown load command: " + Twine(LCI.Command.Type)); + break; + } + outs() << " ),\n"; + + return Res; +} + +int main(int argc, char **argv) { + ProgramName = argv[0]; + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n"); + + // Load the input file. + std::string ErrorStr; + OwningPtr InputBuffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer)) + return Error("unable to read input: '" + ec.message() + "'"); + + // Construct the Mach-O wrapper object. + OwningPtr InputObject( + MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr)); + if (!InputObject) + return Error("unable to load object: '" + ErrorStr + "'"); + + // Print the header + InputObject->printHeader(outs()); + + // Print the load commands. + int Res = 0; + outs() << "('load_commands', [\n"; + for (unsigned i = 0; i != InputObject->getHeader().NumLoadCommands; ++i) + if ((Res = DumpLoadCommand(*InputObject, i))) + break; + outs() << "])\n"; + + return Res; +} diff --git a/contrib/llvm/tools/opt/AnalysisWrappers.cpp b/contrib/llvm/tools/opt/AnalysisWrappers.cpp new file mode 100644 index 000000000000..a2b57bb3e115 --- /dev/null +++ b/contrib/llvm/tools/opt/AnalysisWrappers.cpp @@ -0,0 +1,94 @@ +//===- AnalysisWrappers.cpp - Wrappers around non-pass analyses -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines pass wrappers around LLVM analyses that don't make sense to +// be passes. It provides a nice standard pass interface to these classes so +// that they can be printed out by analyze. +// +// These classes are separated out of analyze.cpp so that it is more clear which +// code is the integral part of the analyze tool, and which part of the code is +// just making it so more passes are available. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + /// ExternalFunctionsPassedConstants - This pass prints out call sites to + /// external functions that are called with constant arguments. This can be + /// useful when looking for standard library functions we should constant fold + /// or handle in alias analyses. + struct ExternalFunctionsPassedConstants : public ModulePass { + static char ID; // Pass ID, replacement for typeid + ExternalFunctionsPassedConstants() : ModulePass(ID) {} + virtual bool runOnModule(Module &M) { + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + if (!I->isDeclaration()) continue; + + bool PrintedFn = false; + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + Instruction *User = dyn_cast(*UI); + if (!User) continue; + + CallSite CS(cast(User)); + if (!CS) continue; + + for (CallSite::arg_iterator AI = CS.arg_begin(), + E = CS.arg_end(); AI != E; ++AI) { + if (!isa(*AI)) continue; + + if (!PrintedFn) { + errs() << "Function '" << I->getName() << "':\n"; + PrintedFn = true; + } + errs() << *User; + break; + } + } + } + + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char ExternalFunctionsPassedConstants::ID = 0; +static RegisterPass + P1("print-externalfnconstants", + "Print external fn callsites passed constants"); + +namespace { + struct CallGraphPrinter : public ModulePass { + static char ID; // Pass ID, replacement for typeid + CallGraphPrinter() : ModulePass(ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + } + virtual bool runOnModule(Module &M) { + getAnalysis().print(errs(), &M); + return false; + } + }; +} + +char CallGraphPrinter::ID = 0; +static RegisterPass + P2("print-callgraph", "Print a call graph"); diff --git a/contrib/llvm/tools/opt/CMakeLists.txt b/contrib/llvm/tools/opt/CMakeLists.txt new file mode 100644 index 000000000000..0570d0e04af7 --- /dev/null +++ b/contrib/llvm/tools/opt/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_LINK_COMPONENTS bitreader asmparser bitwriter instrumentation scalaropts ipo) + +add_llvm_tool(opt + AnalysisWrappers.cpp + GraphPrinters.cpp + PrintSCC.cpp + opt.cpp + ) diff --git a/contrib/llvm/tools/opt/GraphPrinters.cpp b/contrib/llvm/tools/opt/GraphPrinters.cpp new file mode 100644 index 000000000000..30361f501cda --- /dev/null +++ b/contrib/llvm/tools/opt/GraphPrinters.cpp @@ -0,0 +1,118 @@ +//===- GraphPrinters.cpp - DOT printers for various graph types -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines several printers for various different types of graphs used +// by the LLVM infrastructure. It uses the generic graph interface to convert +// the graph into a .dot graph. These graphs can then be processed with the +// "dot" tool to convert them to postscript or some other suitable format. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/GraphWriter.h" +#include "llvm/Pass.h" +#include "llvm/Value.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Support/ToolOutputFile.h" +using namespace llvm; + +template +static void WriteGraphToFile(raw_ostream &O, const std::string &GraphName, + const GraphType >) { + std::string Filename = GraphName + ".dot"; + O << "Writing '" << Filename << "'..."; + std::string ErrInfo; + tool_output_file F(Filename.c_str(), ErrInfo); + + if (ErrInfo.empty()) { + WriteGraph(F.os(), GT); + F.os().close(); + if (!F.os().has_error()) { + O << "\n"; + F.keep(); + return; + } + } + O << " error opening file for writing!\n"; + F.os().clear_error(); +} + + +//===----------------------------------------------------------------------===// +// Call Graph Printer +//===----------------------------------------------------------------------===// + +namespace llvm { + template<> + struct DOTGraphTraits : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + + static std::string getGraphName(CallGraph *F) { + return "Call Graph"; + } + + static std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) { + if (Node->getFunction()) + return ((Value*)Node->getFunction())->getName(); + return "external node"; + } + }; +} + + +namespace { + struct CallGraphPrinter : public ModulePass { + static char ID; // Pass ID, replacement for typeid + CallGraphPrinter() : ModulePass(ID) {} + + virtual bool runOnModule(Module &M) { + WriteGraphToFile(llvm::errs(), "callgraph", &getAnalysis()); + return false; + } + + void print(raw_ostream &OS, const llvm::Module*) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); + } + }; +} + +char CallGraphPrinter::ID = 0; +static RegisterPass P2("dot-callgraph", + "Print Call Graph to 'dot' file"); + +//===----------------------------------------------------------------------===// +// DomInfoPrinter Pass +//===----------------------------------------------------------------------===// + +namespace { + class DomInfoPrinter : public FunctionPass { + public: + static char ID; // Pass identification, replacement for typeid + DomInfoPrinter() : FunctionPass(ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + + } + + virtual bool runOnFunction(Function &F) { + getAnalysis().dump(); + return false; + } + }; +} + +char DomInfoPrinter::ID = 0; +static RegisterPass +DIP("print-dom-info", "Dominator Info Printer", true, true); diff --git a/contrib/llvm/tools/opt/Makefile b/contrib/llvm/tools/opt/Makefile new file mode 100644 index 000000000000..726cad87123f --- /dev/null +++ b/contrib/llvm/tools/opt/Makefile @@ -0,0 +1,14 @@ +##===- tools/opt/Makefile ----------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. +TOOLNAME = opt + +LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/tools/opt/PrintSCC.cpp b/contrib/llvm/tools/opt/PrintSCC.cpp new file mode 100644 index 000000000000..533f49ec2a87 --- /dev/null +++ b/contrib/llvm/tools/opt/PrintSCC.cpp @@ -0,0 +1,112 @@ +//===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides passes to print out SCCs in a CFG or a CallGraph. +// Normally, you would not use these passes; instead, you would use the +// scc_iterator directly to enumerate SCCs and process them in some way. These +// passes serve three purposes: +// +// (1) As a reference for how to use the scc_iterator. +// (2) To print out the SCCs for a CFG or a CallGraph: +// analyze -print-cfg-sccs to print the SCCs in each CFG of a module. +// analyze -print-cfg-sccs -stats to print the #SCCs and the maximum SCC size. +// analyze -print-cfg-sccs -debug > /dev/null to watch the algorithm in action. +// +// and similarly: +// analyze -print-callgraph-sccs [-stats] [-debug] to print SCCs in the CallGraph +// +// (3) To test the scc_iterator. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SCCIterator.h" +using namespace llvm; + +namespace { + struct CFGSCC : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + CFGSCC() : FunctionPass(ID) {} + bool runOnFunction(Function& func); + + void print(raw_ostream &O, const Module* = 0) const { } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; + + struct CallGraphSCC : public ModulePass { + static char ID; // Pass identification, replacement for typeid + CallGraphSCC() : ModulePass(ID) {} + + // run - Print out SCCs in the call graph for the specified module. + bool runOnModule(Module &M); + + void print(raw_ostream &O, const Module* = 0) const { } + + // getAnalysisUsage - This pass requires the CallGraph. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + }; +} + +char CFGSCC::ID = 0; +static RegisterPass +Y("print-cfg-sccs", "Print SCCs of each function CFG"); + +char CallGraphSCC::ID = 0; +static RegisterPass +Z("print-callgraph-sccs", "Print SCCs of the Call Graph"); + +bool CFGSCC::runOnFunction(Function &F) { + unsigned sccNum = 0; + errs() << "SCCs for Function " << F.getName() << " in PostOrder:"; + for (scc_iterator SCCI = scc_begin(&F), + E = scc_end(&F); SCCI != E; ++SCCI) { + std::vector &nextSCC = *SCCI; + errs() << "\nSCC #" << ++sccNum << " : "; + for (std::vector::const_iterator I = nextSCC.begin(), + E = nextSCC.end(); I != E; ++I) + errs() << (*I)->getName() << ", "; + if (nextSCC.size() == 1 && SCCI.hasLoop()) + errs() << " (Has self-loop)."; + } + errs() << "\n"; + + return true; +} + + +// run - Print out SCCs in the call graph for the specified module. +bool CallGraphSCC::runOnModule(Module &M) { + CallGraphNode* rootNode = getAnalysis().getRoot(); + unsigned sccNum = 0; + errs() << "SCCs for the program in PostOrder:"; + for (scc_iterator SCCI = scc_begin(rootNode), + E = scc_end(rootNode); SCCI != E; ++SCCI) { + const std::vector &nextSCC = *SCCI; + errs() << "\nSCC #" << ++sccNum << " : "; + for (std::vector::const_iterator I = nextSCC.begin(), + E = nextSCC.end(); I != E; ++I) + errs() << ((*I)->getFunction() ? (*I)->getFunction()->getNameStr() + : std::string("external node")) << ", "; + if (nextSCC.size() == 1 && SCCI.hasLoop()) + errs() << " (Has self-loop)."; + } + errs() << "\n"; + + return true; +} diff --git a/contrib/llvm/tools/opt/opt.cpp b/contrib/llvm/tools/opt/opt.cpp new file mode 100644 index 000000000000..ffd2c21736e5 --- /dev/null +++ b/contrib/llvm/tools/opt/opt.cpp @@ -0,0 +1,713 @@ +//===- opt.cpp - The LLVM Modular Optimizer -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Optimizations may be specified an arbitrary number of times on the command +// line, They are run in the order specified. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/CallGraphSCCPass.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/RegionPass.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLibraryInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/PassNameParser.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/IRReader.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/LinkAllPasses.h" +#include "llvm/LinkAllVMCore.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include +#include +using namespace llvm; + +// The OptimizationList is automatically populated with registered Passes by the +// PassNameParser. +// +static cl::list +PassList(cl::desc("Optimizations available:")); + +// Other command line options... +// +static cl::opt +InputFilename(cl::Positional, cl::desc(""), + cl::init("-"), cl::value_desc("filename")); + +static cl::opt +OutputFilename("o", cl::desc("Override output filename"), + cl::value_desc("filename")); + +static cl::opt +Force("f", cl::desc("Enable binary output on terminals")); + +static cl::opt +PrintEachXForm("p", cl::desc("Print module after each transformation")); + +static cl::opt +NoOutput("disable-output", + cl::desc("Do not write result bitcode file"), cl::Hidden); + +static cl::opt +OutputAssembly("S", cl::desc("Write output as LLVM assembly")); + +static cl::opt +NoVerify("disable-verify", cl::desc("Do not verify result module"), cl::Hidden); + +static cl::opt +VerifyEach("verify-each", cl::desc("Verify after each transform")); + +static cl::opt +StripDebug("strip-debug", + cl::desc("Strip debugger symbol info from translation unit")); + +static cl::opt +DisableInline("disable-inlining", cl::desc("Do not run the inliner pass")); + +static cl::opt +DisableOptimizations("disable-opt", + cl::desc("Do not run any optimization passes")); + +static cl::opt +DisableInternalize("disable-internalize", + cl::desc("Do not mark all symbols as internal")); + +static cl::opt +StandardCompileOpts("std-compile-opts", + cl::desc("Include the standard compile time optimizations")); + +static cl::opt +StandardLinkOpts("std-link-opts", + cl::desc("Include the standard link time optimizations")); + +static cl::opt +OptLevelO1("O1", + cl::desc("Optimization level 1. Similar to llvm-gcc -O1")); + +static cl::opt +OptLevelO2("O2", + cl::desc("Optimization level 2. Similar to llvm-gcc -O2")); + +static cl::opt +OptLevelO3("O3", + cl::desc("Optimization level 3. Similar to llvm-gcc -O3")); + +static cl::opt +UnitAtATime("funit-at-a-time", + cl::desc("Enable IPO. This is same as llvm-gcc's -funit-at-a-time"), + cl::init(true)); + +static cl::opt +DisableSimplifyLibCalls("disable-simplify-libcalls", + cl::desc("Disable simplify-libcalls")); + +static cl::opt +Quiet("q", cl::desc("Obsolete option"), cl::Hidden); + +static cl::alias +QuietA("quiet", cl::desc("Alias for -q"), cl::aliasopt(Quiet)); + +static cl::opt +AnalyzeOnly("analyze", cl::desc("Only perform analysis, no optimization")); + +static cl::opt +PrintBreakpoints("print-breakpoints-for-testing", + cl::desc("Print select breakpoints location for testing")); + +static cl::opt +DefaultDataLayout("default-data-layout", + cl::desc("data layout string to use if not specified by module"), + cl::value_desc("layout-string"), cl::init("")); + +// ---------- Define Printers for module and function passes ------------ +namespace { + +struct CallGraphSCCPassPrinter : public CallGraphSCCPass { + static char ID; + const PassInfo *PassToPrint; + raw_ostream &Out; + std::string PassName; + + CallGraphSCCPassPrinter(const PassInfo *PI, raw_ostream &out) : + CallGraphSCCPass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "CallGraphSCCPass Printer: " + PassToPrintName; + } + + virtual bool runOnSCC(CallGraphSCC &SCC) { + if (!Quiet) + Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n"; + + // Get and print pass... + for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { + Function *F = (*I)->getFunction(); + if (F) + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, + F->getParent()); + } + return false; + } + + virtual const char *getPassName() const { return PassName.c_str(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(PassToPrint->getTypeInfo()); + AU.setPreservesAll(); + } +}; + +char CallGraphSCCPassPrinter::ID = 0; + +struct ModulePassPrinter : public ModulePass { + static char ID; + const PassInfo *PassToPrint; + raw_ostream &Out; + std::string PassName; + + ModulePassPrinter(const PassInfo *PI, raw_ostream &out) + : ModulePass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "ModulePass Printer: " + PassToPrintName; + } + + virtual bool runOnModule(Module &M) { + if (!Quiet) + Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n"; + + // Get and print pass... + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, &M); + return false; + } + + virtual const char *getPassName() const { return PassName.c_str(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(PassToPrint->getTypeInfo()); + AU.setPreservesAll(); + } +}; + +char ModulePassPrinter::ID = 0; +struct FunctionPassPrinter : public FunctionPass { + const PassInfo *PassToPrint; + raw_ostream &Out; + static char ID; + std::string PassName; + + FunctionPassPrinter(const PassInfo *PI, raw_ostream &out) + : FunctionPass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "FunctionPass Printer: " + PassToPrintName; + } + + virtual bool runOnFunction(Function &F) { + if (!Quiet) + Out << "Printing analysis '" << PassToPrint->getPassName() + << "' for function '" << F.getName() << "':\n"; + + // Get and print pass... + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, + F.getParent()); + return false; + } + + virtual const char *getPassName() const { return PassName.c_str(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(PassToPrint->getTypeInfo()); + AU.setPreservesAll(); + } +}; + +char FunctionPassPrinter::ID = 0; + +struct LoopPassPrinter : public LoopPass { + static char ID; + const PassInfo *PassToPrint; + raw_ostream &Out; + std::string PassName; + + LoopPassPrinter(const PassInfo *PI, raw_ostream &out) : + LoopPass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "LoopPass Printer: " + PassToPrintName; + } + + + virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { + if (!Quiet) + Out << "Printing analysis '" << PassToPrint->getPassName() << "':\n"; + + // Get and print pass... + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, + L->getHeader()->getParent()->getParent()); + return false; + } + + virtual const char *getPassName() const { return PassName.c_str(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(PassToPrint->getTypeInfo()); + AU.setPreservesAll(); + } +}; + +char LoopPassPrinter::ID = 0; + +struct RegionPassPrinter : public RegionPass { + static char ID; + const PassInfo *PassToPrint; + raw_ostream &Out; + std::string PassName; + + RegionPassPrinter(const PassInfo *PI, raw_ostream &out) : RegionPass(ID), + PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "RegionPass Printer: " + PassToPrintName; + } + + virtual bool runOnRegion(Region *R, RGPassManager &RGM) { + if (!Quiet) { + Out << "Printing analysis '" << PassToPrint->getPassName() << "' for " + << "region: '" << R->getNameStr() << "' in function '" + << R->getEntry()->getParent()->getNameStr() << "':\n"; + } + // Get and print pass... + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, + R->getEntry()->getParent()->getParent()); + return false; + } + + virtual const char *getPassName() const { return PassName.c_str(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(PassToPrint->getTypeInfo()); + AU.setPreservesAll(); + } +}; + +char RegionPassPrinter::ID = 0; + +struct BasicBlockPassPrinter : public BasicBlockPass { + const PassInfo *PassToPrint; + raw_ostream &Out; + static char ID; + std::string PassName; + + BasicBlockPassPrinter(const PassInfo *PI, raw_ostream &out) + : BasicBlockPass(ID), PassToPrint(PI), Out(out) { + std::string PassToPrintName = PassToPrint->getPassName(); + PassName = "BasicBlockPass Printer: " + PassToPrintName; + } + + virtual bool runOnBasicBlock(BasicBlock &BB) { + if (!Quiet) + Out << "Printing Analysis info for BasicBlock '" << BB.getName() + << "': Pass " << PassToPrint->getPassName() << ":\n"; + + // Get and print pass... + getAnalysisID(PassToPrint->getTypeInfo()).print(Out, + BB.getParent()->getParent()); + return false; + } + + virtual const char *getPassName() const { return PassName.c_str(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(PassToPrint->getTypeInfo()); + AU.setPreservesAll(); + } +}; + +char BasicBlockPassPrinter::ID = 0; + +struct BreakpointPrinter : public ModulePass { + raw_ostream &Out; + static char ID; + + BreakpointPrinter(raw_ostream &out) + : ModulePass(ID), Out(out) { + } + + void getContextName(DIDescriptor Context, std::string &N) { + if (Context.isNameSpace()) { + DINameSpace NS(Context); + if (!NS.getName().empty()) { + getContextName(NS.getContext(), N); + N = N + NS.getName().str() + "::"; + } + } else if (Context.isType()) { + DIType TY(Context); + if (!TY.getName().empty()) { + getContextName(TY.getContext(), N); + N = N + TY.getName().str() + "::"; + } + } + } + + virtual bool runOnModule(Module &M) { + StringSet<> Processed; + if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + std::string Name; + DISubprogram SP(NMD->getOperand(i)); + if (SP.Verify()) + getContextName(SP.getContext(), Name); + Name = Name + SP.getDisplayName().str(); + if (!Name.empty() && Processed.insert(Name)) { + Out << Name << "\n"; + } + } + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +}; + +} // anonymous namespace + +char BreakpointPrinter::ID = 0; + +static inline void addPass(PassManagerBase &PM, Pass *P) { + // Add the pass to the pass manager... + PM.add(P); + + // If we are verifying all of the intermediate steps, add the verifier... + if (VerifyEach) PM.add(createVerifierPass()); +} + +/// AddOptimizationPasses - This routine adds optimization passes +/// based on selected optimization level, OptLevel. This routine +/// duplicates llvm-gcc behaviour. +/// +/// OptLevel - Optimization Level +static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM, + unsigned OptLevel) { + PassManagerBuilder Builder; + Builder.OptLevel = OptLevel; + + if (DisableInline) { + // No inlining pass + } else if (OptLevel > 1) { + unsigned Threshold = 225; + if (OptLevel > 2) + Threshold = 275; + Builder.Inliner = createFunctionInliningPass(Threshold); + } else { + Builder.Inliner = createAlwaysInlinerPass(); + } + Builder.DisableUnitAtATime = !UnitAtATime; + Builder.DisableUnrollLoops = OptLevel == 0; + Builder.DisableSimplifyLibCalls = DisableSimplifyLibCalls; + + Builder.populateFunctionPassManager(FPM); + Builder.populateModulePassManager(MPM); +} + +static void AddStandardCompilePasses(PassManagerBase &PM) { + PM.add(createVerifierPass()); // Verify that input is correct + + // If the -strip-debug command line option was specified, do it. + if (StripDebug) + addPass(PM, createStripSymbolsPass(true)); + + if (DisableOptimizations) return; + + // -std-compile-opts adds the same module passes as -O3. + PassManagerBuilder Builder; + if (!DisableInline) + Builder.Inliner = createFunctionInliningPass(); + Builder.OptLevel = 3; + Builder.DisableSimplifyLibCalls = DisableSimplifyLibCalls; + Builder.populateModulePassManager(PM); +} + +static void AddStandardLinkPasses(PassManagerBase &PM) { + PM.add(createVerifierPass()); // Verify that input is correct + + // If the -strip-debug command line option was specified, do it. + if (StripDebug) + addPass(PM, createStripSymbolsPass(true)); + + if (DisableOptimizations) return; + + PassManagerBuilder Builder; + Builder.populateLTOPassManager(PM, /*Internalize=*/ !DisableInternalize, + /*RunInliner=*/ !DisableInline); +} + + +//===----------------------------------------------------------------------===// +// main for opt +// +int main(int argc, char **argv) { + sys::PrintStackTraceOnErrorSignal(); + llvm::PrettyStackTraceProgram X(argc, argv); + + // Enable debug stream buffering. + EnableDebugBuffering = true; + + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + LLVMContext &Context = getGlobalContext(); + + // Initialize passes + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeScalarOpts(Registry); + initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + initializeInstrumentation(Registry); + initializeTarget(Registry); + + cl::ParseCommandLineOptions(argc, argv, + "llvm .bc -> .bc modular optimizer and analysis printer\n"); + + if (AnalyzeOnly && NoOutput) { + errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; + return 1; + } + + // Allocate a full target machine description only if necessary. + // FIXME: The choice of target should be controllable on the command line. + std::auto_ptr target; + + SMDiagnostic Err; + + // Load the input module... + std::auto_ptr M; + M.reset(ParseIRFile(InputFilename, Err, Context)); + + if (M.get() == 0) { + Err.Print(argv[0], errs()); + return 1; + } + + // Figure out what stream we are supposed to write to... + OwningPtr Out; + if (NoOutput) { + if (!OutputFilename.empty()) + errs() << "WARNING: The -o (output filename) option is ignored when\n" + "the --disable-output option is used.\n"; + } else { + // Default to standard output. + if (OutputFilename.empty()) + OutputFilename = "-"; + + std::string ErrorInfo; + Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary)); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << '\n'; + return 1; + } + } + + // If the output is set to be emitted to standard out, and standard out is a + // console, print out a warning message and refuse to do it. We don't + // impress anyone by spewing tons of binary goo to a terminal. + if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) + if (CheckBitcodeOutputToConsole(Out->os(), !Quiet)) + NoOutput = true; + + // Create a PassManager to hold and optimize the collection of passes we are + // about to build. + // + PassManager Passes; + + // Add an appropriate TargetLibraryInfo pass for the module's triple. + TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple())); + + // The -disable-simplify-libcalls flag actually disables all builtin optzns. + if (DisableSimplifyLibCalls) + TLI->disableAllFunctions(); + Passes.add(TLI); + + // Add an appropriate TargetData instance for this module. + TargetData *TD = 0; + const std::string &ModuleDataLayout = M.get()->getDataLayout(); + if (!ModuleDataLayout.empty()) + TD = new TargetData(ModuleDataLayout); + else if (!DefaultDataLayout.empty()) + TD = new TargetData(DefaultDataLayout); + + if (TD) + Passes.add(TD); + + OwningPtr FPasses; + if (OptLevelO1 || OptLevelO2 || OptLevelO3) { + FPasses.reset(new FunctionPassManager(M.get())); + if (TD) + FPasses->add(new TargetData(*TD)); + } + + if (PrintBreakpoints) { + // Default to standard output. + if (!Out) { + if (OutputFilename.empty()) + OutputFilename = "-"; + + std::string ErrorInfo; + Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, + raw_fd_ostream::F_Binary)); + if (!ErrorInfo.empty()) { + errs() << ErrorInfo << '\n'; + return 1; + } + } + Passes.add(new BreakpointPrinter(Out->os())); + NoOutput = true; + } + + // If the -strip-debug command line option was specified, add it. If + // -std-compile-opts was also specified, it will handle StripDebug. + if (StripDebug && !StandardCompileOpts) + addPass(Passes, createStripSymbolsPass(true)); + + // Create a new optimization pass for each one specified on the command line + for (unsigned i = 0; i < PassList.size(); ++i) { + // Check to see if -std-compile-opts was specified before this option. If + // so, handle it. + if (StandardCompileOpts && + StandardCompileOpts.getPosition() < PassList.getPosition(i)) { + AddStandardCompilePasses(Passes); + StandardCompileOpts = false; + } + + if (StandardLinkOpts && + StandardLinkOpts.getPosition() < PassList.getPosition(i)) { + AddStandardLinkPasses(Passes); + StandardLinkOpts = false; + } + + if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { + AddOptimizationPasses(Passes, *FPasses, 1); + OptLevelO1 = false; + } + + if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { + AddOptimizationPasses(Passes, *FPasses, 2); + OptLevelO2 = false; + } + + if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { + AddOptimizationPasses(Passes, *FPasses, 3); + OptLevelO3 = false; + } + + const PassInfo *PassInf = PassList[i]; + Pass *P = 0; + if (PassInf->getNormalCtor()) + P = PassInf->getNormalCtor()(); + else + errs() << argv[0] << ": cannot create pass: " + << PassInf->getPassName() << "\n"; + if (P) { + PassKind Kind = P->getPassKind(); + addPass(Passes, P); + + if (AnalyzeOnly) { + switch (Kind) { + case PT_BasicBlock: + Passes.add(new BasicBlockPassPrinter(PassInf, Out->os())); + break; + case PT_Region: + Passes.add(new RegionPassPrinter(PassInf, Out->os())); + break; + case PT_Loop: + Passes.add(new LoopPassPrinter(PassInf, Out->os())); + break; + case PT_Function: + Passes.add(new FunctionPassPrinter(PassInf, Out->os())); + break; + case PT_CallGraphSCC: + Passes.add(new CallGraphSCCPassPrinter(PassInf, Out->os())); + break; + default: + Passes.add(new ModulePassPrinter(PassInf, Out->os())); + break; + } + } + } + + if (PrintEachXForm) + Passes.add(createPrintModulePass(&errs())); + } + + // If -std-compile-opts was specified at the end of the pass list, add them. + if (StandardCompileOpts) { + AddStandardCompilePasses(Passes); + StandardCompileOpts = false; + } + + if (StandardLinkOpts) { + AddStandardLinkPasses(Passes); + StandardLinkOpts = false; + } + + if (OptLevelO1) + AddOptimizationPasses(Passes, *FPasses, 1); + + if (OptLevelO2) + AddOptimizationPasses(Passes, *FPasses, 2); + + if (OptLevelO3) + AddOptimizationPasses(Passes, *FPasses, 3); + + if (OptLevelO1 || OptLevelO2 || OptLevelO3) { + FPasses->doInitialization(); + for (Module::iterator F = M->begin(), E = M->end(); F != E; ++F) + FPasses->run(*F); + FPasses->doFinalization(); + } + + // Check that the module is well formed on completion of optimization + if (!NoVerify && !VerifyEach) + Passes.add(createVerifierPass()); + + // Write bitcode or assembly to the output as the last step... + if (!NoOutput && !AnalyzeOnly) { + if (OutputAssembly) + Passes.add(createPrintModulePass(&Out->os())); + else + Passes.add(createBitcodeWriterPass(Out->os())); + } + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + // Now that we have all of the passes ready, run them. + Passes.run(*M.get()); + + // Declare success. + if (!NoOutput || PrintBreakpoints) + Out->keep(); + + return 0; +} diff --git a/crypto/openssh/auth2.c b/crypto/openssh/auth2.c index 2dc9122fb51f..55238cdcf9aa 100644 --- a/crypto/openssh/auth2.c +++ b/crypto/openssh/auth2.c @@ -223,8 +223,8 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) login_cap_t *lc; const char *from_host, *from_ip; - from_host = get_canonical_hostname(options.use_dns); - from_ip = get_remote_ipaddr(); + from_host = get_canonical_hostname(options.use_dns); + from_ip = get_remote_ipaddr(); #endif if (authctxt == NULL) @@ -272,23 +272,23 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) } #ifdef HAVE_LOGIN_CAP - if (authctxt->pw != NULL) { - lc = login_getpwclass(authctxt->pw); - if (lc == NULL) - lc = login_getclassbyname(NULL, authctxt->pw); - if (!auth_hostok(lc, from_host, from_ip)) { - logit("Denied connection for %.200s from %.200s [%.200s].", - authctxt->pw->pw_name, from_host, from_ip); - packet_disconnect("Sorry, you are not allowed to connect."); - } - if (!auth_timeok(lc, time(NULL))) { - logit("LOGIN %.200s REFUSED (TIME) FROM %.200s", - authctxt->pw->pw_name, from_host); - packet_disconnect("Logins not available right now."); - } - login_close(lc); - lc = NULL; - } + if (authctxt->pw != NULL) { + lc = login_getpwclass(authctxt->pw); + if (lc == NULL) + lc = login_getclassbyname(NULL, authctxt->pw); + if (!auth_hostok(lc, from_host, from_ip)) { + logit("Denied connection for %.200s from %.200s [%.200s].", + authctxt->pw->pw_name, from_host, from_ip); + packet_disconnect("Sorry, you are not allowed to connect."); + } + if (!auth_timeok(lc, time(NULL))) { + logit("LOGIN %.200s REFUSED (TIME) FROM %.200s", + authctxt->pw->pw_name, from_host); + packet_disconnect("Logins not available right now."); + } + login_close(lc); + lc = NULL; + } #endif /* HAVE_LOGIN_CAP */ /* reset state */ diff --git a/crypto/openssh/channels.c b/crypto/openssh/channels.c index 4cff8f2098cb..2242579fd08e 100644 --- a/crypto/openssh/channels.c +++ b/crypto/openssh/channels.c @@ -824,7 +824,7 @@ channel_tcpwinsz(void) u_int maxlen; /* If we are not on a socket return 128KB. */ - if (!packet_connection_is_on_socket()) + if (!packet_connection_is_on_socket()) return (128 * 1024); tcpwinsz = 0; @@ -854,7 +854,7 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) limit = MIN(compat20 ? c->remote_window : packet_get_maxsize(), 2 * c->tcpwinsz); - + if (c->istate == CHAN_INPUT_OPEN && limit > 0 && buffer_len(&c->input) < limit && @@ -2687,10 +2687,10 @@ channel_set_af(int af) IPv4or6 = af; } -void +void channel_set_hpn(int disabled, u_int buf_size) { - hpn_disabled = disabled; + hpn_disabled = disabled; buffer_size = buf_size; debug("HPN Disabled: %d, HPN Buffer Size: %d", hpn_disabled, buffer_size); @@ -2856,10 +2856,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr, c = channel_new("port listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "port listener", 1); - else - c = channel_new("port listener", type, sock, sock, -1, - buffer_size, CHAN_TCP_PACKET_DEFAULT, - 0, "port listener", 1); + else + c = channel_new("port listener", type, sock, sock, -1, + buffer_size, CHAN_TCP_PACKET_DEFAULT, + 0, "port listener", 1); c->path = xstrdup(host); c->host_port = port_to_connect; c->listening_port = listen_port; diff --git a/crypto/openssh/channels.h b/crypto/openssh/channels.h index 6ee993ad8948..c469720b7187 100644 --- a/crypto/openssh/channels.h +++ b/crypto/openssh/channels.h @@ -126,7 +126,7 @@ struct Channel { u_int local_window_max; u_int local_consumed; u_int local_maxpacket; - u_int tcpwinsz; + u_int tcpwinsz; int dynamic_window; int extended_usage; int single_connection; @@ -165,13 +165,10 @@ struct Channel { /* default window/packet sizes for tcp/x11-fwd-channel */ #define CHAN_SES_PACKET_DEFAULT (32*1024) #define CHAN_SES_WINDOW_DEFAULT (64*CHAN_SES_PACKET_DEFAULT) - #define CHAN_TCP_PACKET_DEFAULT (32*1024) #define CHAN_TCP_WINDOW_DEFAULT (64*CHAN_TCP_PACKET_DEFAULT) - #define CHAN_X11_PACKET_DEFAULT (16*1024) #define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) - #define CHAN_HPN_MIN_WINDOW_DEFAULT (2*1024*1024) /* possible input states */ @@ -302,6 +299,7 @@ void chan_write_failed(Channel *); void chan_obuf_empty(Channel *); /* hpn handler */ -void channel_set_hpn(int, u_int); + +void channel_set_hpn(int, u_int); #endif diff --git a/crypto/openssh/kex.c b/crypto/openssh/kex.c index ca3c4206a106..0e8d5c75b2ac 100644 --- a/crypto/openssh/kex.c +++ b/crypto/openssh/kex.c @@ -457,13 +457,13 @@ kex_choose_conf(Kex *kex) #ifdef NONE_CIPHER_ENABLED debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); if (strcmp(newkeys->enc.name, "none") == 0) { - debug("Requesting NONE. Authflag is %d", auth_flag); + debug("Requesting NONE. Authflag is %d", auth_flag); if (auth_flag == 1) debug("None requested post authentication."); else fatal("Pre-authentication none cipher requests " "are not allowed."); - } + } #endif debug("kex: %s %s %s %s", ctos ? "client->server" : "server->client", diff --git a/crypto/openssh/loginrec.c b/crypto/openssh/loginrec.c index 0d0e807b6377..32941c985ea4 100644 --- a/crypto/openssh/loginrec.c +++ b/crypto/openssh/loginrec.c @@ -146,7 +146,6 @@ */ #include "includes.h" -__RCSID("$FreeBSD$"); #include #include @@ -516,10 +515,6 @@ getlast_entry(struct logininfo *li) return (utmpx_get_entry(li)); #endif -#if 1 - return (utmpx_get_entry(li)); -#endif - #if defined(DISABLE_LASTLOG) /* On some systems we shouldn't even try to obtain last login * time, e.g. AIX */ diff --git a/crypto/openssh/readconf.c b/crypto/openssh/readconf.c index c6c3354d2775..35fa2d4ca7c1 100644 --- a/crypto/openssh/readconf.c +++ b/crypto/openssh/readconf.c @@ -264,6 +264,7 @@ static struct { { "noneswitch", oNoneSwitch }, #endif { "versionaddendum", oVersionAddendum }, + { NULL, oBadOption } }; @@ -1092,9 +1093,9 @@ process_config_line(Options *options, const char *host, case oNoneEnabled: intptr = &options->none_enabled; goto parse_flag; - + /* - * We check to see if the command comes from the command line or not. + * We check to see if the command comes from the command line or not. * If it does then enable it otherwise fail. NONE must never be a * default configuration. */ @@ -1110,7 +1111,7 @@ process_config_line(Options *options, const char *host, "from the command line", filename); error("Continuing..."); return 0; - } + } #endif case oVersionAddendum: @@ -1458,7 +1459,7 @@ fill_default_options(Options * options) /* options->host_key_alias should not be set by default */ /* options->preferred_authentications will be set in ssh */ if (options->hpn_disabled == -1) - options->hpn_disabled = 0; + options->hpn_disabled = 0; if (options->hpn_buffer_size > -1) { u_int maxlen; @@ -1478,7 +1479,7 @@ fill_default_options(Options * options) } if (options->tcp_rcv_buf == 0) options->tcp_rcv_buf = 1; - if (options->tcp_rcv_buf > -1) + if (options->tcp_rcv_buf > -1) options->tcp_rcv_buf *= 1024; if (options->tcp_rcv_buf_poll == -1) options->tcp_rcv_buf_poll = 1; diff --git a/crypto/openssh/readconf.h b/crypto/openssh/readconf.h index af89bb484ea0..afa5bebe3735 100644 --- a/crypto/openssh/readconf.h +++ b/crypto/openssh/readconf.h @@ -133,6 +133,7 @@ typedef struct { int visual_host_key; int use_roaming; + int request_tty; int hpn_disabled; /* Switch to disable HPN buffer management. */ diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index 1d88bbf8b9e6..0b7395b61721 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -166,7 +166,7 @@ fill_default_server_options(ServerOptions *options) _PATH_HOST_KEY_FILE; if (options->protocol & SSH_PROTO_2) { options->host_key_files[options->num_host_key_files++] = - _PATH_HOST_RSA_KEY_FILE; + _PATH_HOST_RSA_KEY_FILE; options->host_key_files[options->num_host_key_files++] = _PATH_HOST_DSA_KEY_FILE; #ifdef OPENSSL_HAS_ECC @@ -286,7 +286,7 @@ fill_default_server_options(ServerOptions *options) options->ip_qos_interactive = IPTOS_LOWDELAY; if (options->ip_qos_bulk == -1) options->ip_qos_bulk = IPTOS_THROUGHPUT; - if (options->hpn_disabled == -1) + if (options->hpn_disabled == -1) options->hpn_disabled = 0; if (options->hpn_buffer_size == -1) { /* diff --git a/crypto/openssh/sftp.1 b/crypto/openssh/sftp.1 index 389c8e8ee520..e703bbf9c6ff 100644 --- a/crypto/openssh/sftp.1 +++ b/crypto/openssh/sftp.1 @@ -246,7 +246,7 @@ diagnostic messages from Specify how many requests may be outstanding at any one time. Increasing this may slightly improve file transfer speed but will increase memory usage. -The default is 256 outstanding requests providing for 8MB +The default is 256 outstanding requests providing for 8MB of outstanding data with a 32KB buffer. .It Fl r Recursively copy entire directories when uploading and downloading. diff --git a/crypto/openssh/ssh.c b/crypto/openssh/ssh.c index 7fdae3a71355..21fe19bf5dbe 100644 --- a/crypto/openssh/ssh.c +++ b/crypto/openssh/ssh.c @@ -1461,6 +1461,7 @@ ssh_session2_open(void) c->dynamic_window = 1; debug("Enabled Dynamic Window Scaling\n"); } + debug3("ssh_session2_open: channel_new: %d", c->self); channel_send_open(c->self); diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c index 070ef0c1750e..7851a6cfe3b6 100644 --- a/crypto/openssh/sshd.c +++ b/crypto/openssh/sshd.c @@ -1916,11 +1916,11 @@ main(int ac, char **av) #ifdef __FreeBSD__ /* * Initialize the resolver. This may not happen automatically - * before privsep chroot(). + * before privsep chroot(). */ if ((_res.options & RES_INIT) == 0) { - debug("res_init()"); - res_init(); + debug("res_init()"); + res_init(); } #ifdef GSSAPI /* diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index 894ad3a3275c..19c615e6cd6d 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -499,7 +499,7 @@ or .Pp .Pa /etc/hosts.equiv and -.Pa /etc/ssh/shosts.equiv +.Pa /etc/ssh/shosts.equiv are still used. The default is .Dq yes . diff --git a/crypto/openssh/version.h b/crypto/openssh/version.h index 3afcb715db5a..3eb10fc4ffc4 100644 --- a/crypto/openssh/version.h +++ b/crypto/openssh/version.h @@ -2,11 +2,11 @@ /* $FreeBSD$ */ #ifndef SSH_VERSION -#define SSH_VERSION_BASE "OpenSSH_5.9p1" -#define SSH_VERSION_ADDENDUM "FreeBSD-20111001" +#define SSH_VERSION_BASE "OpenSSH_5.9p1" +#define SSH_VERSION_ADDENDUM "FreeBSD-20111001" #define SSH_VERSION_HPN "_hpn13v11" #define SSH_VERSION SSH_VERSION_BASE SSH_VERSION_HPN " " SSH_VERSION_ADDENDUM -#define SSH_RELEASE (ssh_version_get()) +#define SSH_RELEASE (ssh_version_get()) const char *ssh_version_get(void); void ssh_version_set_addendum(const char *); diff --git a/etc/Makefile b/etc/Makefile index 42d695939d2d..0df9ec7affb8 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -7,18 +7,48 @@ SUBDIR= sendmail .endif -BIN1= auth.conf \ - crontab devd.conf devfs.conf \ - ddb.conf dhclient.conf disktab fbtab \ - ftpusers gettytab group \ - hosts hosts.allow hosts.equiv \ - inetd.conf libalias.conf login.access login.conf mac.conf motd \ - netconfig network.subr networks newsyslog.conf nsswitch.conf \ - phones profile protocols \ - rc rc.bsdextended rc.firewall rc.initdiskless \ - rc.sendmail rc.shutdown \ - rc.subr remote rpc services shells \ - sysctl.conf syslog.conf termcap.small +BIN1= auth.conf +BIN1+= crontab +BIN1+= devd.conf +BIN1+= devfs.conf +BIN1+= ddb.conf +BIN1+= dhclient.conf +BIN1+= disktab +BIN1+= fbtab +BIN1+= ftpusers +BIN1+= gettytab +BIN1+= group +BIN1+= hosts +BIN1+= hosts.allow +BIN1+= hosts.equiv +BIN1+= inetd.conf +BIN1+= libalias.conf +BIN1+= login.access +BIN1+= login.conf +BIN1+= mac.conf +BIN1+= motd +BIN1+= netconfig +BIN1+= network.subr +BIN1+= networks +BIN1+= newsyslog.conf +BIN1+= nsswitch.conf +BIN1+= phones +BIN1+= profile +BIN1+= protocols +BIN1+= rc +BIN1+= rc.bsdextended +BIN1+= rc.firewall +BIN1+= rc.initdiskless +BIN1+= rc.sendmail +BIN1+= rc.shutdown +BIN1+= rc.subr +BIN1+= remote +BIN1+= rpc +BIN1+= services +BIN1+= shells +BIN1+= sysctl.conf +BIN1+= syslog.conf +BIN1+= termcap.small .if exists(${.CURDIR}/etc.${MACHINE}/ttys) BIN1+= etc.${MACHINE}/ttys diff --git a/etc/defaults/periodic.conf b/etc/defaults/periodic.conf index 27192bc039e3..66fbcd37322f 100644 --- a/etc/defaults/periodic.conf +++ b/etc/defaults/periodic.conf @@ -96,6 +96,7 @@ daily_status_disks_df_flags="-l -h" # df(1) flags for check # 404.status-zfs daily_status_zfs_enable="NO" # Check ZFS +daily_status_zfs_zpool_list_enable="YES" # List ZFS pools # 405.status-ata_raid daily_status_ata_raid_enable="NO" # Check ATA raid status diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index b9e78ce0f11a..906151be115a 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -29,6 +29,8 @@ early_late_divider="FILESYSTEMS" # Script that separates early/late # stages of the boot process. Make sure you know # the ramifications if you change this. # See rc.conf(5) for more details. +always_force_depends="NO" # Set to check that indicated dependencies are + # running during boot (can increase boot time). swapfile="NO" # Set to name of swapfile if aux swapfile desired. apm_enable="NO" # Set to YES to enable APM BIOS functions (or NO). @@ -648,6 +650,7 @@ devfs_rulesets="/etc/defaults/devfs.rules /etc/devfs.rules" # Files containing devfs_system_ruleset="" # The name (NOT number) of a ruleset to apply to /dev devfs_set_rulesets="" # A list of /mount/dev=ruleset_name settings to # apply (must be mounted already, i.e. fstab(5)) +devfs_load_rulesets="NO" # Enable to always load the default rulesets performance_cx_lowest="HIGH" # Online CPU idle state performance_cpu_freq="NONE" # Online CPU frequency economy_cx_lowest="HIGH" # Offline CPU idle state diff --git a/etc/devd/usb.conf b/etc/devd/usb.conf index 22cb7ad0b3dd..e44f348e356f 100644 --- a/etc/devd/usb.conf +++ b/etc/devd/usb.conf @@ -157,7 +157,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0403"; - match "product" "(0x6001|0x6004|0x6010|0x6011|0x8372|0x9e90|0xcc48|0xcc49|0xcc4a|0xd678|0xe6c8|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xee18|0xf608|0xf60b|0xf850|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfc08|0xfc09|0xfc0b|0xfc0c|0xfc0d|0xfc82)"; + match "product" "(0x6001|0x6004|0x6010|0x6011|0x8372|0x9e90|0xa6d0|0xa6d0|0xcc48|0xcc49|0xcc4a|0xd678|0xe6c8|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xee18|0xf608|0xf60b|0xf850|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfc08|0xfc09|0xfc0b|0xfc0c|0xfc0d|0xfc82)"; action "kldload uftdi"; }; @@ -293,7 +293,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0411"; - match "product" "(0x0148|0x0150|0x015d|0x016f)"; + match "product" "(0x0148|0x0150|0x015d|0x016f|0x01a2)"; action "kldload if_run"; }; @@ -1021,7 +1021,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x05c6"; - match "product" "(0x6000|0x6613)"; + match "product" "(0x1000|0x6000|0x6613)"; action "kldload u3g"; }; @@ -1301,7 +1301,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0789"; - match "product" "(0x0162|0x0163|0x0164)"; + match "product" "(0x0162|0x0163|0x0164|0x0166)"; action "kldload if_run"; }; @@ -2093,7 +2093,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0b95"; - match "product" "(0x1720|0x1780|0x7720|0x772a|0x772b)"; + match "product" "(0x1720|0x1780|0x7720|0x772a|0x772b|0x7e2b)"; action "kldload if_axe"; }; @@ -4202,6 +4202,15 @@ nomatch 32 { action "kldload umodem"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x02"; + match "intsubclass" "0x02"; + match "intprotocol" "0xff"; + action "kldload umodem"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -4327,5 +4336,5 @@ nomatch 32 { action "kldload umass"; }; -# 1645 USB entries processed +# 1652 USB entries processed diff --git a/etc/periodic/daily/404.status-zfs b/etc/periodic/daily/404.status-zfs index 81cc3e4bbb38..df23bae7a37e 100755 --- a/etc/periodic/daily/404.status-zfs +++ b/etc/periodic/daily/404.status-zfs @@ -16,12 +16,21 @@ case "$daily_status_zfs_enable" in echo echo 'Checking status of zfs pools:' - out=`zpool status -x` - echo "$out" + case "$daily_status_zfs_zpool_list_enable" in + [Yy][Ee][Ss]) + lout=`zpool list` + echo "$lout" + echo + ;; + *) + ;; + esac + sout=`zpool status -x` + echo "$sout" # zpool status -x always exits with 0, so we have to interpret its # output to see what's going on. - if [ "$out" = "all pools are healthy" \ - -o "$out" = "no pools available" ]; then + if [ "$sout" = "all pools are healthy" \ + -o "$sout" = "no pools available" ]; then rc=0 else rc=1 diff --git a/etc/rc.d/LOGIN b/etc/rc.d/LOGIN index 2b45ba88a4b4..ad4c8a7dbfc7 100755 --- a/etc/rc.d/LOGIN +++ b/etc/rc.d/LOGIN @@ -4,7 +4,7 @@ # # PROVIDE: LOGIN -# REQUIRE: DAEMON +# REQUIRE: DAEMON utx # This is a dummy dependency to ensure user services such as xdm, # inetd, cron and kerberos are started after everything else, in case diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index a665ba9f8a88..460de6f40706 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -144,6 +144,7 @@ FILES= DAEMON \ tmp \ ${_ubthidhci} \ ugidfw \ + ${_utx} \ var \ virecover \ watchdogd \ @@ -177,6 +178,10 @@ _nscd= nscd _ubthidhci= ubthidhci .endif +.if ${MK_UTMPX} != "no" +_utx= utx +.endif + FILESDIR= /etc/rc.d FILESMODE= ${BINMODE} diff --git a/etc/rc.d/SERVERS b/etc/rc.d/SERVERS index 3398487cb84f..1cf019a056dd 100755 --- a/etc/rc.d/SERVERS +++ b/etc/rc.d/SERVERS @@ -4,7 +4,7 @@ # # PROVIDE: SERVERS -# REQUIRE: mountcritremote abi ldconfig savecore +# REQUIRE: mountcritremote abi ldconfig savecore watchdogd # This is a dummy dependency, for early-start servers relying on # some basic configuration. diff --git a/etc/rc.d/addswap b/etc/rc.d/addswap index 79bf1f1a1d95..78a45c556541 100755 --- a/etc/rc.d/addswap +++ b/etc/rc.d/addswap @@ -6,7 +6,7 @@ # # PROVIDE: addswap -# REQUIRE: FILESYSTEMS +# REQUIRE: FILESYSTEMS kld # KEYWORD: nojail . /etc/rc.subr diff --git a/etc/rc.d/amd b/etc/rc.d/amd index e313f0cd2490..2ed70ebfb106 100755 --- a/etc/rc.d/amd +++ b/etc/rc.d/amd @@ -19,15 +19,8 @@ extra_commands="reload" amd_precmd() { - if ! checkyesno nfs_client_enable; then - force_depend nfsclient || return 1 - fi - - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi + force_depend nfsclient nfs_client || return 1 + force_depend rpcbind || return 1 case ${amd_map_program} in [Nn][Oo] | '') @@ -49,7 +42,6 @@ amd_precmd() command_args="> /var/run/amd.pid 2> /dev/null" ;; esac - return 0 } load_rc_config $name diff --git a/etc/rc.d/apmd b/etc/rc.d/apmd index 2a326c18726f..beca9121172a 100755 --- a/etc/rc.d/apmd +++ b/etc/rc.d/apmd @@ -19,24 +19,18 @@ apmd_prestart() { case `${SYSCTL_N} hw.machine_arch` in i386) - # Enable apm if it is not already enabled - if ! checkyesno apm_enable && \ - ! /etc/rc.d/apm forcestatus 1>/dev/null 2>&1 - then - force_depend apm || return 1 - fi + force_depend apm || return 1 # Warn user about acpi apm compatibility support which # does not work with apmd. if [ ! -e /dev/apmctl ]; then - warn "/dev/apmctl not found; kernel is missing apm(4)" + warn "/dev/apmctl not found; kernel is missing apm(4)" fi ;; *) return 1 ;; esac - return 0 } load_rc_config $name diff --git a/etc/rc.d/cleanvar b/etc/rc.d/cleanvar index 62c8f42db70c..dade4a21bcc2 100755 --- a/etc/rc.d/cleanvar +++ b/etc/rc.d/cleanvar @@ -58,8 +58,6 @@ cleanvar_start () { if [ -d /var/run -a ! -f /var/run/clean_var ]; then purgedir /var/run - # And an initial utmpx active session file - (cd /var/run && cp /dev/null utx.active && chmod 644 utx.active) >/var/run/clean_var fi if [ -d /var/spool/lock -a ! -f /var/spool/lock/clean_var ]; then diff --git a/etc/rc.d/devfs b/etc/rc.d/devfs index 82278af53cf4..206a3eddaa27 100755 --- a/etc/rc.d/devfs +++ b/etc/rc.d/devfs @@ -16,7 +16,8 @@ stop_cmd=':' devfs_start() { - if [ -n "$devfs_system_ruleset" -o -n "$devfs_set_rulesets" ]; then + if [ -n "$devfs_system_ruleset" -o -n "$devfs_set_rulesets" ] || + checkyesno devfs_load_rulesets; then devfs_init_rulesets if [ -n "$devfs_system_ruleset" ]; then devfs_set_ruleset $devfs_system_ruleset /dev diff --git a/etc/rc.d/keyserv b/etc/rc.d/keyserv index 84b169a471ce..33c631a6df8b 100755 --- a/etc/rc.d/keyserv +++ b/etc/rc.d/keyserv @@ -19,13 +19,7 @@ start_precmd="keyserv_prestart" keyserv_prestart() { - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi - - return 0 + force_depend rpcbind || return 1 } load_rc_config $name diff --git a/etc/rc.d/lockd b/etc/rc.d/lockd index 135dda75dcb4..970477378a40 100755 --- a/etc/rc.d/lockd +++ b/etc/rc.d/lockd @@ -15,28 +15,16 @@ name="lockd" rcvar=rpc_lockd_enable command="/usr/sbin/rpc.${name}" start_precmd='lockd_precmd' -stop_precmd='checkyesno nfs_server_enable || checkyesno nfs_client_enable' -status_precmd=$stop_precmd # Make sure that we are either an NFS client or server, and that we get # the correct flags from rc.conf(5). # lockd_precmd() { - local ret - ret=0 - - if ! checkyesno nfs_server_enable && ! checkyesno nfs_client_enable - then - ret=1 - fi - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || ret=1 - fi + force_depend rpcbind || return 1 + force_depend statd rpc_statd || return 1 + rc_flags=${rpc_lockd_flags} - return ${ret} } load_rc_config $name diff --git a/etc/rc.d/mountd b/etc/rc.d/mountd index 826a15885c49..f3ebfdb5b86e 100755 --- a/etc/rc.d/mountd +++ b/etc/rc.d/mountd @@ -19,11 +19,7 @@ extra_commands="reload" mountd_precmd() { - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi + force_depend rpcbind || return 1 # mountd flags will differ depending on rc.conf settings # @@ -48,8 +44,8 @@ mountd_precmd() fi rm -f /var/db/mountdtab - ( umask 022 ; > /var/db/mountdtab ) - return 0 + ( umask 022 ; > /var/db/mountdtab ) || + err 1 'Cannot create /var/db/mountdtab' } load_rc_config $name diff --git a/etc/rc.d/nfsd b/etc/rc.d/nfsd index 235a8660651c..e067ad1ec779 100755 --- a/etc/rc.d/nfsd +++ b/etc/rc.d/nfsd @@ -48,31 +48,15 @@ nfsd_precmd() if checkyesno nfsv4_server_enable; then sysctl vfs.nfsd.server_max_nfsvers=4 > /dev/null - if ! checkyesno nfsuserd_enable && \ - ! /etc/rc.d/nfsuserd forcestatus 1>/dev/null 2>&1 - then - if ! force_depend nfsuserd; then - err 1 "Cannot run nfsuserd" - fi - fi + force_depend nfsuserd || err 1 "Cannot run nfsuserd" else echo 'NFSv4 is disabled' sysctl vfs.nfsd.server_max_nfsvers=3 > /dev/null fi fi - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi - - if ! checkyesno mountd_enable && \ - ! /etc/rc.d/mountd forcestatus 1>/dev/null 2>&1 - then - force_depend mountd || return 1 - fi - return 0 + force_depend rpcbind || return 1 + force_depend mountd || return 1 } run_rc_command "$1" diff --git a/etc/rc.d/routing b/etc/rc.d/routing index f86fd3a54f54..5903accff150 100755 --- a/etc/rc.d/routing +++ b/etc/rc.d/routing @@ -98,8 +98,10 @@ routing_stop_inet6() local i route -n flush -inet6 - for i in ${ipv6_network_interfaces}; do - ifconfig $i inet6 -defaultif + for i in `list_net_interfaces`; do + if ipv6if $i; then + ifconfig $i inet6 -defaultif + fi done } diff --git a/etc/rc.d/statd b/etc/rc.d/statd index 4e4a0a4cac3e..511983082a4b 100755 --- a/etc/rc.d/statd +++ b/etc/rc.d/statd @@ -15,28 +15,15 @@ name="statd" rcvar=rpc_statd_enable command="/usr/sbin/rpc.${name}" start_precmd='statd_precmd' -stop_precmd='checkyesno nfs_server_enable || checkyesno nfs_client_enable' -status_precmd=$stop_precmd # Make sure that we are either an NFS client or server, and that we get # the correct flags from rc.conf(5). # statd_precmd() { - local ret - ret=0 - - if ! checkyesno nfs_server_enable && ! checkyesno nfs_client_enable - then - ret=1 - fi - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || ret=1 - fi + force_depend rpcbind || return 1 + rc_flags=${rpc_statd_flags} - return ${ret} } load_rc_config $name diff --git a/etc/rc.d/utx b/etc/rc.d/utx new file mode 100755 index 000000000000..e23ae008eb8f --- /dev/null +++ b/etc/rc.d/utx @@ -0,0 +1,17 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: utx +# REQUIRE: DAEMON cleanvar +# KEYWORD: shutdown + +. /etc/rc.subr + +name="utx" +start_cmd="utx boot" +stop_cmd="utx shutdown" + +load_rc_config $name +run_rc_command "$1" diff --git a/etc/rc.d/var b/etc/rc.d/var index 0655658bd967..2b4121985eff 100755 --- a/etc/rc.d/var +++ b/etc/rc.d/var @@ -28,7 +28,7 @@ # # PROVIDE: var -# REQUIRE: FILESYSTEMS kld +# REQUIRE: FILESYSTEMS kld addswap . /etc/rc.subr diff --git a/etc/rc.d/watchdogd b/etc/rc.d/watchdogd index 043e5bc0274b..d3c0d9c4d15d 100755 --- a/etc/rc.d/watchdogd +++ b/etc/rc.d/watchdogd @@ -28,7 +28,7 @@ # # PROVIDE: watchdogd -# REQUIRE: DAEMON cleanvar +# REQUIRE: FILESYSTEMS cleanvar syslogd # KEYWORD: nojail shutdown . /etc/rc.subr diff --git a/etc/rc.d/ypbind b/etc/rc.d/ypbind index 4dbf3519f390..71aea92c8033 100755 --- a/etc/rc.d/ypbind +++ b/etc/rc.d/ypbind @@ -11,22 +11,20 @@ . /etc/rc.subr name="ypbind" -command="/usr/sbin/${name}" -start_precmd="ypbind_precmd" +rcvar="nis_client_enable" load_rc_config $name -rcvar="nis_client_enable" + +command="/usr/sbin/${name}" command_args="${nis_client_flags}" +start_precmd="ypbind_precmd" + ypbind_precmd() { local _domain - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi + force_depend rpcbind || return 1 _domain=`domainname` if [ -z "$_domain" ]; then diff --git a/etc/rc.d/yppasswdd b/etc/rc.d/yppasswdd index fbb80bcf443a..cc25d9f6b1e0 100755 --- a/etc/rc.d/yppasswdd +++ b/etc/rc.d/yppasswdd @@ -11,27 +11,22 @@ . /etc/rc.subr name="yppasswdd" -command="/usr/sbin/rpc.${name}" -start_precmd="yppasswdd_precmd" +rcvar="nis_yppasswdd_enable" load_rc_config $name -rcvar="nis_yppasswdd_enable" + +command="/usr/sbin/rpc.${name}" command_args="${nis_yppasswdd_flags}" +start_precmd="yppasswdd_precmd" + yppasswdd_precmd() { local _domain - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi - if ! checkyesno nis_server_enable && \ - ! /etc/rc.d/ypserv forcestatus 1>/dev/null 2>&1 - then - force_depend ypserv || return 1 - fi + force_depend rpcbind || return 1 + force_depend ypserv nis_server || return 1 + _domain=`domainname` if [ -z "$_domain" ]; then warn "NIS domainname(1) is not set." diff --git a/etc/rc.d/ypserv b/etc/rc.d/ypserv index 8e17fd77398b..90e70614717f 100755 --- a/etc/rc.d/ypserv +++ b/etc/rc.d/ypserv @@ -11,21 +11,20 @@ name="ypserv" rcvar="nis_server_enable" -command="/usr/sbin/${name}" -start_precmd="ypserv_prestart" load_rc_config $name + +command="/usr/sbin/${name}" command_args="${nis_server_flags}" +start_precmd="ypserv_prestart" + ypserv_prestart() { local _domain - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi + force_depend rpcbind || return 1 + _domain=`domainname` if [ -z "$_domain" ]; then warn "NIS domainname(1) is not set." diff --git a/etc/rc.d/ypset b/etc/rc.d/ypset index 78c408bde8dd..f725545ac563 100755 --- a/etc/rc.d/ypset +++ b/etc/rc.d/ypset @@ -11,25 +11,20 @@ name="ypset" rcvar="nis_ypset_enable" -command="/usr/sbin/${name}" -start_precmd="ypset_precmd" + load_rc_config $name + +command="/usr/sbin/${name}" command_args="${nis_ypset_flags}" +start_precmd="ypset_precmd" + ypset_precmd() { local _domain - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi - if ! checkyesno nis_client_enable && \ - ! /etc/rc.d/ypbind forcestatus 1>/dev/null 2>&1 - then - force_depend ypbind || return 1 - fi + force_depend rpcbind || return 1 + force_depend ypbind nis_client || return 1 _domain=`domainname` if [ -z "$_domain" ]; then diff --git a/etc/rc.d/ypupdated b/etc/rc.d/ypupdated index 98ef2038565f..4098bd773c3e 100755 --- a/etc/rc.d/ypupdated +++ b/etc/rc.d/ypupdated @@ -11,6 +11,9 @@ name="ypupdated" rcvar="rpc_ypupdated_enable" + +load_rc_config $name + command="/usr/sbin/rpc.${name}" start_precmd="rpc_ypupdated_precmd" @@ -18,16 +21,8 @@ rpc_ypupdated_precmd() { local _domain - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi - if ! checkyesno nis_server_enable && \ - ! /etc/rc.d/ypserv forcestatus 1>/dev/null 2>&1 - then - force_depend ypserv || return 1 - fi + force_depend rpcbind || return 1 + force_depend ypserv nis_server || return 1 _domain=`domainname` if [ -z "$_domain" ]; then @@ -36,5 +31,4 @@ rpc_ypupdated_precmd() fi } -load_rc_config $name run_rc_command "$1" diff --git a/etc/rc.d/ypxfrd b/etc/rc.d/ypxfrd index f125a30159db..63924e468f0f 100755 --- a/etc/rc.d/ypxfrd +++ b/etc/rc.d/ypxfrd @@ -11,25 +11,20 @@ name="ypxfrd" rcvar="nis_ypxfrd_enable" -command="/usr/sbin/rpc.${name}" -start_precmd="ypxfrd_precmd" + load_rc_config $name + +command="/usr/sbin/rpc.${name}" command_args="${nis_ypxfrd_flags}" +start_precmd="ypxfrd_precmd" + ypxfrd_precmd() { local _domain - if ! checkyesno rpcbind_enable && \ - ! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1 - then - force_depend rpcbind || return 1 - fi - if ! checkyesno nis_server_enable && \ - ! /etc/rc.d/ypserv forcestatus 1>/dev/null 2>&1 - then - force_depend ypserv || return 1 - fi + force_depend rpcbind || return 1 + force_depend ypserv nis_server || return 1 _domain=`domainname` if [ -z "$_domain" ]; then diff --git a/etc/rc.resume b/etc/rc.resume index 3b2e9706643c..b68f9819f64c 100755 --- a/etc/rc.resume +++ b/etc/rc.resume @@ -43,12 +43,6 @@ if [ -r /var/run/rc.suspend.pid ]; then echo 'rc.resume: killed rc.suspend that was still around' fi -if [ -r /var/run/rc.suspend.tch ]; then - _t=`cat /var/run/rc.suspend.tch` - /sbin/sysctl -n kern.timecounter.hardware=$_t > /dev/null 2>&1 - /bin/rm -f /var/run/rc.suspend.tch -fi - if [ -r /var/run/moused.pid ]; then pkill -HUP -F /var/run/moused.pid fi diff --git a/etc/rc.subr b/etc/rc.subr index 0da7c07a4083..e629bc7db82e 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -71,22 +71,29 @@ set_rcvar_obsolete() } # -# force_depend script +# force_depend script [rcvar] # Force a service to start. Intended for use by services -# to resolve dependency issues. It is assumed the caller -# has check to make sure this call is necessary +# to resolve dependency issues. # $1 - filename of script, in /etc/rc.d, to run +# $2 - name of the script's rcvar (minus the _enable) # force_depend() { + local _depend _dep_rcvar + _depend="$1" + _dep_rcvar="${2:-$1}_enable" + + [ -n "$rc_fast" ] && ! checkyesno always_force_depends && + checkyesno $_dep_rcvar && return 0 + + /etc/rc.d/${_depend} forcestatus >/dev/null 2>&1 && return 0 info "${name} depends on ${_depend}, which will be forced to start." if ! /etc/rc.d/${_depend} forcestart; then warn "Unable to force ${_depend}. It may already be running." return 1 fi - return 0 } # diff --git a/etc/rc.suspend b/etc/rc.suspend index 90c085b8acf2..5f22cd1a05b1 100755 --- a/etc/rc.suspend +++ b/etc/rc.suspend @@ -43,18 +43,6 @@ fi echo $$ 2> /dev/null > /var/run/rc.suspend.pid -_t=`/sbin/sysctl -n kern.timecounter.hardware 2> /dev/null` -case ${_t#ACPI-} in -fast|safe) - /bin/rm -f /var/run/rc.suspend.tch - ;; -*) - { /sbin/sysctl -n kern.timecounter.hardware=ACPI-fast || \ - /sbin/sysctl -n kern.timecounter.hardware=ACPI-safe; } \ - > /dev/null 2>&1 && echo $_t > /var/run/rc.suspend.tch - ;; -esac - # If you have troubles on suspending with PC-CARD modem, try this. # See also contrib/pccardq.c (Only for PAO users). # pccardq | awk -F '~' '$5 == "filled" && $4 ~ /uart/ \ diff --git a/gnu/usr.bin/cc/cc_tools/auto-host.h b/gnu/usr.bin/cc/cc_tools/auto-host.h index a6ce739b36fe..5d6ddc01205e 100644 --- a/gnu/usr.bin/cc/cc_tools/auto-host.h +++ b/gnu/usr.bin/cc/cc_tools/auto-host.h @@ -287,10 +287,8 @@ /* Define if your assembler supports thread-local storage. */ #ifndef USED_FOR_TARGET -#if !defined(__arm__) #define HAVE_AS_TLS 1 #endif -#endif /* Define to 1 if you have the `atoll' function. */ diff --git a/include/rpc/Makefile b/include/rpc/Makefile index 40d4c47b3a07..cf17ca2d4d62 100644 --- a/include/rpc/Makefile +++ b/include/rpc/Makefile @@ -3,7 +3,7 @@ .SUFFIXES: .x -RPCCOM = rpcgen -C +RPCCOM= RPCGEN_CPP=${CPP:Q} rpcgen -C HDRS= rpcb_prot.h diff --git a/include/rpc/svc.h b/include/rpc/svc.h index d73625e9303d..4a3833c7cad5 100644 --- a/include/rpc/svc.h +++ b/include/rpc/svc.h @@ -226,7 +226,7 @@ struct svc_req { * const SVCXPRT *xprt; * const rpcprog_t prog; * const rpcvers_t vers; - * const void (*dispatch)(); + * const void (*dispatch)(struct svc_req *, SVCXPRT *); * const struct netconfig *nconf; */ @@ -376,7 +376,7 @@ __BEGIN_DECLS extern int svc_create(void (*)(struct svc_req *, SVCXPRT *), const rpcprog_t, const rpcvers_t, const char *); /* - * void (*dispatch)(); -- dispatch routine + * void (*dispatch)(struct svc_req *, SVCXPRT *); * const rpcprog_t prognum; -- program number * const rpcvers_t versnum; -- version number * const char *nettype; -- network type @@ -392,7 +392,7 @@ extern SVCXPRT *svc_tp_create(void (*)(struct svc_req *, SVCXPRT *), const rpcprog_t, const rpcvers_t, const struct netconfig *); /* - * void (*dispatch)(); -- dispatch routine + * void (*dispatch)(struct svc_req *, SVCXPRT *); * const rpcprog_t prognum; -- program number * const rpcvers_t versnum; -- version number * const struct netconfig *nconf; -- netconfig structure diff --git a/include/rpcsvc/Makefile b/include/rpcsvc/Makefile index d7d093fe5eb7..66acc9d5a727 100644 --- a/include/rpcsvc/Makefile +++ b/include/rpcsvc/Makefile @@ -3,7 +3,7 @@ .SUFFIXES: .x -RPCCOM = rpcgen -C +RPCCOM= RPCGEN_CPP=${CPP:Q} rpcgen -C HDRS= key_prot.h klm_prot.h mount.h nfs_prot.h nlm_prot.h rex.h rnusers.h \ rquota.h rstat.h rwall.h sm_inter.h spray.h yppasswd.h yp.h \ diff --git a/lib/clang/Makefile b/lib/clang/Makefile index 8f7d18a31213..e0a6201e0340 100644 --- a/lib/clang/Makefile +++ b/lib/clang/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + .if !make(install) SUBDIR= libclanganalysis \ libclangarcmigrate \ @@ -60,6 +62,19 @@ SUBDIR= libclanganalysis \ libllvmx86info \ libllvmx86instprinter \ libllvmx86utils + +.if ${MK_CLANG_EXTRAS} != "no" +SUBDIR+=libllvmarchive \ + libllvmdebuginfo \ + libllvmexecutionengine \ + libllvminterpreter \ + libllvmjit \ + libllvmlinker \ + libllvmmcdisassembler \ + libllvmmcjit \ + libllvmobject \ + libllvmruntimedyld +.endif .endif SUBDIR+= include diff --git a/lib/clang/libllvmanalysis/Makefile b/lib/clang/libllvmanalysis/Makefile index 2b0bccff976a..301c39b16471 100644 --- a/lib/clang/libllvmanalysis/Makefile +++ b/lib/clang/libllvmanalysis/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= llvmanalysis SRCDIR= lib/Analysis @@ -55,6 +57,14 @@ SRCS= AliasAnalysis.cpp \ TypeBasedAliasAnalysis.cpp \ ValueTracking.cpp +.if ${MK_CLANG_EXTRAS} != "no" +SRCS+= BlockFrequencyInfo.cpp \ + LibCallSemantics.cpp \ + PathNumbering.cpp \ + PathProfileInfo.cpp \ + PathProfileVerifier.cpp +.endif + TGHDRS= Intrinsics .include "../clang.lib.mk" diff --git a/lib/clang/libllvmarchive/Makefile b/lib/clang/libllvmarchive/Makefile new file mode 100644 index 000000000000..a28f2f510a69 --- /dev/null +++ b/lib/clang/libllvmarchive/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +LIB= llvmarchive + +SRCDIR= lib/Archive +SRCS= Archive.cpp \ + ArchiveReader.cpp \ + ArchiveWriter.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmdebuginfo/Makefile b/lib/clang/libllvmdebuginfo/Makefile new file mode 100644 index 000000000000..b7241573c123 --- /dev/null +++ b/lib/clang/libllvmdebuginfo/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +LIB= llvmdebuginfo + +SRCDIR= lib/DebugInfo +SRCS= DIContext.cpp \ + DWARFAbbreviationDeclaration.cpp \ + DWARFCompileUnit.cpp \ + DWARFContext.cpp \ + DWARFDebugAbbrev.cpp \ + DWARFDebugArangeSet.cpp \ + DWARFDebugAranges.cpp \ + DWARFDebugInfoEntry.cpp \ + DWARFDebugLine.cpp \ + DWARFFormValue.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmexecutionengine/Makefile b/lib/clang/libllvmexecutionengine/Makefile new file mode 100644 index 000000000000..c0dde71debb4 --- /dev/null +++ b/lib/clang/libllvmexecutionengine/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +LIB= llvmexecutionengine + +SRCDIR= lib/ExecutionEngine +SRCS= ExecutionEngine.cpp \ + ExecutionEngineBindings.cpp \ + TargetSelect.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvminterpreter/Makefile b/lib/clang/libllvminterpreter/Makefile new file mode 100644 index 000000000000..6a1b453459b2 --- /dev/null +++ b/lib/clang/libllvminterpreter/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +LIB= llvminterpreter + +SRCDIR= lib/ExecutionEngine/Interpreter +SRCS= Execution.cpp \ + ExternalFunctions.cpp \ + Interpreter.cpp \ + +TGHDRS= Intrinsics + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmipa/Makefile b/lib/clang/libllvmipa/Makefile index fc241dfc241e..4caa0e5dec84 100644 --- a/lib/clang/libllvmipa/Makefile +++ b/lib/clang/libllvmipa/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= llvmipa SRCDIR= lib/Analysis/IPA @@ -8,6 +10,10 @@ SRCS= CallGraph.cpp \ FindUsedTypes.cpp \ GlobalsModRef.cpp +.if ${MK_CLANG_EXTRAS} != "no" +SRCS+= IPA.cpp +.endif + TGHDRS= Intrinsics .include "../clang.lib.mk" diff --git a/lib/clang/libllvmipo/Makefile b/lib/clang/libllvmipo/Makefile index 42cc2fa93252..a493532d6504 100644 --- a/lib/clang/libllvmipo/Makefile +++ b/lib/clang/libllvmipo/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= llvmipo SRCDIR= lib/Transforms/IPO @@ -23,6 +25,10 @@ SRCS= ArgumentPromotion.cpp \ StripDeadPrototypes.cpp \ StripSymbols.cpp +.if ${MK_CLANG_EXTRAS} != "no" +SRCS+= IPO.cpp +.endif + TGHDRS= Intrinsics .include "../clang.lib.mk" diff --git a/lib/clang/libllvmjit/Makefile b/lib/clang/libllvmjit/Makefile new file mode 100644 index 000000000000..fc92fd07d93e --- /dev/null +++ b/lib/clang/libllvmjit/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ + +LIB= llvmjit + +SRCDIR= lib/ExecutionEngine/JIT +SRCS= Intercept.cpp \ + JIT.cpp \ + JITDebugRegisterer.cpp \ + JITDwarfEmitter.cpp \ + JITEmitter.cpp \ + JITMemoryManager.cpp \ + OProfileJITEventListener.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmlinker/Makefile b/lib/clang/libllvmlinker/Makefile new file mode 100644 index 000000000000..73f153b378fb --- /dev/null +++ b/lib/clang/libllvmlinker/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +LIB= llvmlinker + +SRCDIR= lib/Linker +SRCS= LinkArchives.cpp \ + LinkItems.cpp \ + LinkModules.cpp \ + Linker.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmmc/Makefile b/lib/clang/libllvmmc/Makefile index 5fef440114b9..9bb572390edb 100644 --- a/lib/clang/libllvmmc/Makefile +++ b/lib/clang/libllvmmc/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= llvmmc SRCDIR= lib/MC @@ -43,4 +45,8 @@ SRCS= ELFObjectWriter.cpp \ WinCOFFObjectWriter.cpp \ WinCOFFStreamer.cpp +.if ${MK_CLANG_EXTRAS} != "no" +SRCS+= MCDisassembler.cpp +.endif + .include "../clang.lib.mk" diff --git a/lib/clang/libllvmmcdisassembler/Makefile b/lib/clang/libllvmmcdisassembler/Makefile new file mode 100644 index 000000000000..dc5f29437e0c --- /dev/null +++ b/lib/clang/libllvmmcdisassembler/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +LIB= llvmmcdisassembler + +SRCDIR= lib/MC/MCDisassembler +SRCS= Disassembler.cpp \ + EDDisassembler.cpp \ + EDInst.cpp \ + EDOperand.cpp \ + EDToken.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmmcjit/Makefile b/lib/clang/libllvmmcjit/Makefile new file mode 100644 index 000000000000..58e25292587e --- /dev/null +++ b/lib/clang/libllvmmcjit/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +LIB= llvmmcjit + +SRCDIR= lib/ExecutionEngine/MCJIT +SRCS= Intercept.cpp \ + MCJIT.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmobject/Makefile b/lib/clang/libllvmobject/Makefile new file mode 100644 index 000000000000..d056dc7c15d3 --- /dev/null +++ b/lib/clang/libllvmobject/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +LIB= llvmobject + +SRCDIR= lib/Object +SRCS= Archive.cpp \ + Binary.cpp \ + COFFObjectFile.cpp \ + ELFObjectFile.cpp \ + Error.cpp \ + MachOObject.cpp \ + MachOObjectFile.cpp \ + Object.cpp \ + ObjectFile.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmruntimedyld/Makefile b/lib/clang/libllvmruntimedyld/Makefile new file mode 100644 index 000000000000..c17f0317289a --- /dev/null +++ b/lib/clang/libllvmruntimedyld/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +LIB= llvmruntimedyld + +SRCDIR= lib/ExecutionEngine/RuntimeDyld +SRCS= RuntimeDyld.cpp \ + RuntimeDyldMachO.cpp + +.include "../clang.lib.mk" diff --git a/lib/clang/libllvmscalaropts/Makefile b/lib/clang/libllvmscalaropts/Makefile index c376b685d591..20235958c737 100644 --- a/lib/clang/libllvmscalaropts/Makefile +++ b/lib/clang/libllvmscalaropts/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= llvmscalaropts SRCDIR= lib/Transforms/Scalar @@ -31,6 +33,13 @@ SRCS= ADCE.cpp \ Sink.cpp \ TailRecursionElimination.cpp +.if ${MK_CLANG_EXTRAS} != "no" +SRCS+= LoopInstSimplify.cpp \ + LowerAtomic.cpp \ + Reg2Mem.cpp \ + Scalar.cpp +.endif + TGHDRS= Intrinsics .include "../clang.lib.mk" diff --git a/lib/clang/libllvmsupport/Makefile b/lib/clang/libllvmsupport/Makefile index e1a16c46260e..fb9309f67a0c 100644 --- a/lib/clang/libllvmsupport/Makefile +++ b/lib/clang/libllvmsupport/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= llvmsupport SRCDIR= lib/Support @@ -67,4 +69,14 @@ SRCS= APFloat.cpp \ system_error.cpp LLVM_REQUIRES_RTTI= +.if ${MK_CLANG_EXTRAS} != "no" +SRCS+= BlockFrequency.cpp \ + BranchProbability.cpp \ + DataExtractor.cpp \ + Disassembler.cpp \ + FileUtilities.cpp \ + MemoryObject.cpp \ + SystemUtils.cpp +.endif + .include "../clang.lib.mk" diff --git a/lib/clang/libllvmtransformutils/Makefile b/lib/clang/libllvmtransformutils/Makefile index 18eecda5d62c..196978156a54 100644 --- a/lib/clang/libllvmtransformutils/Makefile +++ b/lib/clang/libllvmtransformutils/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= llvmtransformutils SRCDIR= lib/Transforms/Utils @@ -29,6 +31,11 @@ SRCS= AddrModeMatcher.cpp \ UnifyFunctionExitNodes.cpp \ ValueMapper.cpp +.if ${MK_CLANG_EXTRAS} != "no" +SRCS+= SimplifyInstructions.cpp \ + Utils.cpp +.endif + TGHDRS= Intrinsics .include "../clang.lib.mk" diff --git a/lib/clang/libllvmx86disassembler/Makefile b/lib/clang/libllvmx86disassembler/Makefile index 1d1b3b651620..9b738007c72a 100644 --- a/lib/clang/libllvmx86disassembler/Makefile +++ b/lib/clang/libllvmx86disassembler/Makefile @@ -1,11 +1,17 @@ # $FreeBSD$ +.include + LIB= llvmx86disassembler SRCDIR= lib/Target/X86/Disassembler INCDIR= lib/Target/X86 SRCS= X86Disassembler.cpp +.if ${MK_CLANG_EXTRAS} != "no" +SRCS+= X86DisassemblerDecoder.c +.endif + TGHDRS= X86GenDisassemblerTables \ X86GenEDInfo \ X86GenInstrInfo \ diff --git a/lib/libc/arm/gen/Makefile.inc b/lib/libc/arm/gen/Makefile.inc index b47f57d2f71c..e0ebd988846f 100644 --- a/lib/libc/arm/gen/Makefile.inc +++ b/lib/libc/arm/gen/Makefile.inc @@ -3,4 +3,4 @@ SRCS+= _ctx_start.S _setjmp.S _set_tp.c alloca.S fabs.c \ getcontextx.c infinity.c ldexp.c makecontext.c \ - setjmp.S signalcontext.c sigsetjmp.S divsi3.S flt_rounds.c + __aeabi_read_tp.c setjmp.S signalcontext.c sigsetjmp.S divsi3.S flt_rounds.c diff --git a/lib/libc/arm/gen/__aeabi_read_tp.c b/lib/libc/arm/gen/__aeabi_read_tp.c new file mode 100644 index 000000000000..39b5fb798b7e --- /dev/null +++ b/lib/libc/arm/gen/__aeabi_read_tp.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2012 Oleksandr Tymoshenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include "machine/sysarch.h" + +void * +__aeabi_read_tp() +{ + void **_tp = (void **)ARM_TP_ADDRESS; + + return (*_tp); +} diff --git a/lib/libc/db/man/hash.3 b/lib/libc/db/man/hash.3 index 133885d841c9..a2a8bca65c14 100644 --- a/lib/libc/db/man/hash.3 +++ b/lib/libc/db/man/hash.3 @@ -65,7 +65,7 @@ typedef struct { u_int ffactor; u_int nelem; u_int cachesize; - u_int32_t (*hash)(const void *, size_t); + uint32_t (*hash)(const void *, size_t); int lorder; } HASHINFO; .Ed diff --git a/lib/libc/gen/arc4random.3 b/lib/libc/gen/arc4random.3 index be1f69092fcd..e1124c622e77 100644 --- a/lib/libc/gen/arc4random.3 +++ b/lib/libc/gen/arc4random.3 @@ -44,12 +44,12 @@ .Lb libc .Sh SYNOPSIS .In stdlib.h -.Ft u_int32_t +.Ft uint32_t .Fn arc4random "void" .Ft void .Fn arc4random_buf "void *buf" "size_t nbytes" -.Ft u_int32_t -.Fn arc4random_uniform "u_int32_t upper_bound" +.Ft uint32_t +.Fn arc4random_uniform "uint32_t upper_bound" .Ft void .Fn arc4random_stir "void" .Ft void diff --git a/lib/libc/gen/directory.3 b/lib/libc/gen/directory.3 index 992d2fcde520..1c568fc14b1b 100644 --- a/lib/libc/gen/directory.3 +++ b/lib/libc/gen/directory.3 @@ -122,9 +122,12 @@ function returns a pointer to the next directory entry. It returns .Dv NULL -upon reaching the end of the directory or detecting an invalid -.Fn seekdir -operation. +upon reaching the end of the directory or on error. +In the event of an error, +.Va errno +may be set to any of the values documented for the +.Xr getdirentries 2 +system call. .Pp The .Fn readdir_r diff --git a/lib/libc/gen/getutxent.3 b/lib/libc/gen/getutxent.3 index 2707ee85513c..2ea09712d8d4 100644 --- a/lib/libc/gen/getutxent.3 +++ b/lib/libc/gen/getutxent.3 @@ -423,7 +423,7 @@ The file format is invalid. .Xr tty 4 , .Xr ac 8 , .Xr newsyslog 8 , -.Xr utxrm 8 +.Xr utx 8 .Sh STANDARDS The .Fn endutxent , diff --git a/lib/libc/gen/getutxent.c b/lib/libc/gen/getutxent.c index 556df56220ed..4e608687795f 100644 --- a/lib/libc/gen/getutxent.c +++ b/lib/libc/gen/getutxent.c @@ -70,13 +70,18 @@ setutxdb(int db, const char *file) if (uf == NULL) return (-1); - /* Safety check: never use broken files. */ - if (db != UTXDB_LOG && _fstat(fileno(uf), &sb) != -1 && - sb.st_size % sizeof(struct futx) != 0) { - fclose(uf); - uf = NULL; - errno = EFTYPE; - return (-1); + if (db != UTXDB_LOG) { + /* Safety check: never use broken files. */ + if (_fstat(fileno(uf), &sb) != -1 && + sb.st_size % sizeof(struct futx) != 0) { + fclose(uf); + uf = NULL; + errno = EFTYPE; + return (-1); + } + /* Prevent reading of partial records. */ + (void)setvbuf(uf, NULL, _IOFBF, + rounddown(BUFSIZ, sizeof(struct futx))); } udb = db; diff --git a/lib/libc/gen/sysctl.3 b/lib/libc/gen/sysctl.3 index a841545f2d54..b3737e2d1aaa 100644 --- a/lib/libc/gen/sysctl.3 +++ b/lib/libc/gen/sysctl.3 @@ -28,7 +28,7 @@ .\" @(#)sysctl.3 8.4 (Berkeley) 5/9/95 .\" $FreeBSD$ .\" -.Dd April 25, 2010 +.Dd February 11, 2012 .Dt SYSCTL 3 .Os .Sh NAME @@ -554,6 +554,7 @@ The fifth and sixth level names are as follows: .It "NET_RT_DUMP None" .It "NET_RT_IFLIST 0 or if_index" .It "NET_RT_IFMALIST 0 or if_index" +.It "NET_RT_IFLISTL 0 or if_index" .El .Pp The @@ -561,6 +562,19 @@ The name returns information about multicast group memberships on all interfaces if 0 is specified, or for the interface specified by .Va if_index . +.Pp +The +.Dv NET_RT_IFLISTL +is like +.Dv NET_RT_IFLIST , +just returning message header structs with additional fields allowing the +interface to be extended without breaking binary compatibility. +The +.Dv NET_RT_IFLISTL +uses 'l' versions of the message header structures: +.Va struct if_msghdrl +and +.Va struct ifa_msghdrl . .It Li PF_INET Get or set various global information about the IPv4 (Internet Protocol version 4). diff --git a/lib/libc/locale/btowc.3 b/lib/libc/locale/btowc.3 index 85ee7515f948..9eca4373c5cb 100644 --- a/lib/libc/locale/btowc.3 +++ b/lib/libc/locale/btowc.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 3, 2002 +.Dd February 13, 2012 .Dt BTOWC 3 .Os .Sh NAME @@ -58,7 +58,7 @@ If the wide character is or not able to be represented as a single byte in the initial shift state, .Fn wctob returns -.Dv WEOF . +.Dv EOF . .Sh SEE ALSO .Xr mbrtowc 3 , .Xr multibyte 3 , diff --git a/lib/libc/net/eui64.3 b/lib/libc/net/eui64.3 index 7cc5718ca964..fc563d157a14 100644 --- a/lib/libc/net/eui64.3 +++ b/lib/libc/net/eui64.3 @@ -221,10 +221,3 @@ These functions first appears in They are derived from the .Xr ethers 3 family of functions. -.Sh BUGS -The -.Fn eui64_aton -and -.Fn eui64_ntoa -functions returns values that are stored in static memory areas -which may be overwritten the next time they are called. diff --git a/lib/libc/net/getifaddrs.c b/lib/libc/net/getifaddrs.c index aada929c1e42..f8633d5b959a 100644 --- a/lib/libc/net/getifaddrs.c +++ b/lib/libc/net/getifaddrs.c @@ -72,19 +72,6 @@ __FBSDID("$FreeBSD$"); #define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES) #endif -#if _BSDI_VERSION >= 199701 -#define HAVE_IFM_DATA -#endif - -#if (_BSDI_VERSION >= 199802) || (__FreeBSD_version >= 1000003) -/* ifam_data is very specific to recent versions of bsdi */ -#define HAVE_IFAM_DATA -#endif - -#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) -#define HAVE_IFM_DATA -#endif - #define MAX_SYSCTL_TRY 5 int @@ -93,7 +80,6 @@ getifaddrs(struct ifaddrs **pif) int icnt = 1; int dcnt = 0; int ncnt = 0; -#ifdef NET_RT_IFLIST int ntry = 0; int mib[6]; size_t needed; @@ -102,30 +88,23 @@ getifaddrs(struct ifaddrs **pif) struct ifaddrs *cif = 0; char *p, *p0; struct rt_msghdr *rtm; - struct if_msghdr *ifm; - struct ifa_msghdr *ifam; + struct if_msghdrl *ifm; + struct ifa_msghdrl *ifam; struct sockaddr_dl *dl; struct sockaddr *sa; struct ifaddrs *ifa, *ift; + struct if_data *if_data; u_short idx = 0; -#else /* NET_RT_IFLIST */ - char buf[1024]; - int m, sock; - struct ifconf ifc; - struct ifreq *ifr; - struct ifreq *lifr; -#endif /* NET_RT_IFLIST */ int i; size_t len, alen; char *data; char *names; -#ifdef NET_RT_IFLIST mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; /* protocol */ mib[3] = 0; /* wildcard address family */ - mib[4] = NET_RT_IFLIST; + mib[4] = NET_RT_IFLISTL;/* extra fields for extensible msghdr structs */ mib[5] = 0; /* no flags */ do { /* @@ -159,34 +138,33 @@ getifaddrs(struct ifaddrs **pif) continue; switch (rtm->rtm_type) { case RTM_IFINFO: - ifm = (struct if_msghdr *)(void *)rtm; + ifm = (struct if_msghdrl *)(void *)rtm; if (ifm->ifm_addrs & RTA_IFP) { idx = ifm->ifm_index; ++icnt; - dl = (struct sockaddr_dl *)(void *)(ifm + 1); + if_data = IF_MSGHDRL_IFM_DATA(ifm); + dcnt += if_data->ifi_datalen; + dl = (struct sockaddr_dl *)IF_MSGHDRL_RTA(ifm); dcnt += SA_RLEN((struct sockaddr *)(void*)dl) + ALIGNBYTES; -#ifdef HAVE_IFM_DATA - dcnt += sizeof(ifm->ifm_data); -#endif /* HAVE_IFM_DATA */ ncnt += dl->sdl_nlen + 1; } else idx = 0; break; case RTM_NEWADDR: - ifam = (struct ifa_msghdr *)(void *)rtm; + ifam = (struct ifa_msghdrl *)(void *)rtm; if (idx && ifam->ifam_index != idx) abort(); /* this cannot happen */ #define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD) if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0) break; - p = (char *)(void *)(ifam + 1); + p = (char *)IFA_MSGHDRL_RTA(ifam); ++icnt; -#ifdef HAVE_IFAM_DATA - dcnt += sizeof(ifam->ifam_data) + ALIGNBYTES; -#endif /* HAVE_IFAM_DATA */ + if_data = IFA_MSGHDRL_IFAM_DATA(ifam); + dcnt += if_data->ifi_datalen + ALIGNBYTES; + /* Scan to look for length of address */ alen = 0; for (p0 = p, i = 0; i < RTAX_MAX; i++) { @@ -216,34 +194,6 @@ getifaddrs(struct ifaddrs **pif) break; } } -#else /* NET_RT_IFLIST */ - ifc.ifc_buf = buf; - ifc.ifc_len = sizeof(buf); - - if ((sock = _socket(AF_INET, SOCK_STREAM, 0)) < 0) - return (-1); - i = _ioctl(sock, SIOCGIFCONF, (char *)&ifc); - _close(sock); - if (i < 0) - return (-1); - - ifr = ifc.ifc_req; - lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; - - while (ifr < lifr) { - struct sockaddr *sa; - - sa = &ifr->ifr_addr; - ++icnt; - dcnt += SA_RLEN(sa); - ncnt += sizeof(ifr->ifr_name) + 1; - - if (SA_LEN(sa) < sizeof(*sa)) - ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa)); - else - ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa)); - } -#endif /* NET_RT_IFLIST */ if (icnt + dcnt + ncnt == 1) { *pif = NULL; @@ -263,7 +213,6 @@ getifaddrs(struct ifaddrs **pif) memset(ifa, 0, sizeof(struct ifaddrs) * icnt); ift = ifa; -#ifdef NET_RT_IFLIST idx = 0; for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)(void *)next; @@ -271,41 +220,38 @@ getifaddrs(struct ifaddrs **pif) continue; switch (rtm->rtm_type) { case RTM_IFINFO: - ifm = (struct if_msghdr *)(void *)rtm; - if (ifm->ifm_addrs & RTA_IFP) { - idx = ifm->ifm_index; - dl = (struct sockaddr_dl *)(void *)(ifm + 1); - - cif = ift; - ift->ifa_name = names; - ift->ifa_flags = (int)ifm->ifm_flags; - memcpy(names, dl->sdl_data, - (size_t)dl->sdl_nlen); - names[dl->sdl_nlen] = 0; - names += dl->sdl_nlen + 1; - - ift->ifa_addr = (struct sockaddr *)(void *)data; - memcpy(data, dl, - (size_t)SA_LEN((struct sockaddr *) - (void *)dl)); - data += SA_RLEN((struct sockaddr *)(void *)dl); - -#ifdef HAVE_IFM_DATA - /* ifm_data needs to be aligned */ - ift->ifa_data = data = (void *)ALIGN(data); - memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data)); - data += sizeof(ifm->ifm_data); -#else /* HAVE_IFM_DATA */ - ift->ifa_data = NULL; -#endif /* HAVE_IFM_DATA */ - - ift = (ift->ifa_next = ift + 1); - } else + ifm = (struct if_msghdrl *)(void *)rtm; + if ((ifm->ifm_addrs & RTA_IFP) == 0) { idx = 0; + break; + } + + idx = ifm->ifm_index; + dl = (struct sockaddr_dl *)IF_MSGHDRL_RTA(ifm); + + cif = ift; + ift->ifa_name = names; + ift->ifa_flags = (int)ifm->ifm_flags; + memcpy(names, dl->sdl_data, (size_t)dl->sdl_nlen); + names[dl->sdl_nlen] = 0; + names += dl->sdl_nlen + 1; + + ift->ifa_addr = (struct sockaddr *)(void *)data; + memcpy(data, dl, (size_t)SA_LEN((struct sockaddr *) + (void *)dl)); + data += SA_RLEN((struct sockaddr *)(void *)dl); + + if_data = IF_MSGHDRL_IFM_DATA(ifm); + /* ifm_data needs to be aligned */ + ift->ifa_data = data = (void *)ALIGN(data); + memcpy(data, if_data, if_data->ifi_datalen); + data += if_data->ifi_datalen; + + ift = (ift->ifa_next = ift + 1); break; case RTM_NEWADDR: - ifam = (struct ifa_msghdr *)(void *)rtm; + ifam = (struct ifa_msghdrl *)(void *)rtm; if (idx && ifam->ifam_index != idx) abort(); /* this cannot happen */ @@ -314,7 +260,8 @@ getifaddrs(struct ifaddrs **pif) ift->ifa_name = cif->ifa_name; ift->ifa_flags = cif->ifa_flags; ift->ifa_data = NULL; - p = (char *)(void *)(ifam + 1); + + p = (char *)IFA_MSGHDRL_RTA(ifam); /* Scan to look for length of address */ alen = 0; for (p0 = p, i = 0; i < RTAX_MAX; i++) { @@ -365,12 +312,11 @@ getifaddrs(struct ifaddrs **pif) p += len; } -#ifdef HAVE_IFAM_DATA + if_data = IFA_MSGHDRL_IFAM_DATA(ifam); /* ifam_data needs to be aligned */ ift->ifa_data = data = (void *)ALIGN(data); - memcpy(data, &ifam->ifam_data, sizeof(ifam->ifam_data)); - data += sizeof(ifam->ifam_data); -#endif /* HAVE_IFAM_DATA */ + memcpy(data, if_data, if_data->ifi_datalen); + data += if_data->ifi_datalen; ift = (ift->ifa_next = ift + 1); break; @@ -378,28 +324,7 @@ getifaddrs(struct ifaddrs **pif) } free(buf); -#else /* NET_RT_IFLIST */ - ifr = ifc.ifc_req; - lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; - while (ifr < lifr) { - struct sockaddr *sa; - - ift->ifa_name = names; - names[sizeof(ifr->ifr_name)] = 0; - strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name)); - while (*names++) - ; - - ift->ifa_addr = (struct sockaddr *)data; - sa = &ifr->ifr_addr; - memcpy(data, sa, SA_LEN(sa)); - data += SA_RLEN(sa); - - ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa)); - ift = (ift->ifa_next = ift + 1); - } -#endif /* NET_RT_IFLIST */ if (--ift >= ifa) { ift->ifa_next = NULL; *pif = ifa; diff --git a/lib/libc/net/nsdispatch.3 b/lib/libc/net/nsdispatch.3 index d1d8d5a0e71e..2fd9ec9c6337 100644 --- a/lib/libc/net/nsdispatch.3 +++ b/lib/libc/net/nsdispatch.3 @@ -129,7 +129,7 @@ structures, which have the following format: .Bd -literal -offset indent typedef struct _ns_src { const char *src; - u_int32_t flags; + uint32_t flags; } ns_src; .Ed .Bd -ragged -offset indent diff --git a/lib/libc/powerpc/SYS.h b/lib/libc/powerpc/SYS.h index f775f37101bd..0bd793f3353a 100644 --- a/lib/libc/powerpc/SYS.h +++ b/lib/libc/powerpc/SYS.h @@ -33,38 +33,38 @@ #include #include -#define _SYSCALL(x) \ +#define _SYSCALL(name) \ .text; \ .align 2; \ - li 0,(__CONCAT(SYS_,x)); \ + li 0,(__CONCAT(SYS_, name)); \ sc -#define SYSCALL(x) \ +#define SYSCALL(name) \ .text; \ .align 2; \ 2: b PIC_PLT(CNAME(HIDENAME(cerror))); \ -ENTRY(__CONCAT(__sys_,x)); \ - WEAK_ALIAS(x,__CONCAT(__sys_,x)); \ - WEAK_ALIAS(__CONCAT(_,x),__CONCAT(__sys_,x)); \ - _SYSCALL(x); \ +ENTRY(__CONCAT(__sys_, name)); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), name); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name));\ + _SYSCALL(name); \ bso 2b -#define PSEUDO(x) \ +#define PSEUDO(name) \ .text; \ .align 2; \ -ENTRY(__CONCAT(__sys_,x)); \ - WEAK_ALIAS(__CONCAT(_,x),__CONCAT(__sys_,x)); \ - _SYSCALL(x); \ +ENTRY(__CONCAT(__sys_, name)); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name));\ + _SYSCALL(name); \ bnslr; \ b PIC_PLT(CNAME(HIDENAME(cerror))) -#define RSYSCALL(x) \ +#define RSYSCALL(name) \ .text; \ .align 2; \ 2: b PIC_PLT(CNAME(HIDENAME(cerror))); \ -ENTRY(__CONCAT(__sys_,x)); \ - WEAK_ALIAS(x,__CONCAT(__sys_,x)); \ - WEAK_ALIAS(__CONCAT(_,x), __CONCAT(__sys_,x)); \ - _SYSCALL(x); \ +ENTRY(__CONCAT(__sys_, name)); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), name); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name));\ + _SYSCALL(name); \ bnslr; \ b PIC_PLT(CNAME(HIDENAME(cerror))) diff --git a/lib/libc/powerpc/gen/setjmp.S b/lib/libc/powerpc/gen/setjmp.S index 27567ff7be5b..447ba57de8d7 100644 --- a/lib/libc/powerpc/gen/setjmp.S +++ b/lib/libc/powerpc/gen/setjmp.S @@ -69,7 +69,7 @@ ENTRY(setjmp) li %r3,0 /* return (0) */ blr - WEAK_ALIAS(longjmp, __longjmp) + WEAK_REFERENCE(CNAME(__longjmp), longjmp) ENTRY(__longjmp) lmw %r9,20(%r3) /* restore regs */ mr %r6,%r4 /* save val param */ diff --git a/lib/libc/powerpc64/SYS.h b/lib/libc/powerpc64/SYS.h index 80a6b1bf5905..8b3281fb1a4a 100644 --- a/lib/libc/powerpc64/SYS.h +++ b/lib/libc/powerpc64/SYS.h @@ -33,13 +33,13 @@ #include #include -#define _SYSCALL(x) \ +#define _SYSCALL(name) \ .text; \ .align 2; \ - li 0,(__CONCAT(SYS_,x)); \ + li 0,(__CONCAT(SYS_, name)); \ sc -#define SYSCALL(x) \ +#define SYSCALL(name) \ .text; \ .align 2; \ 2: mflr %r0; \ @@ -51,18 +51,18 @@ ld %r0,16(%r1); \ mtlr %r0; \ blr; \ -ENTRY(__CONCAT(__sys_,x)); \ - WEAK_ALIAS(x,__CONCAT(__sys_,x)); \ - WEAK_ALIAS(__CONCAT(_,x),__CONCAT(__sys_,x)); \ - _SYSCALL(x); \ +ENTRY(__CONCAT(__sys_, name)); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), name); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name)); \ + _SYSCALL(name); \ bso 2b -#define PSEUDO(x) \ +#define PSEUDO(name) \ .text; \ .align 2; \ -ENTRY(__CONCAT(__sys_,x)); \ - WEAK_ALIAS(__CONCAT(_,x),__CONCAT(__sys_,x)); \ - _SYSCALL(x); \ +ENTRY(__CONCAT(__sys_, name)); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name)); \ + _SYSCALL(name); \ bnslr; \ mflr %r0; \ std %r0,16(%r1); \ @@ -74,13 +74,13 @@ ENTRY(__CONCAT(__sys_,x)); \ mtlr %r0; \ blr; -#define RSYSCALL(x) \ +#define RSYSCALL(name) \ .text; \ .align 2; \ -ENTRY(__CONCAT(__sys_,x)); \ - WEAK_ALIAS(x,__CONCAT(__sys_,x)); \ - WEAK_ALIAS(__CONCAT(_,x), __CONCAT(__sys_,x)); \ - _SYSCALL(x); \ +ENTRY(__CONCAT(__sys_, name)); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), name); \ + WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name));\ + _SYSCALL(name); \ bnslr; \ \ mflr %r0; \ diff --git a/lib/libc/powerpc64/gen/setjmp.S b/lib/libc/powerpc64/gen/setjmp.S index 23002aba6f25..deda7c569a71 100644 --- a/lib/libc/powerpc64/gen/setjmp.S +++ b/lib/libc/powerpc64/gen/setjmp.S @@ -93,7 +93,7 @@ ENTRY(setjmp) li %r3,0 /* return (0) */ blr - WEAK_ALIAS(longjmp, __longjmp) + WEAK_REFERENCE(__longjmp, longjmp) ENTRY(__longjmp) ld %r9,40 + 0*8(%r3) ld %r10,40 + 1*8(%r3) diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc index db0b8ad3e785..32e8f86b7169 100644 --- a/lib/libc/rpc/Makefile.inc +++ b/lib/libc/rpc/Makefile.inc @@ -34,7 +34,7 @@ CFLAGS+= -I${.CURDIR}/rpc CLEANFILES+= crypt_clnt.c crypt_xdr.c crypt.h RPCDIR= ${DESTDIR}/usr/include/rpcsvc -RPCGEN= rpcgen -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -C crypt_clnt.c: ${RPCDIR}/crypt.x crypt.h ${RPCGEN} -l -o ${.TARGET} ${RPCDIR}/crypt.x diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc.3 index 81a24ca63163..4fa3e2cee58f 100644 --- a/lib/libc/rpc/rpc.3 +++ b/lib/libc/rpc/rpc.3 @@ -119,12 +119,12 @@ file. .Sh Derived Types The derived types used in the RPC interfaces are defined as follows: .Bd -literal - typedef u_int32_t rpcprog_t; - typedef u_int32_t rpcvers_t; - typedef u_int32_t rpcproc_t; - typedef u_int32_t rpcprot_t; - typedef u_int32_t rpcport_t; - typedef int32_t rpc_inline_t; + typedef uint32_t rpcprog_t; + typedef uint32_t rpcvers_t; + typedef uint32_t rpcproc_t; + typedef uint32_t rpcprot_t; + typedef uint32_t rpcport_t; + typedef int32_t rpc_inline_t; .Ed .Sh "Data Structures" Some of the data structures used by the diff --git a/lib/libc/rpc/rpc_clnt_create.3 b/lib/libc/rpc/rpc_clnt_create.3 index 34c90ed77d1d..079c9eb729bf 100644 --- a/lib/libc/rpc/rpc_clnt_create.3 +++ b/lib/libc/rpc/rpc_clnt_create.3 @@ -106,10 +106,10 @@ Set the timeout argument to 0 for batching calls. .It Dv CLGET_FD Ta "int *" Ta "get fd from handle" .It Dv CLSET_FD_CLOSE Ta "void" Ta "close fd on destroy" .It Dv CLSET_FD_NCLOSE Ta void Ta "do not close fd on destroy" -.It Dv CLGET_VERS Ta "u_int32_t *" Ta "get RPC program version" -.It Dv CLSET_VERS Ta "u_int32_t *" Ta "set RPC program version" -.It Dv CLGET_XID Ta "u_int32_t *" Ta "get XID of previous call" -.It Dv CLSET_XID Ta "u_int32_t *" Ta "set XID of next call" +.It Dv CLGET_VERS Ta "uint32_t *" Ta "get RPC program version" +.It Dv CLSET_VERS Ta "uint32_t *" Ta "set RPC program version" +.It Dv CLGET_XID Ta "uint32_t *" Ta "get XID of previous call" +.It Dv CLSET_XID Ta "uint32_t *" Ta "set XID of next call" .El .Pp The following operations are valid for connectionless transports only: diff --git a/lib/libc/string/strerror.3 b/lib/libc/string/strerror.3 index 0ec6cb0af406..5961a84a9d83 100644 --- a/lib/libc/string/strerror.3 +++ b/lib/libc/string/strerror.3 @@ -147,6 +147,7 @@ or should be used instead. .Sh SEE ALSO .Xr intro 2 , +.Xr err 3 , .Xr psignal 3 .Sh STANDARDS The diff --git a/lib/libc/sys/getdirentries.2 b/lib/libc/sys/getdirentries.2 index e16e7f2a77f8..3fe16327ed32 100644 --- a/lib/libc/sys/getdirentries.2 +++ b/lib/libc/sys/getdirentries.2 @@ -71,10 +71,10 @@ The data in the buffer is a series of .Vt dirent structures each containing the following entries: .Bd -literal -offset indent -u_int32_t d_fileno; -u_int16_t d_reclen; -u_int8_t d_type; -u_int8_t d_namlen; +uint32_t d_fileno; +uint16_t d_reclen; +uint8_t d_type; +uint8_t d_namlen; char d_name[MAXNAMELEN + 1]; /* see below */ .Ed .Pp diff --git a/lib/libc/sys/jail.2 b/lib/libc/sys/jail.2 index bf6218ceff38..7e7ec13db011 100644 --- a/lib/libc/sys/jail.2 +++ b/lib/libc/sys/jail.2 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 23, 2009 +.Dd February 8, 2012 .Dt JAIL 2 .Os .Sh NAME @@ -59,7 +59,7 @@ system call sets up a jail and locks the current process in it. The argument is a pointer to a structure describing the prison: .Bd -literal -offset indent struct jail { - u_int32_t version; + uint32_t version; char *path; char *hostname; char *jailname; @@ -400,6 +400,8 @@ and system calls will fail if: .Bl -tag -width Er +.It Bq Er EPERM +A user other than the super-user attempted to attach to or remove a jail. .It Bq Er EINVAL The jail specified by .Fa jid diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2 index 74824056957a..4fa30201576e 100644 --- a/lib/libc/sys/kqueue.2 +++ b/lib/libc/sys/kqueue.2 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 7, 2011 +.Dd February 15, 2012 .Dt KQUEUE 2 .Os .Sh NAME @@ -322,6 +322,9 @@ The sigevent portion of the AIO request is filled in, with .Va sigev_notify_kqueue containing the descriptor of the kqueue that the event should be attached to, +.Va sigev_notify_kevent_flags +containing the kevent flags which should be EV_ONESHOT, EV_CLEAR or +EV_DISPATCH, .Va sigev_value containing the udata value, and .Va sigev_notify diff --git a/lib/libc/sys/nfssvc.2 b/lib/libc/sys/nfssvc.2 index cf52187cdbd0..f816231ef0a1 100644 --- a/lib/libc/sys/nfssvc.2 +++ b/lib/libc/sys/nfssvc.2 @@ -143,14 +143,14 @@ and a pointer to a struct nfsd_srvargs { struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */ uid_t nsd_uid; /* Effective uid mapped to cred */ - u_int32_t nsd_haddr; /* Ip address of client */ + uint32_t nsd_haddr; /* Ip address of client */ struct ucred nsd_cr; /* Cred. uid maps to */ int nsd_authlen; /* Length of auth string (ret) */ u_char *nsd_authstr; /* Auth string (ret) */ int nsd_verflen; /* and the verifier */ u_char *nsd_verfstr; struct timeval nsd_timestamp; /* timestamp from verifier */ - u_int32_t nsd_ttl; /* credential ttl (sec) */ + uint32_t nsd_ttl; /* credential ttl (sec) */ NFSKERBKEY_T nsd_key; /* Session key */ }; .Ed diff --git a/lib/libc/yp/Makefile.inc b/lib/libc/yp/Makefile.inc index 842e63eb08da..6faa9a54175d 100644 --- a/lib/libc/yp/Makefile.inc +++ b/lib/libc/yp/Makefile.inc @@ -10,7 +10,7 @@ CLEANFILES+= yp.h yp_xdr.c SYM_MAPS+= ${.CURDIR}/yp/Symbol.map RPCSRC= ${DESTDIR}/usr/include/rpcsvc/yp.x -RPCGEN= rpcgen -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -C yp_xdr.c: ${RPCSRC} ${RPCGEN} -c -o ${.TARGET} ${RPCSRC} diff --git a/lib/libcam/cam.3 b/lib/libcam/cam.3 index c11d8fdb21ac..4f918d2c09f9 100644 --- a/lib/libcam/cam.3 +++ b/lib/libcam/cam.3 @@ -145,7 +145,7 @@ struct cam_device { * Device name given by * the user. */ - u_int32_t given_unit_number; /* + uint32_t given_unit_number; /* * Unit number given by * the user. */ @@ -153,7 +153,7 @@ struct cam_device { * Name of the device, * e.g. 'pass' */ - u_int32_t dev_unit_num; /* Unit number of the passthrough + uint32_t dev_unit_num; /* Unit number of the passthrough * device associated with this * particular device. */ @@ -161,18 +161,18 @@ struct cam_device { char sim_name[SIM_IDLEN+1];/* * Controller name, e.g.'ahc' */ - u_int32_t sim_unit_number; /* Controller unit number */ - u_int32_t bus_id; /* Controller bus number */ + uint32_t sim_unit_number; /* Controller unit number */ + uint32_t bus_id; /* Controller bus number */ lun_id_t target_lun; /* Logical Unit Number */ target_id_t target_id; /* Target ID */ path_id_t path_id; /* System SCSI bus number */ - u_int16_t pd_type; /* type of peripheral device */ + uint16_t pd_type; /* type of peripheral device */ struct scsi_inquiry_data inq_data; /* SCSI Inquiry data */ - u_int8_t serial_num[252]; /* device serial number */ - u_int8_t serial_num_len; /* length of the serial number */ - u_int8_t sync_period; /* Negotiated sync period */ - u_int8_t sync_offset; /* Negotiated sync offset */ - u_int8_t bus_width; /* Negotiated bus width */ + uint8_t serial_num[252]; /* device serial number */ + uint8_t serial_num_len; /* length of the serial number */ + uint8_t sync_period; /* Negotiated sync period */ + uint8_t sync_offset; /* Negotiated sync offset */ + uint8_t bus_width; /* Negotiated bus width */ int fd; /* file descriptor for device */ }; .Ed diff --git a/lib/libcam/cam_cdbparse.3 b/lib/libcam/cam_cdbparse.3 index 0dfa6c8c8903..d0f267fa9a17 100644 --- a/lib/libcam/cam_cdbparse.3 +++ b/lib/libcam/cam_cdbparse.3 @@ -83,9 +83,9 @@ .Ft int .Fo csio_build .Fa "struct ccb_scsiio *csio" -.Fa "u_int8_t *data_ptr" -.Fa "u_int32_t dxfer_len" -.Fa "u_int32_t flags" +.Fa "uint8_t *data_ptr" +.Fa "uint32_t dxfer_len" +.Fa "uint32_t flags" .Fa "int retry_count" .Fa "int timeout" .Fa "const char *cmd_spec" @@ -94,9 +94,9 @@ .Ft int .Fo csio_build_visit .Fa "struct ccb_scsiio *csio" -.Fa "u_int8_t *data_ptr" -.Fa "u_int32_t dxfer_len" -.Fa "u_int32_t flags" +.Fa "uint8_t *data_ptr" +.Fa "uint32_t dxfer_len" +.Fa "uint32_t flags" .Fa "int retry_count" .Fa "int timeout" .Fa "const char *cmd_spec" @@ -122,14 +122,14 @@ .Fc .Ft int .Fo buff_decode -.Fa "u_int8_t *buff" +.Fa "uint8_t *buff" .Fa "size_t len" .Fa "const char *fmt" .Fa "..." .Fc .Ft int .Fo buff_decode_visit -.Fa "u_int8_t *buff" +.Fa "uint8_t *buff" .Fa "size_t len" .Fa "const char *fmt" .Fa "void (*arg_put)(void *, int, void *, int, char *)" @@ -150,7 +150,7 @@ .Fc .Ft int .Fo buff_encode_visit -.Fa "u_int8_t *buff" +.Fa "uint8_t *buff" .Fa "size_t len" .Fa "const char *fmt" .Fa "int (*arg_get)(void *hook, char *field_name)" diff --git a/lib/libdevstat/devstat.3 b/lib/libdevstat/devstat.3 index fb8214667805..8d0ce4dc0117 100644 --- a/lib/libdevstat/devstat.3 +++ b/lib/libdevstat/devstat.3 @@ -193,7 +193,7 @@ subelement contains the following elements: .Bd -literal -offset indent struct devinfo { struct devstat *devices; - u_int8_t *mem_ptr; + uint8_t *mem_ptr; long generation; int numdevs; }; @@ -472,7 +472,7 @@ structure to calculate statistics over For each statistics to be calculated, the user should supply the proper enumerated type (listed below), and a variable of the indicated type. All statistics are either integer values, for which a -.Vt u_int64_t +.Vt uint64_t is used, or floating point, for which a .Vt "long double" @@ -489,7 +489,7 @@ be the last argument passed to It is an argument list terminator. .It Dv DSM_TOTAL_BYTES type: -.Vt "u_int64_t *" +.Vt "uint64_t *" .Pp The total number of bytes transferred between the acquisition of .Fa previous @@ -499,7 +499,7 @@ and .It Dv DSM_TOTAL_BYTES_WRITE .It Dv DSM_TOTAL_BYTES_FREE type: -.Vt "u_int64_t *" +.Vt "uint64_t *" .Pp The total number of bytes in transactions of the specified type between the acquisition of @@ -508,7 +508,7 @@ and .Fa current . .It Dv DSM_TOTAL_TRANSFERS type: -.Vt "u_int64_t *" +.Vt "uint64_t *" .Pp The total number of transfers between the acquisition of .Fa previous @@ -519,7 +519,7 @@ and .It Dv DSM_TOTAL_TRANSFERS_WRITE .It Dv DSM_TOTAL_TRANSFERS_FREE type: -.Vt "u_int64_t *" +.Vt "uint64_t *" .Pp The total number of transactions of the specified type between the acquisition of @@ -528,7 +528,7 @@ and .Fa current . .It Dv DSM_TOTAL_BLOCKS type: -.Vt "u_int64_t *" +.Vt "uint64_t *" .Pp The total number of blocks transferred between the acquisition of .Fa previous @@ -541,7 +541,7 @@ blocksize of 512 bytes will be used in the calculation. .It Dv DSM_TOTAL_BLOCKS_WRITE .It Dv DSM_TOTAL_BLOCKS_FREE type: -.Vt "u_int64_t *" +.Vt "uint64_t *" .Pp The total number of blocks of the specified type between the acquisition of .Fa previous @@ -665,7 +665,7 @@ and .Fa current . .It Dv DSM_QUEUE_LENGTH type: -.Vt "u_int64_t *" +.Vt "uint64_t *" .Pp The number of not yet completed transactions at the time when .Fa current diff --git a/lib/libipsec/pfkey.c b/lib/libipsec/pfkey.c index 2dd9d7183c4d..234e7c8bbcea 100644 --- a/lib/libipsec/pfkey.c +++ b/lib/libipsec/pfkey.c @@ -662,7 +662,7 @@ pfkey_send_register(so, satype) { int len, algno; - if (satype == PF_UNSPEC) { + if (satype == SADB_SATYPE_UNSPEC) { for (algno = 0; algno < sizeof(supported_map)/sizeof(supported_map[0]); algno++) { @@ -1778,6 +1778,18 @@ pfkey_align(msg, mhp) case SADB_X_EXT_SA2: mhp[ext->sadb_ext_type] = (caddr_t)ext; break; + case SADB_X_EXT_NAT_T_TYPE: + case SADB_X_EXT_NAT_T_SPORT: + case SADB_X_EXT_NAT_T_DPORT: + /* case SADB_X_EXT_NAT_T_OA: is OAI */ + case SADB_X_EXT_NAT_T_OAI: + case SADB_X_EXT_NAT_T_OAR: + case SADB_X_EXT_NAT_T_FRAG: + if (feature_present("ipsec_natt")) { + mhp[ext->sadb_ext_type] = (caddr_t)ext; + break; + } + /* FALLTHROUGH */ default: __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; return -1; diff --git a/lib/libprocstat/common_kvm.c b/lib/libprocstat/common_kvm.c index 1ff181c8077a..63302bc4f6ed 100644 --- a/lib/libprocstat/common_kvm.c +++ b/lib/libprocstat/common_kvm.c @@ -80,7 +80,7 @@ kdevtoname(kvm_t *kd, struct cdev *dev, char *buf) assert(buf); if (!kvm_read_all(kd, (unsigned long)dev, &si, sizeof(si))) return (1); - strlcpy(buf, si.__si_namebuf, SPECNAMELEN + 1); + strlcpy(buf, si.si_name, SPECNAMELEN + 1); return (0); } diff --git a/lib/libradius/libradius.3 b/lib/libradius/libradius.3 index dca38ca009ee..da60d52474bb 100644 --- a/lib/libradius/libradius.3 +++ b/lib/libradius/libradius.3 @@ -51,14 +51,14 @@ .Fn rad_create_response "struct rad_handle *h" "int code" .Ft "struct in_addr" .Fn rad_cvt_addr "const void *data" -.Ft u_int32_t +.Ft uint32_t .Fn rad_cvt_int "const void *data" .Ft char * .Fn rad_cvt_string "const void *data" "size_t len" .Ft int .Fn rad_get_attr "struct rad_handle *h" "const void **data" "size_t *len" .Ft int -.Fn rad_get_vendor_attr "u_int32_t *vendor" "const void **data" "size_t *len" +.Fn rad_get_vendor_attr "uint32_t *vendor" "const void **data" "size_t *len" .Ft int .Fn rad_init_send_request "struct rad_handle *h" "int *fd" "struct timeval *tv" .Ft int @@ -66,7 +66,7 @@ .Ft int .Fn rad_put_attr "struct rad_handle *h" "int type" "const void *data" "size_t len" .Ft int -.Fn rad_put_int "struct rad_handle *h" "int type" "u_int32_t value" +.Fn rad_put_int "struct rad_handle *h" "int type" "uint32_t value" .Ft int .Fn rad_put_string "struct rad_handle *h" "int type" "const char *str" .Ft int @@ -76,7 +76,7 @@ .Ft int .Fn rad_put_vendor_attr "struct rad_handle *h" "int vendor" "int type" "const void *data" "size_t len" .Ft int -.Fn rad_put_vendor_int "struct rad_handle *h" "int vendor" "int type" "u_int32_t value" +.Fn rad_put_vendor_int "struct rad_handle *h" "int vendor" "int type" "uint32_t value" .Ft int .Fn rad_put_vendor_string "struct rad_handle *h" "int vendor" "int type" "const char *str" .Ft ssize_t diff --git a/lib/librpcsvc/Makefile b/lib/librpcsvc/Makefile index 8bb745882984..9c9e3ae04d53 100644 --- a/lib/librpcsvc/Makefile +++ b/lib/librpcsvc/Makefile @@ -18,7 +18,7 @@ SECRPCSRCS= secretkey.c xcrypt.c OTHERSRCS+= yp_passwd.c yp_update.c .endif -RPCCOM = rpcgen -C +RPCCOM= RPCGEN_CPP=${CPP:Q} rpcgen -C INCDIRS= -I${DESTDIR}/usr/include/rpcsvc diff --git a/lib/libthr/arch/arm/arm/pthread_md.c b/lib/libthr/arch/arm/arm/pthread_md.c index 7ca2b25dcf9c..028f06c17933 100644 --- a/lib/libthr/arch/arm/arm/pthread_md.c +++ b/lib/libthr/arch/arm/arm/pthread_md.c @@ -37,14 +37,17 @@ _tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; - tcb = malloc(sizeof(struct tcb)); + tcb = _rtld_allocate_tls((initial) ? _tcb_get() : NULL, + sizeof(struct tcb), 16); if (tcb) tcb->tcb_thread = thread; + return (tcb); } void _tcb_dtor(struct tcb *tcb) { - free(tcb); + + _rtld_free_tls(tcb, sizeof(struct tcb), 16); } diff --git a/lib/libthr/arch/arm/include/pthread_md.h b/lib/libthr/arch/arm/include/pthread_md.h index e799c542feb3..83ddf7f85951 100644 --- a/lib/libthr/arch/arm/include/pthread_md.h +++ b/lib/libthr/arch/arm/include/pthread_md.h @@ -43,10 +43,8 @@ * Variant II tcb, first two members are required by rtld. */ struct tcb { - struct tcb *tcb_self; /* required by rtld */ void *tcb_dtv; /* required by rtld */ struct pthread *tcb_thread; /* our hook */ - void *tcb_spare[1]; }; /* diff --git a/lib/libthr/arch/mips/include/pthread_md.h b/lib/libthr/arch/mips/include/pthread_md.h index 24139a3a71f1..f7c286a322ce 100644 --- a/lib/libthr/arch/mips/include/pthread_md.h +++ b/lib/libthr/arch/mips/include/pthread_md.h @@ -39,15 +39,19 @@ #define CPU_SPINWAIT #define DTV_OFFSET offsetof(struct tcb, tcb_dtv) +#ifdef __mips_n64 +#define TP_OFFSET 0x7010 +#else +#define TP_OFFSET 0x7008 +#endif /* - * Variant II tcb, first two members are required by rtld. + * Variant I tcb. The structure layout is fixed, don't blindly + * change it! */ struct tcb { - struct tcb *tcb_self; /* required by rtld */ - void *tcb_dtv; /* required by rtld */ - struct pthread *tcb_thread; /* our hook */ - void *tcb_spare[1]; + void *tcb_dtv; + struct pthread *tcb_thread; }; /* @@ -61,7 +65,7 @@ static __inline void _tcb_set(struct tcb *tcb) { - sysarch(MIPS_SET_TLS, tcb); + sysarch(MIPS_SET_TLS, ((uint8_t*)tcb + TP_OFFSET)); } /* @@ -70,10 +74,10 @@ _tcb_set(struct tcb *tcb) static __inline struct tcb * _tcb_get(void) { - void *tcb; + uint8_t *tcb; sysarch(MIPS_GET_TLS, &tcb); - return tcb; + return ((struct tcb *)(tcb - TP_OFFSET)); } extern struct pthread *_thr_initial; diff --git a/lib/libthr/arch/mips/mips/pthread_md.c b/lib/libthr/arch/mips/mips/pthread_md.c index 53ac5971da1a..e596edc0e2ec 100644 --- a/lib/libthr/arch/mips/mips/pthread_md.c +++ b/lib/libthr/arch/mips/mips/pthread_md.c @@ -34,6 +34,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include "pthread_md.h" struct tcb * @@ -41,16 +43,17 @@ _tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; - tcb = malloc(sizeof(struct tcb)); - if (tcb) { - bzero(tcb, sizeof(struct tcb)); + tcb = _rtld_allocate_tls((initial) ? _tcb_get() : NULL, + sizeof(struct tcb), 16); + if (tcb) tcb->tcb_thread = thread; - } + return (tcb); } void _tcb_dtor(struct tcb *tcb) { - free(tcb); + + _rtld_free_tls(tcb, sizeof(struct tcb), 16); } diff --git a/lib/libthr/thread/thr_list.c b/lib/libthr/thread/thr_list.c index 249501cc5293..d27d87dac37c 100644 --- a/lib/libthr/thread/thr_list.c +++ b/lib/libthr/thread/thr_list.c @@ -149,11 +149,20 @@ _thr_alloc(struct pthread *curthread) if (total_threads > MAX_THREADS) return (NULL); atomic_fetchadd_int(&total_threads, 1); - thread = malloc(sizeof(struct pthread)); + thread = calloc(1, sizeof(struct pthread)); if (thread == NULL) { atomic_fetchadd_int(&total_threads, -1); return (NULL); } + if ((thread->sleepqueue = _sleepq_alloc()) == NULL || + (thread->wake_addr = _thr_alloc_wake_addr()) == NULL) { + thr_destroy(curthread, thread); + atomic_fetchadd_int(&total_threads, -1); + return (NULL); + } + } else { + bzero(&thread->_pthread_startzero, + __rangeof(struct pthread, _pthread_startzero, _pthread_endzero)); } if (curthread != NULL) { THR_LOCK_ACQUIRE(curthread, &tcb_lock); @@ -163,10 +172,7 @@ _thr_alloc(struct pthread *curthread) tcb = _tcb_ctor(thread, 1 /* initial tls */); } if (tcb != NULL) { - memset(thread, 0, sizeof(*thread)); thread->tcb = tcb; - thread->sleepqueue = _sleepq_alloc(); - thread->wake_addr = _thr_alloc_wake_addr(); } else { thr_destroy(curthread, thread); atomic_fetchadd_int(&total_threads, -1); @@ -194,8 +200,6 @@ _thr_free(struct pthread *curthread, struct pthread *thread) } thread->tcb = NULL; if ((curthread == NULL) || (free_thread_count >= MAX_CACHED_THREADS)) { - _sleepq_free(thread->sleepqueue); - _thr_release_wake_addr(thread->wake_addr); thr_destroy(curthread, thread); atomic_fetchadd_int(&total_threads, -1); } else { @@ -213,6 +217,10 @@ _thr_free(struct pthread *curthread, struct pthread *thread) static void thr_destroy(struct pthread *curthread __unused, struct pthread *thread) { + if (thread->sleepqueue != NULL) + _sleepq_free(thread->sleepqueue); + if (thread->wake_addr != NULL) + _thr_release_wake_addr(thread->wake_addr); free(thread); } diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index 9b9227b2bece..7a9727f715a1 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -343,6 +343,7 @@ struct pthread_key { * Thread structure. */ struct pthread { +#define _pthread_startzero tid /* Kernel thread id. */ long tid; #define TID_TERMINATED 1 @@ -506,12 +507,6 @@ struct pthread { /* Event */ td_event_msg_t event_buf; - struct wake_addr *wake_addr; -#define WAKE_ADDR(td) ((td)->wake_addr) - - /* Sleep queue */ - struct sleepqueue *sleepqueue; - /* Wait channel */ void *wchan; @@ -526,6 +521,14 @@ struct pthread { /* Deferred threads from pthread_cond_signal. */ unsigned int *defer_waiters[MAX_DEFER_WAITERS]; +#define _pthread_endzero wake_addr + + struct wake_addr *wake_addr; +#define WAKE_ADDR(td) ((td)->wake_addr) + + /* Sleep queue */ + struct sleepqueue *sleepqueue; + }; #define THR_SHOULD_GC(thrd) \ diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c index 68fdf2b49ff7..263044f446a9 100644 --- a/lib/libutil/login_class.c +++ b/lib/libutil/login_class.c @@ -452,18 +452,21 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in p = (rtp.prio > RTP_PRIO_MAX) ? 31 : p; if (rtprio(RTP_SET, 0, &rtp)) syslog(LOG_WARNING, "rtprio '%s' (%s): %m", - pwd->pw_name, lc ? lc->lc_class : LOGIN_DEFCLASS); + pwd ? pwd->pw_name : "-", + lc ? lc->lc_class : LOGIN_DEFCLASS); } else if (p < PRIO_MIN) { rtp.type = RTP_PRIO_REALTIME; rtp.prio = abs(p - PRIO_MIN + RTP_PRIO_MAX); p = (rtp.prio > RTP_PRIO_MAX) ? 1 : p; if (rtprio(RTP_SET, 0, &rtp)) syslog(LOG_WARNING, "rtprio '%s' (%s): %m", - pwd->pw_name, lc ? lc->lc_class : LOGIN_DEFCLASS); + pwd ? pwd->pw_name : "-", + lc ? lc->lc_class : LOGIN_DEFCLASS); } else { if (setpriority(PRIO_PROCESS, 0, (int)p) != 0) syslog(LOG_WARNING, "setpriority '%s' (%s): %m", - pwd->pw_name, lc ? lc->lc_class : LOGIN_DEFCLASS); + pwd ? pwd->pw_name : "-", + lc ? lc->lc_class : LOGIN_DEFCLASS); } } diff --git a/lib/libutil/pidfile.3 b/lib/libutil/pidfile.3 index d10ab81e4f8b..30c880c1ad06 100644 --- a/lib/libutil/pidfile.3 +++ b/lib/libutil/pidfile.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 16, 2011 +.Dd February 8, 2012 .Dt PIDFILE 3 .Os .Sh NAME @@ -85,6 +85,9 @@ function sets the O_CLOEXEC close-on-exec flag when opening the pidfile. The .Fn pidfile_write function writes process' PID into a previously opened file. +The file is truncated before write, so calling the +.Fn pidfile_write +function multiple times is supported. .Pp The .Fn pidfile_close @@ -147,6 +150,11 @@ if (pfh == NULL) { } /* If we cannot create pidfile from other reasons, only warn. */ warn("Cannot open or create pidfile"); + /* + * Eventhough pfh is NULL we can continue, as the other pidfile_* + * function can handle such situation by doing nothing except setting + * errno to EDOOFUS. + */ } if (daemon(0, 0) == -1) { diff --git a/lib/libutil/pidfile.c b/lib/libutil/pidfile.c index bca0315b219c..55e3e0fa1830 100644 --- a/lib/libutil/pidfile.c +++ b/lib/libutil/pidfile.c @@ -124,7 +124,7 @@ pidfile_open(const char *path, mode_t mode, pid_t *pidptr) * pidfile_write() can be called multiple times. */ fd = flopen(pfh->pf_path, - O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NONBLOCK, mode); + O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode); if (fd == -1) { if (errno == EWOULDBLOCK && pidptr != NULL) { count = 20; diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c index 5cd27b155ff4..63c63de81aa6 100644 --- a/lib/libutil/pw_util.c +++ b/lib/libutil/pw_util.c @@ -347,7 +347,8 @@ pw_edit(int notsetuid) sigprocmask(SIG_SETMASK, &oldsigset, NULL); if (stat(tempname, &st2) == -1) return (-1); - return (st1.st_mtime != st2.st_mtime); + return (st1.st_mtim.tv_sec != st2.st_mtim.tv_sec || + st1.st_mtim.tv_nsec != st2.st_mtim.tv_nsec); } /* diff --git a/lib/libypclnt/Makefile b/lib/libypclnt/Makefile index 5a3ecb42aa2c..2e302f124289 100644 --- a/lib/libypclnt/Makefile +++ b/lib/libypclnt/Makefile @@ -22,7 +22,7 @@ GENSRCS=yp.h \ yppasswd_private_clnt.c \ yppasswd_private_xdr.c -RPCGEN= rpcgen -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -C RPCSRC= ${.CURDIR}/../../include/rpcsvc/yp.x RPCSRC_PW= ${.CURDIR}/../../include/rpcsvc/yppasswd.x RPCSRC_PRIV= ${.CURDIR}/../../usr.sbin/rpc.yppasswdd/yppasswd_private.x diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c index c0afba937de7..11b962acef21 100644 --- a/libexec/rtld-elf/arm/reloc.c +++ b/libexec/rtld-elf/arm/reloc.c @@ -10,6 +10,9 @@ __FBSDID("$FreeBSD$"); #include #include #include + +#include "machine/sysarch.h" + #include "debug.h" #include "rtld.h" @@ -233,6 +236,63 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache, dbg("COPY (avoid in main)"); break; + case R_ARM_TLS_DTPOFF32: + def = find_symdef(symnum, obj, &defobj, false, cache, + lockstate); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(def->st_value); + if (__predict_true(RELOC_ALIGNED_P(where))) + *where = tmp; + else + store_ptr(where, tmp); + + dbg("TLS_DTPOFF32 %s in %s --> %p", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp); + + break; + case R_ARM_TLS_DTPMOD32: + def = find_symdef(symnum, obj, &defobj, false, cache, + lockstate); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->tlsindex); + if (__predict_true(RELOC_ALIGNED_P(where))) + *where = tmp; + else + store_ptr(where, tmp); + + dbg("TLS_DTPMOD32 %s in %s --> %p", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp); + + break; + + case R_ARM_TLS_TPOFF32: + def = find_symdef(symnum, obj, &defobj, false, cache, + lockstate); + if (def == NULL) + return -1; + + if (!defobj->tls_done && allocate_tls_offset(obj)) + return -1; + + /* XXX: FIXME */ + tmp = (Elf_Addr)def->st_value + defobj->tlsoffset + + TLS_TCB_SIZE; + if (__predict_true(RELOC_ALIGNED_P(where))) + *where = tmp; + else + store_ptr(where, tmp); + dbg("TLS_TPOFF32 %s in %s --> %p", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp); + break; + + default: dbg("sym = %lu, type = %lu, offset = %p, " "contents = %p, symbol = %s", @@ -369,11 +429,26 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj, void allocate_initial_tls(Obj_Entry *objs) { - + void **_tp = (void **)ARM_TP_ADDRESS; + + /* + * Fix the size of the static TLS block by using the maximum + * offset allocated so far and adding a bit for dynamic modules to + * use. + */ + + tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; + + (*_tp) = (void *) allocate_tls(objs, NULL, TLS_TCB_SIZE, 8); } void * __tls_get_addr(tls_index* ti) { - return (NULL); + void **_tp = (void **)ARM_TP_ADDRESS; + char *p; + + p = tls_get_addr_common((Elf_Addr **)(*_tp), ti->ti_module, ti->ti_offset); + + return (p); } diff --git a/libexec/rtld-elf/arm/rtld_machdep.h b/libexec/rtld-elf/arm/rtld_machdep.h index 8a1b7869e3f0..cd597dd21b76 100644 --- a/libexec/rtld-elf/arm/rtld_machdep.h +++ b/libexec/rtld-elf/arm/rtld_machdep.h @@ -48,20 +48,20 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_initfini_pointer(obj, target) \ (((InitFunc)(target))()) +#define TLS_TCB_SIZE 8 typedef struct { unsigned long ti_module; unsigned long ti_offset; } tls_index; #define round(size, align) \ - (((size) + (align) - 1) & ~((align) - 1)) + (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - round(size, align) + round(8, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ - round(prev_offset + prev_size, align) + round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) - /* * Lazy binding entry point, called via PLT. */ diff --git a/libexec/rtld-elf/mips/reloc.c b/libexec/rtld-elf/mips/reloc.c index 35c732e6867e..7b520c92d9b1 100644 --- a/libexec/rtld-elf/mips/reloc.c +++ b/libexec/rtld-elf/mips/reloc.c @@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +#include #include "debug.h" #include "rtld.h" @@ -244,9 +247,9 @@ _mips_rtld_bind(Obj_Entry *obj, Elf_Size reloff) _rtld_error("bind failed no symbol"); target = (Elf_Addr)(defobj->relocbase + def->st_value); - dbg("bind now/fixup at %s sym # %d in %s --> was=%p new=%p", + dbg("bind now/fixup at %s sym # %jd in %s --> was=%p new=%p", obj->path, - reloff, defobj->strtab + def->st_name, + (intmax_t)reloff, defobj->strtab + def->st_name, (void *)got[obj->local_gotno + reloff - obj->gotsym], (void *)target); got[obj->local_gotno + reloff - obj->gotsym] = target; @@ -283,8 +286,8 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) /* Relocate the local GOT entries */ got += i; - dbg("got:%p for %d entries adding %x", - got, obj->local_gotno, (uint32_t)obj->relocbase); + dbg("got:%p for %d entries adding %p", + got, obj->local_gotno, obj->relocbase); for (; i < obj->local_gotno; i++) { *got += (Elf_Addr)obj->relocbase; got++; @@ -339,8 +342,8 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) */ *got = sym->st_value + (Elf_Addr)obj->relocbase; if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) { - dbg("Warning2, i:%d maps to relocbase address:%x", - i, (uint32_t)obj->relocbase); + dbg("Warning2, i:%d maps to relocbase address:%p", + i, obj->relocbase); } } else if (sym->st_info == ELF_ST_INFO(STB_GLOBAL, STT_SECTION)) { @@ -349,8 +352,8 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) *got = sym->st_value + (Elf_Addr)obj->relocbase; if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) { - dbg("Warning3, i:%d maps to relocbase address:%x", - i, (uint32_t)obj->relocbase); + dbg("Warning3, i:%d maps to relocbase address:%p", + i, obj->relocbase); } } } else { @@ -363,8 +366,8 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) } *got = def->st_value + (Elf_Addr)defobj->relocbase; if ((Elf_Addr)(*got) == (Elf_Addr)obj->relocbase) { - dbg("Warning4, i:%d maps to relocbase address:%x", - i, (uint32_t)obj->relocbase); + dbg("Warning4, i:%d maps to relocbase address:%p", + i, obj->relocbase); dbg("via first obj symbol %s", obj->strtab + obj->symtab[i].st_name); dbg("found in obj %p:%s", @@ -443,6 +446,89 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) break; } +#ifdef __mips_n64 + case R_TYPE(TLS_DTPMOD64): +#else + case R_TYPE(TLS_DTPMOD32): +#endif + { + + const size_t rlen = sizeof(Elf_Addr); + Elf_Addr old = load_ptr(where, rlen); + Elf_Addr val = old; + + def = find_symdef(r_symndx, obj, &defobj, false, NULL, + lockstate); + if (def == NULL) + return -1; + + val += (Elf_Addr)defobj->tlsindex; + + store_ptr(where, val, rlen); + dbg("DTPMOD %s in %s %p --> %p in %s", + obj->strtab + obj->symtab[r_symndx].st_name, + obj->path, (void *)old, (void*)val, defobj->path); + break; + } + +#ifdef __mips_n64 + case R_TYPE(TLS_DTPREL64): +#else + case R_TYPE(TLS_DTPREL32): +#endif + { + const size_t rlen = sizeof(Elf_Addr); + Elf_Addr old = load_ptr(where, rlen); + Elf_Addr val = old; + + def = find_symdef(r_symndx, obj, &defobj, false, NULL, + lockstate); + if (def == NULL) + return -1; + + if (!defobj->tls_done && allocate_tls_offset(obj)) + return -1; + + val += (Elf_Addr)def->st_value - TLS_DTP_OFFSET; + store_ptr(where, val, rlen); + + dbg("DTPREL %s in %s %p --> %p in %s", + obj->strtab + obj->symtab[r_symndx].st_name, + obj->path, (void*)old, (void *)val, defobj->path); + break; + } + +#ifdef __mips_n64 + case R_TYPE(TLS_TPREL64): +#else + case R_TYPE(TLS_TPREL32): +#endif + { + const size_t rlen = sizeof(Elf_Addr); + Elf_Addr old = load_ptr(where, rlen); + Elf_Addr val = old; + + def = find_symdef(r_symndx, obj, &defobj, false, NULL, + lockstate); + + if (def == NULL) + return -1; + + if (!defobj->tls_done && allocate_tls_offset(obj)) + return -1; + + val += (Elf_Addr)(def->st_value + defobj->tlsoffset + - TLS_TP_OFFSET - TLS_TCB_SIZE); + store_ptr(where, val, rlen); + + dbg("TPREL %s in %s %p --> %p in %s", + obj->strtab + obj->symtab[r_symndx].st_name, + obj->path, (void*)old, (void *)val, defobj->path); + break; + } + + + default: dbg("sym = %lu, type = %lu, offset = %p, " "contents = %p, symbol = %s", @@ -470,8 +556,8 @@ reloc_plt(Obj_Entry *obj) const Elf_Rel *rellim; const Elf_Rel *rel; - dbg("reloc_plt obj:%p pltrel:%p sz:%d", obj, obj->pltrel, (int)obj->pltrelsize); - dbg("gottable %p num syms:%d", obj->pltgot, obj->symtabno ); + dbg("reloc_plt obj:%p pltrel:%p sz:%s", obj, obj->pltrel, (int)obj->pltrelsize); + dbg("gottable %p num syms:%s", obj->pltgot, obj->symtabno ); dbg("*****************************************************"); rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize); @@ -527,11 +613,31 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj, void allocate_initial_tls(Obj_Entry *objs) { + char *tls; + /* + * Fix the size of the static TLS block by using the maximum + * offset allocated so far and adding a bit for dynamic modules to + * use. + */ + tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; + + tls = ((char *) allocate_tls(objs, NULL, TLS_TCB_SIZE, 8) + + TLS_TP_OFFSET + TLS_TCB_SIZE); + + sysarch(MIPS_SET_TLS, tls); } void * __tls_get_addr(tls_index* ti) { - return (NULL); + Elf_Addr** tls; + char *p; + + sysarch(MIPS_GET_TLS, &tls); + + p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tls - TLS_TP_OFFSET + - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset + TLS_DTP_OFFSET); + + return (p); } diff --git a/libexec/rtld-elf/mips/rtld_machdep.h b/libexec/rtld-elf/mips/rtld_machdep.h index 8a1b7869e3f0..b7cdc00786e8 100644 --- a/libexec/rtld-elf/mips/rtld_machdep.h +++ b/libexec/rtld-elf/mips/rtld_machdep.h @@ -47,21 +47,33 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define call_initfini_pointer(obj, target) \ (((InitFunc)(target))()) - + +/* + * TLS + */ + +#define TLS_TP_OFFSET 0x7000 +#define TLS_DTP_OFFSET 0x8000 + +#ifdef __mips_n64 +#define TLS_TCB_SIZE 16 +#else +#define TLS_TCB_SIZE 8 +#endif + typedef struct { unsigned long ti_module; unsigned long ti_offset; } tls_index; #define round(size, align) \ - (((size) + (align) - 1) & ~((align) - 1)) + (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - round(size, align) + round(TLS_TCB_SIZE, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ - round(prev_offset + prev_size, align) + round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) - - + /* * Lazy binding entry point, called via PLT. */ diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 53e44d51b6dc..568d10bf23ae 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -757,6 +757,7 @@ die(void) if (msg == NULL) msg = "Fatal error"; rtld_fdputstr(STDERR_FILENO, msg); + rtld_fdputchar(STDERR_FILENO, '\n'); _exit(1); } @@ -3541,9 +3542,7 @@ tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset) return (void*) (dtv[index + 1] + offset); } -/* XXX not sure what variants to use for arm. */ - -#if defined(__ia64__) || defined(__powerpc__) +#if defined(__arm__) || defined(__ia64__) || defined(__mips__) || defined(__powerpc__) /* * Allocate Static TLS using the Variant I method. @@ -3624,8 +3623,7 @@ free_tls(void *tcb, size_t tcbsize, size_t tcbalign) #endif -#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \ - defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) /* * Allocate Static TLS using the Variant II method. diff --git a/libexec/ypxfr/Makefile b/libexec/ypxfr/Makefile index 91a42eff1776..476a296fa7f3 100644 --- a/libexec/ypxfr/Makefile +++ b/libexec/ypxfr/Makefile @@ -22,7 +22,7 @@ LDADD= -lrpcsvc CLEANFILES= ${GENSRCS} RPCDIR= ${.CURDIR}/../../include/rpcsvc -RPCGEN= rpcgen -I -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -I -C ypxfr_clnt.c: ${RPCDIR}/yp.x rm -f ${.TARGET} diff --git a/release/picobsd/tinyware/passwd/Makefile b/release/picobsd/tinyware/passwd/Makefile index 5f6b8c45bd15..fa603083bcce 100644 --- a/release/picobsd/tinyware/passwd/Makefile +++ b/release/picobsd/tinyware/passwd/Makefile @@ -26,7 +26,7 @@ CFLAGS+= -DLOGIN_CAP -DCRYPT -I. -I${.CURDIR} \ CLEANFILES= ${GENSRCS} -RPCGEN= rpcgen -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -C RPCSRC= ${DESTDIR}/usr/include/rpcsvc/yp.x RPCSRC_PW= ${DESTDIR}/usr/include/rpcsvc/yppasswd.x RPCSRC_PRIV= ${.CURDIR}/../../usr.sbin/rpc.yppasswdd/yppasswd_private.x diff --git a/release/rc.local b/release/rc.local index d84bcc2dde84..b1f9b19c2253 100755 --- a/release/rc.local +++ b/release/rc.local @@ -8,17 +8,23 @@ : ${DIALOG_ITEM_HELP=4} : ${DIALOG_ESC=255} +MACHINE=`uname -m` + kbdcontrol -d >/dev/null 2>&1 if [ $? -eq 0 ]; then # Syscons: use xterm, start interesting things on other VTYs - TERM=xterm + if [ ${MACHINE} = "pc98" ]; then + TERM=cons25w + else + TERM=xterm + fi if [ -z "$EXTERNAL_VTY_STARTED" ]; then # Init will clean these processes up if/when the system # goes multiuser touch /tmp/bsdinstall_log tail -f /tmp/bsdinstall_log > /dev/ttyv2 & - /usr/libexec/getty autologin ttyv3 + /usr/libexec/getty autologin ttyv3 & EXTERNAL_VTY_STARTED=1 fi else @@ -31,6 +37,7 @@ else echo " ansi Standard ANSI terminal" echo " vt100 VT100 or compatible terminal" echo " xterm xterm terminal emulator (or compatible)" + echo " cons25w cons25w terminal" echo echo -n "Console type [vt100]: " read TERM diff --git a/rescue/rescue/Makefile b/rescue/rescue/Makefile index 8bb8f1f71a13..e3236226edfc 100644 --- a/rescue/rescue/Makefile +++ b/rescue/rescue/Makefile @@ -125,7 +125,7 @@ CRUNCH_LIBS+= -lipx .if ${MK_ZFS} != "no" CRUNCH_LIBS+= -lavl -lnvpair -lzfs -lpthread -luutil -lumem .endif -CRUNCH_LIBS+= -lgeom -lbsdxml -ljail -lkiconv -lmd -lsbuf -lufs -lz +CRUNCH_LIBS+= -lgeom -lbsdxml -lkiconv -lmd -lsbuf -lufs -lz .if ${MACHINE_CPUARCH} == "i386" CRUNCH_PROGS_sbin+= bsdlabel sconfig fdisk diff --git a/sbin/bsdlabel/bsdlabel.8 b/sbin/bsdlabel/bsdlabel.8 index 1d3b6f3c5673..e5e47142a46b 100644 --- a/sbin/bsdlabel/bsdlabel.8 +++ b/sbin/bsdlabel/bsdlabel.8 @@ -475,7 +475,7 @@ The kernel device drivers will not allow the size of a disk partition to be decreased or the offset of a partition to be changed while it is open. .Sh COMPATIBILITY Due to the use of an -.Vt u_int32_t +.Vt uint32_t to store the number of sectors, .Bx labels are restricted to a maximum of 2^32-1 sectors. diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8 index 523cb6543ed8..0513017cd4e2 100644 --- a/sbin/fsck_ffs/fsck_ffs.8 +++ b/sbin/fsck_ffs/fsck_ffs.8 @@ -29,7 +29,7 @@ .\" @(#)fsck.8 8.4 (Berkeley) 5/9/95 .\" $FreeBSD$ .\" -.Dd April 27, 2011 +.Dd February 10, 2012 .Dt FSCK_FFS 8 .Os .Sh NAME @@ -193,6 +193,11 @@ Use the block specified immediately after the flag as the super block for the file system. An alternate super block is usually located at block 32 for UFS1, and block 160 for UFS2. +.Pp +See the +.Fl N +flag of +.Xr newfs 8 . .It Fl C Check if file system was dismounted cleanly. If so, skip file system checks (like "preen"). diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c index e51c0a906bfc..ae0ea0519e42 100644 --- a/sbin/fsck_ffs/setup.c +++ b/sbin/fsck_ffs/setup.c @@ -194,7 +194,7 @@ setup(char *dev) "-b OPTION TO FSCK TO SPECIFY THE", "LOCATION OF AN ALTERNATE", "SUPER-BLOCK TO SUPPLY NEEDED", - "INFORMATION; SEE fsck(8)."); + "INFORMATION; SEE fsck_ffs(8)."); bflag = 0; return(0); } diff --git a/sbin/fsdb/fsdbutil.c b/sbin/fsdb/fsdbutil.c index 7ed78a7f39ee..f434677beea9 100644 --- a/sbin/fsdb/fsdbutil.c +++ b/sbin/fsdb/fsdbutil.c @@ -293,22 +293,21 @@ printblocks(ino_t inum, union dinode *dp) printf("Blocks for inode %d:\n", inum); printf("Direct blocks:\n"); ndb = howmany(DIP(dp, di_size), sblock.fs_bsize); - for (i = 0; i < NDADDR; i++) { - if (DIP(dp, di_db[i]) == 0) { - putchar('\n'); - return; - } + for (i = 0; i < NDADDR && i < ndb; i++) { if (i > 0) printf(", "); blkno = DIP(dp, di_db[i]); printf("%jd", (intmax_t)blkno); - if (--ndb == 0 && (offset = blkoff(&sblock, DIP(dp, di_size))) != 0) { + } + if (ndb <= NDADDR) { + offset = blkoff(&sblock, DIP(dp, di_size)); + if (offset != 0) { nfrags = numfrags(&sblock, fragroundup(&sblock, offset)); printf(" (%d frag%s)", nfrags, nfrags > 1? "s": ""); } } putchar('\n'); - if (ndb == 0) + if (ndb <= NDADDR) return; bufp = malloc((unsigned int)sblock.fs_bsize); diff --git a/sbin/hastd/parse.y b/sbin/hastd/parse.y index eefd591dd455..2c16f34f6747 100644 --- a/sbin/hastd/parse.y +++ b/sbin/hastd/parse.y @@ -85,7 +85,7 @@ isitme(const char *name) size_t bufsize; /* - * First check if the give name matches our full hostname. + * First check if the given name matches our full hostname. */ if (gethostname(buf, sizeof(buf)) < 0) { pjdlog_errno(LOG_ERR, "gethostname() failed"); diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c index ca1ab53afa6c..81d08eb648ad 100644 --- a/sbin/hastd/primary.c +++ b/sbin/hastd/primary.c @@ -1255,7 +1255,7 @@ ggate_recv_thread(void *arg) pjdlog_debug(2, "ggate_recv: (%p) Moving request to the send queues.", hio); refcount_init(&hio->hio_countdown, ncomps); - for (ii = ncomp; ii < ncomps; ii++) + for (ii = ncomp; ii < ncomp + ncomps; ii++) QUEUE_INSERT1(hio, send, ii); } /* NOTREACHED */ @@ -1326,7 +1326,8 @@ local_send_thread(void *arg) } else { hio->hio_errors[ncomp] = 0; if (hio->hio_replication == - HAST_REPLICATION_ASYNC) { + HAST_REPLICATION_ASYNC && + !ISSYNCREQ(hio)) { ggio->gctl_error = 0; write_complete(res, hio); } diff --git a/sbin/hastd/rangelock.c b/sbin/hastd/rangelock.c index 5ff1f19daeeb..e14c5b8075f7 100644 --- a/sbin/hastd/rangelock.c +++ b/sbin/hastd/rangelock.c @@ -128,15 +128,13 @@ bool rangelock_islocked(struct rangelocks *rls, off_t offset, off_t length) { struct rlock *rl; + off_t end; PJDLOG_ASSERT(rls->rls_magic == RANGELOCKS_MAGIC); + end = offset + length; TAILQ_FOREACH(rl, &rls->rls_locks, rl_next) { - if (rl->rl_start >= offset && rl->rl_start < offset + length) - break; - else if (rl->rl_end > offset && rl->rl_end <= offset + length) - break; - else if (rl->rl_start < offset && rl->rl_end > offset + length) + if (rl->rl_start < end && rl->rl_end > offset) break; } return (rl != NULL); diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile index dafaea284e8f..a98840dde304 100644 --- a/sbin/ifconfig/Makefile +++ b/sbin/ifconfig/Makefile @@ -35,8 +35,8 @@ SRCS+= ifgre.c # GRE keys etc SRCS+= ifgif.c # GIF reversed header workaround SRCS+= ifieee80211.c regdomain.c # SIOC[GS]IEEE80211 support -DPADD+= ${LIBBSDXML} ${LIBJAIL} ${LIBSBUF} -LDADD+= -lbsdxml -ljail -lsbuf +DPADD+= ${LIBBSDXML} ${LIBSBUF} +LDADD+= -lbsdxml -lsbuf SRCS+= carp.c # SIOC[GS]VH support SRCS+= ifgroup.c # ... @@ -56,6 +56,11 @@ SRCS+= af_ipx.c # IPX support DPADD+= ${LIBIPX} LDADD+= -lipx .endif +.if ${MK_JAIL} != "no" && !defined(RELEASE_CRUNCH) && !defined(RESCUE) +CFLAGS+= -DJAIL +DPADD+= ${LIBJAIL} +LDADD+= -ljail +.endif MAN= ifconfig.8 diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 0e3c3a30bae9..5eb71eadc0ca 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -66,7 +66,9 @@ static const char rcsid[] = #include #include #include +#ifdef JAIL #include +#endif #include #include #include @@ -255,6 +257,7 @@ main(int argc, char *argv[]) ifconfig(argc, argv, 1, NULL); exit(0); } +#ifdef JAIL /* * NOTE: We have to special-case the `-vnet' command * right here as we would otherwise fail when trying @@ -268,6 +271,7 @@ main(int argc, char *argv[]) ifconfig(argc, argv, 0, NULL); exit(0); } +#endif errx(1, "interface %s does not exist", ifname); } } @@ -688,6 +692,7 @@ deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) err(1, "SIOCDIFPHYADDR"); } +#ifdef JAIL static void setifvnet(const char *jname, int dummy __unused, int s, const struct afswtch *afp) @@ -715,6 +720,7 @@ setifrvnet(const char *jname, int dummy __unused, int s, if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0) err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name); } +#endif static void setifnetmask(const char *addr, int dummy __unused, int s, @@ -1173,8 +1179,10 @@ static struct cmd basic_cmds[] = { DEF_CMD_ARG2("tunnel", settunnel), DEF_CMD("-tunnel", 0, deletetunnel), DEF_CMD("deletetunnel", 0, deletetunnel), +#ifdef JAIL DEF_CMD_ARG("vnet", setifvnet), DEF_CMD_ARG("-vnet", setifrvnet), +#endif DEF_CMD("link0", IFF_LINK0, setifflags), DEF_CMD("-link0", -IFF_LINK0, setifflags), DEF_CMD("link1", IFF_LINK1, setifflags), diff --git a/sbin/init/init.8 b/sbin/init/init.8 index 264d82286416..1d7bc2e78403 100644 --- a/sbin/init/init.8 +++ b/sbin/init/init.8 @@ -31,7 +31,7 @@ .\" @(#)init.8 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd January 23, 2011 +.Dd February 11, 2012 .Dt INIT 8 .Os .Sh NAME @@ -146,14 +146,7 @@ executes a shell for that user. When this shell dies, either because the user logged out or an abnormal termination occurred (a signal), -.Nm login -records the logout in the user accounting -database (see -.Xr getutxent 3) -and terminates. -The cycle is -then restarted by -.Nm +the cycle is restarted by executing a new .Nm getty for the line. diff --git a/sbin/init/init.c b/sbin/init/init.c index cce74bb8a0ee..e936a7898f2a 100644 --- a/sbin/init/init.c +++ b/sbin/init/init.c @@ -66,7 +66,6 @@ static const char rcsid[] = #include #include #include -#include #include #include @@ -181,8 +180,6 @@ static void setprocresources(const char *); #endif static int clang; -static void clear_session_logs(session_t *); - static int start_session_db(void); static void add_session(session_t *); static void del_session(session_t *); @@ -566,20 +563,6 @@ transition(state_t s) current_state = (state_t) (*current_state)(); } -/* - * Close out the accounting files for a login session. - * NB: should send a message to the session logger to avoid blocking. - */ -static void -clear_session_logs(session_t *sp __unused) -{ - - /* - * XXX: Use getutxline() and call pututxline() for each entry. - * Is this safe to do this here? Is it really required anyway? - */ -} - /* * Start a session and allocate a controlling terminal. * Only called by children of init after forking. @@ -780,17 +763,12 @@ single_user(void) static state_func_t runcom(void) { - struct utmpx utx; state_func_t next_transition; if ((next_transition = run_script(_PATH_RUNCOM)) != 0) return next_transition; runcom_mode = AUTOBOOT; /* the default */ - /* NB: should send a message to the session logger to avoid blocking. */ - utx.ut_type = BOOT_TIME; - gettimeofday(&utx.ut_tv, NULL); - pututxline(&utx); return (state_func_t) read_ttys; } @@ -1119,8 +1097,6 @@ read_ttys(void) * There shouldn't be any, but just in case... */ for (sp = sessions; sp; sp = snext) { - if (sp->se_process) - clear_session_logs(sp); snext = sp->se_next; free_session(sp); } @@ -1274,7 +1250,6 @@ collect_child(pid_t pid) if (! (sp = find_session(pid))) return; - clear_session_logs(sp); del_session(sp); sp->se_process = 0; @@ -1504,14 +1479,8 @@ alrm_handler(int sig) static state_func_t death(void) { - struct utmpx utx; session_t *sp; - /* NB: should send a message to the session logger to avoid blocking. */ - utx.ut_type = SHUTDOWN_TIME; - gettimeofday(&utx.ut_tv, NULL); - pututxline(&utx); - /* * Also revoke the TTY here. Because runshutdown() may reopen * the TTY whose getty we're killing here, there is no guarantee diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index 027080237bb4..370d104f5ff7 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -1,7 +1,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 10, 2011 +.Dd February 6, 2012 .Dt IPFW 8 .Os .Sh NAME @@ -1652,10 +1652,12 @@ option for details on matching fragmented packets. TCP packets only. Match if the TCP header sequence number field is set to .Ar seq . -.It Cm tcpwin Ar win -TCP packets only. -Match if the TCP header window field is set to -.Ar win . +.It Cm tcpwin Ar tcpwin-list +Matches TCP packets whose header window field is set to +.Ar tcpwin-list , +which is either a single value or a list of values or ranges +specified in the same way as +.Ar ports . .It Cm tcpoptions Ar spec TCP packets only. Match if the TCP header contains the comma separated list of diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 6b0e0f0b54b8..ac0632e4aaa0 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -512,6 +512,7 @@ static struct _s_x _port_name[] = { {"ipttl", O_IPTTL}, {"mac-type", O_MAC_TYPE}, {"tcpdatalen", O_TCPDATALEN}, + {"tcpwin", O_TCPWIN}, {"tagged", O_TAGGED}, {NULL, 0} }; @@ -1480,7 +1481,11 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth) break; case O_TCPWIN: - printf(" tcpwin %d", ntohs(cmd->arg1)); + if (F_LEN(cmd) == 1) + printf(" tcpwin %u", cmd->arg1); + else + print_newports((ipfw_insn_u16 *)cmd, 0, + O_TCPWIN); break; case O_TCPACK: @@ -3447,8 +3452,12 @@ ipfw_add(char *av[]) case TOK_TCPWIN: NEED1("tcpwin requires length"); - fill_cmd(cmd, O_TCPWIN, 0, - htons(strtoul(*av, NULL, 0))); + if (strpbrk(*av, "-,")) { + if (!add_ports(cmd, *av, 0, O_TCPWIN)) + errx(EX_DATAERR, "invalid tcpwin len %s", *av); + } else + fill_cmd(cmd, O_TCPWIN, 0, + strtoul(*av, NULL, 0)); av++; break; diff --git a/sbin/newfs_msdos/newfs_msdos.8 b/sbin/newfs_msdos/newfs_msdos.8 index 5896992b9493..ce51113c700b 100644 --- a/sbin/newfs_msdos/newfs_msdos.8 +++ b/sbin/newfs_msdos/newfs_msdos.8 @@ -180,27 +180,27 @@ For reference purposes, this structure is presented below. .Bd -literal struct bsbpb { - u_int16_t bpbBytesPerSec; /* [-S] bytes per sector */ - u_int8_t bpbSecPerClust; /* [-c] sectors per cluster */ - u_int16_t bpbResSectors; /* [-r] reserved sectors */ - u_int8_t bpbFATs; /* [-n] number of FATs */ - u_int16_t bpbRootDirEnts; /* [-e] root directory entries */ - u_int16_t bpbSectors; /* [-s] total sectors */ - u_int8_t bpbMedia; /* [-m] media descriptor */ - u_int16_t bpbFATsecs; /* [-a] sectors per FAT */ - u_int16_t bpbSecPerTrack; /* [-u] sectors per track */ - u_int16_t bpbHeads; /* [-h] drive heads */ - u_int32_t bpbHiddenSecs; /* [-o] hidden sectors */ - u_int32_t bpbHugeSectors; /* [-s] big total sectors */ + uint16_t bpbBytesPerSec; /* [-S] bytes per sector */ + uint8_t bpbSecPerClust; /* [-c] sectors per cluster */ + uint16_t bpbResSectors; /* [-r] reserved sectors */ + uint8_t bpbFATs; /* [-n] number of FATs */ + uint16_t bpbRootDirEnts; /* [-e] root directory entries */ + uint16_t bpbSectors; /* [-s] total sectors */ + uint8_t bpbMedia; /* [-m] media descriptor */ + uint16_t bpbFATsecs; /* [-a] sectors per FAT */ + uint16_t bpbSecPerTrack; /* [-u] sectors per track */ + uint16_t bpbHeads; /* [-h] drive heads */ + uint32_t bpbHiddenSecs; /* [-o] hidden sectors */ + uint32_t bpbHugeSectors; /* [-s] big total sectors */ }; /* FAT32 extensions */ struct bsxbpb { - u_int32_t bpbBigFATsecs; /* [-a] big sectors per FAT */ - u_int16_t bpbExtFlags; /* control flags */ - u_int16_t bpbFSVers; /* file system version */ - u_int32_t bpbRootClust; /* root directory start cluster */ - u_int16_t bpbFSInfo; /* [-i] file system info sector */ - u_int16_t bpbBackup; /* [-k] backup boot sector */ + uint32_t bpbBigFATsecs; /* [-a] big sectors per FAT */ + uint16_t bpbExtFlags; /* control flags */ + uint16_t bpbFSVers; /* file system version */ + uint32_t bpbRootClust; /* root directory start cluster */ + uint16_t bpbFSInfo; /* [-i] file system info sector */ + uint16_t bpbBackup; /* [-k] backup boot sector */ }; .Ed .Sh LIMITATION diff --git a/sbin/reboot/nextboot.sh b/sbin/reboot/nextboot.sh index 253ccf797b2f..655e53305911 100644 --- a/sbin/reboot/nextboot.sh +++ b/sbin/reboot/nextboot.sh @@ -1,9 +1,29 @@ #! /bin/sh # -# Copyright 2002. Gordon Tetlow. -# gordon@FreeBSD.org +# Copyright (c) 2002 Gordon Tetlow. All rights reserved. # Copyright (c) 2012 Sandvine Incorporated. All rights reserved. # +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# # $FreeBSD$ delete="NO" diff --git a/sbin/route/route.c b/sbin/route/route.c index 4b2f16ea73b6..717a09ad2a8b 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -460,8 +460,8 @@ netname(struct sockaddr *sa) * Guess at the subnet mask, assuming reasonable * width subnet fields. */ - while (in.s_addr &~ mask) - mask = (long)mask >> subnetshift; + while (in.s_addr & ~mask) + mask |= mask >> subnetshift; net = in.s_addr & mask; while ((mask & 1) == 0) mask >>= 1, net >>= 1; diff --git a/share/man/man3/Makefile b/share/man/man3/Makefile index 470650693427..d1453ebc308f 100644 --- a/share/man/man3/Makefile +++ b/share/man/man3/Makefile @@ -10,6 +10,7 @@ MAN= assert.3 \ fpgetround.3 \ intro.3 \ makedev.3 \ + offsetof.3 \ ${PTHREAD_MAN} \ queue.3 \ siginfo.3 \ diff --git a/share/man/man3/offsetof.3 b/share/man/man3/offsetof.3 new file mode 100644 index 000000000000..e63916b18483 --- /dev/null +++ b/share/man/man3/offsetof.3 @@ -0,0 +1,47 @@ +.\" $OpenBSD: offsetof.3,v 1.2 2010/02/18 18:30:19 jmc Exp $ +.\" +.\" Copyright (c) 2010 Thomas Pfaff +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 18 2010 +.Dt OFFSETOF 3 +.Os +.Sh NAME +.Nm offsetof +.Nd offset of a structure member +.Sh SYNOPSIS +.Fd #include +.Ft size_t +.Fn offsetof "type" "member" +.Sh DESCRIPTION +The +.Fn offsetof +macro expands to an integer constant expression of type +.Ft size_t +and yields the offset, +in bytes, of the field +.Ar member +from the start of the structure +.Ar type . +.Pp +A compiler error will result if +.Ar member +is not aligned to a byte boundary (i.e. it is a bit-field). +.Sh STANDARDS +The +.Fn offsetof +macro conforms to +.St -ansiC . diff --git a/share/man/man4/ada.4 b/share/man/man4/ada.4 index c807a4bf9c6a..9e31756d55bc 100644 --- a/share/man/man4/ada.4 +++ b/share/man/man4/ada.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 8, 2011 +.Dd February 8, 2012 .Dt ADA 4 .Os .Sh NAME @@ -139,7 +139,6 @@ The per-device default is to leave it as-is (follow global setting). ATA device nodes .El .Sh SEE ALSO -.Xr ad 4 , .Xr ahci 4 , .Xr cam 4 , .Xr da 4 , diff --git a/share/man/man4/agp.4 b/share/man/man4/agp.4 index 06bee7374fb6..8af97d6387e1 100644 --- a/share/man/man4/agp.4 +++ b/share/man/man4/agp.4 @@ -80,8 +80,8 @@ The result is a pointer to the following structure: .Bd -literal typedef struct _agp_info { agp_version version; /* version of the driver */ - u_int32_t bridge_id; /* bridge vendor/device */ - u_int32_t agp_mode; /* mode info of bridge */ + uint32_t bridge_id; /* bridge vendor/device */ + uint32_t agp_mode; /* mode info of bridge */ off_t aper_base; /* base of aperture */ size_t aper_size; /* size of aperture */ size_t pg_total; /* max pages (swap + system) */ @@ -105,7 +105,7 @@ This takes the following structure: .Bd -literal typedef struct _agp_setup { - u_int32_t agp_mode; /* mode info of bridge */ + uint32_t agp_mode; /* mode info of bridge */ } agp_setup; .Ed .Pp @@ -120,8 +120,8 @@ takes the following structure: typedef struct _agp_allocate { int key; /* tag of allocation */ size_t pg_count; /* number of pages */ - u_int32_t type; /* 0 == normal, other devspec */ - u_int32_t physical; /* device specific (some devices + uint32_t type; /* 0 == normal, other devspec */ + uint32_t physical; /* device specific (some devices * need a phys address of the * actual page behind the gatt * table) */ @@ -159,7 +159,7 @@ takes the following structure: .Bd -literal typedef struct _agp_unbind { int key; /* tag of allocation */ - u_int32_t priority; /* priority for paging out */ + uint32_t priority; /* priority for paging out */ } agp_unbind; .Ed .El diff --git a/share/man/man4/cd.4 b/share/man/man4/cd.4 index 83b9f3b193b9..47ce3bd522f0 100644 --- a/share/man/man4/cd.4 +++ b/share/man/man4/cd.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 8, 2009 +.Dd February 8, 2012 .Dt CD 4 .Os .Sh NAME @@ -52,7 +52,7 @@ but it will only last until the .Tn CD-ROM is unmounted. In general the interfaces are similar to those described by -.Xr ad 4 +.Xr ada 4 and .Xr da 4 . .Pp diff --git a/share/man/man4/da.4 b/share/man/man4/da.4 index cf5693484ff0..39e1dbabfb96 100644 --- a/share/man/man4/da.4 +++ b/share/man/man4/da.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 2, 2003 +.Dd February 8, 2012 .Dt DA 4 .Os .Sh NAME @@ -195,7 +195,7 @@ SCSI disk device nodes .Sh DIAGNOSTICS None. .Sh SEE ALSO -.Xr ad 4 , +.Xr ada 4 , .Xr cam 4 , .Xr geom 4 , .Xr bsdlabel 8 , diff --git a/share/man/man4/ed.4 b/share/man/man4/ed.4 index d002b9613b47..3bc70774ae2b 100644 --- a/share/man/man4/ed.4 +++ b/share/man/man4/ed.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 9, 2009 +.Dd February 8, 2012 .Dt ED 4 .Os .Sh NAME @@ -435,7 +435,7 @@ Some devices supported by do not generate the link state change events used by .Xr devd 8 to start -.Xr dhclinet 8 . +.Xr dhclient 8 . If you have problems with .Xr dhclient 8 not starting and the device is always attached to the network it may diff --git a/share/man/man4/icmp6.4 b/share/man/man4/icmp6.4 index e6c366502322..1c6026f8fb2c 100644 --- a/share/man/man4/icmp6.4 +++ b/share/man/man4/icmp6.4 @@ -140,13 +140,13 @@ This header corresponds to the structure and has the following definition: .Bd -literal -offset indent struct icmp6_hdr { - u_int8_t icmp6_type; /* type field */ - u_int8_t icmp6_code; /* code field */ - u_int16_t icmp6_cksum; /* checksum field */ + uint8_t icmp6_type; /* type field */ + uint8_t icmp6_code; /* code field */ + uint16_t icmp6_cksum; /* checksum field */ union { - u_int32_t icmp6_un_data32[1]; /* type-specific */ - u_int16_t icmp6_un_data16[2]; /* type-specific */ - u_int8_t icmp6_un_data8[4]; /* type-specific */ + uint32_t icmp6_un_data32[1]; /* type-specific */ + uint16_t icmp6_un_data16[2]; /* type-specific */ + uint8_t icmp6_un_data8[4]; /* type-specific */ } icmp6_dataun; } __packed; diff --git a/share/man/man4/ip6.4 b/share/man/man4/ip6.4 index b79685192b46..fdbb9563d1ed 100644 --- a/share/man/man4/ip6.4 +++ b/share/man/man4/ip6.4 @@ -75,12 +75,12 @@ The header has the following definition: struct ip6_hdr { union { struct ip6_hdrctl { - u_int32_t ip6_un1_flow; /* 20 bits of flow ID */ - u_int16_t ip6_un1_plen; /* payload length */ - u_int8_t ip6_un1_nxt; /* next header */ - u_int8_t ip6_un1_hlim; /* hop limit */ + uint32_t ip6_un1_flow; /* 20 bits of flow ID */ + uint16_t ip6_un1_plen; /* payload length */ + uint8_t ip6_un1_nxt; /* next header */ + uint8_t ip6_un1_hlim; /* hop limit */ } ip6_un1; - u_int8_t ip6_un2_vfc; /* version and class */ + uint8_t ip6_un2_vfc; /* version and class */ } ip6_ctlun; struct in6_addr ip6_src; /* source address */ struct in6_addr ip6_dst; /* destination address */ @@ -121,8 +121,8 @@ The IPv6 header may be followed by any number of extension headers that start with the following generic definition: .Bd -literal -offset indent struct ip6_ext { - u_int8_t ip6e_nxt; - u_int8_t ip6e_len; + uint8_t ip6e_nxt; + uint8_t ip6e_len; } __packed; .Ed .Ss Options @@ -281,8 +281,8 @@ The option is stored in the following structure in the ancillary data returned: .Bd -literal struct ip6_hbh { - u_int8_t ip6h_nxt; /* next header */ - u_int8_t ip6h_len; /* length in units of 8 octets */ + uint8_t ip6h_nxt; /* next header */ + uint8_t ip6h_len; /* length in units of 8 octets */ /* followed by options */ } __packed; .Ed @@ -301,8 +301,8 @@ The option is stored in the following structure in the ancillary data returned: .Bd -literal struct ip6_dest { - u_int8_t ip6d_nxt; /* next header */ - u_int8_t ip6d_len; /* length in units of 8 octets */ + uint8_t ip6d_nxt; /* next header */ + uint8_t ip6d_len; /* length in units of 8 octets */ /* followed by options */ } __packed; .Ed @@ -333,10 +333,10 @@ The header is stored in the following structure in the ancillary data returned: .Bd -literal struct ip6_rthdr { - u_int8_t ip6r_nxt; /* next header */ - u_int8_t ip6r_len; /* length in units of 8 octets */ - u_int8_t ip6r_type; /* routing type */ - u_int8_t ip6r_segleft; /* segments left */ + uint8_t ip6r_nxt; /* next header */ + uint8_t ip6r_len; /* length in units of 8 octets */ + uint8_t ip6r_type; /* routing type */ + uint8_t ip6r_segleft; /* segments left */ /* followed by routing-type-specific data */ } __packed; .Ed diff --git a/share/man/man4/isci.4 b/share/man/man4/isci.4 index 4d00dc8cd970..b99cb8cfe596 100644 --- a/share/man/man4/isci.4 +++ b/share/man/man4/isci.4 @@ -57,7 +57,7 @@ The .Nm driver provides support for Intel C600 .Tn SAS -controller. +controllers. .Sh CONFIGURATION To force legacy interrupts for all .Nm @@ -77,9 +77,11 @@ hw.isci.debug_level variable to a value between 1 and 4 in .Xr loader.conf 5 . .Pp -The hardware layer in the isci driver has extensive logging capabilities -which are disabled by default for performance reasons. These can be enabled -by adding +The hardware layer in the +.Nm +driver has extensive logging capabilities +which are disabled by default for performance reasons. +These can be enabled by adding .Bd -literal -offset indent options ISCI_LOGGING .Ed @@ -91,12 +93,12 @@ to the kernel configuration file. .Xr da 4 , .Xr pci 4 , .Xr sa 4 , -.Xr scsi 4 . +.Xr scsi 4 .Sh HISTORY The .Nm driver first appeared in -.Fx 10.0 . +.Fx 8.3 and 9.1 . .Sh AUTHORS .An -nosplit The diff --git a/share/man/man4/lmc.4 b/share/man/man4/lmc.4 index 439a10fcc70b..2cf6e49aa83f 100644 --- a/share/man/man4/lmc.4 +++ b/share/man/man4/lmc.4 @@ -43,7 +43,7 @@ .\" this program; if not, write to the Free Software Foundation, Inc., 59 .\" Temple Place - Suite 330, Boston, MA 02111-1307, USA. .\" -.Dd July 23, 2011 +.Dd February 8, 2012 .Dt LMC 4 .Os .\" @@ -179,7 +179,7 @@ higher-level issues like protocol multiplexing and security. This driver is compatible with several line protocol packages: .Bl -tag -width "Generic HDLC" .It Sy "Netgraph" -.Xr Netgraph 4 +.Xr netgraph 4 implements many basic packet-handling functions as kernel loadable modules. They can be interconnected in a graph to implement many protocols. Configuration is done from userland without rebuilding the kernel. diff --git a/share/man/man4/mem.4 b/share/man/man4/mem.4 index 5dd2cb98f1ec..38c5110ae537 100644 --- a/share/man/man4/mem.4 +++ b/share/man/man4/mem.4 @@ -101,8 +101,8 @@ The region cannot be written to. Memory ranges are described by .Vt struct mem_range_desc : .Bd -literal -offset indent -u_int64_t mr_base; /\(** physical base address \(**/ -u_int64_t mr_len; /\(** physical length of region \(**/ +uint64_t mr_base; /\(** physical base address \(**/ +uint64_t mr_len; /\(** physical length of region \(**/ int mr_flags; /\(** attributes of region \(**/ char mr_owner[8]; .Ed diff --git a/share/man/man4/mps.4 b/share/man/man4/mps.4 index 2899747f38ec..54b0c0b0a245 100644 --- a/share/man/man4/mps.4 +++ b/share/man/man4/mps.4 @@ -31,10 +31,10 @@ .\" .\" Author: Ken Merry .\" -.\" $Id: //depot/SpectraBSD/head/share/man/man4/mps.4#4 $ +.\" $Id: //depot/SpectraBSD/head/share/man/man4/mps.4#6 $ .\" $FreeBSD$ .\" -.Dd September 13, 2010 +.Dd February 7, 2012 .Dt MPS 4 .Os .Sh NAME @@ -58,7 +58,7 @@ The .Nm driver provides support for LSI Logic Fusion-MPT 2 .Tn SAS -controllers. +controllers and WarpDrive solid state storage cards. .Sh HARDWARE The .Nm @@ -90,6 +90,16 @@ driver instances, set the following tunable value in hw.mps.disable_msi=1 .Ed .Pp +To disable MSI interrupts for a specific +.Nm +driver instance, set the following tunable value in +.Xr loader.conf 5 : +.Bd -literal -offset indent +dev.mps.X.disable_msi=1 +.Ed +.Pp +where X is the adapter number. +.Pp To disable MSI-X interrupts for all .Nm driver instances, set the following tunable value in @@ -98,19 +108,51 @@ driver instances, set the following tunable value in hw.mps.disable_msix=1 .Ed .Pp -To allow the driver to send multiple task management commands (like abort, -LUN reset, etc.), set the following variable: +To disable MSI-X interrupts for a specific +.Nm +driver instance, set the following tunable value in +.Xr loader.conf 5 : .Bd -literal -offset indent -hw.mps.X.allow_multiple_tm_cmds=1 +dev.mps.X.disable_msix=1 .Ed .Pp -via -.Xr loader.conf 5 -or -.Xr sysctl 8 , -where X is the adapter number. -By default the driver only sends one task management command at a time, to -avoid causing a potential controller lock-up. +To set the maximum number of DMA chains allocated for all adapters, +set the following variable in +.Xr loader.conf 5 : +.Bd -literal -offset indent +hw.mps.max_chains=NNNN +.Ed +.Pp +To set the maximum number of DMA chains allocated for a specific adapter, +set the following variable in +.Xr loader.conf 5 : +.Bd -literal -offset indent +dev.mps.X.max_chains=NNNN +.Ed +.Pp +This variable may also be viewed via +.Xr sysctl 8 +to see the maximum set for a given adapter. +.Pp +The current number of free chain frames may be seen via the +dev.mps.X.chain_free +.Xr sysctl 8 +variable. +.Pp +The lowest number of free chain frames may be seen via the +dev.mps.X.chain_free_lowwater +.Xr sysctl 8 +variable. +.Pp +The current number of active I/O commands is shown in the +dev.mps.X.io_cmds_active +.Xr sysctl 8 +variable. +.Pp +The maximum number of active I/O command seen since boot is shown in the +dev.mps.X.io_cmds_highwater +.Xr sysctl 8 +variable. .Sh DEBUGGING To enable debugging prints from the .Nm @@ -142,7 +184,9 @@ Enable prints for controller events. .Xr pci 4 , .Xr sa 4 , .Xr scsi 4 , -.Xr targ 4 +.Xr targ 4 , +.Xr loader.conf 5 , +.Xr sysctl 8 .Sh HISTORY The .Nm @@ -154,20 +198,19 @@ The .Nm driver was originally written by .An Scott Long Aq scottl@FreeBSD.org . +It has been improved and tested by LSI Logic Corporation. This man page was written by .An Ken Merry Aq ken@FreeBSD.org . .Sh BUGS -This driver is still in development, it has only been tested on the amd64 -architecture and has some known shortcomings: +This driver has a couple of known shortcomings: .Bl -bullet -compact .It -No IR (Integrated RAID) support. +Not endian safe. +It only works on little endian machines (e.g. amd64 and i386). .It -No userland utility support (e.g. -.Xr mptutil 8). +No userland utility available (e.g. +.Xr mptutil 8) .It -Sometimes the driver gets into a state where devices arrive and depart multiple -times, without user intervention. -.It -The error recovery code isn't complete. +The driver probes devices sequentially. +If your system has a large number of devices, the probe will take a while. .El diff --git a/share/man/man4/mtio.4 b/share/man/man4/mtio.4 index f3dd602dc33f..e8056e6f65a4 100644 --- a/share/man/man4/mtio.4 +++ b/share/man/man4/mtio.4 @@ -175,7 +175,7 @@ struct mtget { #if defined (__FreeBSD__) int32_t mt_blksiz; /* presently operating blocksize */ int32_t mt_density; /* presently operating density */ - u_int32_t mt_comp; /* presently operating compression */ + uint32_t mt_comp; /* presently operating compression */ int32_t mt_blksiz0; /* blocksize for mode 0 */ int32_t mt_blksiz1; /* blocksize for mode 1 */ int32_t mt_blksiz2; /* blocksize for mode 2 */ @@ -185,10 +185,10 @@ struct mtget { int32_t mt_density2; /* density for mode 2 */ int32_t mt_density3; /* density for mode 3 */ /* the following are not yet implemented */ - u_int32_t mt_comp0; /* compression type for mode 0 */ - u_int32_t mt_comp1; /* compression type for mode 1 */ - u_int32_t mt_comp2; /* compression type for mode 2 */ - u_int32_t mt_comp3; /* compression type for mode 3 */ + uint32_t mt_comp0; /* compression type for mode 0 */ + uint32_t mt_comp1; /* compression type for mode 1 */ + uint32_t mt_comp2; /* compression type for mode 2 */ + uint32_t mt_comp3; /* compression type for mode 3 */ /* end not yet implemented */ #endif int32_t mt_fileno; /* relative file number of current position */ @@ -203,23 +203,23 @@ struct scsi_tape_errors { * Check Condition noted for these operations. The act * of issuing an MTIOCERRSTAT unlatches and clears them. */ - u_int8_t io_sense[32]; /* Last Sense Data For Data I/O */ + uint8_t io_sense[32]; /* Last Sense Data For Data I/O */ int32_t io_resid; /* residual count from last Data I/O */ - u_int8_t io_cdb[16]; /* Command that Caused the Last Data Sense */ - u_int8_t ctl_sense[32]; /* Last Sense Data For Control I/O */ + uint8_t io_cdb[16]; /* Command that Caused the Last Data Sense */ + uint8_t ctl_sense[32]; /* Last Sense Data For Control I/O */ int32_t ctl_resid; /* residual count from last Control I/O */ - u_int8_t ctl_cdb[16]; /* Command that Caused the Last Control Sense */ + uint8_t ctl_cdb[16]; /* Command that Caused the Last Control Sense */ /* * These are the read and write cumulative error counters. * (how to reset cumulative error counters is not yet defined). * (not implemented as yet but space is being reserved for them) */ struct { - u_int32_t retries; /* total # retries performed */ - u_int32_t corrected; /* total # corrections performed */ - u_int32_t processed; /* total # corrections successful */ - u_int32_t failures; /* total # corrections/retries failed */ - u_int64_t nbytes; /* total # bytes processed */ + uint32_t retries; /* total # retries performed */ + uint32_t corrected; /* total # corrections performed */ + uint32_t processed; /* total # corrections successful */ + uint32_t failures; /* total # corrections/retries failed */ + uint64_t nbytes; /* total # bytes processed */ } wterr, rderr; }; @@ -265,18 +265,18 @@ union mterrstat { * rethink these ioctls to support all the entities they haul into * the picture (64 bit blocks, logical file record numbers, etc..). */ -#define MTIOCRDSPOS _IOR('m', 5, u_int32_t) /* get logical blk addr */ -#define MTIOCRDHPOS _IOR('m', 6, u_int32_t) /* get hardware blk addr */ -#define MTIOCSLOCATE _IOW('m', 5, u_int32_t) /* seek to logical blk addr */ -#define MTIOCHLOCATE _IOW('m', 6, u_int32_t) /* seek to hardware blk addr */ +#define MTIOCRDSPOS _IOR('m', 5, uint32_t) /* get logical blk addr */ +#define MTIOCRDHPOS _IOR('m', 6, uint32_t) /* get hardware blk addr */ +#define MTIOCSLOCATE _IOW('m', 5, uint32_t) /* seek to logical blk addr */ +#define MTIOCHLOCATE _IOW('m', 6, uint32_t) /* seek to hardware blk addr */ #define MTIOCERRSTAT _IOR('m', 7, union mterrstat) /* get tape errors */ /* * Set EOT model- argument is number of filemarks to end a tape with. * Note that not all possible values will be accepted. */ -#define MTIOCSETEOTMODEL _IOW('m', 8, u_int32_t) +#define MTIOCSETEOTMODEL _IOW('m', 8, uint32_t) /* Get current EOT model */ -#define MTIOCGETEOTMODEL _IOR('m', 8, u_int32_t) +#define MTIOCGETEOTMODEL _IOR('m', 8, uint32_t) #ifndef _KERNEL #define DEFTAPE "/dev/nsa0" diff --git a/share/man/man4/natm.4 b/share/man/man4/natm.4 index 59e5559d3fd2..a553f6ebd9e5 100644 --- a/share/man/man4/natm.4 +++ b/share/man/man4/natm.4 @@ -23,11 +23,11 @@ The NATM layer uses a to specify a virtual circuit: .Bd -literal -offset indent struct sockaddr_natm { - u_int8_t snatm_len; /* length */ - u_int8_t snatm_family; /* AF_NATM */ + uint8_t snatm_len; /* length */ + uint8_t snatm_family; /* AF_NATM */ char snatm_if[IFNAMSIZ]; /* interface name */ - u_int16_t snatm_vci; /* vci */ - u_int8_t snatm_vpi; /* vpi */ + uint16_t snatm_vci; /* vci */ + uint8_t snatm_vpi; /* vpi */ }; .Ed .Pp diff --git a/share/man/man4/net80211.4 b/share/man/man4/net80211.4 index 693f6b92f2e8..1af240d53ef3 100644 --- a/share/man/man4/net80211.4 +++ b/share/man/man4/net80211.4 @@ -64,7 +64,7 @@ This structure is defined as follows: .Bd -literal struct ieee80211req { char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */ - u_int16_t i_type; /* req type */ + uint16_t i_type; /* req type */ int16_t i_val; /* Index or simple value */ int16_t i_len; /* Index or simple value */ void *i_data; /* Extra data */ diff --git a/share/man/man4/ng_async.4 b/share/man/man4/ng_async.4 index bb6b0be929d5..2349cb3c6fac 100644 --- a/share/man/man4/ng_async.4 +++ b/share/man/man4/ng_async.4 @@ -118,9 +118,9 @@ Sets the node configuration, which is described by a .Bd -literal -offset 4n struct ng_async_cfg { u_char enabled; /* Turn encoding on/off */ - u_int16_t amru; /* Max receive async frame len */ - u_int16_t smru; /* Max receive sync frame len */ - u_int32_t accm; /* ACCM encoding */ + uint16_t amru; /* Max receive async frame len */ + uint16_t smru; /* Max receive sync frame len */ + uint32_t accm; /* ACCM encoding */ }; .Ed .Pp diff --git a/share/man/man4/ng_bridge.4 b/share/man/man4/ng_bridge.4 index 8884e3395587..b00dc6088b8b 100644 --- a/share/man/man4/ng_bridge.4 +++ b/share/man/man4/ng_bridge.4 @@ -108,9 +108,9 @@ as an argument: struct ng_bridge_config { u_char ipfw[NG_BRIDGE_MAX_LINKS]; /* enable ipfw */ u_char debugLevel; /* debug level */ - u_int32_t loopTimeout; /* link loopback mute time */ - u_int32_t maxStaleness; /* max host age before nuking */ - u_int32_t minStableAge; /* min time for a stable host */ + uint32_t loopTimeout; /* link loopback mute time */ + uint32_t maxStaleness; /* max host age before nuking */ + uint32_t minStableAge; /* min time for a stable host */ }; .Ed .Pp @@ -155,20 +155,20 @@ currently connected: .Bd -literal -offset 0n /* Statistics structure (one for each link) */ struct ng_bridge_link_stats { - u_int64_t recvOctets; /* total octets rec'd on link */ - u_int64_t recvPackets; /* total pkts rec'd on link */ - u_int64_t recvMulticasts; /* multicast pkts rec'd on link */ - u_int64_t recvBroadcasts; /* broadcast pkts rec'd on link */ - u_int64_t recvUnknown; /* pkts rec'd with unknown dest addr */ - u_int64_t recvRunts; /* pkts rec'd less than 14 bytes */ - u_int64_t recvInvalid; /* pkts rec'd with bogus source addr */ - u_int64_t xmitOctets; /* total octets xmit'd on link */ - u_int64_t xmitPackets; /* total pkts xmit'd on link */ - u_int64_t xmitMulticasts; /* multicast pkts xmit'd on link */ - u_int64_t xmitBroadcasts; /* broadcast pkts xmit'd on link */ - u_int64_t loopDrops; /* pkts dropped due to loopback */ - u_int64_t loopDetects; /* number of loop detections */ - u_int64_t memoryFailures; /* times couldn't get mem or mbuf */ + uint64_t recvOctets; /* total octets rec'd on link */ + uint64_t recvPackets; /* total pkts rec'd on link */ + uint64_t recvMulticasts; /* multicast pkts rec'd on link */ + uint64_t recvBroadcasts; /* broadcast pkts rec'd on link */ + uint64_t recvUnknown; /* pkts rec'd with unknown dest addr */ + uint64_t recvRunts; /* pkts rec'd less than 14 bytes */ + uint64_t recvInvalid; /* pkts rec'd with bogus source addr */ + uint64_t xmitOctets; /* total octets xmit'd on link */ + uint64_t xmitPackets; /* total pkts xmit'd on link */ + uint64_t xmitMulticasts; /* multicast pkts xmit'd on link */ + uint64_t xmitBroadcasts; /* broadcast pkts xmit'd on link */ + uint64_t loopDrops; /* pkts dropped due to loopback */ + uint64_t loopDetects; /* number of loop detections */ + uint64_t memoryFailures; /* times couldn't get mem or mbuf */ }; .Ed .It Dv NGM_BRIDGE_CLR_STATS diff --git a/share/man/man4/ng_btsocket.4 b/share/man/man4/ng_btsocket.4 index 7db8178b1626..22763f98626e 100644 --- a/share/man/man4/ng_btsocket.4 +++ b/share/man/man4/ng_btsocket.4 @@ -154,7 +154,7 @@ The Bluetooth L2CAP socket address is defined as follows: struct sockaddr_l2cap { u_char l2cap_len; /* total length */ u_char l2cap_family; /* address family */ - u_int16_t l2cap_psm; /* Protocol/Service Multiplexor */ + uint16_t l2cap_psm; /* Protocol/Service Multiplexor */ bdaddr_t l2cap_bdaddr; /* address */ }; .Ed @@ -272,7 +272,7 @@ struct sockaddr_rfcomm { u_char rfcomm_len; /* total length */ u_char rfcomm_family; /* address family */ bdaddr_t rfcomm_bdaddr; /* address */ - u_int8_t rfcomm_channel; /* channel */ + uint8_t rfcomm_channel; /* channel */ }; .Ed .Ss Dv SOCK_STREAM Ss RFCOMM sockets diff --git a/share/man/man4/ng_car.4 b/share/man/man4/ng_car.4 index a536fb704444..080986e4da19 100644 --- a/share/man/man4/ng_car.4 +++ b/share/man/man4/ng_car.4 @@ -123,15 +123,15 @@ Return current node configuration as .Vt "struct ng_car_bulkconf" .Bd -literal struct ng_car_hookconf { - u_int64_t cbs; /* Committed burst size */ - u_int64_t ebs; /* Exceeded/Peak burst size */ - u_int64_t cir; /* Committed information rate */ - u_int64_t pir; /* Peak information rate */ - u_int8_t green_action; /* Action for green packets */ - u_int8_t yellow_action; /* Action for yellow packets */ - u_int8_t red_action; /* Action for red packets */ - u_int8_t mode; /* operation mode */ - u_int8_t opt; /* mode options */ + uint64_t cbs; /* Committed burst size */ + uint64_t ebs; /* Exceeded/Peak burst size */ + uint64_t cir; /* Committed information rate */ + uint64_t pir; /* Peak information rate */ + uint8_t green_action; /* Action for green packets */ + uint8_t yellow_action; /* Action for yellow packets */ + uint8_t red_action; /* Action for red packets */ + uint8_t mode; /* operation mode */ + uint8_t opt; /* mode options */ }; /* possible actions (..._action) */ @@ -161,12 +161,12 @@ Return node statistics as .Vt "struct ng_car_bulkstats" .Bd -literal struct ng_car_hookstats { - u_int64_t passed_pkts; - u_int64_t droped_pkts; - u_int64_t green_pkts; - u_int64_t yellow_pkts; - u_int64_t red_pkts; - u_int64_t errors; + uint64_t passed_pkts; + uint64_t droped_pkts; + uint64_t green_pkts; + uint64_t yellow_pkts; + uint64_t red_pkts; + uint64_t errors; }; struct ng_car_bulkstats { diff --git a/share/man/man4/ng_ccatm.4 b/share/man/man4/ng_ccatm.4 index 3a9e1212f060..1010c0fba5f3 100644 --- a/share/man/man4/ng_ccatm.4 +++ b/share/man/man4/ng_ccatm.4 @@ -110,7 +110,7 @@ The interface on these hooks is defined in and uses a structure .Bd -literal struct ccatm_op { - u_int32_t op; /* request code */ + uint32_t op; /* request code */ u_char data[]; /* optional data */ }; .Ed @@ -230,7 +230,7 @@ struct ngm_ccatm_get_addresses { struct ngm_ccatm_address_req addr[0]; }; struct ngm_ccatm_address_req { - u_int32_t port; + uint32_t port; struct uni_addr addr; }; .Ed diff --git a/share/man/man4/ng_cisco.4 b/share/man/man4/ng_cisco.4 index d2b382f86132..e4300a040b9c 100644 --- a/share/man/man4/ng_cisco.4 +++ b/share/man/man4/ng_cisco.4 @@ -148,8 +148,8 @@ Returns a .Dv "struct ngciscostat" : .Bd -literal -offset 4n struct ngciscostat { - u_int32_t seq_retries; /* # unack'd retries */ - u_int32_t keepalive_period; /* in seconds */ + uint32_t seq_retries; /* # unack'd retries */ + uint32_t keepalive_period; /* in seconds */ }; .Ed .El diff --git a/share/man/man4/ng_etf.4 b/share/man/man4/ng_etf.4 index 18bb99e88a2a..bc42726cbf38 100644 --- a/share/man/man4/ng_etf.4 +++ b/share/man/man4/ng_etf.4 @@ -102,7 +102,7 @@ are specified in a structure of type .Bd -literal -offset 4n struct ng_etffilter { char matchhook[NG_HOOKSIZ]; /* hook name */ - u_int16_t ethertype; /* catch these */ + uint16_t ethertype; /* catch these */ }; .Ed .El diff --git a/share/man/man4/ng_hci.4 b/share/man/man4/ng_hci.4 index 28de180c2426..0234d4105a6f 100644 --- a/share/man/man4/ng_hci.4 +++ b/share/man/man4/ng_hci.4 @@ -133,9 +133,9 @@ The next sections specify the HCI packet formats. .Bd -literal -offset indent #define NG_HCI_CMD_PKT 0x01 typedef struct { - u_int8_t type; /* MUST be 0x1 */ - u_int16_t opcode; /* OpCode */ - u_int8_t length; /* parameter(s) length in bytes */ + uint8_t type; /* MUST be 0x1 */ + uint16_t opcode; /* OpCode */ + uint8_t length; /* parameter(s) length in bytes */ } __attribute__ ((packed)) ng_hci_cmd_pkt_t; .Ed .Pp @@ -156,9 +156,9 @@ Controller to the Host. .Bd -literal -offset indent #define NG_HCI_EVENT_PKT 0x04 typedef struct { - u_int8_t type; /* MUST be 0x4 */ - u_int8_t event; /* event */ - u_int8_t length; /* parameter(s) length in bytes */ + uint8_t type; /* MUST be 0x4 */ + uint8_t event; /* event */ + uint8_t length; /* parameter(s) length in bytes */ } __attribute__ ((packed)) ng_hci_event_pkt_t; .Ed .Pp @@ -168,9 +168,9 @@ when events occur. .Bd -literal -offset indent #define NG_HCI_ACL_DATA_PKT 0x02 typedef struct { - u_int8_t type; /* MUST be 0x2 */ - u_int16_t con_handle; /* connection handle + PB + BC flags */ - u_int16_t length; /* payload length in bytes */ + uint8_t type; /* MUST be 0x2 */ + uint16_t con_handle; /* connection handle + PB + BC flags */ + uint16_t length; /* payload length in bytes */ } __attribute__ ((packed)) ng_hci_acldata_pkt_t; .Ed .Pp @@ -180,9 +180,9 @@ Host Controller. .Bd -literal -offset indent #define NG_HCI_SCO_DATA_PKT 0x03 typedef struct { - u_int8_t type; /* MUST be 0x3 */ - u_int16_t con_handle; /* connection handle + reserved bits */ - u_int8_t length; /* payload length in bytes */ + uint8_t type; /* MUST be 0x3 */ + uint16_t con_handle; /* connection handle + reserved bits */ + uint8_t length; /* payload length in bytes */ } __attribute__ ((packed)) ng_hci_scodata_pkt_t; .Ed .Pp @@ -216,9 +216,9 @@ Netgraph message defined as follows. .Bd -literal -offset indent #define NGM_HCI_NODE_UP 112 /* HCI -> Upper */ typedef struct { - u_int16_t pkt_size; /* max. ACL/SCO packet size (w/o hdr) */ - u_int16_t num_pkts; /* ACL/SCO packet queue size */ - u_int16_t reserved; /* place holder */ + uint16_t pkt_size; /* max. ACL/SCO packet size (w/o hdr) */ + uint16_t num_pkts; /* ACL/SCO packet queue size */ + uint16_t reserved; /* place holder */ bdaddr_t bdaddr; /* bdaddr */ } ng_hci_node_up_ep; .Ed @@ -244,8 +244,8 @@ Netgraph message is defined as follows. .Bd -literal -offset indent #define NGM_HCI_SYNC_CON_QUEUE 113 /* HCI -> Upper */ typedef struct { - u_int16_t con_handle; /* connection handle */ - u_int16_t completed; /* number of completed packets */ + uint16_t con_handle; /* connection handle */ + uint16_t completed; /* number of completed packets */ } ng_hci_sync_con_queue_ep; .Ed .Sh HOOKS diff --git a/share/man/man4/ng_l2cap.4 b/share/man/man4/ng_l2cap.4 index d4b7815f19a8..949b0390cabf 100644 --- a/share/man/man4/ng_l2cap.4 +++ b/share/man/man4/ng_l2cap.4 @@ -310,9 +310,9 @@ appropriate upstream hook and must be prepended with header defined as follows. .Bd -literal -offset indent /* L2CA data packet header */ typedef struct { - u_int32_t token; /* token to use in L2CAP_L2CA_WRITE */ - u_int16_t length; /* length of the data */ - u_int16_t lcid; /* local channel ID */ + uint32_t token; /* token to use in L2CAP_L2CA_WRITE */ + uint16_t length; /* length of the data */ + uint16_t lcid; /* local channel ID */ } __attribute__ ((packed)) ng_l2cap_l2ca_hdr_t; .Ed .Pp diff --git a/share/man/man4/ng_l2tp.4 b/share/man/man4/ng_l2tp.4 index 49fedf1bea4b..c556a49b828e 100644 --- a/share/man/man4/ng_l2tp.4 +++ b/share/man/man4/ng_l2tp.4 @@ -115,11 +115,11 @@ as an argument: struct ng_l2tp_config { u_char enabled; /* enables traffic flow */ u_char match_id; /* tunnel id must match 'tunnel_id' */ - u_int16_t tunnel_id; /* local tunnel id */ - u_int16_t peer_id; /* peer's tunnel id */ - u_int16_t peer_win; /* peer's max recv window size */ - u_int16_t rexmit_max; /* max retransmits before failure */ - u_int16_t rexmit_max_to; /* max delay between retransmits */ + uint16_t tunnel_id; /* local tunnel id */ + uint16_t peer_id; /* peer's tunnel id */ + uint16_t peer_win; /* peer's max recv window size */ + uint16_t rexmit_max; /* max retransmits before failure */ + uint16_t rexmit_max_to; /* max delay between retransmits */ }; .Ed .Pp @@ -197,8 +197,8 @@ The argument is a .Bd -literal /* Configuration for a session hook */ struct ng_l2tp_sess_config { - u_int16_t session_id; /* local session id */ - u_int16_t peer_id; /* peer's session id */ + uint16_t session_id; /* local session id */ + uint16_t peer_id; /* peer's session id */ u_char control_dseq; /* we control data sequencing? */ u_char enable_dseq; /* enable data sequencing? */ u_char include_length; /* include length field? */ diff --git a/share/man/man4/ng_mppc.4 b/share/man/man4/ng_mppc.4 index a146228a743b..df3b3a76bea0 100644 --- a/share/man/man4/ng_mppc.4 +++ b/share/man/man4/ng_mppc.4 @@ -106,7 +106,7 @@ as an argument: /* Configuration for a session */ struct ng_mppc_config { u_char enable; /* enable */ - u_int32_t bits; /* config bits */ + uint32_t bits; /* config bits */ u_char startkey[MPPE_KEY_LEN]; /* start key */ }; diff --git a/share/man/man4/ng_netflow.4 b/share/man/man4/ng_netflow.4 index 914489baf88e..ff54fc66ccb0 100644 --- a/share/man/man4/ng_netflow.4 +++ b/share/man/man4/ng_netflow.4 @@ -148,8 +148,8 @@ This message requires as an argument: .Bd -literal -offset 4n struct ng_netflow_setifindex { - u_int16_t iface; /* which iface to operate on */ - u_int16_t index; /* new index */ + uint16_t iface; /* which iface to operate on */ + uint16_t index; /* new index */ }; .Ed .Pp @@ -175,8 +175,8 @@ This message requires as an argument: .Bd -literal -offset 4n struct ng_netflow_setconfig { - u_int16_t iface; - u_int32_t conf; + uint16_t iface; + uint32_t conf; #define NG_NETFLOW_CONF_INGRESS 1 #define NG_NETFLOW_CONF_EGRESS 2 #define NG_NETFLOW_CONF_ONCE 4 diff --git a/share/man/man4/ng_one2many.4 b/share/man/man4/ng_one2many.4 index 434ea73d5d4a..948b763f911c 100644 --- a/share/man/man4/ng_one2many.4 +++ b/share/man/man4/ng_one2many.4 @@ -156,8 +156,8 @@ as the control message argument: .Bd -literal /* Node configuration structure */ struct ng_one2many_config { - u_int32_t xmitAlg; /* how to distribute packets */ - u_int32_t failAlg; /* how to detect link failure */ + uint32_t xmitAlg; /* how to distribute packets */ + uint32_t failAlg; /* how to detect link failure */ u_char enabledLinks[NG_ONE2MANY_MAX_LINKS]; }; .Ed @@ -187,10 +187,10 @@ link, which may or may not be currently connected: .Bd -literal /* Statistics structure (one for each link) */ struct ng_one2many_link_stats { - u_int64_t recvOctets; /* total octets rec'd on link */ - u_int64_t recvPackets; /* total pkts rec'd on link */ - u_int64_t xmitOctets; /* total octets xmit'd on link */ - u_int64_t xmitPackets; /* total pkts xmit'd on link */ + uint64_t recvOctets; /* total octets rec'd on link */ + uint64_t recvPackets; /* total pkts rec'd on link */ + uint64_t xmitOctets; /* total octets xmit'd on link */ + uint64_t xmitPackets; /* total pkts xmit'd on link */ }; .Ed .Pp diff --git a/share/man/man4/ng_ppp.4 b/share/man/man4/ng_ppp.4 index 9fd72cad17c8..453d1bd66ae9 100644 --- a/share/man/man4/ng_ppp.4 +++ b/share/man/man4/ng_ppp.4 @@ -355,14 +355,14 @@ struct ng_ppp_link_conf { u_char enableLink; /* enable this link */ u_char enableProtoComp;/* enable protocol field compression */ u_char enableACFComp; /* enable addr/ctrl field compression */ - u_int16_t mru; /* peer MRU */ - u_int32_t latency; /* link latency (in milliseconds) */ - u_int32_t bandwidth; /* link bandwidth (in bytes/second) */ + uint16_t mru; /* peer MRU */ + uint32_t latency; /* link latency (in milliseconds) */ + uint32_t bandwidth; /* link bandwidth (in bytes/second) */ }; /* Bundle config structure */ struct ng_ppp_bund_conf { - u_int16_t mrru; /* multilink peer MRRU */ + uint16_t mrru; /* multilink peer MRRU */ u_char enableMultilink; /* enable multilink */ u_char recvShortSeq; /* recv multilink short seq # */ u_char xmitShortSeq; /* xmit multilink short seq # */ diff --git a/share/man/man4/ng_pppoe.4 b/share/man/man4/ng_pppoe.4 index 32efa69ee7b8..e7a9939b29f5 100644 --- a/share/man/man4/ng_pppoe.4 +++ b/share/man/man4/ng_pppoe.4 @@ -148,7 +148,7 @@ The three commands above use a common data structure: .Bd -literal -offset 4n struct ngpppoe_init_data { char hook[NG_HOOKSIZ]; /* hook to monitor on */ - u_int16_t data_len; /* service name length */ + uint16_t data_len; /* service name length */ char data[0]; /* init data goes here */ }; .Ed @@ -345,8 +345,8 @@ setup(char *ethername, char *service, char *sessname, * The following is available about the node: * ninfo->name (string) * ninfo->type (string) - * ninfo->id (u_int32_t) - * ninfo->hooks (u_int32_t) (count of hooks) + * ninfo->id (uint32_t) + * ninfo->hooks (uint32_t) (count of hooks) * check it is the correct type. and get it's ID for use * with mkpeer later. */ @@ -366,8 +366,8 @@ setup(char *ethername, char *service, char *sessname, * link->peerhook (string) * peer->name (string) * peer->type (string) - * peer->id (u_int32_t) - * peer->hooks (u_int32_t) + * peer->id (uint32_t) + * peer->hooks (uint32_t) */ link = &hlist->link[k]; peer = &hlist->link[k].nodeinfo; diff --git a/share/man/man4/ng_pptpgre.4 b/share/man/man4/ng_pptpgre.4 index 89557dc3b779..e0d41f1c0cfd 100644 --- a/share/man/man4/ng_pptpgre.4 +++ b/share/man/man4/ng_pptpgre.4 @@ -97,10 +97,10 @@ struct ng_pptpgre_conf { u_char enableDelayedAck; /* enables delayed acks */ u_char enableAlwaysAck; /* always send ack with data */ u_char enableWindowing; /* enable windowing algorithm */ - u_int16_t cid; /* my call id */ - u_int16_t peerCid; /* peer call id */ - u_int16_t recvWin; /* peer recv window size */ - u_int16_t peerPpd; /* peer packet processing delay + uint16_t cid; /* my call id */ + uint16_t peerCid; /* peer call id */ + uint16_t recvWin; /* peer recv window size */ + uint16_t peerPpd; /* peer packet processing delay (in 1/10 of a second) */ }; .Ed diff --git a/share/man/man4/ppi.4 b/share/man/man4/ppi.4 index a6041d2a8fa7..a4084ad63648 100644 --- a/share/man/man4/ppi.4 +++ b/share/man/man4/ppi.4 @@ -53,7 +53,7 @@ interface is performed using .Fn ioctl calls. Each command takes a single -.Ft u_int8_t +.Ft uint8_t argument, transferring one byte of data. The following commands are available: .Bl -tag -width indent @@ -85,7 +85,7 @@ again, the following code fragment can be used: .Bd -literal -compact int fd; - u_int8_t val; + uint8_t val; val = 0x5a; ioctl(fd, PPISDATA, &val); diff --git a/share/man/man4/sbp.4 b/share/man/man4/sbp.4 index 0f86213dfd49..eeddd5da02c9 100644 --- a/share/man/man4/sbp.4 +++ b/share/man/man4/sbp.4 @@ -31,7 +31,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 20, 2002 +.Dd February 8, 2012 .Dt SBP 4 .Os .Sh NAME @@ -71,7 +71,7 @@ topology. If you want to force to detach the device, run .Dq Nm fwcontrol Fl r several times or set hw.firewire.hold_count=0 by -.Xr sysctl 1 . +.Xr sysctl 8 . .Pp Some (broken) HDDs do not work well with tagged queuing. If you have problems with such drives, try diff --git a/share/man/man4/sdhci.4 b/share/man/man4/sdhci.4 index 09d431370942..e9729a1e46e2 100644 --- a/share/man/man4/sdhci.4 +++ b/share/man/man4/sdhci.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 14, 2009 +.Dd February 9, 2012 .Dt SDHCI 4 .Os .Sh NAME @@ -69,6 +69,8 @@ ENE CB714 .It RICOH R5C822 .It +RICOH R5CE823 +.It TI PCIXX21/XX11 .El .Sh SEE ALSO diff --git a/share/man/man4/sfxge.4 b/share/man/man4/sfxge.4 index 33063d92e2dd..3f27275fc65c 100644 --- a/share/man/man4/sfxge.4 +++ b/share/man/man4/sfxge.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 16, 2011 +.Dd February 8, 2012 .Dt SFXGE 4 .Os .Sh NAME @@ -57,7 +57,7 @@ and Receive Side Scaling (RSS) using MSI-X interrupts. The driver allocates 1 receive queue, transmit queue, event queue and IRQ per CPU up to a maximum of 64. IRQ affinities should be spread out using -.Xr cpuset 8 . +.Xr cpuset 1 . Interrupt moderation may be controlled through the sysctl .Va dev.sfxge.%d.int_mod (units are microseconds). @@ -85,7 +85,7 @@ go to the Solarflare support website at: .Xr netintro 4 , .Xr ng_ether 4 , .Xr vlan 4 , -.Xr cpuset 8 , +.Xr cpuset 1 , .Xr ifconfig 8 .Sh AUTHORS The diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4 index e2d4ad342664..34c2a2863b73 100644 --- a/share/man/man4/tcp.4 +++ b/share/man/man4/tcp.4 @@ -38,7 +38,7 @@ .\" From: @(#)tcp.4 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd November 14, 2011 +.Dd February 5, 2012 .Dt TCP 4 .Os .Sh NAME @@ -146,6 +146,65 @@ connection. See .Xr mod_cc 4 for details. +.It Dv TCP_KEEPINIT +This write-only +.Xr setsockopt 2 +option accepts a per-socket timeout argument of +.Vt "u_int" +in seconds, for new, non-established +.Tn TCP +connections. +For the global default in milliseconds see +.Va keepinit +in the +.Sx MIB Variables +section further down. +.It Dv TCP_KEEPIDLE +This write-only +.Xr setsockopt 2 +option accepts an argument of +.Vt "u_int" +for the amount of time, in seconds, that the connection must be idle +before keepalive probes (if enabled) are sent for the connection of this +socket. +If set on a listening socket, the value is inherited by the newly created +socket upon +.Xr accept 2 . +For the global default in milliseconds see +.Va keepidle +in the +.Sx MIB Variables +section further down. +.It Dv TCP_KEEPINTVL +This write-only +.Xr setsockopt 2 +option accepts an argument of +.Vt "u_int" +to set the per-socket interval, in seconds, between keepalive probes sent +to a peer. +If set on a listening socket, the value is inherited by the newly created +socket upon +.Xr accept 2 . +For the global default in milliseconds see +.Va keepintvl +in the +.Sx MIB Variables +section further down. +.It Dv TCP_KEEPCNT +This write-only +.Xr setsockopt 2 +option accepts an argument of +.Vt "u_int" +and allows a per-socket tuning of the number of probes sent, with no response, +before the connection will be dropped. +If set on a listening socket, the value is inherited by the newly created +socket upon +.Xr accept 2 . +For the global default see the +.Va keepcnt +in the +.Sx MIB Variables +section further down. .It Dv TCP_NODELAY Under most circumstances, .Tn TCP @@ -296,17 +355,21 @@ The Maximum Segment Lifetime, in milliseconds, for a packet. Timeout, in milliseconds, for new, non-established .Tn TCP connections. +The default is 75000 msec. .It Va keepidle Amount of time, in milliseconds, that the connection must be idle before keepalive probes (if enabled) are sent. +The default is 7200000 msec (2 hours). .It Va keepintvl The interval, in milliseconds, between keepalive probes sent to remote machines, when no response is received on a .Va keepidle probe. -After -.Dv TCPTV_KEEPCNT -(default 8) probes are sent, with no response, the connection is dropped. +The default is 75000 msec. +.It Va keepcnt +Number of probes sent, with no response, before a connection +is dropped. +The default is 8 packets. .It Va always_keepalive Assume that .Dv SO_KEEPALIVE diff --git a/share/man/man4/u3g.4 b/share/man/man4/u3g.4 index 87e382456ccf..d65c2c899a64 100644 --- a/share/man/man4/u3g.4 +++ b/share/man/man4/u3g.4 @@ -18,7 +18,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 20, 2011 +.Dd February 8, 2012 .Dt U3G 4 .Os .Sh NAME @@ -88,7 +88,7 @@ driver is present which contains Windows and Mac OS X drivers. The device starts up in disk mode (TruInstall, ZeroCD, etc.) and requires additional commands to switch it to modem mode. If your device is not switching automatically, please try to add quirks. See -.Xr usbconfig 5 +.Xr usbconfig 8 and .Xr usb_quirk 4 . .Pp @@ -97,7 +97,7 @@ and .Xr ucom 4 , .Xr usb 4 , .Xr usb_quirk 4 , -.Xr usbconfig 5 +.Xr usbconfig 8 .Sh HISTORY The .Nm diff --git a/share/man/man4/usb_quirk.4 b/share/man/man4/usb_quirk.4 index 00e4ba43ab7e..23234956886a 100644 --- a/share/man/man4/usb_quirk.4 +++ b/share/man/man4/usb_quirk.4 @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 27, 2011 +.Dd February 8, 2012 .Dt USB_QUIRK 4 .Os .Sh NAME @@ -41,7 +41,7 @@ The .Nm module provides support for dynamically adding and removing quirks for USB devices with -.Xr usbconfig 5 . +.Xr usbconfig 8 . .Sh General quirks: .Bl -tag -width Ds .It UQ_AUDIO_SWAP_LR @@ -183,7 +183,7 @@ device which appears as a USB device on usbconfig -d ugen0.3 add_quirk UQ_MSC_EJECT_WAIT .Ed .Sh SEE ALSO -.Xr usbconfig 5 +.Xr usbconfig 8 .Sh HISTORY The .Nm diff --git a/share/man/man5/devfs.5 b/share/man/man5/devfs.5 index 8c7e598af2ff..7b483fc7a5f1 100644 --- a/share/man/man5/devfs.5 +++ b/share/man/man5/devfs.5 @@ -38,7 +38,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 18, 2010 +.Dd February 9, 2012 .Dt DEVFS 5 .Os .Sh NAME @@ -90,6 +90,29 @@ and .Pa 2 . .Xr fdescfs 5 creates files for all open descriptors. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl o Ar options +Use the specified mount +.Ar options , +as described in +.Xr mount 8 . +The following devfs file system-specific options are available: +.Bl -tag -width indent +.It Cm ruleset Ns No = Ns Ar ruleset +Set ruleset number +.Ar ruleset +as the current ruleset for the mount-point and apply all its rules. If the +ruleset number +.Ar ruleset +does not exist, an empty ruleset with the number +.Ar ruleset +is created. See +.Xr devfs 8 +for more information on working with devfs rulesets. +.El +.El .Sh FILES .Bl -tag -width /dev/XXXX -compact .It Pa /dev diff --git a/share/man/man5/fs.5 b/share/man/man5/fs.5 index abb0f470bf8e..fbe870645dd8 100644 --- a/share/man/man5/fs.5 +++ b/share/man/man5/fs.5 @@ -145,12 +145,12 @@ struct fs { int8_t fs_old_flags; /* old FS_ flags */ u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ u_char fs_volname[MAXVOLLEN]; /* volume name */ - u_int64_t fs_swuid; /* system-wide uid */ + uint64_t fs_swuid; /* system-wide uid */ int32_t fs_pad; /* due to alignment of fs_swuid */ /* these fields retain the current block allocation info */ int32_t fs_cgrotor; /* last cg searched */ void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */ - u_int8_t *fs_contigdirs; /* # of contiguously allocated dirs */ + uint8_t *fs_contigdirs; /* # of contiguously allocated dirs */ struct csum *fs_csp; /* cg summary info buffer for fs_cs */ int32_t *fs_maxcluster; /* max cluster in each cyl group */ u_int *fs_active; /* used by snapshots to track fs */ @@ -175,7 +175,7 @@ struct fs { int32_t fs_contigsumsize; /* size of cluster summary array */ int32_t fs_maxsymlinklen; /* max length of an internal symlink */ int32_t fs_old_inodefmt; /* format of on-disk inodes */ - u_int64_t fs_maxfilesize; /* maximum representable file size */ + uint64_t fs_maxfilesize; /* maximum representable file size */ int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */ int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */ int32_t fs_state; /* validate fs_clean field */ diff --git a/share/man/man5/periodic.conf.5 b/share/man/man5/periodic.conf.5 index 540ef2e0cd93..4ab009c18a98 100644 --- a/share/man/man5/periodic.conf.5 +++ b/share/man/man5/periodic.conf.5 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 8, 2011 +.Dd February 7, 2012 .Dt PERIODIC.CONF 5 .Os .Sh NAME @@ -335,6 +335,28 @@ utility when .Va daily_status_disks_enable is set to .Dq Li YES . +.It Va daily_status_zfs_enable +.Pq Vt bool +Set to +.Dq Li YES +if you want to run +.Nm zpool Cm status +on your +.Xr zfs 8 +pools. +.It Va daily_status_zfs_zpool_list_enable +.Pq Vt bool +Set to +.Dq Li YES +if you want to run +.Nm zpool Cm list +on your +.Xr zfs 8 +pools. +Requires +.Va daily_status_zfs_enable +to be set to +.Li YES . .It Va daily_status_ata_raid_enable .Pq Vt bool Set to diff --git a/share/man/man5/portindex.5 b/share/man/man5/portindex.5 index f7b126fc4396..35261965f238 100644 --- a/share/man/man5/portindex.5 +++ b/share/man/man5/portindex.5 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 28, 2009 +.Dd February 8, 2012 .Dt PORTINDEX 5 .Os .Sh NAME @@ -90,7 +90,7 @@ branch. vim-6.3.15|/usr/ports/editors/vim|/usr/local|Vi "workalike", with many additional features|/usr/ports/editors/vim/pkg-descr|obrien@FreeBSD.org|editors|libiconv-1.9.2_1|libiconv-1.9.2_1|http://www.vim.org/||| .Ed .Sh SEE ALSO -.Xr build 1 , +.Xr build 7 , .Xr csup 1 , .Xr ports 7 .Sh AUTHORS diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 47a325be1edc..83d91be19165 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 13, 2011 +.Dd February 11, 2012 .Dt RC.CONF 5 .Os .Sh NAME @@ -149,6 +149,19 @@ and before changing it one should ensure that there are adequate provisions to recover from a failed boot (such as physical contact with the machine, or reliable remote console access). +.It Va always_force_depends +.Pq Vt bool +Various +.Pa rc.d +scripts use the force_depend function to check whether required +services are already running, and to start them if necessary. +By default during boot time this check is bypassed if the +required service is enabled in +.Pa /etc/rc.conf[.local] . +Setting this option will bypass that check at boot time and +always test whether or not the service is actually running. +Enabling this option is likely to increase your boot time if +services are enabled that utilize the force_depend check. .It Va swapfile .Pq Vt str If set to @@ -3673,6 +3686,25 @@ is set to these are the flags passed to the .Xr watchdogd 8 daemon. +.It Va devfs_rulesets +.Pq Vt str +List of files containing sets of rules for +.Xr devfs 8 . +.It Va devfs_system_ruleset +.Pq Vt str +Rule name(s) to apply to the system +.Pa /dev +itself. +.It Va devfs_set_rulesets +.Pq Vt str +Pairs of already-mounted +.Pa dev +directories and rulesets that should be applied to them. +For example: /mount/dev=ruleset_name +.It Va devfs_load_rulesets +.Pq Vt bool +If set, always load the default rulesets listed in +.Va devfs_rulesets . .It Va performance_cx_lowest .Pq Vt str CPU idle state to use while on AC power. @@ -4532,6 +4564,7 @@ The default is 30. .Xr chkprintcap 8 , .Xr chown 8 , .Xr cron 8 , +.Xr devfs 8 , .Xr dhclient 8 , .Xr ftpd 8 , .Xr geli 8 , diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index 68a93cd26ac8..d29115b15fe1 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,7 +1,7 @@ .\" DO NOT EDIT-- this file is automatically generated. .\" from FreeBSD: head/tools/build/options/makeman 221733 2011-05-10 13:01:11Z ru .\" $FreeBSD$ -.Dd January 13, 2012 +.Dd February 6, 2012 .Dt SRC.CONF 5 .Os .Sh NAME @@ -271,12 +271,21 @@ Set to not build the Clang C/C++ compiler. .Pp It is a default setting on arm/arm, arm/armeb, ia64/ia64, mips/mipsel, mips/mipseb, mips/mips64el, mips/mips64eb, mips/mipsn32eb and sparc64/sparc64. +When set, it also enforces the following options: +.Pp +.Bl -item -compact +.It +.Va WITHOUT_CLANG_EXTRAS +.El .It Va WITH_CLANG .\" from FreeBSD: head/tools/build/options/WITH_CLANG 221730 2011-05-10 11:14:40Z ru Set to build the Clang C/C++ compiler. .Pp It is a default setting on amd64/amd64, i386/i386, pc98/i386, powerpc/powerpc and powerpc/powerpc64. +.It Va WITH_CLANG_EXTRAS +.\" $FreeBSD$ +Set to build additional clang and llvm tools, such as bugpoint. .It Va WITHOUT_CPP .\" from FreeBSD: head/tools/build/options/WITHOUT_CPP 156932 2006-03-21 07:50:50Z ru Set to not build @@ -869,6 +878,23 @@ as a set-user-ID root program. Set to not build the .Bx 4.4 legacy docs. +.It Va WITHOUT_SOURCELESS +.\" from FreeBSD: head/tools/build/options/WITHOUT_SOURCELESS 230972 2012-02-04 00:54:43Z rmh +Set to not build kernel modules that include sourceless code (either microcode or native code for host CPU). +When set, it also enforces the following options: +.Pp +.Bl -item -compact +.It +.Va WITHOUT_SOURCELESS_HOST +.It +.Va WITHOUT_SOURCELESS_UCODE +.El +.It Va WITHOUT_SOURCELESS_HOST +.\" from FreeBSD: head/tools/build/options/WITHOUT_SOURCELESS_HOST 230972 2012-02-04 00:54:43Z rmh +Set to not build kernel modules that include sourceless native code for host CPU. +.It Va WITHOUT_SOURCELESS_UCODE +.\" from FreeBSD: head/tools/build/options/WITHOUT_SOURCELESS_UCODE 230972 2012-02-04 00:54:43Z rmh +Set to not build kernel modules that include sourceless microcode. .It Va WITHOUT_SSP .\" from FreeBSD: head/tools/build/options/WITHOUT_SSP 180012 2008-06-25 21:33:28Z ru Set to not build world with propolice stack smashing protection. diff --git a/share/man/man7/hier.7 b/share/man/man7/hier.7 index b7aa57eb30fc..df76f46df55a 100644 --- a/share/man/man7/hier.7 +++ b/share/man/man7/hier.7 @@ -639,6 +639,8 @@ third-party, and/or local source files .Bl -tag -width ".Pa kerberos5/" -compact .It Pa bin/ source code for files in /bin +.It Pa cddl/ +Utilities covered by the Common Development and Distribution License .It Pa contrib/ source code for contributed software .It Pa crypto/ diff --git a/share/man/man7/ports.7 b/share/man/man7/ports.7 index 975b8258a275..29312da4f800 100644 --- a/share/man/man7/ports.7 +++ b/share/man/man7/ports.7 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 30, 2011 +.Dd February 9, 2012 .Dt PORTS 7 .Os .Sh NAME @@ -408,10 +408,13 @@ Directory to put the package in. .It Va PKGFILE The full path to the package. .El -.It Va PREFIX -Where to install things in general -(usually +.It Va LOCALBASE +Where existing things are installed and where to search for files when +resolving dependencies (usually .Pa /usr/local ) . +.It Va PREFIX +Where to install this port (usually set to the same as +.Va LOCALBASE ) . .It Va MASTER_SITES Primary sites for distribution files if not found locally. .It Va PATCH_SITES diff --git a/share/man/man7/security.7 b/share/man/man7/security.7 index 197fe3e14072..a3882d65bd0d 100644 --- a/share/man/man7/security.7 +++ b/share/man/man7/security.7 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 7, 2010 +.Dd February 8, 2012 .Dt SECURITY 7 .Os .Sh NAME @@ -579,7 +579,7 @@ configuration cannot be adjusted. .El .Pp The security level can be configured with variables documented in -.Xr rc.conf 8 . +.Xr rc.conf 5 . .Sh CHECKING FILE INTEGRITY: BINARIES, CONFIG FILES, ETC When it comes right down to it, you can only protect your core system configuration and control files so much before the convenience factor diff --git a/share/man/man9/DEVICE_PROBE.9 b/share/man/man9/DEVICE_PROBE.9 index bf592c5affef..b536b90ec4f8 100644 --- a/share/man/man9/DEVICE_PROBE.9 +++ b/share/man/man9/DEVICE_PROBE.9 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 3, 2008 +.Dd February 8, 2012 .Dt DEVICE_PROBE 9 .Os .Sh NAME @@ -120,7 +120,7 @@ treatment for some reason. .It BUS_PROBE_HOOVER The driver matches all unclaimed devices on a bus. The -.Xr ugen 5 +.Xr ugen 4 device is one example. .It BUS_PROBE_NOWILDCARD The driver expects its parent to tell it which children to manage diff --git a/share/man/man9/MD5.9 b/share/man/man9/MD5.9 index b2d257fbc261..1b9fcd2fb6e9 100644 --- a/share/man/man9/MD5.9 +++ b/share/man/man9/MD5.9 @@ -44,7 +44,7 @@ .Ft void .Fn MD5Init "MD5_CTX *buf" .Ft void -.Fn MD5Transform "u_int32_t buf[4]" "const unsigned char block[64]" +.Fn MD5Transform "uint32_t buf[4]" "const unsigned char block[64]" .Sh DESCRIPTION The .Nm diff --git a/share/man/man9/bios.9 b/share/man/man9/bios.9 index 0621b72c5582..48bbe16c0fcf 100644 --- a/share/man/man9/bios.9 +++ b/share/man/man9/bios.9 @@ -40,8 +40,8 @@ .In machine/param.h .In machine/pmap.h .In machine/pc/bios.h -.Ft u_int32_t -.Fn bios_sigsearch "u_int32_t start" "u_char *sig" "int siglen" "int paralen" "int sigofs" +.Ft uint32_t +.Fn bios_sigsearch "uint32_t start" "u_char *sig" "int siglen" "int paralen" "int sigofs" .Ft int .Fn bios32_SDlookup "struct bios32_SDentry *ent" .Ft int diff --git a/share/man/man9/bus_space.9 b/share/man/man9/bus_space.9 index b3234c47e10f..59c360724ce9 100644 --- a/share/man/man9/bus_space.9 +++ b/share/man/man9/bus_space.9 @@ -167,77 +167,77 @@ .Fo bus_space_free .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t size" .Fc -.Ft u_int8_t +.Ft uint8_t .Fo bus_space_read_1 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t offset" .Fc -.Ft u_int16_t +.Ft uint16_t .Fo bus_space_read_2 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t offset" .Fc -.Ft u_int32_t +.Ft uint32_t .Fo bus_space_read_4 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t offset" .Fc -.Ft u_int64_t +.Ft uint64_t .Fo bus_space_read_8 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t offset" .Fc -.Ft u_int8_t +.Ft uint8_t .Fo bus_space_read_stream_1 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t offset" .Fc -.Ft u_int16_t +.Ft uint16_t .Fo bus_space_read_stream_2 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t offset" .Fc -.Ft u_int32_t +.Ft uint32_t .Fo bus_space_read_stream_4 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t offset" .Fc -.Ft u_int64_t +.Ft uint64_t .Fo bus_space_read_stream_8 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" "bus_size_t offset" .Fc .Ft void .Fo bus_space_write_1 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" -.Fa "bus_size_t offset" "u_int8_t value" +.Fa "bus_size_t offset" "uint8_t value" .Fc .Ft void .Fo bus_space_write_2 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" -.Fa "bus_size_t offset" "u_int16_t value" +.Fa "bus_size_t offset" "uint16_t value" .Fc .Ft void .Fo bus_space_write_4 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" -.Fa "bus_size_t offset" "u_int32_t value" +.Fa "bus_size_t offset" "uint32_t value" .Fc .Ft void .Fo bus_space_write_8 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" -.Fa "bus_size_t offset" "u_int64_t value" +.Fa "bus_size_t offset" "uint64_t value" .Fc .Ft void .Fo bus_space_write_stream_1 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" -.Fa "bus_size_t offset" "u_int8_t value" +.Fa "bus_size_t offset" "uint8_t value" .Fc .Ft void .Fo bus_space_write_stream_2 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" -.Fa "bus_size_t offset" "u_int16_t value" +.Fa "bus_size_t offset" "uint16_t value" .Fc .Ft void .Fo bus_space_write_stream_4 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" -.Fa "bus_size_t offset" "u_int32_t value" +.Fa "bus_size_t offset" "uint32_t value" .Fc .Ft void .Fo bus_space_write_stream_8 .Fa "bus_space_tag_t space" "bus_space_handle_t handle" -.Fa "bus_size_t offset" "u_int64_t value" +.Fa "bus_size_t offset" "uint64_t value" .Fc .Ft void .Fo bus_space_barrier @@ -247,97 +247,97 @@ .Ft void .Fo bus_space_read_region_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_region_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_region_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_region_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_region_stream_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_region_stream_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_region_stream_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_region_stream_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_region_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_region_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_region_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_region_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_region_stream_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_region_stream_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_region_stream_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_region_stream_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t *datap" .Fa "bus_size_t count" .Fc .Ft void @@ -391,193 +391,193 @@ .Ft void .Fo bus_space_set_region_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_region_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_region_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_region_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_region_stream_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_region_stream_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_region_stream_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_region_stream_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_multi_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_multi_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_multi_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_multi_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_multi_stream_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_multi_stream_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_multi_stream_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_read_multi_stream_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_multi_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_multi_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_multi_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_multi_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_multi_stream_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_multi_stream_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_multi_stream_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_write_multi_stream_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t *datap" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t *datap" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_multi_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_multi_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_multi_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_multi_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_multi_stream_1 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int8_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint8_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_multi_stream_2 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int16_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint16_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_multi_stream_4 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int32_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint32_t value" .Fa "bus_size_t count" .Fc .Ft void .Fo bus_space_set_multi_stream_8 .Fa "bus_space_tag_t space" -.Fa "bus_space_handle_t handle" "bus_size_t offset" "u_int64_t value" +.Fa "bus_space_handle_t handle" "bus_size_t offset" "uint64_t value" .Fa "bus_size_t count" .Fc .Sh DESCRIPTION diff --git a/share/man/man9/crypto.9 b/share/man/man9/crypto.9 index ba13254f2f45..762d78523c4d 100644 --- a/share/man/man9/crypto.9 +++ b/share/man/man9/crypto.9 @@ -26,29 +26,29 @@ .Sh SYNOPSIS .In opencrypto/cryptodev.h .Ft int32_t -.Fn crypto_get_driverid u_int8_t +.Fn crypto_get_driverid uint8_t .Ft int -.Fn crypto_register u_int32_t int u_int16_t u_int32_t "int \*[lp]*\*[rp]\*[lp]void *, u_int32_t *, struct cryptoini *\*[rp]" "int \*[lp]*\*[rp]\*[lp]void *, u_int64_t\*[rp]" "int \*[lp]*\*[rp]\*[lp]void *, struct cryptop *\*[rp]" "void *" +.Fn crypto_register uint32_t int uint16_t uint32_t "int \*[lp]*\*[rp]\*[lp]void *, uint32_t *, struct cryptoini *\*[rp]" "int \*[lp]*\*[rp]\*[lp]void *, uint64_t\*[rp]" "int \*[lp]*\*[rp]\*[lp]void *, struct cryptop *\*[rp]" "void *" .Ft int -.Fn crypto_kregister u_int32_t int u_int32_t "int \*[lp]*\*[rp]\*[lp]void *, struct cryptkop *\*[rp]" "void *" +.Fn crypto_kregister uint32_t int uint32_t "int \*[lp]*\*[rp]\*[lp]void *, struct cryptkop *\*[rp]" "void *" .Ft int -.Fn crypto_unregister u_int32_t int +.Fn crypto_unregister uint32_t int .Ft int -.Fn crypto_unregister_all u_int32_t +.Fn crypto_unregister_all uint32_t .Ft void .Fn crypto_done "struct cryptop *" .Ft void .Fn crypto_kdone "struct cryptkop *" .Ft int -.Fn crypto_newsession "u_int64_t *" "struct cryptoini *" int +.Fn crypto_newsession "uint64_t *" "struct cryptoini *" int .Ft int -.Fn crypto_freesession u_int64_t +.Fn crypto_freesession uint64_t .Ft int .Fn crypto_dispatch "struct cryptop *" .Ft int .Fn crypto_kdispatch "struct cryptkop *" .Ft int -.Fn crypto_unblock u_int32_t int +.Fn crypto_unblock uint32_t int .Ft "struct cryptop *" .Fn crypto_getreq int .Ft void @@ -64,7 +64,7 @@ struct cryptoini { int cri_klen; int cri_mlen; caddr_t cri_key; - u_int8_t cri_iv[EALG_MAX_BLOCK_LEN]; + uint8_t cri_iv[EALG_MAX_BLOCK_LEN]; struct cryptoini *cri_next; }; @@ -83,7 +83,7 @@ struct cryptodesc { struct cryptop { TAILQ_ENTRY(cryptop) crp_next; - u_int64_t crp_sid; + uint64_t crp_sid; int crp_ilen; int crp_olen; int crp_etype; @@ -108,7 +108,7 @@ struct cryptkop { u_int krp_status; /* return status */ u_short krp_iparams; /* # of input parameters */ u_short krp_oparams; /* # of output parameters */ - u_int32_t krp_hid; + uint32_t krp_hid; struct crparam krp_param[CRK_MAXPARAM]; int (*krp_callback)(struct cryptkop *); }; @@ -524,10 +524,10 @@ The calling convention for the three driver-supplied routines is: .Bl -item -compact .It .Ft int -.Fn \*[lp]*newsession\*[rp] "void *" "u_int32_t *" "struct cryptoini *" ; +.Fn \*[lp]*newsession\*[rp] "void *" "uint32_t *" "struct cryptoini *" ; .It .Ft int -.Fn \*[lp]*freesession\*[rp] "void *" "u_int64_t" ; +.Fn \*[lp]*freesession\*[rp] "void *" "uint64_t" ; .It .Ft int .Fn \*[lp]*process\*[rp] "void *" "struct cryptop *" ; diff --git a/share/man/man9/device_set_flags.9 b/share/man/man9/device_set_flags.9 index aed306950e16..3a836ffddfae 100644 --- a/share/man/man9/device_set_flags.9 +++ b/share/man/man9/device_set_flags.9 @@ -39,8 +39,8 @@ .In sys/param.h .In sys/bus.h .Ft void -.Fn device_set_flags "device_t dev" "u_int32_t flags" -.Ft u_int32_t +.Fn device_set_flags "device_t dev" "uint32_t flags" +.Ft uint32_t .Fn device_get_flags "device_t dev" .Sh DESCRIPTION Each device supports a set of driver-dependent flags which are often diff --git a/share/man/man9/devstat.9 b/share/man/man9/devstat.9 index fa378560564a..7ed7ec13975d 100644 --- a/share/man/man9/devstat.9 +++ b/share/man/man9/devstat.9 @@ -45,7 +45,7 @@ .Fa "struct devstat *ds" .Fa "const char *dev_name" .Fa "int unit_number" -.Fa "u_int32_t block_size" +.Fa "uint32_t block_size" .Fa "devstat_support_flags flags" .Fa "devstat_type_flags device_type" .Fa "devstat_priority priority" @@ -57,7 +57,7 @@ .Ft void .Fo devstat_end_transaction .Fa "struct devstat *ds" -.Fa "u_int32_t bytes" +.Fa "uint32_t bytes" .Fa "devstat_tag_type tag_type" .Fa "devstat_trans_flags flags" .Fc diff --git a/share/man/man9/devtoname.9 b/share/man/man9/devtoname.9 index 0e6e0db655e2..07ec04fb852f 100644 --- a/share/man/man9/devtoname.9 +++ b/share/man/man9/devtoname.9 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 19, 2012 +.Dd February 10, 2012 .Dt DEVTONAME 9 .Os .Sh NAME @@ -41,15 +41,6 @@ The function returns a pointer to the name of the device passed to it. The name is whatever was set to it in .Fn make_dev . -If no name is associated with -.Va dev , -a pointer to a string consisting of a -.Dq # -followed by -.Dq Va major Ns / Ns Va minor -as it applies to -.Va dev -is returned. .Sh HISTORY The .Fn devtoname diff --git a/share/man/man9/eventtimers.9 b/share/man/man9/eventtimers.9 index db530a90ee9c..c21b1a79f3ee 100644 --- a/share/man/man9/eventtimers.9 +++ b/share/man/man9/eventtimers.9 @@ -52,7 +52,7 @@ struct eventtimer { #define ET_FLAGS_POW2DIV 16 int et_quality; int et_active; - u_int64_t et_frequency; + uint64_t et_frequency; struct bintime et_min_period; struct bintime et_max_period; et_start_t *et_start; diff --git a/share/man/man9/get_cyclecount.9 b/share/man/man9/get_cyclecount.9 index 30db0d86709f..eabaeb1fa806 100644 --- a/share/man/man9/get_cyclecount.9 +++ b/share/man/man9/get_cyclecount.9 @@ -34,7 +34,7 @@ .In sys/param.h .In sys/systm.h .In machine/cpu.h -.Ft u_int64_t +.Ft uint64_t .Fn get_cyclecount "void" .Sh DESCRIPTION The diff --git a/share/man/man9/mbchain.9 b/share/man/man9/mbchain.9 index f9a452165762..4e05e7ad3ec9 100644 --- a/share/man/man9/mbchain.9 +++ b/share/man/man9/mbchain.9 @@ -66,15 +66,15 @@ .Ft caddr_t .Fn mb_reserve "struct mbchain *mbp" "int size" .Ft int -.Fn mb_put_uint8 "struct mbchain *mbp" "u_int8_t x" +.Fn mb_put_uint8 "struct mbchain *mbp" "uint8_t x" .Ft int -.Fn mb_put_uint16be "struct mbchain *mbp" "u_int16_t x" +.Fn mb_put_uint16be "struct mbchain *mbp" "uint16_t x" .Ft int -.Fn mb_put_uint16le "struct mbchain *mbp" "u_int16_t x" +.Fn mb_put_uint16le "struct mbchain *mbp" "uint16_t x" .Ft int -.Fn mb_put_uint32be "struct mbchain *mbp" "u_int32_t x" +.Fn mb_put_uint32be "struct mbchain *mbp" "uint32_t x" .Ft int -.Fn mb_put_uint32le "struct mbchain *mbp" "u_int32_t x" +.Fn mb_put_uint32le "struct mbchain *mbp" "uint32_t x" .Ft int .Fn mb_put_int64be "struct mbchain *mbp" "int64_t x" .Ft int diff --git a/share/man/man9/mbuf_tags.9 b/share/man/man9/mbuf_tags.9 index d84c56b825d0..d9627e8bc6a7 100644 --- a/share/man/man9/mbuf_tags.9 +++ b/share/man/man9/mbuf_tags.9 @@ -29,7 +29,7 @@ .Sh SYNOPSIS .In sys/mbuf.h .Ft "struct m_tag *" -.Fn m_tag_alloc "u_int32_t cookie" "int type" "int len" "int wait" +.Fn m_tag_alloc "uint32_t cookie" "int type" "int len" "int wait" .Ft "struct m_tag *" .Fn m_tag_copy "struct m_tag *t" "int how" .Ft int @@ -51,7 +51,7 @@ .Ft void .Fn m_tag_init "struct mbuf *m" .Ft struct m_tag * -.Fn m_tag_locate "struct mbuf *m" "u_int32_t cookie" "int type" "struct m_tag *t" +.Fn m_tag_locate "struct mbuf *m" "uint32_t cookie" "int type" "struct m_tag *t" .Ft "struct m_tag *" .Fn m_tag_next "struct mbuf *m" "struct m_tag *t" .Ft void @@ -100,9 +100,9 @@ bytes of a tag contain a .Bd -literal struct m_tag { SLIST_ENTRY(m_tag) m_tag_link; /* List of packet tags */ - u_int16_t m_tag_id; /* Tag ID */ - u_int16_t m_tag_len; /* Length of data */ - u_int32_t m_tag_cookie; /* ABI/Module ID */ + uint16_t m_tag_id; /* Tag ID */ + uint16_t m_tag_len; /* Length of data */ + uint32_t m_tag_cookie; /* ABI/Module ID */ void (*m_tag_free)(struct m_tag *); }; .Ed diff --git a/share/man/man9/mdchain.9 b/share/man/man9/mdchain.9 index 57291c70f6ed..5b0bf4ace4ff 100644 --- a/share/man/man9/mdchain.9 +++ b/share/man/man9/mdchain.9 @@ -63,19 +63,19 @@ .Ft int .Fn md_next_record "struct mdchain *mdp" .Ft int -.Fn md_get_uint8 "struct mdchain *mdp" "u_int8_t *x" +.Fn md_get_uint8 "struct mdchain *mdp" "uint8_t *x" .Ft int -.Fn md_get_uint16 "struct mdchain *mdp" "u_int16_t *x" +.Fn md_get_uint16 "struct mdchain *mdp" "uint16_t *x" .Ft int -.Fn md_get_uint16be "struct mdchain *mdp" "u_int16_t *x" +.Fn md_get_uint16be "struct mdchain *mdp" "uint16_t *x" .Ft int -.Fn md_get_uint16le "struct mdchain *mdp" "u_int16_t *x" +.Fn md_get_uint16le "struct mdchain *mdp" "uint16_t *x" .Ft int -.Fn md_get_uint32 "struct mdchain *mdp" "u_int32_t *x" +.Fn md_get_uint32 "struct mdchain *mdp" "uint32_t *x" .Ft int -.Fn md_get_uint32be "struct mdchain *mdp" "u_int32_t *x" +.Fn md_get_uint32be "struct mdchain *mdp" "uint32_t *x" .Ft int -.Fn md_get_uint32le "struct mdchain *mdp" "u_int32_t *x" +.Fn md_get_uint32le "struct mdchain *mdp" "uint32_t *x" .Ft int .Fn md_get_int64 "struct mdchain *mdp" "int64_t *x" .Ft int @@ -193,8 +193,8 @@ function can safely be called to destroy it. .Bd -literal struct mdchain *mdp; struct mbuf *m; -u_int16_t length; -u_int8_t byte; +uint16_t length; +uint8_t byte; receive(so, &m); md_initm(mdp, m); diff --git a/share/man/man9/netisr.9 b/share/man/man9/netisr.9 index ee6fbedf4d7c..bb64b0eb2c85 100644 --- a/share/man/man9/netisr.9 +++ b/share/man/man9/netisr.9 @@ -50,7 +50,7 @@ .Ft void .Fn netisr_clearqdrops "const struct netisr_handler *nhp" .Ft void -.Fn netisr_getqdrops "const struct netisr_handler *nhp" "u_int64_t *qdropsp" +.Fn netisr_getqdrops "const struct netisr_handler *nhp" "uint64_t *qdropsp" .Ft void .Fn netisr_getqlimit "const struct netisr_handler *nhp" "u_int *qlimitp" .Ft int diff --git a/share/man/man9/random.9 b/share/man/man9/random.9 index 1d7c7daf0894..a6bccda701b4 100644 --- a/share/man/man9/random.9 +++ b/share/man/man9/random.9 @@ -44,7 +44,7 @@ .Fn random "void" .Ft void .Fn arc4rand "void *ptr" "u_int length" "int reseed" -.Ft u_int32_t +.Ft uint32_t .Fn arc4random "void" .Pp .In sys/random.h diff --git a/share/man/man9/rijndael.9 b/share/man/man9/rijndael.9 index 48b402bc0f11..1d8d90412b0e 100644 --- a/share/man/man9/rijndael.9 +++ b/share/man/man9/rijndael.9 @@ -43,47 +43,47 @@ .Ft int .Fo rijndael_makeKey .Fa "keyInstance *key" -.Fa "u_int8_t direction" +.Fa "uint8_t direction" .Fa "int keyLen" .Fa "char *keyMaterial" .Fc .Ft int .Fo rijndael_cipherInit .Fa "cipherInstance *cipher" -.Fa "u_int8_t mode" +.Fa "uint8_t mode" .Fa "char *IV" .Fc .Ft int .Fo rijndael_blockEncrypt .Fa "cipherInstance *cipher" .Fa "keyInstance *key" -.Fa "u_int8_t *input" +.Fa "uint8_t *input" .Fa "int inputLen" -.Fa "u_int8_t *outBuffer" +.Fa "uint8_t *outBuffer" .Fc .Ft int .Fo rijndael_padEncrypt .Fa "cipherInstance *cipher" .Fa "keyInstance *key" -.Fa "u_int8_t *input" +.Fa "uint8_t *input" .Fa "int inputOctets" -.Fa "u_int8_t *outBuffer" +.Fa "uint8_t *outBuffer" .Fc .Ft int .Fo rijndael_blockDecrypt .Fa "cipherInstance *cipher" .Fa "keyInstance *key" -.Fa "u_int8_t *input" +.Fa "uint8_t *input" .Fa "int inputLen" -.Fa "u_int8_t *outBuffer" +.Fa "uint8_t *outBuffer" .Fc .Ft int .Fo rijndael_padDecrypt .Fa "cipherInstance *cipher" .Fa "keyInstance *key" -.Fa "u_int8_t *input" +.Fa "uint8_t *input" .Fa "int inputOctets" -.Fa "u_int8_t *outBuffer" +.Fa "uint8_t *outBuffer" .Fc .Sh DESCRIPTION The diff --git a/share/man/man9/zone.9 b/share/man/man9/zone.9 index 32531bb4ade1..df7a3530e769 100644 --- a/share/man/man9/zone.9 +++ b/share/man/man9/zone.9 @@ -47,7 +47,7 @@ .Fo uma_zcreate .Fa "char *name" "int size" .Fa "uma_ctor ctor" "uma_dtor dtor" "uma_init uminit" "uma_fini fini" -.Fa "int align" "u_int16_t flags" +.Fa "int align" "uint16_t flags" .Fc .Ft "void *" .Fn uma_zalloc "uma_zone_t zone" "int flags" diff --git a/share/misc/committers-ports.dot b/share/misc/committers-ports.dot index a4e858c95b31..e795bd0f3583 100644 --- a/share/misc/committers-ports.dot +++ b/share/misc/committers-ports.dot @@ -134,6 +134,7 @@ marcus [label="Joe Marcus Clarke\nmarcus@FreeBSD.org\n2002/04/05"] markus [label="Markus Brueffer\nmarkus@FreeBSD.org\n2004/02/21"] martymac [label="Ganael Laplanche\nmartymac@FreeBSD.org\n2010/09/24"] mat [label="Mathieu Arnold\nmat@FreeBSD.org\n2003/08/15"] +matthew [label="Matthew Seaman\nmatthew@FreeBSD.org\n2012/02/07"] mezz [label="Jeremy Messenger\nmezz@FreeBSD.org\n2004/04/30"] miwi [label="Martin Wilke\nmiwi@FreeBSD.org\n2006/06/04"] mm [label="Martin Matuska\nmm@FreeBSD.org\n2007/04/04"] @@ -184,6 +185,7 @@ trasz [label="Edward Tomasz Napierala\ntrasz@FreeBSD.org\n2007/04/12"] trhodes [label="Tom Rhodes\ntrhodes@FreeBSD.org\n2004/07/06"] thierry [label="Thierry Thomas\nthierry@FreeBSD.org\n2004/03/15"] tmclaugh [label="Tom McLaughlin\ntmclaugh@FreeBSD.org\n2005/09/15"] +uqs [label="Ulrich Spoerlein\nuqs@FreeBSD.org\n2012/01/19"] vd [label="Vasil Dimov\nvd@FreeBSD.org\n2006/01/19"] wen [label="Wen Heping\nwen@FreeBSD.org\n2010/12/13"] wxs [label="Wesley Shields\nwxs@FreeBSD.org\n2008/01/03"] @@ -220,6 +222,7 @@ bapt -> eadler bapt -> jlaffaye beat -> decke +beat -> uqs beech -> glarkin beech -> mva @@ -411,6 +414,7 @@ sem -> delphij sem -> stas shaun -> timur +shaun -> matthew sobomax -> demon sobomax -> glewis diff --git a/share/mk/bsd.kmod.mk b/share/mk/bsd.kmod.mk index 9c0434f70564..fd4f993de7cb 100644 --- a/share/mk/bsd.kmod.mk +++ b/share/mk/bsd.kmod.mk @@ -9,7 +9,7 @@ SYSDIR= ${_dir} .endfor .if !defined(SYSDIR) || !exists(${SYSDIR}/kern/) || \ !exists(${SYSDIR}/conf/kmod.mk) -.error "can't find kernel source tree" +.error Unable to locate the kernel source tree. Set SYSDIR to override. .endif .include "${SYSDIR}/conf/kmod.mk" diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index d3183c4a89f5..7ecb634aa6e3 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -320,6 +320,9 @@ __DEFAULT_YES_OPTIONS = \ BOOT \ BSD_CPIO \ BSNMP \ + SOURCELESS \ + SOURCELESS_HOST \ + SOURCELESS_UCODE \ BZIP2 \ CALENDAR \ CAPSICUM \ @@ -415,6 +418,7 @@ __DEFAULT_NO_OPTIONS = \ BIND_LIBS \ BIND_SIGCHASE \ BIND_XML \ + CLANG_EXTRAS \ CTF \ HESIOD \ ICONV \ @@ -511,11 +515,20 @@ MK_BIND_UTILS:= no MK_BIND_ETC:= no .endif +.if ${MK_SOURCELESS} == "no" +MK_SOURCELESS_HOST:= no +MK_SOURCELESS_UCODE:= no +.endif + .if ${MK_CDDL} == "no" MK_ZFS:= no MK_CTF:= no .endif +.if ${MK_CLANG} == "no" +MK_CLANG_EXTRAS:= no +.endif + .if ${MK_CRYPT} == "no" MK_OPENSSL:= no MK_OPENSSH:= no diff --git a/sys/amd64/acpica/acpi_switch.S b/sys/amd64/acpica/acpi_switch.S index 35295068539a..11e53564ccf8 100644 --- a/sys/amd64/acpica/acpi_switch.S +++ b/sys/amd64/acpica/acpi_switch.S @@ -120,15 +120,6 @@ ENTRY(acpi_restorecpu) #undef SDT_SYSTSS #undef SDT_SYSBSY - /* Restore other callee saved registers. */ - movq PCB_R15(%rdi), %r15 - movq PCB_R14(%rdi), %r14 - movq PCB_R13(%rdi), %r13 - movq PCB_R12(%rdi), %r12 - movq PCB_RBP(%rdi), %rbp - movq PCB_RSP(%rdi), %rsp - movq PCB_RBX(%rdi), %rbx - /* Restore debug registers. */ movq PCB_DR0(%rdi), %rax movq %rax, %dr0 @@ -145,6 +136,7 @@ ENTRY(acpi_restorecpu) /* Restore FPU state. */ fninit + movq WAKEUP_CTX(fpusave), %rbx movq WAKEUP_CTX(xsmask), %rax testq %rax, %rax jz 1f @@ -153,19 +145,26 @@ ENTRY(acpi_restorecpu) movl $XCR0, %ecx /* xsetbv */ .byte 0x0f, 0x01, 0xd1 - movq WAKEUP_CTX(fpusave), %rcx -/* xrstor (%rcx) */ - .byte 0x0f, 0xae, 0x29 +/* xrstor (%rbx) */ + .byte 0x0f, 0xae, 0x2b jmp 2f 1: - movq WAKEUP_CTX(fpusave), %rcx - fxrstor (%rcx) + fxrstor (%rbx) 2: /* Reload CR0. */ movq PCB_CR0(%rdi), %rax movq %rax, %cr0 + /* Restore other callee saved registers. */ + movq PCB_R15(%rdi), %r15 + movq PCB_R14(%rdi), %r14 + movq PCB_R13(%rdi), %r13 + movq PCB_R12(%rdi), %r12 + movq PCB_RBP(%rdi), %rbp + movq PCB_RSP(%rdi), %rsp + movq PCB_RBX(%rdi), %rbx + /* Restore return address. */ movq PCB_RIP(%rdi), %rax movq %rax, (%rsp) diff --git a/sys/amd64/acpica/acpi_wakecode.S b/sys/amd64/acpica/acpi_wakecode.S index 0f34d396e18a..82d0ab21e5a6 100644 --- a/sys/amd64/acpica/acpi_wakecode.S +++ b/sys/amd64/acpica/acpi_wakecode.S @@ -30,7 +30,9 @@ */ #include +#include #include +#include #include "assym.s" @@ -71,13 +73,21 @@ wakeup_start: testb $~0, resume_beep - wakeup_start jz 1f movb $0, resume_beep - wakeup_start - movb $0xc0, %al - outb %al, $0x42 - movb $0x04, %al - outb %al, $0x42 - inb $0x61, %al - orb $0x3, %al - outb %al, $0x61 + + /* Set PIC timer2 to beep. */ + movb $(TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT), %al + outb %al, $TIMER_MODE + + /* Turn on speaker. */ + inb $IO_PPI, %al + orb $PIT_SPKR, %al + outb %al, $IO_PPI + + /* Set frequency. */ + movw $0x4c0, %ax + outb %al, $TIMER_CNTR2 + shrw $8, %ax + outb %al, $TIMER_CNTR2 1: /* Re-initialize video BIOS if the reset_video tunable is set. */ diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c index bc5e08f0bc31..ec61ed986862 100644 --- a/sys/amd64/acpica/acpi_wakeup.c +++ b/sys/amd64/acpica/acpi_wakeup.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -40,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -74,7 +76,7 @@ static struct pcb **susppcbs; static void **suspfpusave; #endif -int acpi_restorecpu(vm_offset_t, struct pcb *); +int acpi_restorecpu(uint64_t, vm_offset_t); static void *acpi_alloc_wakeup_handler(void); static void acpi_stop_beep(void *); @@ -92,11 +94,12 @@ static void acpi_wakeup_cpus(struct acpi_softc *, const cpuset_t *); *addr = val; \ } while (0) -/* Turn off bits 1&2 of the PIT, stopping the beep. */ static void acpi_stop_beep(void *arg) { - outb(0x61, inb(0x61) & ~0x3); + + if (acpi_resume_beep != 0) + timer_spkr_release(); } #ifdef SMP @@ -220,7 +223,6 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) #ifdef SMP cpuset_t wakeup_cpus; #endif - register_t cr3, rf; ACPI_STATUS status; int ret; @@ -234,19 +236,14 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) CPU_CLR(PCPU_GET(cpuid), &wakeup_cpus); #endif + if (acpi_resume_beep != 0) + timer_spkr_acquire(); + AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc)); - rf = intr_disable(); + spinlock_enter(); intr_suspend(); - /* - * Temporarily switch to the kernel pmap because it provides - * an identity mapping (setup at boot) for the low physical - * memory region containing the wakeup code. - */ - cr3 = rcr3(); - load_cr3(KPML4phys); - if (savectx(susppcbs[0])) { ctx_fpusave(suspfpusave[0]); #ifdef SMP @@ -285,13 +282,13 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) ia32_pause(); } else { pmap_init_pat(); + load_cr3(susppcbs[0]->pcb_cr3); PCPU_SET(switchtime, 0); PCPU_SET(switchticks, ticks); #ifdef SMP if (!CPU_EMPTY(&wakeup_cpus)) acpi_wakeup_cpus(sc, &wakeup_cpus); #endif - acpi_resync_clock(sc); ret = 0; } @@ -301,10 +298,9 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) restart_cpus(wakeup_cpus); #endif - load_cr3(cr3); mca_resume(); intr_resume(); - intr_restore(rf); + spinlock_exit(); AcpiSetFirmwareWakingVector(0); @@ -312,10 +308,6 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) mem_range_softc.mr_op->reinit != NULL) mem_range_softc.mr_op->reinit(&mem_range_softc); - /* If we beeped, turn it off after a delay. */ - if (acpi_resume_beep) - timeout(acpi_stop_beep, NULL, 3 * hz); - return (ret); } @@ -332,12 +324,18 @@ acpi_alloc_wakeup_handler(void) * and ROM area (0xa0000 and above). The temporary page tables must be * page-aligned. */ - wakeaddr = contigmalloc(4 * PAGE_SIZE, M_DEVBUF, M_NOWAIT, 0x500, + wakeaddr = contigmalloc(4 * PAGE_SIZE, M_DEVBUF, M_WAITOK, 0x500, 0xa0000, PAGE_SIZE, 0ul); if (wakeaddr == NULL) { printf("%s: can't alloc wake memory\n", __func__); return (NULL); } + if (EVENTHANDLER_REGISTER(power_resume, acpi_stop_beep, NULL, + EVENTHANDLER_PRI_LAST) == NULL) { + printf("%s: can't register event handler\n", __func__); + contigfree(wakeaddr, 4 * PAGE_SIZE, M_DEVBUF); + return (NULL); + } susppcbs = malloc(mp_ncpus * sizeof(*susppcbs), M_DEVBUF, M_WAITOK); suspfpusave = malloc(mp_ncpus * sizeof(void *), M_DEVBUF, M_WAITOK); for (i = 0; i < mp_ncpus; i++) { diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S index 96c778d7fdbc..646524717c2c 100644 --- a/sys/amd64/amd64/apic_vector.S +++ b/sys/amd64/amd64/apic_vector.S @@ -300,13 +300,10 @@ IDTVEC(cpustop) IDTVEC(cpususpend) PUSH_FRAME + call cpususpend_handler movq lapic, %rax movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */ - - call cpususpend_handler - - POP_FRAME - jmp doreti_iret + jmp doreti /* * Executed by a CPU when it receives a RENDEZVOUS IPI from another CPU. diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index bc14745140b5..b45adde1c539 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1381,7 +1381,7 @@ getmemsize(caddr_t kmdp, u_int64_t first) { int i, physmap_idx, pa_indx, da_indx; vm_paddr_t pa, physmap[PHYSMAP_SIZE]; - u_long physmem_tunable, memtest; + u_long physmem_start, physmem_tunable, memtest; pt_entry_t *pte; struct bios_smap *smapbase, *smap, *smapend; u_int32_t smapsize; @@ -1469,8 +1469,19 @@ getmemsize(caddr_t kmdp, u_int64_t first) /* * Size up each available chunk of physical memory. + * + * XXX Some BIOSes corrupt low 64KB between suspend and resume. + * By default, mask off the first 16 pages unless we appear to be + * running in a VM. */ - physmap[0] = PAGE_SIZE; /* mask off page 0 */ + physmem_start = (vm_guest > VM_GUEST_NO ? 1 : 16) << PAGE_SHIFT; + TUNABLE_ULONG_FETCH("hw.physmem.start", &physmem_start); + if (physmem_start < PAGE_SIZE) + physmap[0] = PAGE_SIZE; + else if (physmem_start >= physmap[1]) + physmap[0] = round_page(physmap[1] - PAGE_SIZE); + else + physmap[0] = round_page(physmem_start); pa_indx = 0; da_indx = 1; phys_avail[pa_indx++] = physmap[0]; diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index da1812dd96ba..2c52fd16d5aa 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -1414,20 +1414,17 @@ cpustop_handler(void) void cpususpend_handler(void) { - register_t cr3, rf; u_int cpu; cpu = PCPU_GET(cpuid); - rf = intr_disable(); - cr3 = rcr3(); - if (savectx(susppcbs[cpu])) { ctx_fpusave(suspfpusave[cpu]); wbinvd(); CPU_SET_ATOMIC(cpu, &stopped_cpus); } else { pmap_init_pat(); + load_cr3(susppcbs[cpu]->pcb_cr3); PCPU_SET(switchtime, 0); PCPU_SET(switchticks, ticks); } @@ -1439,11 +1436,9 @@ cpususpend_handler(void) CPU_CLR_ATOMIC(cpu, &started_cpus); CPU_CLR_ATOMIC(cpu, &stopped_cpus); - /* Restore CR3 and enable interrupts */ - load_cr3(cr3); + /* Resume MCA and local APIC */ mca_resume(); lapic_setup(0); - intr_restore(rf); } /* diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c index acb21889ae3a..103fa0d509f8 100644 --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -552,6 +552,7 @@ cpu_set_user_tls(struct thread *td, void *tls_base) return (EINVAL); pcb = td->td_pcb; + set_pcb_flags(pcb, PCB_FULL_IRET); #ifdef COMPAT_FREEBSD32 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { pcb->pcb_gsbase = (register_t)tls_base; @@ -559,7 +560,6 @@ cpu_set_user_tls(struct thread *td, void *tls_base) } #endif pcb->pcb_fsbase = (register_t)tls_base; - set_pcb_flags(pcb, PCB_FULL_IRET); return (0); } diff --git a/sys/boot/ficl/fileaccess.c b/sys/boot/ficl/fileaccess.c index 686c72153e02..2b981c870975 100644 --- a/sys/boot/ficl/fileaccess.c +++ b/sys/boot/ficl/fileaccess.c @@ -420,6 +420,6 @@ void ficlCompileFile(FICL_SYSTEM *pSys) ficlSetEnv(pSys, "file-ext", FICL_TRUE); #endif /* FICL_HAVE_FTRUNCATE */ #else - &pSys; + (void)pSys; #endif /* FICL_WANT_FILE */ } diff --git a/sys/boot/ficl/i386/sysdep.h b/sys/boot/ficl/i386/sysdep.h index e1900e2a4659..94fda2047ede 100644 --- a/sys/boot/ficl/i386/sysdep.h +++ b/sys/boot/ficl/i386/sysdep.h @@ -58,7 +58,7 @@ #include #if !defined IGNORE /* Macro to silence unused param warnings */ -#define IGNORE(x) &x +#define IGNORE(x) (void)x #endif /* @@ -405,7 +405,7 @@ void *ficlRealloc(void *p, size_t size); #if FICL_MULTITHREAD int ficlLockDictionary(short fLock); #else -#define ficlLockDictionary(x) 0 /* ignore */ +#define ficlLockDictionary(x) /* ignore */ #endif /* diff --git a/sys/boot/pc98/loader/Makefile b/sys/boot/pc98/loader/Makefile index d289cceb9b41..48db11bd380f 100644 --- a/sys/boot/pc98/loader/Makefile +++ b/sys/boot/pc98/loader/Makefile @@ -3,7 +3,8 @@ .include MK_SSP= no -PROG= loader.sym +LOADER?= loader +PROG= ${LOADER}.sym INTERNALPROG= NEWVERSWHAT= "bootstrap loader" pc98 @@ -39,14 +40,14 @@ CFLAGS+= -DLOADER_BZIP2_SUPPORT CFLAGS+= -DLOADER_GZIP_SUPPORT .endif -# Always add MI sources +# Always add MI sources .PATH: ${.CURDIR}/../../common .include "${.CURDIR}/../../common/Makefile.inc" CFLAGS+= -I${.CURDIR}/../../common CFLAGS+= -I${.CURDIR}/../../i386 CFLAGS+= -I. -CLEANFILES= vers.c loader loader.bin loader.help +CLEANFILES= vers.c ${LOADER} ${LOADER}.bin loader.help CFLAGS+= -Wall LDFLAGS= -static -Ttext 0x0 @@ -68,36 +69,37 @@ CFLAGS+= -I${.CURDIR}/../btx/lib vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../../i386/loader/version sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../../i386/loader/version ${NEWVERSWHAT} -loader: loader.bin ${BTXLDR} ${BTXKERN} +${LOADER}: ${LOADER}.bin ${BTXLDR} ${BTXKERN} btxld -v -f aout -e ${LOADER_ADDRESS} -o ${.TARGET} -l ${BTXLDR} \ - -b ${BTXKERN} loader.bin + -b ${BTXKERN} ${LOADER}.bin -loader.bin: loader.sym +${LOADER}.bin: ${LOADER}.sym cp ${.ALLSRC} ${.TARGET} strip -R .comment -R .note ${.TARGET} loader.help: help.common help.pc98 cat ${.ALLSRC} | awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET} -.PATH: ${.CURDIR}/../../forth -FILES= loader loader.help loader.4th support.4th loader.conf +FILES= ${LOADER} +# XXX INSTALLFLAGS_loader= -b +FILESMODE_${LOADER}= ${BINMODE} -b + +.PATH: ${.CURDIR}/../../forth +FILES+= loader.help loader.4th support.4th loader.conf FILES+= screen.4th frames.4th beastie.4th FILES+= brand.4th check-password.4th color.4th delay.4th FILES+= menu.4th menu-commands.4th shortcuts.4th version.4th -# XXX INSTALLFLAGS_loader= -b -FILESMODE_loader= ${BINMODE} -b FILESDIR_loader.conf= /boot/defaults .if !exists(${DESTDIR}/boot/loader.rc) FILES+= ${.CURDIR}/../../i386/loader/loader.rc .endif - .if !exists(${DESTDIR}/boot/menu.rc) FILES+= menu.rc .endif # XXX crt0.o needs to be first for pxeboot(8) to work -OBJS= ${BTXCRT} +OBJS= ${BTXCRT} DPADD= ${LIBFICL} ${LIBPC98} ${LIBSTAND} LDADD= ${LIBFICL} ${LIBPC98} ${LIBSTAND} diff --git a/sys/boot/powerpc/boot1.chrp/Makefile b/sys/boot/powerpc/boot1.chrp/Makefile index 71d0ce6af975..943d146dbb98 100644 --- a/sys/boot/powerpc/boot1.chrp/Makefile +++ b/sys/boot/powerpc/boot1.chrp/Makefile @@ -8,16 +8,17 @@ BINDIR?= /boot INSTALLFLAGS= -b FILES= boot1.hfs -SRCS= boot1.c ashldi3.c +SRCS= boot1.c ashldi3.c syncicache.c NO_MAN= CFLAGS= -ffreestanding -msoft-float -Os \ - -I${.CURDIR}/../../common -I${.CURDIR}/../../../ + -I${.CURDIR}/../../common -I${.CURDIR}/../../../ \ + -D_STANDALONE LDFLAGS=-nostdlib -static -N .include "${.CURDIR}/../Makefile.inc" -.PATH: ${.CURDIR}/../../../libkern ${.CURDIR} +.PATH: ${.CURDIR}/../../../libkern ${.CURDIR}/../../../../lib/libc/powerpc/gen ${.CURDIR} # The following inserts out objects into a template HFS # created by generate-hfs.sh diff --git a/sys/boot/powerpc/boot1.chrp/boot1.c b/sys/boot/powerpc/boot1.chrp/boot1.c index f5bc4d575498..5ad405bbb480 100644 --- a/sys/boot/powerpc/boot1.chrp/boot1.c +++ b/sys/boot/powerpc/boot1.chrp/boot1.c @@ -77,6 +77,8 @@ static int __sputc(char c, void *arg); static char *__uitoa(char *buf, u_int val, int base); static char *__ultoa(char *buf, u_long val, int base); +void __syncicache(void *, int); + /* * Open Firmware interface functions */ @@ -523,6 +525,7 @@ load(const char *fname) } if (ph.p_filesz != ph.p_memsz) bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); + __syncicache(p, ph.p_memsz); } ofw_close(bootdev); (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0, diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c index bfd1e60f916d..058c2c2cbeb0 100644 --- a/sys/cam/ctl/ctl_frontend_cam_sim.c +++ b/sys/cam/ctl/ctl_frontend_cam_sim.c @@ -221,6 +221,7 @@ cfcs_init(void) mtx_lock(&softc->lock); if (xpt_bus_register(softc->sim, NULL, 0) != CAM_SUCCESS) { + mtx_unlock(&softc->lock); printf("%s: error registering SIM\n", __func__); retval = ENOMEM; goto bailout; @@ -230,6 +231,7 @@ cfcs_init(void) cam_sim_path(softc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + mtx_unlock(&softc->lock); printf("%s: error creating path\n", __func__); xpt_bus_deregister(cam_sim_path(softc->sim)); retval = 1; @@ -253,8 +255,6 @@ cfcs_init(void) else if (softc->devq) cam_simq_free(softc->devq); - mtx_unlock(&softc->lock); - return (retval); } diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 7ff4f7e59459..ce721806f18b 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -293,6 +293,14 @@ static struct scsi_quirk_entry scsi_quirk_table[] = { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST39140*", "*"}, /*quirks*/0, /*mintags*/2, /*maxtags*/2 }, + { + /* + * Experiences command timeouts under load with a + * tag count higher than 55. + */ + { T_DIRECT, SIP_MEDIA_FIXED, seagate, "ST3146855LW", "*"}, + /*quirks*/0, /*mintags*/2, /*maxtags*/55 + }, { /* * Slow when tagged queueing is enabled. Write performance diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c index 554da179c063..ca2b69ab12f9 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c @@ -20,9 +20,6 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Portions Copyright 2012 Sergey Kandaurov - * Portions Copyright 2012 Martin Matuska */ #include @@ -996,7 +993,7 @@ dnode_buf_pageout(dmu_buf_t *db, void *arg) dnh->dnh_dnode = NULL; } kmem_free(children_dnodes, sizeof (dnode_children_t) + - epb * sizeof (dnode_handle_t)); + (epb - 1) * sizeof (dnode_handle_t)); } /* @@ -1081,7 +1078,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int i; dnode_children_t *winner; children_dnodes = kmem_zalloc(sizeof (dnode_children_t) + - epb * sizeof (dnode_handle_t), KM_SLEEP); + (epb - 1) * sizeof (dnode_handle_t), KM_SLEEP); children_dnodes->dnc_count = epb; dnh = &children_dnodes->dnc_children[0]; for (i = 0; i < epb; i++) { @@ -1091,7 +1088,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, if (winner = dmu_buf_set_user(&db->db, children_dnodes, NULL, dnode_buf_pageout)) { kmem_free(children_dnodes, sizeof (dnode_children_t) + - epb * sizeof (dnode_handle_t)); + (epb - 1) * sizeof (dnode_handle_t)); children_dnodes = winner; } } diff --git a/sys/compat/freebsd32/freebsd32_signal.h b/sys/compat/freebsd32/freebsd32_signal.h index 2669581bf750..d31a8ae6b002 100644 --- a/sys/compat/freebsd32/freebsd32_signal.h +++ b/sys/compat/freebsd32/freebsd32_signal.h @@ -92,6 +92,7 @@ struct sigevent32 { uint32_t _function; uint32_t _attribute; } _sigev_thread; + unsigned short _kevent_flags; uint32_t __spare__[8]; } _sigev_un; }; diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c index bea7747fdb99..2e05c8543c39 100644 --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -66,7 +66,7 @@ translate_vnhook_major_minor(struct vnode *vp, struct stat *sb) int major, minor; if (vp->v_type == VCHR && vp->v_rdev != NULL && - linux_driver_get_major_minor(vp->v_rdev->si_name, + linux_driver_get_major_minor(devtoname(vp->v_rdev), &major, &minor) == 0) { sb->st_rdev = (major << 8 | minor); } @@ -149,14 +149,14 @@ translate_fd_major_minor(struct thread *td, int fd, struct stat *buf) return; vp = fp->f_vnode; if (vp != NULL && vp->v_rdev != NULL && - linux_driver_get_major_minor(vp->v_rdev->si_name, + linux_driver_get_major_minor(devtoname(vp->v_rdev), &major, &minor) == 0) { buf->st_rdev = (major << 8 | minor); } else if (fp->f_type == DTYPE_PTS) { struct tty *tp = fp->f_data; /* Convert the numbers for the slave device. */ - if (linux_driver_get_major_minor(tp->t_dev->si_name, + if (linux_driver_get_major_minor(devtoname(tp->t_dev), &major, &minor) == 0) { buf->st_rdev = (major << 8 | minor); } diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c index 3412c370b419..3c26f88d6983 100644 --- a/sys/compat/linux/linux_util.c +++ b/sys/compat/linux/linux_util.c @@ -124,7 +124,7 @@ linux_driver_get_name_dev(device_t dev) } int -linux_driver_get_major_minor(char *node, int *major, int *minor) +linux_driver_get_major_minor(const char *node, int *major, int *minor) { struct device_element *de; diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h index 13cd3598572c..2908a0fe4e2a 100644 --- a/sys/compat/linux/linux_util.h +++ b/sys/compat/linux/linux_util.h @@ -97,7 +97,7 @@ struct linux_device_handler { int linux_device_register_handler(struct linux_device_handler *h); int linux_device_unregister_handler(struct linux_device_handler *h); char *linux_driver_get_name_dev(device_t dev); -int linux_driver_get_major_minor(char *node, int *major, int *minor); +int linux_driver_get_major_minor(const char *node, int *major, int *minor); char *linux_get_char_devices(void); void linux_free_get_char_devices(char *string); diff --git a/sys/conf/NOTES b/sys/conf/NOTES index af351fa80c1a..c61c0a15ebc0 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1972,6 +1972,7 @@ device xmphy # XaQti XMAC II # SMC EZ Card 1000 (SMC9462TX), D-Link DGE-500T, Asante FriendlyNet # GigaNIX 1000TA and 1000TPC, the Addtron AEG320T, the Surecom # EP-320G-TX and the Netgear GA622T. +# oce: Emulex 10 Gbit adapters (OneConnect Ethernet) # pcn: Support for PCI fast ethernet adapters based on the AMD Am79c97x # PCnet-FAST, PCnet-FAST+, PCnet-FAST III, PCnet-PRO and PCnet-Home # chipsets. These can also be handled by the le(4) driver if the @@ -2112,6 +2113,7 @@ device ixgbe # Intel Pro/10Gbe PCIE Ethernet device le # AMD Am7900 LANCE and Am79C9xx PCnet device mxge # Myricom Myri-10G 10GbE NIC device nxge # Neterion Xframe 10GbE Server/Storage Adapter +device oce # Emulex 10 GbE (OneConnect Ethernet) device ti # Alteon Networks Tigon I/II gigabit Ethernet device txp # 3Com 3cR990 (``Typhoon'') device vx # 3Com 3c590, 3c595 (``Vortex'') diff --git a/sys/conf/WITHOUT_SOURCELESS b/sys/conf/WITHOUT_SOURCELESS new file mode 100644 index 000000000000..3425dda64487 --- /dev/null +++ b/sys/conf/WITHOUT_SOURCELESS @@ -0,0 +1,7 @@ +# +# WITHOUT_SOURCELESS -- Disable drivers that include sourceless code. +# +# $FreeBSD$ + +include WITHOUT_SOURCELESS_HOST +include WITHOUT_SOURCELESS_UCODE diff --git a/sys/conf/WITHOUT_SOURCELESS_HOST b/sys/conf/WITHOUT_SOURCELESS_HOST new file mode 100644 index 000000000000..7775fb894d10 --- /dev/null +++ b/sys/conf/WITHOUT_SOURCELESS_HOST @@ -0,0 +1,10 @@ +# +# WITHOUT_SOURCELESS_HOST -- Disable drivers that include sourceless +# native code for host CPU. +# +# $FreeBSD$ + +nodevice hpt27xx +nodevice hptmv +nodevice hptrr +nodevice nve diff --git a/sys/conf/WITHOUT_SOURCELESS_UCODE b/sys/conf/WITHOUT_SOURCELESS_UCODE new file mode 100644 index 000000000000..3d02c21257d7 --- /dev/null +++ b/sys/conf/WITHOUT_SOURCELESS_UCODE @@ -0,0 +1,41 @@ +# +# WITHOUT_SOURCELESS_UCODE -- Disable drivers that include sourceless +# microcode. +# +# $FreeBSD$ + +nodevice adw +nodevice bce +nodevice fatm +nodevice fxp +nodevice ispfw +nodevice mwlfw +nodevice ralfw +nodevice runfw +nodevice sf +nodevice sn +nodevice ti +nodevice txp +nodevice ce +nodevice cp +nodevice ctau +nodevice ipwfw +nodevice iwifw +nodevice iwnfw +nodevice wpifw + +# drm +nodevice mga +nodevice r128 +nodevice radeon + +# sound +nodevice csa +nodevice ds1 +nodevice maestro3 + +# usb +nodevice rum +nodevice uath +nodevice zyd +nodevice kue diff --git a/sys/conf/files b/sys/conf/files index 7df4f6720a61..57de9cad0de7 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -153,155 +153,157 @@ contrib/altq/altq/altq_rio.c optional altq \ contrib/altq/altq/altq_rmclass.c optional altq contrib/altq/altq/altq_subr.c optional altq \ compile-with "${NORMAL_C} -I$S/contrib/pf" -contrib/dev/acpica/debugger/dbcmds.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbdisply.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbexec.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbfileio.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbhistry.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbinput.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbmethod.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbnames.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbstats.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbutils.c optional acpi acpi_debug -contrib/dev/acpica/debugger/dbxface.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmbuffer.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmnames.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmopcode.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmobject.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmresrc.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmresrcl.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmresrcl2.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmresrcs.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmutils.c optional acpi acpi_debug -contrib/dev/acpica/disassembler/dmwalk.c optional acpi acpi_debug -contrib/dev/acpica/dispatcher/dsargs.c optional acpi -contrib/dev/acpica/dispatcher/dscontrol.c optional acpi -contrib/dev/acpica/dispatcher/dsfield.c optional acpi -contrib/dev/acpica/dispatcher/dsinit.c optional acpi -contrib/dev/acpica/dispatcher/dsmethod.c optional acpi -contrib/dev/acpica/dispatcher/dsmthdat.c optional acpi -contrib/dev/acpica/dispatcher/dsobject.c optional acpi -contrib/dev/acpica/dispatcher/dsopcode.c optional acpi -contrib/dev/acpica/dispatcher/dsutils.c optional acpi -contrib/dev/acpica/dispatcher/dswexec.c optional acpi -contrib/dev/acpica/dispatcher/dswload.c optional acpi -contrib/dev/acpica/dispatcher/dswload2.c optional acpi -contrib/dev/acpica/dispatcher/dswscope.c optional acpi -contrib/dev/acpica/dispatcher/dswstate.c optional acpi -contrib/dev/acpica/events/evevent.c optional acpi -contrib/dev/acpica/events/evglock.c optional acpi -contrib/dev/acpica/events/evgpe.c optional acpi -contrib/dev/acpica/events/evgpeblk.c optional acpi -contrib/dev/acpica/events/evgpeinit.c optional acpi -contrib/dev/acpica/events/evgpeutil.c optional acpi -contrib/dev/acpica/events/evmisc.c optional acpi -contrib/dev/acpica/events/evregion.c optional acpi -contrib/dev/acpica/events/evrgnini.c optional acpi -contrib/dev/acpica/events/evsci.c optional acpi -contrib/dev/acpica/events/evxface.c optional acpi -contrib/dev/acpica/events/evxfevnt.c optional acpi -contrib/dev/acpica/events/evxfgpe.c optional acpi -contrib/dev/acpica/events/evxfregn.c optional acpi -contrib/dev/acpica/executer/exconfig.c optional acpi -contrib/dev/acpica/executer/exconvrt.c optional acpi -contrib/dev/acpica/executer/excreate.c optional acpi -contrib/dev/acpica/executer/exdebug.c optional acpi -contrib/dev/acpica/executer/exdump.c optional acpi -contrib/dev/acpica/executer/exfield.c optional acpi -contrib/dev/acpica/executer/exfldio.c optional acpi -contrib/dev/acpica/executer/exmisc.c optional acpi -contrib/dev/acpica/executer/exmutex.c optional acpi -contrib/dev/acpica/executer/exnames.c optional acpi -contrib/dev/acpica/executer/exoparg1.c optional acpi -contrib/dev/acpica/executer/exoparg2.c optional acpi -contrib/dev/acpica/executer/exoparg3.c optional acpi -contrib/dev/acpica/executer/exoparg6.c optional acpi -contrib/dev/acpica/executer/exprep.c optional acpi -contrib/dev/acpica/executer/exregion.c optional acpi -contrib/dev/acpica/executer/exresnte.c optional acpi -contrib/dev/acpica/executer/exresolv.c optional acpi -contrib/dev/acpica/executer/exresop.c optional acpi -contrib/dev/acpica/executer/exstore.c optional acpi -contrib/dev/acpica/executer/exstoren.c optional acpi -contrib/dev/acpica/executer/exstorob.c optional acpi -contrib/dev/acpica/executer/exsystem.c optional acpi -contrib/dev/acpica/executer/exutils.c optional acpi -contrib/dev/acpica/hardware/hwacpi.c optional acpi -contrib/dev/acpica/hardware/hwgpe.c optional acpi -contrib/dev/acpica/hardware/hwpci.c optional acpi -contrib/dev/acpica/hardware/hwregs.c optional acpi -contrib/dev/acpica/hardware/hwsleep.c optional acpi -contrib/dev/acpica/hardware/hwtimer.c optional acpi -contrib/dev/acpica/hardware/hwvalid.c optional acpi -contrib/dev/acpica/hardware/hwxface.c optional acpi -contrib/dev/acpica/namespace/nsaccess.c optional acpi -contrib/dev/acpica/namespace/nsalloc.c optional acpi -contrib/dev/acpica/namespace/nsdump.c optional acpi -contrib/dev/acpica/namespace/nseval.c optional acpi -contrib/dev/acpica/namespace/nsinit.c optional acpi -contrib/dev/acpica/namespace/nsload.c optional acpi -contrib/dev/acpica/namespace/nsnames.c optional acpi -contrib/dev/acpica/namespace/nsobject.c optional acpi -contrib/dev/acpica/namespace/nsparse.c optional acpi -contrib/dev/acpica/namespace/nspredef.c optional acpi -contrib/dev/acpica/namespace/nsrepair.c optional acpi -contrib/dev/acpica/namespace/nsrepair2.c optional acpi -contrib/dev/acpica/namespace/nssearch.c optional acpi -contrib/dev/acpica/namespace/nsutils.c optional acpi -contrib/dev/acpica/namespace/nswalk.c optional acpi -contrib/dev/acpica/namespace/nsxfeval.c optional acpi -contrib/dev/acpica/namespace/nsxfname.c optional acpi -contrib/dev/acpica/namespace/nsxfobj.c optional acpi -contrib/dev/acpica/parser/psargs.c optional acpi -contrib/dev/acpica/parser/psloop.c optional acpi -contrib/dev/acpica/parser/psopcode.c optional acpi -contrib/dev/acpica/parser/psparse.c optional acpi -contrib/dev/acpica/parser/psscope.c optional acpi -contrib/dev/acpica/parser/pstree.c optional acpi -contrib/dev/acpica/parser/psutils.c optional acpi -contrib/dev/acpica/parser/pswalk.c optional acpi -contrib/dev/acpica/parser/psxface.c optional acpi -contrib/dev/acpica/resources/rsaddr.c optional acpi -contrib/dev/acpica/resources/rscalc.c optional acpi -contrib/dev/acpica/resources/rscreate.c optional acpi -contrib/dev/acpica/resources/rsdump.c optional acpi -contrib/dev/acpica/resources/rsinfo.c optional acpi -contrib/dev/acpica/resources/rsio.c optional acpi -contrib/dev/acpica/resources/rsirq.c optional acpi -contrib/dev/acpica/resources/rslist.c optional acpi -contrib/dev/acpica/resources/rsmemory.c optional acpi -contrib/dev/acpica/resources/rsmisc.c optional acpi -contrib/dev/acpica/resources/rsserial.c optional acpi -contrib/dev/acpica/resources/rsutils.c optional acpi -contrib/dev/acpica/resources/rsxface.c optional acpi -contrib/dev/acpica/tables/tbfadt.c optional acpi -contrib/dev/acpica/tables/tbfind.c optional acpi -contrib/dev/acpica/tables/tbinstal.c optional acpi -contrib/dev/acpica/tables/tbutils.c optional acpi -contrib/dev/acpica/tables/tbxface.c optional acpi -contrib/dev/acpica/tables/tbxfroot.c optional acpi -contrib/dev/acpica/utilities/utaddress.c optional acpi -contrib/dev/acpica/utilities/utalloc.c optional acpi -contrib/dev/acpica/utilities/utcache.c optional acpi -contrib/dev/acpica/utilities/utcopy.c optional acpi -contrib/dev/acpica/utilities/utdebug.c optional acpi -contrib/dev/acpica/utilities/utdecode.c optional acpi -contrib/dev/acpica/utilities/utdelete.c optional acpi -contrib/dev/acpica/utilities/uteval.c optional acpi -contrib/dev/acpica/utilities/utglobal.c optional acpi -contrib/dev/acpica/utilities/utids.c optional acpi -contrib/dev/acpica/utilities/utinit.c optional acpi -contrib/dev/acpica/utilities/utlock.c optional acpi -contrib/dev/acpica/utilities/utmath.c optional acpi -contrib/dev/acpica/utilities/utmisc.c optional acpi -contrib/dev/acpica/utilities/utmutex.c optional acpi -contrib/dev/acpica/utilities/utobject.c optional acpi -contrib/dev/acpica/utilities/utosi.c optional acpi -contrib/dev/acpica/utilities/utresrc.c optional acpi -contrib/dev/acpica/utilities/utstate.c optional acpi -contrib/dev/acpica/utilities/utxface.c optional acpi -contrib/dev/acpica/utilities/utxferror.c optional acpi -#contrib/dev/acpica/utilities/utxfmutex.c optional acpi +contrib/dev/acpica/components/debugger/dbcmds.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbdisply.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbexec.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbfileio.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbhistry.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbinput.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbmethod.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbnames.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbstats.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbutils.c optional acpi acpi_debug +contrib/dev/acpica/components/debugger/dbxface.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmbuffer.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmnames.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmopcode.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmobject.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmresrc.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmresrcl.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmresrcl2.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmresrcs.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmutils.c optional acpi acpi_debug +contrib/dev/acpica/components/disassembler/dmwalk.c optional acpi acpi_debug +contrib/dev/acpica/components/dispatcher/dsargs.c optional acpi +contrib/dev/acpica/components/dispatcher/dscontrol.c optional acpi +contrib/dev/acpica/components/dispatcher/dsfield.c optional acpi +contrib/dev/acpica/components/dispatcher/dsinit.c optional acpi +contrib/dev/acpica/components/dispatcher/dsmethod.c optional acpi +contrib/dev/acpica/components/dispatcher/dsmthdat.c optional acpi +contrib/dev/acpica/components/dispatcher/dsobject.c optional acpi +contrib/dev/acpica/components/dispatcher/dsopcode.c optional acpi +contrib/dev/acpica/components/dispatcher/dsutils.c optional acpi +contrib/dev/acpica/components/dispatcher/dswexec.c optional acpi +contrib/dev/acpica/components/dispatcher/dswload.c optional acpi +contrib/dev/acpica/components/dispatcher/dswload2.c optional acpi +contrib/dev/acpica/components/dispatcher/dswscope.c optional acpi +contrib/dev/acpica/components/dispatcher/dswstate.c optional acpi +contrib/dev/acpica/components/events/evevent.c optional acpi +contrib/dev/acpica/components/events/evglock.c optional acpi +contrib/dev/acpica/components/events/evgpe.c optional acpi +contrib/dev/acpica/components/events/evgpeblk.c optional acpi +contrib/dev/acpica/components/events/evgpeinit.c optional acpi +contrib/dev/acpica/components/events/evgpeutil.c optional acpi +contrib/dev/acpica/components/events/evmisc.c optional acpi +contrib/dev/acpica/components/events/evregion.c optional acpi +contrib/dev/acpica/components/events/evrgnini.c optional acpi +contrib/dev/acpica/components/events/evsci.c optional acpi +contrib/dev/acpica/components/events/evxface.c optional acpi +contrib/dev/acpica/components/events/evxfevnt.c optional acpi +contrib/dev/acpica/components/events/evxfgpe.c optional acpi +contrib/dev/acpica/components/events/evxfregn.c optional acpi +contrib/dev/acpica/components/executer/exconfig.c optional acpi +contrib/dev/acpica/components/executer/exconvrt.c optional acpi +contrib/dev/acpica/components/executer/excreate.c optional acpi +contrib/dev/acpica/components/executer/exdebug.c optional acpi +contrib/dev/acpica/components/executer/exdump.c optional acpi +contrib/dev/acpica/components/executer/exfield.c optional acpi +contrib/dev/acpica/components/executer/exfldio.c optional acpi +contrib/dev/acpica/components/executer/exmisc.c optional acpi +contrib/dev/acpica/components/executer/exmutex.c optional acpi +contrib/dev/acpica/components/executer/exnames.c optional acpi +contrib/dev/acpica/components/executer/exoparg1.c optional acpi +contrib/dev/acpica/components/executer/exoparg2.c optional acpi +contrib/dev/acpica/components/executer/exoparg3.c optional acpi +contrib/dev/acpica/components/executer/exoparg6.c optional acpi +contrib/dev/acpica/components/executer/exprep.c optional acpi +contrib/dev/acpica/components/executer/exregion.c optional acpi +contrib/dev/acpica/components/executer/exresnte.c optional acpi +contrib/dev/acpica/components/executer/exresolv.c optional acpi +contrib/dev/acpica/components/executer/exresop.c optional acpi +contrib/dev/acpica/components/executer/exstore.c optional acpi +contrib/dev/acpica/components/executer/exstoren.c optional acpi +contrib/dev/acpica/components/executer/exstorob.c optional acpi +contrib/dev/acpica/components/executer/exsystem.c optional acpi +contrib/dev/acpica/components/executer/exutils.c optional acpi +contrib/dev/acpica/components/hardware/hwacpi.c optional acpi +contrib/dev/acpica/components/hardware/hwesleep.c optional acpi +contrib/dev/acpica/components/hardware/hwgpe.c optional acpi +contrib/dev/acpica/components/hardware/hwpci.c optional acpi +contrib/dev/acpica/components/hardware/hwregs.c optional acpi +contrib/dev/acpica/components/hardware/hwsleep.c optional acpi +contrib/dev/acpica/components/hardware/hwtimer.c optional acpi +contrib/dev/acpica/components/hardware/hwvalid.c optional acpi +contrib/dev/acpica/components/hardware/hwxface.c optional acpi +contrib/dev/acpica/components/hardware/hwxfsleep.c optional acpi +contrib/dev/acpica/components/namespace/nsaccess.c optional acpi +contrib/dev/acpica/components/namespace/nsalloc.c optional acpi +contrib/dev/acpica/components/namespace/nsdump.c optional acpi +contrib/dev/acpica/components/namespace/nseval.c optional acpi +contrib/dev/acpica/components/namespace/nsinit.c optional acpi +contrib/dev/acpica/components/namespace/nsload.c optional acpi +contrib/dev/acpica/components/namespace/nsnames.c optional acpi +contrib/dev/acpica/components/namespace/nsobject.c optional acpi +contrib/dev/acpica/components/namespace/nsparse.c optional acpi +contrib/dev/acpica/components/namespace/nspredef.c optional acpi +contrib/dev/acpica/components/namespace/nsrepair.c optional acpi +contrib/dev/acpica/components/namespace/nsrepair2.c optional acpi +contrib/dev/acpica/components/namespace/nssearch.c optional acpi +contrib/dev/acpica/components/namespace/nsutils.c optional acpi +contrib/dev/acpica/components/namespace/nswalk.c optional acpi +contrib/dev/acpica/components/namespace/nsxfeval.c optional acpi +contrib/dev/acpica/components/namespace/nsxfname.c optional acpi +contrib/dev/acpica/components/namespace/nsxfobj.c optional acpi +contrib/dev/acpica/components/parser/psargs.c optional acpi +contrib/dev/acpica/components/parser/psloop.c optional acpi +contrib/dev/acpica/components/parser/psopcode.c optional acpi +contrib/dev/acpica/components/parser/psparse.c optional acpi +contrib/dev/acpica/components/parser/psscope.c optional acpi +contrib/dev/acpica/components/parser/pstree.c optional acpi +contrib/dev/acpica/components/parser/psutils.c optional acpi +contrib/dev/acpica/components/parser/pswalk.c optional acpi +contrib/dev/acpica/components/parser/psxface.c optional acpi +contrib/dev/acpica/components/resources/rsaddr.c optional acpi +contrib/dev/acpica/components/resources/rscalc.c optional acpi +contrib/dev/acpica/components/resources/rscreate.c optional acpi +contrib/dev/acpica/components/resources/rsdump.c optional acpi +contrib/dev/acpica/components/resources/rsinfo.c optional acpi +contrib/dev/acpica/components/resources/rsio.c optional acpi +contrib/dev/acpica/components/resources/rsirq.c optional acpi +contrib/dev/acpica/components/resources/rslist.c optional acpi +contrib/dev/acpica/components/resources/rsmemory.c optional acpi +contrib/dev/acpica/components/resources/rsmisc.c optional acpi +contrib/dev/acpica/components/resources/rsserial.c optional acpi +contrib/dev/acpica/components/resources/rsutils.c optional acpi +contrib/dev/acpica/components/resources/rsxface.c optional acpi +contrib/dev/acpica/components/tables/tbfadt.c optional acpi +contrib/dev/acpica/components/tables/tbfind.c optional acpi +contrib/dev/acpica/components/tables/tbinstal.c optional acpi +contrib/dev/acpica/components/tables/tbutils.c optional acpi +contrib/dev/acpica/components/tables/tbxface.c optional acpi +contrib/dev/acpica/components/tables/tbxfroot.c optional acpi +contrib/dev/acpica/components/utilities/utaddress.c optional acpi +contrib/dev/acpica/components/utilities/utalloc.c optional acpi +contrib/dev/acpica/components/utilities/utcache.c optional acpi +contrib/dev/acpica/components/utilities/utcopy.c optional acpi +contrib/dev/acpica/components/utilities/utdebug.c optional acpi +contrib/dev/acpica/components/utilities/utdecode.c optional acpi +contrib/dev/acpica/components/utilities/utdelete.c optional acpi +contrib/dev/acpica/components/utilities/uteval.c optional acpi +contrib/dev/acpica/components/utilities/utglobal.c optional acpi +contrib/dev/acpica/components/utilities/utids.c optional acpi +contrib/dev/acpica/components/utilities/utinit.c optional acpi +contrib/dev/acpica/components/utilities/utlock.c optional acpi +contrib/dev/acpica/components/utilities/utmath.c optional acpi +contrib/dev/acpica/components/utilities/utmisc.c optional acpi +contrib/dev/acpica/components/utilities/utmutex.c optional acpi +contrib/dev/acpica/components/utilities/utobject.c optional acpi +contrib/dev/acpica/components/utilities/utosi.c optional acpi +contrib/dev/acpica/components/utilities/utresrc.c optional acpi +contrib/dev/acpica/components/utilities/utstate.c optional acpi +contrib/dev/acpica/components/utilities/utxface.c optional acpi +contrib/dev/acpica/components/utilities/utxferror.c optional acpi +#contrib/dev/acpica/components/utilities/utxfmutex.c optional acpi contrib/ipfilter/netinet/fil.c optional ipfilter inet \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_auth.c optional ipfilter inet \ @@ -1549,6 +1551,12 @@ dev/nmdm/nmdm.c optional nmdm dev/nsp/nsp.c optional nsp dev/nsp/nsp_pccard.c optional nsp pccard dev/null/null.c standard +dev/oce/oce_hw.c optional oce pci +dev/oce/oce_if.c optional oce pci +dev/oce/oce_mbox.c optional oce pci +dev/oce/oce_queue.c optional oce pci +dev/oce/oce_sysctl.c optional oce pci +dev/oce/oce_util.c optional oce pci dev/patm/if_patm.c optional patm pci dev/patm/if_patm_attach.c optional patm pci dev/patm/if_patm_intr.c optional patm pci @@ -2405,9 +2413,8 @@ kern/sched_ule.c optional sched_ule kern/serdev_if.m standard kern/stack_protector.c standard \ compile-with "${NORMAL_C:N-fstack-protector*}" -# XXX subr_acl_nfs4.c is also used by ZFS -kern/subr_acl_nfs4.c optional ufs_acl -kern/subr_acl_posix1e.c optional ufs_acl +kern/subr_acl_nfs4.c standard +kern/subr_acl_posix1e.c standard kern/subr_autoconf.c standard kern/subr_blist.c standard kern/subr_bus.c standard @@ -2500,17 +2507,17 @@ kern/vfs_vnops.c standard # gssd.h optional kgssapi \ dependency "$S/kgssapi/gssd.x" \ - compile-with "rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h" \ + compile-with "RPCGEN_CPP='${CPP}' rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h" \ no-obj no-implicit-rule before-depend local \ clean "gssd.h" gssd_xdr.c optional kgssapi \ dependency "$S/kgssapi/gssd.x gssd.h" \ - compile-with "rpcgen -c $S/kgssapi/gssd.x -o gssd_xdr.c" \ + compile-with "RPCGEN_CPP='${CPP}' rpcgen -c $S/kgssapi/gssd.x -o gssd_xdr.c" \ no-implicit-rule before-depend local \ clean "gssd_xdr.c" gssd_clnt.c optional kgssapi \ dependency "$S/kgssapi/gssd.x gssd.h" \ - compile-with "rpcgen -lM $S/kgssapi/gssd.x | grep -v string.h > gssd_clnt.c" \ + compile-with "RPCGEN_CPP='${CPP}' rpcgen -lM $S/kgssapi/gssd.x | grep -v string.h > gssd_clnt.c" \ no-implicit-rule before-depend local \ clean "gssd_clnt.c" kgssapi/gss_accept_sec_context.c optional kgssapi diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 2760edf14112..31dfb91b275d 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -133,6 +133,7 @@ powerpc/mpc85xx/openpic_fdt.c optional fdt powerpc/mpc85xx/pci_fdt.c optional pci mpc85xx powerpc/ofw/ofw_cpu.c optional aim powerpc/ofw/ofw_machdep.c optional aim +powerpc/ofw/ofw_pci.c optional pci aim powerpc/ofw/ofw_pcibus.c optional pci aim powerpc/ofw/ofw_pcib_pci.c optional pci aim powerpc/ofw/ofw_real.c optional aim diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 44d74fe3749c..cd523cab6441 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -92,11 +92,15 @@ for dir in /bin /usr/bin /usr/local/bin; do svnversion=${dir}/svnversion break fi - if [ -d "${SYSDIR}/../.git" -a -x "${dir}/git" ] ; then - git_cmd="${dir}/git --git-dir=${SYSDIR}/../.git" - break - fi done +if [ -d "${SYSDIR}/../.git" ] ; then + for dir in /bin /usr/bin /usr/local/bin; do + if [ -x "${dir}/git" ] ; then + git_cmd="${dir}/git --git-dir=${SYSDIR}/../.git" + break + fi + done +fi if [ -n "$svnversion" ] ; then svn=`cd ${SYSDIR} && $svnversion` diff --git a/sys/contrib/dev/acpica/acpica_prep.sh b/sys/contrib/dev/acpica/acpica_prep.sh index dccf7968738d..74aaaa5e4c0c 100755 --- a/sys/contrib/dev/acpica/acpica_prep.sh +++ b/sys/contrib/dev/acpica/acpica_prep.sh @@ -14,12 +14,10 @@ wrk=`realpath ./_acpi_ca_unpack` dst=`realpath ./acpi_ca_destination` # files that should keep their full directory path -fulldirs="common compiler debugger disassembler dispatcher events \ - executer hardware include namespace os_specific parser \ - resources tables utilities" +fulldirs="common compiler components include os_specific" # files to remove -stripdirs="generate tests tools" +stripdirs="generate libraries tests tools" stripfiles="Makefile README acintel.h aclinux.h acmsvc.h acnetbsd.h \ acos2.h accygwin.h acefi.h acwin.h acwin64.h osunixdir.c \ oswindir.c oswintbl.c oswinxf.c readme.txt utclib.c" diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt index 3271b2b95020..f328ad1f847c 100644 --- a/sys/contrib/dev/acpica/changes.txt +++ b/sys/contrib/dev/acpica/changes.txt @@ -1,3 +1,95 @@ +---------------------------------------- +15 February 2012. Summary of changes for version 20120215: + +This release is available at www.acpica.org/downloads. +The ACPI 5.0 specification is available at www.acpi.info. + +1) ACPICA Core Subsystem: + +There have been some major changes to the sleep/wake support code, as +described below (a - e). + +a) The AcpiLeaveSleepState has been split into two interfaces, similar to +AcpiEnterSleepStatePrep and AcpiEnterSleepState. The new interface is +AcpiLeaveSleepStatePrep. This allows the host to perform actions between the +time the _BFS method is called and the _WAK method is called. NOTE: all hosts +must update their wake/resume code or else sleep/wake will not work properly. +Rafael Wysocki. + +b) In AcpiLeaveSleepState, now enable all runtime GPEs before calling the _WAK +method. Some machines require that the GPEs are enabled before the _WAK method +is executed. Thomas Renninger. + +c) In AcpiLeaveSleepState, now always clear the WAK_STS (wake status) bit. +Some BIOS code assumes that WAK_STS will be cleared on resume and use it to +determine whether the system is rebooting or resuming. Matthew Garrett. + +d) Move the invocations of _GTS (Going To Sleep) and _BFS (Back From Sleep) to +match the ACPI specification requirement. Rafael Wysocki. + +e) Implemented full support for the ACPI 5.0 SleepStatus and SleepControl +registers within the V5 FADT. This support adds two new files: +hardware/hwesleep.c implements the support for the new registers. Moved all +sleep/wake external interfaces to hardware/hwxfsleep.c. + + +Added a new OSL interface for ACPI table overrides, +AcpiOsPhysicalTableOverride. This interface allows the host to override a +table via a physical address, instead of the logical address required by +AcpiOsTableOverride. This simplifies the host implementation. Initial +implementation by Thomas Renninger. The ACPICA implementation creates a single +shared function for table overrides that attempts both a logical and a +physical override. + +Expanded the OSL memory read/write interfaces to 64-bit data +(AcpiOsReadMemory, AcpiOsWriteMemory.) This enables full 64-bit memory +transfer support for GAS register structures passed to AcpiRead and AcpiWrite. + +Implemented the ACPI_REDUCED_HARDWARE option to allow the creation of a custom +build of ACPICA that supports only the ACPI 5.0 reduced hardware (SoC) model. +See the ACPICA reference for details. ACPICA BZ 942. This option removes about +10% of the code and 5% of the static data, and the following hardware ACPI +features become unavailable: + PM Event and Control registers + SCI interrupt (and handler) + Fixed Events + General Purpose Events (GPEs) + Global Lock + ACPI PM timer + FACS table (Waking vectors and Global Lock) + +Updated the unix tarball directory structure to match the ACPICA git source +tree. This ensures that the generic unix makefiles work properly (in +generate/unix). Also updated the Linux makefiles to match. ACPICA BZ 867. + +Updated the return value of the _REV predefined method to integer value 5 to +reflect ACPI 5.0 support. + +Moved the external ACPI PM timer interface prototypes to the public acpixf.h +file where they belong. + +Example Code and Data Size: These are the sizes for the OS-independent +acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The debug +version of the code includes the debug output trace mechanism and has a much +larger code and data size. + + Previous Release: + Non-Debug Version: 92.8K Code, 24.9K Data, 117.7K Total + Debug Version: 171.7K Code, 72.9K Data, 244.5K Total + Current Release: + Non-Debug Version: 93.0K Code, 25.0K Data, 118.0K Total + Debug Version: 172.5K Code, 73.2K Data, 245.7K Total + + +2) iASL Compiler/Disassembler and Tools: + +Disassembler: Fixed a problem with the new ACPI 5.0 serial resource +descriptors (I2C, SPI, UART) where the resource produce/consumer bit was +incorrectly displayed. + +AcpiHelp: Add display of ACPI/PNP device IDs that are defined in the ACPI +specification. + ---------------------------------------- 11 January 2012. Summary of changes for version 20120111: diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2s.c b/sys/contrib/dev/acpica/compiler/aslrestype2s.c index 4c54d24f0df7..fa30b588a9f4 100644 --- a/sys/contrib/dev/acpica/compiler/aslrestype2s.c +++ b/sys/contrib/dev/acpica/compiler/aslrestype2s.c @@ -192,7 +192,7 @@ RsGetVendorData ( UINT16 ActualLength = 0; - /* VendorData field is always optional */ + /* Vendor Data field is always optional */ if (InitializerOp->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) { @@ -374,7 +374,7 @@ RsDoGpioIntDescriptor ( CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.PinConfig)); break; - case 4: /* DebounceTimeout [WORD] (_DBT) */ + case 4: /* Debounce Timeout [WORD] (_DBT) */ Descriptor->Gpio.DebounceTimeout = (UINT16) InitializerOp->Asl.Value.Integer; RsCreateWordField (InitializerOp, ACPI_RESTAG_DEBOUNCETIME, @@ -405,7 +405,7 @@ RsDoGpioIntDescriptor ( RsSetFlagBits16 (&Descriptor->Gpio.Flags, InitializerOp, 0, 1); break; - case 8: /* ResourceTag (Descriptor Name) */ + case 8: /* Resource Tag (Descriptor Name) */ UtAttachNamepathToOwner (Op, InitializerOp); break; @@ -566,7 +566,7 @@ RsDoGpioIoDescriptor ( CurrentByteOffset + ASL_RESDESC_OFFSET (Gpio.PinConfig)); break; - case 2: /* DebounceTimeout [WORD] (_DBT) */ + case 2: /* Debounce Timeout [WORD] (_DBT) */ Descriptor->Gpio.DebounceTimeout = (UINT16) InitializerOp->Asl.Value.Integer; RsCreateWordField (InitializerOp, ACPI_RESTAG_DEBOUNCETIME, @@ -611,7 +611,7 @@ RsDoGpioIoDescriptor ( RsSetFlagBits16 (&Descriptor->Gpio.Flags, InitializerOp, 0, 1); break; - case 8: /* ResourceTag (Descriptor Name) */ + case 8: /* Resource Tag (Descriptor Name) */ UtAttachNamepathToOwner (Op, InitializerOp); break; @@ -762,14 +762,14 @@ RsDoI2cSerialBusDescriptor ( CurrentByteOffset + ASL_RESDESC_OFFSET (I2cSerialBus.Flags), 0); break; - case 2: /* ConnectionSpeed [DWORD] (_SPE) */ + case 2: /* Connection Speed [DWORD] (_SPE) */ Descriptor->I2cSerialBus.ConnectionSpeed = (UINT32) InitializerOp->Asl.Value.Integer; RsCreateDwordField (InitializerOp, ACPI_RESTAG_SPEED, CurrentByteOffset + ASL_RESDESC_OFFSET (I2cSerialBus.ConnectionSpeed)); break; - case 3: /* Addresssing Mode [Flag] (_MOD) */ + case 3: /* Addressing Mode [Flag] (_MOD) */ RsSetFlagBits16 (&Descriptor->I2cSerialBus.TypeSpecificFlags, InitializerOp, 0, 0); RsCreateBitField (InitializerOp, ACPI_RESTAG_MODE, @@ -800,7 +800,7 @@ RsDoI2cSerialBusDescriptor ( RsSetFlagBits (&Descriptor->I2cSerialBus.Flags, InitializerOp, 1, 1); break; - case 7: /* ResourceTag (Descriptor Name) */ + case 7: /* Resource Tag (Descriptor Name) */ UtAttachNamepathToOwner (Op, InitializerOp); break; @@ -929,7 +929,7 @@ RsDoSpiSerialBusDescriptor ( CurrentByteOffset + ASL_RESDESC_OFFSET (SpiSerialBus.Flags), 0); break; - case 5: /* ConnectionSpeed [DWORD] (_SPE) */ + case 5: /* Connection Speed [DWORD] (_SPE) */ Descriptor->SpiSerialBus.ConnectionSpeed = (UINT32) InitializerOp->Asl.Value.Integer; RsCreateDwordField (InitializerOp, ACPI_RESTAG_SPEED, @@ -974,7 +974,7 @@ RsDoSpiSerialBusDescriptor ( RsSetFlagBits (&Descriptor->SpiSerialBus.Flags, InitializerOp, 1, 1); break; - case 11: /* ResourceTag (Descriptor Name) */ + case 11: /* Resource Tag (Descriptor Name) */ UtAttachNamepathToOwner (Op, InitializerOp); break; @@ -1068,7 +1068,7 @@ RsDoUartSerialBusDescriptor ( { switch (i) { - case 0: /* ConnectionSpeed (Baud Rate) [DWORD] (_SPE) */ + case 0: /* Connection Speed (Baud Rate) [DWORD] (_SPE) */ Descriptor->UartSerialBus.DefaultBaudRate = (UINT32) InitializerOp->Asl.Value.Integer; RsCreateDwordField (InitializerOp, ACPI_RESTAG_SPEED, @@ -1165,7 +1165,7 @@ RsDoUartSerialBusDescriptor ( CurrentByteOffset + ASL_RESDESC_OFFSET (UartSerialBus.Flags), 0); break; - case 12: /* ResourceTag (Descriptor Name) */ + case 12: /* Resource Tag (Descriptor Name) */ UtAttachNamepathToOwner (Op, InitializerOp); break; diff --git a/sys/contrib/dev/acpica/compiler/aslstubs.c b/sys/contrib/dev/acpica/compiler/aslstubs.c index 5a83a0bf8fc0..f953b301e3d9 100644 --- a/sys/contrib/dev/acpica/compiler/aslstubs.c +++ b/sys/contrib/dev/acpica/compiler/aslstubs.c @@ -127,13 +127,6 @@ AcpiDsStoreObjectToLocal ( return (AE_OK); } -ACPI_STATUS -AcpiEvDeleteGpeBlock ( - ACPI_GPE_BLOCK_INFO *GpeBlock) -{ - return (AE_OK); -} - ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, @@ -149,6 +142,14 @@ AcpiEvIsNotifyObject ( return (FALSE); } +#if (!ACPI_REDUCED_HARDWARE) +ACPI_STATUS +AcpiEvDeleteGpeBlock ( + ACPI_GPE_BLOCK_INFO *GpeBlock) +{ + return (AE_OK); +} + ACPI_STATUS AcpiEvAcquireGlobalLock ( UINT16 Timeout) @@ -162,6 +163,7 @@ AcpiEvReleaseGlobalLock ( { return (AE_OK); } +#endif /* !ACPI_REDUCED_HARDWARE */ ACPI_STATUS AcpiEvInitializeRegion ( diff --git a/sys/contrib/dev/acpica/debugger/dbcmds.c b/sys/contrib/dev/acpica/components/debugger/dbcmds.c similarity index 98% rename from sys/contrib/dev/acpica/debugger/dbcmds.c rename to sys/contrib/dev/acpica/components/debugger/dbcmds.c index 13bc3b806c0d..7b995718e935 100644 --- a/sys/contrib/dev/acpica/debugger/dbcmds.c +++ b/sys/contrib/dev/acpica/components/debugger/dbcmds.c @@ -161,28 +161,49 @@ AcpiDbSleep ( UINT8 SleepState; + ACPI_FUNCTION_TRACE (AcpiDbSleep); + + SleepState = (UINT8) ACPI_STRTOUL (ObjectArg, NULL, 0); AcpiOsPrintf ("**** Prepare to sleep ****\n"); Status = AcpiEnterSleepStatePrep (SleepState); if (ACPI_FAILURE (Status)) { - return (Status); + goto ErrorExit; } AcpiOsPrintf ("**** Going to sleep ****\n"); Status = AcpiEnterSleepState (SleepState); if (ACPI_FAILURE (Status)) { - return (Status); + goto ErrorExit; } - AcpiOsPrintf ("**** returning from sleep ****\n"); + AcpiOsPrintf ("**** Prepare to return from sleep ****\n"); + Status = AcpiLeaveSleepStatePrep (SleepState); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + AcpiOsPrintf ("**** Returning from sleep ****\n"); Status = AcpiLeaveSleepState (SleepState); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } return (Status); + + +ErrorExit: + + ACPI_EXCEPTION ((AE_INFO, Status, "During sleep test")); + return (Status); } + /******************************************************************************* * * FUNCTION: AcpiDbDisplayLocks @@ -1019,6 +1040,7 @@ AcpiDbDisplayResources ( } +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: AcpiDbGenerateGpe @@ -1057,5 +1079,6 @@ AcpiDbGenerateGpe ( (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber); } +#endif /* !ACPI_REDUCED_HARDWARE */ #endif /* ACPI_DEBUGGER */ diff --git a/sys/contrib/dev/acpica/debugger/dbdisply.c b/sys/contrib/dev/acpica/components/debugger/dbdisply.c similarity index 99% rename from sys/contrib/dev/acpica/debugger/dbdisply.c rename to sys/contrib/dev/acpica/components/debugger/dbdisply.c index 5b17da530f78..dcedc30cd229 100644 --- a/sys/contrib/dev/acpica/debugger/dbdisply.c +++ b/sys/contrib/dev/acpica/components/debugger/dbdisply.c @@ -770,6 +770,7 @@ AcpiDbDisplayArgumentObject ( } +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: AcpiDbDisplayGpes @@ -932,6 +933,7 @@ AcpiDbDisplayGpes ( GpeXruptInfo = GpeXruptInfo->Next; } } +#endif /* !ACPI_REDUCED_HARDWARE */ /******************************************************************************* @@ -1011,6 +1013,8 @@ AcpiDbDisplayHandlers ( } } +#if (!ACPI_REDUCED_HARDWARE) + /* Fixed event handlers */ AcpiOsPrintf ("\nFixed Event Handlers:\n"); @@ -1029,6 +1033,8 @@ AcpiDbDisplayHandlers ( } } +#endif /* !ACPI_REDUCED_HARDWARE */ + /* Miscellaneous global handlers */ AcpiOsPrintf ("\nMiscellaneous Global Handlers:\n"); diff --git a/sys/contrib/dev/acpica/debugger/dbexec.c b/sys/contrib/dev/acpica/components/debugger/dbexec.c similarity index 100% rename from sys/contrib/dev/acpica/debugger/dbexec.c rename to sys/contrib/dev/acpica/components/debugger/dbexec.c diff --git a/sys/contrib/dev/acpica/debugger/dbfileio.c b/sys/contrib/dev/acpica/components/debugger/dbfileio.c similarity index 100% rename from sys/contrib/dev/acpica/debugger/dbfileio.c rename to sys/contrib/dev/acpica/components/debugger/dbfileio.c diff --git a/sys/contrib/dev/acpica/debugger/dbhistry.c b/sys/contrib/dev/acpica/components/debugger/dbhistry.c similarity index 100% rename from sys/contrib/dev/acpica/debugger/dbhistry.c rename to sys/contrib/dev/acpica/components/debugger/dbhistry.c diff --git a/sys/contrib/dev/acpica/debugger/dbinput.c b/sys/contrib/dev/acpica/components/debugger/dbinput.c similarity index 99% rename from sys/contrib/dev/acpica/debugger/dbinput.c rename to sys/contrib/dev/acpica/components/debugger/dbinput.c index 5f60997fb6a9..e56fad980cee 100644 --- a/sys/contrib/dev/acpica/debugger/dbinput.c +++ b/sys/contrib/dev/acpica/components/debugger/dbinput.c @@ -662,12 +662,15 @@ AcpiDbCommandDispatch ( break; case CMD_ENABLEACPI: +#if (!ACPI_REDUCED_HARDWARE) + Status = AcpiEnable(); if (ACPI_FAILURE(Status)) { AcpiOsPrintf("AcpiEnable failed (Status=%X)\n", Status); return (Status); } +#endif /* !ACPI_REDUCED_HARDWARE */ break; case CMD_EVENT: diff --git a/sys/contrib/dev/acpica/debugger/dbmethod.c b/sys/contrib/dev/acpica/components/debugger/dbmethod.c similarity index 100% rename from sys/contrib/dev/acpica/debugger/dbmethod.c rename to sys/contrib/dev/acpica/components/debugger/dbmethod.c diff --git a/sys/contrib/dev/acpica/debugger/dbnames.c b/sys/contrib/dev/acpica/components/debugger/dbnames.c similarity index 100% rename from sys/contrib/dev/acpica/debugger/dbnames.c rename to sys/contrib/dev/acpica/components/debugger/dbnames.c diff --git a/sys/contrib/dev/acpica/debugger/dbstats.c b/sys/contrib/dev/acpica/components/debugger/dbstats.c similarity index 100% rename from sys/contrib/dev/acpica/debugger/dbstats.c rename to sys/contrib/dev/acpica/components/debugger/dbstats.c diff --git a/sys/contrib/dev/acpica/debugger/dbutils.c b/sys/contrib/dev/acpica/components/debugger/dbutils.c similarity index 100% rename from sys/contrib/dev/acpica/debugger/dbutils.c rename to sys/contrib/dev/acpica/components/debugger/dbutils.c diff --git a/sys/contrib/dev/acpica/debugger/dbxface.c b/sys/contrib/dev/acpica/components/debugger/dbxface.c similarity index 100% rename from sys/contrib/dev/acpica/debugger/dbxface.c rename to sys/contrib/dev/acpica/components/debugger/dbxface.c diff --git a/sys/contrib/dev/acpica/disassembler/dmbuffer.c b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmbuffer.c rename to sys/contrib/dev/acpica/components/disassembler/dmbuffer.c diff --git a/sys/contrib/dev/acpica/disassembler/dmnames.c b/sys/contrib/dev/acpica/components/disassembler/dmnames.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmnames.c rename to sys/contrib/dev/acpica/components/disassembler/dmnames.c diff --git a/sys/contrib/dev/acpica/disassembler/dmobject.c b/sys/contrib/dev/acpica/components/disassembler/dmobject.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmobject.c rename to sys/contrib/dev/acpica/components/disassembler/dmobject.c diff --git a/sys/contrib/dev/acpica/disassembler/dmopcode.c b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmopcode.c rename to sys/contrib/dev/acpica/components/disassembler/dmopcode.c diff --git a/sys/contrib/dev/acpica/disassembler/dmresrc.c b/sys/contrib/dev/acpica/components/disassembler/dmresrc.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmresrc.c rename to sys/contrib/dev/acpica/components/disassembler/dmresrc.c diff --git a/sys/contrib/dev/acpica/disassembler/dmresrcl.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmresrcl.c rename to sys/contrib/dev/acpica/components/disassembler/dmresrcl.c diff --git a/sys/contrib/dev/acpica/disassembler/dmresrcl2.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c similarity index 98% rename from sys/contrib/dev/acpica/disassembler/dmresrcl2.c rename to sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c index 9cd9f27771c9..fbc80a1962de 100644 --- a/sys/contrib/dev/acpica/disassembler/dmresrcl2.c +++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c @@ -503,7 +503,7 @@ AcpiDmI2cSerialBusDescriptor ( AcpiOsPrintf ("0x%2.2X, ", Resource->I2cSerialBus.ResSourceIndex); AcpiOsPrintf ("%s, ", - AcpiGbl_ConsumeDecode [(Resource->I2cSerialBus.Flags & 1)]); + AcpiGbl_ConsumeDecode [(Resource->I2cSerialBus.Flags >> 1) & 1]); /* Insert a descriptor name */ @@ -578,7 +578,7 @@ AcpiDmSpiSerialBusDescriptor ( AcpiOsPrintf ("0x%2.2X, ", Resource->SpiSerialBus.ResSourceIndex); AcpiOsPrintf ("%s, ", - AcpiGbl_ConsumeDecode [(Resource->SpiSerialBus.Flags & 1)]); + AcpiGbl_ConsumeDecode [(Resource->SpiSerialBus.Flags >> 1) & 1]); /* Insert a descriptor name */ @@ -656,7 +656,7 @@ AcpiDmUartSerialBusDescriptor ( AcpiOsPrintf ("0x%2.2X, ", Resource->UartSerialBus.ResSourceIndex); AcpiOsPrintf ("%s, ", - AcpiGbl_ConsumeDecode [(Resource->UartSerialBus.Flags & 1)]); + AcpiGbl_ConsumeDecode [(Resource->UartSerialBus.Flags >> 1) & 1]); /* Insert a descriptor name */ diff --git a/sys/contrib/dev/acpica/disassembler/dmresrcs.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmresrcs.c rename to sys/contrib/dev/acpica/components/disassembler/dmresrcs.c diff --git a/sys/contrib/dev/acpica/disassembler/dmutils.c b/sys/contrib/dev/acpica/components/disassembler/dmutils.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmutils.c rename to sys/contrib/dev/acpica/components/disassembler/dmutils.c diff --git a/sys/contrib/dev/acpica/disassembler/dmwalk.c b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c similarity index 100% rename from sys/contrib/dev/acpica/disassembler/dmwalk.c rename to sys/contrib/dev/acpica/components/disassembler/dmwalk.c diff --git a/sys/contrib/dev/acpica/dispatcher/dsargs.c b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dsargs.c rename to sys/contrib/dev/acpica/components/dispatcher/dsargs.c diff --git a/sys/contrib/dev/acpica/dispatcher/dscontrol.c b/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dscontrol.c rename to sys/contrib/dev/acpica/components/dispatcher/dscontrol.c diff --git a/sys/contrib/dev/acpica/dispatcher/dsfield.c b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dsfield.c rename to sys/contrib/dev/acpica/components/dispatcher/dsfield.c diff --git a/sys/contrib/dev/acpica/dispatcher/dsinit.c b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dsinit.c rename to sys/contrib/dev/acpica/components/dispatcher/dsinit.c diff --git a/sys/contrib/dev/acpica/dispatcher/dsmethod.c b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dsmethod.c rename to sys/contrib/dev/acpica/components/dispatcher/dsmethod.c diff --git a/sys/contrib/dev/acpica/dispatcher/dsmthdat.c b/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dsmthdat.c rename to sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c diff --git a/sys/contrib/dev/acpica/dispatcher/dsobject.c b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dsobject.c rename to sys/contrib/dev/acpica/components/dispatcher/dsobject.c diff --git a/sys/contrib/dev/acpica/dispatcher/dsopcode.c b/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dsopcode.c rename to sys/contrib/dev/acpica/components/dispatcher/dsopcode.c diff --git a/sys/contrib/dev/acpica/dispatcher/dsutils.c b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dsutils.c rename to sys/contrib/dev/acpica/components/dispatcher/dsutils.c diff --git a/sys/contrib/dev/acpica/dispatcher/dswexec.c b/sys/contrib/dev/acpica/components/dispatcher/dswexec.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dswexec.c rename to sys/contrib/dev/acpica/components/dispatcher/dswexec.c diff --git a/sys/contrib/dev/acpica/dispatcher/dswload.c b/sys/contrib/dev/acpica/components/dispatcher/dswload.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dswload.c rename to sys/contrib/dev/acpica/components/dispatcher/dswload.c diff --git a/sys/contrib/dev/acpica/dispatcher/dswload2.c b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dswload2.c rename to sys/contrib/dev/acpica/components/dispatcher/dswload2.c diff --git a/sys/contrib/dev/acpica/dispatcher/dswscope.c b/sys/contrib/dev/acpica/components/dispatcher/dswscope.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dswscope.c rename to sys/contrib/dev/acpica/components/dispatcher/dswscope.c diff --git a/sys/contrib/dev/acpica/dispatcher/dswstate.c b/sys/contrib/dev/acpica/components/dispatcher/dswstate.c similarity index 100% rename from sys/contrib/dev/acpica/dispatcher/dswstate.c rename to sys/contrib/dev/acpica/components/dispatcher/dswstate.c diff --git a/sys/contrib/dev/acpica/events/evevent.c b/sys/contrib/dev/acpica/components/events/evevent.c similarity index 99% rename from sys/contrib/dev/acpica/events/evevent.c rename to sys/contrib/dev/acpica/components/events/evevent.c index ad8f33404210..18eef050c898 100644 --- a/sys/contrib/dev/acpica/events/evevent.c +++ b/sys/contrib/dev/acpica/components/events/evevent.c @@ -48,6 +48,8 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evevent") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + /* Local prototypes */ static ACPI_STATUS @@ -329,4 +331,6 @@ AcpiEvFixedEventDispatch ( AcpiGbl_FixedEventHandlers[Event].Context)); } +#endif /* !ACPI_REDUCED_HARDWARE */ + diff --git a/sys/contrib/dev/acpica/events/evglock.c b/sys/contrib/dev/acpica/components/events/evglock.c similarity index 99% rename from sys/contrib/dev/acpica/events/evglock.c rename to sys/contrib/dev/acpica/components/events/evglock.c index 092e6e83e169..894e132caeda 100644 --- a/sys/contrib/dev/acpica/events/evglock.c +++ b/sys/contrib/dev/acpica/components/events/evglock.c @@ -49,6 +49,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evglock") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* Local prototypes */ @@ -372,3 +373,5 @@ AcpiEvReleaseGlobalLock ( AcpiOsReleaseMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex); return_ACPI_STATUS (Status); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evgpe.c b/sys/contrib/dev/acpica/components/events/evgpe.c similarity index 99% rename from sys/contrib/dev/acpica/events/evgpe.c rename to sys/contrib/dev/acpica/components/events/evgpe.c index 076456a38afe..61b3e6cb05de 100644 --- a/sys/contrib/dev/acpica/events/evgpe.c +++ b/sys/contrib/dev/acpica/components/events/evgpe.c @@ -49,6 +49,8 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evgpe") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + /* Local prototypes */ static void ACPI_SYSTEM_XFACE @@ -826,3 +828,4 @@ AcpiEvGpeDispatch ( return_UINT32 (ACPI_INTERRUPT_HANDLED); } +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evgpeblk.c b/sys/contrib/dev/acpica/components/events/evgpeblk.c similarity index 99% rename from sys/contrib/dev/acpica/events/evgpeblk.c rename to sys/contrib/dev/acpica/components/events/evgpeblk.c index 074e449869fb..6a1c04abe579 100644 --- a/sys/contrib/dev/acpica/events/evgpeblk.c +++ b/sys/contrib/dev/acpica/components/events/evgpeblk.c @@ -49,6 +49,8 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evgpeblk") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + /* Local prototypes */ static ACPI_STATUS @@ -545,3 +547,4 @@ AcpiEvInitializeGpeBlock ( return_ACPI_STATUS (AE_OK); } +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evgpeinit.c b/sys/contrib/dev/acpica/components/events/evgpeinit.c similarity index 99% rename from sys/contrib/dev/acpica/events/evgpeinit.c rename to sys/contrib/dev/acpica/components/events/evgpeinit.c index b48cb795f708..9266d6067a81 100644 --- a/sys/contrib/dev/acpica/events/evgpeinit.c +++ b/sys/contrib/dev/acpica/components/events/evgpeinit.c @@ -50,6 +50,7 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evgpeinit") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /* * Note: History of _PRW support in ACPICA @@ -457,3 +458,5 @@ AcpiEvMatchGpeMethod ( Name, GpeNumber)); return_ACPI_STATUS (AE_OK); } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evgpeutil.c b/sys/contrib/dev/acpica/components/events/evgpeutil.c similarity index 99% rename from sys/contrib/dev/acpica/events/evgpeutil.c rename to sys/contrib/dev/acpica/components/events/evgpeutil.c index 276e25a6f2bf..7b27b414a0e0 100644 --- a/sys/contrib/dev/acpica/events/evgpeutil.c +++ b/sys/contrib/dev/acpica/components/events/evgpeutil.c @@ -41,7 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ - #include #include #include @@ -50,6 +49,7 @@ ACPI_MODULE_NAME ("evgpeutil") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /******************************************************************************* * * FUNCTION: AcpiEvWalkGpeList @@ -422,3 +422,4 @@ AcpiEvDeleteGpeHandlers ( return_ACPI_STATUS (AE_OK); } +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evmisc.c b/sys/contrib/dev/acpica/components/events/evmisc.c similarity index 93% rename from sys/contrib/dev/acpica/events/evmisc.c rename to sys/contrib/dev/acpica/components/events/evmisc.c index f059137cb1e4..52978bed3e14 100644 --- a/sys/contrib/dev/acpica/events/evmisc.c +++ b/sys/contrib/dev/acpica/components/events/evmisc.c @@ -120,27 +120,29 @@ AcpiEvQueueNotifyRequest ( /* - * For value 3 (Ejection Request), some device method may need to be run. - * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need - * to be run. + * For value 0x03 (Ejection Request), may need to run a device method. + * For value 0x02 (Device Wake), if _PRW exists, may need to run + * the _PS0 method. * For value 0x80 (Status Change) on the power button or sleep button, - * initiate soft-off or sleep operation? + * initiate soft-off or sleep operation. + * + * For all cases, simply dispatch the notify to the handler. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", - AcpiUtGetNodeName (Node), Node, NotifyValue, - AcpiUtGetNotifyName (NotifyValue))); + "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), + NotifyValue, AcpiUtGetNotifyName (NotifyValue), Node)); /* Get the notify object attached to the NS Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { - /* We have the notify object, Get the right handler */ + /* We have the notify object, Get the correct handler */ switch (Node->Type) { - /* Notify allowed only on these types */ + /* Notify is allowed only on these types */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: @@ -165,7 +167,7 @@ AcpiEvQueueNotifyRequest ( } /* - * If there is any handler to run, schedule the dispatcher. + * If there is a handler to run, schedule the dispatcher. * Check for: * 1) Global system notify handler * 2) Global device notify handler @@ -291,6 +293,7 @@ AcpiEvNotifyDispatch ( } +#if (!ACPI_REDUCED_HARDWARE) /****************************************************************************** * * FUNCTION: AcpiEvTerminate @@ -370,3 +373,5 @@ AcpiEvTerminate ( } return_VOID; } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evregion.c b/sys/contrib/dev/acpica/components/events/evregion.c similarity index 100% rename from sys/contrib/dev/acpica/events/evregion.c rename to sys/contrib/dev/acpica/components/events/evregion.c diff --git a/sys/contrib/dev/acpica/events/evrgnini.c b/sys/contrib/dev/acpica/components/events/evrgnini.c similarity index 100% rename from sys/contrib/dev/acpica/events/evrgnini.c rename to sys/contrib/dev/acpica/components/events/evrgnini.c diff --git a/sys/contrib/dev/acpica/events/evsci.c b/sys/contrib/dev/acpica/components/events/evsci.c similarity index 98% rename from sys/contrib/dev/acpica/events/evsci.c rename to sys/contrib/dev/acpica/components/events/evsci.c index 143524718455..0e7a65aab585 100644 --- a/sys/contrib/dev/acpica/events/evsci.c +++ b/sys/contrib/dev/acpica/components/events/evsci.c @@ -50,6 +50,8 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evsci") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + /* Local prototypes */ static UINT32 ACPI_SYSTEM_XFACE @@ -204,4 +206,4 @@ AcpiEvRemoveSciHandler ( return_ACPI_STATUS (Status); } - +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evxface.c b/sys/contrib/dev/acpica/components/events/evxface.c similarity index 99% rename from sys/contrib/dev/acpica/events/evxface.c rename to sys/contrib/dev/acpica/components/events/evxface.c index 6ea997c25924..8d50c900a018 100644 --- a/sys/contrib/dev/acpica/events/evxface.c +++ b/sys/contrib/dev/acpica/components/events/evxface.c @@ -54,257 +54,6 @@ ACPI_MODULE_NAME ("evxface") -/******************************************************************************* - * - * FUNCTION: AcpiInstallExceptionHandler - * - * PARAMETERS: Handler - Pointer to the handler function for the - * event - * - * RETURN: Status - * - * DESCRIPTION: Saves the pointer to the handler function - * - ******************************************************************************/ - -ACPI_STATUS -AcpiInstallExceptionHandler ( - ACPI_EXCEPTION_HANDLER Handler) -{ - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); - - - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Don't allow two handlers. */ - - if (AcpiGbl_ExceptionHandler) - { - Status = AE_ALREADY_EXISTS; - goto Cleanup; - } - - /* Install the handler */ - - AcpiGbl_ExceptionHandler = Handler; - -Cleanup: - (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); - return_ACPI_STATUS (Status); -} - -ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) - - -/******************************************************************************* - * - * FUNCTION: AcpiInstallGlobalEventHandler - * - * PARAMETERS: Handler - Pointer to the global event handler function - * Context - Value passed to the handler on each event - * - * RETURN: Status - * - * DESCRIPTION: Saves the pointer to the handler function. The global handler - * is invoked upon each incoming GPE and Fixed Event. It is - * invoked at interrupt level at the time of the event dispatch. - * Can be used to update event counters, etc. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiInstallGlobalEventHandler ( - ACPI_GBL_EVENT_HANDLER Handler, - void *Context) -{ - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler); - - - /* Parameter validation */ - - if (!Handler) - { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Don't allow two handlers. */ - - if (AcpiGbl_GlobalEventHandler) - { - Status = AE_ALREADY_EXISTS; - goto Cleanup; - } - - AcpiGbl_GlobalEventHandler = Handler; - AcpiGbl_GlobalEventHandlerContext = Context; - - -Cleanup: - (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); - return_ACPI_STATUS (Status); -} - -ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) - - -/******************************************************************************* - * - * FUNCTION: AcpiInstallFixedEventHandler - * - * PARAMETERS: Event - Event type to enable. - * Handler - Pointer to the handler function for the - * event - * Context - Value passed to the handler on each GPE - * - * RETURN: Status - * - * DESCRIPTION: Saves the pointer to the handler function and then enables the - * event. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiInstallFixedEventHandler ( - UINT32 Event, - ACPI_EVENT_HANDLER Handler, - void *Context) -{ - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); - - - /* Parameter validation */ - - if (Event > ACPI_EVENT_MAX) - { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Don't allow two handlers. */ - - if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler) - { - Status = AE_ALREADY_EXISTS; - goto Cleanup; - } - - /* Install the handler before enabling the event */ - - AcpiGbl_FixedEventHandlers[Event].Handler = Handler; - AcpiGbl_FixedEventHandlers[Event].Context = Context; - - Status = AcpiEnableEvent (Event, 0); - if (ACPI_FAILURE (Status)) - { - ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event)); - - /* Remove the handler */ - - AcpiGbl_FixedEventHandlers[Event].Handler = NULL; - AcpiGbl_FixedEventHandlers[Event].Context = NULL; - } - else - { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Enabled fixed event %X, Handler=%p\n", Event, Handler)); - } - - -Cleanup: - (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); - return_ACPI_STATUS (Status); -} - -ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) - - -/******************************************************************************* - * - * FUNCTION: AcpiRemoveFixedEventHandler - * - * PARAMETERS: Event - Event type to disable. - * Handler - Address of the handler - * - * RETURN: Status - * - * DESCRIPTION: Disables the event and unregisters the event handler. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiRemoveFixedEventHandler ( - UINT32 Event, - ACPI_EVENT_HANDLER Handler) -{ - ACPI_STATUS Status = AE_OK; - - - ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); - - - /* Parameter validation */ - - if (Event > ACPI_EVENT_MAX) - { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Disable the event before removing the handler */ - - Status = AcpiDisableEvent (Event, 0); - - /* Always Remove the handler */ - - AcpiGbl_FixedEventHandlers[Event].Handler = NULL; - AcpiGbl_FixedEventHandlers[Event].Context = NULL; - - if (ACPI_FAILURE (Status)) - { - ACPI_WARNING ((AE_INFO, - "Could not write to fixed event enable register 0x%X", Event)); - } - else - { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event)); - } - - (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); - return_ACPI_STATUS (Status); -} - -ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) - - /******************************************************************************* * * FUNCTION: AcpiInstallNotifyHandler @@ -656,6 +405,258 @@ AcpiRemoveNotifyHandler ( ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) +/******************************************************************************* + * + * FUNCTION: AcpiInstallExceptionHandler + * + * PARAMETERS: Handler - Pointer to the handler function for the + * event + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallExceptionHandler ( + ACPI_EXCEPTION_HANDLER Handler) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Don't allow two handlers. */ + + if (AcpiGbl_ExceptionHandler) + { + Status = AE_ALREADY_EXISTS; + goto Cleanup; + } + + /* Install the handler */ + + AcpiGbl_ExceptionHandler = Handler; + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) + + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiInstallGlobalEventHandler + * + * PARAMETERS: Handler - Pointer to the global event handler function + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function. The global handler + * is invoked upon each incoming GPE and Fixed Event. It is + * invoked at interrupt level at the time of the event dispatch. + * Can be used to update event counters, etc. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallGlobalEventHandler ( + ACPI_GBL_EVENT_HANDLER Handler, + void *Context) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler); + + + /* Parameter validation */ + + if (!Handler) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Don't allow two handlers. */ + + if (AcpiGbl_GlobalEventHandler) + { + Status = AE_ALREADY_EXISTS; + goto Cleanup; + } + + AcpiGbl_GlobalEventHandler = Handler; + AcpiGbl_GlobalEventHandlerContext = Context; + + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallFixedEventHandler + * + * PARAMETERS: Event - Event type to enable. + * Handler - Pointer to the handler function for the + * event + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function and then enables the + * event. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallFixedEventHandler ( + UINT32 Event, + ACPI_EVENT_HANDLER Handler, + void *Context) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); + + + /* Parameter validation */ + + if (Event > ACPI_EVENT_MAX) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Don't allow two handlers. */ + + if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler) + { + Status = AE_ALREADY_EXISTS; + goto Cleanup; + } + + /* Install the handler before enabling the event */ + + AcpiGbl_FixedEventHandlers[Event].Handler = Handler; + AcpiGbl_FixedEventHandlers[Event].Context = Context; + + Status = AcpiEnableEvent (Event, 0); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event)); + + /* Remove the handler */ + + AcpiGbl_FixedEventHandlers[Event].Handler = NULL; + AcpiGbl_FixedEventHandlers[Event].Context = NULL; + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Enabled fixed event %X, Handler=%p\n", Event, Handler)); + } + + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveFixedEventHandler + * + * PARAMETERS: Event - Event type to disable. + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Disables the event and unregisters the event handler. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRemoveFixedEventHandler ( + UINT32 Event, + ACPI_EVENT_HANDLER Handler) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); + + + /* Parameter validation */ + + if (Event > ACPI_EVENT_MAX) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Disable the event before removing the handler */ + + Status = AcpiDisableEvent (Event, 0); + + /* Always Remove the handler */ + + AcpiGbl_FixedEventHandlers[Event].Handler = NULL; + AcpiGbl_FixedEventHandlers[Event].Context = NULL; + + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, + "Could not write to fixed event enable register 0x%X", Event)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) + + /******************************************************************************* * * FUNCTION: AcpiInstallGpeHandler @@ -975,3 +976,4 @@ AcpiReleaseGlobalLock ( ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock) +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evxfevnt.c b/sys/contrib/dev/acpica/components/events/evxfevnt.c similarity index 99% rename from sys/contrib/dev/acpica/events/evxfevnt.c rename to sys/contrib/dev/acpica/components/events/evxfevnt.c index 38b6d2bb4716..4e87cdee20fd 100644 --- a/sys/contrib/dev/acpica/events/evxfevnt.c +++ b/sys/contrib/dev/acpica/components/events/evxfevnt.c @@ -52,6 +52,7 @@ ACPI_MODULE_NAME ("evxfevnt") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /******************************************************************************* * * FUNCTION: AcpiEnable @@ -377,4 +378,4 @@ AcpiGetEventStatus ( ACPI_EXPORT_SYMBOL (AcpiGetEventStatus) - +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evxfgpe.c b/sys/contrib/dev/acpica/components/events/evxfgpe.c similarity index 99% rename from sys/contrib/dev/acpica/events/evxfgpe.c rename to sys/contrib/dev/acpica/components/events/evxfgpe.c index c0ea07f7c7db..c75b4c59cc8f 100644 --- a/sys/contrib/dev/acpica/events/evxfgpe.c +++ b/sys/contrib/dev/acpica/components/events/evxfgpe.c @@ -53,6 +53,7 @@ ACPI_MODULE_NAME ("evxfgpe") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /******************************************************************************* * * FUNCTION: AcpiUpdateAllGpes @@ -898,3 +899,5 @@ AcpiGetGpeDevice ( } ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/events/evxfregn.c b/sys/contrib/dev/acpica/components/events/evxfregn.c similarity index 100% rename from sys/contrib/dev/acpica/events/evxfregn.c rename to sys/contrib/dev/acpica/components/events/evxfregn.c diff --git a/sys/contrib/dev/acpica/executer/exconfig.c b/sys/contrib/dev/acpica/components/executer/exconfig.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exconfig.c rename to sys/contrib/dev/acpica/components/executer/exconfig.c diff --git a/sys/contrib/dev/acpica/executer/exconvrt.c b/sys/contrib/dev/acpica/components/executer/exconvrt.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exconvrt.c rename to sys/contrib/dev/acpica/components/executer/exconvrt.c diff --git a/sys/contrib/dev/acpica/executer/excreate.c b/sys/contrib/dev/acpica/components/executer/excreate.c similarity index 100% rename from sys/contrib/dev/acpica/executer/excreate.c rename to sys/contrib/dev/acpica/components/executer/excreate.c diff --git a/sys/contrib/dev/acpica/executer/exdebug.c b/sys/contrib/dev/acpica/components/executer/exdebug.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exdebug.c rename to sys/contrib/dev/acpica/components/executer/exdebug.c diff --git a/sys/contrib/dev/acpica/executer/exdump.c b/sys/contrib/dev/acpica/components/executer/exdump.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exdump.c rename to sys/contrib/dev/acpica/components/executer/exdump.c diff --git a/sys/contrib/dev/acpica/executer/exfield.c b/sys/contrib/dev/acpica/components/executer/exfield.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exfield.c rename to sys/contrib/dev/acpica/components/executer/exfield.c diff --git a/sys/contrib/dev/acpica/executer/exfldio.c b/sys/contrib/dev/acpica/components/executer/exfldio.c similarity index 99% rename from sys/contrib/dev/acpica/executer/exfldio.c rename to sys/contrib/dev/acpica/components/executer/exfldio.c index 7a7cf2007307..539ea9738770 100644 --- a/sys/contrib/dev/acpica/executer/exfldio.c +++ b/sys/contrib/dev/acpica/components/executer/exfldio.c @@ -350,8 +350,6 @@ AcpiExRegisterOverflow ( ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Value) { - ACPI_FUNCTION_NAME (ExRegisterOverflow); - if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE) { diff --git a/sys/contrib/dev/acpica/executer/exmisc.c b/sys/contrib/dev/acpica/components/executer/exmisc.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exmisc.c rename to sys/contrib/dev/acpica/components/executer/exmisc.c diff --git a/sys/contrib/dev/acpica/executer/exmutex.c b/sys/contrib/dev/acpica/components/executer/exmutex.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exmutex.c rename to sys/contrib/dev/acpica/components/executer/exmutex.c diff --git a/sys/contrib/dev/acpica/executer/exnames.c b/sys/contrib/dev/acpica/components/executer/exnames.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exnames.c rename to sys/contrib/dev/acpica/components/executer/exnames.c diff --git a/sys/contrib/dev/acpica/executer/exoparg1.c b/sys/contrib/dev/acpica/components/executer/exoparg1.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exoparg1.c rename to sys/contrib/dev/acpica/components/executer/exoparg1.c diff --git a/sys/contrib/dev/acpica/executer/exoparg2.c b/sys/contrib/dev/acpica/components/executer/exoparg2.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exoparg2.c rename to sys/contrib/dev/acpica/components/executer/exoparg2.c diff --git a/sys/contrib/dev/acpica/executer/exoparg3.c b/sys/contrib/dev/acpica/components/executer/exoparg3.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exoparg3.c rename to sys/contrib/dev/acpica/components/executer/exoparg3.c diff --git a/sys/contrib/dev/acpica/executer/exoparg6.c b/sys/contrib/dev/acpica/components/executer/exoparg6.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exoparg6.c rename to sys/contrib/dev/acpica/components/executer/exoparg6.c diff --git a/sys/contrib/dev/acpica/executer/exprep.c b/sys/contrib/dev/acpica/components/executer/exprep.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exprep.c rename to sys/contrib/dev/acpica/components/executer/exprep.c diff --git a/sys/contrib/dev/acpica/executer/exregion.c b/sys/contrib/dev/acpica/components/executer/exregion.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exregion.c rename to sys/contrib/dev/acpica/components/executer/exregion.c diff --git a/sys/contrib/dev/acpica/executer/exresnte.c b/sys/contrib/dev/acpica/components/executer/exresnte.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exresnte.c rename to sys/contrib/dev/acpica/components/executer/exresnte.c diff --git a/sys/contrib/dev/acpica/executer/exresolv.c b/sys/contrib/dev/acpica/components/executer/exresolv.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exresolv.c rename to sys/contrib/dev/acpica/components/executer/exresolv.c diff --git a/sys/contrib/dev/acpica/executer/exresop.c b/sys/contrib/dev/acpica/components/executer/exresop.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exresop.c rename to sys/contrib/dev/acpica/components/executer/exresop.c diff --git a/sys/contrib/dev/acpica/executer/exstore.c b/sys/contrib/dev/acpica/components/executer/exstore.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exstore.c rename to sys/contrib/dev/acpica/components/executer/exstore.c diff --git a/sys/contrib/dev/acpica/executer/exstoren.c b/sys/contrib/dev/acpica/components/executer/exstoren.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exstoren.c rename to sys/contrib/dev/acpica/components/executer/exstoren.c diff --git a/sys/contrib/dev/acpica/executer/exstorob.c b/sys/contrib/dev/acpica/components/executer/exstorob.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exstorob.c rename to sys/contrib/dev/acpica/components/executer/exstorob.c diff --git a/sys/contrib/dev/acpica/executer/exsystem.c b/sys/contrib/dev/acpica/components/executer/exsystem.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exsystem.c rename to sys/contrib/dev/acpica/components/executer/exsystem.c diff --git a/sys/contrib/dev/acpica/executer/exutils.c b/sys/contrib/dev/acpica/components/executer/exutils.c similarity index 100% rename from sys/contrib/dev/acpica/executer/exutils.c rename to sys/contrib/dev/acpica/components/executer/exutils.c diff --git a/sys/contrib/dev/acpica/hardware/hwacpi.c b/sys/contrib/dev/acpica/components/hardware/hwacpi.c similarity index 98% rename from sys/contrib/dev/acpica/hardware/hwacpi.c rename to sys/contrib/dev/acpica/components/hardware/hwacpi.c index 23fc4bfb7e77..a7bc6b826b91 100644 --- a/sys/contrib/dev/acpica/hardware/hwacpi.c +++ b/sys/contrib/dev/acpica/components/hardware/hwacpi.c @@ -52,6 +52,7 @@ ACPI_MODULE_NAME ("hwacpi") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /****************************************************************************** * * FUNCTION: AcpiHwSetMode @@ -204,3 +205,5 @@ AcpiHwGetMode ( return_UINT32 (ACPI_SYS_MODE_LEGACY); } } + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/components/hardware/hwesleep.c b/sys/contrib/dev/acpica/components/hardware/hwesleep.c new file mode 100644 index 000000000000..8133e85854c9 --- /dev/null +++ b/sys/contrib/dev/acpica/components/hardware/hwesleep.c @@ -0,0 +1,263 @@ +/****************************************************************************** + * + * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the + * extended FADT-V5 sleep registers. + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwesleep") + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExecuteSleepMethod + * + * PARAMETERS: MethodName - Pathname of method to execute + * IntegerArgument - Argument to pass to the method + * + * RETURN: None + * + * DESCRIPTION: Execute a sleep/wake related method with one integer argument + * and no return value. + * + ******************************************************************************/ + +void +AcpiHwExecuteSleepMethod ( + char *MethodName, + UINT32 IntegerArgument) +{ + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwExecuteSleepMethod); + + + /* One argument, IntegerArgument; No return value expected */ + + ArgList.Count = 1; + ArgList.Pointer = &Arg; + Arg.Type = ACPI_TYPE_INTEGER; + Arg.Integer.Value = (UINT64) IntegerArgument; + + Status = AcpiEvaluateObject (NULL, MethodName, &ArgList, NULL); + if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While executing method %s", + MethodName)); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExtendedSleep + * + * PARAMETERS: SleepState - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state via the extended FADT sleep + * registers (V5 FADT). + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwExtendedSleep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + UINT8 SleepTypeValue; + UINT64 SleepStatus; + + + ACPI_FUNCTION_TRACE (HwExtendedSleep); + + + /* Extended sleep registers must be valid */ + + if (!AcpiGbl_FADT.SleepControl.Address || + !AcpiGbl_FADT.SleepStatus.Address) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Clear wake status (WAK_STS) */ + + Status = AcpiWrite (ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiGbl_SystemAwakeAndRunning = FALSE; + + /* Execute the _GTS method (Going To Sleep) */ + + AcpiHwExecuteSleepMethod (METHOD_NAME__GTS, SleepState); + + /* Flush caches, as per ACPI specification */ + + ACPI_FLUSH_CPU_CACHE (); + + /* + * Set the SLP_TYP and SLP_EN bits. + * + * Note: We only use the first value returned by the \_Sx method + * (AcpiGbl_SleepTypeA) - As per ACPI specification. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "Entering sleep state [S%u]\n", SleepState)); + + SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK); + + Status = AcpiWrite ((SleepTypeValue | ACPI_X_SLEEP_ENABLE), + &AcpiGbl_FADT.SleepControl); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Wait for transition back to Working State */ + + do + { + Status = AcpiRead (&SleepStatus, &AcpiGbl_FADT.SleepStatus); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + } while (!(((UINT8) SleepStatus) & ACPI_X_WAKE_STATUS)); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExtendedWakePrep + * + * PARAMETERS: SleepState - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after + * a sleep. Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwExtendedWakePrep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + UINT8 SleepTypeValue; + + + ACPI_FUNCTION_TRACE (HwExtendedWakePrep); + + + Status = AcpiGetSleepTypeData (ACPI_STATE_S0, + &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); + if (ACPI_SUCCESS (Status)) + { + SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK); + + (void) AcpiWrite ((SleepTypeValue | ACPI_X_SLEEP_ENABLE), + &AcpiGbl_FADT.SleepControl); + } + + AcpiHwExecuteSleepMethod (METHOD_NAME__BFS, SleepState); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExtendedWake + * + * PARAMETERS: SleepState - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwExtendedWake ( + UINT8 SleepState) +{ + ACPI_FUNCTION_TRACE (HwExtendedWake); + + + /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */ + + AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID; + + /* Execute the wake methods */ + + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WAKING); + AcpiHwExecuteSleepMethod (METHOD_NAME__WAK, SleepState); + + /* + * Some BIOS code assumes that WAK_STS will be cleared on resume + * and use it to determine whether the system is rebooting or + * resuming. Clear WAK_STS for compatibility. + */ + (void) AcpiWrite (ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus); + AcpiGbl_SystemAwakeAndRunning = TRUE; + + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WORKING); + return_ACPI_STATUS (AE_OK); +} diff --git a/sys/contrib/dev/acpica/hardware/hwgpe.c b/sys/contrib/dev/acpica/components/hardware/hwgpe.c similarity index 99% rename from sys/contrib/dev/acpica/hardware/hwgpe.c rename to sys/contrib/dev/acpica/components/hardware/hwgpe.c index 7a94acbcbca3..a4aa86418980 100644 --- a/sys/contrib/dev/acpica/hardware/hwgpe.c +++ b/sys/contrib/dev/acpica/components/hardware/hwgpe.c @@ -49,6 +49,8 @@ #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME ("hwgpe") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ + /* Local prototypes */ static ACPI_STATUS @@ -538,3 +540,4 @@ AcpiHwEnableAllWakeupGpes ( return_ACPI_STATUS (Status); } +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/hardware/hwpci.c b/sys/contrib/dev/acpica/components/hardware/hwpci.c similarity index 100% rename from sys/contrib/dev/acpica/hardware/hwpci.c rename to sys/contrib/dev/acpica/components/hardware/hwpci.c diff --git a/sys/contrib/dev/acpica/hardware/hwregs.c b/sys/contrib/dev/acpica/components/hardware/hwregs.c similarity index 98% rename from sys/contrib/dev/acpica/hardware/hwregs.c rename to sys/contrib/dev/acpica/components/hardware/hwregs.c index 14de562d5c37..a43539f027d0 100644 --- a/sys/contrib/dev/acpica/hardware/hwregs.c +++ b/sys/contrib/dev/acpica/components/hardware/hwregs.c @@ -53,6 +53,8 @@ ACPI_MODULE_NAME ("hwregs") +#if (!ACPI_REDUCED_HARDWARE) + /* Local Prototypes */ static ACPI_STATUS @@ -67,6 +69,7 @@ AcpiHwWriteMultiple ( ACPI_GENERIC_ADDRESS *RegisterA, ACPI_GENERIC_ADDRESS *RegisterB); +#endif /* !ACPI_REDUCED_HARDWARE */ /****************************************************************************** * @@ -170,6 +173,7 @@ AcpiHwRead ( ACPI_GENERIC_ADDRESS *Reg) { UINT64 Address; + UINT64 Value64; ACPI_STATUS Status; @@ -195,7 +199,9 @@ AcpiHwRead ( if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) { Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) - Address, Value, Reg->BitWidth); + Address, &Value64, Reg->BitWidth); + + *Value = (UINT32) Value64; } else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ { @@ -254,7 +260,7 @@ AcpiHwWrite ( if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) { Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) - Address, Value, Reg->BitWidth); + Address, (UINT64) Value, Reg->BitWidth); } else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ { @@ -271,6 +277,7 @@ AcpiHwWrite ( } +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: AcpiHwClearAcpiStatus @@ -321,7 +328,7 @@ AcpiHwClearAcpiStatus ( /******************************************************************************* * - * FUNCTION: AcpiHwGetRegisterBitMask + * FUNCTION: AcpiHwGetBitRegisterInfo * * PARAMETERS: RegisterId - Index of ACPI Register to access * @@ -731,3 +738,4 @@ AcpiHwWriteMultiple ( return (Status); } +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/hardware/hwsleep.c b/sys/contrib/dev/acpica/components/hardware/hwsleep.c similarity index 55% rename from sys/contrib/dev/acpica/hardware/hwsleep.c rename to sys/contrib/dev/acpica/components/hardware/hwsleep.c index 9cc824601a9a..cb8eb6629a7c 100644 --- a/sys/contrib/dev/acpica/hardware/hwsleep.c +++ b/sys/contrib/dev/acpica/components/hardware/hwsleep.c @@ -1,7 +1,7 @@ - /****************************************************************************** * - * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the + * original/legacy sleep/PM registers. * *****************************************************************************/ @@ -49,211 +49,37 @@ ACPI_MODULE_NAME ("hwsleep") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /******************************************************************************* * - * FUNCTION: AcpiSetFirmwareWakingVector - * - * PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode - * entry point. - * - * RETURN: Status - * - * DESCRIPTION: Sets the 32-bit FirmwareWakingVector field of the FACS - * - ******************************************************************************/ - -ACPI_STATUS -AcpiSetFirmwareWakingVector ( - UINT32 PhysicalAddress) -{ - ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector); - - - /* Set the 32-bit vector */ - - AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress; - - /* Clear the 64-bit vector if it exists */ - - if ((AcpiGbl_FACS->Length > 32) && (AcpiGbl_FACS->Version >= 1)) - { - AcpiGbl_FACS->XFirmwareWakingVector = 0; - } - - return_ACPI_STATUS (AE_OK); -} - -ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector) - - -#if ACPI_MACHINE_WIDTH == 64 -/******************************************************************************* - * - * FUNCTION: AcpiSetFirmwareWakingVector64 - * - * PARAMETERS: PhysicalAddress - 64-bit physical address of ACPI protected - * mode entry point. - * - * RETURN: Status - * - * DESCRIPTION: Sets the 64-bit X_FirmwareWakingVector field of the FACS, if - * it exists in the table. This function is intended for use with - * 64-bit host operating systems. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiSetFirmwareWakingVector64 ( - UINT64 PhysicalAddress) -{ - ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64); - - - /* Determine if the 64-bit vector actually exists */ - - if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1)) - { - return_ACPI_STATUS (AE_NOT_EXIST); - } - - /* Clear 32-bit vector, set the 64-bit X_ vector */ - - AcpiGbl_FACS->FirmwareWakingVector = 0; - AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress; - return_ACPI_STATUS (AE_OK); -} - -ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector64) -#endif - -/******************************************************************************* - * - * FUNCTION: AcpiEnterSleepStatePrep + * FUNCTION: AcpiHwLegacySleep * * PARAMETERS: SleepState - Which sleep state to enter * * RETURN: Status * - * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) - * This function must execute with interrupts enabled. - * We break sleeping into 2 stages so that OSPM can handle - * various OS-specific tasks between the two steps. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEnterSleepStatePrep ( - UINT8 SleepState) -{ - ACPI_STATUS Status; - ACPI_OBJECT_LIST ArgList; - ACPI_OBJECT Arg; - - - ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep); - - - /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ - - Status = AcpiGetSleepTypeData (SleepState, - &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Execute the _PTS method (Prepare To Sleep) */ - - ArgList.Count = 1; - ArgList.Pointer = &Arg; - Arg.Type = ACPI_TYPE_INTEGER; - Arg.Integer.Value = SleepState; - - Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL); - if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) - { - return_ACPI_STATUS (Status); - } - - /* Setup the argument to the _SST method (System STatus) */ - - switch (SleepState) - { - case ACPI_STATE_S0: - Arg.Integer.Value = ACPI_SST_WORKING; - break; - - case ACPI_STATE_S1: - case ACPI_STATE_S2: - case ACPI_STATE_S3: - Arg.Integer.Value = ACPI_SST_SLEEPING; - break; - - case ACPI_STATE_S4: - Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT; - break; - - default: - Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is off */ - break; - } - - /* - * Set the system indicators to show the desired sleep state. - * _SST is an optional method (return no error if not found) - */ - Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL); - if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) - { - ACPI_EXCEPTION ((AE_INFO, Status, "While executing method _SST")); - } - - return_ACPI_STATUS (AE_OK); -} - -ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep) - - -/******************************************************************************* - * - * FUNCTION: AcpiEnterSleepState - * - * PARAMETERS: SleepState - Which sleep state to enter - * - * RETURN: Status - * - * DESCRIPTION: Enter a system sleep state + * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ ACPI_STATUS -AcpiEnterSleepState ( +AcpiHwLegacySleep ( UINT8 SleepState) { - UINT32 Pm1aControl; - UINT32 Pm1bControl; ACPI_BIT_REGISTER_INFO *SleepTypeRegInfo; ACPI_BIT_REGISTER_INFO *SleepEnableRegInfo; + UINT32 Pm1aControl; + UINT32 Pm1bControl; UINT32 InValue; - ACPI_OBJECT_LIST ArgList; - ACPI_OBJECT Arg; UINT32 Retry; ACPI_STATUS Status; - ACPI_FUNCTION_TRACE (AcpiEnterSleepState); + ACPI_FUNCTION_TRACE (HwLegacySleep); - if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) || - (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX)) - { - ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", - AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB)); - return_ACPI_STATUS (AE_AML_OPERAND_VALUE); - } - - SleepTypeRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE); + SleepTypeRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE); SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE); /* Clear wake status */ @@ -305,16 +131,7 @@ AcpiEnterSleepState ( /* Execute the _GTS method (Going To Sleep) */ - ArgList.Count = 1; - ArgList.Pointer = &Arg; - Arg.Type = ACPI_TYPE_INTEGER; - Arg.Integer.Value = SleepState; - - Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL); - if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) - { - return_ACPI_STATUS (Status); - } + AcpiHwExecuteSleepMethod (METHOD_NAME__GTS, SleepState); /* Get current value of PM1A control */ @@ -391,7 +208,7 @@ AcpiEnterSleepState ( } } - /* Wait until we enter sleep state */ + /* Wait for transition back to Working State */ Retry = 1000; do @@ -414,110 +231,30 @@ AcpiEnterSleepState ( } } - /* Spin until we wake */ - } while (!InValue); return_ACPI_STATUS (AE_OK); } -ACPI_EXPORT_SYMBOL (AcpiEnterSleepState) - /******************************************************************************* * - * FUNCTION: AcpiEnterSleepStateS4bios - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Perform a S4 bios request. - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEnterSleepStateS4bios ( - void) -{ - UINT32 InValue; - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios); - - - /* Clear the wake status bit (PM1) */ - - Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - Status = AcpiHwClearAcpiStatus (); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* - * 1) Disable/Clear all GPEs - * 2) Enable all wakeup GPEs - */ - Status = AcpiHwDisableAllGpes (); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - AcpiGbl_SystemAwakeAndRunning = FALSE; - - Status = AcpiHwEnableAllWakeupGpes (); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - ACPI_FLUSH_CPU_CACHE (); - - Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, - (UINT32) AcpiGbl_FADT.S4BiosRequest, 8); - - do { - AcpiOsStall(1000); - Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - } while (!InValue); - - return_ACPI_STATUS (AE_OK); -} - -ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios) - - -/******************************************************************************* - * - * FUNCTION: AcpiLeaveSleepState + * FUNCTION: AcpiHwLegacyWakePrep * * PARAMETERS: SleepState - Which sleep state we just exited * * RETURN: Status * - * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a + * sleep. * Called with interrupts ENABLED. * ******************************************************************************/ ACPI_STATUS -AcpiLeaveSleepState ( +AcpiHwLegacyWakePrep ( UINT8 SleepState) { - ACPI_OBJECT_LIST ArgList; - ACPI_OBJECT Arg; ACPI_STATUS Status; ACPI_BIT_REGISTER_INFO *SleepTypeRegInfo; ACPI_BIT_REGISTER_INFO *SleepEnableRegInfo; @@ -525,8 +262,7 @@ AcpiLeaveSleepState ( UINT32 Pm1bControl; - ACPI_FUNCTION_TRACE (AcpiLeaveSleepState); - + ACPI_FUNCTION_TRACE (HwLegacyWakePrep); /* * Set SLP_TYPE and SLP_EN to state S0. @@ -567,40 +303,43 @@ AcpiLeaveSleepState ( } } + AcpiHwExecuteSleepMethod (METHOD_NAME__BFS, SleepState); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiHwLegacyWake + * + * PARAMETERS: SleepState - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwLegacyWake ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (HwLegacyWake); + + /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */ AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID; - - /* Setup parameter object */ - - ArgList.Count = 1; - ArgList.Pointer = &Arg; - Arg.Type = ACPI_TYPE_INTEGER; - - /* Ignore any errors from these methods */ - - Arg.Integer.Value = ACPI_SST_WAKING; - Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL); - if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) - { - ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST")); - } - - Arg.Integer.Value = SleepState; - Status = AcpiEvaluateObject (NULL, METHOD_NAME__BFS, &ArgList, NULL); - if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) - { - ACPI_EXCEPTION ((AE_INFO, Status, "During Method _BFS")); - } - - Status = AcpiEvaluateObject (NULL, METHOD_NAME__WAK, &ArgList, NULL); - if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) - { - ACPI_EXCEPTION ((AE_INFO, Status, "During Method _WAK")); - } - /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WAKING); /* + * GPEs must be enabled before _WAK is called as GPEs + * might get fired there + * * Restore the GPEs: * 1) Disable/Clear all GPEs * 2) Enable all runtime GPEs @@ -610,7 +349,6 @@ AcpiLeaveSleepState ( { return_ACPI_STATUS (Status); } - AcpiGbl_SystemAwakeAndRunning = TRUE; Status = AcpiHwEnableAllRuntimeGpes (); if (ACPI_FAILURE (Status)) @@ -618,6 +356,20 @@ AcpiLeaveSleepState ( return_ACPI_STATUS (Status); } + /* + * Now we can execute _WAK, etc. Some machines require that the GPEs + * are enabled before the wake methods are executed. + */ + AcpiHwExecuteSleepMethod (METHOD_NAME__WAK, SleepState); + + /* + * Some BIOS code assumes that WAK_STS will be cleared on resume + * and use it to determine whether the system is rebooting or + * resuming. Clear WAK_STS for compatibility. + */ + (void) AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); + AcpiGbl_SystemAwakeAndRunning = TRUE; + /* Enable power button */ (void) AcpiWriteBitRegister( @@ -639,15 +391,8 @@ AcpiLeaveSleepState ( return_ACPI_STATUS (Status); } - Arg.Integer.Value = ACPI_SST_WORKING; - Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL); - if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) - { - ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST")); - } - + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, ACPI_SST_WORKING); return_ACPI_STATUS (Status); } -ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState) - +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/hardware/hwtimer.c b/sys/contrib/dev/acpica/components/hardware/hwtimer.c similarity index 98% rename from sys/contrib/dev/acpica/hardware/hwtimer.c rename to sys/contrib/dev/acpica/components/hardware/hwtimer.c index 933b98bd2947..fd1cc351964c 100644 --- a/sys/contrib/dev/acpica/hardware/hwtimer.c +++ b/sys/contrib/dev/acpica/components/hardware/hwtimer.c @@ -49,6 +49,7 @@ ACPI_MODULE_NAME ("hwtimer") +#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ /****************************************************************************** * * FUNCTION: AcpiGetTimerResolution @@ -214,3 +215,4 @@ AcpiGetTimerDuration ( ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration) +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/sys/contrib/dev/acpica/hardware/hwvalid.c b/sys/contrib/dev/acpica/components/hardware/hwvalid.c similarity index 100% rename from sys/contrib/dev/acpica/hardware/hwvalid.c rename to sys/contrib/dev/acpica/components/hardware/hwvalid.c diff --git a/sys/contrib/dev/acpica/hardware/hwxface.c b/sys/contrib/dev/acpica/components/hardware/hwxface.c similarity index 94% rename from sys/contrib/dev/acpica/hardware/hwxface.c rename to sys/contrib/dev/acpica/components/hardware/hwxface.c index eeb293b0bd0b..cac0f239071f 100644 --- a/sys/contrib/dev/acpica/hardware/hwxface.c +++ b/sys/contrib/dev/acpica/components/hardware/hwxface.c @@ -154,12 +154,6 @@ AcpiRead ( return (Status); } - Width = Reg->BitWidth; - if (Width == 64) - { - Width = 32; /* Break into two 32-bit transfers */ - } - /* Initialize entire 64-bit return value to zero */ *ReturnValue = 0; @@ -172,28 +166,20 @@ AcpiRead ( if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) { Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) - Address, &Value, Width); + Address, ReturnValue, Reg->BitWidth); if (ACPI_FAILURE (Status)) { return (Status); } - *ReturnValue = Value; - - if (Reg->BitWidth == 64) - { - /* Read the top 32 bits */ - - Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) - (Address + 4), &Value, 32); - if (ACPI_FAILURE (Status)) - { - return (Status); - } - *ReturnValue |= ((UINT64) Value << 32); - } } else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ { + Width = Reg->BitWidth; + if (Width == 64) + { + Width = 32; /* Break into two 32-bit transfers */ + } + Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address, &Value, Width); if (ACPI_FAILURE (Status)) @@ -262,12 +248,6 @@ AcpiWrite ( return (Status); } - Width = Reg->BitWidth; - if (Width == 64) - { - Width = 32; /* Break into two 32-bit transfers */ - } - /* * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient @@ -275,24 +255,20 @@ AcpiWrite ( if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) { Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) - Address, ACPI_LODWORD (Value), Width); + Address, Value, Reg->BitWidth); if (ACPI_FAILURE (Status)) { return (Status); } - - if (Reg->BitWidth == 64) - { - Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) - (Address + 4), ACPI_HIDWORD (Value), 32); - if (ACPI_FAILURE (Status)) - { - return (Status); - } - } } else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ { + Width = Reg->BitWidth; + if (Width == 64) + { + Width = 32; /* Break into two 32-bit transfers */ + } + Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address, ACPI_LODWORD (Value), Width); if (ACPI_FAILURE (Status)) @@ -323,6 +299,7 @@ AcpiWrite ( ACPI_EXPORT_SYMBOL (AcpiWrite) +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: AcpiReadBitRegister @@ -505,6 +482,8 @@ AcpiWriteBitRegister ( ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) +#endif /* !ACPI_REDUCED_HARDWARE */ + /******************************************************************************* * diff --git a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c new file mode 100644 index 000000000000..7adee6968a13 --- /dev/null +++ b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c @@ -0,0 +1,474 @@ +/****************************************************************************** + * + * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwxfsleep") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiHwSleepDispatch ( + UINT8 SleepState, + UINT32 FunctionId); + +/* + * Dispatch table used to efficiently branch to the various sleep + * functions. + */ +#define ACPI_SLEEP_FUNCTION_ID 0 +#define ACPI_WAKE_PREP_FUNCTION_ID 1 +#define ACPI_WAKE_FUNCTION_ID 2 + +/* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */ + +static ACPI_SLEEP_FUNCTIONS AcpiSleepDispatch[] = +{ + {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacySleep), AcpiHwExtendedSleep}, + {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWakePrep), AcpiHwExtendedWakePrep}, + {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWake), AcpiHwExtendedWake} +}; + + +/* + * These functions are removed for the ACPI_REDUCED_HARDWARE case: + * AcpiSetFirmwareWakingVector + * AcpiSetFirmwareWakingVector64 + * AcpiEnterSleepStateS4bios + */ + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: AcpiSetFirmwareWakingVector + * + * PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode + * entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 32-bit FirmwareWakingVector field of the FACS + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetFirmwareWakingVector ( + UINT32 PhysicalAddress) +{ + ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector); + + + /* Set the 32-bit vector */ + + AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress; + + /* Clear the 64-bit vector if it exists */ + + if ((AcpiGbl_FACS->Length > 32) && (AcpiGbl_FACS->Version >= 1)) + { + AcpiGbl_FACS->XFirmwareWakingVector = 0; + } + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector) + + +#if ACPI_MACHINE_WIDTH == 64 +/******************************************************************************* + * + * FUNCTION: AcpiSetFirmwareWakingVector64 + * + * PARAMETERS: PhysicalAddress - 64-bit physical address of ACPI protected + * mode entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 64-bit X_FirmwareWakingVector field of the FACS, if + * it exists in the table. This function is intended for use with + * 64-bit host operating systems. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetFirmwareWakingVector64 ( + UINT64 PhysicalAddress) +{ + ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64); + + + /* Determine if the 64-bit vector actually exists */ + + if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1)) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Clear 32-bit vector, set the 64-bit X_ vector */ + + AcpiGbl_FACS->FirmwareWakingVector = 0; + AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress; + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector64) +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiEnterSleepStateS4bios + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Perform a S4 bios request. + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnterSleepStateS4bios ( + void) +{ + UINT32 InValue; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios); + + + /* Clear the wake status bit (PM1) */ + + Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiHwClearAcpiStatus (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * 1) Disable/Clear all GPEs + * 2) Enable all wakeup GPEs + */ + Status = AcpiHwDisableAllGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + AcpiGbl_SystemAwakeAndRunning = FALSE; + + Status = AcpiHwEnableAllWakeupGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ACPI_FLUSH_CPU_CACHE (); + + Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, + (UINT32) AcpiGbl_FADT.S4BiosRequest, 8); + + do { + AcpiOsStall(1000); + Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } while (!InValue); + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios) + +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/******************************************************************************* + * + * FUNCTION: AcpiHwSleepDispatch + * + * PARAMETERS: SleepState - Which sleep state to enter/exit + * FunctionId - Sleep, WakePrep, or Wake + * + * RETURN: Status from the invoked sleep handling function. + * + * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling + * function. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwSleepDispatch ( + UINT8 SleepState, + UINT32 FunctionId) +{ + ACPI_STATUS Status; + ACPI_SLEEP_FUNCTIONS *SleepFunctions = &AcpiSleepDispatch[FunctionId]; + + +#if (!ACPI_REDUCED_HARDWARE) + + /* + * If the Hardware Reduced flag is set (from the FADT), we must + * use the extended sleep registers + */ + if (AcpiGbl_ReducedHardware || + AcpiGbl_FADT.SleepControl.Address) + { + Status = SleepFunctions->ExtendedFunction (SleepState); + } + else + { + /* Legacy sleep */ + + Status = SleepFunctions->LegacyFunction (SleepState); + } + + return (Status); + +#else + /* + * For the case where reduced-hardware-only code is being generated, + * we know that only the extended sleep registers are available + */ + Status = SleepFunctions->ExtendedFunction (SleepState); + return (Status); + +#endif /* !ACPI_REDUCED_HARDWARE */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEnterSleepStatePrep + * + * PARAMETERS: SleepState - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Prepare to enter a system sleep state. + * This function must execute with interrupts enabled. + * We break sleeping into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnterSleepStatePrep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + ACPI_OBJECT_LIST ArgList; + ACPI_OBJECT Arg; + UINT32 SstValue; + + + ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep); + + + /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ + + Status = AcpiGetSleepTypeData (SleepState, + &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Execute the _PTS method (Prepare To Sleep) */ + + ArgList.Count = 1; + ArgList.Pointer = &Arg; + Arg.Type = ACPI_TYPE_INTEGER; + Arg.Integer.Value = SleepState; + + Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL); + if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) + { + return_ACPI_STATUS (Status); + } + + /* Setup the argument to the _SST method (System STatus) */ + + switch (SleepState) + { + case ACPI_STATE_S0: + SstValue = ACPI_SST_WORKING; + break; + + case ACPI_STATE_S1: + case ACPI_STATE_S2: + case ACPI_STATE_S3: + SstValue = ACPI_SST_SLEEPING; + break; + + case ACPI_STATE_S4: + SstValue = ACPI_SST_SLEEP_CONTEXT; + break; + + default: + SstValue = ACPI_SST_INDICATOR_OFF; /* Default is off */ + break; + } + + /* + * Set the system indicators to show the desired sleep state. + * _SST is an optional method (return no error if not found) + */ + AcpiHwExecuteSleepMethod (METHOD_NAME__SST, SstValue); + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep) + + +/******************************************************************************* + * + * FUNCTION: AcpiEnterSleepState + * + * PARAMETERS: SleepState - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnterSleepState ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiEnterSleepState); + + + if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) || + (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX)) + { + ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", + AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB)); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + + Status = AcpiHwSleepDispatch (SleepState, ACPI_SLEEP_FUNCTION_ID); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnterSleepState) + + +/******************************************************************************* + * + * FUNCTION: AcpiLeaveSleepStatePrep + * + * PARAMETERS: SleepState - Which sleep state we are exiting + * + * RETURN: Status + * + * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a + * sleep. Called with interrupts DISABLED. + * We break wake/resume into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiLeaveSleepStatePrep ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiLeaveSleepStatePrep); + + + Status = AcpiHwSleepDispatch (SleepState, ACPI_WAKE_PREP_FUNCTION_ID); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiLeaveSleepStatePrep) + + +/******************************************************************************* + * + * FUNCTION: AcpiLeaveSleepState + * + * PARAMETERS: SleepState - Which sleep state we are exiting + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiLeaveSleepState ( + UINT8 SleepState) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiLeaveSleepState); + + + Status = AcpiHwSleepDispatch (SleepState, ACPI_WAKE_FUNCTION_ID); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState) diff --git a/sys/contrib/dev/acpica/namespace/nsaccess.c b/sys/contrib/dev/acpica/components/namespace/nsaccess.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsaccess.c rename to sys/contrib/dev/acpica/components/namespace/nsaccess.c diff --git a/sys/contrib/dev/acpica/namespace/nsalloc.c b/sys/contrib/dev/acpica/components/namespace/nsalloc.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsalloc.c rename to sys/contrib/dev/acpica/components/namespace/nsalloc.c diff --git a/sys/contrib/dev/acpica/namespace/nsdump.c b/sys/contrib/dev/acpica/components/namespace/nsdump.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsdump.c rename to sys/contrib/dev/acpica/components/namespace/nsdump.c diff --git a/sys/contrib/dev/acpica/namespace/nsdumpdv.c b/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsdumpdv.c rename to sys/contrib/dev/acpica/components/namespace/nsdumpdv.c diff --git a/sys/contrib/dev/acpica/namespace/nseval.c b/sys/contrib/dev/acpica/components/namespace/nseval.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nseval.c rename to sys/contrib/dev/acpica/components/namespace/nseval.c diff --git a/sys/contrib/dev/acpica/namespace/nsinit.c b/sys/contrib/dev/acpica/components/namespace/nsinit.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsinit.c rename to sys/contrib/dev/acpica/components/namespace/nsinit.c diff --git a/sys/contrib/dev/acpica/namespace/nsload.c b/sys/contrib/dev/acpica/components/namespace/nsload.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsload.c rename to sys/contrib/dev/acpica/components/namespace/nsload.c diff --git a/sys/contrib/dev/acpica/namespace/nsnames.c b/sys/contrib/dev/acpica/components/namespace/nsnames.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsnames.c rename to sys/contrib/dev/acpica/components/namespace/nsnames.c diff --git a/sys/contrib/dev/acpica/namespace/nsobject.c b/sys/contrib/dev/acpica/components/namespace/nsobject.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsobject.c rename to sys/contrib/dev/acpica/components/namespace/nsobject.c diff --git a/sys/contrib/dev/acpica/namespace/nsparse.c b/sys/contrib/dev/acpica/components/namespace/nsparse.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsparse.c rename to sys/contrib/dev/acpica/components/namespace/nsparse.c diff --git a/sys/contrib/dev/acpica/namespace/nspredef.c b/sys/contrib/dev/acpica/components/namespace/nspredef.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nspredef.c rename to sys/contrib/dev/acpica/components/namespace/nspredef.c diff --git a/sys/contrib/dev/acpica/namespace/nsrepair.c b/sys/contrib/dev/acpica/components/namespace/nsrepair.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsrepair.c rename to sys/contrib/dev/acpica/components/namespace/nsrepair.c diff --git a/sys/contrib/dev/acpica/namespace/nsrepair2.c b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsrepair2.c rename to sys/contrib/dev/acpica/components/namespace/nsrepair2.c diff --git a/sys/contrib/dev/acpica/namespace/nssearch.c b/sys/contrib/dev/acpica/components/namespace/nssearch.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nssearch.c rename to sys/contrib/dev/acpica/components/namespace/nssearch.c diff --git a/sys/contrib/dev/acpica/namespace/nsutils.c b/sys/contrib/dev/acpica/components/namespace/nsutils.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsutils.c rename to sys/contrib/dev/acpica/components/namespace/nsutils.c diff --git a/sys/contrib/dev/acpica/namespace/nswalk.c b/sys/contrib/dev/acpica/components/namespace/nswalk.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nswalk.c rename to sys/contrib/dev/acpica/components/namespace/nswalk.c diff --git a/sys/contrib/dev/acpica/namespace/nsxfeval.c b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsxfeval.c rename to sys/contrib/dev/acpica/components/namespace/nsxfeval.c diff --git a/sys/contrib/dev/acpica/namespace/nsxfname.c b/sys/contrib/dev/acpica/components/namespace/nsxfname.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsxfname.c rename to sys/contrib/dev/acpica/components/namespace/nsxfname.c diff --git a/sys/contrib/dev/acpica/namespace/nsxfobj.c b/sys/contrib/dev/acpica/components/namespace/nsxfobj.c similarity index 100% rename from sys/contrib/dev/acpica/namespace/nsxfobj.c rename to sys/contrib/dev/acpica/components/namespace/nsxfobj.c diff --git a/sys/contrib/dev/acpica/parser/psargs.c b/sys/contrib/dev/acpica/components/parser/psargs.c similarity index 100% rename from sys/contrib/dev/acpica/parser/psargs.c rename to sys/contrib/dev/acpica/components/parser/psargs.c diff --git a/sys/contrib/dev/acpica/parser/psloop.c b/sys/contrib/dev/acpica/components/parser/psloop.c similarity index 100% rename from sys/contrib/dev/acpica/parser/psloop.c rename to sys/contrib/dev/acpica/components/parser/psloop.c diff --git a/sys/contrib/dev/acpica/parser/psopcode.c b/sys/contrib/dev/acpica/components/parser/psopcode.c similarity index 100% rename from sys/contrib/dev/acpica/parser/psopcode.c rename to sys/contrib/dev/acpica/components/parser/psopcode.c diff --git a/sys/contrib/dev/acpica/parser/psparse.c b/sys/contrib/dev/acpica/components/parser/psparse.c similarity index 100% rename from sys/contrib/dev/acpica/parser/psparse.c rename to sys/contrib/dev/acpica/components/parser/psparse.c diff --git a/sys/contrib/dev/acpica/parser/psscope.c b/sys/contrib/dev/acpica/components/parser/psscope.c similarity index 100% rename from sys/contrib/dev/acpica/parser/psscope.c rename to sys/contrib/dev/acpica/components/parser/psscope.c diff --git a/sys/contrib/dev/acpica/parser/pstree.c b/sys/contrib/dev/acpica/components/parser/pstree.c similarity index 100% rename from sys/contrib/dev/acpica/parser/pstree.c rename to sys/contrib/dev/acpica/components/parser/pstree.c diff --git a/sys/contrib/dev/acpica/parser/psutils.c b/sys/contrib/dev/acpica/components/parser/psutils.c similarity index 100% rename from sys/contrib/dev/acpica/parser/psutils.c rename to sys/contrib/dev/acpica/components/parser/psutils.c diff --git a/sys/contrib/dev/acpica/parser/pswalk.c b/sys/contrib/dev/acpica/components/parser/pswalk.c similarity index 100% rename from sys/contrib/dev/acpica/parser/pswalk.c rename to sys/contrib/dev/acpica/components/parser/pswalk.c diff --git a/sys/contrib/dev/acpica/parser/psxface.c b/sys/contrib/dev/acpica/components/parser/psxface.c similarity index 100% rename from sys/contrib/dev/acpica/parser/psxface.c rename to sys/contrib/dev/acpica/components/parser/psxface.c diff --git a/sys/contrib/dev/acpica/resources/rsaddr.c b/sys/contrib/dev/acpica/components/resources/rsaddr.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsaddr.c rename to sys/contrib/dev/acpica/components/resources/rsaddr.c diff --git a/sys/contrib/dev/acpica/resources/rscalc.c b/sys/contrib/dev/acpica/components/resources/rscalc.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rscalc.c rename to sys/contrib/dev/acpica/components/resources/rscalc.c diff --git a/sys/contrib/dev/acpica/resources/rscreate.c b/sys/contrib/dev/acpica/components/resources/rscreate.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rscreate.c rename to sys/contrib/dev/acpica/components/resources/rscreate.c diff --git a/sys/contrib/dev/acpica/resources/rsdump.c b/sys/contrib/dev/acpica/components/resources/rsdump.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsdump.c rename to sys/contrib/dev/acpica/components/resources/rsdump.c diff --git a/sys/contrib/dev/acpica/resources/rsinfo.c b/sys/contrib/dev/acpica/components/resources/rsinfo.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsinfo.c rename to sys/contrib/dev/acpica/components/resources/rsinfo.c diff --git a/sys/contrib/dev/acpica/resources/rsio.c b/sys/contrib/dev/acpica/components/resources/rsio.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsio.c rename to sys/contrib/dev/acpica/components/resources/rsio.c diff --git a/sys/contrib/dev/acpica/resources/rsirq.c b/sys/contrib/dev/acpica/components/resources/rsirq.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsirq.c rename to sys/contrib/dev/acpica/components/resources/rsirq.c diff --git a/sys/contrib/dev/acpica/resources/rslist.c b/sys/contrib/dev/acpica/components/resources/rslist.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rslist.c rename to sys/contrib/dev/acpica/components/resources/rslist.c diff --git a/sys/contrib/dev/acpica/resources/rsmemory.c b/sys/contrib/dev/acpica/components/resources/rsmemory.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsmemory.c rename to sys/contrib/dev/acpica/components/resources/rsmemory.c diff --git a/sys/contrib/dev/acpica/resources/rsmisc.c b/sys/contrib/dev/acpica/components/resources/rsmisc.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsmisc.c rename to sys/contrib/dev/acpica/components/resources/rsmisc.c diff --git a/sys/contrib/dev/acpica/resources/rsserial.c b/sys/contrib/dev/acpica/components/resources/rsserial.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsserial.c rename to sys/contrib/dev/acpica/components/resources/rsserial.c diff --git a/sys/contrib/dev/acpica/resources/rsutils.c b/sys/contrib/dev/acpica/components/resources/rsutils.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsutils.c rename to sys/contrib/dev/acpica/components/resources/rsutils.c diff --git a/sys/contrib/dev/acpica/resources/rsxface.c b/sys/contrib/dev/acpica/components/resources/rsxface.c similarity index 100% rename from sys/contrib/dev/acpica/resources/rsxface.c rename to sys/contrib/dev/acpica/components/resources/rsxface.c diff --git a/sys/contrib/dev/acpica/tables/tbfadt.c b/sys/contrib/dev/acpica/components/tables/tbfadt.c similarity index 100% rename from sys/contrib/dev/acpica/tables/tbfadt.c rename to sys/contrib/dev/acpica/components/tables/tbfadt.c diff --git a/sys/contrib/dev/acpica/tables/tbfind.c b/sys/contrib/dev/acpica/components/tables/tbfind.c similarity index 100% rename from sys/contrib/dev/acpica/tables/tbfind.c rename to sys/contrib/dev/acpica/components/tables/tbfind.c diff --git a/sys/contrib/dev/acpica/tables/tbinstal.c b/sys/contrib/dev/acpica/components/tables/tbinstal.c similarity index 86% rename from sys/contrib/dev/acpica/tables/tbinstal.c rename to sys/contrib/dev/acpica/components/tables/tbinstal.c index 7cfbf4df38f1..e178d94c7488 100644 --- a/sys/contrib/dev/acpica/tables/tbinstal.c +++ b/sys/contrib/dev/acpica/components/tables/tbinstal.c @@ -128,7 +128,6 @@ AcpiTbAddTable ( { UINT32 i; ACPI_STATUS Status = AE_OK; - ACPI_TABLE_HEADER *OverrideTable = NULL; ACPI_FUNCTION_TRACE (TbAddTable); @@ -242,26 +241,10 @@ AcpiTbAddTable ( /* * ACPI Table Override: * Allow the host to override dynamically loaded tables. + * NOTE: the table is fully mapped at this point, and the mapping will + * be deleted by TbTableOverride if the table is actually overridden. */ - Status = AcpiOsTableOverride (TableDesc->Pointer, &OverrideTable); - if (ACPI_SUCCESS (Status) && OverrideTable) - { - ACPI_INFO ((AE_INFO, - "%4.4s @ 0x%p Table override, replaced with:", - TableDesc->Pointer->Signature, - ACPI_CAST_PTR (void, TableDesc->Address))); - - /* We can delete the table that was passed as a parameter */ - - AcpiTbDeleteTable (TableDesc); - - /* Setup descriptor for the new table */ - - TableDesc->Address = ACPI_PTR_TO_PHYSADDR (OverrideTable); - TableDesc->Pointer = OverrideTable; - TableDesc->Length = OverrideTable->Length; - TableDesc->Flags = ACPI_TABLE_ORIGIN_OVERRIDE; - } + (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc); /* Add the table to the global root table list */ @@ -281,6 +264,98 @@ AcpiTbAddTable ( } +/******************************************************************************* + * + * FUNCTION: AcpiTbTableOverride + * + * PARAMETERS: TableHeader - Header for the original table + * TableDesc - Table descriptor initialized for the + * original table. May or may not be mapped. + * + * RETURN: Pointer to the entire new table. NULL if table not overridden. + * If overridden, installs the new table within the input table + * descriptor. + * + * DESCRIPTION: Attempt table override by calling the OSL override functions. + * Note: If the table is overridden, then the entire new table + * is mapped and returned by this function. + * + ******************************************************************************/ + +ACPI_TABLE_HEADER * +AcpiTbTableOverride ( + ACPI_TABLE_HEADER *TableHeader, + ACPI_TABLE_DESC *TableDesc) +{ + ACPI_STATUS Status; + ACPI_TABLE_HEADER *NewTable = NULL; + ACPI_PHYSICAL_ADDRESS NewAddress = 0; + UINT32 NewTableLength = 0; + UINT8 NewFlags; + char *OverrideType; + + + /* (1) Attempt logical override (returns a logical address) */ + + Status = AcpiOsTableOverride (TableHeader, &NewTable); + if (ACPI_SUCCESS (Status) && NewTable) + { + NewAddress = ACPI_PTR_TO_PHYSADDR (NewTable); + NewTableLength = NewTable->Length; + NewFlags = ACPI_TABLE_ORIGIN_OVERRIDE; + OverrideType = "Logical"; + goto FinishOverride; + } + + /* (2) Attempt physical override (returns a physical address) */ + + Status = AcpiOsPhysicalTableOverride (TableHeader, + &NewAddress, &NewTableLength); + if (ACPI_SUCCESS (Status) && NewAddress && NewTableLength) + { + /* Map the entire new table */ + + NewTable = AcpiOsMapMemory (NewAddress, NewTableLength); + if (!NewTable) + { + ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, + "%4.4s %p Attempted physical table override failed", + TableHeader->Signature, + ACPI_CAST_PTR (void, TableDesc->Address))); + return (NULL); + } + + OverrideType = "Physical"; + NewFlags = ACPI_TABLE_ORIGIN_MAPPED; + goto FinishOverride; + } + + return (NULL); /* There was no override */ + + +FinishOverride: + + ACPI_INFO ((AE_INFO, + "%4.4s %p %s table override, new table: %p", + TableHeader->Signature, + ACPI_CAST_PTR (void, TableDesc->Address), + OverrideType, NewTable)); + + /* We can now unmap/delete the original table (if fully mapped) */ + + AcpiTbDeleteTable (TableDesc); + + /* Setup descriptor for the new table */ + + TableDesc->Address = NewAddress; + TableDesc->Pointer = NewTable; + TableDesc->Length = NewTableLength; + TableDesc->Flags = NewFlags; + + return (NewTable); +} + + /******************************************************************************* * * FUNCTION: AcpiTbResizeRootTableList diff --git a/sys/contrib/dev/acpica/tables/tbutils.c b/sys/contrib/dev/acpica/components/tables/tbutils.c similarity index 92% rename from sys/contrib/dev/acpica/tables/tbutils.c rename to sys/contrib/dev/acpica/components/tables/tbutils.c index 6a1068bc8799..02ee3e66164d 100644 --- a/sys/contrib/dev/acpica/tables/tbutils.c +++ b/sys/contrib/dev/acpica/components/tables/tbutils.c @@ -50,6 +50,7 @@ #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME ("tbutils") + /* Local prototypes */ static void @@ -68,6 +69,7 @@ AcpiTbGetRootTableEntry ( UINT32 TableEntrySize); +#if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * * FUNCTION: AcpiTbInitializeFacs @@ -100,6 +102,7 @@ AcpiTbInitializeFacs ( ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_FACS)); return (Status); } +#endif /* !ACPI_REDUCED_HARDWARE */ /******************************************************************************* @@ -423,7 +426,7 @@ AcpiTbCopyDsdt ( * RETURN: None * * DESCRIPTION: Install an ACPI table into the global data structure. The - * table override mechanism is implemented here to allow the host + * table override mechanism is called to allow the host * OS to replace any table before it is installed in the root * table array. * @@ -435,11 +438,9 @@ AcpiTbInstallTable ( char *Signature, UINT32 TableIndex) { - UINT8 Flags; - ACPI_STATUS Status; - ACPI_TABLE_HEADER *TableToInstall; - ACPI_TABLE_HEADER *MappedTable; - ACPI_TABLE_HEADER *OverrideTable = NULL; + ACPI_TABLE_HEADER *Table; + ACPI_TABLE_HEADER *FinalTable; + ACPI_TABLE_DESC *TableDesc; if (!Address) @@ -451,15 +452,17 @@ AcpiTbInstallTable ( /* Map just the table header */ - MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); - if (!MappedTable) + Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); + if (!Table) { + ACPI_ERROR ((AE_INFO, "Could not map memory for table [%s] at %p", + Signature, ACPI_CAST_PTR (void, Address))); return; } /* Skip SSDT when DSDT is overriden */ - if (ACPI_COMPARE_NAME (MappedTable->Signature, ACPI_SIG_SSDT) && + if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT) && (AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags & ACPI_TABLE_ORIGIN_OVERRIDE)) { @@ -475,61 +478,58 @@ AcpiTbInstallTable ( /* If a particular signature is expected (DSDT/FACS), it must match */ if (Signature && - !ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) + !ACPI_COMPARE_NAME (Table->Signature, Signature)) { ACPI_ERROR ((AE_INFO, "Invalid signature 0x%X for ACPI table, expected [%s]", - *ACPI_CAST_PTR (UINT32, MappedTable->Signature), Signature)); + *ACPI_CAST_PTR (UINT32, Table->Signature), Signature)); goto UnmapAndExit; } + /* + * Initialize the table entry. Set the pointer to NULL, since the + * table is not fully mapped at this time. + */ + TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; + + TableDesc->Address = Address; + TableDesc->Pointer = NULL; + TableDesc->Length = Table->Length; + TableDesc->Flags = ACPI_TABLE_ORIGIN_MAPPED; + ACPI_MOVE_32_TO_32 (TableDesc->Signature.Ascii, Table->Signature); + /* * ACPI Table Override: * * Before we install the table, let the host OS override it with a new * one if desired. Any table within the RSDT/XSDT can be replaced, * including the DSDT which is pointed to by the FADT. + * + * NOTE: If the table is overridden, then FinalTable will contain a + * mapped pointer to the full new table. If the table is not overridden, + * then the table will be fully mapped elsewhere (in verify table). + * In any case, we must unmap the header that was mapped above. */ - Status = AcpiOsTableOverride (MappedTable, &OverrideTable); - if (ACPI_SUCCESS (Status) && OverrideTable) + FinalTable = AcpiTbTableOverride (Table, TableDesc); + if (!FinalTable) { - ACPI_INFO ((AE_INFO, - "%4.4s @ 0x%p Table override, replaced with:", - MappedTable->Signature, ACPI_CAST_PTR (void, Address))); - - AcpiGbl_RootTableList.Tables[TableIndex].Pointer = OverrideTable; - Address = ACPI_PTR_TO_PHYSADDR (OverrideTable); - - TableToInstall = OverrideTable; - Flags = ACPI_TABLE_ORIGIN_OVERRIDE; - } - else - { - TableToInstall = MappedTable; - Flags = ACPI_TABLE_ORIGIN_MAPPED; + FinalTable = Table; /* There was no override */ } - /* Initialize the table entry */ + AcpiTbPrintTableHeader (TableDesc->Address, FinalTable); - AcpiGbl_RootTableList.Tables[TableIndex].Address = Address; - AcpiGbl_RootTableList.Tables[TableIndex].Length = TableToInstall->Length; - AcpiGbl_RootTableList.Tables[TableIndex].Flags = Flags; - - ACPI_MOVE_32_TO_32 ( - &(AcpiGbl_RootTableList.Tables[TableIndex].Signature), - TableToInstall->Signature); - - AcpiTbPrintTableHeader (Address, TableToInstall); + /* Set the global integer width (based upon revision of the DSDT) */ if (TableIndex == ACPI_TABLE_INDEX_DSDT) { - /* Global integer width is based upon revision of the DSDT */ - - AcpiUtSetIntegerWidth (TableToInstall->Revision); + AcpiUtSetIntegerWidth (FinalTable->Revision); } UnmapAndExit: - AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); + + /* Always unmap the table header that we mapped above */ + + AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); } diff --git a/sys/contrib/dev/acpica/tables/tbxface.c b/sys/contrib/dev/acpica/components/tables/tbxface.c similarity index 100% rename from sys/contrib/dev/acpica/tables/tbxface.c rename to sys/contrib/dev/acpica/components/tables/tbxface.c diff --git a/sys/contrib/dev/acpica/tables/tbxfroot.c b/sys/contrib/dev/acpica/components/tables/tbxfroot.c similarity index 100% rename from sys/contrib/dev/acpica/tables/tbxfroot.c rename to sys/contrib/dev/acpica/components/tables/tbxfroot.c diff --git a/sys/contrib/dev/acpica/utilities/utaddress.c b/sys/contrib/dev/acpica/components/utilities/utaddress.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utaddress.c rename to sys/contrib/dev/acpica/components/utilities/utaddress.c diff --git a/sys/contrib/dev/acpica/utilities/utalloc.c b/sys/contrib/dev/acpica/components/utilities/utalloc.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utalloc.c rename to sys/contrib/dev/acpica/components/utilities/utalloc.c diff --git a/sys/contrib/dev/acpica/utilities/utcache.c b/sys/contrib/dev/acpica/components/utilities/utcache.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utcache.c rename to sys/contrib/dev/acpica/components/utilities/utcache.c diff --git a/sys/contrib/dev/acpica/utilities/utcopy.c b/sys/contrib/dev/acpica/components/utilities/utcopy.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utcopy.c rename to sys/contrib/dev/acpica/components/utilities/utcopy.c diff --git a/sys/contrib/dev/acpica/utilities/utdebug.c b/sys/contrib/dev/acpica/components/utilities/utdebug.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utdebug.c rename to sys/contrib/dev/acpica/components/utilities/utdebug.c diff --git a/sys/contrib/dev/acpica/utilities/utdecode.c b/sys/contrib/dev/acpica/components/utilities/utdecode.c similarity index 96% rename from sys/contrib/dev/acpica/utilities/utdecode.c rename to sys/contrib/dev/acpica/components/utilities/utdecode.c index da59fbcdd736..689d495e01d4 100644 --- a/sys/contrib/dev/acpica/utilities/utdecode.c +++ b/sys/contrib/dev/acpica/components/utilities/utdecode.c @@ -567,20 +567,21 @@ AcpiUtGetMutexName ( /* Names for Notify() values, used for debug output */ -static const char *AcpiGbl_NotifyValueNames[] = +static const char *AcpiGbl_NotifyValueNames[ACPI_NOTIFY_MAX + 1] = { - "Bus Check", - "Device Check", - "Device Wake", - "Eject Request", - "Device Check Light", - "Frequency Mismatch", - "Bus Mode Mismatch", - "Power Fault", - "Capabilities Check", - "Device PLD Check", - "Reserved", - "System Locality Update" + /* 00 */ "Bus Check", + /* 01 */ "Device Check", + /* 02 */ "Device Wake", + /* 03 */ "Eject Request", + /* 04 */ "Device Check Light", + /* 05 */ "Frequency Mismatch", + /* 06 */ "Bus Mode Mismatch", + /* 07 */ "Power Fault", + /* 08 */ "Capabilities Check", + /* 09 */ "Device PLD Check", + /* 10 */ "Reserved", + /* 11 */ "System Locality Update", + /* 12 */ "Shutdown Request" }; const char * @@ -596,9 +597,13 @@ AcpiUtGetNotifyName ( { return ("Reserved"); } - else /* Greater or equal to 0x80 */ + else if (NotifyValue <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) { - return ("**Device Specific**"); + return ("Device Specific"); + } + else + { + return ("Hardware Specific"); } } #endif diff --git a/sys/contrib/dev/acpica/utilities/utdelete.c b/sys/contrib/dev/acpica/components/utilities/utdelete.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utdelete.c rename to sys/contrib/dev/acpica/components/utilities/utdelete.c diff --git a/sys/contrib/dev/acpica/utilities/uteval.c b/sys/contrib/dev/acpica/components/utilities/uteval.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/uteval.c rename to sys/contrib/dev/acpica/components/utilities/uteval.c diff --git a/sys/contrib/dev/acpica/utilities/utglobal.c b/sys/contrib/dev/acpica/components/utilities/utglobal.c similarity index 99% rename from sys/contrib/dev/acpica/utilities/utglobal.c rename to sys/contrib/dev/acpica/components/utilities/utglobal.c index 0d79dae11336..ab15231c6b5b 100644 --- a/sys/contrib/dev/acpica/utilities/utglobal.c +++ b/sys/contrib/dev/acpica/components/utilities/utglobal.c @@ -155,6 +155,7 @@ const ACPI_PREDEFINED_NAMES AcpiGbl_PreDefinedNames[] = }; +#if (!ACPI_REDUCED_HARDWARE) /****************************************************************************** * * Event and Hardware globals @@ -199,6 +200,7 @@ ACPI_FIXED_EVENT_INFO AcpiGbl_FixedEventInfo[ACPI_NUM_FIXED_EVENTS] = /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, ACPI_BITREG_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, ACPI_BITREG_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE}, }; +#endif /* !ACPI_REDUCED_HARDWARE */ /******************************************************************************* @@ -269,6 +271,8 @@ AcpiUtInitGlobals ( AcpiFixedEventCount[i] = 0; } +#if (!ACPI_REDUCED_HARDWARE) + /* GPE support */ AcpiGbl_AllGpesInitialized = FALSE; @@ -277,6 +281,10 @@ AcpiUtInitGlobals ( AcpiGbl_GpeFadtBlocks[1] = NULL; AcpiCurrentGpeCount = 0; + AcpiGbl_GlobalEventHandler = NULL; + +#endif /* !ACPI_REDUCED_HARDWARE */ + /* Global handlers */ AcpiGbl_SystemNotify.Handler = NULL; @@ -285,7 +293,6 @@ AcpiUtInitGlobals ( AcpiGbl_InitHandler = NULL; AcpiGbl_TableHandler = NULL; AcpiGbl_InterfaceHandler = NULL; - AcpiGbl_GlobalEventHandler = NULL; /* Global Lock support */ diff --git a/sys/contrib/dev/acpica/utilities/utids.c b/sys/contrib/dev/acpica/components/utilities/utids.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utids.c rename to sys/contrib/dev/acpica/components/utilities/utids.c diff --git a/sys/contrib/dev/acpica/utilities/utinit.c b/sys/contrib/dev/acpica/components/utilities/utinit.c similarity index 88% rename from sys/contrib/dev/acpica/utilities/utinit.c rename to sys/contrib/dev/acpica/components/utilities/utinit.c index 5b2f71391ebc..6694ec77ab80 100644 --- a/sys/contrib/dev/acpica/utilities/utinit.c +++ b/sys/contrib/dev/acpica/components/utilities/utinit.c @@ -58,21 +58,33 @@ static void AcpiUtTerminate ( void); +#if (!ACPI_REDUCED_HARDWARE) +static void +AcpiUtFreeGpeLists ( + void); + +#else + +#define AcpiUtFreeGpeLists() +#endif /* !ACPI_REDUCED_HARDWARE */ + + +#if (!ACPI_REDUCED_HARDWARE) /****************************************************************************** * - * FUNCTION: AcpiUtTerminate + * FUNCTION: AcpiUtFreeGpeLists * * PARAMETERS: none * * RETURN: none * - * DESCRIPTION: Free global memory + * DESCRIPTION: Free global GPE lists * ******************************************************************************/ static void -AcpiUtTerminate ( +AcpiUtFreeGpeLists ( void) { ACPI_GPE_BLOCK_INFO *GpeBlock; @@ -81,9 +93,6 @@ AcpiUtTerminate ( ACPI_GPE_XRUPT_INFO *NextGpeXruptInfo; - ACPI_FUNCTION_TRACE (UtTerminate); - - /* Free global GPE blocks and related info structures */ GpeXruptInfo = AcpiGbl_GpeXruptListHead; @@ -103,7 +112,29 @@ AcpiUtTerminate ( ACPI_FREE (GpeXruptInfo); GpeXruptInfo = NextGpeXruptInfo; } +} +#endif /* !ACPI_REDUCED_HARDWARE */ + +/****************************************************************************** + * + * FUNCTION: AcpiUtTerminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Free global memory + * + ******************************************************************************/ + +static void +AcpiUtTerminate ( + void) +{ + ACPI_FUNCTION_TRACE (UtTerminate); + + AcpiUtFreeGpeLists (); AcpiUtDeleteAddressLists (); return_VOID; } diff --git a/sys/contrib/dev/acpica/utilities/utlock.c b/sys/contrib/dev/acpica/components/utilities/utlock.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utlock.c rename to sys/contrib/dev/acpica/components/utilities/utlock.c diff --git a/sys/contrib/dev/acpica/utilities/utmath.c b/sys/contrib/dev/acpica/components/utilities/utmath.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utmath.c rename to sys/contrib/dev/acpica/components/utilities/utmath.c diff --git a/sys/contrib/dev/acpica/utilities/utmisc.c b/sys/contrib/dev/acpica/components/utilities/utmisc.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utmisc.c rename to sys/contrib/dev/acpica/components/utilities/utmisc.c diff --git a/sys/contrib/dev/acpica/utilities/utmutex.c b/sys/contrib/dev/acpica/components/utilities/utmutex.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utmutex.c rename to sys/contrib/dev/acpica/components/utilities/utmutex.c diff --git a/sys/contrib/dev/acpica/utilities/utobject.c b/sys/contrib/dev/acpica/components/utilities/utobject.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utobject.c rename to sys/contrib/dev/acpica/components/utilities/utobject.c diff --git a/sys/contrib/dev/acpica/utilities/utosi.c b/sys/contrib/dev/acpica/components/utilities/utosi.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utosi.c rename to sys/contrib/dev/acpica/components/utilities/utosi.c diff --git a/sys/contrib/dev/acpica/utilities/utresrc.c b/sys/contrib/dev/acpica/components/utilities/utresrc.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utresrc.c rename to sys/contrib/dev/acpica/components/utilities/utresrc.c diff --git a/sys/contrib/dev/acpica/utilities/utstate.c b/sys/contrib/dev/acpica/components/utilities/utstate.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utstate.c rename to sys/contrib/dev/acpica/components/utilities/utstate.c diff --git a/sys/contrib/dev/acpica/utilities/uttrack.c b/sys/contrib/dev/acpica/components/utilities/uttrack.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/uttrack.c rename to sys/contrib/dev/acpica/components/utilities/uttrack.c diff --git a/sys/contrib/dev/acpica/utilities/utxface.c b/sys/contrib/dev/acpica/components/utilities/utxface.c similarity index 99% rename from sys/contrib/dev/acpica/utilities/utxface.c rename to sys/contrib/dev/acpica/components/utilities/utxface.c index 1cb23e07a9bd..3c4cbdf62a34 100644 --- a/sys/contrib/dev/acpica/utilities/utxface.c +++ b/sys/contrib/dev/acpica/components/utilities/utxface.c @@ -50,14 +50,12 @@ #include #include #include -#include #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utxface") #ifndef ACPI_ASL_COMPILER - /******************************************************************************* * * FUNCTION: AcpiInitializeSubsystem @@ -163,6 +161,8 @@ AcpiEnableSubsystem ( ACPI_FUNCTION_TRACE (AcpiEnableSubsystem); +#if (!ACPI_REDUCED_HARDWARE) + /* Enable ACPI mode */ if (!(Flags & ACPI_NO_ACPI_ENABLE)) @@ -190,6 +190,8 @@ AcpiEnableSubsystem ( return_ACPI_STATUS (Status); } +#endif /* !ACPI_REDUCED_HARDWARE */ + /* * Install the default OpRegion handlers. These are installed unless * other handlers have already been installed via the @@ -207,6 +209,7 @@ AcpiEnableSubsystem ( } } +#if (!ACPI_REDUCED_HARDWARE) /* * Initialize ACPI Event handling (Fixed and General Purpose) * @@ -249,6 +252,8 @@ AcpiEnableSubsystem ( } } +#endif /* !ACPI_REDUCED_HARDWARE */ + return_ACPI_STATUS (Status); } diff --git a/sys/contrib/dev/acpica/utilities/utxferror.c b/sys/contrib/dev/acpica/components/utilities/utxferror.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utxferror.c rename to sys/contrib/dev/acpica/components/utilities/utxferror.c diff --git a/sys/contrib/dev/acpica/utilities/utxfmutex.c b/sys/contrib/dev/acpica/components/utilities/utxfmutex.c similarity index 100% rename from sys/contrib/dev/acpica/utilities/utxfmutex.c rename to sys/contrib/dev/acpica/components/utilities/utxfmutex.c diff --git a/sys/contrib/dev/acpica/include/acconfig.h b/sys/contrib/dev/acpica/include/acconfig.h index 18825912fd15..7880516e4755 100644 --- a/sys/contrib/dev/acpica/include/acconfig.h +++ b/sys/contrib/dev/acpica/include/acconfig.h @@ -86,6 +86,23 @@ */ #define ACPI_CHECKSUM_ABORT FALSE +/* + * Generate a version of ACPICA that only supports "reduced hardware" + * platforms (as defined in ACPI 5.0). Set to TRUE to generate a specialized + * version of ACPICA that ONLY supports the ACPI 5.0 "reduced hardware" + * model. In other words, no ACPI hardware is supported. + * + * If TRUE, this means no support for the following: + * PM Event and Control registers + * SCI interrupt (and handler) + * Fixed Events + * General Purpose Events (GPEs) + * Global Lock + * ACPI PM timer + * FACS table (Waking vectors and Global Lock) + */ +#define ACPI_REDUCED_HARDWARE FALSE + /****************************************************************************** * @@ -95,7 +112,7 @@ /* Version of ACPI supported */ -#define ACPI_CA_SUPPORT_LEVEL 3 +#define ACPI_CA_SUPPORT_LEVEL 5 /* Maximum count for a semaphore object */ diff --git a/sys/contrib/dev/acpica/include/acdebug.h b/sys/contrib/dev/acpica/include/acdebug.h index 33470fbb3605..bcc505c8d511 100644 --- a/sys/contrib/dev/acpica/include/acdebug.h +++ b/sys/contrib/dev/acpica/include/acdebug.h @@ -137,18 +137,20 @@ void AcpiDbDisplayResources ( char *ObjectArg); +ACPI_HW_DEPENDENT_RETURN_VOID ( void AcpiDbDisplayGpes ( - void); + void)) void AcpiDbDisplayHandlers ( void); +ACPI_HW_DEPENDENT_RETURN_VOID ( void AcpiDbGenerateGpe ( char *GpeArg, - char *BlockArg); + char *BlockArg)) /* diff --git a/sys/contrib/dev/acpica/include/acevents.h b/sys/contrib/dev/acpica/include/acevents.h index 142c24730ba2..3b874f10759e 100644 --- a/sys/contrib/dev/acpica/include/acevents.h +++ b/sys/contrib/dev/acpica/include/acevents.h @@ -85,13 +85,15 @@ ACPI_STATUS AcpiEvInitGlobalLockHandler ( void); +ACPI_HW_DEPENDENT_RETURN_OK ( ACPI_STATUS AcpiEvAcquireGlobalLock( - UINT16 Timeout); + UINT16 Timeout)) +ACPI_HW_DEPENDENT_RETURN_OK ( ACPI_STATUS AcpiEvReleaseGlobalLock( - void); + void)) ACPI_STATUS AcpiEvRemoveGlobalLockHandler ( @@ -154,9 +156,10 @@ AcpiEvInitializeGpeBlock ( ACPI_GPE_BLOCK_INFO *GpeBlock, void *Context); +ACPI_HW_DEPENDENT_RETURN_OK ( ACPI_STATUS AcpiEvDeleteGpeBlock ( - ACPI_GPE_BLOCK_INFO *GpeBlock); + ACPI_GPE_BLOCK_INFO *GpeBlock)) UINT32 AcpiEvGpeDispatch ( @@ -171,9 +174,10 @@ ACPI_STATUS AcpiEvGpeInitialize ( void); +ACPI_HW_DEPENDENT_RETURN_VOID ( void AcpiEvUpdateGpes ( - ACPI_OWNER_ID TableOwnerId); + ACPI_OWNER_ID TableOwnerId)) ACPI_STATUS AcpiEvMatchGpeMethod ( @@ -335,9 +339,9 @@ UINT32 AcpiEvInitializeSCI ( UINT32 ProgramSCI); +ACPI_HW_DEPENDENT_RETURN_VOID ( void AcpiEvTerminate ( - void); - + void)) #endif /* __ACEVENTS_H__ */ diff --git a/sys/contrib/dev/acpica/include/acexcep.h b/sys/contrib/dev/acpica/include/acexcep.h index 9262d7bcb302..10f5a113da8e 100644 --- a/sys/contrib/dev/acpica/include/acexcep.h +++ b/sys/contrib/dev/acpica/include/acexcep.h @@ -92,8 +92,9 @@ #define AE_SAME_HANDLER (ACPI_STATUS) (0x0019 | AE_CODE_ENVIRONMENTAL) #define AE_NO_HANDLER (ACPI_STATUS) (0x001A | AE_CODE_ENVIRONMENTAL) #define AE_OWNER_ID_LIMIT (ACPI_STATUS) (0x001B | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_CONFIGURED (ACPI_STATUS) (0x001C | AE_CODE_ENVIRONMENTAL) -#define AE_CODE_ENV_MAX 0x001B +#define AE_CODE_ENV_MAX 0x001C /* @@ -222,7 +223,8 @@ char const *AcpiGbl_ExceptionNames_Env[] = "AE_ABORT_METHOD", "AE_SAME_HANDLER", "AE_NO_HANDLER", - "AE_OWNER_ID_LIMIT" + "AE_OWNER_ID_LIMIT", + "AE_NOT_CONFIGURED" }; char const *AcpiGbl_ExceptionNames_Pgm[] = diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h index 6b45877d8529..edf33d68ed7d 100644 --- a/sys/contrib/dev/acpica/include/acglobal.h +++ b/sys/contrib/dev/acpica/include/acglobal.h @@ -150,8 +150,7 @@ BOOLEAN AcpiGbl_SystemAwakeAndRunning; */ BOOLEAN AcpiGbl_ReducedHardware; - -#endif +#endif /* DEFINE_ACPI_GLOBALS */ /* Do not disassemble buffers to resource descriptors */ @@ -168,8 +167,12 @@ ACPI_EXTERN UINT8 ACPI_INIT_GLOBAL (AcpiGbl_NoResourceDisassembly, FALSE); * found in the RSDT/XSDT. */ ACPI_EXTERN ACPI_TABLE_LIST AcpiGbl_RootTableList; + +#if (!ACPI_REDUCED_HARDWARE) ACPI_EXTERN ACPI_TABLE_FACS *AcpiGbl_FACS; +#endif /* !ACPI_REDUCED_HARDWARE */ + /* These addresses are calculated from the FADT Event Block addresses */ ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1aStatus; @@ -381,6 +384,8 @@ ACPI_EXTERN UINT8 AcpiGbl_SleepTypeB; * ****************************************************************************/ +#if (!ACPI_REDUCED_HARDWARE) + ACPI_EXTERN UINT8 AcpiGbl_AllGpesInitialized; ACPI_EXTERN ACPI_GPE_XRUPT_INFO *AcpiGbl_GpeXruptListHead; ACPI_EXTERN ACPI_GPE_BLOCK_INFO *AcpiGbl_GpeFadtBlocks[ACPI_MAX_GPE_BLOCKS]; @@ -389,6 +394,7 @@ ACPI_EXTERN void *AcpiGbl_GlobalEventHandlerContext; ACPI_EXTERN ACPI_FIXED_EVENT_HANDLER AcpiGbl_FixedEventHandlers[ACPI_NUM_FIXED_EVENTS]; extern ACPI_FIXED_EVENT_INFO AcpiGbl_FixedEventInfo[ACPI_NUM_FIXED_EVENTS]; +#endif /* !ACPI_REDUCED_HARDWARE */ /***************************************************************************** * diff --git a/sys/contrib/dev/acpica/include/achware.h b/sys/contrib/dev/acpica/include/achware.h index e808be4cbc55..004795dbfa12 100644 --- a/sys/contrib/dev/acpica/include/achware.h +++ b/sys/contrib/dev/acpica/include/achware.h @@ -109,6 +109,43 @@ AcpiHwClearAcpiStatus ( void); +/* + * hwsleep - sleep/wake support (Legacy sleep registers) + */ +ACPI_STATUS +AcpiHwLegacySleep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiHwLegacyWakePrep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiHwLegacyWake ( + UINT8 SleepState); + + +/* + * hwesleep - sleep/wake support (Extended FADT-V5 sleep registers) + */ +void +AcpiHwExecuteSleepMethod ( + char *MethodName, + UINT32 IntegerArgument); + +ACPI_STATUS +AcpiHwExtendedSleep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiHwExtendedWakePrep ( + UINT8 SleepState); + +ACPI_STATUS +AcpiHwExtendedWake ( + UINT8 SleepState); + + /* * hwvalid - Port I/O with validation */ @@ -188,22 +225,4 @@ AcpiHwDerivePciId ( ACPI_HANDLE PciRegion); -/* - * hwtimer - ACPI Timer prototypes - */ -ACPI_STATUS -AcpiGetTimerResolution ( - UINT32 *Resolution); - -ACPI_STATUS -AcpiGetTimer ( - UINT32 *Ticks); - -ACPI_STATUS -AcpiGetTimerDuration ( - UINT32 StartTicks, - UINT32 EndTicks, - UINT32 *TimeElapsed); - - #endif /* __ACHWARE_H__ */ diff --git a/sys/contrib/dev/acpica/include/acmacros.h b/sys/contrib/dev/acpica/include/acmacros.h index a0be136bf9be..cdb9cb109e06 100644 --- a/sys/contrib/dev/acpica/include/acmacros.h +++ b/sys/contrib/dev/acpica/include/acmacros.h @@ -428,7 +428,6 @@ #endif /* ACPI_SIMPLE_RETURN_MACROS */ - /* Conditional execution */ #define ACPI_DEBUG_EXEC(a) a @@ -477,6 +476,14 @@ #endif /* ACPI_DEBUG_OUTPUT */ + +#if (!ACPI_REDUCED_HARDWARE) +#define ACPI_HW_OPTIONAL_FUNCTION(addr) addr +#else +#define ACPI_HW_OPTIONAL_FUNCTION(addr) NULL +#endif + + /* * Some code only gets executed when the debugger is built in. * Note that this is entirely independent of whether the diff --git a/sys/contrib/dev/acpica/include/acpiosxf.h b/sys/contrib/dev/acpica/include/acpiosxf.h index 9a439aa79cbf..8106d8a8ecbe 100644 --- a/sys/contrib/dev/acpica/include/acpiosxf.h +++ b/sys/contrib/dev/acpica/include/acpiosxf.h @@ -112,6 +112,12 @@ AcpiOsTableOverride ( ACPI_TABLE_HEADER *ExistingTable, ACPI_TABLE_HEADER **NewTable); +ACPI_STATUS +AcpiOsPhysicalTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_PHYSICAL_ADDRESS *NewAddress, + UINT32 *NewTableLength); + /* * Spinlock primitives @@ -302,13 +308,13 @@ AcpiOsWritePort ( ACPI_STATUS AcpiOsReadMemory ( ACPI_PHYSICAL_ADDRESS Address, - UINT32 *Value, + UINT64 *Value, UINT32 Width); ACPI_STATUS AcpiOsWriteMemory ( ACPI_PHYSICAL_ADDRESS Address, - UINT32 Value, + UINT64 Value, UINT32 Width); diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h index 8618c79636f0..0eeb320a9637 100644 --- a/sys/contrib/dev/acpica/include/acpixf.h +++ b/sys/contrib/dev/acpica/include/acpixf.h @@ -48,8 +48,9 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20120111 +#define ACPI_CA_VERSION 0x20120215 +#include #include #include @@ -80,6 +81,34 @@ extern UINT8 AcpiGbl_TruncateIoAddresses; extern UINT8 AcpiGbl_DisableAutoRepair; +/* + * Hardware-reduced prototypes. All interfaces that use these macros will + * be configured out of the ACPICA build if the ACPI_REDUCED_HARDWARE flag + * is set to TRUE. + */ +#if (!ACPI_REDUCED_HARDWARE) +#define ACPI_HW_DEPENDENT_RETURN_STATUS(Prototype) \ + Prototype; + +#define ACPI_HW_DEPENDENT_RETURN_OK(Prototype) \ + Prototype; + +#define ACPI_HW_DEPENDENT_RETURN_VOID(Prototype) \ + Prototype; + +#else +#define ACPI_HW_DEPENDENT_RETURN_STATUS(Prototype) \ + static ACPI_INLINE Prototype {return(AE_NOT_CONFIGURED);} + +#define ACPI_HW_DEPENDENT_RETURN_OK(Prototype) \ + static ACPI_INLINE Prototype {return(AE_OK);} + +#define ACPI_HW_DEPENDENT_RETURN_VOID(Prototype) \ + static ACPI_INLINE Prototype {} + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* * Initialization */ @@ -109,13 +138,15 @@ AcpiTerminate ( /* * Miscellaneous global interfaces */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiEnable ( - void); + void)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiDisable ( - void); + void)) ACPI_STATUS AcpiSubsystemStatus ( @@ -321,35 +352,40 @@ AcpiInstallInitializationHandler ( ACPI_INIT_HANDLER Handler, UINT32 Function); +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiInstallGlobalEventHandler ( ACPI_GBL_EVENT_HANDLER Handler, - void *Context); + void *Context)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiInstallFixedEventHandler ( UINT32 AcpiEvent, ACPI_EVENT_HANDLER Handler, - void *Context); + void *Context)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiRemoveFixedEventHandler ( UINT32 AcpiEvent, - ACPI_EVENT_HANDLER Handler); + ACPI_EVENT_HANDLER Handler)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiInstallGpeHandler ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, UINT32 Type, ACPI_GPE_HANDLER Address, - void *Context); + void *Context)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiRemoveGpeHandler ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - ACPI_GPE_HANDLER Address); + ACPI_GPE_HANDLER Address)) ACPI_STATUS AcpiInstallNotifyHandler ( @@ -390,14 +426,16 @@ AcpiInstallInterfaceHandler ( /* * Global Lock interfaces */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiAcquireGlobalLock ( UINT16 Timeout, - UINT32 *Handle); + UINT32 *Handle)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiReleaseGlobalLock ( - UINT32 Handle); + UINT32 Handle)) /* @@ -418,100 +456,118 @@ AcpiReleaseMutex ( /* * Fixed Event interfaces */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiEnableEvent ( UINT32 Event, - UINT32 Flags); + UINT32 Flags)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiDisableEvent ( UINT32 Event, - UINT32 Flags); + UINT32 Flags)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiClearEvent ( - UINT32 Event); + UINT32 Event)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiGetEventStatus ( UINT32 Event, - ACPI_EVENT_STATUS *EventStatus); + ACPI_EVENT_STATUS *EventStatus)) /* * General Purpose Event (GPE) Interfaces */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiUpdateAllGpes ( - void); + void)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiEnableGpe ( ACPI_HANDLE GpeDevice, - UINT32 GpeNumber); + UINT32 GpeNumber)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiDisableGpe ( ACPI_HANDLE GpeDevice, - UINT32 GpeNumber); + UINT32 GpeNumber)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiClearGpe ( ACPI_HANDLE GpeDevice, - UINT32 GpeNumber); + UINT32 GpeNumber)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiSetGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT8 Action); + UINT8 Action)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiFinishGpe ( ACPI_HANDLE GpeDevice, - UINT32 GpeNumber); + UINT32 GpeNumber)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiSetupGpeForWake ( ACPI_HANDLE ParentDevice, ACPI_HANDLE GpeDevice, - UINT32 GpeNumber); + UINT32 GpeNumber)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiSetGpeWakeMask ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT8 Action); + UINT8 Action)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiGetGpeStatus ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - ACPI_EVENT_STATUS *EventStatus); + ACPI_EVENT_STATUS *EventStatus)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiDisableAllGpes ( - void); + void)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiEnableAllRuntimeGpes ( - void); + void)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiGetGpeDevice ( UINT32 GpeIndex, - ACPI_HANDLE *GpeDevice); + ACPI_HANDLE *GpeDevice)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiInstallGpeBlock ( ACPI_HANDLE GpeDevice, ACPI_GENERIC_ADDRESS *GpeBlockAddress, UINT32 RegisterCount, - UINT32 InterruptNumber); + UINT32 InterruptNumber)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiRemoveGpeBlock ( - ACPI_HANDLE GpeDevice); + ACPI_HANDLE GpeDevice)) /* @@ -590,16 +646,22 @@ AcpiWrite ( UINT64 Value, ACPI_GENERIC_ADDRESS *Reg); +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiReadBitRegister ( UINT32 RegisterId, - UINT32 *ReturnValue); + UINT32 *ReturnValue)) +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiWriteBitRegister ( UINT32 RegisterId, - UINT32 Value); + UINT32 Value)) + +/* + * Sleep/Wake interfaces + */ ACPI_STATUS AcpiGetSleepTypeData ( UINT8 SleepState, @@ -614,25 +676,53 @@ ACPI_STATUS AcpiEnterSleepState ( UINT8 SleepState); +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiEnterSleepStateS4bios ( - void); + void)) + +ACPI_STATUS +AcpiLeaveSleepStatePrep ( + UINT8 SleepState); ACPI_STATUS AcpiLeaveSleepState ( - UINT8 SleepState) - ; + UINT8 SleepState); + +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiSetFirmwareWakingVector ( - UINT32 PhysicalAddress); + UINT32 PhysicalAddress)) #if ACPI_MACHINE_WIDTH == 64 +ACPI_HW_DEPENDENT_RETURN_STATUS ( ACPI_STATUS AcpiSetFirmwareWakingVector64 ( - UINT64 PhysicalAddress); + UINT64 PhysicalAddress)) #endif +/* + * ACPI Timer interfaces + */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTimerResolution ( + UINT32 *Resolution)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTimer ( + UINT32 *Ticks)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTimerDuration ( + UINT32 StartTicks, + UINT32 EndTicks, + UINT32 *TimeElapsed)) + + /* * Error/Warning output */ diff --git a/sys/contrib/dev/acpica/include/actables.h b/sys/contrib/dev/acpica/include/actables.h index 4277ff5e9ba1..26a7947dc97b 100644 --- a/sys/contrib/dev/acpica/include/actables.h +++ b/sys/contrib/dev/acpica/include/actables.h @@ -84,6 +84,11 @@ ACPI_STATUS AcpiTbVerifyTable ( ACPI_TABLE_DESC *TableDesc); +ACPI_TABLE_HEADER * +AcpiTbTableOverride ( + ACPI_TABLE_HEADER *TableHeader, + ACPI_TABLE_DESC *TableDesc); + ACPI_STATUS AcpiTbAddTable ( ACPI_TABLE_DESC *TableDesc, diff --git a/sys/contrib/dev/acpica/include/actbl.h b/sys/contrib/dev/acpica/include/actbl.h index 35e2ffbb22f9..23897a73ac4e 100644 --- a/sys/contrib/dev/acpica/include/actbl.h +++ b/sys/contrib/dev/acpica/include/actbl.h @@ -354,6 +354,13 @@ enum AcpiPreferedPmProfiles PM_TABLET = 8 }; +/* Values for SleepStatus and SleepControl registers (V5 FADT) */ + +#define ACPI_X_WAKE_STATUS 0x80 +#define ACPI_X_SLEEP_TYPE_MASK 0x1C +#define ACPI_X_SLEEP_TYPE_POSITION 0x02 +#define ACPI_X_SLEEP_ENABLE 0x20 + /* Reset to default packing */ diff --git a/sys/contrib/dev/acpica/include/actypes.h b/sys/contrib/dev/acpica/include/actypes.h index 2d78c0b962d3..30d9088b8eb4 100644 --- a/sys/contrib/dev/acpica/include/actypes.h +++ b/sys/contrib/dev/acpica/include/actypes.h @@ -534,8 +534,9 @@ typedef UINT64 ACPI_INTEGER; #define ACPI_NOTIFY_DEVICE_PLD_CHECK (UINT8) 0x09 #define ACPI_NOTIFY_RESERVED (UINT8) 0x0A #define ACPI_NOTIFY_LOCALITY_UPDATE (UINT8) 0x0B +#define ACPI_NOTIFY_SHUTDOWN_REQUEST (UINT8) 0x0C -#define ACPI_NOTIFY_MAX 0x0B +#define ACPI_NOTIFY_MAX 0x0C /* * Types associated with ACPI names and objects. The first group of @@ -701,7 +702,8 @@ typedef UINT32 ACPI_EVENT_STATUS; #define ACPI_ALL_NOTIFY (ACPI_SYSTEM_NOTIFY | ACPI_DEVICE_NOTIFY) #define ACPI_MAX_NOTIFY_HANDLER_TYPE 0x3 -#define ACPI_MAX_SYS_NOTIFY 0x7f +#define ACPI_MAX_SYS_NOTIFY 0x7F +#define ACPI_MAX_DEVICE_SPECIFIC_NOTIFY 0xBF /* Address Space (Operation Region) Types */ @@ -792,6 +794,19 @@ typedef UINT8 ACPI_ADR_SPACE_TYPE; #define ACPI_DISABLE_EVENT 0 +/* Sleep function dispatch */ + +typedef ACPI_STATUS (*ACPI_SLEEP_FUNCTION) ( + UINT8 SleepState); + +typedef struct acpi_sleep_functions +{ + ACPI_SLEEP_FUNCTION LegacyFunction; + ACPI_SLEEP_FUNCTION ExtendedFunction; + +} ACPI_SLEEP_FUNCTIONS; + + /* * External ACPI object definition */ diff --git a/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c b/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c index 07d84738af2c..189bfcdd9551 100644 --- a/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c +++ b/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c @@ -212,6 +212,33 @@ AcpiOsTableOverride ( } +/****************************************************************************** + * + * FUNCTION: AcpiOsPhysicalTableOverride + * + * PARAMETERS: ExistingTable - Header of current table (probably firmware) + * NewAddress - Where new table address is returned + * (Physical address) + * NewTableLength - Where new table length is returned + * + * RETURN: Status, address/length of new table. Null pointer returned + * if no table is available to override. + * + * DESCRIPTION: Returns AE_SUPPORT, function not used in user space. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsPhysicalTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_PHYSICAL_ADDRESS *NewAddress, + UINT32 *NewTableLength) +{ + + return (AE_SUPPORT); +} + + /****************************************************************************** * * FUNCTION: AcpiOsRedirectOutput @@ -1017,9 +1044,10 @@ AcpiOsWritePort ( * * PARAMETERS: Address - Physical Memory Address to read * Value - Where value is placed - * Width - Number of bits + * Width - Number of bits (8,16,32, or 64) * - * RETURN: Value read from physical memory address + * RETURN: Value read from physical memory address. Always returned + * as a 64-bit integer, regardless of the read width. * * DESCRIPTION: Read data from a physical memory address * @@ -1028,7 +1056,7 @@ AcpiOsWritePort ( ACPI_STATUS AcpiOsReadMemory ( ACPI_PHYSICAL_ADDRESS Address, - UINT32 *Value, + UINT64 *Value, UINT32 Width) { @@ -1037,6 +1065,7 @@ AcpiOsReadMemory ( case 8: case 16: case 32: + case 64: *Value = 0; break; @@ -1053,7 +1082,7 @@ AcpiOsReadMemory ( * * PARAMETERS: Address - Physical Memory Address to write * Value - Value to write - * Width - Number of bits + * Width - Number of bits (8,16,32, or 64) * * RETURN: None * @@ -1064,7 +1093,7 @@ AcpiOsReadMemory ( ACPI_STATUS AcpiOsWriteMemory ( ACPI_PHYSICAL_ADDRESS Address, - UINT32 Value, + UINT64 Value, UINT32 Width) { diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index 68854ae885e1..9f315b6307b7 100644 --- a/sys/dev/aac/aac.c +++ b/sys/dev/aac/aac.c @@ -291,6 +291,15 @@ aac_attach(struct aac_softc *sc) */ aac_describe_controller(sc); + /* + * Add sysctls. + */ + SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->aac_dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(sc->aac_dev)), + OID_AUTO, "firmware_build", CTLFLAG_RD, + &sc->aac_revision.buildNumber, 0, + "firmware build number"); + /* * Register to probe our containers later. */ diff --git a/sys/dev/acpica/Osd/OsdMemory.c b/sys/dev/acpica/Osd/OsdMemory.c index 615c4b54408a..b806642a61fc 100644 --- a/sys/dev/acpica/Osd/OsdMemory.c +++ b/sys/dev/acpica/Osd/OsdMemory.c @@ -87,7 +87,7 @@ AcpiOsWritable (void *Pointer, ACPI_SIZE Length) } ACPI_STATUS -AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value, UINT32 Width) +AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width) { void *LogicalAddress; @@ -105,6 +105,9 @@ AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value, UINT32 Width) case 32: *Value = *(volatile uint32_t *)LogicalAddress; break; + case 64: + *Value = *(volatile uint64_t *)LogicalAddress; + break; } pmap_unmapdev((vm_offset_t)LogicalAddress, Width / 8); @@ -113,7 +116,7 @@ AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 *Value, UINT32 Width) } ACPI_STATUS -AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 Value, UINT32 Width) +AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width) { void *LogicalAddress; @@ -131,6 +134,9 @@ AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT32 Value, UINT32 Width) case 32: *(volatile uint32_t *)LogicalAddress = Value; break; + case 64: + *(volatile uint64_t *)LogicalAddress = Value; + break; } pmap_unmapdev((vm_offset_t)LogicalAddress, Width / 8); diff --git a/sys/dev/acpica/Osd/OsdSynch.c b/sys/dev/acpica/Osd/OsdSynch.c index 84e331c18061..dedfa6e0a724 100644 --- a/sys/dev/acpica/Osd/OsdSynch.c +++ b/sys/dev/acpica/Osd/OsdSynch.c @@ -566,11 +566,8 @@ AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags) } /* Section 5.2.10.1: global lock acquire/release functions */ -#define GL_ACQUIRED (-1) -#define GL_BUSY 0 #define GL_BIT_PENDING 0x01 #define GL_BIT_OWNED 0x02 -#define GL_BIT_MASK (GL_BIT_PENDING | GL_BIT_OWNED) /* * Acquire the global lock. If busy, set the pending bit. The caller @@ -584,11 +581,12 @@ acpi_acquire_global_lock(uint32_t *lock) do { old = *lock; - new = ((old & ~GL_BIT_MASK) | GL_BIT_OWNED) | - ((old >> 1) & GL_BIT_PENDING); + new = (old & ~GL_BIT_PENDING) | GL_BIT_OWNED; + if ((old & GL_BIT_OWNED) != 0) + new |= GL_BIT_PENDING; } while (atomic_cmpset_acq_int(lock, old, new) == 0); - return ((new < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY); + return ((new & GL_BIT_PENDING) == 0); } /* @@ -603,8 +601,8 @@ acpi_release_global_lock(uint32_t *lock) do { old = *lock; - new = old & ~GL_BIT_MASK; + new = old & ~(GL_BIT_PENDING | GL_BIT_OWNED); } while (atomic_cmpset_rel_int(lock, old, new) == 0); - return (old & GL_BIT_PENDING); + return ((old & GL_BIT_PENDING) != 0); } diff --git a/sys/dev/acpica/Osd/OsdTable.c b/sys/dev/acpica/Osd/OsdTable.c index def88c6be262..da220e5c5f2b 100644 --- a/sys/dev/acpica/Osd/OsdTable.c +++ b/sys/dev/acpica/Osd/OsdTable.c @@ -96,3 +96,11 @@ AcpiOsTableOverride(ACPI_TABLE_HEADER *ExistingTable, return (AE_OK); } + +ACPI_STATUS +AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExistingTable, + ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength) +{ + + return (AE_SUPPORT); +} diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index bff74fba9333..fc5fec132f77 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -152,6 +152,7 @@ static ACPI_STATUS acpi_EnterSleepState(struct acpi_softc *sc, int state); static void acpi_shutdown_final(void *arg, int howto); static void acpi_enable_fixed_events(struct acpi_softc *sc); static BOOLEAN acpi_has_hid(ACPI_HANDLE handle); +static void acpi_resync_clock(struct acpi_softc *sc); static int acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate); static int acpi_wake_run_prep(ACPI_HANDLE handle, int sstate); static int acpi_wake_prep_walk(int sstate); @@ -277,11 +278,13 @@ TUNABLE_INT("debug.acpi.interpreter_slack", &acpi_interpreter_slack); SYSCTL_INT(_debug_acpi, OID_AUTO, interpreter_slack, CTLFLAG_RDTUN, &acpi_interpreter_slack, 1, "Turn on interpreter slack mode."); +#ifdef __amd64__ /* Reset system clock while resuming. XXX Remove once tested. */ static int acpi_reset_clock = 1; TUNABLE_INT("debug.acpi.reset_clock", &acpi_reset_clock); SYSCTL_INT(_debug_acpi, OID_AUTO, reset_clock, CTLFLAG_RW, &acpi_reset_clock, 1, "Reset system clock while resuming."); +#endif /* Allow users to override quirks. */ TUNABLE_INT("debug.acpi.quirks", &acpi_quirks); @@ -1812,23 +1815,29 @@ acpi_probe_children(device_t bus) static void acpi_probe_order(ACPI_HANDLE handle, int *order) { - ACPI_OBJECT_TYPE type; + ACPI_OBJECT_TYPE type; - /* - * 1. CPUs - * 2. I/O port and memory system resource holders - * 3. Embedded controllers (to handle early accesses) - * 4. PCI Link Devices - */ - AcpiGetType(handle, &type); - if (type == ACPI_TYPE_PROCESSOR) - *order = 1; - else if (acpi_MatchHid(handle, "PNP0C01") || acpi_MatchHid(handle, "PNP0C02")) - *order = 2; - else if (acpi_MatchHid(handle, "PNP0C09")) - *order = 3; - else if (acpi_MatchHid(handle, "PNP0C0F")) - *order = 4; + /* + * 0. CPUs + * 1. I/O port and memory system resource holders + * 2. Clocks and timers (to handle early accesses) + * 3. Embedded controllers (to handle early accesses) + * 4. PCI Link Devices + */ + AcpiGetType(handle, &type); + if (type == ACPI_TYPE_PROCESSOR) + *order = 0; + else if (acpi_MatchHid(handle, "PNP0C01") || + acpi_MatchHid(handle, "PNP0C02")) + *order = 1; + else if (acpi_MatchHid(handle, "PNP0100") || + acpi_MatchHid(handle, "PNP0103") || + acpi_MatchHid(handle, "PNP0B00")) + *order = 2; + else if (acpi_MatchHid(handle, "PNP0C09")) + *order = 3; + else if (acpi_MatchHid(handle, "PNP0C0F")) + *order = 4; } /* @@ -1889,7 +1898,7 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status) * resources). */ ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "scanning '%s'\n", handle_str)); - order = level * 10 + 100; + order = level * 10 + ACPI_DEV_BASE_ORDER; acpi_probe_order(handle, &order); child = BUS_ADD_CHILD(bus, order, NULL, -1); if (child == NULL) @@ -2706,7 +2715,8 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state) DELAY(sc->acpi_sleep_delay * 1000000); if (state != ACPI_STATE_S1) { - acpi_sleep_machdep(sc, state); + if (acpi_sleep_machdep(sc, state)) + goto backout; /* Re-enable ACPI hardware on wakeup from sleep state 4. */ if (state == ACPI_STATE_S4) @@ -2731,12 +2741,16 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state) acpi_wake_prep_walk(state); sc->acpi_sstate = ACPI_STATE_S0; } - if (slp_state >= ACPI_SS_SLP_PREP) + if (slp_state >= ACPI_SS_SLP_PREP) { + AcpiLeaveSleepStatePrep(state); AcpiLeaveSleepState(state); + } if (slp_state >= ACPI_SS_DEV_SUSPEND) DEVICE_RESUME(root_bus); - if (slp_state >= ACPI_SS_SLEPT) + if (slp_state >= ACPI_SS_SLEPT) { + acpi_resync_clock(sc); acpi_enable_fixed_events(sc); + } sc->acpi_next_sstate = 0; mtx_unlock(&Giant); @@ -2759,10 +2773,10 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state) return_ACPI_STATUS (status); } -void +static void acpi_resync_clock(struct acpi_softc *sc) { - +#ifdef __amd64__ if (!acpi_reset_clock) return; @@ -2772,6 +2786,7 @@ acpi_resync_clock(struct acpi_softc *sc) (void)timecounter->tc_get_timecount(timecounter); (void)timecounter->tc_get_timecount(timecounter); inittodr(time_second + sc->acpi_sleep_delay); +#endif } /* Enable or disable the device's wake GPE. */ diff --git a/sys/dev/acpica/acpi_ec.c b/sys/dev/acpica/acpi_ec.c index 5c71d3d492ba..f8af33c454b2 100644 --- a/sys/dev/acpica/acpi_ec.c +++ b/sys/dev/acpica/acpi_ec.c @@ -295,7 +295,7 @@ acpi_ec_ecdt_probe(device_t parent) } /* Create the child device with the given unit number. */ - child = BUS_ADD_CHILD(parent, 0, "acpi_ec", ecdt->Uid); + child = BUS_ADD_CHILD(parent, 3, "acpi_ec", ecdt->Uid); if (child == NULL) { printf("%s: can't add child\n", __func__); return; diff --git a/sys/dev/acpica/acpi_hpet.c b/sys/dev/acpica/acpi_hpet.c index 134a86afe73a..2fa7122173c5 100644 --- a/sys/dev/acpica/acpi_hpet.c +++ b/sys/dev/acpica/acpi_hpet.c @@ -342,7 +342,7 @@ hpet_identify(driver_t *driver, device_t parent) if (found) continue; /* If not - create it from table info. */ - child = BUS_ADD_CHILD(parent, ACPI_DEV_BASE_ORDER, "hpet", 0); + child = BUS_ADD_CHILD(parent, 2, "hpet", 0); if (child == NULL) { printf("%s: can't add child\n", __func__); continue; diff --git a/sys/dev/acpica/acpi_timer.c b/sys/dev/acpica/acpi_timer.c index 17416838e9e4..9f61cd8cff2d 100644 --- a/sys/dev/acpica/acpi_timer.c +++ b/sys/dev/acpica/acpi_timer.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include #include +#include #include #include #include @@ -60,12 +61,15 @@ static device_t acpi_timer_dev; static struct resource *acpi_timer_reg; static bus_space_handle_t acpi_timer_bsh; static bus_space_tag_t acpi_timer_bst; +static eventhandler_tag acpi_timer_eh; static u_int acpi_timer_frequency = 14318182 / 4; static void acpi_timer_identify(driver_t *driver, device_t parent); static int acpi_timer_probe(device_t dev); static int acpi_timer_attach(device_t dev); +static void acpi_timer_resume_handler(struct timecounter *); +static void acpi_timer_suspend_handler(struct timecounter *); static u_int acpi_timer_get_timecount(struct timecounter *tc); static u_int acpi_timer_get_timecount_safe(struct timecounter *tc); static int acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS); @@ -124,7 +128,7 @@ acpi_timer_identify(driver_t *driver, device_t parent) acpi_timer_dev) return_VOID; - if ((dev = BUS_ADD_CHILD(parent, 0, "acpi_timer", 0)) == NULL) { + if ((dev = BUS_ADD_CHILD(parent, 2, "acpi_timer", 0)) == NULL) { device_printf(parent, "could not add acpi_timer0\n"); return_VOID; } @@ -244,9 +248,60 @@ acpi_timer_attach(device_t dev) return (ENXIO); acpi_timer_bsh = rman_get_bushandle(acpi_timer_reg); acpi_timer_bst = rman_get_bustag(acpi_timer_reg); + + /* Register suspend event handler. */ + if (EVENTHANDLER_REGISTER(power_suspend, acpi_timer_suspend_handler, + &acpi_timer_timecounter, EVENTHANDLER_PRI_LAST) == NULL) + device_printf(dev, "failed to register suspend event handler\n"); + return (0); } +static void +acpi_timer_resume_handler(struct timecounter *newtc) +{ + struct timecounter *tc; + + tc = timecounter; + if (tc != newtc) { + if (bootverbose) + device_printf(acpi_timer_dev, + "restoring timecounter, %s -> %s\n", + tc->tc_name, newtc->tc_name); + (void)newtc->tc_get_timecount(newtc); + (void)newtc->tc_get_timecount(newtc); + timecounter = newtc; + } +} + +static void +acpi_timer_suspend_handler(struct timecounter *newtc) +{ + struct timecounter *tc; + + /* Deregister existing resume event handler. */ + if (acpi_timer_eh != NULL) { + EVENTHANDLER_DEREGISTER(power_resume, acpi_timer_eh); + acpi_timer_eh = NULL; + } + + KASSERT(newtc == &acpi_timer_timecounter, + ("acpi_timer_suspend_handler: wrong timecounter")); + + tc = timecounter; + if (tc != newtc) { + if (bootverbose) + device_printf(acpi_timer_dev, + "switching timecounter, %s -> %s\n", + tc->tc_name, newtc->tc_name); + (void)acpi_timer_read(); + (void)acpi_timer_read(); + timecounter = newtc; + acpi_timer_eh = EVENTHANDLER_REGISTER(power_resume, + acpi_timer_resume_handler, tc, EVENTHANDLER_PRI_LAST); + } +} + /* * Fetch current time value from reliable hardware. */ diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 19f8ca4fc7d3..c05859b26f46 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -339,7 +339,6 @@ ACPI_STATUS acpi_SetIntrModel(int model); int acpi_ReqSleepState(struct acpi_softc *sc, int state); int acpi_AckSleepState(struct apm_clone_data *clone, int error); ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state); -void acpi_resync_clock(struct acpi_softc *sc); int acpi_wake_set_enable(device_t dev, int enable); int acpi_parse_prw(ACPI_HANDLE h, struct acpi_prw_data *prw); ACPI_STATUS acpi_Startup(void); @@ -473,7 +472,7 @@ ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj); * probe order sorted so that things like sysresource are available before * their children need them. */ -#define ACPI_DEV_BASE_ORDER 10 +#define ACPI_DEV_BASE_ORDER 100 /* Default maximum number of tasks to enqueue. */ #ifndef ACPI_MAX_TASKS diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c index 27fbf7f4792a..a58423be9d7e 100644 --- a/sys/dev/ata/ata-queue.c +++ b/sys/dev/ata/ata-queue.c @@ -112,6 +112,7 @@ ata_queue_request(struct ata_request *request) ATA_DEBUG_RQ(request, "wait for completion"); if (!dumping && sema_timedwait(&request->done, request->timeout * hz * 4)) { + callout_drain(&request->callout); device_printf(request->dev, "WARNING - %s taskqueue timeout " "- completing request directly\n", diff --git a/sys/dev/ath/ath_dfs/null/dfs_null.c b/sys/dev/ath/ath_dfs/null/dfs_null.c index f10b0109b2a0..a8aabb4018b2 100644 --- a/sys/dev/ath/ath_dfs/null/dfs_null.c +++ b/sys/dev/ath/ath_dfs/null/dfs_null.c @@ -70,6 +70,28 @@ __FBSDID("$FreeBSD$"); #include +/* + * These are default parameters for the AR5416 and + * later 802.11n NICs. They simply enable some + * radar pulse event generation. + * + * These are very likely not valid for the AR5212 era + * NICs. + * + * Since these define signal sizing and threshold + * parameters, they may need changing based on the + * specific antenna and receive amplifier + * configuration. + */ +#define AR5416_DFS_FIRPWR -33 +#define AR5416_DFS_RRSSI 20 +#define AR5416_DFS_HEIGHT 10 +#define AR5416_DFS_PRSSI 15 +#define AR5416_DFS_INBAND 15 +#define AR5416_DFS_RELPWR 8 +#define AR5416_DFS_RELSTEP 12 +#define AR5416_DFS_MAXLEN 255 + /* * Methods which are required */ @@ -98,16 +120,45 @@ ath_dfs_detach(struct ath_softc *sc) int ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan) { +#if 0 + HAL_PHYERR_PARAM pe; + /* Check if the current channel is radar-enabled */ if (! IEEE80211_IS_CHAN_DFS(chan)) return (0); + /* Enable radar PHY error reporting */ + sc->sc_dodfs = 1; + /* - * Enabling the radar parameters and setting sc->sc_dodfs = 1 - * would occur here. + * These are general examples of the parameter values + * to use when configuring radar pulse detection for + * the AR5416, AR91xx, AR92xx NICs. They are only + * for testing and do require tuning depending upon the + * hardware and deployment specifics. */ + pe.pe_firpwr = AR5416_DFS_FIRPWR; + pe.pe_rrssi = AR5416_DFS_RRSSI; + pe.pe_height = AR5416_DFS_HEIGHT; + pe.pe_prssi = AR5416_DFS_PRSSI; + pe.pe_inband = AR5416_DFS_INBAND; + pe.pe_relpwr = AR5416_DFS_RELPWR; + pe.pe_relstep = AR5416_DFS_RELSTEP; + pe.pe_maxlen = AR5416_DFS_MAXLEN; + pe.pe_enabled = 1; + + /* Flip on extension channel events only if doing HT40 */ + if (IEEE80211_IS_CHAN_HT40(chan)) + pe.pe_extchannel = 1; + else + pe.pe_extchannel = 0; + + ath_hal_enabledfs(sc->sc_ah, &pe); return (1); +#else + return (0); +#endif } /* diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h index 5c373f0d0f0a..55e0f2b8b8ed 100644 --- a/sys/dev/ath/ath_hal/ah.h +++ b/sys/dev/ath/ath_hal/ah.h @@ -733,10 +733,11 @@ typedef struct { */ int32_t pe_extchannel; /* Enable DFS on ext channel */ int32_t pe_enabled; /* Whether radar detection is enabled */ + int32_t pe_enrelpwr; + int32_t pe_en_relstep_check; } HAL_PHYERR_PARAM; #define HAL_PHYERR_PARAM_NOVAL 65535 -#define HAL_PHYERR_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */ /* * DFS operating mode flags. diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h index 5006c313e7ee..7099b56abb24 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h @@ -207,6 +207,9 @@ extern HAL_STATUS ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); extern HAL_STATUS ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result); +extern HAL_BOOL ar5416SetCapability(struct ath_hal *ah, + HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t val, + HAL_STATUS *status); extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request, const void *args, uint32_t argsize, void **result, uint32_t *resultsize); diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index 83fc3138e0ec..059799ef4add 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -129,6 +129,7 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, /* Misc Functions */ ah->ah_getCapability = ar5416GetCapability; + ah->ah_setCapability = ar5416SetCapability; ah->ah_getDiagState = ar5416GetDiagState; ah->ah_setLedState = ar5416SetLedState; ah->ah_gpioCfgOutput = ar5416GpioCfgOutput; @@ -884,6 +885,7 @@ ar5416FillCapabilityInfo(struct ath_hal *ah) /* AR5416 may have 3 antennas but is a 2x2 stream device */ pCap->halTxStreams = 2; pCap->halRxStreams = 2; + /* * If the TX or RX chainmask has less than 2 chains active, * mark it as a 1-stream device for the relevant stream. diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c index 4df10cdd4f1a..eb7f797a9ee9 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c @@ -27,6 +27,8 @@ #include "ar5416/ar5416reg.h" #include "ar5416/ar5416phy.h" +#include "ah_eeprom_v14.h" /* for owl_get_ntxchains() */ + /* * Return the wireless modes (a,b,g,n,t) supported by hardware. * @@ -430,6 +432,35 @@ ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, return ar5212GetCapability(ah, type, capability, result); } +HAL_BOOL +ar5416SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, + u_int32_t capability, u_int32_t setting, HAL_STATUS *status) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + switch (type) { + case HAL_CAP_RX_CHAINMASK: + setting &= ath_hal_eepromGet(ah, AR_EEP_RXMASK, NULL); + pCap->halRxChainMask = setting; + if (owl_get_ntxchains(setting) > 2) + pCap->halRxStreams = 2; + else + pCap->halRxStreams = 1; + return HAL_OK; + case HAL_CAP_TX_CHAINMASK: + setting &= ath_hal_eepromGet(ah, AR_EEP_TXMASK, NULL); + pCap->halTxChainMask = setting; + if (owl_get_ntxchains(setting) > 2) + pCap->halTxStreams = 2; + else + pCap->halTxStreams = 1; + return HAL_OK; + default: + break; + } + return ar5212SetCapability(ah, type, capability, setting, status); +} + static int ar5416DetectMacHang(struct ath_hal *ah); static int ar5416DetectBBHang(struct ath_hal *ah); @@ -709,19 +740,12 @@ ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); + /* RADAR_1 values */ val = OS_REG_READ(ah, AR_PHY_RADAR_1); - temp = val & AR_PHY_RADAR_1_RELPWR_ENA; pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH); - if (temp) - pe->pe_relpwr |= HAL_PHYERR_PARAM_ENABLE; - temp = val & AR_PHY_RADAR_1_RELSTEP_CHECK; pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH); - if (temp) - pe->pe_enabled = 1; - else - pe->pe_enabled = 0; - pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN); + pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) & AR_PHY_RADAR_EXT_ENA); @@ -731,6 +755,12 @@ ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) AR_PHY_RADAR_1_BLOCK_CHECK); pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & AR_PHY_RADAR_1_MAX_RRSSI); + pe->pe_enabled = !! + (OS_REG_READ(ah, AR_PHY_RADAR_0) & AR_PHY_RADAR_0_ENA); + pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_RELPWR_ENA); + pe->pe_en_relstep_check = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) & + AR_PHY_RADAR_1_RELSTEP_CHECK); } /* @@ -767,13 +797,18 @@ ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) /*Enable FFT data*/ val |= AR_PHY_RADAR_0_FFT_ENA; + OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); - OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA); + /* Implicitly enable */ + if (pe->pe_enabled == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); + else if (pe->pe_enabled == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); if (pe->pe_usefir128 == 1) - OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); - else if (pe->pe_usefir128 == 0) OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); + else if (pe->pe_usefir128 == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128); if (pe->pe_enmaxrssi == 1) OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI); @@ -785,6 +820,33 @@ ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) else if (pe->pe_blockradar == 0) OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK); + if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; + val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); + OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); + } + if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { + val = OS_REG_READ(ah, AR_PHY_RADAR_1); + val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; + val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); + OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); + } + + if (pe->pe_en_relstep_check == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, + AR_PHY_RADAR_1_RELSTEP_CHECK); + else if (pe->pe_en_relstep_check == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, + AR_PHY_RADAR_1_RELSTEP_CHECK); + + if (pe->pe_enrelpwr == 1) + OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, + AR_PHY_RADAR_1_RELPWR_ENA); + else if (pe->pe_enrelpwr == 0) + OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, + AR_PHY_RADAR_1_RELPWR_ENA); + if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) { val = OS_REG_READ(ah, AR_PHY_RADAR_1); val &= ~AR_PHY_RADAR_1_MAXLEN; @@ -801,19 +863,6 @@ ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); else if (pe->pe_extchannel == 0) OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); - - if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { - val = OS_REG_READ(ah, AR_PHY_RADAR_1); - val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; - val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); - OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); - } - if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { - val = OS_REG_READ(ah, AR_PHY_RADAR_1); - val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; - val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); - OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); - } } /* diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 6740332730e3..51318ef74d62 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -284,6 +284,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) int error = 0, i; u_int wmodes; uint8_t macaddr[IEEE80211_ADDR_LEN]; + int rx_chainmask, tx_chainmask; DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid); @@ -633,6 +634,29 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) } #endif + /* + * Allow the TX and RX chainmasks to be overridden by + * environment variables and/or device.hints. + * + * This must be done early - before the hardware is + * calibrated or before the 802.11n stream calculation + * is done. + */ + if (resource_int_value(device_get_name(sc->sc_dev), + device_get_unit(sc->sc_dev), "rx_chainmask", + &rx_chainmask) == 0) { + device_printf(sc->sc_dev, "Setting RX chainmask to 0x%x\n", + rx_chainmask); + (void) ath_hal_setrxchainmask(sc->sc_ah, rx_chainmask); + } + if (resource_int_value(device_get_name(sc->sc_dev), + device_get_unit(sc->sc_dev), "tx_chainmask", + &tx_chainmask) == 0) { + device_printf(sc->sc_dev, "Setting TX chainmask to 0x%x\n", + tx_chainmask); + (void) ath_hal_settxchainmask(sc->sc_ah, tx_chainmask); + } + /* * The if_ath 11n support is completely not ready for normal use. * Enabling this option will likely break everything and everything. @@ -1645,6 +1669,7 @@ ath_bmiss_vap(struct ieee80211vap *vap) struct ath_softc *sc = ifp->if_softc; u_int64_t lastrx = sc->sc_lastrx; u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah); + /* XXX should take a locked ref to iv_bss */ u_int bmisstimeout = vap->iv_bmissthreshold * vap->iv_bss->ni_intval * 1024; @@ -3221,7 +3246,7 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) if (vap == NULL) vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */ - ni = vap->iv_bss; + ni = ieee80211_ref_node(vap->iv_bss); /* extract tstamp from last beacon and convert to TU */ nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4), @@ -3391,6 +3416,7 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) ath_beacon_start_adhoc(sc, vap); } sc->sc_syncbeacon = 0; + ieee80211_free_node(ni); #undef FUDGE #undef TSF_TO_TU } @@ -3829,6 +3855,7 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, switch (subtype) { case IEEE80211_FC0_SUBTYPE_BEACON: /* update rssi statistics for use by the hal */ + /* XXX unlocked check against vap->iv_bss? */ ATH_RSSI_LPF(sc->sc_halstats.ns_avgbrssi, rssi); if (sc->sc_syncbeacon && ni == vap->iv_bss && vap->iv_state == IEEE80211_S_RUN) { @@ -5697,7 +5724,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) taskqueue_unblock(sc->sc_tq); } - ni = vap->iv_bss; + ni = ieee80211_ref_node(vap->iv_bss); rfilt = ath_calcrxfilter(sc); stamode = (vap->iv_opmode == IEEE80211_M_STA || vap->iv_opmode == IEEE80211_M_AHDEMO || @@ -5728,7 +5755,8 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) if (nstate == IEEE80211_S_RUN) { /* NB: collect bss node again, it may have changed */ - ni = vap->iv_bss; + ieee80211_free_node(ni); + ni = ieee80211_ref_node(vap->iv_bss); DPRINTF(sc, ATH_DEBUG_STATE, "%s(RUN): iv_flags 0x%08x bintvl %d bssid %s " @@ -5851,6 +5879,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) #endif } bad: + ieee80211_free_node(ni); return error; } @@ -5869,6 +5898,7 @@ ath_setup_stationkey(struct ieee80211_node *ni) struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; ieee80211_keyix keyix, rxkeyix; + /* XXX should take a locked ref to vap->iv_bss */ if (!ath_key_alloc(vap, &ni->ni_ucastkey, &keyix, &rxkeyix)) { /* * Key cache is full; we'll fall back to doing @@ -6424,6 +6454,7 @@ ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap) return; } } + /* XXX should take a locked ref to iv_bss */ tp = vap->iv_bss->ni_txparms; /* * Calculate the guard time for each slot. This is the @@ -6673,6 +6704,7 @@ ath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap) * Record local TSF for our last send for use * in arbitrating slot collisions. */ + /* XXX should take a locked ref to iv_bss */ vap->iv_bss->ni_tstamp.tsf = ath_hal_gettsf64(ah); } } diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index a6d919648d49..919ecec9ef65 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -888,6 +888,10 @@ void ath_intr(void *); (ath_hal_getcapability(_ah, HAL_CAP_RX_CHAINMASK, 0, _prxchainmask)) #define ath_hal_gettxchainmask(_ah, _ptxchainmask) \ (ath_hal_getcapability(_ah, HAL_CAP_TX_CHAINMASK, 0, _ptxchainmask)) +#define ath_hal_setrxchainmask(_ah, _rx) \ + (ath_hal_setcapability(_ah, HAL_CAP_RX_CHAINMASK, 1, _rx, NULL)) +#define ath_hal_settxchainmask(_ah, _tx) \ + (ath_hal_setcapability(_ah, HAL_CAP_TX_CHAINMASK, 1, _tx, NULL)) #define ath_hal_split4ktrans(_ah) \ (ath_hal_getcapability(_ah, HAL_CAP_SPLIT_4KB_TRANS, \ 0, NULL) == HAL_OK) diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index 4329a8d23cf7..d74577733c18 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -2786,6 +2786,8 @@ bge_attach(device_t dev) sc = device_get_softc(dev); sc->bge_dev = dev; + bge_add_sysctls(sc); + TASK_INIT(&sc->bge_intr_task, 0, bge_intr_task, sc); /* @@ -3198,8 +3200,6 @@ bge_attach(device_t dev) goto fail; } - bge_add_sysctls(sc); - /* Set default tuneable values. */ sc->bge_stat_ticks = BGE_TICKS_PER_SEC; sc->bge_rx_coal_ticks = 150; diff --git a/sys/dev/cxgb/cxgb_adapter.h b/sys/dev/cxgb/cxgb_adapter.h index 511b4700a0e3..ed75e7888b9d 100644 --- a/sys/dev/cxgb/cxgb_adapter.h +++ b/sys/dev/cxgb/cxgb_adapter.h @@ -572,5 +572,4 @@ static inline int offload_running(adapter_t *adapter) void cxgb_tx_watchdog(void *arg); int cxgb_transmit(struct ifnet *ifp, struct mbuf *m); void cxgb_qflush(struct ifnet *ifp); -void cxgb_start(struct ifnet *ifp); #endif diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c index c5d46a04046c..fb420044901f 100644 --- a/sys/dev/cxgb/cxgb_main.c +++ b/sys/dev/cxgb/cxgb_main.c @@ -227,14 +227,6 @@ TUNABLE_INT("hw.cxgb.use_16k_clusters", &cxgb_use_16k_clusters); SYSCTL_INT(_hw_cxgb, OID_AUTO, use_16k_clusters, CTLFLAG_RDTUN, &cxgb_use_16k_clusters, 0, "use 16kB clusters for the jumbo queue "); -/* - * Tune the size of the output queue. - */ -int cxgb_snd_queue_len = IFQ_MAXLEN; -TUNABLE_INT("hw.cxgb.snd_queue_len", &cxgb_snd_queue_len); -SYSCTL_INT(_hw_cxgb, OID_AUTO, snd_queue_len, CTLFLAG_RDTUN, - &cxgb_snd_queue_len, 0, "send queue size "); - static int nfilters = -1; TUNABLE_INT("hw.cxgb.nfilters", &nfilters); SYSCTL_INT(_hw_cxgb, OID_AUTO, nfilters, CTLFLAG_RDTUN, @@ -481,15 +473,6 @@ cxgb_controller_attach(device_t dev) device_printf(dev, "Cannot allocate BAR region 0\n"); return (ENXIO); } - sc->udbs_rid = PCIR_BAR(2); - sc->udbs_res = NULL; - if (is_offload(sc) && - ((sc->udbs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->udbs_rid, RF_ACTIVE)) == NULL)) { - device_printf(dev, "Cannot allocate BAR region 1\n"); - error = ENXIO; - goto out; - } snprintf(sc->lockbuf, ADAPTER_LOCK_NAME_LEN, "cxgb controller lock %d", device_get_unit(dev)); @@ -518,6 +501,17 @@ cxgb_controller_attach(device_t dev) error = ENODEV; goto out; } + + sc->udbs_rid = PCIR_BAR(2); + sc->udbs_res = NULL; + if (is_offload(sc) && + ((sc->udbs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->udbs_rid, RF_ACTIVE)) == NULL)) { + device_printf(dev, "Cannot allocate BAR region 1\n"); + error = ENXIO; + goto out; + } + /* Allocate the BAR for doing MSI-X. If it succeeds, try to allocate * enough messages for the queue sets. If that fails, try falling * back to MSI. If that fails, then try falling back to the legacy @@ -988,7 +982,7 @@ cxgb_makedev(struct port_info *pi) #define CXGB_CAP (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | \ IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO | \ IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE) -#define CXGB_CAP_ENABLE (CXGB_CAP & ~IFCAP_TSO6) +#define CXGB_CAP_ENABLE CXGB_CAP static int cxgb_port_attach(device_t dev) @@ -1019,11 +1013,8 @@ cxgb_port_attach(device_t dev) ifp->if_softc = p; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = cxgb_ioctl; - ifp->if_start = cxgb_start; - - ifp->if_snd.ifq_drv_maxlen = max(cxgb_snd_queue_len, ifqmaxlen); - IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); - IFQ_SET_READY(&ifp->if_snd); + ifp->if_transmit = cxgb_transmit; + ifp->if_qflush = cxgb_qflush; ifp->if_capabilities = CXGB_CAP; ifp->if_capenable = CXGB_CAP_ENABLE; @@ -1039,8 +1030,6 @@ cxgb_port_attach(device_t dev) } ether_ifattach(ifp, p->hw_addr); - ifp->if_transmit = cxgb_transmit; - ifp->if_qflush = cxgb_qflush; #ifdef DEFAULT_JUMBO if (sc->params.nports <= 2) @@ -2070,8 +2059,8 @@ cxgb_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data) } if (mask & IFCAP_RXCSUM) ifp->if_capenable ^= IFCAP_RXCSUM; - if (mask & IFCAP_TSO4) { - ifp->if_capenable ^= IFCAP_TSO4; + if (mask & IFCAP_TSO) { + ifp->if_capenable ^= IFCAP_TSO; if (IFCAP_TSO & ifp->if_capenable) { if (IFCAP_TXCSUM & ifp->if_capenable) diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c index 5fce3f574772..a34dab28b5da 100644 --- a/sys/dev/cxgb/cxgb_sge.c +++ b/sys/dev/cxgb/cxgb_sge.c @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -1492,10 +1493,10 @@ t3_encap(struct sge_qset *qs, struct mbuf **m) check_ring_tx_db(sc, txq, 0); return (0); } else if (tso_info) { - int eth_type; + uint16_t eth_type; struct cpl_tx_pkt_lso *hdr = (struct cpl_tx_pkt_lso *)txd; struct ether_header *eh; - struct ip *ip; + void *l3hdr; struct tcphdr *tcp; txd->flit[2] = 0; @@ -1521,18 +1522,37 @@ t3_encap(struct sge_qset *qs, struct mbuf **m) } eh = mtod(m0, struct ether_header *); - if (eh->ether_type == htons(ETHERTYPE_VLAN)) { - eth_type = CPL_ETH_II_VLAN; - ip = (struct ip *)((struct ether_vlan_header *)eh + 1); - } else { - eth_type = CPL_ETH_II; - ip = (struct ip *)(eh + 1); - } - tcp = (struct tcphdr *)(ip + 1); + eth_type = eh->ether_type; + if (eth_type == htons(ETHERTYPE_VLAN)) { + struct ether_vlan_header *evh = (void *)eh; - tso_info |= V_LSO_ETH_TYPE(eth_type) | - V_LSO_IPHDR_WORDS(ip->ip_hl) | - V_LSO_TCPHDR_WORDS(tcp->th_off); + tso_info |= V_LSO_ETH_TYPE(CPL_ETH_II_VLAN); + l3hdr = evh + 1; + eth_type = evh->evl_proto; + } else { + tso_info |= V_LSO_ETH_TYPE(CPL_ETH_II); + l3hdr = eh + 1; + } + + if (eth_type == htons(ETHERTYPE_IP)) { + struct ip *ip = l3hdr; + + tso_info |= V_LSO_IPHDR_WORDS(ip->ip_hl); + tcp = (struct tcphdr *)(ip + 1); + } else if (eth_type == htons(ETHERTYPE_IPV6)) { + struct ip6_hdr *ip6 = l3hdr; + + KASSERT(ip6->ip6_nxt == IPPROTO_TCP, + ("%s: CSUM_TSO with ip6_nxt %d", + __func__, ip6->ip6_nxt)); + + tso_info |= F_LSO_IPV6; + tso_info |= V_LSO_IPHDR_WORDS(sizeof(*ip6) >> 2); + tcp = (struct tcphdr *)(ip6 + 1); + } else + panic("%s: CSUM_TSO but neither ip nor ip6", __func__); + + tso_info |= V_LSO_TCPHDR_WORDS(tcp->th_off); hdr->lso_info = htonl(tso_info); if (__predict_false(mlen <= PIO_LEN)) { @@ -1767,19 +1787,6 @@ cxgb_transmit(struct ifnet *ifp, struct mbuf *m) error = drbr_enqueue(ifp, qs->txq[TXQ_ETH].txq_mr, m); return (error); } -void -cxgb_start(struct ifnet *ifp) -{ - struct port_info *pi = ifp->if_softc; - struct sge_qset *qs = &pi->adapter->sge.qs[pi->first_qset]; - - if (!pi->link_config.link_ok) - return; - - TXQ_LOCK(qs); - cxgb_start_locked(qs); - TXQ_UNLOCK(qs); -} void cxgb_qflush(struct ifnet *ifp) diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index 7e56932c2a72..020c4738056a 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -66,6 +66,17 @@ prefetch(void *x) #define prefetch(x) #endif +#ifndef SYSCTL_ADD_UQUAD +#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD +#define sysctl_handle_64 sysctl_handle_quad +#define CTLTYPE_U64 CTLTYPE_QUAD +#endif + +#if (__FreeBSD_version >= 900030) || \ + ((__FreeBSD_version >= 802507) && (__FreeBSD_version < 900000)) +#define SBUF_DRAIN 1 +#endif + #ifdef __amd64__ /* XXX: need systemwide bus_space_read_8/bus_space_write_8 */ static __inline uint64_t diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 48462aa68664..6f4dd8de4c0d 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -4314,7 +4314,7 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid, V_FW_VI_MAC_CMD_IDX(idx)); memcpy(p->macaddr, addr, sizeof(p->macaddr)); - ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); + ret = t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), &c); if (ret == 0) { ret = G_FW_VI_MAC_CMD_IDX(ntohs(p->valid_to_idx)); if (ret >= FW_CLS_TCAM_NUM_ENTRIES) diff --git a/sys/dev/cxgbe/t4_l2t.c b/sys/dev/cxgbe/t4_l2t.c index be206c1fe892..55491cda3043 100644 --- a/sys/dev/cxgbe/t4_l2t.c +++ b/sys/dev/cxgbe/t4_l2t.c @@ -259,6 +259,7 @@ t4_free_l2t(struct l2t_data *d) return (0); } +#ifdef SBUF_DRAIN static inline unsigned int vlan_prio(const struct l2t_entry *e) { @@ -333,6 +334,7 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS) return (rc); } +#endif #ifndef TCP_OFFLOAD_DISABLE static inline void @@ -652,6 +654,11 @@ t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa) } else return (NULL); +#ifndef VLAN_TAG + if (ifp->if_type == IFT_L2VLAN) + return (NULL); +#endif + hash = addr_hash(addr, addr_len, ifp->if_index); rw_wlock(&d->lock); @@ -678,10 +685,12 @@ t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa) e->v6 = (addr_len == 16); e->lle = NULL; atomic_store_rel_int(&e->refcnt, 1); +#ifdef VLAN_TAG if (ifp->if_type == IFT_L2VLAN) VLAN_TAG(ifp, &e->vlan); else e->vlan = VLAN_NONE; +#endif e->next = d->l2tab[hash].first; d->l2tab[hash].first = e; mtx_unlock(&e->lock); diff --git a/sys/dev/cxgbe/t4_l2t.h b/sys/dev/cxgbe/t4_l2t.h index 8004c9ec3b39..5dfce839b8bb 100644 --- a/sys/dev/cxgbe/t4_l2t.h +++ b/sys/dev/cxgbe/t4_l2t.h @@ -67,7 +67,9 @@ struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *); int t4_l2t_set_switching(struct adapter *, struct l2t_entry *, uint16_t, uint8_t, uint8_t *); void t4_l2t_release(struct l2t_entry *); +#ifdef SBUF_DRAIN int sysctl_l2t(SYSCTL_HANDLER_ARGS); +#endif #ifndef TCP_OFFLOAD_DISABLE struct l2t_entry *t4_l2t_get(struct port_info *, struct ifnet *, diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 37a4a7c4e2bd..a344952fcae1 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -112,7 +112,6 @@ static struct cdevsw t4_cdevsw = { /* ifnet + media interface */ static void cxgbe_init(void *); static int cxgbe_ioctl(struct ifnet *, unsigned long, caddr_t); -static void cxgbe_start(struct ifnet *); static int cxgbe_transmit(struct ifnet *, struct mbuf *); static void cxgbe_qflush(struct ifnet *); static int cxgbe_media_change(struct ifnet *); @@ -309,6 +308,7 @@ static int sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS); static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS); static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS); static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS); +#ifdef SBUF_DRAIN static int sysctl_cctrl(SYSCTL_HANDLER_ARGS); static int sysctl_cpl_stats(SYSCTL_HANDLER_ARGS); static int sysctl_ddp_stats(SYSCTL_HANDLER_ARGS); @@ -324,6 +324,7 @@ static int sysctl_tcp_stats(SYSCTL_HANDLER_ARGS); static int sysctl_tids(SYSCTL_HANDLER_ARGS); static int sysctl_tp_err_stats(SYSCTL_HANDLER_ARGS); static int sysctl_tx_rate(SYSCTL_HANDLER_ARGS); +#endif static inline void txq_start(struct ifnet *, struct sge_txq *); static uint32_t fconf_to_mode(uint32_t); static uint32_t mode_to_fconf(uint32_t); @@ -827,14 +828,9 @@ cxgbe_attach(device_t dev) ifp->if_init = cxgbe_init; ifp->if_ioctl = cxgbe_ioctl; - ifp->if_start = cxgbe_start; ifp->if_transmit = cxgbe_transmit; ifp->if_qflush = cxgbe_qflush; - ifp->if_snd.ifq_drv_maxlen = 1024; - IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); - IFQ_SET_READY(&ifp->if_snd); - ifp->if_capabilities = T4_CAP; #ifndef TCP_OFFLOAD_DISABLE if (is_offload(pi->adapter)) @@ -1093,21 +1089,6 @@ cxgbe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data) return (rc); } -static void -cxgbe_start(struct ifnet *ifp) -{ - struct port_info *pi = ifp->if_softc; - struct sge_txq *txq; - int i; - - for_each_txq(pi, i, txq) { - if (TXQ_TRYLOCK(txq)) { - txq_start(ifp, txq); - TXQ_UNLOCK(txq); - } - } -} - static int cxgbe_transmit(struct ifnet *ifp, struct mbuf *m) { @@ -2032,6 +2013,8 @@ build_medialist(struct port_info *pi) PORT_UNLOCK(pi); } +#define FW_MAC_EXACT_CHUNK 7 + /* * Program the port's XGMAC based on parameters in ifnet. The caller also * indicates which parameters should be programmed (the rest are left alone). @@ -2083,28 +2066,57 @@ update_mac_settings(struct port_info *pi, int flags) } if (flags & XGMAC_MCADDRS) { - const uint8_t *mcaddr; + const uint8_t *mcaddr[FW_MAC_EXACT_CHUNK]; int del = 1; uint64_t hash = 0; struct ifmultiaddr *ifma; + int i = 0, j; if_maddr_rlock(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) + if (ifma->ifma_addr->sa_family == AF_LINK) continue; - mcaddr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); + mcaddr[i++] = + LLADDR((struct sockaddr_dl *)ifma->ifma_addr); - rc = t4_alloc_mac_filt(sc, sc->mbox, pi->viid, del, 1, - &mcaddr, NULL, &hash, 0); + if (i == FW_MAC_EXACT_CHUNK) { + rc = t4_alloc_mac_filt(sc, sc->mbox, pi->viid, + del, i, mcaddr, NULL, &hash, 0); + if (rc < 0) { + rc = -rc; + for (j = 0; j < i; j++) { + if_printf(ifp, + "failed to add mc address" + " %02x:%02x:%02x:" + "%02x:%02x:%02x rc=%d\n", + mcaddr[j][0], mcaddr[j][1], + mcaddr[j][2], mcaddr[j][3], + mcaddr[j][4], mcaddr[j][5], + rc); + } + goto mcfail; + } + del = 0; + i = 0; + } + } + if (i > 0) { + rc = t4_alloc_mac_filt(sc, sc->mbox, pi->viid, + del, i, mcaddr, NULL, &hash, 0); if (rc < 0) { rc = -rc; - if_printf(ifp, "failed to add mc address" - " %02x:%02x:%02x:%02x:%02x:%02x rc=%d\n", - mcaddr[0], mcaddr[1], mcaddr[2], mcaddr[3], - mcaddr[4], mcaddr[5], rc); + for (j = 0; j < i; j++) { + if_printf(ifp, + "failed to add mc address" + " %02x:%02x:%02x:" + "%02x:%02x:%02x rc=%d\n", + mcaddr[j][0], mcaddr[j][1], + mcaddr[j][2], mcaddr[j][3], + mcaddr[j][4], mcaddr[j][5], + rc); + } goto mcfail; } - del = 0; } rc = -t4_set_addr_hash(sc, sc->mbox, pi->viid, 0, hash, 0); @@ -2980,6 +2992,7 @@ t4_sysctls(struct adapter *sc) sizeof(sc->sge.counter_val), sysctl_int_array, "A", "interrupt holdoff packet counter values"); +#ifdef SBUF_DRAIN /* * dev.t4nex.X.misc. Marked CTLFLAG_SKIP to avoid information overload. */ @@ -3051,6 +3064,7 @@ t4_sysctls(struct adapter *sc) SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_rate", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_tx_rate, "A", "Tx rate"); +#endif #ifndef TCP_OFFLOAD_DISABLE if (is_offload(sc)) { @@ -3465,6 +3479,7 @@ sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS) return (sysctl_handle_64(oidp, &val, 0, req)); } +#ifdef SBUF_DRAIN static int sysctl_cctrl(SYSCTL_HANDLER_ARGS) { @@ -4297,6 +4312,7 @@ sysctl_tx_rate(SYSCTL_HANDLER_ARGS) return (rc); } +#endif static inline void txq_start(struct ifnet *ifp, struct sge_txq *txq) @@ -4854,22 +4870,22 @@ filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) unsigned int rc = G_COOKIE(rpl->cookie); struct filter_entry *f = &sc->tids.ftid_tab[idx]; + ADAPTER_LOCK(sc); if (rc == FW_FILTER_WR_FLT_ADDED) { f->smtidx = (be64toh(rpl->oldval) >> 24) & 0xff; f->pending = 0; /* asynchronous setup completed */ f->valid = 1; - return (0); - } + } else { + if (rc != FW_FILTER_WR_FLT_DELETED) { + /* Add or delete failed, display an error */ + log(LOG_ERR, + "filter %u setup failed with error %u\n", + idx, rc); + } - if (rc != FW_FILTER_WR_FLT_DELETED) { - /* Add or delete failed, need to display an error */ - device_printf(sc->dev, - "filter %u setup failed with error %u\n", idx, rc); + clear_filter(f); + sc->tids.ftids_in_use--; } - - clear_filter(f); - ADAPTER_LOCK(sc); - sc->tids.ftids_in_use--; ADAPTER_UNLOCK(sc); } diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 95d8b9a3da80..9495c7948475 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -3296,12 +3296,10 @@ em_setup_transmit_ring(struct tx_ring *txr) } #ifdef DEV_NETMAP if (slot) { - int si = i + na->tx_rings[txr->me].nkr_hwofs; + int si = netmap_tidx_n2k(na, txr->me, i); uint64_t paddr; void *addr; - if (si >= na->num_tx_desc) - si -= na->num_tx_desc; addr = PNMB(slot + si, &paddr); txr->tx_base[i].buffer_addr = htole64(paddr); /* reload the map for netmap mode */ @@ -4053,13 +4051,10 @@ em_setup_receive_ring(struct rx_ring *rxr) rxbuf = &rxr->rx_buffers[j]; #ifdef DEV_NETMAP if (slot) { - /* slot si is mapped to the j-th NIC-ring entry */ - int si = j + na->rx_rings[0].nkr_hwofs; + int si = netmap_ridx_n2k(na, rxr->me, j); uint64_t paddr; void *addr; - if (si > na->num_rx_desc) - si -= na->num_rx_desc; addr = PNMB(slot + si, &paddr); netmap_load_map(rxr->rxtag, rxbuf->map, addr); /* Update descriptor */ diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 2c0caa448a2c..a70b4adce937 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -3315,11 +3315,8 @@ igb_setup_transmit_ring(struct tx_ring *txr) } #ifdef DEV_NETMAP if (slot) { - /* slot si is mapped to the i-th NIC-ring entry */ - int si = i + na->tx_rings[txr->me].nkr_hwofs; - - if (si < 0) - si += na->num_tx_desc; + int si = netmap_tidx_n2k(na, txr->me, i); + /* no need to set the address */ netmap_load_map(txr->txtag, txbuf->map, NMB(slot + si)); } #endif /* DEV_NETMAP */ @@ -4060,12 +4057,10 @@ igb_setup_receive_ring(struct rx_ring *rxr) #ifdef DEV_NETMAP if (slot) { /* slot sj is mapped to the i-th NIC-ring entry */ - int sj = j + na->rx_rings[rxr->me].nkr_hwofs; + int sj = netmap_ridx_n2k(na, rxr->me, j); uint64_t paddr; void *addr; - if (sj < 0) - sj += na->num_rx_desc; addr = PNMB(slot + sj, &paddr); netmap_load_map(rxr->ptag, rxbuf->pmap, addr); /* Update descriptor */ diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c index 0774cb99f5cb..be4626054a53 100644 --- a/sys/dev/e1000/if_lem.c +++ b/sys/dev/e1000/if_lem.c @@ -2668,13 +2668,11 @@ lem_setup_transmit_structures(struct adapter *adapter) tx_buffer->m_head = NULL; #ifdef DEV_NETMAP if (slot) { - /* slot si is mapped to the i-th NIC-ring entry */ - int si = i + na->tx_rings[0].nkr_hwofs; + /* the i-th NIC entry goes to slot si */ + int si = netmap_tidx_n2k(na, 0, i); uint64_t paddr; void *addr; - if (si > na->num_tx_desc) - si -= na->num_tx_desc; addr = PNMB(slot + si, &paddr); adapter->tx_desc_base[si].buffer_addr = htole64(paddr); /* reload the map for netmap mode */ @@ -3244,13 +3242,11 @@ lem_setup_receive_structures(struct adapter *adapter) for (i = 0; i < adapter->num_rx_desc; i++) { #ifdef DEV_NETMAP if (slot) { - /* slot si is mapped to the i-th NIC-ring entry */ - int si = i + na->rx_rings[0].nkr_hwofs; + /* the i-th NIC entry goes to slot si */ + int si = netmap_ridx_n2k(na, 0, i); uint64_t paddr; void *addr; - if (si > na->num_rx_desc) - si -= na->num_rx_desc; addr = PNMB(slot + si, &paddr); netmap_load_map(adapter->rxtag, rx_buffer->map, addr); /* Update descriptor */ diff --git a/sys/dev/fb/vesa.c b/sys/dev/fb/vesa.c index ee97ff1902a7..fcb384dee43c 100644 --- a/sys/dev/fb/vesa.c +++ b/sys/dev/fb/vesa.c @@ -1311,7 +1311,9 @@ vesa_set_mode(video_adapter_t *adp, int mode) if (!(info.vi_flags & V_INFO_GRAPHICS)) info.vi_flags &= ~V_INFO_LINEAR; - if (vesa_bios_set_mode(mode | ((info.vi_flags & V_INFO_LINEAR) ? 0x4000 : 0))) + if ((info.vi_flags & V_INFO_LINEAR) != 0) + mode |= 0x4000; + if (vesa_bios_set_mode(mode)) return (1); /* Palette format is reset by the above VBE function call. */ @@ -1329,7 +1331,7 @@ vesa_set_mode(video_adapter_t *adp, int mode) #if VESA_DEBUG > 0 printf("VESA: mode set!\n"); #endif - vesa_adp->va_mode = mode; + vesa_adp->va_mode = mode & 0x1ff; /* Mode number is 9-bit. */ vesa_adp->va_flags &= ~V_ADP_COLOR; vesa_adp->va_flags |= (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; @@ -1467,6 +1469,7 @@ vesa_save_state(video_adapter_t *adp, void *p, size_t size) static int vesa_load_state(video_adapter_t *adp, void *p) { + int mode; if ((adp != vesa_adp) || (((adp_state_t *)p)->sig != V_STATE_SIG)) return ((*prevvidsw->load_state)(adp, p)); @@ -1476,8 +1479,10 @@ vesa_load_state(video_adapter_t *adp, void *p) /* Try BIOS POST to restore a sane state. */ (void)vesa_bios_post(); - (void)int10_set_mode(adp->va_initial_bios_mode); - (void)vesa_set_mode(adp, adp->va_mode); + mode = adp->va_mode; + (void)vesa_set_mode(adp, adp->va_initial_mode); + if (mode != adp->va_initial_mode); + (void)vesa_set_mode(adp, mode); return (vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs)); } diff --git a/sys/dev/fb/vesa.h b/sys/dev/fb/vesa.h index 25b9bd50f2d1..17314394f9b3 100644 --- a/sys/dev/fb/vesa.h +++ b/sys/dev/fb/vesa.h @@ -126,7 +126,7 @@ struct vesa_mode #ifdef _KERNEL -#define VESA_MODE(x) ((x) >= M_VESA_BASE) +#define VESA_MODE(x) ((x) >= M_VESA_BASE && (x) <= M_VESA_MODE_MAX) int vesa_load_ioctl(void); int vesa_unload_ioctl(void); diff --git a/sys/dev/isci/isci.h b/sys/dev/isci/isci.h index fce5b721240e..66a0330c4bda 100644 --- a/sys/dev/isci/isci.h +++ b/sys/dev/isci/isci.h @@ -160,7 +160,6 @@ struct ISCI_REQUEST struct ISCI_IO_REQUEST { struct ISCI_REQUEST parent; - SCI_STATUS status; SCI_IO_REQUEST_HANDLE_T sci_object; union ccb *ccb; uint32_t num_segments; diff --git a/sys/dev/isci/isci_io_request.c b/sys/dev/isci/isci_io_request.c index ae6830dfcfdc..b671e67e950e 100644 --- a/sys/dev/isci/isci_io_request.c +++ b/sys/dev/isci/isci_io_request.c @@ -626,16 +626,16 @@ isci_io_request_construct(void *arg, bus_dma_segment_t *seg, int nseg, return; } - io_request->status = scif_io_request_construct( + status = scif_io_request_construct( io_request->parent.controller_handle, io_request->parent.remote_device_handle, SCI_CONTROLLER_INVALID_IO_TAG, (void *)io_request, (void *)((char*)io_request + sizeof(struct ISCI_IO_REQUEST)), &io_request->sci_object); - if (io_request->status != SCI_SUCCESS) { + if (status != SCI_SUCCESS) { isci_io_request_complete(io_request->parent.controller_handle, - device, io_request, io_request->status); + device, io_request, (SCI_IO_STATUS)status); return; } @@ -650,7 +650,7 @@ isci_io_request_construct(void *arg, bus_dma_segment_t *seg, int nseg, if (status != SCI_SUCCESS) { isci_io_request_complete(io_request->parent.controller_handle, - device, io_request, status); + device, io_request, (SCI_IO_STATUS)status); return; } @@ -900,7 +900,7 @@ isci_io_request_execute_smp_io(union ccb *ccb, if (status != SCI_SUCCESS) { isci_io_request_complete(controller->scif_controller_handle, - smp_device_handle, io_request, status); + smp_device_handle, io_request, (SCI_IO_STATUS)status); return; } @@ -912,7 +912,7 @@ isci_io_request_execute_smp_io(union ccb *ccb, if (status != SCI_SUCCESS) { isci_io_request_complete(controller->scif_controller_handle, - smp_device_handle, io_request, status); + smp_device_handle, io_request, (SCI_IO_STATUS)status); return; } diff --git a/sys/dev/isci/isci_remote_device.c b/sys/dev/isci/isci_remote_device.c index c75105844384..2388dae39bae 100644 --- a/sys/dev/isci/isci_remote_device.c +++ b/sys/dev/isci/isci_remote_device.c @@ -195,7 +195,7 @@ isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device, if (status != SCI_SUCCESS) { isci_task_request_complete(controller->scif_controller_handle, remote_device->sci_object, task_request->sci_object, - status); + (SCI_TASK_STATUS)status); return; } @@ -207,7 +207,7 @@ isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device, isci_task_request_complete( controller->scif_controller_handle, remote_device->sci_object, task_request->sci_object, - status); + (SCI_TASK_STATUS)status); return; } } diff --git a/sys/dev/isci/scil/sati_abort_task_set.c b/sys/dev/isci/scil/sati_abort_task_set.c index e7a3b411627d..9de790303265 100644 --- a/sys/dev/isci/scil/sati_abort_task_set.c +++ b/sys/dev/isci/scil/sati_abort_task_set.c @@ -124,8 +124,8 @@ SATI_STATUS sati_abort_task_set_translate_data( for (tag_index = 0; tag_index < 32; tag_index++) { - void * matching_command; - SCI_STATUS completion_status; + void * matching_command; + SCI_IO_STATUS completion_status; sati_cb_device_get_request_by_ncq_tag( scsi_task, tag_index, @@ -141,7 +141,7 @@ SATI_STATUS sati_abort_task_set_translate_data( ) { sati_translate_error(sequence, matching_command, log->error); - completion_status = SCI_FAILURE_IO_RESPONSE_VALID; + completion_status = SCI_IO_FAILURE_RESPONSE_VALID; if(sequence->state == SATI_SEQUENCE_STATE_READ_ERROR) { @@ -159,7 +159,7 @@ SATI_STATUS sati_abort_task_set_translate_data( } else { - completion_status = SCI_FAILURE_IO_TERMINATED; + completion_status = SCI_IO_FAILURE_TERMINATED; } sati_cb_io_request_complete(matching_command, completion_status); diff --git a/sys/dev/isci/scil/scic_sds_controller.c b/sys/dev/isci/scil/scic_sds_controller.c index 1fc7b924a6d4..413ef5bacef7 100644 --- a/sys/dev/isci/scil/scic_sds_controller.c +++ b/sys/dev/isci/scil/scic_sds_controller.c @@ -4165,7 +4165,7 @@ SCI_IO_STATUS scic_controller_start_io( U16 io_tag ) { - SCI_IO_STATUS status; + SCI_STATUS status; SCIC_SDS_CONTROLLER_T *this_controller; this_controller = (SCIC_SDS_CONTROLLER_T *)controller; @@ -4183,7 +4183,7 @@ SCI_IO_STATUS scic_controller_start_io( io_tag ); - return status; + return (SCI_IO_STATUS)status; } // --------------------------------------------------------------------------- @@ -4253,7 +4253,7 @@ SCI_TASK_STATUS scic_controller_start_task( U16 task_tag ) { - SCI_TASK_STATUS status = SCI_FAILURE_INVALID_STATE; + SCI_STATUS status = SCI_FAILURE_INVALID_STATE; SCIC_SDS_CONTROLLER_T *this_controller; this_controller = (SCIC_SDS_CONTROLLER_T *)controller; @@ -4282,7 +4282,7 @@ SCI_TASK_STATUS scic_controller_start_task( )); } - return status; + return (SCI_TASK_STATUS)status; } // --------------------------------------------------------------------------- diff --git a/sys/dev/isci/scil/scic_sds_stp_request.c b/sys/dev/isci/scil/scic_sds_stp_request.c index 058b4dd14baa..ed597b1ce8ac 100644 --- a/sys/dev/isci/scil/scic_sds_stp_request.c +++ b/sys/dev/isci/scil/scic_sds_stp_request.c @@ -1124,9 +1124,6 @@ SCI_STATUS scic_sds_stp_request_pio_data_out_transmit_data( if (status == SCI_SUCCESS) { this_sds_stp_request->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; - - //update the current sgl, sgl_offset and save for future - current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_sds_stp_request); sgl_offset = 0; } } diff --git a/sys/dev/isci/scil/scif_sas_controller.c b/sys/dev/isci/scil/scif_sas_controller.c index 1f4a66e28dc3..274dc64f50e4 100644 --- a/sys/dev/isci/scil/scif_sas_controller.c +++ b/sys/dev/isci/scil/scif_sas_controller.c @@ -87,6 +87,10 @@ SCI_STATUS scif_controller_construct( SCIF_SAS_LIBRARY_T * fw_library = (SCIF_SAS_LIBRARY_T*) library; SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; + // Validate the user supplied parameters. + if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE)) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + SCIF_LOG_TRACE(( sci_base_object_get_logger(library), SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, @@ -94,10 +98,6 @@ SCI_STATUS scif_controller_construct( library, controller )); - // Validate the user supplied parameters. - if ((library == SCI_INVALID_HANDLE) || (controller == SCI_INVALID_HANDLE)) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - // Construct the base controller. As part of constructing the base // controller we ask it to also manage the MDL iteration for the Core. sci_base_controller_construct( @@ -144,6 +144,10 @@ SCI_STATUS scif_controller_initialize( { SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; + // Validate the user supplied parameters. + if (controller == SCI_INVALID_HANDLE) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + SCIF_LOG_TRACE(( sci_base_object_get_logger(controller), SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, @@ -151,10 +155,6 @@ SCI_STATUS scif_controller_initialize( controller )); - // Validate the user supplied parameters. - if (controller == SCI_INVALID_HANDLE) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - return fw_controller->state_handlers->initialize_handler( &fw_controller->parent ); @@ -187,6 +187,10 @@ SCI_STATUS scif_controller_start( { SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; + // Validate the user supplied parameters. + if (controller == SCI_INVALID_HANDLE) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + SCIF_LOG_TRACE(( sci_base_object_get_logger(controller), SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION, @@ -194,10 +198,6 @@ SCI_STATUS scif_controller_start( controller, timeout )); - // Validate the user supplied parameters. - if (controller == SCI_INVALID_HANDLE) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - return fw_controller->state_handlers-> start_handler(&fw_controller->parent, timeout); } @@ -211,6 +211,10 @@ SCI_STATUS scif_controller_stop( { SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; + // Validate the user supplied parameters. + if (controller == SCI_INVALID_HANDLE) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + SCIF_LOG_TRACE(( sci_base_object_get_logger(controller), SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN, @@ -218,10 +222,6 @@ SCI_STATUS scif_controller_stop( controller, timeout )); - // Validate the user supplied parameters. - if (controller == SCI_INVALID_HANDLE) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - return fw_controller->state_handlers-> stop_handler(&fw_controller->parent, timeout); @@ -235,6 +235,10 @@ SCI_STATUS scif_controller_reset( { SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; + // Validate the user supplied parameters. + if (controller == SCI_INVALID_HANDLE) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + SCIF_LOG_TRACE(( sci_base_object_get_logger(controller), SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_CONTROLLER_RESET, @@ -242,10 +246,6 @@ SCI_STATUS scif_controller_reset( controller )); - // Validate the user supplied parameters. - if (controller == SCI_INVALID_HANDLE) - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - return fw_controller->state_handlers-> reset_handler(&fw_controller->parent); } @@ -271,6 +271,7 @@ SCI_IO_STATUS scif_controller_start_io( ) { SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; + SCI_STATUS status; SCIF_LOG_TRACE(( sci_base_object_get_logger(controller), @@ -284,7 +285,7 @@ SCI_IO_STATUS scif_controller_start_io( || scif_sas_controller_sufficient_resource(controller) ) { - return fw_controller->state_handlers->start_io_handler( + status = fw_controller->state_handlers->start_io_handler( (SCI_BASE_CONTROLLER_T*) controller, (SCI_BASE_REMOTE_DEVICE_T*) remote_device, (SCI_BASE_REQUEST_T*) io_request, @@ -292,7 +293,9 @@ SCI_IO_STATUS scif_controller_start_io( ); } else - return SCI_FAILURE_INSUFFICIENT_RESOURCES; + status = SCI_FAILURE_INSUFFICIENT_RESOURCES; + + return (SCI_IO_STATUS)status; } // --------------------------------------------------------------------------- @@ -305,6 +308,15 @@ SCI_TASK_STATUS scif_controller_start_task( ) { SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; + SCI_STATUS status; + + // Validate the user supplied parameters. + if ( (controller == SCI_INVALID_HANDLE) + || (remote_device == SCI_INVALID_HANDLE) + || (task_request == SCI_INVALID_HANDLE) ) + { + return SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE; + } SCIF_LOG_TRACE(( sci_base_object_get_logger(controller), @@ -313,17 +325,9 @@ SCI_TASK_STATUS scif_controller_start_task( controller, remote_device, task_request, io_tag )); - // Validate the user supplied parameters. - if ( (controller == SCI_INVALID_HANDLE) - || (remote_device == SCI_INVALID_HANDLE) - || (task_request == SCI_INVALID_HANDLE) ) - { - return SCI_FAILURE_INVALID_PARAMETER_VALUE; - } - if (scif_sas_controller_sufficient_resource(controller)) { - return fw_controller->state_handlers->start_task_handler( + status = fw_controller->state_handlers->start_task_handler( (SCI_BASE_CONTROLLER_T*) controller, (SCI_BASE_REMOTE_DEVICE_T*) remote_device, (SCI_BASE_REQUEST_T*) task_request, @@ -331,7 +335,9 @@ SCI_TASK_STATUS scif_controller_start_task( ); } else - return SCI_FAILURE_INSUFFICIENT_RESOURCES; + status = SCI_FAILURE_INSUFFICIENT_RESOURCES; + + return (SCI_TASK_STATUS)status; } // --------------------------------------------------------------------------- @@ -368,13 +374,6 @@ SCI_STATUS scif_controller_complete_task( { SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller; - SCIF_LOG_TRACE(( - sci_base_object_get_logger(controller), - SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT, - "scif_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n", - controller, remote_device, task_request - )); - // Validate the user supplied parameters. if ( (controller == SCI_INVALID_HANDLE) || (remote_device == SCI_INVALID_HANDLE) @@ -383,6 +382,13 @@ SCI_STATUS scif_controller_complete_task( return SCI_FAILURE_INVALID_PARAMETER_VALUE; } + SCIF_LOG_TRACE(( + sci_base_object_get_logger(controller), + SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_TASK_MANAGEMENT, + "scif_controller_complete_task(0x%x, 0x%x, 0x%x) enter\n", + controller, remote_device, task_request + )); + return fw_controller->state_handlers->complete_task_handler( (SCI_BASE_CONTROLLER_T*) controller, (SCI_BASE_REMOTE_DEVICE_T*) remote_device, diff --git a/sys/dev/isci/scil/scif_sas_controller_state_handlers.c b/sys/dev/isci/scil/scif_sas_controller_state_handlers.c index 7cf520f0ce3c..397cfbca1576 100644 --- a/sys/dev/isci/scil/scif_sas_controller_state_handlers.c +++ b/sys/dev/isci/scil/scif_sas_controller_state_handlers.c @@ -586,7 +586,7 @@ SCI_STATUS scif_sas_controller_ready_start_io_handler( if (status == SCI_SUCCESS) { // Ask the core to start processing for this IO request. - status = scic_controller_start_io( + status = (SCI_STATUS)scic_controller_start_io( fw_controller->core_object, fw_device->core_object, fw_io->parent.core_object, @@ -903,7 +903,7 @@ SCI_STATUS scif_sas_controller_ready_start_task_handler( } // Ask the core to start processing for this task request. - status = scic_controller_start_task( + status = (SCI_STATUS)scic_controller_start_task( fw_controller->core_object, fw_device->core_object, fw_task->parent.core_object, @@ -1072,7 +1072,7 @@ SCI_STATUS scif_sas_controller_common_start_high_priority_io_handler( if (status == SCI_SUCCESS) { // Ask the core to start processing for this IO request. - status = scic_controller_start_io( + status = (SCI_STATUS)scic_controller_start_io( fw_controller->core_object, fw_device->core_object, fw_io->parent.core_object, @@ -1683,7 +1683,7 @@ SCI_STATUS scif_sas_controller_failed_state_start_io_handler( &((SCIF_SAS_CONTROLLER_T *)controller)->parent.state_machine) )); - return SCI_IO_FAILURE; + return SCI_FAILURE; } #define scif_sas_controller_stopping_complete_io_handler \ diff --git a/sys/dev/isci/scil/scif_sas_domain.c b/sys/dev/isci/scil/scif_sas_domain.c index 8e7927756836..4907710bb16f 100644 --- a/sys/dev/isci/scil/scif_sas_domain.c +++ b/sys/dev/isci/scil/scif_sas_domain.c @@ -142,8 +142,8 @@ SCI_PORT_HANDLE_T scif_domain_get_scic_port_handle( { SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*) domain; - if ( (fw_domain != NULL) && (fw_domain->core_object != SCI_INVALID_HANDLE) ) - return fw_domain->core_object; + if ( (fw_domain == NULL) || (fw_domain->core_object == SCI_INVALID_HANDLE) ) + return SCI_INVALID_HANDLE; SCIF_LOG_WARNING(( sci_base_object_get_logger(fw_domain), @@ -152,7 +152,7 @@ SCI_PORT_HANDLE_T scif_domain_get_scic_port_handle( fw_domain )); - return SCI_INVALID_HANDLE; + return fw_domain->core_object; } // --------------------------------------------------------------------------- diff --git a/sys/dev/isci/scil/scif_sas_io_request.c b/sys/dev/isci/scil/scif_sas_io_request.c index 82a907c0fd97..4983c37ac1d2 100644 --- a/sys/dev/isci/scil/scif_sas_io_request.c +++ b/sys/dev/isci/scil/scif_sas_io_request.c @@ -811,7 +811,7 @@ SCI_STATUS scif_sas_io_request_continue( ); //start the new constructed IO. - return scif_controller_start_io( + return (SCI_STATUS)scif_controller_start_io( (SCI_CONTROLLER_HANDLE_T) fw_controller, (SCI_REMOTE_DEVICE_HANDLE_T) fw_device, (SCI_IO_REQUEST_HANDLE_T) fw_request, diff --git a/sys/dev/isci/scil/scif_sas_remote_device.c b/sys/dev/isci/scil/scif_sas_remote_device.c index 7088b3813b35..5fcebd6497b1 100644 --- a/sys/dev/isci/scil/scif_sas_remote_device.c +++ b/sys/dev/isci/scil/scif_sas_remote_device.c @@ -362,8 +362,8 @@ SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device_get_scic_handle( SCIF_SAS_REMOTE_DEVICE_T * fw_device = (SCIF_SAS_REMOTE_DEVICE_T*) scif_remote_device; - if ( (fw_device != NULL) && (fw_device->core_object != SCI_INVALID_HANDLE) ) - return fw_device->core_object; + if ( (fw_device == NULL) || (fw_device->core_object == SCI_INVALID_HANDLE) ) + return SCI_INVALID_HANDLE; SCIF_LOG_WARNING(( sci_base_object_get_logger(fw_device), @@ -372,7 +372,7 @@ SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device_get_scic_handle( fw_device )); - return SCI_INVALID_HANDLE; + return fw_device->core_object; } // --------------------------------------------------------------------------- diff --git a/sys/dev/isci/scil/scif_sas_remote_device_ready_substates.c b/sys/dev/isci/scil/scif_sas_remote_device_ready_substates.c index 2240be8be0a4..f13166e154ff 100644 --- a/sys/dev/isci/scil/scif_sas_remote_device_ready_substates.c +++ b/sys/dev/isci/scil/scif_sas_remote_device_ready_substates.c @@ -255,7 +255,7 @@ void scif_sas_remote_device_ready_ncq_error_substate_enter( } } - status = scif_controller_start_task( + scif_controller_start_task( fw_controller, fw_device, fw_request, diff --git a/sys/dev/isci/scil/scif_sas_smp_io_request.c b/sys/dev/isci/scil/scif_sas_smp_io_request.c index 9a05232fc977..818eb5f9e9a2 100644 --- a/sys/dev/isci/scil/scif_sas_smp_io_request.c +++ b/sys/dev/isci/scil/scif_sas_smp_io_request.c @@ -580,7 +580,7 @@ SCI_STATUS scif_sas_smp_external_request_retry( default: //unsupported case, TBD - break; + return SCI_FAILURE; } //end of switch //set the retry count to new built smp request. diff --git a/sys/dev/isci/scil/scif_sas_smp_remote_device.c b/sys/dev/isci/scil/scif_sas_smp_remote_device.c index 6df955a3a60a..c27a0e8bd478 100644 --- a/sys/dev/isci/scil/scif_sas_smp_remote_device.c +++ b/sys/dev/isci/scil/scif_sas_smp_remote_device.c @@ -748,7 +748,6 @@ SCI_STATUS scif_sas_smp_remote_device_decode_target_reset_discover_response( { SCIF_SAS_DOMAIN_T * fw_domain; SCI_SAS_ADDRESS_T attached_device_address; - SCIF_SAS_REMOTE_DEVICE_T * attached_remote_device; SMP_RESPONSE_DISCOVER_T * discover_response = &smp_response->response.discover; @@ -782,13 +781,11 @@ SCI_STATUS scif_sas_smp_remote_device_decode_target_reset_discover_response( fw_domain = fw_device->domain; attached_device_address = discover_response->attached_sas_address; - attached_remote_device = (SCIF_SAS_REMOTE_DEVICE_T *) - scif_domain_get_device_by_sas_address( - fw_domain, &attached_device_address - ); - // the device should have already existed in the domian. - ASSERT (attached_remote_device != SCI_INVALID_HANDLE); + ASSERT(scif_domain_get_device_by_sas_address( + fw_domain, + &attached_device_address + ) != SCI_INVALID_HANDLE); return SCI_SUCCESS; } else @@ -1774,6 +1771,8 @@ SCIF_SAS_SMP_PHY_T * scif_sas_smp_remote_device_find_smp_phy_by_id( SCI_FAST_LIST_ELEMENT_T * element = smp_remote_device->smp_phy_list.list_head; SCIF_SAS_SMP_PHY_T * curr_smp_phy = NULL; + ASSERT(phy_identifier < smp_remote_device->smp_phy_list.number_of_phys); + while (element != NULL) { curr_smp_phy = (SCIF_SAS_SMP_PHY_T*) sci_fast_list_get_object(element); @@ -1854,7 +1853,7 @@ void scif_sas_smp_remote_device_terminated_request_handler( )); scif_sas_smp_remote_device_decode_smp_response( - fw_device, fw_request, NULL, SCI_FAILURE_RETRY_REQUIRED + fw_device, fw_request, NULL, SCI_IO_FAILURE_RETRY_REQUIRED ); } @@ -1934,11 +1933,8 @@ SCI_STATUS scif_sas_smp_remote_device_save_smp_phy_info( scif_domain_get_device_by_sas_address( fw_device->domain, &discover_response->attached_sas_address); - if (smp_phy != NULL) - { - scif_sas_smp_phy_save_information( - smp_phy, attached_device, discover_response); - } + scif_sas_smp_phy_save_information( + smp_phy, attached_device, discover_response); //handle the special case of smp phys between expanders. if ( discover_response->protocols.u.bits.attached_smp_target ) @@ -2372,11 +2368,7 @@ void scif_sas_smp_remote_device_clean_route_table( SCIF_SAS_REMOTE_DEVICE_T * fw_device ) { - SCIF_SAS_SMP_PHY_T * smp_phy_being_config = - scif_sas_smp_remote_device_find_smp_phy_by_id( - fw_device->protocol_device.smp_device.current_activity_phy_index, - &(fw_device->protocol_device.smp_device) - ); + SCIF_SAS_SMP_PHY_T * smp_phy_being_config; SCIF_LOG_TRACE(( sci_base_object_get_logger(fw_device), diff --git a/sys/dev/isci/scil/scif_sas_stp_io_request.c b/sys/dev/isci/scil/scif_sas_stp_io_request.c index 55a19a2a7dfc..36910bd70962 100644 --- a/sys/dev/isci/scil/scif_sas_stp_io_request.c +++ b/sys/dev/isci/scil/scif_sas_stp_io_request.c @@ -396,7 +396,7 @@ SCI_STATUS scif_sas_stp_io_request_construct( fw_io->parent.protocol_complete_handler = scif_sas_stp_core_cb_io_request_complete_handler; // Done with translation - sci_status = SATI_SUCCESS; + sci_status = SCI_SUCCESS; } else if (sati_status == SATI_COMPLETE) sci_status = SCI_SUCCESS_IO_COMPLETE_BEFORE_START; diff --git a/sys/dev/isci/scil/scif_sas_stp_task_request.c b/sys/dev/isci/scil/scif_sas_stp_task_request.c index 2e2635633215..0a9f953e83d4 100644 --- a/sys/dev/isci/scil/scif_sas_stp_task_request.c +++ b/sys/dev/isci/scil/scif_sas_stp_task_request.c @@ -254,7 +254,7 @@ void scif_sas_stp_task_request_abort_task_set_failure_handler( fw_domain->controller, fw_device, pending_request, - SCI_FAILURE_IO_TERMINATED + SCI_IO_FAILURE_TERMINATED ); } //otherwise, the abort succeeded. Since the waiting flag is cleared, diff --git a/sys/dev/iscsi/initiator/isc_sm.c b/sys/dev/iscsi/initiator/isc_sm.c index ae043c97e69c..7f47e9fdaa05 100644 --- a/sys/dev/iscsi/initiator/isc_sm.c +++ b/sys/dev/iscsi/initiator/isc_sm.c @@ -652,13 +652,13 @@ static void isc_add_sysctls(isc_session_t *sp) { debug_called(8); - sdebug(6, "sid=%d %s", sp->sid, sp->dev->si_name); + sdebug(6, "sid=%d %s", sp->sid, devtoname(sp->dev)); sysctl_ctx_init(&sp->clist); sp->oid = SYSCTL_ADD_NODE(&sp->clist, SYSCTL_CHILDREN(sp->isc->oid), OID_AUTO, - sp->dev->si_name+5, // iscsi0 + devtoname(sp->dev) + 5, // iscsi0 CTLFLAG_RD, 0, "initiator"); diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c index bf7e3aa33266..48a27b015bd5 100644 --- a/sys/dev/ixgbe/ixgbe.c +++ b/sys/dev/ixgbe/ixgbe.c @@ -2969,14 +2969,11 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr) * Slots in the netmap ring (indexed by "si") are * kring->nkr_hwofs positions "ahead" wrt the * corresponding slot in the NIC ring. In some drivers - * (not here) nkr_hwofs can be negative. When computing - * si = i + kring->nkr_hwofs make sure to handle wraparounds. + * (not here) nkr_hwofs can be negative. Function + * netmap_tidx_n2k() handles wraparounds properly. */ if (slot) { - int si = i + na->tx_rings[txr->me].nkr_hwofs; - - if (si >= na->num_tx_desc) - si -= na->num_tx_desc; + int si = netmap_tidx_n2k(na, txr->me, i); netmap_load_map(txr->txtag, txbuf->map, NMB(slot + si)); } #endif /* DEV_NETMAP */ @@ -3925,12 +3922,10 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr) * an mbuf, so end the block with a continue; */ if (slot) { - int sj = j + na->rx_rings[rxr->me].nkr_hwofs; + int sj = netmap_ridx_n2k(na, rxr->me, j); uint64_t paddr; void *addr; - if (sj >= na->num_rx_desc) - sj -= na->num_rx_desc; addr = PNMB(slot + sj, &paddr); netmap_load_map(rxr->ptag, rxbuf->pmap, addr); /* Update descriptor */ diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index d3d068b8fc5b..e11e9a62243f 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -529,7 +529,7 @@ mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm) mps_dprint(sc, MPS_TRACE, "%s SMID %u cm %p ccb %p\n", __func__, cm->cm_desc.Default.SMID, cm, cm->cm_ccb); - if (sc->mps_flags & MPS_FLAGS_ATTACH_DONE) + if (sc->mps_flags & MPS_FLAGS_ATTACH_DONE && !(sc->mps_flags & MPS_FLAGS_SHUTDOWN)) mtx_assert(&sc->mps_mtx, MA_OWNED); if (++sc->io_cmds_active > sc->io_cmds_highwater) @@ -1335,6 +1335,8 @@ mps_free(struct mps_softc *sc) ((error = mps_detach_sas(sc)) != 0)) return (error); + mps_detach_user(sc); + /* Put the IOC back in the READY state. */ mps_lock(sc); if ((error = mps_transition_ready(sc)) != 0) { @@ -2142,7 +2144,7 @@ mps_wait_command(struct mps_softc *sc, struct mps_command *cm, int timeout) error = mps_map_command(sc, cm); if ((error != 0) && (error != EINPROGRESS)) return (error); - error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout); + error = msleep(cm, &sc->mps_mtx, 0, "mpswait", timeout*hz); if (error == EWOULDBLOCK) error = ETIMEDOUT; return (error); diff --git a/sys/dev/mps/mps_pci.c b/sys/dev/mps/mps_pci.c index c50dd25ad979..f2bdcb0f0b48 100644 --- a/sys/dev/mps/mps_pci.c +++ b/sys/dev/mps/mps_pci.c @@ -172,7 +172,7 @@ mps_pci_probe(device_t dev) if ((id = mps_find_ident(dev)) != NULL) { device_set_desc(dev, id->desc); - return (BUS_PROBE_VENDOR); + return (BUS_PROBE_DEFAULT); } return (ENXIO); } diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index fb57b63b1743..65009bc7fc8f 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -139,7 +139,6 @@ static uint8_t op_code_prot[256] = { MALLOC_DEFINE(M_MPSSAS, "MPSSAS", "MPS SAS memory"); -static struct mpssas_target * mpssas_find_target_by_handle(struct mpssas_softc *, int, uint16_t); static void mpssas_discovery_timeout(void *data); static void mpssas_remove_device(struct mps_softc *, struct mps_command *); static void mpssas_remove_complete(struct mps_softc *, struct mps_command *); @@ -175,7 +174,7 @@ static int mpssas_send_portenable(struct mps_softc *sc); static void mpssas_portenable_complete(struct mps_softc *sc, struct mps_command *cm); -static struct mpssas_target * +struct mpssas_target * mpssas_find_target_by_handle(struct mpssas_softc *sassc, int start, uint16_t handle) { struct mpssas_target *target; @@ -351,22 +350,123 @@ mpssas_log_command(struct mps_command *cm, const char *fmt, ...) va_end(ap); } -static void -mpssas_lost_target(struct mps_softc *sc, struct mpssas_target *targ) -{ - struct mpssas_softc *sassc = sc->sassc; - path_id_t pathid = cam_sim_path(sassc->sim); - struct cam_path *path; - mps_printf(sc, "%s targetid %u\n", __func__, targ->tid); - if (xpt_create_path(&path, NULL, pathid, targ->tid, 0) != CAM_REQ_CMP) { - mps_printf(sc, "unable to create path for lost target %d\n", - targ->tid); +static void +mpssas_remove_volume(struct mps_softc *sc, struct mps_command *tm) +{ + MPI2_SCSI_TASK_MANAGE_REPLY *reply; + struct mpssas_target *targ; + uint16_t handle; + + mps_dprint(sc, MPS_INFO, "%s\n", __func__); + + reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; + handle = (uint16_t)(uintptr_t)tm->cm_complete_data; + targ = tm->cm_targ; + + if (reply == NULL) { + /* XXX retry the remove after the diag reset completes? */ + mps_printf(sc, "%s NULL reply reseting device 0x%04x\n", + __func__, handle); + mpssas_free_tm(sc, tm); return; } - xpt_async(AC_LOST_DEVICE, path, NULL); - xpt_free_path(path); + if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) { + mps_printf(sc, "IOCStatus = 0x%x while resetting device 0x%x\n", + reply->IOCStatus, handle); + mpssas_free_tm(sc, tm); + return; + } + + mps_printf(sc, "Reset aborted %u commands\n", reply->TerminationCount); + mps_free_reply(sc, tm->cm_reply_data); + tm->cm_reply = NULL; /* Ensures the the reply won't get re-freed */ + + mps_printf(sc, "clearing target %u handle 0x%04x\n", targ->tid, handle); + + /* + * Don't clear target if remove fails because things will get confusing. + * Leave the devname and sasaddr intact so that we know to avoid reusing + * this target id if possible, and so we can assign the same target id + * to this device if it comes back in the future. + */ + if (reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) { + targ = tm->cm_targ; + targ->handle = 0x0; + targ->encl_handle = 0x0; + targ->encl_slot = 0x0; + targ->exp_dev_handle = 0x0; + targ->phy_num = 0x0; + targ->linkrate = 0x0; + targ->devinfo = 0x0; + targ->flags = 0x0; + } + + mpssas_free_tm(sc, tm); +} + + +/* + * No Need to call "MPI2_SAS_OP_REMOVE_DEVICE" For Volume removal. + * Otherwise Volume Delete is same as Bare Drive Removal. + */ +void +mpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle) +{ + MPI2_SCSI_TASK_MANAGE_REQUEST *req; + struct mps_softc *sc; + struct mps_command *cm; + struct mpssas_target *targ = NULL; + + mps_dprint(sassc->sc, MPS_INFO, "%s\n", __func__); + sc = sassc->sc; + +#ifdef WD_SUPPORT + /* + * If this is a WD controller, determine if the disk should be exposed + * to the OS or not. If disk should be exposed, return from this + * function without doing anything. + */ + if (sc->WD_available && (sc->WD_hide_expose == + MPS_WD_EXPOSE_ALWAYS)) { + return; + } +#endif //WD_SUPPORT + + targ = mpssas_find_target_by_handle(sassc, 0, handle); + if (targ == NULL) { + /* FIXME: what is the action? */ + /* We don't know about this device? */ + printf("%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle); + return; + } + + targ->flags |= MPSSAS_TARGET_INREMOVAL; + + cm = mpssas_alloc_tm(sc); + if (cm == NULL) { + mps_printf(sc, "%s: command alloc failure\n", __func__); + return; + } + + mpssas_rescan_target(sc, targ); + + req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; + req->DevHandle = targ->handle; + req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; + req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; + + /* SAS Hard Link Reset / SATA Link Reset */ + req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; + + cm->cm_targ = targ; + cm->cm_data = NULL; + cm->cm_desc.HighPriority.RequestFlags = + MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; + cm->cm_complete = mpssas_remove_volume; + cm->cm_complete_data = (void *)(uintptr_t)handle; + mps_map_command(sc, cm); } /* @@ -386,7 +486,7 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle) struct mps_command *cm; struct mpssas_target *targ = NULL; - mps_dprint(sassc->sc, MPS_TRACE, "%s\n", __func__); + mps_dprint(sassc->sc, MPS_INFO, "%s\n", __func__); /* * If this is a WD controller, determine if the disk should be exposed @@ -403,7 +503,7 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle) if (targ == NULL) { /* FIXME: what is the action? */ /* We don't know about this device? */ - printf("%s: invalid handle 0x%x \n", __func__, handle); + printf("%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle); return; } @@ -415,7 +515,7 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle) return; } - mpssas_lost_target(sc, targ); + mpssas_rescan_target(sc, targ); req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req; memset(req, 0, sizeof(*req)); @@ -443,7 +543,7 @@ mpssas_remove_device(struct mps_softc *sc, struct mps_command *tm) struct mps_command *next_cm; uint16_t handle; - mps_dprint(sc, MPS_TRACE, "%s\n", __func__); + mps_dprint(sc, MPS_INFO, "%s\n", __func__); reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; handle = (uint16_t)(uintptr_t)tm->cm_complete_data; @@ -514,7 +614,7 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm) uint16_t handle; struct mpssas_target *targ; - mps_dprint(sc, MPS_TRACE, "%s\n", __func__); + mps_dprint(sc, MPS_INFO, "%s\n", __func__); reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply; handle = (uint16_t)(uintptr_t)tm->cm_complete_data; @@ -558,6 +658,7 @@ mpssas_remove_complete(struct mps_softc *sc, struct mps_command *tm) targ->phy_num = 0x0; targ->linkrate = 0x0; targ->devinfo = 0x0; + targ->flags = 0x0; } mpssas_free_tm(sc, tm); @@ -690,7 +791,7 @@ mps_detach_sas(struct mps_softc *sc) { struct mpssas_softc *sassc; - mps_dprint(sc, MPS_TRACE, "%s\n", __func__); + mps_dprint(sc, MPS_INFO, "%s\n", __func__); if (sc->sassc == NULL) return (0); @@ -733,6 +834,7 @@ mps_detach_sas(struct mps_softc *sc) } mps_unlock(sc); + mps_dprint(sc, MPS_INFO, "%s:%d\n", __func__,__LINE__); if (sassc->devq != NULL) cam_simq_free(sassc->devq); @@ -817,7 +919,7 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb) cpi->hba_misc = PIM_NOBUSRESET; cpi->hba_eng_cnt = 0; cpi->max_target = sassc->sc->facts->MaxTargets - 1; - cpi->max_lun = 0; + cpi->max_lun = 8; cpi->initiator_id = 255; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); @@ -1475,11 +1577,11 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) uint16_t eedp_flags; sc = sassc->sc; - mps_dprint(sc, MPS_TRACE, "%s ccb %p\n", __func__, ccb); mtx_assert(&sc->mps_mtx, MA_OWNED); csio = &ccb->csio; targ = &sassc->targets[csio->ccb_h.target_id]; + mps_dprint(sc, MPS_TRACE, "%s ccb %p target flag %x\n", __func__, ccb, targ->flags); if (targ->handle == 0x0) { mps_dprint(sc, MPS_TRACE, "%s NULL handle for target %u\n", __func__, csio->ccb_h.target_id); @@ -1487,6 +1589,13 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) xpt_done(ccb); return; } + if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) { + mps_dprint(sc, MPS_TRACE, "%s Raid component no SCSI IO supported %u\n", + __func__, csio->ccb_h.target_id); + csio->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return; + } /* * If devinfo is 0 this will be a volume. In that case don't tell CAM * that the volume has timed out. We want volumes to be enumerated @@ -1683,6 +1792,198 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) return; } +static void +mps_response_code(struct mps_softc *sc, u8 response_code) +{ + char *desc; + + switch (response_code) { + case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: + desc = "task management request completed"; + break; + case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: + desc = "invalid frame"; + break; + case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: + desc = "task management request not supported"; + break; + case MPI2_SCSITASKMGMT_RSP_TM_FAILED: + desc = "task management request failed"; + break; + case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: + desc = "task management request succeeded"; + break; + case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: + desc = "invalid lun"; + break; + case 0xA: + desc = "overlapped tag attempted"; + break; + case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: + desc = "task queued, however not sent to target"; + break; + default: + desc = "unknown"; + break; + } + mps_dprint(sc, MPS_INFO, "response_code(0x%01x): %s\n", + response_code, desc); +} +/** + * mps_sc_failed_io_info - translated non-succesfull SCSI_IO request + */ +static void +mps_sc_failed_io_info(struct mps_softc *sc, struct ccb_scsiio *csio, + Mpi2SCSIIOReply_t *mpi_reply) +{ + u32 response_info; + u8 *response_bytes; + u16 ioc_status = le16toh(mpi_reply->IOCStatus) & + MPI2_IOCSTATUS_MASK; + u8 scsi_state = mpi_reply->SCSIState; + u8 scsi_status = mpi_reply->SCSIStatus; + char *desc_ioc_state = NULL; + char *desc_scsi_status = NULL; + char *desc_scsi_state = sc->tmp_string; + u32 log_info = le32toh(mpi_reply->IOCLogInfo); + + if (log_info == 0x31170000) + return; + + switch (ioc_status) { + case MPI2_IOCSTATUS_SUCCESS: + desc_ioc_state = "success"; + break; + case MPI2_IOCSTATUS_INVALID_FUNCTION: + desc_ioc_state = "invalid function"; + break; + case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: + desc_ioc_state = "scsi recovered error"; + break; + case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: + desc_ioc_state = "scsi invalid dev handle"; + break; + case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: + desc_ioc_state = "scsi device not there"; + break; + case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: + desc_ioc_state = "scsi data overrun"; + break; + case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: + desc_ioc_state = "scsi data underrun"; + break; + case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: + desc_ioc_state = "scsi io data error"; + break; + case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: + desc_ioc_state = "scsi protocol error"; + break; + case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: + desc_ioc_state = "scsi task terminated"; + break; + case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: + desc_ioc_state = "scsi residual mismatch"; + break; + case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: + desc_ioc_state = "scsi task mgmt failed"; + break; + case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: + desc_ioc_state = "scsi ioc terminated"; + break; + case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: + desc_ioc_state = "scsi ext terminated"; + break; + case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: + desc_ioc_state = "eedp guard error"; + break; + case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: + desc_ioc_state = "eedp ref tag error"; + break; + case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: + desc_ioc_state = "eedp app tag error"; + break; + default: + desc_ioc_state = "unknown"; + break; + } + + switch (scsi_status) { + case MPI2_SCSI_STATUS_GOOD: + desc_scsi_status = "good"; + break; + case MPI2_SCSI_STATUS_CHECK_CONDITION: + desc_scsi_status = "check condition"; + break; + case MPI2_SCSI_STATUS_CONDITION_MET: + desc_scsi_status = "condition met"; + break; + case MPI2_SCSI_STATUS_BUSY: + desc_scsi_status = "busy"; + break; + case MPI2_SCSI_STATUS_INTERMEDIATE: + desc_scsi_status = "intermediate"; + break; + case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: + desc_scsi_status = "intermediate condmet"; + break; + case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: + desc_scsi_status = "reservation conflict"; + break; + case MPI2_SCSI_STATUS_COMMAND_TERMINATED: + desc_scsi_status = "command terminated"; + break; + case MPI2_SCSI_STATUS_TASK_SET_FULL: + desc_scsi_status = "task set full"; + break; + case MPI2_SCSI_STATUS_ACA_ACTIVE: + desc_scsi_status = "aca active"; + break; + case MPI2_SCSI_STATUS_TASK_ABORTED: + desc_scsi_status = "task aborted"; + break; + default: + desc_scsi_status = "unknown"; + break; + } + + desc_scsi_state[0] = '\0'; + if (!scsi_state) + desc_scsi_state = " "; + if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) + strcat(desc_scsi_state, "response info "); + if (scsi_state & MPI2_SCSI_STATE_TERMINATED) + strcat(desc_scsi_state, "state terminated "); + if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) + strcat(desc_scsi_state, "no status "); + if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) + strcat(desc_scsi_state, "autosense failed "); + if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) + strcat(desc_scsi_state, "autosense valid "); + + mps_dprint(sc, MPS_INFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x), \n", + le16toh(mpi_reply->DevHandle), + desc_ioc_state, ioc_status); + /* We can add more detail about underflow data here + * TO-DO + * */ + mps_dprint(sc, MPS_INFO, "\tscsi_status(%s)(0x%02x), " + "scsi_state(%s)(0x%02x)\n", desc_scsi_status, + scsi_status, desc_scsi_state, scsi_state); + + if (sc->mps_debug & MPS_INFO && + scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { + mps_dprint(sc, MPS_INFO, "-> Sense Buffer Data : Start :\n"); + scsi_sense_print(csio); + mps_dprint(sc, MPS_INFO, "-> Sense Buffer Data : End :\n"); + } + + if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { + response_info = le32toh(mpi_reply->ResponseInfo); + response_bytes = (u8 *)&response_info; + mps_response_code(sc,response_bytes[0]); + } +} + static void mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) { @@ -2018,6 +2319,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) ccb->ccb_h.status = CAM_REQ_CMP_ERR; break; } + + mps_sc_failed_io_info(sc,csio,rep); if (sassc->flags & MPSSAS_QUEUE_FROZEN) { ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -2799,17 +3102,26 @@ mpssas_scanner_thread(void *arg) mps_lock(sc); for (;;) { + /* Sleep for 1 second and check the queue status*/ msleep(&sassc->ccb_scanq, &sc->mps_mtx, PRIBIO, - "mps_scanq", 0); + "mps_scanq", 1 * hz); if (sassc->flags & MPSSAS_SHUTDOWN) { mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n"); break; } +next_work: + // Get first work. ccb = (union ccb *)TAILQ_FIRST(&sassc->ccb_scanq); if (ccb == NULL) continue; + // Got first work. TAILQ_REMOVE(&sassc->ccb_scanq, &ccb->ccb_h, sim_links.tqe); xpt_action(ccb); + if (sassc->flags & MPSSAS_SHUTDOWN) { + mps_dprint(sc, MPS_TRACE, "Scanner shutting down\n"); + break; + } + goto next_work; } sassc->flags &= ~MPSSAS_SCANTHREAD; @@ -3009,7 +3321,7 @@ mpssas_check_eedp(struct mpssas_softc *sassc) } if (!found_lun) { lun = malloc(sizeof(struct mpssas_lun), - M_MPT2, M_WAITOK | M_ZERO); + M_MPT2, M_NOWAIT | M_ZERO); if (lun == NULL) { mps_dprint(sc, MPS_FAULT, "Unable to alloc LUN for " @@ -3084,6 +3396,20 @@ mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) if (done_ccb == NULL) return; + + /* Driver need to release devq, it Scsi command is + * generated by driver internally. + * Currently there is a single place where driver + * calls scsi command internally. In future if driver + * calls more scsi command internally, it needs to release + * devq internally, since those command will not go back to + * cam_periph. + */ + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) ) { + done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; + xpt_release_devq(done_ccb->ccb_h.path, + /*count*/ 1, /*run_queue*/TRUE); + } rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; diff --git a/sys/dev/mps/mps_sas.h b/sys/dev/mps/mps_sas.h index 343247f91e97..6653cc365e48 100644 --- a/sys/dev/mps/mps_sas.h +++ b/sys/dev/mps/mps_sas.h @@ -49,8 +49,11 @@ struct mpssas_target { #define MPSSAS_TARGET_INRESET (1 << 1) #define MPSSAS_TARGET_INDIAGRESET (1 << 2) #define MPSSAS_TARGET_INREMOVAL (1 << 3) +#define MPS_TARGET_FLAGS_RAID_COMPONENT (1 << 4) +#define MPS_TARGET_FLAGS_VOLUME (1 << 5) #define MPSSAS_TARGET_INRECOVERY (MPSSAS_TARGET_INABORT | \ MPSSAS_TARGET_INRESET | MPSSAS_TARGET_INCHIPRESET) + #define MPSSAS_TARGET_ADD (1 << 29) #define MPSSAS_TARGET_REMOVE (1 << 30) uint16_t tid; diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c index 70c74eaea551..41814056fccb 100644 --- a/sys/dev/mps/mps_sas_lsi.c +++ b/sys/dev/mps/mps_sas_lsi.c @@ -107,7 +107,7 @@ struct _ata_identify_device_data { u16 model_number[20]; /* 27-46*/ u16 reserved3[209]; /* 47-255*/ }; - +static u32 event_count; static void mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event); static void mpssas_fw_event_free(struct mps_softc *, @@ -119,7 +119,7 @@ static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle, int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc, u64 *sas_address, u16 handle, u32 device_info); static int mpssas_volume_add(struct mps_softc *sc, - Mpi2EventIrConfigElement_t *element); + u16 handle); void mpssas_evt_handler(struct mps_softc *sc, uintptr_t data, @@ -191,6 +191,8 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) struct mpssas_softc *sassc; sassc = sc->sassc; + mps_dprint(sc, MPS_INFO, "(%d)->(%s) Working on Event: [%x]\n", + event_count++,__func__,fw_event->event); switch (fw_event->event) { case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: { @@ -284,7 +286,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: case MPI2_EVENT_IR_CHANGE_RC_ADDED: if (!foreign_config) { - if (mpssas_volume_add(sc, element)) { + if (mpssas_volume_add(sc, le16toh(element->VolDevHandle))){ printf("%s: failed to add RAID " "volume with handle 0x%x\n", __func__, le16toh(element-> @@ -319,12 +321,18 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) } break; case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: + case MPI2_EVENT_IR_CHANGE_RC_HIDE: /* * Phys Disk of a volume has been created. Hide * it from the OS. */ - mpssas_prepare_remove(sassc, element-> - PhysDiskDevHandle); + targ = mpssas_find_target_by_handle(sassc, 0, element->PhysDiskDevHandle); + if (targ == NULL) + break; + + targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT; + mpssas_rescan_target(sc, targ); + break; case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: /* @@ -379,6 +387,35 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) "handle 0x%x", event_data->PreviousValue, event_data->NewValue, event_data->VolDevHandle); + u32 state; + struct mpssas_target *targ; + state = le32toh(event_data->NewValue); + switch (state) { + case MPI2_RAID_VOL_STATE_MISSING: + case MPI2_RAID_VOL_STATE_FAILED: + mpssas_prepare_volume_remove(sassc, event_data-> + VolDevHandle); + break; + + case MPI2_RAID_VOL_STATE_ONLINE: + case MPI2_RAID_VOL_STATE_DEGRADED: + case MPI2_RAID_VOL_STATE_OPTIMAL: + targ = mpssas_find_target_by_handle(sassc, 0, event_data->VolDevHandle); + if (targ) { + printf("%s %d: Volume handle 0x%x is already added \n", + __func__, __LINE__ , event_data->VolDevHandle); + break; + } + if (mpssas_volume_add(sc, le16toh(event_data->VolDevHandle))) { + printf("%s: failed to add RAID " + "volume with handle 0x%x\n", + __func__, le16toh(event_data-> + VolDevHandle)); + } + break; + default: + break; + } break; default: break; @@ -389,6 +426,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) { Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; + struct mpssas_target *targ; /* * Informational only. @@ -399,7 +437,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) mps_dprint(sc, MPS_INFO, " Phys Disk Settings " "changed from 0x%x to 0x%x for Phys Disk Number " "%d and handle 0x%x at Enclosure handle 0x%x, Slot " - "%d", event_data->PreviousValue, + "%d\n", event_data->PreviousValue, event_data->NewValue, event_data->PhysDiskNum, event_data->PhysDiskDevHandle, event_data->EnclosureHandle, event_data->Slot); @@ -407,7 +445,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED: mps_dprint(sc, MPS_INFO, " Phys Disk Status changed " "from 0x%x to 0x%x for Phys Disk Number %d and " - "handle 0x%x at Enclosure handle 0x%x, Slot %d", + "handle 0x%x at Enclosure handle 0x%x, Slot %d\n", event_data->PreviousValue, event_data->NewValue, event_data->PhysDiskNum, event_data->PhysDiskDevHandle, @@ -416,12 +454,38 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED: mps_dprint(sc, MPS_INFO, " Phys Disk State changed " "from 0x%x to 0x%x for Phys Disk Number %d and " - "handle 0x%x at Enclosure handle 0x%x, Slot %d", + "handle 0x%x at Enclosure handle 0x%x, Slot %d\n", event_data->PreviousValue, event_data->NewValue, event_data->PhysDiskNum, event_data->PhysDiskDevHandle, event_data->EnclosureHandle, event_data->Slot); - break; + switch (event_data->NewValue) { + case MPI2_RAID_PD_STATE_ONLINE: + case MPI2_RAID_PD_STATE_DEGRADED: + case MPI2_RAID_PD_STATE_REBUILDING: + case MPI2_RAID_PD_STATE_OPTIMAL: + case MPI2_RAID_PD_STATE_HOT_SPARE: + targ = mpssas_find_target_by_handle(sassc, 0, + event_data->PhysDiskDevHandle); + if (targ) { + targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT; + printf("%s %d: Found Target for handle 0x%x. \n", + __func__, __LINE__ , event_data->PhysDiskDevHandle); + } + break; + case MPI2_RAID_PD_STATE_OFFLINE: + case MPI2_RAID_PD_STATE_NOT_CONFIGURED: + case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: + default: + targ = mpssas_find_target_by_handle(sassc, 0, + event_data->PhysDiskDevHandle); + if (targ) { + targ->flags |= ~MPS_TARGET_FLAGS_RAID_COMPONENT; + printf("%s %d: Found Target for handle 0x%x. \n", + __func__, __LINE__ , event_data->PhysDiskDevHandle); + } + break; + } default: break; } @@ -494,6 +558,7 @@ mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event) break; } + mps_dprint(sc, MPS_INFO, "(%d)->(%s) Event Free: [%x]\n",event_count,__func__, fw_event->event); mpssas_fw_event_free(sc, fw_event); } @@ -584,7 +649,7 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ error = ENXIO; goto out; } - mps_vprintf(sc, "SAS Address from SAS device page0 = %jx\n", + mps_dprint(sc, MPS_INFO, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; targ->devinfo = device_info; @@ -605,12 +670,12 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ TAILQ_INIT(&targ->timedout_commands); SLIST_INIT(&targ->luns); mps_describe_devinfo(targ->devinfo, devstring, 80); - mps_vprintf(sc, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring, + mps_dprint(sc, MPS_INFO, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring, mps_describe_table(mps_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); if ((sassc->flags & MPSSAS_IN_STARTUP) == 0) mpssas_rescan_target(sc, targ); - mps_vprintf(sc, "Target id 0x%x added\n", targ->tid); + mps_dprint(sc, MPS_INFO, "Target id 0x%x added\n", targ->tid); out: mpssas_startup_decrement(sassc); return (error); @@ -751,12 +816,11 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle, } static int -mpssas_volume_add(struct mps_softc *sc, Mpi2EventIrConfigElement_t *element) +mpssas_volume_add(struct mps_softc *sc, u16 handle) { struct mpssas_softc *sassc; struct mpssas_target *targ; u64 wwid; - u16 handle = le16toh(element->VolDevHandle); unsigned int id; int error = 0; @@ -855,7 +919,9 @@ mpssas_ir_shutdown(struct mps_softc *sc) action->Function = MPI2_FUNCTION_RAID_ACTION; action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; + mps_lock(sc); mps_request_polled(sc, cm); + mps_unlock(sc); /* * Don't check for reply, just leave. diff --git a/sys/dev/mps/mps_user.c b/sys/dev/mps/mps_user.c index 75bb7ada0e5b..f4e5e35b58df 100644 --- a/sys/dev/mps/mps_user.c +++ b/sys/dev/mps/mps_user.c @@ -712,7 +712,7 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd) cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; mps_lock(sc); - err = mps_wait_command(sc, cm, 0); + err = mps_wait_command(sc, cm, 30); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", @@ -842,7 +842,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data) cm->cm_complete = NULL; cm->cm_complete_data = NULL; - err = mps_wait_command(sc, cm, 0); + err = mps_wait_command(sc, cm, 30); if (err != 0) { err = EIO; @@ -979,7 +979,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data) mps_lock(sc); - err = mps_wait_command(sc, cm, 0); + err = mps_wait_command(sc, cm, 30); if (err) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, @@ -1098,10 +1098,12 @@ mps_user_get_adapter_data(struct mps_softc *sc, mps_adapter_data_t *data) * Need to get BIOS Config Page 3 for the BIOS Version. */ data->BiosVersion = 0; + mps_lock(sc); if (mps_config_get_bios_pg3(sc, &mpi_reply, &config_page)) printf("%s: Error while retrieving BIOS Version\n", __func__); else data->BiosVersion = config_page.BiosVersion; + mps_unlock(sc); } static void @@ -1194,7 +1196,7 @@ mps_post_fw_diag_buffer(struct mps_softc *sc, /* * Send command synchronously. */ - status = mps_wait_command(sc, cm, 0); + status = mps_wait_command(sc, cm, 30); if (status) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); @@ -1278,7 +1280,7 @@ mps_release_fw_diag_buffer(struct mps_softc *sc, /* * Send command synchronously. */ - status = mps_wait_command(sc, cm, 0); + status = mps_wait_command(sc, cm, 30); if (status) { mps_printf(sc, "%s: invalid request: error %d\n", __func__, status); diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index c6f83dfde732..6246c4651950 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -58,7 +58,7 @@ #ifndef _MPSVAR_H #define _MPSVAR_H -#define MPS_DRIVER_VERSION "11.255.03.00-fbsd" +#define MPS_DRIVER_VERSION "13.00.00.00-fbsd" #define MPS_DB_MAX_WAIT 2500 @@ -78,6 +78,7 @@ #define MPS_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */ #define MPS_SCSI_RI_INVALID_FRAME (0x00000002) +#define MPS_STRING_LENGTH 64 /* * host mapping related macro definitions @@ -309,7 +310,7 @@ struct mps_softc { struct callout periodic; struct mpssas_softc *sassc; - + char tmp_string[MPS_STRING_LENGTH]; TAILQ_HEAD(, mps_command) req_list; TAILQ_HEAD(, mps_command) high_priority_req_list; TAILQ_HEAD(, mps_chain) chain_list; @@ -521,6 +522,12 @@ mps_free_command(struct mps_softc *sc, struct mps_command *cm) cm->cm_max_segs = 0; cm->cm_lun = 0; cm->cm_state = MPS_CM_STATE_FREE; + cm->cm_data = NULL; + cm->cm_length = 0; + cm->cm_out_len = 0; + cm->cm_sglsize = 0; + cm->cm_sge = NULL; + TAILQ_FOREACH_SAFE(chain, &cm->cm_chain_list, chain_link, chain_temp) { TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link); mps_free_chain(sc, chain); @@ -749,7 +756,9 @@ void mps_mapping_ir_config_change_event(struct mps_softc *sc, void mpssas_evt_handler(struct mps_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *event); void mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle); +void mpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle); int mpssas_startup(struct mps_softc *sc); +struct mpssas_target * mpssas_find_target_by_handle(struct mpssas_softc *, int, uint16_t); SYSCTL_DECL(_hw_mps); diff --git a/sys/dev/mpt/mpilib/mpi_type.h b/sys/dev/mpt/mpilib/mpi_type.h index 236baf674f20..6ff133c0b600 100644 --- a/sys/dev/mpt/mpilib/mpi_type.h +++ b/sys/dev/mpt/mpilib/mpi_type.h @@ -84,7 +84,7 @@ typedef uint32_t U32; #else -#if defined(unix) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc) +#if defined(__unix__) || defined(__arm) || defined(ALPHA) || defined(__PPC__) || defined(__ppc) typedef signed int S32; typedef unsigned int U32; diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c index 5f0e0cf24995..a95c742ce2e7 100644 --- a/sys/dev/mpt/mpt.c +++ b/sys/dev/mpt/mpt.c @@ -148,7 +148,7 @@ static __inline struct mpt_personality * mpt_pers_find(struct mpt_softc *mpt, u_int start_at) { KASSERT(start_at <= MPT_MAX_PERSONALITIES, - ("mpt_pers_find: starting position out of range\n")); + ("mpt_pers_find: starting position out of range")); while (start_at < MPT_MAX_PERSONALITIES && (mpt->mpt_pers_mask & (0x1 << start_at)) == 0) { @@ -1053,6 +1053,12 @@ mpt_hard_reset(struct mpt_softc *mpt) mpt_lprt(mpt, MPT_PRT_DEBUG, "hard reset\n"); + if (mpt->is_1078) { + mpt_write(mpt, MPT_OFFSET_RESET_1078, 0x07); + DELAY(1000); + return; + } + error = mpt_enable_diag_mode(mpt); if (error) { mpt_prt(mpt, "WARNING - Could not enter diagnostic mode !\n"); @@ -1197,8 +1203,7 @@ mpt_free_request(struct mpt_softc *mpt, request_t *req) uint32_t offset, reply_baddr; if (req == NULL || req != &mpt->request_pool[req->index]) { - panic("mpt_free_request bad req ptr\n"); - return; + panic("mpt_free_request: bad req ptr"); } if ((nxt = req->chain) != NULL) { req->chain = NULL; @@ -1261,7 +1266,7 @@ mpt_get_request(struct mpt_softc *mpt, int sleep_ok) req = TAILQ_FIRST(&mpt->request_free_list); if (req != NULL) { KASSERT(req == &mpt->request_pool[req->index], - ("mpt_get_request: corrupted request free list\n")); + ("mpt_get_request: corrupted request free list")); KASSERT(req->state == REQ_STATE_FREE, ("req %p:%u not free on free list %x index %d function %x", req, req->serno, req->state, req->index, @@ -2451,6 +2456,11 @@ mpt_download_fw(struct mpt_softc *mpt) uint32_t ext_offset; uint32_t data; + if (mpt->pci_pio_reg == NULL) { + mpt_prt(mpt, "No PIO resource!\n"); + return (ENXIO); + } + mpt_prt(mpt, "Downloading Firmware - Image Size %d\n", mpt->fw_image_size); diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h index 8a20e82b92d5..c3a44b8f83d0 100644 --- a/sys/dev/mpt/mpt.h +++ b/sys/dev/mpt/mpt.h @@ -608,7 +608,7 @@ struct mpt_softc { #endif uint32_t mpt_pers_mask; uint32_t - : 8, + : 7, unit : 8, ready : 1, fw_uploaded : 1, @@ -625,7 +625,8 @@ struct mpt_softc { disabled : 1, is_spi : 1, is_sas : 1, - is_fc : 1; + is_fc : 1, + is_1078 : 1; u_int cfg_role; u_int role; /* role: none, ini, target, both */ @@ -851,7 +852,7 @@ mpt_lockspl(struct mpt_softc *mpt) mpt->mpt_splsaved = s; } else { splx(s); - panic("Recursed lock with mask: 0x%x\n", s); + panic("Recursed lock with mask: 0x%x", s); } } @@ -863,7 +864,7 @@ mpt_unlockspl(struct mpt_softc *mpt) splx(mpt->mpt_splsaved); } } else - panic("Negative lock count\n"); + panic("Negative lock count"); } static __inline int @@ -982,12 +983,14 @@ mpt_read(struct mpt_softc *mpt, int offset) static __inline void mpt_pio_write(struct mpt_softc *mpt, size_t offset, uint32_t val) { + KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource")); bus_space_write_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset, val); } static __inline uint32_t mpt_pio_read(struct mpt_softc *mpt, int offset) { + KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource")); return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset)); } /*********************** Reply Frame/Request Management ***********************/ @@ -1144,7 +1147,7 @@ static __inline request_t * mpt_tag_2_req(struct mpt_softc *mpt, uint32_t tag) { uint16_t rtg = (tag >> 18); - KASSERT(rtg < mpt->tgt_cmds_allocated, ("bad tag %d\n", tag)); + KASSERT(rtg < mpt->tgt_cmds_allocated, ("bad tag %d", tag)); KASSERT(mpt->tgt_cmd_ptrs, ("no cmd backpointer array")); KASSERT(mpt->tgt_cmd_ptrs[rtg], ("no cmd backpointer")); return (mpt->tgt_cmd_ptrs[rtg]); @@ -1211,7 +1214,7 @@ mpt_req_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line) return; } } - panic("%s(%d): req %p:%u function %x not in els or tgt ptrs\n", + panic("%s(%d): req %p:%u function %x not in els or tgt ptrs", s, line, req, req->serno, ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function); } @@ -1225,13 +1228,13 @@ mpt_req_not_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line) int i; for (i = 0; i < mpt->els_cmds_allocated; i++) { KASSERT(req != mpt->els_cmd_ptrs[i], - ("%s(%d): req %p:%u func %x in els ptrs at ioindex %d\n", + ("%s(%d): req %p:%u func %x in els ptrs at ioindex %d", s, line, req, req->serno, ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function, i)); } for (i = 0; i < mpt->tgt_cmds_allocated; i++) { KASSERT(req != mpt->tgt_cmd_ptrs[i], - ("%s(%d): req %p:%u func %x in tgt ptrs at ioindex %d\n", + ("%s(%d): req %p:%u func %x in tgt ptrs at ioindex %d", s, line, req, req->serno, ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function, i)); } diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c index 50134f72fdf0..d312b6742b67 100644 --- a/sys/dev/mpt/mpt_cam.c +++ b/sys/dev/mpt/mpt_cam.c @@ -1279,8 +1279,9 @@ mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) char *mpt_off; union ccb *ccb; struct mpt_softc *mpt; - int seg, first_lim; - uint32_t flags, nxt_off; + bus_addr_t chain_list_addr; + int first_lim, seg, this_seg_lim; + uint32_t addr, cur_off, flags, nxt_off, tf; void *sglp = NULL; MSG_REQUEST_HEADER *hdrp; SGE_SIMPLE64 *se; @@ -1356,7 +1357,7 @@ mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) MPT_TGT_STATE(mpt, cmd_req)->req = NULL; } ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d\n", __LINE__)); + KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__)); xpt_done(ccb); CAMLOCK_2_MPTLOCK(mpt); mpt_free_request(mpt, req); @@ -1434,16 +1435,20 @@ mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) se = (SGE_SIMPLE64 *) sglp; for (seg = 0; seg < first_lim; seg++, se++, dm_segs++) { - uint32_t tf; - + tf = flags; memset(se, 0, sizeof (*se)); + MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len); se->Address.Low = htole32(dm_segs->ds_addr & 0xffffffff); if (sizeof(bus_addr_t) > 4) { - se->Address.High = - htole32(((uint64_t)dm_segs->ds_addr) >> 32); + addr = ((uint64_t)dm_segs->ds_addr) >> 32; + /* SAS1078 36GB limitation WAR */ + if (mpt->is_1078 && (((uint64_t)dm_segs->ds_addr + + MPI_SGE_LENGTH(se->FlagsLength)) >> 32) == 9) { + addr |= (1 << 31); + tf |= MPI_SGE_FLAGS_LOCAL_ADDRESS; + } + se->Address.High = htole32(addr); } - MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len); - tf = flags; if (seg == first_lim - 1) { tf |= MPI_SGE_FLAGS_LAST_ELEMENT; } @@ -1468,15 +1473,11 @@ mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) /* * Make up the rest of the data segments out of a chain element - * (contiained in the current request frame) which points to + * (contained in the current request frame) which points to * SIMPLE64 elements in the next request frame, possibly ending * with *another* chain element (if there's more). */ while (seg < nseg) { - int this_seg_lim; - uint32_t tf, cur_off; - bus_addr_t chain_list_addr; - /* * Point to the chain descriptor. Note that the chain * descriptor is at the end of the *previous* list (whether @@ -1504,7 +1505,7 @@ mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) nxt_off += MPT_RQSL(mpt); /* - * Now initialized the chain descriptor. + * Now initialize the chain descriptor. */ memset(ce, 0, sizeof (*ce)); @@ -1554,16 +1555,24 @@ mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) * set the end of list and end of buffer flags. */ while (seg < this_seg_lim) { + tf = flags; memset(se, 0, sizeof (*se)); + MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len); se->Address.Low = htole32(dm_segs->ds_addr & 0xffffffff); if (sizeof (bus_addr_t) > 4) { - se->Address.High = - htole32(((uint64_t)dm_segs->ds_addr) >> 32); + addr = ((uint64_t)dm_segs->ds_addr) >> 32; + /* SAS1078 36GB limitation WAR */ + if (mpt->is_1078 && + (((uint64_t)dm_segs->ds_addr + + MPI_SGE_LENGTH(se->FlagsLength)) >> + 32) == 9) { + addr |= (1 << 31); + tf |= MPI_SGE_FLAGS_LOCAL_ADDRESS; + } + se->Address.High = htole32(addr); } - MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len); - tf = flags; - if (seg == this_seg_lim - 1) { + if (seg == this_seg_lim - 1) { tf |= MPI_SGE_FLAGS_LAST_ELEMENT; } if (seg == nseg - 1) { @@ -1634,7 +1643,7 @@ mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) bus_dmamap_unload(mpt->buffer_dmat, req->dmap); } ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d\n", __LINE__)); + KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__)); xpt_done(ccb); CAMLOCK_2_MPTLOCK(mpt); mpt_free_request(mpt, req); @@ -1759,7 +1768,7 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) MPT_TGT_STATE(mpt, cmd_req)->req = NULL; } ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d\n", __LINE__)); + KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__)); xpt_done(ccb); CAMLOCK_2_MPTLOCK(mpt); mpt_free_request(mpt, req); @@ -1868,7 +1877,7 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) /* * Make up the rest of the data segments out of a chain element - * (contiained in the current request frame) which points to + * (contained in the current request frame) which points to * SIMPLE32 elements in the next request frame, possibly ending * with *another* chain element (if there's more). */ @@ -1904,7 +1913,7 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) nxt_off += MPT_RQSL(mpt); /* - * Now initialized the chain descriptor. + * Now initialize the chain descriptor. */ memset(ce, 0, sizeof (*ce)); @@ -1958,7 +1967,7 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len); tf = flags; - if (seg == this_seg_lim - 1) { + if (seg == this_seg_lim - 1) { tf |= MPI_SGE_FLAGS_LAST_ELEMENT; } if (seg == nseg - 1) { @@ -2029,7 +2038,7 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) bus_dmamap_unload(mpt->buffer_dmat, req->dmap); } ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d\n", __LINE__)); + KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__)); xpt_done(ccb); CAMLOCK_2_MPTLOCK(mpt); mpt_free_request(mpt, req); @@ -2737,7 +2746,7 @@ mpt_scsi_reply_handler(struct mpt_softc *mpt, request_t *req, mpt_prt(mpt, "mpt_scsi_reply_handler: %p:%u complete\n", req, req->serno); } - KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d\n", __LINE__)); + KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__)); MPTLOCK_2_CAMLOCK(mpt); xpt_done(ccb); CAMLOCK_2_MPTLOCK(mpt); @@ -3652,7 +3661,7 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) break; } mpt_calc_geometry(ccg, /*extended*/1); - KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d\n", __LINE__)); + KASSERT(ccb->ccb_h.status, ("zero ccb sts at %d", __LINE__)); break; } case XPT_PATH_INQ: /* Path routing inquiry */ @@ -4551,7 +4560,7 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb) request_t *req; KASSERT((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE, - ("dxfer_len %u but direction is NONE\n", csio->dxfer_len)); + ("dxfer_len %u but direction is NONE", csio->dxfer_len)); if ((req = mpt_get_request(mpt, FALSE)) == NULL) { if (mpt->outofbeer == 0) { @@ -5455,7 +5464,7 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, mpt_set_ccb_status(ccb, CAM_REQ_CMP); ccb->ccb_h.status &= ~CAM_SIM_QUEUED; KASSERT(ccb->ccb_h.status, - ("zero ccb sts at %d\n", __LINE__)); + ("zero ccb sts at %d", __LINE__)); tgt->state = TGT_STATE_IN_CAM; if (mpt->outofbeer) { ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -5517,7 +5526,7 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, mpt_set_ccb_status(ccb, CAM_REQ_CMP); ccb->ccb_h.status &= ~CAM_SIM_QUEUED; KASSERT(ccb->ccb_h.status, - ("ZERO ccb sts at %d\n", __LINE__)); + ("ZERO ccb sts at %d", __LINE__)); tgt->ccb = NULL; } else { mpt_lprt(mpt, MPT_PRT_DEBUG, @@ -5589,7 +5598,7 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, } tgt = MPT_TGT_STATE(mpt, req); KASSERT(tgt->state == TGT_STATE_LOADING, - ("bad state 0x%x on reply to buffer post\n", tgt->state)); + ("bad state 0x%x on reply to buffer post", tgt->state)); mpt_assign_serno(mpt, req); tgt->state = TGT_STATE_LOADED; break; diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c index 7e3211b4722e..72b5891fda1b 100644 --- a/sys/dev/mpt/mpt_pci.c +++ b/sys/dev/mpt/mpt_pci.c @@ -438,6 +438,10 @@ mpt_pci_attach(device_t dev) case PCI_PRODUCT_LSI_FC7X04X: mpt->is_fc = 1; break; + case PCI_PRODUCT_LSI_SAS1078: + case PCI_PRODUCT_LSI_SAS1078DE: + mpt->is_1078 = 1; + /* FALLTHROUGH */ case PCI_PRODUCT_LSI_SAS1064: case PCI_PRODUCT_LSI_SAS1064A: case PCI_PRODUCT_LSI_SAS1064E: @@ -445,8 +449,6 @@ mpt_pci_attach(device_t dev) case PCI_PRODUCT_LSI_SAS1066E: case PCI_PRODUCT_LSI_SAS1068: case PCI_PRODUCT_LSI_SAS1068E: - case PCI_PRODUCT_LSI_SAS1078: - case PCI_PRODUCT_LSI_SAS1078DE: mpt->is_sas = 1; break; default: @@ -527,23 +529,31 @@ mpt_pci_attach(device_t dev) mpt->pci_pio_reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &mpt_io_bar, RF_ACTIVE); if (mpt->pci_pio_reg == NULL) { - device_printf(dev, "unable to map registers in PIO mode\n"); - goto bad; + if (bootverbose) { + device_printf(dev, + "unable to map registers in PIO mode\n"); + } + } else { + mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg); + mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg); } - mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg); - mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg); /* Allocate kernel virtual memory for the 9x9's Mem0 region */ mpt_mem_bar = PCIR_BAR(mpt_mem_bar); mpt->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mpt_mem_bar, RF_ACTIVE); if (mpt->pci_reg == NULL) { - device_printf(dev, "Unable to memory map registers.\n"); - if (mpt->is_sas) { + if (bootverbose || mpt->is_sas || mpt->pci_pio_reg == NULL) { + device_printf(dev, + "Unable to memory map registers.\n"); + } + if (mpt->is_sas || mpt->pci_pio_reg == NULL) { device_printf(dev, "Giving Up.\n"); goto bad; } - device_printf(dev, "Falling back to PIO mode.\n"); + if (bootverbose) { + device_printf(dev, "Falling back to PIO mode.\n"); + } mpt->pci_st = mpt->pci_pio_st; mpt->pci_sh = mpt->pci_pio_sh; } else { diff --git a/sys/dev/mpt/mpt_reg.h b/sys/dev/mpt/mpt_reg.h index dca924c84569..746c9b5ea267 100644 --- a/sys/dev/mpt/mpt_reg.h +++ b/sys/dev/mpt/mpt_reg.h @@ -77,6 +77,7 @@ #define MPT_OFFSET_REPLY_Q 0x44 #define MPT_OFFSET_HOST_INDEX 0x50 #define MPT_OFFSET_FUBAR 0x90 +#define MPT_OFFSET_RESET_1078 0x10fc /* Bit Maps for DOORBELL register */ enum DB_STATE_BITS { diff --git a/sys/dev/netmap/if_em_netmap.h b/sys/dev/netmap/if_em_netmap.h index 959f52fd69fa..a10bef040419 100644 --- a/sys/dev/netmap/if_em_netmap.h +++ b/sys/dev/netmap/if_em_netmap.h @@ -27,7 +27,7 @@ * $FreeBSD$ * $Id: if_em_netmap.h 9802 2011-12-02 18:42:37Z luigi $ * - * netmap changes for if_em. + * netmap support for if_em.c * * For structure and details on the individual functions please see * ixgbe_netmap.h @@ -42,9 +42,10 @@ static void em_netmap_block_tasks(struct adapter *); static void em_netmap_unblock_tasks(struct adapter *); static int em_netmap_reg(struct ifnet *, int onoff); -static int em_netmap_txsync(void *, u_int, int); -static int em_netmap_rxsync(void *, u_int, int); -static void em_netmap_lock_wrapper(void *, int, u_int); +static int em_netmap_txsync(struct ifnet *, u_int, int); +static int em_netmap_rxsync(struct ifnet *, u_int, int); +static void em_netmap_lock_wrapper(struct ifnet *, int, u_int); + static void em_netmap_attach(struct adapter *adapter) @@ -61,18 +62,14 @@ em_netmap_attach(struct adapter *adapter) na.nm_rxsync = em_netmap_rxsync; na.nm_lock = em_netmap_lock_wrapper; na.nm_register = em_netmap_reg; - na.buff_size = NETMAP_BUF_SIZE; netmap_attach(&na, adapter->num_queues); } -/* - * wrapper to export locks to the generic code - */ static void -em_netmap_lock_wrapper(void *_a, int what, u_int queueid) +em_netmap_lock_wrapper(struct ifnet *ifp, int what, u_int queueid) { - struct adapter *adapter = _a; + struct adapter *adapter = ifp->if_softc; ASSERT(queueid < adapter->num_queues); switch (what) { @@ -138,6 +135,7 @@ em_netmap_unblock_tasks(struct adapter *adapter) } } + /* * register-unregister routine */ @@ -171,7 +169,7 @@ em_netmap_reg(struct ifnet *ifp, int onoff) } } else { fail: - /* restore if_transmit */ + /* return to non-netmap mode */ ifp->if_transmit = na->if_transmit; ifp->if_capenable &= ~IFCAP_NETMAP; em_init_locked(adapter); /* also enable intr */ @@ -180,13 +178,14 @@ em_netmap_reg(struct ifnet *ifp, int onoff) return (error); } + /* * Reconcile hardware and user view of the transmit ring. */ static int -em_netmap_txsync(void *a, u_int ring_nr, int do_lock) +em_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct adapter *adapter = a; + struct adapter *adapter = ifp->if_softc; struct tx_ring *txr = &adapter->tx_rings[ring_nr]; struct netmap_adapter *na = NA(adapter->ifp); struct netmap_kring *kring = &na->tx_rings[ring_nr]; @@ -212,9 +211,7 @@ em_netmap_txsync(void *a, u_int ring_nr, int do_lock) */ j = kring->nr_hwcur; if (j != k) { /* we have packets to send */ - l = j - kring->nkr_hwofs; - if (l < 0) - l += lim + 1; + l = netmap_tidx_k2n(na, ring_nr, j); while (j != k) { struct netmap_slot *slot = &ring->slot[j]; struct e1000_tx_desc *curr = &txr->tx_base[l]; @@ -225,6 +222,7 @@ em_netmap_txsync(void *a, u_int ring_nr, int do_lock) uint64_t paddr; void *addr = PNMB(slot, &paddr); int len = slot->len; + if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { if (do_lock) EM_TX_UNLOCK(txr); @@ -263,9 +261,9 @@ em_netmap_txsync(void *a, u_int ring_nr, int do_lock) if (n == 0 || kring->nr_hwavail < 1) { int delta; - /* record completed transmissions using THD. */ + /* record completed transmissions using TDH */ l = E1000_READ_REG(&adapter->hw, E1000_TDH(ring_nr)); - if (l >= kring->nkr_num_slots) { /* XXX can happen */ + if (l >= kring->nkr_num_slots) { /* XXX can it happen ? */ D("TDH wrap %d", l); l -= kring->nkr_num_slots; } @@ -286,13 +284,14 @@ em_netmap_txsync(void *a, u_int ring_nr, int do_lock) return 0; } + /* * Reconcile kernel and user view of the receive ring. */ static int -em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) +em_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct adapter *adapter = a; + struct adapter *adapter = ifp->if_softc; struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; struct netmap_adapter *na = NA(adapter->ifp); struct netmap_kring *kring = &na->rx_rings[ring_nr]; @@ -305,6 +304,7 @@ em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) if (do_lock) EM_RX_LOCK(rxr); + /* XXX check sync modes */ bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); @@ -317,12 +317,7 @@ em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) * j == (l + kring->nkr_hwofs) % ring_size */ l = rxr->next_to_check; - j = l + kring->nkr_hwofs; - /* here nkr_hwofs can be negative so must check for j < 0 */ - if (j < 0) - j += lim + 1; - else if (j > lim) - j -= lim + 1; + j = netmap_ridx_n2k(na, ring_nr, l); for (n = 0; ; n++) { struct e1000_rx_desc *curr = &rxr->rx_base[l]; @@ -342,15 +337,10 @@ em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) } /* skip past packets that userspace has already processed */ - j = kring->nr_hwcur; + j = kring->nr_hwcur; /* netmap ring index */ if (j != k) { /* userspace has read some packets. */ n = 0; - l = j - kring->nkr_hwofs; /* NIC ring index */ - /* here nkr_hwofs can be negative so check for l > lim */ - if (l < 0) - l += lim + 1; - else if (l > lim) - l -= lim + 1; + l = netmap_ridx_k2n(na, ring_nr, j); /* NIC ring index */ while (j != k) { struct netmap_slot *slot = &ring->slot[j]; struct e1000_rx_desc *curr = &rxr->rx_base[l]; @@ -396,3 +386,4 @@ em_netmap_rxsync(void *a, u_int ring_nr, int do_lock) EM_RX_UNLOCK(rxr); return 0; } +/* end of file */ diff --git a/sys/dev/netmap/if_igb_netmap.h b/sys/dev/netmap/if_igb_netmap.h index 0e4229bb0c7b..7bea4b146a79 100644 --- a/sys/dev/netmap/if_igb_netmap.h +++ b/sys/dev/netmap/if_igb_netmap.h @@ -27,8 +27,7 @@ * $FreeBSD$ * $Id: if_igb_netmap.h 9802 2011-12-02 18:42:37Z luigi $ * - * netmap modifications for igb - * contribured by Ahmed Kooli + * netmap modifications for igb contributed by Ahmed Kooli */ #include @@ -38,9 +37,9 @@ #include static int igb_netmap_reg(struct ifnet *, int onoff); -static int igb_netmap_txsync(void *, u_int, int); -static int igb_netmap_rxsync(void *, u_int, int); -static void igb_netmap_lock_wrapper(void *, int, u_int); +static int igb_netmap_txsync(struct ifnet *, u_int, int); +static int igb_netmap_rxsync(struct ifnet *, u_int, int); +static void igb_netmap_lock_wrapper(struct ifnet *, int, u_int); static void @@ -58,7 +57,6 @@ igb_netmap_attach(struct adapter *adapter) na.nm_rxsync = igb_netmap_rxsync; na.nm_lock = igb_netmap_lock_wrapper; na.nm_register = igb_netmap_reg; - na.buff_size = NETMAP_BUF_SIZE; netmap_attach(&na, adapter->num_queues); } @@ -67,9 +65,9 @@ igb_netmap_attach(struct adapter *adapter) * wrapper to export locks to the generic code */ static void -igb_netmap_lock_wrapper(void *_a, int what, u_int queueid) +igb_netmap_lock_wrapper(struct ifnet *ifp, int what, u_int queueid) { - struct adapter *adapter = _a; + struct adapter *adapter = ifp->if_softc; ASSERT(queueid < adapter->num_queues); switch (what) { @@ -96,8 +94,7 @@ igb_netmap_lock_wrapper(void *_a, int what, u_int queueid) /* - * support for netmap register/unregisted. We are already under core lock. - * only called on the first init or the last unregister. + * register-unregister routine */ static int igb_netmap_reg(struct ifnet *ifp, int onoff) @@ -107,7 +104,7 @@ igb_netmap_reg(struct ifnet *ifp, int onoff) int error = 0; if (na == NULL) - return EINVAL; + return EINVAL; /* no netmap support here */ igb_disable_intr(adapter); @@ -117,7 +114,6 @@ igb_netmap_reg(struct ifnet *ifp, int onoff) if (onoff) { ifp->if_capenable |= IFCAP_NETMAP; - /* save if_transmit to restore it later */ na->if_transmit = ifp->if_transmit; ifp->if_transmit = netmap_start; @@ -131,19 +127,19 @@ igb_netmap_reg(struct ifnet *ifp, int onoff) /* restore if_transmit */ ifp->if_transmit = na->if_transmit; ifp->if_capenable &= ~IFCAP_NETMAP; - igb_init_locked(adapter); /* also enables intr */ + igb_init_locked(adapter); /* also enable intr */ } return (error); } /* - * Reconcile kernel and user view of the transmit ring. + * Reconcile hardware and user view of the transmit ring. */ static int -igb_netmap_txsync(void *a, u_int ring_nr, int do_lock) +igb_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct adapter *adapter = a; + struct adapter *adapter = ifp->if_softc; struct tx_ring *txr = &adapter->tx_rings[ring_nr]; struct netmap_adapter *na = NA(adapter->ifp); struct netmap_kring *kring = &na->tx_rings[ring_nr]; @@ -162,30 +158,28 @@ igb_netmap_txsync(void *a, u_int ring_nr, int do_lock) bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map, BUS_DMASYNC_POSTREAD); - /* update avail to what the hardware knows */ - ring->avail = kring->nr_hwavail; - - j = kring->nr_hwcur; /* netmap ring index */ - if (j != k) { /* we have new packets to send */ - u32 olinfo_status = 0; - - l = j - kring->nkr_hwofs; /* NIC ring index */ - if (l < 0) - l += lim + 1; + /* check for new packets to send. + * j indexes the netmap ring, l indexes the nic ring, and + * j = kring->nr_hwcur, l = E1000_TDT (not tracked), + * j == (l + kring->nkr_hwofs) % ring_size + */ + j = kring->nr_hwcur; + if (j != k) { /* we have packets to send */ /* 82575 needs the queue index added */ - if (adapter->hw.mac.type == e1000_82575) - olinfo_status |= txr->me << 4; + u32 olinfo_status = + (adapter->hw.mac.type == e1000_82575) ? (txr->me << 4) : 0; + l = netmap_tidx_k2n(na, ring_nr, j); while (j != k) { struct netmap_slot *slot = &ring->slot[j]; - struct igb_tx_buffer *txbuf = &txr->tx_buffers[l]; union e1000_adv_tx_desc *curr = (union e1000_adv_tx_desc *)&txr->tx_base[l]; - uint64_t paddr; - void *addr = PNMB(slot, &paddr); + struct igb_tx_buffer *txbuf = &txr->tx_buffers[l]; int flags = ((slot->flags & NS_REPORT) || j == 0 || j == report_frequency) ? E1000_ADVTXD_DCMD_RS : 0; + uint64_t paddr; + void *addr = PNMB(slot, &paddr); int len = slot->len; if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { @@ -195,7 +189,7 @@ igb_netmap_txsync(void *a, u_int ring_nr, int do_lock) } slot->flags &= ~NS_REPORT; - // XXX do we need to set the address ? + // XXX set the address unconditionally curr->read.buffer_addr = htole64(paddr); curr->read.olinfo_status = htole32(olinfo_status | @@ -221,7 +215,6 @@ igb_netmap_txsync(void *a, u_int ring_nr, int do_lock) /* decrease avail by number of sent packets */ kring->nr_hwavail -= n; - ring->avail = kring->nr_hwavail; /* Set the watchdog XXX ? */ txr->queue_status = IGB_QUEUE_WORKING; @@ -232,23 +225,28 @@ igb_netmap_txsync(void *a, u_int ring_nr, int do_lock) E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), l); } + if (n == 0 || kring->nr_hwavail < 1) { int delta; - /* record completed transmission using TDH */ + /* record completed transmissions using TDH */ l = E1000_READ_REG(&adapter->hw, E1000_TDH(ring_nr)); - if (l >= kring->nkr_num_slots) /* XXX can it happen ? */ + if (l >= kring->nkr_num_slots) { /* XXX can it happen ? */ + D("TDH wrap %d", l); l -= kring->nkr_num_slots; + } delta = l - txr->next_to_clean; if (delta) { - /* new tx were completed */ + /* some completed, increment hwavail. */ if (delta < 0) delta += kring->nkr_num_slots; txr->next_to_clean = l; kring->nr_hwavail += delta; - ring->avail = kring->nr_hwavail; } } + /* update avail to what the hardware knows */ + ring->avail = kring->nr_hwavail; + if (do_lock) IGB_TX_UNLOCK(txr); return 0; @@ -259,9 +257,9 @@ igb_netmap_txsync(void *a, u_int ring_nr, int do_lock) * Reconcile kernel and user view of the receive ring. */ static int -igb_netmap_rxsync(void *a, u_int ring_nr, int do_lock) +igb_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct adapter *adapter = a; + struct adapter *adapter = ifp->if_softc; struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; struct netmap_adapter *na = NA(adapter->ifp); struct netmap_kring *kring = &na->rx_rings[ring_nr]; @@ -275,14 +273,19 @@ igb_netmap_rxsync(void *a, u_int ring_nr, int do_lock) if (do_lock) IGB_RX_LOCK(rxr); - /* Sync the ring. */ + /* XXX check sync modes */ bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + /* import newly received packets into the netmap ring. + * j is an index in the netmap ring, l in the NIC ring, and + * j = (kring->nr_hwcur + kring->nr_hwavail) % ring_size + * l = rxr->next_to_check; + * and + * j == (l + kring->nkr_hwofs) % ring_size + */ l = rxr->next_to_check; - j = l + kring->nkr_hwofs; - if (j > lim) - j -= lim + 1; + j = netmap_ridx_n2k(na, ring_nr, l); for (n = 0; ; n++) { union e1000_adv_rx_desc *curr = &rxr->rx_base[l]; uint32_t staterr = le32toh(curr->wb.upper.status_error); @@ -290,7 +293,6 @@ igb_netmap_rxsync(void *a, u_int ring_nr, int do_lock) if ((staterr & E1000_RXD_STAT_DD) == 0) break; ring->slot[j].len = le16toh(curr->wb.upper.length); - bus_dmamap_sync(rxr->ptag, rxr->rx_buffers[l].pmap, BUS_DMASYNC_POSTREAD); j = (j == lim) ? 0 : j + 1; @@ -301,18 +303,11 @@ igb_netmap_rxsync(void *a, u_int ring_nr, int do_lock) kring->nr_hwavail += n; } - /* skip past packets that userspace has already processed, - * making them available for reception. - * advance nr_hwcur and issue a bus_dmamap_sync on the - * buffers so it is safe to write to them. - * Also increase nr_hwavail - */ + /* skip past packets that userspace has already processed */ j = kring->nr_hwcur; - l = kring->nr_hwcur - kring->nkr_hwofs; - if (l < 0) - l += lim + 1; - if (j != k) { /* userspace has read some packets. */ + if (j != k) { /* userspace has read some packets. */ n = 0; + l = netmap_ridx_k2n(na, ring_nr, j); while (j != k) { struct netmap_slot *slot = ring->slot + j; union e1000_adv_rx_desc *curr = &rxr->rx_base[l]; @@ -341,10 +336,11 @@ igb_netmap_rxsync(void *a, u_int ring_nr, int do_lock) n++; } kring->nr_hwavail -= n; - kring->nr_hwcur = ring->cur; + kring->nr_hwcur = k; bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - /* IMPORTANT: we must leave one free slot in the ring, + /* + * IMPORTANT: we must leave one free slot in the ring, * so move l back by one unit */ l = (l == 0) ? lim : l - 1; @@ -356,3 +352,4 @@ igb_netmap_rxsync(void *a, u_int ring_nr, int do_lock) IGB_RX_UNLOCK(rxr); return 0; } +/* end of file */ diff --git a/sys/dev/netmap/if_lem_netmap.h b/sys/dev/netmap/if_lem_netmap.h index b9438fbf099b..0f5c5a0acfe6 100644 --- a/sys/dev/netmap/if_lem_netmap.h +++ b/sys/dev/netmap/if_lem_netmap.h @@ -40,13 +40,11 @@ #include static int lem_netmap_reg(struct ifnet *, int onoff); -static int lem_netmap_txsync(void *, u_int, int); -static int lem_netmap_rxsync(void *, u_int, int); -static void lem_netmap_lock_wrapper(void *, int, u_int); +static int lem_netmap_txsync(struct ifnet *, u_int, int); +static int lem_netmap_rxsync(struct ifnet *, u_int, int); +static void lem_netmap_lock_wrapper(struct ifnet *, int, u_int); -SYSCTL_NODE(_dev, OID_AUTO, lem, CTLFLAG_RW, 0, "lem card"); - static void lem_netmap_attach(struct adapter *adapter) { @@ -62,15 +60,14 @@ lem_netmap_attach(struct adapter *adapter) na.nm_rxsync = lem_netmap_rxsync; na.nm_lock = lem_netmap_lock_wrapper; na.nm_register = lem_netmap_reg; - na.buff_size = NETMAP_BUF_SIZE; netmap_attach(&na, 1); } static void -lem_netmap_lock_wrapper(void *_a, int what, u_int ringid) +lem_netmap_lock_wrapper(struct ifnet *ifp, int what, u_int ringid) { - struct adapter *adapter = _a; + struct adapter *adapter = ifp->if_softc; /* only one ring here so ignore the ringid */ switch (what) { @@ -97,7 +94,7 @@ lem_netmap_lock_wrapper(void *_a, int what, u_int ringid) /* - * Register/unregister routine + * register-unregister routine */ static int lem_netmap_reg(struct ifnet *ifp, int onoff) @@ -107,14 +104,13 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) int error = 0; if (na == NULL) - return EINVAL; + return EINVAL; /* no netmap support here */ lem_disable_intr(adapter); /* Tell the stack that the interface is no longer active */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - /* lem_netmap_block_tasks(adapter); */ #ifndef EM_LEGACY_IRQ // XXX do we need this ? taskqueue_block(adapter->tq); taskqueue_drain(adapter->tq, &adapter->rxtx_task); @@ -123,9 +119,6 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) if (onoff) { ifp->if_capenable |= IFCAP_NETMAP; - /* save if_transmit to restore it when exiting. - * XXX what about if_start and if_qflush ? - */ na->if_transmit = ifp->if_transmit; ifp->if_transmit = netmap_start; @@ -136,10 +129,10 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) } } else { fail: - /* restore non-netmap mode */ + /* return to non-netmap mode */ ifp->if_transmit = na->if_transmit; ifp->if_capenable &= ~IFCAP_NETMAP; - lem_init_locked(adapter); /* also enables intr */ + lem_init_locked(adapter); /* also enable intr */ } #ifndef EM_LEGACY_IRQ @@ -151,14 +144,14 @@ lem_netmap_reg(struct ifnet *ifp, int onoff) /* - * Reconcile kernel and user view of the transmit ring. + * Reconcile hardware and user view of the transmit ring. */ static int -lem_netmap_txsync(void *a, u_int ring_nr, int do_lock) +lem_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct adapter *adapter = a; + struct adapter *adapter = ifp->if_softc; struct netmap_adapter *na = NA(adapter->ifp); - struct netmap_kring *kring = &na->tx_rings[0]; + struct netmap_kring *kring = &na->tx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; int j, k, l, n = 0, lim = kring->nkr_num_slots - 1; @@ -174,23 +167,23 @@ lem_netmap_txsync(void *a, u_int ring_nr, int do_lock) bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_POSTREAD); - /* update avail to what the hardware knows */ - ring->avail = kring->nr_hwavail; - - j = kring->nr_hwcur; /* points into the netmap ring */ - if (j != k) { /* we have new packets to send */ - l = j - kring->nkr_hwofs; /* points into the NIC ring */ - if (l < 0) - l += lim + 1; + /* check for new packets to send. + * j indexes the netmap ring, l indexes the nic ring, and + * j = kring->nr_hwcur, l = E1000_TDT (not tracked), + * j == (l + kring->nkr_hwofs) % ring_size + */ + j = kring->nr_hwcur; + if (j != k) { /* we have packets to send */ + l = netmap_tidx_k2n(na, ring_nr, j); while (j != k) { struct netmap_slot *slot = &ring->slot[j]; struct e1000_tx_desc *curr = &adapter->tx_desc_base[l]; struct em_buffer *txbuf = &adapter->tx_buffer_area[l]; - uint64_t paddr; - void *addr = PNMB(slot, &paddr); int flags = ((slot->flags & NS_REPORT) || j == 0 || j == report_frequency) ? E1000_TXD_CMD_RS : 0; + uint64_t paddr; + void *addr = PNMB(slot, &paddr); int len = slot->len; if (addr == netmap_buffer_base || len > NETMAP_BUF_SIZE) { @@ -221,7 +214,6 @@ lem_netmap_txsync(void *a, u_int ring_nr, int do_lock) /* decrease avail by number of sent packets */ kring->nr_hwavail -= n; - ring->avail = kring->nr_hwavail; bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -234,19 +226,22 @@ lem_netmap_txsync(void *a, u_int ring_nr, int do_lock) /* record completed transmissions using TDH */ l = E1000_READ_REG(&adapter->hw, E1000_TDH(0)); - if (l >= kring->nkr_num_slots) { /* can it happen ? */ + if (l >= kring->nkr_num_slots) { /* XXX can it happen ? */ D("bad TDH %d", l); l -= kring->nkr_num_slots; } delta = l - adapter->next_tx_to_clean; if (delta) { + /* some completed, increment hwavail. */ if (delta < 0) delta += kring->nkr_num_slots; adapter->next_tx_to_clean = l; kring->nr_hwavail += delta; - ring->avail = kring->nr_hwavail; } } + /* update avail to what the hardware knows */ + ring->avail = kring->nr_hwavail; + if (do_lock) EM_TX_UNLOCK(adapter); return 0; @@ -257,11 +252,11 @@ lem_netmap_txsync(void *a, u_int ring_nr, int do_lock) * Reconcile kernel and user view of the receive ring. */ static int -lem_netmap_rxsync(void *a, u_int ring_nr, int do_lock) +lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct adapter *adapter = a; + struct adapter *adapter = ifp->if_softc; struct netmap_adapter *na = NA(adapter->ifp); - struct netmap_kring *kring = &na->rx_rings[0]; + struct netmap_kring *kring = &na->rx_rings[ring_nr]; struct netmap_ring *ring = kring->ring; int j, k, l, n, lim = kring->nkr_num_slots - 1; @@ -271,15 +266,20 @@ lem_netmap_rxsync(void *a, u_int ring_nr, int do_lock) if (do_lock) EM_RX_LOCK(adapter); + /* XXX check sync modes */ bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - /* import newly received packets into the netmap ring */ - l = adapter->next_rx_desc_to_check; /* points into the NIC ring */ - j = l + kring->nkr_hwofs; /* points into the netmap ring */ - if (j > lim) - j -= lim + 1; + /* import newly received packets into the netmap ring + * j is an index in the netmap ring, l in the NIC ring, and + * j = (kring->nr_hwcur + kring->nr_hwavail) % ring_size + * l = rxr->next_to_check; + * and + * j == (l + kring->nkr_hwofs) % ring_size + */ + l = adapter->next_rx_desc_to_check; + j = netmap_ridx_n2k(na, ring_nr, l); for (n = 0; ; n++) { struct e1000_rx_desc *curr = &adapter->rx_desc_base[l]; int len; @@ -304,12 +304,10 @@ lem_netmap_rxsync(void *a, u_int ring_nr, int do_lock) } /* skip past packets that userspace has already processed */ - j = kring->nr_hwcur; /* netmap ring index */ + j = kring->nr_hwcur; /* netmap ring index */ if (j != k) { /* userspace has read some packets. */ n = 0; - l = j - kring->nkr_hwofs; /* NIC ring index */ - if (l < 0) - l += lim + 1; + l = netmap_ridx_k2n(na, ring_nr, j); /* NIC ring index */ while (j != k) { struct netmap_slot *slot = &ring->slot[j]; struct e1000_rx_desc *curr = &adapter->rx_desc_base[l]; @@ -322,10 +320,11 @@ lem_netmap_rxsync(void *a, u_int ring_nr, int do_lock) EM_RX_UNLOCK(adapter); return netmap_ring_reinit(kring); } + curr->status = 0; if (slot->flags & NS_BUF_CHANGED) { curr->buffer_addr = htole64(paddr); - /* buffer has changed, and reload map */ + /* buffer has changed, reload map */ netmap_reload_map(adapter->rxtag, rxbuf->map, addr); slot->flags &= ~NS_BUF_CHANGED; } @@ -348,12 +347,10 @@ lem_netmap_rxsync(void *a, u_int ring_nr, int do_lock) l = (l == 0) ? lim : l - 1; E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), l); } - /* tell userspace that there are new packets */ ring->avail = kring->nr_hwavail ; if (do_lock) EM_RX_UNLOCK(adapter); return 0; } - - +/* end of file */ diff --git a/sys/dev/netmap/if_re_netmap.h b/sys/dev/netmap/if_re_netmap.h index a92432cca81e..d0b89193fe6c 100644 --- a/sys/dev/netmap/if_re_netmap.h +++ b/sys/dev/netmap/if_re_netmap.h @@ -37,9 +37,9 @@ #include static int re_netmap_reg(struct ifnet *, int onoff); -static int re_netmap_txsync(void *, u_int, int); -static int re_netmap_rxsync(void *, u_int, int); -static void re_netmap_lock_wrapper(void *, int, u_int); +static int re_netmap_txsync(struct ifnet *, u_int, int); +static int re_netmap_rxsync(struct ifnet *, u_int, int); +static void re_netmap_lock_wrapper(struct ifnet *, int, u_int); static void re_netmap_attach(struct rl_softc *sc) @@ -56,7 +56,6 @@ re_netmap_attach(struct rl_softc *sc) na.nm_rxsync = re_netmap_rxsync; na.nm_lock = re_netmap_lock_wrapper; na.nm_register = re_netmap_reg; - na.buff_size = NETMAP_BUF_SIZE; netmap_attach(&na, 1); } @@ -66,9 +65,9 @@ re_netmap_attach(struct rl_softc *sc) * We should not use the tx/rx locks */ static void -re_netmap_lock_wrapper(void *_a, int what, u_int queueid) +re_netmap_lock_wrapper(struct ifnet *ifp, int what, u_int queueid) { - struct rl_softc *adapter = _a; + struct rl_softc *adapter = ifp->if_softc; switch (what) { case NETMAP_CORE_LOCK: @@ -134,9 +133,9 @@ re_netmap_reg(struct ifnet *ifp, int onoff) * Reconcile kernel and user view of the transmit ring. */ static int -re_netmap_txsync(void *a, u_int ring_nr, int do_lock) +re_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct rl_softc *sc = a; + struct rl_softc *sc = ifp->if_softc; struct rl_txdesc *txd = sc->rl_ldata.rl_tx_desc; struct netmap_adapter *na = NA(sc->rl_ifp); struct netmap_kring *kring = &na->tx_rings[ring_nr]; @@ -237,9 +236,9 @@ re_netmap_txsync(void *a, u_int ring_nr, int do_lock) * Reconcile kernel and user view of the receive ring. */ static int -re_netmap_rxsync(void *a, u_int ring_nr, int do_lock) +re_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct rl_softc *sc = a; + struct rl_softc *sc = ifp->if_softc; struct rl_rxdesc *rxd = sc->rl_ldata.rl_rx_desc; struct netmap_adapter *na = NA(sc->rl_ifp); struct netmap_kring *kring = &na->rx_rings[ring_nr]; @@ -264,7 +263,7 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock) * is to limit the amount of data reported up to 'lim' */ l = sc->rl_ldata.rl_rx_prodidx; /* next pkt to check */ - j = l + kring->nkr_hwofs; + j = netmap_ridx_n2k(na, ring_nr, l); /* the kring index */ for (n = kring->nr_hwavail; n < lim ; n++) { struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[l]; uint32_t rxstat = le32toh(cur_rx->rl_cmdstat); @@ -297,9 +296,7 @@ re_netmap_rxsync(void *a, u_int ring_nr, int do_lock) j = kring->nr_hwcur; if (j != k) { /* userspace has read some packets. */ n = 0; - l = kring->nr_hwcur - kring->nkr_hwofs; - if (l < 0) - l += lim + 1; + l = netmap_ridx_k2n(na, ring_nr, j); /* the NIC index */ while (j != k) { struct netmap_slot *slot = ring->slot + j; struct rl_desc *desc = &sc->rl_ldata.rl_rx_list[l]; @@ -371,11 +368,7 @@ re_netmap_tx_init(struct rl_softc *sc) for (i = 0; i < n; i++) { void *addr; uint64_t paddr; - struct netmap_kring *kring = &na->tx_rings[0]; - int l = i + kring->nkr_hwofs; - - if (l >= n) - l -= n; + int l = netmap_tidx_n2k(na, 0, i); addr = PNMB(slot + l, &paddr); desc[i].rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); @@ -392,19 +385,21 @@ re_netmap_rx_init(struct rl_softc *sc) struct netmap_slot *slot = netmap_reset(na, NR_RX, 0, 0); struct rl_desc *desc = sc->rl_ldata.rl_rx_list; uint32_t cmdstat; - int i, n; + int i, n, max_avail; if (!slot) return; n = sc->rl_ldata.rl_rx_desc_cnt; + /* + * Userspace owned hwavail packets before the reset, + * so the NIC that last hwavail descriptors of the ring + * are still owned by the driver (and keep one empty). + */ + max_avail = n - 1 - na->rx_rings[0].nr_hwavail; for (i = 0; i < n; i++) { void *addr; uint64_t paddr; - struct netmap_kring *kring = &na->rx_rings[0]; - int l = i + kring->nkr_hwofs; - - if (l >= n) - l -= n; + int l = netmap_ridx_n2k(na, 0, i); addr = PNMB(slot + l, &paddr); @@ -415,14 +410,9 @@ re_netmap_rx_init(struct rl_softc *sc) desc[i].rl_bufaddr_lo = htole32(RL_ADDR_LO(paddr)); desc[i].rl_bufaddr_hi = htole32(RL_ADDR_HI(paddr)); cmdstat = na->buff_size; - if (i == n - 1) + if (i == n - 1) /* mark the end of ring */ cmdstat |= RL_RDESC_CMD_EOR; - /* - * userspace knows that hwavail packets were ready before the - * reset, so we need to tell the NIC that last hwavail - * descriptors of the ring are still owned by the driver. - */ - if (i < n - 1 - kring->nr_hwavail) // XXX + 1 ? + if (i < max_avail) cmdstat |= RL_RDESC_CMD_OWN; desc[i].rl_cmdstat = htole32(cmdstat); } diff --git a/sys/dev/netmap/ixgbe_netmap.h b/sys/dev/netmap/ixgbe_netmap.h index 8e5fe1b2f71d..5f5a240b4921 100644 --- a/sys/dev/netmap/ixgbe_netmap.h +++ b/sys/dev/netmap/ixgbe_netmap.h @@ -55,9 +55,9 @@ * *_netmap_attach() routine. */ static int ixgbe_netmap_reg(struct ifnet *, int onoff); -static int ixgbe_netmap_txsync(void *, u_int, int); -static int ixgbe_netmap_rxsync(void *, u_int, int); -static void ixgbe_netmap_lock_wrapper(void *, int, u_int); +static int ixgbe_netmap_txsync(struct ifnet *, u_int, int); +static int ixgbe_netmap_rxsync(struct ifnet *, u_int, int); +static void ixgbe_netmap_lock_wrapper(struct ifnet *, int, u_int); /* @@ -82,13 +82,6 @@ ixgbe_netmap_attach(struct adapter *adapter) na.nm_rxsync = ixgbe_netmap_rxsync; na.nm_lock = ixgbe_netmap_lock_wrapper; na.nm_register = ixgbe_netmap_reg; - /* - * XXX where do we put this comment ? - * adapter->rx_mbuf_sz is set by SIOCSETMTU, but in netmap mode - * we allocate the buffers on the first register. So we must - * disallow a SIOCSETMTU when if_capenable & IFCAP_NETMAP is set. - */ - na.buff_size = NETMAP_BUF_SIZE; netmap_attach(&na, adapter->num_queues); } @@ -97,9 +90,9 @@ ixgbe_netmap_attach(struct adapter *adapter) * wrapper to export locks to the generic netmap code. */ static void -ixgbe_netmap_lock_wrapper(void *_a, int what, u_int queueid) +ixgbe_netmap_lock_wrapper(struct ifnet *_a, int what, u_int queueid) { - struct adapter *adapter = _a; + struct adapter *adapter = _a->if_softc; ASSERT(queueid < adapter->num_queues); switch (what) { @@ -197,9 +190,9 @@ ixgbe_netmap_reg(struct ifnet *ifp, int onoff) * buffers irrespective of interrupt mitigation. */ static int -ixgbe_netmap_txsync(void *a, u_int ring_nr, int do_lock) +ixgbe_netmap_txsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct adapter *adapter = a; + struct adapter *adapter = ifp->if_softc; struct tx_ring *txr = &adapter->tx_rings[ring_nr]; struct netmap_adapter *na = NA(adapter->ifp); struct netmap_kring *kring = &na->tx_rings[ring_nr]; @@ -217,6 +210,7 @@ ixgbe_netmap_txsync(void *a, u_int ring_nr, int do_lock) IXGBE_TX_LOCK(txr); /* take a copy of ring->cur now, and never read it again */ k = ring->cur; + /* do a sanity check on cur - hwcur XXX verify */ l = k - kring->nr_hwcur; if (l < 0) l += lim + 1; @@ -247,9 +241,7 @@ ixgbe_netmap_txsync(void *a, u_int ring_nr, int do_lock) */ j = kring->nr_hwcur; if (j != k) { /* we have new packets to send */ - l = j - kring->nkr_hwofs; - if (l < 0) /* wraparound */ - l += lim + 1; + l = netmap_tidx_k2n(na, ring_nr, j); /* NIC index */ while (j != k) { /* @@ -354,7 +346,8 @@ ixgbe_netmap_txsync(void *a, u_int ring_nr, int do_lock) * otherwise we go to sleep (in netmap_poll()) and will be * woken up when slot nr_kflags will be ready. */ - struct ixgbe_legacy_tx_desc *txd = (struct ixgbe_legacy_tx_desc *)txr->tx_base; + struct ixgbe_legacy_tx_desc *txd = + (struct ixgbe_legacy_tx_desc *)txr->tx_base; j = txr->next_to_clean + kring->nkr_num_slots/2; if (j >= kring->nkr_num_slots) @@ -365,9 +358,7 @@ ixgbe_netmap_txsync(void *a, u_int ring_nr, int do_lock) kring->nr_kflags = j; /* the slot to check */ j = txd[j].upper.fields.status & IXGBE_TXD_STAT_DD; } - if (!j) { - netmap_skip_txsync++; - } else { + if (j) { int delta; /* @@ -426,9 +417,9 @@ ixgbe_netmap_txsync(void *a, u_int ring_nr, int do_lock) * do_lock has a special meaning: please refer to txsync. */ static int -ixgbe_netmap_rxsync(void *a, u_int ring_nr, int do_lock) +ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock) { - struct adapter *adapter = a; + struct adapter *adapter = ifp->if_softc; struct rx_ring *rxr = &adapter->rx_rings[ring_nr]; struct netmap_adapter *na = NA(adapter->ifp); struct netmap_kring *kring = &na->rx_rings[ring_nr]; @@ -467,11 +458,9 @@ ixgbe_netmap_rxsync(void *a, u_int ring_nr, int do_lock) * rxr->next_to_check is set to 0 on a ring reinit */ l = rxr->next_to_check; - j = rxr->next_to_check + kring->nkr_hwofs; - if (j > lim) - j -= lim + 1; + j = netmap_ridx_n2k(na, ring_nr, l); - if (force_update) { + if (netmap_no_pendintr || force_update) { for (n = 0; ; n++) { union ixgbe_adv_rx_desc *curr = &rxr->rx_base[l]; uint32_t staterr = le32toh(curr->wb.upper.status_error); @@ -501,9 +490,7 @@ ixgbe_netmap_rxsync(void *a, u_int ring_nr, int do_lock) j = kring->nr_hwcur; if (j != k) { /* userspace has read some packets. */ n = 0; - l = kring->nr_hwcur - kring->nkr_hwofs; - if (l < 0) - l += lim + 1; + l = netmap_ridx_k2n(na, ring_nr, j); while (j != k) { /* collect per-slot info, with similar validations * and flag handling as in the txsync code. @@ -548,6 +535,7 @@ ixgbe_netmap_rxsync(void *a, u_int ring_nr, int do_lock) } /* tell userspace that there are new packets */ ring->avail = kring->nr_hwavail ; + if (do_lock) IXGBE_RX_UNLOCK(rxr); return 0; diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c index 1f282cecd959..198a845311c4 100644 --- a/sys/dev/netmap/netmap.c +++ b/sys/dev/netmap/netmap.c @@ -92,6 +92,39 @@ MALLOC_DEFINE(M_NETMAP, "netmap", "Network memory map"); */ #define NMA_LOCK() mtx_lock(&netmap_mem_d->nm_mtx); #define NMA_UNLOCK() mtx_unlock(&netmap_mem_d->nm_mtx); +struct netmap_mem_d; +static struct netmap_mem_d *netmap_mem_d; /* Our memory allocator. */ + +u_int netmap_total_buffers; +char *netmap_buffer_base; /* address of an invalid buffer */ + +/* user-controlled variables */ +int netmap_verbose; + +static int netmap_no_timestamp; /* don't timestamp on rxsync */ + +SYSCTL_NODE(_dev, OID_AUTO, netmap, CTLFLAG_RW, 0, "Netmap args"); +SYSCTL_INT(_dev_netmap, OID_AUTO, verbose, + CTLFLAG_RW, &netmap_verbose, 0, "Verbose mode"); +SYSCTL_INT(_dev_netmap, OID_AUTO, no_timestamp, + CTLFLAG_RW, &netmap_no_timestamp, 0, "no_timestamp"); +int netmap_buf_size = 2048; +TUNABLE_INT("hw.netmap.buf_size", &netmap_buf_size); +SYSCTL_INT(_dev_netmap, OID_AUTO, buf_size, + CTLFLAG_RD, &netmap_buf_size, 0, "Size of packet buffers"); +int netmap_mitigate = 1; +SYSCTL_INT(_dev_netmap, OID_AUTO, mitigate, CTLFLAG_RW, &netmap_mitigate, 0, ""); +int netmap_no_pendintr; +SYSCTL_INT(_dev_netmap, OID_AUTO, no_pendintr, + CTLFLAG_RW, &netmap_no_pendintr, 0, "Always look for new received packets."); + + + +/*----- memory allocator -----------------*/ +/* + * Here we have the low level routines for memory allocator + * and its primary users. + */ /* * Default amount of memory pre-allocated by the module. @@ -128,30 +161,13 @@ struct netmap_buf_pool { uint32_t *bitmap; /* one bit per buffer, 1 means free */ }; struct netmap_buf_pool nm_buf_pool; -/* XXX move these two vars back into netmap_buf_pool */ -u_int netmap_total_buffers; -char *netmap_buffer_base; /* address of an invalid buffer */ - -/* user-controlled variables */ -int netmap_verbose; - -static int no_timestamp; /* don't timestamp on rxsync */ - -SYSCTL_NODE(_dev, OID_AUTO, netmap, CTLFLAG_RW, 0, "Netmap args"); -SYSCTL_INT(_dev_netmap, OID_AUTO, verbose, - CTLFLAG_RW, &netmap_verbose, 0, "Verbose mode"); -SYSCTL_INT(_dev_netmap, OID_AUTO, no_timestamp, - CTLFLAG_RW, &no_timestamp, 0, "no_timestamp"); SYSCTL_INT(_dev_netmap, OID_AUTO, total_buffers, CTLFLAG_RD, &nm_buf_pool.total_buffers, 0, "total_buffers"); SYSCTL_INT(_dev_netmap, OID_AUTO, free_buffers, CTLFLAG_RD, &nm_buf_pool.free, 0, "free_buffers"); -int netmap_mitigate = 1; -SYSCTL_INT(_dev_netmap, OID_AUTO, mitigate, CTLFLAG_RW, &netmap_mitigate, 0, ""); -int netmap_skip_txsync; -SYSCTL_INT(_dev_netmap, OID_AUTO, skip_txsync, CTLFLAG_RW, &netmap_skip_txsync, 0, ""); -int netmap_skip_rxsync; -SYSCTL_INT(_dev_netmap, OID_AUTO, skip_rxsync, CTLFLAG_RW, &netmap_skip_rxsync, 0, ""); + + + /* * Allocate n buffers from the ring, and fill the slot. @@ -239,17 +255,6 @@ struct netmap_mem_d { area. */ }; - -/* Structure associated to each thread which registered an interface. */ -struct netmap_priv_d { - struct netmap_if *np_nifp; /* netmap interface descriptor. */ - - struct ifnet *np_ifp; /* device for which we hold a reference */ - int np_ringid; /* from the ioctl */ - u_int np_qfirst, np_qlast; /* range of rings to scan */ - uint16_t np_txpoll; -}; - /* Shorthand to compute a netmap interface offset. */ #define netmap_if_offset(v) \ ((char *) (v) - (char *) netmap_mem_d->nm_buffer) @@ -257,1147 +262,6 @@ struct netmap_priv_d { #define netmap_ofstophys(o) \ (vtophys(netmap_mem_d->nm_buffer) + (o)) -static struct cdev *netmap_dev; /* /dev/netmap character device. */ -static struct netmap_mem_d *netmap_mem_d; /* Our memory allocator. */ - - -static d_mmap_t netmap_mmap; -static d_ioctl_t netmap_ioctl; -static d_poll_t netmap_poll; - -#ifdef NETMAP_KEVENT -static d_kqfilter_t netmap_kqfilter; -#endif - -static struct cdevsw netmap_cdevsw = { - .d_version = D_VERSION, - .d_name = "netmap", - .d_mmap = netmap_mmap, - .d_ioctl = netmap_ioctl, - .d_poll = netmap_poll, -#ifdef NETMAP_KEVENT - .d_kqfilter = netmap_kqfilter, -#endif -}; - -#ifdef NETMAP_KEVENT -static int netmap_kqread(struct knote *, long); -static int netmap_kqwrite(struct knote *, long); -static void netmap_kqdetach(struct knote *); - -static struct filterops netmap_read_filterops = { - .f_isfd = 1, - .f_attach = NULL, - .f_detach = netmap_kqdetach, - .f_event = netmap_kqread, -}; - -static struct filterops netmap_write_filterops = { - .f_isfd = 1, - .f_attach = NULL, - .f_detach = netmap_kqdetach, - .f_event = netmap_kqwrite, -}; - -/* - * support for the kevent() system call. - * - * This is the kevent filter, and is executed each time a new event - * is triggered on the device. This function execute some operation - * depending on the received filter. - * - * The implementation should test the filters and should implement - * filter operations we are interested on (a full list in /sys/event.h). - * - * On a match we should: - * - set kn->kn_fop - * - set kn->kn_hook - * - call knlist_add() to deliver the event to the application. - * - * Return 0 if the event should be delivered to the application. - */ -static int -netmap_kqfilter(struct cdev *dev, struct knote *kn) -{ - /* declare variables needed to read/write */ - - switch(kn->kn_filter) { - case EVFILT_READ: - if (netmap_verbose) - D("%s kqfilter: EVFILT_READ" ifp->if_xname); - - /* read operations */ - kn->kn_fop = &netmap_read_filterops; - break; - - case EVFILT_WRITE: - if (netmap_verbose) - D("%s kqfilter: EVFILT_WRITE" ifp->if_xname); - - /* write operations */ - kn->kn_fop = &netmap_write_filterops; - break; - - default: - if (netmap_verbose) - D("%s kqfilter: invalid filter" ifp->if_xname); - return(EINVAL); - } - - kn->kn_hook = 0;// - knlist_add(&netmap_sc->tun_rsel.si_note, kn, 0); - - return (0); -} -#endif /* NETMAP_KEVENT */ - -/* - * File descriptor's private data destructor. - * - * Call nm_register(ifp,0) to stop netmap mode on the interface and - * revert to normal operation. We expect that np_ifp has not gone. - */ -static void -netmap_dtor(void *data) -{ - struct netmap_priv_d *priv = data; - struct ifnet *ifp = priv->np_ifp; - struct netmap_adapter *na = NA(ifp); - struct netmap_if *nifp = priv->np_nifp; - - if (0) - printf("%s starting for %p ifp %p\n", __FUNCTION__, priv, - priv ? priv->np_ifp : NULL); - - na->nm_lock(ifp->if_softc, NETMAP_CORE_LOCK, 0); - - na->refcount--; - if (na->refcount <= 0) { /* last instance */ - u_int i; - - D("deleting last netmap instance for %s", ifp->if_xname); - /* - * there is a race here with *_netmap_task() and - * netmap_poll(), which don't run under NETMAP_CORE_LOCK. - * na->refcount == 0 && na->ifp->if_capenable & IFCAP_NETMAP - * (aka NETMAP_DELETING(na)) are a unique marker that the - * device is dying. - * Before destroying stuff we sleep a bit, and then complete - * the job. NIOCREG should realize the condition and - * loop until they can continue; the other routines - * should check the condition at entry and quit if - * they cannot run. - */ - na->nm_lock(ifp->if_softc, NETMAP_CORE_UNLOCK, 0); - tsleep(na, 0, "NIOCUNREG", 4); - na->nm_lock(ifp->if_softc, NETMAP_CORE_LOCK, 0); - na->nm_register(ifp, 0); /* off, clear IFCAP_NETMAP */ - /* Wake up any sleeping threads. netmap_poll will - * then return POLLERR - */ - for (i = 0; i < na->num_queues + 2; i++) { - selwakeuppri(&na->tx_rings[i].si, PI_NET); - selwakeuppri(&na->rx_rings[i].si, PI_NET); - } - /* release all buffers */ - NMA_LOCK(); - for (i = 0; i < na->num_queues + 1; i++) { - int j, lim; - struct netmap_ring *ring; - - ND("tx queue %d", i); - ring = na->tx_rings[i].ring; - lim = na->tx_rings[i].nkr_num_slots; - for (j = 0; j < lim; j++) - netmap_free_buf(nifp, ring->slot[j].buf_idx); - - ND("rx queue %d", i); - ring = na->rx_rings[i].ring; - lim = na->rx_rings[i].nkr_num_slots; - for (j = 0; j < lim; j++) - netmap_free_buf(nifp, ring->slot[j].buf_idx); - } - NMA_UNLOCK(); - netmap_free_rings(na); - wakeup(na); - } - netmap_if_free(nifp); - - na->nm_lock(ifp->if_softc, NETMAP_CORE_UNLOCK, 0); - - if_rele(ifp); - - bzero(priv, sizeof(*priv)); /* XXX for safety */ - free(priv, M_DEVBUF); -} - - -/* - * Create and return a new ``netmap_if`` object, and possibly also - * rings and packet buffors. - * - * Return NULL on failure. - */ -static void * -netmap_if_new(const char *ifname, struct netmap_adapter *na) -{ - struct netmap_if *nifp; - struct netmap_ring *ring; - char *buff; - u_int i, len, ofs; - u_int n = na->num_queues + 1; /* shorthand, include stack queue */ - - /* - * the descriptor is followed inline by an array of offsets - * to the tx and rx rings in the shared memory region. - */ - len = sizeof(struct netmap_if) + 2 * n * sizeof(ssize_t); - nifp = netmap_if_malloc(len); - if (nifp == NULL) - return (NULL); - - /* initialize base fields */ - *(int *)(uintptr_t)&nifp->ni_num_queues = na->num_queues; - strncpy(nifp->ni_name, ifname, IFNAMSIZ); - - (na->refcount)++; /* XXX atomic ? we are under lock */ - if (na->refcount > 1) - goto final; - - /* - * If this is the first instance, allocate the shadow rings and - * buffers for this card (one for each hw queue, one for the host). - * The rings are contiguous, but have variable size. - * The entire block is reachable at - * na->tx_rings[0].ring - */ - - len = n * (2 * sizeof(struct netmap_ring) + - (na->num_tx_desc + na->num_rx_desc) * - sizeof(struct netmap_slot) ); - buff = netmap_ring_malloc(len); - if (buff == NULL) { - D("failed to allocate %d bytes for %s shadow ring", - len, ifname); -error: - (na->refcount)--; - netmap_if_free(nifp); - return (NULL); - } - /* do we have the bufers ? we are in need of num_tx_desc buffers for - * each tx ring and num_tx_desc buffers for each rx ring. */ - len = n * (na->num_tx_desc + na->num_rx_desc); - NMA_LOCK(); - if (nm_buf_pool.free < len) { - NMA_UNLOCK(); - netmap_free(buff, "not enough bufs"); - goto error; - } - /* - * in the kring, store the pointers to the shared rings - * and initialize the rings. We are under NMA_LOCK(). - */ - ofs = 0; - for (i = 0; i < n; i++) { - struct netmap_kring *kring; - int numdesc; - - /* Transmit rings */ - kring = &na->tx_rings[i]; - numdesc = na->num_tx_desc; - bzero(kring, sizeof(*kring)); - kring->na = na; - - ring = kring->ring = (struct netmap_ring *)(buff + ofs); - *(ssize_t *)(uintptr_t)&ring->buf_ofs = - nm_buf_pool.base - (char *)ring; - ND("txring[%d] at %p ofs %d", i, ring, ring->buf_ofs); - *(int *)(int *)(uintptr_t)&ring->num_slots = - kring->nkr_num_slots = numdesc; - - /* - * IMPORTANT: - * Always keep one slot empty, so we can detect new - * transmissions comparing cur and nr_hwcur (they are - * the same only if there are no new transmissions). - */ - ring->avail = kring->nr_hwavail = numdesc - 1; - ring->cur = kring->nr_hwcur = 0; - netmap_new_bufs(nifp, ring->slot, numdesc); - - ofs += sizeof(struct netmap_ring) + - numdesc * sizeof(struct netmap_slot); - - /* Receive rings */ - kring = &na->rx_rings[i]; - numdesc = na->num_rx_desc; - bzero(kring, sizeof(*kring)); - kring->na = na; - - ring = kring->ring = (struct netmap_ring *)(buff + ofs); - *(ssize_t *)(uintptr_t)&ring->buf_ofs = - nm_buf_pool.base - (char *)ring; - ND("rxring[%d] at %p offset %d", i, ring, ring->buf_ofs); - *(int *)(int *)(uintptr_t)&ring->num_slots = - kring->nkr_num_slots = numdesc; - ring->cur = kring->nr_hwcur = 0; - ring->avail = kring->nr_hwavail = 0; /* empty */ - netmap_new_bufs(nifp, ring->slot, numdesc); - ofs += sizeof(struct netmap_ring) + - numdesc * sizeof(struct netmap_slot); - } - NMA_UNLOCK(); - for (i = 0; i < n+1; i++) { - // XXX initialize the selrecord structs. - } -final: - /* - * fill the slots for the rx and tx queues. They contain the offset - * between the ring and nifp, so the information is usable in - * userspace to reach the ring from the nifp. - */ - for (i = 0; i < n; i++) { - char *base = (char *)nifp; - *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i] = - (char *)na->tx_rings[i].ring - base; - *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i+n] = - (char *)na->rx_rings[i].ring - base; - } - return (nifp); -} - - -/* - * mmap(2) support for the "netmap" device. - * - * Expose all the memory previously allocated by our custom memory - * allocator: this way the user has only to issue a single mmap(2), and - * can work on all the data structures flawlessly. - * - * Return 0 on success, -1 otherwise. - */ -static int -#if __FreeBSD_version < 900000 -netmap_mmap(__unused struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, - int nprot) -#else -netmap_mmap(__unused struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, - int nprot, __unused vm_memattr_t *memattr) -#endif -{ - if (nprot & PROT_EXEC) - return (-1); // XXX -1 or EINVAL ? - - ND("request for offset 0x%x", (uint32_t)offset); - *paddr = netmap_ofstophys(offset); - - return (0); -} - - -/* - * Handlers for synchronization of the queues from/to the host. - * - * netmap_sync_to_host() passes packets up. We are called from a - * system call in user process context, and the only contention - * can be among multiple user threads erroneously calling - * this routine concurrently. In principle we should not even - * need to lock. - */ -static void -netmap_sync_to_host(struct netmap_adapter *na) -{ - struct netmap_kring *kring = &na->tx_rings[na->num_queues]; - struct netmap_ring *ring = kring->ring; - struct mbuf *head = NULL, *tail = NULL, *m; - u_int k, n, lim = kring->nkr_num_slots - 1; - - k = ring->cur; - if (k > lim) { - netmap_ring_reinit(kring); - return; - } - // na->nm_lock(na->ifp->if_softc, NETMAP_CORE_LOCK, 0); - - /* Take packets from hwcur to cur and pass them up. - * In case of no buffers we give up. At the end of the loop, - * the queue is drained in all cases. - */ - for (n = kring->nr_hwcur; n != k;) { - struct netmap_slot *slot = &ring->slot[n]; - - n = (n == lim) ? 0 : n + 1; - if (slot->len < 14 || slot->len > NETMAP_BUF_SIZE) { - D("bad pkt at %d len %d", n, slot->len); - continue; - } - m = m_devget(NMB(slot), slot->len, 0, na->ifp, NULL); - - if (m == NULL) - break; - if (tail) - tail->m_nextpkt = m; - else - head = m; - tail = m; - m->m_nextpkt = NULL; - } - kring->nr_hwcur = k; - kring->nr_hwavail = ring->avail = lim; - // na->nm_lock(na->ifp->if_softc, NETMAP_CORE_UNLOCK, 0); - - /* send packets up, outside the lock */ - while ((m = head) != NULL) { - head = head->m_nextpkt; - m->m_nextpkt = NULL; - m->m_pkthdr.rcvif = na->ifp; - if (netmap_verbose & NM_VERB_HOST) - D("sending up pkt %p size %d", m, m->m_pkthdr.len); - (na->ifp->if_input)(na->ifp, m); - } -} - -/* - * rxsync backend for packets coming from the host stack. - * They have been put in the queue by netmap_start() so we - * need to protect access to the kring using a lock. - * - * This routine also does the selrecord if called from the poll handler - * (we know because td != NULL). - */ -static void -netmap_sync_from_host(struct netmap_adapter *na, struct thread *td) -{ - struct netmap_kring *kring = &na->rx_rings[na->num_queues]; - struct netmap_ring *ring = kring->ring; - int error = 1, delta; - u_int k = ring->cur, lim = kring->nkr_num_slots; - - na->nm_lock(na->ifp->if_softc, NETMAP_CORE_LOCK, 0); - if (k >= lim) /* bad value */ - goto done; - delta = k - kring->nr_hwcur; - if (delta < 0) - delta += lim; - kring->nr_hwavail -= delta; - if (kring->nr_hwavail < 0) /* error */ - goto done; - kring->nr_hwcur = k; - error = 0; - k = ring->avail = kring->nr_hwavail; - if (k == 0 && td) - selrecord(td, &kring->si); - if (k && (netmap_verbose & NM_VERB_HOST)) - D("%d pkts from stack", k); -done: - na->nm_lock(na->ifp->if_softc, NETMAP_CORE_UNLOCK, 0); - if (error) - netmap_ring_reinit(kring); -} - - -/* - * get a refcounted reference to an interface. - * Return ENXIO if the interface does not exist, EINVAL if netmap - * is not supported by the interface. - * If successful, hold a reference. - */ -static int -get_ifp(const char *name, struct ifnet **ifp) -{ - *ifp = ifunit_ref(name); - if (*ifp == NULL) - return (ENXIO); - /* can do this if the capability exists and if_pspare[0] - * points to the netmap descriptor. - */ - if ((*ifp)->if_capabilities & IFCAP_NETMAP && NA(*ifp)) - return 0; /* valid pointer, we hold the refcount */ - if_rele(*ifp); - return EINVAL; // not NETMAP capable -} - - -/* - * Error routine called when txsync/rxsync detects an error. - * Can't do much more than resetting cur = hwcur, avail = hwavail. - * Return 1 on reinit. - * - * This routine is only called by the upper half of the kernel. - * It only reads hwcur (which is changed only by the upper half, too) - * and hwavail (which may be changed by the lower half, but only on - * a tx ring and only to increase it, so any error will be recovered - * on the next call). For the above, we don't strictly need to call - * it under lock. - */ -int -netmap_ring_reinit(struct netmap_kring *kring) -{ - struct netmap_ring *ring = kring->ring; - u_int i, lim = kring->nkr_num_slots - 1; - int errors = 0; - - D("called for %s", kring->na->ifp->if_xname); - if (ring->cur > lim) - errors++; - for (i = 0; i <= lim; i++) { - u_int idx = ring->slot[i].buf_idx; - u_int len = ring->slot[i].len; - if (idx < 2 || idx >= netmap_total_buffers) { - if (!errors++) - D("bad buffer at slot %d idx %d len %d ", i, idx, len); - ring->slot[i].buf_idx = 0; - ring->slot[i].len = 0; - } else if (len > NETMAP_BUF_SIZE) { - ring->slot[i].len = 0; - if (!errors++) - D("bad len %d at slot %d idx %d", - len, i, idx); - } - } - if (errors) { - int pos = kring - kring->na->tx_rings; - int n = kring->na->num_queues + 2; - - D("total %d errors", errors); - errors++; - D("%s %s[%d] reinit, cur %d -> %d avail %d -> %d", - kring->na->ifp->if_xname, - pos < n ? "TX" : "RX", pos < n ? pos : pos - n, - ring->cur, kring->nr_hwcur, - ring->avail, kring->nr_hwavail); - ring->cur = kring->nr_hwcur; - ring->avail = kring->nr_hwavail; - } - return (errors ? 1 : 0); -} - - -/* - * Set the ring ID. For devices with a single queue, a request - * for all rings is the same as a single ring. - */ -static int -netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid) -{ - struct ifnet *ifp = priv->np_ifp; - struct netmap_adapter *na = NA(ifp); - void *adapter = na->ifp->if_softc; /* shorthand */ - u_int i = ringid & NETMAP_RING_MASK; - /* first time we don't lock */ - int need_lock = (priv->np_qfirst != priv->np_qlast); - - if ( (ringid & NETMAP_HW_RING) && i >= na->num_queues) { - D("invalid ring id %d", i); - return (EINVAL); - } - if (need_lock) - na->nm_lock(adapter, NETMAP_CORE_LOCK, 0); - priv->np_ringid = ringid; - if (ringid & NETMAP_SW_RING) { - priv->np_qfirst = na->num_queues; - priv->np_qlast = na->num_queues + 1; - } else if (ringid & NETMAP_HW_RING) { - priv->np_qfirst = i; - priv->np_qlast = i + 1; - } else { - priv->np_qfirst = 0; - priv->np_qlast = na->num_queues; - } - priv->np_txpoll = (ringid & NETMAP_NO_TX_POLL) ? 0 : 1; - if (need_lock) - na->nm_lock(adapter, NETMAP_CORE_UNLOCK, 0); - if (ringid & NETMAP_SW_RING) - D("ringid %s set to SW RING", ifp->if_xname); - else if (ringid & NETMAP_HW_RING) - D("ringid %s set to HW RING %d", ifp->if_xname, - priv->np_qfirst); - else - D("ringid %s set to all %d HW RINGS", ifp->if_xname, - priv->np_qlast); - return 0; -} - -/* - * ioctl(2) support for the "netmap" device. - * - * Following a list of accepted commands: - * - NIOCGINFO - * - SIOCGIFADDR just for convenience - * - NIOCREGIF - * - NIOCUNREGIF - * - NIOCTXSYNC - * - NIOCRXSYNC - * - * Return 0 on success, errno otherwise. - */ -static int -netmap_ioctl(__unused struct cdev *dev, u_long cmd, caddr_t data, - __unused int fflag, struct thread *td) -{ - struct netmap_priv_d *priv = NULL; - struct ifnet *ifp; - struct nmreq *nmr = (struct nmreq *) data; - struct netmap_adapter *na; - void *adapter; - int error; - u_int i; - struct netmap_if *nifp; - - CURVNET_SET(TD_TO_VNET(td)); - - error = devfs_get_cdevpriv((void **)&priv); - if (error != ENOENT && error != 0) { - CURVNET_RESTORE(); - return (error); - } - - error = 0; /* Could be ENOENT */ - switch (cmd) { - case NIOCGINFO: /* return capabilities etc */ - /* memsize is always valid */ - nmr->nr_memsize = netmap_mem_d->nm_totalsize; - nmr->nr_offset = 0; - nmr->nr_numrings = 0; - nmr->nr_numslots = 0; - if (nmr->nr_name[0] == '\0') /* just get memory info */ - break; - error = get_ifp(nmr->nr_name, &ifp); /* get a refcount */ - if (error) - break; - na = NA(ifp); /* retrieve netmap_adapter */ - nmr->nr_numrings = na->num_queues; - nmr->nr_numslots = na->num_tx_desc; - if_rele(ifp); /* return the refcount */ - break; - - case NIOCREGIF: - if (priv != NULL) { /* thread already registered */ - error = netmap_set_ringid(priv, nmr->nr_ringid); - break; - } - /* find the interface and a reference */ - error = get_ifp(nmr->nr_name, &ifp); /* keep reference */ - if (error) - break; - na = NA(ifp); /* retrieve netmap adapter */ - adapter = na->ifp->if_softc; /* shorthand */ - /* - * Allocate the private per-thread structure. - * XXX perhaps we can use a blocking malloc ? - */ - priv = malloc(sizeof(struct netmap_priv_d), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (priv == NULL) { - error = ENOMEM; - if_rele(ifp); /* return the refcount */ - break; - } - - - for (i = 10; i > 0; i--) { - na->nm_lock(adapter, NETMAP_CORE_LOCK, 0); - if (!NETMAP_DELETING(na)) - break; - na->nm_lock(adapter, NETMAP_CORE_UNLOCK, 0); - tsleep(na, 0, "NIOCREGIF", hz/10); - } - if (i == 0) { - D("too many NIOCREGIF attempts, give up"); - error = EINVAL; - free(priv, M_DEVBUF); - if_rele(ifp); /* return the refcount */ - break; - } - - priv->np_ifp = ifp; /* store the reference */ - error = netmap_set_ringid(priv, nmr->nr_ringid); - if (error) - goto error; - priv->np_nifp = nifp = netmap_if_new(nmr->nr_name, na); - if (nifp == NULL) { /* allocation failed */ - error = ENOMEM; - } else if (ifp->if_capenable & IFCAP_NETMAP) { - /* was already set */ - } else { - /* Otherwise set the card in netmap mode - * and make it use the shared buffers. - */ - error = na->nm_register(ifp, 1); /* mode on */ - if (error) { - /* - * do something similar to netmap_dtor(). - */ - netmap_free_rings(na); - // XXX tx_rings is inline, must not be freed. - // free(na->tx_rings, M_DEVBUF); // XXX wrong ? - na->tx_rings = na->rx_rings = NULL; - na->refcount--; - netmap_if_free(nifp); - nifp = NULL; - } - } - - if (error) { /* reg. failed, release priv and ref */ -error: - na->nm_lock(adapter, NETMAP_CORE_UNLOCK, 0); - free(priv, M_DEVBUF); - if_rele(ifp); /* return the refcount */ - break; - } - - na->nm_lock(adapter, NETMAP_CORE_UNLOCK, 0); - error = devfs_set_cdevpriv(priv, netmap_dtor); - - if (error != 0) { - /* could not assign the private storage for the - * thread, call the destructor explicitly. - */ - netmap_dtor(priv); - break; - } - - /* return the offset of the netmap_if object */ - nmr->nr_numrings = na->num_queues; - nmr->nr_numslots = na->num_tx_desc; - nmr->nr_memsize = netmap_mem_d->nm_totalsize; - nmr->nr_offset = netmap_if_offset(nifp); - break; - - case NIOCUNREGIF: - if (priv == NULL) { - error = ENXIO; - break; - } - - /* the interface is unregistered inside the - destructor of the private data. */ - devfs_clear_cdevpriv(); - break; - - case NIOCTXSYNC: - case NIOCRXSYNC: - if (priv == NULL) { - error = ENXIO; - break; - } - ifp = priv->np_ifp; /* we have a reference */ - na = NA(ifp); /* retrieve netmap adapter */ - adapter = ifp->if_softc; /* shorthand */ - - if (priv->np_qfirst == na->num_queues) { - /* queues to/from host */ - if (cmd == NIOCTXSYNC) - netmap_sync_to_host(na); - else - netmap_sync_from_host(na, NULL); - break; - } - - for (i = priv->np_qfirst; i < priv->np_qlast; i++) { - if (cmd == NIOCTXSYNC) { - struct netmap_kring *kring = &na->tx_rings[i]; - if (netmap_verbose & NM_VERB_TXSYNC) - D("sync tx ring %d cur %d hwcur %d", - i, kring->ring->cur, - kring->nr_hwcur); - na->nm_txsync(adapter, i, 1 /* do lock */); - if (netmap_verbose & NM_VERB_TXSYNC) - D("after sync tx ring %d cur %d hwcur %d", - i, kring->ring->cur, - kring->nr_hwcur); - } else { - na->nm_rxsync(adapter, i, 1 /* do lock */); - microtime(&na->rx_rings[i].ring->ts); - } - } - - break; - - case BIOCIMMEDIATE: - case BIOCGHDRCMPLT: - case BIOCSHDRCMPLT: - case BIOCSSEESENT: - D("ignore BIOCIMMEDIATE/BIOCSHDRCMPLT/BIOCSHDRCMPLT/BIOCSSEESENT"); - break; - - default: - { - /* - * allow device calls - */ - struct socket so; - bzero(&so, sizeof(so)); - error = get_ifp(nmr->nr_name, &ifp); /* keep reference */ - if (error) - break; - so.so_vnet = ifp->if_vnet; - // so->so_proto not null. - error = ifioctl(&so, cmd, data, td); - if_rele(ifp); - } - } - - CURVNET_RESTORE(); - return (error); -} - - -/* - * select(2) and poll(2) handlers for the "netmap" device. - * - * Can be called for one or more queues. - * Return true the event mask corresponding to ready events. - * If there are no ready events, do a selrecord on either individual - * selfd or on the global one. - * Device-dependent parts (locking and sync of tx/rx rings) - * are done through callbacks. - */ -static int -netmap_poll(__unused struct cdev *dev, int events, struct thread *td) -{ - struct netmap_priv_d *priv = NULL; - struct netmap_adapter *na; - struct ifnet *ifp; - struct netmap_kring *kring; - u_int core_lock, i, check_all, want_tx, want_rx, revents = 0; - void *adapter; - enum {NO_CL, NEED_CL, LOCKED_CL }; /* see below */ - - if (devfs_get_cdevpriv((void **)&priv) != 0 || priv == NULL) - return POLLERR; - - ifp = priv->np_ifp; - // XXX check for deleting() ? - if ( (ifp->if_capenable & IFCAP_NETMAP) == 0) - return POLLERR; - - if (netmap_verbose & 0x8000) - D("device %s events 0x%x", ifp->if_xname, events); - want_tx = events & (POLLOUT | POLLWRNORM); - want_rx = events & (POLLIN | POLLRDNORM); - - adapter = ifp->if_softc; - na = NA(ifp); /* retrieve netmap adapter */ - - /* how many queues we are scanning */ - i = priv->np_qfirst; - if (i == na->num_queues) { /* from/to host */ - if (priv->np_txpoll || want_tx) { - /* push any packets up, then we are always ready */ - kring = &na->tx_rings[i]; - netmap_sync_to_host(na); - revents |= want_tx; - } - if (want_rx) { - kring = &na->rx_rings[i]; - if (kring->ring->avail == 0) - netmap_sync_from_host(na, td); - if (kring->ring->avail > 0) { - revents |= want_rx; - } - } - return (revents); - } - - /* - * check_all is set if the card has more than one queue and - * the client is polling all of them. If true, we sleep on - * the "global" selfd, otherwise we sleep on individual selfd - * (we can only sleep on one of them per direction). - * The interrupt routine in the driver should always wake on - * the individual selfd, and also on the global one if the card - * has more than one ring. - * - * If the card has only one lock, we just use that. - * If the card has separate ring locks, we just use those - * unless we are doing check_all, in which case the whole - * loop is wrapped by the global lock. - * We acquire locks only when necessary: if poll is called - * when buffers are available, we can just return without locks. - * - * rxsync() is only called if we run out of buffers on a POLLIN. - * txsync() is called if we run out of buffers on POLLOUT, or - * there are pending packets to send. The latter can be disabled - * passing NETMAP_NO_TX_POLL in the NIOCREG call. - */ - check_all = (i + 1 != priv->np_qlast); - - /* - * core_lock indicates what to do with the core lock. - * The core lock is used when either the card has no individual - * locks, or it has individual locks but we are cheking all - * rings so we need the core lock to avoid missing wakeup events. - * - * It has three possible states: - * NO_CL we don't need to use the core lock, e.g. - * because we are protected by individual locks. - * NEED_CL we need the core lock. In this case, when we - * call the lock routine, move to LOCKED_CL - * to remember to release the lock once done. - * LOCKED_CL core lock is set, so we need to release it. - */ - core_lock = (check_all || !na->separate_locks) ? NEED_CL : NO_CL; - /* - * We start with a lock free round which is good if we have - * data available. If this fails, then lock and call the sync - * routines. - */ - for (i = priv->np_qfirst; want_rx && i < priv->np_qlast; i++) { - kring = &na->rx_rings[i]; - if (kring->ring->avail > 0) { - revents |= want_rx; - want_rx = 0; /* also breaks the loop */ - } - } - for (i = priv->np_qfirst; want_tx && i < priv->np_qlast; i++) { - kring = &na->tx_rings[i]; - if (kring->ring->avail > 0) { - revents |= want_tx; - want_tx = 0; /* also breaks the loop */ - } - } - - /* - * If we to push packets out (priv->np_txpoll) or want_tx is - * still set, we do need to run the txsync calls (on all rings, - * to avoid that the tx rings stall). - */ - if (priv->np_txpoll || want_tx) { - for (i = priv->np_qfirst; i < priv->np_qlast; i++) { - kring = &na->tx_rings[i]; - if (!want_tx && kring->ring->cur == kring->nr_hwcur) - continue; - if (core_lock == NEED_CL) { - na->nm_lock(adapter, NETMAP_CORE_LOCK, 0); - core_lock = LOCKED_CL; - } - if (na->separate_locks) - na->nm_lock(adapter, NETMAP_TX_LOCK, i); - if (netmap_verbose & NM_VERB_TXSYNC) - D("send %d on %s %d", - kring->ring->cur, - ifp->if_xname, i); - if (na->nm_txsync(adapter, i, 0 /* no lock */)) - revents |= POLLERR; - - if (want_tx) { - if (kring->ring->avail > 0) { - /* stop at the first ring. We don't risk - * starvation. - */ - revents |= want_tx; - want_tx = 0; - } else if (!check_all) - selrecord(td, &kring->si); - } - if (na->separate_locks) - na->nm_lock(adapter, NETMAP_TX_UNLOCK, i); - } - } - - /* - * now if want_rx is still set we need to lock and rxsync. - * Do it on all rings because otherwise we starve. - */ - if (want_rx) { - for (i = priv->np_qfirst; i < priv->np_qlast; i++) { - kring = &na->rx_rings[i]; - if (core_lock == NEED_CL) { - na->nm_lock(adapter, NETMAP_CORE_LOCK, 0); - core_lock = LOCKED_CL; - } - if (na->separate_locks) - na->nm_lock(adapter, NETMAP_RX_LOCK, i); - - if (na->nm_rxsync(adapter, i, 0 /* no lock */)) - revents |= POLLERR; - if (no_timestamp == 0 || - kring->ring->flags & NR_TIMESTAMP) - microtime(&kring->ring->ts); - - if (kring->ring->avail > 0) - revents |= want_rx; - else if (!check_all) - selrecord(td, &kring->si); - if (na->separate_locks) - na->nm_lock(adapter, NETMAP_RX_UNLOCK, i); - } - } - if (check_all && revents == 0) { - i = na->num_queues + 1; /* the global queue */ - if (want_tx) - selrecord(td, &na->tx_rings[i].si); - if (want_rx) - selrecord(td, &na->rx_rings[i].si); - } - if (core_lock == LOCKED_CL) - na->nm_lock(adapter, NETMAP_CORE_UNLOCK, 0); - - return (revents); -} - -/*------- driver support routines ------*/ - -/* - * Initialize a ``netmap_adapter`` object created by driver on attach. - * We allocate a block of memory with room for a struct netmap_adapter - * plus two sets of N+2 struct netmap_kring (where N is the number - * of hardware rings): - * krings 0..N-1 are for the hardware queues. - * kring N is for the host stack queue - * kring N+1 is only used for the selinfo for all queues. - * Return 0 on success, ENOMEM otherwise. - */ -int -netmap_attach(struct netmap_adapter *na, int num_queues) -{ - int n = num_queues + 2; - int size = sizeof(*na) + 2 * n * sizeof(struct netmap_kring); - void *buf; - struct ifnet *ifp = na->ifp; - - if (ifp == NULL) { - D("ifp not set, giving up"); - return EINVAL; - } - na->refcount = 0; - na->num_queues = num_queues; - - buf = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); - if (buf) { - WNA(ifp) = buf; - na->tx_rings = (void *)((char *)buf + sizeof(*na)); - na->rx_rings = na->tx_rings + n; - bcopy(na, buf, sizeof(*na)); - ifp->if_capabilities |= IFCAP_NETMAP; - } - D("%s for %s", buf ? "ok" : "failed", ifp->if_xname); - - return (buf ? 0 : ENOMEM); -} - - -/* - * Free the allocated memory linked to the given ``netmap_adapter`` - * object. - */ -void -netmap_detach(struct ifnet *ifp) -{ - u_int i; - struct netmap_adapter *na = NA(ifp); - - if (!na) - return; - - for (i = 0; i < na->num_queues + 2; i++) { - knlist_destroy(&na->tx_rings[i].si.si_note); - knlist_destroy(&na->rx_rings[i].si.si_note); - } - bzero(na, sizeof(*na)); - WNA(ifp) = NULL; - free(na, M_DEVBUF); -} - - -/* - * Intercept packets from the network stack and pass them - * to netmap as incoming packets on the 'software' ring. - * We are not locked when called. - */ -int -netmap_start(struct ifnet *ifp, struct mbuf *m) -{ - struct netmap_adapter *na = NA(ifp); - struct netmap_kring *kring = &na->rx_rings[na->num_queues]; - u_int i, len = m->m_pkthdr.len; - int error = EBUSY, lim = kring->nkr_num_slots - 1; - struct netmap_slot *slot; - - if (netmap_verbose & NM_VERB_HOST) - D("%s packet %d len %d from the stack", ifp->if_xname, - kring->nr_hwcur + kring->nr_hwavail, len); - na->nm_lock(ifp->if_softc, NETMAP_CORE_LOCK, 0); - if (kring->nr_hwavail >= lim) { - D("stack ring %s full\n", ifp->if_xname); - goto done; /* no space */ - } - if (len > na->buff_size) { - D("drop packet size %d > %d", len, na->buff_size); - goto done; /* too long for us */ - } - - /* compute the insert position */ - i = kring->nr_hwcur + kring->nr_hwavail; - if (i > lim) - i -= lim + 1; - slot = &kring->ring->slot[i]; - m_copydata(m, 0, len, NMB(slot)); - slot->len = len; - kring->nr_hwavail++; - if (netmap_verbose & NM_VERB_HOST) - D("wake up host ring %s %d", na->ifp->if_xname, na->num_queues); - selwakeuppri(&kring->si, PI_NET); - error = 0; -done: - na->nm_lock(ifp->if_softc, NETMAP_CORE_UNLOCK, 0); - - /* release the mbuf in either cases of success or failure. As an - * alternative, put the mbuf in a free list and free the list - * only when really necessary. - */ - m_freem(m); - - return (error); -} - - -/* - * netmap_reset() is called by the driver routines when reinitializing - * a ring. The driver is in charge of locking to protect the kring. - * If netmap mode is not set just return NULL. - */ -struct netmap_slot * -netmap_reset(struct netmap_adapter *na, enum txrx tx, int n, - u_int new_cur) -{ - struct netmap_kring *kring; - struct netmap_ring *ring; - int new_hwofs, lim; - - if (na == NULL) - return NULL; /* no netmap support here */ - if (!(na->ifp->if_capenable & IFCAP_NETMAP)) - return NULL; /* nothing to reinitialize */ - kring = tx == NR_TX ? na->tx_rings + n : na->rx_rings + n; - ring = kring->ring; - lim = kring->nkr_num_slots - 1; - - if (tx == NR_TX) - new_hwofs = kring->nr_hwcur - new_cur; - else - new_hwofs = kring->nr_hwcur + kring->nr_hwavail - new_cur; - if (new_hwofs > lim) - new_hwofs -= lim + 1; - - /* Alwayws set the new offset value and realign the ring. */ - kring->nkr_hwofs = new_hwofs; - if (tx == NR_TX) - kring->nr_hwavail = kring->nkr_num_slots - 1; - D("new hwofs %d on %s %s[%d]", - kring->nkr_hwofs, na->ifp->if_xname, - tx == NR_TX ? "TX" : "RX", n); - - /* - * We do the wakeup here, but the ring is not yet reconfigured. - * However, we are under lock so there are no races. - */ - selwakeuppri(&kring->si, PI_NET); - selwakeuppri(&kring[na->num_queues + 1 - n].si, PI_NET); - return kring->ring->slot; -} - /*------ netmap memory allocator -------*/ /* @@ -1502,6 +366,142 @@ netmap_free(void *addr, const char *msg) } +/* + * Create and return a new ``netmap_if`` object, and possibly also + * rings and packet buffors. + * + * Return NULL on failure. + */ +static void * +netmap_if_new(const char *ifname, struct netmap_adapter *na) +{ + struct netmap_if *nifp; + struct netmap_ring *ring; + char *buff; + u_int i, len, ofs; + u_int n = na->num_queues + 1; /* shorthand, include stack queue */ + + /* + * the descriptor is followed inline by an array of offsets + * to the tx and rx rings in the shared memory region. + */ + len = sizeof(struct netmap_if) + 2 * n * sizeof(ssize_t); + nifp = netmap_if_malloc(len); + if (nifp == NULL) + return (NULL); + + /* initialize base fields */ + *(int *)(uintptr_t)&nifp->ni_num_queues = na->num_queues; + strncpy(nifp->ni_name, ifname, IFNAMSIZ); + + (na->refcount)++; /* XXX atomic ? we are under lock */ + if (na->refcount > 1) + goto final; + + /* + * If this is the first instance, allocate the shadow rings and + * buffers for this card (one for each hw queue, one for the host). + * The rings are contiguous, but have variable size. + * The entire block is reachable at + * na->tx_rings[0].ring + */ + + len = n * (2 * sizeof(struct netmap_ring) + + (na->num_tx_desc + na->num_rx_desc) * + sizeof(struct netmap_slot) ); + buff = netmap_ring_malloc(len); + if (buff == NULL) { + D("failed to allocate %d bytes for %s shadow ring", + len, ifname); +error: + (na->refcount)--; + netmap_if_free(nifp); + return (NULL); + } + /* do we have the bufers ? we are in need of num_tx_desc buffers for + * each tx ring and num_tx_desc buffers for each rx ring. */ + len = n * (na->num_tx_desc + na->num_rx_desc); + NMA_LOCK(); + if (nm_buf_pool.free < len) { + NMA_UNLOCK(); + netmap_free(buff, "not enough bufs"); + goto error; + } + /* + * in the kring, store the pointers to the shared rings + * and initialize the rings. We are under NMA_LOCK(). + */ + ofs = 0; + for (i = 0; i < n; i++) { + struct netmap_kring *kring; + int numdesc; + + /* Transmit rings */ + kring = &na->tx_rings[i]; + numdesc = na->num_tx_desc; + bzero(kring, sizeof(*kring)); + kring->na = na; + + ring = kring->ring = (struct netmap_ring *)(buff + ofs); + *(ssize_t *)(uintptr_t)&ring->buf_ofs = + nm_buf_pool.base - (char *)ring; + ND("txring[%d] at %p ofs %d", i, ring, ring->buf_ofs); + *(uint32_t *)(uintptr_t)&ring->num_slots = + kring->nkr_num_slots = numdesc; + + /* + * IMPORTANT: + * Always keep one slot empty, so we can detect new + * transmissions comparing cur and nr_hwcur (they are + * the same only if there are no new transmissions). + */ + ring->avail = kring->nr_hwavail = numdesc - 1; + ring->cur = kring->nr_hwcur = 0; + *(uint16_t *)(uintptr_t)&ring->nr_buf_size = NETMAP_BUF_SIZE; + netmap_new_bufs(nifp, ring->slot, numdesc); + + ofs += sizeof(struct netmap_ring) + + numdesc * sizeof(struct netmap_slot); + + /* Receive rings */ + kring = &na->rx_rings[i]; + numdesc = na->num_rx_desc; + bzero(kring, sizeof(*kring)); + kring->na = na; + + ring = kring->ring = (struct netmap_ring *)(buff + ofs); + *(ssize_t *)(uintptr_t)&ring->buf_ofs = + nm_buf_pool.base - (char *)ring; + ND("rxring[%d] at %p offset %d", i, ring, ring->buf_ofs); + *(uint32_t *)(uintptr_t)&ring->num_slots = + kring->nkr_num_slots = numdesc; + ring->cur = kring->nr_hwcur = 0; + ring->avail = kring->nr_hwavail = 0; /* empty */ + *(uint16_t *)(uintptr_t)&ring->nr_buf_size = NETMAP_BUF_SIZE; + netmap_new_bufs(nifp, ring->slot, numdesc); + ofs += sizeof(struct netmap_ring) + + numdesc * sizeof(struct netmap_slot); + } + NMA_UNLOCK(); + for (i = 0; i < n+1; i++) { + // XXX initialize the selrecord structs. + } +final: + /* + * fill the slots for the rx and tx queues. They contain the offset + * between the ring and nifp, so the information is usable in + * userspace to reach the ring from the nifp. + */ + for (i = 0; i < n; i++) { + char *base = (char *)nifp; + *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i] = + (char *)na->tx_rings[i].ring - base; + *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i+n] = + (char *)na->rx_rings[i].ring - base; + } + return (nifp); +} + /* * Initialize the memory allocator. * @@ -1620,8 +620,1117 @@ netmap_memory_fini(void) // XXX mutex_destroy(nm_mtx); free(netmap_mem_d, M_NETMAP); } +/*------------- end of memory allocator -----------------*/ +/* Structure associated to each thread which registered an interface. */ +struct netmap_priv_d { + struct netmap_if *np_nifp; /* netmap interface descriptor. */ + + struct ifnet *np_ifp; /* device for which we hold a reference */ + int np_ringid; /* from the ioctl */ + u_int np_qfirst, np_qlast; /* range of rings to scan */ + uint16_t np_txpoll; +}; + + +static struct cdev *netmap_dev; /* /dev/netmap character device. */ + + +static d_mmap_t netmap_mmap; +static d_ioctl_t netmap_ioctl; +static d_poll_t netmap_poll; + +#ifdef NETMAP_KEVENT +static d_kqfilter_t netmap_kqfilter; +#endif + +static struct cdevsw netmap_cdevsw = { + .d_version = D_VERSION, + .d_name = "netmap", + .d_mmap = netmap_mmap, + .d_ioctl = netmap_ioctl, + .d_poll = netmap_poll, +#ifdef NETMAP_KEVENT + .d_kqfilter = netmap_kqfilter, +#endif +}; + +#ifdef NETMAP_KEVENT +static int netmap_kqread(struct knote *, long); +static int netmap_kqwrite(struct knote *, long); +static void netmap_kqdetach(struct knote *); + +static struct filterops netmap_read_filterops = { + .f_isfd = 1, + .f_attach = NULL, + .f_detach = netmap_kqdetach, + .f_event = netmap_kqread, +}; + +static struct filterops netmap_write_filterops = { + .f_isfd = 1, + .f_attach = NULL, + .f_detach = netmap_kqdetach, + .f_event = netmap_kqwrite, +}; + +/* + * support for the kevent() system call. + * + * This is the kevent filter, and is executed each time a new event + * is triggered on the device. This function execute some operation + * depending on the received filter. + * + * The implementation should test the filters and should implement + * filter operations we are interested on (a full list in /sys/event.h). + * + * On a match we should: + * - set kn->kn_fop + * - set kn->kn_hook + * - call knlist_add() to deliver the event to the application. + * + * Return 0 if the event should be delivered to the application. + */ +static int +netmap_kqfilter(struct cdev *dev, struct knote *kn) +{ + /* declare variables needed to read/write */ + + switch(kn->kn_filter) { + case EVFILT_READ: + if (netmap_verbose) + D("%s kqfilter: EVFILT_READ" ifp->if_xname); + + /* read operations */ + kn->kn_fop = &netmap_read_filterops; + break; + + case EVFILT_WRITE: + if (netmap_verbose) + D("%s kqfilter: EVFILT_WRITE" ifp->if_xname); + + /* write operations */ + kn->kn_fop = &netmap_write_filterops; + break; + + default: + if (netmap_verbose) + D("%s kqfilter: invalid filter" ifp->if_xname); + return(EINVAL); + } + + kn->kn_hook = 0;// + knlist_add(&netmap_sc->tun_rsel.si_note, kn, 0); + + return (0); +} +#endif /* NETMAP_KEVENT */ + + +/* + * File descriptor's private data destructor. + * + * Call nm_register(ifp,0) to stop netmap mode on the interface and + * revert to normal operation. We expect that np_ifp has not gone. + */ +static void +netmap_dtor_locked(void *data) +{ + struct netmap_priv_d *priv = data; + struct ifnet *ifp = priv->np_ifp; + struct netmap_adapter *na = NA(ifp); + struct netmap_if *nifp = priv->np_nifp; + + na->refcount--; + if (na->refcount <= 0) { /* last instance */ + u_int i; + + D("deleting last netmap instance for %s", ifp->if_xname); + /* + * there is a race here with *_netmap_task() and + * netmap_poll(), which don't run under NETMAP_REG_LOCK. + * na->refcount == 0 && na->ifp->if_capenable & IFCAP_NETMAP + * (aka NETMAP_DELETING(na)) are a unique marker that the + * device is dying. + * Before destroying stuff we sleep a bit, and then complete + * the job. NIOCREG should realize the condition and + * loop until they can continue; the other routines + * should check the condition at entry and quit if + * they cannot run. + */ + na->nm_lock(ifp, NETMAP_REG_UNLOCK, 0); + tsleep(na, 0, "NIOCUNREG", 4); + na->nm_lock(ifp, NETMAP_REG_LOCK, 0); + na->nm_register(ifp, 0); /* off, clear IFCAP_NETMAP */ + /* Wake up any sleeping threads. netmap_poll will + * then return POLLERR + */ + for (i = 0; i < na->num_queues + 2; i++) { + selwakeuppri(&na->tx_rings[i].si, PI_NET); + selwakeuppri(&na->rx_rings[i].si, PI_NET); + } + /* release all buffers */ + NMA_LOCK(); + for (i = 0; i < na->num_queues + 1; i++) { + int j, lim; + struct netmap_ring *ring; + + ND("tx queue %d", i); + ring = na->tx_rings[i].ring; + lim = na->tx_rings[i].nkr_num_slots; + for (j = 0; j < lim; j++) + netmap_free_buf(nifp, ring->slot[j].buf_idx); + + ND("rx queue %d", i); + ring = na->rx_rings[i].ring; + lim = na->rx_rings[i].nkr_num_slots; + for (j = 0; j < lim; j++) + netmap_free_buf(nifp, ring->slot[j].buf_idx); + } + NMA_UNLOCK(); + netmap_free_rings(na); + wakeup(na); + } + netmap_if_free(nifp); +} + + +static void +netmap_dtor(void *data) +{ + struct netmap_priv_d *priv = data; + struct ifnet *ifp = priv->np_ifp; + struct netmap_adapter *na = NA(ifp); + + na->nm_lock(ifp, NETMAP_REG_LOCK, 0); + netmap_dtor_locked(data); + na->nm_lock(ifp, NETMAP_REG_UNLOCK, 0); + + if_rele(ifp); + bzero(priv, sizeof(*priv)); /* XXX for safety */ + free(priv, M_DEVBUF); +} + + +/* + * mmap(2) support for the "netmap" device. + * + * Expose all the memory previously allocated by our custom memory + * allocator: this way the user has only to issue a single mmap(2), and + * can work on all the data structures flawlessly. + * + * Return 0 on success, -1 otherwise. + */ +static int +#if __FreeBSD_version < 900000 +netmap_mmap(__unused struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, + int nprot) +#else +netmap_mmap(__unused struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, + int nprot, __unused vm_memattr_t *memattr) +#endif +{ + if (nprot & PROT_EXEC) + return (-1); // XXX -1 or EINVAL ? + + ND("request for offset 0x%x", (uint32_t)offset); + *paddr = netmap_ofstophys(offset); + + return (0); +} + + +/* + * Handlers for synchronization of the queues from/to the host. + * + * netmap_sync_to_host() passes packets up. We are called from a + * system call in user process context, and the only contention + * can be among multiple user threads erroneously calling + * this routine concurrently. In principle we should not even + * need to lock. + */ +static void +netmap_sync_to_host(struct netmap_adapter *na) +{ + struct netmap_kring *kring = &na->tx_rings[na->num_queues]; + struct netmap_ring *ring = kring->ring; + struct mbuf *head = NULL, *tail = NULL, *m; + u_int k, n, lim = kring->nkr_num_slots - 1; + + k = ring->cur; + if (k > lim) { + netmap_ring_reinit(kring); + return; + } + // na->nm_lock(na->ifp, NETMAP_CORE_LOCK, 0); + + /* Take packets from hwcur to cur and pass them up. + * In case of no buffers we give up. At the end of the loop, + * the queue is drained in all cases. + */ + for (n = kring->nr_hwcur; n != k;) { + struct netmap_slot *slot = &ring->slot[n]; + + n = (n == lim) ? 0 : n + 1; + if (slot->len < 14 || slot->len > NETMAP_BUF_SIZE) { + D("bad pkt at %d len %d", n, slot->len); + continue; + } + m = m_devget(NMB(slot), slot->len, 0, na->ifp, NULL); + + if (m == NULL) + break; + if (tail) + tail->m_nextpkt = m; + else + head = m; + tail = m; + m->m_nextpkt = NULL; + } + kring->nr_hwcur = k; + kring->nr_hwavail = ring->avail = lim; + // na->nm_lock(na->ifp, NETMAP_CORE_UNLOCK, 0); + + /* send packets up, outside the lock */ + while ((m = head) != NULL) { + head = head->m_nextpkt; + m->m_nextpkt = NULL; + if (netmap_verbose & NM_VERB_HOST) + D("sending up pkt %p size %d", m, MBUF_LEN(m)); + NM_SEND_UP(na->ifp, m); + } +} + +/* + * rxsync backend for packets coming from the host stack. + * They have been put in the queue by netmap_start() so we + * need to protect access to the kring using a lock. + * + * This routine also does the selrecord if called from the poll handler + * (we know because td != NULL). + */ +static void +netmap_sync_from_host(struct netmap_adapter *na, struct thread *td) +{ + struct netmap_kring *kring = &na->rx_rings[na->num_queues]; + struct netmap_ring *ring = kring->ring; + int error = 1, delta; + u_int k = ring->cur, lim = kring->nkr_num_slots; + + na->nm_lock(na->ifp, NETMAP_CORE_LOCK, 0); + if (k >= lim) /* bad value */ + goto done; + delta = k - kring->nr_hwcur; + if (delta < 0) + delta += lim; + kring->nr_hwavail -= delta; + if (kring->nr_hwavail < 0) /* error */ + goto done; + kring->nr_hwcur = k; + error = 0; + k = ring->avail = kring->nr_hwavail; + if (k == 0 && td) + selrecord(td, &kring->si); + if (k && (netmap_verbose & NM_VERB_HOST)) + D("%d pkts from stack", k); +done: + na->nm_lock(na->ifp, NETMAP_CORE_UNLOCK, 0); + if (error) + netmap_ring_reinit(kring); +} + + +/* + * get a refcounted reference to an interface. + * Return ENXIO if the interface does not exist, EINVAL if netmap + * is not supported by the interface. + * If successful, hold a reference. + */ +static int +get_ifp(const char *name, struct ifnet **ifp) +{ + *ifp = ifunit_ref(name); + if (*ifp == NULL) + return (ENXIO); + /* can do this if the capability exists and if_pspare[0] + * points to the netmap descriptor. + */ + if ((*ifp)->if_capabilities & IFCAP_NETMAP && NA(*ifp)) + return 0; /* valid pointer, we hold the refcount */ + if_rele(*ifp); + return EINVAL; // not NETMAP capable +} + + +/* + * Error routine called when txsync/rxsync detects an error. + * Can't do much more than resetting cur = hwcur, avail = hwavail. + * Return 1 on reinit. + * + * This routine is only called by the upper half of the kernel. + * It only reads hwcur (which is changed only by the upper half, too) + * and hwavail (which may be changed by the lower half, but only on + * a tx ring and only to increase it, so any error will be recovered + * on the next call). For the above, we don't strictly need to call + * it under lock. + */ +int +netmap_ring_reinit(struct netmap_kring *kring) +{ + struct netmap_ring *ring = kring->ring; + u_int i, lim = kring->nkr_num_slots - 1; + int errors = 0; + + D("called for %s", kring->na->ifp->if_xname); + if (ring->cur > lim) + errors++; + for (i = 0; i <= lim; i++) { + u_int idx = ring->slot[i].buf_idx; + u_int len = ring->slot[i].len; + if (idx < 2 || idx >= netmap_total_buffers) { + if (!errors++) + D("bad buffer at slot %d idx %d len %d ", i, idx, len); + ring->slot[i].buf_idx = 0; + ring->slot[i].len = 0; + } else if (len > NETMAP_BUF_SIZE) { + ring->slot[i].len = 0; + if (!errors++) + D("bad len %d at slot %d idx %d", + len, i, idx); + } + } + if (errors) { + int pos = kring - kring->na->tx_rings; + int n = kring->na->num_queues + 2; + + D("total %d errors", errors); + errors++; + D("%s %s[%d] reinit, cur %d -> %d avail %d -> %d", + kring->na->ifp->if_xname, + pos < n ? "TX" : "RX", pos < n ? pos : pos - n, + ring->cur, kring->nr_hwcur, + ring->avail, kring->nr_hwavail); + ring->cur = kring->nr_hwcur; + ring->avail = kring->nr_hwavail; + } + return (errors ? 1 : 0); +} + + +/* + * Set the ring ID. For devices with a single queue, a request + * for all rings is the same as a single ring. + */ +static int +netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid) +{ + struct ifnet *ifp = priv->np_ifp; + struct netmap_adapter *na = NA(ifp); + u_int i = ringid & NETMAP_RING_MASK; + /* first time we don't lock */ + int need_lock = (priv->np_qfirst != priv->np_qlast); + + if ( (ringid & NETMAP_HW_RING) && i >= na->num_queues) { + D("invalid ring id %d", i); + return (EINVAL); + } + if (need_lock) + na->nm_lock(ifp, NETMAP_CORE_LOCK, 0); + priv->np_ringid = ringid; + if (ringid & NETMAP_SW_RING) { + priv->np_qfirst = na->num_queues; + priv->np_qlast = na->num_queues + 1; + } else if (ringid & NETMAP_HW_RING) { + priv->np_qfirst = i; + priv->np_qlast = i + 1; + } else { + priv->np_qfirst = 0; + priv->np_qlast = na->num_queues; + } + priv->np_txpoll = (ringid & NETMAP_NO_TX_POLL) ? 0 : 1; + if (need_lock) + na->nm_lock(ifp, NETMAP_CORE_UNLOCK, 0); + if (ringid & NETMAP_SW_RING) + D("ringid %s set to SW RING", ifp->if_xname); + else if (ringid & NETMAP_HW_RING) + D("ringid %s set to HW RING %d", ifp->if_xname, + priv->np_qfirst); + else + D("ringid %s set to all %d HW RINGS", ifp->if_xname, + priv->np_qlast); + return 0; +} + +/* + * ioctl(2) support for the "netmap" device. + * + * Following a list of accepted commands: + * - NIOCGINFO + * - SIOCGIFADDR just for convenience + * - NIOCREGIF + * - NIOCUNREGIF + * - NIOCTXSYNC + * - NIOCRXSYNC + * + * Return 0 on success, errno otherwise. + */ +static int +netmap_ioctl(__unused struct cdev *dev, u_long cmd, caddr_t data, + __unused int fflag, struct thread *td) +{ + struct netmap_priv_d *priv = NULL; + struct ifnet *ifp; + struct nmreq *nmr = (struct nmreq *) data; + struct netmap_adapter *na; + int error; + u_int i; + struct netmap_if *nifp; + + CURVNET_SET(TD_TO_VNET(td)); + + error = devfs_get_cdevpriv((void **)&priv); + if (error != ENOENT && error != 0) { + CURVNET_RESTORE(); + return (error); + } + + error = 0; /* Could be ENOENT */ + switch (cmd) { + case NIOCGINFO: /* return capabilities etc */ + /* memsize is always valid */ + nmr->nr_memsize = netmap_mem_d->nm_totalsize; + nmr->nr_offset = 0; + nmr->nr_numrings = 0; + nmr->nr_numslots = 0; + if (nmr->nr_name[0] == '\0') /* just get memory info */ + break; + error = get_ifp(nmr->nr_name, &ifp); /* get a refcount */ + if (error) + break; + na = NA(ifp); /* retrieve netmap_adapter */ + nmr->nr_numrings = na->num_queues; + nmr->nr_numslots = na->num_tx_desc; + if_rele(ifp); /* return the refcount */ + break; + + case NIOCREGIF: + if (priv != NULL) { /* thread already registered */ + error = netmap_set_ringid(priv, nmr->nr_ringid); + break; + } + /* find the interface and a reference */ + error = get_ifp(nmr->nr_name, &ifp); /* keep reference */ + if (error) + break; + na = NA(ifp); /* retrieve netmap adapter */ + /* + * Allocate the private per-thread structure. + * XXX perhaps we can use a blocking malloc ? + */ + priv = malloc(sizeof(struct netmap_priv_d), M_DEVBUF, + M_NOWAIT | M_ZERO); + if (priv == NULL) { + error = ENOMEM; + if_rele(ifp); /* return the refcount */ + break; + } + + for (i = 10; i > 0; i--) { + na->nm_lock(ifp, NETMAP_REG_LOCK, 0); + if (!NETMAP_DELETING(na)) + break; + na->nm_lock(ifp, NETMAP_REG_UNLOCK, 0); + tsleep(na, 0, "NIOCREGIF", hz/10); + } + if (i == 0) { + D("too many NIOCREGIF attempts, give up"); + error = EINVAL; + free(priv, M_DEVBUF); + if_rele(ifp); /* return the refcount */ + break; + } + + priv->np_ifp = ifp; /* store the reference */ + error = netmap_set_ringid(priv, nmr->nr_ringid); + if (error) + goto error; + priv->np_nifp = nifp = netmap_if_new(nmr->nr_name, na); + if (nifp == NULL) { /* allocation failed */ + error = ENOMEM; + } else if (ifp->if_capenable & IFCAP_NETMAP) { + /* was already set */ + } else { + /* Otherwise set the card in netmap mode + * and make it use the shared buffers. + */ + error = na->nm_register(ifp, 1); /* mode on */ + if (error) + netmap_dtor_locked(priv); + } + + if (error) { /* reg. failed, release priv and ref */ +error: + na->nm_lock(ifp, NETMAP_REG_UNLOCK, 0); + if_rele(ifp); /* return the refcount */ + bzero(priv, sizeof(*priv)); + free(priv, M_DEVBUF); + break; + } + + na->nm_lock(ifp, NETMAP_REG_UNLOCK, 0); + error = devfs_set_cdevpriv(priv, netmap_dtor); + + if (error != 0) { + /* could not assign the private storage for the + * thread, call the destructor explicitly. + */ + netmap_dtor(priv); + break; + } + + /* return the offset of the netmap_if object */ + nmr->nr_numrings = na->num_queues; + nmr->nr_numslots = na->num_tx_desc; + nmr->nr_memsize = netmap_mem_d->nm_totalsize; + nmr->nr_offset = netmap_if_offset(nifp); + break; + + case NIOCUNREGIF: + if (priv == NULL) { + error = ENXIO; + break; + } + + /* the interface is unregistered inside the + destructor of the private data. */ + devfs_clear_cdevpriv(); + break; + + case NIOCTXSYNC: + case NIOCRXSYNC: + if (priv == NULL) { + error = ENXIO; + break; + } + ifp = priv->np_ifp; /* we have a reference */ + na = NA(ifp); /* retrieve netmap adapter */ + + if (priv->np_qfirst == na->num_queues) { + /* queues to/from host */ + if (cmd == NIOCTXSYNC) + netmap_sync_to_host(na); + else + netmap_sync_from_host(na, NULL); + break; + } + + for (i = priv->np_qfirst; i < priv->np_qlast; i++) { + if (cmd == NIOCTXSYNC) { + struct netmap_kring *kring = &na->tx_rings[i]; + if (netmap_verbose & NM_VERB_TXSYNC) + D("sync tx ring %d cur %d hwcur %d", + i, kring->ring->cur, + kring->nr_hwcur); + na->nm_txsync(ifp, i, 1 /* do lock */); + if (netmap_verbose & NM_VERB_TXSYNC) + D("after sync tx ring %d cur %d hwcur %d", + i, kring->ring->cur, + kring->nr_hwcur); + } else { + na->nm_rxsync(ifp, i, 1 /* do lock */); + microtime(&na->rx_rings[i].ring->ts); + } + } + + break; + + case BIOCIMMEDIATE: + case BIOCGHDRCMPLT: + case BIOCSHDRCMPLT: + case BIOCSSEESENT: + D("ignore BIOCIMMEDIATE/BIOCSHDRCMPLT/BIOCSHDRCMPLT/BIOCSSEESENT"); + break; + + default: + { + /* + * allow device calls + */ + struct socket so; + bzero(&so, sizeof(so)); + error = get_ifp(nmr->nr_name, &ifp); /* keep reference */ + if (error) + break; + so.so_vnet = ifp->if_vnet; + // so->so_proto not null. + error = ifioctl(&so, cmd, data, td); + if_rele(ifp); + } + } + + CURVNET_RESTORE(); + return (error); +} + + +/* + * select(2) and poll(2) handlers for the "netmap" device. + * + * Can be called for one or more queues. + * Return true the event mask corresponding to ready events. + * If there are no ready events, do a selrecord on either individual + * selfd or on the global one. + * Device-dependent parts (locking and sync of tx/rx rings) + * are done through callbacks. + */ +static int +netmap_poll(__unused struct cdev *dev, int events, struct thread *td) +{ + struct netmap_priv_d *priv = NULL; + struct netmap_adapter *na; + struct ifnet *ifp; + struct netmap_kring *kring; + u_int core_lock, i, check_all, want_tx, want_rx, revents = 0; + enum {NO_CL, NEED_CL, LOCKED_CL }; /* see below */ + + if (devfs_get_cdevpriv((void **)&priv) != 0 || priv == NULL) + return POLLERR; + + ifp = priv->np_ifp; + // XXX check for deleting() ? + if ( (ifp->if_capenable & IFCAP_NETMAP) == 0) + return POLLERR; + + if (netmap_verbose & 0x8000) + D("device %s events 0x%x", ifp->if_xname, events); + want_tx = events & (POLLOUT | POLLWRNORM); + want_rx = events & (POLLIN | POLLRDNORM); + + na = NA(ifp); /* retrieve netmap adapter */ + + /* how many queues we are scanning */ + i = priv->np_qfirst; + if (i == na->num_queues) { /* from/to host */ + if (priv->np_txpoll || want_tx) { + /* push any packets up, then we are always ready */ + kring = &na->tx_rings[i]; + netmap_sync_to_host(na); + revents |= want_tx; + } + if (want_rx) { + kring = &na->rx_rings[i]; + if (kring->ring->avail == 0) + netmap_sync_from_host(na, td); + if (kring->ring->avail > 0) { + revents |= want_rx; + } + } + return (revents); + } + + /* + * check_all is set if the card has more than one queue and + * the client is polling all of them. If true, we sleep on + * the "global" selfd, otherwise we sleep on individual selfd + * (we can only sleep on one of them per direction). + * The interrupt routine in the driver should always wake on + * the individual selfd, and also on the global one if the card + * has more than one ring. + * + * If the card has only one lock, we just use that. + * If the card has separate ring locks, we just use those + * unless we are doing check_all, in which case the whole + * loop is wrapped by the global lock. + * We acquire locks only when necessary: if poll is called + * when buffers are available, we can just return without locks. + * + * rxsync() is only called if we run out of buffers on a POLLIN. + * txsync() is called if we run out of buffers on POLLOUT, or + * there are pending packets to send. The latter can be disabled + * passing NETMAP_NO_TX_POLL in the NIOCREG call. + */ + check_all = (i + 1 != priv->np_qlast); + + /* + * core_lock indicates what to do with the core lock. + * The core lock is used when either the card has no individual + * locks, or it has individual locks but we are cheking all + * rings so we need the core lock to avoid missing wakeup events. + * + * It has three possible states: + * NO_CL we don't need to use the core lock, e.g. + * because we are protected by individual locks. + * NEED_CL we need the core lock. In this case, when we + * call the lock routine, move to LOCKED_CL + * to remember to release the lock once done. + * LOCKED_CL core lock is set, so we need to release it. + */ + core_lock = (check_all || !na->separate_locks) ? NEED_CL : NO_CL; + /* + * We start with a lock free round which is good if we have + * data available. If this fails, then lock and call the sync + * routines. + */ + for (i = priv->np_qfirst; want_rx && i < priv->np_qlast; i++) { + kring = &na->rx_rings[i]; + if (kring->ring->avail > 0) { + revents |= want_rx; + want_rx = 0; /* also breaks the loop */ + } + } + for (i = priv->np_qfirst; want_tx && i < priv->np_qlast; i++) { + kring = &na->tx_rings[i]; + if (kring->ring->avail > 0) { + revents |= want_tx; + want_tx = 0; /* also breaks the loop */ + } + } + + /* + * If we to push packets out (priv->np_txpoll) or want_tx is + * still set, we do need to run the txsync calls (on all rings, + * to avoid that the tx rings stall). + */ + if (priv->np_txpoll || want_tx) { + for (i = priv->np_qfirst; i < priv->np_qlast; i++) { + kring = &na->tx_rings[i]; + /* + * Skip the current ring if want_tx == 0 + * (we have already done a successful sync on + * a previous ring) AND kring->cur == kring->hwcur + * (there are no pending transmissions for this ring). + */ + if (!want_tx && kring->ring->cur == kring->nr_hwcur) + continue; + if (core_lock == NEED_CL) { + na->nm_lock(ifp, NETMAP_CORE_LOCK, 0); + core_lock = LOCKED_CL; + } + if (na->separate_locks) + na->nm_lock(ifp, NETMAP_TX_LOCK, i); + if (netmap_verbose & NM_VERB_TXSYNC) + D("send %d on %s %d", + kring->ring->cur, + ifp->if_xname, i); + if (na->nm_txsync(ifp, i, 0 /* no lock */)) + revents |= POLLERR; + + /* Check avail/call selrecord only if called with POLLOUT */ + if (want_tx) { + if (kring->ring->avail > 0) { + /* stop at the first ring. We don't risk + * starvation. + */ + revents |= want_tx; + want_tx = 0; + } else if (!check_all) + selrecord(td, &kring->si); + } + if (na->separate_locks) + na->nm_lock(ifp, NETMAP_TX_UNLOCK, i); + } + } + + /* + * now if want_rx is still set we need to lock and rxsync. + * Do it on all rings because otherwise we starve. + */ + if (want_rx) { + for (i = priv->np_qfirst; i < priv->np_qlast; i++) { + kring = &na->rx_rings[i]; + if (core_lock == NEED_CL) { + na->nm_lock(ifp, NETMAP_CORE_LOCK, 0); + core_lock = LOCKED_CL; + } + if (na->separate_locks) + na->nm_lock(ifp, NETMAP_RX_LOCK, i); + + if (na->nm_rxsync(ifp, i, 0 /* no lock */)) + revents |= POLLERR; + if (netmap_no_timestamp == 0 || + kring->ring->flags & NR_TIMESTAMP) { + microtime(&kring->ring->ts); + } + + if (kring->ring->avail > 0) + revents |= want_rx; + else if (!check_all) + selrecord(td, &kring->si); + if (na->separate_locks) + na->nm_lock(ifp, NETMAP_RX_UNLOCK, i); + } + } + if (check_all && revents == 0) { + i = na->num_queues + 1; /* the global queue */ + if (want_tx) + selrecord(td, &na->tx_rings[i].si); + if (want_rx) + selrecord(td, &na->rx_rings[i].si); + } + if (core_lock == LOCKED_CL) + na->nm_lock(ifp, NETMAP_CORE_UNLOCK, 0); + + return (revents); +} + +/*------- driver support routines ------*/ + +/* + * default lock wrapper. On linux we use mostly netmap-specific locks. + */ +static void +netmap_lock_wrapper(struct ifnet *_a, int what, u_int queueid) +{ + struct netmap_adapter *na = NA(_a); + + switch (what) { +#ifndef __FreeBSD__ /* some system do not need lock on register */ + case NETMAP_REG_LOCK: + case NETMAP_REG_UNLOCK: + break; +#endif + + case NETMAP_CORE_LOCK: + mtx_lock(&na->core_lock); + break; + + case NETMAP_CORE_UNLOCK: + mtx_unlock(&na->core_lock); + break; + + case NETMAP_TX_LOCK: + mtx_lock(&na->tx_rings[queueid].q_lock); + break; + + case NETMAP_TX_UNLOCK: + mtx_unlock(&na->tx_rings[queueid].q_lock); + break; + + case NETMAP_RX_LOCK: + mtx_lock(&na->rx_rings[queueid].q_lock); + break; + + case NETMAP_RX_UNLOCK: + mtx_unlock(&na->rx_rings[queueid].q_lock); + break; + } +} + + +/* + * Initialize a ``netmap_adapter`` object created by driver on attach. + * We allocate a block of memory with room for a struct netmap_adapter + * plus two sets of N+2 struct netmap_kring (where N is the number + * of hardware rings): + * krings 0..N-1 are for the hardware queues. + * kring N is for the host stack queue + * kring N+1 is only used for the selinfo for all queues. + * Return 0 on success, ENOMEM otherwise. + */ +int +netmap_attach(struct netmap_adapter *na, int num_queues) +{ + int n = num_queues + 2; + int size = sizeof(*na) + 2 * n * sizeof(struct netmap_kring); + void *buf; + struct ifnet *ifp = na->ifp; + int i; + + if (ifp == NULL) { + D("ifp not set, giving up"); + return EINVAL; + } + na->refcount = 0; + na->num_queues = num_queues; + + buf = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); + if (buf) { + WNA(ifp) = buf; + na->tx_rings = (void *)((char *)buf + sizeof(*na)); + na->rx_rings = na->tx_rings + n; + na->buff_size = NETMAP_BUF_SIZE; + bcopy(na, buf, sizeof(*na)); + ifp->if_capabilities |= IFCAP_NETMAP; + + na = buf; + if (na->nm_lock == NULL) + na->nm_lock = netmap_lock_wrapper; + mtx_init(&na->core_lock, "netmap core lock", NULL, MTX_DEF); + for (i = 0 ; i < num_queues; i++) + mtx_init(&na->tx_rings[i].q_lock, "netmap txq lock", NULL, MTX_DEF); + for (i = 0 ; i < num_queues; i++) + mtx_init(&na->rx_rings[i].q_lock, "netmap rxq lock", NULL, MTX_DEF); + } + D("%s for %s", buf ? "ok" : "failed", ifp->if_xname); + + return (buf ? 0 : ENOMEM); +} + + +/* + * Free the allocated memory linked to the given ``netmap_adapter`` + * object. + */ +void +netmap_detach(struct ifnet *ifp) +{ + u_int i; + struct netmap_adapter *na = NA(ifp); + + if (!na) + return; + + for (i = 0; i < na->num_queues + 2; i++) { + knlist_destroy(&na->tx_rings[i].si.si_note); + knlist_destroy(&na->rx_rings[i].si.si_note); + } + bzero(na, sizeof(*na)); + WNA(ifp) = NULL; + free(na, M_DEVBUF); +} + + +/* + * Intercept packets from the network stack and pass them + * to netmap as incoming packets on the 'software' ring. + * We are not locked when called. + */ +int +netmap_start(struct ifnet *ifp, struct mbuf *m) +{ + struct netmap_adapter *na = NA(ifp); + struct netmap_kring *kring = &na->rx_rings[na->num_queues]; + u_int i, len = MBUF_LEN(m); + int error = EBUSY, lim = kring->nkr_num_slots - 1; + struct netmap_slot *slot; + + if (netmap_verbose & NM_VERB_HOST) + D("%s packet %d len %d from the stack", ifp->if_xname, + kring->nr_hwcur + kring->nr_hwavail, len); + na->nm_lock(ifp, NETMAP_CORE_LOCK, 0); + if (kring->nr_hwavail >= lim) { + D("stack ring %s full\n", ifp->if_xname); + goto done; /* no space */ + } + if (len > na->buff_size) { + D("drop packet size %d > %d", len, na->buff_size); + goto done; /* too long for us */ + } + + /* compute the insert position */ + i = kring->nr_hwcur + kring->nr_hwavail; + if (i > lim) + i -= lim + 1; + slot = &kring->ring->slot[i]; + m_copydata(m, 0, len, NMB(slot)); + slot->len = len; + kring->nr_hwavail++; + if (netmap_verbose & NM_VERB_HOST) + D("wake up host ring %s %d", na->ifp->if_xname, na->num_queues); + selwakeuppri(&kring->si, PI_NET); + error = 0; +done: + na->nm_lock(ifp, NETMAP_CORE_UNLOCK, 0); + + /* release the mbuf in either cases of success or failure. As an + * alternative, put the mbuf in a free list and free the list + * only when really necessary. + */ + m_freem(m); + + return (error); +} + + +/* + * netmap_reset() is called by the driver routines when reinitializing + * a ring. The driver is in charge of locking to protect the kring. + * If netmap mode is not set just return NULL. + */ +struct netmap_slot * +netmap_reset(struct netmap_adapter *na, enum txrx tx, int n, + u_int new_cur) +{ + struct netmap_kring *kring; + struct netmap_ring *ring; + int new_hwofs, lim; + + if (na == NULL) + return NULL; /* no netmap support here */ + if (!(na->ifp->if_capenable & IFCAP_NETMAP)) + return NULL; /* nothing to reinitialize */ + kring = tx == NR_TX ? na->tx_rings + n : na->rx_rings + n; + ring = kring->ring; + lim = kring->nkr_num_slots - 1; + + if (tx == NR_TX) + new_hwofs = kring->nr_hwcur - new_cur; + else + new_hwofs = kring->nr_hwcur + kring->nr_hwavail - new_cur; + if (new_hwofs > lim) + new_hwofs -= lim + 1; + + /* Alwayws set the new offset value and realign the ring. */ + kring->nkr_hwofs = new_hwofs; + if (tx == NR_TX) + kring->nr_hwavail = kring->nkr_num_slots - 1; + D("new hwofs %d on %s %s[%d]", + kring->nkr_hwofs, na->ifp->if_xname, + tx == NR_TX ? "TX" : "RX", n); + + /* + * We do the wakeup here, but the ring is not yet reconfigured. + * However, we are under lock so there are no races. + */ + selwakeuppri(&kring->si, PI_NET); + selwakeuppri(&kring[na->num_queues + 1 - n].si, PI_NET); + return kring->ring->slot; +} + + +/* + * Default functions to handle rx/tx interrupts + * we have 4 cases: + * 1 ring, single lock: + * lock(core); wake(i=0); unlock(core) + * N rings, single lock: + * lock(core); wake(i); wake(N+1) unlock(core) + * 1 ring, separate locks: (i=0) + * lock(i); wake(i); unlock(i) + * N rings, separate locks: + * lock(i); wake(i); unlock(i); lock(core) wake(N+1) unlock(core) + */ +int netmap_rx_irq(struct ifnet *ifp, int q, int *work_done) +{ + struct netmap_adapter *na; + struct netmap_kring *r; + + if (!(ifp->if_capenable & IFCAP_NETMAP)) + return 0; + na = NA(ifp); + r = work_done ? na->rx_rings : na->tx_rings; + if (na->separate_locks) { + mtx_lock(&r[q].q_lock); + selwakeuppri(&r[q].si, PI_NET); + mtx_unlock(&r[q].q_lock); + if (na->num_queues > 1) { + mtx_lock(&na->core_lock); + selwakeuppri(&r[na->num_queues + 1].si, PI_NET); + mtx_unlock(&na->core_lock); + } + } else { + mtx_lock(&na->core_lock); + selwakeuppri(&r[q].si, PI_NET); + if (na->num_queues > 1) + selwakeuppri(&r[na->num_queues + 1].si, PI_NET); + mtx_unlock(&na->core_lock); + } + if (work_done) + *work_done = 1; /* do not fire napi again */ + return 1; +} + /* * Module loader. * diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h index 08f11fe614bb..6e0357047773 100644 --- a/sys/dev/netmap/netmap_kern.h +++ b/sys/dev/netmap/netmap_kern.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. + * Copyright (C) 2011-2012 Matteo Landi, Luigi Rizzo. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,6 +34,20 @@ #ifndef _NET_NETMAP_KERN_H_ #define _NET_NETMAP_KERN_H_ +#if defined(__FreeBSD__) +#define NM_LOCK_T struct mtx +#define NM_SELINFO_T struct selinfo +#define MBUF_LEN(m) ((m)->m_pkthdr.len) +#define NM_SEND_UP(ifp, m) ((ifp)->if_input)(ifp, m) +#elif defined (__linux__) +#define NM_LOCK_T spinlock_t +#define NM_SELINFO_T wait_queue_head_t +#define MBUF_LEN(m) ((m)->len) +#define NM_SEND_UP(ifp, m) netif_rx(m) +#else +#error unsupported platform +#endif + #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_NETMAP); #endif @@ -53,11 +67,10 @@ struct netmap_adapter; /* * private, kernel view of a ring. * - * XXX 20110627-todo - * The index in the NIC and netmap ring is offset by nkr_hwofs slots. + * The indexes in the NIC and netmap rings are offset by nkr_hwofs slots. * This is so that, on a reset, buffers owned by userspace are not * modified by the kernel. In particular: - * RX rings: the next empty buffer (hwcur + hwavail + hwofs) coincides + * RX rings: the next empty buffer (hwcur + hwavail + hwofs) coincides with * the next empty buffer as known by the hardware (next_to_check or so). * TX rings: hwcur + hwofs coincides with next_to_send */ @@ -70,12 +83,13 @@ struct netmap_kring { u_int nkr_num_slots; int nkr_hwofs; /* offset between NIC and netmap ring */ - struct netmap_adapter *na; // debugging - struct selinfo si; /* poll/select wait queue */ + struct netmap_adapter *na; + NM_SELINFO_T si; /* poll/select wait queue */ + NM_LOCK_T q_lock; /* used if no device lock available */ } __attribute__((__aligned__(64))); /* - * This struct is part of and extends the 'struct adapter' (or + * This struct extends the 'struct adapter' (or * equivalent) device descriptor. It contains all fields needed to * support netmap operation. */ @@ -93,9 +107,9 @@ struct netmap_adapter { u_int num_tx_desc; /* number of descriptor in each queue */ u_int num_rx_desc; - u_int buff_size; + u_int buff_size; - u_int flags; + //u_int flags; // XXX unused /* tx_rings and rx_rings are private but allocated * as a contiguous chunk of memory. Each array has * N+1 entries, for the adapter queues and for the host queue. @@ -107,7 +121,7 @@ struct netmap_adapter { * packets from the network stack when netmap is active. * XXX probably if_qflush is not necessary. */ - void (*if_qflush)(struct ifnet *); + //void (*if_qflush)(struct ifnet *); // XXX unused int (*if_transmit)(struct ifnet *, struct mbuf *); /* references to the ifnet and device routines, used by @@ -115,10 +129,12 @@ struct netmap_adapter { */ struct ifnet *ifp; /* adapter is ifp->if_softc */ + NM_LOCK_T core_lock; /* used if no device lock available */ + int (*nm_register)(struct ifnet *, int onoff); - void (*nm_lock)(void *, int what, u_int ringid); - int (*nm_txsync)(void *, u_int ring, int lock); - int (*nm_rxsync)(void *, u_int ring, int lock); + void (*nm_lock)(struct ifnet *, int what, u_int ringid); + int (*nm_txsync)(struct ifnet *, u_int ring, int lock); + int (*nm_rxsync)(struct ifnet *, u_int ring, int lock); }; /* @@ -144,6 +160,12 @@ enum { NETMAP_CORE_LOCK, NETMAP_CORE_UNLOCK, NETMAP_TX_LOCK, NETMAP_TX_UNLOCK, NETMAP_RX_LOCK, NETMAP_RX_UNLOCK, +#ifdef __FreeBSD__ +#define NETMAP_REG_LOCK NETMAP_CORE_LOCK +#define NETMAP_REG_UNLOCK NETMAP_CORE_UNLOCK +#else + NETMAP_REG_LOCK, NETMAP_REG_UNLOCK +#endif }; /* @@ -172,8 +194,10 @@ struct netmap_slot *netmap_reset(struct netmap_adapter *na, enum txrx tx, int n, u_int new_cur); int netmap_ring_reinit(struct netmap_kring *); +extern int netmap_buf_size; +#define NETMAP_BUF_SIZE netmap_buf_size extern int netmap_mitigate; -extern int netmap_skip_txsync, netmap_skip_rxsync; +extern int netmap_no_pendintr; extern u_int netmap_total_buffers; extern char *netmap_buffer_base; extern int netmap_verbose; // XXX debugging @@ -226,6 +250,58 @@ netmap_reload_map(bus_dma_tag_t tag, bus_dmamap_t map, void *buf) } } +/* + * functions to map NIC to KRING indexes (n2k) and vice versa (k2n) + */ +static inline int +netmap_ridx_n2k(struct netmap_adapter *na, int ring, int nic_idx) +{ + int kring_idx = nic_idx + na->rx_rings[ring].nkr_hwofs; + if (kring_idx < 0) + return kring_idx + na->num_rx_desc; + else if (kring_idx < na->num_rx_desc) + return kring_idx; + else + return kring_idx - na->num_rx_desc; +} + +static inline int +netmap_tidx_n2k(struct netmap_adapter *na, int ring, int nic_idx) +{ + int kring_idx = nic_idx + na->tx_rings[ring].nkr_hwofs; + if (kring_idx < 0) + return kring_idx + na->num_tx_desc; + else if (kring_idx < na->num_tx_desc) + return kring_idx; + else + return kring_idx - na->num_tx_desc; +} + + +static inline int +netmap_ridx_k2n(struct netmap_adapter *na, int ring, int kring_idx) +{ + int nic_idx = kring_idx - na->rx_rings[ring].nkr_hwofs; + if (nic_idx < 0) + return nic_idx + na->num_rx_desc; + else if (nic_idx < na->num_rx_desc) + return nic_idx; + else + return nic_idx - na->num_rx_desc; +} + + +static inline int +netmap_tidx_k2n(struct netmap_adapter *na, int ring, int kring_idx) +{ + int nic_idx = kring_idx - na->tx_rings[ring].nkr_hwofs; + if (nic_idx < 0) + return nic_idx + na->num_tx_desc; + else if (nic_idx < na->num_tx_desc) + return nic_idx; + else + return nic_idx - na->num_tx_desc; +} /* * NMB return the virtual address of a buffer (buffer 0 on bad index) @@ -236,11 +312,7 @@ NMB(struct netmap_slot *slot) { uint32_t i = slot->buf_idx; return (i >= netmap_total_buffers) ? netmap_buffer_base : -#if NETMAP_BUF_SIZE == 2048 - netmap_buffer_base + (i << 11); -#else netmap_buffer_base + (i *NETMAP_BUF_SIZE); -#endif } static inline void * @@ -248,13 +320,16 @@ PNMB(struct netmap_slot *slot, uint64_t *pp) { uint32_t i = slot->buf_idx; void *ret = (i >= netmap_total_buffers) ? netmap_buffer_base : -#if NETMAP_BUF_SIZE == 2048 - netmap_buffer_base + (i << 11); -#else netmap_buffer_base + (i *NETMAP_BUF_SIZE); -#endif *pp = vtophys(ret); return ret; } +/* default functions to handle rx/tx interrupts */ +int netmap_rx_irq(struct ifnet *, int, int *); +#define netmap_tx_irq(_n, _q) netmap_rx_irq(_n, _q, NULL) +#ifdef __linux__ +#define bus_dmamap_sync(_a, _b, _c) // wmb() or rmb() ? +netdev_tx_t netmap_start_linux(struct sk_buff *skb, struct net_device *dev); +#endif #endif /* _NET_NETMAP_KERN_H_ */ diff --git a/sys/dev/oce/oce_hw.c b/sys/dev/oce/oce_hw.c new file mode 100644 index 000000000000..05486d2cdfac --- /dev/null +++ b/sys/dev/oce/oce_hw.c @@ -0,0 +1,588 @@ +/*- + * Copyright (C) 2012 Emulex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Emulex Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact Information: + * freebsd-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + +/* $FreeBSD$ */ + +#include "oce_if.h" + +static int oce_POST(POCE_SOFTC sc); + +/** + * @brief Function to post status + * @param sc software handle to the device + */ +static int +oce_POST(POCE_SOFTC sc) +{ + mpu_ep_semaphore_t post_status; + int tmo = 60000; + + /* read semaphore CSR */ + post_status.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_SEMAPHORE(sc)); + + /* if host is ready then wait for fw ready else send POST */ + if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) { + post_status.bits.stage = POST_STAGE_CHIP_RESET; + OCE_WRITE_REG32(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0); + } + + /* wait for FW ready */ + for (;;) { + if (--tmo == 0) + break; + + DELAY(1000); + + post_status.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_SEMAPHORE(sc)); + if (post_status.bits.error) { + device_printf(sc->dev, + "POST failed: %x\n", post_status.dw0); + return ENXIO; + } + if (post_status.bits.stage == POST_STAGE_ARMFW_READY) + return 0; + } + + device_printf(sc->dev, "POST timed out: %x\n", post_status.dw0); + + return ENXIO; +} + +/** + * @brief Function for hardware initialization + * @param sc software handle to the device + */ +int +oce_hw_init(POCE_SOFTC sc) +{ + int rc = 0; + + rc = oce_POST(sc); + if (rc) + return rc; + + /* create the bootstrap mailbox */ + rc = oce_dma_alloc(sc, sizeof(struct oce_bmbx), &sc->bsmbx, 0); + if (rc) { + device_printf(sc->dev, "Mailbox alloc failed\n"); + return rc; + } + + rc = oce_reset_fun(sc); + if (rc) + goto error; + + + rc = oce_mbox_init(sc); + if (rc) + goto error; + + + rc = oce_get_fw_version(sc); + if (rc) + goto error; + + + rc = oce_get_fw_config(sc); + if (rc) + goto error; + + + sc->macaddr.size_of_struct = 6; + rc = oce_read_mac_addr(sc, 0, 1, MAC_ADDRESS_TYPE_NETWORK, + &sc->macaddr); + if (rc) + goto error; + + if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) { + rc = oce_mbox_check_native_mode(sc); + if (rc) + goto error; + } else + sc->be3_native = 0; + + return rc; + +error: + oce_dma_free(sc, &sc->bsmbx); + device_printf(sc->dev, "Hardware initialisation failed\n"); + return rc; +} + + + +/** + * @brief Releases the obtained pci resources + * @param sc software handle to the device + */ +void +oce_hw_pci_free(POCE_SOFTC sc) +{ + int pci_cfg_barnum = 0; + + if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) + pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR; + else + pci_cfg_barnum = OCE_DEV_CFG_BAR; + + if (sc->devcfg_res != NULL) { + bus_release_resource(sc->dev, + SYS_RES_MEMORY, + PCIR_BAR(pci_cfg_barnum), sc->devcfg_res); + sc->devcfg_res = (struct resource *)NULL; + sc->devcfg_btag = (bus_space_tag_t) 0; + sc->devcfg_bhandle = (bus_space_handle_t)0; + sc->devcfg_vhandle = (void *)NULL; + } + + if (sc->csr_res != NULL) { + bus_release_resource(sc->dev, + SYS_RES_MEMORY, + PCIR_BAR(OCE_PCI_CSR_BAR), sc->csr_res); + sc->csr_res = (struct resource *)NULL; + sc->csr_btag = (bus_space_tag_t)0; + sc->csr_bhandle = (bus_space_handle_t)0; + sc->csr_vhandle = (void *)NULL; + } + + if (sc->db_res != NULL) { + bus_release_resource(sc->dev, + SYS_RES_MEMORY, + PCIR_BAR(OCE_PCI_DB_BAR), sc->db_res); + sc->db_res = (struct resource *)NULL; + sc->db_btag = (bus_space_tag_t)0; + sc->db_bhandle = (bus_space_handle_t)0; + sc->db_vhandle = (void *)NULL; + } +} + + + + +/** + * @brief Function to get the PCI capabilities + * @param sc software handle to the device + */ +static +void oce_get_pci_capabilities(POCE_SOFTC sc) +{ + uint32_t val; + + if (pci_find_extcap(sc->dev, PCIY_PCIX, &val) == 0) { + if (val != 0) + sc->flags |= OCE_FLAGS_PCIX; + } + + if (pci_find_extcap(sc->dev, PCIY_EXPRESS, &val) == 0) { + if (val != 0) { + uint16_t link_status = + pci_read_config(sc->dev, val + 0x12, 2); + + sc->flags |= OCE_FLAGS_PCIE; + sc->pcie_link_speed = link_status & 0xf; + sc->pcie_link_width = (link_status >> 4) & 0x3f; + } + } + + if (pci_find_extcap(sc->dev, PCIY_MSI, &val) == 0) { + if (val != 0) + sc->flags |= OCE_FLAGS_MSI_CAPABLE; + } + + if (pci_find_extcap(sc->dev, PCIY_MSIX, &val) == 0) { + if (val != 0) { + val = pci_msix_count(sc->dev); + sc->flags |= OCE_FLAGS_MSIX_CAPABLE; + } + } +} + +/** + * @brief Allocate PCI resources. + * + * @param sc software handle to the device + * @returns 0 if successful, or error + */ +int +oce_hw_pci_alloc(POCE_SOFTC sc) +{ + int rr, pci_cfg_barnum = 0; + pci_sli_intf_t intf; + + pci_enable_busmaster(sc->dev); + + oce_get_pci_capabilities(sc); + + sc->fn = pci_get_function(sc->dev); + + /* setup the device config region */ + if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) + pci_cfg_barnum = OCE_DEV_BE2_CFG_BAR; + else + pci_cfg_barnum = OCE_DEV_CFG_BAR; + + rr = PCIR_BAR(pci_cfg_barnum); + + if (IS_BE(sc)) + sc->devcfg_res = bus_alloc_resource_any(sc->dev, + SYS_RES_MEMORY, &rr, + RF_ACTIVE|RF_SHAREABLE); + else + sc->devcfg_res = bus_alloc_resource(sc->dev, + SYS_RES_MEMORY, &rr, + 0ul, ~0ul, 32768, + RF_ACTIVE|RF_SHAREABLE); + + if (!sc->devcfg_res) + goto error; + + sc->devcfg_btag = rman_get_bustag(sc->devcfg_res); + sc->devcfg_bhandle = rman_get_bushandle(sc->devcfg_res); + sc->devcfg_vhandle = rman_get_virtual(sc->devcfg_res); + + /* Read the SLI_INTF register and determine whether we + * can use this port and its features + */ + intf.dw0 = pci_read_config((sc)->dev,OCE_INTF_REG_OFFSET,4); + + if (intf.bits.sli_valid != OCE_INTF_VALID_SIG) + goto error; + + if (intf.bits.sli_rev != OCE_INTF_SLI_REV4) { + device_printf(sc->dev, "Adapter doesnt support SLI4\n"); + goto error; + } + + if (intf.bits.sli_if_type == OCE_INTF_IF_TYPE_1) + sc->flags |= OCE_FLAGS_MBOX_ENDIAN_RQD; + + if (intf.bits.sli_hint1 == OCE_INTF_FUNC_RESET_REQD) + sc->flags |= OCE_FLAGS_FUNCRESET_RQD; + + if (intf.bits.sli_func_type == OCE_INTF_VIRT_FUNC) + sc->flags |= OCE_FLAGS_VIRTUAL_PORT; + + /* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */ + if (IS_BE(sc)) { + /* set up CSR region */ + rr = PCIR_BAR(OCE_PCI_CSR_BAR); + sc->csr_res = bus_alloc_resource_any(sc->dev, + SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE); + if (!sc->csr_res) + goto error; + sc->csr_btag = rman_get_bustag(sc->csr_res); + sc->csr_bhandle = rman_get_bushandle(sc->csr_res); + sc->csr_vhandle = rman_get_virtual(sc->csr_res); + + /* set up DB doorbell region */ + rr = PCIR_BAR(OCE_PCI_DB_BAR); + sc->db_res = bus_alloc_resource_any(sc->dev, + SYS_RES_MEMORY, &rr, RF_ACTIVE|RF_SHAREABLE); + if (!sc->db_res) + goto error; + sc->db_btag = rman_get_bustag(sc->db_res); + sc->db_bhandle = rman_get_bushandle(sc->db_res); + sc->db_vhandle = rman_get_virtual(sc->db_res); + } + + return 0; + +error: + oce_hw_pci_free(sc); + return ENXIO; +} + + +/** + * @brief Function for device shutdown + * @param sc software handle to the device + * @returns 0 on success, error otherwise + */ +void +oce_hw_shutdown(POCE_SOFTC sc) +{ + + oce_stats_free(sc); + /* disable hardware interrupts */ + oce_hw_intr_disable(sc); + /* Free LRO resources */ + oce_free_lro(sc); + /* Release queue*/ + oce_queue_release_all(sc); + /*Delete Network Interface*/ + oce_delete_nw_interface(sc); + /* After fw clean we dont send any cmds to fw.*/ + oce_fw_clean(sc); + /* release intr resources */ + oce_intr_free(sc); + /* release PCI resources */ + oce_hw_pci_free(sc); + /* free mbox specific resources */ + LOCK_DESTROY(&sc->bmbx_lock); + LOCK_DESTROY(&sc->dev_lock); + + oce_dma_free(sc, &sc->bsmbx); +} + + +/** + * @brief Function for creating nw interface. + * @param sc software handle to the device + * @returns 0 on success, error otherwise + */ +int +oce_create_nw_interface(POCE_SOFTC sc) +{ + int rc; + uint32_t capab_flags; + uint32_t capab_en_flags; + + /* interface capabilities to give device when creating interface */ + capab_flags = OCE_CAPAB_FLAGS; + + /* capabilities to enable by default (others set dynamically) */ + capab_en_flags = OCE_CAPAB_ENABLE; + + if (IS_XE201(sc)) { + /* LANCER A0 workaround */ + capab_en_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR; + capab_flags &= ~MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR; + } + + /* enable capabilities controlled via driver startup parameters */ + if (sc->rss_enable) + capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS; + else { + capab_en_flags &= ~MBX_RX_IFACE_FLAGS_RSS; + capab_flags &= ~MBX_RX_IFACE_FLAGS_RSS; + } + + rc = oce_if_create(sc, + capab_flags, + capab_en_flags, + 0, &sc->macaddr.mac_addr[0], &sc->if_id); + if (rc) + return rc; + + atomic_inc_32(&sc->nifs); + + sc->if_cap_flags = capab_en_flags; + + /* Enable VLAN Promisc on HW */ + rc = oce_config_vlan(sc, (uint8_t) sc->if_id, NULL, 0, 1, 1); + if (rc) + goto error; + + /* set default flow control */ + rc = oce_set_flow_control(sc, sc->flow_control); + if (rc) + goto error; + + rc = oce_rxf_set_promiscuous(sc, sc->promisc); + if (rc) + goto error; + + return rc; + +error: + oce_delete_nw_interface(sc); + return rc; + +} + +/** + * @brief Function to delete a nw interface. + * @param sc software handle to the device + */ +void +oce_delete_nw_interface(POCE_SOFTC sc) +{ + /* currently only single interface is implmeneted */ + if (sc->nifs > 0) { + oce_if_del(sc, sc->if_id); + atomic_dec_32(&sc->nifs); + } +} + +/** + * @brief Soft reset. + * @param sc software handle to the device + * @returns 0 on success, error otherwise + */ +int +oce_pci_soft_reset(POCE_SOFTC sc) +{ + int rc; + mpu_ep_control_t ctrl; + + ctrl.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_CONTROL); + ctrl.bits.cpu_reset = 1; + OCE_WRITE_REG32(sc, csr, MPU_EP_CONTROL, ctrl.dw0); + DELAY(50); + rc=oce_POST(sc); + + return rc; +} + +/** + * @brief Function for hardware start + * @param sc software handle to the device + * @returns 0 on success, error otherwise + */ +int +oce_hw_start(POCE_SOFTC sc) +{ + struct link_status link = { 0 }; + int rc = 0; + + rc = oce_get_link_status(sc, &link); + if (rc) + return 1; + + if (link.logical_link_status == NTWK_LOGICAL_LINK_UP) { + sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->link_status = NTWK_LOGICAL_LINK_UP; + if_link_state_change(sc->ifp, LINK_STATE_UP); + } else { + sc->ifp->if_drv_flags &= + ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->link_status = NTWK_LOGICAL_LINK_DOWN; + if_link_state_change(sc->ifp, LINK_STATE_DOWN); + } + + if (link.mac_speed > 0 && link.mac_speed < 5) + sc->link_speed = link.mac_speed; + else + sc->link_speed = 0; + + sc->qos_link_speed = (uint32_t )link.qos_link_speed * 10; + + rc = oce_start_mq(sc->mq); + + /* we need to get MCC aync events. + So enable intrs and also arm first EQ + */ + oce_hw_intr_enable(sc); + oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE); + + return rc; +} + + +/** + * @brief Function for hardware enable interupts. + * @param sc software handle to the device + */ +void +oce_hw_intr_enable(POCE_SOFTC sc) +{ + uint32_t reg; + + reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL); + reg |= HOSTINTR_MASK; + OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg); + +} + + +/** + * @brief Function for hardware disable interupts + * @param sc software handle to the device + */ +void +oce_hw_intr_disable(POCE_SOFTC sc) +{ + uint32_t reg; + + reg = OCE_READ_REG32(sc, devcfg, PCICFG_INTR_CTRL); + reg &= ~HOSTINTR_MASK; + OCE_WRITE_REG32(sc, devcfg, PCICFG_INTR_CTRL, reg); +} + + + +/** + * @brief Function for hardware update multicast filter + * @param sc software handle to the device + */ +int +oce_hw_update_multicast(POCE_SOFTC sc) +{ + struct ifnet *ifp = sc->ifp; + struct ifmultiaddr *ifma; + struct mbx_set_common_iface_multicast *req = NULL; + OCE_DMA_MEM dma; + int rc = 0; + + /* Allocate DMA mem*/ + if (oce_dma_alloc(sc, sizeof(struct mbx_set_common_iface_multicast), + &dma, 0)) + return ENOMEM; + + req = OCE_DMAPTR(&dma, struct mbx_set_common_iface_multicast); + bzero(req, sizeof(struct mbx_set_common_iface_multicast)); + +#if __FreeBSD_version > 800000 + if_maddr_rlock(ifp); +#endif + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + if (req->params.req.num_mac == OCE_MAX_MC_FILTER_SIZE) { + /*More multicast addresses than our hardware table + So Enable multicast promiscus in our hardware to + accept all multicat packets + */ + req->params.req.promiscuous = 1; + break; + } + bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), + &req->params.req.mac[req->params.req.num_mac], + ETH_ADDR_LEN); + req->params.req.num_mac = req->params.req.num_mac + 1; + } +#if __FreeBSD_version > 800000 + if_maddr_runlock(ifp); +#endif + req->params.req.if_id = sc->if_id; + rc = oce_update_multicast(sc, &dma); + oce_dma_free(sc, &dma); + return rc; +} + diff --git a/sys/dev/oce/oce_hw.h b/sys/dev/oce/oce_hw.h new file mode 100644 index 000000000000..6aee9fa82ce2 --- /dev/null +++ b/sys/dev/oce/oce_hw.h @@ -0,0 +1,3381 @@ +/*- + * Copyright (C) 2012 Emulex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Emulex Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact Information: + * freebsd-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + +/* $FreeBSD$ */ + +#include + +#undef _BIG_ENDIAN /* TODO */ +#pragma pack(1) + +#define OC_CNA_GEN2 0x2 +#define OC_CNA_GEN3 0x3 +#define DEVID_TIGERSHARK 0x700 +#define DEVID_TOMCAT 0x710 + +/* PCI CSR offsets */ +#define PCICFG_F1_CSR 0x0 /* F1 for NIC */ +#define PCICFG_SEMAPHORE 0xbc +#define PCICFG_SOFT_RESET 0x5c +#define PCICFG_UE_STATUS_HI_MASK 0xac +#define PCICFG_UE_STATUS_LO_MASK 0xa8 +#define PCICFG_ONLINE0 0xb0 +#define PCICFG_ONLINE1 0xb4 +#define INTR_EN 0x20000000 +#define IMAGE_TRANSFER_SIZE (32 * 1024) /* 32K at a time */ + +/* CSR register offsets */ +#define MPU_EP_CONTROL 0 +#define MPU_EP_SEMAPHORE_BE3 0xac +#define MPU_EP_SEMAPHORE_XE201 0x400 +#define MPU_EP_SEMAPHORE(sc) \ + ((IS_BE(sc)) ? MPU_EP_SEMAPHORE_BE3 : MPU_EP_SEMAPHORE_XE201) +#define PCICFG_INTR_CTRL 0xfc +#define HOSTINTR_MASK (1 << 29) +#define HOSTINTR_PFUNC_SHIFT 26 +#define HOSTINTR_PFUNC_MASK 7 + +/* POST status reg struct */ +#define POST_STAGE_POWER_ON_RESET 0x00 +#define POST_STAGE_AWAITING_HOST_RDY 0x01 +#define POST_STAGE_HOST_RDY 0x02 +#define POST_STAGE_CHIP_RESET 0x03 +#define POST_STAGE_ARMFW_READY 0xc000 +#define POST_STAGE_ARMFW_UE 0xf000 + +/* DOORBELL registers */ +#define PD_RXULP_DB 0x0100 +#define PD_TXULP_DB 0x0060 +#define DB_RQ_ID_MASK 0x3FF + +#define PD_CQ_DB 0x0120 +#define PD_EQ_DB PD_CQ_DB +#define PD_MPU_MBOX_DB 0x0160 +#define PD_MQ_DB 0x0140 + +/* EQE completion types */ +#define EQ_MINOR_CODE_COMPLETION 0x00 +#define EQ_MINOR_CODE_OTHER 0x01 +#define EQ_MAJOR_CODE_COMPLETION 0x00 + +/* Link Status field values */ +#define PHY_LINK_FAULT_NONE 0x0 +#define PHY_LINK_FAULT_LOCAL 0x01 +#define PHY_LINK_FAULT_REMOTE 0x02 + +#define PHY_LINK_SPEED_ZERO 0x0 /* No link */ +#define PHY_LINK_SPEED_10MBPS 0x1 /* (10 Mbps) */ +#define PHY_LINK_SPEED_100MBPS 0x2 /* (100 Mbps) */ +#define PHY_LINK_SPEED_1GBPS 0x3 /* (1 Gbps) */ +#define PHY_LINK_SPEED_10GBPS 0x4 /* (10 Gbps) */ + +#define PHY_LINK_DUPLEX_NONE 0x0 +#define PHY_LINK_DUPLEX_HALF 0x1 +#define PHY_LINK_DUPLEX_FULL 0x2 + +#define NTWK_PORT_A 0x0 /* (Port A) */ +#define NTWK_PORT_B 0x1 /* (Port B) */ + +#define PHY_LINK_SPEED_ZERO 0x0 /* (No link.) */ +#define PHY_LINK_SPEED_10MBPS 0x1 /* (10 Mbps) */ +#define PHY_LINK_SPEED_100MBPS 0x2 /* (100 Mbps) */ +#define PHY_LINK_SPEED_1GBPS 0x3 /* (1 Gbps) */ +#define PHY_LINK_SPEED_10GBPS 0x4 /* (10 Gbps) */ + +/* Hardware Address types */ +#define MAC_ADDRESS_TYPE_STORAGE 0x0 /* (Storage MAC Address) */ +#define MAC_ADDRESS_TYPE_NETWORK 0x1 /* (Network MAC Address) */ +#define MAC_ADDRESS_TYPE_PD 0x2 /* (Protection Domain MAC Addr) */ +#define MAC_ADDRESS_TYPE_MANAGEMENT 0x3 /* (Management MAC Address) */ +#define MAC_ADDRESS_TYPE_FCOE 0x4 /* (FCoE MAC Address) */ + +/* CREATE_IFACE capability and cap_en flags */ +#define MBX_RX_IFACE_FLAGS_RSS 0x4 +#define MBX_RX_IFACE_FLAGS_PROMISCUOUS 0x8 +#define MBX_RX_IFACE_FLAGS_BROADCAST 0x10 +#define MBX_RX_IFACE_FLAGS_UNTAGGED 0x20 +#define MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS 0x80 +#define MBX_RX_IFACE_FLAGS_VLAN 0x100 +#define MBX_RX_IFACE_FLAGS_MCAST_PROMISCUOUS 0x200 +#define MBX_RX_IFACE_FLAGS_PASS_L2_ERR 0x400 +#define MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR 0x800 +#define MBX_RX_IFACE_FLAGS_MULTICAST 0x1000 +#define MBX_RX_IFACE_RX_FILTER_IF_MULTICAST_HASH 0x2000 +#define MBX_RX_IFACE_FLAGS_HDS 0x4000 +#define MBX_RX_IFACE_FLAGS_DIRECTED 0x8000 +#define MBX_RX_IFACE_FLAGS_VMQ 0x10000 +#define MBX_RX_IFACE_FLAGS_NETQ 0x20000 +#define MBX_RX_IFACE_FLAGS_QGROUPS 0x40000 +#define MBX_RX_IFACE_FLAGS_LSO 0x80000 +#define MBX_RX_IFACE_FLAGS_LRO 0x100000 + +#define MQ_RING_CONTEXT_SIZE_16 0x5 /* (16 entries) */ +#define MQ_RING_CONTEXT_SIZE_32 0x6 /* (32 entries) */ +#define MQ_RING_CONTEXT_SIZE_64 0x7 /* (64 entries) */ +#define MQ_RING_CONTEXT_SIZE_128 0x8 /* (128 entries) */ + +#define MBX_DB_READY_BIT 0x1 +#define MBX_DB_HI_BIT 0x2 +#define ASYNC_EVENT_CODE_LINK_STATE 0x1 +#define ASYNC_EVENT_LINK_UP 0x1 +#define ASYNC_EVENT_LINK_DOWN 0x0 + +/* port link_status */ +#define ASYNC_EVENT_LOGICAL 0x02 + +/* Logical Link Status */ +#define NTWK_LOGICAL_LINK_DOWN 0 +#define NTWK_LOGICAL_LINK_UP 1 + +/* Rx filter bits */ +#define NTWK_RX_FILTER_IP_CKSUM 0x1 +#define NTWK_RX_FILTER_TCP_CKSUM 0x2 +#define NTWK_RX_FILTER_UDP_CKSUM 0x4 +#define NTWK_RX_FILTER_STRIP_CRC 0x8 + +/* max SGE per mbx */ +#define MAX_MBX_SGE 19 + +/* Max multicast filter size*/ +#define OCE_MAX_MC_FILTER_SIZE 64 + +/* PCI SLI (Service Level Interface) capabilities register */ +#define OCE_INTF_REG_OFFSET 0x58 +#define OCE_INTF_VALID_SIG 6 /* register's signature */ +#define OCE_INTF_FUNC_RESET_REQD 1 +#define OCE_INTF_HINT1_NOHINT 0 +#define OCE_INTF_HINT1_SEMAINIT 1 +#define OCE_INTF_HINT1_STATCTRL 2 +#define OCE_INTF_IF_TYPE_0 0 +#define OCE_INTF_IF_TYPE_1 1 +#define OCE_INTF_IF_TYPE_2 2 +#define OCE_INTF_IF_TYPE_3 3 +#define OCE_INTF_SLI_REV3 3 /* not supported by driver */ +#define OCE_INTF_SLI_REV4 4 /* driver supports SLI-4 */ +#define OCE_INTF_PHYS_FUNC 0 +#define OCE_INTF_VIRT_FUNC 1 +#define OCE_INTF_FAMILY_BE2 0 /* not supported by driver */ +#define OCE_INTF_FAMILY_BE3 1 /* driver supports BE3 */ +#define OCE_INTF_FAMILY_A0_CHIP 0xA /* Lancer A0 chip (supported) */ +#define OCE_INTF_FAMILY_B0_CHIP 0xB /* Lancer B0 chip (future) */ + +#define NIC_WQE_SIZE 16 +#define NIC_UNICAST 0x00 +#define NIC_MULTICAST 0x01 +#define NIC_BROADCAST 0x02 + +#define NIC_HDS_NO_SPLIT 0x00 +#define NIC_HDS_SPLIT_L3PL 0x01 +#define NIC_HDS_SPLIT_L4PL 0x02 + +#define NIC_WQ_TYPE_FORWARDING 0x01 +#define NIC_WQ_TYPE_STANDARD 0x02 +#define NIC_WQ_TYPE_LOW_LATENCY 0x04 + +#define OCE_RESET_STATS 1 +#define OCE_RETAIN_STATS 0 +#define OCE_TXP_SW_SZ 48 + +typedef union pci_sli_intf_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t sli_valid:3; + uint32_t sli_hint2:5; + uint32_t sli_hint1:8; + uint32_t sli_if_type:4; + uint32_t sli_family:4; + uint32_t sli_rev:4; + uint32_t rsv0:3; + uint32_t sli_func_type:1; +#else + uint32_t sli_func_type:1; + uint32_t rsv0:3; + uint32_t sli_rev:4; + uint32_t sli_family:4; + uint32_t sli_if_type:4; + uint32_t sli_hint1:8; + uint32_t sli_hint2:5; + uint32_t sli_valid:3; +#endif + } bits; +} pci_sli_intf_t; + + + +/* physical address structure to be used in MBX */ +struct phys_addr { + /* dw0 */ + uint32_t lo; + /* dw1 */ + uint32_t hi; +}; + + + +typedef union pcicfg_intr_ctl_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t winselect:2; + uint32_t hostintr:1; + uint32_t pfnum:3; + uint32_t vf_cev_int_line_en:1; + uint32_t winaddr:23; + uint32_t membarwinen:1; +#else + uint32_t membarwinen:1; + uint32_t winaddr:23; + uint32_t vf_cev_int_line_en:1; + uint32_t pfnum:3; + uint32_t hostintr:1; + uint32_t winselect:2; +#endif + } bits; +} pcicfg_intr_ctl_t; + + + + +typedef union pcicfg_semaphore_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t rsvd:31; + uint32_t lock:1; +#else + uint32_t lock:1; + uint32_t rsvd:31; +#endif + } bits; +} pcicfg_semaphore_t; + + + + +typedef union pcicfg_soft_reset_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t nec_ll_rcvdetect:8; + uint32_t dbg_all_reqs_62_49:14; + uint32_t scratchpad0:1; + uint32_t exception_oe:1; + uint32_t soft_reset:1; + uint32_t rsvd0:7; +#else + uint32_t rsvd0:7; + uint32_t soft_reset:1; + uint32_t exception_oe:1; + uint32_t scratchpad0:1; + uint32_t dbg_all_reqs_62_49:14; + uint32_t nec_ll_rcvdetect:8; +#endif + } bits; +} pcicfg_soft_reset_t; + + + + +typedef union pcicfg_online1_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t host8_online:1; + uint32_t host7_online:1; + uint32_t host6_online:1; + uint32_t host5_online:1; + uint32_t host4_online:1; + uint32_t host3_online:1; + uint32_t host2_online:1; + uint32_t ipc_online:1; + uint32_t arm_online:1; + uint32_t txp_online:1; + uint32_t xaui_online:1; + uint32_t rxpp_online:1; + uint32_t txpb_online:1; + uint32_t rr_online:1; + uint32_t pmem_online:1; + uint32_t pctl1_online:1; + uint32_t pctl0_online:1; + uint32_t pcs1online_online:1; + uint32_t mpu_iram_online:1; + uint32_t pcs0online_online:1; + uint32_t mgmt_mac_online:1; + uint32_t lpcmemhost_online:1; +#else + uint32_t lpcmemhost_online:1; + uint32_t mgmt_mac_online:1; + uint32_t pcs0online_online:1; + uint32_t mpu_iram_online:1; + uint32_t pcs1online_online:1; + uint32_t pctl0_online:1; + uint32_t pctl1_online:1; + uint32_t pmem_online:1; + uint32_t rr_online:1; + uint32_t txpb_online:1; + uint32_t rxpp_online:1; + uint32_t xaui_online:1; + uint32_t txp_online:1; + uint32_t arm_online:1; + uint32_t ipc_online:1; + uint32_t host2_online:1; + uint32_t host3_online:1; + uint32_t host4_online:1; + uint32_t host5_online:1; + uint32_t host6_online:1; + uint32_t host7_online:1; + uint32_t host8_online:1; +#endif + } bits; +} pcicfg_online1_t; + + + +typedef union mpu_ep_semaphore_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t error:1; + uint32_t backup_fw:1; + uint32_t iscsi_no_ip:1; + uint32_t iscsi_ip_conflict:1; + uint32_t option_rom_installed:1; + uint32_t iscsi_drv_loaded:1; + uint32_t rsvd0:10; + uint32_t stage:16; +#else + uint32_t stage:16; + uint32_t rsvd0:10; + uint32_t iscsi_drv_loaded:1; + uint32_t option_rom_installed:1; + uint32_t iscsi_ip_conflict:1; + uint32_t iscsi_no_ip:1; + uint32_t backup_fw:1; + uint32_t error:1; +#endif + } bits; +} mpu_ep_semaphore_t; + + + + +typedef union mpu_ep_control_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t cpu_reset:1; + uint32_t rsvd1:15; + uint32_t ep_ram_init_status:1; + uint32_t rsvd0:12; + uint32_t m2_rxpbuf:1; + uint32_t m1_rxpbuf:1; + uint32_t m0_rxpbuf:1; +#else + uint32_t m0_rxpbuf:1; + uint32_t m1_rxpbuf:1; + uint32_t m2_rxpbuf:1; + uint32_t rsvd0:12; + uint32_t ep_ram_init_status:1; + uint32_t rsvd1:15; + uint32_t cpu_reset:1; +#endif + } bits; +} mpu_ep_control_t; + + + + +/* RX doorbell */ +typedef union pd_rxulp_db_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t num_posted:8; + uint32_t invalidate:1; + uint32_t rsvd1:13; + uint32_t qid:10; +#else + uint32_t qid:10; + uint32_t rsvd1:13; + uint32_t invalidate:1; + uint32_t num_posted:8; +#endif + } bits; +} pd_rxulp_db_t; + + +/* TX doorbell */ +typedef union pd_txulp_db_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t rsvd1:2; + uint32_t num_posted:14; + uint32_t rsvd0:6; + uint32_t qid:10; +#else + uint32_t qid:10; + uint32_t rsvd0:6; + uint32_t num_posted:14; + uint32_t rsvd1:2; +#endif + } bits; +} pd_txulp_db_t; + +/* CQ doorbell */ +typedef union cq_db_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t rsvd1:2; + uint32_t rearm:1; + uint32_t num_popped:13; + uint32_t rsvd0:5; + uint32_t event:1; + uint32_t qid:10; +#else + uint32_t qid:10; + uint32_t event:1; + uint32_t rsvd0:5; + uint32_t num_popped:13; + uint32_t rearm:1; + uint32_t rsvd1:2; +#endif + } bits; +} cq_db_t; + +/* EQ doorbell */ +typedef union eq_db_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t rsvd1:2; + uint32_t rearm:1; + uint32_t num_popped:13; + uint32_t rsvd0:5; + uint32_t event:1; + uint32_t clrint:1; + uint32_t qid:9; +#else + uint32_t qid:9; + uint32_t clrint:1; + uint32_t event:1; + uint32_t rsvd0:5; + uint32_t num_popped:13; + uint32_t rearm:1; + uint32_t rsvd1:2; +#endif + } bits; +} eq_db_t; + +/* bootstrap mbox doorbell */ +typedef union pd_mpu_mbox_db_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t address:30; + uint32_t hi:1; + uint32_t ready:1; +#else + uint32_t ready:1; + uint32_t hi:1; + uint32_t address:30; +#endif + } bits; +} pd_mpu_mbox_db_t; + +/* MQ ring doorbell */ +typedef union pd_mq_db_u { + uint32_t dw0; + struct { +#ifdef _BIG_ENDIAN + uint32_t rsvd1:2; + uint32_t num_posted:14; + uint32_t rsvd0:5; + uint32_t mq_id:11; +#else + uint32_t mq_id:11; + uint32_t rsvd0:5; + uint32_t num_posted:14; + uint32_t rsvd1:2; +#endif + } bits; +} pd_mq_db_t; + +/* + * Event Queue Entry + */ +struct oce_eqe { + uint32_t evnt; +}; + +/* MQ scatter gather entry. Array of these make an SGL */ +struct oce_mq_sge { + uint32_t pa_lo; + uint32_t pa_hi; + uint32_t length; +}; + +/* + * payload can contain an SGL or an embedded array of upto 59 dwords + */ +struct oce_mbx_payload { + union { + union { + struct oce_mq_sge sgl[MAX_MBX_SGE]; + uint32_t embedded[59]; + } u1; + uint32_t dw[59]; + } u0; +}; + +/* + * MQ MBX structure + */ +struct oce_mbx { + union { + struct { +#ifdef _BIG_ENDIAN + uint32_t special:8; + uint32_t rsvd1:16; + uint32_t sge_count:5; + uint32_t rsvd0:2; + uint32_t embedded:1; +#else + uint32_t embedded:1; + uint32_t rsvd0:2; + uint32_t sge_count:5; + uint32_t rsvd1:16; + uint32_t special:8; +#endif + } s; + uint32_t dw0; + } u0; + + uint32_t payload_length; + uint32_t tag[2]; + uint32_t rsvd2[1]; + struct oce_mbx_payload payload; +}; + +/* completion queue entry for MQ */ +struct oce_mq_cqe { + union { + struct { +#ifdef _BIG_ENDIAN + /* dw0 */ + uint32_t extended_status:16; + uint32_t completion_status:16; + /* dw1 dw2 */ + uint32_t mq_tag[2]; + /* dw3 */ + uint32_t valid:1; + uint32_t async_event:1; + uint32_t hpi_buffer_cmpl:1; + uint32_t completed:1; + uint32_t consumed:1; + uint32_t rsvd0:27; +#else + /* dw0 */ + uint32_t completion_status:16; + uint32_t extended_status:16; + /* dw1 dw2 */ + uint32_t mq_tag[2]; + /* dw3 */ + uint32_t rsvd0:27; + uint32_t consumed:1; + uint32_t completed:1; + uint32_t hpi_buffer_cmpl:1; + uint32_t async_event:1; + uint32_t valid:1; +#endif + } s; + uint32_t dw[4]; + } u0; +}; + +/* Mailbox Completion Status Codes */ +enum MBX_COMPLETION_STATUS { + MBX_CQE_STATUS_SUCCESS = 0x00, + MBX_CQE_STATUS_INSUFFICIENT_PRIVILEDGES = 0x01, + MBX_CQE_STATUS_INVALID_PARAMETER = 0x02, + MBX_CQE_STATUS_INSUFFICIENT_RESOURCES = 0x03, + MBX_CQE_STATUS_QUEUE_FLUSHING = 0x04, + MBX_CQE_STATUS_DMA_FAILED = 0x05 +}; + +struct oce_async_cqe_link_state { + union { + struct { +#ifdef _BIG_ENDIAN + /* dw0 */ + uint8_t speed; + uint8_t duplex; + uint8_t link_status; + uint8_t phy_port; + /* dw1 */ + uint16_t qos_link_speed; + uint8_t rsvd0; + uint8_t fault; + /* dw2 */ + uint32_t event_tag; + /* dw3 */ + uint32_t valid:1; + uint32_t async_event:1; + uint32_t rsvd2:6; + uint32_t event_type:8; + uint32_t event_code:8; + uint32_t rsvd1:8; +#else + /* dw0 */ + uint8_t phy_port; + uint8_t link_status; + uint8_t duplex; + uint8_t speed; + /* dw1 */ + uint8_t fault; + uint8_t rsvd0; + uint16_t qos_link_speed; + /* dw2 */ + uint32_t event_tag; + /* dw3 */ + uint32_t rsvd1:8; + uint32_t event_code:8; + uint32_t event_type:8; + uint32_t rsvd2:6; + uint32_t async_event:1; + uint32_t valid:1; +#endif + } s; + uint32_t dw[4]; + } u0; +}; + +/* MQ mailbox structure */ +struct oce_bmbx { + struct oce_mbx mbx; + struct oce_mq_cqe cqe; +}; + +/* ---[ MBXs start here ]---------------------------------------------- */ +/* MBXs sub system codes */ +enum MBX_SUBSYSTEM_CODES { + MBX_SUBSYSTEM_RSVD = 0, + MBX_SUBSYSTEM_COMMON = 1, + MBX_SUBSYSTEM_COMMON_ISCSI = 2, + MBX_SUBSYSTEM_NIC = 3, + MBX_SUBSYSTEM_TOE = 4, + MBX_SUBSYSTEM_PXE_UNDI = 5, + MBX_SUBSYSTEM_ISCSI_INI = 6, + MBX_SUBSYSTEM_ISCSI_TGT = 7, + MBX_SUBSYSTEM_MILI_PTL = 8, + MBX_SUBSYSTEM_MILI_TMD = 9, + MBX_SUBSYSTEM_RDMA = 10, + MBX_SUBSYSTEM_LOWLEVEL = 11, + MBX_SUBSYSTEM_LRO = 13, + IOCBMBX_SUBSYSTEM_DCBX = 15, + IOCBMBX_SUBSYSTEM_DIAG = 16, + IOCBMBX_SUBSYSTEM_VENDOR = 17 +}; + +/* common ioctl opcodes */ +enum COMMON_SUBSYSTEM_OPCODES { +/* These opcodes are common to both networking and storage PCI functions + * They are used to reserve resources and configure CNA. These opcodes + * all use the MBX_SUBSYSTEM_COMMON subsystem code. + */ + OPCODE_COMMON_QUERY_IFACE_MAC = 1, + OPCODE_COMMON_SET_IFACE_MAC = 2, + OPCODE_COMMON_SET_IFACE_MULTICAST = 3, + OPCODE_COMMON_CONFIG_IFACE_VLAN = 4, + OPCODE_COMMON_QUERY_LINK_CONFIG = 5, + OPCODE_COMMON_READ_FLASHROM = 6, + OPCODE_COMMON_WRITE_FLASHROM = 7, + OPCODE_COMMON_QUERY_MAX_MBX_BUFFER_SIZE = 8, + OPCODE_COMMON_CREATE_CQ = 12, + OPCODE_COMMON_CREATE_EQ = 13, + OPCODE_COMMON_CREATE_MQ = 21, + OPCODE_COMMON_GET_QOS = 27, + OPCODE_COMMON_SET_QOS = 28, + OPCODE_COMMON_READ_EPROM = 30, + OPCODE_COMMON_GET_CNTL_ATTRIBUTES = 32, + OPCODE_COMMON_NOP = 33, + OPCODE_COMMON_SET_IFACE_RX_FILTER = 34, + OPCODE_COMMON_GET_FW_VERSION = 35, + OPCODE_COMMON_SET_FLOW_CONTROL = 36, + OPCODE_COMMON_GET_FLOW_CONTROL = 37, + OPCODE_COMMON_SET_FRAME_SIZE = 39, + OPCODE_COMMON_MODIFY_EQ_DELAY = 41, + OPCODE_COMMON_CREATE_IFACE = 50, + OPCODE_COMMON_DESTROY_IFACE = 51, + OPCODE_COMMON_MODIFY_MSI_MESSAGES = 52, + OPCODE_COMMON_DESTROY_MQ = 53, + OPCODE_COMMON_DESTROY_CQ = 54, + OPCODE_COMMON_DESTROY_EQ = 55, + OPCODE_COMMON_UPLOAD_TCP = 56, + OPCODE_COMMON_SET_NTWK_LINK_SPEED = 57, + OPCODE_COMMON_QUERY_FIRMWARE_CONFIG = 58, + OPCODE_COMMON_ADD_IFACE_MAC = 59, + OPCODE_COMMON_DEL_IFACE_MAC = 60, + OPCODE_COMMON_FUNCTION_RESET = 61, + OPCODE_COMMON_SET_PHYSICAL_LINK_CONFIG = 62, + OPCODE_COMMON_GET_BOOT_CONFIG = 66, + OPCPDE_COMMON_SET_BOOT_CONFIG = 67, + OPCODE_COMMON_SET_BEACON_CONFIG = 69, + OPCODE_COMMON_GET_BEACON_CONFIG = 70, + OPCODE_COMMON_GET_PHYSICAL_LINK_CONFIG = 71, + OPCODE_COMMON_GET_OEM_ATTRIBUTES = 76, + OPCODE_COMMON_GET_PORT_NAME = 77, + OPCODE_COMMON_GET_CONFIG_SIGNATURE = 78, + OPCODE_COMMON_SET_CONFIG_SIGNATURE = 79, + OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG = 80, + OPCODE_COMMON_GET_BE_CONFIGURATION_RESOURCES = 81, + OPCODE_COMMON_SET_BE_CONFIGURATION_RESOURCES = 82, + OPCODE_COMMON_GET_RESET_NEEDED = 84, + OPCODE_COMMON_GET_SERIAL_NUMBER = 85, + OPCODE_COMMON_GET_NCSI_CONFIG = 86, + OPCODE_COMMON_SET_NCSI_CONFIG = 87, + OPCODE_COMMON_CREATE_MQ_EXT = 90, + OPCODE_COMMON_SET_FUNCTION_PRIVILEGES = 100, + OPCODE_COMMON_SET_VF_PORT_TYPE = 101, + OPCODE_COMMON_GET_PHY_CONFIG = 102, + OPCODE_COMMON_SET_FUNCTIONAL_CAPS = 103, + OPCODE_COMMON_GET_ADAPTER_ID = 110, + OPCODE_COMMON_GET_UPGRADE_FEATURES = 111, + OPCODE_COMMON_GET_INSTALLED_FEATURES = 112, + OPCODE_COMMON_GET_AVAIL_PERSONALITIES = 113, + OPCODE_COMMON_GET_CONFIG_PERSONALITIES = 114, + OPCODE_COMMON_SEND_ACTIVATION = 115, + OPCODE_COMMON_RESET_LICENSES = 116, + OPCODE_COMMON_GET_CNTL_ADDL_ATTRIBUTES = 121, + OPCODE_COMMON_QUERY_TCB = 144, + OPCODE_COMMON_ADD_IFACE_QUEUE_FILTER = 145, + OPCODE_COMMON_DEL_IFACE_QUEUE_FILTER = 146, + OPCODE_COMMON_GET_IFACE_MAC_LIST = 147, + OPCODE_COMMON_SET_IFACE_MAC_LIST = 148, + OPCODE_COMMON_MODIFY_CQ = 149, + OPCODE_COMMON_GET_IFACE_VLAN_LIST = 150, + OPCODE_COMMON_SET_IFACE_VLAN_LIST = 151, + OPCODE_COMMON_GET_HSW_CONFIG = 152, + OPCODE_COMMON_SET_HSW_CONFIG = 153, + OPCODE_COMMON_GET_RESOURCE_EXTENT_INFO = 154, + OPCODE_COMMON_GET_ALLOCATED_RESOURCE_EXTENTS = 155, + OPCODE_COMMON_ALLOC_RESOURCE_EXTENTS = 156, + OPCODE_COMMON_DEALLOC_RESOURCE_EXTENTS = 157, + OPCODE_COMMON_SET_DIAG_REGISTERS = 158, + OPCODE_COMMON_GET_FUNCTION_CONFIG = 160, + OPCODE_COMMON_GET_PROFILE_CAPACITIES = 161, + OPCODE_COMMON_GET_MR_PROFILE_CAPACITIES = 162, + OPCODE_COMMON_SET_MR_PROFILE_CAPACITIES = 163, + OPCODE_COMMON_GET_PROFILE_CONFIG = 164, + OPCODE_COMMON_SET_PROFILE_CONFIG = 165, + OPCODE_COMMON_GET_PROFILE_LIST = 166, + OPCODE_COMMON_GET_ACTIVE_PROFILE = 167, + OPCODE_COMMON_SET_ACTIVE_PROFILE = 168, + OPCODE_COMMON_GET_FUNCTION_PRIVILEGES = 170, + OPCODE_COMMON_READ_OBJECT = 171, + OPCODE_COMMON_WRITE_OBJECT = 172 +}; + +/* common ioctl header */ +#define OCE_MBX_VER_V2 0x0002 /* Version V2 mailbox command */ +#define OCE_MBX_VER_V1 0x0001 /* Version V1 mailbox command */ +#define OCE_MBX_VER_V0 0x0000 /* Version V0 mailbox command */ +struct mbx_hdr { + union { + uint32_t dw[4]; + struct { + #ifdef _BIG_ENDIAN + /* dw 0 */ + uint32_t domain:8; + uint32_t port_number:8; + uint32_t subsystem:8; + uint32_t opcode:8; + /* dw 1 */ + uint32_t timeout; + /* dw 2 */ + uint32_t request_length; + /* dw 3 */ + uint32_t rsvd0:24; + uint32_t version:8; + #else + /* dw 0 */ + uint32_t opcode:8; + uint32_t subsystem:8; + uint32_t port_number:8; + uint32_t domain:8; + /* dw 1 */ + uint32_t timeout; + /* dw 2 */ + uint32_t request_length; + /* dw 3 */ + uint32_t version:8; + uint32_t rsvd0:24; + #endif + } req; + struct { + #ifdef _BIG_ENDIAN + /* dw 0 */ + uint32_t domain:8; + uint32_t rsvd0:8; + uint32_t subsystem:8; + uint32_t opcode:8; + /* dw 1 */ + uint32_t rsvd1:16; + uint32_t additional_status:8; + uint32_t status:8; + #else + /* dw 0 */ + uint32_t opcode:8; + uint32_t subsystem:8; + uint32_t rsvd0:8; + uint32_t domain:8; + /* dw 1 */ + uint32_t status:8; + uint32_t additional_status:8; + uint32_t rsvd1:16; + #endif + uint32_t rsp_length; + uint32_t actual_rsp_length; + } rsp; + } u0; +}; +#define OCE_BMBX_RHDR_SZ 20 +#define OCE_MBX_RRHDR_SZ sizeof (struct mbx_hdr) +#define OCE_MBX_ADDL_STATUS(_MHDR) ((_MHDR)->u0.rsp.additional_status) +#define OCE_MBX_STATUS(_MHDR) ((_MHDR)->u0.rsp.status) + +/* [05] OPCODE_COMMON_QUERY_LINK_CONFIG */ +struct mbx_query_common_link_config { + struct mbx_hdr hdr; + union { + struct { + uint32_t rsvd0; + } req; + + struct { + /* dw 0 */ + uint8_t physical_port; + uint8_t mac_duplex; + uint8_t mac_speed; + uint8_t mac_fault; + /* dw 1 */ + uint8_t mgmt_mac_duplex; + uint8_t mgmt_mac_speed; + uint16_t qos_link_speed; + uint32_t logical_link_status; + } rsp; + } params; +}; + +/* [57] OPCODE_COMMON_SET_LINK_SPEED */ +struct mbx_set_common_link_speed { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + uint8_t rsvd0; + uint8_t mac_speed; + uint8_t virtual_port; + uint8_t physical_port; +#else + uint8_t physical_port; + uint8_t virtual_port; + uint8_t mac_speed; + uint8_t rsvd0; +#endif + } req; + + struct { + uint32_t rsvd0; + } rsp; + + uint32_t dw; + } params; +}; + +struct mac_address_format { + uint16_t size_of_struct; + uint8_t mac_addr[6]; +}; + +/* [01] OPCODE_COMMON_QUERY_IFACE_MAC */ +struct mbx_query_common_iface_mac { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + uint16_t if_id; + uint8_t permanent; + uint8_t type; +#else + uint8_t type; + uint8_t permanent; + uint16_t if_id; +#endif + + } req; + + struct { + struct mac_address_format mac; + } rsp; + } params; +}; + +/* [02] OPCODE_COMMON_SET_IFACE_MAC */ +struct mbx_set_common_iface_mac { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + /* dw 0 */ + uint16_t if_id; + uint8_t invalidate; + uint8_t type; +#else + /* dw 0 */ + uint8_t type; + uint8_t invalidate; + uint16_t if_id; +#endif + /* dw 1 */ + struct mac_address_format mac; + } req; + + struct { + uint32_t rsvd0; + } rsp; + + uint32_t dw[2]; + } params; +}; + +/* [03] OPCODE_COMMON_SET_IFACE_MULTICAST */ +struct mbx_set_common_iface_multicast { + struct mbx_hdr hdr; + union { + struct { + /* dw 0 */ + uint16_t num_mac; + uint8_t promiscuous; + uint8_t if_id; + /* dw 1-48 */ + struct { + uint8_t byte[6]; + } mac[32]; + + } req; + + struct { + uint32_t rsvd0; + } rsp; + + uint32_t dw[49]; + } params; +}; + +struct qinq_vlan { +#ifdef _BIG_ENDIAN + uint16_t inner; + uint16_t outer; +#else + uint16_t outer; + uint16_t inner; +#endif +}; + +struct normal_vlan { + uint16_t vtag; +}; + +struct ntwk_if_vlan_tag { + union { + struct normal_vlan normal; + struct qinq_vlan qinq; + } u0; +}; + +/* [50] OPCODE_COMMON_CREATE_IFACE */ +struct mbx_create_common_iface { + struct mbx_hdr hdr; + union { + struct { + uint32_t version; + uint32_t cap_flags; + uint32_t enable_flags; + uint8_t mac_addr[6]; + uint8_t rsvd0; + uint8_t mac_invalid; + struct ntwk_if_vlan_tag vlan_tag; + } req; + + struct { + uint32_t if_id; + uint32_t pmac_id; + } rsp; + uint32_t dw[4]; + } params; +}; + +/* [51] OPCODE_COMMON_DESTROY_IFACE */ +struct mbx_destroy_common_iface { + struct mbx_hdr hdr; + union { + struct { + uint32_t if_id; + } req; + + struct { + uint32_t rsvd0; + } rsp; + + uint32_t dw; + } params; +}; + +/* event queue context structure */ +struct oce_eq_ctx { +#ifdef _BIG_ENDIAN + uint32_t dw4rsvd1:16; + uint32_t num_pages:16; + + uint32_t size:1; + uint32_t dw5rsvd2:1; + uint32_t valid:1; + uint32_t dw5rsvd1:29; + + uint32_t armed:1; + uint32_t dw6rsvd2:2; + uint32_t count:3; + uint32_t dw6rsvd1:26; + + uint32_t dw7rsvd2:9; + uint32_t delay_mult:10; + uint32_t dw7rsvd1:13; + + uint32_t dw8rsvd1; +#else + uint32_t num_pages:16; + uint32_t dw4rsvd1:16; + + uint32_t dw5rsvd1:29; + uint32_t valid:1; + uint32_t dw5rsvd2:1; + uint32_t size:1; + + uint32_t dw6rsvd1:26; + uint32_t count:3; + uint32_t dw6rsvd2:2; + uint32_t armed:1; + + uint32_t dw7rsvd1:13; + uint32_t delay_mult:10; + uint32_t dw7rsvd2:9; + + uint32_t dw8rsvd1; +#endif +}; + +/* [13] OPCODE_COMMON_CREATE_EQ */ +struct mbx_create_common_eq { + struct mbx_hdr hdr; + union { + struct { + struct oce_eq_ctx ctx; + struct phys_addr pages[8]; + } req; + + struct { + uint16_t eq_id; + uint16_t rsvd0; + } rsp; + } params; +}; + +/* [55] OPCODE_COMMON_DESTROY_EQ */ +struct mbx_destroy_common_eq { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + uint16_t rsvd0; + uint16_t id; +#else + uint16_t id; + uint16_t rsvd0; +#endif + } req; + + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + +/* SLI-4 CQ context - use version V0 for B3, version V2 for Lancer */ +typedef union oce_cq_ctx_u { + uint32_t dw[5]; + struct { + #ifdef _BIG_ENDIAN + /* dw4 */ + uint32_t dw4rsvd1:16; + uint32_t num_pages:16; + /* dw5 */ + uint32_t eventable:1; + uint32_t dw5rsvd3:1; + uint32_t valid:1; + uint32_t count:2; + uint32_t dw5rsvd2:12; + uint32_t nodelay:1; + uint32_t coalesce_wm:2; + uint32_t dw5rsvd1:12; + /* dw6 */ + uint32_t armed:1; + uint32_t dw6rsvd2:1; + uint32_t eq_id:8; + uint32_t dw6rsvd1:22; + #else + /* dw4 */ + uint32_t num_pages:16; + uint32_t dw4rsvd1:16; + /* dw5 */ + uint32_t dw5rsvd1:12; + uint32_t coalesce_wm:2; + uint32_t nodelay:1; + uint32_t dw5rsvd2:12; + uint32_t count:2; + uint32_t valid:1; + uint32_t dw5rsvd3:1; + uint32_t eventable:1; + /* dw6 */ + uint32_t dw6rsvd1:22; + uint32_t eq_id:8; + uint32_t dw6rsvd2:1; + uint32_t armed:1; + #endif + /* dw7 */ + uint32_t dw7rsvd1; + /* dw8 */ + uint32_t dw8rsvd1; + } v0; + struct { + #ifdef _BIG_ENDIAN + /* dw4 */ + uint32_t dw4rsvd1:8; + uint32_t page_size:8; + uint32_t num_pages:16; + /* dw5 */ + uint32_t eventable:1; + uint32_t dw5rsvd3:1; + uint32_t valid:1; + uint32_t count:2; + uint32_t dw5rsvd2:11; + uint32_t autovalid:1; + uint32_t nodelay:1; + uint32_t coalesce_wm:2; + uint32_t dw5rsvd1:12; + /* dw6 */ + uint32_t armed:1; + uint32_t dw6rsvd1:15; + uint32_t eq_id:16; + /* dw7 */ + uint32_t dw7rsvd1:16; + uint32_t cqe_count:16; + #else + /* dw4 */ + uint32_t num_pages:16; + uint32_t page_size:8; + uint32_t dw4rsvd1:8; + /* dw5 */ + uint32_t dw5rsvd1:12; + uint32_t coalesce_wm:2; + uint32_t nodelay:1; + uint32_t autovalid:1; + uint32_t dw5rsvd2:11; + uint32_t count:2; + uint32_t valid:1; + uint32_t dw5rsvd3:1; + uint32_t eventable:1; + /* dw6 */ + uint32_t eq_id:8; + uint32_t dw6rsvd1:15; + uint32_t armed:1; + /* dw7 */ + uint32_t cqe_count:16; + uint32_t dw7rsvd1:16; + #endif + /* dw8 */ + uint32_t dw8rsvd1; + } v2; +} oce_cq_ctx_t; + +/* [12] OPCODE_COMMON_CREATE_CQ */ +struct mbx_create_common_cq { + struct mbx_hdr hdr; + union { + struct { + oce_cq_ctx_t cq_ctx; + struct phys_addr pages[4]; + } req; + + struct { + uint16_t cq_id; + uint16_t rsvd0; + } rsp; + } params; +}; + +/* [54] OPCODE_COMMON_DESTROY_CQ */ +struct mbx_destroy_common_cq { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + uint16_t rsvd0; + uint16_t id; +#else + uint16_t id; + uint16_t rsvd0; +#endif + } req; + + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + +typedef union oce_mq_ctx_u { + uint32_t dw[5]; + struct { + #ifdef _BIG_ENDIAN + /* dw4 */ + uint32_t dw4rsvd1:16; + uint32_t num_pages:16; + /* dw5 */ + uint32_t cq_id:10; + uint32_t dw5rsvd2:2; + uint32_t ring_size:4; + uint32_t dw5rsvd1:16; + /* dw6 */ + uint32_t valid:1; + uint32_t dw6rsvd1:31; + /* dw7 */ + uint32_t dw7rsvd1:21; + uint32_t async_cq_id:10; + uint32_t async_cq_valid:1; + #else + /* dw4 */ + uint32_t num_pages:16; + uint32_t dw4rsvd1:16; + /* dw5 */ + uint32_t dw5rsvd1:16; + uint32_t ring_size:4; + uint32_t dw5rsvd2:2; + uint32_t cq_id:10; + /* dw6 */ + uint32_t dw6rsvd1:31; + uint32_t valid:1; + /* dw7 */ + uint32_t async_cq_valid:1; + uint32_t async_cq_id:10; + uint32_t dw7rsvd1:21; + #endif + /* dw8 */ + uint32_t dw8rsvd1; + } v0; +} oce_mq_ctx_t; + +/** + * @brief [21] OPCODE_COMMON_CREATE_MQ + * A MQ must be at least 16 entries deep (corresponding to 1 page) and + * at most 128 entries deep (corresponding to 8 pages). + */ +struct mbx_create_common_mq { + struct mbx_hdr hdr; + union { + struct { + oce_mq_ctx_t context; + struct phys_addr pages[8]; + } req; + + struct { + uint32_t mq_id:16; + uint32_t rsvd0:16; + } rsp; + } params; +}; + +/* [53] OPCODE_COMMON_DESTROY_MQ */ +struct mbx_destroy_common_mq { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + uint16_t rsvd0; + uint16_t id; +#else + uint16_t id; + uint16_t rsvd0; +#endif + } req; + + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + +/* [35] OPCODE_COMMON_GET_ FW_VERSION */ +struct mbx_get_common_fw_version { + struct mbx_hdr hdr; + union { + struct { + uint32_t rsvd0; + } req; + + struct { + uint8_t fw_ver_str[32]; + uint8_t fw_on_flash_ver_str[32]; + } rsp; + } params; +}; + +/* [52] OPCODE_COMMON_CEV_MODIFY_MSI_MESSAGES */ +struct mbx_common_cev_modify_msi_messages { + struct mbx_hdr hdr; + union { + struct { + uint32_t num_msi_msgs; + } req; + + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + +/* [36] OPCODE_COMMON_SET_FLOW_CONTROL */ +/* [37] OPCODE_COMMON_GET_FLOW_CONTROL */ +struct mbx_common_get_set_flow_control { + struct mbx_hdr hdr; +#ifdef _BIG_ENDIAN + uint16_t tx_flow_control; + uint16_t rx_flow_control; +#else + uint16_t rx_flow_control; + uint16_t tx_flow_control; +#endif +}; + +enum e_flash_opcode { + MGMT_FLASHROM_OPCODE_FLASH = 1, + MGMT_FLASHROM_OPCODE_SAVE = 2 +}; + +/* [06] OPCODE_READ_COMMON_FLASHROM */ +/* [07] OPCODE_WRITE_COMMON_FLASHROM */ + +struct mbx_common_read_write_flashrom { + struct mbx_hdr hdr; + uint32_t flash_op_code; + uint32_t flash_op_type; + uint32_t data_buffer_size; + uint32_t data_offset; + uint8_t data_buffer[4]; /* + IMAGE_TRANSFER_SIZE */ +}; + +struct oce_phy_info { + uint16_t phy_type; + uint16_t interface_type; + uint32_t misc_params; + uint16_t ext_phy_details; + uint16_t rsvd; + uint16_t auto_speeds_supported; + uint16_t fixed_speeds_supported; + uint32_t future_use[2]; +}; + +struct mbx_common_phy_info { + struct mbx_hdr hdr; + union { + struct { + uint32_t rsvd0[4]; + } req; + struct { + struct oce_phy_info phy_info; + } rsp; + } params; +}; + +/*Lancer firmware*/ + +struct mbx_lancer_common_write_object { + union { + struct { + struct mbx_hdr hdr; + uint32_t write_length: 24; + uint32_t rsvd: 7; + uint32_t eof: 1; + uint32_t write_offset; + uint8_t object_name[104]; + uint32_t descriptor_count; + uint32_t buffer_length; + uint32_t address_lower; + uint32_t address_upper; + } req; + struct { + uint8_t opcode; + uint8_t subsystem; + uint8_t rsvd1[2]; + uint8_t status; + uint8_t additional_status; + uint8_t rsvd2[2]; + uint32_t response_length; + uint32_t actual_response_length; + uint32_t actual_write_length; + } rsp; + } params; +}; + +/** + * @brief MBX Common Quiery Firmaware Config + * This command retrieves firmware configuration parameters and adapter + * resources available to the driver originating the request. The firmware + * configuration defines supported protocols by the installed adapter firmware. + * This includes which ULP processors support the specified protocols and + * the number of TCP connections allowed for that protocol. + */ +struct mbx_common_query_fw_config { + struct mbx_hdr hdr; + union { + struct { + uint32_t rsvd0[30]; + } req; + + struct { + uint32_t config_number; + uint32_t asic_revision; + uint32_t port_id; /* used for stats retrieval */ + uint32_t function_mode; + struct { + + uint32_t ulp_mode; + uint32_t nic_wqid_base; + uint32_t nic_wq_tot; + uint32_t toe_wqid_base; + uint32_t toe_wq_tot; + uint32_t toe_rqid_base; + uint32_t toe_rqid_tot; + uint32_t toe_defrqid_base; + uint32_t toe_defrqid_count; + uint32_t lro_rqid_base; + uint32_t lro_rqid_tot; + uint32_t iscsi_icd_base; + uint32_t iscsi_icd_count; + } ulp[2]; + uint32_t function_caps; + uint32_t cqid_base; + uint32_t cqid_tot; + uint32_t eqid_base; + uint32_t eqid_tot; + } rsp; + } params; +}; + +enum CQFW_CONFIG_NUMBER { + FCN_NIC_ISCSI_Initiator = 0x0, + FCN_ISCSI_Target = 0x3, + FCN_FCoE = 0x7, + FCN_ISCSI_Initiator_Target = 0x9, + FCN_NIC_RDMA_TOE = 0xA, + FCN_NIC_RDMA_FCoE = 0xB, + FCN_NIC_RDMA_iSCSI = 0xC, + FCN_NIC_iSCSI_FCoE = 0xD +}; + +/** + * @brief Function Capabilites + * This field contains the flags indicating the capabilities of + * the SLI Host’s PCI function. + */ +enum CQFW_FUNCTION_CAPABILITIES { + FNC_UNCLASSIFIED_STATS = 0x1, + FNC_RSS = 0x2, + FNC_PROMISCUOUS = 0x4, + FNC_LEGACY_MODE = 0x8, + FNC_HDS = 0x4000, + FNC_VMQ = 0x10000, + FNC_NETQ = 0x20000, + FNC_QGROUPS = 0x40000, + FNC_LRO = 0x100000, + FNC_VLAN_OFFLOAD = 0x800000 +}; + +enum CQFW_ULP_MODES_SUPPORTED { + ULP_TOE_MODE = 0x1, + ULP_NIC_MODE = 0x2, + ULP_RDMA_MODE = 0x4, + ULP_ISCSI_INI_MODE = 0x10, + ULP_ISCSI_TGT_MODE = 0x20, + ULP_FCOE_INI_MODE = 0x40, + ULP_FCOE_TGT_MODE = 0x80, + ULP_DAL_MODE = 0x100, + ULP_LRO_MODE = 0x200 +}; + +/** + * @brief Function Modes Supported + * Valid function modes (or protocol-types) supported on the SLI-Host’s + * PCIe function. This field is a logical OR of the following values: + */ +enum CQFW_FUNCTION_MODES_SUPPORTED { + FNM_TOE_MODE = 0x1, /* TCP offload supported */ + FNM_NIC_MODE = 0x2, /* Raw Ethernet supported */ + FNM_RDMA_MODE = 0x4, /* RDMA protocol supported */ + FNM_VM_MODE = 0x8, /* Virtual Machines supported */ + FNM_ISCSI_INI_MODE = 0x10, /* iSCSI initiator supported */ + FNM_ISCSI_TGT_MODE = 0x20, /* iSCSI target plus initiator */ + FNM_FCOE_INI_MODE = 0x40, /* FCoE Initiator supported */ + FNM_FCOE_TGT_MODE = 0x80, /* FCoE target supported */ + FNM_DAL_MODE = 0x100, /* DAL supported */ + FNM_LRO_MODE = 0x200, /* LRO supported */ + FNM_FLEX10_MODE = 0x400, /* QinQ, FLEX-10 or VNIC */ + FNM_NCSI_MODE = 0x800, /* NCSI supported */ + FNM_IPV6_MODE = 0x1000, /* IPV6 stack enabled */ + FNM_BE2_COMPAT_MODE = 0x2000, /* BE2 compatibility (BE3 disable)*/ + FNM_INVALID_MODE = 0x8000, /* Invalid */ + FNM_BE3_COMPAT_MODE = 0x10000, /* BE3 features */ + FNM_VNIC_MODE = 0x20000, /* Set when IBM vNIC mode is set */ + FNM_VNTAG_MODE = 0x40000, /* Set when VNTAG mode is set */ + FNM_UMC_MODE = 0x80000, /* Set when UMC mode is set */ + FNM_UMC_DEF_EN = 0x100000, /* Set when UMC Default is set */ + FNM_ONE_GB_EN = 0x200000, /* Set when 1GB Default is set */ + FNM_VNIC_DEF_VALID = 0x400000, /* Set when VNIC_DEF_EN is valid */ + FNM_VNIC_DEF_EN = 0x800000 /* Set when VNIC Default enabled */ +}; + + +struct mbx_common_config_vlan { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + uint8_t num_vlans; + uint8_t untagged; + uint8_t promisc; + uint8_t if_id; +#else + uint8_t if_id; + uint8_t promisc; + uint8_t untagged; + uint8_t num_vlans; +#endif + union { + struct normal_vlan normal_vlans[64]; + struct qinq_vlan qinq_vlans[32]; + } tags; + } req; + + struct { + uint32_t rsvd; + } rsp; + } params; +}; + +typedef struct iface_rx_filter_ctx { + uint32_t global_flags_mask; + uint32_t global_flags; + uint32_t iface_flags_mask; + uint32_t iface_flags; + uint32_t if_id; + #define IFACE_RX_NUM_MCAST_MAX 64 + uint32_t num_mcast; + struct mbx_mcast_addr { + uint8_t byte[6]; + } mac[IFACE_RX_NUM_MCAST_MAX]; +} iface_rx_filter_ctx_t; + +/* [34] OPCODE_COMMON_SET_IFACE_RX_FILTER */ +struct mbx_set_common_iface_rx_filter { + struct mbx_hdr hdr; + union { + iface_rx_filter_ctx_t req; + iface_rx_filter_ctx_t rsp; + } params; +}; + +/* [41] OPCODE_COMMON_MODIFY_EQ_DELAY */ +struct mbx_modify_common_eq_delay { + struct mbx_hdr hdr; + union { + struct { + uint32_t num_eq; + struct { + uint32_t eq_id; + uint32_t phase; + uint32_t dm; + } delay[8]; + } req; + + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + +/* [59] OPCODE_ADD_COMMON_IFACE_MAC */ +struct mbx_add_common_iface_mac { + struct mbx_hdr hdr; + union { + struct { + uint32_t if_id; + uint8_t mac_address[6]; + uint8_t rsvd0[2]; + } req; + struct { + uint32_t pmac_id; + } rsp; + } params; +}; + +/* [60] OPCODE_DEL_COMMON_IFACE_MAC */ +struct mbx_del_common_iface_mac { + struct mbx_hdr hdr; + union { + struct { + uint32_t if_id; + uint32_t pmac_id; + } req; + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + +/* [8] OPCODE_QUERY_COMMON_MAX_MBX_BUFFER_SIZE */ +struct mbx_query_common_max_mbx_buffer_size { + struct mbx_hdr hdr; + struct { + uint32_t max_ioctl_bufsz; + } rsp; +}; + +/* [61] OPCODE_COMMON_FUNCTION_RESET */ +struct ioctl_common_function_reset { + struct mbx_hdr hdr; +}; + +/* [80] OPCODE_COMMON_FUNCTION_LINK_CONFIG */ +struct mbx_common_func_link_cfg { + struct mbx_hdr hdr; + union { + struct { + uint32_t enable; + } req; + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + +/* [103] OPCODE_COMMON_SET_FUNCTIONAL_CAPS */ +#define CAP_SW_TIMESTAMPS 2 +#define CAP_BE3_NATIVE_ERX_API 4 + +struct mbx_common_set_function_cap { + struct mbx_hdr hdr; + union { + struct { + uint32_t valid_capability_flags; + uint32_t capability_flags; + uint8_t sbz[212]; + } req; + struct { + uint32_t valid_capability_flags; + uint32_t capability_flags; + uint8_t sbz[212]; + } rsp; + } params; +}; +struct mbx_lowlevel_test_loopback_mode { + struct mbx_hdr hdr; + union { + struct { + uint32_t loopback_type; + uint32_t num_pkts; + uint64_t pattern; + uint32_t src_port; + uint32_t dest_port; + uint32_t pkt_size; + }req; + struct { + uint32_t status; + uint32_t num_txfer; + uint32_t num_rx; + uint32_t miscomp_off; + uint32_t ticks_compl; + }rsp; + } params; +}; + +struct mbx_lowlevel_set_loopback_mode { + struct mbx_hdr hdr; + union { + struct { + uint8_t src_port; + uint8_t dest_port; + uint8_t loopback_type; + uint8_t loopback_state; + } req; + struct { + uint8_t rsvd0[4]; + } rsp; + } params; +}; + +struct flash_file_hdr { + uint8_t sign[52]; + uint8_t ufi_version[4]; + uint32_t file_len; + uint32_t cksum; + uint32_t antidote; + uint32_t num_imgs; + uint8_t build[24]; + uint8_t rsvd[32]; +}; + +struct image_hdr { + uint32_t imageid; + uint32_t imageoffset; + uint32_t imagelength; + uint32_t image_checksum; + uint8_t image_version[32]; +}; + +struct flash_section_hdr { + uint32_t format_rev; + uint32_t cksum; + uint32_t antidote; + uint32_t num_images; + uint8_t id_string[128]; + uint32_t rsvd[4]; +}; + +struct flash_section_entry { + uint32_t type; + uint32_t offset; + uint32_t pad_size; + uint32_t image_size; + uint32_t cksum; + uint32_t entry_point; + uint32_t rsvd0; + uint32_t rsvd1; + uint8_t ver_data[32]; +}; + +struct flash_sec_info { + uint8_t cookie[32]; + struct flash_section_hdr fsec_hdr; + struct flash_section_entry fsec_entry[32]; +}; + + +enum LOWLEVEL_SUBSYSTEM_OPCODES { +/* Opcodes used for lowlevel functions common to many subystems. + * Some of these opcodes are used for diagnostic functions only. + * These opcodes use the MBX_SUBSYSTEM_LOWLEVEL subsystem code. + */ + OPCODE_LOWLEVEL_TEST_LOOPBACK = 18, + OPCODE_LOWLEVEL_SET_LOOPBACK_MODE = 19, + OPCODE_LOWLEVEL_GET_LOOPBACK_MODE = 20 +}; + +enum LLDP_SUBSYSTEM_OPCODES { +/* Opcodes used for LLDP susbsytem for configuring the LLDP state machines. */ + OPCODE_LLDP_GET_CFG = 1, + OPCODE_LLDP_SET_CFG = 2, + OPCODE_LLDP_GET_STATS = 3 +}; + +enum DCBX_SUBSYSTEM_OPCODES { +/* Opcodes used for DCBX. */ + OPCODE_DCBX_GET_CFG = 1, + OPCODE_DCBX_SET_CFG = 2, + OPCODE_DCBX_GET_MIB_INFO = 3, + OPCODE_DCBX_GET_DCBX_MODE = 4, + OPCODE_DCBX_SET_MODE = 5 +}; + +enum DMTF_SUBSYSTEM_OPCODES { +/* Opcodes used for DCBX subsystem. */ + OPCODE_DMTF_EXEC_CLP_CMD = 1 +}; + +enum DIAG_SUBSYSTEM_OPCODES { +/* Opcodes used for diag functions common to many subsystems. */ + OPCODE_DIAG_RUN_DMA_TEST = 1, + OPCODE_DIAG_RUN_MDIO_TEST = 2, + OPCODE_DIAG_RUN_NLB_TEST = 3, + OPCODE_DIAG_RUN_ARM_TIMER_TEST = 4, + OPCODE_DIAG_GET_MAC = 5 +}; + +enum VENDOR_SUBSYSTEM_OPCODES { +/* Opcodes used for Vendor subsystem. */ + OPCODE_VENDOR_SLI = 1 +}; + +/* Management Status Codes */ +enum MGMT_STATUS_SUCCESS { + MGMT_SUCCESS = 0, + MGMT_FAILED = 1, + MGMT_ILLEGAL_REQUEST = 2, + MGMT_ILLEGAL_FIELD = 3, + MGMT_INSUFFICIENT_BUFFER = 4, + MGMT_UNAUTHORIZED_REQUEST = 5, + MGMT_INVALID_ISNS_ADDRESS = 10, + MGMT_INVALID_IPADDR = 11, + MGMT_INVALID_GATEWAY = 12, + MGMT_INVALID_SUBNETMASK = 13, + MGMT_INVALID_TARGET_IPADDR = 16, + MGMT_TGTTBL_FULL = 20, + MGMT_FLASHROM_SAVE_FAILED = 23, + MGMT_IOCTLHANDLE_ALLOC_FAILED = 27, + MGMT_INVALID_SESSION = 31, + MGMT_INVALID_CONNECTION = 32, + MGMT_BTL_PATH_EXCEEDS_OSM_LIMIT = 33, + MGMT_BTL_TGTID_EXCEEDS_OSM_LIMIT = 34, + MGMT_BTL_PATH_TGTID_OCCUPIED = 35, + MGMT_BTL_NO_FREE_SLOT_PATH = 36, + MGMT_BTL_NO_FREE_SLOT_TGTID = 37, + MGMT_POLL_IOCTL_TIMEOUT = 40, + MGMT_ERROR_ACITISCSI = 41, + MGMT_BUFFER_SIZE_EXCEED_OSM_OR_OS_LIMIT = 43, + MGMT_REBOOT_REQUIRED = 44, + MGMT_INSUFFICIENT_TIMEOUT = 45, + MGMT_IPADDR_NOT_SET = 46, + MGMT_IPADDR_DUP_DETECTED = 47, + MGMT_CANT_REMOVE_LAST_CONNECTION = 48, + MGMT_TARGET_BUSY = 49, + MGMT_TGT_ERR_LISTEN_SOCKET = 50, + MGMT_TGT_ERR_BIND_SOCKET = 51, + MGMT_TGT_ERR_NO_SOCKET = 52, + MGMT_TGT_ERR_ISNS_COMM_FAILED = 55, + MGMT_CANNOT_DELETE_BOOT_TARGET = 56, + MGMT_TGT_PORTAL_MODE_IN_LISTEN = 57, + MGMT_FCF_IN_USE = 58 , + MGMT_NO_CQE = 59, + MGMT_TARGET_NOT_FOUND = 65, + MGMT_NOT_SUPPORTED = 66, + MGMT_NO_FCF_RECORDS = 67, + MGMT_FEATURE_NOT_SUPPORTED = 68, + MGMT_VPD_FUNCTION_OUT_OF_RANGE = 69, + MGMT_VPD_FUNCTION_TYPE_INCORRECT = 70, + MGMT_INVALID_NON_EMBEDDED_WRB = 71, + MGMT_OOR = 100, + MGMT_INVALID_PD = 101, + MGMT_STATUS_PD_INUSE = 102, + MGMT_INVALID_CQ = 103, + MGMT_INVALID_QP = 104, + MGMT_INVALID_STAG = 105, + MGMT_ORD_EXCEEDS = 106, + MGMT_IRD_EXCEEDS = 107, + MGMT_SENDQ_WQE_EXCEEDS = 108, + MGMT_RECVQ_RQE_EXCEEDS = 109, + MGMT_SGE_SEND_EXCEEDS = 110, + MGMT_SGE_WRITE_EXCEEDS = 111, + MGMT_SGE_RECV_EXCEEDS = 112, + MGMT_INVALID_STATE_CHANGE = 113, + MGMT_MW_BOUND = 114, + MGMT_INVALID_VA = 115, + MGMT_INVALID_LENGTH = 116, + MGMT_INVALID_FBO = 117, + MGMT_INVALID_ACC_RIGHTS = 118, + MGMT_INVALID_PBE_SIZE = 119, + MGMT_INVALID_PBL_ENTRY = 120, + MGMT_INVALID_PBL_OFFSET = 121, + MGMT_ADDR_NON_EXIST = 122, + MGMT_INVALID_VLANID = 123, + MGMT_INVALID_MTU = 124, + MGMT_INVALID_BACKLOG = 125, + MGMT_CONNECTION_INPROGRESS = 126, + MGMT_INVALID_RQE_SIZE = 127, + MGMT_INVALID_RQE_ENTRY = 128 +}; + +/* Additional Management Status Codes */ +enum MGMT_ADDI_STATUS { + MGMT_ADDI_NO_STATUS = 0, + MGMT_ADDI_INVALID_IPTYPE = 1, + MGMT_ADDI_TARGET_HANDLE_NOT_FOUND = 9, + MGMT_ADDI_SESSION_HANDLE_NOT_FOUND = 10, + MGMT_ADDI_CONNECTION_HANDLE_NOT_FOUND = 11, + MGMT_ADDI_ACTIVE_SESSIONS_PRESENT = 16, + MGMT_ADDI_SESSION_ALREADY_OPENED = 17, + MGMT_ADDI_SESSION_ALREADY_CLOSED = 18, + MGMT_ADDI_DEST_HOST_UNREACHABLE = 19, + MGMT_ADDI_LOGIN_IN_PROGRESS = 20, + MGMT_ADDI_TCP_CONNECT_FAILED = 21, + MGMT_ADDI_INSUFFICIENT_RESOURCES = 22, + MGMT_ADDI_LINK_DOWN = 23, + MGMT_ADDI_DHCP_ERROR = 24, + MGMT_ADDI_CONNECTION_OFFLOADED = 25, + MGMT_ADDI_CONNECTION_NOT_OFFLOADED = 26, + MGMT_ADDI_CONNECTION_UPLOAD_IN_PROGRESS = 27, + MGMT_ADDI_REQUEST_REJECTED = 28, + MGMT_ADDI_INVALID_SUBSYSTEM = 29, + MGMT_ADDI_INVALID_OPCODE = 30, + MGMT_ADDI_INVALID_MAXCONNECTION_PARAM = 31, + MGMT_ADDI_INVALID_KEY = 32, + MGMT_ADDI_INVALID_DOMAIN = 35, + MGMT_ADDI_LOGIN_INITIATOR_ERROR = 43, + MGMT_ADDI_LOGIN_AUTHENTICATION_ERROR = 44, + MGMT_ADDI_LOGIN_AUTHORIZATION_ERROR = 45, + MGMT_ADDI_LOGIN_NOT_FOUND = 46, + MGMT_ADDI_LOGIN_TARGET_REMOVED = 47, + MGMT_ADDI_LOGIN_UNSUPPORTED_VERSION = 48, + MGMT_ADDI_LOGIN_TOO_MANY_CONNECTIONS = 49, + MGMT_ADDI_LOGIN_MISSING_PARAMETER = 50, + MGMT_ADDI_LOGIN_NO_SESSION_SPANNING = 51, + MGMT_ADDI_LOGIN_SESSION_TYPE_NOT_SUPPORTED = 52, + MGMT_ADDI_LOGIN_SESSION_DOES_NOT_EXIST = 53, + MGMT_ADDI_LOGIN_INVALID_DURING_LOGIN = 54, + MGMT_ADDI_LOGIN_TARGET_ERROR = 55, + MGMT_ADDI_LOGIN_SERVICE_UNAVAILABLE = 56, + MGMT_ADDI_LOGIN_OUT_OF_RESOURCES = 57, + MGMT_ADDI_SAME_CHAP_SECRET = 58, + MGMT_ADDI_INVALID_SECRET_LENGTH = 59, + MGMT_ADDI_DUPLICATE_ENTRY = 60, + MGMT_ADDI_SETTINGS_MODIFIED_REBOOT_REQD = 63, + MGMT_ADDI_INVALID_EXTENDED_TIMEOUT = 64, + MGMT_ADDI_INVALID_INTERFACE_HANDLE = 65, + MGMT_ADDI_ERR_VLAN_ON_DEF_INTERFACE = 66, + MGMT_ADDI_INTERFACE_DOES_NOT_EXIST = 67, + MGMT_ADDI_INTERFACE_ALREADY_EXISTS = 68, + MGMT_ADDI_INVALID_VLAN_RANGE = 69, + MGMT_ADDI_ERR_SET_VLAN = 70, + MGMT_ADDI_ERR_DEL_VLAN = 71, + MGMT_ADDI_CANNOT_DEL_DEF_INTERFACE = 72, + MGMT_ADDI_DHCP_REQ_ALREADY_PENDING = 73, + MGMT_ADDI_TOO_MANY_INTERFACES = 74, + MGMT_ADDI_INVALID_REQUEST = 75 +}; + +enum NIC_SUBSYSTEM_OPCODES { +/** + * @brief NIC Subsystem Opcodes (see Network SLI-4 manual >= Rev4, v21-2) + * These opcodes are used for configuring the Ethernet interfaces. + * These opcodes all use the MBX_SUBSYSTEM_NIC subsystem code. + */ + NIC_CONFIG_RSS = 1, + NIC_CONFIG_ACPI = 2, + NIC_CONFIG_PROMISCUOUS = 3, + NIC_GET_STATS = 4, + NIC_CREATE_WQ = 7, + NIC_CREATE_RQ = 8, + NIC_DELETE_WQ = 9, + NIC_DELETE_RQ = 10, + NIC_CONFIG_ACPI_WOL_MAGIC = 12, + NIC_GET_NETWORK_STATS = 13, + NIC_CREATE_HDS_RQ = 16, + NIC_DELETE_HDS_RQ = 17, + NIC_GET_PPORT_STATS = 18, + NIC_GET_VPORT_STATS = 19, + NIC_GET_QUEUE_STATS = 20 +}; + +/* Hash option flags for RSS enable */ +enum RSS_ENABLE_FLAGS { + RSS_ENABLE_NONE = 0x0, /* (No RSS) */ + RSS_ENABLE_IPV4 = 0x1, /* (IPV4 HASH enabled ) */ + RSS_ENABLE_TCP_IPV4 = 0x2, /* (TCP IPV4 Hash enabled) */ + RSS_ENABLE_IPV6 = 0x4, /* (IPV6 HASH enabled) */ + RSS_ENABLE_TCP_IPV6 = 0x8 /* (TCP IPV6 HASH */ +}; +#define RSS_ENABLE (RSS_ENABLE_IPV4 | RSS_ENABLE_TCP_IPV4) +#define RSS_DISABLE RSS_ENABLE_NONE + +/* NIC header WQE */ +struct oce_nic_hdr_wqe { + union { + struct { +#ifdef _BIG_ENDIAN + /* dw0 */ + uint32_t rsvd0; + + /* dw1 */ + uint32_t last_seg_udp_len:14; + uint32_t rsvd1:18; + + /* dw2 */ + uint32_t lso_mss:14; + uint32_t num_wqe:5; + uint32_t rsvd4:2; + uint32_t vlan:1; + uint32_t lso:1; + uint32_t tcpcs:1; + uint32_t udpcs:1; + uint32_t ipcs:1; + uint32_t rsvd3:1; + uint32_t rsvd2:1; + uint32_t forward:1; + uint32_t crc:1; + uint32_t event:1; + uint32_t complete:1; + + /* dw3 */ + uint32_t vlan_tag:16; + uint32_t total_length:16; +#else + /* dw0 */ + uint32_t rsvd0; + + /* dw1 */ + uint32_t rsvd1:18; + uint32_t last_seg_udp_len:14; + + /* dw2 */ + uint32_t complete:1; + uint32_t event:1; + uint32_t crc:1; + uint32_t forward:1; + uint32_t rsvd2:1; + uint32_t rsvd3:1; + uint32_t ipcs:1; + uint32_t udpcs:1; + uint32_t tcpcs:1; + uint32_t lso:1; + uint32_t vlan:1; + uint32_t rsvd4:2; + uint32_t num_wqe:5; + uint32_t lso_mss:14; + + /* dw3 */ + uint32_t total_length:16; + uint32_t vlan_tag:16; +#endif + } s; + uint32_t dw[4]; + } u0; +}; + +/* NIC fragment WQE */ +struct oce_nic_frag_wqe { + union { + struct { + /* dw0 */ + uint32_t frag_pa_hi; + /* dw1 */ + uint32_t frag_pa_lo; + /* dw2 */ + uint32_t rsvd0; + uint32_t frag_len; + } s; + uint32_t dw[4]; + } u0; +}; + +/* Ethernet Tx Completion Descriptor */ +struct oce_nic_tx_cqe { + union { + struct { +#ifdef _BIG_ENDIAN + /* dw 0 */ + uint32_t status:4; + uint32_t rsvd0:8; + uint32_t port:2; + uint32_t ct:2; + uint32_t wqe_index:16; + + /* dw 1 */ + uint32_t rsvd1:5; + uint32_t cast_enc:2; + uint32_t lso:1; + uint32_t nwh_bytes:8; + uint32_t user_bytes:16; + + /* dw 2 */ + uint32_t rsvd2; + + /* dw 3 */ + uint32_t valid:1; + uint32_t rsvd3:4; + uint32_t wq_id:11; + uint32_t num_pkts:16; +#else + /* dw 0 */ + uint32_t wqe_index:16; + uint32_t ct:2; + uint32_t port:2; + uint32_t rsvd0:8; + uint32_t status:4; + + /* dw 1 */ + uint32_t user_bytes:16; + uint32_t nwh_bytes:8; + uint32_t lso:1; + uint32_t cast_enc:2; + uint32_t rsvd1:5; + /* dw 2 */ + uint32_t rsvd2; + + /* dw 3 */ + uint32_t num_pkts:16; + uint32_t wq_id:11; + uint32_t rsvd3:4; + uint32_t valid:1; +#endif + } s; + uint32_t dw[4]; + } u0; +}; +#define WQ_CQE_VALID(_cqe) (_cqe->u0.dw[3]) +#define WQ_CQE_INVALIDATE(_cqe) (_cqe->u0.dw[3] = 0) + +/* Receive Queue Entry (RQE) */ +struct oce_nic_rqe { + union { + struct { + uint32_t frag_pa_hi; + uint32_t frag_pa_lo; + } s; + uint32_t dw[2]; + } u0; +}; + +/* NIC Receive CQE */ +struct oce_nic_rx_cqe { + union { + struct { +#ifdef _BIG_ENDIAN + /* dw 0 */ + uint32_t ip_options:1; + uint32_t port:1; + uint32_t pkt_size:14; + uint32_t vlan_tag:16; + + /* dw 1 */ + uint32_t num_fragments:3; + uint32_t switched:1; + uint32_t ct:2; + uint32_t frag_index:10; + uint32_t rsvd0:1; + uint32_t vlan_tag_present:1; + uint32_t mac_dst:6; + uint32_t ip_ver:1; + uint32_t l4_cksum_pass:1; + uint32_t ip_cksum_pass:1; + uint32_t udpframe:1; + uint32_t tcpframe:1; + uint32_t ipframe:1; + uint32_t rss_hp:1; + uint32_t error:1; + + /* dw 2 */ + uint32_t valid:1; + uint32_t hds_type:2; + uint32_t lro_pkt:1; + uint32_t rsvd4:1; + uint32_t hds_hdr_size:12; + uint32_t hds_hdr_frag_index:10; + uint32_t rss_bank:1; + uint32_t qnq:1; + uint32_t pkt_type:2; + uint32_t rss_flush:1; + + /* dw 3 */ + uint32_t rss_hash_value; +#else + /* dw 0 */ + uint32_t vlan_tag:16; + uint32_t pkt_size:14; + uint32_t port:1; + uint32_t ip_options:1; + /* dw 1 */ + uint32_t error:1; + uint32_t rss_hp:1; + uint32_t ipframe:1; + uint32_t tcpframe:1; + uint32_t udpframe:1; + uint32_t ip_cksum_pass:1; + uint32_t l4_cksum_pass:1; + uint32_t ip_ver:1; + uint32_t mac_dst:6; + uint32_t vlan_tag_present:1; + uint32_t rsvd0:1; + uint32_t frag_index:10; + uint32_t ct:2; + uint32_t switched:1; + uint32_t num_fragments:3; + + /* dw 2 */ + uint32_t rss_flush:1; + uint32_t pkt_type:2; + uint32_t qnq:1; + uint32_t rss_bank:1; + uint32_t hds_hdr_frag_index:10; + uint32_t hds_hdr_size:12; + uint32_t rsvd4:1; + uint32_t lro_pkt:1; + uint32_t hds_type:2; + uint32_t valid:1; + /* dw 3 */ + uint32_t rss_hash_value; +#endif + } s; + uint32_t dw[4]; + } u0; +}; +/* NIC Receive CQE_v1 */ +struct oce_nic_rx_cqe_v1 { + union { + struct { +#ifdef _BIG_ENDIAN + /* dw 0 */ + uint32_t ip_options:1; + uint32_t vlan_tag_present:1; + uint32_t pkt_size:14; + uint32_t vlan_tag:16; + + /* dw 1 */ + uint32_t num_fragments:3; + uint32_t switched:1; + uint32_t ct:2; + uint32_t frag_index:10; + uint32_t rsvd0:1; + uint32_t mac_dst:7; + uint32_t ip_ver:1; + uint32_t l4_cksum_pass:1; + uint32_t ip_cksum_pass:1; + uint32_t udpframe:1; + uint32_t tcpframe:1; + uint32_t ipframe:1; + uint32_t rss_hp:1; + uint32_t error:1; + + /* dw 2 */ + uint32_t valid:1; + uint32_t rsvd4:13; + uint32_t hds_hdr_size: + uint32_t hds_hdr_frag_index:8; + uint32_t vlantag:1; + uint32_t port:2; + uint32_t rss_bank:1; + uint32_t qnq:1; + uint32_t pkt_type:2; + uint32_t rss_flush:1; + + /* dw 3 */ + uint32_t rss_hash_value; + #else + /* dw 0 */ + uint32_t vlan_tag:16; + uint32_t pkt_size:14; + uint32_t vlan_tag_present:1; + uint32_t ip_options:1; + /* dw 1 */ + uint32_t error:1; + uint32_t rss_hp:1; + uint32_t ipframe:1; + uint32_t tcpframe:1; + uint32_t udpframe:1; + uint32_t ip_cksum_pass:1; + uint32_t l4_cksum_pass:1; + uint32_t ip_ver:1; + uint32_t mac_dst:7; + uint32_t rsvd0:1; + uint32_t frag_index:10; + uint32_t ct:2; + uint32_t switched:1; + uint32_t num_fragments:3; + + /* dw 2 */ + uint32_t rss_flush:1; + uint32_t pkt_type:2; + uint32_t qnq:1; + uint32_t rss_bank:1; + uint32_t port:2; + uint32_t vlantag:1; + uint32_t hds_hdr_frag_index:8; + uint32_t hds_hdr_size:2; + uint32_t rsvd4:13; + uint32_t valid:1; + /* dw 3 */ + uint32_t rss_hash_value; +#endif + } s; + uint32_t dw[4]; + } u0; +}; + +#define RQ_CQE_VALID_MASK 0x80 +#define RQ_CQE_VALID(_cqe) (_cqe->u0.dw[2]) +#define RQ_CQE_INVALIDATE(_cqe) (_cqe->u0.dw[2] = 0) + +struct mbx_config_nic_promiscuous { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + uint16_t rsvd0; + uint8_t port1_promisc; + uint8_t port0_promisc; +#else + uint8_t port0_promisc; + uint8_t port1_promisc; + uint16_t rsvd0; +#endif + } req; + + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + +typedef union oce_wq_ctx_u { + uint32_t dw[17]; + struct { +#ifdef _BIG_ENDIAN + /* dw4 */ + uint32_t dw4rsvd2:8; + uint32_t nic_wq_type:8; + uint32_t dw4rsvd1:8; + uint32_t num_pages:8; + /* dw5 */ + uint32_t dw5rsvd2:12; + uint32_t wq_size:4; + uint32_t dw5rsvd1:16; + /* dw6 */ + uint32_t valid:1; + uint32_t dw6rsvd1:31; + /* dw7 */ + uint32_t dw7rsvd1:16; + uint32_t cq_id:16; +#else + /* dw4 */ + uint32_t num_pages:8; +#if 0 + uint32_t dw4rsvd1:8; +#else +/* PSP: this workaround is not documented: fill 0x01 for ulp_mask */ + uint32_t ulp_mask:8; +#endif + uint32_t nic_wq_type:8; + uint32_t dw4rsvd2:8; + /* dw5 */ + uint32_t dw5rsvd1:16; + uint32_t wq_size:4; + uint32_t dw5rsvd2:12; + /* dw6 */ + uint32_t dw6rsvd1:31; + uint32_t valid:1; + /* dw7 */ + uint32_t cq_id:16; + uint32_t dw7rsvd1:16; +#endif + /* dw8 - dw20 */ + uint32_t dw8_20rsvd1[13]; + } v0; + struct { +#ifdef _BIG_ENDIAN + /* dw4 */ + uint32_t dw4rsvd2:8; + uint32_t nic_wq_type:8; + uint32_t dw4rsvd1:8; + uint32_t num_pages:8; + /* dw5 */ + uint32_t dw5rsvd2:12; + uint32_t wq_size:4; + uint32_t iface_id:16; + /* dw6 */ + uint32_t valid:1; + uint32_t dw6rsvd1:31; + /* dw7 */ + uint32_t dw7rsvd1:16; + uint32_t cq_id:16; +#else + /* dw4 */ + uint32_t num_pages:8; + uint32_t dw4rsvd1:8; + uint32_t nic_wq_type:8; + uint32_t dw4rsvd2:8; + /* dw5 */ + uint32_t iface_id:16; + uint32_t wq_size:4; + uint32_t dw5rsvd2:12; + /* dw6 */ + uint32_t dw6rsvd1:31; + uint32_t valid:1; + /* dw7 */ + uint32_t cq_id:16; + uint32_t dw7rsvd1:16; +#endif + /* dw8 - dw20 */ + uint32_t dw8_20rsvd1[13]; + } v1; +} oce_wq_ctx_t; + +/** + * @brief [07] NIC_CREATE_WQ + * @note + * Lancer requires an InterfaceID to be specified with every WQ. This + * is the basis for NIC IOV where the Interface maps to a vPort and maps + * to both Tx and Rx sides. + */ +#define OCE_WQ_TYPE_FORWARDING 0x1 /* wq forwards pkts to TOE */ +#define OCE_WQ_TYPE_STANDARD 0x2 /* wq sends network pkts */ +struct mbx_create_nic_wq { + struct mbx_hdr hdr; + union { + struct { + uint8_t num_pages; + uint8_t ulp_num; + uint16_t nic_wq_type; + uint16_t if_id; + uint8_t wq_size; + uint8_t rsvd1; + uint32_t rsvd2; + uint16_t cq_id; + uint16_t rsvd3; + uint32_t rsvd4[13]; + struct phys_addr pages[8]; + + } req; + + struct { + uint16_t wq_id; + uint16_t rid; + uint32_t db_offset; + uint8_t tc_id; + uint8_t rsvd0[3]; + } rsp; + } params; +}; + +/* [09] NIC_DELETE_WQ */ +struct mbx_delete_nic_wq { + /* dw0 - dw3 */ + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + /* dw4 */ + uint16_t rsvd0; + uint16_t wq_id; +#else + /* dw4 */ + uint16_t wq_id; + uint16_t rsvd0; +#endif + } req; + struct { + uint32_t rsvd0; + } rsp; + } params; +}; + + + +struct mbx_create_nic_rq { + struct mbx_hdr hdr; + union { + struct { + uint16_t cq_id; + uint8_t frag_size; + uint8_t num_pages; + struct phys_addr pages[2]; + uint32_t if_id; + uint16_t max_frame_size; + uint16_t page_size; + uint32_t is_rss_queue; + } req; + + struct { + uint16_t rq_id; + uint8_t rss_cpuid; + uint8_t rsvd0; + } rsp; + + } params; +}; + + + +/* [10] NIC_DELETE_RQ */ +struct mbx_delete_nic_rq { + /* dw0 - dw3 */ + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + /* dw4 */ + uint16_t bypass_flush; + uint16_t rq_id; +#else + /* dw4 */ + uint16_t rq_id; + uint16_t bypass_flush; +#endif + } req; + + struct { + /* dw4 */ + uint32_t rsvd0; + } rsp; + } params; +}; + + + + +struct oce_port_rxf_stats_v0 { + uint32_t rx_bytes_lsd; /* dword 0*/ + uint32_t rx_bytes_msd; /* dword 1*/ + uint32_t rx_total_frames; /* dword 2*/ + uint32_t rx_unicast_frames; /* dword 3*/ + uint32_t rx_multicast_frames; /* dword 4*/ + uint32_t rx_broadcast_frames; /* dword 5*/ + uint32_t rx_crc_errors; /* dword 6*/ + uint32_t rx_alignment_symbol_errors; /* dword 7*/ + uint32_t rx_pause_frames; /* dword 8*/ + uint32_t rx_control_frames; /* dword 9*/ + uint32_t rx_in_range_errors; /* dword 10*/ + uint32_t rx_out_range_errors; /* dword 11*/ + uint32_t rx_frame_too_long; /* dword 12*/ + uint32_t rx_address_match_errors; /* dword 13*/ + uint32_t rx_vlan_mismatch; /* dword 14*/ + uint32_t rx_dropped_too_small; /* dword 15*/ + uint32_t rx_dropped_too_short; /* dword 16*/ + uint32_t rx_dropped_header_too_small; /* dword 17*/ + uint32_t rx_dropped_tcp_length; /* dword 18*/ + uint32_t rx_dropped_runt; /* dword 19*/ + uint32_t rx_64_byte_packets; /* dword 20*/ + uint32_t rx_65_127_byte_packets; /* dword 21*/ + uint32_t rx_128_256_byte_packets; /* dword 22*/ + uint32_t rx_256_511_byte_packets; /* dword 23*/ + uint32_t rx_512_1023_byte_packets; /* dword 24*/ + uint32_t rx_1024_1518_byte_packets; /* dword 25*/ + uint32_t rx_1519_2047_byte_packets; /* dword 26*/ + uint32_t rx_2048_4095_byte_packets; /* dword 27*/ + uint32_t rx_4096_8191_byte_packets; /* dword 28*/ + uint32_t rx_8192_9216_byte_packets; /* dword 29*/ + uint32_t rx_ip_checksum_errs; /* dword 30*/ + uint32_t rx_tcp_checksum_errs; /* dword 31*/ + uint32_t rx_udp_checksum_errs; /* dword 32*/ + uint32_t rx_non_rss_packets; /* dword 33*/ + uint32_t rx_ipv4_packets; /* dword 34*/ + uint32_t rx_ipv6_packets; /* dword 35*/ + uint32_t rx_ipv4_bytes_lsd; /* dword 36*/ + uint32_t rx_ipv4_bytes_msd; /* dword 37*/ + uint32_t rx_ipv6_bytes_lsd; /* dword 38*/ + uint32_t rx_ipv6_bytes_msd; /* dword 39*/ + uint32_t rx_chute1_packets; /* dword 40*/ + uint32_t rx_chute2_packets; /* dword 41*/ + uint32_t rx_chute3_packets; /* dword 42*/ + uint32_t rx_management_packets; /* dword 43*/ + uint32_t rx_switched_unicast_packets; /* dword 44*/ + uint32_t rx_switched_multicast_packets; /* dword 45*/ + uint32_t rx_switched_broadcast_packets; /* dword 46*/ + uint32_t tx_bytes_lsd; /* dword 47*/ + uint32_t tx_bytes_msd; /* dword 48*/ + uint32_t tx_unicastframes; /* dword 49*/ + uint32_t tx_multicastframes; /* dword 50*/ + uint32_t tx_broadcastframes; /* dword 51*/ + uint32_t tx_pauseframes; /* dword 52*/ + uint32_t tx_controlframes; /* dword 53*/ + uint32_t tx_64_byte_packets; /* dword 54*/ + uint32_t tx_65_127_byte_packets; /* dword 55*/ + uint32_t tx_128_256_byte_packets; /* dword 56*/ + uint32_t tx_256_511_byte_packets; /* dword 57*/ + uint32_t tx_512_1023_byte_packets; /* dword 58*/ + uint32_t tx_1024_1518_byte_packets; /* dword 59*/ + uint32_t tx_1519_2047_byte_packets; /* dword 60*/ + uint32_t tx_2048_4095_byte_packets; /* dword 61*/ + uint32_t tx_4096_8191_byte_packets; /* dword 62*/ + uint32_t tx_8192_9216_byte_packets; /* dword 63*/ + uint32_t rxpp_fifo_overflow_drop; /* dword 64*/ + uint32_t rx_input_fifo_overflow_drop; /* dword 65*/ +}; + + +struct oce_rxf_stats_v0 { + struct oce_port_rxf_stats_v0 port[2]; + uint32_t rx_drops_no_pbuf; /* dword 132*/ + uint32_t rx_drops_no_txpb; /* dword 133*/ + uint32_t rx_drops_no_erx_descr; /* dword 134*/ + uint32_t rx_drops_no_tpre_descr; /* dword 135*/ + uint32_t management_rx_port_packets; /* dword 136*/ + uint32_t management_rx_port_bytes; /* dword 137*/ + uint32_t management_rx_port_pause_frames;/* dword 138*/ + uint32_t management_rx_port_errors; /* dword 139*/ + uint32_t management_tx_port_packets; /* dword 140*/ + uint32_t management_tx_port_bytes; /* dword 141*/ + uint32_t management_tx_port_pause; /* dword 142*/ + uint32_t management_rx_port_rxfifo_overflow; /* dword 143*/ + uint32_t rx_drops_too_many_frags; /* dword 144*/ + uint32_t rx_drops_invalid_ring; /* dword 145*/ + uint32_t forwarded_packets; /* dword 146*/ + uint32_t rx_drops_mtu; /* dword 147*/ + uint32_t rsvd0[7]; + uint32_t port0_jabber_events; + uint32_t port1_jabber_events; + uint32_t rsvd1[6]; +}; + +struct oce_port_rxf_stats_v1 { + uint32_t rsvd0[12]; + uint32_t rx_crc_errors; + uint32_t rx_alignment_symbol_errors; + uint32_t rx_pause_frames; + uint32_t rx_priority_pause_frames; + uint32_t rx_control_frames; + uint32_t rx_in_range_errors; + uint32_t rx_out_range_errors; + uint32_t rx_frame_too_long; + uint32_t rx_address_match_errors; + uint32_t rx_dropped_too_small; + uint32_t rx_dropped_too_short; + uint32_t rx_dropped_header_too_small; + uint32_t rx_dropped_tcp_length; + uint32_t rx_dropped_runt; + uint32_t rsvd1[10]; + uint32_t rx_ip_checksum_errs; + uint32_t rx_tcp_checksum_errs; + uint32_t rx_udp_checksum_errs; + uint32_t rsvd2[7]; + uint32_t rx_switched_unicast_packets; + uint32_t rx_switched_multicast_packets; + uint32_t rx_switched_broadcast_packets; + uint32_t rsvd3[3]; + uint32_t tx_pauseframes; + uint32_t tx_priority_pauseframes; + uint32_t tx_controlframes; + uint32_t rsvd4[10]; + uint32_t rxpp_fifo_overflow_drop; + uint32_t rx_input_fifo_overflow_drop; + uint32_t pmem_fifo_overflow_drop; + uint32_t jabber_events; + uint32_t rsvd5[3]; +}; + + +struct oce_rxf_stats_v1 { + struct oce_port_rxf_stats_v1 port[4]; + uint32_t rsvd0[2]; + uint32_t rx_drops_no_pbuf; + uint32_t rx_drops_no_txpb; + uint32_t rx_drops_no_erx_descr; + uint32_t rx_drops_no_tpre_descr; + uint32_t rsvd1[6]; + uint32_t rx_drops_too_many_frags; + uint32_t rx_drops_invalid_ring; + uint32_t forwarded_packets; + uint32_t rx_drops_mtu; + uint32_t rsvd2[14]; +}; + +struct oce_erx_stats_v1 { + uint32_t rx_drops_no_fragments[68]; + uint32_t rsvd[4]; +}; + + +struct oce_erx_stats_v0 { + uint32_t rx_drops_no_fragments[44]; + uint32_t rsvd[4]; +}; + +struct oce_pmem_stats { + uint32_t eth_red_drops; + uint32_t rsvd[5]; +}; + +struct oce_hw_stats_v1 { + struct oce_rxf_stats_v1 rxf; + uint32_t rsvd0[OCE_TXP_SW_SZ]; + struct oce_erx_stats_v1 erx; + struct oce_pmem_stats pmem; + uint32_t rsvd1[18]; +}; + +struct oce_hw_stats_v0 { + struct oce_rxf_stats_v0 rxf; + uint32_t rsvd[48]; + struct oce_erx_stats_v0 erx; + struct oce_pmem_stats pmem; +}; + +struct mbx_get_nic_stats_v0 { + struct mbx_hdr hdr; + union { + struct { + uint32_t rsvd0; + } req; + + union { + struct oce_hw_stats_v0 stats; + } rsp; + } params; +}; + +struct mbx_get_nic_stats { + struct mbx_hdr hdr; + union { + struct { + uint32_t rsvd0; + } req; + + struct { + struct oce_hw_stats_v1 stats; + } rsp; + } params; +}; + + +/* [18(0x12)] NIC_GET_PPORT_STATS */ +struct pport_stats { + uint64_t tx_pkts; + uint64_t tx_unicast_pkts; + uint64_t tx_multicast_pkts; + uint64_t tx_broadcast_pkts; + uint64_t tx_bytes; + uint64_t tx_unicast_bytes; + uint64_t tx_multicast_bytes; + uint64_t tx_broadcast_bytes; + uint64_t tx_discards; + uint64_t tx_errors; + uint64_t tx_pause_frames; + uint64_t tx_pause_on_frames; + uint64_t tx_pause_off_frames; + uint64_t tx_internal_mac_errors; + uint64_t tx_control_frames; + uint64_t tx_pkts_64_bytes; + uint64_t tx_pkts_65_to_127_bytes; + uint64_t tx_pkts_128_to_255_bytes; + uint64_t tx_pkts_256_to_511_bytes; + uint64_t tx_pkts_512_to_1023_bytes; + uint64_t tx_pkts_1024_to_1518_bytes; + uint64_t tx_pkts_1519_to_2047_bytes; + uint64_t tx_pkts_2048_to_4095_bytes; + uint64_t tx_pkts_4096_to_8191_bytes; + uint64_t tx_pkts_8192_to_9216_bytes; + uint64_t tx_lso_pkts; + uint64_t rx_pkts; + uint64_t rx_unicast_pkts; + uint64_t rx_multicast_pkts; + uint64_t rx_broadcast_pkts; + uint64_t rx_bytes; + uint64_t rx_unicast_bytes; + uint64_t rx_multicast_bytes; + uint64_t rx_broadcast_bytes; + uint32_t rx_unknown_protos; + uint32_t reserved_word69; + uint64_t rx_discards; + uint64_t rx_errors; + uint64_t rx_crc_errors; + uint64_t rx_alignment_errors; + uint64_t rx_symbol_errors; + uint64_t rx_pause_frames; + uint64_t rx_pause_on_frames; + uint64_t rx_pause_off_frames; + uint64_t rx_frames_too_long; + uint64_t rx_internal_mac_errors; + uint32_t rx_undersize_pkts; + uint32_t rx_oversize_pkts; + uint32_t rx_fragment_pkts; + uint32_t rx_jabbers; + uint64_t rx_control_frames; + uint64_t rx_control_frames_unknown_opcode; + uint32_t rx_in_range_errors; + uint32_t rx_out_of_range_errors; + uint32_t rx_address_match_errors; + uint32_t rx_vlan_mismatch_errors; + uint32_t rx_dropped_too_small; + uint32_t rx_dropped_too_short; + uint32_t rx_dropped_header_too_small; + uint32_t rx_dropped_invalid_tcp_length; + uint32_t rx_dropped_runt; + uint32_t rx_ip_checksum_errors; + uint32_t rx_tcp_checksum_errors; + uint32_t rx_udp_checksum_errors; + uint32_t rx_non_rss_pkts; + uint64_t reserved_word111; + uint64_t rx_ipv4_pkts; + uint64_t rx_ipv6_pkts; + uint64_t rx_ipv4_bytes; + uint64_t rx_ipv6_bytes; + uint64_t rx_nic_pkts; + uint64_t rx_tcp_pkts; + uint64_t rx_iscsi_pkts; + uint64_t rx_management_pkts; + uint64_t rx_switched_unicast_pkts; + uint64_t rx_switched_multicast_pkts; + uint64_t rx_switched_broadcast_pkts; + uint64_t num_forwards; + uint32_t rx_fifo_overflow; + uint32_t rx_input_fifo_overflow; + uint64_t rx_drops_too_many_frags; + uint32_t rx_drops_invalid_queue; + uint32_t reserved_word141; + uint64_t rx_drops_mtu; + uint64_t rx_pkts_64_bytes; + uint64_t rx_pkts_65_to_127_bytes; + uint64_t rx_pkts_128_to_255_bytes; + uint64_t rx_pkts_256_to_511_bytes; + uint64_t rx_pkts_512_to_1023_bytes; + uint64_t rx_pkts_1024_to_1518_bytes; + uint64_t rx_pkts_1519_to_2047_bytes; + uint64_t rx_pkts_2048_to_4095_bytes; + uint64_t rx_pkts_4096_to_8191_bytes; + uint64_t rx_pkts_8192_to_9216_bytes; +}; + +struct mbx_get_pport_stats { + /* dw0 - dw3 */ + struct mbx_hdr hdr; + union { + struct { + /* dw4 */ +#ifdef _BIG_ENDIAN + uint32_t reset_stats:8; + uint32_t rsvd0:8; + uint32_t port_number:16; +#else + uint32_t port_number:16; + uint32_t rsvd0:8; + uint32_t reset_stats:8; +#endif + } req; + + union { + struct pport_stats pps; + uint32_t pport_stats[164 - 4 + 1]; + } rsp; + } params; +}; + +/* [19(0x13)] NIC_GET_VPORT_STATS */ +struct vport_stats { + uint64_t tx_pkts; + uint64_t tx_unicast_pkts; + uint64_t tx_multicast_pkts; + uint64_t tx_broadcast_pkts; + uint64_t tx_bytes; + uint64_t tx_unicast_bytes; + uint64_t tx_multicast_bytes; + uint64_t tx_broadcast_bytes; + uint64_t tx_discards; + uint64_t tx_errors; + uint64_t tx_pkts_64_bytes; + uint64_t tx_pkts_65_to_127_bytes; + uint64_t tx_pkts_128_to_255_bytes; + uint64_t tx_pkts_256_to_511_bytes; + uint64_t tx_pkts_512_to_1023_bytes; + uint64_t tx_pkts_1024_to_1518_bytes; + uint64_t tx_pkts_1519_to_9699_bytes; + uint64_t tx_pkts_over_9699_bytes; + uint64_t rx_pkts; + uint64_t rx_unicast_pkts; + uint64_t rx_multicast_pkts; + uint64_t rx_broadcast_pkts; + uint64_t rx_bytes; + uint64_t rx_unicast_bytes; + uint64_t rx_multicast_bytes; + uint64_t rx_broadcast_bytes; + uint64_t rx_discards; + uint64_t rx_errors; + uint64_t rx_pkts_64_bytes; + uint64_t rx_pkts_65_to_127_bytes; + uint64_t rx_pkts_128_to_255_bytes; + uint64_t rx_pkts_256_to_511_bytes; + uint64_t rx_pkts_512_to_1023_bytes; + uint64_t rx_pkts_1024_to_1518_bytes; + uint64_t rx_pkts_1519_to_9699_bytes; + uint64_t rx_pkts_gt_9699_bytes; +}; +struct mbx_get_vport_stats { + /* dw0 - dw3 */ + struct mbx_hdr hdr; + union { + struct { + /* dw4 */ +#ifdef _BIG_ENDIAN + uint32_t reset_stats:8; + uint32_t rsvd0:8; + uint32_t vport_number:16; +#else + uint32_t vport_number:16; + uint32_t rsvd0:8; + uint32_t reset_stats:8; +#endif + } req; + + union { + struct vport_stats vps; + uint32_t vport_stats[75 - 4 + 1]; + } rsp; + } params; +}; + +/** + * @brief [20(0x14)] NIC_GET_QUEUE_STATS + * The significant difference between vPort and Queue statistics is + * the packet byte counters. + */ +struct queue_stats { + uint64_t packets; + uint64_t bytes; + uint64_t errors; + uint64_t drops; + uint64_t buffer_errors; /* rsvd when tx */ +}; + +#define QUEUE_TYPE_WQ 0 +#define QUEUE_TYPE_RQ 1 +#define QUEUE_TYPE_HDS_RQ 1 /* same as RQ */ + +struct mbx_get_queue_stats { + /* dw0 - dw3 */ + struct mbx_hdr hdr; + union { + struct { + /* dw4 */ +#ifdef _BIG_ENDIAN + uint32_t reset_stats:8; + uint32_t queue_type:8; + uint32_t queue_id:16; +#else + uint32_t queue_id:16; + uint32_t queue_type:8; + uint32_t reset_stats:8; +#endif + } req; + + union { + struct queue_stats qs; + uint32_t queue_stats[13 - 4 + 1]; + } rsp; + } params; +}; + + +/* [01] NIC_CONFIG_RSS */ +#define OCE_HASH_TBL_SZ 10 +#define OCE_CPU_TBL_SZ 128 +#define OCE_FLUSH 1 /* RSS flush completion per CQ port */ +struct mbx_config_nic_rss { + struct mbx_hdr hdr; + union { + struct { +#ifdef _BIG_ENDIAN + uint32_t if_id; + uint16_t cpu_tbl_sz_log2; + uint16_t enable_rss; + uint32_t hash[OCE_HASH_TBL_SZ]; + uint8_t cputable[OCE_CPU_TBL_SZ]; + uint8_t rsvd[3]; + uint8_t flush; +#else + uint32_t if_id; + uint16_t enable_rss; + uint16_t cpu_tbl_sz_log2; + uint32_t hash[OCE_HASH_TBL_SZ]; + uint8_t cputable[OCE_CPU_TBL_SZ]; + uint8_t flush; + uint8_t rsvd[3]; +#endif + } req; + struct { + uint8_t rsvd[3]; + uint8_t rss_bank; + } rsp; + } params; +}; + + +#pragma pack() + + +typedef uint32_t oce_stat_t; /* statistic counter */ + +enum OCE_RXF_PORT_STATS { + RXF_RX_BYTES_LSD, + RXF_RX_BYTES_MSD, + RXF_RX_TOTAL_FRAMES, + RXF_RX_UNICAST_FRAMES, + RXF_RX_MULTICAST_FRAMES, + RXF_RX_BROADCAST_FRAMES, + RXF_RX_CRC_ERRORS, + RXF_RX_ALIGNMENT_SYMBOL_ERRORS, + RXF_RX_PAUSE_FRAMES, + RXF_RX_CONTROL_FRAMES, + RXF_RX_IN_RANGE_ERRORS, + RXF_RX_OUT_RANGE_ERRORS, + RXF_RX_FRAME_TOO_LONG, + RXF_RX_ADDRESS_MATCH_ERRORS, + RXF_RX_VLAN_MISMATCH, + RXF_RX_DROPPED_TOO_SMALL, + RXF_RX_DROPPED_TOO_SHORT, + RXF_RX_DROPPED_HEADER_TOO_SMALL, + RXF_RX_DROPPED_TCP_LENGTH, + RXF_RX_DROPPED_RUNT, + RXF_RX_64_BYTE_PACKETS, + RXF_RX_65_127_BYTE_PACKETS, + RXF_RX_128_256_BYTE_PACKETS, + RXF_RX_256_511_BYTE_PACKETS, + RXF_RX_512_1023_BYTE_PACKETS, + RXF_RX_1024_1518_BYTE_PACKETS, + RXF_RX_1519_2047_BYTE_PACKETS, + RXF_RX_2048_4095_BYTE_PACKETS, + RXF_RX_4096_8191_BYTE_PACKETS, + RXF_RX_8192_9216_BYTE_PACKETS, + RXF_RX_IP_CHECKSUM_ERRS, + RXF_RX_TCP_CHECKSUM_ERRS, + RXF_RX_UDP_CHECKSUM_ERRS, + RXF_RX_NON_RSS_PACKETS, + RXF_RX_IPV4_PACKETS, + RXF_RX_IPV6_PACKETS, + RXF_RX_IPV4_BYTES_LSD, + RXF_RX_IPV4_BYTES_MSD, + RXF_RX_IPV6_BYTES_LSD, + RXF_RX_IPV6_BYTES_MSD, + RXF_RX_CHUTE1_PACKETS, + RXF_RX_CHUTE2_PACKETS, + RXF_RX_CHUTE3_PACKETS, + RXF_RX_MANAGEMENT_PACKETS, + RXF_RX_SWITCHED_UNICAST_PACKETS, + RXF_RX_SWITCHED_MULTICAST_PACKETS, + RXF_RX_SWITCHED_BROADCAST_PACKETS, + RXF_TX_BYTES_LSD, + RXF_TX_BYTES_MSD, + RXF_TX_UNICAST_FRAMES, + RXF_TX_MULTICAST_FRAMES, + RXF_TX_BROADCAST_FRAMES, + RXF_TX_PAUSE_FRAMES, + RXF_TX_CONTROL_FRAMES, + RXF_TX_64_BYTE_PACKETS, + RXF_TX_65_127_BYTE_PACKETS, + RXF_TX_128_256_BYTE_PACKETS, + RXF_TX_256_511_BYTE_PACKETS, + RXF_TX_512_1023_BYTE_PACKETS, + RXF_TX_1024_1518_BYTE_PACKETS, + RXF_TX_1519_2047_BYTE_PACKETS, + RXF_TX_2048_4095_BYTE_PACKETS, + RXF_TX_4096_8191_BYTE_PACKETS, + RXF_TX_8192_9216_BYTE_PACKETS, + RXF_RX_FIFO_OVERFLOW, + RXF_RX_INPUT_FIFO_OVERFLOW, + RXF_PORT_STATS_N_WORDS +}; + +enum OCE_RXF_ADDL_STATS { + RXF_RX_DROPS_NO_PBUF, + RXF_RX_DROPS_NO_TXPB, + RXF_RX_DROPS_NO_ERX_DESCR, + RXF_RX_DROPS_NO_TPRE_DESCR, + RXF_MANAGEMENT_RX_PORT_PACKETS, + RXF_MANAGEMENT_RX_PORT_BYTES, + RXF_MANAGEMENT_RX_PORT_PAUSE_FRAMES, + RXF_MANAGEMENT_RX_PORT_ERRORS, + RXF_MANAGEMENT_TX_PORT_PACKETS, + RXF_MANAGEMENT_TX_PORT_BYTES, + RXF_MANAGEMENT_TX_PORT_PAUSE, + RXF_MANAGEMENT_RX_PORT_RXFIFO_OVERFLOW, + RXF_RX_DROPS_TOO_MANY_FRAGS, + RXF_RX_DROPS_INVALID_RING, + RXF_FORWARDED_PACKETS, + RXF_RX_DROPS_MTU, + RXF_ADDL_STATS_N_WORDS +}; + +enum OCE_TX_CHUTE_PORT_STATS { + CTPT_XMT_IPV4_PKTS, + CTPT_XMT_IPV4_LSD, + CTPT_XMT_IPV4_MSD, + CTPT_XMT_IPV6_PKTS, + CTPT_XMT_IPV6_LSD, + CTPT_XMT_IPV6_MSD, + CTPT_REXMT_IPV4_PKTs, + CTPT_REXMT_IPV4_LSD, + CTPT_REXMT_IPV4_MSD, + CTPT_REXMT_IPV6_PKTs, + CTPT_REXMT_IPV6_LSD, + CTPT_REXMT_IPV6_MSD, + CTPT_N_WORDS, +}; + +enum OCE_RX_ERR_STATS { + RX_DROPS_NO_FRAGMENTS_0, + RX_DROPS_NO_FRAGMENTS_1, + RX_DROPS_NO_FRAGMENTS_2, + RX_DROPS_NO_FRAGMENTS_3, + RX_DROPS_NO_FRAGMENTS_4, + RX_DROPS_NO_FRAGMENTS_5, + RX_DROPS_NO_FRAGMENTS_6, + RX_DROPS_NO_FRAGMENTS_7, + RX_DROPS_NO_FRAGMENTS_8, + RX_DROPS_NO_FRAGMENTS_9, + RX_DROPS_NO_FRAGMENTS_10, + RX_DROPS_NO_FRAGMENTS_11, + RX_DROPS_NO_FRAGMENTS_12, + RX_DROPS_NO_FRAGMENTS_13, + RX_DROPS_NO_FRAGMENTS_14, + RX_DROPS_NO_FRAGMENTS_15, + RX_DROPS_NO_FRAGMENTS_16, + RX_DROPS_NO_FRAGMENTS_17, + RX_DROPS_NO_FRAGMENTS_18, + RX_DROPS_NO_FRAGMENTS_19, + RX_DROPS_NO_FRAGMENTS_20, + RX_DROPS_NO_FRAGMENTS_21, + RX_DROPS_NO_FRAGMENTS_22, + RX_DROPS_NO_FRAGMENTS_23, + RX_DROPS_NO_FRAGMENTS_24, + RX_DROPS_NO_FRAGMENTS_25, + RX_DROPS_NO_FRAGMENTS_26, + RX_DROPS_NO_FRAGMENTS_27, + RX_DROPS_NO_FRAGMENTS_28, + RX_DROPS_NO_FRAGMENTS_29, + RX_DROPS_NO_FRAGMENTS_30, + RX_DROPS_NO_FRAGMENTS_31, + RX_DROPS_NO_FRAGMENTS_32, + RX_DROPS_NO_FRAGMENTS_33, + RX_DROPS_NO_FRAGMENTS_34, + RX_DROPS_NO_FRAGMENTS_35, + RX_DROPS_NO_FRAGMENTS_36, + RX_DROPS_NO_FRAGMENTS_37, + RX_DROPS_NO_FRAGMENTS_38, + RX_DROPS_NO_FRAGMENTS_39, + RX_DROPS_NO_FRAGMENTS_40, + RX_DROPS_NO_FRAGMENTS_41, + RX_DROPS_NO_FRAGMENTS_42, + RX_DROPS_NO_FRAGMENTS_43, + RX_DEBUG_WDMA_SENT_HOLD, + RX_DEBUG_WDMA_PBFREE_SENT_HOLD, + RX_DEBUG_WDMA_0B_PBFREE_SENT_HOLD, + RX_DEBUG_PMEM_PBUF_DEALLOC, + RX_ERRORS_N_WORDS +}; + +enum OCE_PMEM_ERR_STATS { + PMEM_ETH_RED_DROPS, + PMEM_LRO_RED_DROPS, + PMEM_ULP0_RED_DROPS, + PMEM_ULP1_RED_DROPS, + PMEM_GLOBAL_RED_DROPS, + PMEM_ERRORS_N_WORDS +}; + +/** + * @brief Statistics for a given Physical Port + * These satisfy all the required BE2 statistics and also the + * following MIB objects: + * + * RFC 2863 - The Interfaces Group MIB + * RFC 2819 - Remote Network Monitoring Management Information Base (RMON) + * RFC 3635 - Managed Objects for the Ethernet-like Interface Types + * RFC 4502 - Remote Network Monitoring Mgmt Information Base Ver-2 (RMON2) + * + */ +enum OCE_PPORT_STATS { + PPORT_TX_PKTS = 0, + PPORT_TX_UNICAST_PKTS = 2, + PPORT_TX_MULTICAST_PKTS = 4, + PPORT_TX_BROADCAST_PKTS = 6, + PPORT_TX_BYTES = 8, + PPORT_TX_UNICAST_BYTES = 10, + PPORT_TX_MULTICAST_BYTES = 12, + PPORT_TX_BROADCAST_BYTES = 14, + PPORT_TX_DISCARDS = 16, + PPORT_TX_ERRORS = 18, + PPORT_TX_PAUSE_FRAMES = 20, + PPORT_TX_PAUSE_ON_FRAMES = 22, + PPORT_TX_PAUSE_OFF_FRAMES = 24, + PPORT_TX_INTERNAL_MAC_ERRORS = 26, + PPORT_TX_CONTROL_FRAMES = 28, + PPORT_TX_PKTS_64_BYTES = 30, + PPORT_TX_PKTS_65_TO_127_BYTES = 32, + PPORT_TX_PKTS_128_TO_255_BYTES = 34, + PPORT_TX_PKTS_256_TO_511_BYTES = 36, + PPORT_TX_PKTS_512_TO_1023_BYTES = 38, + PPORT_TX_PKTS_1024_TO_1518_BYTES = 40, + PPORT_TX_PKTS_1519_TO_2047_BYTES = 42, + PPORT_TX_PKTS_2048_TO_4095_BYTES = 44, + PPORT_TX_PKTS_4096_TO_8191_BYTES = 46, + PPORT_TX_PKTS_8192_TO_9216_BYTES = 48, + PPORT_TX_LSO_PKTS = 50, + PPORT_RX_PKTS = 52, + PPORT_RX_UNICAST_PKTS = 54, + PPORT_RX_MULTICAST_PKTS = 56, + PPORT_RX_BROADCAST_PKTS = 58, + PPORT_RX_BYTES = 60, + PPORT_RX_UNICAST_BYTES = 62, + PPORT_RX_MULTICAST_BYTES = 64, + PPORT_RX_BROADCAST_BYTES = 66, + PPORT_RX_UNKNOWN_PROTOS = 68, + PPORT_RESERVED_WORD69 = 69, + PPORT_RX_DISCARDS = 70, + PPORT_RX_ERRORS = 72, + PPORT_RX_CRC_ERRORS = 74, + PPORT_RX_ALIGNMENT_ERRORS = 76, + PPORT_RX_SYMBOL_ERRORS = 78, + PPORT_RX_PAUSE_FRAMES = 80, + PPORT_RX_PAUSE_ON_FRAMES = 82, + PPORT_RX_PAUSE_OFF_FRAMES = 84, + PPORT_RX_FRAMES_TOO_LONG = 86, + PPORT_RX_INTERNAL_MAC_ERRORS = 88, + PPORT_RX_UNDERSIZE_PKTS = 90, + PPORT_RX_OVERSIZE_PKTS = 91, + PPORT_RX_FRAGMENT_PKTS = 92, + PPORT_RX_JABBERS = 93, + PPORT_RX_CONTROL_FRAMES = 94, + PPORT_RX_CONTROL_FRAMES_UNK_OPCODE = 96, + PPORT_RX_IN_RANGE_ERRORS = 98, + PPORT_RX_OUT_OF_RANGE_ERRORS = 99, + PPORT_RX_ADDRESS_MATCH_ERRORS = 100, + PPORT_RX_VLAN_MISMATCH_ERRORS = 101, + PPORT_RX_DROPPED_TOO_SMALL = 102, + PPORT_RX_DROPPED_TOO_SHORT = 103, + PPORT_RX_DROPPED_HEADER_TOO_SMALL = 104, + PPORT_RX_DROPPED_INVALID_TCP_LENGTH = 105, + PPORT_RX_DROPPED_RUNT = 106, + PPORT_RX_IP_CHECKSUM_ERRORS = 107, + PPORT_RX_TCP_CHECKSUM_ERRORS = 108, + PPORT_RX_UDP_CHECKSUM_ERRORS = 109, + PPORT_RX_NON_RSS_PKTS = 110, + PPORT_RESERVED_WORD111 = 111, + PPORT_RX_IPV4_PKTS = 112, + PPORT_RX_IPV6_PKTS = 114, + PPORT_RX_IPV4_BYTES = 116, + PPORT_RX_IPV6_BYTES = 118, + PPORT_RX_NIC_PKTS = 120, + PPORT_RX_TCP_PKTS = 122, + PPORT_RX_ISCSI_PKTS = 124, + PPORT_RX_MANAGEMENT_PKTS = 126, + PPORT_RX_SWITCHED_UNICAST_PKTS = 128, + PPORT_RX_SWITCHED_MULTICAST_PKTS = 130, + PPORT_RX_SWITCHED_BROADCAST_PKTS = 132, + PPORT_NUM_FORWARDS = 134, + PPORT_RX_FIFO_OVERFLOW = 136, + PPORT_RX_INPUT_FIFO_OVERFLOW = 137, + PPORT_RX_DROPS_TOO_MANY_FRAGS = 138, + PPORT_RX_DROPS_INVALID_QUEUE = 140, + PPORT_RESERVED_WORD141 = 141, + PPORT_RX_DROPS_MTU = 142, + PPORT_RX_PKTS_64_BYTES = 144, + PPORT_RX_PKTS_65_TO_127_BYTES = 146, + PPORT_RX_PKTS_128_TO_255_BYTES = 148, + PPORT_RX_PKTS_256_TO_511_BYTES = 150, + PPORT_RX_PKTS_512_TO_1023_BYTES = 152, + PPORT_RX_PKTS_1024_TO_1518_BYTES = 154, + PPORT_RX_PKTS_1519_TO_2047_BYTES = 156, + PPORT_RX_PKTS_2048_TO_4095_BYTES = 158, + PPORT_RX_PKTS_4096_TO_8191_BYTES = 160, + PPORT_RX_PKTS_8192_TO_9216_BYTES = 162, + PPORT_N_WORDS = 164 +}; + +/** + * @brief Statistics for a given Virtual Port (vPort) + * The following describes the vPort statistics satisfying + * requirements of Linux/VMWare netdev statistics and + * Microsoft Windows Statistics along with other Operating Systems. + */ +enum OCE_VPORT_STATS { + VPORT_TX_PKTS = 0, + VPORT_TX_UNICAST_PKTS = 2, + VPORT_TX_MULTICAST_PKTS = 4, + VPORT_TX_BROADCAST_PKTS = 6, + VPORT_TX_BYTES = 8, + VPORT_TX_UNICAST_BYTES = 10, + VPORT_TX_MULTICAST_BYTES = 12, + VPORT_TX_BROADCAST_BYTES = 14, + VPORT_TX_DISCARDS = 16, + VPORT_TX_ERRORS = 18, + VPORT_TX_PKTS_64_BYTES = 20, + VPORT_TX_PKTS_65_TO_127_BYTES = 22, + VPORT_TX_PKTS_128_TO_255_BYTES = 24, + VPORT_TX_PKTS_256_TO_511_BYTES = 26, + VPORT_TX_PKTS_512_TO_1023_BYTEs = 28, + VPORT_TX_PKTS_1024_TO_1518_BYTEs = 30, + VPORT_TX_PKTS_1519_TO_9699_BYTEs = 32, + VPORT_TX_PKTS_OVER_9699_BYTES = 34, + VPORT_RX_PKTS = 36, + VPORT_RX_UNICAST_PKTS = 38, + VPORT_RX_MULTICAST_PKTS = 40, + VPORT_RX_BROADCAST_PKTS = 42, + VPORT_RX_BYTES = 44, + VPORT_RX_UNICAST_BYTES = 46, + VPORT_RX_MULTICAST_BYTES = 48, + VPORT_RX_BROADCAST_BYTES = 50, + VPORT_RX_DISCARDS = 52, + VPORT_RX_ERRORS = 54, + VPORT_RX_PKTS_64_BYTES = 56, + VPORT_RX_PKTS_65_TO_127_BYTES = 58, + VPORT_RX_PKTS_128_TO_255_BYTES = 60, + VPORT_RX_PKTS_256_TO_511_BYTES = 62, + VPORT_RX_PKTS_512_TO_1023_BYTEs = 64, + VPORT_RX_PKTS_1024_TO_1518_BYTEs = 66, + VPORT_RX_PKTS_1519_TO_9699_BYTEs = 68, + VPORT_RX_PKTS_OVER_9699_BYTES = 70, + VPORT_N_WORDS = 72 +}; + +/** + * @brief Statistics for a given queue (NIC WQ, RQ, or HDS RQ) + * This set satisfies requirements of VMQare NetQueue and Microsoft VMQ + */ +enum OCE_QUEUE_TX_STATS { + QUEUE_TX_PKTS = 0, + QUEUE_TX_BYTES = 2, + QUEUE_TX_ERRORS = 4, + QUEUE_TX_DROPS = 6, + QUEUE_TX_N_WORDS = 8 +}; + +enum OCE_QUEUE_RX_STATS { + QUEUE_RX_PKTS = 0, + QUEUE_RX_BYTES = 2, + QUEUE_RX_ERRORS = 4, + QUEUE_RX_DROPS = 6, + QUEUE_RX_BUFFER_ERRORS = 8, + QUEUE_RX_N_WORDS = 10 +}; + diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c new file mode 100644 index 000000000000..601b1b7bd17b --- /dev/null +++ b/sys/dev/oce/oce_if.c @@ -0,0 +1,2044 @@ +/*- + * Copyright (C) 2012 Emulex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Emulex Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact Information: + * freebsd-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + + +/* $FreeBSD$ */ + +#include "opt_inet6.h" +#include "opt_inet.h" + +#include "oce_if.h" + + +/* Driver entry points prototypes */ +static int oce_probe(device_t dev); +static int oce_attach(device_t dev); +static int oce_detach(device_t dev); +static int oce_shutdown(device_t dev); +static int oce_ioctl(struct ifnet *ifp, u_long command, caddr_t data); +static void oce_init(void *xsc); +static int oce_multiq_start(struct ifnet *ifp, struct mbuf *m); +static void oce_multiq_flush(struct ifnet *ifp); + +/* Driver interrupt routines protypes */ +static void oce_intr(void *arg, int pending); +static int oce_setup_intr(POCE_SOFTC sc); +static int oce_fast_isr(void *arg); +static int oce_alloc_intr(POCE_SOFTC sc, int vector, + void (*isr) (void *arg, int pending)); + +/* Media callbacks prototypes */ +static void oce_media_status(struct ifnet *ifp, struct ifmediareq *req); +static int oce_media_change(struct ifnet *ifp); + +/* Transmit routines prototypes */ +static int oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index); +static void oce_tx_restart(POCE_SOFTC sc, struct oce_wq *wq); +static void oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx, + uint32_t status); +#if defined(INET6) || defined(INET) +static struct mbuf * oce_tso_setup(POCE_SOFTC sc, struct mbuf **mpp, + uint16_t *mss); +#endif +static int oce_multiq_transmit(struct ifnet *ifp, struct mbuf *m, + struct oce_wq *wq); + +/* Receive routines prototypes */ +static void oce_discard_rx_comp(struct oce_rq *rq, struct oce_nic_rx_cqe *cqe); +static int oce_cqe_vtp_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe); +static int oce_cqe_portid_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe); +#if defined(INET6) || defined(INET) +static void oce_rx_flush_lro(struct oce_rq *rq); +#endif +static void oce_rx(struct oce_rq *rq, uint32_t rqe_idx, + struct oce_nic_rx_cqe *cqe); + +/* Helper function prototypes in this file */ +static int oce_attach_ifp(POCE_SOFTC sc); +static void oce_add_vlan(void *arg, struct ifnet *ifp, uint16_t vtag); +static void oce_del_vlan(void *arg, struct ifnet *ifp, uint16_t vtag); +static int oce_vid_config(POCE_SOFTC sc); +static void oce_mac_addr_set(POCE_SOFTC sc); +static int oce_handle_passthrough(struct ifnet *ifp, caddr_t data); +static void oce_local_timer(void *arg); +#if defined(INET6) || defined(INET) +static int oce_init_lro(POCE_SOFTC sc); +#endif +static void oce_if_deactivate(POCE_SOFTC sc); +static void oce_if_activate(POCE_SOFTC sc); +static void setup_max_queues_want(POCE_SOFTC sc); +static void update_queues_got(POCE_SOFTC sc); + +static device_method_t oce_dispatch[] = { + DEVMETHOD(device_probe, oce_probe), + DEVMETHOD(device_attach, oce_attach), + DEVMETHOD(device_detach, oce_detach), + DEVMETHOD(device_shutdown, oce_shutdown), + {0, 0} +}; + +static driver_t oce_driver = { + "oce", + oce_dispatch, + sizeof(OCE_SOFTC) +}; +static devclass_t oce_devclass; + + +DRIVER_MODULE(oce, pci, oce_driver, oce_devclass, 0, 0); +MODULE_DEPEND(oce, pci, 1, 1, 1); +MODULE_DEPEND(oce, ether, 1, 1, 1); +MODULE_VERSION(oce, 1); + + +/* global vars */ +const char component_revision[32] = {"///" COMPONENT_REVISION "///"}; + +/* Module capabilites and parameters */ +uint32_t oce_max_rsp_handled = OCE_MAX_RSP_HANDLED; +uint32_t oce_enable_rss = OCE_MODCAP_RSS; + + +TUNABLE_INT("hw.oce.max_rsp_handled", &oce_max_rsp_handled); +TUNABLE_INT("hw.oce.enable_rss", &oce_enable_rss); + + +/* Supported devices table */ +static uint32_t supportedDevices[] = { + (PCI_VENDOR_SERVERENGINES << 16) | PCI_PRODUCT_BE2, + (PCI_VENDOR_SERVERENGINES << 16) | PCI_PRODUCT_BE3, + (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_BE3, + (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_XE201, + (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_XE201_VF, +}; + + + + +/***************************************************************************** + * Driver entry points functions * + *****************************************************************************/ + +static int +oce_probe(device_t dev) +{ + uint16_t vendor; + uint16_t device; + int i; + char str[80]; + POCE_SOFTC sc; + + sc = device_get_softc(dev); + bzero(sc, sizeof(OCE_SOFTC)); + sc->dev = dev; + + vendor = pci_get_vendor(dev); + device = pci_get_device(dev); + + for (i = 0; i < (sizeof(supportedDevices) / sizeof(uint16_t)); i++) { + if (vendor == ((supportedDevices[i] >> 16) & 0xffff)) { + if (device == (supportedDevices[i] & 0xffff)) { + sprintf(str, "%s:%s", + "Emulex CNA NIC function", + component_revision); + device_set_desc_copy(dev, str); + + switch (device) { + case PCI_PRODUCT_BE2: + sc->flags |= OCE_FLAGS_BE2; + break; + case PCI_PRODUCT_BE3: + sc->flags |= OCE_FLAGS_BE3; + break; + case PCI_PRODUCT_XE201: + case PCI_PRODUCT_XE201_VF: + sc->flags |= OCE_FLAGS_XE201; + break; + default: + return ENXIO; + } + return BUS_PROBE_DEFAULT; + } + } + } + + return ENXIO; +} + + +static int +oce_attach(device_t dev) +{ + POCE_SOFTC sc; + int rc = 0; + + sc = device_get_softc(dev); + + rc = oce_hw_pci_alloc(sc); + if (rc) + return rc; + + sc->rss_enable = oce_enable_rss; + sc->tx_ring_size = OCE_TX_RING_SIZE; + sc->rx_ring_size = OCE_RX_RING_SIZE; + sc->rq_frag_size = OCE_RQ_BUF_SIZE; + sc->flow_control = OCE_DEFAULT_FLOW_CONTROL; + sc->promisc = OCE_DEFAULT_PROMISCUOUS; + + LOCK_CREATE(&sc->bmbx_lock, "Mailbox_lock"); + LOCK_CREATE(&sc->dev_lock, "Device_lock"); + + /* initialise the hardware */ + rc = oce_hw_init(sc); + if (rc) + goto pci_res_free; + + + setup_max_queues_want(sc); + + + rc = oce_setup_intr(sc); + if (rc) + goto mbox_free; + + + rc = oce_queue_init_all(sc); + if (rc) + goto intr_free; + + + rc = oce_attach_ifp(sc); + if (rc) + goto queues_free; + + +#if defined(INET6) || defined(INET) + rc = oce_init_lro(sc); + if (rc) + goto ifp_free; +#endif + + + rc = oce_hw_start(sc); + if (rc) + goto lro_free;; + + + sc->vlan_attach = EVENTHANDLER_REGISTER(vlan_config, + oce_add_vlan, sc, EVENTHANDLER_PRI_FIRST); + sc->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig, + oce_del_vlan, sc, EVENTHANDLER_PRI_FIRST); + + rc = oce_stats_init(sc); + if (rc) + goto vlan_free; + + oce_add_sysctls(sc); + + + callout_init(&sc->timer, CALLOUT_MPSAFE); + rc = callout_reset(&sc->timer, 2 * hz, oce_local_timer, sc); + if (rc) + goto stats_free; + + return 0; + +stats_free: + callout_drain(&sc->timer); + oce_stats_free(sc); +vlan_free: + if (sc->vlan_attach) + EVENTHANDLER_DEREGISTER(vlan_config, sc->vlan_attach); + if (sc->vlan_detach) + EVENTHANDLER_DEREGISTER(vlan_unconfig, sc->vlan_detach); + oce_hw_intr_disable(sc); +lro_free: +#if defined(INET6) || defined(INET) + oce_free_lro(sc); +ifp_free: +#endif + ether_ifdetach(sc->ifp); + if_free(sc->ifp); +queues_free: + oce_queue_release_all(sc); +intr_free: + oce_intr_free(sc); +mbox_free: + oce_dma_free(sc, &sc->bsmbx); +pci_res_free: + oce_hw_pci_free(sc); + LOCK_DESTROY(&sc->dev_lock); + LOCK_DESTROY(&sc->bmbx_lock); + return rc; + +} + + +static int +oce_detach(device_t dev) +{ + POCE_SOFTC sc = device_get_softc(dev); + + LOCK(&sc->dev_lock); + + oce_if_deactivate(sc); + + UNLOCK(&sc->dev_lock); + + callout_drain(&sc->timer); + + if (sc->vlan_attach != NULL) + EVENTHANDLER_DEREGISTER(vlan_config, sc->vlan_attach); + if (sc->vlan_detach != NULL) + EVENTHANDLER_DEREGISTER(vlan_unconfig, sc->vlan_detach); + + ether_ifdetach(sc->ifp); + + if_free(sc->ifp); + + oce_hw_shutdown(sc); + + bus_generic_detach(dev); + + return 0; +} + + +static int +oce_shutdown(device_t dev) +{ + int rc; + + rc = oce_detach(dev); + + return rc; +} + + +static int +oce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) +{ + struct ifreq *ifr = (struct ifreq *)data; + POCE_SOFTC sc = ifp->if_softc; + int rc = 0; + uint32_t u; + + switch (command) { + case SIOCGIFPSRCADDR_IN6: + rc = ether_ioctl(ifp, command, data); + break; + + case SIOCGIFPSRCADDR: + rc = ether_ioctl(ifp, command, data); + break; + + case SIOCGIFSTATUS: + rc = ether_ioctl(ifp, command, data); + break; + + case SIOCGIFMEDIA: + rc = ifmedia_ioctl(ifp, ifr, &sc->media, command); + break; + + case SIOCSIFMEDIA: + rc = ether_ioctl(ifp, command, data); + break; + + case SIOCGIFGENERIC: + rc = ether_ioctl(ifp, command, data); + break; + + case SIOCGETMIFCNT_IN6: + rc = ether_ioctl(ifp, command, data); + break; + + case SIOCSIFMTU: + if (ifr->ifr_mtu > OCE_MAX_MTU) + rc = EINVAL; + else + ifp->if_mtu = ifr->ifr_mtu; + break; + + case SIOCSIFFLAGS: + if (ifp->if_flags & IFF_UP) { + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; + oce_init(sc); + } + device_printf(sc->dev, "Interface Up\n"); + } else { + LOCK(&sc->dev_lock); + + sc->ifp->if_drv_flags &= + ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + oce_if_deactivate(sc); + + UNLOCK(&sc->dev_lock); + + device_printf(sc->dev, "Interface Down\n"); + } + + if ((ifp->if_flags & IFF_PROMISC) && !sc->promisc) { + sc->promisc = TRUE; + oce_rxf_set_promiscuous(sc, sc->promisc); + } else if (!(ifp->if_flags & IFF_PROMISC) && sc->promisc) { + sc->promisc = FALSE; + oce_rxf_set_promiscuous(sc, sc->promisc); + } + + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + rc = oce_hw_update_multicast(sc); + if (rc) + device_printf(sc->dev, + "Update multicast address failed\n"); + break; + + case SIOCSIFCAP: + u = ifr->ifr_reqcap ^ ifp->if_capenable; + + if (u & IFCAP_TXCSUM) { + ifp->if_capenable ^= IFCAP_TXCSUM; + ifp->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP); + + if (IFCAP_TSO & ifp->if_capenable && + !(IFCAP_TXCSUM & ifp->if_capenable)) { + ifp->if_capenable &= ~IFCAP_TSO; + ifp->if_hwassist &= ~CSUM_TSO; + if_printf(ifp, + "TSO disabled due to -txcsum.\n"); + } + } + + if (u & IFCAP_RXCSUM) + ifp->if_capenable ^= IFCAP_RXCSUM; + + if (u & IFCAP_TSO4) { + ifp->if_capenable ^= IFCAP_TSO4; + + if (IFCAP_TSO & ifp->if_capenable) { + if (IFCAP_TXCSUM & ifp->if_capenable) + ifp->if_hwassist |= CSUM_TSO; + else { + ifp->if_capenable &= ~IFCAP_TSO; + ifp->if_hwassist &= ~CSUM_TSO; + if_printf(ifp, + "Enable txcsum first.\n"); + rc = EAGAIN; + } + } else + ifp->if_hwassist &= ~CSUM_TSO; + } + + if (u & IFCAP_VLAN_HWTAGGING) + ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + + if (u & IFCAP_VLAN_HWFILTER) { + ifp->if_capenable ^= IFCAP_VLAN_HWFILTER; + oce_vid_config(sc); + } + +#if defined(INET6) || defined(INET) + if (u & IFCAP_LRO) + ifp->if_capenable ^= IFCAP_LRO; +#endif + + break; + + case SIOCGPRIVATE_0: + rc = oce_handle_passthrough(ifp, data); + break; + default: + rc = ether_ioctl(ifp, command, data); + break; + } + + return rc; +} + + +static void +oce_init(void *arg) +{ + POCE_SOFTC sc = arg; + + LOCK(&sc->dev_lock); + + if (sc->ifp->if_flags & IFF_UP) { + oce_if_deactivate(sc); + oce_if_activate(sc); + } + + UNLOCK(&sc->dev_lock); + +} + + +static int +oce_multiq_start(struct ifnet *ifp, struct mbuf *m) +{ + POCE_SOFTC sc = ifp->if_softc; + struct oce_wq *wq = NULL; + int queue_index = 0; + int status = 0; + + if ((m->m_flags & M_FLOWID) != 0) + queue_index = m->m_pkthdr.flowid % sc->nwqs; + + wq = sc->wq[queue_index]; + + if (TRY_LOCK(&wq->tx_lock)) { + status = oce_multiq_transmit(ifp, m, wq); + UNLOCK(&wq->tx_lock); + } else { + status = drbr_enqueue(ifp, wq->br, m); + } + return status; + +} + + +static void +oce_multiq_flush(struct ifnet *ifp) +{ + POCE_SOFTC sc = ifp->if_softc; + struct mbuf *m; + int i = 0; + + for (i = 0; i < sc->nwqs; i++) { + while ((m = buf_ring_dequeue_sc(sc->wq[i]->br)) != NULL) + m_freem(m); + } + if_qflush(ifp); +} + + + +/***************************************************************************** + * Driver interrupt routines functions * + *****************************************************************************/ + +static void +oce_intr(void *arg, int pending) +{ + + POCE_INTR_INFO ii = (POCE_INTR_INFO) arg; + POCE_SOFTC sc = ii->sc; + struct oce_eq *eq = ii->eq; + struct oce_eqe *eqe; + struct oce_cq *cq = NULL; + int i, num_eqes = 0; + + + bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map, + BUS_DMASYNC_POSTWRITE); + do { + eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe); + if (eqe->evnt == 0) + break; + eqe->evnt = 0; + bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map, + BUS_DMASYNC_POSTWRITE); + RING_GET(eq->ring, 1); + num_eqes++; + + } while (TRUE); + + if (!num_eqes) + goto eq_arm; /* Spurious */ + + /* Clear EQ entries, but dont arm */ + oce_arm_eq(sc, eq->eq_id, num_eqes, FALSE, FALSE); + + /* Process TX, RX and MCC. But dont arm CQ*/ + for (i = 0; i < eq->cq_valid; i++) { + cq = eq->cq[i]; + (*cq->cq_handler)(cq->cb_arg); + } + + /* Arm all cqs connected to this EQ */ + for (i = 0; i < eq->cq_valid; i++) { + cq = eq->cq[i]; + oce_arm_cq(sc, cq->cq_id, 0, TRUE); + } + +eq_arm: + oce_arm_eq(sc, eq->eq_id, 0, TRUE, FALSE); + return; +} + + +static int +oce_setup_intr(POCE_SOFTC sc) +{ + int rc = 0, use_intx = 0; + int vector = 0, req_vectors = 0; + + if (sc->rss_enable) + req_vectors = MAX((sc->nrqs - 1), sc->nwqs); + else + req_vectors = 1; + + if (sc->flags & OCE_FLAGS_MSIX_CAPABLE) { + sc->intr_count = req_vectors; + rc = pci_alloc_msix(sc->dev, &sc->intr_count); + if (rc != 0) { + use_intx = 1; + pci_release_msi(sc->dev); + } else + sc->flags |= OCE_FLAGS_USING_MSIX; + } else + use_intx = 1; + + if (use_intx) + sc->intr_count = 1; + + /* Scale number of queues based on intr we got */ + update_queues_got(sc); + + if (use_intx) { + device_printf(sc->dev, "Using legacy interrupt\n"); + rc = oce_alloc_intr(sc, vector, oce_intr); + if (rc) + goto error; + } else { + for (; vector < sc->intr_count; vector++) { + rc = oce_alloc_intr(sc, vector, oce_intr); + if (rc) + goto error; + } + } + + return 0; +error: + oce_intr_free(sc); + return rc; +} + + +static int +oce_fast_isr(void *arg) +{ + POCE_INTR_INFO ii = (POCE_INTR_INFO) arg; + POCE_SOFTC sc = ii->sc; + + if (ii->eq == NULL) + return FILTER_STRAY; + + oce_arm_eq(sc, ii->eq->eq_id, 0, FALSE, TRUE); + + taskqueue_enqueue_fast(ii->tq, &ii->task); + + return FILTER_HANDLED; +} + + +static int +oce_alloc_intr(POCE_SOFTC sc, int vector, void (*isr) (void *arg, int pending)) +{ + POCE_INTR_INFO ii = &sc->intrs[vector]; + int rc = 0, rr; + + if (vector >= OCE_MAX_EQ) + return (EINVAL); + + /* Set the resource id for the interrupt. + * MSIx is vector + 1 for the resource id, + * INTx is 0 for the resource id. + */ + if (sc->flags & OCE_FLAGS_USING_MSIX) + rr = vector + 1; + else + rr = 0; + ii->intr_res = bus_alloc_resource_any(sc->dev, + SYS_RES_IRQ, + &rr, RF_ACTIVE|RF_SHAREABLE); + ii->irq_rr = rr; + if (ii->intr_res == NULL) { + device_printf(sc->dev, + "Could not allocate interrupt\n"); + rc = ENXIO; + return rc; + } + + TASK_INIT(&ii->task, 0, isr, ii); + ii->vector = vector; + sprintf(ii->task_name, "oce_task[%d]", ii->vector); + ii->tq = taskqueue_create_fast(ii->task_name, + M_NOWAIT, + taskqueue_thread_enqueue, + &ii->tq); + taskqueue_start_threads(&ii->tq, 1, PI_NET, "%s taskq", + device_get_nameunit(sc->dev)); + + ii->sc = sc; + rc = bus_setup_intr(sc->dev, + ii->intr_res, + INTR_TYPE_NET, + oce_fast_isr, NULL, ii, &ii->tag); + return rc; + +} + + +void +oce_intr_free(POCE_SOFTC sc) +{ + int i = 0; + + for (i = 0; i < sc->intr_count; i++) { + + if (sc->intrs[i].tag != NULL) + bus_teardown_intr(sc->dev, sc->intrs[i].intr_res, + sc->intrs[i].tag); + if (sc->intrs[i].tq != NULL) + taskqueue_free(sc->intrs[i].tq); + + if (sc->intrs[i].intr_res != NULL) + bus_release_resource(sc->dev, SYS_RES_IRQ, + sc->intrs[i].irq_rr, + sc->intrs[i].intr_res); + sc->intrs[i].tag = NULL; + sc->intrs[i].intr_res = NULL; + } + + if (sc->flags & OCE_FLAGS_USING_MSIX) + pci_release_msi(sc->dev); + +} + + + +/****************************************************************************** +* Media callbacks functions * +******************************************************************************/ + +static void +oce_media_status(struct ifnet *ifp, struct ifmediareq *req) +{ + POCE_SOFTC sc = (POCE_SOFTC) ifp->if_softc; + + + req->ifm_status = IFM_AVALID; + req->ifm_active = IFM_ETHER; + + if (sc->link_status == 1) + req->ifm_status |= IFM_ACTIVE; + else + return; + + switch (sc->link_speed) { + case 1: /* 10 Mbps */ + req->ifm_active |= IFM_10_T | IFM_FDX; + sc->speed = 10; + break; + case 2: /* 100 Mbps */ + req->ifm_active |= IFM_100_TX | IFM_FDX; + sc->speed = 100; + break; + case 3: /* 1 Gbps */ + req->ifm_active |= IFM_1000_T | IFM_FDX; + sc->speed = 1000; + break; + case 4: /* 10 Gbps */ + req->ifm_active |= IFM_10G_SR | IFM_FDX; + sc->speed = 10000; + break; + } + + return; +} + + +int +oce_media_change(struct ifnet *ifp) +{ + return 0; +} + + + + +/***************************************************************************** + * Transmit routines functions * + *****************************************************************************/ + +static int +oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index) +{ + int rc = 0, i, retry_cnt = 0; + bus_dma_segment_t segs[OCE_MAX_TX_ELEMENTS]; + struct mbuf *m, *m_temp; + struct oce_wq *wq = sc->wq[wq_index]; + struct oce_packet_desc *pd; + uint32_t out; + struct oce_nic_hdr_wqe *nichdr; + struct oce_nic_frag_wqe *nicfrag; + int num_wqes; + uint32_t reg_value; +#if defined(INET6) || defined(INET) + uint16_t mss = 0; +#endif + + m = *mpp; + if (!m) + return EINVAL; + + if (!(m->m_flags & M_PKTHDR)) { + rc = ENXIO; + goto free_ret; + } + + if (m->m_pkthdr.csum_flags & CSUM_TSO) { +#if defined(INET6) || defined(INET) + /* consolidate packet buffers for TSO/LSO segment offload */ + m = oce_tso_setup(sc, mpp, &mss); +#else + m = NULL; +#endif + if (m == NULL) { + rc = ENXIO; + goto free_ret; + } + } + + out = wq->packets_out + 1; + if (out == OCE_WQ_PACKET_ARRAY_SIZE) + out = 0; + if (out == wq->packets_in) + return EBUSY; + + pd = &wq->pckts[wq->packets_out]; +retry: + rc = bus_dmamap_load_mbuf_sg(wq->tag, + pd->map, + m, segs, &pd->nsegs, BUS_DMA_NOWAIT); + if (rc == 0) { + num_wqes = pd->nsegs + 1; + if (IS_BE(sc)) { + /*Dummy required only for BE3.*/ + if (num_wqes & 1) + num_wqes++; + } + if (num_wqes >= RING_NUM_FREE(wq->ring)) { + bus_dmamap_unload(wq->tag, pd->map); + return EBUSY; + } + + bus_dmamap_sync(wq->tag, pd->map, BUS_DMASYNC_PREWRITE); + pd->mbuf = m; + wq->packets_out = out; + + nichdr = + RING_GET_PRODUCER_ITEM_VA(wq->ring, struct oce_nic_hdr_wqe); + nichdr->u0.dw[0] = 0; + nichdr->u0.dw[1] = 0; + nichdr->u0.dw[2] = 0; + nichdr->u0.dw[3] = 0; + + nichdr->u0.s.complete = 1; + nichdr->u0.s.event = 1; + nichdr->u0.s.crc = 1; + nichdr->u0.s.forward = 0; + nichdr->u0.s.ipcs = (m->m_pkthdr.csum_flags & CSUM_IP) ? 1 : 0; + nichdr->u0.s.udpcs = + (m->m_pkthdr.csum_flags & CSUM_UDP) ? 1 : 0; + nichdr->u0.s.tcpcs = + (m->m_pkthdr.csum_flags & CSUM_TCP) ? 1 : 0; + nichdr->u0.s.num_wqe = num_wqes; + nichdr->u0.s.total_length = m->m_pkthdr.len; + if (m->m_flags & M_VLANTAG) { + nichdr->u0.s.vlan = 1; /*Vlan present*/ + nichdr->u0.s.vlan_tag = m->m_pkthdr.ether_vtag; + } + if (m->m_pkthdr.csum_flags & CSUM_TSO) { + if (m->m_pkthdr.tso_segsz) { + nichdr->u0.s.lso = 1; + nichdr->u0.s.lso_mss = m->m_pkthdr.tso_segsz; + } + if (!IS_BE(sc)) + nichdr->u0.s.ipcs = 1; + } + + RING_PUT(wq->ring, 1); + wq->ring->num_used++; + + for (i = 0; i < pd->nsegs; i++) { + nicfrag = + RING_GET_PRODUCER_ITEM_VA(wq->ring, + struct oce_nic_frag_wqe); + nicfrag->u0.s.rsvd0 = 0; + nicfrag->u0.s.frag_pa_hi = ADDR_HI(segs[i].ds_addr); + nicfrag->u0.s.frag_pa_lo = ADDR_LO(segs[i].ds_addr); + nicfrag->u0.s.frag_len = segs[i].ds_len; + pd->wqe_idx = wq->ring->pidx; + RING_PUT(wq->ring, 1); + wq->ring->num_used++; + } + if (num_wqes > (pd->nsegs + 1)) { + nicfrag = + RING_GET_PRODUCER_ITEM_VA(wq->ring, + struct oce_nic_frag_wqe); + nicfrag->u0.dw[0] = 0; + nicfrag->u0.dw[1] = 0; + nicfrag->u0.dw[2] = 0; + nicfrag->u0.dw[3] = 0; + pd->wqe_idx = wq->ring->pidx; + RING_PUT(wq->ring, 1); + wq->ring->num_used++; + pd->nsegs++; + } + + sc->ifp->if_opackets++; + wq->tx_stats.tx_reqs++; + wq->tx_stats.tx_wrbs += num_wqes; + wq->tx_stats.tx_bytes += m->m_pkthdr.len; + wq->tx_stats.tx_pkts++; + + bus_dmamap_sync(wq->ring->dma.tag, wq->ring->dma.map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + reg_value = (num_wqes << 16) | wq->wq_id; + OCE_WRITE_REG32(sc, db, PD_TXULP_DB, reg_value); + + } else if (rc == EFBIG) { + if (retry_cnt == 0) { + m_temp = m_defrag(m, M_DONTWAIT); + if (m_temp == NULL) + goto free_ret; + m = m_temp; + *mpp = m_temp; + retry_cnt = retry_cnt + 1; + goto retry; + } else + goto free_ret; + } else if (rc == ENOMEM) + return rc; + else + goto free_ret; + + return 0; + +free_ret: + m_freem(*mpp); + *mpp = NULL; + return rc; +} + + +static void +oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx, uint32_t status) +{ + uint32_t in; + struct oce_packet_desc *pd; + POCE_SOFTC sc = (POCE_SOFTC) wq->parent; + struct mbuf *m; + + if (wq->packets_out == wq->packets_in) + device_printf(sc->dev, "WQ transmit descriptor missing\n"); + + in = wq->packets_in + 1; + if (in == OCE_WQ_PACKET_ARRAY_SIZE) + in = 0; + + pd = &wq->pckts[wq->packets_in]; + wq->packets_in = in; + wq->ring->num_used -= (pd->nsegs + 1); + bus_dmamap_sync(wq->tag, pd->map, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(wq->tag, pd->map); + + m = pd->mbuf; + m_freem(m); + pd->mbuf = NULL; + + if (sc->ifp->if_drv_flags & IFF_DRV_OACTIVE) { + if (wq->ring->num_used < (wq->ring->num_items / 2)) { + sc->ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE); + oce_tx_restart(sc, wq); + } + } +} + + +static void +oce_tx_restart(POCE_SOFTC sc, struct oce_wq *wq) +{ + + if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING) + return; + +#if __FreeBSD_version >= 800000 + if (!drbr_empty(sc->ifp, wq->br)) +#else + if (!IFQ_DRV_IS_EMPTY(&sc->ifp->if_snd)) +#endif + taskqueue_enqueue_fast(taskqueue_swi, &wq->txtask); + +} + +#if defined(INET6) || defined(INET) +static struct mbuf * +oce_tso_setup(POCE_SOFTC sc, struct mbuf **mpp, uint16_t *mss) +{ + struct mbuf *m; +#ifdef INET + struct ip *ip; +#endif +#ifdef INET6 + struct ip6_hdr *ip6; +#endif + struct ether_vlan_header *eh; + struct tcphdr *th; + int total_len = 0; + uint16_t etype; + int ehdrlen = 0; + + m = *mpp; + *mss = m->m_pkthdr.tso_segsz; + + if (M_WRITABLE(m) == 0) { + m = m_dup(*mpp, M_DONTWAIT); + if (!m) + return NULL; + m_freem(*mpp); + *mpp = m; + } + + eh = mtod(m, struct ether_vlan_header *); + if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { + etype = ntohs(eh->evl_proto); + ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; + } else { + etype = ntohs(eh->evl_encap_proto); + ehdrlen = ETHER_HDR_LEN; + } + + + switch (etype) { +#ifdef INET + case ETHERTYPE_IP: + ip = (struct ip *)(m->m_data + ehdrlen); + if (ip->ip_p != IPPROTO_TCP) + return NULL; + th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); + + total_len = ehdrlen + (ip->ip_hl << 2) + (th->th_off << 2); + break; +#endif +#ifdef INET6 + case ETHERTYPE_IPV6: + ip6 = (struct ip6_hdr *)(m->m_data + ehdrlen); + if (ip6->ip6_nxt != IPPROTO_TCP) + return NULL; + th = (struct tcphdr *)((caddr_t)ip6 + sizeof(struct ip6_hdr)); + + total_len = ehdrlen + sizeof(struct ip6_hdr) + (th->th_off << 2); + break; +#endif + default: + return NULL; + } + + m = m_pullup(m, total_len); + if (!m) + return NULL; + *mpp = m; + return m; + +} +#endif /* INET6 || INET */ + + +void +oce_tx_task(void *arg, int npending) +{ + struct oce_wq *wq = arg; + POCE_SOFTC sc = wq->parent; + struct ifnet *ifp = sc->ifp; + int rc = 0; + +#if __FreeBSD_version >= 800000 + if (TRY_LOCK(&wq->tx_lock)) { + rc = oce_multiq_transmit(ifp, NULL, wq); + if (rc) { + device_printf(sc->dev, + "TX[%d] restart failed\n", wq->queue_index); + } + UNLOCK(&wq->tx_lock); + } +#else + oce_start(ifp); +#endif + +} + + +void +oce_start(struct ifnet *ifp) +{ + POCE_SOFTC sc = ifp->if_softc; + struct mbuf *m; + int rc = 0; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return; + + do { + IF_DEQUEUE(&sc->ifp->if_snd, m); + if (m == NULL) + break; + /* oce_start always uses default TX queue 0 */ + LOCK(&sc->wq[0]->tx_lock); + rc = oce_tx(sc, &m, 0); + UNLOCK(&sc->wq[0]->tx_lock); + if (rc) { + if (m != NULL) { + sc->wq[0]->tx_stats.tx_stops ++; + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + IFQ_DRV_PREPEND(&ifp->if_snd, m); + m = NULL; + } + break; + } + if (m != NULL) + ETHER_BPF_MTAP(ifp, m); + + } while (1); + + return; +} + + +/* Handle the Completion Queue for transmit */ +uint16_t +oce_wq_handler(void *arg) +{ + struct oce_wq *wq = (struct oce_wq *)arg; + POCE_SOFTC sc = wq->parent; + struct oce_cq *cq = wq->cq; + struct oce_nic_tx_cqe *cqe; + int num_cqes = 0; + + LOCK(&wq->tx_lock); + bus_dmamap_sync(cq->ring->dma.tag, + cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); + cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe); + while (cqe->u0.dw[3]) { + DW_SWAP((uint32_t *) cqe, sizeof(oce_wq_cqe)); + + wq->ring->cidx = cqe->u0.s.wqe_index + 1; + if (wq->ring->cidx >= wq->ring->num_items) + wq->ring->cidx -= wq->ring->num_items; + + oce_tx_complete(wq, cqe->u0.s.wqe_index, cqe->u0.s.status); + wq->tx_stats.tx_compl++; + cqe->u0.dw[3] = 0; + RING_GET(cq->ring, 1); + bus_dmamap_sync(cq->ring->dma.tag, + cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); + cqe = + RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe); + num_cqes++; + } + + if (num_cqes) + oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + UNLOCK(&wq->tx_lock); + + return 0; +} + + +static int +oce_multiq_transmit(struct ifnet *ifp, struct mbuf *m, struct oce_wq *wq) +{ + POCE_SOFTC sc = ifp->if_softc; + int status = 0, queue_index = 0; + struct mbuf *next = NULL; + struct buf_ring *br = NULL; + + br = wq->br; + queue_index = wq->queue_index; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) { + if (m != NULL) + status = drbr_enqueue(ifp, br, m); + return status; + } + + if (m == NULL) + next = drbr_dequeue(ifp, br); + else if (drbr_needs_enqueue(ifp, br)) { + if ((status = drbr_enqueue(ifp, br, m)) != 0) + return status; + next = drbr_dequeue(ifp, br); + } else + next = m; + + while (next != NULL) { + if (oce_tx(sc, &next, queue_index)) { + if (next != NULL) { + wq->tx_stats.tx_stops ++; + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + status = drbr_enqueue(ifp, br, next); + } + break; + } + drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags); + ETHER_BPF_MTAP(ifp, next); + next = drbr_dequeue(ifp, br); + } + + return status; +} + + + + +/***************************************************************************** + * Receive routines functions * + *****************************************************************************/ + +static void +oce_rx(struct oce_rq *rq, uint32_t rqe_idx, struct oce_nic_rx_cqe *cqe) +{ + uint32_t out; + struct oce_packet_desc *pd; + POCE_SOFTC sc = (POCE_SOFTC) rq->parent; + int i, len, frag_len; + struct mbuf *m = NULL, *tail = NULL; + uint16_t vtag; + + len = cqe->u0.s.pkt_size; + vtag = cqe->u0.s.vlan_tag; + if (!len) { + /*partial DMA workaround for Lancer*/ + oce_discard_rx_comp(rq, cqe); + goto exit; + } + + for (i = 0; i < cqe->u0.s.num_fragments; i++) { + + if (rq->packets_out == rq->packets_in) { + device_printf(sc->dev, + "RQ transmit descriptor missing\n"); + } + out = rq->packets_out + 1; + if (out == OCE_RQ_PACKET_ARRAY_SIZE) + out = 0; + pd = &rq->pckts[rq->packets_out]; + rq->packets_out = out; + + bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(rq->tag, pd->map); + rq->pending--; + + frag_len = (len > rq->cfg.frag_size) ? rq->cfg.frag_size : len; + pd->mbuf->m_len = frag_len; + + if (tail != NULL) { + /* additional fragments */ + pd->mbuf->m_flags &= ~M_PKTHDR; + tail->m_next = pd->mbuf; + tail = pd->mbuf; + } else { + /* first fragment, fill out much of the packet header */ + pd->mbuf->m_pkthdr.len = len; + pd->mbuf->m_pkthdr.csum_flags = 0; + if (IF_CSUM_ENABLED(sc)) { + if (cqe->u0.s.l4_cksum_pass) { + pd->mbuf->m_pkthdr.csum_flags |= + (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); + pd->mbuf->m_pkthdr.csum_data = 0xffff; + } + if (cqe->u0.s.ip_cksum_pass) { + if (!cqe->u0.s.ip_ver) { //IPV4 + pd->mbuf->m_pkthdr.csum_flags |= + (CSUM_IP_CHECKED|CSUM_IP_VALID); + } + } + } + m = tail = pd->mbuf; + } + pd->mbuf = NULL; + len -= frag_len; + } + + if (m) { + if (!oce_cqe_portid_valid(sc, cqe)) { + m_freem(m); + goto exit; + } + + m->m_pkthdr.rcvif = sc->ifp; +#if __FreeBSD_version >= 800000 + m->m_pkthdr.flowid = rq->queue_index; + m->m_flags |= M_FLOWID; +#endif + //This deternies if vlan tag is present + if (oce_cqe_vtp_valid(sc, cqe)) { + if (sc->function_mode & FNM_FLEX10_MODE) { + /* FLEX10 */ + if (cqe->u0.s.qnq) { + /* If QnQ is not set, neglect VLAN */ + if (IS_BE(sc)) + m->m_pkthdr.ether_vtag = + BSWAP_16(vtag); + else + m->m_pkthdr.ether_vtag = vtag; + m->m_flags |= M_VLANTAG; + } + } else { + if (IS_BE(sc)) + m->m_pkthdr.ether_vtag = BSWAP_16(vtag); + else + m->m_pkthdr.ether_vtag = vtag; + m->m_flags |= M_VLANTAG; + } + } + + sc->ifp->if_ipackets++; +#if defined(INET6) || defined(INET) + /* Try to queue to LRO */ + if (IF_LRO_ENABLED(sc) && + !(m->m_flags & M_VLANTAG) && + (cqe->u0.s.ip_cksum_pass) && + (cqe->u0.s.l4_cksum_pass) && + (!cqe->u0.s.ip_ver) && + (rq->lro.lro_cnt != 0)) { + + if (tcp_lro_rx(&rq->lro, m, 0) == 0) { + rq->lro_pkts_queued ++; + goto post_done; + } + /* If LRO posting fails then try to post to STACK */ + } +#endif + + (*sc->ifp->if_input) (sc->ifp, m); +#if defined(INET6) || defined(INET) +post_done: +#endif + /* Update rx stats per queue */ + rq->rx_stats.rx_pkts++; + rq->rx_stats.rx_bytes += cqe->u0.s.pkt_size; + rq->rx_stats.rx_frags += cqe->u0.s.num_fragments; + if (cqe->u0.s.pkt_type == OCE_MULTICAST_PACKET) + rq->rx_stats.rx_mcast_pkts++; + if (cqe->u0.s.pkt_type == OCE_UNICAST_PACKET) + rq->rx_stats.rx_ucast_pkts++; + } +exit: + return; +} + + +static void +oce_discard_rx_comp(struct oce_rq *rq, struct oce_nic_rx_cqe *cqe) +{ + uint32_t out, i = 0; + struct oce_packet_desc *pd; + POCE_SOFTC sc = (POCE_SOFTC) rq->parent; + int num_frags = cqe->u0.s.num_fragments; + + if (IS_XE201(sc) && cqe->u0.s.error) { + /* Lancer A0 workaround + * num_frags will be 1 more than actual in case of error + */ + if (num_frags) + num_frags -= 1; + } + for (i = 0; i < num_frags; i++) { + if (rq->packets_out == rq->packets_in) { + device_printf(sc->dev, + "RQ transmit descriptor missing\n"); + } + out = rq->packets_out + 1; + if (out == OCE_RQ_PACKET_ARRAY_SIZE) + out = 0; + pd = &rq->pckts[rq->packets_out]; + rq->packets_out = out; + + bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(rq->tag, pd->map); + rq->pending--; + m_freem(pd->mbuf); + } + +} + + +static int +oce_cqe_vtp_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe) +{ + struct oce_nic_rx_cqe_v1 *cqe_v1; + int vtp = 0; + + if (sc->be3_native) { + cqe_v1 = (struct oce_nic_rx_cqe_v1 *)cqe; + vtp = cqe_v1->u0.s.vlan_tag_present; + } else { + vtp = cqe->u0.s.vlan_tag_present; + } + + return vtp; + +} + + +static int +oce_cqe_portid_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe) +{ + struct oce_nic_rx_cqe_v1 *cqe_v1; + int port_id = 0; + + if (sc->be3_native && IS_BE(sc)) { + cqe_v1 = (struct oce_nic_rx_cqe_v1 *)cqe; + port_id = cqe_v1->u0.s.port; + if (sc->port_id != port_id) + return 0; + } else + ;/* For BE3 legacy and Lancer this is dummy */ + + return 1; + +} + + +#if defined(INET6) || defined(INET) +static void +oce_rx_flush_lro(struct oce_rq *rq) +{ + struct lro_ctrl *lro = &rq->lro; + struct lro_entry *queued; + POCE_SOFTC sc = (POCE_SOFTC) rq->parent; + + if (!IF_LRO_ENABLED(sc)) + return; + + while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) { + SLIST_REMOVE_HEAD(&lro->lro_active, next); + tcp_lro_flush(lro, queued); + } + rq->lro_pkts_queued = 0; + + return; +} + + +static int +oce_init_lro(POCE_SOFTC sc) +{ + struct lro_ctrl *lro = NULL; + int i = 0, rc = 0; + + for (i = 0; i < sc->nrqs; i++) { + lro = &sc->rq[i]->lro; + rc = tcp_lro_init(lro); + if (rc != 0) { + device_printf(sc->dev, "LRO init failed\n"); + return rc; + } + lro->ifp = sc->ifp; + } + + return rc; +} +#endif /* INET6 || INET */ + +void +oce_free_lro(POCE_SOFTC sc) +{ +#if defined(INET6) || defined(INET) + struct lro_ctrl *lro = NULL; + int i = 0; + + for (i = 0; i < sc->nrqs; i++) { + lro = &sc->rq[i]->lro; + if (lro) + tcp_lro_free(lro); + } +#endif +} + + +int +oce_alloc_rx_bufs(struct oce_rq *rq, int count) +{ + POCE_SOFTC sc = (POCE_SOFTC) rq->parent; + int i, in, rc; + struct oce_packet_desc *pd; + bus_dma_segment_t segs[6]; + int nsegs, added = 0; + struct oce_nic_rqe *rqe; + pd_rxulp_db_t rxdb_reg; + + + for (i = 0; i < count; i++) { + in = rq->packets_in + 1; + if (in == OCE_RQ_PACKET_ARRAY_SIZE) + in = 0; + if (in == rq->packets_out) + break; /* no more room */ + + pd = &rq->pckts[rq->packets_in]; + pd->mbuf = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + if (pd->mbuf == NULL) + break; + + pd->mbuf->m_len = pd->mbuf->m_pkthdr.len = MCLBYTES; + rc = bus_dmamap_load_mbuf_sg(rq->tag, + pd->map, + pd->mbuf, + segs, &nsegs, BUS_DMA_NOWAIT); + if (rc) { + m_free(pd->mbuf); + break; + } + + if (nsegs != 1) { + i--; + continue; + } + + rq->packets_in = in; + bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_PREREAD); + + rqe = RING_GET_PRODUCER_ITEM_VA(rq->ring, struct oce_nic_rqe); + rqe->u0.s.frag_pa_hi = ADDR_HI(segs[0].ds_addr); + rqe->u0.s.frag_pa_lo = ADDR_LO(segs[0].ds_addr); + DW_SWAP(u32ptr(rqe), sizeof(struct oce_nic_rqe)); + RING_PUT(rq->ring, 1); + added++; + rq->pending++; + } + if (added != 0) { + for (i = added / OCE_MAX_RQ_POSTS; i > 0; i--) { + DELAY(1); + rxdb_reg.bits.num_posted = OCE_MAX_RQ_POSTS; + rxdb_reg.bits.qid = rq->rq_id; + OCE_WRITE_REG32(sc, db, PD_RXULP_DB, rxdb_reg.dw0); + added -= OCE_MAX_RQ_POSTS; + } + if (added > 0) { + DELAY(1); + rxdb_reg.bits.qid = rq->rq_id; + rxdb_reg.bits.num_posted = added; + OCE_WRITE_REG32(sc, db, PD_RXULP_DB, rxdb_reg.dw0); + } + } + + return 0; +} + + +/* Handle the Completion Queue for receive */ +uint16_t +oce_rq_handler(void *arg) +{ + struct oce_rq *rq = (struct oce_rq *)arg; + struct oce_cq *cq = rq->cq; + POCE_SOFTC sc = rq->parent; + struct oce_nic_rx_cqe *cqe; + int num_cqes = 0, rq_buffers_used = 0; + + + LOCK(&rq->rx_lock); + bus_dmamap_sync(cq->ring->dma.tag, + cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); + cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe); + while (cqe->u0.dw[2]) { + DW_SWAP((uint32_t *) cqe, sizeof(oce_rq_cqe)); + + RING_GET(rq->ring, 1); + if (cqe->u0.s.error == 0) { + oce_rx(rq, cqe->u0.s.frag_index, cqe); + } else { + rq->rx_stats.rxcp_err++; + sc->ifp->if_ierrors++; + if (IS_XE201(sc)) + /* Lancer A0 no buffer workaround */ + oce_discard_rx_comp(rq, cqe); + else + /* Post L3/L4 errors to stack.*/ + oce_rx(rq, cqe->u0.s.frag_index, cqe); + + } + rq->rx_stats.rx_compl++; + cqe->u0.dw[2] = 0; + +#if defined(INET6) || defined(INET) + if (IF_LRO_ENABLED(sc) && rq->lro_pkts_queued >= 16) { + oce_rx_flush_lro(rq); + } +#endif + + RING_GET(cq->ring, 1); + bus_dmamap_sync(cq->ring->dma.tag, + cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); + cqe = + RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe); + num_cqes++; + if (num_cqes >= (IS_XE201(sc) ? 8 : oce_max_rsp_handled)) + break; + } +#if defined(INET6) || defined(INET) + if (IF_LRO_ENABLED(sc)) + oce_rx_flush_lro(rq); +#endif + + if (num_cqes) { + oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + rq_buffers_used = OCE_RQ_PACKET_ARRAY_SIZE - rq->pending; + if (rq_buffers_used > 1) + oce_alloc_rx_bufs(rq, (rq_buffers_used - 1)); + } + + UNLOCK(&rq->rx_lock); + + return 0; + +} + + + + +/***************************************************************************** + * Helper function prototypes in this file * + *****************************************************************************/ + +static int +oce_attach_ifp(POCE_SOFTC sc) +{ + + sc->ifp = if_alloc(IFT_ETHER); + if (!sc->ifp) + return ENOMEM; + + ifmedia_init(&sc->media, IFM_IMASK, oce_media_change, oce_media_status); + ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); + + sc->ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; + sc->ifp->if_ioctl = oce_ioctl; + sc->ifp->if_start = oce_start; + sc->ifp->if_init = oce_init; + sc->ifp->if_mtu = ETHERMTU; + sc->ifp->if_softc = sc; +#if __FreeBSD_version >= 800000 + sc->ifp->if_transmit = oce_multiq_start; + sc->ifp->if_qflush = oce_multiq_flush; +#endif + + if_initname(sc->ifp, + device_get_name(sc->dev), device_get_unit(sc->dev)); + + sc->ifp->if_snd.ifq_drv_maxlen = OCE_MAX_TX_DESC - 1; + IFQ_SET_MAXLEN(&sc->ifp->if_snd, sc->ifp->if_snd.ifq_drv_maxlen); + IFQ_SET_READY(&sc->ifp->if_snd); + + sc->ifp->if_hwassist = OCE_IF_HWASSIST; + sc->ifp->if_hwassist |= CSUM_TSO; + sc->ifp->if_hwassist |= (CSUM_IP | CSUM_TCP | CSUM_UDP); + + sc->ifp->if_capabilities = OCE_IF_CAPABILITIES; + sc->ifp->if_capabilities |= IFCAP_HWCSUM; + sc->ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; +#if defined(INET6) || defined(INET) + sc->ifp->if_capabilities |= IFCAP_TSO; + sc->ifp->if_capabilities |= IFCAP_LRO; +#endif + + sc->ifp->if_capenable = sc->ifp->if_capabilities; + sc->ifp->if_baudrate = IF_Gbps(10UL); + + ether_ifattach(sc->ifp, sc->macaddr.mac_addr); + + return 0; +} + + +static void +oce_add_vlan(void *arg, struct ifnet *ifp, uint16_t vtag) +{ + POCE_SOFTC sc = ifp->if_softc; + + if (ifp->if_softc != arg) + return; + if ((vtag == 0) || (vtag > 4095)) + return; + + sc->vlan_tag[vtag] = 1; + sc->vlans_added++; + oce_vid_config(sc); +} + + +static void +oce_del_vlan(void *arg, struct ifnet *ifp, uint16_t vtag) +{ + POCE_SOFTC sc = ifp->if_softc; + + if (ifp->if_softc != arg) + return; + if ((vtag == 0) || (vtag > 4095)) + return; + + sc->vlan_tag[vtag] = 0; + sc->vlans_added--; + oce_vid_config(sc); +} + + +/* + * A max of 64 vlans can be configured in BE. If the user configures + * more, place the card in vlan promiscuous mode. + */ +static int +oce_vid_config(POCE_SOFTC sc) +{ + struct normal_vlan vtags[MAX_VLANFILTER_SIZE]; + uint16_t ntags = 0, i; + int status = 0; + + if ((sc->vlans_added <= MAX_VLANFILTER_SIZE) && + (sc->ifp->if_capenable & IFCAP_VLAN_HWFILTER)) { + for (i = 0; i < MAX_VLANS; i++) { + if (sc->vlan_tag[i]) { + vtags[ntags].vtag = i; + ntags++; + } + } + if (ntags) + status = oce_config_vlan(sc, (uint8_t) sc->if_id, + vtags, ntags, 1, 0); + } else + status = oce_config_vlan(sc, (uint8_t) sc->if_id, + NULL, 0, 1, 1); + return status; +} + + +static void +oce_mac_addr_set(POCE_SOFTC sc) +{ + uint32_t old_pmac_id = sc->pmac_id; + int status = 0; + + + status = bcmp((IF_LLADDR(sc->ifp)), sc->macaddr.mac_addr, + sc->macaddr.size_of_struct); + if (!status) + return; + + status = oce_mbox_macaddr_add(sc, (uint8_t *)(IF_LLADDR(sc->ifp)), + sc->if_id, &sc->pmac_id); + if (!status) { + status = oce_mbox_macaddr_del(sc, sc->if_id, old_pmac_id); + bcopy((IF_LLADDR(sc->ifp)), sc->macaddr.mac_addr, + sc->macaddr.size_of_struct); + } + if (status) + device_printf(sc->dev, "Failed update macaddress\n"); + +} + + +static int +oce_handle_passthrough(struct ifnet *ifp, caddr_t data) +{ + POCE_SOFTC sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + int rc = ENXIO; + char cookie[32] = {0}; + void *priv_data = (void *)ifr->ifr_data; + void *ioctl_ptr; + uint32_t req_size; + struct mbx_hdr req; + OCE_DMA_MEM dma_mem; + + + if (copyin(priv_data, cookie, strlen(IOCTL_COOKIE))) + return EFAULT; + + if (memcmp(cookie, IOCTL_COOKIE, strlen(IOCTL_COOKIE))) + return EINVAL; + + ioctl_ptr = (char *)priv_data + strlen(IOCTL_COOKIE); + if (copyin(ioctl_ptr, &req, sizeof(struct mbx_hdr))) + return EFAULT; + + req_size = le32toh(req.u0.req.request_length); + if (req_size > 65536) + return EINVAL; + + req_size += sizeof(struct mbx_hdr); + rc = oce_dma_alloc(sc, req_size, &dma_mem, 0); + if (rc) + return ENOMEM; + + if (copyin(ioctl_ptr, OCE_DMAPTR(&dma_mem,char), req_size)) { + rc = EFAULT; + goto dma_free; + } + + rc = oce_pass_through_mbox(sc, &dma_mem, req_size); + if (rc) { + rc = EIO; + goto dma_free; + } + + if (copyout(OCE_DMAPTR(&dma_mem,char), ioctl_ptr, req_size)) + rc = EFAULT; + +dma_free: + oce_dma_free(sc, &dma_mem); + return rc; + +} + + +static void +oce_local_timer(void *arg) +{ + POCE_SOFTC sc = arg; + int i = 0; + + oce_refresh_nic_stats(sc); + oce_refresh_queue_stats(sc); + oce_mac_addr_set(sc); + + /* TX Watch Dog*/ + for (i = 0; i < sc->nwqs; i++) + oce_tx_restart(sc, sc->wq[i]); + + callout_reset(&sc->timer, hz, oce_local_timer, sc); +} + + +static void +oce_if_deactivate(POCE_SOFTC sc) +{ + int i, mtime = 0; + int wait_req = 0; + struct oce_rq *rq; + struct oce_wq *wq; + struct oce_eq *eq; + + sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + + /*Wait for max of 400ms for TX completions to be done */ + while (mtime < 400) { + wait_req = 0; + for_all_wq_queues(sc, wq, i) { + if (wq->ring->num_used) { + wait_req = 1; + DELAY(1); + break; + } + } + mtime += 1; + if (!wait_req) + break; + } + + /* Stop intrs and finish any bottom halves pending */ + oce_hw_intr_disable(sc); + + for (i = 0; i < sc->intr_count; i++) { + if (sc->intrs[i].tq != NULL) { + taskqueue_drain(sc->intrs[i].tq, &sc->intrs[i].task); + } + } + + /* Delete RX queue in card with flush param */ + oce_stop_rx(sc); + + /* Invalidate any pending cq and eq entries*/ + for_all_evnt_queues(sc, eq, i) + oce_drain_eq(eq); + for_all_rq_queues(sc, rq, i) + oce_drain_rq_cq(rq); + for_all_wq_queues(sc, wq, i) + oce_drain_wq_cq(wq); + + /* But still we need to get MCC aync events. + So enable intrs and also arm first EQ + */ + oce_hw_intr_enable(sc); + oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE); + + DELAY(10); +} + + +static void +oce_if_activate(POCE_SOFTC sc) +{ + struct oce_eq *eq; + struct oce_rq *rq; + struct oce_wq *wq; + int i, rc = 0; + + sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; + + oce_hw_intr_disable(sc); + + oce_start_rx(sc); + + for_all_rq_queues(sc, rq, i) { + rc = oce_start_rq(rq); + if (rc) + device_printf(sc->dev, "Unable to start RX\n"); + } + + for_all_wq_queues(sc, wq, i) { + rc = oce_start_wq(wq); + if (rc) + device_printf(sc->dev, "Unable to start TX\n"); + } + + + for_all_evnt_queues(sc, eq, i) + oce_arm_eq(sc, eq->eq_id, 0, TRUE, FALSE); + + oce_hw_intr_enable(sc); + +} + +/* Handle the Completion Queue for the Mailbox/Async notifications */ +uint16_t +oce_mq_handler(void *arg) +{ + struct oce_mq *mq = (struct oce_mq *)arg; + POCE_SOFTC sc = mq->parent; + struct oce_cq *cq = mq->cq; + int num_cqes = 0; + struct oce_mq_cqe *cqe; + struct oce_async_cqe_link_state *acqe; + + bus_dmamap_sync(cq->ring->dma.tag, + cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); + cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe); + while (cqe->u0.dw[3]) { + DW_SWAP((uint32_t *) cqe, sizeof(oce_mq_cqe)); + if (cqe->u0.s.async_event) { + acqe = (struct oce_async_cqe_link_state *)cqe; + if ((acqe->u0.s.link_status & ~ASYNC_EVENT_LOGICAL) == + ASYNC_EVENT_LINK_UP) { + sc->link_status = ASYNC_EVENT_LINK_UP; + if_link_state_change(sc->ifp, LINK_STATE_UP); + } else { + sc->link_status = ASYNC_EVENT_LINK_DOWN; + if_link_state_change(sc->ifp, LINK_STATE_DOWN); + } + + if (acqe->u0.s.event_code == + ASYNC_EVENT_CODE_LINK_STATE) { + sc->link_speed = acqe->u0.s.speed; + sc->qos_link_speed = + (uint32_t )acqe->u0.s.qos_link_speed * 10; + } + } + cqe->u0.dw[3] = 0; + RING_GET(cq->ring, 1); + RING_GET(mq->ring, 1); + bus_dmamap_sync(cq->ring->dma.tag, + cq->ring->dma.map, BUS_DMASYNC_POSTWRITE); + cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe); + num_cqes++; + } + + if (num_cqes) + oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + + return 0; +} + + +static void +setup_max_queues_want(POCE_SOFTC sc) +{ + int max_rss = 0; + + /* Check if it is FLEX machine. Is so dont use RSS */ + if ((sc->function_mode & FNM_FLEX10_MODE) || + (!sc->rss_enable) || + (sc->flags & OCE_FLAGS_BE2)) { + sc->nrqs = 1; + sc->nwqs = 1; + sc->rss_enable = 0; + } else { + /* For multiq, our deisgn is to have TX rings equal to + RSS rings. So that we can pair up one RSS ring and TX + to a single intr, which improves CPU cache efficiency. + */ + if (IS_BE(sc) && (!sc->be3_native)) + max_rss = OCE_LEGACY_MODE_RSS; + else + max_rss = OCE_MAX_RSS; + + sc->nrqs = MIN(OCE_NCPUS, max_rss) + 1; /* 1 for def RX */ + sc->nwqs = MIN(OCE_NCPUS, max_rss); + + /*Hardware issue. Turn off multi TX for be2 */ + if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) + sc->nwqs = 1; + + } + +} + + +static void +update_queues_got(POCE_SOFTC sc) +{ + if (sc->rss_enable) { + sc->nrqs = sc->intr_count + 1; + sc->nwqs = sc->intr_count; + if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE2)) + sc->nwqs = 1; + } else { + sc->nrqs = 1; + sc->nwqs = 1; + } +} + diff --git a/sys/dev/oce/oce_if.h b/sys/dev/oce/oce_if.h new file mode 100644 index 000000000000..b08865de1c3f --- /dev/null +++ b/sys/dev/oce/oce_if.h @@ -0,0 +1,1071 @@ +/*- + * Copyright (C) 2012 Emulex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Emulex Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact Information: + * freebsd-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + + +/* $FreeBSD$ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "oce_hw.h" + +#define COMPONENT_REVISION "4.2.116.0" + +/* OCE devices supported by this driver */ +#define PCI_VENDOR_EMULEX 0x10df /* Emulex */ +#define PCI_VENDOR_SERVERENGINES 0x19a2 /* ServerEngines (BE) */ +#define PCI_PRODUCT_BE2 0x0700 /* BE2 network adapter */ +#define PCI_PRODUCT_BE3 0x0710 /* BE3 network adapter */ +#define PCI_PRODUCT_XE201 0xe220 /* XE201 network adapter */ +#define PCI_PRODUCT_XE201_VF 0xe228 /* XE201 with VF in Lancer */ + +#define IS_BE(sc) (((sc->flags & OCE_FLAGS_BE3) | \ + (sc->flags & OCE_FLAGS_BE2))? 1:0) +#define IS_XE201(sc) ((sc->flags & OCE_FLAGS_XE201) ? 1:0) +#define HAS_A0_CHIP(sc) ((sc->flags & OCE_FLAGS_HAS_A0_CHIP) ? 1:0) + + +/* proportion Service Level Interface queues */ +#define OCE_MAX_UNITS 2 +#define OCE_MAX_PPORT OCE_MAX_UNITS +#define OCE_MAX_VPORT OCE_MAX_UNITS + +extern int mp_ncpus; /* system's total active cpu cores */ +#define OCE_NCPUS mp_ncpus +#define OCE_MAX_RSS 8 /* This should be powers of 2. Like 2,4,8 & 16 */ +#define OCE_LEGACY_MODE_RSS 4 /* For BE3 Legacy mode*/ + +#define OCE_MIN_RQ 1 +#define OCE_MIN_WQ 1 + +#define OCE_MAX_RQ OCE_MAX_RSS + 1 /* one default queue */ +#define OCE_MAX_WQ 8 + +#define OCE_MAX_EQ 32 +#define OCE_MAX_CQ OCE_MAX_RQ + OCE_MAX_WQ + 1 /* one MCC queue */ +#define OCE_MAX_CQ_EQ 8 /* Max CQ that can attached to an EQ */ + +#define OCE_DEFAULT_WQ_EQD 16 +#define OCE_MAX_PACKET_Q 16 +#define OCE_RQ_BUF_SIZE 2048 +#define OCE_LSO_MAX_SIZE (64 * 1024) +#define LONG_TIMEOUT 30 +#define OCE_MAX_JUMBO_FRAME_SIZE 16360 +#define OCE_MAX_MTU (OCE_MAX_JUMBO_FRAME_SIZE - \ + ETHER_VLAN_ENCAP_LEN - \ + ETHER_HDR_LEN) + +#define OCE_MAX_TX_ELEMENTS 29 +#define OCE_MAX_TX_DESC 1024 +#define OCE_MAX_TX_SIZE 65535 +#define OCE_MAX_RX_SIZE 4096 +#define OCE_MAX_RQ_POSTS 255 +#define OCE_DEFAULT_PROMISCUOUS 0 + + +#define RSS_ENABLE_IPV4 0x1 +#define RSS_ENABLE_TCP_IPV4 0x2 +#define RSS_ENABLE_IPV6 0x4 +#define RSS_ENABLE_TCP_IPV6 0x8 + + +/* flow control definitions */ +#define OCE_FC_NONE 0x00000000 +#define OCE_FC_TX 0x00000001 +#define OCE_FC_RX 0x00000002 +#define OCE_DEFAULT_FLOW_CONTROL (OCE_FC_TX | OCE_FC_RX) + + +/* Interface capabilities to give device when creating interface */ +#define OCE_CAPAB_FLAGS (MBX_RX_IFACE_FLAGS_BROADCAST | \ + MBX_RX_IFACE_FLAGS_UNTAGGED | \ + MBX_RX_IFACE_FLAGS_PROMISCUOUS | \ + MBX_RX_IFACE_FLAGS_MCAST_PROMISCUOUS | \ + MBX_RX_IFACE_FLAGS_RSS | \ + MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR) + +/* Interface capabilities to enable by default (others set dynamically) */ +#define OCE_CAPAB_ENABLE (MBX_RX_IFACE_FLAGS_BROADCAST | \ + MBX_RX_IFACE_FLAGS_UNTAGGED | \ + MBX_RX_IFACE_FLAGS_PASS_L3L4_ERR) + +#define OCE_IF_HWASSIST (CSUM_IP | CSUM_TCP | CSUM_UDP) +#define OCE_IF_CAPABILITIES (IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | \ + IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM | \ + IFCAP_VLAN_HWTSO | IFCAP_JUMBO_MTU | \ + IFCAP_VLAN_MTU) +#define OCE_IF_HWASSIST_NONE 0 +#define OCE_IF_CAPABILITIES_NONE 0 + + +#define ETH_ADDR_LEN 6 +#define MAX_VLANFILTER_SIZE 64 +#define MAX_VLANS 4096 + +#define upper_32_bits(n) ((uint32_t)(((n) >> 16) >> 16)) +#define BSWAP_8(x) ((x) & 0xff) +#define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8)) +#define BSWAP_32(x) ((BSWAP_16(x) << 16) | \ + BSWAP_16((x) >> 16)) +#define BSWAP_64(x) ((BSWAP_32(x) << 32) | \ + BSWAP_32((x) >> 32)) + +#define for_all_wq_queues(sc, wq, i) \ + for (i = 0, wq = sc->wq[0]; i < sc->nwqs; i++, wq = sc->wq[i]) +#define for_all_rq_queues(sc, rq, i) \ + for (i = 0, rq = sc->rq[0]; i < sc->nrqs; i++, rq = sc->rq[i]) +#define for_all_evnt_queues(sc, eq, i) \ + for (i = 0, eq = sc->eq[0]; i < sc->neqs; i++, eq = sc->eq[i]) +#define for_all_cq_queues(sc, cq, i) \ + for (i = 0, cq = sc->cq[0]; i < sc->ncqs; i++, cq = sc->cq[i]) + + +/* Flash specific */ +#define IOCTL_COOKIE "SERVERENGINES CORP" +#define MAX_FLASH_COMP 32 + +#define IMG_ISCSI 160 +#define IMG_REDBOOT 224 +#define IMG_BIOS 34 +#define IMG_PXEBIOS 32 +#define IMG_FCOEBIOS 33 +#define IMG_ISCSI_BAK 176 +#define IMG_FCOE 162 +#define IMG_FCOE_BAK 178 +#define IMG_NCSI 16 +#define IMG_PHY 192 +#define FLASHROM_OPER_FLASH 1 +#define FLASHROM_OPER_SAVE 2 +#define FLASHROM_OPER_REPORT 4 +#define FLASHROM_OPER_FLASH_PHY 9 +#define FLASHROM_OPER_SAVE_PHY 10 +#define TN_8022 13 + +enum { + PHY_TYPE_CX4_10GB = 0, + PHY_TYPE_XFP_10GB, + PHY_TYPE_SFP_1GB, + PHY_TYPE_SFP_PLUS_10GB, + PHY_TYPE_KR_10GB, + PHY_TYPE_KX4_10GB, + PHY_TYPE_BASET_10GB, + PHY_TYPE_BASET_1GB, + PHY_TYPE_BASEX_1GB, + PHY_TYPE_SGMII, + PHY_TYPE_DISABLED = 255 +}; + +/** + * @brief Define and hold all necessary info for a single interrupt + */ +#define OCE_MAX_MSI 32 /* Message Signaled Interrupts */ +#define OCE_MAX_MSIX 2048 /* PCI Express MSI Interrrupts */ + +typedef struct oce_intr_info { + void *tag; /* cookie returned by bus_setup_intr */ + struct resource *intr_res; /* PCI resource container */ + int irq_rr; /* resource id for the interrupt */ + struct oce_softc *sc; /* pointer to the parent soft c */ + struct oce_eq *eq; /* pointer to the connected EQ */ + struct taskqueue *tq; /* Associated task queue */ + struct task task; /* task queue task */ + char task_name[32]; /* task name */ + int vector; /* interrupt vector number */ +} OCE_INTR_INFO, *POCE_INTR_INFO; + + +/* Ring related */ +#define GET_Q_NEXT(_START, _STEP, _END) \ + (((_START) + (_STEP)) < (_END) ? ((_START) + (_STEP)) \ + : (((_START) + (_STEP)) - (_END))) + +#define DBUF_PA(obj) ((obj)->addr) +#define DBUF_VA(obj) ((obj)->ptr) +#define DBUF_TAG(obj) ((obj)->tag) +#define DBUF_MAP(obj) ((obj)->map) +#define DBUF_SYNC(obj, flags) \ + (void) bus_dmamap_sync(DBUF_TAG(obj), DBUF_MAP(obj), (flags)) + +#define RING_NUM_PENDING(ring) ring->num_used +#define RING_FULL(ring) (ring->num_used == ring->num_items) +#define RING_EMPTY(ring) (ring->num_used == 0) +#define RING_NUM_FREE(ring) \ + (uint32_t)(ring->num_items - ring->num_used) +#define RING_GET(ring, n) \ + ring->cidx = GET_Q_NEXT(ring->cidx, n, ring->num_items) +#define RING_PUT(ring, n) \ + ring->pidx = GET_Q_NEXT(ring->pidx, n, ring->num_items) + +#define RING_GET_CONSUMER_ITEM_VA(ring, type) \ + (void*)((type *)DBUF_VA(&ring->dma) + ring->cidx) +#define RING_GET_CONSUMER_ITEM_PA(ring, type) \ + (uint64_t)(((type *)DBUF_PA(ring->dbuf)) + ring->cidx) +#define RING_GET_PRODUCER_ITEM_VA(ring, type) \ + (void *)(((type *)DBUF_VA(&ring->dma)) + ring->pidx) +#define RING_GET_PRODUCER_ITEM_PA(ring, type) \ + (uint64_t)(((type *)DBUF_PA(ring->dbuf)) + ring->pidx) + +#define OCE_DMAPTR(o, c) ((c *)(o)->ptr) + +struct oce_packet_desc { + struct mbuf *mbuf; + bus_dmamap_t map; + int nsegs; + uint32_t wqe_idx; +}; + +typedef struct oce_dma_mem { + bus_dma_tag_t tag; + bus_dmamap_t map; + void *ptr; + bus_addr_t paddr; +} OCE_DMA_MEM, *POCE_DMA_MEM; + +typedef struct oce_ring_buffer_s { + uint16_t cidx; /* Get ptr */ + uint16_t pidx; /* Put Ptr */ + size_t item_size; + size_t num_items; + uint32_t num_used; + OCE_DMA_MEM dma; +} oce_ring_buffer_t; + +/* Stats */ +#define OCE_UNICAST_PACKET 0 +#define OCE_MULTICAST_PACKET 1 +#define OCE_BROADCAST_PACKET 2 +#define OCE_RSVD_PACKET 3 + +struct oce_rx_stats { + /* Total Receive Stats*/ + uint64_t t_rx_pkts; + uint64_t t_rx_bytes; + uint32_t t_rx_frags; + uint32_t t_rx_mcast_pkts; + uint32_t t_rx_ucast_pkts; + uint32_t t_rxcp_errs; +}; +struct oce_tx_stats { + /*Total Transmit Stats */ + uint64_t t_tx_pkts; + uint64_t t_tx_bytes; + uint32_t t_tx_reqs; + uint32_t t_tx_stops; + uint32_t t_tx_wrbs; + uint32_t t_tx_compl; + uint32_t t_ipv6_ext_hdr_tx_drop; +}; + +struct oce_be_stats { + uint8_t be_on_die_temperature; + uint32_t be_tx_events; + uint32_t eth_red_drops; + uint32_t rx_drops_no_pbuf; + uint32_t rx_drops_no_txpb; + uint32_t rx_drops_no_erx_descr; + uint32_t rx_drops_no_tpre_descr; + uint32_t rx_drops_too_many_frags; + uint32_t rx_drops_invalid_ring; + uint32_t forwarded_packets; + uint32_t rx_drops_mtu; + uint32_t rx_crc_errors; + uint32_t rx_alignment_symbol_errors; + uint32_t rx_pause_frames; + uint32_t rx_priority_pause_frames; + uint32_t rx_control_frames; + uint32_t rx_in_range_errors; + uint32_t rx_out_range_errors; + uint32_t rx_frame_too_long; + uint32_t rx_address_match_errors; + uint32_t rx_dropped_too_small; + uint32_t rx_dropped_too_short; + uint32_t rx_dropped_header_too_small; + uint32_t rx_dropped_tcp_length; + uint32_t rx_dropped_runt; + uint32_t rx_ip_checksum_errs; + uint32_t rx_tcp_checksum_errs; + uint32_t rx_udp_checksum_errs; + uint32_t rx_switched_unicast_packets; + uint32_t rx_switched_multicast_packets; + uint32_t rx_switched_broadcast_packets; + uint32_t tx_pauseframes; + uint32_t tx_priority_pauseframes; + uint32_t tx_controlframes; + uint32_t rxpp_fifo_overflow_drop; + uint32_t rx_input_fifo_overflow_drop; + uint32_t pmem_fifo_overflow_drop; + uint32_t jabber_events; +}; + +struct oce_xe201_stats { + uint64_t tx_pkts; + uint64_t tx_unicast_pkts; + uint64_t tx_multicast_pkts; + uint64_t tx_broadcast_pkts; + uint64_t tx_bytes; + uint64_t tx_unicast_bytes; + uint64_t tx_multicast_bytes; + uint64_t tx_broadcast_bytes; + uint64_t tx_discards; + uint64_t tx_errors; + uint64_t tx_pause_frames; + uint64_t tx_pause_on_frames; + uint64_t tx_pause_off_frames; + uint64_t tx_internal_mac_errors; + uint64_t tx_control_frames; + uint64_t tx_pkts_64_bytes; + uint64_t tx_pkts_65_to_127_bytes; + uint64_t tx_pkts_128_to_255_bytes; + uint64_t tx_pkts_256_to_511_bytes; + uint64_t tx_pkts_512_to_1023_bytes; + uint64_t tx_pkts_1024_to_1518_bytes; + uint64_t tx_pkts_1519_to_2047_bytes; + uint64_t tx_pkts_2048_to_4095_bytes; + uint64_t tx_pkts_4096_to_8191_bytes; + uint64_t tx_pkts_8192_to_9216_bytes; + uint64_t tx_lso_pkts; + uint64_t rx_pkts; + uint64_t rx_unicast_pkts; + uint64_t rx_multicast_pkts; + uint64_t rx_broadcast_pkts; + uint64_t rx_bytes; + uint64_t rx_unicast_bytes; + uint64_t rx_multicast_bytes; + uint64_t rx_broadcast_bytes; + uint32_t rx_unknown_protos; + uint64_t rx_discards; + uint64_t rx_errors; + uint64_t rx_crc_errors; + uint64_t rx_alignment_errors; + uint64_t rx_symbol_errors; + uint64_t rx_pause_frames; + uint64_t rx_pause_on_frames; + uint64_t rx_pause_off_frames; + uint64_t rx_frames_too_long; + uint64_t rx_internal_mac_errors; + uint32_t rx_undersize_pkts; + uint32_t rx_oversize_pkts; + uint32_t rx_fragment_pkts; + uint32_t rx_jabbers; + uint64_t rx_control_frames; + uint64_t rx_control_frames_unknown_opcode; + uint32_t rx_in_range_errors; + uint32_t rx_out_of_range_errors; + uint32_t rx_address_match_errors; + uint32_t rx_vlan_mismatch_errors; + uint32_t rx_dropped_too_small; + uint32_t rx_dropped_too_short; + uint32_t rx_dropped_header_too_small; + uint32_t rx_dropped_invalid_tcp_length; + uint32_t rx_dropped_runt; + uint32_t rx_ip_checksum_errors; + uint32_t rx_tcp_checksum_errors; + uint32_t rx_udp_checksum_errors; + uint32_t rx_non_rss_pkts; + uint64_t rx_ipv4_pkts; + uint64_t rx_ipv6_pkts; + uint64_t rx_ipv4_bytes; + uint64_t rx_ipv6_bytes; + uint64_t rx_nic_pkts; + uint64_t rx_tcp_pkts; + uint64_t rx_iscsi_pkts; + uint64_t rx_management_pkts; + uint64_t rx_switched_unicast_pkts; + uint64_t rx_switched_multicast_pkts; + uint64_t rx_switched_broadcast_pkts; + uint64_t num_forwards; + uint32_t rx_fifo_overflow; + uint32_t rx_input_fifo_overflow; + uint64_t rx_drops_too_many_frags; + uint32_t rx_drops_invalid_queue; + uint64_t rx_drops_mtu; + uint64_t rx_pkts_64_bytes; + uint64_t rx_pkts_65_to_127_bytes; + uint64_t rx_pkts_128_to_255_bytes; + uint64_t rx_pkts_256_to_511_bytes; + uint64_t rx_pkts_512_to_1023_bytes; + uint64_t rx_pkts_1024_to_1518_bytes; + uint64_t rx_pkts_1519_to_2047_bytes; + uint64_t rx_pkts_2048_to_4095_bytes; + uint64_t rx_pkts_4096_to_8191_bytes; + uint64_t rx_pkts_8192_to_9216_bytes; +}; + +struct oce_drv_stats { + struct oce_rx_stats rx; + struct oce_tx_stats tx; + union { + struct oce_be_stats be; + struct oce_xe201_stats xe201; + } u0; +}; + + + +#define MAX_LOCK_DESC_LEN 32 +struct oce_lock { + struct mtx mutex; + char name[MAX_LOCK_DESC_LEN+1]; +}; +#define OCE_LOCK struct oce_lock + +#define LOCK_CREATE(lock, desc) { \ + strncpy((lock)->name, (desc), MAX_LOCK_DESC_LEN); \ + (lock)->name[MAX_LOCK_DESC_LEN] = '\0'; \ + mtx_init(&(lock)->mutex, (lock)->name, MTX_NETWORK_LOCK, MTX_DEF); \ +} +#define LOCK_DESTROY(lock) \ + if (mtx_initialized(&(lock)->mutex))\ + mtx_destroy(&(lock)->mutex) +#define TRY_LOCK(lock) mtx_trylock(&(lock)->mutex) +#define LOCK(lock) mtx_lock(&(lock)->mutex) +#define LOCKED(lock) mtx_owned(&(lock)->mutex) +#define UNLOCK(lock) mtx_unlock(&(lock)->mutex) + +#define DEFAULT_MQ_MBOX_TIMEOUT (5 * 1000 * 1000) +#define MBX_READY_TIMEOUT (1 * 1000 * 1000) +#define DEFAULT_DRAIN_TIME 200 +#define MBX_TIMEOUT_SEC 5 +#define STAT_TIMEOUT 2000000 + +/* size of the packet descriptor array in a transmit queue */ +#define OCE_TX_RING_SIZE 2048 +#define OCE_RX_RING_SIZE 1024 +#define OCE_WQ_PACKET_ARRAY_SIZE (OCE_TX_RING_SIZE/2) +#define OCE_RQ_PACKET_ARRAY_SIZE (OCE_RX_RING_SIZE) + +struct oce_dev; + +enum eq_len { + EQ_LEN_256 = 256, + EQ_LEN_512 = 512, + EQ_LEN_1024 = 1024, + EQ_LEN_2048 = 2048, + EQ_LEN_4096 = 4096 +}; + +enum eqe_size { + EQE_SIZE_4 = 4, + EQE_SIZE_16 = 16 +}; + +enum qtype { + QTYPE_EQ, + QTYPE_MQ, + QTYPE_WQ, + QTYPE_RQ, + QTYPE_CQ, + QTYPE_RSS +}; + +typedef enum qstate_e { + QDELETED = 0x0, + QCREATED = 0x1 +} qstate_t; + +struct eq_config { + enum eq_len q_len; + enum eqe_size item_size; + uint32_t q_vector_num; + uint8_t min_eqd; + uint8_t max_eqd; + uint8_t cur_eqd; + uint8_t pad; +}; + +struct oce_eq { + uint32_t eq_id; + void *parent; + void *cb_context; + oce_ring_buffer_t *ring; + uint32_t ref_count; + qstate_t qstate; + struct oce_cq *cq[OCE_MAX_CQ_EQ]; + int cq_valid; + struct eq_config eq_cfg; + int vector; +}; + +enum cq_len { + CQ_LEN_256 = 256, + CQ_LEN_512 = 512, + CQ_LEN_1024 = 1024 +}; + +struct cq_config { + enum cq_len q_len; + uint32_t item_size; + boolean_t is_eventable; + boolean_t sol_eventable; + boolean_t nodelay; + uint16_t dma_coalescing; +}; + +typedef uint16_t(*cq_handler_t) (void *arg1); + +struct oce_cq { + uint32_t cq_id; + void *parent; + struct oce_eq *eq; + cq_handler_t cq_handler; + void *cb_arg; + oce_ring_buffer_t *ring; + qstate_t qstate; + struct cq_config cq_cfg; + uint32_t ref_count; +}; + + +struct mq_config { + uint32_t eqd; + uint8_t q_len; + uint8_t pad[3]; +}; + + +struct oce_mq { + void *parent; + oce_ring_buffer_t *ring; + uint32_t mq_id; + struct oce_cq *cq; + struct oce_cq *async_cq; + uint32_t mq_free; + qstate_t qstate; + struct mq_config cfg; +}; + +struct oce_mbx_ctx { + struct oce_mbx *mbx; + void (*cb) (void *ctx); + void *cb_ctx; +}; + +struct wq_config { + uint8_t wq_type; + uint16_t buf_size; + uint8_t pad[1]; + uint32_t q_len; + uint16_t pd_id; + uint16_t pci_fn_num; + uint32_t eqd; /* interrupt delay */ + uint32_t nbufs; + uint32_t nhdl; +}; + +struct oce_tx_queue_stats { + uint64_t tx_pkts; + uint64_t tx_bytes; + uint32_t tx_reqs; + uint32_t tx_stops; /* number of times TX Q was stopped */ + uint32_t tx_wrbs; + uint32_t tx_compl; + uint32_t tx_rate; + uint32_t ipv6_ext_hdr_tx_drop; +}; + +struct oce_wq { + OCE_LOCK tx_lock; + void *parent; + oce_ring_buffer_t *ring; + struct oce_cq *cq; + bus_dma_tag_t tag; + struct oce_packet_desc pckts[OCE_WQ_PACKET_ARRAY_SIZE]; + uint32_t packets_in; + uint32_t packets_out; + uint32_t wqm_used; + boolean_t resched; + uint32_t wq_free; + uint32_t tx_deferd; + uint32_t pkt_drops; + qstate_t qstate; + uint16_t wq_id; + struct wq_config cfg; + int queue_index; + struct oce_tx_queue_stats tx_stats; + struct buf_ring *br; + struct task txtask; +}; + +struct rq_config { + uint32_t q_len; + uint32_t frag_size; + uint32_t mtu; + uint32_t if_id; + uint32_t is_rss_queue; + uint32_t eqd; + uint32_t nbufs; +}; + +struct oce_rx_queue_stats { + uint32_t rx_post_fail; + uint32_t rx_ucast_pkts; + uint32_t rx_compl; + uint64_t rx_bytes; + uint64_t rx_bytes_prev; + uint64_t rx_pkts; + uint32_t rx_rate; + uint32_t rx_mcast_pkts; + uint32_t rxcp_err; + uint32_t rx_frags; + uint32_t prev_rx_frags; + uint32_t rx_fps; +}; + + +struct oce_rq { + struct rq_config cfg; + uint32_t rq_id; + int queue_index; + uint32_t rss_cpuid; + void *parent; + oce_ring_buffer_t *ring; + struct oce_cq *cq; + void *pad1; + bus_dma_tag_t tag; + struct oce_packet_desc pckts[OCE_RQ_PACKET_ARRAY_SIZE]; + uint32_t packets_in; + uint32_t packets_out; + uint32_t pending; +#ifdef notdef + struct mbuf *head; + struct mbuf *tail; + int fragsleft; +#endif + qstate_t qstate; + OCE_LOCK rx_lock; + struct oce_rx_queue_stats rx_stats; + struct lro_ctrl lro; + int lro_pkts_queued; + +}; + +struct link_status { + uint8_t physical_port; + uint8_t mac_duplex; + uint8_t mac_speed; + uint8_t mac_fault; + uint8_t mgmt_mac_duplex; + uint8_t mgmt_mac_speed; + uint16_t qos_link_speed; + uint32_t logical_link_status; +}; + + + +#define OCE_FLAGS_PCIX 0x00000001 +#define OCE_FLAGS_PCIE 0x00000002 +#define OCE_FLAGS_MSI_CAPABLE 0x00000004 +#define OCE_FLAGS_MSIX_CAPABLE 0x00000008 +#define OCE_FLAGS_USING_MSI 0x00000010 +#define OCE_FLAGS_USING_MSIX 0x00000020 +#define OCE_FLAGS_FUNCRESET_RQD 0x00000040 +#define OCE_FLAGS_VIRTUAL_PORT 0x00000080 +#define OCE_FLAGS_MBOX_ENDIAN_RQD 0x00000100 +#define OCE_FLAGS_BE3 0x00000200 +#define OCE_FLAGS_XE201 0x00000400 +#define OCE_FLAGS_BE2 0x00000800 + +#define OCE_DEV_BE2_CFG_BAR 1 +#define OCE_DEV_CFG_BAR 0 +#define OCE_PCI_CSR_BAR 2 +#define OCE_PCI_DB_BAR 4 + +typedef struct oce_softc { + device_t dev; + OCE_LOCK dev_lock; + + uint32_t flags; + + uint32_t pcie_link_speed; + uint32_t pcie_link_width; + + uint8_t fn; /* PCI function number */ + + struct resource *devcfg_res; + bus_space_tag_t devcfg_btag; + bus_space_handle_t devcfg_bhandle; + void *devcfg_vhandle; + + struct resource *csr_res; + bus_space_tag_t csr_btag; + bus_space_handle_t csr_bhandle; + void *csr_vhandle; + + struct resource *db_res; + bus_space_tag_t db_btag; + bus_space_handle_t db_bhandle; + void *db_vhandle; + + OCE_INTR_INFO intrs[OCE_MAX_EQ]; + int intr_count; + + struct ifnet *ifp; + + struct ifmedia media; + uint8_t link_status; + uint8_t link_speed; + uint8_t duplex; + uint32_t qos_link_speed; + uint32_t speed; + + char fw_version[32]; + struct mac_address_format macaddr; + + OCE_DMA_MEM bsmbx; + OCE_LOCK bmbx_lock; + + uint32_t config_number; + uint32_t asic_revision; + uint32_t port_id; + uint32_t function_mode; + uint32_t function_caps; + uint32_t max_tx_rings; + uint32_t max_rx_rings; + + struct oce_wq *wq[OCE_MAX_WQ]; /* TX work queues */ + struct oce_rq *rq[OCE_MAX_RQ]; /* RX work queues */ + struct oce_cq *cq[OCE_MAX_CQ]; /* Completion queues */ + struct oce_eq *eq[OCE_MAX_EQ]; /* Event queues */ + struct oce_mq *mq; /* Mailbox queue */ + + uint32_t neqs; + uint32_t ncqs; + uint32_t nrqs; + uint32_t nwqs; + + uint32_t tx_ring_size; + uint32_t rx_ring_size; + uint32_t rq_frag_size; + uint32_t rss_enable; + + uint32_t if_id; /* interface ID */ + uint32_t nifs; /* number of adapter interfaces, 0 or 1 */ + uint32_t pmac_id; /* PMAC id */ + + uint32_t if_cap_flags; + + uint32_t flow_control; + uint32_t promisc; + /*Vlan Filtering related */ + eventhandler_tag vlan_attach; + eventhandler_tag vlan_detach; + uint16_t vlans_added; + uint8_t vlan_tag[MAX_VLANS]; + /*stats */ + OCE_DMA_MEM stats_mem; + struct oce_drv_stats oce_stats_info; + struct callout timer; + int8_t be3_native; + +} OCE_SOFTC, *POCE_SOFTC; + + + +/************************************************** + * BUS memory read/write macros + * BE3: accesses three BAR spaces (CFG, CSR, DB) + * Lancer: accesses one BAR space (CFG) + **************************************************/ +#define OCE_READ_REG32(sc, space, o) \ + ((IS_BE(sc)) ? (bus_space_read_4((sc)->space##_btag, \ + (sc)->space##_bhandle,o)) \ + : (bus_space_read_4((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o))) +#define OCE_READ_REG16(sc, space, o) \ + ((IS_BE(sc)) ? (bus_space_read_2((sc)->space##_btag, \ + (sc)->space##_bhandle,o)) \ + : (bus_space_read_2((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o))) +#define OCE_READ_REG8(sc, space, o) \ + ((IS_BE(sc)) ? (bus_space_read_1((sc)->space##_btag, \ + (sc)->space##_bhandle,o)) \ + : (bus_space_read_1((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o))) + +#define OCE_WRITE_REG32(sc, space, o, v) \ + ((IS_BE(sc)) ? (bus_space_write_4((sc)->space##_btag, \ + (sc)->space##_bhandle,o,v)) \ + : (bus_space_write_4((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o,v))) +#define OCE_WRITE_REG16(sc, space, o, v) \ + ((IS_BE(sc)) ? (bus_space_write_2((sc)->space##_btag, \ + (sc)->space##_bhandle,o,v)) \ + : (bus_space_write_2((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o,v))) +#define OCE_WRITE_REG8(sc, space, o, v) \ + ((IS_BE(sc)) ? (bus_space_write_1((sc)->space##_btag, \ + (sc)->space##_bhandle,o,v)) \ + : (bus_space_write_1((sc)->devcfg_btag, \ + (sc)->devcfg_bhandle,o,v))) + + +/*********************************************************** + * DMA memory functions + ***********************************************************/ +#define oce_dma_sync(d, f) bus_dmamap_sync((d)->tag, (d)->map, f) +int oce_dma_alloc(POCE_SOFTC sc, bus_size_t size, POCE_DMA_MEM dma, int flags); +void oce_dma_free(POCE_SOFTC sc, POCE_DMA_MEM dma); +void oce_dma_map_addr(void *arg, bus_dma_segment_t * segs, int nseg, int error); +void oce_destroy_ring_buffer(POCE_SOFTC sc, oce_ring_buffer_t *ring); +oce_ring_buffer_t *oce_create_ring_buffer(POCE_SOFTC sc, + uint32_t q_len, uint32_t num_entries); +/************************************************************ + * oce_hw_xxx functions + ************************************************************/ +int oce_clear_rx_buf(struct oce_rq *rq); +int oce_hw_pci_alloc(POCE_SOFTC sc); +int oce_hw_init(POCE_SOFTC sc); +int oce_hw_start(POCE_SOFTC sc); +int oce_create_nw_interface(POCE_SOFTC sc); +int oce_pci_soft_reset(POCE_SOFTC sc); +int oce_hw_update_multicast(POCE_SOFTC sc); +void oce_delete_nw_interface(POCE_SOFTC sc); +void oce_hw_shutdown(POCE_SOFTC sc); +void oce_hw_intr_enable(POCE_SOFTC sc); +void oce_hw_intr_disable(POCE_SOFTC sc); +void oce_hw_pci_free(POCE_SOFTC sc); + +/*********************************************************** + * oce_queue_xxx functions + ***********************************************************/ +int oce_queue_init_all(POCE_SOFTC sc); +int oce_start_rq(struct oce_rq *rq); +int oce_start_wq(struct oce_wq *wq); +int oce_start_mq(struct oce_mq *mq); +int oce_start_rx(POCE_SOFTC sc); +void oce_arm_eq(POCE_SOFTC sc, + int16_t qid, int npopped, uint32_t rearm, uint32_t clearint); +void oce_queue_release_all(POCE_SOFTC sc); +void oce_arm_cq(POCE_SOFTC sc, int16_t qid, int npopped, uint32_t rearm); +void oce_drain_eq(struct oce_eq *eq); +void oce_drain_mq_cq(void *arg); +void oce_drain_rq_cq(struct oce_rq *rq); +void oce_drain_wq_cq(struct oce_wq *wq); + +uint32_t oce_page_list(oce_ring_buffer_t *ring, struct phys_addr *pa_list); + +/*********************************************************** + * cleanup functions + ***********************************************************/ +void oce_free_lro(POCE_SOFTC sc); +void oce_stop_rx(POCE_SOFTC sc); +void oce_intr_free(POCE_SOFTC sc); +void oce_free_posted_rxbuf(struct oce_rq *rq); + + +/************************************************************ + * Mailbox functions + ************************************************************/ +int oce_fw_clean(POCE_SOFTC sc); +int oce_reset_fun(POCE_SOFTC sc); +int oce_mbox_init(POCE_SOFTC sc); +int oce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec); +int oce_get_fw_version(POCE_SOFTC sc); +int oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id, uint8_t perm, + uint8_t type, struct mac_address_format *mac); +int oce_get_fw_config(POCE_SOFTC sc); +int oce_if_create(POCE_SOFTC sc, uint32_t cap_flags, uint32_t en_flags, + uint16_t vlan_tag, uint8_t *mac_addr, uint32_t *if_id); +int oce_if_del(POCE_SOFTC sc, uint32_t if_id); +int oce_config_vlan(POCE_SOFTC sc, uint32_t if_id, + struct normal_vlan *vtag_arr, uint8_t vtag_cnt, + uint32_t untagged, uint32_t enable_promisc); +int oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control); +int oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss); +int oce_rxf_set_promiscuous(POCE_SOFTC sc, uint32_t enable); +int oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl); +int oce_get_link_status(POCE_SOFTC sc, struct link_status *link); +int oce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem); +int oce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem); +int oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, + uint32_t reset_stats); +int oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, + uint32_t req_size, uint32_t reset_stats); +int oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem); +int oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size); +int oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id); +int oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr, + uint32_t if_id, uint32_t *pmac_id); +int oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num, + uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts, + uint64_t pattern); + +int oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num, + uint8_t loopback_type, uint8_t enable); + +int oce_mbox_check_native_mode(POCE_SOFTC sc); +int oce_mbox_post(POCE_SOFTC sc, + struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx); +int oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode, + POCE_DMA_MEM pdma_mem, uint32_t num_bytes); +int oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size, + uint32_t data_offset,POCE_DMA_MEM pdma_mem, + uint32_t *written_data, uint32_t *additional_status); + +int oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc, + uint32_t offset, uint32_t optype); +int oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info); +int oce_mbox_create_rq(struct oce_rq *rq); +int oce_mbox_create_wq(struct oce_wq *wq); +int oce_mbox_create_eq(struct oce_eq *eq); +int oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, + uint32_t is_eventable); +void mbx_common_req_hdr_init(struct mbx_hdr *hdr, + uint8_t dom, + uint8_t port, + uint8_t subsys, + uint8_t opcode, + uint32_t timeout, uint32_t pyld_len, + uint8_t version); + + +uint16_t oce_mq_handler(void *arg); + +/************************************************************ + * Transmit functions + ************************************************************/ +uint16_t oce_wq_handler(void *arg); +void oce_start(struct ifnet *ifp); +void oce_tx_task(void *arg, int npending); + +/************************************************************ + * Receive functions + ************************************************************/ +int oce_alloc_rx_bufs(struct oce_rq *rq, int count); +uint16_t oce_rq_handler(void *arg); + + +/* Sysctl functions */ +void oce_add_sysctls(POCE_SOFTC sc); +void oce_refresh_queue_stats(POCE_SOFTC sc); +int oce_refresh_nic_stats(POCE_SOFTC sc); +int oce_stats_init(POCE_SOFTC sc); +void oce_stats_free(POCE_SOFTC sc); + +/* Capabilities */ +#define OCE_MODCAP_RSS 1 +#define OCE_MAX_RSP_HANDLED 64 +extern uint32_t oce_max_rsp_handled; /* max responses */ + +#define OCE_MAC_LOOPBACK 0x0 +#define OCE_PHY_LOOPBACK 0x1 +#define OCE_ONE_PORT_EXT_LOOPBACK 0x2 +#define OCE_NO_LOOPBACK 0xff + +#define atomic_inc_32(x) atomic_add_32(x, 1) +#define atomic_dec_32(x) atomic_subtract_32(x, 1) + +#define LE_64(x) htole64(x) +#define LE_32(x) htole32(x) +#define LE_16(x) htole16(x) +#define DW_SWAP(x, l) +#define IS_ALIGNED(x,a) ((x % a) == 0) +#define ADDR_HI(x) ((uint32_t)((uint64_t)(x) >> 32)) +#define ADDR_LO(x) ((uint32_t)((uint64_t)(x) & 0xffffffff)); + +#define IF_LRO_ENABLED(sc) (((sc)->ifp->if_capenable & IFCAP_LRO) ? 1:0) +#define IF_LSO_ENABLED(sc) (((sc)->ifp->if_capenable & IFCAP_TSO4) ? 1:0) +#define IF_CSUM_ENABLED(sc) (((sc)->ifp->if_capenable & IFCAP_HWCSUM) ? 1:0) + +#define OCE_LOG2(x) (oce_highbit(x)) +static inline uint32_t oce_highbit(uint32_t x) +{ + int i; + int c; + int b; + + c = 0; + b = 0; + + for (i = 0; i < 32; i++) { + if ((1 << i) & x) { + c++; + b = i; + } + } + + if (c == 1) + return b; + + return 0; +} + diff --git a/sys/dev/oce/oce_mbox.c b/sys/dev/oce/oce_mbox.c new file mode 100644 index 000000000000..7ca3d41fa2ef --- /dev/null +++ b/sys/dev/oce/oce_mbox.c @@ -0,0 +1,1705 @@ +/*- + * Copyright (C) 2012 Emulex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Emulex Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact Information: + * freebsd-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + + + +/* $FreeBSD$ */ + + +#include "oce_if.h" + + +/** + * @brief Reset (firmware) common function + * @param sc software handle to the device + * @returns 0 on success, ETIMEDOUT on failure + */ +int +oce_reset_fun(POCE_SOFTC sc) +{ + struct oce_mbx *mbx; + struct oce_bmbx *mb; + struct ioctl_common_function_reset *fwcmd; + int rc = 0; + + if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) { + mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx); + mbx = &mb->mbx; + bzero(mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct ioctl_common_function_reset *)&mbx->payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_FUNCTION_RESET, + 10, /* MBX_TIMEOUT_SEC */ + sizeof(struct + ioctl_common_function_reset), + OCE_MBX_VER_V0); + + mbx->u0.s.embedded = 1; + mbx->payload_length = + sizeof(struct ioctl_common_function_reset); + + rc = oce_mbox_dispatch(sc, 2); + } + + return rc; +} + + +/** + * @brief This funtions tells firmware we are + * done with commands. + * @param sc software handle to the device + * @returns 0 on success, ETIMEDOUT on failure + */ +int +oce_fw_clean(POCE_SOFTC sc) +{ + struct oce_bmbx *mbx; + uint8_t *ptr; + int ret = 0; + + mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx); + ptr = (uint8_t *) &mbx->mbx; + + /* Endian Signature */ + *ptr++ = 0xff; + *ptr++ = 0xaa; + *ptr++ = 0xbb; + *ptr++ = 0xff; + *ptr++ = 0xff; + *ptr++ = 0xcc; + *ptr++ = 0xdd; + *ptr = 0xff; + + ret = oce_mbox_dispatch(sc, 2); + + return ret; +} + + +/** + * @brief Mailbox wait + * @param sc software handle to the device + * @param tmo_sec timeout in seconds + */ +static int +oce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec) +{ + tmo_sec *= 10000; + pd_mpu_mbox_db_t mbox_db; + + for (;;) { + if (tmo_sec != 0) { + if (--tmo_sec == 0) + break; + } + + mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB); + + if (mbox_db.bits.ready) + return 0; + + DELAY(100); + } + + device_printf(sc->dev, "Mailbox timed out\n"); + + return ETIMEDOUT; +} + + + +/** + * @brief Mailbox dispatch + * @param sc software handle to the device + * @param tmo_sec timeout in seconds + */ +int +oce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec) +{ + pd_mpu_mbox_db_t mbox_db; + uint32_t pa; + int rc; + + oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE); + pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34); + bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t)); + mbox_db.bits.ready = 0; + mbox_db.bits.hi = 1; + mbox_db.bits.address = pa; + + rc = oce_mbox_wait(sc, tmo_sec); + if (rc == 0) { + OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0); + + pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff; + mbox_db.bits.ready = 0; + mbox_db.bits.hi = 0; + mbox_db.bits.address = pa; + + rc = oce_mbox_wait(sc, tmo_sec); + + if (rc == 0) { + OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0); + + rc = oce_mbox_wait(sc, tmo_sec); + + oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE); + } + } + + return rc; +} + + + +/** + * @brief Mailbox common request header initialization + * @param hdr mailbox header + * @param dom domain + * @param port port + * @param subsys subsystem + * @param opcode opcode + * @param timeout timeout + * @param pyld_len payload length + */ +void +mbx_common_req_hdr_init(struct mbx_hdr *hdr, + uint8_t dom, uint8_t port, + uint8_t subsys, uint8_t opcode, + uint32_t timeout, uint32_t pyld_len, + uint8_t version) +{ + hdr->u0.req.opcode = opcode; + hdr->u0.req.subsystem = subsys; + hdr->u0.req.port_number = port; + hdr->u0.req.domain = dom; + + hdr->u0.req.timeout = timeout; + hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr); + hdr->u0.req.version = version; +} + + + +/** + * @brief Function to initialize the hw with host endian information + * @param sc software handle to the device + * @returns 0 on success, ETIMEDOUT on failure + */ +int +oce_mbox_init(POCE_SOFTC sc) +{ + struct oce_bmbx *mbx; + uint8_t *ptr; + int ret = 0; + + if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) { + mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx); + ptr = (uint8_t *) &mbx->mbx; + + /* Endian Signature */ + *ptr++ = 0xff; + *ptr++ = 0x12; + *ptr++ = 0x34; + *ptr++ = 0xff; + *ptr++ = 0xff; + *ptr++ = 0x56; + *ptr++ = 0x78; + *ptr = 0xff; + + ret = oce_mbox_dispatch(sc, 0); + } + + return ret; +} + + +/** + * @brief Function to get the firmware version + * @param sc software handle to the device + * @returns 0 on success, EIO on failure + */ +int +oce_get_fw_version(POCE_SOFTC sc) +{ + struct oce_mbx mbx; + struct mbx_get_common_fw_version *fwcmd; + int ret = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FW_VERSION, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_get_common_fw_version), + OCE_MBX_VER_V0); + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_get_common_fw_version); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + ret = oce_mbox_post(sc, &mbx, NULL); + if (ret) + return ret; + + bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32); + + return 0; +} + + +/** + * @brief Function to post a MBX to the mbox + * @param sc software handle to the device + * @param mbx pointer to the MBX to send + * @param mbxctx pointer to the mbx context structure + * @returns 0 on success, error on failure + */ +int +oce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx) +{ + struct oce_mbx *mb_mbx = NULL; + struct oce_mq_cqe *mb_cqe = NULL; + struct oce_bmbx *mb = NULL; + int rc = 0; + uint32_t tmo = 0; + uint32_t cstatus = 0; + uint32_t xstatus = 0; + + LOCK(&sc->bmbx_lock); + + mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx); + mb_mbx = &mb->mbx; + + /* get the tmo */ + tmo = mbx->tag[0]; + mbx->tag[0] = 0; + + /* copy mbx into mbox */ + bcopy(mbx, mb_mbx, sizeof(struct oce_mbx)); + + /* now dispatch */ + rc = oce_mbox_dispatch(sc, tmo); + if (rc == 0) { + /* + * the command completed successfully. Now get the + * completion queue entry + */ + mb_cqe = &mb->cqe; + DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe)); + + /* copy mbox mbx back */ + bcopy(mb_mbx, mbx, sizeof(struct oce_mbx)); + + /* pick up the mailbox status */ + cstatus = mb_cqe->u0.s.completion_status; + xstatus = mb_cqe->u0.s.extended_status; + + /* + * store the mbx context in the cqe tag section so that + * the upper layer handling the cqe can associate the mbx + * with the response + */ + if (cstatus == 0 && mbxctx) { + /* save context */ + mbxctx->mbx = mb_mbx; + bcopy(&mbxctx, mb_cqe->u0.s.mq_tag, + sizeof(struct oce_mbx_ctx *)); + } + } + + UNLOCK(&sc->bmbx_lock); + + return rc; +} + +/** + * @brief Function to read the mac address associated with an interface + * @param sc software handle to the device + * @param if_id interface id to read the address from + * @param perm set to 1 if reading the factory mac address. + * In this case if_id is ignored + * @param type type of the mac address, whether network or storage + * @param[out] mac [OUTPUT] pointer to a buffer containing the + * mac address when the command succeeds. + * @returns 0 on success, EIO on failure + */ +int +oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id, + uint8_t perm, uint8_t type, struct mac_address_format *mac) +{ + struct oce_mbx mbx; + struct mbx_query_common_iface_mac *fwcmd; + int ret = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_QUERY_IFACE_MAC, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_query_common_iface_mac), + OCE_MBX_VER_V0); + + fwcmd->params.req.permanent = perm; + if (!perm) + fwcmd->params.req.if_id = (uint16_t) if_id; + else + fwcmd->params.req.if_id = 0; + + fwcmd->params.req.type = type; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_query_common_iface_mac); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + ret = oce_mbox_post(sc, &mbx, NULL); + if (ret) + return ret; + + /* copy the mac addres in the output parameter */ + mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct; + bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0], + mac->size_of_struct); + + return 0; +} + +/** + * @brief Function to query the fw attributes from the hw + * @param sc software handle to the device + * @returns 0 on success, EIO on failure + */ +int +oce_get_fw_config(POCE_SOFTC sc) +{ + struct oce_mbx mbx; + struct mbx_common_query_fw_config *fwcmd; + int ret = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_common_query_fw_config), + OCE_MBX_VER_V0); + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_common_query_fw_config); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + ret = oce_mbox_post(sc, &mbx, NULL); + if (ret) + return ret; + + DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config)); + + sc->config_number = fwcmd->params.rsp.config_number; + sc->asic_revision = fwcmd->params.rsp.asic_revision; + sc->port_id = fwcmd->params.rsp.port_id; + sc->function_mode = fwcmd->params.rsp.function_mode; + sc->function_caps = fwcmd->params.rsp.function_caps; + + if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) { + sc->max_tx_rings = fwcmd->params.rsp.ulp[0].nic_wq_tot; + sc->max_rx_rings = fwcmd->params.rsp.ulp[0].lro_rqid_tot; + } else { + sc->max_tx_rings = fwcmd->params.rsp.ulp[1].nic_wq_tot; + sc->max_rx_rings = fwcmd->params.rsp.ulp[1].lro_rqid_tot; + } + + return 0; + +} + +/** + * + * @brief function to create a device interface + * @param sc software handle to the device + * @param cap_flags capability flags + * @param en_flags enable capability flags + * @param vlan_tag optional vlan tag to associate with the if + * @param mac_addr pointer to a buffer containing the mac address + * @param[out] if_id [OUTPUT] pointer to an integer to hold the ID of the + interface created + * @returns 0 on success, EIO on failure + */ +int +oce_if_create(POCE_SOFTC sc, + uint32_t cap_flags, + uint32_t en_flags, + uint16_t vlan_tag, + uint8_t *mac_addr, + uint32_t *if_id) +{ + struct oce_mbx mbx; + struct mbx_create_common_iface *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_create_common_iface *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_CREATE_IFACE, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_create_common_iface), + OCE_MBX_VER_V0); + DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr)); + + fwcmd->params.req.version = 0; + fwcmd->params.req.cap_flags = LE_32(cap_flags); + fwcmd->params.req.enable_flags = LE_32(en_flags); + if (mac_addr != NULL) { + bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6); + fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag); + fwcmd->params.req.mac_invalid = 0; + } else { + fwcmd->params.req.mac_invalid = 1; + } + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_create_common_iface); + DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) + return rc; + + *if_id = LE_32(fwcmd->params.rsp.if_id); + + if (mac_addr != NULL) + sc->pmac_id = LE_32(fwcmd->params.rsp.pmac_id); + + return 0; +} + +/** + * @brief Function to delete an interface + * @param sc software handle to the device + * @param if_id ID of the interface to delete + * @returns 0 on success, EIO on failure + */ +int +oce_if_del(POCE_SOFTC sc, uint32_t if_id) +{ + struct oce_mbx mbx; + struct mbx_destroy_common_iface *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_DESTROY_IFACE, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_destroy_common_iface), + OCE_MBX_VER_V0); + + fwcmd->params.req.if_id = if_id; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_destroy_common_iface); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + return rc; +} + +/** + * @brief Function to send the mbx command to configure vlan + * @param sc software handle to the device + * @param if_id interface identifier index + * @param vtag_arr array of vlan tags + * @param vtag_cnt number of elements in array + * @param untagged boolean TRUE/FLASE + * @param enable_promisc flag to enable/disable VLAN promiscuous mode + * @returns 0 on success, EIO on failure + */ +int +oce_config_vlan(POCE_SOFTC sc, + uint32_t if_id, + struct normal_vlan *vtag_arr, + uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc) +{ + struct oce_mbx mbx; + struct mbx_common_config_vlan *fwcmd; + int rc; + + bzero(&mbx, sizeof(struct oce_mbx)); + fwcmd = (struct mbx_common_config_vlan *)&mbx.payload; + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_CONFIG_IFACE_VLAN, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_common_config_vlan), + OCE_MBX_VER_V0); + + fwcmd->params.req.if_id = (uint8_t) if_id; + fwcmd->params.req.promisc = (uint8_t) enable_promisc; + fwcmd->params.req.untagged = (uint8_t) untagged; + fwcmd->params.req.num_vlans = vtag_cnt; + + if (!enable_promisc) { + bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans, + vtag_cnt * sizeof(struct normal_vlan)); + } + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_common_config_vlan); + DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length)); + + rc = oce_mbox_post(sc, &mbx, NULL); + + return rc; + +} + +/** + * @brief Function to set flow control capability in the hardware + * @param sc software handle to the device + * @param flow_control flow control flags to set + * @returns 0 on success, EIO on failure + */ +int +oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control) +{ + struct oce_mbx mbx; + struct mbx_common_get_set_flow_control *fwcmd = + (struct mbx_common_get_set_flow_control *)&mbx.payload; + int rc; + + bzero(&mbx, sizeof(struct oce_mbx)); + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_FLOW_CONTROL, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_common_get_set_flow_control), + OCE_MBX_VER_V0); + + if (flow_control & OCE_FC_TX) + fwcmd->tx_flow_control = 1; + + if (flow_control & OCE_FC_RX) + fwcmd->rx_flow_control = 1; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + + return rc; +} + +/** + * @brief Initialize the RSS CPU indirection table + * + * The table is used to choose the queue to place the incomming packets. + * Incomming packets are hashed. The lowest bits in the hash result + * are used as the index into the CPU indirection table. + * Each entry in the table contains the RSS CPU-ID returned by the NIC + * create. Based on the CPU ID, the receive completion is routed to + * the corresponding RSS CQs. (Non-RSS packets are always completed + * on the default (0) CQ). + * + * @param sc software handle to the device + * @param *fwcmd pointer to the rss mbox command + * @returns none + */ +static int +oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd) +{ + int i = 0, j = 0, rc = 0; + uint8_t *tbl = fwcmd->params.req.cputable; + + + for (j = 0; j < sc->nrqs; j++) { + if (sc->rq[j]->cfg.is_rss_queue) { + tbl[i] = sc->rq[j]->rss_cpuid; + i = i + 1; + } + } + if (i == 0) { + device_printf(sc->dev, "error: Invalid number of RSS RQ's\n"); + rc = ENXIO; + + } + + /* fill log2 value indicating the size of the CPU table */ + if (rc == 0) + fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(i)); + + return rc; +} + +/** + * @brief Function to set flow control capability in the hardware + * @param sc software handle to the device + * @param if_id interface id to read the address from + * @param enable_rss 0=disable, RSS_ENABLE_xxx flags otherwise + * @returns 0 on success, EIO on failure + */ +int +oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss) +{ + int rc; + struct oce_mbx mbx; + struct mbx_config_nic_rss *fwcmd = + (struct mbx_config_nic_rss *)&mbx.payload; + + bzero(&mbx, sizeof(struct oce_mbx)); + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_NIC, + NIC_CONFIG_RSS, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_config_nic_rss), + OCE_MBX_VER_V0); + if (enable_rss) + fwcmd->params.req.enable_rss = (RSS_ENABLE_IPV4 | + RSS_ENABLE_TCP_IPV4 | + RSS_ENABLE_IPV6 | + RSS_ENABLE_TCP_IPV6); + fwcmd->params.req.flush = OCE_FLUSH; + fwcmd->params.req.if_id = LE_32(if_id); + + srandom(arc4random()); /* random entropy seed */ + read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash)); + + rc = oce_rss_itbl_init(sc, fwcmd); + if (rc == 0) { + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_config_nic_rss); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + + } + + return rc; +} + +/** + * @brief RXF function to enable/disable device promiscuous mode + * @param sc software handle to the device + * @param enable enable/disable flag + * @returns 0 on success, EIO on failure + * @note + * The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer. + * This function uses the COMMON_SET_IFACE_RX_FILTER command instead. + */ +int +oce_rxf_set_promiscuous(POCE_SOFTC sc, uint32_t enable) +{ + struct mbx_set_common_iface_rx_filter *fwcmd; + int sz = sizeof(struct mbx_set_common_iface_rx_filter); + iface_rx_filter_ctx_t *req; + OCE_DMA_MEM sgl; + int rc; + + /* allocate mbx payload's dma scatter/gather memory */ + rc = oce_dma_alloc(sc, sz, &sgl, 0); + if (rc) + return rc; + + fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter); + + req = &fwcmd->params.req; + req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS | + MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS; + if (enable) { + req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS | + MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS; + } + req->if_id = sc->if_id; + + rc = oce_set_common_iface_rx_filter(sc, &sgl); + oce_dma_free(sc, &sgl); + + return rc; +} + + +/** + * @brief Function modify and select rx filter options + * @param sc software handle to the device + * @param sgl scatter/gather request/response + * @returns 0 on success, error code on failure + */ +int +oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl) +{ + struct oce_mbx mbx; + int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter); + struct mbx_set_common_iface_rx_filter *fwcmd; + int rc; + + bzero(&mbx, sizeof(struct oce_mbx)); + fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter); + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_IFACE_RX_FILTER, + MBX_TIMEOUT_SEC, + mbx_sz, + OCE_MBX_VER_V0); + + oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE); + mbx.u0.s.embedded = 0; + mbx.u0.s.sge_count = 1; + mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr); + mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr); + mbx.payload.u0.u1.sgl[0].length = mbx_sz; + mbx.payload_length = mbx_sz; + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + return rc; +} + +/** + * @brief Function to query the link status from the hardware + * @param sc software handle to the device + * @param[out] link pointer to the structure returning link attributes + * @returns 0 on success, EIO on failure + */ +int +oce_get_link_status(POCE_SOFTC sc, struct link_status *link) +{ + struct oce_mbx mbx; + struct mbx_query_common_link_config *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_query_common_link_config *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_QUERY_LINK_CONFIG, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_query_common_link_config), + OCE_MBX_VER_V0); + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_query_common_link_config); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + + if (rc) { + device_printf(sc->dev, "Could not get link speed: %d\n", rc); + } else { + /* interpret response */ + bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status)); + link->logical_link_status = LE_32(link->logical_link_status); + link->qos_link_speed = LE_16(link->qos_link_speed); + } + + return rc; +} + + + +int +oce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem) +{ + struct oce_mbx mbx; + struct mbx_get_nic_stats_v0 *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v0); + bzero(fwcmd, sizeof(struct mbx_get_nic_stats_v0)); + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_NIC, + NIC_GET_STATS, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_get_nic_stats_v0), + OCE_MBX_VER_V0); + + mbx.u0.s.embedded = 0; + mbx.u0.s.sge_count = 1; + + oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); + + mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr); + mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); + mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats_v0); + + mbx.payload_length = sizeof(struct mbx_get_nic_stats_v0); + + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + + oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); + + if (rc) { + device_printf(sc->dev, + "Could not get nic statistics: %d\n", rc); + } + + return rc; +} + + + +/** + * @brief Function to get NIC statistics + * @param sc software handle to the device + * @param *stats pointer to where to store statistics + * @param reset_stats resets statistics of set + * @returns 0 on success, EIO on failure + * @note command depricated in Lancer + */ +int +oce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem) +{ + struct oce_mbx mbx; + struct mbx_get_nic_stats *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats); + bzero(fwcmd, sizeof(struct mbx_get_nic_stats)); + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_NIC, + NIC_GET_STATS, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_get_nic_stats), + OCE_MBX_VER_V1); + + + mbx.u0.s.embedded = 0; /* stats too large for embedded mbx rsp */ + mbx.u0.s.sge_count = 1; /* using scatter gather instead */ + + oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); + mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr); + mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); + mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats); + + mbx.payload_length = sizeof(struct mbx_get_nic_stats); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); + if (rc) { + device_printf(sc->dev, + "Could not get nic statistics: %d\n", rc); + } + return rc; +} + + +/** + * @brief Function to get pport (physical port) statistics + * @param sc software handle to the device + * @param *stats pointer to where to store statistics + * @param reset_stats resets statistics of set + * @returns 0 on success, EIO on failure + */ +int +oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, + uint32_t reset_stats) +{ + struct oce_mbx mbx; + struct mbx_get_pport_stats *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats); + bzero(fwcmd, sizeof(struct mbx_get_pport_stats)); + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_NIC, + NIC_GET_PPORT_STATS, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_get_pport_stats), + OCE_MBX_VER_V0); + + fwcmd->params.req.reset_stats = reset_stats; + fwcmd->params.req.port_number = sc->if_id; + + mbx.u0.s.embedded = 0; /* stats too large for embedded mbx rsp */ + mbx.u0.s.sge_count = 1; /* using scatter gather instead */ + + oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); + mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr); + mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); + mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats); + + mbx.payload_length = sizeof(struct mbx_get_pport_stats); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); + + if (rc != 0) { + device_printf(sc->dev, + "Could not get physical port statistics: %d\n", rc); + } + + return rc; +} + + +/** + * @brief Function to get vport (virtual port) statistics + * @param sc software handle to the device + * @param *stats pointer to where to store statistics + * @param reset_stats resets statistics of set + * @returns 0 on success, EIO on failure + */ +int +oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem, + uint32_t req_size, uint32_t reset_stats) +{ + struct oce_mbx mbx; + struct mbx_get_vport_stats *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats); + bzero(fwcmd, sizeof(struct mbx_get_vport_stats)); + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_NIC, + NIC_GET_VPORT_STATS, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_get_vport_stats), + OCE_MBX_VER_V0); + + fwcmd->params.req.reset_stats = reset_stats; + fwcmd->params.req.vport_number = sc->if_id; + + mbx.u0.s.embedded = 0; /* stats too large for embedded mbx rsp */ + mbx.u0.s.sge_count = 1; /* using scatter gather instead */ + + oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); + mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr); + mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); + mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats); + + mbx.payload_length = sizeof(struct mbx_get_vport_stats); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); + + if (rc != 0) { + device_printf(sc->dev, + "Could not get physical port statistics: %d\n", rc); + } + + return rc; +} + + +/** + * @brief Function to update the muticast filter with + * values in dma_mem + * @param sc software handle to the device + * @param dma_mem pointer to dma memory region + * @returns 0 on success, EIO on failure + */ +int +oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem) +{ + struct oce_mbx mbx; + struct oce_mq_sge *sgl; + struct mbx_set_common_iface_multicast *req = NULL; + int rc = 0; + + req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast); + mbx_common_req_hdr_init(&req->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_IFACE_MULTICAST, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_set_common_iface_multicast), + OCE_MBX_VER_V0); + + bzero(&mbx, sizeof(struct oce_mbx)); + + mbx.u0.s.embedded = 0; /*Non embeded*/ + mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast); + mbx.u0.s.sge_count = 1; + sgl = &mbx.payload.u0.u1.sgl[0]; + sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr)); + sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF); + sgl->length = htole32(mbx.payload_length); + + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + + return rc; +} + + +/** + * @brief Function to send passthrough Ioctls + * @param sc software handle to the device + * @param dma_mem pointer to dma memory region + * @param req_size size of dma_mem + * @returns 0 on success, EIO on failure + */ +int +oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size) +{ + struct oce_mbx mbx; + struct oce_mq_sge *sgl; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + mbx.u0.s.embedded = 0; /*Non embeded*/ + mbx.payload_length = req_size; + mbx.u0.s.sge_count = 1; + sgl = &mbx.payload.u0.u1.sgl[0]; + sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr)); + sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF); + sgl->length = htole32(req_size); + + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + return rc; +} + + +int +oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr, + uint32_t if_id, uint32_t *pmac_id) +{ + struct oce_mbx mbx; + struct mbx_add_common_iface_mac *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_ADD_IFACE_MAC, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_add_common_iface_mac), + OCE_MBX_VER_V0); + + fwcmd->params.req.if_id = (uint16_t) if_id; + bcopy(mac_addr, fwcmd->params.req.mac_address, 6); + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_add_common_iface_mac); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) + return rc; + + *pmac_id = fwcmd->params.rsp.pmac_id; + + return rc; +} + + +int +oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id) +{ + struct oce_mbx mbx; + struct mbx_del_common_iface_mac *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_DEL_IFACE_MAC, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_del_common_iface_mac), + OCE_MBX_VER_V0); + + fwcmd->params.req.if_id = (uint16_t)if_id; + fwcmd->params.req.pmac_id = pmac_id; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_del_common_iface_mac); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + return rc; +} + + + +int +oce_mbox_check_native_mode(POCE_SOFTC sc) +{ + struct oce_mbx mbx; + struct mbx_common_set_function_cap *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_FUNCTIONAL_CAPS, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_common_set_function_cap), + OCE_MBX_VER_V0); + + fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS | + CAP_BE3_NATIVE_ERX_API; + + fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_common_set_function_cap); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + //if (rc != 0) This can fail in legacy mode. So skip + // FN_LEAVE(rc); + + sc->be3_native = fwcmd->params.rsp.capability_flags + & CAP_BE3_NATIVE_ERX_API; + + return 0; +} + + + +int +oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num, + uint8_t loopback_type, uint8_t enable) +{ + struct oce_mbx mbx; + struct mbx_lowlevel_set_loopback_mode *fwcmd; + int rc = 0; + + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_LOWLEVEL, + OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_lowlevel_set_loopback_mode), + OCE_MBX_VER_V0); + + fwcmd->params.req.src_port = port_num; + fwcmd->params.req.dest_port = port_num; + fwcmd->params.req.loopback_type = loopback_type; + fwcmd->params.req.loopback_state = enable; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_lowlevel_set_loopback_mode); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + + return rc; + +} + +int +oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num, + uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts, + uint64_t pattern) +{ + + struct oce_mbx mbx; + struct mbx_lowlevel_test_loopback_mode *fwcmd; + int rc = 0; + + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_LOWLEVEL, + OPCODE_LOWLEVEL_TEST_LOOPBACK, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_lowlevel_test_loopback_mode), + OCE_MBX_VER_V0); + + fwcmd->params.req.pattern = pattern; + fwcmd->params.req.src_port = port_num; + fwcmd->params.req.dest_port = port_num; + fwcmd->params.req.pkt_size = pkt_size; + fwcmd->params.req.num_pkts = num_pkts; + fwcmd->params.req.loopback_type = loopback_type; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_lowlevel_test_loopback_mode); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) + return rc; + + return(fwcmd->params.rsp.status); +} + +int +oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode, + POCE_DMA_MEM pdma_mem, uint32_t num_bytes) +{ + + struct oce_mbx mbx; + struct oce_mq_sge *sgl = NULL; + struct mbx_common_read_write_flashrom *fwcmd = NULL; + int rc = 0, payload_len = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom); + payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024; + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_WRITE_FLASHROM, + LONG_TIMEOUT, + payload_len, + OCE_MBX_VER_V0); + + fwcmd->flash_op_type = optype; + fwcmd->flash_op_code = opcode; + fwcmd->data_buffer_size = num_bytes; + + mbx.u0.s.embedded = 0; /*Non embeded*/ + mbx.payload_length = payload_len; + mbx.u0.s.sge_count = 1; + + sgl = &mbx.payload.u0.u1.sgl[0]; + sgl->pa_hi = upper_32_bits(pdma_mem->paddr); + sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF; + sgl->length = payload_len; + + /* post the command */ + if (rc) { + device_printf(sc->dev, "Write FlashROM mbox post failed\n"); + } else { + rc = fwcmd->hdr.u0.rsp.status; + } + + return rc; + +} + +int +oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc, + uint32_t offset, uint32_t optype) +{ + + int rc = 0, payload_len = 0; + struct oce_mbx mbx; + struct mbx_common_read_write_flashrom *fwcmd; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload; + + /* Firmware requires extra 4 bytes with this ioctl. Since there + is enough room in the mbx payload it should be good enough + Reference: Bug 14853 + */ + payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4; + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_READ_FLASHROM, + MBX_TIMEOUT_SEC, + payload_len, + OCE_MBX_VER_V0); + + fwcmd->flash_op_type = optype; + fwcmd->flash_op_code = FLASHROM_OPER_REPORT; + fwcmd->data_offset = offset; + fwcmd->data_buffer_size = 0x4; + + mbx.u0.s.embedded = 1; + mbx.payload_length = payload_len; + + /* post the command */ + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) { + device_printf(sc->dev, "Read FlashROM CRC mbox post failed\n"); + } else { + bcopy(fwcmd->data_buffer, flash_crc, 4); + rc = fwcmd->hdr.u0.rsp.status; + } + return rc; +} + +int +oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info) +{ + + struct oce_mbx mbx; + struct mbx_common_phy_info *fwcmd; + int rc = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_common_phy_info *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_PHY_CONFIG, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_common_phy_info), + OCE_MBX_VER_V0); + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_common_phy_info); + + /* now post the command */ + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) { + device_printf(sc->dev, "Read PHY info mbox post failed\n"); + } else { + rc = fwcmd->hdr.u0.rsp.status; + phy_info->phy_type = fwcmd->params.rsp.phy_info.phy_type; + phy_info->interface_type = + fwcmd->params.rsp.phy_info.interface_type; + phy_info->auto_speeds_supported = + fwcmd->params.rsp.phy_info.auto_speeds_supported; + phy_info->fixed_speeds_supported = + fwcmd->params.rsp.phy_info.fixed_speeds_supported; + phy_info->misc_params =fwcmd->params.rsp.phy_info.misc_params; + + } + return rc; + +} + + +int +oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size, + uint32_t data_offset, POCE_DMA_MEM pdma_mem, + uint32_t *written_data, uint32_t *additional_status) +{ + + struct oce_mbx mbx; + struct mbx_lancer_common_write_object *fwcmd = NULL; + int rc = 0, payload_len = 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + payload_len = sizeof(struct mbx_lancer_common_write_object); + + mbx.u0.s.embedded = 1;/* Embedded */ + mbx.payload_length = payload_len; + fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload; + + /* initialize the ioctl header */ + mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_WRITE_OBJECT, + LONG_TIMEOUT, + payload_len, + OCE_MBX_VER_V0); + + fwcmd->params.req.write_length = data_size; + if (data_size == 0) + fwcmd->params.req.eof = 1; + else + fwcmd->params.req.eof = 0; + + strcpy(fwcmd->params.req.object_name, "/prg"); + fwcmd->params.req.descriptor_count = 1; + fwcmd->params.req.write_offset = data_offset; + fwcmd->params.req.buffer_length = data_size; + fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF; + fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr); + + /* post the command */ + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) { + device_printf(sc->dev, + "Write Lancer FlashROM mbox post failed\n"); + } else { + *written_data = fwcmd->params.rsp.actual_write_length; + *additional_status = fwcmd->params.rsp.additional_status; + rc = fwcmd->params.rsp.status; + } + return rc; + +} + + + +int +oce_mbox_create_rq(struct oce_rq *rq) +{ + + struct oce_mbx mbx; + struct mbx_create_nic_rq *fwcmd; + POCE_SOFTC sc = rq->parent; + int rc, num_pages = 0; + + if (rq->qstate == QCREATED) + return 0; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_create_nic_rq *)&mbx.payload; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_NIC, + NIC_CREATE_RQ, MBX_TIMEOUT_SEC, + sizeof(struct mbx_create_nic_rq), + OCE_MBX_VER_V0); + + /* oce_page_list will also prepare pages */ + num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]); + + if (IS_XE201(sc)) { + fwcmd->params.req.frag_size = rq->cfg.frag_size/2048; + fwcmd->params.req.page_size = 1; + fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1; + } else + fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size); + fwcmd->params.req.num_pages = num_pages; + fwcmd->params.req.cq_id = rq->cq->cq_id; + fwcmd->params.req.if_id = sc->if_id; + fwcmd->params.req.max_frame_size = rq->cfg.mtu; + fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_create_nic_rq); + + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) + goto error; + + rq->rq_id = fwcmd->params.rsp.rq_id; + rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid; + + return 0; +error: + device_printf(sc->dev, "Mbox Create RQ failed\n"); + return rc; + +} + + + +int +oce_mbox_create_wq(struct oce_wq *wq) +{ + struct oce_mbx mbx; + struct mbx_create_nic_wq *fwcmd; + POCE_SOFTC sc = wq->parent; + int rc = 0, version, num_pages; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_create_nic_wq *)&mbx.payload; + if (IS_XE201(sc)) { + version = OCE_MBX_VER_V1; + fwcmd->params.req.if_id = sc->if_id; + } else + version = OCE_MBX_VER_V0; + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_NIC, + NIC_CREATE_WQ, MBX_TIMEOUT_SEC, + sizeof(struct mbx_create_nic_wq), + version); + + num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]); + + fwcmd->params.req.nic_wq_type = wq->cfg.wq_type; + fwcmd->params.req.num_pages = num_pages; + fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1; + fwcmd->params.req.cq_id = wq->cq->cq_id; + fwcmd->params.req.ulp_num = 1; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_create_nic_wq); + + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) + goto error; + + wq->wq_id = LE_16(fwcmd->params.rsp.wq_id); + + return 0; +error: + device_printf(sc->dev, "Mbox Create WQ failed\n"); + return rc; + +} + + + +int +oce_mbox_create_eq(struct oce_eq *eq) +{ + struct oce_mbx mbx; + struct mbx_create_common_eq *fwcmd; + POCE_SOFTC sc = eq->parent; + int rc = 0; + uint32_t num_pages; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_create_common_eq *)&mbx.payload; + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC, + sizeof(struct mbx_create_common_eq), + OCE_MBX_VER_V0); + + num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]); + fwcmd->params.req.ctx.num_pages = num_pages; + fwcmd->params.req.ctx.valid = 1; + fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1; + fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256); + fwcmd->params.req.ctx.armed = 0; + fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd; + + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_create_common_eq); + + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) + goto error; + + eq->eq_id = LE_16(fwcmd->params.rsp.eq_id); + + return 0; +error: + device_printf(sc->dev, "Mbox Create EQ failed\n"); + return rc; +} + + + +int +oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable) +{ + struct oce_mbx mbx; + struct mbx_create_common_cq *fwcmd; + POCE_SOFTC sc = cq->parent; + uint8_t version; + oce_cq_ctx_t *ctx; + uint32_t num_pages, page_size; + int rc = 0; + + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_create_common_cq *)&mbx.payload; + + if (IS_XE201(sc)) + version = OCE_MBX_VER_V2; + else + version = OCE_MBX_VER_V0; + + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_CREATE_CQ, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_create_common_cq), + version); + + ctx = &fwcmd->params.req.cq_ctx; + + num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]); + page_size = 1; /* 1 for 4K */ + + if (version == OCE_MBX_VER_V2) { + ctx->v2.num_pages = LE_16(num_pages); + ctx->v2.page_size = page_size; + ctx->v2.eventable = is_eventable; + ctx->v2.valid = 1; + ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256); + ctx->v2.nodelay = cq->cq_cfg.nodelay; + ctx->v2.coalesce_wm = ncoalesce; + ctx->v2.armed = 0; + ctx->v2.eq_id = cq->eq->eq_id; + if (ctx->v2.count == 3) { + if (cq->cq_cfg.q_len > (4*1024)-1) + ctx->v2.cqe_count = (4*1024)-1; + else + ctx->v2.cqe_count = cq->cq_cfg.q_len; + } + } else { + ctx->v0.num_pages = LE_16(num_pages); + ctx->v0.eventable = is_eventable; + ctx->v0.valid = 1; + ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256); + ctx->v0.nodelay = cq->cq_cfg.nodelay; + ctx->v0.coalesce_wm = ncoalesce; + ctx->v0.armed = 0; + ctx->v0.eq_id = cq->eq->eq_id; + } + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_create_common_cq); + + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) + goto error; + + cq->cq_id = LE_16(fwcmd->params.rsp.cq_id); + + return 0; +error: + device_printf(sc->dev, "Mbox Create CQ failed\n"); + return rc; + +} diff --git a/sys/dev/oce/oce_queue.c b/sys/dev/oce/oce_queue.c new file mode 100644 index 000000000000..c59dc5067c44 --- /dev/null +++ b/sys/dev/oce/oce_queue.c @@ -0,0 +1,1213 @@ +/*- + * Copyright (C) 2012 Emulex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Emulex Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact Information: + * freebsd-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + + + +/* $FreeBSD$ */ + + +#include "oce_if.h" + +/***************************************************** + * local queue functions + *****************************************************/ + +static struct oce_wq *oce_wq_init(POCE_SOFTC sc, + uint32_t q_len, uint32_t wq_type); +static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq); +static void oce_wq_free(struct oce_wq *wq); +static void oce_wq_del(struct oce_wq *wq); +static struct oce_rq *oce_rq_init(POCE_SOFTC sc, + uint32_t q_len, + uint32_t frag_size, + uint32_t mtu, uint32_t rss); +static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq); +static void oce_rq_free(struct oce_rq *rq); +static void oce_rq_del(struct oce_rq *rq); +static struct oce_eq *oce_eq_create(POCE_SOFTC sc, + uint32_t q_len, + uint32_t item_size, + uint32_t eq_delay, + uint32_t vector); +static void oce_eq_del(struct oce_eq *eq); +static struct oce_mq *oce_mq_create(POCE_SOFTC sc, + struct oce_eq *eq, uint32_t q_len); +static void oce_mq_free(struct oce_mq *mq); +static int oce_destroy_q(POCE_SOFTC sc, struct oce_mbx + *mbx, size_t req_size, enum qtype qtype); +struct oce_cq *oce_cq_create(POCE_SOFTC sc, + struct oce_eq *eq, + uint32_t q_len, + uint32_t item_size, + uint32_t sol_event, + uint32_t is_eventable, + uint32_t nodelay, uint32_t ncoalesce); +static void oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq); + + + +/** + * @brief Create and initialize all the queues on the board + * @param sc software handle to the device + * @returns 0 if successful, or error + **/ +int +oce_queue_init_all(POCE_SOFTC sc) +{ + int rc = 0, i, vector; + struct oce_wq *wq; + struct oce_rq *rq; + + /* alloc TX/RX queues */ + for_all_wq_queues(sc, wq, i) { + sc->wq[i] = oce_wq_init(sc, sc->tx_ring_size, + NIC_WQ_TYPE_STANDARD); + if (!sc->wq[i]) + goto error; + + } + + for_all_rq_queues(sc, rq, i) { + sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size, + OCE_MAX_JUMBO_FRAME_SIZE, + (i == 0) ? 0 : sc->rss_enable); + if (!sc->rq[i]) + goto error; + } + + /* Create network interface on card */ + if (oce_create_nw_interface(sc)) + goto error; + + /* create all of the event queues */ + for (vector = 0; vector < sc->intr_count; vector++) { + sc->eq[vector] = oce_eq_create(sc, EQ_LEN_1024, EQE_SIZE_4, + 0, vector); + if (!sc->eq[vector]) + goto error; + } + + /* create Tx, Rx and mcc queues */ + for_all_wq_queues(sc, wq, i) { + rc = oce_wq_create(wq, sc->eq[i]); + if (rc) + goto error; + wq->queue_index = i; + TASK_INIT(&wq->txtask, 1, oce_tx_task, wq); + } + + for_all_rq_queues(sc, rq, i) { + rc = oce_rq_create(rq, sc->if_id, + sc->eq[(i == 0) ? 0:(i-1)]); + if (rc) + goto error; + rq->queue_index = i; + } + + sc->mq = oce_mq_create(sc, sc->eq[0], 64); + if (!sc->mq) + goto error; + + return rc; + +error: + oce_queue_release_all(sc); + return 1; +} + + + +/** + * @brief Releases all mailbox queues created + * @param sc software handle to the device + */ +void +oce_queue_release_all(POCE_SOFTC sc) +{ + int i = 0; + struct oce_wq *wq; + struct oce_rq *rq; + struct oce_eq *eq; + + for_all_rq_queues(sc, rq, i) { + if (rq) { + oce_rq_del(sc->rq[i]); + oce_rq_free(sc->rq[i]); + } + } + + for_all_wq_queues(sc, wq, i) { + if (wq) { + oce_wq_del(sc->wq[i]); + oce_wq_free(sc->wq[i]); + } + } + + if (sc->mq) + oce_mq_free(sc->mq); + + for_all_evnt_queues(sc, eq, i) { + if (eq) + oce_eq_del(sc->eq[i]); + } +} + + + +/** + * @brief Function to create a WQ for NIC Tx + * @param sc software handle to the device + * @param qlen number of entries in the queue + * @param wq_type work queue type + * @returns the pointer to the WQ created or NULL on failure + */ +static struct +oce_wq *oce_wq_init(POCE_SOFTC sc, uint32_t q_len, uint32_t wq_type) +{ + struct oce_wq *wq; + int rc = 0, i; + + /* q_len must be min 256 and max 2k */ + if (q_len < 256 || q_len > 2048) { + device_printf(sc->dev, + "Invalid q length. Must be " + "[256, 2000]: 0x%x\n", q_len); + return NULL; + } + + /* allocate wq */ + wq = malloc(sizeof(struct oce_wq), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!wq) + return NULL; + + /* Set the wq config */ + wq->cfg.q_len = q_len; + wq->cfg.wq_type = (uint8_t) wq_type; + wq->cfg.eqd = OCE_DEFAULT_WQ_EQD; + wq->cfg.nbufs = 2 * wq->cfg.q_len; + wq->cfg.nhdl = 2 * wq->cfg.q_len; + + wq->parent = (void *)sc; + + rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), + 1, 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, NULL, + OCE_MAX_TX_SIZE, + OCE_MAX_TX_ELEMENTS, + PAGE_SIZE, 0, NULL, NULL, &wq->tag); + + if (rc) + goto free_wq; + + + for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) { + rc = bus_dmamap_create(wq->tag, 0, &wq->pckts[i].map); + if (rc) + goto free_wq; + } + + wq->ring = oce_create_ring_buffer(sc, q_len, NIC_WQE_SIZE); + if (!wq->ring) + goto free_wq; + + + LOCK_CREATE(&wq->tx_lock, "TX_lock"); + +#if __FreeBSD_version >= 800000 + /* Allocate buf ring for multiqueue*/ + wq->br = buf_ring_alloc(4096, M_DEVBUF, + M_WAITOK, &wq->tx_lock.mutex); + if (!wq->br) + goto free_wq; +#endif + return wq; + + +free_wq: + device_printf(sc->dev, "Create WQ failed\n"); + oce_wq_free(wq); + return NULL; +} + + + +/** + * @brief Frees the work queue + * @param wq pointer to work queue to free + */ +static void +oce_wq_free(struct oce_wq *wq) +{ + POCE_SOFTC sc = (POCE_SOFTC) wq->parent; + int i; + + taskqueue_drain(taskqueue_swi, &wq->txtask); + + if (wq->ring != NULL) { + oce_destroy_ring_buffer(sc, wq->ring); + wq->ring = NULL; + } + + for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) { + if (wq->pckts[i].map != NULL) { + bus_dmamap_unload(wq->tag, wq->pckts[i].map); + bus_dmamap_destroy(wq->tag, wq->pckts[i].map); + wq->pckts[i].map = NULL; + } + } + + if (wq->tag != NULL) + bus_dma_tag_destroy(wq->tag); + if (wq->br != NULL) + buf_ring_free(wq->br, M_DEVBUF); + + LOCK_DESTROY(&wq->tx_lock); + free(wq, M_DEVBUF); +} + + + +/** + * @brief Create a work queue + * @param wq pointer to work queue + * @param eq pointer to associated event queue + */ +static int +oce_wq_create(struct oce_wq *wq, struct oce_eq *eq) +{ + POCE_SOFTC sc = wq->parent; + struct oce_cq *cq; + int rc = 0; + + /* create the CQ */ + cq = oce_cq_create(sc, + eq, + CQ_LEN_1024, + sizeof(struct oce_nic_tx_cqe), 0, 1, 0, 3); + if (!cq) + return ENXIO; + + + wq->cq = cq; + + rc = oce_mbox_create_wq(wq); + if (rc) + goto error; + + wq->qstate = QCREATED; + wq->wq_free = wq->cfg.q_len; + wq->ring->cidx = 0; + wq->ring->pidx = 0; + + eq->cq[eq->cq_valid] = cq; + eq->cq_valid++; + cq->cb_arg = wq; + cq->cq_handler = oce_wq_handler; + + return 0; + +error: + device_printf(sc->dev, "WQ create failed\n"); + oce_wq_del(wq); + return rc; +} + + + + +/** + * @brief Delete a work queue + * @param wq pointer to work queue + */ +static void +oce_wq_del(struct oce_wq *wq) +{ + struct oce_mbx mbx; + struct mbx_delete_nic_wq *fwcmd; + POCE_SOFTC sc = (POCE_SOFTC) wq->parent; + + if (wq->qstate == QCREATED) { + bzero(&mbx, sizeof(struct oce_mbx)); + /* now fill the command */ + fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload; + fwcmd->params.req.wq_id = wq->wq_id; + (void)oce_destroy_q(sc, &mbx, + sizeof(struct mbx_delete_nic_wq), QTYPE_WQ); + wq->qstate = QDELETED; + } + + if (wq->cq != NULL) { + oce_cq_del(sc, wq->cq); + wq->cq = NULL; + } +} + + + +/** + * @brief function to allocate receive queue resources + * @param sc software handle to the device + * @param q_len length of receive queue + * @param frag_size size of an receive queue fragment + * @param mtu maximum transmission unit + * @param rss is-rss-queue flag + * @returns the pointer to the RQ created or NULL on failure + */ +static struct +oce_rq *oce_rq_init(POCE_SOFTC sc, + uint32_t q_len, + uint32_t frag_size, + uint32_t mtu, uint32_t rss) +{ + struct oce_rq *rq; + int rc = 0, i; + + if (OCE_LOG2(frag_size) <= 0) + return NULL; + + if ((q_len == 0) || (q_len > 1024)) + return NULL; + + /* allocate the rq */ + rq = malloc(sizeof(struct oce_rq), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!rq) + return NULL; + + + rq->cfg.q_len = q_len; + rq->cfg.frag_size = frag_size; + rq->cfg.mtu = mtu; + rq->cfg.eqd = 0; + rq->lro_pkts_queued = 0; + rq->cfg.is_rss_queue = rss; + rq->packets_in = 0; + rq->packets_out = 0; + rq->pending = 0; + + rq->parent = (void *)sc; + + rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), + 1, 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, NULL, + OCE_MAX_RX_SIZE, + 1, PAGE_SIZE, 0, NULL, NULL, &rq->tag); + + if (rc) + goto free_rq; + + for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) { + rc = bus_dmamap_create(rq->tag, 0, &rq->pckts[i].map); + if (rc) + goto free_rq; + } + + /* create the ring buffer */ + rq->ring = oce_create_ring_buffer(sc, q_len, + sizeof(struct oce_nic_rqe)); + if (!rq->ring) + goto free_rq; + + LOCK_CREATE(&rq->rx_lock, "RX_lock"); + + return rq; + +free_rq: + device_printf(sc->dev, "Create RQ failed\n"); + oce_rq_free(rq); + return NULL; +} + + + + +/** + * @brief Free a receive queue + * @param rq pointer to receive queue + */ +static void +oce_rq_free(struct oce_rq *rq) +{ + POCE_SOFTC sc = (POCE_SOFTC) rq->parent; + int i = 0 ; + + if (rq->ring != NULL) { + oce_destroy_ring_buffer(sc, rq->ring); + rq->ring = NULL; + } + for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) { + if (rq->pckts[i].map != NULL) { + bus_dmamap_unload(rq->tag, rq->pckts[i].map); + bus_dmamap_destroy(rq->tag, rq->pckts[i].map); + rq->pckts[i].map = NULL; + } + if (rq->pckts[i].mbuf) { + m_free(rq->pckts[i].mbuf); + rq->pckts[i].mbuf = NULL; + } + } + + if (rq->tag != NULL) + bus_dma_tag_destroy(rq->tag); + + LOCK_DESTROY(&rq->rx_lock); + free(rq, M_DEVBUF); +} + + + + +/** + * @brief Create a receive queue + * @param rq receive queue + * @param if_id interface identifier index` + * @param eq pointer to event queue + */ +static int +oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq) +{ + POCE_SOFTC sc = rq->parent; + struct oce_cq *cq; + + cq = oce_cq_create(sc, + eq, + CQ_LEN_1024, + sizeof(struct oce_nic_rx_cqe), 0, 1, 0, 3); + if (!cq) + return ENXIO; + + rq->cq = cq; + rq->cfg.if_id = if_id; + + /* Dont create RQ here. Create in if_activate */ + rq->qstate = 0; + rq->ring->cidx = 0; + rq->ring->pidx = 0; + eq->cq[eq->cq_valid] = cq; + eq->cq_valid++; + cq->cb_arg = rq; + cq->cq_handler = oce_rq_handler; + + return 0; + +} + + + + +/** + * @brief Delete a receive queue + * @param rq receive queue + */ +static void +oce_rq_del(struct oce_rq *rq) +{ + POCE_SOFTC sc = (POCE_SOFTC) rq->parent; + struct oce_mbx mbx; + struct mbx_delete_nic_rq *fwcmd; + + if (rq->qstate == QCREATED) { + bzero(&mbx, sizeof(mbx)); + + fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; + fwcmd->params.req.rq_id = rq->rq_id; + (void)oce_destroy_q(sc, &mbx, + sizeof(struct mbx_delete_nic_rq), QTYPE_RQ); + rq->qstate = QDELETED; + } + + if (rq->cq != NULL) { + oce_cq_del(sc, rq->cq); + rq->cq = NULL; + } +} + + + +/** + * @brief function to create an event queue + * @param sc software handle to the device + * @param q_len length of event queue + * @param item_size size of an event queue item + * @param eq_delay event queue delay + * @retval eq success, pointer to event queue + * @retval NULL failure + */ +static struct +oce_eq *oce_eq_create(POCE_SOFTC sc, uint32_t q_len, + uint32_t item_size, + uint32_t eq_delay, + uint32_t vector) +{ + struct oce_eq *eq; + int rc = 0; + + /* allocate an eq */ + eq = malloc(sizeof(struct oce_eq), M_DEVBUF, M_NOWAIT | M_ZERO); + if (eq == NULL) + return NULL; + + eq->parent = (void *)sc; + eq->eq_id = 0xffff; + eq->ring = oce_create_ring_buffer(sc, q_len, item_size); + if (!eq->ring) + goto free_eq; + + eq->eq_cfg.q_len = q_len; + eq->eq_cfg.item_size = item_size; + eq->eq_cfg.cur_eqd = (uint8_t) eq_delay; + + rc = oce_mbox_create_eq(eq); + if (rc) + goto free_eq; + + sc->intrs[sc->neqs++].eq = eq; + + return eq; + +free_eq: + oce_eq_del(eq); + return NULL; +} + + + + +/** + * @brief Function to delete an event queue + * @param eq pointer to an event queue + */ +static void +oce_eq_del(struct oce_eq *eq) +{ + struct oce_mbx mbx; + struct mbx_destroy_common_eq *fwcmd; + POCE_SOFTC sc = (POCE_SOFTC) eq->parent; + + if (eq->eq_id != 0xffff) { + bzero(&mbx, sizeof(mbx)); + fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload; + fwcmd->params.req.id = eq->eq_id; + (void)oce_destroy_q(sc, &mbx, + sizeof(struct mbx_destroy_common_eq), QTYPE_EQ); + } + + if (eq->ring != NULL) { + oce_destroy_ring_buffer(sc, eq->ring); + eq->ring = NULL; + } + + free(eq, M_DEVBUF); + +} + + + + +/** + * @brief Function to create an MQ + * @param sc software handle to the device + * @param eq the EQ to associate with the MQ for event notification + * @param q_len the number of entries to create in the MQ + * @returns pointer to the created MQ, failure otherwise + */ +static struct oce_mq * +oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len) +{ + struct oce_mbx mbx; + struct mbx_create_common_mq *fwcmd = NULL; + struct oce_mq *mq = NULL; + int rc = 0; + struct oce_cq *cq; + oce_mq_ctx_t *ctx; + uint32_t num_pages; + uint32_t page_size; + uint32_t version; + + + cq = oce_cq_create(sc, eq, CQ_LEN_256, + sizeof(struct oce_mq_cqe), 1, 1, 0, 0); + if (!cq) + return NULL; + + /* allocate the mq */ + mq = malloc(sizeof(struct oce_mq), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!mq) { + oce_cq_del(sc, cq); + goto error; + } + + mq->parent = sc; + + mq->ring = oce_create_ring_buffer(sc, q_len, sizeof(struct oce_mbx)); + if (!mq->ring) + goto error; + + bzero(&mbx, sizeof(struct oce_mbx)); + + fwcmd = (struct mbx_create_common_mq *)&mbx.payload; + version = OCE_MBX_VER_V0; + mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, + MBX_SUBSYSTEM_COMMON, + OPCODE_COMMON_CREATE_MQ, + MBX_TIMEOUT_SEC, + sizeof(struct mbx_create_common_mq), + version); + + num_pages = oce_page_list(mq->ring, &fwcmd->params.req.pages[0]); + page_size = mq->ring->num_items * mq->ring->item_size; + + ctx = &fwcmd->params.req.context; + ctx->v0.num_pages = num_pages; + ctx->v0.cq_id = cq->cq_id; + ctx->v0.ring_size = OCE_LOG2(q_len) + 1; + ctx->v0.valid = 1; + + mbx.u0.s.embedded = 1; + mbx.payload_length = sizeof(struct mbx_create_common_mq); + DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, &mbx, NULL); + if (rc) + goto error; + + mq->mq_id = LE_16(fwcmd->params.rsp.mq_id); + mq->cq = cq; + eq->cq[eq->cq_valid] = cq; + eq->cq_valid++; + mq->cq->eq = eq; + mq->cfg.q_len = (uint8_t) q_len; + mq->cfg.eqd = 0; + mq->qstate = QCREATED; + + mq->cq->cb_arg = mq; + mq->cq->cq_handler = oce_mq_handler; + + return mq; + +error: + device_printf(sc->dev, "MQ create failed\n"); + oce_mq_free(mq); + mq = NULL; + return mq; +} + + + + + +/** + * @brief Function to free a mailbox queue + * @param mq pointer to a mailbox queue + */ +static void +oce_mq_free(struct oce_mq *mq) +{ + POCE_SOFTC sc = (POCE_SOFTC) mq->parent; + struct oce_mbx mbx; + struct mbx_destroy_common_mq *fwcmd; + + if (!mq) + return; + + if (mq->ring != NULL) { + oce_destroy_ring_buffer(sc, mq->ring); + mq->ring = NULL; + if (mq->qstate == QCREATED) { + bzero(&mbx, sizeof (struct oce_mbx)); + fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload; + fwcmd->params.req.id = mq->mq_id; + (void) oce_destroy_q(sc, &mbx, + sizeof (struct mbx_destroy_common_mq), + QTYPE_MQ); + } + mq->qstate = QDELETED; + } + + if (mq->cq != NULL) { + oce_cq_del(sc, mq->cq); + mq->cq = NULL; + } + + free(mq, M_DEVBUF); + mq = NULL; +} + + + +/** + * @brief Function to delete a EQ, CQ, MQ, WQ or RQ + * @param sc sofware handle to the device + * @param mbx mailbox command to send to the fw to delete the queue + * (mbx contains the queue information to delete) + * @param req_size the size of the mbx payload dependent on the qtype + * @param qtype the type of queue i.e. EQ, CQ, MQ, WQ or RQ + * @returns 0 on success, failure otherwise + */ +static int +oce_destroy_q(POCE_SOFTC sc, struct oce_mbx *mbx, size_t req_size, + enum qtype qtype) +{ + struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload; + int opcode; + int subsys; + int rc = 0; + + switch (qtype) { + case QTYPE_EQ: + opcode = OPCODE_COMMON_DESTROY_EQ; + subsys = MBX_SUBSYSTEM_COMMON; + break; + case QTYPE_CQ: + opcode = OPCODE_COMMON_DESTROY_CQ; + subsys = MBX_SUBSYSTEM_COMMON; + break; + case QTYPE_MQ: + opcode = OPCODE_COMMON_DESTROY_MQ; + subsys = MBX_SUBSYSTEM_COMMON; + break; + case QTYPE_WQ: + opcode = NIC_DELETE_WQ; + subsys = MBX_SUBSYSTEM_NIC; + break; + case QTYPE_RQ: + opcode = NIC_DELETE_RQ; + subsys = MBX_SUBSYSTEM_NIC; + break; + default: + return EINVAL; + } + + mbx_common_req_hdr_init(hdr, 0, 0, subsys, + opcode, MBX_TIMEOUT_SEC, req_size, + OCE_MBX_VER_V0); + + mbx->u0.s.embedded = 1; + mbx->payload_length = (uint32_t) req_size; + DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ); + + rc = oce_mbox_post(sc, mbx, NULL); + + if (rc != 0) + device_printf(sc->dev, "Failed to del q\n"); + + return rc; +} + + + +/** + * @brief Function to create a completion queue + * @param sc software handle to the device + * @param eq optional eq to be associated with to the cq + * @param q_len length of completion queue + * @param item_size size of completion queue items + * @param sol_event command context event + * @param is_eventable event table + * @param nodelay no delay flag + * @param ncoalesce no coalescence flag + * @returns pointer to the cq created, NULL on failure + */ +struct oce_cq * +oce_cq_create(POCE_SOFTC sc, struct oce_eq *eq, + uint32_t q_len, + uint32_t item_size, + uint32_t sol_event, + uint32_t is_eventable, + uint32_t nodelay, uint32_t ncoalesce) +{ + struct oce_cq *cq = NULL; + int rc = 0; + + cq = malloc(sizeof(struct oce_cq), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!cq) + return NULL; + + cq->ring = oce_create_ring_buffer(sc, q_len, item_size); + if (!cq->ring) + goto error; + + cq->parent = sc; + cq->eq = eq; + cq->cq_cfg.q_len = q_len; + cq->cq_cfg.item_size = item_size; + cq->cq_cfg.nodelay = (uint8_t) nodelay; + + rc = oce_mbox_cq_create(cq, ncoalesce, is_eventable); + if (rc) + goto error; + + sc->cq[sc->ncqs++] = cq; + + return cq; + +error: + device_printf(sc->dev, "CQ create failed\n"); + oce_cq_del(sc, cq); + return NULL; +} + + + +/** + * @brief Deletes the completion queue + * @param sc software handle to the device + * @param cq pointer to a completion queue + */ +static void +oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq) +{ + struct oce_mbx mbx; + struct mbx_destroy_common_cq *fwcmd; + + if (cq->ring != NULL) { + + bzero(&mbx, sizeof(struct oce_mbx)); + /* now fill the command */ + fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload; + fwcmd->params.req.id = cq->cq_id; + (void)oce_destroy_q(sc, &mbx, + sizeof(struct mbx_destroy_common_cq), QTYPE_CQ); + /*NOW destroy the ring */ + oce_destroy_ring_buffer(sc, cq->ring); + cq->ring = NULL; + } + + free(cq, M_DEVBUF); + cq = NULL; +} + + + +/** + * @brief Start a receive queue + * @param rq pointer to a receive queue + */ +int +oce_start_rq(struct oce_rq *rq) +{ + int rc; + + rc = oce_alloc_rx_bufs(rq, rq->cfg.q_len); + + if (rc == 0) + oce_arm_cq(rq->parent, rq->cq->cq_id, 0, TRUE); + return rc; +} + + + +/** + * @brief Start a work queue + * @param wq pointer to a work queue + */ +int +oce_start_wq(struct oce_wq *wq) +{ + oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE); + return 0; +} + + + +/** + * @brief Start a mailbox queue + * @param mq pointer to a mailbox queue + */ +int +oce_start_mq(struct oce_mq *mq) +{ + oce_arm_cq(mq->parent, mq->cq->cq_id, 0, TRUE); + return 0; +} + + + +/** + * @brief Function to arm an EQ so that it can generate events + * @param sc software handle to the device + * @param qid id of the EQ returned by the fw at the time of creation + * @param npopped number of EQEs to arm + * @param rearm rearm bit enable/disable + * @param clearint bit to clear the interrupt condition because of which + * EQEs are generated + */ +void +oce_arm_eq(POCE_SOFTC sc, + int16_t qid, int npopped, uint32_t rearm, uint32_t clearint) +{ + eq_db_t eq_db = { 0 }; + + eq_db.bits.rearm = rearm; + eq_db.bits.event = 1; + eq_db.bits.num_popped = npopped; + eq_db.bits.clrint = clearint; + eq_db.bits.qid = qid; + OCE_WRITE_REG32(sc, db, PD_EQ_DB, eq_db.dw0); + +} + + + + +/** + * @brief Function to arm a CQ with CQEs + * @param sc software handle to the device + * @param qid id of the CQ returned by the fw at the time of creation + * @param npopped number of CQEs to arm + * @param rearm rearm bit enable/disable + */ +void oce_arm_cq(POCE_SOFTC sc, int16_t qid, int npopped, uint32_t rearm) +{ + cq_db_t cq_db = { 0 }; + + cq_db.bits.rearm = rearm; + cq_db.bits.num_popped = npopped; + cq_db.bits.event = 0; + cq_db.bits.qid = qid; + OCE_WRITE_REG32(sc, db, PD_CQ_DB, cq_db.dw0); + +} + + + + +/* + * @brief function to cleanup the eqs used during stop + * @param eq pointer to event queue structure + * @returns the number of EQs processed + */ +void +oce_drain_eq(struct oce_eq *eq) +{ + + struct oce_eqe *eqe; + uint16_t num_eqe = 0; + POCE_SOFTC sc = eq->parent; + + do { + eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe); + if (eqe->evnt == 0) + break; + eqe->evnt = 0; + bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map, + BUS_DMASYNC_POSTWRITE); + num_eqe++; + RING_GET(eq->ring, 1); + + } while (TRUE); + + oce_arm_eq(sc, eq->eq_id, num_eqe, FALSE, TRUE); + +} + + + +void +oce_drain_wq_cq(struct oce_wq *wq) +{ + POCE_SOFTC sc = wq->parent; + struct oce_cq *cq = wq->cq; + struct oce_nic_tx_cqe *cqe; + int num_cqes = 0; + + bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, + BUS_DMASYNC_POSTWRITE); + + do { + cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe); + if (cqe->u0.dw[3] == 0) + break; + cqe->u0.dw[3] = 0; + bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, + BUS_DMASYNC_POSTWRITE); + RING_GET(cq->ring, 1); + num_cqes++; + + } while (TRUE); + + oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); + +} + + +/* + * @brief function to drain a MCQ and process its CQEs + * @param dev software handle to the device + * @param cq pointer to the cq to drain + * @returns the number of CQEs processed + */ +void +oce_drain_mq_cq(void *arg) +{ + /* TODO: additional code. */ + return; +} + + + +/** + * @brief function to process a Recieve queue + * @param arg pointer to the RQ to charge + * @return number of cqes processed + */ +void +oce_drain_rq_cq(struct oce_rq *rq) +{ + struct oce_nic_rx_cqe *cqe; + uint16_t num_cqe = 0; + struct oce_cq *cq; + POCE_SOFTC sc; + + sc = rq->parent; + cq = rq->cq; + cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe); + /* dequeue till you reach an invalid cqe */ + while (RQ_CQE_VALID(cqe)) { + RQ_CQE_INVALIDATE(cqe); + RING_GET(cq->ring, 1); + cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, + struct oce_nic_rx_cqe); + num_cqe++; + } + oce_arm_cq(sc, cq->cq_id, num_cqe, FALSE); + + return; +} + + +void +oce_free_posted_rxbuf(struct oce_rq *rq) +{ + struct oce_packet_desc *pd; + + while (rq->pending) { + + pd = &rq->pckts[rq->packets_out]; + bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(rq->tag, pd->map); + if (pd->mbuf != NULL) { + m_freem(pd->mbuf); + pd->mbuf = NULL; + } + + if ((rq->packets_out + 1) == OCE_RQ_PACKET_ARRAY_SIZE) + rq->packets_out = 0; + else + rq->packets_out++; + + rq->pending--; + } + +} + +void +oce_stop_rx(POCE_SOFTC sc) +{ + struct oce_mbx mbx; + struct mbx_delete_nic_rq *fwcmd; + struct oce_rq *rq; + int i = 0; + + for_all_rq_queues(sc, rq, i) { + if (rq->qstate == QCREATED) { + /* Delete rxq in firmware */ + + bzero(&mbx, sizeof(mbx)); + fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; + fwcmd->params.req.rq_id = rq->rq_id; + + (void)oce_destroy_q(sc, &mbx, + sizeof(struct mbx_delete_nic_rq), QTYPE_RQ); + + rq->qstate = QDELETED; + + DELAY(1); + + /* Free posted RX buffers that are not used */ + oce_free_posted_rxbuf(rq); + + } + } +} + + + +int +oce_start_rx(POCE_SOFTC sc) +{ + struct oce_rq *rq; + int rc = 0, i; + + for_all_rq_queues(sc, rq, i) { + if (rq->qstate == QCREATED) + continue; + rc = oce_mbox_create_rq(rq); + if (rc) + goto error; + /* reset queue pointers */ + rq->qstate = QCREATED; + rq->pending = 0; + rq->ring->cidx = 0; + rq->ring->pidx = 0; + rq->packets_in = 0; + rq->packets_out = 0; + } + + DELAY(1); + + /* RSS config */ + if (sc->rss_enable) { + rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE); + if (rc) + goto error; + + } + + return rc; +error: + device_printf(sc->dev, "Start RX failed\n"); + return rc; + +} + + + diff --git a/sys/dev/oce/oce_sysctl.c b/sys/dev/oce/oce_sysctl.c new file mode 100644 index 000000000000..e0c50ddcd170 --- /dev/null +++ b/sys/dev/oce/oce_sysctl.c @@ -0,0 +1,1300 @@ +/*- + * Copyright (C) 2012 Emulex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Emulex Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact Information: + * freebsd-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + + +/* $FreeBSD$ */ + + +#include "oce_if.h" + +static void copy_stats_to_sc_xe201(POCE_SOFTC sc); +static void copy_stats_to_sc_be3(POCE_SOFTC sc); +static void copy_stats_to_sc_be2(POCE_SOFTC sc); +static int oce_sysctl_loopback(SYSCTL_HANDLER_ARGS); +static int oce_be3_fwupgrade(POCE_SOFTC sc, const struct firmware *fw); +static int oce_sys_fwupgrade(SYSCTL_HANDLER_ARGS); +static int oce_be3_flashdata(POCE_SOFTC sc, const struct firmware + *fw, int num_imgs); +static int oce_lancer_fwupgrade(POCE_SOFTC sc, const struct firmware *fw); +static boolean_t oce_phy_flashing_required(POCE_SOFTC sc); +static boolean_t oce_img_flashing_required(POCE_SOFTC sc, const char *p, + int img_optype, uint32_t img_offset, + uint32_t img_size, uint32_t hdrs_size); +static void oce_add_stats_sysctls_be3(POCE_SOFTC sc, + struct sysctl_ctx_list *ctx, + struct sysctl_oid *stats_node); +static void oce_add_stats_sysctls_xe201(POCE_SOFTC sc, + struct sysctl_ctx_list *ctx, + struct sysctl_oid *stats_node); + +extern char component_revision[32]; + + +void +oce_add_sysctls(POCE_SOFTC sc) +{ + + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev); + struct sysctl_oid *tree = device_get_sysctl_tree(sc->dev); + struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); + struct sysctl_oid *stats_node; + + SYSCTL_ADD_STRING(ctx, child, + OID_AUTO, "component_revision", + CTLTYPE_INT | CTLFLAG_RD, + &component_revision, + sizeof(component_revision), + "EMULEX One-Connect device driver revision"); + + SYSCTL_ADD_STRING(ctx, child, + OID_AUTO, "firmware_version", + CTLTYPE_INT | CTLFLAG_RD, + &sc->fw_version, + sizeof(sc->fw_version), + "EMULEX One-Connect Firmware Version"); + + SYSCTL_ADD_INT(ctx, child, + OID_AUTO, "max_rsp_handled", + CTLTYPE_INT | CTLFLAG_RW, + &oce_max_rsp_handled, + sizeof(oce_max_rsp_handled), + "Maximum receive frames handled per interupt"); + + if (sc->function_mode & FNM_FLEX10_MODE) + SYSCTL_ADD_UINT(ctx, child, + OID_AUTO, "speed", + CTLFLAG_RD, + &sc->qos_link_speed, + 0,"QOS Speed"); + else + SYSCTL_ADD_UINT(ctx, child, + OID_AUTO, "speed", + CTLFLAG_RD, + &sc->speed, + 0,"Link Speed"); + + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "loop_back", + CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, + oce_sysctl_loopback, "I", "Loop Back Tests"); + + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fw_upgrade", + CTLTYPE_STRING | CTLFLAG_RW, (void *)sc, 0, + oce_sys_fwupgrade, "A", "Firmware ufi file"); + + stats_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", + CTLFLAG_RD, NULL, "Ethernet Statistics"); + + if (IS_BE(sc)) + oce_add_stats_sysctls_be3(sc, ctx, stats_node); + else + oce_add_stats_sysctls_xe201(sc, ctx, stats_node); + + +} + + + +static uint32_t +oce_loopback_test(struct oce_softc *sc, uint8_t loopback_type) +{ + uint32_t status = 0; + + oce_mbox_cmd_set_loopback(sc, sc->if_id, loopback_type, 1); + status = oce_mbox_cmd_test_loopback(sc, sc->if_id, loopback_type, + 1500, 2, 0xabc); + oce_mbox_cmd_set_loopback(sc, sc->if_id, OCE_NO_LOOPBACK, 1); + + return status; +} + + +static int +oce_sysctl_loopback(SYSCTL_HANDLER_ARGS) +{ + int value = 0; + uint32_t status; + struct oce_softc *sc = (struct oce_softc *)arg1; + + status = sysctl_handle_int(oidp, &value, 0, req); + if (status || !req->newptr) + return status; + + if (value != 1) { + device_printf(sc->dev, + "Not a Valid value. Set to loop_back=1 to run tests\n"); + return 0; + } + + if ((status = oce_loopback_test(sc, OCE_MAC_LOOPBACK))) { + device_printf(sc->dev, + "MAC Loopback Test = Failed (Error status = %d)\n", + status); + } else + device_printf(sc->dev, "MAC Loopback Test = Success\n"); + + if ((status = oce_loopback_test(sc, OCE_PHY_LOOPBACK))) { + device_printf(sc->dev, + "PHY Loopback Test = Failed (Error status = %d)\n", + status); + } else + device_printf(sc->dev, "PHY Loopback Test = Success\n"); + + if ((status = oce_loopback_test(sc, OCE_ONE_PORT_EXT_LOOPBACK))) { + device_printf(sc->dev, + "EXT Loopback Test = Failed (Error status = %d)\n", + status); + } else + device_printf(sc->dev, "EXT Loopback Test = Success\n"); + + return 0; +} + + +static int +oce_sys_fwupgrade(SYSCTL_HANDLER_ARGS) +{ + char ufiname[256] = {0}; + uint32_t status = 1; + struct oce_softc *sc = (struct oce_softc *)arg1; + const struct firmware *fw; + + status = sysctl_handle_string(oidp, ufiname, sizeof(ufiname), req); + if (status || !req->newptr) + return status; + + fw = firmware_get(ufiname); + if (fw == NULL) { + device_printf(sc->dev, "Unable to get Firmware. " + "Make sure %s is copied to /boot/modules\n", ufiname); + return ENOENT; + } + + if (IS_BE(sc)) { + if ((sc->flags & OCE_FLAGS_BE2)) { + device_printf(sc->dev, + "Flashing not supported for BE2 yet.\n"); + status = 1; + goto done; + } + status = oce_be3_fwupgrade(sc, fw); + } else + status = oce_lancer_fwupgrade(sc, fw); +done: + if (status) { + device_printf(sc->dev, "Firmware Upgrade failed\n"); + } else { + device_printf(sc->dev, "Firmware Flashed successfully\n"); + } + + /* Release Firmware*/ + firmware_put(fw, FIRMWARE_UNLOAD); + + return status; +} + + +static int +oce_be3_fwupgrade(POCE_SOFTC sc, const struct firmware *fw) +{ + int rc = 0, num_imgs = 0, i = 0; + const struct flash_file_hdr *fhdr; + const struct image_hdr *img_ptr; + + fhdr = (const struct flash_file_hdr *)fw->data; + if (fhdr->build[0] != '3') { + device_printf(sc->dev, "Invalid BE3 firmware image\n"); + return EINVAL; + } + /* Display flash version */ + device_printf(sc->dev, "Flashing Firmware %s\n", &fhdr->build[2]); + + num_imgs = fhdr->num_imgs; + for (i = 0; i < num_imgs; i++) { + img_ptr = (const struct image_hdr *)((const char *)fw->data + + sizeof(struct flash_file_hdr) + + (i * sizeof(struct image_hdr))); + if (img_ptr->imageid == 1) { + rc = oce_be3_flashdata(sc, fw, num_imgs); + break; + } + } + + return rc; +} + + +static int +oce_be3_flashdata(POCE_SOFTC sc, const struct firmware *fw, int num_imgs) +{ + char cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; + const char *p = (const char *)fw->data; + const struct flash_sec_info *fsec = NULL; + struct mbx_common_read_write_flashrom *req; + int rc = 0, i, img_type, bin_offset = 0; + boolean_t skip_image; + uint32_t optype = 0, size = 0, start = 0, num_bytes = 0; + uint32_t opcode = 0; + OCE_DMA_MEM dma_mem; + + /* Validate Cookie */ + bin_offset = (sizeof(struct flash_file_hdr) + + (num_imgs * sizeof(struct image_hdr))); + p += bin_offset; + while (p < ((const char *)fw->data + fw->datasize)) { + fsec = (const struct flash_sec_info *)p; + if (!memcmp(cookie, fsec->cookie, sizeof(cookie))) + break; + fsec = NULL; + p += 32; + } + + if (!fsec) { + device_printf(sc->dev, + "Invalid Cookie. Firmware image corrupted ?\n"); + return EINVAL; + } + + rc = oce_dma_alloc(sc, sizeof(struct mbx_common_read_write_flashrom) + + 32*1024, &dma_mem, 0); + if (rc) { + device_printf(sc->dev, + "Memory allocation failure while flashing\n"); + return ENOMEM; + } + req = OCE_DMAPTR(&dma_mem, struct mbx_common_read_write_flashrom); + + for (i = 0; i < MAX_FLASH_COMP; i++) { + + img_type = fsec->fsec_entry[i].type; + skip_image = FALSE; + switch (img_type) { + case IMG_ISCSI: + optype = 0; + size = 2097152; + start = 2097152; + break; + case IMG_REDBOOT: + optype = 1; + size = 1048576; + start = 262144; + if (!oce_img_flashing_required(sc, fw->data, + optype, start, size, bin_offset)) + skip_image = TRUE; + break; + case IMG_BIOS: + optype = 2; + size = 524288; + start = 12582912; + break; + case IMG_PXEBIOS: + optype = 3; + size = 524288; + start = 13107200; + break; + case IMG_FCOEBIOS: + optype = 8; + size = 524288; + start = 13631488; + break; + case IMG_ISCSI_BAK: + optype = 9; + size = 2097152; + start = 4194304; + break; + case IMG_FCOE: + optype = 10; + size = 2097152; + start = 6291456; + break; + case IMG_FCOE_BAK: + optype = 11; + size = 2097152; + start = 8388608; + break; + case IMG_NCSI: + optype = 13; + size = 262144; + start = 15990784; + break; + case IMG_PHY: + optype = 99; + size = 262144; + start = 1310720; + if (!oce_phy_flashing_required(sc)) + skip_image = TRUE; + break; + default: + skip_image = TRUE; + break; + } + if (skip_image) + continue; + + p = fw->data; + p = p + bin_offset + start; + if ((p + size) > ((const char *)fw->data + fw->datasize)) { + rc = 1; + goto ret; + } + + while (size) { + + if (size > 32*1024) + num_bytes = 32*1024; + else + num_bytes = size; + size -= num_bytes; + + if (!size) + opcode = FLASHROM_OPER_FLASH; + else + opcode = FLASHROM_OPER_SAVE; + + memcpy(req->data_buffer, p, num_bytes); + p += num_bytes; + + rc = oce_mbox_write_flashrom(sc, optype, opcode, + &dma_mem, num_bytes); + if (rc) { + device_printf(sc->dev, + "cmd to write to flash rom failed.\n"); + rc = EIO; + goto ret; + } + /* Leave the CPU for others for some time */ + pause("yield", 10); + + } + } +ret: + oce_dma_free(sc, &dma_mem); + return rc; + +} + + +static boolean_t +oce_phy_flashing_required(POCE_SOFTC sc) +{ + int status = 0; + struct oce_phy_info phy_info; + + status = oce_mbox_get_phy_info(sc, &phy_info); + if (status) + return FALSE; + + if ((phy_info.phy_type == TN_8022) && + (phy_info.interface_type == PHY_TYPE_BASET_10GB)) { + return TRUE; + } + + return FALSE; +} + + +static boolean_t +oce_img_flashing_required(POCE_SOFTC sc, const char *p, + int img_optype, uint32_t img_offset, + uint32_t img_size, uint32_t hdrs_size) +{ + uint32_t crc_offset; + uint8_t flashed_crc[4]; + int status; + + crc_offset = hdrs_size + img_offset + img_size - 4; + + p += crc_offset; + + status = oce_mbox_get_flashrom_crc(sc, flashed_crc, + (img_size - 4), img_optype); + if (status) + return TRUE; /* Some thing worng. ReFlash */ + + /*update redboot only if crc does not match*/ + if (bcmp(flashed_crc, p, 4)) + return TRUE; + else + return FALSE; +} + + +static int +oce_lancer_fwupgrade(POCE_SOFTC sc, const struct firmware *fw) +{ + + int rc = 0; + OCE_DMA_MEM dma_mem; + const uint8_t *data = NULL; + uint8_t *dest_image_ptr = NULL; + size_t size = 0; + uint32_t data_written = 0, chunk_size = 0; + uint32_t offset = 0, add_status = 0; + + if (!IS_ALIGNED(fw->datasize, sizeof(uint32_t))) { + device_printf(sc->dev, + "Lancer FW image is not 4 byte aligned."); + return EINVAL; + } + + rc = oce_dma_alloc(sc, 32*1024, &dma_mem, 0); + if (rc) { + device_printf(sc->dev, + "Memory allocation failure while flashing Lancer\n"); + return ENOMEM; + } + + size = fw->datasize; + data = fw->data; + dest_image_ptr = OCE_DMAPTR(&dma_mem, uint8_t); + + while (size) { + chunk_size = MIN(size, (32*1024)); + + bcopy(data, dest_image_ptr, chunk_size); + + rc = oce_mbox_lancer_write_flashrom(sc, chunk_size, offset, + &dma_mem, &data_written, &add_status); + + if (rc) + break; + + size -= data_written; + data += data_written; + offset += data_written; + pause("yield", 10); + + } + + if (!rc) + /* Commit the firmware*/ + rc = oce_mbox_lancer_write_flashrom(sc, 0, offset, &dma_mem, + &data_written, &add_status); + if (rc) { + device_printf(sc->dev, "Lancer firmware load error. " + "Addstatus = 0x%x, status = %d \n", add_status, rc); + rc = EIO; + } + oce_dma_free(sc, &dma_mem); + return rc; + +} + + +static void +oce_add_stats_sysctls_be3(POCE_SOFTC sc, + struct sysctl_ctx_list *ctx, + struct sysctl_oid *stats_node) +{ + struct sysctl_oid *rx_stats_node, *tx_stats_node; + struct sysctl_oid_list *rx_stat_list, *tx_stat_list; + struct sysctl_oid_list *queue_stats_list; + struct sysctl_oid *queue_stats_node; + struct oce_drv_stats *stats; + char prefix[32]; + int i; + + stats = &sc->oce_stats_info; + + rx_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(stats_node), + OID_AUTO,"rx", CTLFLAG_RD, + NULL, "RX Ethernet Statistics"); + rx_stat_list = SYSCTL_CHILDREN(rx_stats_node); + + + SYSCTL_ADD_QUAD(ctx, rx_stat_list, OID_AUTO, "total_pkts", + CTLFLAG_RD, &stats->rx.t_rx_pkts, + "Total Received Packets"); + SYSCTL_ADD_QUAD(ctx, rx_stat_list, OID_AUTO, "total_bytes", + CTLFLAG_RD, &stats->rx.t_rx_bytes, + "Total Received Bytes"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "total_frags", + CTLFLAG_RD, &stats->rx.t_rx_frags, 0, + "Total Received Fragements"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "total_mcast_pkts", + CTLFLAG_RD, &stats->rx.t_rx_mcast_pkts, 0, + "Total Received Multicast Packets"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "total_ucast_pkts", + CTLFLAG_RD, &stats->rx.t_rx_ucast_pkts, 0, + "Total Received Unicast Packets"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "total_rxcp_errs", + CTLFLAG_RD, &stats->rx.t_rxcp_errs, 0, + "Total Receive completion errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "pause_frames", + CTLFLAG_RD, &stats->u0.be.rx_pause_frames, 0, + "Pause Frames"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "priority_pause_frames", + CTLFLAG_RD, &stats->u0.be.rx_priority_pause_frames, 0, + "Priority Pause Frames"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "control_frames", + CTLFLAG_RD, &stats->u0.be.rx_control_frames, 0, + "Control Frames"); + + for (i = 0; i < sc->nrqs; i++) { + sprintf(prefix, "queue%d",i); + queue_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(rx_stats_node), + OID_AUTO, prefix, CTLFLAG_RD, + NULL, "Queue name"); + queue_stats_list = SYSCTL_CHILDREN(queue_stats_node); + + SYSCTL_ADD_QUAD(ctx, queue_stats_list, OID_AUTO, "rx_pkts", + CTLFLAG_RD, &sc->rq[i]->rx_stats.rx_pkts, + "Receive Packets"); + SYSCTL_ADD_QUAD(ctx, queue_stats_list, OID_AUTO, "rx_bytes", + CTLFLAG_RD, &sc->rq[i]->rx_stats.rx_bytes, + "Recived Bytes"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "rx_frags", + CTLFLAG_RD, &sc->rq[i]->rx_stats.rx_frags, 0, + "Received Fragments"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, + "rx_mcast_pkts", CTLFLAG_RD, + &sc->rq[i]->rx_stats.rx_mcast_pkts, 0, + "Received Multicast Packets"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, + "rx_ucast_pkts", CTLFLAG_RD, + &sc->rq[i]->rx_stats.rx_ucast_pkts, 0, + "Received Unicast Packets"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "rxcp_err", + CTLFLAG_RD, &sc->rq[i]->rx_stats.rxcp_err, 0, + "Received Completion Errors"); + + } + + rx_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(rx_stats_node), + OID_AUTO, "err", CTLFLAG_RD, + NULL, "Receive Error Stats"); + rx_stat_list = SYSCTL_CHILDREN(rx_stats_node); + + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "crc_errs", + CTLFLAG_RD, &stats->u0.be.rx_crc_errors, 0, + "CRC Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "pbuf_errors", + CTLFLAG_RD, &stats->u0.be.rx_drops_no_pbuf, 0, + "Drops due to pbuf full"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "erx_errors", + CTLFLAG_RD, &stats->u0.be.rx_drops_no_erx_descr, 0, + "ERX Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "alignment_errors", + CTLFLAG_RD, &stats->u0.be.rx_drops_too_many_frags, 0, + "RX Alignmnet Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "in_range_errors", + CTLFLAG_RD, &stats->u0.be.rx_in_range_errors, 0, + "In Range Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "out_range_errors", + CTLFLAG_RD, &stats->u0.be.rx_out_range_errors, 0, + "Out Range Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "frame_too_long", + CTLFLAG_RD, &stats->u0.be.rx_frame_too_long, 0, + "Frame Too Long"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "address_match_errors", + CTLFLAG_RD, &stats->u0.be.rx_address_match_errors, 0, + "Address Match Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "dropped_too_small", + CTLFLAG_RD, &stats->u0.be.rx_dropped_too_small, 0, + "Dropped Too Small"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "dropped_too_short", + CTLFLAG_RD, &stats->u0.be.rx_dropped_too_short, 0, + "Dropped Too Short"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, + "dropped_header_too_small", CTLFLAG_RD, + &stats->u0.be.rx_dropped_header_too_small, 0, + "Dropped Header Too Small"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "dropped_tcp_length", + CTLFLAG_RD, &stats->u0.be.rx_dropped_tcp_length, 0, + "Dropped TCP Length"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "dropped_runt", + CTLFLAG_RD, &stats->u0.be.rx_dropped_runt, 0, + "Dropped runt"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "ip_checksum_errs", + CTLFLAG_RD, &stats->u0.be.rx_ip_checksum_errs, 0, + "IP Checksum Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "tcp_checksum_errs", + CTLFLAG_RD, &stats->u0.be.rx_tcp_checksum_errs, 0, + "TCP Checksum Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "udp_checksum_errs", + CTLFLAG_RD, &stats->u0.be.rx_udp_checksum_errs, 0, + "UDP Checksum Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "fifo_overflow_drop", + CTLFLAG_RD, &stats->u0.be.rxpp_fifo_overflow_drop, 0, + "FIFO Overflow Drop"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, + "input_fifo_overflow_drop", CTLFLAG_RD, + &stats->u0.be.rx_input_fifo_overflow_drop, 0, + "Input FIFO Overflow Drop"); + + tx_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(stats_node), OID_AUTO, + "tx",CTLFLAG_RD, NULL, + "TX Ethernet Statistics"); + tx_stat_list = SYSCTL_CHILDREN(tx_stats_node); + + SYSCTL_ADD_QUAD(ctx, tx_stat_list, OID_AUTO, "total_tx_pkts", + CTLFLAG_RD, &stats->tx.t_tx_pkts, + "Total Transmit Packets"); + SYSCTL_ADD_QUAD(ctx, tx_stat_list, OID_AUTO, "total_tx_bytes", + CTLFLAG_RD, &stats->tx.t_tx_bytes, + "Total Transmit Bytes"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "total_tx_reqs", + CTLFLAG_RD, &stats->tx.t_tx_reqs, 0, + "Total Transmit Requests"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "total_tx_stops", + CTLFLAG_RD, &stats->tx.t_tx_stops, 0, + "Total Transmit Stops"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "total_tx_wrbs", + CTLFLAG_RD, &stats->tx.t_tx_wrbs, 0, + "Total Transmit WRB's"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "total_tx_compl", + CTLFLAG_RD, &stats->tx.t_tx_compl, 0, + "Total Transmit Completions"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, + "total_ipv6_ext_hdr_tx_drop", CTLFLAG_RD, + &stats->tx.t_ipv6_ext_hdr_tx_drop, 0, + "Total Transmit IPV6 Drops"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "pauseframes", + CTLFLAG_RD, &stats->u0.be.tx_pauseframes, 0, + "Pause Frames"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "priority_pauseframes", + CTLFLAG_RD, &stats->u0.be.tx_priority_pauseframes, 0, + "Priority Pauseframes"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "controlframes", + CTLFLAG_RD, &stats->u0.be.tx_controlframes, 0, + "Tx Control Frames"); + + for (i = 0; i < sc->nwqs; i++) { + sprintf(prefix, "queue%d",i); + queue_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(tx_stats_node), + OID_AUTO, prefix, CTLFLAG_RD, + NULL, "Queue name"); + queue_stats_list = SYSCTL_CHILDREN(queue_stats_node); + + SYSCTL_ADD_QUAD(ctx, queue_stats_list, OID_AUTO, "tx_pkts", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_pkts, + "Transmit Packets"); + SYSCTL_ADD_QUAD(ctx, queue_stats_list, OID_AUTO, "tx_bytes", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_bytes, + "Transmit Bytes"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "tx_reqs", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_reqs, 0, + "Transmit Requests"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "tx_stops", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_stops, 0, + "Transmit Stops"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "tx_wrbs", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_wrbs, 0, + "Transmit WRB's"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "tx_compl", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_compl, 0, + "Transmit Completions"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, + "ipv6_ext_hdr_tx_drop",CTLFLAG_RD, + &sc->wq[i]->tx_stats.ipv6_ext_hdr_tx_drop, 0, + "Transmit IPV6 Ext Header Drop"); + + } + return; +} + + +static void +oce_add_stats_sysctls_xe201(POCE_SOFTC sc, + struct sysctl_ctx_list *ctx, + struct sysctl_oid *stats_node) +{ + struct sysctl_oid *rx_stats_node, *tx_stats_node; + struct sysctl_oid_list *rx_stat_list, *tx_stat_list; + struct sysctl_oid_list *queue_stats_list; + struct sysctl_oid *queue_stats_node; + struct oce_drv_stats *stats; + char prefix[32]; + int i; + + stats = &sc->oce_stats_info; + + rx_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(stats_node), + OID_AUTO, "rx", CTLFLAG_RD, + NULL, "RX Ethernet Statistics"); + rx_stat_list = SYSCTL_CHILDREN(rx_stats_node); + + + SYSCTL_ADD_QUAD(ctx, rx_stat_list, OID_AUTO, "total_pkts", + CTLFLAG_RD, &stats->rx.t_rx_pkts, + "Total Received Packets"); + SYSCTL_ADD_QUAD(ctx, rx_stat_list, OID_AUTO, "total_bytes", + CTLFLAG_RD, &stats->rx.t_rx_bytes, + "Total Received Bytes"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "total_frags", + CTLFLAG_RD, &stats->rx.t_rx_frags, 0, + "Total Received Fragements"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "total_mcast_pkts", + CTLFLAG_RD, &stats->rx.t_rx_mcast_pkts, 0, + "Total Received Multicast Packets"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "total_ucast_pkts", + CTLFLAG_RD, &stats->rx.t_rx_ucast_pkts, 0, + "Total Received Unicast Packets"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "total_rxcp_errs", + CTLFLAG_RD, &stats->rx.t_rxcp_errs, 0, + "Total Receive completion errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "pause_frames", + CTLFLAG_RD, &stats->u0.xe201.rx_pause_frames, 0, + "Pause Frames"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "control_frames", + CTLFLAG_RD, &stats->u0.xe201.rx_control_frames, 0, + "Control Frames"); + + for (i = 0; i < sc->nrqs; i++) { + sprintf(prefix, "queue%d",i); + queue_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(rx_stats_node), + OID_AUTO, prefix, CTLFLAG_RD, + NULL, "Queue name"); + queue_stats_list = SYSCTL_CHILDREN(queue_stats_node); + + SYSCTL_ADD_QUAD(ctx, queue_stats_list, OID_AUTO, "rx_pkts", + CTLFLAG_RD, &sc->rq[i]->rx_stats.rx_pkts, + "Receive Packets"); + SYSCTL_ADD_QUAD(ctx, queue_stats_list, OID_AUTO, "rx_bytes", + CTLFLAG_RD, &sc->rq[i]->rx_stats.rx_bytes, + "Recived Bytes"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "rx_frags", + CTLFLAG_RD, &sc->rq[i]->rx_stats.rx_frags, 0, + "Received Fragments"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, + "rx_mcast_pkts", CTLFLAG_RD, + &sc->rq[i]->rx_stats.rx_mcast_pkts, 0, + "Received Multicast Packets"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, + "rx_ucast_pkts",CTLFLAG_RD, + &sc->rq[i]->rx_stats.rx_ucast_pkts, 0, + "Received Unicast Packets"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "rxcp_err", + CTLFLAG_RD, &sc->rq[i]->rx_stats.rxcp_err, 0, + "Received Completion Errors"); + + } + + rx_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(rx_stats_node), + OID_AUTO, "err", CTLFLAG_RD, + NULL, "Receive Error Stats"); + rx_stat_list = SYSCTL_CHILDREN(rx_stats_node); + + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "crc_errs", + CTLFLAG_RD, &stats->u0.xe201.rx_crc_errors, 0, + "CRC Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "alignment_errors", + CTLFLAG_RD, &stats->u0.xe201.rx_alignment_errors, 0, + "RX Alignmnet Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "in_range_errors", + CTLFLAG_RD, &stats->u0.xe201.rx_in_range_errors, 0, + "In Range Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "out_range_errors", + CTLFLAG_RD, &stats->u0.xe201.rx_out_of_range_errors, 0, + "Out Range Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "frame_too_long", + CTLFLAG_RD, &stats->u0.xe201.rx_frames_too_long, 0, + "Frame Too Long"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "address_match_errors", + CTLFLAG_RD, &stats->u0.xe201.rx_address_match_errors, 0, + "Address Match Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "dropped_too_small", + CTLFLAG_RD, &stats->u0.xe201.rx_dropped_too_small, 0, + "Dropped Too Small"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "dropped_too_short", + CTLFLAG_RD, &stats->u0.xe201.rx_dropped_too_short, 0, + "Dropped Too Short"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, + "dropped_header_too_small", CTLFLAG_RD, + &stats->u0.xe201.rx_dropped_header_too_small, 0, + "Dropped Header Too Small"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, + "dropped_tcp_length", CTLFLAG_RD, + &stats->u0.xe201.rx_dropped_invalid_tcp_length, 0, + "Dropped TCP Length"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "dropped_runt", + CTLFLAG_RD, &stats->u0.xe201.rx_dropped_runt, 0, + "Dropped runt"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "ip_checksum_errs", + CTLFLAG_RD, &stats->u0.xe201.rx_ip_checksum_errors, 0, + "IP Checksum Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "tcp_checksum_errs", + CTLFLAG_RD, &stats->u0.xe201.rx_tcp_checksum_errors, 0, + "TCP Checksum Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "udp_checksum_errs", + CTLFLAG_RD, &stats->u0.xe201.rx_udp_checksum_errors, 0, + "UDP Checksum Errors"); + SYSCTL_ADD_UINT(ctx, rx_stat_list, OID_AUTO, "input_fifo_overflow_drop", + CTLFLAG_RD, &stats->u0.xe201.rx_fifo_overflow, 0, + "Input FIFO Overflow Drop"); + + tx_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(stats_node), + OID_AUTO, "tx", CTLFLAG_RD, + NULL, "TX Ethernet Statistics"); + tx_stat_list = SYSCTL_CHILDREN(tx_stats_node); + + SYSCTL_ADD_QUAD(ctx, tx_stat_list, OID_AUTO, "total_tx_pkts", + CTLFLAG_RD, &stats->tx.t_tx_pkts, + "Total Transmit Packets"); + SYSCTL_ADD_QUAD(ctx, tx_stat_list, OID_AUTO, "total_tx_bytes", + CTLFLAG_RD, &stats->tx.t_tx_bytes, + "Total Transmit Bytes"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "total_tx_reqs", + CTLFLAG_RD, &stats->tx.t_tx_reqs, 0, + "Total Transmit Requests"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "total_tx_stops", + CTLFLAG_RD, &stats->tx.t_tx_stops, 0, + "Total Transmit Stops"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "total_tx_wrbs", + CTLFLAG_RD, &stats->tx.t_tx_wrbs, 0, + "Total Transmit WRB's"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "total_tx_compl", + CTLFLAG_RD, &stats->tx.t_tx_compl, 0, + "Total Transmit Completions"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, + "total_ipv6_ext_hdr_tx_drop", + CTLFLAG_RD, &stats->tx.t_ipv6_ext_hdr_tx_drop, 0, + "Total Transmit IPV6 Drops"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "pauseframes", + CTLFLAG_RD, &stats->u0.xe201.tx_pause_frames, 0, + "Pause Frames"); + SYSCTL_ADD_UINT(ctx, tx_stat_list, OID_AUTO, "controlframes", + CTLFLAG_RD, &stats->u0.xe201.tx_control_frames, 0, + "Tx Control Frames"); + + for (i = 0; i < sc->nwqs; i++) { + sprintf(prefix, "queue%d",i); + queue_stats_node = SYSCTL_ADD_NODE(ctx, + SYSCTL_CHILDREN(tx_stats_node), + OID_AUTO, prefix, CTLFLAG_RD, + NULL, "Queue name"); + queue_stats_list = SYSCTL_CHILDREN(queue_stats_node); + + SYSCTL_ADD_QUAD(ctx, queue_stats_list, OID_AUTO, "tx_pkts", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_pkts, + "Transmit Packets"); + SYSCTL_ADD_QUAD(ctx, queue_stats_list, OID_AUTO, "tx_bytes", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_bytes, + "Transmit Bytes"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "tx_reqs", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_reqs, 0, + "Transmit Requests"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "tx_stops", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_stops, 0, + "Transmit Stops"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "tx_wrbs", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_wrbs, 0, + "Transmit WRB's"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, "tx_compl", + CTLFLAG_RD, &sc->wq[i]->tx_stats.tx_compl, 0, + "Transmit Completions"); + SYSCTL_ADD_UINT(ctx, queue_stats_list, OID_AUTO, + "ipv6_ext_hdr_tx_drop", CTLFLAG_RD, + &sc->wq[i]->tx_stats.ipv6_ext_hdr_tx_drop, 0, + "Transmit IPV6 Ext Header Drop"); + + } + return; +} + + +void +oce_refresh_queue_stats(POCE_SOFTC sc) +{ + struct oce_drv_stats *adapter_stats; + int i; + + adapter_stats = &sc->oce_stats_info; + + /* Caluculate total TX and TXstats from all queues */ + + bzero(&adapter_stats->rx, sizeof(struct oce_rx_stats)); + for (i = 0; i < sc->nrqs; i++) { + + adapter_stats->rx.t_rx_pkts += sc->rq[i]->rx_stats.rx_pkts; + adapter_stats->rx.t_rx_bytes += sc->rq[i]->rx_stats.rx_bytes; + adapter_stats->rx.t_rx_frags += sc->rq[i]->rx_stats.rx_frags; + adapter_stats->rx.t_rx_mcast_pkts += + sc->rq[i]->rx_stats.rx_mcast_pkts; + adapter_stats->rx.t_rx_ucast_pkts += + sc->rq[i]->rx_stats.rx_ucast_pkts; + adapter_stats->rx.t_rxcp_errs += sc-> rq[i]->rx_stats.rxcp_err; + } + + bzero(&adapter_stats->tx, sizeof(struct oce_tx_stats)); + for (i = 0; i < sc->nwqs; i++) { + adapter_stats->tx.t_tx_reqs += sc->wq[i]->tx_stats.tx_reqs; + adapter_stats->tx.t_tx_stops += sc->wq[i]->tx_stats.tx_stops; + adapter_stats->tx.t_tx_wrbs += sc->wq[i]->tx_stats.tx_wrbs; + adapter_stats->tx.t_tx_compl += sc->wq[i]->tx_stats.tx_compl; + adapter_stats->tx.t_tx_bytes += sc->wq[i]->tx_stats.tx_bytes; + adapter_stats->tx.t_tx_pkts += sc->wq[i]->tx_stats.tx_pkts; + adapter_stats->tx.t_ipv6_ext_hdr_tx_drop += + sc->wq[i]->tx_stats.ipv6_ext_hdr_tx_drop; + } + +} + + + +static void +copy_stats_to_sc_xe201(POCE_SOFTC sc) +{ + struct oce_xe201_stats *adapter_stats; + struct mbx_get_pport_stats *nic_mbx; + struct pport_stats *port_stats; + + nic_mbx = OCE_DMAPTR(&sc->stats_mem, struct mbx_get_pport_stats); + port_stats = &nic_mbx->params.rsp.pps; + adapter_stats = &sc->oce_stats_info.u0.xe201; + + adapter_stats->tx_pkts = port_stats->tx_pkts; + adapter_stats->tx_unicast_pkts = port_stats->tx_unicast_pkts; + adapter_stats->tx_multicast_pkts = port_stats->tx_multicast_pkts; + adapter_stats->tx_broadcast_pkts = port_stats->tx_broadcast_pkts; + adapter_stats->tx_bytes = port_stats->tx_bytes; + adapter_stats->tx_unicast_bytes = port_stats->tx_unicast_bytes; + adapter_stats->tx_multicast_bytes = port_stats->tx_multicast_bytes; + adapter_stats->tx_broadcast_bytes = port_stats->tx_broadcast_bytes; + adapter_stats->tx_discards = port_stats->tx_discards; + adapter_stats->tx_errors = port_stats->tx_errors; + adapter_stats->tx_pause_frames = port_stats->tx_pause_frames; + adapter_stats->tx_pause_on_frames = port_stats->tx_pause_on_frames; + adapter_stats->tx_pause_off_frames = port_stats->tx_pause_off_frames; + adapter_stats->tx_internal_mac_errors = + port_stats->tx_internal_mac_errors; + adapter_stats->tx_control_frames = port_stats->tx_control_frames; + adapter_stats->tx_pkts_64_bytes = port_stats->tx_pkts_64_bytes; + adapter_stats->tx_pkts_65_to_127_bytes = + port_stats->tx_pkts_65_to_127_bytes; + adapter_stats->tx_pkts_128_to_255_bytes = + port_stats->tx_pkts_128_to_255_bytes; + adapter_stats->tx_pkts_256_to_511_bytes = + port_stats->tx_pkts_256_to_511_bytes; + adapter_stats->tx_pkts_512_to_1023_bytes = + port_stats->tx_pkts_512_to_1023_bytes; + adapter_stats->tx_pkts_1024_to_1518_bytes = + port_stats->tx_pkts_1024_to_1518_bytes; + adapter_stats->tx_pkts_1519_to_2047_bytes = + port_stats->tx_pkts_1519_to_2047_bytes; + adapter_stats->tx_pkts_2048_to_4095_bytes = + port_stats->tx_pkts_2048_to_4095_bytes; + adapter_stats->tx_pkts_4096_to_8191_bytes = + port_stats->tx_pkts_4096_to_8191_bytes; + adapter_stats->tx_pkts_8192_to_9216_bytes = + port_stats->tx_pkts_8192_to_9216_bytes; + adapter_stats->tx_lso_pkts = port_stats->tx_lso_pkts; + adapter_stats->rx_pkts = port_stats->rx_pkts; + adapter_stats->rx_unicast_pkts = port_stats->rx_unicast_pkts; + adapter_stats->rx_multicast_pkts = port_stats->rx_multicast_pkts; + adapter_stats->rx_broadcast_pkts = port_stats->rx_broadcast_pkts; + adapter_stats->rx_bytes = port_stats->rx_bytes; + adapter_stats->rx_unicast_bytes = port_stats->rx_unicast_bytes; + adapter_stats->rx_multicast_bytes = port_stats->rx_multicast_bytes; + adapter_stats->rx_broadcast_bytes = port_stats->rx_broadcast_bytes; + adapter_stats->rx_unknown_protos = port_stats->rx_unknown_protos; + adapter_stats->rx_discards = port_stats->rx_discards; + adapter_stats->rx_errors = port_stats->rx_errors; + adapter_stats->rx_crc_errors = port_stats->rx_crc_errors; + adapter_stats->rx_alignment_errors = port_stats->rx_alignment_errors; + adapter_stats->rx_symbol_errors = port_stats->rx_symbol_errors; + adapter_stats->rx_pause_frames = port_stats->rx_pause_frames; + adapter_stats->rx_pause_on_frames = port_stats->rx_pause_on_frames; + adapter_stats->rx_pause_off_frames = port_stats->rx_pause_off_frames; + adapter_stats->rx_frames_too_long = port_stats->rx_frames_too_long; + adapter_stats->rx_internal_mac_errors = + port_stats->rx_internal_mac_errors; + adapter_stats->rx_undersize_pkts = port_stats->rx_undersize_pkts; + adapter_stats->rx_oversize_pkts = port_stats->rx_oversize_pkts; + adapter_stats->rx_fragment_pkts = port_stats->rx_fragment_pkts; + adapter_stats->rx_jabbers = port_stats->rx_jabbers; + adapter_stats->rx_control_frames = port_stats->rx_control_frames; + adapter_stats->rx_control_frames_unknown_opcode = + port_stats->rx_control_frames_unknown_opcode; + adapter_stats->rx_in_range_errors = port_stats->rx_in_range_errors; + adapter_stats->rx_out_of_range_errors = + port_stats->rx_out_of_range_errors; + adapter_stats->rx_address_match_errors = + port_stats->rx_address_match_errors; + adapter_stats->rx_vlan_mismatch_errors = + port_stats->rx_vlan_mismatch_errors; + adapter_stats->rx_dropped_too_small = port_stats->rx_dropped_too_small; + adapter_stats->rx_dropped_too_short = port_stats->rx_dropped_too_short; + adapter_stats->rx_dropped_header_too_small = + port_stats->rx_dropped_header_too_small; + adapter_stats->rx_dropped_invalid_tcp_length = + port_stats->rx_dropped_invalid_tcp_length; + adapter_stats->rx_dropped_runt = port_stats->rx_dropped_runt; + adapter_stats->rx_ip_checksum_errors = + port_stats->rx_ip_checksum_errors; + adapter_stats->rx_tcp_checksum_errors = + port_stats->rx_tcp_checksum_errors; + adapter_stats->rx_udp_checksum_errors = + port_stats->rx_udp_checksum_errors; + adapter_stats->rx_non_rss_pkts = port_stats->rx_non_rss_pkts; + adapter_stats->rx_ipv4_pkts = port_stats->rx_ipv4_pkts; + adapter_stats->rx_ipv6_pkts = port_stats->rx_ipv6_pkts; + adapter_stats->rx_ipv4_bytes = port_stats->rx_ipv4_bytes; + adapter_stats->rx_ipv6_bytes = port_stats->rx_ipv6_bytes; + adapter_stats->rx_nic_pkts = port_stats->rx_nic_pkts; + adapter_stats->rx_tcp_pkts = port_stats->rx_tcp_pkts; + adapter_stats->rx_iscsi_pkts = port_stats->rx_iscsi_pkts; + adapter_stats->rx_management_pkts = port_stats->rx_management_pkts; + adapter_stats->rx_switched_unicast_pkts = + port_stats->rx_switched_unicast_pkts; + adapter_stats->rx_switched_multicast_pkts = + port_stats->rx_switched_multicast_pkts; + adapter_stats->rx_switched_broadcast_pkts = + port_stats->rx_switched_broadcast_pkts; + adapter_stats->num_forwards = port_stats->num_forwards; + adapter_stats->rx_fifo_overflow = port_stats->rx_fifo_overflow; + adapter_stats->rx_input_fifo_overflow = + port_stats->rx_input_fifo_overflow; + adapter_stats->rx_drops_too_many_frags = + port_stats->rx_drops_too_many_frags; + adapter_stats->rx_drops_invalid_queue = + port_stats->rx_drops_invalid_queue; + adapter_stats->rx_drops_mtu = port_stats->rx_drops_mtu; + adapter_stats->rx_pkts_64_bytes = port_stats->rx_pkts_64_bytes; + adapter_stats->rx_pkts_65_to_127_bytes = + port_stats->rx_pkts_65_to_127_bytes; + adapter_stats->rx_pkts_128_to_255_bytes = + port_stats->rx_pkts_128_to_255_bytes; + adapter_stats->rx_pkts_256_to_511_bytes = + port_stats->rx_pkts_256_to_511_bytes; + adapter_stats->rx_pkts_512_to_1023_bytes = + port_stats->rx_pkts_512_to_1023_bytes; + adapter_stats->rx_pkts_1024_to_1518_bytes = + port_stats->rx_pkts_1024_to_1518_bytes; + adapter_stats->rx_pkts_1519_to_2047_bytes = + port_stats->rx_pkts_1519_to_2047_bytes; + adapter_stats->rx_pkts_2048_to_4095_bytes = + port_stats->rx_pkts_2048_to_4095_bytes; + adapter_stats->rx_pkts_4096_to_8191_bytes = + port_stats->rx_pkts_4096_to_8191_bytes; + adapter_stats->rx_pkts_8192_to_9216_bytes = + port_stats->rx_pkts_8192_to_9216_bytes; +} + + + +static void +copy_stats_to_sc_be2(POCE_SOFTC sc) +{ + struct oce_be_stats *adapter_stats; + struct oce_pmem_stats *pmem; + struct oce_rxf_stats_v0 *rxf_stats; + struct oce_port_rxf_stats_v0 *port_stats; + struct mbx_get_nic_stats_v0 *nic_mbx; + uint32_t port = sc->port_id; + + nic_mbx = OCE_DMAPTR(&sc->stats_mem, struct mbx_get_nic_stats_v0); + pmem = &nic_mbx->params.rsp.stats.pmem; + rxf_stats = &nic_mbx->params.rsp.stats.rxf; + port_stats = &nic_mbx->params.rsp.stats.rxf.port[port]; + + adapter_stats = &sc->oce_stats_info.u0.be; + + + /* Update stats */ + adapter_stats->rx_pause_frames = port_stats->rx_pause_frames; + adapter_stats->rx_crc_errors = port_stats->rx_crc_errors; + adapter_stats->rx_control_frames = port_stats->rx_control_frames; + adapter_stats->rx_in_range_errors = port_stats->rx_in_range_errors; + adapter_stats->rx_frame_too_long = port_stats->rx_frame_too_long; + adapter_stats->rx_dropped_runt = port_stats->rx_dropped_runt; + adapter_stats->rx_ip_checksum_errs = port_stats->rx_ip_checksum_errs; + adapter_stats->rx_tcp_checksum_errs = port_stats->rx_tcp_checksum_errs; + adapter_stats->rx_udp_checksum_errs = port_stats->rx_udp_checksum_errs; + adapter_stats->rxpp_fifo_overflow_drop = + port_stats->rxpp_fifo_overflow_drop; + adapter_stats->rx_dropped_tcp_length = + port_stats->rx_dropped_tcp_length; + adapter_stats->rx_dropped_too_small = port_stats->rx_dropped_too_small; + adapter_stats->rx_dropped_too_short = port_stats->rx_dropped_too_short; + adapter_stats->rx_out_range_errors = port_stats->rx_out_range_errors; + adapter_stats->rx_dropped_header_too_small = + port_stats->rx_dropped_header_too_small; + adapter_stats->rx_input_fifo_overflow_drop = + port_stats->rx_input_fifo_overflow_drop; + adapter_stats->rx_address_match_errors = + port_stats->rx_address_match_errors; + adapter_stats->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + adapter_stats->tx_pauseframes = port_stats->tx_pauseframes; + adapter_stats->tx_controlframes = port_stats->tx_controlframes; + + if (sc->if_id) + adapter_stats->jabber_events = rxf_stats->port1_jabber_events; + else + adapter_stats->jabber_events = rxf_stats->port0_jabber_events; + + adapter_stats->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; + adapter_stats->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; + adapter_stats->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; + adapter_stats->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; + adapter_stats->forwarded_packets = rxf_stats->forwarded_packets; + adapter_stats->rx_drops_mtu = rxf_stats->rx_drops_mtu; + adapter_stats->rx_drops_no_tpre_descr = + rxf_stats->rx_drops_no_tpre_descr; + adapter_stats->rx_drops_too_many_frags = + rxf_stats->rx_drops_too_many_frags; + adapter_stats->eth_red_drops = pmem->eth_red_drops; +} + + +static void +copy_stats_to_sc_be3(POCE_SOFTC sc) +{ + struct oce_be_stats *adapter_stats; + struct oce_pmem_stats *pmem; + struct oce_rxf_stats_v1 *rxf_stats; + struct oce_port_rxf_stats_v1 *port_stats; + struct mbx_get_nic_stats *nic_mbx; + uint32_t port = sc->port_id; + + nic_mbx = OCE_DMAPTR(&sc->stats_mem, struct mbx_get_nic_stats); + pmem = &nic_mbx->params.rsp.stats.pmem; + rxf_stats = &nic_mbx->params.rsp.stats.rxf; + port_stats = &nic_mbx->params.rsp.stats.rxf.port[port]; + + adapter_stats = &sc->oce_stats_info.u0.be; + + /* Update stats */ + adapter_stats->pmem_fifo_overflow_drop = + port_stats->pmem_fifo_overflow_drop; + adapter_stats->rx_priority_pause_frames = + port_stats->rx_priority_pause_frames; + adapter_stats->rx_pause_frames = port_stats->rx_pause_frames; + adapter_stats->rx_crc_errors = port_stats->rx_crc_errors; + adapter_stats->rx_control_frames = port_stats->rx_control_frames; + adapter_stats->rx_in_range_errors = port_stats->rx_in_range_errors; + adapter_stats->rx_frame_too_long = port_stats->rx_frame_too_long; + adapter_stats->rx_dropped_runt = port_stats->rx_dropped_runt; + adapter_stats->rx_ip_checksum_errs = port_stats->rx_ip_checksum_errs; + adapter_stats->rx_tcp_checksum_errs = port_stats->rx_tcp_checksum_errs; + adapter_stats->rx_udp_checksum_errs = port_stats->rx_udp_checksum_errs; + adapter_stats->rx_dropped_tcp_length = + port_stats->rx_dropped_tcp_length; + adapter_stats->rx_dropped_too_small = port_stats->rx_dropped_too_small; + adapter_stats->rx_dropped_too_short = port_stats->rx_dropped_too_short; + adapter_stats->rx_out_range_errors = port_stats->rx_out_range_errors; + adapter_stats->rx_dropped_header_too_small = + port_stats->rx_dropped_header_too_small; + adapter_stats->rx_input_fifo_overflow_drop = + port_stats->rx_input_fifo_overflow_drop; + adapter_stats->rx_address_match_errors = + port_stats->rx_address_match_errors; + adapter_stats->rx_alignment_symbol_errors = + port_stats->rx_alignment_symbol_errors; + adapter_stats->rxpp_fifo_overflow_drop = + port_stats->rxpp_fifo_overflow_drop; + adapter_stats->tx_pauseframes = port_stats->tx_pauseframes; + adapter_stats->tx_controlframes = port_stats->tx_controlframes; + adapter_stats->jabber_events = port_stats->jabber_events; + + adapter_stats->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; + adapter_stats->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; + adapter_stats->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; + adapter_stats->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; + adapter_stats->forwarded_packets = rxf_stats->forwarded_packets; + adapter_stats->rx_drops_mtu = rxf_stats->rx_drops_mtu; + adapter_stats->rx_drops_no_tpre_descr = + rxf_stats->rx_drops_no_tpre_descr; + adapter_stats->rx_drops_too_many_frags = + rxf_stats->rx_drops_too_many_frags; + + adapter_stats->eth_red_drops = pmem->eth_red_drops; +} + + +int +oce_stats_init(POCE_SOFTC sc) +{ + int rc = 0, sz; + + if (IS_BE(sc)) { + if (sc->flags & OCE_FLAGS_BE2) + sz = sizeof(struct mbx_get_nic_stats_v0); + else + sz = sizeof(struct mbx_get_nic_stats); + } else + sz = sizeof(struct mbx_get_pport_stats); + + rc = oce_dma_alloc(sc, sz, &sc->stats_mem, 0); + + return rc; +} + + +void +oce_stats_free(POCE_SOFTC sc) +{ + + oce_dma_free(sc, &sc->stats_mem); + +} + + +int +oce_refresh_nic_stats(POCE_SOFTC sc) +{ + int rc = 0, reset = 0; + + if (IS_BE(sc)) { + if (sc->flags & OCE_FLAGS_BE2) { + rc = oce_mbox_get_nic_stats_v0(sc, &sc->stats_mem); + if (!rc) + copy_stats_to_sc_be2(sc); + } else { + rc = oce_mbox_get_nic_stats(sc, &sc->stats_mem); + if (!rc) + copy_stats_to_sc_be3(sc); + } + + } else { + rc = oce_mbox_get_pport_stats(sc, &sc->stats_mem, reset); + if (!rc) + copy_stats_to_sc_xe201(sc); + } + + return rc; +} diff --git a/sys/dev/oce/oce_util.c b/sys/dev/oce/oce_util.c new file mode 100644 index 000000000000..93b13bd0bb7c --- /dev/null +++ b/sys/dev/oce/oce_util.c @@ -0,0 +1,270 @@ +/*- + * Copyright (C) 2012 Emulex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Emulex Corporation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contact Information: + * freebsd-drivers@emulex.com + * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626 + */ + + +/* $FreeBSD$ */ + + +#include "oce_if.h" + +static void oce_dma_map_ring(void *arg, + bus_dma_segment_t *segs, + int nseg, + int error); + +/** + * @brief Allocate DMA memory + * @param sc software handle to the device + * @param size bus size + * @param dma dma memory area + * @param flags creation flags + * @returns 0 on success, error otherwize + */ +int +oce_dma_alloc(POCE_SOFTC sc, bus_size_t size, POCE_DMA_MEM dma, int flags) +{ + int rc; + + + memset(dma, 0, sizeof(OCE_DMA_MEM)); + + rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), + 8, 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, NULL, + size, 1, size, 0, NULL, NULL, &dma->tag); + + if (rc == 0) { + rc = bus_dmamem_alloc(dma->tag, + &dma->ptr, + BUS_DMA_NOWAIT | BUS_DMA_COHERENT, + &dma->map); + } + + dma->paddr = 0; + if (rc == 0) { + rc = bus_dmamap_load(dma->tag, + dma->map, + dma->ptr, + size, + oce_dma_map_addr, + &dma->paddr, flags | BUS_DMA_NOWAIT); + if (dma->paddr == 0) + rc = ENXIO; + } + + if (rc != 0) + oce_dma_free(sc, dma); + + return rc; +} + +/** + * @brief Free DMA memory + * @param sc software handle to the device + * @param dma dma area to free + */ +void +oce_dma_free(POCE_SOFTC sc, POCE_DMA_MEM dma) +{ + if (dma->tag == NULL) + return; + + if (dma->map != NULL) { + bus_dmamap_sync(dma->tag, dma->map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(dma->tag, dma->map); + } + + if (dma->ptr != NULL) { + bus_dmamem_free(dma->tag, dma->ptr, dma->map); + dma->map = NULL; + dma->ptr = NULL; + } + + bus_dma_tag_destroy(dma->tag); + dma->tag = NULL; + + return; +} + + + +/** + * @brief Map DMA memory segment addresses + * @param arg physical address pointer + * @param segs dma memory segments + * @param nseg number of dma memory segments + * @param error if error, zeroes the physical address + */ +void +oce_dma_map_addr(void *arg, bus_dma_segment_t * segs, int nseg, int error) +{ + bus_addr_t *paddr = arg; + + if (error) + *paddr = 0; + else + *paddr = segs->ds_addr; +} + + + +/** + * @brief Destroy a ring buffer + * @param sc software handle to the device + * @param ring ring buffer + */ + +void +oce_destroy_ring_buffer(POCE_SOFTC sc, oce_ring_buffer_t *ring) +{ + oce_dma_free(sc, &ring->dma); + free(ring, M_DEVBUF); +} + + + +oce_ring_buffer_t * +oce_create_ring_buffer(POCE_SOFTC sc, + uint32_t q_len, uint32_t item_size) +{ + uint32_t size = q_len * item_size; + int rc; + oce_ring_buffer_t *ring; + + + ring = malloc(sizeof(oce_ring_buffer_t), M_DEVBUF, M_NOWAIT | M_ZERO); + if (ring == NULL) + return NULL; + + ring->item_size = item_size; + ring->num_items = q_len; + + rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), + 4096, 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, NULL, + size, 8, 4096, 0, NULL, NULL, &ring->dma.tag); + if (rc) + goto fail; + + + rc = bus_dmamem_alloc(ring->dma.tag, + &ring->dma.ptr, + BUS_DMA_NOWAIT | BUS_DMA_COHERENT, + &ring->dma.map); + if (rc) + goto fail; + + bzero(ring->dma.ptr, size); + bus_dmamap_sync(ring->dma.tag, ring->dma.map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + ring->dma.paddr = 0; + + return ring; + +fail: + oce_dma_free(sc, &ring->dma); + free(ring, M_DEVBUF); + ring = NULL; + return NULL; +} + + + +struct _oce_dmamap_paddr_table { + uint32_t max_entries; + uint32_t num_entries; + struct phys_addr *paddrs; +}; + + + +/** + * @brief Map ring buffer + * @param arg dma map phyical address table pointer + * @param segs dma memory segments + * @param nseg number of dma memory segments + * @param error maps only if error is 0 + */ +static void +oce_dma_map_ring(void *arg, bus_dma_segment_t * segs, int nseg, int error) +{ + int i; + struct _oce_dmamap_paddr_table *dpt = + (struct _oce_dmamap_paddr_table *)arg; + + if (error == 0) { + if (nseg <= dpt->max_entries) { + for (i = 0; i < nseg; i++) { + dpt->paddrs[i].lo = ADDR_LO(segs[i].ds_addr); + dpt->paddrs[i].hi = ADDR_HI(segs[i].ds_addr); + } + dpt->num_entries = nseg; + } + } +} + + + +/** + * @brief Load bus dma map for a ring buffer + * @param ring ring buffer pointer + * @param pa_list physical address list + * @returns number entries + */ +uint32_t +oce_page_list(oce_ring_buffer_t *ring, struct phys_addr *pa_list) +{ + struct _oce_dmamap_paddr_table dpt; + + dpt.max_entries = 8; + dpt.num_entries = 0; + dpt.paddrs = pa_list; + + bus_dmamap_load(ring->dma.tag, + ring->dma.map, + ring->dma.ptr, + ring->item_size * ring->num_items, + oce_dma_map_ring, &dpt, BUS_DMA_NOWAIT); + + return dpt.num_entries; +} diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index b4b67fb8969f..e120dbc67a28 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #define PCIR_IS_BIOS(cfg, reg) \ (((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) || \ ((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1)) - static pci_addr_t pci_mapbase(uint64_t mapreg); static const char *pci_maptype(uint64_t mapreg); @@ -171,7 +170,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_msi_count, pci_msi_count_method), DEVMETHOD(pci_msix_count, pci_msix_count_method), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_0(pci, pci_driver, pci_methods, 0); @@ -183,7 +182,6 @@ MODULE_VERSION(pci, 1); static char *pci_vendordata; static size_t pci_vendordata_size; - struct pci_quirk { uint32_t devid; /* Vendor/device of the card */ int type; @@ -194,7 +192,7 @@ struct pci_quirk { int arg2; }; -struct pci_quirk pci_quirks[] = { +static const struct pci_quirk const pci_quirks[] = { /* The Intel 82371AB and 82443MX has a map register at offset 0x90. */ { 0x71138086, PCI_QUIRK_MAP_REG, 0x90, 0 }, { 0x719b8086, PCI_QUIRK_MAP_REG, 0x90, 0 }, @@ -226,6 +224,12 @@ struct pci_quirk pci_quirks[] = { */ { 0x74501022, PCI_QUIRK_DISABLE_MSI, 0, 0 }, + /* + * MSI-X doesn't work with at least LSI SAS1068E passed through by + * VMware. + */ + { 0x079015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, + /* * Some virtualization environments emulate an older chipset * but support MSI just fine. QEMU uses the Intel 82440. @@ -724,7 +728,6 @@ pci_read_cap(device_t pcib, pcicfgregs *cfg) } } - #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) /* * Enable the MSI mapping window for all HyperTransport @@ -1873,7 +1876,7 @@ pci_remap_intr_method(device_t bus, device_t dev, u_int irq) int pci_msi_device_blacklisted(device_t dev) { - struct pci_quirk *q; + const struct pci_quirk *q; if (!pci_honor_msi_blacklist) return (0); @@ -1893,7 +1896,7 @@ pci_msi_device_blacklisted(device_t dev) static int pci_msi_vm_chipset(device_t dev) { - struct pci_quirk *q; + const struct pci_quirk *q; for (q = &pci_quirks[0]; q->devid; q++) { if (q->devid == pci_get_devid(dev) && @@ -3023,7 +3026,7 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) struct pci_devinfo *dinfo = device_get_ivars(dev); pcicfgregs *cfg = &dinfo->cfg; struct resource_list *rl = &dinfo->resources; - struct pci_quirk *q; + const struct pci_quirk *q; int i; /* ATA devices needs special map treatment */ @@ -3864,7 +3867,6 @@ pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) } } - #include "opt_ddb.h" #ifdef DDB #include @@ -4021,7 +4023,6 @@ out:; return (res); } - struct resource * pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c index 0142308ec0cc..916d6ea172ca 100644 --- a/sys/dev/re/if_re.c +++ b/sys/dev/re/if_re.c @@ -1433,11 +1433,16 @@ re_attach(device_t dev) sc->rl_flags |= RL_FLAG_MACSLEEP; /* FALLTHROUGH */ case RL_HWREV_8168CP: - case RL_HWREV_8168D: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 | RL_FLAG_WOL_MANLINK; break; + case RL_HWREV_8168D: + sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM | + RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | + RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 | + RL_FLAG_WOL_MANLINK; + break; case RL_HWREV_8168DP: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_AUTOPAD | diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index e07115506092..0bbf608028fe 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -74,6 +74,8 @@ __FBSDID("$FreeBSD$"); #define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL (1<<7) /* Controller has broken read timings */ #define SDHCI_QUIRK_BROKEN_TIMINGS (1<<8) +/* Controller needs lowered frequency */ +#define SDHCI_QUIRK_LOWER_FREQUENCY (1<<9) static const struct sdhci_device { uint32_t model; @@ -85,6 +87,8 @@ static const struct sdhci_device { SDHCI_QUIRK_FORCE_DMA }, { 0xe8221180, 0xffff, "RICOH SD", SDHCI_QUIRK_FORCE_DMA }, + { 0xe8231180, 0xffff, "RICOH R5CE823 SD", + SDHCI_QUIRK_LOWER_FREQUENCY }, { 0x8034104c, 0xffff, "TI XX21/XX11 SD", SDHCI_QUIRK_FORCE_DMA }, { 0x05501524, 0xffff, "ENE CB712 SD", @@ -349,6 +353,24 @@ sdhci_init(struct sdhci_slot *slot) WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask); } +static void +sdhci_lower_frequency(device_t dev) +{ + + /* Enable SD2.0 mode. */ + pci_write_config(dev, SDHC_PCI_MODE_KEY, 0xfc, 1); + pci_write_config(dev, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20, 1); + pci_write_config(dev, SDHC_PCI_MODE_KEY, 0x00, 1); + + /* + * Some SD/MMC cards don't work with the default base + * clock frequency of 200MHz. Lower it to 50Hz. + */ + pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x01, 1); + pci_write_config(dev, SDHC_PCI_BASE_FREQ, 50, 1); + pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x00, 1); +} + static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) { @@ -631,6 +653,9 @@ sdhci_attach(device_t dev) break; } } + /* Some controllers need to be bumped into the right mode. */ + if (sc->quirks & SDHCI_QUIRK_LOWER_FREQUENCY) + sdhci_lower_frequency(dev); /* Read slots info from PCI registers. */ slots = pci_read_config(dev, PCI_SLOT_INFO, 1); bar = PCI_SLOT_INFO_FIRST_BAR(slots); diff --git a/sys/dev/sdhci/sdhci.h b/sys/dev/sdhci/sdhci.h index a0ad1335e681..5c0253e3efdf 100644 --- a/sys/dev/sdhci/sdhci.h +++ b/sys/dev/sdhci/sdhci.h @@ -37,6 +37,15 @@ #define PCI_SLOT_INFO_SLOTS(x) (((x >> 4) & 7) + 1) #define PCI_SLOT_INFO_FIRST_BAR(x) ((x) & 7) +/* + * RICOH specific PCI registers + */ +#define SDHC_PCI_MODE_KEY 0xf9 +#define SDHC_PCI_MODE 0x150 +#define SDHC_PCI_MODE_SD20 0x10 +#define SDHC_PCI_BASE_FREQ_KEY 0xfc +#define SDHC_PCI_BASE_FREQ 0xe1 + /* * Controller registers */ diff --git a/sys/dev/sound/pci/hda/hdacc.c b/sys/dev/sound/pci/hda/hdacc.c index 5e5a8dda37d1..740b2c5480ba 100644 --- a/sys/dev/sound/pci/hda/hdacc.c +++ b/sys/dev/sound/pci/hda/hdacc.c @@ -612,7 +612,7 @@ hdacc_stream_intr(device_t dev, int dir, int stream) struct hdacc_softc *codec = device_get_softc(dev); device_t child; - if ((child = codec->streams[dir][stream]) != NULL); + if ((child = codec->streams[dir][stream]) != NULL) HDAC_STREAM_INTR(child, dir, stream); } diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c index 58b9326703b0..7a2433229b70 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -1463,7 +1463,7 @@ mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi) * * XXX Described by Hannu@4Front, but not found in * soundcard.h. - strlcpy(mi->devnode, d->mixer_dev->si_name, + strlcpy(mi->devnode, devtoname(d->mixer_dev), sizeof(mi->devnode)); mi->legacy_device = i; */ diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c index 958065f3a541..4a813dab2351 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -1415,7 +1415,6 @@ sound_modevent(module_t mod, int type, void *data) pcmsg_unrhdr = new_unrhdr(1, INT_MAX, NULL); break; case MOD_UNLOAD: - case MOD_SHUTDOWN: ret = sndstat_acquire(curthread); if (ret != 0) break; @@ -1424,6 +1423,8 @@ sound_modevent(module_t mod, int type, void *data) pcmsg_unrhdr = NULL; } break; + case MOD_SHUTDOWN: + break; default: ret = ENOTSUP; } diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c index 3d59ad9462fc..dfbbe26d5aad 100644 --- a/sys/dev/usb/serial/u3g.c +++ b/sys/dev/usb/serial/u3g.c @@ -433,6 +433,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = { U3G_DEV(QUANTA, Q111, 0), U3G_DEV(SIERRA, AC402, 0), U3G_DEV(SIERRA, AC595U, 0), + U3G_DEV(SIERRA, AC313U, 0), U3G_DEV(SIERRA, AC597E, 0), U3G_DEV(SIERRA, AC875E, 0), U3G_DEV(SIERRA, AC875U, 0), diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c index e2c934e8d4d6..2b99036410fa 100644 --- a/sys/dev/usb/usb_dev.c +++ b/sys/dev/usb/usb_dev.c @@ -842,7 +842,7 @@ usb_open(struct cdev *dev, int fflags, int devtype, struct thread *td) struct usb_cdev_privdata *cpd; int err, ep; - DPRINTFN(2, "%s fflags=0x%08x\n", dev->si_name, fflags); + DPRINTFN(2, "%s fflags=0x%08x\n", devtoname(dev), fflags); KASSERT(fflags & (FREAD|FWRITE), ("invalid open flags")); if (((fflags & FREAD) && !(pd->mode & FREAD)) || diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 352568942efa..c43d5f929c79 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -3005,6 +3005,7 @@ product SIERRA E6892 0x6892 E6892 product SIERRA E6893 0x6893 E6893 product SIERRA MC8700 0x68A3 MC8700 product SIERRA AIRCARD875 0x6820 Aircard 875 HSDPA +product SIERRA AC313U 0x68aa Sierra Wireless AirCard 313U product SIERRA TRUINSTALL 0x0fff Aircard Tru Installer /* Sigmatel products */ diff --git a/sys/dev/vge/if_vge.c b/sys/dev/vge/if_vge.c index a49af277f53e..402a55c5e228 100644 --- a/sys/dev/vge/if_vge.c +++ b/sys/dev/vge/if_vge.c @@ -2022,11 +2022,9 @@ static void vge_init_locked(struct vge_softc *sc) { struct ifnet *ifp = sc->vge_ifp; - struct mii_data *mii; int error, i; VGE_LOCK_ASSERT(sc); - mii = device_get_softc(sc->vge_miibus); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) return; diff --git a/sys/dev/wtap/if_wtap.c b/sys/dev/wtap/if_wtap.c index c257517ad51a..41693685829e 100644 --- a/sys/dev/wtap/if_wtap.c +++ b/sys/dev/wtap/if_wtap.c @@ -84,7 +84,7 @@ wtap_node_write(struct cdev *dev, struct uio *uio, int ioflag) uint8_t buf[1024]; int buf_len; - uprintf("write device %s \"echo.\"\n", dev->si_name); + uprintf("write device %s \"echo.\"\n", devtoname(dev)); buf_len = MIN(uio->uio_iov->iov_len, 1024); err = copyin(uio->uio_iov->iov_base, buf, buf_len); @@ -101,7 +101,7 @@ wtap_node_write(struct cdev *dev, struct uio *uio, int ioflag) TAILQ_FOREACH(ifp, &V_ifnet, if_link) { printf("ifp->if_xname = %s\n", ifp->if_xname); - if(strcmp(dev->si_name, ifp->if_xname) == 0){ + if(strcmp(devtoname(dev), ifp->if_xname) == 0){ printf("found match, correspoding wtap = %s\n", ifp->if_xname); sc = (struct wtap_softc *)ifp->if_softc; diff --git a/sys/dev/wtap/if_wtap_module.c b/sys/dev/wtap/if_wtap_module.c index d0108af7e029..7a87d570b3d1 100644 --- a/sys/dev/wtap/if_wtap_module.c +++ b/sys/dev/wtap/if_wtap_module.c @@ -184,3 +184,4 @@ static moduledata_t wtap_conf = { }; DECLARE_MODULE(wtap, wtap_conf, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); +MODULE_DEPEND(wtap, wlan, 1, 1, 1); /* 802.11 media layer */ diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c index c6ab5621d897..15e5a2966522 100644 --- a/sys/dev/xen/blkback/blkback.c +++ b/sys/dev/xen/blkback/blkback.c @@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$"); * a FreeBSD domain to other domains. */ +#include "opt_kdtrace.h" + #include #include #include @@ -63,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -124,7 +127,7 @@ __FBSDID("$FreeBSD$"); static MALLOC_DEFINE(M_XENBLOCKBACK, "xbbd", "Xen Block Back Driver Data"); #ifdef XBB_DEBUG -#define DPRINTF(fmt, args...) \ +#define DPRINTF(fmt, args...) \ printf("xbb(%s:%d): " fmt, __FUNCTION__, __LINE__, ##args) #else #define DPRINTF(fmt, args...) do {} while(0) @@ -134,7 +137,7 @@ static MALLOC_DEFINE(M_XENBLOCKBACK, "xbbd", "Xen Block Back Driver Data"); * The maximum mapped region size per request we will allow in a negotiated * block-front/back communication channel. */ -#define XBB_MAX_REQUEST_SIZE \ +#define XBB_MAX_REQUEST_SIZE \ MIN(MAXPHYS, BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) /** @@ -142,9 +145,9 @@ static MALLOC_DEFINE(M_XENBLOCKBACK, "xbbd", "Xen Block Back Driver Data"); * segment blocks) per request we will allow in a negotiated block-front/back * communication channel. */ -#define XBB_MAX_SEGMENTS_PER_REQUEST \ - (MIN(UIO_MAXIOV, \ - MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST, \ +#define XBB_MAX_SEGMENTS_PER_REQUEST \ + (MIN(UIO_MAXIOV, \ + MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST, \ (XBB_MAX_REQUEST_SIZE / PAGE_SIZE) + 1))) /** @@ -980,9 +983,10 @@ xbb_get_gntaddr(struct xbb_xen_reqlist *reqlist, int pagenr, int sector) static uint8_t * xbb_get_kva(struct xbb_softc *xbb, int nr_pages) { - intptr_t first_clear, num_clear; + intptr_t first_clear; + intptr_t num_clear; uint8_t *free_kva; - int i; + int i; KASSERT(nr_pages != 0, ("xbb_get_kva of zero length")); @@ -1681,19 +1685,19 @@ xbb_dispatch_io(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist) req_ring_idx++; switch (xbb->abi) { case BLKIF_PROTOCOL_NATIVE: - sg = BLKRING_GET_SG_REQUEST(&xbb->rings.native, - req_ring_idx); + sg = BLKRING_GET_SEG_BLOCK(&xbb->rings.native, + req_ring_idx); break; case BLKIF_PROTOCOL_X86_32: { - sg = BLKRING_GET_SG_REQUEST(&xbb->rings.x86_32, - req_ring_idx); + sg = BLKRING_GET_SEG_BLOCK(&xbb->rings.x86_32, + req_ring_idx); break; } case BLKIF_PROTOCOL_X86_64: { - sg = BLKRING_GET_SG_REQUEST(&xbb->rings.x86_64, - req_ring_idx); + sg = BLKRING_GET_SEG_BLOCK(&xbb->rings.x86_64, + req_ring_idx); break; } default: @@ -1817,8 +1821,8 @@ xbb_run_queue(void *context, int pending) struct xbb_xen_reqlist *reqlist; - xbb = (struct xbb_softc *)context; - rings = &xbb->rings; + xbb = (struct xbb_softc *)context; + rings = &xbb->rings; /* * Work gather and dispatch loop. Note that we have a bias here @@ -2032,6 +2036,13 @@ xbb_intr(void *arg) taskqueue_enqueue(xbb->io_taskqueue, &xbb->io_task); } +SDT_PROVIDER_DEFINE(xbb); +SDT_PROBE_DEFINE1(xbb, kernel, xbb_dispatch_dev, flush, flush, "int"); +SDT_PROBE_DEFINE3(xbb, kernel, xbb_dispatch_dev, read, read, "int", "uint64_t", + "uint64_t"); +SDT_PROBE_DEFINE3(xbb, kernel, xbb_dispatch_dev, write, write, "int", + "uint64_t", "uint64_t"); + /*----------------------------- Backend Handlers -----------------------------*/ /** * Backend handler for character device access. @@ -2087,6 +2098,9 @@ xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, nreq->pendcnt = 1; + SDT_PROBE1(xbb, kernel, xbb_dispatch_dev, flush, + device_get_unit(xbb->dev)); + (*dev_data->csw->d_strategy)(bio); return (0); @@ -2181,6 +2195,17 @@ xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, bios[bio_idx]->bio_bcount); } #endif + if (operation == BIO_READ) { + SDT_PROBE3(xbb, kernel, xbb_dispatch_dev, read, + device_get_unit(xbb->dev), + bios[bio_idx]->bio_offset, + bios[bio_idx]->bio_length); + } else if (operation == BIO_WRITE) { + SDT_PROBE3(xbb, kernel, xbb_dispatch_dev, write, + device_get_unit(xbb->dev), + bios[bio_idx]->bio_offset, + bios[bio_idx]->bio_length); + } (*dev_data->csw->d_strategy)(bios[bio_idx]); } @@ -2193,6 +2218,12 @@ xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, return (error); } +SDT_PROBE_DEFINE1(xbb, kernel, xbb_dispatch_file, flush, flush, "int"); +SDT_PROBE_DEFINE3(xbb, kernel, xbb_dispatch_file, read, read, "int", "uint64_t", + "uint64_t"); +SDT_PROBE_DEFINE3(xbb, kernel, xbb_dispatch_file, write, write, "int", + "uint64_t", "uint64_t"); + /** * Backend handler for file access. * @@ -2237,6 +2268,9 @@ xbb_dispatch_file(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, case BIO_FLUSH: { struct mount *mountpoint; + SDT_PROBE1(xbb, kernel, xbb_dispatch_file, flush, + device_get_unit(xbb->dev)); + vfs_is_locked = VFS_LOCK_GIANT(xbb->vn->v_mount); (void) vn_start_write(xbb->vn, &mountpoint, V_WAIT); @@ -2336,6 +2370,10 @@ xbb_dispatch_file(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, switch (operation) { case BIO_READ: + SDT_PROBE3(xbb, kernel, xbb_dispatch_file, read, + device_get_unit(xbb->dev), xuio.uio_offset, + xuio.uio_resid); + vn_lock(xbb->vn, LK_EXCLUSIVE | LK_RETRY); /* @@ -2366,6 +2404,10 @@ xbb_dispatch_file(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, case BIO_WRITE: { struct mount *mountpoint; + SDT_PROBE3(xbb, kernel, xbb_dispatch_file, write, + device_get_unit(xbb->dev), xuio.uio_offset, + xuio.uio_resid); + (void)vn_start_write(xbb->vn, &mountpoint, V_WAIT); vn_lock(xbb->vn, LK_EXCLUSIVE | LK_RETRY); @@ -3028,6 +3070,8 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) const char *otherend_path; int error; u_int ring_idx; + u_int ring_page_order; + size_t ring_size; otherend_path = xenbus_get_otherend_path(xbb->dev); @@ -3035,23 +3079,19 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) * Protocol defaults valid even if all negotiation fails. */ xbb->ring_config.ring_pages = 1; - xbb->max_requests = BLKIF_MAX_RING_REQUESTS(PAGE_SIZE); xbb->max_request_segments = BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK; xbb->max_request_size = xbb->max_request_segments * PAGE_SIZE; /* * Mandatory data (used in all versions of the protocol) first. */ - error = xs_gather(XST_NIL, otherend_path, - "ring-ref", "%" PRIu32, - &xbb->ring_config.ring_ref[0], - "event-channel", "%" PRIu32, - &xbb->ring_config.evtchn, - NULL); + error = xs_scanf(XST_NIL, otherend_path, + "event-channel", NULL, "%" PRIu32, + &xbb->ring_config.evtchn); if (error != 0) { xenbus_dev_fatal(xbb->dev, error, - "Unable to retrieve ring information from " - "frontend %s. Unable to connect.", + "Unable to retrieve event-channel information " + "from frontend %s. Unable to connect.", xenbus_get_otherend_path(xbb->dev)); return (error); } @@ -3065,10 +3105,20 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) * we must use independant calls in order to guarantee * we don't miss information in a sparsly populated front-end * tree. + * + * \note xs_scanf() does not update variables for unmatched + * fields. */ + ring_page_order = 0; (void)xs_scanf(XST_NIL, otherend_path, - "ring-pages", NULL, "%u", + "ring-page-order", NULL, "%u", + &ring_page_order); + xbb->ring_config.ring_pages = 1 << ring_page_order; + (void)xs_scanf(XST_NIL, otherend_path, + "num-ring-pages", NULL, "%u", &xbb->ring_config.ring_pages); + ring_size = PAGE_SIZE * xbb->ring_config.ring_pages; + xbb->max_requests = BLKIF_MAX_RING_REQUESTS(ring_size); (void)xs_scanf(XST_NIL, otherend_path, "max-requests", NULL, "%u", @@ -3084,7 +3134,7 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) if (xbb->ring_config.ring_pages > XBB_MAX_RING_PAGES) { xenbus_dev_fatal(xbb->dev, EINVAL, - "Front-end specificed ring-pages of %u " + "Front-end specified ring-pages of %u " "exceeds backend limit of %zu. " "Unable to connect.", xbb->ring_config.ring_pages, @@ -3092,7 +3142,7 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) return (EINVAL); } else if (xbb->max_requests > XBB_MAX_REQUESTS) { xenbus_dev_fatal(xbb->dev, EINVAL, - "Front-end specificed max_requests of %u " + "Front-end specified max_requests of %u " "exceeds backend limit of %u. " "Unable to connect.", xbb->max_requests, @@ -3100,7 +3150,7 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) return (EINVAL); } else if (xbb->max_request_segments > XBB_MAX_SEGMENTS_PER_REQUEST) { xenbus_dev_fatal(xbb->dev, EINVAL, - "Front-end specificed max_requests_segments " + "Front-end specified max_requests_segments " "of %u exceeds backend limit of %u. " "Unable to connect.", xbb->max_request_segments, @@ -3108,7 +3158,7 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) return (EINVAL); } else if (xbb->max_request_size > XBB_MAX_REQUEST_SIZE) { xenbus_dev_fatal(xbb->dev, EINVAL, - "Front-end specificed max_request_size " + "Front-end specified max_request_size " "of %u exceeds backend limit of %u. " "Unable to connect.", xbb->max_request_size, @@ -3116,22 +3166,39 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) return (EINVAL); } - /* If using a multi-page ring, pull in the remaining references. */ - for (ring_idx = 1; ring_idx < xbb->ring_config.ring_pages; ring_idx++) { - char ring_ref_name[]= "ring_refXX"; - - snprintf(ring_ref_name, sizeof(ring_ref_name), - "ring-ref%u", ring_idx); - error = xs_scanf(XST_NIL, otherend_path, - ring_ref_name, NULL, "%" PRIu32, - &xbb->ring_config.ring_ref[ring_idx]); + if (xbb->ring_config.ring_pages == 1) { + error = xs_gather(XST_NIL, otherend_path, + "ring-ref", "%" PRIu32, + &xbb->ring_config.ring_ref[0], + NULL); if (error != 0) { xenbus_dev_fatal(xbb->dev, error, - "Failed to retriev grant reference " - "for page %u of shared ring. Unable " - "to connect.", ring_idx); + "Unable to retrieve ring information " + "from frontend %s. Unable to " + "connect.", + xenbus_get_otherend_path(xbb->dev)); return (error); } + } else { + /* Multi-page ring format. */ + for (ring_idx = 0; ring_idx < xbb->ring_config.ring_pages; + ring_idx++) { + char ring_ref_name[]= "ring_refXX"; + + snprintf(ring_ref_name, sizeof(ring_ref_name), + "ring-ref%u", ring_idx); + error = xs_scanf(XST_NIL, otherend_path, + ring_ref_name, NULL, "%" PRIu32, + &xbb->ring_config.ring_ref[ring_idx]); + if (error != 0) { + xenbus_dev_fatal(xbb->dev, error, + "Failed to retriev grant " + "reference for page %u of " + "shared ring. Unable " + "to connect.", ring_idx); + return (error); + } + } } error = xs_gather(XST_NIL, otherend_path, @@ -3197,8 +3264,8 @@ xbb_alloc_requests(struct xbb_softc *xbb) static int xbb_alloc_request_lists(struct xbb_softc *xbb) { - int i; struct xbb_xen_reqlist *reqlist; + int i; /* * If no requests can be merged, we need 1 request list per @@ -3318,7 +3385,7 @@ xbb_publish_backend_info(struct xbb_softc *xbb) static void xbb_connect(struct xbb_softc *xbb) { - int error; + int error; if (xenbus_get_state(xbb->dev) == XenbusStateConnected) return; @@ -3399,7 +3466,8 @@ xbb_connect(struct xbb_softc *xbb) static int xbb_shutdown(struct xbb_softc *xbb) { - int error; + XenbusState frontState; + int error; DPRINTF("\n"); @@ -3413,6 +3481,20 @@ xbb_shutdown(struct xbb_softc *xbb) if ((xbb->flags & XBBF_IN_SHUTDOWN) != 0) return (EAGAIN); + xbb->flags |= XBBF_IN_SHUTDOWN; + mtx_unlock(&xbb->lock); + + if (xenbus_get_state(xbb->dev) < XenbusStateClosing) + xenbus_set_state(xbb->dev, XenbusStateClosing); + + frontState = xenbus_get_otherend_state(xbb->dev); + mtx_lock(&xbb->lock); + xbb->flags &= ~XBBF_IN_SHUTDOWN; + + /* The front can submit I/O until entering the closed state. */ + if (frontState < XenbusStateClosed) + return (EAGAIN); + DPRINTF("\n"); /* Indicate shutdown is in progress. */ @@ -3434,19 +3516,6 @@ xbb_shutdown(struct xbb_softc *xbb) DPRINTF("\n"); - /* - * Before unlocking mutex, set this flag to prevent other threads from - * getting into this function - */ - xbb->flags |= XBBF_IN_SHUTDOWN; - mtx_unlock(&xbb->lock); - - if (xenbus_get_state(xbb->dev) < XenbusStateClosing) - xenbus_set_state(xbb->dev, XenbusStateClosing); - - mtx_lock(&xbb->lock); - xbb->flags &= ~XBBF_IN_SHUTDOWN; - /* Indicate to xbb_detach() that is it safe to proceed. */ wakeup(xbb); @@ -3573,6 +3642,16 @@ xbb_setup_sysctl(struct xbb_softc *xbb) "max_request_segments", CTLFLAG_RD, &xbb->max_request_segments, 0, "maximum number of pages per requests (negotiated)"); + + SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "max_request_size", CTLFLAG_RD, + &xbb->max_request_size, 0, + "maximum size in bytes of a request (negotiated)"); + + SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "ring_pages", CTLFLAG_RD, + &xbb->ring_config.ring_pages, 0, + "communication channel pages (negotiated)"); } /** @@ -3587,6 +3666,7 @@ xbb_attach(device_t dev) { struct xbb_softc *xbb; int error; + u_int max_ring_page_order; DPRINTF("Attaching to %s\n", xenbus_get_node(dev)); @@ -3621,6 +3701,10 @@ xbb_attach(device_t dev) return (error); } + /* + * Amazon EC2 client compatility. They refer to max-ring-pages + * instead of to max-ring-page-order. + */ error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev), "max-ring-pages", "%zu", XBB_MAX_RING_PAGES); if (error) { @@ -3629,6 +3713,15 @@ xbb_attach(device_t dev) return (error); } + max_ring_page_order = flsl(XBB_MAX_RING_PAGES) - 1; + error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev), + "max-ring-page-order", "%u", max_ring_page_order); + if (error) { + xbb_attach_failed(xbb, error, "writing %s/max-ring-page-order", + xenbus_get_node(xbb->dev)); + return (error); + } + error = xs_printf(XST_NIL, xenbus_get_node(xbb->dev), "max-requests", "%u", XBB_MAX_REQUESTS); if (error) { @@ -3862,12 +3955,16 @@ xbb_frontend_changed(device_t dev, XenbusState frontend_state) xbb_connect(xbb); break; case XenbusStateClosing: + /* + * Frontend has acknowledged Closing request. + * Wait for Closed state. + */ + break; case XenbusStateClosed: mtx_lock(&xbb->lock); xbb_shutdown(xbb); mtx_unlock(&xbb->lock); - if (frontend_state == XenbusStateClosed) - xenbus_set_state(xbb->dev, XenbusStateClosed); + xenbus_set_state(xbb->dev, XenbusStateClosed); break; default: xenbus_dev_fatal(xbb->dev, EINVAL, "saw state %d at frontend", diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c index 954cf1f58a15..a5e280d1eee4 100644 --- a/sys/dev/xen/blkfront/blkfront.c +++ b/sys/dev/xen/blkfront/blkfront.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -139,7 +140,7 @@ static int xb_dump(void *, void *, vm_offset_t, off_t, size_t); * with blkfront as the emulated drives, easing transition slightly. */ static void -blkfront_vdevice_to_unit(int vdevice, int *unit, const char **name) +blkfront_vdevice_to_unit(uint32_t vdevice, int *unit, const char **name) { static struct vdev_info { int major; @@ -186,6 +187,7 @@ blkfront_vdevice_to_unit(int vdevice, int *unit, const char **name) if (vdevice & (1 << 28)) { *unit = (vdevice & ((1 << 28) - 1)) >> 8; *name = "xbd"; + return; } for (i = 0; info[i].major; i++) { @@ -407,6 +409,40 @@ blkfront_probe(device_t dev) return (ENXIO); } +static void +xb_setup_sysctl(struct xb_softc *xb) +{ + struct sysctl_ctx_list *sysctl_ctx = NULL; + struct sysctl_oid *sysctl_tree = NULL; + + sysctl_ctx = device_get_sysctl_ctx(xb->xb_dev); + if (sysctl_ctx == NULL) + return; + + sysctl_tree = device_get_sysctl_tree(xb->xb_dev); + if (sysctl_tree == NULL) + return; + + SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "max_requests", CTLFLAG_RD, &xb->max_requests, -1, + "maximum outstanding requests (negotiated)"); + + SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "max_request_segments", CTLFLAG_RD, + &xb->max_request_segments, 0, + "maximum number of pages per requests (negotiated)"); + + SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "max_request_size", CTLFLAG_RD, + &xb->max_request_size, 0, + "maximum size in bytes of a request (negotiated)"); + + SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "ring_pages", CTLFLAG_RD, + &xb->ring_pages, 0, + "communication channel pages (negotiated)"); +} + /* * Setup supplies the backend dir, virtual device. We place an event * channel and shared frame entries. We watch backend to wait if it's @@ -417,14 +453,14 @@ blkfront_attach(device_t dev) { struct xb_softc *sc; const char *name; + uint32_t vdevice; int error; - int vdevice; int i; int unit; /* FIXME: Use dynamic device id if this is not set. */ error = xs_scanf(XST_NIL, xenbus_get_node(dev), - "virtual-device", NULL, "%i", &vdevice); + "virtual-device", NULL, "%" PRIu32, &vdevice); if (error) { xenbus_dev_fatal(dev, error, "reading virtual-device"); device_printf(dev, "Couldn't determine virtual device.\n"); @@ -449,6 +485,8 @@ blkfront_attach(device_t dev) sc->vdevice = vdevice; sc->connected = BLKIF_STATE_DISCONNECTED; + xb_setup_sysctl(sc); + /* Wait for backend device to publish its protocol capabilities. */ xenbus_set_state(dev, XenbusStateInitialising); @@ -501,6 +539,7 @@ blkfront_initialize(struct xb_softc *sc) { const char *otherend_path; const char *node_path; + uint32_t max_ring_page_order; int error; int i; @@ -513,10 +552,10 @@ blkfront_initialize(struct xb_softc *sc) * Protocol defaults valid even if negotiation for a * setting fails. */ + max_ring_page_order = 0; sc->ring_pages = 1; - sc->max_requests = BLKIF_MAX_RING_REQUESTS(PAGE_SIZE); sc->max_request_segments = BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK; - sc->max_request_size = (sc->max_request_segments - 1) * PAGE_SIZE; + sc->max_request_size = XBF_SEGS_TO_SIZE(sc->max_request_segments); sc->max_request_blocks = BLKIF_SEGS_TO_BLOCKS(sc->max_request_segments); /* @@ -526,13 +565,25 @@ blkfront_initialize(struct xb_softc *sc) * we must use independant calls in order to guarantee * we don't miss information in a sparsly populated back-end * tree. + * + * \note xs_scanf() does not update variables for unmatched + * fields. */ otherend_path = xenbus_get_otherend_path(sc->xb_dev); node_path = xenbus_get_node(sc->xb_dev); + + /* Support both backend schemes for relaying ring page limits. */ + (void)xs_scanf(XST_NIL, otherend_path, + "max-ring-page-order", NULL, "%" PRIu32, + &max_ring_page_order); + sc->ring_pages = 1 << max_ring_page_order; (void)xs_scanf(XST_NIL, otherend_path, "max-ring-pages", NULL, "%" PRIu32, &sc->ring_pages); + if (sc->ring_pages < 1) + sc->ring_pages = 1; + sc->max_requests = BLKIF_MAX_RING_REQUESTS(sc->ring_pages * PAGE_SIZE); (void)xs_scanf(XST_NIL, otherend_path, "max-requests", NULL, "%" PRIu32, &sc->max_requests); @@ -552,6 +603,16 @@ blkfront_initialize(struct xb_softc *sc) sc->ring_pages = XBF_MAX_RING_PAGES; } + if (powerof2(sc->ring_pages) == 0) { + uint32_t new_page_limit; + + new_page_limit = 0x01 << (fls(sc->ring_pages) - 1); + device_printf(sc->xb_dev, "Back-end specified ring-pages of " + "%u is not a power of 2. Limited to %u.\n", + sc->ring_pages, new_page_limit); + sc->ring_pages = new_page_limit; + } + if (sc->max_requests > XBF_MAX_REQUESTS) { device_printf(sc->xb_dev, "Back-end specified max_requests of " "%u limited to front-end limit of %u.\n", @@ -560,8 +621,8 @@ blkfront_initialize(struct xb_softc *sc) } if (sc->max_request_segments > XBF_MAX_SEGMENTS_PER_REQUEST) { - device_printf(sc->xb_dev, "Back-end specificed " - "max_requests_segments of %u limited to " + device_printf(sc->xb_dev, "Back-end specified " + "max_request_segments of %u limited to " "front-end limit of %u.\n", sc->max_request_segments, XBF_MAX_SEGMENTS_PER_REQUEST); @@ -569,12 +630,23 @@ blkfront_initialize(struct xb_softc *sc) } if (sc->max_request_size > XBF_MAX_REQUEST_SIZE) { - device_printf(sc->xb_dev, "Back-end specificed " + device_printf(sc->xb_dev, "Back-end specified " "max_request_size of %u limited to front-end " "limit of %u.\n", sc->max_request_size, XBF_MAX_REQUEST_SIZE); sc->max_request_size = XBF_MAX_REQUEST_SIZE; } + + if (sc->max_request_size > XBF_SEGS_TO_SIZE(sc->max_request_segments)) { + device_printf(sc->xb_dev, "Back-end specified " + "max_request_size of %u limited to front-end " + "limit of %u. (Too few segments.)\n", + sc->max_request_size, + XBF_SEGS_TO_SIZE(sc->max_request_segments)); + sc->max_request_size = + XBF_SEGS_TO_SIZE(sc->max_request_segments); + } + sc->max_request_blocks = BLKIF_SEGS_TO_BLOCKS(sc->max_request_segments); /* Allocate datastructures based on negotiated values. */ @@ -625,11 +697,20 @@ blkfront_initialize(struct xb_softc *sc) if (setup_blkring(sc) != 0) return; + /* Support both backend schemes for relaying ring page limits. */ error = xs_printf(XST_NIL, node_path, - "ring-pages","%u", sc->ring_pages); + "num-ring-pages","%u", sc->ring_pages); if (error) { xenbus_dev_fatal(sc->xb_dev, error, - "writing %s/ring-pages", + "writing %s/num-ring-pages", + node_path); + return; + } + error = xs_printf(XST_NIL, node_path, + "ring-page-order","%u", fls(sc->ring_pages) - 1); + if (error) { + xenbus_dev_fatal(sc->xb_dev, error, + "writing %s/ring-page-order", node_path); return; } @@ -711,25 +792,31 @@ setup_blkring(struct xb_softc *sc) return (error); } } - error = xs_printf(XST_NIL, xenbus_get_node(sc->xb_dev), - "ring-ref","%u", sc->ring_ref[0]); - if (error) { - xenbus_dev_fatal(sc->xb_dev, error, "writing %s/ring-ref", - xenbus_get_node(sc->xb_dev)); - return (error); - } - for (i = 1; i < sc->ring_pages; i++) { - char ring_ref_name[]= "ring_refXX"; - - snprintf(ring_ref_name, sizeof(ring_ref_name), "ring-ref%u", i); + if (sc->ring_pages == 1) { error = xs_printf(XST_NIL, xenbus_get_node(sc->xb_dev), - ring_ref_name, "%u", sc->ring_ref[i]); + "ring-ref", "%u", sc->ring_ref[0]); if (error) { - xenbus_dev_fatal(sc->xb_dev, error, "writing %s/%s", - xenbus_get_node(sc->xb_dev), - ring_ref_name); + xenbus_dev_fatal(sc->xb_dev, error, + "writing %s/ring-ref", + xenbus_get_node(sc->xb_dev)); return (error); } + } else { + for (i = 0; i < sc->ring_pages; i++) { + char ring_ref_name[]= "ring_refXX"; + + snprintf(ring_ref_name, sizeof(ring_ref_name), + "ring-ref%u", i); + error = xs_printf(XST_NIL, xenbus_get_node(sc->xb_dev), + ring_ref_name, "%u", sc->ring_ref[i]); + if (error) { + xenbus_dev_fatal(sc->xb_dev, error, + "writing %s/%s", + xenbus_get_node(sc->xb_dev), + ring_ref_name); + return (error); + } + } } error = bind_listening_port_to_irqhandler( @@ -795,7 +882,7 @@ blkfront_connect(struct xb_softc *sc) unsigned int binfo; int err, feature_barrier; - if( (sc->connected == BLKIF_STATE_CONNECTED) || + if( (sc->connected == BLKIF_STATE_CONNECTED) || (sc->connected == BLKIF_STATE_SUSPENDED) ) return; @@ -923,15 +1010,13 @@ blkif_close(struct disk *dp) return (ENXIO); sc->xb_flags &= ~XB_OPEN; if (--(sc->users) == 0) { - /* Check whether we have been instructed to close. We will - have ignored this request initially, as the device was - still mounted. */ - device_t dev = sc->xb_dev; - XenbusState state = - xenbus_read_driver_state(xenbus_get_otherend_path(dev)); - - if (state == XenbusStateClosing) - blkfront_closing(dev); + /* + * Check whether we have been instructed to close. We will + * have ignored this request initially, as the device was + * still mounted. + */ + if (xenbus_get_otherend_state(sc->xb_dev) == XenbusStateClosing) + blkfront_closing(sc->xb_dev); } return (0); } @@ -1033,7 +1118,7 @@ blkif_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) struct xb_command *cm; blkif_request_t *ring_req; struct blkif_request_segment *sg; - struct blkif_request_segment *last_block_sg; + struct blkif_request_segment *last_block_sg; grant_ref_t *sg_ref; vm_paddr_t buffer_ma; uint64_t fsect, lsect; @@ -1104,12 +1189,12 @@ blkif_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) nsegs--; } block_segs = MIN(nsegs, BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK); - if (block_segs == 0) - break; + if (block_segs == 0) + break; - sg = BLKRING_GET_SG_REQUEST(&sc->ring, sc->ring.req_prod_pvt); + sg = BLKRING_GET_SEG_BLOCK(&sc->ring, sc->ring.req_prod_pvt); sc->ring.req_prod_pvt++; - last_block_sg = sg + block_segs; + last_block_sg = sg + block_segs; } if (cm->operation == BLKIF_OP_READ) diff --git a/sys/dev/xen/blkfront/block.h b/sys/dev/xen/blkfront/block.h index 6eabcf4e0723..5aa35ae54270 100644 --- a/sys/dev/xen/blkfront/block.h +++ b/sys/dev/xen/blkfront/block.h @@ -34,6 +34,32 @@ #define __XEN_DRIVERS_BLOCK_H__ #include +/** + * Given a number of blkif segments, compute the maximum I/O size supported. + * + * \note This calculation assumes that all but the first and last segments + * of the I/O are fully utilized. + * + * \note We reserve a segement from the maximum supported by the transport to + * guarantee we can handle an unaligned transfer without the need to + * use a bounce buffer. + */ +#define XBF_SEGS_TO_SIZE(segs) \ + (((segs) - 1) * PAGE_SIZE) + +/** + * Compute the maximum number of blkif segments requried to represent + * an I/O of the given size. + * + * \note This calculation assumes that all but the first and last segments + * of the I/O are fully utilized. + * + * \note We reserve a segement to guarantee we can handle an unaligned + * transfer without the need to use a bounce buffer. + */ +#define XBF_SIZE_TO_SEGS(size) \ + ((size / PAGE_SIZE) + 1) + /** * The maximum number of outstanding requests blocks (request headers plus * additional segment blocks) we will allow in a negotiated block-front/back @@ -44,22 +70,18 @@ /** * The maximum mapped region size per request we will allow in a negotiated * block-front/back communication channel. - * - * \note We reserve a segement from the maximum supported by the transport to - * guarantee we can handle an unaligned transfer without the need to - * use a bounce buffer.. */ -#define XBF_MAX_REQUEST_SIZE \ - MIN(MAXPHYS, (BLKIF_MAX_SEGMENTS_PER_REQUEST - 1) * PAGE_SIZE) +#define XBF_MAX_REQUEST_SIZE \ + MIN(MAXPHYS, XBF_SEGS_TO_SIZE(BLKIF_MAX_SEGMENTS_PER_REQUEST)) /** * The maximum number of segments (within a request header and accompanying * segment blocks) per request we will allow in a negotiated block-front/back * communication channel. */ -#define XBF_MAX_SEGMENTS_PER_REQUEST \ - (MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST, \ - (XBF_MAX_REQUEST_SIZE / PAGE_SIZE) + 1)) +#define XBF_MAX_SEGMENTS_PER_REQUEST \ + (MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST, \ + XBF_SIZE_TO_SEGS(XBF_MAX_REQUEST_SIZE))) /** * The maximum number of shared memory ring pages we will allow in a diff --git a/sys/fs/devfs/devfs.h b/sys/fs/devfs/devfs.h index d148f8e487cb..d77baa8657bc 100644 --- a/sys/fs/devfs/devfs.h +++ b/sys/fs/devfs/devfs.h @@ -182,6 +182,8 @@ void devfs_rules_apply(struct devfs_mount *, struct devfs_dirent *); void devfs_rules_cleanup(struct devfs_mount *); int devfs_rules_ioctl(struct devfs_mount *, u_long, caddr_t, struct thread *); +void devfs_ruleset_set(devfs_rsnum rsnum, struct devfs_mount *dm); +void devfs_ruleset_apply(struct devfs_mount *dm); int devfs_allocv(struct devfs_dirent *, struct mount *, int, struct vnode **); char *devfs_fqpn(char *, struct devfs_mount *, struct devfs_dirent *, diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c index a111527a68b4..71caa29b87c9 100644 --- a/sys/fs/devfs/devfs_devs.c +++ b/sys/fs/devfs/devfs_devs.c @@ -133,7 +133,6 @@ devfs_alloc(int flags) cdev = &cdp->cdp_c; - cdev->si_name = cdev->__si_namebuf; LIST_INIT(&cdev->si_children); vfs_timestamp(&ts); cdev->si_atime = cdev->si_mtime = cdev->si_ctime = ts; diff --git a/sys/fs/devfs/devfs_rule.c b/sys/fs/devfs/devfs_rule.c index ea057977b5f0..f37dd9dbafb5 100644 --- a/sys/fs/devfs/devfs_rule.c +++ b/sys/fs/devfs/devfs_rule.c @@ -771,3 +771,38 @@ devfs_rules_cleanup(struct devfs_mount *dm) devfs_ruleset_reap(ds); } } + +/* + * Make rsnum the active ruleset for dm (locked) + */ +void +devfs_ruleset_set(devfs_rsnum rsnum, struct devfs_mount *dm) +{ + + sx_assert(&dm->dm_lock, SX_XLOCKED); + + sx_xlock(&sx_rules); + devfs_ruleset_use(rsnum, dm); + sx_xunlock(&sx_rules); +} + +/* + * Apply the current active ruleset on a mount + */ +void +devfs_ruleset_apply(struct devfs_mount *dm) +{ + struct devfs_ruleset *ds; + + sx_assert(&dm->dm_lock, SX_XLOCKED); + + sx_xlock(&sx_rules); + if (dm->dm_ruleset == 0) { + sx_xunlock(&sx_rules); + return; + } + ds = devfs_ruleset_bynum(dm->dm_ruleset); + if (ds != NULL) + devfs_ruleset_applydm(ds, dm); + sx_xunlock(&sx_rules); +} diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c index 87ec1628851d..96069747e39e 100644 --- a/sys/fs/devfs/devfs_vfsops.c +++ b/sys/fs/devfs/devfs_vfsops.c @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -56,6 +57,10 @@ static vfs_unmount_t devfs_unmount; static vfs_root_t devfs_root; static vfs_statfs_t devfs_statfs; +static const char *devfs_opts[] = { + "from", "ruleset", NULL +}; + /* * Mount the filesystem */ @@ -65,15 +70,57 @@ devfs_mount(struct mount *mp) int error; struct devfs_mount *fmp; struct vnode *rvp; + struct thread *td = curthread; + int rsnum; if (devfs_unr == NULL) devfs_unr = new_unrhdr(0, INT_MAX, NULL); error = 0; - if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS)) + if (mp->mnt_flag & MNT_ROOTFS) return (EOPNOTSUPP); + rsnum = 0; + + if (mp->mnt_optnew != NULL) { + if (vfs_filteropt(mp->mnt_optnew, devfs_opts)) + return (EINVAL); + + if (vfs_getopt(mp->mnt_optnew, "ruleset", NULL, NULL) == 0 && + (vfs_scanopt(mp->mnt_optnew, "ruleset", "%d", + &rsnum) != 1 || rsnum < 0 || rsnum > 65535)) + error = EINVAL; + } + + /* jails enforce their ruleset, prison0 has no restrictions */ + if (td->td_ucred->cr_prison->pr_devfs_rsnum != 0) { + rsnum = td->td_ucred->cr_prison->pr_devfs_rsnum; + if (rsnum == -1) + return (EPERM); + /* check rsnum for sanity, devfs_rsnum is uint16_t */ + if (rsnum < 0 || rsnum > 65535) + error = EINVAL; + } + + if (error) { + vfs_mount_error(mp, "%s", "invalid ruleset specification"); + return (error); + } + + if (mp->mnt_flag & MNT_UPDATE) { + if (rsnum != 0) { + fmp = mp->mnt_data; + if (fmp != NULL) { + sx_xlock(&fmp->dm_lock); + devfs_ruleset_set((devfs_rsnum)rsnum, fmp); + devfs_ruleset_apply(fmp); + sx_xunlock(&fmp->dm_lock); + } + } + return (0); + } + fmp = malloc(sizeof *fmp, M_DEVFS, M_WAITOK | M_ZERO); fmp->dm_idx = alloc_unr(devfs_unr); sx_init(&fmp->dm_lock, "devfsmount"); @@ -101,6 +148,12 @@ devfs_mount(struct mount *mp) return (error); } + if (rsnum != 0) { + sx_xlock(&fmp->dm_lock); + devfs_ruleset_set((devfs_rsnum)rsnum, fmp); + sx_xunlock(&fmp->dm_lock); + } + VOP_UNLOCK(rvp, 0); vfs_mountedfrom(mp, "devfs"); @@ -186,4 +239,4 @@ static struct vfsops devfs_vfsops = { .vfs_unmount = devfs_unmount, }; -VFS_SET(devfs_vfsops, devfs, VFCF_SYNTHETIC); +VFS_SET(devfs_vfsops, devfs, VFCF_SYNTHETIC | VFCF_JAIL); diff --git a/sys/fs/ext2fs/ext2_dinode.h b/sys/fs/ext2fs/ext2_dinode.h index 3d744b994111..6893ccc3f7cc 100755 --- a/sys/fs/ext2fs/ext2_dinode.h +++ b/sys/fs/ext2fs/ext2_dinode.h @@ -70,7 +70,7 @@ struct ext2fs_dinode { uint16_t e2di_uid; /* 2: Owner UID */ uint32_t e2di_size; /* 4: Size (in bytes) */ uint32_t e2di_atime; /* 8: Access time */ - uint32_t e2di_ctime; /* 12: Create time */ + uint32_t e2di_ctime; /* 12: Change time */ uint32_t e2di_mtime; /* 16: Modification time */ uint32_t e2di_dtime; /* 20: Deletion time */ uint16_t e2di_gid; /* 24: Owner GID */ @@ -89,6 +89,8 @@ struct ext2fs_dinode { uint16_t e2di_uid_high; /* 120: Owner UID top 16 bits */ uint16_t e2di_gid_high; /* 122: Owner GID top 16 bits */ uint32_t e2di_linux_reserved3; /* 124 */ + uint16_t e2di_extra_isize; + uint16_t e2di_pad1; }; #endif /* !_FS_EXT2FS_EXT2_DINODE_H_ */ diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h index b57d515d3537..14027ab12f50 100755 --- a/sys/fs/ext2fs/ext2fs.h +++ b/sys/fs/ext2fs/ext2fs.h @@ -123,7 +123,22 @@ struct ext2fs { char e3fs_reserved_char_pad; uint32_t e3fs_default_mount_opts; uint32_t e3fs_first_meta_bg; /* First metablock block group */ - uint32_t reserved2[190]; /* Padding to the end of the block */ + uint32_t e3fs_mkfs_time; /* when the fs was created */ + uint32_t e3fs_jnl_blks[17]; /* backup of the journal inode */ + uint32_t e4fs_bcount_hi; /* block count */ + uint32_t e4fs_rbcount_hi; /* reserved blocks count */ + uint32_t e4fs_fbcount_hi; /* free blocks count */ + uint16_t e4fs_min_extra_isize;/* all inodes have at least some bytes */ + uint16_t e4fs_want_extra_isize; /* new inodes should reserve some bytes */ + uint32_t e4fs_flags; /* miscellaneous flags */ + uint16_t e4fs_raid_stride; /* RAID stride */ + uint16_t e4fs_mmpintv; /* number of seconds to wait in MMP checking */ + uint64_t e4fs_mmpblk; /* block for multi-mount protection */ + uint32_t e4fs_raid_stripe_wid;/* blocks on all data disks (N * stride) */ + uint8_t e4fs_log_gpf; /* FLEX_BG group size */ + uint8_t e4fs_char_pad2; + uint16_t e4fs_pad; + uint32_t reserved2[162]; /* Padding to the end of the block */ }; @@ -139,15 +154,15 @@ struct m_ext2fs { uint32_t e2fs_bsize; /* Block size */ uint32_t e2fs_bshift; /* calc of logical block no */ int32_t e2fs_bmask; /* calc of block offset */ - int32_t e2fs_bpg; /* Number of blocks per group */ + int32_t e2fs_bpg; /* Number of blocks per group */ int64_t e2fs_qbmask; /* = s_blocksize -1 */ uint32_t e2fs_fsbtodb; /* Shift to get disk block */ - uint32_t e2fs_ipg; /* Number of inodes per group */ - uint32_t e2fs_ipb; /* Number of inodes per block */ + uint32_t e2fs_ipg; /* Number of inodes per group */ + uint32_t e2fs_ipb; /* Number of inodes per block */ uint32_t e2fs_itpg; /* Number of inode table per group */ uint32_t e2fs_fsize; /* Size of fragments per block */ - uint32_t e2fs_fpb; /* Number of fragments per block */ - uint32_t e2fs_fpg; /* Number of fragments per group */ + uint32_t e2fs_fpb; /* Number of fragments per block */ + uint32_t e2fs_fpg; /* Number of fragments per group */ uint32_t e2fs_dbpg; /* Number of descriptor blocks per group */ uint32_t e2fs_descpb; /* Number of group descriptors per block */ uint32_t e2fs_gdbcount; /* Number of group descriptors */ @@ -161,7 +176,7 @@ struct m_ext2fs { char e2fs_wasvalid; /* valid at mount time */ off_t e2fs_maxfilesize; struct ext2_gd *e2fs_gd; /* Group Descriptors */ - int32_t e2fs_maxcontig; /* max number of contiguous blks */ + int32_t e2fs_maxcontig; /* max number of contiguous blks */ int32_t e2fs_contigsumsize; /* size of cluster summary array */ int32_t *e2fs_maxcluster; /* max cluster in each cyl group */ struct csum *e2fs_clustersum; /* cluster summary in each cyl group */ diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h index 92a84ac76571..659b950e1069 100644 --- a/sys/fs/ext2fs/inode.h +++ b/sys/fs/ext2fs/inode.h @@ -85,11 +85,13 @@ struct inode { int16_t i_nlink; /* File link count. */ uint64_t i_size; /* File byte count. */ int32_t i_atime; /* Last access time. */ - int32_t i_atimensec; /* Last access time. */ int32_t i_mtime; /* Last modified time. */ - int32_t i_mtimensec; /* Last modified time. */ int32_t i_ctime; /* Last inode change time. */ + int32_t i_birthtime; /* Inode creation time. */ + int32_t i_mtimensec; /* Last modified time. */ + int32_t i_atimensec; /* Last access time. */ int32_t i_ctimensec; /* Last inode change time. */ + int32_t i_birthnsec; /* Inode creation time. */ int32_t i_db[NDADDR]; /* Direct disk blocks. */ int32_t i_ib[NIADDR]; /* Indirect disk blocks. */ uint32_t i_flags; /* Status flags (chflags). */ @@ -158,9 +160,6 @@ struct indir { #define VTOI(vp) ((struct inode *)(vp)->v_data) #define ITOV(ip) ((ip)->i_vnode) -/* Check whether the MNTK_ASYNC flag has been set for a mount point */ -#define DOINGASYNC(vp) ((vp)->v_mount->mnt_kern_flag & MNTK_ASYNC) - /* This overlays the fid structure (see mount.h). */ struct ufid { uint16_t ufid_len; /* Length of structure. */ diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index aff8749c3d11..47c051f15e30 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -109,9 +109,6 @@ MALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback", * Definition of mutex locks. * newnfsd_mtx is used in nfsrvd_nfsd() to protect the nfs socket list * and assorted other nfsd structures. - * Giant is used to protect the nfsd list and count, which is just - * updated when nfsd's start/stop and is grabbed for nfsrvd_dorpc() - * for the VFS ops. */ struct mtx newnfsd_mtx; struct mtx nfs_sockl_mutex; diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index 765b6b9d1567..b54805db8d05 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -559,8 +559,12 @@ nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode, NFSUNLOCKCLSTATE(); return (ENOENT); } - /* for read aheads or write behinds, use the open cred */ - newnfs_copycred(&op->nfso_cred, cred); + /* + * For read aheads or write behinds, use the open cred. + * A read ahead or write behind is indicated by p == NULL. + */ + if (p == NULL) + newnfs_copycred(&op->nfso_cred, cred); } /* diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 7443fc9f3ec0..c842c1916149 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1042,7 +1042,7 @@ nfs_lookup(struct vop_lookup_args *ap) if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) return (error); - error = cache_lookup_times(dvp, vpp, cnp, &nctime, &ncticks); + error = cache_lookup(dvp, vpp, cnp, &nctime, &ncticks); if (error > 0 && error != ENOENT) return (error); if (error == -1) { @@ -1376,7 +1376,7 @@ ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, if (ret && !error) error = ret; } - if (vp->v_mount->mnt_kern_flag & MNTK_ASYNC) + if (DOINGASYNC(vp)) *iomode = NFSWRITE_FILESYNC; if (error && NFS_ISV4(vp)) error = nfscl_maperr(uiop->uio_td, error, (uid_t)0, (gid_t)0); diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 21b5e483b383..d7fa1f67ce9d 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -319,11 +319,7 @@ nfsvno_setattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred, } /* - * Set up nameidata for a lookup() call and do it - * For the cases where we are crossing mount points - * (looking up the public fh path or the v4 root path when - * not using a pseudo-root fs), set/release the Giant lock, - * as required. + * Set up nameidata for a lookup() call and do it. */ int nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp, diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index cf3176fe1a5a..97874b3e0dea 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -357,4 +357,4 @@ static struct vfsops null_vfsops = { .vfs_vget = nullfs_vget, }; -VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK); +VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK | VFCF_JAIL); diff --git a/sys/fs/nwfs/nwfs_vnops.c b/sys/fs/nwfs/nwfs_vnops.c index ddbdc169ec02..b3f26e8e042e 100644 --- a/sys/fs/nwfs/nwfs_vnops.c +++ b/sys/fs/nwfs/nwfs_vnops.c @@ -853,7 +853,7 @@ printf("dvp %d:%d:%d\n", (int)mp, (int)dvp->v_vflag & VV_ROOT, (int)flags & ISDO if (error) return ENOENT; - error = cache_lookup(dvp, vpp, cnp); + error = cache_lookup(dvp, vpp, cnp, NULL, NULL); NCPVNDEBUG("cache_lookup returned %d\n", error); if (error > 0) return error; diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c index a236ca764962..99cbec5de63a 100644 --- a/sys/fs/smbfs/smbfs_vnops.c +++ b/sys/fs/smbfs/smbfs_vnops.c @@ -1131,7 +1131,7 @@ smbfs_lookup(ap) if (error) return ENOENT; - error = cache_lookup(dvp, vpp, cnp); + error = cache_lookup(dvp, vpp, cnp, NULL, NULL); SMBVDEBUG("cache_lookup returned %d\n", error); if (error > 0) return error; diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 3f1482e6566b..93fea8b0693f 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -54,8 +54,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include #include #include @@ -1471,10 +1469,9 @@ tmpfs_print(struct vop_print_args *v) printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%x, links %d\n", node, node->tn_flags, node->tn_links); - printf("\tmode 0%o, owner %d, group %d, size %" PRIdMAX - ", status 0x%x\n", + printf("\tmode 0%o, owner %d, group %d, size %jd, status 0x%x\n", node->tn_mode, node->tn_uid, node->tn_gid, - (uintmax_t)node->tn_size, node->tn_status); + (intmax_t)node->tn_size, node->tn_status); if (vp->v_type == VFIFO) fifo_printinfo(vp); diff --git a/sys/geom/journal/g_journal.c b/sys/geom/journal/g_journal.c index 706d6d418a9d..a31f5904ce77 100644 --- a/sys/geom/journal/g_journal.c +++ b/sys/geom/journal/g_journal.c @@ -2870,7 +2870,7 @@ g_journal_do_switch(struct g_class *classp) struct mount *mp; struct bintime bt; char *mountpoint; - int error, vfslocked; + int error, save, vfslocked; DROP_GIANT(); g_topology_lock(); @@ -2932,10 +2932,7 @@ g_journal_do_switch(struct g_class *classp) goto next; } - MNT_ILOCK(mp); - mp->mnt_noasync++; - mp->mnt_kern_flag &= ~MNTK_ASYNC; - MNT_IUNLOCK(mp); + save = curthread_pflags_set(TDP_SYNCIO); GJ_TIMER_START(1, &bt); vfs_msync(mp, MNT_NOWAIT); @@ -2950,11 +2947,7 @@ g_journal_do_switch(struct g_class *classp) mountpoint, error); } - MNT_ILOCK(mp); - mp->mnt_noasync--; - if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0) - mp->mnt_kern_flag |= MNTK_ASYNC; - MNT_IUNLOCK(mp); + curthread_pflags_restore(save); vn_finished_write(mp); diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index 8ea5bb6d6fc4..b183e144eef3 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -215,7 +215,7 @@ g_part_geometry(struct g_part_table *table, struct g_consumer *cp, continue; /* * Prefer a geometry with sectors > 1, but only if - * it doesn't bump down the numbver of heads to 1. + * it doesn't bump down the number of heads to 1. */ if (chs > bestchs || (chs == bestchs && heads > 1 && table->gpt_sectors == 1)) { @@ -2057,6 +2057,7 @@ g_part_start(struct bio *bp) struct g_part_table *table; struct g_kerneldump *gkd; struct g_provider *pp; + char buf[64]; pp = bp->bio_to; gp = pp->geom; @@ -2105,6 +2106,9 @@ g_part_start(struct bio *bp) if (g_handleattr_str(bp, "PART::scheme", table->gpt_scheme->name)) return; + if (g_handleattr_str(bp, "PART::type", + G_PART_TYPE(table, entry, buf, sizeof(buf)))) + return; if (!strcmp("GEOM::kerneldump", bp->bio_attribute)) { /* * Check that the partition is suitable for kernel diff --git a/sys/geom/part/g_part_apm.c b/sys/geom/part/g_part_apm.c index 1adee7c30e84..d99ddda7ac71 100644 --- a/sys/geom/part/g_part_apm.c +++ b/sys/geom/part/g_part_apm.c @@ -102,7 +102,7 @@ static struct g_part_scheme g_part_apm_scheme = { sizeof(struct g_part_apm_table), .gps_entrysz = sizeof(struct g_part_apm_entry), .gps_minent = 16, - .gps_maxent = INT_MAX, + .gps_maxent = 4096, }; G_PART_SCHEME_DECLARE(g_part_apm); diff --git a/sys/geom/part/g_part_ebr.c b/sys/geom/part/g_part_ebr.c index c7657f845b57..889f26378113 100644 --- a/sys/geom/part/g_part_ebr.c +++ b/sys/geom/part/g_part_ebr.c @@ -268,7 +268,7 @@ g_part_ebr_add(struct g_part_table *basetable, struct g_part_entry *baseentry, static int g_part_ebr_create(struct g_part_table *basetable, struct g_part_parms *gpp) { - char psn[8]; + char type[64]; struct g_consumer *cp; struct g_provider *pp; uint32_t msize; @@ -285,10 +285,15 @@ g_part_ebr_create(struct g_part_table *basetable, struct g_part_parms *gpp) if (basetable->gpt_depth == 0) return (ENXIO); cp = LIST_FIRST(&pp->consumers); - error = g_getattr("PART::scheme", cp, &psn); - if (error) + error = g_getattr("PART::scheme", cp, &type); + if (error != 0) return (error); - if (strcmp(psn, "MBR")) + if (strcmp(type, "MBR") != 0) + return (ENXIO); + error = g_getattr("PART::type", cp, &type); + if (error != 0) + return (error); + if (strcmp(type, "ebr") != 0) return (ENXIO); msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX); @@ -405,7 +410,7 @@ g_part_ebr_precheck(struct g_part_table *table, enum g_part_ctl req, static int g_part_ebr_probe(struct g_part_table *table, struct g_consumer *cp) { - char psn[8]; + char type[64]; struct g_provider *pp; u_char *buf, *p; int error, index, res; @@ -422,10 +427,16 @@ g_part_ebr_probe(struct g_part_table *table, struct g_consumer *cp) /* Check that we have a parent and that it's a MBR. */ if (table->gpt_depth == 0) return (ENXIO); - error = g_getattr("PART::scheme", cp, &psn); - if (error) + error = g_getattr("PART::scheme", cp, &type); + if (error != 0) return (error); - if (strcmp(psn, "MBR")) + if (strcmp(type, "MBR") != 0) + return (ENXIO); + /* Check that partition has type DOSPTYP_EBR. */ + error = g_getattr("PART::type", cp, &type); + if (error != 0) + return (error); + if (strcmp(type, "ebr") != 0) return (ENXIO); /* Check that there's a EBR. */ diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index 126210b5629c..f3e57707b4f6 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -119,6 +119,7 @@ static struct g_part_mbr_alias { { DOSPTYP_EXT, G_PART_ALIAS_EBR }, { DOSPTYP_NTFS, G_PART_ALIAS_MS_NTFS }, { DOSPTYP_FAT32, G_PART_ALIAS_MS_FAT32 }, + { DOSPTYP_LDM, G_PART_ALIAS_MS_LDM_DATA }, { DOSPTYP_LINSWP, G_PART_ALIAS_LINUX_SWAP }, { DOSPTYP_LINUX, G_PART_ALIAS_LINUX_DATA }, { DOSPTYP_LINLVM, G_PART_ALIAS_LINUX_LVM }, diff --git a/sys/ia64/ia64/vm_machdep.c b/sys/ia64/ia64/vm_machdep.c index 1711f1a6d425..09987fd7b77f 100644 --- a/sys/ia64/ia64/vm_machdep.c +++ b/sys/ia64/ia64/vm_machdep.c @@ -192,7 +192,7 @@ cpu_set_upcall(struct thread *td, struct thread *td0) bcopy(td0->td_pcb, pcb, sizeof(*pcb)); pcb->pcb_special.bspstore = td->td_kstack; pcb->pcb_special.pfs = 0; - pcb->pcb_current_pmap = vmspace_pmap(td->td_proc->p_vmspace); + pcb->pcb_current_pmap = vmspace_pmap(td0->td_proc->p_vmspace); pcb->pcb_special.sp = (uintptr_t)tf - 16; pcb->pcb_special.rp = FDESC_FUNC(fork_trampoline); cpu_set_fork_handler(td, (void (*)(void*))fork_return, td); diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index 85737e8873d5..461f008cb3f1 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -690,16 +690,15 @@ prep_devname(struct cdev *dev, const char *fmt, va_list ap) mtx_assert(&devmtx, MA_OWNED); - len = vsnrprintf(dev->__si_namebuf, sizeof(dev->__si_namebuf), 32, - fmt, ap); - if (len > sizeof(dev->__si_namebuf) - 1) + len = vsnrprintf(dev->si_name, sizeof(dev->si_name), 32, fmt, ap); + if (len > sizeof(dev->si_name) - 1) return (ENAMETOOLONG); /* Strip leading slashes. */ - for (from = dev->__si_namebuf; *from == '/'; from++) + for (from = dev->si_name; *from == '/'; from++) ; - for (to = dev->__si_namebuf; *from != '\0'; from++, to++) { + for (to = dev->si_name; *from != '\0'; from++, to++) { /* Treat multiple sequential slashes as single. */ while (from[0] == '/' && from[1] == '/') from++; @@ -710,11 +709,11 @@ prep_devname(struct cdev *dev, const char *fmt, va_list ap) } *to = '\0'; - if (dev->__si_namebuf[0] == '\0') + if (dev->si_name[0] == '\0') return (EINVAL); /* Disallow "." and ".." components. */ - for (s = dev->__si_namebuf;;) { + for (s = dev->si_name;;) { for (q = s; *q != '/' && *q != '\0'; q++) ; if (q - s == 1 && s[0] == '.') @@ -726,7 +725,7 @@ prep_devname(struct cdev *dev, const char *fmt, va_list ap) s = q + 1; } - if (devfs_dev_exists(dev->__si_namebuf) != 0) + if (devfs_dev_exists(dev->si_name) != 0) return (EEXIST); return (0); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 60639c9fcb84..e447c93215a1 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1035,7 +1035,9 @@ fork_return(struct thread *td, struct trapframe *frame) p->p_oppid = p->p_pptr->p_pid; proc_reparent(p, dbg); sx_xunlock(&proctree_lock); + td->td_dbgflags |= TDB_CHILD; ptracestop(td, SIGSTOP); + td->td_dbgflags &= ~TDB_CHILD; } else { /* * ... otherwise clear the request. diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 9f5e8b878124..b800eaa29089 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -103,6 +103,7 @@ struct prison prison0 = { .pr_uref = 1, .pr_path = "/", .pr_securelevel = -1, + .pr_devfs_rsnum = 0, .pr_childmax = JAIL_MAX, .pr_hostuuid = DEFAULT_HOSTUUID, .pr_children = LIST_HEAD_INITIALIZER(prison0.pr_children), @@ -216,8 +217,10 @@ const size_t pr_allow_nonames_size = sizeof(pr_allow_nonames); #define JAIL_DEFAULT_ALLOW PR_ALLOW_SET_HOSTNAME #define JAIL_DEFAULT_ENFORCE_STATFS 2 +#define JAIL_DEFAULT_DEVFS_RSNUM -1 static unsigned jail_default_allow = JAIL_DEFAULT_ALLOW; static int jail_default_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS; +static int jail_default_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM; #if defined(INET) || defined(INET6) static unsigned jail_max_af_ips = 255; #endif @@ -529,9 +532,9 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) unsigned long hid; size_t namelen, onamelen; int created, cuflags, descend, enforce, error, errmsg_len, errmsg_pos; - int gotchildmax, gotenforce, gothid, gotslevel; + int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel; int fi, jid, jsys, len, level; - int childmax, slevel, vfslocked; + int childmax, rsnum, slevel, vfslocked; int fullpath_disabled; #if defined(INET) || defined(INET6) int ii, ij; @@ -612,6 +615,14 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) } else gotenforce = 1; + error = vfs_copyopt(opts, "devfs_ruleset", &rsnum, sizeof(rsnum)); + if (error == ENOENT) + gotrsnum = 0; + else if (error != 0) + goto done_free; + else + gotrsnum = 1; + pr_flags = ch_flags = 0; for (fi = 0; fi < sizeof(pr_flag_names) / sizeof(pr_flag_names[0]); fi++) { @@ -1268,6 +1279,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) pr->pr_securelevel = ppr->pr_securelevel; pr->pr_allow = JAIL_DEFAULT_ALLOW & ppr->pr_allow; pr->pr_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS; + pr->pr_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM; LIST_INIT(&pr->pr_children); mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF | MTX_DUPOK); @@ -1346,6 +1358,27 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) goto done_deref_locked; } } + if (gotrsnum) { + /* + * devfs_rsnum is a uint16_t + * value of -1 disables devfs mounts + */ + if (rsnum < -1 || rsnum > 65535) { + error = EINVAL; + goto done_deref_locked; + } + /* + * Nested jails may inherit parent's devfs ruleset + * or disable devfs + */ + if (jailed(td->td_ucred)) { + if (rsnum > 0 && rsnum != ppr->pr_devfs_rsnum) { + error = EPERM; + goto done_deref_locked; + } else if (rsnum == 0) + rsnum = ppr->pr_devfs_rsnum; + } + } #ifdef INET if (ip4s > 0) { if (ppr->pr_flags & PR_IP4) { @@ -1586,6 +1619,13 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) if (tpr->pr_enforce_statfs < enforce) tpr->pr_enforce_statfs = enforce; } + if (gotrsnum) { + pr->pr_devfs_rsnum = rsnum; + /* Pass this restriction on to the children. */ + FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend) + if (tpr->pr_devfs_rsnum != -1) + tpr->pr_devfs_rsnum = rsnum; + } if (name != NULL) { if (ppr == &prison0) strlcpy(pr->pr_name, name, sizeof(pr->pr_name)); @@ -2020,6 +2060,10 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags) sizeof(pr->pr_enforce_statfs)); if (error != 0 && error != ENOENT) goto done_deref; + error = vfs_setopt(opts, "devfs_ruleset", &pr->pr_devfs_rsnum, + sizeof(pr->pr_devfs_rsnum)); + if (error != 0 && error != ENOENT) + goto done_deref; for (fi = 0; fi < sizeof(pr_flag_names) / sizeof(pr_flag_names[0]); fi++) { if (pr_flag_names[fi] == NULL) @@ -4173,6 +4217,12 @@ SYSCTL_PROC(_security_jail, OID_AUTO, enforce_statfs, sysctl_jail_default_level, "I", "Processes in jail cannot see all mounted file systems"); +SYSCTL_PROC(_security_jail, OID_AUTO, devfs_ruleset, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + &jail_default_devfs_rsnum, offsetof(struct prison, pr_devfs_rsnum), + sysctl_jail_default_level, "I", + "Ruleset for the devfs filesystem in jail"); + /* * Nodes to describe jail parameters. Maximum length of string parameters * is returned in the string itself, and the other parameters exist merely @@ -4221,6 +4271,8 @@ SYSCTL_JAIL_PARAM(, securelevel, CTLTYPE_INT | CTLFLAG_RW, "I", "Jail secure level"); SYSCTL_JAIL_PARAM(, enforce_statfs, CTLTYPE_INT | CTLFLAG_RW, "I", "Jail cannot see all mounted file systems"); +SYSCTL_JAIL_PARAM(, devfs_ruleset, CTLTYPE_INT | CTLFLAG_RW, + "I", "Ruleset for in-jail devfs mounts"); SYSCTL_JAIL_PARAM(, persist, CTLTYPE_INT | CTLFLAG_RW, "B", "Jail persistence"); #ifdef VIMAGE @@ -4413,6 +4465,7 @@ db_show_prison(struct prison *pr) #endif db_printf(" root = %p\n", pr->pr_root); db_printf(" securelevel = %d\n", pr->pr_securelevel); + db_printf(" devfs_rsnum = %d\n", pr->pr_devfs_rsnum); db_printf(" children.max = %d\n", pr->pr_childmax); db_printf(" children.cur = %d\n", pr->pr_childcount); db_printf(" child = %p\n", LIST_FIRST(&pr->pr_children)); diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index bb1246980d5b..dc3fdab8b4f9 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -117,6 +118,9 @@ kproc_create(void (*func)(void *), void *arg, /* call the processes' main()... */ cpu_set_fork_handler(td, func, arg); + + /* Avoid inheriting affinity from a random parent. */ + cpuset_setthread(td->td_tid, cpuset_root); thread_lock(td); TD_SET_CAN_RUN(td); sched_prio(td, PVM); @@ -299,6 +303,9 @@ kthread_add(void (*func)(void *), void *arg, struct proc *p, tidhash_add(newtd); + /* Avoid inheriting affinity from a random parent. */ + cpuset_setthread(newtd->td_tid, cpuset_root); + /* Delay putting it on the run queue until now. */ if (!(flags & RFSTOPPED)) { thread_lock(newtd); diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index d8d53a23512e..8f08df55a9da 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -1085,6 +1085,7 @@ sysclock_snap2bintime(struct sysclock_snap *cs, struct bintime *bt, /* Boot time adjustment, for uptime/monotonic clocks. */ if (flags & FFCLOCK_UPTIME) bintime_sub(bt, &ffclock_boottime); + break; #endif default: return (EINVAL); diff --git a/sys/kern/subr_mchain.c b/sys/kern/subr_mchain.c index faf8f6719011..cd2a5f370ed2 100644 --- a/sys/kern/subr_mchain.c +++ b/sys/kern/subr_mchain.c @@ -62,7 +62,7 @@ mb_init(struct mbchain *mbp) m = m_gethdr(M_WAIT, MT_DATA); m->m_len = 0; mb_initm(mbp, m); - return 0; + return (0); } void @@ -89,13 +89,13 @@ mb_detach(struct mbchain *mbp) m = mbp->mb_top; mbp->mb_top = NULL; - return m; + return (m); } int mb_fixhdr(struct mbchain *mbp) { - return mbp->mb_top->m_pkthdr.len = m_fixhdr(mbp->mb_top); + return (mbp->mb_top->m_pkthdr.len = m_fixhdr(mbp->mb_top)); } /* @@ -124,70 +124,70 @@ mb_reserve(struct mbchain *mbp, int size) mbp->mb_count += size; bpos = mtod(m, caddr_t) + m->m_len; m->m_len += size; - return bpos; + return (bpos); } int mb_put_padbyte(struct mbchain *mbp) { caddr_t dst; - char x = 0; + uint8_t x = 0; dst = mtod(mbp->mb_cur, caddr_t) + mbp->mb_cur->m_len; - /* only add padding if address is odd */ + /* Only add padding if address is odd */ if ((unsigned long)dst & 1) - return mb_put_mem(mbp, (caddr_t)&x, 1, MB_MSYSTEM); + return (mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM)); else - return 0; + return (0); } int mb_put_uint8(struct mbchain *mbp, uint8_t x) { - return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); + return (mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM)); } int mb_put_uint16be(struct mbchain *mbp, uint16_t x) { x = htobe16(x); - return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); + return (mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM)); } int mb_put_uint16le(struct mbchain *mbp, uint16_t x) { x = htole16(x); - return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); + return (mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM)); } int mb_put_uint32be(struct mbchain *mbp, uint32_t x) { x = htobe32(x); - return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); + return (mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM)); } int mb_put_uint32le(struct mbchain *mbp, uint32_t x) { x = htole32(x); - return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); + return (mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM)); } int mb_put_int64be(struct mbchain *mbp, int64_t x) { x = htobe64(x); - return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); + return (mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM)); } int mb_put_int64le(struct mbchain *mbp, int64_t x) { x = htole64(x); - return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); + return (mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM)); } int @@ -220,7 +220,7 @@ mb_put_mem(struct mbchain *mbp, c_caddr_t source, int size, int type) dstlen = mleft; error = mbp->mb_copy(mbp, source, dst, &srclen, &dstlen); if (error) - return error; + return (error); break; case MB_MINLINE: for (src = source, count = cplen; count; count--) @@ -232,7 +232,7 @@ mb_put_mem(struct mbchain *mbp, c_caddr_t source, int size, int type) case MB_MUSER: error = copyin(source, dst, cplen); if (error) - return error; + return (error); break; case MB_MZERO: bzero(dst, cplen); @@ -246,7 +246,7 @@ mb_put_mem(struct mbchain *mbp, c_caddr_t source, int size, int type) } mbp->mb_cur = m; mbp->mb_mleft = mleft; - return 0; + return (0); } int @@ -261,7 +261,7 @@ mb_put_mbuf(struct mbchain *mbp, struct mbuf *m) } mbp->mb_mleft = M_TRAILINGSPACE(m); mbp->mb_cur = m; - return 0; + return (0); } /* @@ -277,7 +277,7 @@ mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) while (size > 0 && uiop->uio_resid) { if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) - return EFBIG; + return (EFBIG); left = uiop->uio_iov->iov_len; if (left == 0) { uiop->uio_iov++; @@ -288,7 +288,7 @@ mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) left = size; error = mb_put_mem(mbp, uiop->uio_iov->iov_base, left, mtype); if (error) - return error; + return (error); uiop->uio_offset += left; uiop->uio_resid -= left; uiop->uio_iov->iov_base = @@ -296,7 +296,7 @@ mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) uiop->uio_iov->iov_len -= left; size -= left; } - return 0; + return (0); } /* @@ -310,7 +310,7 @@ md_init(struct mdchain *mdp) m = m_gethdr(M_WAIT, MT_DATA); m->m_len = 0; md_initm(mdp, m); - return 0; + return (0); } void @@ -360,25 +360,25 @@ md_next_record(struct mdchain *mdp) struct mbuf *m; if (mdp->md_top == NULL) - return ENOENT; + return (ENOENT); m = mdp->md_top->m_nextpkt; md_done(mdp); if (m == NULL) - return ENOENT; + return (ENOENT); md_initm(mdp, m); - return 0; + return (0); } int md_get_uint8(struct mdchain *mdp, uint8_t *x) { - return md_get_mem(mdp, x, 1, MB_MINLINE); + return (md_get_mem(mdp, x, 1, MB_MINLINE)); } int md_get_uint16(struct mdchain *mdp, uint16_t *x) { - return md_get_mem(mdp, (caddr_t)x, 2, MB_MINLINE); + return (md_get_mem(mdp, (caddr_t)x, 2, MB_MINLINE)); } int @@ -389,7 +389,7 @@ md_get_uint16le(struct mdchain *mdp, uint16_t *x) if (x != NULL) *x = le16toh(v); - return error; + return (error); } int @@ -400,13 +400,13 @@ md_get_uint16be(struct mdchain *mdp, uint16_t *x) if (x != NULL) *x = be16toh(v); - return error; + return (error); } int md_get_uint32(struct mdchain *mdp, uint32_t *x) { - return md_get_mem(mdp, (caddr_t)x, 4, MB_MINLINE); + return (md_get_mem(mdp, (caddr_t)x, 4, MB_MINLINE)); } int @@ -418,7 +418,7 @@ md_get_uint32be(struct mdchain *mdp, uint32_t *x) error = md_get_uint32(mdp, &v); if (x != NULL) *x = be32toh(v); - return error; + return (error); } int @@ -430,13 +430,13 @@ md_get_uint32le(struct mdchain *mdp, uint32_t *x) error = md_get_uint32(mdp, &v); if (x != NULL) *x = le32toh(v); - return error; + return (error); } int md_get_int64(struct mdchain *mdp, int64_t *x) { - return md_get_mem(mdp, (caddr_t)x, 8, MB_MINLINE); + return (md_get_mem(mdp, (caddr_t)x, 8, MB_MINLINE)); } int @@ -448,7 +448,7 @@ md_get_int64be(struct mdchain *mdp, int64_t *x) error = md_get_int64(mdp, &v); if (x != NULL) *x = be64toh(v); - return error; + return (error); } int @@ -460,7 +460,7 @@ md_get_int64le(struct mdchain *mdp, int64_t *x) error = md_get_int64(mdp, &v); if (x != NULL) *x = le64toh(v); - return error; + return (error); } int @@ -474,7 +474,7 @@ md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type) while (size > 0) { if (m == NULL) { MBERROR("incomplete copy\n"); - return EBADRPC; + return (EBADRPC); } s = mdp->md_pos; count = mtod(m, u_char*) + m->m_len - s; @@ -506,7 +506,7 @@ md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type) } target += count; } - return 0; + return (0); } int @@ -517,7 +517,7 @@ md_get_mbuf(struct mdchain *mdp, int size, struct mbuf **ret) rm = m_copym(m, mdp->md_pos - mtod(m, u_char*), size, M_WAIT); md_get_mem(mdp, NULL, size, MB_MZERO); *ret = rm; - return 0; + return (0); } int @@ -530,7 +530,7 @@ md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; while (size > 0 && uiop->uio_resid) { if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) - return EFBIG; + return (EFBIG); left = uiop->uio_iov->iov_len; if (left == 0) { uiop->uio_iov++; @@ -542,7 +542,7 @@ md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) left = size; error = md_get_mem(mdp, uiocp, left, mtype); if (error) - return error; + return (error); uiop->uio_offset += left; uiop->uio_resid -= left; uiop->uio_iov->iov_base = @@ -550,5 +550,5 @@ md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) uiop->uio_iov->iov_len -= left; size -= left; } - return 0; + return (0); } diff --git a/sys/kern/subr_msgbuf.c b/sys/kern/subr_msgbuf.c index cd9c55149775..2d141e36c6fa 100644 --- a/sys/kern/subr_msgbuf.c +++ b/sys/kern/subr_msgbuf.c @@ -32,8 +32,10 @@ #include #include #include +#include #include #include +#include /* * Maximum number conversion buffer length: uintmax_t in base 2, plus <> @@ -46,6 +48,14 @@ static u_int msgbuf_cksum(struct msgbuf *mbp); +/* + * + */ +static int msgbuf_show_timestamp = 0; +SYSCTL_INT(_kern, OID_AUTO, msgbuf_show_timestamp, CTLFLAG_RW | CTLFLAG_TUN, + &msgbuf_show_timestamp, 0, "Show timestamp in msgbuf"); +TUNABLE_INT("kern.msgbuf_show_timestamp", &msgbuf_show_timestamp); + /* * Initialize a message buffer of the specified size at the specified * location. This also zeros the buffer area. @@ -60,7 +70,7 @@ msgbuf_init(struct msgbuf *mbp, void *ptr, int size) msgbuf_clear(mbp); mbp->msg_magic = MSG_MAGIC; mbp->msg_lastpri = -1; - mbp->msg_needsnl = 0; + mbp->msg_flags = 0; bzero(&mbp->msg_lock, sizeof(mbp->msg_lock)); mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN); } @@ -95,7 +105,7 @@ msgbuf_reinit(struct msgbuf *mbp, void *ptr, int size) mbp->msg_lastpri = -1; /* Assume that the old message buffer didn't end in a newline. */ - mbp->msg_needsnl = 1; + mbp->msg_flags |= MSGBUF_NEEDNL; bzero(&mbp->msg_lock, sizeof(mbp->msg_lock)); mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN); } @@ -134,7 +144,7 @@ msgbuf_getcount(struct msgbuf *mbp) * The caller should hold the message buffer spinlock. */ static inline void -msgbuf_do_addchar(struct msgbuf *mbp, u_int *seq, int c) +__msgbuf_do_addchar(struct msgbuf * const mbp, u_int * const seq, const int c) { u_int pos; @@ -149,6 +159,33 @@ msgbuf_do_addchar(struct msgbuf *mbp, u_int *seq, int c) *seq = MSGBUF_SEQNORM(mbp, *seq + 1); } +static inline void +msgbuf_do_addchar(struct msgbuf * const mbp, u_int * const seq, const int c) +{ + + if (msgbuf_show_timestamp && + (mbp->msg_flags & MSGBUF_NEXT_NEW_LINE) != 0) { + char buf[32]; + char const *bufp; + struct timespec ts; + int err; + + getnanouptime(&ts); + err = snprintf(buf, sizeof (buf), "[%jd.%ld] ", + (intmax_t)ts.tv_sec, ts.tv_nsec / 1000); + + for (bufp = buf; *bufp != '\0'; bufp++) + __msgbuf_do_addchar(mbp, seq, *bufp); + + mbp->msg_flags &= ~MSGBUF_NEXT_NEW_LINE; + } + + __msgbuf_do_addchar(mbp, seq, c); + + if (c == '\n') + mbp->msg_flags |= MSGBUF_NEXT_NEW_LINE; +} + /* * Append a character to a message buffer. */ @@ -207,10 +244,10 @@ msgbuf_addstr(struct msgbuf *mbp, int pri, char *str, int filter_cr) * did not end with a newline. If that is the case, we need to * insert a newline before this string. */ - if (mbp->msg_lastpri != pri && mbp->msg_needsnl != 0) { + if (mbp->msg_lastpri != pri && (mbp->msg_flags & MSGBUF_NEEDNL) != 0) { msgbuf_do_addchar(mbp, &seq, '\n'); - mbp->msg_needsnl = 0; + mbp->msg_flags &= ~MSGBUF_NEEDNL; } for (i = 0; i < len; i++) { @@ -219,7 +256,7 @@ msgbuf_addstr(struct msgbuf *mbp, int pri, char *str, int filter_cr) * (and therefore prefix_len != 0), then we need a priority * prefix for this line. */ - if (mbp->msg_needsnl == 0 && prefix_len != 0) { + if ((mbp->msg_flags & MSGBUF_NEEDNL) == 0 && prefix_len != 0) { int j; for (j = 0; j < prefix_len; j++) @@ -242,9 +279,9 @@ msgbuf_addstr(struct msgbuf *mbp, int pri, char *str, int filter_cr) * we need to insert a new prefix or insert a newline later. */ if (str[i] == '\n') - mbp->msg_needsnl = 0; + mbp->msg_flags &= ~MSGBUF_NEEDNL; else - mbp->msg_needsnl = 1; + mbp->msg_flags |= MSGBUF_NEEDNL; msgbuf_do_addchar(mbp, &seq, str[i]); } diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c index 75328f6a6379..9c4dd4888f57 100644 --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -85,7 +85,11 @@ syscallenter(struct thread *td, struct syscall_args *sa) if (error == 0) { STOPEVENT(p, S_SCE, sa->narg); - PTRACESTOP_SC(p, td, S_PT_SCE); + if (p->p_flag & P_TRACED && p->p_stops & S_PT_SCE) { + PROC_LOCK(p); + ptracestop((td), SIGTRAP); + PROC_UNLOCK(p); + } if (td->td_dbgflags & TDB_USERWR) { /* * Reread syscall number and arguments if diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 451038036da0..2060efe6a337 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -1145,6 +1145,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) pl->pl_flags |= PL_FLAG_FORKED; pl->pl_child_pid = td2->td_dbg_forked; } + if (td2->td_dbgflags & TDB_CHILD) + pl->pl_flags |= PL_FLAG_CHILD; pl->pl_sigmask = td2->td_sigmask; pl->pl_siglist = td2->td_siglist; strcpy(pl->pl_tdname, td2->td_name); diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 2bad48494c3e..c717c0d9675f 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -891,14 +891,14 @@ shminit() printf("kern.ipc.shmmaxpgs is now called kern.ipc.shmall!\n"); #endif TUNABLE_ULONG_FETCH("kern.ipc.shmall", &shminfo.shmall); - - /* Initialize shmmax dealing with possible overflow. */ - for (i = PAGE_SIZE; i > 0; i--) { - shminfo.shmmax = shminfo.shmall * i; - if (shminfo.shmmax >= shminfo.shmall) - break; + if (!TUNABLE_ULONG_FETCH("kern.ipc.shmmax", &shminfo.shmmax)) { + /* Initialize shmmax dealing with possible overflow. */ + for (i = PAGE_SIZE; i > 0; i--) { + shminfo.shmmax = shminfo.shmall * i; + if (shminfo.shmmax >= shminfo.shmall) + break; + } } - TUNABLE_ULONG_FETCH("kern.ipc.shmmin", &shminfo.shmmin); TUNABLE_ULONG_FETCH("kern.ipc.shmmni", &shminfo.shmmni); TUNABLE_ULONG_FETCH("kern.ipc.shmseg", &shminfo.shmseg); diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 01ac80900a14..9a701d7ba2e8 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1229,7 +1229,7 @@ tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...) /* Slave call-out devices. */ if (tp->t_flags & TF_INITLOCK) { - dev = make_dev_cred(&ttyil_cdevsw, + dev = make_dev_cred(&ttyil_cdevsw, TTYUNIT_CALLOUT | TTYUNIT_INIT, cred, UID_UUCP, GID_DIALER, 0660, "cua%s.init", name); dev_depends(tp->t_dev, dev); diff --git a/sys/kern/tty_info.c b/sys/kern/tty_info.c index d2b059ca41b0..6849d0b06ed1 100644 --- a/sys/kern/tty_info.c +++ b/sys/kern/tty_info.c @@ -109,7 +109,7 @@ thread_compare(struct thread *td, struct thread *td2) /* * Fetch running stats, pctcpu usage, and interruptable flag. - */ + */ thread_lock(td); runa = TD_IS_RUNNING(td) | TD_ON_RUNQ(td); slpa = td->td_flags & TDF_SINTR; @@ -173,7 +173,7 @@ proc_compare(struct proc *p1, struct proc *p2) PROC_LOCK(p2); runb = proc_sum(p2, &estb); PROC_UNLOCK(p2); - + /* * see if at least one of them is runnable */ diff --git a/sys/kern/tty_ttydisc.c b/sys/kern/tty_ttydisc.c index 2a0bb4b7c6f7..1ac204b3aaa7 100644 --- a/sys/kern/tty_ttydisc.c +++ b/sys/kern/tty_ttydisc.c @@ -661,7 +661,6 @@ ttydisc_echo(struct tty *tp, char c, int quote) return ttydisc_echo_force(tp, c, quote); } - static void ttydisc_reprint_char(void *d, char c, int quote) { diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index eaadf1314646..76f8da6f663d 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -2706,6 +2706,7 @@ convert_sigevent32(struct sigevent32 *sig32, struct sigevent *sig) break; case SIGEV_KEVENT: CP(*sig32, *sig, sigev_notify_kqueue); + CP(*sig32, *sig, sigev_notify_kevent_flags); PTRIN_CP(*sig32, *sig, sigev_value.sival_ptr); break; default: diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 4562ebc0888d..81ad44e0a3ab 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -456,7 +456,7 @@ cache_zap(ncp) */ int -cache_lookup_times(dvp, vpp, cnp, tsp, ticksp) +cache_lookup(dvp, vpp, cnp, tsp, ticksp) struct vnode *dvp; struct vnode **vpp; struct componentname *cnp; @@ -994,7 +994,7 @@ vfs_cache_lookup(ap) if (error) return (error); - error = cache_lookup(dvp, vpp, cnp); + error = cache_lookup(dvp, vpp, cnp, NULL, NULL); if (error == 0) return (VOP_CACHEDLOOKUP(dvp, vpp, cnp)); if (error == -1) @@ -1374,12 +1374,9 @@ vn_commname(struct vnode *vp, char *buf, u_int buflen) /* ABI compat shims for old kernel modules. */ #undef cache_enter -#undef cache_lookup void cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp); -int cache_lookup(struct vnode *dvp, struct vnode **vpp, - struct componentname *cnp); void cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) @@ -1388,13 +1385,6 @@ cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) cache_enter_time(dvp, vp, cnp, NULL); } -int -cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) -{ - - return (cache_lookup_times(dvp, vpp, cnp, NULL, NULL)); -} - /* * This function updates path string to vnode's full global path * and checks the size of the new path string against the pathlen argument. diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 9b10db37b24d..aca7058e8f1c 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -604,7 +604,7 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount) int async; if (vp->v_type == VREG) { - async = vp->v_mount->mnt_kern_flag & MNTK_ASYNC; + async = DOINGASYNC(vp); lblocksize = vp->v_mount->mnt_stat.f_iosize; } else { async = 0; diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 5fa086cf944b..ddc17cc326ea 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1039,6 +1039,7 @@ vfs_domount( struct vfsconf *vfsp; struct nameidata nd; struct vnode *vp; + char *pathbuf; int error; /* @@ -1102,12 +1103,15 @@ vfs_domount( NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; if ((fsflags & MNT_UPDATE) == 0) { - error = vn_path_to_global_path(td, vp, fspath, MNAMELEN); + pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK); + strcpy(pathbuf, fspath); + error = vn_path_to_global_path(td, vp, pathbuf, MNAMELEN); /* debug.disablefullpath == 1 results in ENODEV */ if (error == 0 || error == ENODEV) { - error = vfs_domount_first(td, vfsp, fspath, vp, + error = vfs_domount_first(td, vfsp, pathbuf, vp, fsflags, optlist); } + free(pathbuf, M_TEMP); } else error = vfs_domount_update(td, vp, fsflags, optlist); mtx_unlock(&Giant); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 6cdd3725122a..28562e62bc83 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -3521,7 +3521,7 @@ sync_fsync(struct vop_fsync_args *ap) { struct vnode *syncvp = ap->a_vp; struct mount *mp = syncvp->v_mount; - int error; + int error, save; struct bufobj *bo; /* @@ -3551,17 +3551,10 @@ sync_fsync(struct vop_fsync_args *ap) vfs_unbusy(mp); return (0); } - MNT_ILOCK(mp); - mp->mnt_noasync++; - mp->mnt_kern_flag &= ~MNTK_ASYNC; - MNT_IUNLOCK(mp); + save = curthread_pflags_set(TDP_SYNCIO); vfs_msync(mp, MNT_NOWAIT); error = VFS_SYNC(mp, MNT_LAZY); - MNT_ILOCK(mp); - mp->mnt_noasync--; - if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0) - mp->mnt_kern_flag |= MNTK_ASYNC; - MNT_IUNLOCK(mp); + curthread_pflags_restore(save); vn_finished_write(mp); vfs_unbusy(mp); return (error); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 31ad27644150..e460570102f9 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -134,7 +134,7 @@ sys_sync(td, uap) struct sync_args *uap; { struct mount *mp, *nmp; - int vfslocked; + int save, vfslocked; mtx_lock(&mountlist_mtx); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { @@ -145,18 +145,10 @@ sys_sync(td, uap) vfslocked = VFS_LOCK_GIANT(mp); if ((mp->mnt_flag & MNT_RDONLY) == 0 && vn_start_write(NULL, &mp, V_NOWAIT) == 0) { - MNT_ILOCK(mp); - mp->mnt_noasync++; - mp->mnt_kern_flag &= ~MNTK_ASYNC; - MNT_IUNLOCK(mp); + save = curthread_pflags_set(TDP_SYNCIO); vfs_msync(mp, MNT_NOWAIT); VFS_SYNC(mp, MNT_NOWAIT); - MNT_ILOCK(mp); - mp->mnt_noasync--; - if ((mp->mnt_flag & MNT_ASYNC) != 0 && - mp->mnt_noasync == 0) - mp->mnt_kern_flag |= MNTK_ASYNC; - MNT_IUNLOCK(mp); + curthread_pflags_restore(save); vn_finished_write(mp); } VFS_UNLOCK_GIANT(vfslocked); diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h index 30cc5f2e7ab7..39efeeeee0bd 100644 --- a/sys/mips/include/elf.h +++ b/sys/mips/include/elf.h @@ -189,9 +189,27 @@ typedef struct { #define R_MIPS_REL16 33 #define R_MIPS_ADD_IMMEDIATE 34 #define R_MIPS_PJUMP 35 -#define R_MIPS_ERLGOT 36 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 -#define R_MIPS_max 37 +/* + * TLS relocations + */ +#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ +#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ +#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ +#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ +#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ +#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ +#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ +#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ +#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ +#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ +#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ +#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ +#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ + +#define R_MIPS_max 51 #define R_TYPE(name) __CONCAT(R_MIPS_,name) /* Define "machine" characteristics */ diff --git a/sys/mips/include/mips_opcode.h b/sys/mips/include/mips_opcode.h index 72f281a619d6..fd0e9763e4af 100644 --- a/sys/mips/include/mips_opcode.h +++ b/sys/mips/include/mips_opcode.h @@ -176,6 +176,11 @@ typedef union { #define OP_LDL 032 #define OP_LDR 033 +#define OP_SPECIAL2 034 +#define OP_JALX 035 + +#define OP_SPECIAL3 037 + #define OP_LB 040 #define OP_LH 041 #define OP_LWL 042 @@ -388,6 +393,11 @@ typedef union { #define OP_R_BLTZALL OP_BLTZALL #define OP_R_BGEZALL OP_BGEZALL +/* + * Values for the 'func' field when 'op' == OP_SPECIAL3. + */ +#define OP_RDHWR 073 + /* * Values for the 'rs' field when 'op' == OP_COPz. */ diff --git a/sys/mips/mips/locore.S b/sys/mips/mips/locore.S index c6e78a26c5d0..3b967a2da166 100644 --- a/sys/mips/mips/locore.S +++ b/sys/mips/mips/locore.S @@ -118,7 +118,7 @@ VECTOR(_locore, unknown) */ li t1, MIPS_SR_COP_1_BIT #ifdef __mips_n64 - or t1, MIPS_SR_KX | MIPS_SR_UX + or t1, MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX #endif #endif /* diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c index 3b632d0c690e..77cfcd0ec1d6 100644 --- a/sys/mips/mips/trap.c +++ b/sys/mips/mips/trap.c @@ -414,6 +414,7 @@ trap(struct trapframe *trapframe) intptr_t addr = 0; register_t pc; int cop; + register_t *frame_regs; trapdebug_enter(trapframe, 0); @@ -762,9 +763,29 @@ trap(struct trapframe *trapframe) } case T_RES_INST + T_USER: - log_illegal_instruction("RES_INST", trapframe); - i = SIGILL; - addr = trapframe->pc; + { + InstFmt inst; + inst = *(InstFmt *)(intptr_t)trapframe->pc; + switch (inst.RType.op) { + case OP_SPECIAL3: + switch (inst.RType.func) { + case OP_RDHWR: + /* Register 29 used for TLS */ + if (inst.RType.rd == 29) { + frame_regs = &(trapframe->zero); + frame_regs[inst.RType.rt] = (register_t)(intptr_t)td->td_md.md_tls; + trapframe->pc += sizeof(int); + goto out; + } + break; + } + break; + } + + log_illegal_instruction("RES_INST", trapframe); + i = SIGILL; + addr = trapframe->pc; + } break; case T_C2E: case T_C2E + T_USER: diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c index bdd73e75c88a..faff43ba496c 100644 --- a/sys/mips/mips/vm_machdep.c +++ b/sys/mips/mips/vm_machdep.c @@ -601,7 +601,18 @@ int cpu_set_user_tls(struct thread *td, void *tls_base) { - td->td_md.md_tls = tls_base; + /* + * tls_base passed to this function + * from thr_new call and points to actual TCB struct, + * so we should add TP_OFFSET + sizeof(struct tcb) + * to make it the same way TLS base is passed to + * MIPS_SET_TLS/MIPS_GET_TLS API + */ +#ifdef __mips_n64 + td->td_md.md_tls = (char*)tls_base + 0x7010; +#else + td->td_md.md_tls = (char*)tls_base + 0x7008; +#endif return (0); } diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 9ea9bb62bb0b..0cf237fb88d5 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -2,6 +2,9 @@ .include +# Modules that include binary-only blobs of microcode should be selectable by +# MK_SOURCELESS_UCODE option (see below). + SUBDIR= ${_3dfx} \ ${_3dfx_linux} \ ${_aac} \ @@ -36,7 +39,7 @@ SUBDIR= ${_3dfx} \ ath \ ath_pci \ ${_auxio} \ - bce \ + ${_bce} \ bfe \ bge \ ${_bxe} \ @@ -95,13 +98,13 @@ SUBDIR= ${_3dfx} \ ${_ex} \ ${_exca} \ ${_ext2fs} \ - fatm \ + ${_fatm} \ fdc \ fdescfs \ ${_fe} \ firewire \ firmware \ - fxp \ + ${_fxp} \ gem \ geom \ ${_glxiic} \ @@ -148,7 +151,7 @@ SUBDIR= ${_3dfx} \ ${_isci} \ iscsi \ isp \ - ispfw \ + ${_ispfw} \ ${_iwi} \ ${_iwifw} \ ${_iwn} \ @@ -209,7 +212,7 @@ SUBDIR= ${_3dfx} \ ${_mthca} \ mvs \ mwl \ - mwlfw \ + ${_mwlfw} \ mxge \ my \ ${_ncp} \ @@ -237,6 +240,7 @@ SUBDIR= ${_3dfx} \ ${_nwfs} \ ${_nxge} \ ${_opensolaris} \ + oce \ ${_padlock} \ patm \ ${_pccard} \ @@ -259,14 +263,14 @@ SUBDIR= ${_3dfx} \ puc \ ${_qlxgb} \ ral \ - ralfw \ + ${_ralfw} \ ${_random} \ rc4 \ ${_rdma} \ re \ reiserfs \ rl \ - runfw \ + ${_runfw} \ ${_s3} \ ${_safe} \ ${_sbni} \ @@ -276,7 +280,7 @@ SUBDIR= ${_3dfx} \ sdhci \ sem \ send \ - sf \ + ${_sf} \ ${_sfxge} \ sge \ siba_bwn \ @@ -285,7 +289,7 @@ SUBDIR= ${_3dfx} \ sis \ sk \ ${_smbfs} \ - sn \ + ${_sn} \ ${_snc} \ snp \ ${_sound} \ @@ -300,7 +304,7 @@ SUBDIR= ${_3dfx} \ ${_sym} \ ${_syscons} \ sysvipc \ - ti \ + ${_ti} \ tl \ tmpfs \ ${_tpm} \ @@ -309,7 +313,7 @@ SUBDIR= ${_3dfx} \ twe \ tws \ tx \ - txp \ + ${_txp} \ uart \ ubsec \ udf \ @@ -358,8 +362,10 @@ _vpo= vpo # No barrier instruction support (specific to this driver) _sym= sym # intr_disable() is a macro, causes problems +.if ${MK_SOURCELESS_UCODE} != "no" _cxgb= cxgb .endif +.endif .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) .if exists(${.CURDIR}/../opencrypto) @@ -402,6 +408,20 @@ _pfsync= pfsync .endif .endif +.if ${MK_SOURCELESS_UCODE} != "no" +_bce= bce +_fatm= fatm +_fxp= fxp +_ispfw= ispfw +_mwlfw= mwlfw +_ralfw= ralfw +_runfw= runfw +_sf= sf +_sn= sn +_ti= ti +_txp= txp +.endif + .if ${MACHINE_CPUARCH} == "i386" # XXX some of these can move to the general case when de-i386'ed # XXX some of these can move now, but are untested on other architectures. @@ -417,9 +437,13 @@ _bktr= bktr _bxe= bxe _cardbus= cardbus _cbb= cbb +.if ${MK_SOURCELESS_UCODE} != "no" _ce= ce +.endif _coff= coff +.if ${MK_SOURCELESS_UCODE} != "no" _cp= cp +.endif _cpuctl= cpuctl _cpufreq= cpufreq _cs= cs @@ -508,36 +532,52 @@ _ciss= ciss _cm= cm _cmx= cmx _coretemp= coretemp +.if ${MK_SOURCELESS_UCODE} != "no" _ctau= ctau +.endif _dpt= dpt _ex= ex +.if ${MK_SOURCELESS_HOST} != "no" _hpt27xx= hpt27xx +.endif _hptiop= hptiop +.if ${MK_SOURCELESS_HOST} != "no" _hptmv= hptmv _hptrr= hptrr +.endif _ichwd= ichwd _ida= ida _iir= iir _ipmi= ipmi _ips= ips _ipw= ipw +.if ${MK_SOURCELESS_UCODE} != "no" _ipwfw= ipwfw +.endif _isci= isci _iwi= iwi +.if ${MK_SOURCELESS_UCODE} != "no" _iwifw= iwifw +.endif _iwn= iwn +.if ${MK_SOURCELESS_UCODE} != "no" _iwnfw= iwnfw +.endif _ixgb= ixgb _ixgbe= ixgbe _mly= mly _nfe= nfe +.if ${MK_SOURCELESS_HOST} != "no" _nve= nve +.endif _nvram= nvram _nxge= nxge _tpm= tpm _viawd= viawd _wpi= wpi +.if ${MK_SOURCELESS_UCODE} != "no" _wpifw= wpifw +.endif .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _padlock= padlock .endif @@ -589,10 +629,14 @@ _et= et _em= em _exca= exca _ext2fs= ext2fs +.if ${MK_SOURCELESS_HOST} != "no" _hpt27xx= hpt27xx +.endif _hptiop= hptiop +.if ${MK_SOURCELESS_HOST} != "no" _hptmv= hptmv _hptrr= hptrr +.endif _i2c= i2c _ichwd= ichwd _ida= ida @@ -603,12 +647,18 @@ _io= io _ipmi= ipmi _ips= ips _ipw= ipw +.if ${MK_SOURCELESS_UCODE} != "no" _ipwfw= ipwfw +.endif _isci= isci _iwi= iwi +.if ${MK_SOURCELESS_UCODE} != "no" _iwifw= iwifw +.endif _iwn= iwn +.if ${MK_SOURCELESS_UCODE} != "no" _iwnfw= iwnfw +.endif _ixgb= ixgb _ixgbe= ixgbe _lindev= lindev @@ -624,7 +674,9 @@ _mthca= mthca .endif _ndis= ndis _nfe= nfe +.if ${MK_SOURCELESS_HOST} != "no" _nve= nve +.endif _nvram= nvram _nxge= nxge .if ${MK_CDDL} != "no" || defined(ALL_MODULES) @@ -654,7 +706,9 @@ _vxge= vxge _x86bios= x86bios _wi= wi _wpi= wpi +.if ${MK_SOURCELESS_UCODE} != "no" _wpifw= wpifw +.endif .if ${MK_ZFS} != "no" || defined(ALL_MODULES) _zfs= zfs .endif @@ -711,6 +765,7 @@ _cardbus= cardbus _cbb= cbb _cfi= cfi _cpufreq= cpufreq +_exca= exca _nvram= powermac_nvram _pccard= pccard _smbfs= smbfs diff --git a/sys/modules/acpi/acpi/Makefile b/sys/modules/acpi/acpi/Makefile index 3c2e7babd35f..6da186fdc4fc 100644 --- a/sys/modules/acpi/acpi/Makefile +++ b/sys/modules/acpi/acpi/Makefile @@ -12,17 +12,17 @@ .error "The ACPI module is only for amd64 and i386" .endif -.PATH: ${.CURDIR}/../../../contrib/dev/acpica/debugger \ - ${.CURDIR}/../../../contrib/dev/acpica/disassembler \ - ${.CURDIR}/../../../contrib/dev/acpica/dispatcher \ - ${.CURDIR}/../../../contrib/dev/acpica/events \ - ${.CURDIR}/../../../contrib/dev/acpica/executer \ - ${.CURDIR}/../../../contrib/dev/acpica/hardware \ - ${.CURDIR}/../../../contrib/dev/acpica/namespace \ - ${.CURDIR}/../../../contrib/dev/acpica/parser \ - ${.CURDIR}/../../../contrib/dev/acpica/resources \ - ${.CURDIR}/../../../contrib/dev/acpica/tables \ - ${.CURDIR}/../../../contrib/dev/acpica/utilities \ +.PATH: ${.CURDIR}/../../../contrib/dev/acpica/components/debugger \ + ${.CURDIR}/../../../contrib/dev/acpica/components/disassembler \ + ${.CURDIR}/../../../contrib/dev/acpica/components/dispatcher \ + ${.CURDIR}/../../../contrib/dev/acpica/components/events \ + ${.CURDIR}/../../../contrib/dev/acpica/components/executer \ + ${.CURDIR}/../../../contrib/dev/acpica/components/hardware \ + ${.CURDIR}/../../../contrib/dev/acpica/components/namespace \ + ${.CURDIR}/../../../contrib/dev/acpica/components/parser \ + ${.CURDIR}/../../../contrib/dev/acpica/components/resources \ + ${.CURDIR}/../../../contrib/dev/acpica/components/tables \ + ${.CURDIR}/../../../contrib/dev/acpica/components/utilities \ ${.CURDIR}/../../../pci \ ${.CURDIR}/../../../dev/acpica \ ${.CURDIR}/../../../dev/acpica/Osd \ @@ -45,8 +45,8 @@ SRCS+= exconfig.c exconvrt.c excreate.c exdebug.c exdump.c exfield.c SRCS+= exfldio.c exmisc.c exmutex.c exnames.c exoparg1.c exoparg2.c SRCS+= exoparg3.c exoparg6.c exprep.c exregion.c exresnte.c exresolv.c SRCS+= exresop.c exstore.c exstoren.c exstorob.c exsystem.c exutils.c -SRCS+= hwacpi.c hwgpe.c hwpci.c hwregs.c hwsleep.c hwtimer.c hwvalid.c -SRCS+= hwxface.c +SRCS+= hwacpi.c hwesleep.c hwgpe.c hwpci.c hwregs.c hwsleep.c hwtimer.c +SRCS+= hwvalid.c hwxface.c hwxfsleep.c SRCS+= nsaccess.c nsalloc.c nsdump.c nseval.c nsinit.c nsload.c nsnames.c SRCS+= nsobject.c nsparse.c nspredef.c nsrepair.c nsrepair2.c nssearch.c SRCS+= nsutils.c nswalk.c nsxfeval.c nsxfname.c nsxfobj.c diff --git a/sys/modules/drm/Makefile b/sys/modules/drm/Makefile index c2c74a522056..21328fcca951 100644 --- a/sys/modules/drm/Makefile +++ b/sys/modules/drm/Makefile @@ -1,15 +1,26 @@ # $FreeBSD$ +.include + +# Modules that include binary-only blobs of microcode should be selectable by +# MK_SOURCELESS_UCODE option (see below). + SUBDIR = \ drm \ i915 \ mach64 \ - mga \ - r128 \ - radeon \ + ${_mga} \ + ${_r128} \ + ${_radeon} \ savage \ sis \ tdfx \ via +.if ${MK_SOURCELESS_UCODE} != "no" +_mga= mga +_r128= r128 +_radeon= radeon +.endif + .include diff --git a/sys/modules/ipdivert/Makefile b/sys/modules/ipdivert/Makefile index 14f92ad3d879..39500ceca19a 100644 --- a/sys/modules/ipdivert/Makefile +++ b/sys/modules/ipdivert/Makefile @@ -5,7 +5,7 @@ .PATH: ${.CURDIR}/../../netinet KMOD= ipdivert -SRCS= ip_divert.c opt_inet.h opt_inet6.h +SRCS= ip_divert.c opt_inet.h opt_inet6.h opt_sctp.h .if !defined(KERNBUILDDIR) .if ${MK_INET_SUPPORT} != "no" diff --git a/sys/modules/isci/Makefile b/sys/modules/isci/Makefile index 38b991021c91..82d401864dc2 100755 --- a/sys/modules/isci/Makefile +++ b/sys/modules/isci/Makefile @@ -87,6 +87,4 @@ SRCS += \ SRCS += opt_scsi.h opt_cam.h opt_isci.h SRCS += device_if.h bus_if.h pci_if.h -CC = gcc - .include diff --git a/sys/modules/kgssapi/Makefile b/sys/modules/kgssapi/Makefile index 223ef246cdbb..691763336b1e 100644 --- a/sys/modules/kgssapi/Makefile +++ b/sys/modules/kgssapi/Makefile @@ -44,12 +44,12 @@ CLEANFILES= gssd.h gssd_xdr.c gssd_clnt.c S= ${.CURDIR}/../.. gssd.h: $S/kgssapi/gssd.x - rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h + RPCGEN_CPP=${CPP:Q} rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h gssd_xdr.c: $S/kgssapi/gssd.x - rpcgen -c $S/kgssapi/gssd.x -o gssd_xdr.c + RPCGEN_CPP=${CPP:Q} rpcgen -c $S/kgssapi/gssd.x -o gssd_xdr.c gssd_clnt.c: $S/kgssapi/gssd.x - rpcgen -lM $S/kgssapi/gssd.x | grep -v string.h > gssd_clnt.c + RPCGEN_CPP=${CPP:Q} rpcgen -lM $S/kgssapi/gssd.x | grep -v string.h > gssd_clnt.c .include diff --git a/sys/modules/kgssapi_krb5/Makefile b/sys/modules/kgssapi_krb5/Makefile index 9dbb946a2f9f..337402f64e63 100644 --- a/sys/modules/kgssapi_krb5/Makefile +++ b/sys/modules/kgssapi_krb5/Makefile @@ -18,6 +18,6 @@ CLEANFILES= gssd.h S= ${.CURDIR}/../.. gssd.h: $S/kgssapi/gssd.x - rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h + RPCGEN_CPP=${CPP:Q} rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h .include diff --git a/sys/modules/oce/Makefile b/sys/modules/oce/Makefile new file mode 100644 index 000000000000..4821533f01c5 --- /dev/null +++ b/sys/modules/oce/Makefile @@ -0,0 +1,15 @@ +# +# $FreeBSD$ +# + +.PATH: ${.CURDIR}/../../dev/oce +KMOD = oce +SRCS = oce_if.c oce_hw.c oce_mbox.c oce_util.c oce_queue.c oce_sysctl.c +SRCS += bus_if.h device_if.h pci_if.h opt_inet.h opt_inet6.h + +CFLAGS+= -I${.CURDIR}/../../dev/oce -DSMP + +# uncomment for lock profiling statistics +#CFLAGS += -DLOCK_PROFILING + +.include diff --git a/sys/modules/sound/driver/Makefile b/sys/modules/sound/driver/Makefile index ef018b2f6074..80df177c9f2f 100644 --- a/sys/modules/sound/driver/Makefile +++ b/sys/modules/sound/driver/Makefile @@ -1,10 +1,21 @@ # $FreeBSD$ -SUBDIR= ad1816 als4000 atiixp cs4281 csa ds1 emu10k1 emu10kx -SUBDIR+= envy24 envy24ht es137x ess fm801 hda ich maestro maestro3 +.include + +# Modules that include binary-only blobs of microcode should be selectable by +# MK_SOURCELESS_UCODE option (see below). + +SUBDIR= ad1816 als4000 atiixp cs4281 ${_csa} ${_ds1} emu10k1 emu10kx +SUBDIR+= envy24 envy24ht es137x ess fm801 hda ich maestro ${_maestro3} SUBDIR+= neomagic sb16 sb8 sbc solo spicds t4dwave via8233 SUBDIR+= via82c686 vibes driver uaudio +.if ${MK_SOURCELESS_UCODE} != "no" +_csa= csa +_ds1= ds1 +_maestro3= maestro3 +.endif + .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" SUBDIR+= cmi mss .endif diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile index 3df35bc79857..18748dd3c138 100644 --- a/sys/modules/usb/Makefile +++ b/sys/modules/usb/Makefile @@ -25,16 +25,28 @@ # SUCH DAMAGE. # +.include + +# Modules that include binary-only blobs of microcode should be selectable by +# MK_SOURCELESS_UCODE option (see below). + SUBDIR = usb SUBDIR += ehci musb ohci uhci xhci uss820dci ${_at91dci} ${_atmegadci} ${_avr32dci} -SUBDIR += rum run uath upgt usie ural zyd ${_urtw} +SUBDIR += ${_rum} run ${_uath} upgt usie ural ${_zyd} ${_urtw} SUBDIR += atp uhid ukbd ums udbp ufm uep SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \ umct umcs umodem umoscom uplcom uslcom uvisor uvscom -SUBDIR += uether aue axe cdce cue kue mos rue udav uhso ipheth +SUBDIR += uether aue axe cdce cue ${_kue} mos rue udav uhso ipheth SUBDIR += usfs umass urio SUBDIR += quirk template +.if ${MK_SOURCELESS_UCODE} != "no" +_rum= rum +_uath= uath +_zyd= zyd +_kue= kue +.endif + .if ${MACHINE_CPUARCH} == "amd64" _urtw= urtw .endif diff --git a/sys/modules/wi/Makefile b/sys/modules/wi/Makefile index 3d7cc71b6c8f..badbd750616e 100644 --- a/sys/modules/wi/Makefile +++ b/sys/modules/wi/Makefile @@ -4,6 +4,7 @@ KMOD= if_wi SRCS= if_wi.c if_wi_pccard.c if_wi_pci.c \ - card_if.h device_if.h bus_if.h pci_if.h pccarddevs.h + card_if.h device_if.h bus_if.h pci_if.h pccarddevs.h \ + opt_wlan.h .include diff --git a/sys/modules/wlan/Makefile b/sys/modules/wlan/Makefile index 8eb83bf60f8c..7205e28f14db 100644 --- a/sys/modules/wlan/Makefile +++ b/sys/modules/wlan/Makefile @@ -13,8 +13,8 @@ SRCS= ieee80211.c ieee80211_action.c ieee80211_ageq.c \ ieee80211_ht.c ieee80211_hwmp.c ieee80211_adhoc.c ieee80211_hostap.c \ ieee80211_monitor.c ieee80211_sta.c ieee80211_wds.c ieee80211_ddb.c \ ieee80211_tdma.c -SRCS+= bus_if.h device_if.h opt_inet.h opt_inet6.h opt_ipx.h opt_wlan.h \ - opt_ddb.h +SRCS+= bus_if.h device_if.h opt_ddb.h opt_inet.h opt_inet6.h opt_ipx.h \ + opt_tdma.h opt_wlan.h .if !defined(KERNBUILDDIR) opt_wlan.h: diff --git a/sys/net/if.c b/sys/net/if.c index 63ae79bfc02b..42ccda70dfad 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -456,7 +456,6 @@ if_alloc(u_char type) ifp->if_afdata_initialized = 0; IF_AFDATA_LOCK_INIT(ifp); TAILQ_INIT(&ifp->if_addrhead); - TAILQ_INIT(&ifp->if_prefixhead); TAILQ_INIT(&ifp->if_multiaddrs); TAILQ_INIT(&ifp->if_groups); #ifdef MAC @@ -1408,7 +1407,7 @@ if_maddr_runlock(struct ifnet *ifp) } /* - * Reference count functions for ifaddrs. + * Initialization, destruction and refcounting functions for ifaddrs. */ void ifa_init(struct ifaddr *ifa) @@ -1416,6 +1415,7 @@ ifa_init(struct ifaddr *ifa) mtx_init(&ifa->ifa_mtx, "ifaddr", NULL, MTX_DEF); refcount_init(&ifa->ifa_refcnt, 1); + ifa->if_data.ifi_datalen = sizeof(ifa->if_data); } void diff --git a/sys/net/if.h b/sys/net/if.h index e17dac2d97fa..47292cb29985 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -244,6 +244,7 @@ struct if_data { /* * Message format for use in obtaining information about interfaces * from getkerninfo and the routing socket + * For the new, extensible interface see struct if_msghdrl below. */ struct if_msghdr { u_short ifm_msglen; /* to skip over non-understood messages */ @@ -255,9 +256,35 @@ struct if_msghdr { struct if_data ifm_data;/* statistics and other data about if */ }; +/* + * The 'l' version shall be used by new interfaces, like NET_RT_IFLISTL. It is + * extensible after ifm_data_off or within ifm_data. Both the if_msghdr and + * if_data now have a member field detailing the struct length in addition to + * the routing message length. Macros are provided to find the start of + * ifm_data and the start of the socket address strucutres immediately following + * struct if_msghdrl given a pointer to struct if_msghdrl. + */ +#define IF_MSGHDRL_IFM_DATA(_l) \ + (struct if_data *)((char *)(_l) + (_l)->ifm_data_off) +#define IF_MSGHDRL_RTA(_l) \ + (void *)((uintptr_t)(_l) + (_l)->ifm_len) +struct if_msghdrl { + u_short ifm_msglen; /* to skip over non-understood messages */ + u_char ifm_version; /* future binary compatibility */ + u_char ifm_type; /* message type */ + int ifm_addrs; /* like rtm_addrs */ + int ifm_flags; /* value of if_flags */ + u_short ifm_index; /* index for associated ifp */ + u_short _ifm_spare1; /* spare space to grow if_index, see if_var.h */ + u_short ifm_len; /* length of if_msghdrl incl. if_data */ + u_short ifm_data_off; /* offset of if_data from beginning */ + struct if_data ifm_data;/* statistics and other data about if */ +}; + /* * Message format for use in obtaining information about interface addresses * from getkerninfo and the routing socket + * For the new, extensible interface see struct ifa_msghdrl below. */ struct ifa_msghdr { u_short ifam_msglen; /* to skip over non-understood messages */ @@ -267,6 +294,31 @@ struct ifa_msghdr { int ifam_flags; /* value of ifa_flags */ u_short ifam_index; /* index for associated ifp */ int ifam_metric; /* value of ifa_metric */ +}; + +/* + * The 'l' version shall be used by new interfaces, like NET_RT_IFLISTL. It is + * extensible after ifam_metric or within ifam_data. Both the ifa_msghdrl and + * if_data now have a member field detailing the struct length in addition to + * the routing message length. Macros are provided to find the start of + * ifm_data and the start of the socket address strucutres immediately following + * struct ifa_msghdrl given a pointer to struct ifa_msghdrl. + */ +#define IFA_MSGHDRL_IFAM_DATA(_l) \ + (struct if_data *)((char *)(_l) + (_l)->ifam_data_off) +#define IFA_MSGHDRL_RTA(_l) \ + (void *)((uintptr_t)(_l) + (_l)->ifam_len) +struct ifa_msghdrl { + u_short ifam_msglen; /* to skip over non-understood messages */ + u_char ifam_version; /* future binary compatibility */ + u_char ifam_type; /* message type */ + int ifam_addrs; /* like rtm_addrs */ + int ifam_flags; /* value of ifa_flags */ + u_short ifam_index; /* index for associated ifp */ + u_short _ifam_spare1; /* spare space to grow if_index, see if_var.h */ + u_short ifam_len; /* length of ifa_msghdrl incl. if_data */ + u_short ifam_data_off; /* offset of if_data from beginning */ + int ifam_metric; /* value of ifa_metric */ struct if_data ifam_data;/* statistics and other data about if or * address */ }; diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 8793cf73ec03..8f9dc9c37f6e 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -355,19 +355,26 @@ static int pfil_local_phys = 0; /* run pfil hooks on the physical interface for locally destined packets */ static int log_stp = 0; /* log STP state changes */ static int bridge_inherit_mac = 0; /* share MAC with first bridge member */ +TUNABLE_INT("net.link.bridge.pfil_onlyip", &pfil_onlyip); SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RW, &pfil_onlyip, 0, "Only pass IP packets when pfil is enabled"); +TUNABLE_INT("net.link.bridge.ipfw_arp", &pfil_ipfw_arp); SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp, CTLFLAG_RW, &pfil_ipfw_arp, 0, "Filter ARP packets through IPFW layer2"); +TUNABLE_INT("net.link.bridge.pfil_bridge", &pfil_bridge); SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RW, &pfil_bridge, 0, "Packet filter on the bridge interface"); +TUNABLE_INT("net.link.bridge.pfil_member", &pfil_member); SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RW, &pfil_member, 0, "Packet filter on the member interface"); +TUNABLE_INT("net.link.bridge.pfil_local_phys", &pfil_local_phys); SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys, CTLFLAG_RW, &pfil_local_phys, 0, "Packet filter on the physical interface for locally destined packets"); +TUNABLE_INT("net.link.bridge.log_stp", &log_stp); SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp, CTLFLAG_RW, &log_stp, 0, "Log STP state changes"); +TUNABLE_INT("net.link.bridge.inherit_mac", &bridge_inherit_mac); SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac, CTLFLAG_RW, &bridge_inherit_mac, 0, "Inherit MAC address from the first bridge member"); diff --git a/sys/net/if_var.h b/sys/net/if_var.h index d1157afeae8f..f7567853434e 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -96,7 +96,6 @@ struct vnet; TAILQ_HEAD(ifnethead, ifnet); /* we use TAILQs so that the order of */ TAILQ_HEAD(ifaddrhead, ifaddr); /* instantiation is preserved in the list */ -TAILQ_HEAD(ifprefixhead, ifprefix); TAILQ_HEAD(ifmultihead, ifmultiaddr); TAILQ_HEAD(ifgrouphead, ifg_group); @@ -184,7 +183,7 @@ struct ifnet { struct label *if_label; /* interface MAC label */ /* these are only used by IPv6 */ - struct ifprefixhead if_prefixhead; /* list of prefixes per if */ + void *if_unused[2]; void *if_afdata[AF_MAX]; int if_afdata_initialized; struct rwlock if_afdata_lock; @@ -761,20 +760,6 @@ void ifa_init(struct ifaddr *ifa); void ifa_ref(struct ifaddr *ifa); #endif -/* - * The prefix structure contains information about one prefix - * of an interface. They are maintained by the different address families, - * are allocated and attached when a prefix or an address is set, - * and are linked together so all prefixes for an interface can be located. - */ -struct ifprefix { - struct sockaddr *ifpr_prefix; /* prefix of interface */ - struct ifnet *ifpr_ifp; /* back-pointer to interface */ - TAILQ_ENTRY(ifprefix) ifpr_list; /* queue macro glue */ - u_char ifpr_plen; /* prefix length in bits */ - u_char ifpr_type; /* protocol dependent prefix type */ -}; - /* * Multicast address structure. This is analogous to the ifaddr * structure except that it keeps track of multicast addresses. diff --git a/sys/net/netmap.h b/sys/net/netmap.h index 4dec1fddbb3c..0ba1537b4e1a 100644 --- a/sys/net/netmap.h +++ b/sys/net/netmap.h @@ -258,12 +258,6 @@ struct nmreq { #define NETMAP_RING_MASK 0xfff /* the ring number */ }; -/* - * default buf size is 2048, but it may make sense to have - * it shorter for better cache usage. - */ - -#define NETMAP_BUF_SIZE (2048) #define NIOCGINFO _IOWR('i', 145, struct nmreq) /* return IF info */ #define NIOCREGIF _IOWR('i', 146, struct nmreq) /* interface register */ #define NIOCUNREGIF _IO('i', 147) /* interface unregister */ diff --git a/sys/net/netmap_user.h b/sys/net/netmap_user.h index c9443b89e43f..64490452fe0c 100644 --- a/sys/net/netmap_user.h +++ b/sys/net/netmap_user.h @@ -73,14 +73,8 @@ ((struct netmap_ring *)((char *)(nifp) + \ (nifp)->ring_ofs[index + (nifp)->ni_num_queues+1] ) ) -#if NETMAP_BUF_SIZE != 2048 -#error cannot handle odd size #define NETMAP_BUF(ring, index) \ - ((char *)(ring) + (ring)->buf_ofs + ((index)*NETMAP_BUF_SIZE)) -#else -#define NETMAP_BUF(ring, index) \ - ((char *)(ring) + (ring)->buf_ofs + ((index)<<11)) -#endif + ((char *)(ring) + (ring)->buf_ofs + ((index)*(ring)->nr_buf_size)) #define NETMAP_RING_NEXT(r, i) \ ((i)+1 == (r)->num_slots ? 0 : (i) + 1 ) diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 4da2e1bd1167..43539ba1223c 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -115,7 +115,34 @@ struct if_msghdr32 { uint16_t ifm_index; struct if_data32 ifm_data; }; -#endif + +struct if_msghdrl32 { + uint16_t ifm_msglen; + uint8_t ifm_version; + uint8_t ifm_type; + int32_t ifm_addrs; + int32_t ifm_flags; + uint16_t ifm_index; + uint16_t _ifm_spare1; + uint16_t ifm_len; + uint16_t ifm_data_off; + struct if_data32 ifm_data; +}; + +struct ifa_msghdrl32 { + uint16_t ifam_msglen; + uint8_t ifam_version; + uint8_t ifam_type; + int32_t ifam_addrs; + int32_t ifam_flags; + uint16_t ifam_index; + uint16_t _ifam_spare1; + uint16_t ifam_len; + uint16_t ifam_data_off; + int32_t ifam_metric; + struct if_data32 ifam_data; +}; +#endif /* COMPAT_FREEBSD32 */ MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables"); @@ -1014,6 +1041,9 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) return (0); } +/* + * Used by the routing socket. + */ static struct mbuf * rt_msg1(int type, struct rt_addrinfo *rtinfo) { @@ -1081,6 +1111,9 @@ rt_msg1(int type, struct rt_addrinfo *rtinfo) return (m); } +/* + * Used by the sysctl code and routing socket. + */ static int rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w) { @@ -1094,17 +1127,31 @@ rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w) case RTM_DELADDR: case RTM_NEWADDR: - len = sizeof(struct ifa_msghdr); + if (w != NULL && w->w_op == NET_RT_IFLISTL) { +#ifdef COMPAT_FREEBSD32 + if (w->w_req->flags & SCTL_MASK32) + len = sizeof(struct ifa_msghdrl32); + else +#endif + len = sizeof(struct ifa_msghdrl); + } else + len = sizeof(struct ifa_msghdr); break; case RTM_IFINFO: #ifdef COMPAT_FREEBSD32 if (w != NULL && w->w_req->flags & SCTL_MASK32) { - len = sizeof(struct if_msghdr32); + if (w->w_op == NET_RT_IFLISTL) + len = sizeof(struct if_msghdrl32); + else + len = sizeof(struct if_msghdr32); break; } #endif - len = sizeof(struct if_msghdr); + if (w != NULL && w->w_op == NET_RT_IFLISTL) + len = sizeof(struct if_msghdrl); + else + len = sizeof(struct if_msghdr); break; case RTM_NEWMADDR: @@ -1534,6 +1581,147 @@ copy_ifdata32(struct if_data *src, struct if_data32 *dst) } #endif +static int +sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info, + struct walkarg *w, int len) +{ + struct if_msghdrl *ifm; + +#ifdef COMPAT_FREEBSD32 + if (w->w_req->flags & SCTL_MASK32) { + struct if_msghdrl32 *ifm32; + + ifm32 = (struct if_msghdrl32 *)w->w_tmem; + ifm32->ifm_addrs = info->rti_addrs; + ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags; + ifm32->ifm_index = ifp->if_index; + ifm32->_ifm_spare1 = 0; + ifm32->ifm_len = sizeof(*ifm32); + ifm32->ifm_data_off = offsetof(struct if_msghdrl32, ifm_data); + + copy_ifdata32(&ifp->if_data, &ifm32->ifm_data); + /* Fixup if_data carp(4) vhid. */ + if (carp_get_vhid_p != NULL) + ifm32->ifm_data.ifi_vhid = + (*carp_get_vhid_p)(ifp->if_addr); + + return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len)); + } +#endif + ifm = (struct if_msghdrl *)w->w_tmem; + ifm->ifm_addrs = info->rti_addrs; + ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags; + ifm->ifm_index = ifp->if_index; + ifm->_ifm_spare1 = 0; + ifm->ifm_len = sizeof(*ifm); + ifm->ifm_data_off = offsetof(struct if_msghdrl, ifm_data); + + ifm->ifm_data = ifp->if_data; + /* Fixup if_data carp(4) vhid. */ + if (carp_get_vhid_p != NULL) + ifm->ifm_data.ifi_vhid = (*carp_get_vhid_p)(ifp->if_addr); + + return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len)); +} + +static int +sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info, + struct walkarg *w, int len) +{ + struct if_msghdr *ifm; + +#ifdef COMPAT_FREEBSD32 + if (w->w_req->flags & SCTL_MASK32) { + struct if_msghdr32 *ifm32; + + ifm32 = (struct if_msghdr32 *)w->w_tmem; + ifm32->ifm_addrs = info->rti_addrs; + ifm32->ifm_flags = ifp->if_flags | ifp->if_drv_flags; + ifm32->ifm_index = ifp->if_index; + + copy_ifdata32(&ifp->if_data, &ifm32->ifm_data); + /* Fixup if_data carp(4) vhid. */ + if (carp_get_vhid_p != NULL) + ifm32->ifm_data.ifi_vhid = + (*carp_get_vhid_p)(ifp->if_addr); + + return (SYSCTL_OUT(w->w_req, (caddr_t)ifm32, len)); + } +#endif + ifm = (struct if_msghdr *)w->w_tmem; + ifm->ifm_addrs = info->rti_addrs; + ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags; + ifm->ifm_index = ifp->if_index; + + ifm->ifm_data = ifp->if_data; + /* Fixup if_data carp(4) vhid. */ + if (carp_get_vhid_p != NULL) + ifm->ifm_data.ifi_vhid = (*carp_get_vhid_p)(ifp->if_addr); + + return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len)); +} + +static int +sysctl_iflist_ifaml(struct ifaddr *ifa, struct rt_addrinfo *info, + struct walkarg *w, int len) +{ + struct ifa_msghdrl *ifam; + +#ifdef COMPAT_FREEBSD32 + if (w->w_req->flags & SCTL_MASK32) { + struct ifa_msghdrl32 *ifam32; + + ifam32 = (struct ifa_msghdrl32 *)w->w_tmem; + ifam32->ifam_addrs = info->rti_addrs; + ifam32->ifam_flags = ifa->ifa_flags; + ifam32->ifam_index = ifa->ifa_ifp->if_index; + ifam32->_ifam_spare1 = 0; + ifam32->ifam_len = sizeof(*ifam32); + ifam32->ifam_data_off = + offsetof(struct ifa_msghdrl32, ifam_data); + ifam32->ifam_metric = ifa->ifa_metric; + + copy_ifdata32(&ifa->ifa_ifp->if_data, &ifam32->ifam_data); + /* Fixup if_data carp(4) vhid. */ + if (carp_get_vhid_p != NULL) + ifam32->ifam_data.ifi_vhid = (*carp_get_vhid_p)(ifa); + + return (SYSCTL_OUT(w->w_req, (caddr_t)ifam32, len)); + } +#endif + + ifam = (struct ifa_msghdrl *)w->w_tmem; + ifam->ifam_addrs = info->rti_addrs; + ifam->ifam_flags = ifa->ifa_flags; + ifam->ifam_index = ifa->ifa_ifp->if_index; + ifam->_ifam_spare1 = 0; + ifam->ifam_len = sizeof(*ifam); + ifam->ifam_data_off = offsetof(struct ifa_msghdrl, ifam_data); + ifam->ifam_metric = ifa->ifa_metric; + + ifam->ifam_data = ifa->if_data; + /* Fixup if_data carp(4) vhid. */ + if (carp_get_vhid_p != NULL) + ifam->ifam_data.ifi_vhid = (*carp_get_vhid_p)(ifa); + + return (SYSCTL_OUT(w->w_req, w->w_tmem, len)); +} + +static int +sysctl_iflist_ifam(struct ifaddr *ifa, struct rt_addrinfo *info, + struct walkarg *w, int len) +{ + struct ifa_msghdr *ifam; + + ifam = (struct ifa_msghdr *)w->w_tmem; + ifam->ifam_addrs = info->rti_addrs; + ifam->ifam_flags = ifa->ifa_flags; + ifam->ifam_index = ifa->ifa_ifp->if_index; + ifam->ifam_metric = ifa->ifa_metric; + + return (SYSCTL_OUT(w->w_req, w->w_tmem, len)); +} + static int sysctl_iflist(int af, struct walkarg *w) { @@ -1553,38 +1741,10 @@ sysctl_iflist(int af, struct walkarg *w) len = rt_msg2(RTM_IFINFO, &info, NULL, w); info.rti_info[RTAX_IFP] = NULL; if (w->w_req && w->w_tmem) { - struct if_msghdr *ifm; - -#ifdef COMPAT_FREEBSD32 - if (w->w_req->flags & SCTL_MASK32) { - struct if_msghdr32 *ifm32; - - ifm32 = (struct if_msghdr32 *)w->w_tmem; - ifm32->ifm_index = ifp->if_index; - ifm32->ifm_flags = ifp->if_flags | - ifp->if_drv_flags; - copy_ifdata32(&ifp->if_data, &ifm32->ifm_data); - if (carp_get_vhid_p != NULL) - ifm32->ifm_data.ifi_vhid = - (*carp_get_vhid_p)(ifa); - ifm32->ifm_addrs = info.rti_addrs; - error = SYSCTL_OUT(w->w_req, (caddr_t)ifm32, - len); - goto sysctl_out; - } -#endif - ifm = (struct if_msghdr *)w->w_tmem; - ifm->ifm_index = ifp->if_index; - ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags; - ifm->ifm_data = ifp->if_data; - if (carp_get_vhid_p != NULL) - ifm->ifm_data.ifi_vhid = - (*carp_get_vhid_p)(ifa); - ifm->ifm_addrs = info.rti_addrs; - error = SYSCTL_OUT(w->w_req, (caddr_t)ifm, len); -#ifdef COMPAT_FREEBSD32 - sysctl_out: -#endif + if (w->w_op == NET_RT_IFLISTL) + error = sysctl_iflist_ifml(ifp, &info, w, len); + else + error = sysctl_iflist_ifm(ifp, &info, w, len); if (error) goto done; } @@ -1599,18 +1759,12 @@ sysctl_iflist(int af, struct walkarg *w) info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; len = rt_msg2(RTM_NEWADDR, &info, NULL, w); if (w->w_req && w->w_tmem) { - struct ifa_msghdr *ifam; - - ifam = (struct ifa_msghdr *)w->w_tmem; - ifam->ifam_index = ifa->ifa_ifp->if_index; - ifam->ifam_flags = ifa->ifa_flags; - ifam->ifam_metric = ifa->ifa_metric; - ifam->ifam_addrs = info.rti_addrs; - ifam->ifam_data = ifa->if_data; - if (carp_get_vhid_p != NULL) - ifam->ifam_data.ifi_vhid = - (*carp_get_vhid_p)(ifa); - error = SYSCTL_OUT(w->w_req, w->w_tmem, len); + if (w->w_op == NET_RT_IFLISTL) + error = sysctl_iflist_ifaml(ifa, &info, + w, len); + else + error = sysctl_iflist_ifam(ifa, &info, + w, len); if (error) goto done; } @@ -1740,6 +1894,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) break; case NET_RT_IFLIST: + case NET_RT_IFLISTL: error = sysctl_iflist(af, &w); break; diff --git a/sys/net/zlib.h b/sys/net/zlib.h index 85db8d405c68..44aa425475cc 100644 --- a/sys/net/zlib.h +++ b/sys/net/zlib.h @@ -109,7 +109,7 @@ extern "C" { #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) # define WIN32 #endif -#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(__i386__) # ifndef __32BIT__ # define __32BIT__ # endif diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index 028afec2cbe0..39f6d581bada 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -709,27 +709,32 @@ enum { IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ /* - * 802.11s IEs based on D3.03 spec and were not assigned by - * ANA. Beware changing them because some of them are being - * kept compatible with Linux. + * 802.11s IEs + * NB: On vanilla Linux still IEEE80211_ELEMID_MESHPEER = 55, + * but they defined a new with id 117 called PEER_MGMT. + * NB: complies with open80211 */ - IEEE80211_ELEMID_MESHCONF = 51, - IEEE80211_ELEMID_MESHID = 52, - IEEE80211_ELEMID_MESHLINK = 35, - IEEE80211_ELEMID_MESHCNGST = 36, - IEEE80211_ELEMID_MESHPEER = 55, - IEEE80211_ELEMID_MESHCSA = 38, - IEEE80211_ELEMID_MESHTIM = 39, - IEEE80211_ELEMID_MESHAWAKEW = 40, - IEEE80211_ELEMID_MESHBEACONT = 41, - IEEE80211_ELEMID_MESHPANN = 48, - IEEE80211_ELEMID_MESHRANN = 49, - IEEE80211_ELEMID_MESHPREQ = 68, - IEEE80211_ELEMID_MESHPREP = 69, - IEEE80211_ELEMID_MESHPERR = 70, - IEEE80211_ELEMID_MESHPXU = 53, - IEEE80211_ELEMID_MESHPXUC = 54, - IEEE80211_ELEMID_MESHAH = 60, /* Abbreviated Handshake */ + IEEE80211_ELEMID_MESHCONF = 113, + IEEE80211_ELEMID_MESHID = 114, + IEEE80211_ELEMID_MESHLINK = 115, + IEEE80211_ELEMID_MESHCNGST = 116, + IEEE80211_ELEMID_MESHPEER = 117, + IEEE80211_ELEMID_MESHCSA = 118, + IEEE80211_ELEMID_MESHTIM = 39, /* XXX: remove */ + IEEE80211_ELEMID_MESHAWAKEW = 119, + IEEE80211_ELEMID_MESHBEACONT = 120, + /* 121-124 MMCAOP not implemented yet */ + IEEE80211_ELEMID_MESHPANN = 125, /* XXX: is GANN now, not used */ + IEEE80211_ELEMID_MESHRANN = 126, + /* 127 Extended Capabilities */ + /* 128-129 reserved */ + IEEE80211_ELEMID_MESHPREQ = 130, + IEEE80211_ELEMID_MESHPREP = 131, + IEEE80211_ELEMID_MESHPERR = 132, + /* 133-136 reserved */ + IEEE80211_ELEMID_MESHPXU = 137, + IEEE80211_ELEMID_MESHPXUC = 138, + IEEE80211_ELEMID_MESHAH = 60, /* XXX: remove */ }; struct ieee80211_tim_ie { @@ -927,19 +932,21 @@ enum { IEEE80211_REASON_SETUP_NEEDED = 38, /* 11e */ IEEE80211_REASON_TIMEOUT = 39, /* 11e */ - /* values not yet allocated by ANA */ - IEEE80211_REASON_PEER_LINK_CANCELED = 2, /* 11s */ - IEEE80211_REASON_MESH_MAX_PEERS = 3, /* 11s */ - IEEE80211_REASON_MESH_CPVIOLATION = 4, /* 11s */ - IEEE80211_REASON_MESH_CLOSE_RCVD = 5, /* 11s */ - IEEE80211_REASON_MESH_MAX_RETRIES = 6, /* 11s */ - IEEE80211_REASON_MESH_CONFIRM_TIMEOUT = 7, /* 11s */ - IEEE80211_REASON_MESH_INVALID_GTK = 8, /* 11s */ - IEEE80211_REASON_MESH_INCONS_PARAMS = 9, /* 11s */ - IEEE80211_REASON_MESH_INVALID_SECURITY = 10, /* 11s */ - IEEE80211_REASON_MESH_PERR_UNSPEC = 11, /* 11s */ - IEEE80211_REASON_MESH_PERR_NO_FI = 12, /* 11s */ - IEEE80211_REASON_MESH_PERR_DEST_UNREACH = 13, /* 11s */ + IEEE80211_REASON_PEER_LINK_CANCELED = 52, /* 11s */ + IEEE80211_REASON_MESH_MAX_PEERS = 53, /* 11s */ + IEEE80211_REASON_MESH_CPVIOLATION = 54, /* 11s */ + IEEE80211_REASON_MESH_CLOSE_RCVD = 55, /* 11s */ + IEEE80211_REASON_MESH_MAX_RETRIES = 56, /* 11s */ + IEEE80211_REASON_MESH_CONFIRM_TIMEOUT = 57, /* 11s */ + IEEE80211_REASON_MESH_INVALID_GTK = 58, /* 11s */ + IEEE80211_REASON_MESH_INCONS_PARAMS = 59, /* 11s */ + IEEE80211_REASON_MESH_INVALID_SECURITY = 60, /* 11s */ + IEEE80211_REASON_MESH_PERR_NO_PROXY = 61, /* 11s */ + IEEE80211_REASON_MESH_PERR_NO_FI = 62, /* 11s */ + IEEE80211_REASON_MESH_PERR_DEST_UNREACH = 63, /* 11s */ + IEEE80211_REASON_MESH_MAC_ALRDY_EXISTS_MBSS = 64, /* 11s */ + IEEE80211_REASON_MESH_CHAN_SWITCH_REG = 65, /* 11s */ + IEEE80211_REASON_MESH_CHAN_SWITCH_UNSPEC = 66, /* 11s */ IEEE80211_STATUS_SUCCESS = 0, IEEE80211_STATUS_UNSPECIFIED = 1, diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 2ef36492ec06..1f8518cd13ae 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -2289,7 +2289,6 @@ mesh_verify_meshconf(struct ieee80211vap *vap, const uint8_t *ie) const struct ieee80211_meshconf_ie *meshconf = (const struct ieee80211_meshconf_ie *) ie; const struct ieee80211_mesh_state *ms = vap->iv_mesh; - uint16_t cap; if (meshconf == NULL) return 1; @@ -2323,10 +2322,8 @@ mesh_verify_meshconf(struct ieee80211vap *vap, const uint8_t *ie) meshconf->conf_pselid); return 1; } - /* NB: conf_cap is only read correctly here */ - cap = LE_READ_2(&meshconf->conf_cap); /* Not accepting peers */ - if (!(cap & IEEE80211_MESHCONF_CAP_AP)) { + if (!(meshconf->conf_cap & IEEE80211_MESHCONF_CAP_AP)) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH, "not accepting peers: 0x%x\n", meshconf->conf_cap); return 1; @@ -2395,7 +2392,7 @@ ieee80211_add_meshconf(uint8_t *frm, struct ieee80211vap *vap) KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap")); *frm++ = IEEE80211_ELEMID_MESHCONF; - *frm++ = sizeof(struct ieee80211_meshconf_ie) - 2; + *frm++ = IEEE80211_MESH_CONF_SZ; *frm++ = ms->ms_ppath->mpp_ie; /* path selection */ *frm++ = ms->ms_pmetric->mpm_ie; /* link metric */ *frm++ = IEEE80211_MESHCONF_CC_DISABLED; @@ -2411,7 +2408,7 @@ ieee80211_add_meshconf(uint8_t *frm, struct ieee80211vap *vap) caps |= IEEE80211_MESHCONF_CAP_AP; if (ms->ms_flags & IEEE80211_MESHFLAGS_FWD) caps |= IEEE80211_MESHCONF_CAP_FWRD; - ADDSHORT(frm, caps); + *frm++ = caps; return frm; } diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index ad1b02afbb1a..85ee6a7ba4e9 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -40,6 +40,7 @@ * 802.11s Information Elements. */ /* Mesh Configuration */ +#define IEEE80211_MESH_CONF_SZ (7) struct ieee80211_meshconf_ie { uint8_t conf_ie; /* IEEE80211_ELEMID_MESHCONF */ uint8_t conf_len; @@ -49,31 +50,66 @@ struct ieee80211_meshconf_ie { uint8_t conf_syncid; /* Sync. Protocol ID */ uint8_t conf_authid; /* Auth. Protocol ID */ uint8_t conf_form; /* Formation Information */ - uint16_t conf_cap; + uint8_t conf_cap; } __packed; /* Hybrid Wireless Mesh Protocol */ -#define IEEE80211_MESHCONF_PATH_HWMP 0x00 +enum { + /* 0 reserved */ + IEEE80211_MESHCONF_PATH_HWMP = 1, + /* 2-254 reserved */ + IEEE80211_MESHCONF_PATH_VENDOR = 255, +}; + /* Airtime Link Metric */ -#define IEEE80211_MESHCONF_METRIC_AIRTIME 0x00 +enum { + /* 0 reserved */ + IEEE80211_MESHCONF_METRIC_AIRTIME = 1, + /* 2-254 reserved */ + IEEE80211_MESHCONF_METRIC_VENDOR = 255, +}; + /* Congestion Control */ -#define IEEE80211_MESHCONF_CC_DISABLED 0x00 -#define IEEE80211_MESHCONF_CC_SIG 0x01 +enum { + IEEE80211_MESHCONF_CC_DISABLED = 0, + IEEE80211_MESHCONF_CC_SIG = 1, + /* 2-254 reserved */ + IEEE80211_MESHCONF_CC_VENDOR = 255, +}; + /* Neighbour Offset */ -#define IEEE80211_MESHCONF_SYNC_NEIGHOFF 0x00 -#define IEEE80211_MESHCONF_AUTH_DISABLED 0x00 -/* Simultaneous Authenticaction of Equals */ -#define IEEE80211_MESHCONF_AUTH_SAE 0x01 -#define IEEE80211_MESHCONF_FORM_MP 0x01 /* Connected to Portal */ -#define IEEE80211_MESHCONF_FORM_NNEIGH_MASK 0x04 /* Number of Neighbours */ +enum { + /* 0 reserved */ + IEEE80211_MESHCONF_SYNC_NEIGHOFF = 1, + /* 2-254 rserved */ + IEEE80211_MESHCONF_SYNC_VENDOR = 255, +}; + +/* Authentication Protocol Identifier */ +enum { + + IEEE80211_MESHCONF_AUTH_DISABLED = 0, + /* Simultaneous Authenticaction of Equals */ + IEEE80211_MESHCONF_AUTH_SEA = 1, + IEEE80211_MESHCONF_AUTH_8021X = 2, /* IEEE 802.1X */ + /* 3-254 reserved */ + IEEE80211_MESHCONF_AUTH_VENDOR = 255, +}; + +/* Mesh Formation Info */ +#define IEEE80211_MESHCONF_FORM_MP 0x01 /* Connected to Portal */ +#define IEEE80211_MESHCONF_FORM_NNEIGH_MASK 0x7E /* Number of Neighbours */ +#define IEEE80211_MESHCONF_FORM_SA 0xF0 /* indicating 802.1X auth */ + +/* Mesh Capability */ #define IEEE80211_MESHCONF_CAP_AP 0x01 /* Accepting Peers */ #define IEEE80211_MESHCONF_CAP_MCCAS 0x02 /* MCCA supported */ #define IEEE80211_MESHCONF_CAP_MCCAE 0x04 /* MCCA enabled */ #define IEEE80211_MESHCONF_CAP_FWRD 0x08 /* forwarding enabled */ #define IEEE80211_MESHCONF_CAP_BTR 0x10 /* Beacon Timing Report Enab */ -#define IEEE80211_MESHCONF_CAP_TBTTA 0x20 /* TBTT Adj. Enabled */ -#define IEEE80211_MESHCONF_CAP_TBTT 0x40 /* TBTT Adjusting */ -#define IEEE80211_MESHCONF_CAP_PSL 0x80 /* Power Save Level */ +#define IEEE80211_MESHCONF_CAP_TBTT 0x20 /* TBTT Adjusting */ +#define IEEE80211_MESHCONF_CAP_PSL 0x40 /* Power Save Level */ +/* 0x80 reserved */ /* Mesh Identifier */ struct ieee80211_meshid_ie { diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h index d649c6c7154d..dc008f446df0 100644 --- a/sys/netgraph/netgraph.h +++ b/sys/netgraph/netgraph.h @@ -365,7 +365,7 @@ struct ng_node { void *nd_private; /* node type dependant node ID */ ng_ID_t nd_ID; /* Unique per node */ LIST_HEAD(hooks, ng_hook) nd_hooks; /* linked list of node hooks */ - LIST_ENTRY(ng_node) nd_nodes; /* linked list of all nodes */ + LIST_ENTRY(ng_node) nd_nodes; /* name hash collision list */ LIST_ENTRY(ng_node) nd_idnodes; /* ID hash collision list */ struct ng_queue nd_input_queue; /* input queue for locking */ int nd_refs; /* # of references to this node */ @@ -1202,10 +1202,6 @@ typedef void *meta_p; #define NGI_GET_META(i,m) #define ng_copy_meta(meta) NULL -/* Hash related definitions */ -#define NG_ID_HASH_SIZE 128 /* most systems wont need even this many */ -#define NG_NAME_HASH_SIZE 128 /* most systems wont need even this many */ - /* * Mark the current thread when called from the outbound path of the * network stack, in order to enforce queuing on ng nodes calling into diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index 6bd86be674d8..6a9b08feb0df 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -45,23 +45,23 @@ #include #include #include -#include +#include #include #include +#include #include #include #include #include #include +#include #include +#include +#include +#include #include #include -#include -#include -#include #include -#include -#include #include #include @@ -171,10 +171,20 @@ static struct rwlock ng_typelist_lock; #define TYPELIST_WLOCK() rw_wlock(&ng_typelist_lock) #define TYPELIST_WUNLOCK() rw_wunlock(&ng_typelist_lock) -/* Hash related definitions */ -/* XXX Don't need to initialise them because it's a LIST */ -static VNET_DEFINE(LIST_HEAD(, ng_node), ng_ID_hash[NG_ID_HASH_SIZE]); -#define V_ng_ID_hash VNET(ng_ID_hash) +/* Hash related definitions. */ +LIST_HEAD(nodehash, ng_node); +static VNET_DEFINE(struct nodehash *, ng_ID_hash); +static VNET_DEFINE(u_long, ng_ID_hmask); +static VNET_DEFINE(u_long, ng_nodes); +static VNET_DEFINE(struct nodehash *, ng_name_hash); +static VNET_DEFINE(u_long, ng_name_hmask); +static VNET_DEFINE(u_long, ng_named_nodes); +#define V_ng_ID_hash VNET(ng_ID_hash) +#define V_ng_ID_hmask VNET(ng_ID_hmask) +#define V_ng_nodes VNET(ng_nodes) +#define V_ng_name_hash VNET(ng_name_hash) +#define V_ng_name_hmask VNET(ng_name_hmask) +#define V_ng_named_nodes VNET(ng_named_nodes) static struct rwlock ng_idhash_lock; #define IDHASH_RLOCK() rw_rlock(&ng_idhash_lock) @@ -183,7 +193,7 @@ static struct rwlock ng_idhash_lock; #define IDHASH_WUNLOCK() rw_wunlock(&ng_idhash_lock) /* Method to find a node.. used twice so do it here */ -#define NG_IDHASH_FN(ID) ((ID) % (NG_ID_HASH_SIZE)) +#define NG_IDHASH_FN(ID) ((ID) % (V_ng_ID_hmask + 1)) #define NG_IDHASH_FIND(ID, node) \ do { \ rw_assert(&ng_idhash_lock, RA_LOCKED); \ @@ -196,18 +206,6 @@ static struct rwlock ng_idhash_lock; } \ } while (0) -static VNET_DEFINE(LIST_HEAD(, ng_node), ng_name_hash[NG_NAME_HASH_SIZE]); -#define V_ng_name_hash VNET(ng_name_hash) - -#define NG_NAMEHASH(NAME, HASH) \ - do { \ - u_char h = 0; \ - const u_char *c; \ - for (c = (const u_char*)(NAME); *c; c++)\ - h += *c; \ - (HASH) = h % (NG_NAME_HASH_SIZE); \ - } while (0) - static struct rwlock ng_namehash_lock; #define NAMEHASH_RLOCK() rw_rlock(&ng_namehash_lock) #define NAMEHASH_RUNLOCK() rw_runlock(&ng_namehash_lock) @@ -228,8 +226,10 @@ static int ng_con_nodes(item_p item, node_p node, const char *name, node_p node2, const char *name2); static int ng_con_part2(node_p node, item_p item, hook_p hook); static int ng_con_part3(node_p node, item_p item, hook_p hook); -static int ng_mkpeer(node_p node, const char *name, - const char *name2, char *type); +static int ng_mkpeer(node_p node, const char *name, const char *name2, + char *type); +static void ng_name_rehash(void); +static void ng_ID_rehash(void); /* Imported, these used to be externally visible, some may go back. */ void ng_destroy_hook(hook_p hook); @@ -240,7 +240,6 @@ int ng_path_parse(char *addr, char **node, char **path, char **hook); void ng_rmnode(node_p node, hook_p dummy1, void *dummy2, int dummy3); void ng_unname(node_p node); - /* Our own netgraph malloc type */ MALLOC_DEFINE(M_NETGRAPH, "netgraph", "netgraph structures and ctrl messages"); MALLOC_DEFINE(M_NETGRAPH_MSG, "netgraph_msg", "netgraph name storage"); @@ -341,7 +340,6 @@ ng_alloc_node(void) #define NG_ALLOC_HOOK(hook) do { (hook) = ng_alloc_hook(); } while (0) #define NG_ALLOC_NODE(node) do { (node) = ng_alloc_node(); } while (0) - #define NG_FREE_HOOK(hook) \ do { \ mtx_lock(&ng_nodelist_mtx); \ @@ -664,12 +662,7 @@ ng_make_node_common(struct ng_type *type, node_p *nodepp) /* Initialize hook list for new node */ LIST_INIT(&node->nd_hooks); - /* Link us into the name hash. */ - NAMEHASH_WLOCK(); - LIST_INSERT_HEAD(&V_ng_name_hash[0], node, nd_nodes); - NAMEHASH_WUNLOCK(); - - /* get an ID and put us in the hash chain */ + /* Get an ID and put us in the hash chain. */ IDHASH_WLOCK(); for (;;) { /* wrap protection, even if silly */ node_p node2 = NULL; @@ -681,6 +674,9 @@ ng_make_node_common(struct ng_type *type, node_p *nodepp) break; } } + V_ng_nodes++; + if (V_ng_nodes * 2 > V_ng_ID_hmask) + ng_ID_rehash(); LIST_INSERT_HEAD(&V_ng_ID_hash[NG_IDHASH_FN(node->nd_ID)], node, nd_idnodes); IDHASH_WUNLOCK(); @@ -797,10 +793,14 @@ ng_unref_node(node_p node) node->nd_type->refs--; /* XXX maybe should get types lock? */ NAMEHASH_WLOCK(); - LIST_REMOVE(node, nd_nodes); + if (NG_NODE_HAS_NAME(node)) { + V_ng_named_nodes--; + LIST_REMOVE(node, nd_nodes); + } NAMEHASH_WUNLOCK(); IDHASH_WLOCK(); + V_ng_nodes--; LIST_REMOVE(node, nd_idnodes); IDHASH_WUNLOCK(); @@ -816,9 +816,10 @@ static node_p ng_ID2noderef(ng_ID_t ID) { node_p node; + IDHASH_RLOCK(); NG_IDHASH_FIND(ID, node); - if(node) + if (node) NG_NODE_REF(node); IDHASH_RUNLOCK(); return(node); @@ -840,8 +841,9 @@ ng_node2ID(node_p node) int ng_name_node(node_p node, const char *name) { - int i, hash; + uint32_t hash; node_p node2; + int i; /* Check the name is valid */ for (i = 0; i < NG_NODESIZ; i++) { @@ -857,20 +859,26 @@ ng_name_node(node_p node, const char *name) return (EINVAL); } - /* Check the name isn't already being used */ - if ((node2 = ng_name2noderef(node, name)) != NULL) { - NG_NODE_UNREF(node2); - TRAP_ERROR(); - return (EADDRINUSE); - } - - /* copy it */ - strlcpy(NG_NODE_NAME(node), name, NG_NODESIZ); - - /* Update name hash. */ - NG_NAMEHASH(name, hash); NAMEHASH_WLOCK(); - LIST_REMOVE(node, nd_nodes); + if (V_ng_named_nodes * 2 > V_ng_name_hmask) + ng_name_rehash(); + + hash = hash32_str(name, HASHINIT) & V_ng_name_hmask; + /* Check the name isn't already being used. */ + LIST_FOREACH(node2, &V_ng_name_hash[hash], nd_nodes) + if (NG_NODE_IS_VALID(node2) && + (strcmp(NG_NODE_NAME(node2), name) == 0)) { + NAMEHASH_WUNLOCK(); + return (EADDRINUSE); + } + + if (NG_NODE_HAS_NAME(node)) + LIST_REMOVE(node, nd_nodes); + else + V_ng_named_nodes++; + /* Copy it. */ + strlcpy(NG_NODE_NAME(node), name, NG_NODESIZ); + /* Update name hash. */ LIST_INSERT_HEAD(&V_ng_name_hash[hash], node, nd_nodes); NAMEHASH_WUNLOCK(); @@ -905,8 +913,8 @@ ng_name2noderef(node_p here, const char *name) return (ng_ID2noderef(temp)); } - /* Find node by name */ - NG_NAMEHASH(name, hash); + /* Find node by name. */ + hash = hash32_str(name, HASHINIT) & V_ng_name_hmask; NAMEHASH_RLOCK(); LIST_FOREACH(node, &V_ng_name_hash[hash], nd_nodes) if (NG_NODE_IS_VALID(node) && @@ -952,6 +960,68 @@ ng_unname(node_p node) { } +/* + * Allocate a bigger name hash. + */ +static void +ng_name_rehash() +{ + struct nodehash *new; + uint32_t hash; + u_long hmask; + node_p node, node2; + int i; + + new = hashinit_flags((V_ng_name_hmask + 1) * 2, M_NETGRAPH_NODE, &hmask, + HASH_NOWAIT); + if (new == NULL) + return; + + for (i = 0; i <= V_ng_name_hmask; i++) + LIST_FOREACH_SAFE(node, &V_ng_name_hash[i], nd_nodes, node2) { +#ifdef INVARIANTS + LIST_REMOVE(node, nd_nodes); +#endif + hash = hash32_str(NG_NODE_NAME(node), HASHINIT) & hmask; + LIST_INSERT_HEAD(&new[hash], node, nd_nodes); + } + + hashdestroy(V_ng_name_hash, M_NETGRAPH_NODE, V_ng_name_hmask); + V_ng_name_hash = new; + V_ng_name_hmask = hmask; +} + +/* + * Allocate a bigger ID hash. + */ +static void +ng_ID_rehash() +{ + struct nodehash *new; + uint32_t hash; + u_long hmask; + node_p node, node2; + int i; + + new = hashinit_flags((V_ng_ID_hmask + 1) * 2, M_NETGRAPH_NODE, &hmask, + HASH_NOWAIT); + if (new == NULL) + return; + + for (i = 0; i <= V_ng_ID_hmask; i++) + LIST_FOREACH_SAFE(node, &V_ng_ID_hash[i], nd_idnodes, node2) { +#ifdef INVARIANTS + LIST_REMOVE(node, nd_idnodes); +#endif + hash = (node->nd_ID % (hmask + 1)); + LIST_INSERT_HEAD(&new[hash], node, nd_idnodes); + } + + hashdestroy(V_ng_ID_hash, M_NETGRAPH_NODE, V_ng_name_hmask); + V_ng_ID_hash = new; + V_ng_ID_hmask = hmask; +} + /************************************************************************ Hook routines Names are not optional. Hooks are always connected, except for a @@ -1161,6 +1231,10 @@ ng_bypass(hook_p hook1, hook_p hook2) return (EINVAL); } mtx_lock(&ng_topo_mtx); + if (NG_HOOK_NOT_VALID(hook1) || NG_HOOK_NOT_VALID(hook2)) { + mtx_unlock(&ng_topo_mtx); + return (EINVAL); + } hook1->hk_peer->hk_peer = hook2->hk_peer; hook2->hk_peer->hk_peer = hook1->hk_peer; @@ -1202,7 +1276,6 @@ ng_newtype(struct ng_type *tp) return (EEXIST); } - /* Link in new type */ TYPELIST_WLOCK(); LIST_INSERT_HEAD(&ng_typelist, tp, types); @@ -2574,28 +2647,55 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook) break; } - case NGM_LISTNAMES: case NGM_LISTNODES: { - const int unnamed = (msg->header.cmd == NGM_LISTNODES); struct namelist *nl; node_p node; - int num = 0, i; + int i; - NAMEHASH_RLOCK(); - /* Count number of nodes */ - for (i = 0; i < NG_NAME_HASH_SIZE; i++) { - LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) { - if (NG_NODE_IS_VALID(node) && - (unnamed || NG_NODE_HAS_NAME(node))) { - num++; - } + IDHASH_RLOCK(); + /* Get response struct. */ + NG_MKRESPONSE(resp, msg, sizeof(*nl) + + (V_ng_nodes * sizeof(struct nodeinfo)), M_NOWAIT | M_ZERO); + if (resp == NULL) { + IDHASH_RUNLOCK(); + error = ENOMEM; + break; + } + nl = (struct namelist *) resp->data; + + /* Cycle through the lists of nodes. */ + nl->numnames = 0; + for (i = 0; i <= V_ng_ID_hmask; i++) { + LIST_FOREACH(node, &V_ng_ID_hash[i], nd_idnodes) { + struct nodeinfo *const np = + &nl->nodeinfo[nl->numnames]; + + if (NG_NODE_NOT_VALID(node)) + continue; + if (NG_NODE_HAS_NAME(node)) + strcpy(np->name, NG_NODE_NAME(node)); + strcpy(np->type, node->nd_type->name); + np->id = ng_node2ID(node); + np->hooks = node->nd_numhooks; + KASSERT(nl->numnames < V_ng_nodes, + ("%s: no space", __func__)); + nl->numnames++; } } + IDHASH_RUNLOCK(); + break; + } + case NGM_LISTNAMES: + { + struct namelist *nl; + node_p node; + int i; - /* Get response struct */ + NAMEHASH_RLOCK(); + /* Get response struct. */ NG_MKRESPONSE(resp, msg, sizeof(*nl) + - (num * sizeof(struct nodeinfo)), M_NOWAIT); + (V_ng_named_nodes * sizeof(struct nodeinfo)), M_NOWAIT); if (resp == NULL) { NAMEHASH_RUNLOCK(); error = ENOMEM; @@ -2603,24 +2703,21 @@ ng_generic_msg(node_p here, item_p item, hook_p lasthook) } nl = (struct namelist *) resp->data; - /* Cycle through the linked list of nodes */ + /* Cycle through the lists of nodes. */ nl->numnames = 0; - for (i = 0; i < NG_NAME_HASH_SIZE; i++) { + for (i = 0; i <= V_ng_name_hmask; i++) { LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) { struct nodeinfo *const np = &nl->nodeinfo[nl->numnames]; if (NG_NODE_NOT_VALID(node)) continue; - if (!unnamed && (! NG_NODE_HAS_NAME(node))) - continue; - if (NG_NODE_HAS_NAME(node)) - strcpy(np->name, NG_NODE_NAME(node)); + strcpy(np->name, NG_NODE_NAME(node)); strcpy(np->type, node->nd_type->name); np->id = ng_node2ID(node); np->hooks = node->nd_numhooks; - KASSERT(nl->numnames < num, ("%s: no space", - __func__)); + KASSERT(nl->numnames < V_ng_named_nodes, + ("%s: no space", __func__)); nl->numnames++; } } @@ -3027,6 +3124,17 @@ ng_mod_event(module_t mod, int event, void *data) return (error); } +static void +vnet_netgraph_init(const void *unused __unused) +{ + + /* We start with small hashes, but they can grow. */ + V_ng_ID_hash = hashinit(16, M_NETGRAPH_NODE, &V_ng_ID_hmask); + V_ng_name_hash = hashinit(16, M_NETGRAPH_NODE, &V_ng_name_hmask); +} +VNET_SYSINIT(vnet_netgraph_init, SI_SUB_NETGRAPH, SI_ORDER_FIRST, + vnet_netgraph_init, NULL); + #ifdef VIMAGE static void vnet_netgraph_uninit(const void *unused __unused) @@ -3036,9 +3144,9 @@ vnet_netgraph_uninit(const void *unused __unused) do { /* Find a node to kill */ - NAMEHASH_RLOCK(); - for (i = 0; i < NG_NAME_HASH_SIZE; i++) { - LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) { + IDHASH_RLOCK(); + for (i = 0; i <= V_ng_ID_hmask; i++) { + LIST_FOREACH(node, &V_ng_ID_hash[i], nd_idnodes) { if (node != &ng_deadnode) { NG_NODE_REF(node); break; @@ -3047,7 +3155,7 @@ vnet_netgraph_uninit(const void *unused __unused) if (node != NULL) break; } - NAMEHASH_RUNLOCK(); + IDHASH_RUNLOCK(); /* Attempt to kill it only if it is a regular node */ if (node != NULL) { @@ -3065,8 +3173,11 @@ vnet_netgraph_uninit(const void *unused __unused) last_killed = node; } } while (node != NULL); + + hashdestroy(V_ng_name_hash, M_NETGRAPH_NODE, V_ng_name_hmask); + hashdestroy(V_ng_ID_hash, M_NETGRAPH_NODE, V_ng_ID_hmask); } -VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_NETGRAPH, SI_ORDER_FIRST, vnet_netgraph_uninit, NULL); #endif /* VIMAGE */ @@ -3097,11 +3208,11 @@ ngb_mod_event(module_t mod, int event, void *data) MTX_DEF); #endif ng_qzone = uma_zcreate("NetGraph items", sizeof(struct ng_item), - NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0); + NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, M_WAITOK); uma_zone_set_max(ng_qzone, maxalloc); ng_qdzone = uma_zcreate("NetGraph data items", sizeof(struct ng_item), NULL, NULL, NULL, NULL, - UMA_ALIGN_CACHE, 0); + UMA_ALIGN_CACHE, M_WAITOK); uma_zone_set_max(ng_qdzone, maxdata); /* Autoconfigure number of threads. */ if (numthreads <= 0) @@ -3132,7 +3243,7 @@ static moduledata_t netgraph_mod = { ngb_mod_event, (NULL) }; -DECLARE_MODULE(netgraph, netgraph_mod, SI_SUB_NETGRAPH, SI_ORDER_MIDDLE); +DECLARE_MODULE(netgraph, netgraph_mod, SI_SUB_NETGRAPH, SI_ORDER_FIRST); SYSCTL_NODE(_net, OID_AUTO, graph, CTLFLAG_RW, 0, "netgraph Family"); SYSCTL_INT(_net_graph, OID_AUTO, abi_version, CTLFLAG_RD, 0, NG_ABI_VERSION,""); SYSCTL_INT(_net_graph, OID_AUTO, msg_version, CTLFLAG_RD, 0, NG_VERSION, ""); @@ -3271,7 +3382,6 @@ SYSCTL_PROC(_debug, OID_AUTO, ng_dump_items, CTLTYPE_INT | CTLFLAG_RW, 0, sizeof(int), sysctl_debug_ng_dump_items, "I", "Number of allocated items"); #endif /* NETGRAPH_DEBUG */ - /*********************************************************************** * Worklist routines **********************************************************************/ @@ -3355,7 +3465,6 @@ ng_worklist_add(node_p node) } } - /*********************************************************************** * Externally useable functions to set up a queue item ready for sending ***********************************************************************/ @@ -3436,8 +3545,6 @@ ng_package_msg(struct ng_mesg *msg, int flags) return (item); } - - #define SET_RETADDR(item, here, retaddr) \ do { /* Data or fn items don't have retaddrs */ \ if ((item->el_flags & NGQF_TYPE) == NGQF_MESG) { \ @@ -3663,7 +3770,6 @@ ng_callout_trampoline(void *arg) CURVNET_RESTORE(); } - int ng_callout(struct callout *c, node_p node, hook_p hook, int ticks, ng_item_fn *fn, void * arg1, int arg2) @@ -3733,32 +3839,3 @@ ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr) NGI_RETADDR(item) = ng_node2ID(here); } } - -#define TESTING -#ifdef TESTING -/* just test all the macros */ -void -ng_macro_test(item_p item); -void -ng_macro_test(item_p item) -{ - node_p node = NULL; - hook_p hook = NULL; - struct mbuf *m; - struct ng_mesg *msg; - ng_ID_t retaddr; - int error; - - NGI_GET_M(item, m); - NGI_GET_MSG(item, msg); - retaddr = NGI_RETADDR(item); - NG_SEND_DATA(error, hook, m, NULL); - NG_SEND_DATA_ONLY(error, hook, m); - NG_FWD_NEW_DATA(error, item, hook, m); - NG_FWD_ITEM_HOOK(error, item, hook); - NG_SEND_MSG_HOOK(error, node, msg, hook, retaddr); - NG_SEND_MSG_ID(error, node, msg, retaddr, retaddr); - NG_SEND_MSG_PATH(error, node, msg, ".:", retaddr); - NG_FWD_MSG_HOOK(error, node, item, hook, retaddr); -} -#endif /* TESTING */ diff --git a/sys/netgraph/ng_cisco.c b/sys/netgraph/ng_cisco.c index aa12b757bcaf..7183369ee38a 100644 --- a/sys/netgraph/ng_cisco.c +++ b/sys/netgraph/ng_cisco.c @@ -75,33 +75,33 @@ #define KEEPALIVE_SECS 10 struct cisco_header { - u_char address; - u_char control; - u_short protocol; -}; + uint8_t address; + uint8_t control; + uint16_t protocol; +} __packed; #define CISCO_HEADER_LEN sizeof (struct cisco_header) struct cisco_packet { - u_long type; - u_long par1; - u_long par2; - u_short rel; - u_short time0; - u_short time1; -}; + uint32_t type; + uint32_t par1; + uint32_t par2; + uint16_t rel; + uint16_t time0; + uint16_t time1; +} __packed; #define CISCO_PACKET_LEN (sizeof(struct cisco_packet)) struct protoent { hook_p hook; /* the hook for this proto */ - u_short af; /* address family, -1 = downstream */ + uint16_t af; /* address family, -1 = downstream */ }; struct cisco_priv { - u_long local_seq; - u_long remote_seq; - u_long seqRetries; /* how many times we've been here throwing out + uint32_t local_seq; + uint32_t remote_seq; + uint32_t seqRetries; /* how many times we've been here throwing out * the same sequence number without ack */ node_p node; struct callout handle; @@ -271,7 +271,7 @@ cisco_rcvmsg(node_p node, item_p item, hook_p lasthook) pos = sprintf(arg, "keepalive period: %d sec; ", KEEPALIVE_SECS); pos += sprintf(arg + pos, - "unacknowledged keepalives: %ld", sc->seqRetries); + "unacknowledged keepalives: %d", sc->seqRetries); resp->header.arglen = pos + 1; break; } @@ -603,7 +603,7 @@ cisco_send(sc_p sc, int type, long par1, long par2) struct cisco_packet *ch; struct mbuf *m; struct timeval time; - u_long t; + uint32_t t; int error = 0; getmicrouptime(&time); @@ -626,8 +626,8 @@ cisco_send(sc_p sc, int type, long par1, long par2) ch->par1 = htonl(par1); ch->par2 = htonl(par2); ch->rel = -1; - ch->time0 = htons((u_short) (t >> 16)); - ch->time1 = htons((u_short) t); + ch->time0 = htons((uint16_t) (t >> 16)); + ch->time1 = htons((uint16_t) t); NG_SEND_DATA_ONLY(error, sc->downstream.hook, m); return (error); diff --git a/sys/netgraph/ng_cisco.h b/sys/netgraph/ng_cisco.h index e6ed9a212460..ebded7a76982 100644 --- a/sys/netgraph/ng_cisco.h +++ b/sys/netgraph/ng_cisco.h @@ -76,8 +76,8 @@ struct ng_cisco_ipaddr { } struct ng_cisco_stats { - u_int32_t seqRetries; /* # unack'd retries */ - u_int32_t keepAlivePeriod; /* in seconds */ + uint32_t seqRetries; /* # unack'd retries */ + uint32_t keepAlivePeriod; /* in seconds */ }; /* Keep this in sync with the above structure definition */ diff --git a/sys/netgraph/ng_device.c b/sys/netgraph/ng_device.c index b8c339cd933a..f6e60879e351 100644 --- a/sys/netgraph/ng_device.c +++ b/sys/netgraph/ng_device.c @@ -203,6 +203,7 @@ ng_device_rcvmsg(node_p node, item_p item, hook_p lasthook) const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *msg; struct ng_mesg *resp = NULL; + const char *dn; int error = 0; NGI_GET_MSG(item, msg); @@ -217,8 +218,8 @@ ng_device_rcvmsg(node_p node, item_p item, hook_p lasthook) if (resp == NULL) ERROUT(ENOMEM); - strlcpy((char *)resp->data, priv->ngddev->si_name, - strlen(priv->ngddev->si_name) + 1); + dn = devtoname(priv->ngddev); + strlcpy((char *)resp->data, dn, strlen(dn) + 1); break; default: diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c index f997d49d1985..16ea7c54a4a0 100644 --- a/sys/netgraph/ng_socket.c +++ b/sys/netgraph/ng_socket.c @@ -490,33 +490,30 @@ ng_getsockaddr(struct socket *so, struct sockaddr **addr) int sg_len; int error = 0; - /* Why isn't sg_data a `char[1]' ? :-( */ - sg_len = sizeof(struct sockaddr_ng) - sizeof(sg->sg_data) + 1; - pcbp = sotongpcb(so); if ((pcbp == NULL) || (pcbp->sockdata == NULL)) /* XXXGL: can this still happen? */ return (EINVAL); + sg_len = sizeof(struct sockaddr_ng) + NG_NODESIZ - + sizeof(sg->sg_data); + sg = malloc(sg_len, M_SONAME, M_WAITOK | M_ZERO); + mtx_lock(&pcbp->sockdata->mtx); if (pcbp->sockdata->node != NULL) { node_p node = pcbp->sockdata->node; - int namelen = 0; /* silence compiler! */ if (NG_NODE_HAS_NAME(node)) - sg_len += namelen = strlen(NG_NODE_NAME(node)); - - sg = malloc(sg_len, M_SONAME, M_WAITOK | M_ZERO); - - if (NG_NODE_HAS_NAME(node)) - bcopy(NG_NODE_NAME(node), sg->sg_data, namelen); + bcopy(NG_NODE_NAME(node), sg->sg_data, + strlen(NG_NODE_NAME(node))); + mtx_unlock(&pcbp->sockdata->mtx); sg->sg_len = sg_len; sg->sg_family = AF_NETGRAPH; *addr = (struct sockaddr *)sg; - mtx_unlock(&pcbp->sockdata->mtx); } else { mtx_unlock(&pcbp->sockdata->mtx); + free(sg, M_SONAME); error = EINVAL; } @@ -850,12 +847,9 @@ ngs_findhook(node_p node, const char *name) uint32_t h; /* - * Microoptimisations for a ng_socket with no - * hooks, or with a single hook, which is a - * common case. + * Microoptimisation for an ng_socket with + * a single hook, which is a common case. */ - if (node->nd_numhooks == 0) - return (NULL); if (node->nd_numhooks == 1) { hook_p hook; diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 13768686a385..4d8f350d80a8 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -707,19 +707,24 @@ carp_send_ad_all(void *ctx __unused, int pending __unused) LIST_FOREACH(sc, &carp_list, sc_next) if (sc->sc_state == MASTER) { CARP_LOCK(sc); + CURVNET_SET(sc->sc_carpdev->if_vnet); carp_send_ad_locked(sc); + CURVNET_RESTORE(); CARP_UNLOCK(sc); } mtx_unlock(&carp_mtx); } +/* Send a periodic advertisement, executed in callout context. */ static void carp_send_ad(void *v) { struct carp_softc *sc = v; CARP_LOCK_ASSERT(sc); + CURVNET_SET(sc->sc_carpdev->if_vnet); carp_send_ad_locked(sc); + CURVNET_RESTORE(); CARP_UNLOCK(sc); } @@ -1090,6 +1095,7 @@ carp_forus(struct ifnet *ifp, u_char *dhost) return (0); } +/* Master down timeout event, executed in callout context. */ static void carp_master_down(void *v) { @@ -1097,12 +1103,14 @@ carp_master_down(void *v) CARP_LOCK_ASSERT(sc); + CURVNET_SET(sc->sc_carpdev->if_vnet); if (sc->sc_state == BACKUP) { CARP_LOG("VHID %u@%s: BACKUP -> MASTER (master down)\n", sc->sc_vhid, sc->sc_carpdev->if_xname); carp_master_down_locked(sc); } + CURVNET_RESTORE(); CARP_UNLOCK(sc); } diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c index 1b16bc693140..cbb4ed76081a 100644 --- a/sys/netinet/ipfw/ip_fw2.c +++ b/sys/netinet/ipfw/ip_fw2.c @@ -1649,8 +1649,22 @@ do { \ break; case O_TCPWIN: - match = (proto == IPPROTO_TCP && offset == 0 && - cmd->arg1 == TCP(ulp)->th_win); + if (proto == IPPROTO_TCP && offset == 0) { + uint16_t x; + uint16_t *p; + int i; + + x = ntohs(TCP(ulp)->th_win); + if (cmdlen == 1) { + match = (cmd->arg1 == x); + break; + } + /* Otherwise we have ranges. */ + p = ((ipfw_insn_u16 *)cmd)->ports; + i = cmdlen - 1; + for (; !match && i > 0; i--, p += 2) + match = (x >= p[0] && x <= p[1]); + } break; case O_ESTAB: diff --git a/sys/netinet/ipfw/ip_fw_sockopt.c b/sys/netinet/ipfw/ip_fw_sockopt.c index dce3fdc750ba..1302452c7216 100644 --- a/sys/netinet/ipfw/ip_fw_sockopt.c +++ b/sys/netinet/ipfw/ip_fw_sockopt.c @@ -569,7 +569,6 @@ check_ipfw_struct(struct ip_fw *rule, int size) case O_IPPRECEDENCE: case O_IPVER: case O_SOCKARG: - case O_TCPWIN: case O_TCPFLAGS: case O_TCPOPTS: case O_ESTAB: @@ -679,6 +678,7 @@ check_ipfw_struct(struct ip_fw *rule, int size) case O_IPTTL: case O_IPLEN: case O_TCPDATALEN: + case O_TCPWIN: case O_TAGGED: if (cmdlen < 1 || cmdlen > 31) goto bad_size; diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index a36603678646..b5bceb2d29d6 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -7612,16 +7612,22 @@ sctp_fill_outqueue(struct sctp_tcb *stcb, SCTP_TCB_LOCK_ASSERT(stcb); asoc = &stcb->asoc; -#ifdef INET6 - if (net->ro._l_addr.sin6.sin6_family == AF_INET6) { - goal_mtu = net->mtu - SCTP_MIN_OVERHEAD; - } else { - /* ?? not sure what else to do */ + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: goal_mtu = net->mtu - SCTP_MIN_V4_OVERHEAD; - } -#else - goal_mtu = net->mtu - SCTP_MIN_OVERHEAD; + break; #endif +#ifdef INET6 + case AF_INET6: + goal_mtu = net->mtu - SCTP_MIN_OVERHEAD; + break; +#endif + default: + /* TSNH */ + goal_mtu = net->mtu; + break; + } /* Need an allowance for the data chunk header too */ goal_mtu -= sizeof(struct sctp_data_chunk); @@ -8180,10 +8186,21 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, if (!no_out_cnt) *num_out += ctl_cnt; /* recalc a clean slate and setup */ - if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - mtu = (net->mtu - SCTP_MIN_OVERHEAD); - } else { - mtu = (net->mtu - SCTP_MIN_V4_OVERHEAD); + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + mtu = net->mtu - SCTP_MIN_V4_OVERHEAD; + break; +#endif +#ifdef INET6 + case AF_INET6: + mtu = net->mtu - SCTP_MIN_OVERHEAD; + break; +#endif + default: + /* TSNH */ + mtu = net->mtu; + break; } to_out = 0; no_fragmentflg = 1; @@ -8446,10 +8463,21 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, if (!no_out_cnt) *num_out += ctl_cnt; /* recalc a clean slate and setup */ - if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - mtu = (net->mtu - SCTP_MIN_OVERHEAD); - } else { - mtu = (net->mtu - SCTP_MIN_V4_OVERHEAD); + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + mtu = net->mtu - SCTP_MIN_V4_OVERHEAD; + break; +#endif +#ifdef INET6 + case AF_INET6: + mtu = net->mtu - SCTP_MIN_OVERHEAD; + break; +#endif + default: + /* TSNH */ + mtu = net->mtu; + break; } to_out = 0; no_fragmentflg = 1; @@ -9492,10 +9520,21 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, } /* pick up the net */ net = chk->whoTo; - if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - mtu = (net->mtu - SCTP_MIN_OVERHEAD); - } else { + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: mtu = net->mtu - SCTP_MIN_V4_OVERHEAD; + break; +#endif +#ifdef INET6 + case AF_INET6: + mtu = net->mtu - SCTP_MIN_OVERHEAD; + break; +#endif + default: + /* TSNH */ + mtu = net->mtu; + break; } if ((asoc->peers_rwnd < mtu) && (asoc->total_flight > 0)) { @@ -9816,12 +9855,10 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, return (0); } - -static int +static void sctp_timer_validation(struct sctp_inpcb *inp, struct sctp_tcb *stcb, - struct sctp_association *asoc, - int ret) + struct sctp_association *asoc) { struct sctp_nets *net; @@ -9829,7 +9866,7 @@ sctp_timer_validation(struct sctp_inpcb *inp, TAILQ_FOREACH(net, &asoc->nets, sctp_next) { if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { /* Here is a timer */ - return (ret); + return; } } SCTP_TCB_LOCK_ASSERT(stcb); @@ -9840,7 +9877,7 @@ sctp_timer_validation(struct sctp_inpcb *inp, } else { sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->primary_destination); } - return (ret); + return; } void @@ -9950,7 +9987,7 @@ sctp_chunk_output(struct sctp_inpcb *inp, #ifdef SCTP_AUDITING_ENABLED sctp_auditing(8, inp, stcb, NULL); #endif - (void)sctp_timer_validation(inp, stcb, asoc, ret); + sctp_timer_validation(inp, stcb, asoc); return; } if (ret < 0) { diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index 0f3692452607..8685dfe0a02b 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -416,7 +416,7 @@ TAILQ_HEAD(sctpchunk_listhead, sctp_tmit_chunk); #define CHUNK_FLAGS_PR_SCTP_BUF SCTP_PR_SCTP_BUF #define CHUNK_FLAGS_PR_SCTP_RTX SCTP_PR_SCTP_RTX -/* The upper byte is used a a bit mask */ +/* The upper byte is used as a bit mask */ #define CHUNK_FLAGS_FRAGMENT_OK 0x0100 struct chk_id { diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h index 805a5616dc1c..c714360c1644 100644 --- a/sys/netinet/tcp.h +++ b/sys/netinet/tcp.h @@ -159,6 +159,10 @@ struct tcphdr { #define TCP_MD5SIG 0x10 /* use MD5 digests (RFC2385) */ #define TCP_INFO 0x20 /* retrieve tcp_info structure */ #define TCP_CONGESTION 0x40 /* get/set congestion control algorithm */ +#define TCP_KEEPINIT 0x80 /* N, time to establish connection */ +#define TCP_KEEPIDLE 0x100 /* L,N,X start keeplives after this period */ +#define TCP_KEEPINTVL 0x200 /* L,N interval between keepalives */ +#define TCP_KEEPCNT 0x400 /* L,N number of keepalives before close */ #define TCP_CA_NAME_MAX 16 /* max congestion control name length */ diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index db373cd93337..1a31c5e46640 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1446,7 +1446,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ tp->t_rcvtime = ticks; if (TCPS_HAVEESTABLISHED(tp->t_state)) - tcp_timer_activate(tp, TT_KEEP, tcp_keepidle); + tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); /* * Unscale the window into a 32-bit value. @@ -1493,7 +1493,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ if ((to.to_flags & TOF_TS) && (to.to_tsecr != 0)) { to.to_tsecr -= tp->ts_offset; - if (TSTMP_GT(to.to_tsecr, ticks)) + if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks())) to.to_tsecr = 0; } @@ -1518,7 +1518,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, if (to.to_flags & TOF_TS) { tp->t_flags |= TF_RCVD_TSTMP; tp->ts_recent = to.to_tsval; - tp->ts_recent_age = ticks; + tp->ts_recent_age = tcp_ts_getticks(); } if (to.to_flags & TOF_MSS) tcp_mss(tp, to.to_mss); @@ -1562,7 +1562,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ if ((to.to_flags & TOF_TS) != 0 && SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { - tp->ts_recent_age = ticks; + tp->ts_recent_age = tcp_ts_getticks(); tp->ts_recent = to.to_tsval; } @@ -1600,11 +1600,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) { - if (!tp->t_rttlow || - tp->t_rttlow > ticks - to.to_tsecr) - tp->t_rttlow = ticks - to.to_tsecr; + u_int t; + + t = tcp_ts_getticks() - to.to_tsecr; + if (!tp->t_rttlow || tp->t_rttlow > t) + tp->t_rttlow = t; tcp_xmit_timer(tp, - ticks - to.to_tsecr + 1); + TCP_TS_TO_TICKS(t) + 1); } else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) { if (!tp->t_rttlow || @@ -1889,7 +1891,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, } else { tp->t_state = TCPS_ESTABLISHED; cc_conn_init(tp); - tcp_timer_activate(tp, TT_KEEP, tcp_keepidle); + tcp_timer_activate(tp, TT_KEEP, + TP_KEEPIDLE(tp)); } } else { /* @@ -2069,7 +2072,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, TSTMP_LT(to.to_tsval, tp->ts_recent)) { /* Check to see if ts_recent is over 24 days old. */ - if (ticks - tp->ts_recent_age > TCP_PAWS_IDLE) { + if (tcp_ts_getticks() - tp->ts_recent_age > TCP_PAWS_IDLE) { /* * Invalidate ts_recent. If this segment updates * ts_recent, the age will be reset later and ts_recent @@ -2228,7 +2231,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, SEQ_LEQ(th->th_seq, tp->last_ack_sent) && SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen + ((thflags & (TH_SYN|TH_FIN)) != 0))) { - tp->ts_recent_age = ticks; + tp->ts_recent_age = tcp_ts_getticks(); tp->ts_recent = to.to_tsval; } @@ -2293,7 +2296,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, } else { tp->t_state = TCPS_ESTABLISHED; cc_conn_init(tp); - tcp_timer_activate(tp, TT_KEEP, tcp_keepidle); + tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); } /* * If segment contains data or ACK, will call tcp_reass() @@ -2542,11 +2545,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * timestamps of 0 or we could calculate a * huge RTT and blow up the retransmit timer. */ - if ((to.to_flags & TOF_TS) != 0 && - to.to_tsecr) { - if (!tp->t_rttlow || tp->t_rttlow > ticks - to.to_tsecr) - tp->t_rttlow = ticks - to.to_tsecr; - tcp_xmit_timer(tp, ticks - to.to_tsecr + 1); + if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) { + u_int t; + + t = tcp_ts_getticks() - to.to_tsecr; + if (!tp->t_rttlow || tp->t_rttlow > t) + tp->t_rttlow = t; + tcp_xmit_timer(tp, TCP_TS_TO_TICKS(t) + 1); } else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) { if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime) tp->t_rttlow = ticks - tp->t_rtttime; @@ -2630,12 +2635,11 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * compressed state. */ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { - int timeout; - soisdisconnected(so); - timeout = (tcp_fast_finwait2_recycle) ? - tcp_finwait2_timeout : tcp_maxidle; - tcp_timer_activate(tp, TT_2MSL, timeout); + tcp_timer_activate(tp, TT_2MSL, + (tcp_fast_finwait2_recycle ? + tcp_finwait2_timeout : + TP_MAXIDLE(tp))); } tp->t_state = TCPS_FIN_WAIT_2; } diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 21620d3a1920..1965db15d9cd 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -680,13 +680,13 @@ tcp_output(struct tcpcb *tp) /* Timestamps. */ if ((tp->t_flags & TF_RCVD_TSTMP) || ((flags & TH_SYN) && (tp->t_flags & TF_REQ_TSTMP))) { - to.to_tsval = ticks + tp->ts_offset; + to.to_tsval = tcp_ts_getticks() + tp->ts_offset; to.to_tsecr = tp->ts_recent; to.to_flags |= TOF_TS; /* Set receive buffer autosizing timestamp. */ if (tp->rfbuf_ts == 0 && (so->so_rcv.sb_flags & SB_AUTOSIZE)) - tp->rfbuf_ts = ticks; + tp->rfbuf_ts = tcp_ts_getticks(); } /* Selective ACK's. */ if (tp->t_flags & TF_SACK_PERMIT) { diff --git a/sys/netinet/tcp_seq.h b/sys/netinet/tcp_seq.h index f58b537c72a2..51d971f22bee 100644 --- a/sys/netinet/tcp_seq.h +++ b/sys/netinet/tcp_seq.h @@ -62,7 +62,34 @@ (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \ (tp)->snd_recover = (tp)->iss -#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * hz) - /* timestamp wrap-around time */ +#ifdef _KERNEL +/* + * Clock macros for RFC 1323 timestamps. + */ +#define TCP_TS_TO_TICKS(_t) ((_t) * hz / 1000) + +/* Timestamp wrap-around time, 24 days. */ +#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * 1000) + +/* + * tcp_ts_getticks() in ms, should be 1ms < x < 1000ms according to RFC 1323. + * We always use 1ms granularity independent of hz. + */ +static __inline u_int +tcp_ts_getticks(void) +{ + struct timeval tv; + u_long ms; + + /* + * getmicrouptime() should be good enough for any 1-1000ms granularity. + * Do not use getmicrotime() here as it might break nfsroot/tcp. + */ + getmicrouptime(&tv); + ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + return (ms); +} +#endif /* _KERNEL */ #endif /* _NETINET_TCP_SEQ_H_ */ diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 2e9c37cb2600..8df7ce0d0825 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -819,7 +819,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) if (sc->sc_flags & SCF_TIMESTAMP) { tp->t_flags |= TF_REQ_TSTMP|TF_RCVD_TSTMP; tp->ts_recent = sc->sc_tsreflect; - tp->ts_recent_age = ticks; + tp->ts_recent_age = tcp_ts_getticks(); tp->ts_offset = sc->sc_tsoff; } #ifdef TCP_SIGNATURE @@ -845,7 +845,15 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) */ if (sc->sc_rxmits > 1) tp->snd_cwnd = tp->t_maxseg; - tcp_timer_activate(tp, TT_KEEP, tcp_keepinit); + + /* + * Copy and activate timers. + */ + tp->t_keepinit = sototcpcb(lso)->t_keepinit; + tp->t_keepidle = sototcpcb(lso)->t_keepidle; + tp->t_keepintvl = sototcpcb(lso)->t_keepintvl; + tp->t_keepcnt = sototcpcb(lso)->t_keepcnt; + tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); INP_WUNLOCK(inp); @@ -1218,7 +1226,7 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, */ if (to->to_flags & TOF_TS) { sc->sc_tsreflect = to->to_tsval; - sc->sc_ts = ticks; + sc->sc_ts = tcp_ts_getticks(); sc->sc_flags |= SCF_TIMESTAMP; } if (to->to_flags & TOF_SCALE) { @@ -1659,7 +1667,7 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc, data |= md5_buffer[2] << 10; /* more digest bits */ data ^= md5_buffer[3]; sc->sc_ts = data; - sc->sc_tsoff = data - ticks; /* after XOR */ + sc->sc_tsoff = data - tcp_ts_getticks(); /* after XOR */ } TCPSTAT_INC(tcps_sc_sendcookie); @@ -1744,7 +1752,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch, sc->sc_flags |= SCF_TIMESTAMP; sc->sc_tsreflect = to->to_tsval; sc->sc_ts = to->to_tsecr; - sc->sc_tsoff = to->to_tsecr - ticks; + sc->sc_tsoff = to->to_tsecr - tcp_ts_getticks(); sc->sc_flags |= (data & 0x1) ? SCF_SIGNATURE : 0; sc->sc_flags |= ((data >> 1) & 0x1) ? SCF_SACK : 0; sc->sc_requested_s_scale = min((data >> 2) & 0xf, diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 1651d6928ba0..9c3c74925be1 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -111,12 +111,12 @@ int tcp_finwait2_timeout; SYSCTL_PROC(_net_inet_tcp, OID_AUTO, finwait2_timeout, CTLTYPE_INT|CTLFLAG_RW, &tcp_finwait2_timeout, 0, sysctl_msec_to_ticks, "I", "FIN-WAIT2 timeout"); +int tcp_keepcnt = TCPTV_KEEPCNT; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0, + "Number of keepalive probes to send"); -static int tcp_keepcnt = TCPTV_KEEPCNT; /* max idle probes */ int tcp_maxpersistidle; - /* max idle time in persist */ -int tcp_maxidle; static int per_cpu_timers = 0; SYSCTL_INT(_net_inet_tcp, OID_AUTO, per_cpu_timers, CTLFLAG_RW, @@ -138,7 +138,6 @@ tcp_slowtimo(void) VNET_LIST_RLOCK_NOSLEEP(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); - tcp_maxidle = tcp_keepcnt * tcp_keepintvl; INP_INFO_WLOCK(&V_tcbinfo); (void) tcp_tw_2msl_scan(0); INP_INFO_WUNLOCK(&V_tcbinfo); @@ -255,9 +254,9 @@ tcp_timer_2msl(void *xtp) tp = tcp_close(tp); } else { if (tp->t_state != TCPS_TIME_WAIT && - ticks - tp->t_rcvtime <= tcp_maxidle) - callout_reset_on(&tp->t_timers->tt_2msl, tcp_keepintvl, - tcp_timer_2msl, tp, INP_CPU(inp)); + ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) + callout_reset_on(&tp->t_timers->tt_2msl, + TP_KEEPINTVL(tp), tcp_timer_2msl, tp, INP_CPU(inp)); else tp = tcp_close(tp); } @@ -318,7 +317,7 @@ tcp_timer_keep(void *xtp) goto dropit; if ((always_keepalive || inp->inp_socket->so_options & SO_KEEPALIVE) && tp->t_state <= TCPS_CLOSING) { - if (ticks - tp->t_rcvtime >= tcp_keepidle + tcp_maxidle) + if (ticks - tp->t_rcvtime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp)) goto dropit; /* * Send a packet designed to force a response @@ -340,9 +339,11 @@ tcp_timer_keep(void *xtp) tp->rcv_nxt, tp->snd_una - 1, 0); free(t_template, M_TEMP); } - callout_reset_on(&tp->t_timers->tt_keep, tcp_keepintvl, tcp_timer_keep, tp, INP_CPU(inp)); + callout_reset_on(&tp->t_timers->tt_keep, TP_KEEPINTVL(tp), + tcp_timer_keep, tp, INP_CPU(inp)); } else - callout_reset_on(&tp->t_timers->tt_keep, tcp_keepidle, tcp_timer_keep, tp, INP_CPU(inp)); + callout_reset_on(&tp->t_timers->tt_keep, TP_KEEPIDLE(tp), + tcp_timer_keep, tp, INP_CPU(inp)); #ifdef TCPDEBUG if (inp->inp_socket->so_options & SO_DEBUG) diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index 4bfcdf65c155..2fc8f7b99d0f 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -153,10 +153,16 @@ struct tcp_timer { #define TT_KEEP 0x08 #define TT_2MSL 0x10 +#define TP_KEEPINIT(tp) ((tp)->t_keepinit ? (tp)->t_keepinit : tcp_keepinit) +#define TP_KEEPIDLE(tp) ((tp)->t_keepidle ? (tp)->t_keepidle : tcp_keepidle) +#define TP_KEEPINTVL(tp) ((tp)->t_keepintvl ? (tp)->t_keepintvl : tcp_keepintvl) +#define TP_KEEPCNT(tp) ((tp)->t_keepcnt ? (tp)->t_keepcnt : tcp_keepcnt) +#define TP_MAXIDLE(tp) (TP_KEEPCNT(tp) * TP_KEEPINTVL(tp)) + extern int tcp_keepinit; /* time to establish connection */ extern int tcp_keepidle; /* time before keepalive probes begin */ extern int tcp_keepintvl; /* time between keepalive probes */ -extern int tcp_maxidle; /* time to drop after starting probes */ +extern int tcp_keepcnt; /* number of keepalives */ extern int tcp_delacktime; /* time before sending a delayed ACK */ extern int tcp_maxpersistidle; extern int tcp_rexmit_min; diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 469c7c07ac90..894e926e9e53 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -558,7 +558,7 @@ tcp_twrespond(struct tcptw *tw, int flags) */ if (tw->t_recent && flags == TH_ACK) { to.to_flags |= TOF_TS; - to.to_tsval = ticks + tw->ts_offset; + to.to_tsval = tcp_ts_getticks() + tw->ts_offset; to.to_tsecr = tw->t_recent; } optlen = tcp_addoptions(&to, (u_char *)(th + 1)); diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 5e2af8f81e2f..a9045f31483d 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -1118,7 +1119,7 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) soisconnecting(so); TCPSTAT_INC(tcps_connattempt); tp->t_state = TCPS_SYN_SENT; - tcp_timer_activate(tp, TT_KEEP, tcp_keepinit); + tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); tp->iss = tcp_new_isn(tp); tcp_sendseqinit(tp); @@ -1191,7 +1192,7 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) soisconnecting(so); TCPSTAT_INC(tcps_connattempt); tp->t_state = TCPS_SYN_SENT; - tcp_timer_activate(tp, TT_KEEP, tcp_keepinit); + tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); tp->iss = tcp_new_isn(tp); tcp_sendseqinit(tp); @@ -1272,6 +1273,7 @@ int tcp_ctloutput(struct socket *so, struct sockopt *sopt) { int error, opt, optval; + u_int ui; struct inpcb *inp; struct tcpcb *tp; struct tcp_info ti; @@ -1439,6 +1441,59 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt) INP_WUNLOCK(inp); break; + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: + case TCP_KEEPCNT: + case TCP_KEEPINIT: + INP_WUNLOCK(inp); + error = sooptcopyin(sopt, &ui, sizeof(ui), sizeof(ui)); + if (error) + return (error); + + if (ui > (UINT_MAX / hz)) { + error = EINVAL; + break; + } + ui *= hz; + + INP_WLOCK_RECHECK(inp); + switch (sopt->sopt_name) { + case TCP_KEEPIDLE: + tp->t_keepidle = ui; + /* + * XXX: better check current remaining + * timeout and "merge" it with new value. + */ + if ((tp->t_state > TCPS_LISTEN) && + (tp->t_state <= TCPS_CLOSING)) + tcp_timer_activate(tp, TT_KEEP, + TP_KEEPIDLE(tp)); + break; + case TCP_KEEPINTVL: + tp->t_keepintvl = ui; + if ((tp->t_state == TCPS_FIN_WAIT_2) && + (TP_MAXIDLE(tp) > 0)) + tcp_timer_activate(tp, TT_2MSL, + TP_MAXIDLE(tp)); + break; + case TCP_KEEPCNT: + tp->t_keepcnt = ui; + if ((tp->t_state == TCPS_FIN_WAIT_2) && + (TP_MAXIDLE(tp) > 0)) + tcp_timer_activate(tp, TT_2MSL, + TP_MAXIDLE(tp)); + break; + case TCP_KEEPINIT: + tp->t_keepinit = ui; + if (tp->t_state == TCPS_SYN_RECEIVED || + tp->t_state == TCPS_SYN_SENT) + tcp_timer_activate(tp, TT_KEEP, + TP_KEEPINIT(tp)); + break; + } + INP_WUNLOCK(inp); + break; + default: INP_WUNLOCK(inp); error = ENOPROTOOPT; @@ -1636,7 +1691,7 @@ tcp_usrclosed(struct tcpcb *tp) int timeout; timeout = (tcp_fast_finwait2_recycle) ? - tcp_finwait2_timeout : tcp_maxidle; + tcp_finwait2_timeout : TP_MAXIDLE(tp); tcp_timer_activate(tp, TT_2MSL, timeout); } } diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index bc64ac2ba8ef..b602c27aa2d0 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -203,7 +203,12 @@ struct tcpcb { struct cc_var *ccv; /* congestion control specific vars */ struct osd *osd; /* storage for Khelp module data */ - uint32_t t_ispare[12]; /* 4 keep timers, 5 UTO, 3 TBD */ + u_int t_keepinit; /* time to establish connection */ + u_int t_keepidle; /* time before keepalive probes begin */ + u_int t_keepintvl; /* interval between keepalives */ + u_int t_keepcnt; /* number of keepalives before close */ + + uint32_t t_ispare[8]; /* 5 UTO, 3 TBD */ void *t_pspare2[4]; /* 4 TBD */ uint64_t _pad[6]; /* 6 TBD (1-2 CC/RTT?) */ }; diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index 4ba1f7b3a586..241af51410a8 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -938,7 +938,7 @@ nfs_lookup(struct vop_lookup_args *ap) *vpp = NULLVP; return (error); } - error = cache_lookup_times(dvp, vpp, cnp, &nctime, &ncticks); + error = cache_lookup(dvp, vpp, cnp, &nctime, &ncticks); if (error > 0 && error != ENOENT) return (error); if (error == -1) { @@ -1448,7 +1448,7 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, tsiz -= len; } nfsmout: - if (vp->v_mount->mnt_kern_flag & MNTK_ASYNC) + if (DOINGASYNC(vp)) committed = NFSV3WRITE_FILESYNC; *iomode = committed; if (error) diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC index bcc13e655b37..cd49214171e7 100644 --- a/sys/pc98/conf/GENERIC +++ b/sys/pc98/conf/GENERIC @@ -67,20 +67,8 @@ options CAPABILITY_MODE # Capsicum capability mode options CAPABILITIES # Capsicum capabilities options MAC # TrustedBSD MAC Framework options INCLUDE_CONFIG_FILE # Include this file in kernel - -# Debugging support. Always need this: -options KDB # Enable kernel debugger support. -# For minimum debugger support (stable branch) use: -#options KDB_TRACE # Print a stack trace for a panic. -# For full debugger support use this instead: -options DDB # Support DDB. -options GDB # Support remote GDB. -options DEADLKRES # Enable the deadlock resolver -options INVARIANTS # Enable calls of extra sanity checking -options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -options WITNESS # Enable checks to detect deadlocks and cycles -options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed -options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones +options KDB # Kernel debugger related code +options KDB_TRACE # Print a stack trace for a panic # To make an SMP kernel, the next two lines are needed #options SMP # Symmetric MultiProcessor Kernel @@ -167,8 +155,7 @@ device plip # TCP/IP over parallel device ppi # Parallel port interface device #device vpo # Requires scbus and da # OLD Parallel port -# Please stay olpt driver after ppc driver -device olpt +#device olpt # PCI Ethernet NICs. device de # DEC/Intel DC21x4x (``Tulip'') diff --git a/sys/powerpc/aim/swtch64.S b/sys/powerpc/aim/swtch64.S index 489ec406934d..3b09adf3209e 100644 --- a/sys/powerpc/aim/swtch64.S +++ b/sys/powerpc/aim/swtch64.S @@ -68,7 +68,7 @@ /* * void cpu_throw(struct thread *old, struct thread *new) */ -ENTRY_NOPROF(cpu_throw) +ENTRY(cpu_throw) mr %r13, %r4 b cpu_switchin @@ -79,7 +79,7 @@ ENTRY_NOPROF(cpu_throw) * * Switch to a new thread saving the current state in the old thread. */ -ENTRY_NOPROF(cpu_switch) +ENTRY(cpu_switch) ld %r6,TD_PCB(%r3) /* Get the old thread's PCB ptr */ std %r12,PCB_CONTEXT(%r6) /* Save the non-volatile GP regs. These can now be used for scratch */ @@ -237,7 +237,7 @@ blocked_loop: * savectx(pcb) * Update pcb, saving current processor state */ -ENTRY_NOPROF(savectx) +ENTRY(savectx) std %r12,PCB_CONTEXT(%r3) /* Save the non-volatile GP regs. */ std %r13,PCB_CONTEXT+1*8(%r3) std %r14,PCB_CONTEXT+2*8(%r3) diff --git a/sys/powerpc/include/asm.h b/sys/powerpc/include/asm.h index bfc939b32536..5f8b77910eb1 100644 --- a/sys/powerpc/include/asm.h +++ b/sys/powerpc/include/asm.h @@ -116,9 +116,9 @@ #define __FBSDID(s) /* nothing */ #endif /* not lint and not STRIP_FBSDID */ -#define WEAK_ALIAS(alias,sym) \ +#define WEAK_REFERENCE(sym, alias) \ .weak alias; \ - alias = sym + .equ alias,sym #ifdef __STDC__ #define WARN_REFERENCES(_sym,_msg) \ diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c new file mode 100644 index 000000000000..46d483d62b4f --- /dev/null +++ b/sys/powerpc/ofw/ofw_pci.c @@ -0,0 +1,535 @@ +/*- + * Copyright (c) 2011 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include "pcib_if.h" + +/* + * Bus interface. + */ +static int ofw_pci_read_ivar(device_t, device_t, int, + uintptr_t *); +static struct resource * ofw_pci_alloc_resource(device_t bus, + device_t child, int type, int *rid, u_long start, + u_long end, u_long count, u_int flags); +static int ofw_pci_release_resource(device_t bus, device_t child, + int type, int rid, struct resource *res); +static int ofw_pci_activate_resource(device_t bus, device_t child, + int type, int rid, struct resource *res); +static int ofw_pci_deactivate_resource(device_t bus, + device_t child, int type, int rid, + struct resource *res); +static int ofw_pci_adjust_resource(device_t bus, device_t child, + int type, struct resource *res, u_long start, + u_long end); + +/* + * pcib interface. + */ +static int ofw_pci_maxslots(device_t); +static int ofw_pci_route_interrupt(device_t, device_t, int); + +/* + * ofw_bus interface + */ +static phandle_t ofw_pci_get_node(device_t bus, device_t dev); + +/* + * local methods + */ + +static int ofw_pci_nranges(phandle_t node); +static int ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges); + +/* + * Driver methods. + */ +static device_method_t ofw_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_attach, ofw_pci_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_alloc_resource, ofw_pci_alloc_resource), + DEVMETHOD(bus_release_resource, ofw_pci_release_resource), + DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource), + DEVMETHOD(bus_deactivate_resource, ofw_pci_deactivate_resource), + DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, ofw_pci_maxslots), + DEVMETHOD(pcib_route_interrupt, ofw_pci_route_interrupt), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(ofw_pci, ofw_pci_driver, ofw_pci_methods, 0); + +int +ofw_pci_attach(device_t dev) +{ + struct ofw_pci_softc *sc; + phandle_t node; + u_int32_t busrange[2]; + struct ofw_pci_range *rp; + int error; + + node = ofw_bus_get_node(dev); + sc = device_get_softc(dev); + + if (OF_getprop(node, "reg", &sc->sc_pcir, sizeof(sc->sc_pcir)) == -1) + return (ENXIO); + + if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8) + busrange[0] = 0; + + sc->sc_dev = dev; + sc->sc_node = node; + sc->sc_bus = busrange[0]; + + if (sc->sc_quirks & OFW_PCI_QUIRK_RANGES_ON_CHILDREN) { + phandle_t c; + int n, i; + + sc->sc_nrange = 0; + for (c = OF_child(node); c != 0; c = OF_peer(c)) { + n = ofw_pci_nranges(c); + if (n > 0) + sc->sc_nrange += n; + } + if (sc->sc_nrange == 0) + return (ENXIO); + sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]), + M_DEVBUF, M_WAITOK); + i = 0; + for (c = OF_child(node); c != 0; c = OF_peer(c)) { + n = ofw_pci_fill_ranges(c, &sc->sc_range[i]); + if (n > 0) + i += n; + } + KASSERT(i == sc->sc_nrange, ("range count mismatch")); + } else { + sc->sc_nrange = ofw_pci_nranges(node); + if (sc->sc_nrange <= 0) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } + sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]), + M_DEVBUF, M_WAITOK); + ofw_pci_fill_ranges(node, sc->sc_range); + } + + sc->sc_io_rman.rm_type = RMAN_ARRAY; + sc->sc_io_rman.rm_descr = "PCI I/O Ports"; + error = rman_init(&sc->sc_io_rman); + if (error) { + device_printf(dev, "rman_init() failed. error = %d\n", error); + return (error); + } + + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "PCI Memory"; + error = rman_init(&sc->sc_mem_rman); + if (error) { + device_printf(dev, "rman_init() failed. error = %d\n", error); + return (error); + } + + for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && + rp->pci_hi != 0; rp++) { + error = 0; + + switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + case OFW_PCI_PHYS_HI_SPACE_CONFIG: + break; + case OFW_PCI_PHYS_HI_SPACE_IO: + error = rman_manage_region(&sc->sc_io_rman, rp->pci, + rp->pci + rp->size - 1); + break; + case OFW_PCI_PHYS_HI_SPACE_MEM32: + case OFW_PCI_PHYS_HI_SPACE_MEM64: + error = rman_manage_region(&sc->sc_mem_rman, rp->pci, + rp->pci + rp->size - 1); + break; + } + + if (error) { + device_printf(dev, + "rman_manage_region(%x, %#jx, %#jx) failed. " + "error = %d\n", rp->pci_hi & + OFW_PCI_PHYS_HI_SPACEMASK, rp->pci, + rp->pci + rp->size - 1, error); + panic("AHOY"); + return (error); + } + } + + ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); + + device_add_child(dev, "pci", device_get_unit(dev)); + return (bus_generic_attach(dev)); +} + +static int +ofw_pci_maxslots(device_t dev) +{ + + return (PCI_SLOTMAX); +} + +static int +ofw_pci_route_interrupt(device_t bus, device_t dev, int pin) +{ + struct ofw_pci_softc *sc; + struct ofw_pci_register reg; + uint32_t pintr, mintr; + phandle_t iparent; + uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; + + sc = device_get_softc(bus); + pintr = pin; + if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, + sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), + &iparent, maskbuf)) + return (MAP_IRQ(iparent, mintr)); + + /* Maybe it's a real interrupt, not an intpin */ + if (pin > 4) + return (pin); + + device_printf(bus, "could not route pin %d for device %d.%d\n", + pin, pci_get_slot(dev), pci_get_function(dev)); + return (PCI_INVALID_IRQ); +} + +static int +ofw_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct ofw_pci_softc *sc; + + sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_DOMAIN: + *result = device_get_unit(dev); + return (0); + case PCIB_IVAR_BUS: + *result = sc->sc_bus; + return (0); + } + + return (ENOENT); +} + +static struct resource * +ofw_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct ofw_pci_softc *sc; + struct resource *rv; + struct rman *rm; + int needactivate; + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + + sc = device_get_softc(bus); + + switch (type) { + case SYS_RES_MEMORY: + rm = &sc->sc_mem_rman; + break; + + case SYS_RES_IOPORT: + rm = &sc->sc_io_rman; + break; + + case SYS_RES_IRQ: + return (bus_alloc_resource(bus, type, rid, start, end, count, + flags)); + + default: + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == NULL) { + device_printf(bus, "failed to reserve resource for %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rman_set_rid(rv, *rid); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + device_printf(bus, + "failed to activate resource for %s\n", + device_get_nameunit(child)); + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + +static int +ofw_pci_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + if (rman_get_flags(res) & RF_ACTIVE) { + int error = bus_deactivate_resource(child, type, rid, res); + if (error) + return error; + } + + return (rman_release_resource(res)); +} + +static int +ofw_pci_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + struct ofw_pci_softc *sc; + void *p; + + sc = device_get_softc(bus); + + if (type == SYS_RES_IRQ) { + return (bus_activate_resource(bus, type, rid, res)); + } + if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + struct ofw_pci_range *rp; + vm_offset_t start; + int space; + + start = (vm_offset_t)rman_get_start(res); + + /* + * Map this through the ranges list + */ + for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && + rp->pci_hi != 0; rp++) { + if (start < rp->pci || start >= rp->pci + rp->size) + continue; + + switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + case OFW_PCI_PHYS_HI_SPACE_IO: + space = SYS_RES_IOPORT; + break; + case OFW_PCI_PHYS_HI_SPACE_MEM32: + case OFW_PCI_PHYS_HI_SPACE_MEM64: + space = SYS_RES_MEMORY; + break; + default: + space = -1; + } + + if (type == space) { + start += (rp->host - rp->pci); + break; + } + } + + if (bootverbose) + printf("ofw_pci mapdev: start %zx, len %ld\n", start, + rman_get_size(res)); + + p = pmap_mapdev(start, (vm_size_t)rman_get_size(res)); + if (p == NULL) + return (ENOMEM); + + rman_set_virtual(res, p); + rman_set_bustag(res, &bs_le_tag); + rman_set_bushandle(res, (u_long)p); + } + + return (rman_activate_resource(res)); +} + +static int +ofw_pci_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + /* + * If this is a memory resource, unmap it. + */ + if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { + u_int32_t psize; + + psize = rman_get_size(res); + pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); + } + + return (rman_deactivate_resource(res)); +} + +static int +ofw_pci_adjust_resource(device_t bus, device_t child, int type, + struct resource *res, u_long start, u_long end) +{ + struct rman *rm = NULL; + struct ofw_pci_softc *sc = device_get_softc(bus); + + KASSERT(!(rman_get_flags(res) & RF_ACTIVE), + ("active resources cannot be adjusted")); + if (rman_get_flags(res) & RF_ACTIVE) + return (EINVAL); + + switch (type) { + case SYS_RES_MEMORY: + rm = &sc->sc_mem_rman; + break; + case SYS_RES_IOPORT: + rm = &sc->sc_io_rman; + break; + default: + return (ENXIO); + } + + if (!rman_is_region_manager(res, rm)) + return (EINVAL); + + return (rman_adjust_resource(res, start, end)); +} + + +static phandle_t +ofw_pci_get_node(device_t bus, device_t dev) +{ + struct ofw_pci_softc *sc; + + sc = device_get_softc(bus); + /* We only have one child, the PCI bus, which needs our own node. */ + + return (sc->sc_node); +} + +static int +ofw_pci_nranges(phandle_t node) +{ + int host_address_cells = 1, pci_address_cells = 3, size_cells = 2; + ssize_t nbase_ranges; + + OF_getprop(OF_parent(node), "#address-cells", &host_address_cells, + sizeof(host_address_cells)); + OF_getprop(node, "#address-cells", &pci_address_cells, + sizeof(pci_address_cells)); + OF_getprop(node, "#size-cells", &size_cells, sizeof(size_cells)); + + nbase_ranges = OF_getproplen(node, "ranges"); + if (nbase_ranges <= 0) + return (-1); + + return (nbase_ranges / sizeof(cell_t) / + (pci_address_cells + host_address_cells + size_cells)); +} + +static int +ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges) +{ + int host_address_cells = 1, pci_address_cells = 3, size_cells = 2; + cell_t *base_ranges; + ssize_t nbase_ranges; + int nranges; + int i, j, k; + + OF_getprop(OF_parent(node), "#address-cells", &host_address_cells, + sizeof(host_address_cells)); + OF_getprop(node, "#address-cells", &pci_address_cells, + sizeof(pci_address_cells)); + OF_getprop(node, "#size-cells", &size_cells, sizeof(size_cells)); + + nbase_ranges = OF_getproplen(node, "ranges"); + if (nbase_ranges <= 0) + return (-1); + nranges = nbase_ranges / sizeof(cell_t) / + (pci_address_cells + host_address_cells + size_cells); + + base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); + OF_getprop(node, "ranges", base_ranges, nbase_ranges); + + for (i = 0, j = 0; i < nranges; i++) { + ranges[i].pci_hi = base_ranges[j++]; + ranges[i].pci = 0; + for (k = 0; k < pci_address_cells - 1; k++) { + ranges[i].pci <<= 32; + ranges[i].pci |= base_ranges[j++]; + } + ranges[i].host = 0; + for (k = 0; k < host_address_cells; k++) { + ranges[i].host <<= 32; + ranges[i].host |= base_ranges[j++]; + } + ranges[i].size = 0; + for (k = 0; k < size_cells; k++) { + ranges[i].size <<= 32; + ranges[i].size |= base_ranges[j++]; + } + } + + free(base_ranges, M_DEVBUF); + return (nranges); +} + diff --git a/sys/powerpc/ofw/ofw_pci.h b/sys/powerpc/ofw/ofw_pci.h new file mode 100644 index 000000000000..dd277e9a0e9c --- /dev/null +++ b/sys/powerpc/ofw/ofw_pci.h @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2011 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef POWERPC_OFW_OFW_PCI_H +#define POWERPC_OFW_OFW_PCI_H + +/* + * Export class definition for inheritance purposes + */ +DECLARE_CLASS(ofw_pci_driver); + +struct ofw_pci_range { + uint32_t pci_hi; + uint64_t pci; + uint64_t host; + uint64_t size; +}; + +/* + * Quirks for some adapters + */ +enum { + OFW_PCI_QUIRK_RANGES_ON_CHILDREN = 1, +}; + +struct ofw_pci_softc { + device_t sc_dev; + phandle_t sc_node; + int sc_bus; + + int sc_quirks; + + struct ofw_pci_register sc_pcir; + + struct ofw_pci_range *sc_range; + int sc_nrange; + + struct rman sc_io_rman; + struct rman sc_mem_rman; + bus_space_tag_t sc_memt; + bus_dma_tag_t sc_dmat; + + struct ofw_bus_iinfo sc_pci_iinfo; +}; + +int ofw_pci_attach(device_t dev); + +#endif // POWERPC_OFW_OFW_PCI_H + diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c index 5ecddb3b20cd..6d4bc7a000e2 100644 --- a/sys/powerpc/ofw/ofw_pcib_pci.c +++ b/sys/powerpc/ofw/ofw_pcib_pci.c @@ -56,31 +56,10 @@ static int ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, static device_method_t ofw_pcib_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ofw_pcib_pci_probe), - DEVMETHOD(device_attach, ofw_pcib_pci_attach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_read_ivar, pcib_read_ivar), - DEVMETHOD(bus_write_ivar, pcib_write_ivar), - DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(device_attach, ofw_pcib_pci_attach), /* pcib interface */ - DEVMETHOD(pcib_maxslots, pcib_maxslots), - DEVMETHOD(pcib_read_config, pcib_read_config), - DEVMETHOD(pcib_write_config, pcib_write_config), DEVMETHOD(pcib_route_interrupt, ofw_pcib_pci_route_interrupt), - DEVMETHOD(pcib_alloc_msi, pcib_alloc_msi), - DEVMETHOD(pcib_release_msi, pcib_release_msi), - DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix), - DEVMETHOD(pcib_release_msix, pcib_release_msix), - DEVMETHOD(pcib_map_msi, pcib_map_msi), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, ofw_pcib_pci_get_node), @@ -101,8 +80,8 @@ struct ofw_pcib_softc { struct ofw_bus_iinfo ops_iinfo; }; -DEFINE_CLASS_0(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods, - sizeof(struct ofw_pcib_softc)); +DEFINE_CLASS_1(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods, + sizeof(struct ofw_pcib_softc), pcib_driver); DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0); static int diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c index 059871cf9522..92e109b8b8bf 100644 --- a/sys/powerpc/ofw/ofw_syscons.c +++ b/sys/powerpc/ofw/ofw_syscons.c @@ -984,7 +984,7 @@ static driver_t ofwfb_sc_driver = { static devclass_t sc_devclass; -DRIVER_MODULE(sc, nexus, ofwfb_sc_driver, sc_devclass, 0, 0); +DRIVER_MODULE(ofwfb, nexus, ofwfb_sc_driver, sc_devclass, 0, 0); /* * Define a stub keyboard driver in case one hasn't been diff --git a/sys/powerpc/powermac/cpcht.c b/sys/powerpc/powermac/cpcht.c index 48a73eea8ad8..03d07e9b8ee2 100644 --- a/sys/powerpc/powermac/cpcht.c +++ b/sys/powerpc/powermac/cpcht.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -65,31 +66,14 @@ static int cpcht_attach(device_t); static void cpcht_configure_htbridge(device_t, phandle_t); -/* - * Bus interface. - */ -static int cpcht_read_ivar(device_t, device_t, int, - uintptr_t *); -static struct resource *cpcht_alloc_resource(device_t bus, device_t child, - int type, int *rid, u_long start, u_long end, - u_long count, u_int flags); -static int cpcht_activate_resource(device_t bus, device_t child, - int type, int rid, struct resource *res); -static int cpcht_release_resource(device_t bus, device_t child, - int type, int rid, struct resource *res); -static int cpcht_deactivate_resource(device_t bus, device_t child, - int type, int rid, struct resource *res); - /* * pcib interface. */ -static int cpcht_maxslots(device_t); static u_int32_t cpcht_read_config(device_t, u_int, u_int, u_int, u_int, int); static void cpcht_write_config(device_t, u_int, u_int, u_int, u_int, u_int32_t, int); -static int cpcht_route_interrupt(device_t bus, device_t dev, - int pin); +static int cpcht_route_interrupt(device_t, device_t, int); static int cpcht_alloc_msi(device_t dev, device_t child, int count, int maxcount, int *irqs); static int cpcht_release_msi(device_t dev, device_t child, @@ -101,12 +85,6 @@ static int cpcht_release_msix(device_t dev, device_t child, static int cpcht_map_msi(device_t dev, device_t child, int irq, uint64_t *addr, uint32_t *data); -/* - * ofw_bus interface - */ - -static phandle_t cpcht_get_node(device_t bus, device_t child); - /* * Driver methods. */ @@ -115,17 +93,7 @@ static device_method_t cpcht_methods[] = { DEVMETHOD(device_probe, cpcht_probe), DEVMETHOD(device_attach, cpcht_attach), - /* Bus interface */ - DEVMETHOD(bus_read_ivar, cpcht_read_ivar), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - DEVMETHOD(bus_alloc_resource, cpcht_alloc_resource), - DEVMETHOD(bus_release_resource, cpcht_release_resource), - DEVMETHOD(bus_activate_resource, cpcht_activate_resource), - DEVMETHOD(bus_deactivate_resource, cpcht_deactivate_resource), - /* pcib interface */ - DEVMETHOD(pcib_maxslots, cpcht_maxslots), DEVMETHOD(pcib_read_config, cpcht_read_config), DEVMETHOD(pcib_write_config, cpcht_write_config), DEVMETHOD(pcib_route_interrupt, cpcht_route_interrupt), @@ -135,9 +103,6 @@ static device_method_t cpcht_methods[] = { DEVMETHOD(pcib_release_msix, cpcht_release_msix), DEVMETHOD(pcib_map_msi, cpcht_map_msi), - /* ofw_bus interface */ - DEVMETHOD(ofw_bus_get_node, cpcht_get_node), - DEVMETHOD_END }; @@ -158,25 +123,17 @@ static struct cpcht_irq *cpcht_irqmap = NULL; uint32_t cpcht_msipic = 0; struct cpcht_softc { - device_t sc_dev; - phandle_t sc_node; + struct ofw_pci_softc pci_sc; vm_offset_t sc_data; uint64_t sc_populated_slots; - struct rman sc_mem_rman; - struct rman sc_io_rman; struct cpcht_irq htirq_map[128]; struct mtx htirq_mtx; }; -static driver_t cpcht_driver = { - "pcib", - cpcht_methods, - sizeof(struct cpcht_softc) -}; - static devclass_t cpcht_devclass; - +DEFINE_CLASS_1(pcib, cpcht_driver, cpcht_methods, sizeof(struct cpcht_softc), + ofw_pci_driver); DRIVER_MODULE(cpcht, nexus, cpcht_driver, cpcht_devclass, 0, 0); #define CPCHT_IOPORT_BASE 0xf4000000UL /* Hardwired */ @@ -186,17 +143,6 @@ DRIVER_MODULE(cpcht, nexus, cpcht_driver, cpcht_devclass, 0, 0); #define HTAPIC_TRIGGER_LEVEL 0x02 #define HTAPIC_MASK 0x01 -struct cpcht_range { - u_int32_t pci_hi; - u_int32_t pci_mid; - u_int32_t pci_lo; - u_int32_t junk; - u_int32_t host_hi; - u_int32_t host_lo; - u_int32_t size_hi; - u_int32_t size_lo; -}; - static int cpcht_probe(device_t dev) { @@ -214,7 +160,6 @@ cpcht_probe(device_t dev) if (strcmp(compatible, "u3-ht") != 0) return (ENXIO); - device_set_desc(dev, "IBM CPC9X5 HyperTransport Tunnel"); return (0); } @@ -225,7 +170,7 @@ cpcht_attach(device_t dev) struct cpcht_softc *sc; phandle_t node, child; u_int32_t reg[3]; - int i, error; + int i; node = ofw_bus_get_node(dev); sc = device_get_softc(dev); @@ -233,35 +178,21 @@ cpcht_attach(device_t dev) if (OF_getprop(node, "reg", reg, sizeof(reg)) < 12) return (ENXIO); - sc->sc_dev = dev; - sc->sc_node = node; + if (OF_getproplen(node, "ranges") <= 0) + sc->pci_sc.sc_quirks = OFW_PCI_QUIRK_RANGES_ON_CHILDREN; sc->sc_populated_slots = 0; sc->sc_data = (vm_offset_t)pmap_mapdev(reg[1], reg[2]); - sc->sc_mem_rman.rm_type = RMAN_ARRAY; - sc->sc_mem_rman.rm_descr = "CPCHT Device Memory"; - error = rman_init(&sc->sc_mem_rman); - if (error) { - device_printf(dev, "rman_init() failed. error = %d\n", error); - return (error); - } - - sc->sc_io_rman.rm_type = RMAN_ARRAY; - sc->sc_io_rman.rm_descr = "CPCHT I/O Memory"; - error = rman_init(&sc->sc_io_rman); - if (error) { - device_printf(dev, "rman_init() failed. error = %d\n", error); - return (error); - } - /* * Set up the resource manager and the HT->MPIC mapping. For cpcht, * the ranges are properties of the child bridges, and this is also * where we get the HT interrupts properties. */ +#if 0 /* I/O port mappings are usually not in the device tree */ - rman_manage_region(&sc->sc_io_rman, 0, CPCHT_IOPORT_SIZE - 1); + rman_manage_region(&sc->pci_sc.sc_io_rman, 0, CPCHT_IOPORT_SIZE - 1); +#endif bzero(sc->htirq_map, sizeof(sc->htirq_map)); mtx_init(&sc->htirq_mtx, "cpcht irq", NULL, MTX_DEF); @@ -273,9 +204,7 @@ cpcht_attach(device_t dev) /* Now make the mapping table available to the MPIC */ cpcht_irqmap = sc->htirq_map; - device_add_child(dev, "pci", device_get_unit(dev)); - - return (bus_generic_attach(dev)); + return (ofw_pci_attach(dev)); } static void @@ -283,16 +212,16 @@ cpcht_configure_htbridge(device_t dev, phandle_t child) { struct cpcht_softc *sc; struct ofw_pci_register pcir; - struct cpcht_range ranges[7], *rp; - int nranges, ptr, nextptr; + int ptr, nextptr; uint32_t vend, val; int i, nirq, irq; - u_int f, s; + u_int b, f, s; sc = device_get_softc(dev); if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) return; + b = OFW_PCI_PHYS_HI_BUS(pcir.phys_hi); s = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); f = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); @@ -302,32 +231,6 @@ cpcht_configure_htbridge(device_t dev, phandle_t child) */ sc->sc_populated_slots |= (1 << s); - /* - * Next grab this child bus's bus ranges. - */ - bzero(ranges, sizeof(ranges)); - nranges = OF_getprop(child, "ranges", ranges, sizeof(ranges)); - nranges /= sizeof(ranges[0]); - - ranges[6].pci_hi = 0; - for (rp = ranges; rp < ranges + nranges && rp->pci_hi != 0; rp++) { - switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { - case OFW_PCI_PHYS_HI_SPACE_CONFIG: - break; - case OFW_PCI_PHYS_HI_SPACE_IO: - rman_manage_region(&sc->sc_io_rman, rp->pci_lo, - rp->pci_lo + rp->size_lo - 1); - break; - case OFW_PCI_PHYS_HI_SPACE_MEM32: - rman_manage_region(&sc->sc_mem_rman, rp->pci_lo, - rp->pci_lo + rp->size_lo - 1); - break; - case OFW_PCI_PHYS_HI_SPACE_MEM64: - panic("64-bit CPCHT reserved memory!"); - break; - } - } - /* * Next build up any HT->MPIC mappings for this sub-bus. One would * naively hope that enabling, disabling, and EOIing interrupts would @@ -341,41 +244,41 @@ cpcht_configure_htbridge(device_t dev, phandle_t child) */ /* All the devices we are interested in have caps */ - if (!(PCIB_READ_CONFIG(dev, 0, s, f, PCIR_STATUS, 2) + if (!(PCIB_READ_CONFIG(dev, b, s, f, PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT)) return; - nextptr = PCIB_READ_CONFIG(dev, 0, s, f, PCIR_CAP_PTR, 1); + nextptr = PCIB_READ_CONFIG(dev, b, s, f, PCIR_CAP_PTR, 1); while (nextptr != 0) { ptr = nextptr; - nextptr = PCIB_READ_CONFIG(dev, 0, s, f, + nextptr = PCIB_READ_CONFIG(dev, b, s, f, ptr + PCICAP_NEXTPTR, 1); /* Find the HT IRQ capabilities */ - if (PCIB_READ_CONFIG(dev, 0, s, f, + if (PCIB_READ_CONFIG(dev, b, s, f, ptr + PCICAP_ID, 1) != PCIY_HT) continue; - val = PCIB_READ_CONFIG(dev, 0, s, f, ptr + PCIR_HT_COMMAND, 2); + val = PCIB_READ_CONFIG(dev, b, s, f, ptr + PCIR_HT_COMMAND, 2); if ((val & PCIM_HTCMD_CAP_MASK) != PCIM_HTCAP_INTERRUPT) continue; /* Ask for the IRQ count */ - PCIB_WRITE_CONFIG(dev, 0, s, f, ptr + PCIR_HT_COMMAND, 0x1, 1); - nirq = PCIB_READ_CONFIG(dev, 0, s, f, ptr + 4, 4); + PCIB_WRITE_CONFIG(dev, b, s, f, ptr + PCIR_HT_COMMAND, 0x1, 1); + nirq = PCIB_READ_CONFIG(dev, b, s, f, ptr + 4, 4); nirq = ((nirq >> 16) & 0xff) + 1; device_printf(dev, "%d HT IRQs on device %d.%d\n", nirq, s, f); for (i = 0; i < nirq; i++) { - PCIB_WRITE_CONFIG(dev, 0, s, f, + PCIB_WRITE_CONFIG(dev, b, s, f, ptr + PCIR_HT_COMMAND, 0x10 + (i << 1), 1); - irq = PCIB_READ_CONFIG(dev, 0, s, f, ptr + 4, 4); + irq = PCIB_READ_CONFIG(dev, b, s, f, ptr + 4, 4); /* * Mask this interrupt for now. */ - PCIB_WRITE_CONFIG(dev, 0, s, f, ptr + 4, + PCIB_WRITE_CONFIG(dev, b, s, f, ptr + 4, irq | HTAPIC_MASK, 4); irq = (irq >> 16) & 0xff; @@ -384,10 +287,10 @@ cpcht_configure_htbridge(device_t dev, phandle_t child) sc->htirq_map[irq].ht_base = sc->sc_data + (((((s & 0x1f) << 3) | (f & 0x07)) << 8) | (ptr)); - PCIB_WRITE_CONFIG(dev, 0, s, f, + PCIB_WRITE_CONFIG(dev, b, s, f, ptr + PCIR_HT_COMMAND, 0x11 + (i << 1), 1); sc->htirq_map[irq].eoi_data = - PCIB_READ_CONFIG(dev, 0, s, f, ptr + 4, 4) | + PCIB_READ_CONFIG(dev, b, s, f, ptr + 4, 4) | 0x80000000; /* @@ -395,7 +298,7 @@ cpcht_configure_htbridge(device_t dev, phandle_t child) * in how we signal EOIs. Check if this device was * made by Apple, and act accordingly. */ - vend = PCIB_READ_CONFIG(dev, 0, s, f, + vend = PCIB_READ_CONFIG(dev, b, s, f, PCIR_DEVVENDOR, 4); if ((vend & 0xffff) == 0x106b) sc->htirq_map[irq].apple_eoi = @@ -404,13 +307,6 @@ cpcht_configure_htbridge(device_t dev, phandle_t child) } } -static int -cpcht_maxslots(device_t dev) -{ - - return (PCI_SLOTMAX); -} - static u_int32_t cpcht_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) @@ -473,157 +369,12 @@ cpcht_write_config(device_t dev, u_int bus, u_int slot, u_int func, } } -static int -cpcht_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = device_get_unit(dev); - return (0); - case PCIB_IVAR_BUS: - *result = 0; /* Root bus */ - return (0); - } - - return (ENOENT); -} - -static phandle_t -cpcht_get_node(device_t bus, device_t dev) -{ - struct cpcht_softc *sc; - - sc = device_get_softc(bus); - /* We only have one child, the PCI bus, which needs our own node. */ - return (sc->sc_node); -} - static int cpcht_route_interrupt(device_t bus, device_t dev, int pin) { return (pin); } -static struct resource * -cpcht_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct cpcht_softc *sc; - struct resource *rv; - struct rman *rm; - int needactivate; - - needactivate = flags & RF_ACTIVE; - flags &= ~RF_ACTIVE; - - sc = device_get_softc(bus); - - switch (type) { - case SYS_RES_IOPORT: - end = min(end, start + count); - rm = &sc->sc_io_rman; - break; - - case SYS_RES_MEMORY: - rm = &sc->sc_mem_rman; - break; - - case SYS_RES_IRQ: - return (bus_alloc_resource(bus, type, rid, start, end, count, - flags)); - - default: - device_printf(bus, "unknown resource request from %s\n", - device_get_nameunit(child)); - return (NULL); - } - - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == NULL) { - device_printf(bus, "failed to reserve resource for %s\n", - device_get_nameunit(child)); - return (NULL); - } - - rman_set_rid(rv, *rid); - - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv) != 0) { - device_printf(bus, - "failed to activate resource for %s\n", - device_get_nameunit(child)); - rman_release_resource(rv); - return (NULL); - } - } - - return (rv); -} - -static int -cpcht_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - void *p; - - if (type == SYS_RES_IRQ) - return (bus_activate_resource(bus, type, rid, res)); - - if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { - vm_offset_t start; - - start = (vm_offset_t)rman_get_start(res); - - if (type == SYS_RES_IOPORT) - start += CPCHT_IOPORT_BASE; - - if (bootverbose) - printf("cpcht mapdev: start %zx, len %ld\n", start, - rman_get_size(res)); - - p = pmap_mapdev(start, (vm_size_t)rman_get_size(res)); - if (p == NULL) - return (ENOMEM); - rman_set_virtual(res, p); - rman_set_bustag(res, &bs_le_tag); - rman_set_bushandle(res, (u_long)p); - } - - return (rman_activate_resource(res)); -} - -static int -cpcht_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - - if (rman_get_flags(res) & RF_ACTIVE) { - int error = bus_deactivate_resource(child, type, rid, res); - if (error) - return error; - } - - return (rman_release_resource(res)); -} - -static int -cpcht_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - - /* - * If this is a memory resource, unmap it. - */ - if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { - u_int32_t psize; - - psize = rman_get_size(res); - pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); - } - - return (rman_deactivate_resource(res)); -} - static int cpcht_alloc_msi(device_t dev, device_t child, int count, int maxcount, int *irqs) diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c index 55610cf87eae..ddb7f702e608 100644 --- a/sys/powerpc/powermac/grackle.c +++ b/sys/powerpc/powermac/grackle.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include @@ -66,37 +67,13 @@ int badaddr(void *, size_t); /* XXX */ static int grackle_probe(device_t); static int grackle_attach(device_t); -/* - * Bus interface. - */ -static int grackle_read_ivar(device_t, device_t, int, - uintptr_t *); -static struct resource * grackle_alloc_resource(device_t bus, - device_t child, int type, int *rid, u_long start, - u_long end, u_long count, u_int flags); -static int grackle_release_resource(device_t bus, device_t child, - int type, int rid, struct resource *res); -static int grackle_activate_resource(device_t bus, device_t child, - int type, int rid, struct resource *res); -static int grackle_deactivate_resource(device_t bus, - device_t child, int type, int rid, - struct resource *res); - - /* * pcib interface. */ -static int grackle_maxslots(device_t); static u_int32_t grackle_read_config(device_t, u_int, u_int, u_int, u_int, int); static void grackle_write_config(device_t, u_int, u_int, u_int, u_int, u_int32_t, int); -static int grackle_route_interrupt(device_t, device_t, int); - -/* - * ofw_bus interface - */ -static phandle_t grackle_get_node(device_t bus, device_t dev); /* * Local routines. @@ -113,35 +90,16 @@ static device_method_t grackle_methods[] = { DEVMETHOD(device_probe, grackle_probe), DEVMETHOD(device_attach, grackle_attach), - /* Bus interface */ - DEVMETHOD(bus_read_ivar, grackle_read_ivar), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - DEVMETHOD(bus_alloc_resource, grackle_alloc_resource), - DEVMETHOD(bus_release_resource, grackle_release_resource), - DEVMETHOD(bus_activate_resource, grackle_activate_resource), - DEVMETHOD(bus_deactivate_resource, grackle_deactivate_resource), - /* pcib interface */ - DEVMETHOD(pcib_maxslots, grackle_maxslots), DEVMETHOD(pcib_read_config, grackle_read_config), DEVMETHOD(pcib_write_config, grackle_write_config), - DEVMETHOD(pcib_route_interrupt, grackle_route_interrupt), - - /* ofw_bus interface */ - DEVMETHOD(ofw_bus_get_node, grackle_get_node), DEVMETHOD_END }; -static driver_t grackle_driver = { - "pcib", - grackle_methods, - sizeof(struct grackle_softc) -}; - static devclass_t grackle_devclass; - +DEFINE_CLASS_1(pcib, grackle_driver, grackle_methods, + sizeof(struct grackle_softc), ofw_pci_driver); DRIVER_MODULE(grackle, nexus, grackle_driver, grackle_devclass, 0, 0); static int @@ -166,21 +124,9 @@ static int grackle_attach(device_t dev) { struct grackle_softc *sc; - phandle_t node; - u_int32_t busrange[2]; - struct grackle_range *rp, *io, *mem[2]; - int nmem, i, error; - node = ofw_bus_get_node(dev); sc = device_get_softc(dev); - if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8) - return (ENXIO); - - sc->sc_dev = dev; - sc->sc_node = node; - sc->sc_bus = busrange[0]; - /* * The Grackle PCI config addr/data registers are actually in * PCI space, but since they are needed to actually probe the @@ -190,83 +136,7 @@ grackle_attach(device_t dev) sc->sc_addr = (vm_offset_t)pmap_mapdev(GRACKLE_ADDR, PAGE_SIZE); sc->sc_data = (vm_offset_t)pmap_mapdev(GRACKLE_DATA, PAGE_SIZE); - bzero(sc->sc_range, sizeof(sc->sc_range)); - sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range, - sizeof(sc->sc_range)); - - if (sc->sc_nrange == -1) { - device_printf(dev, "could not get ranges\n"); - return (ENXIO); - } - - sc->sc_nrange /= sizeof(sc->sc_range[0]); - - sc->sc_range[6].pci_hi = 0; - io = NULL; - nmem = 0; - - for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && - rp->pci_hi != 0; rp++) { - switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { - case OFW_PCI_PHYS_HI_SPACE_CONFIG: - break; - case OFW_PCI_PHYS_HI_SPACE_IO: - io = rp; - break; - case OFW_PCI_PHYS_HI_SPACE_MEM32: - mem[nmem] = rp; - nmem++; - break; - case OFW_PCI_PHYS_HI_SPACE_MEM64: - break; - } - } - - if (io == NULL) { - device_printf(dev, "can't find io range\n"); - return (ENXIO); - } - sc->sc_io_rman.rm_type = RMAN_ARRAY; - sc->sc_io_rman.rm_descr = "Grackle PCI I/O Ports"; - sc->sc_iostart = io->pci_iospace; - if (rman_init(&sc->sc_io_rman) != 0 || - rman_manage_region(&sc->sc_io_rman, io->pci_lo, - io->pci_lo + io->size_lo) != 0) { - panic("grackle_attach: failed to set up I/O rman"); - } - - if (nmem == 0) { - device_printf(dev, "can't find mem ranges\n"); - return (ENXIO); - } - sc->sc_mem_rman.rm_type = RMAN_ARRAY; - sc->sc_mem_rman.rm_descr = "Grackle PCI Memory"; - error = rman_init(&sc->sc_mem_rman); - if (error) { - device_printf(dev, "rman_init() failed. error = %d\n", error); - return (error); - } - for (i = 0; i < nmem; i++) { - error = rman_manage_region(&sc->sc_mem_rman, mem[i]->pci_lo, - mem[i]->pci_lo + mem[i]->size_lo); - if (error) { - device_printf(dev, - "rman_manage_region() failed. error = %d\n", error); - return (error); - } - } - - ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); - - device_add_child(dev, "pci", device_get_unit(dev)); - return (bus_generic_attach(dev)); -} - -static int -grackle_maxslots(device_t dev) -{ - - return (PCI_SLOTMAX); + return (ofw_pci_attach(dev)); } static u_int32_t @@ -339,175 +209,6 @@ grackle_write_config(device_t dev, u_int bus, u_int slot, u_int func, grackle_disable_config(sc); } -static int -grackle_route_interrupt(device_t bus, device_t dev, int pin) -{ - struct grackle_softc *sc; - struct ofw_pci_register reg; - uint32_t pintr, mintr; - phandle_t iparent; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; - - sc = device_get_softc(bus); - pintr = pin; - if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, - sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - &iparent, maskbuf)) - return (MAP_IRQ(iparent, mintr)); - - /* Maybe it's a real interrupt, not an intpin */ - if (pin > 4) - return (pin); - - device_printf(bus, "could not route pin %d for device %d.%d\n", - pin, pci_get_slot(dev), pci_get_function(dev)); - return (PCI_INVALID_IRQ); -} - -static int -grackle_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct grackle_softc *sc; - - sc = device_get_softc(dev); - - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = 0; - return (0); - case PCIB_IVAR_BUS: - *result = sc->sc_bus; - return (0); - } - - return (ENOENT); -} - -static struct resource * -grackle_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct grackle_softc *sc; - struct resource *rv; - struct rman *rm; - int needactivate; - - needactivate = flags & RF_ACTIVE; - flags &= ~RF_ACTIVE; - - sc = device_get_softc(bus); - - switch (type) { - case SYS_RES_MEMORY: - rm = &sc->sc_mem_rman; - break; - - case SYS_RES_IOPORT: - rm = &sc->sc_io_rman; - break; - - case SYS_RES_IRQ: - return (bus_alloc_resource(bus, type, rid, start, end, count, - flags)); - - default: - device_printf(bus, "unknown resource request from %s\n", - device_get_nameunit(child)); - return (NULL); - } - - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == NULL) { - device_printf(bus, "failed to reserve resource for %s\n", - device_get_nameunit(child)); - return (NULL); - } - - rman_set_rid(rv, *rid); - - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv) != 0) { - device_printf(bus, - "failed to activate resource for %s\n", - device_get_nameunit(child)); - rman_release_resource(rv); - return (NULL); - } - } - - return (rv); -} - -static int -grackle_release_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - if (rman_get_flags(res) & RF_ACTIVE) { - int error = bus_deactivate_resource(child, type, rid, res); - if (error) - return error; - } - - return (rman_release_resource(res)); -} - -static int -grackle_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - struct grackle_softc *sc; - void *p; - - sc = device_get_softc(bus); - - if (type == SYS_RES_IRQ) { - return (bus_activate_resource(bus, type, rid, res)); - } - if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { - vm_offset_t start; - - start = (vm_offset_t)rman_get_start(res); - /* - * For i/o-ports, convert the start address to the - * MPC106 PCI i/o window - */ - if (type == SYS_RES_IOPORT) - start += sc->sc_iostart; - - if (bootverbose) - printf("grackle mapdev: start %zx, len %ld\n", start, - rman_get_size(res)); - - p = pmap_mapdev(start, (vm_size_t)rman_get_size(res)); - if (p == NULL) - return (ENOMEM); - - rman_set_virtual(res, p); - rman_set_bustag(res, &bs_le_tag); - rman_set_bushandle(res, (u_long)p); - } - - return (rman_activate_resource(res)); -} - -static int -grackle_deactivate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - /* - * If this is a memory resource, unmap it. - */ - if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { - u_int32_t psize; - - psize = rman_get_size(res); - pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); - } - - return (rman_deactivate_resource(res)); -} - - static int grackle_enable_config(struct grackle_softc *sc, u_int bus, u_int slot, u_int func, u_int reg) @@ -537,17 +238,6 @@ grackle_disable_config(struct grackle_softc *sc) out32rb(sc->sc_addr, 0); } -static phandle_t -grackle_get_node(device_t bus, device_t dev) -{ - struct grackle_softc *sc; - - sc = device_get_softc(bus); - /* We only have one child, the PCI bus, which needs our own node. */ - - return sc->sc_node; -} - /* * Driver to swallow Grackle host bridges from the PCI bus side. */ diff --git a/sys/powerpc/powermac/gracklevar.h b/sys/powerpc/powermac/gracklevar.h index bc8b664f3cb1..184f7e95c62d 100644 --- a/sys/powerpc/powermac/gracklevar.h +++ b/sys/powerpc/powermac/gracklevar.h @@ -30,30 +30,10 @@ #ifndef _POWERPC_POWERMAC_GRACKLEVAR_H_ #define _POWERPC_POWERMAC_GRACKLEVAR_H_ -struct grackle_range { - u_int32_t pci_hi; - u_int32_t pci_mid; - u_int32_t pci_lo; - u_int32_t pci_iospace; - u_int32_t size_hi; - u_int32_t size_lo; -}; - struct grackle_softc { - device_t sc_dev; - phandle_t sc_node; + struct ofw_pci_softc pci_sc; vm_offset_t sc_addr; vm_offset_t sc_data; - int sc_bus; - struct grackle_range sc_range[7]; - int sc_nrange; - int sc_iostart; - struct rman sc_io_rman; - struct rman sc_mem_rman; - bus_space_tag_t sc_memt; - bus_dma_tag_t sc_dmat; - - struct ofw_bus_iinfo sc_pci_iinfo; }; /* diff --git a/sys/powerpc/powermac/smusat.c b/sys/powerpc/powermac/smusat.c index 974e98c54144..2e37ae418add 100644 --- a/sys/powerpc/powermac/smusat.c +++ b/sys/powerpc/powermac/smusat.c @@ -202,33 +202,46 @@ static int smusat_updatecache(device_t dev) { uint8_t reg = 0x3f; + uint8_t value[16]; struct smusat_softc *sc = device_get_softc(dev); + int error; struct iic_msg msgs[2] = { {0, IIC_M_WR | IIC_M_NOSTOP, 1, ®}, - {0, IIC_M_RD, 16, sc->sc_cache}, + {0, IIC_M_RD, 16, value}, }; msgs[0].slave = msgs[1].slave = iicbus_get_addr(dev); - sc->sc_last_update = time_uptime; + error = iicbus_transfer(dev, msgs, 2); + if (error) + return (error); - return (iicbus_transfer(dev, msgs, 2)); + sc->sc_last_update = time_uptime; + memcpy(sc->sc_cache, value, sizeof(value)); + return (0); } static int smusat_sensor_read(struct smu_sensor *sens) { - int value; + int value, error; device_t dev; struct smusat_softc *sc; dev = sens->dev; sc = device_get_softc(dev); + error = 0; if (time_uptime - sc->sc_last_update > 1) - smusat_updatecache(dev); + error = smusat_updatecache(dev); + if (error) + return (-error); value = (sc->sc_cache[sens->reg*2] << 8) + sc->sc_cache[sens->reg*2 + 1]; + if (value == 0xffff) { + sc->sc_last_update = 0; /* Result was bad, don't cache */ + return (-EINVAL); + } switch (sens->type) { case SMU_TEMP_SENSOR: diff --git a/sys/powerpc/powermac/uninorthpci.c b/sys/powerpc/powermac/uninorthpci.c index 2add0489036c..f55fb726429a 100644 --- a/sys/powerpc/powermac/uninorthpci.c +++ b/sys/powerpc/powermac/uninorthpci.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include @@ -64,32 +65,13 @@ __FBSDID("$FreeBSD$"); static int uninorth_probe(device_t); static int uninorth_attach(device_t); -/* - * Bus interface. - */ -static int uninorth_read_ivar(device_t, device_t, int, - uintptr_t *); -static struct resource * uninorth_alloc_resource(device_t bus, - device_t child, int type, int *rid, u_long start, - u_long end, u_long count, u_int flags); -static int uninorth_activate_resource(device_t bus, device_t child, - int type, int rid, struct resource *res); - /* * pcib interface. */ -static int uninorth_maxslots(device_t); static u_int32_t uninorth_read_config(device_t, u_int, u_int, u_int, u_int, int); static void uninorth_write_config(device_t, u_int, u_int, u_int, u_int, u_int32_t, int); -static int uninorth_route_interrupt(device_t, device_t, int); - -/* - * OFW Bus interface - */ - -static phandle_t uninorth_get_node(device_t bus, device_t dev); /* * Local routines. @@ -105,33 +87,17 @@ static device_method_t uninorth_methods[] = { DEVMETHOD(device_probe, uninorth_probe), DEVMETHOD(device_attach, uninorth_attach), - /* Bus interface */ - DEVMETHOD(bus_read_ivar, uninorth_read_ivar), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - DEVMETHOD(bus_alloc_resource, uninorth_alloc_resource), - DEVMETHOD(bus_activate_resource, uninorth_activate_resource), - /* pcib interface */ - DEVMETHOD(pcib_maxslots, uninorth_maxslots), DEVMETHOD(pcib_read_config, uninorth_read_config), DEVMETHOD(pcib_write_config, uninorth_write_config), - DEVMETHOD(pcib_route_interrupt, uninorth_route_interrupt), - - /* ofw_bus interface */ - DEVMETHOD(ofw_bus_get_node, uninorth_get_node), DEVMETHOD_END }; -static driver_t uninorth_driver = { - "pcib", - uninorth_methods, - sizeof(struct uninorth_softc) -}; - static devclass_t uninorth_devclass; +DEFINE_CLASS_1(pcib, uninorth_driver, uninorth_methods, + sizeof(struct uninorth_softc), ofw_pci_driver); DRIVER_MODULE(uninorth, nexus, uninorth_driver, uninorth_devclass, 0, 0); static int @@ -168,9 +134,7 @@ uninorth_attach(device_t dev) struct uninorth_softc *sc; const char *compatible; phandle_t node; - u_int32_t reg[3], busrange[2]; - struct uninorth_range *rp, *io, *mem[2]; - int nmem, i, error; + u_int32_t reg[3]; node = ofw_bus_get_node(dev); sc = device_get_softc(dev); @@ -178,9 +142,6 @@ uninorth_attach(device_t dev) if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8) return (ENXIO); - if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8) - return (ENXIO); - sc->sc_ver = 0; compatible = ofw_bus_get_compat(dev); if (strcmp(compatible, "u3-agp") == 0) @@ -188,8 +149,6 @@ uninorth_attach(device_t dev) if (strcmp(compatible, "u4-pcie") == 0) sc->sc_ver = 4; - sc->sc_dev = dev; - sc->sc_node = node; if (sc->sc_ver >= 3) { sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[1] + 0x800000, PAGE_SIZE); sc->sc_data = (vm_offset_t)pmap_mapdev(reg[1] + 0xc00000, PAGE_SIZE); @@ -197,108 +156,8 @@ uninorth_attach(device_t dev) sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[0] + 0x800000, PAGE_SIZE); sc->sc_data = (vm_offset_t)pmap_mapdev(reg[0] + 0xc00000, PAGE_SIZE); } - sc->sc_bus = busrange[0]; - bzero(sc->sc_range, sizeof(sc->sc_range)); - if (sc->sc_ver >= 3) { - /* - * On Apple U3 systems, we have an otherwise standard - * Uninorth controller driving AGP. The one difference - * is that it uses a new PCI ranges format, so do the - * translation. - */ - - struct uninorth_range64 range64[6]; - bzero(range64, sizeof(range64)); - - sc->sc_nrange = OF_getprop(node, "ranges", range64, - sizeof(range64)); - for (i = 0; range64[i].pci_hi != 0; i++) { - sc->sc_range[i].pci_hi = range64[i].pci_hi; - sc->sc_range[i].pci_mid = range64[i].pci_mid; - sc->sc_range[i].pci_lo = range64[i].pci_lo; - sc->sc_range[i].host = range64[i].host_lo; - sc->sc_range[i].size_hi = range64[i].size_hi; - sc->sc_range[i].size_lo = range64[i].size_lo; - } - } else { - sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range, - sizeof(sc->sc_range)); - } - - if (sc->sc_nrange == -1) { - device_printf(dev, "could not get ranges\n"); - return (ENXIO); - } - - sc->sc_nrange /= sizeof(sc->sc_range[0]); - - sc->sc_range[6].pci_hi = 0; - io = NULL; - nmem = 0; - - for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange && - rp->pci_hi != 0; rp++) { - switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { - case OFW_PCI_PHYS_HI_SPACE_CONFIG: - break; - case OFW_PCI_PHYS_HI_SPACE_IO: - io = rp; - break; - case OFW_PCI_PHYS_HI_SPACE_MEM32: - mem[nmem] = rp; - nmem++; - break; - case OFW_PCI_PHYS_HI_SPACE_MEM64: - break; - } - } - - if (io == NULL) { - device_printf(dev, "can't find io range\n"); - return (ENXIO); - } - sc->sc_io_rman.rm_type = RMAN_ARRAY; - sc->sc_io_rman.rm_descr = "UniNorth PCI I/O Ports"; - sc->sc_iostart = io->host; - if (rman_init(&sc->sc_io_rman) != 0 || - rman_manage_region(&sc->sc_io_rman, io->pci_lo, - io->pci_lo + io->size_lo - 1) != 0) { - panic("uninorth_attach: failed to set up I/O rman"); - } - - if (nmem == 0) { - device_printf(dev, "can't find mem ranges\n"); - return (ENXIO); - } - sc->sc_mem_rman.rm_type = RMAN_ARRAY; - sc->sc_mem_rman.rm_descr = "UniNorth PCI Memory"; - error = rman_init(&sc->sc_mem_rman); - if (error) { - device_printf(dev, "rman_init() failed. error = %d\n", error); - return (error); - } - for (i = 0; i < nmem; i++) { - error = rman_manage_region(&sc->sc_mem_rman, mem[i]->pci_lo, - mem[i]->pci_lo + mem[i]->size_lo - 1); - if (error) { - device_printf(dev, - "rman_manage_region() failed. error = %d\n", error); - return (error); - } - } - - ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t)); - - device_add_child(dev, "pci", device_get_unit(dev)); - return (bus_generic_attach(dev)); -} - -static int -uninorth_maxslots(device_t dev) -{ - - return (PCI_SLOTMAX); + return (ofw_pci_attach(dev)); } static u_int32_t @@ -353,143 +212,6 @@ uninorth_write_config(device_t dev, u_int bus, u_int slot, u_int func, } } -static int -uninorth_route_interrupt(device_t bus, device_t dev, int pin) -{ - struct uninorth_softc *sc; - struct ofw_pci_register reg; - uint32_t pintr, mintr; - phandle_t iparent; - uint8_t maskbuf[sizeof(reg) + sizeof(pintr)]; - - sc = device_get_softc(bus); - pintr = pin; - if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, - sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - &iparent, maskbuf)) - return (MAP_IRQ(iparent, mintr)); - - /* Maybe it's a real interrupt, not an intpin */ - if (pin > 4) - return (pin); - - device_printf(bus, "could not route pin %d for device %d.%d\n", - pin, pci_get_slot(dev), pci_get_function(dev)); - return (PCI_INVALID_IRQ); -} - -static int -uninorth_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) -{ - struct uninorth_softc *sc; - - sc = device_get_softc(dev); - - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = device_get_unit(dev); - return (0); - case PCIB_IVAR_BUS: - *result = sc->sc_bus; - return (0); - } - - return (ENOENT); -} - -static struct resource * -uninorth_alloc_resource(device_t bus, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - struct uninorth_softc *sc; - struct resource *rv; - struct rman *rm; - int needactivate; - - needactivate = flags & RF_ACTIVE; - flags &= ~RF_ACTIVE; - - sc = device_get_softc(bus); - - switch (type) { - case SYS_RES_MEMORY: - rm = &sc->sc_mem_rman; - break; - - case SYS_RES_IOPORT: - rm = &sc->sc_io_rman; - break; - - case SYS_RES_IRQ: - return (bus_alloc_resource(bus, type, rid, start, end, count, - flags)); - - default: - device_printf(bus, "unknown resource request from %s\n", - device_get_nameunit(child)); - return (NULL); - } - - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv == NULL) { - device_printf(bus, "failed to reserve resource for %s\n", - device_get_nameunit(child)); - return (NULL); - } - - rman_set_rid(rv, *rid); - - if (needactivate) { - if (bus_activate_resource(child, type, *rid, rv) != 0) { - device_printf(bus, - "failed to activate resource for %s\n", - device_get_nameunit(child)); - rman_release_resource(rv); - return (NULL); - } - } - - return (rv); -} - -static int -uninorth_activate_resource(device_t bus, device_t child, int type, int rid, - struct resource *res) -{ - void *p; - struct uninorth_softc *sc; - - sc = device_get_softc(bus); - - if (type == SYS_RES_IRQ) - return (bus_activate_resource(bus, type, rid, res)); - - if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { - vm_offset_t start; - - start = (vm_offset_t)rman_get_start(res); - /* - * For i/o-ports, convert the start address to the - * uninorth PCI i/o window - */ - if (type == SYS_RES_IOPORT) - start += sc->sc_iostart; - - if (bootverbose) - printf("uninorth mapdev: start %zx, len %ld\n", start, - rman_get_size(res)); - - p = pmap_mapdev(start, (vm_size_t)rman_get_size(res)); - if (p == NULL) - return (ENOMEM); - rman_set_virtual(res, p); - rman_set_bustag(res, &bs_le_tag); - rman_set_bushandle(res, (u_long)p); - } - - return (rman_activate_resource(res)); -} - static int uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot, u_int func, u_int reg) @@ -497,8 +219,8 @@ uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot, uint32_t cfgval; uint32_t pass; - if (resource_int_value(device_get_name(sc->sc_dev), - device_get_unit(sc->sc_dev), "skipslot", &pass) == 0) { + if (resource_int_value(device_get_name(sc->pci_sc.sc_dev), + device_get_unit(sc->pci_sc.sc_dev), "skipslot", &pass) == 0) { if (pass == slot) return (0); } @@ -510,7 +232,7 @@ uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot, * PCI Express <-> PCI Express bridge not present in the device tree, * and we need to route all of our configuration space through it. */ - if (sc->sc_bus == bus && sc->sc_ver < 4) { + if (sc->pci_sc.sc_bus == bus && sc->sc_ver < 4) { /* * No slots less than 11 on the primary bus on U3 and lower */ @@ -534,14 +256,3 @@ uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot, return (1); } -static phandle_t -uninorth_get_node(device_t bus, device_t dev) -{ - struct uninorth_softc *sc; - - sc = device_get_softc(bus); - /* We only have one child, the PCI bus, which needs our own node. */ - - return sc->sc_node; -} - diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h index 2c37d770ed4d..43aa01d0e004 100644 --- a/sys/powerpc/powermac/uninorthvar.h +++ b/sys/powerpc/powermac/uninorthvar.h @@ -28,41 +28,12 @@ #ifndef _POWERPC_POWERMAC_UNINORTHVAR_H_ #define _POWERPC_POWERMAC_UNINORTHVAR_H_ -struct uninorth_range { - u_int32_t pci_hi; - u_int32_t pci_mid; - u_int32_t pci_lo; - u_int32_t host; - u_int32_t size_hi; - u_int32_t size_lo; -}; - -struct uninorth_range64 { - u_int32_t pci_hi; - u_int32_t pci_mid; - u_int32_t pci_lo; - u_int32_t host_hi; - u_int32_t host_lo; - u_int32_t size_hi; - u_int32_t size_lo; -}; +#include struct uninorth_softc { - device_t sc_dev; - phandle_t sc_node; + struct ofw_pci_softc pci_sc; vm_offset_t sc_addr; vm_offset_t sc_data; - int sc_bus; - struct uninorth_range sc_range[7]; - int sc_nrange; - int sc_iostart; - struct rman sc_io_rman; - struct rman sc_mem_rman; - bus_space_tag_t sc_iot; - bus_space_tag_t sc_memt; - bus_dma_tag_t sc_dmat; - struct ofw_bus_iinfo sc_pci_iinfo; - int sc_ver; }; diff --git a/sys/powerpc/ps3/ps3_syscons.c b/sys/powerpc/ps3/ps3_syscons.c index c53c275b118e..2b6e18201393 100644 --- a/sys/powerpc/ps3/ps3_syscons.c +++ b/sys/powerpc/ps3/ps3_syscons.c @@ -749,7 +749,7 @@ static driver_t ps3fb_sc_driver = { static devclass_t sc_devclass; -DRIVER_MODULE(sc, nexus, ps3fb_sc_driver, sc_devclass, 0, 0); +DRIVER_MODULE(ps3fb, nexus, ps3fb_sc_driver, sc_devclass, 0, 0); /* * Define a stub keyboard driver in case one hasn't been diff --git a/sys/security/mac_biba/mac_biba.c b/sys/security/mac_biba/mac_biba.c index 3f24ff824bef..aa37fc79fa37 100644 --- a/sys/security/mac_biba/mac_biba.c +++ b/sys/security/mac_biba/mac_biba.c @@ -948,18 +948,20 @@ biba_devfs_create_device(struct ucred *cred, struct mount *mp, struct cdev *dev, struct devfs_dirent *de, struct label *delabel) { struct mac_biba *mb; + const char *dn; int biba_type; mb = SLOT(delabel); - if (strcmp(dev->si_name, "null") == 0 || - strcmp(dev->si_name, "zero") == 0 || - strcmp(dev->si_name, "random") == 0 || - strncmp(dev->si_name, "fd/", strlen("fd/")) == 0) + dn = devtoname(dev); + if (strcmp(dn, "null") == 0 || + strcmp(dn, "zero") == 0 || + strcmp(dn, "random") == 0 || + strncmp(dn, "fd/", strlen("fd/")) == 0) biba_type = MAC_BIBA_TYPE_EQUAL; else if (ptys_equal && - (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || - strncmp(dev->si_name, "pts/", strlen("pts/")) == 0 || - strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) + (strncmp(dn, "ttyp", strlen("ttyp")) == 0 || + strncmp(dn, "pts/", strlen("pts/")) == 0 || + strncmp(dn, "ptyp", strlen("ptyp")) == 0)) biba_type = MAC_BIBA_TYPE_EQUAL; else biba_type = MAC_BIBA_TYPE_HIGH; diff --git a/sys/security/mac_lomac/mac_lomac.c b/sys/security/mac_lomac/mac_lomac.c index 8dc92e4e6ff5..40c9c2f88728 100644 --- a/sys/security/mac_lomac/mac_lomac.c +++ b/sys/security/mac_lomac/mac_lomac.c @@ -1032,19 +1032,21 @@ lomac_devfs_create_device(struct ucred *cred, struct mount *mp, struct cdev *dev, struct devfs_dirent *de, struct label *delabel) { struct mac_lomac *ml; + const char *dn; int lomac_type; ml = SLOT(delabel); - if (strcmp(dev->si_name, "null") == 0 || - strcmp(dev->si_name, "zero") == 0 || - strcmp(dev->si_name, "random") == 0 || - strncmp(dev->si_name, "fd/", strlen("fd/")) == 0 || - strncmp(dev->si_name, "ttyv", strlen("ttyv")) == 0) + dn = devtoname(dev); + if (strcmp(dn, "null") == 0 || + strcmp(dn, "zero") == 0 || + strcmp(dn, "random") == 0 || + strncmp(dn, "fd/", strlen("fd/")) == 0 || + strncmp(dn, "ttyv", strlen("ttyv")) == 0) lomac_type = MAC_LOMAC_TYPE_EQUAL; else if (ptys_equal && - (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || - strncmp(dev->si_name, "pts/", strlen("pts/")) == 0 || - strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) + (strncmp(dn, "ttyp", strlen("ttyp")) == 0 || + strncmp(dn, "pts/", strlen("pts/")) == 0 || + strncmp(dn, "ptyp", strlen("ptyp")) == 0)) lomac_type = MAC_LOMAC_TYPE_EQUAL; else lomac_type = MAC_LOMAC_TYPE_HIGH; diff --git a/sys/security/mac_mls/mac_mls.c b/sys/security/mac_mls/mac_mls.c index 8019469d54a7..8ffa76b597f3 100644 --- a/sys/security/mac_mls/mac_mls.c +++ b/sys/security/mac_mls/mac_mls.c @@ -908,21 +908,23 @@ mls_devfs_create_device(struct ucred *cred, struct mount *mp, struct cdev *dev, struct devfs_dirent *de, struct label *delabel) { struct mac_mls *mm; + const char *dn; int mls_type; mm = SLOT(delabel); - if (strcmp(dev->si_name, "null") == 0 || - strcmp(dev->si_name, "zero") == 0 || - strcmp(dev->si_name, "random") == 0 || - strncmp(dev->si_name, "fd/", strlen("fd/")) == 0) + dn = devtoname(dev); + if (strcmp(dn, "null") == 0 || + strcmp(dn, "zero") == 0 || + strcmp(dn, "random") == 0 || + strncmp(dn, "fd/", strlen("fd/")) == 0) mls_type = MAC_MLS_TYPE_EQUAL; - else if (strcmp(dev->si_name, "kmem") == 0 || - strcmp(dev->si_name, "mem") == 0) + else if (strcmp(dn, "kmem") == 0 || + strcmp(dn, "mem") == 0) mls_type = MAC_MLS_TYPE_HIGH; else if (ptys_equal && - (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || - strncmp(dev->si_name, "pts/", strlen("pts/")) == 0 || - strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) + (strncmp(dn, "ttyp", strlen("ttyp")) == 0 || + strncmp(dn, "pts/", strlen("pts/")) == 0 || + strncmp(dn, "ptyp", strlen("ptyp")) == 0)) mls_type = MAC_MLS_TYPE_EQUAL; else mls_type = MAC_MLS_TYPE_LOW; diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 7dfa82eff23c..0a12124f54f7 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -78,7 +78,7 @@ struct cdev { LIST_HEAD(, cdev) si_children; LIST_ENTRY(cdev) si_siblings; struct cdev *si_parent; - char *si_name; + void *si_spare0; void *si_drv1, *si_drv2; struct cdevsw *si_devsw; int si_iosize_max; /* maximum I/O size (for physio &al) */ @@ -87,7 +87,7 @@ struct cdev { union { struct snapdata *__sid_snapdata; } __si_u; - char __si_namebuf[SPECNAMELEN + 1]; + char si_name[SPECNAMELEN + 1]; }; #define si_snapdata __si_u.__sid_snapdata diff --git a/sys/sys/diskmbr.h b/sys/sys/diskmbr.h index 0caf0d773e85..dcb39185ba1a 100644 --- a/sys/sys/diskmbr.h +++ b/sys/sys/diskmbr.h @@ -49,6 +49,7 @@ #define DOSPTYP_FAT32 0x0b /* FAT32 partition */ #define DOSPTYP_EXTLBA 0x0f /* DOS extended partition */ #define DOSPTYP_PPCBOOT 0x41 /* PReP/CHRP boot partition */ +#define DOSPTYP_LDM 0x42 /* Win2k dynamic extended partition */ #define DOSPTYP_386BSD 0xa5 /* 386BSD partition type */ #define DOSPTYP_LINSWP 0x82 /* Linux swap partition */ #define DOSPTYP_LINUX 0x83 /* Linux partition */ diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 12d79ca6de27..916fad5f0053 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -633,6 +633,10 @@ typedef struct { #define R_ARM_THM_SWI8 14 #define R_ARM_XPC25 15 #define R_ARM_THM_XPC22 16 +/* TLS relocations */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ #define R_ARM_COPY 20 /* Copy data from shared object. */ #define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ #define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ diff --git a/sys/sys/jail.h b/sys/sys/jail.h index bbaf38162e7c..565efa86dccd 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -176,7 +176,8 @@ struct prison { unsigned pr_allow; /* (p) PR_ALLOW_* flags */ int pr_securelevel; /* (p) securelevel */ int pr_enforce_statfs; /* (p) statfs permission */ - int pr_spare[5]; + int pr_devfs_rsnum; /* (p) devfs ruleset */ + int pr_spare[4]; unsigned long pr_hostid; /* (p) jail hostid */ char pr_name[MAXHOSTNAMELEN]; /* (p) admin jail name */ char pr_path[MAXPATHLEN]; /* (c) chroot path */ diff --git a/sys/sys/msgbuf.h b/sys/sys/msgbuf.h index ed7d49540f36..0e25a1e34bd9 100644 --- a/sys/sys/msgbuf.h +++ b/sys/sys/msgbuf.h @@ -46,7 +46,9 @@ struct msgbuf { u_int msg_cksum; /* checksum of contents */ u_int msg_seqmod; /* range for sequence numbers */ int msg_lastpri; /* saved priority value */ - int msg_needsnl; /* set when newline needed */ + u_int msg_flags; +#define MSGBUF_NEEDNL 0x01 /* set when newline needed */ +#define MSGBUF_NEXT_NEW_LINE 0x02 struct mtx msg_lock; /* mutex to protect the buffer */ }; diff --git a/sys/sys/param.h b/sys/sys/param.h index 35bca559e79e..bebec506e6f0 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1000006 /* Master, propagated to newvers */ +#define __FreeBSD_version 1000008 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 76f33553cbee..0245e88f9019 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -384,6 +384,7 @@ do { \ process */ #define TDB_STOPATFORK 0x00000080 /* Stop at the return from fork (child only) */ +#define TDB_CHILD 0x00000100 /* New child indicator for ptrace() */ /* * "Private" flags kept in td_pflags: @@ -400,7 +401,7 @@ do { \ #define TDP_NOSLEEPING 0x00000100 /* Thread is not allowed to sleep on a sq. */ #define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */ #define TDP_ITHREAD 0x00000400 /* Thread is an interrupt thread. */ -#define TDP_UNUSED800 0x00000800 /* available. */ +#define TDP_SYNCIO 0x00000800 /* Local override, disable async i/o. */ #define TDP_SCHED1 0x00001000 /* Reserved for scheduler private use */ #define TDP_SCHED2 0x00002000 /* Reserved for scheduler private use */ #define TDP_SCHED3 0x00004000 /* Reserved for scheduler private use */ diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h index 2583d59466d0..e770a0612eac 100644 --- a/sys/sys/ptrace.h +++ b/sys/sys/ptrace.h @@ -107,6 +107,7 @@ struct ptrace_lwpinfo { #define PL_FLAG_EXEC 0x10 /* exec(2) succeeded */ #define PL_FLAG_SI 0x20 /* siginfo is valid */ #define PL_FLAG_FORKED 0x40 /* new child */ +#define PL_FLAG_CHILD 0x80 /* I am from child */ sigset_t pl_sigmask; /* LWP signal mask */ sigset_t pl_siglist; /* LWP pending signal */ struct __siginfo pl_siginfo; /* siginfo for signal */ @@ -130,12 +131,6 @@ struct ptrace_vm_entry { #ifdef _KERNEL -#define PTRACESTOP_SC(p, td, flag) \ - if ((p)->p_flag & P_TRACED && (p)->p_stops & (flag)) { \ - PROC_LOCK(p); \ - ptracestop((td), SIGTRAP); \ - PROC_UNLOCK(p); \ - } /* * The flags below are used for ptrace(2) tracing and have no relation * to procfs. They are stored in struct proc's p_stops member. diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 7800c42b897c..0d51a5bf56ef 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -396,7 +396,9 @@ struct sockproto { #define NET_RT_FLAGS 2 /* by flags, e.g. RESOLVING */ #define NET_RT_IFLIST 3 /* survey interface list */ #define NET_RT_IFMALIST 4 /* return multicast address list */ -#define NET_RT_MAXID 5 +#define NET_RT_IFLISTL 5 /* Survey interface list, using 'l'en + * versions of msghdr structs. */ +#define NET_RT_MAXID 6 #define CTL_NET_RT_NAMES { \ { 0, 0 }, \ @@ -404,6 +406,7 @@ struct sockproto { { "flags", CTLTYPE_STRUCT }, \ { "iflist", CTLTYPE_STRUCT }, \ { "ifmalist", CTLTYPE_STRUCT }, \ + { "iflistl", CTLTYPE_STRUCT }, \ } #endif /* __BSD_VISIBLE */ diff --git a/sys/sys/ttycom.h b/sys/sys/ttycom.h index 68a411ea1080..8d7547f5795a 100644 --- a/sys/sys/ttycom.h +++ b/sys/sys/ttycom.h @@ -105,7 +105,7 @@ struct winsize { #define TIOCM_SR 0020 /* secondary receive */ #define TIOCM_CTS 0040 /* clear to send */ #define TIOCM_DCD 0100 /* data carrier detect */ -#define TIOCM_RI 0200 /* ring indicate */ +#define TIOCM_RI 0200 /* ring indicate */ #define TIOCM_DSR 0400 /* data set ready */ #define TIOCM_CD TIOCM_DCD #define TIOCM_CAR TIOCM_DCD diff --git a/sys/sys/ttydefaults.h b/sys/sys/ttydefaults.h index 5813bda62076..409ebc7da4e1 100644 --- a/sys/sys/ttydefaults.h +++ b/sys/sys/ttydefaults.h @@ -79,9 +79,9 @@ #define CSTART CTRL('Q') #define CSTOP CTRL('S') #define CLNEXT CTRL('V') -#define CDISCARD CTRL('O') -#define CWERASE CTRL('W') -#define CREPRINT CTRL('R') +#define CDISCARD CTRL('O') +#define CWERASE CTRL('W') +#define CREPRINT CTRL('R') #define CEOT CEOF /* compat */ #define CBRK CEOL diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 0ef497971e1f..4fd5a28cc1e4 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -149,8 +149,8 @@ struct vnode { struct lock *v_vnlock; /* u pointer to vnode lock */ int v_holdcnt; /* i prevents recycling. */ int v_usecount; /* i ref count of users */ - u_long v_iflag; /* i vnode flags (see below) */ - u_long v_vflag; /* v vnode flags */ + u_int v_iflag; /* i vnode flags (see below) */ + u_int v_vflag; /* v vnode flags */ int v_writecount; /* v ref count of writers */ /* @@ -538,6 +538,10 @@ void assert_vop_unlocked(struct vnode *vp, const char *str); */ #define VCALL(c) ((c)->a_desc->vdesc_call(c)) +#define DOINGASYNC(vp) \ + (((vp)->v_mount->mnt_kern_flag & MNTK_ASYNC) != 0 && \ + ((curthread->td_pflags & TDP_SYNCIO) == 0)) + /* * VMIO support inline */ @@ -582,9 +586,7 @@ struct vnode; cache_enter_time(dvp, vp, cnp, NULL) void cache_enter_time(struct vnode *dvp, struct vnode *vp, struct componentname *cnp, struct timespec *tsp); -#define cache_lookup(dvp, vpp, cnp) \ - cache_lookup_times(dvp, vpp, cnp, NULL, NULL) -int cache_lookup_times(struct vnode *dvp, struct vnode **vpp, +int cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct timespec *tsp, int *ticksp); void cache_purge(struct vnode *vp); void cache_purge_negative(struct vnode *vp); diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 5b4b6b91daa0..9639076b04aa 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ffs.h" +#include "opt_quota.h" #include "opt_ddb.h" /* @@ -6428,7 +6429,7 @@ softdep_setup_freeblocks(ip, length, flags) } #ifdef QUOTA /* Reference the quotas in case the block count is wrong in the end. */ - quotaref(vp, freeblks->fb_quota); + quotaref(ITOV(ip), freeblks->fb_quota); (void) chkdq(ip, -datablocks, NOCRED, 0); #endif freeblks->fb_chkcnt = -datablocks; @@ -7160,13 +7161,16 @@ check_inode_unwritten(inodedep) mtx_assert(&lk, MA_OWNED); if ((inodedep->id_state & (DEPCOMPLETE | UNLINKED)) != 0 || + !LIST_EMPTY(&inodedep->id_dirremhd) || !LIST_EMPTY(&inodedep->id_pendinghd) || !LIST_EMPTY(&inodedep->id_bufwait) || !LIST_EMPTY(&inodedep->id_inowait) || + !TAILQ_EMPTY(&inodedep->id_inoreflst) || !TAILQ_EMPTY(&inodedep->id_inoupdt) || !TAILQ_EMPTY(&inodedep->id_newinoupdt) || !TAILQ_EMPTY(&inodedep->id_extupdt) || !TAILQ_EMPTY(&inodedep->id_newextupdt) || + !TAILQ_EMPTY(&inodedep->id_freeblklst) || inodedep->id_mkdiradd != NULL || inodedep->id_nlinkdelta != 0) return (0); @@ -12112,6 +12116,7 @@ softdep_sync_buf(struct vnode *vp, struct buf *bp, int waitfor) case D_FREEWORK: case D_FREEDEP: case D_JSEGDEP: + case D_JNEWBLK: continue; default: diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index a97d23a07ec0..a12fd83b0a64 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1436,17 +1436,26 @@ ffs_sync(mp, waitfor) int softdep_accdeps; struct bufobj *bo; + wait = 0; + suspend = 0; + suspended = 0; td = curthread; fs = ump->um_fs; if (fs->fs_fmod != 0 && fs->fs_ronly != 0 && ump->um_fsckpid == 0) panic("%s: ffs_sync: modification on read-only filesystem", fs->fs_fsmnt); + /* + * For a lazy sync, we just care about the filesystem metadata. + */ + if (waitfor == MNT_LAZY) { + secondary_accwrites = 0; + secondary_writes = 0; + lockreq = 0; + goto metasync; + } /* * Write back each (modified) inode. */ - wait = 0; - suspend = 0; - suspended = 0; lockreq = LK_EXCLUSIVE | LK_NOWAIT; if (waitfor == MNT_SUSPEND) { suspend = 1; @@ -1517,11 +1526,12 @@ ffs_sync(mp, waitfor) #ifdef QUOTA qsync(mp); #endif + +metasync: devvp = ump->um_devvp; bo = &devvp->v_bufobj; BO_LOCK(bo); - if (waitfor != MNT_LAZY && - (bo->bo_numoutput > 0 || bo->bo_dirty.bv_cnt > 0)) { + if (bo->bo_numoutput > 0 || bo->bo_dirty.bv_cnt > 0) { BO_UNLOCK(bo); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); if ((error = VOP_FSYNC(devvp, waitfor, td)) != 0) diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 81c7af40811f..333f44789fba 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -718,15 +718,6 @@ ffs_write(ap) vnode_pager_setsize(vp, ip->i_size); break; } - /* - * If the buffer is not valid we have to clear out any - * garbage data from the pages instantiated for the buffer. - * If we do not, a failed uiomove() during a write can leave - * the prior contents of the pages exposed to a userland - * mmap(). XXX deal with uiomove() errors a better way. - */ - if ((bp->b_flags & B_CACHE) == 0 && fs->fs_bsize <= xfersize) - vfs_bio_clrbuf(bp); if (ioflag & IO_DIRECT) bp->b_flags |= B_DIRECT; if ((ioflag & (IO_SYNC|IO_INVAL)) == (IO_SYNC|IO_INVAL)) @@ -743,6 +734,26 @@ ffs_write(ap) error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); + /* + * If the buffer is not already filled and we encounter an + * error while trying to fill it, we have to clear out any + * garbage data from the pages instantiated for the buffer. + * If we do not, a failed uiomove() during a write can leave + * the prior contents of the pages exposed to a userland mmap. + * + * Note that we need only clear buffers with a transfer size + * equal to the block size because buffers with a shorter + * transfer size were cleared above by the call to UFS_BALLOC() + * with the BA_CLRBUF flag set. + * + * If the source region for uiomove identically mmaps the + * buffer, uiomove() performed the NOP copy, and the buffer + * content remains valid because the page fault handler + * validated the pages. + */ + if (error != 0 && (bp->b_flags & B_CACHE) == 0 && + fs->fs_bsize == xfersize) + vfs_bio_clrbuf(bp); if ((ioflag & (IO_VMIO|IO_DIRECT)) && (LIST_EMPTY(&bp->b_dep))) { bp->b_flags |= B_RELBUF; diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index 6f3d6f9853ea..3519ca24f54c 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -176,7 +176,6 @@ struct indir { /* Determine if soft dependencies are being done */ #define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & (MNT_SOFTDEP | MNT_SUJ)) #define MOUNTEDSOFTDEP(mp) ((mp)->mnt_flag & (MNT_SOFTDEP | MNT_SUJ)) -#define DOINGASYNC(vp) ((vp)->v_mount->mnt_kern_flag & MNTK_ASYNC) #define DOINGSUJ(vp) ((vp)->v_mount->mnt_flag & MNT_SUJ) #define MOUNTEDSUJ(mp) ((mp)->mnt_flag & MNT_SUJ) diff --git a/sys/ufs/ufs/ufs_acl.c b/sys/ufs/ufs/ufs_acl.c index 11794517f71a..76a4186cd9f4 100644 --- a/sys/ufs/ufs/ufs_acl.c +++ b/sys/ufs/ufs/ufs_acl.c @@ -422,7 +422,8 @@ ufs_setacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct thread *td) VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); - return (0); + error = UFS_UPDATE(vp, 0); + return (error); } static int @@ -591,10 +592,11 @@ ufs_setacl_posix1e(struct vop_setacl_args *ap) */ ufs_sync_inode_from_acl(ap->a_aclp, ip); ip->i_flag |= IN_CHANGE; + error = UFS_UPDATE(ap->a_vp, 0); } VN_KNOTE_UNLOCKED(ap->a_vp, NOTE_ATTRIB); - return (0); + return (error); } int diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 171ef753c3d8..ab33ef34b150 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -571,8 +571,9 @@ ufs_setattr(ap) DIP_SET(ip, i_flags, ip->i_flags); } ip->i_flag |= IN_CHANGE; + error = UFS_UPDATE(vp, 0); if (vap->va_flags & (IMMUTABLE | APPEND)) - return (0); + return (error); } if (ip->i_flags & (IMMUTABLE | APPEND)) return (EPERM); @@ -738,6 +739,9 @@ ufs_markatime(ap) VI_LOCK(vp); ip->i_flag |= IN_ACCESS; VI_UNLOCK(vp); + /* + * XXXKIB No UFS_UPDATE(ap->a_vp, 0) there. + */ return (0); } @@ -794,6 +798,9 @@ ufs_chmod(vp, mode, cred, td) if ((vp->v_mount->mnt_flag & MNT_NFS4ACLS) != 0) error = ufs_update_nfs4_acl_after_mode_change(vp, mode, ip->i_uid, cred, td); #endif + if (error == 0 && (ip->i_flag & IN_CHANGE) != 0) + error = UFS_UPDATE(vp, 0); + return (error); } @@ -912,7 +919,8 @@ ufs_chown(vp, uid, gid, cred, td) DIP_SET(ip, i_mode, ip->i_mode); } } - return (0); + error = UFS_UPDATE(vp, 0); + return (error); } static int @@ -2079,6 +2087,7 @@ ufs_rmdir(ap) dp->i_nlink--; DIP_SET(dp, i_nlink, dp->i_nlink); dp->i_flag |= IN_CHANGE; + error = UFS_UPDATE(dvp, 0); ip->i_nlink--; DIP_SET(ip, i_nlink, ip->i_nlink); ip->i_flag |= IN_CHANGE; @@ -2122,6 +2131,7 @@ ufs_symlink(ap) ip->i_size = len; DIP_SET(ip, i_size, len); ip->i_flag |= IN_CHANGE | IN_UPDATE; + error = UFS_UPDATE(vp, 0); } else error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 93621a9513d0..be999cc8c13e 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -2320,7 +2320,7 @@ swapoff_all(void) TAILQ_FOREACH_SAFE(sp, &swtailq, sw_list, spt) { mtx_unlock(&sw_dev_mtx); if (vn_isdisk(sp->sw_vp, NULL)) - devname = sp->sw_vp->v_rdev->si_name; + devname = devtoname(sp->sw_vp->v_rdev); else devname = "[file]"; error = swapoff_one(sp, thread0.td_ucred); @@ -2358,7 +2358,7 @@ int swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len) { struct swdevt *sp; - char *tmp_devname; + const char *tmp_devname; int error, n; n = 0; @@ -2376,7 +2376,7 @@ swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len) xs->xsw_used = sp->sw_used; if (devname != NULL) { if (vn_isdisk(sp->sw_vp, NULL)) - tmp_devname = sp->sw_vp->v_rdev->si_name; + tmp_devname = devtoname(sp->sw_vp->v_rdev); else tmp_devname = "[file]"; strncpy(devname, tmp_devname, len); diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index d62576f31e50..0c98d568cac0 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -1130,6 +1130,7 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset, vm_map_entry_t temp_entry; vm_eflags_t protoeflags; struct ucred *cred; + vm_inherit_t inheritance; boolean_t charge_prev_obj; VM_MAP_ASSERT_LOCKED(map); @@ -1173,6 +1174,10 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset, protoeflags |= MAP_ENTRY_NOSYNC; if (cow & MAP_DISABLE_COREDUMP) protoeflags |= MAP_ENTRY_NOCOREDUMP; + if (cow & MAP_INHERIT_SHARE) + inheritance = VM_INHERIT_SHARE; + else + inheritance = VM_INHERIT_DEFAULT; cred = NULL; KASSERT((object != kmem_object && object != kernel_object) || @@ -1227,7 +1232,7 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset, * can extend the previous map entry to include the * new range as well. */ - if ((prev_entry->inheritance == VM_INHERIT_DEFAULT) && + if ((prev_entry->inheritance == inheritance) && (prev_entry->protection == prot) && (prev_entry->max_protection == max)) { map->size += (end - prev_entry->end); @@ -1276,7 +1281,7 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset, new_entry->offset = offset; new_entry->avail_ssize = 0; - new_entry->inheritance = VM_INHERIT_DEFAULT; + new_entry->inheritance = inheritance; new_entry->protection = prot; new_entry->max_protection = max; new_entry->wired_count = 0; diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index 5311e027baa2..11ff63262b0f 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -307,7 +307,7 @@ long vmspace_wired_count(struct vmspace *vmspace); /* * Copy-on-write flags for vm_map operations */ -#define MAP_UNUSED_01 0x0001 +#define MAP_INHERIT_SHARE 0x0001 #define MAP_COPY_ON_WRITE 0x0002 #define MAP_NOFAULT 0x0004 #define MAP_PREFAULT 0x0008 diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index e85b681a8694..6ed24f67c34e 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -1438,18 +1438,18 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, size = round_page(size); - PROC_LOCK(td->td_proc); - if (td->td_proc->p_vmspace->vm_map.size + size > - lim_cur(td->td_proc, RLIMIT_VMEM)) { + if (map == &td->td_proc->p_vmspace->vm_map) { + PROC_LOCK(td->td_proc); + if (map->size + size > lim_cur(td->td_proc, RLIMIT_VMEM)) { + PROC_UNLOCK(td->td_proc); + return (ENOMEM); + } + if (racct_set(td->td_proc, RACCT_VMEM, map->size + size)) { + PROC_UNLOCK(td->td_proc); + return (ENOMEM); + } PROC_UNLOCK(td->td_proc); - return (ENOMEM); } - if (racct_set(td->td_proc, RACCT_VMEM, - td->td_proc->p_vmspace->vm_map.size + size)) { - PROC_UNLOCK(td->td_proc); - return (ENOMEM); - } - PROC_UNLOCK(td->td_proc); /* * We currently can only deal with page aligned file offsets. @@ -1517,6 +1517,9 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, docow |= MAP_DISABLE_SYNCER; if (flags & MAP_NOCORE) docow |= MAP_DISABLE_COREDUMP; + /* Shared memory is also shared with children. */ + if (flags & MAP_SHARED) + docow |= MAP_INHERIT_SHARE; if (flags & MAP_STACK) rv = vm_map_stack(map, *addr, size, prot, maxprot, @@ -1536,13 +1539,6 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, * or named anonymous without other references. */ vm_object_deallocate(object); - } else if (flags & MAP_SHARED) { - /* - * Shared memory is also shared with children. - */ - rv = vm_map_inherit(map, *addr, *addr + size, VM_INHERIT_SHARE); - if (rv != KERN_SUCCESS) - (void) vm_map_remove(map, *addr, *addr + size); } /* diff --git a/sys/xen/interface/io/blkif.h b/sys/xen/interface/io/blkif.h index 020936b1f539..ffc897909362 100644 --- a/sys/xen/interface/io/blkif.h +++ b/sys/xen/interface/io/blkif.h @@ -1,8 +1,8 @@ /****************************************************************************** * blkif.h - * + * * Unified block-device I/O interface for Xen guest OSes. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the @@ -22,6 +22,7 @@ * DEALINGS IN THE SOFTWARE. * * Copyright (c) 2003-2004, Keir Fraser + * Copyright (c) 2012, Spectra Logic Corporation */ #ifndef __XEN_PUBLIC_IO_BLKIF_H__ @@ -35,7 +36,7 @@ * notification can be made conditional on req_event (i.e., the generic * hold-off mechanism provided by the ring macros). Backends must set * req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()). - * + * * Back->front notifications: When enqueuing a new response, sending a * notification can be made conditional on rsp_event (i.e., the generic * hold-off mechanism provided by the ring macros). Frontends must set @@ -47,38 +48,414 @@ #endif #define blkif_sector_t uint64_t +/* + * Feature and Parameter Negotiation + * ================================= + * The two halves of a Xen block driver utilize nodes within the XenStore to + * communicate capabilities and to negotiate operating parameters. This + * section enumerates these nodes which reside in the respective front and + * backend portions of the XenStore, following the XenBus convention. + * + * All data in the XenStore is stored as strings. Nodes specifying numeric + * values are encoded in decimal. Integer value ranges listed below are + * expressed as fixed sized integer types capable of storing the conversion + * of a properly formated node string, without loss of information. + * + * Any specified default value is in effect if the corresponding XenBus node + * is not present in the XenStore. + * + * XenStore nodes in sections marked "PRIVATE" are solely for use by the + * driver side whose XenBus tree contains them. + * + * See the XenBus state transition diagram below for details on when XenBus + * nodes must be published and when they can be queried. + * + ***************************************************************************** + * Backend XenBus Nodes + ***************************************************************************** + * + *------------------ Backend Device Identification (PRIVATE) ------------------ + * + * mode + * Values: "r" (read only), "w" (writable) + * + * The read or write access permissions to the backing store to be + * granted to the frontend. + * + * params + * Values: string + * + * A free formatted string providing sufficient information for the + * backend driver to open the backing device. (e.g. the path to the + * file or block device representing the backing store.) + * + * type + * Values: "file", "phy", "tap" + * + * The type of the backing device/object. + * + *--------------------------------- Features --------------------------------- + * + * feature-barrier + * Values: 0/1 (boolean) + * Default Value: 0 + * + * A value of "1" indicates that the backend can process requests + * containing the BLKIF_OP_WRITE_BARRIER request opcode. Requests + * of this type may still be returned at any time with the + * BLKIF_RSP_EOPNOTSUPP result code. + * + * feature-flush-cache + * Values: 0/1 (boolean) + * Default Value: 0 + * + * A value of "1" indicates that the backend can process requests + * containing the BLKIF_OP_FLUSH_DISKCACHE request opcode. Requests + * of this type may still be returned at any time with the + * BLKIF_RSP_EOPNOTSUPP result code. + * + * feature-discard + * Values: 0/1 (boolean) + * Default Value: 0 + * + * A value of "1" indicates that the backend can process requests + * containing the BLKIF_OP_DISCARD request opcode. Requests + * of this type may still be returned at any time with the + * BLKIF_RSP_EOPNOTSUPP result code. + * + *----------------------- Request Transport Parameters ------------------------ + * + * max-ring-page-order + * Values: + * Default Value: 0 + * Notes: 1, 3 + * + * The maximum supported size of the request ring buffer in units of + * lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages, + * etc.). + * + * max-ring-pages + * Values: + * Default Value: 1 + * Notes: 2, 3 + * + * The maximum supported size of the request ring buffer in units of + * machine pages. The value must be a power of 2. + * + * max-requests + * Default Value: BLKIF_MAX_RING_REQUESTS(PAGE_SIZE) + * Maximum Value: BLKIF_MAX_RING_REQUESTS(PAGE_SIZE * max-ring-pages) + * + * The maximum number of concurrent, logical requests that will be + * issued by the backend. + * + * Note: A logical request may span multiple ring entries. + * + * max-request-segments + * Values: + * Default Value: BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK + * Maximum Value: BLKIF_MAX_SEGMENTS_PER_REQUEST + * + * The maximum value of blkif_request.nr_segments supported by + * the backend. + * + * max-request-size + * Values: + * Default Value: BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK * PAGE_SIZE + * Maximum Value: BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE + * + * The maximum amount of data, in bytes, that can be referenced by a + * request type that accesses frontend memory (currently BLKIF_OP_READ, + * BLKIF_OP_WRITE, or BLKIF_OP_WRITE_BARRIER). + * + *------------------------- Backend Device Properties ------------------------- + * + * discard-aligment + * Values: + * Default Value: 0 + * Notes: 4, 5 + * + * The offset, in bytes from the beginning of the virtual block device, + * to the first, addressable, discard extent on the underlying device. + * + * discard-granularity + * Values: + * Default Value: <"sector-size"> + * Notes: 4 + * + * The size, in bytes, of the individually addressable discard extents + * of the underlying device. + * + * discard-secure + * Values: 0/1 (boolean) + * Default Value: 0 + * + * A value of "1" indicates that the backend can process BLKIF_OP_DISCARD + * requests with the BLKIF_DISCARD_SECURE flag set. + * + * info + * Values: (bitmap) + * + * A collection of bit flags describing attributes of the backing + * device. The VDISK_* macros define the meaning of each bit + * location. + * + * sector-size + * Values: + * + * The native sector size, in bytes, of the backend device. + * + * sectors + * Values: + * + * The size of the backend device, expressed in units of its native + * sector size ("sector-size"). + * + ***************************************************************************** + * Frontend XenBus Nodes + ***************************************************************************** + * + *----------------------- Request Transport Parameters ----------------------- + * + * event-channel + * Values: + * + * The identifier of the Xen event channel used to signal activity + * in the ring buffer. + * + * ring-ref + * Values: + * Notes: 6 + * + * The Xen grant reference granting permission for the backend to map + * the sole page in a single page sized ring buffer. + * + * ring-ref%u + * Values: + * Notes: 6 + * + * For a frontend providing a multi-page ring, a "num-ring-pages" sized + * list of nodes, each containing a Xen grant reference granting + * permission for the backend to map the page of the ring located + * at page index "%u". Page indexes are zero based. + * + * protocol + * Values: string (XEN_IO_PROTO_ABI_*) + * Default Value: XEN_IO_PROTO_ABI_NATIVE + * + * The machine ABI rules governing the format of all ring request and + * response structures. + * + * ring-page-order + * Values: + * Default Value: 0 + * Maximum Value: MAX(ffs(max-ring-pages) - 1, max-ring-page-order) + * Notes: 1, 3 + * + * The size of the frontend allocated request ring buffer in units + * of lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages, + * etc.). + * + * num-ring-pages + * Values: + * Default Value: 1 + * Maximum Value: MAX(max-ring-pages,(0x1 << max-ring-page-order)) + * Notes: 2, 3 + * + * The size of the frontend allocated request ring buffer in units of + * machine pages. The value must be a power of 2. + * + * max-requests + * Values: + * Default Value: BLKIF_MAX_RING_REQUESTS(PAGE_SIZE) + * Maximum Value: BLKIF_MAX_RING_REQUESTS(PAGE_SIZE * max-ring-pages) + * + * The maximum number of concurrent, logical requests that will be + * issued by the frontend. + * + * Note: A logical request may span multiple ring entries. + * + * max-request-segments + * Values: + * Default Value: BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK + * Maximum Value: MIN(255, backend/max-request-segments) + * + * The maximum value the frontend will set in the + * blkif_request.nr_segments field. + * + * max-request-size + * Values: + * Default Value: BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK * PAGE_SIZE + * Maximum Value: max-request-segments * PAGE_SIZE + * + * The maximum amount of data, in bytes, that can be referenced by + * a request type that accesses frontend memory (currently BLKIF_OP_READ, + * BLKIF_OP_WRITE, or BLKIF_OP_WRITE_BARRIER). + * + *------------------------- Virtual Device Properties ------------------------- + * + * device-type + * Values: "disk", "cdrom", "floppy", etc. + * + * virtual-device + * Values: + * + * A value indicating the physical device to virtualize within the + * frontend's domain. (e.g. "The first ATA disk", "The third SCSI + * disk", etc.) + * + * See docs/misc/vbd-interface.txt for details on the format of this + * value. + * + * Notes + * ----- + * (1) Multi-page ring buffer scheme first developed in the Citrix XenServer + * PV drivers. + * (2) Multi-page ring buffer scheme first used in some RedHat distributions + * including a distribution deployed on certain nodes of the Amazon + * EC2 cluster. + * (3) Support for multi-page ring buffers was implemented independently, + * in slightly different forms, by both Citrix and RedHat/Amazon. + * For full interoperability, block front and backends should publish + * identical ring parameters, adjusted for unit differences, to the + * XenStore nodes used in both schemes. + * (4) Devices that support discard functionality may internally allocate + * space (discardable extents) in units that are larger than the + * exported logical block size. + * (5) The discard-alignment parameter allows a physical device to be + * partitioned into virtual devices that do not necessarily begin or + * end on a discardable extent boundary. + * (6) When there is only a single page allocated to the request ring, + * 'ring-ref' is used to communicate the grant reference for this + * page to the backend. When using a multi-page ring, the 'ring-ref' + * node is not created. Instead 'ring-ref0' - 'ring-refN' are used. + */ + +/* + * STATE DIAGRAMS + * + ***************************************************************************** + * Startup * + ***************************************************************************** + * + * Tool stack creates front and back nodes with state XenbusStateInitialising. + * + * Front Back + * ================================= ===================================== + * XenbusStateInitialising XenbusStateInitialising + * o Query virtual device o Query backend device identification + * properties. data. + * o Setup OS device instance. o Open and validate backend device. + * o Publish backend features and + * transport parameters. + * | + * | + * V + * XenbusStateInitWait + * + * o Query backend features and + * transport parameters. + * o Allocate and initialize the + * request ring. + * o Publish transport parameters + * that will be in effect during + * this connection. + * | + * | + * V + * XenbusStateInitialised + * + * o Query frontend transport parameters. + * o Connect to the request ring and + * event channel. + * o Publish backend device properties. + * | + * | + * V + * XenbusStateConnected + * + * o Query backend device properties. + * o Finalize OS virtual device + * instance. + * | + * | + * V + * XenbusStateConnected + * + * Note: Drivers that do not support any optional features, or the negotiation + * of transport parameters, can skip certain states in the state machine: + * + * o A frontend may transition to XenbusStateInitialised without + * waiting for the backend to enter XenbusStateInitWait. In this + * case, default transport parameters are in effect and any + * transport parameters published by the frontend must contain + * their default values. + * + * o A backend may transition to XenbusStateInitialised, bypassing + * XenbusStateInitWait, without waiting for the frontend to first + * enter the XenbusStateInitialised state. In this case, default + * transport parameters are in effect and any transport parameters + * published by the backend must contain their default values. + * + * Drivers that support optional features and/or transport parameter + * negotiation must tolerate these additional state transition paths. + * In general this means performing the work of any skipped state + * transition, if it has not already been performed, in addition to the + * work associated with entry into the current state. + */ + /* * REQUEST CODES. */ #define BLKIF_OP_READ 0 #define BLKIF_OP_WRITE 1 /* - * Recognised only if "feature-barrier" is present in backend xenbus info. - * The "feature-barrier" node contains a boolean indicating whether barrier - * requests are likely to succeed or fail. Either way, a barrier request - * may fail at any time with BLKIF_RSP_EOPNOTSUPP if it is unsupported by - * the underlying block-device hardware. The boolean simply indicates whether - * or not it is worthwhile for the frontend to attempt barrier requests. - * If a backend does not recognise BLKIF_OP_WRITE_BARRIER, it should *not* - * create the "feature-barrier" node! + * All writes issued prior to a request with the BLKIF_OP_WRITE_BARRIER + * operation code ("barrier request") must be completed prior to the + * execution of the barrier request. All writes issued after the barrier + * request must not execute until after the completion of the barrier request. + * + * Optional. See "feature-barrier" XenBus node documentation above. */ #define BLKIF_OP_WRITE_BARRIER 2 /* - * Recognised if "feature-flush-cache" is present in backend xenbus - * info. A flush will ask the underlying storage hardware to flush its - * non-volatile caches as appropriate. The "feature-flush-cache" node - * contains a boolean indicating whether flush requests are likely to - * succeed or fail. Either way, a flush request may fail at any time - * with BLKIF_RSP_EOPNOTSUPP if it is unsupported by the underlying - * block-device hardware. The boolean simply indicates whether or not it - * is worthwhile for the frontend to attempt flushes. If a backend does - * not recognise BLKIF_OP_WRITE_FLUSH_CACHE, it should *not* create the - * "feature-flush-cache" node! + * Commit any uncommitted contents of the backing device's volatile cache + * to stable storage. + * + * Optional. See "feature-flush-cache" XenBus node documentation above. */ #define BLKIF_OP_FLUSH_DISKCACHE 3 +/* + * Used in SLES sources for device specific command packet + * contained within the request. Reserved for that purpose. + */ +#define BLKIF_OP_RESERVED_1 4 +/* + * Indicate to the backend device that a region of storage is no longer in + * use, and may be discarded at any time without impact to the client. If + * the BLKIF_DISCARD_SECURE flag is set on the request, all copies of the + * discarded region on the device must be rendered unrecoverable before the + * command returns. + * + * This operation is analogous to performing a trim (ATA) or unamp (SCSI), + * command on a native device. + * + * More information about trim/unmap operations can be found at: + * http://t13.org/Documents/UploadedDocuments/docs2008/ + * e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc + * http://www.seagate.com/staticfiles/support/disc/manuals/ + * Interface%20manuals/100293068c.pdf + * + * Optional. See "feature-discard", "discard-alignment", + * "discard-granularity", and "discard-secure" in the XenBus node + * documentation above. + */ +#define BLKIF_OP_DISCARD 5 /* * Maximum scatter/gather segments associated with a request header block. + * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE. + * NB. This could be 12 if the ring indexes weren't stored in the same page. */ #define BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK 11 @@ -92,6 +469,13 @@ */ #define BLKIF_MAX_SEGMENTS_PER_REQUEST 255 +/* + * NB. first_sect and last_sect in blkif_request_segment, as well as + * sector_number in blkif_request, are always expressed in 512-byte units. + * However they must be properly aligned to the real sector size of the + * physical disk, which is reported in the "sector-size" node in the backend + * xenbus info. Also the xenbus "sectors" node is expressed in 512-byte units. + */ struct blkif_request_segment { grant_ref_t gref; /* reference to I/O buffer frame */ /* @first_sect: first sector in frame to transfer (inclusive). */ @@ -100,16 +484,60 @@ struct blkif_request_segment { }; typedef struct blkif_request_segment blkif_request_segment_t; +/* + * Starting ring element for any I/O request. + * + * One or more segment blocks can be inserted into the request ring + * just after a blkif_request_t, allowing requests to operate on + * up to BLKIF_MAX_SEGMENTS_PER_REQUEST. + * + * BLKIF_SEGS_TO_BLOCKS() can be used on blkif_requst.nr_segments + * to determine the number of contiguous ring entries associated + * with this request. + * + * Note: Due to the way Xen request rings operate, the producer and + * consumer indices of the ring must be incremented by the + * BLKIF_SEGS_TO_BLOCKS() value of the associated request. + * (e.g. a response to a 3 ring entry request must also consume + * 3 entries in the ring, even though only the first ring entry + * in the response has any data.) + */ struct blkif_request { uint8_t operation; /* BLKIF_OP_??? */ uint8_t nr_segments; /* number of segments */ blkif_vdev_t handle; /* only for read/write requests */ uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK]; + blkif_request_segment_t seg[BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK]; }; typedef struct blkif_request blkif_request_t; +/* + * A segment block is a ring request structure that contains only + * segment data. + * + * sizeof(struct blkif_segment_block) <= sizeof(struct blkif_request) + */ +struct blkif_segment_block { + blkif_request_segment_t seg[BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK]; +}; +typedef struct blkif_segment_block blkif_segment_block_t; + +/* + * Cast to this structure when blkif_request.operation == BLKIF_OP_DISCARD + * sizeof(struct blkif_request_discard) <= sizeof(struct blkif_request) + */ +struct blkif_request_discard { + uint8_t operation; /* BLKIF_OP_DISCARD */ + uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */ +#define BLKIF_DISCARD_SECURE (1<<0) /* ignored if discard-secure=0 */ + blkif_vdev_t handle; /* same as for read/write requests */ + uint64_t id; /* private guest value, echoed in resp */ + blkif_sector_t sector_number;/* start sector idx on disk */ + uint64_t nr_sectors; /* number of contiguous sectors to discard*/ +}; +typedef struct blkif_request_discard blkif_request_discard_t; + struct blkif_response { uint64_t id; /* copied from request */ uint8_t operation; /* copied from request */ @@ -130,24 +558,26 @@ typedef struct blkif_response blkif_response_t; /* * Generate blkif ring structures and types. */ - DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response); -#define BLKRING_GET_SG_REQUEST(_r, _idx) \ - ((struct blkif_request_segment *)RING_GET_REQUEST(_r, _idx)) - -#define VDISK_CDROM 0x1 -#define VDISK_REMOVABLE 0x2 -#define VDISK_READONLY 0x4 +/* + * Index to, and treat as a segment block, an entry in the ring. + */ +#define BLKRING_GET_SEG_BLOCK(_r, _idx) \ + (((blkif_segment_block_t *)RING_GET_REQUEST(_r, _idx))->seg) /* * The number of ring request blocks required to handle an I/O * request containing _segs segments. */ -#define BLKIF_SEGS_TO_BLOCKS(_segs) \ - ((((_segs - BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK) \ - + (BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK - 1)) \ - / BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK) + /*header_block*/1) +#define BLKIF_SEGS_TO_BLOCKS(_segs) \ + ((((_segs - BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK) \ + + (BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK - 1)) \ + / BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK) + /*header_block*/1) + +#define VDISK_CDROM 0x1 +#define VDISK_REMOVABLE 0x2 +#define VDISK_READONLY 0x4 #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */ diff --git a/sys/xen/xenbus/xenbusvar.h b/sys/xen/xenbus/xenbusvar.h index bf2a342b546f..1c730fb900a5 100644 --- a/sys/xen/xenbus/xenbusvar.h +++ b/sys/xen/xenbus/xenbusvar.h @@ -103,6 +103,20 @@ XENBUS_ACCESSOR(otherend_path, OTHEREND_PATH, const char *) */ XenbusState xenbus_read_driver_state(const char *path); +/** + * Return the state of the "other end" (peer) of a XenBus device. + * + * \param dev The XenBus device whose peer to query. + * + * \return The current state of the peer device or XenbusStateClosed if no + * state can be read. + */ +static inline XenbusState +xenbus_get_otherend_state(device_t dev) +{ + return (xenbus_read_driver_state(xenbus_get_otherend_path(dev))); +} + /** * Initialize and register a watch on the given path (client suplied storage). * diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 1ec1ce109b27..5aab001915e8 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -671,6 +671,44 @@ OLD_FILES+=usr/share/man/man1/clang-cpp.1.gz OLD_FILES+=usr/share/man/man1/tblgen.1.gz .endif +.if ${MK_CLANG_EXTRAS} == no +OLD_FILES+=usr/bin/bugpoint +OLD_FILES+=usr/bin/llc +OLD_FILES+=usr/bin/lli +OLD_FILES+=usr/bin/llvm-ar +OLD_FILES+=usr/bin/llvm-as +OLD_FILES+=usr/bin/llvm-bcanalyzer +OLD_FILES+=usr/bin/llvm-diff +OLD_FILES+=usr/bin/llvm-dis +OLD_FILES+=usr/bin/llvm-extract +OLD_FILES+=usr/bin/llvm-ld +OLD_FILES+=usr/bin/llvm-link +OLD_FILES+=usr/bin/llvm-mc +OLD_FILES+=usr/bin/llvm-nm +OLD_FILES+=usr/bin/llvm-objdump +OLD_FILES+=usr/bin/llvm-prof +OLD_FILES+=usr/bin/llvm-ranlib +OLD_FILES+=usr/bin/llvm-rtdyld +OLD_FILES+=usr/bin/llvm-stub +OLD_FILES+=usr/bin/macho-dump +OLD_FILES+=usr/bin/opt +OLD_FILES+=usr/share/man/man1/bugpoint.1.gz +OLD_FILES+=usr/share/man/man1/llc.1.gz +OLD_FILES+=usr/share/man/man1/lli.1.gz +OLD_FILES+=usr/share/man/man1/llvm-ar.1.gz +OLD_FILES+=usr/share/man/man1/llvm-as.1.gz +OLD_FILES+=usr/share/man/man1/llvm-bcanalyzer.1.gz +OLD_FILES+=usr/share/man/man1/llvm-diff.1.gz +OLD_FILES+=usr/share/man/man1/llvm-dis.1.gz +OLD_FILES+=usr/share/man/man1/llvm-extract.1.gz +OLD_FILES+=usr/share/man/man1/llvm-ld.1.gz +OLD_FILES+=usr/share/man/man1/llvm-link.1.gz +OLD_FILES+=usr/share/man/man1/llvm-nm.1.gz +OLD_FILES+=usr/share/man/man1/llvm-prof.1.gz +OLD_FILES+=usr/share/man/man1/llvm-ranlib.1.gz +OLD_FILES+=usr/share/man/man1/opt.1.gz +.endif + .if ${MK_CPP} == no OLD_FILES+=usr/bin/cpp OLD_FILES+=usr/share/man/man1/cpp.1.gz @@ -3369,6 +3407,7 @@ OLD_FILES+=usr/bin/who OLD_FILES+=usr/bin/wtmpcvt OLD_FILES+=usr/sbin/ac OLD_FILES+=usr/sbin/lastlogin +OLD_FILES+=usr/sbin/utx OLD_FILES+=usr/sbin/utxrm OLD_FILES+=usr/share/man/man1/last.1.gz OLD_FILES+=usr/share/man/man1/users.1.gz @@ -3376,6 +3415,7 @@ OLD_FILES+=usr/share/man/man1/who.1.gz OLD_FILES+=usr/share/man/man1/wtmpcvt.1.gz OLD_FILES+=usr/share/man/man8/ac.8.gz OLD_FILES+=usr/share/man/man8/lastlogin.8.gz +OLD_FILES+=usr/share/man/man8/utx.8.gz OLD_FILES+=usr/share/man/man8/utxrm.8.gz .endif diff --git a/tools/build/options/WITHOUT_SOURCELESS b/tools/build/options/WITHOUT_SOURCELESS new file mode 100644 index 000000000000..995252ec9215 --- /dev/null +++ b/tools/build/options/WITHOUT_SOURCELESS @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to not build kernel modules that include sourceless code (either microcode or native code for host CPU). diff --git a/tools/build/options/WITHOUT_SOURCELESS_HOST b/tools/build/options/WITHOUT_SOURCELESS_HOST new file mode 100644 index 000000000000..22a8dffe392f --- /dev/null +++ b/tools/build/options/WITHOUT_SOURCELESS_HOST @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to not build kernel modules that include sourceless native code for host CPU. diff --git a/tools/build/options/WITHOUT_SOURCELESS_UCODE b/tools/build/options/WITHOUT_SOURCELESS_UCODE new file mode 100644 index 000000000000..c356a95e386e --- /dev/null +++ b/tools/build/options/WITHOUT_SOURCELESS_UCODE @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to not build kernel modules that include sourceless microcode. diff --git a/tools/build/options/WITHOUT_UTMPX b/tools/build/options/WITHOUT_UTMPX index 3c98f28b4087..80be74ebf02b 100644 --- a/tools/build/options/WITHOUT_UTMPX +++ b/tools/build/options/WITHOUT_UTMPX @@ -6,4 +6,4 @@ Set to not build user accounting tools such as .Xr ac 8 , .Xr lastlogin 8 and -.Xr utxrm 8 . +.Xr utx 8 . diff --git a/tools/build/options/WITH_CLANG_EXTRAS b/tools/build/options/WITH_CLANG_EXTRAS new file mode 100644 index 000000000000..87da08fef93f --- /dev/null +++ b/tools/build/options/WITH_CLANG_EXTRAS @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to build additional clang and llvm tools, such as bugpoint. diff --git a/tools/regression/bin/sh/builtins/hash4.0 b/tools/regression/bin/sh/builtins/hash4.0 new file mode 100644 index 000000000000..dec584c4538f --- /dev/null +++ b/tools/regression/bin/sh/builtins/hash4.0 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +exec 3>&1 +m=`hash nosuchtool 2>&1 >&3` +r=$? +[ "$r" != 0 ] && [ -n "$m" ] diff --git a/tools/regression/usr.bin/make/execution/joberr/expected.stdout.1 b/tools/regression/usr.bin/make/execution/joberr/expected.stdout.1 index eb1736341e91..0ee28f4fd515 100644 --- a/tools/regression/usr.bin/make/execution/joberr/expected.stdout.1 +++ b/tools/regression/usr.bin/make/execution/joberr/expected.stdout.1 @@ -1,90 +1,90 @@ Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 +*** [do-check-joberr] Error code 1 Error: build failed -*** Error code 1 -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) -*** Error code 2 (ignored) +*** [do-check-joberr] Error code 1 +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) +*** [check-joberr] Error code 2 (ignored) diff --git a/tools/test/hwpmc/pmctest.py b/tools/test/hwpmc/pmctest.py new file mode 100755 index 000000000000..e3c12d3ddd51 --- /dev/null +++ b/tools/test/hwpmc/pmctest.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# Copyright (c) 2012, Neville-Neil Consulting +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Neville-Neil Consulting nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Author: George V. Neville-Neil +# +# $FreeBSD$ + +# Description: A program to run a simple program against every available +# pmc counter present in a system. +# +# To use: +# +# pmctest.py -p ls > /dev/null +# +# This should result in ls being run with every available counter +# and the system should neither lock up nor panic. +# +# The default is to wait after each counter is tested. Since the +# prompt would go to stdout you won't see it, just press return +# to continue or Ctrl-D to stop. + +import sys +import subprocess +from subprocess import PIPE + +# A list of strings that are not really counters, just +# name tags that are output by pmccontrol -L +notcounter = ["IAF", "IAP", "TSC", "UNC", "UCF", "UCP"] + +def main(): + + from optparse import OptionParser + + parser = OptionParser() + parser.add_option("-p", "--program", dest="program", + help="program to execute") + parser.add_option("-w", "--wait", action="store_true", dest="wait", + default=True, help="wait after each execution") + + (options, args) = parser.parse_args() + + p = subprocess.Popen(["pmccontrol", "-L"], stdout=PIPE) + counters = p.communicate()[0] + + if len(counters) <= 0: + print "no counters found" + sys.exit() + + for counter in counters.split(): + if counter in notcounter: + continue + p = subprocess.Popen(["pmcstat", "-p", counter, options.program], + stdout=PIPE) + result = p.communicate()[0] + print result + if (options.wait == True): + try: + value = raw_input("next?") + except EOFError: + sys.exit() + +# The canonical way to make a python module into a script. +# Remove if unnecessary. + +if __name__ == "__main__": + main() diff --git a/usr.sbin/utxrm/Makefile b/tools/test/ptrace/Makefile similarity index 54% rename from usr.sbin/utxrm/Makefile rename to tools/test/ptrace/Makefile index cf38b816f2e5..681aee574385 100644 --- a/usr.sbin/utxrm/Makefile +++ b/tools/test/ptrace/Makefile @@ -1,6 +1,7 @@ # $FreeBSD$ -PROG= utxrm -MAN= utxrm.8 +PROG= scescx +NO_MAN= +WARNS?= 6 .include diff --git a/tools/test/ptrace/scescx.c b/tools/test/ptrace/scescx.c new file mode 100644 index 000000000000..cdd8b6014946 --- /dev/null +++ b/tools/test/ptrace/scescx.c @@ -0,0 +1,406 @@ +/*- + * Copyright (c) 2011, 2012 Konstantin Belousov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TRACE ">>>> " + +static const char * +decode_wait_status(int status) +{ + static char c[128]; + char b[32]; + int first; + + c[0] = '\0'; + first = 1; + if (WIFCONTINUED(status)) { + first = 0; + strlcat(c, "CONT", sizeof(c)); + } + if (WIFEXITED(status)) { + if (first) + first = 0; + else + strlcat(c, ",", sizeof(c)); + snprintf(b, sizeof(b), "EXIT(%d)", WEXITSTATUS(status)); + strlcat(c, b, sizeof(c)); + } + if (WIFSIGNALED(status)) { + if (first) + first = 0; + else + strlcat(c, ",", sizeof(c)); + snprintf(b, sizeof(b), "SIG(%s)", strsignal(WTERMSIG(status))); + strlcat(c, b, sizeof(c)); + if (WCOREDUMP(status)) + strlcat(c, ",CORE", sizeof(c)); + } + if (WIFSTOPPED(status)) { + if (first) + first = 0; + else + strlcat(c, ",", sizeof(c)); + snprintf(b, sizeof(b), "SIG(%s)", strsignal(WSTOPSIG(status))); + strlcat(c, b, sizeof(c)); + } + return (c); +} + +static const char * +decode_pl_flags(struct ptrace_lwpinfo *lwpinfo) +{ + static char c[128]; + static struct decode_tag { + int flag; + const char *desc; + } decode[] = { + { PL_FLAG_SA, "SA" }, + { PL_FLAG_BOUND, "BOUND" }, + { PL_FLAG_SCE, "SCE" }, + { PL_FLAG_SCX, "SCX" }, + { PL_FLAG_EXEC, "EXEC" }, + { PL_FLAG_SI, "SI" }, + { PL_FLAG_FORKED, "FORKED" }, + }; + char de[32]; + unsigned first, flags, i; + + c[0] = '\0'; + first = 1; + flags = lwpinfo->pl_flags; + for (i = 0; i < sizeof(decode) / sizeof(decode[0]); i++) { + if ((flags & decode[i].flag) != 0) { + if (first) + first = 0; + else + strlcat(c, ",", sizeof(c)); + strlcat(c, decode[i].desc, sizeof(c)); + flags &= ~decode[i].flag; + } + } + for (i = 0; i < sizeof(flags) * NBBY; i++) { + if ((flags & (1 << i)) != 0) { + if (first) + first = 0; + else + strlcat(c, ",", sizeof(c)); + snprintf(de, sizeof(de), "<%d>", i); + strlcat(c, de, sizeof(c)); + } + } + return (c); +} + +static const char * +decode_pl_event(struct ptrace_lwpinfo *lwpinfo) +{ + + switch (lwpinfo->pl_event) { + case PL_EVENT_NONE: + return ("NONE"); + + case PL_EVENT_SIGNAL: + return ("SIG"); + + default: + return ("UNKNOWN"); + } +} + +static void +get_pathname(pid_t pid) +{ + char pathname[PATH_MAX]; + int error, name[4]; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_PATHNAME; + name[3] = pid; + + len = sizeof(pathname); + error = sysctl(name, 4, pathname, &len, NULL, 0); + if (error < 0) { + if (errno != ESRCH) { + fprintf(stderr, "sysctl kern.proc.pathname.%d: %s\n", + pid, strerror(errno)); + return; + } + fprintf(stderr, "pid %d exited\n", pid); + return; + } + if (len == 0 || strlen(pathname) == 0) { + fprintf(stderr, "No cached pathname for process %d\n", pid); + return; + } + printf(TRACE "pid %d path %s\n", pid, pathname); +} + +static void +wait_info(int pid, int status, struct ptrace_lwpinfo *lwpinfo) +{ + + printf(TRACE "pid %d wait %s", pid, + decode_wait_status(status)); + if (lwpinfo != NULL) { + printf(" event %s flags %s", + decode_pl_event(lwpinfo), decode_pl_flags(lwpinfo)); + } + printf("\n"); +} + +static int +trace_sc(int pid) +{ + struct ptrace_lwpinfo lwpinfo; + int status; + + if (ptrace(PT_TO_SCE, pid, (caddr_t)1, 0) < 0) { + perror("PT_TO_SCE"); + ptrace(PT_KILL, pid, NULL, 0); + return (-1); + } + + if (waitpid(pid, &status, 0) == -1) { + perror("waitpid"); + return (-1); + } + if (WIFEXITED(status) || WIFSIGNALED(status)) { + wait_info(pid, status, NULL); + return (-1); + } + assert(WIFSTOPPED(status)); + assert(WSTOPSIG(status) == SIGTRAP); + + if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) { + perror("PT_LWPINFO"); + ptrace(PT_KILL, pid, NULL, 0); + return (-1); + } + wait_info(pid, status, &lwpinfo); + assert(lwpinfo.pl_flags & PL_FLAG_SCE); + + if (ptrace(PT_TO_SCX, pid, (caddr_t)1, 0) < 0) { + perror("PT_TO_SCX"); + ptrace(PT_KILL, pid, NULL, 0); + return (-1); + } + + if (waitpid(pid, &status, 0) == -1) { + perror("waitpid"); + return (-1); + } + if (WIFEXITED(status) || WIFSIGNALED(status)) { + wait_info(pid, status, NULL); + return (-1); + } + assert(WIFSTOPPED(status)); + assert(WSTOPSIG(status) == SIGTRAP); + + if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) { + perror("PT_LWPINFO"); + ptrace(PT_KILL, pid, NULL, 0); + return (-1); + } + wait_info(pid, status, &lwpinfo); + assert(lwpinfo.pl_flags & PL_FLAG_SCX); + + if (lwpinfo.pl_flags & PL_FLAG_EXEC) + get_pathname(pid); + + if (lwpinfo.pl_flags & PL_FLAG_FORKED) { + printf(TRACE "forked child %d\n", lwpinfo.pl_child_pid); + return (lwpinfo.pl_child_pid); + } + return (0); +} + +static int +trace_cont(int pid) +{ + struct ptrace_lwpinfo lwpinfo; + int status; + + if (ptrace(PT_CONTINUE, pid, (caddr_t)1, 0) < 0) { + perror("PT_CONTINUE"); + ptrace(PT_KILL, pid, NULL, 0); + return (-1); + } + + if (waitpid(pid, &status, 0) == -1) { + perror("waitpid"); + return (-1); + } + if (WIFEXITED(status) || WIFSIGNALED(status)) { + wait_info(pid, status, NULL); + return (-1); + } + assert(WIFSTOPPED(status)); + assert(WSTOPSIG(status) == SIGTRAP); + + if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)) < 0) { + perror("PT_LWPINFO"); + ptrace(PT_KILL, pid, NULL, 0); + return (-1); + } + wait_info(pid, status, &lwpinfo); + + if ((lwpinfo.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) == + (PL_FLAG_EXEC | PL_FLAG_SCX)) + get_pathname(pid); + + if ((lwpinfo.pl_flags & (PL_FLAG_FORKED | PL_FLAG_SCX)) == + (PL_FLAG_FORKED | PL_FLAG_SCX)) { + printf(TRACE "forked child %d\n", lwpinfo.pl_child_pid); + return (lwpinfo.pl_child_pid); + } + + return (0); +} + +static int trace_syscalls = 1; + +static int +trace(pid_t pid) +{ + + return (trace_syscalls ? trace_sc(pid) : trace_cont(pid)); +} + + +int +main(int argc, char *argv[]) +{ + struct ptrace_lwpinfo lwpinfo; + int c, status, use_vfork; + pid_t pid, pid1; + + trace_syscalls = 1; + use_vfork = 0; + while ((c = getopt(argc, argv, "csv")) != -1) { + switch (c) { + case 'c': + trace_syscalls = 0; + break; + case 's': + trace_syscalls = 1; + break; + case 'v': + use_vfork = 1; + break; + default: + case '?': + fprintf(stderr, "Usage: %s [-c] [-s] [-v]\n", argv[0]); + return (2); + } + } + + if ((pid = fork()) < 0) { + perror("fork"); + return 1; + } + else if (pid == 0) { + if (ptrace(PT_TRACE_ME, 0, NULL, 0) < 0) { + perror("PT_TRACE_ME"); + _exit(1); + } + kill(getpid(), SIGSTOP); + getpid(); + if ((pid1 = use_vfork ? vfork() : fork()) < 0) { + perror("fork1"); + return (1); + } else if (pid1 == 0) { + printf("Hi from child %d\n", getpid()); + execl("/bin/ls", "ls", "/", (char *)NULL); + } + } + else { /* parent */ + if (waitpid(pid, &status, 0) == -1) { + perror("waitpid"); + return (-1); + } + assert(WIFSTOPPED(status)); + assert(WSTOPSIG(status) == SIGSTOP); + + if (ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, + sizeof(lwpinfo)) < 0) { + perror("PT_LWPINFO"); + ptrace(PT_KILL, pid, NULL, 0); + return (-1); + } + wait_info(pid, status, &lwpinfo); + + if (ptrace(PT_FOLLOW_FORK, pid, 0, 1) < 0) { + perror("PT_FOLLOW_FORK"); + ptrace(PT_KILL, pid, NULL, 0); + return (2); + } + + while ((pid1 = trace(pid)) >= 0) { + if (pid1 != 0) { + printf(TRACE "attached to pid %d\n", pid1); +#if 0 + kill(pid1, SIGCONT); +#endif + if (waitpid(pid1, &status, 0) == -1) { + perror("waitpid"); + return (-1); + } + printf(TRACE "nested loop, pid %d status %s\n", + pid1, decode_wait_status(status)); + assert(WIFSTOPPED(status)); + assert(WSTOPSIG(status) == SIGSTOP); + if (ptrace(PT_LWPINFO, pid1, (caddr_t)&lwpinfo, + sizeof(lwpinfo)) < 0) { + perror("PT_LWPINFO"); + ptrace(PT_KILL, pid1, NULL, 0); + return (-1); + } + wait_info(pid1, status, &lwpinfo); + + while (trace(pid1) >= 0) + ; + } + } + + ptrace(PT_CONTINUE, pid, (caddr_t)1, 0); + } + return (0); +} diff --git a/tools/tools/ath/athradar/athradar.c b/tools/tools/ath/athradar/athradar.c index 5f086085e1b7..f40e1bd09be5 100644 --- a/tools/tools/ath/athradar/athradar.c +++ b/tools/tools/ath/athradar/athradar.c @@ -101,6 +101,8 @@ radarset(struct radarhandler *radar, int op, u_int32_t param) pe.pe_enmaxrssi = HAL_PHYERR_PARAM_NOVAL; pe.pe_extchannel = HAL_PHYERR_PARAM_NOVAL; + pe.pe_enrelpwr = HAL_PHYERR_PARAM_NOVAL; + pe.pe_en_relstep_check = HAL_PHYERR_PARAM_NOVAL; switch (op) { case DFS_PARAM_ENABLE: @@ -142,7 +144,14 @@ radarset(struct radarhandler *radar, int op, u_int32_t param) case DFS_PARAM_EN_EXTCH: pe.pe_extchannel = param; break; + case DFS_PARAM_RELPWR_EN: + pe.pe_enrelpwr = param; + break; + case DFS_PARAM_RELSTEP_EN: + pe.pe_en_relstep_check = param; + break; } + radar->atd.ad_id = DFS_SET_THRESH | ATH_DIAG_IN; radar->atd.ad_out_data = NULL; radar->atd.ad_out_size = 0; @@ -182,16 +191,21 @@ radar_get(struct radarhandler *radar) printf(" pe_blockradar: %d\n", pe.pe_blockradar); printf(" pe_enmaxrssi: %d\n", pe.pe_enmaxrssi); printf(" pe_extchannel: %d\n", pe.pe_extchannel); + printf(" pe_enrelpwr: %d\n", pe.pe_enrelpwr); + printf(" pe_en_relstep_check: %d\n", pe.pe_en_relstep_check); } static int -radar_set_param(struct radarhandler *radar, const char *param, const char *val) +radar_set_param(struct radarhandler *radar, const char *param, + const char *val) { int v; v = atoi(val); - if (strcmp(param, "firpwr") == 0) { + if (strcmp(param, "enabled") == 0) { + radarset(radar, DFS_PARAM_ENABLE, v); + } else if (strcmp(param, "firpwr") == 0) { radarset(radar, DFS_PARAM_FIRPWR, v); } else if (strcmp(param, "rrssi") == 0) { radarset(radar, DFS_PARAM_RRSSI, v); @@ -215,6 +229,10 @@ radar_set_param(struct radarhandler *radar, const char *param, const char *val) radarset(radar, DFS_PARAM_MAXRSSI_EN, v); } else if (strcmp(param, "extchannel") == 0) { radarset(radar, DFS_PARAM_EN_EXTCH, v); + } else if (strcmp(param, "enrelpwr") == 0) { + radarset(radar, DFS_PARAM_RELPWR_EN, v); + } else if (strcmp(param, "en_relstep_check") == 0) { + radarset(radar, DFS_PARAM_RELSTEP_EN, v); } else { return 0; } diff --git a/tools/tools/fixwhite/Makefile b/tools/tools/fixwhite/Makefile new file mode 100644 index 000000000000..dbaabc25410b --- /dev/null +++ b/tools/tools/fixwhite/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +PROG= fixwhite +BINDIR= /usr/bin +WARNS= 6 + +.include diff --git a/tools/tools/fixwhite/fixwhite.1 b/tools/tools/fixwhite/fixwhite.1 new file mode 100644 index 000000000000..ccf5ecec03dc --- /dev/null +++ b/tools/tools/fixwhite/fixwhite.1 @@ -0,0 +1,48 @@ +.\" Copyright (c) 2012 Ed Schouten +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 6, 2012 +.Dt FIXWHITE 1 +.Os +.Sh NAME +.Nm fixwhite +.Nd remove unneeded whitespace from text files +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +The +.Nm +utility removes unneeded whitespace from text passed to standard input +and prints the result to standard output. +.Pp +It removes leading and trailing empty lines from the input, as well as +trailing whitespace characters from ever line of text. +Multiple successive empty lines are merged together. +If the whitespace at the beginning of a sentence is exactly a multiple +of eight spaces, the whitespace is replaced by tabs. +Also, spaces preceeding tabs will be merged into the tab character. +.Sh AUTHORS +.An Ed Schouten Aq ed@FreeBSD.org diff --git a/tools/tools/fixwhite/fixwhite.c b/tools/tools/fixwhite/fixwhite.c new file mode 100644 index 000000000000..903a5a355651 --- /dev/null +++ b/tools/tools/fixwhite/fixwhite.c @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2012 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +static char *queue = NULL; +static size_t queuelen = 0, queuesize = 0; +static off_t column = 0; + +static void +savebyte(char c) +{ + + if (queuelen >= queuesize) { + queuesize += 128; + queue = realloc(queue, queuesize); + if (queue == NULL) { + perror("malloc"); + exit(1); + } + } + queue[queuelen++] = c; + + switch (c) { + case '\n': + column = 0; + break; + case ' ': + column++; + break; + case '\t': + column = (column / 8 + 1) * 8; + break; + } +} + +static bool +peekbyte(size_t back, char c) +{ + + return (queuelen >= back && queue[queuelen - back] == c); +} + +static void +savewhite(char c, bool leading) +{ + off_t ncolumn; + + switch (c) { + case '\n': + if (leading) { + /* Remove empty lines before input. */ + queuelen = 0; + column = 0; + } else { + /* Remove trailing whitespace. */ + while (peekbyte(1, ' ') || peekbyte(1, '\t')) + queuelen--; + /* Remove redundant empty lines. */ + if (peekbyte(2, '\n') && peekbyte(1, '\n')) + return; + savebyte('\n'); + } + break; + case ' ': + savebyte(' '); + break; + case '\t': + /* Convert preceeding spaces to tabs. */ + ncolumn = (column / 8 + 1) * 8; + while (peekbyte(1, ' ')) { + queuelen--; + column--; + } + while (column < ncolumn) + savebyte('\t'); + break; + } +} + +static void +printwhite(void) +{ + off_t i; + + /* Merge spaces at the start of a sentence to tabs if possible. */ + if ((column % 8) == 0) { + for (i = 0; i < column; i++) + if (!peekbyte(i + 1, ' ')) + break; + if (i == column) { + queuelen -= column; + for (i = 0; i < column; i += 8) + queue[queuelen++] = '\t'; + } + } + + if (fwrite(queue, 1, queuelen, stdout) != queuelen) { + perror("write"); + exit(1); + } + queuelen = 0; +} + +static char +readchar(void) +{ + int c; + + c = getchar(); + if (c == EOF && ferror(stdin)) { + perror("read"); + exit(1); + } + return (c); +} + +static void +writechar(char c) +{ + + if (putchar(c) == EOF) { + perror("write"); + exit(1); + } + /* XXX: Multi-byte characters. */ + column++; +} + +int +main(void) +{ + int c; + bool leading = true; + + while ((c = readchar()) != EOF) { + if (isspace(c)) + /* Save whitespace. */ + savewhite(c, leading); + else { + /* Reprint whitespace and print regular character. */ + printwhite(); + writechar(c); + leading = false; + } + } + /* Terminate non-empty files with a newline. */ + if (!leading) + writechar('\n'); + return (0); +} diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c index f2f4e40b8705..5627e9ea3ab5 100644 --- a/tools/tools/netmap/pkt-gen.c +++ b/tools/tools/netmap/pkt-gen.c @@ -124,7 +124,7 @@ struct pkt { struct ether_header eh; struct ip ip; struct udphdr udp; - uint8_t body[NETMAP_BUF_SIZE]; + uint8_t body[2048]; // XXX hardwired } __attribute__((__packed__)); /* diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd index caa47b7f54ae..5c6dfb81e446 100644 --- a/usr.bin/calendar/calendars/calendar.freebsd +++ b/usr.bin/calendar/calendars/calendar.freebsd @@ -239,6 +239,7 @@ 08/05 Alfred Perlstein born in Brooklyn, New York, United States, 1978 08/06 Anton Berezin born in Dnepropetrovsk, Ukraine, 1970 08/06 John-Mark Gurney born in Detroit, Michigan, United States, 1978 +08/06 Damjan Marion born in Rijeka, Croatia, 1978 08/07 Jonathan Mini born in San Mateo, California, United States, 1979 08/08 Mikolaj Golub born in Kharkov, USSR, 1977 08/10 Peter Pentchev born in Sofia, Bulgaria, 1977 @@ -274,6 +275,7 @@ 09/12 Weongyo Jeong born in Haman, Korea, 1980 09/12 Benedict Christopher Reuschling born in Darmstadt, Germany, 1981 09/12 William C. Fumerola II born in Detroit, Michigan, United States, 1981 +09/14 Matthew Seaman born in Bristol, United Kingdom, 1965 09/15 Aleksandr Rybalko born in Odessa, Ukraine, 1977 09/15 Dima Panov born in Khabarovsk, Russian Federation, 1978 09/17 Maxim Bolotin born in Rostov-on-Don, Russian Federation, 1976 diff --git a/usr.bin/chpass/util.c b/usr.bin/chpass/util.c index 07d96e227a96..baf160e8762e 100644 --- a/usr.bin/chpass/util.c +++ b/usr.bin/chpass/util.c @@ -110,10 +110,10 @@ atot(char *p, time_t *store) } } } - if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t)) + if (!(t = strtok(NULL, " \t,")) || !isdigit(*t)) goto bad; day = atoi(t); - if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t)) + if (!(t = strtok(NULL, " \t,")) || !isdigit(*t)) goto bad; year = atoi(t); if (day < 1 || day > 31 || month < 1 || month > 12) diff --git a/usr.bin/clang/Makefile b/usr.bin/clang/Makefile index ef5a0e794f26..1cfa57ffa5a3 100644 --- a/usr.bin/clang/Makefile +++ b/usr.bin/clang/Makefile @@ -1,5 +1,30 @@ # $FreeBSD$ +.include + SUBDIR= clang clang-tblgen tblgen +.if ${MK_CLANG_EXTRAS} != "no" +SUBDIR+=bugpoint \ + llc \ + lli \ + llvm-ar \ + llvm-as \ + llvm-bcanalyzer \ + llvm-diff \ + llvm-dis \ + llvm-extract \ + llvm-ld \ + llvm-link \ + llvm-mc \ + llvm-nm \ + llvm-objdump \ + llvm-prof \ + llvm-ranlib \ + llvm-rtdyld \ + llvm-stub \ + macho-dump \ + opt +.endif + .include diff --git a/usr.bin/clang/bugpoint/Makefile b/usr.bin/clang/bugpoint/Makefile new file mode 100644 index 000000000000..6fc25f371890 --- /dev/null +++ b/usr.bin/clang/bugpoint/Makefile @@ -0,0 +1,34 @@ +# $FreeBSD$ + +PROG_CXX=bugpoint + +SRCDIR= tools/bugpoint +SRCS= BugDriver.cpp \ + CrashDebugger.cpp \ + ExecutionDriver.cpp \ + ExtractFunction.cpp \ + FindBugs.cpp \ + Miscompilation.cpp \ + OptimizerDriver.cpp \ + ToolRunner.cpp \ + bugpoint.cpp + +TGHDRS= Intrinsics +LIBDEPS=llvmbitwriter \ + llvmlinker \ + llvmarchive \ + llvmbitreader \ + llvmipo \ + llvmscalaropts \ + llvminstcombine \ + llvminstrumentation \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmmc \ + llvmasmparser \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/bugpoint/bugpoint.1 b/usr.bin/clang/bugpoint/bugpoint.1 new file mode 100644 index 000000000000..9d86c100aaea --- /dev/null +++ b/usr.bin/clang/bugpoint/bugpoint.1 @@ -0,0 +1,291 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "BUGPOINT 1" +.TH BUGPOINT 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +bugpoint \- automatic test case reduction tool +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBbugpoint\fR [\fIoptions\fR] [\fIinput \s-1LLVM\s0 ll/bc files\fR] [\fI\s-1LLVM\s0 passes\fR] \fB\-\-args\fR +\&\fIprogram arguments\fR +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBbugpoint\fR narrows down the source of problems in \s-1LLVM\s0 tools and passes. It +can be used to debug three types of failures: optimizer crashes, miscompilations +by optimizers, or bad native code generation (including problems in the static +and \s-1JIT\s0 compilers). It aims to reduce large test cases to small, useful ones. +For more information on the design and inner workings of \fBbugpoint\fR, as well as +advice for using bugpoint, see \fIllvm/docs/Bugpoint.html\fR in the \s-1LLVM\s0 +distribution. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-\-additional\-so\fR \fIlibrary\fR" 4 +.IX Item "--additional-so library" +Load the dynamic shared object \fIlibrary\fR into the test program whenever it is +run. This is useful if you are debugging programs which depend on non-LLVM +libraries (such as the X or curses libraries) to run. +.IP "\fB\-\-append\-exit\-code\fR=\fI{true,false}\fR" 4 +.IX Item "--append-exit-code={true,false}" +Append the test programs exit code to the output file so that a change in exit +code is considered a test failure. Defaults to false. +.IP "\fB\-\-args\fR \fIprogram args\fR" 4 +.IX Item "--args program args" +Pass all arguments specified after \-args to the test program whenever it runs. +Note that if any of the \fIprogram args\fR start with a '\-', you should use: +.Sp +.Vb 1 +\& bugpoint [bugpoint args] \-\-args \-\- [program args] +.Ve +.Sp +The \*(L"\-\-\*(R" right after the \fB\-\-args\fR option tells \fBbugpoint\fR to consider any +options starting with \f(CW\*(C`\-\*(C'\fR to be part of the \fB\-\-args\fR option, not as options to +\&\fBbugpoint\fR itself. +.IP "\fB\-\-tool\-args\fR \fItool args\fR" 4 +.IX Item "--tool-args tool args" +Pass all arguments specified after \-\-tool\-args to the \s-1LLVM\s0 tool under test +(\fBllc\fR, \fBlli\fR, etc.) whenever it runs. You should use this option in the +following way: +.Sp +.Vb 1 +\& bugpoint [bugpoint args] \-\-tool\-args \-\- [tool args] +.Ve +.Sp +The \*(L"\-\-\*(R" right after the \fB\-\-tool\-args\fR option tells \fBbugpoint\fR to consider any +options starting with \f(CW\*(C`\-\*(C'\fR to be part of the \fB\-\-tool\-args\fR option, not as +options to \fBbugpoint\fR itself. (See \fB\-\-args\fR, above.) +.IP "\fB\-\-safe\-tool\-args\fR \fItool args\fR" 4 +.IX Item "--safe-tool-args tool args" +Pass all arguments specified after \fB\-\-safe\-tool\-args\fR to the \*(L"safe\*(R" execution +tool. +.IP "\fB\-\-gcc\-tool\-args\fR \fIgcc tool args\fR" 4 +.IX Item "--gcc-tool-args gcc tool args" +Pass all arguments specified after \fB\-\-gcc\-tool\-args\fR to the invocation of +\&\fBgcc\fR. +.IP "\fB\-\-opt\-args\fR \fIopt args\fR" 4 +.IX Item "--opt-args opt args" +Pass all arguments specified after \fB\-\-opt\-args\fR to the invocation of \fBopt\fR. +.IP "\fB\-\-disable\-{dce,simplifycfg}\fR" 4 +.IX Item "--disable-{dce,simplifycfg}" +Do not run the specified passes to clean up and reduce the size of the test +program. By default, \fBbugpoint\fR uses these passes internally when attempting to +reduce test programs. If you're trying to find a bug in one of these passes, +\&\fBbugpoint\fR may crash. +.IP "\fB\-\-enable\-valgrind\fR" 4 +.IX Item "--enable-valgrind" +Use valgrind to find faults in the optimization phase. This will allow +bugpoint to find otherwise asymptomatic problems caused by memory +mis-management. +.IP "\fB\-find\-bugs\fR" 4 +.IX Item "-find-bugs" +Continually randomize the specified passes and run them on the test program +until a bug is found or the user kills \fBbugpoint\fR. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-\-input\fR \fIfilename\fR" 4 +.IX Item "--input filename" +Open \fIfilename\fR and redirect the standard input of the test program, whenever +it runs, to come from that file. +.IP "\fB\-\-load\fR \fIplugin\fR" 4 +.IX Item "--load plugin" +Load the dynamic object \fIplugin\fR into \fBbugpoint\fR itself. This object should +register new optimization passes. Once loaded, the object will add new command +line options to enable various optimizations. To see the new complete list of +optimizations, use the \fB\-help\fR and \fB\-\-load\fR options together; for example: +.Sp +.Vb 1 +\& bugpoint \-\-load myNewPass.so \-help +.Ve +.IP "\fB\-\-mlimit\fR \fImegabytes\fR" 4 +.IX Item "--mlimit megabytes" +Specifies an upper limit on memory usage of the optimization and codegen. Set +to zero to disable the limit. +.IP "\fB\-\-output\fR \fIfilename\fR" 4 +.IX Item "--output filename" +Whenever the test program produces output on its standard output stream, it +should match the contents of \fIfilename\fR (the \*(L"reference output\*(R"). If you +do not use this option, \fBbugpoint\fR will attempt to generate a reference output +by compiling the program with the \*(L"safe\*(R" backend and running it. +.IP "\fB\-\-profile\-info\-file\fR \fIfilename\fR" 4 +.IX Item "--profile-info-file filename" +Profile file loaded by \fB\-\-profile\-loader\fR. +.IP "\fB\-\-run\-{int,jit,llc,cbe,custom}\fR" 4 +.IX Item "--run-{int,jit,llc,cbe,custom}" +Whenever the test program is compiled, \fBbugpoint\fR should generate code for it +using the specified code generator. These options allow you to choose the +interpreter, the \s-1JIT\s0 compiler, the static native code compiler, the C +backend, or a custom command (see \fB\-\-exec\-command\fR) respectively. +.IP "\fB\-\-safe\-{llc,cbe,custom}\fR" 4 +.IX Item "--safe-{llc,cbe,custom}" +When debugging a code generator, \fBbugpoint\fR should use the specified code +generator as the \*(L"safe\*(R" code generator. This is a known-good code generator +used to generate the \*(L"reference output\*(R" if it has not been provided, and to +compile portions of the program that as they are excluded from the testcase. +These options allow you to choose the +static native code compiler, the C backend, or a custom command, +(see \fB\-\-exec\-command\fR) respectively. The interpreter and the \s-1JIT\s0 backends +cannot currently be used as the \*(L"safe\*(R" backends. +.IP "\fB\-\-exec\-command\fR \fIcommand\fR" 4 +.IX Item "--exec-command command" +This option defines the command to use with the \fB\-\-run\-custom\fR and +\&\fB\-\-safe\-custom\fR options to execute the bitcode testcase. This can +be useful for cross-compilation. +.IP "\fB\-\-compile\-command\fR \fIcommand\fR" 4 +.IX Item "--compile-command command" +This option defines the command to use with the \fB\-\-compile\-custom\fR +option to compile the bitcode testcase. This can be useful for +testing compiler output without running any link or execute stages. To +generate a reduced unit test, you may add \s-1CHECK\s0 directives to the +testcase and pass the name of an executable compile-command script in this form: +.Sp +.Vb 3 +\& #!/bin/sh +\& llc "$@" +\& not FileCheck [bugpoint input file].ll < bugpoint\-test\-program.s +.Ve +.Sp +This script will \*(L"fail\*(R" as long as FileCheck passes. So the result +will be the minimum bitcode that passes FileCheck. +.IP "\fB\-\-safe\-path\fR \fIpath\fR" 4 +.IX Item "--safe-path path" +This option defines the path to the command to execute with the +\&\fB\-\-safe\-{int,jit,llc,cbe,custom}\fR +option. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBbugpoint\fR succeeds in finding a problem, it will exit with 0. Otherwise, +if an error occurs, it will exit with a non-zero value. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +opt +.SH "AUTHOR" +.IX Header "AUTHOR" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llc/Makefile b/usr.bin/clang/llc/Makefile new file mode 100644 index 000000000000..db5f12d1b588 --- /dev/null +++ b/usr.bin/clang/llc/Makefile @@ -0,0 +1,45 @@ +# $FreeBSD$ + +PROG_CXX=llc + +SRCDIR= tools/llc +SRCS= llc.cpp + +LIBDEPS=llvmasmparser \ + llvmbitreader \ + llvmarmdisassembler \ + llvmarmasmparser \ + llvmarmcodegen \ + llvmarmdesc \ + llvmarminstprinter \ + llvmarminfo \ + llvmmipscodegen \ + llvmmipsdesc \ + llvmmipsinstprinter \ + llvmmipsinfo \ + llvmpowerpccodegen \ + llvmpowerpcdesc \ + llvmpowerpcinstprinter \ + llvmpowerpcinfo \ + llvmx86disassembler \ + llvmx86asmparser \ + llvmx86codegen \ + llvmx86desc \ + llvmselectiondag \ + llvmasmprinter \ + llvmmcparser \ + llvmcodegen \ + llvmscalaropts \ + llvminstcombine \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmx86instprinter \ + llvmx86utils \ + llvmcore \ + llvmx86info \ + llvmmc \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llc/llc.1 b/usr.bin/clang/llc/llc.1 new file mode 100644 index 000000000000..3c422bc3b718 --- /dev/null +++ b/usr.bin/clang/llc/llc.1 @@ -0,0 +1,285 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLC 1" +.TH LLC 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llc \- LLVM static compiler +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllc\fR [\fIoptions\fR] [\fIfilename\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllc\fR command compiles \s-1LLVM\s0 source inputs into assembly language for a +specified architecture. The assembly language output can then be passed through +a native assembler and linker to generate a native executable. +.PP +The choice of architecture for the output assembly code is automatically +determined from the input file, unless the \fB\-march\fR option is used to override +the default. +.SH "OPTIONS" +.IX Header "OPTIONS" +If \fIfilename\fR is \- or omitted, \fBllc\fR reads from standard input. Otherwise, it +will from \fIfilename\fR. Inputs can be in either the \s-1LLVM\s0 assembly language +format (.ll) or the \s-1LLVM\s0 bitcode format (.bc). +.PP +If the \fB\-o\fR option is omitted, then \fBllc\fR will send its output to standard +output if the input is from standard input. If the \fB\-o\fR option specifies \-, +then the output will also be sent to standard output. +.PP +If no \fB\-o\fR option is specified and an input file other than \- is specified, +then \fBllc\fR creates the output filename by taking the input filename, +removing any existing \fI.bc\fR extension, and adding a \fI.s\fR suffix. +.PP +Other \fBllc\fR options are as follows: +.SS "End-user Options" +.IX Subsection "End-user Options" +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-O\fR=\fIuint\fR" 4 +.IX Item "-O=uint" +Generate code at different optimization levels. These correspond to the \fI\-O0\fR, +\&\fI\-O1\fR, \fI\-O2\fR, \fI\-O3\fR, and \fI\-O4\fR optimization levels used by \fBllvm-gcc\fR and +\&\fBclang\fR. +.IP "\fB\-mtriple\fR=\fItarget triple\fR" 4 +.IX Item "-mtriple=target triple" +Override the target triple specified in the input file with the specified +string. +.IP "\fB\-march\fR=\fIarch\fR" 4 +.IX Item "-march=arch" +Specify the architecture for which to generate assembly, overriding the target +encoded in the input file. See the output of \fBllc \-help\fR for a list of +valid architectures. By default this is inferred from the target triple or +autodetected to the current architecture. +.IP "\fB\-mcpu\fR=\fIcpuname\fR" 4 +.IX Item "-mcpu=cpuname" +Specify a specific chip in the current architecture to generate code for. +By default this is inferred from the target triple and autodetected to +the current architecture. For a list of available CPUs, use: +\&\fBllvm-as < /dev/null | llc \-march=xyz \-mcpu=help\fR +.IP "\fB\-mattr\fR=\fIa1,+a2,\-a3,...\fR" 4 +.IX Item "-mattr=a1,+a2,-a3,..." +Override or control specific attributes of the target, such as whether \s-1SIMD\s0 +operations are enabled or not. The default set of attributes is set by the +current \s-1CPU\s0. For a list of available attributes, use: +\&\fBllvm-as < /dev/null | llc \-march=xyz \-mattr=help\fR +.IP "\fB\-\-disable\-fp\-elim\fR" 4 +.IX Item "--disable-fp-elim" +Disable frame pointer elimination optimization. +.IP "\fB\-\-disable\-excess\-fp\-precision\fR" 4 +.IX Item "--disable-excess-fp-precision" +Disable optimizations that may produce excess precision for floating point. +Note that this option can dramatically slow down code on some systems +(e.g. X86). +.IP "\fB\-\-enable\-no\-infs\-fp\-math\fR" 4 +.IX Item "--enable-no-infs-fp-math" +Enable optimizations that assume no Inf values. +.IP "\fB\-\-enable\-no\-nans\-fp\-math\fR" 4 +.IX Item "--enable-no-nans-fp-math" +Enable optimizations that assume no \s-1NAN\s0 values. +.IP "\fB\-\-enable\-unsafe\-fp\-math\fR" 4 +.IX Item "--enable-unsafe-fp-math" +Enable optimizations that make unsafe assumptions about \s-1IEEE\s0 math (e.g. that +addition is associative) or may not work for all input ranges. These +optimizations allow the code generator to make use of some instructions which +would otherwise not be usable (such as fsin on X86). +.IP "\fB\-\-enable\-correct\-eh\-support\fR" 4 +.IX Item "--enable-correct-eh-support" +Instruct the \fBlowerinvoke\fR pass to insert code for correct exception handling +support. This is expensive and is by default omitted for efficiency. +.IP "\fB\-\-stats\fR" 4 +.IX Item "--stats" +Print statistics recorded by code-generation passes. +.IP "\fB\-\-time\-passes\fR" 4 +.IX Item "--time-passes" +Record the amount of time needed for each pass and print a report to standard +error. +.IP "\fB\-\-load\fR=\fIdso_path\fR" 4 +.IX Item "--load=dso_path" +Dynamically load \fIdso_path\fR (a path to a dynamically shared object) that +implements an \s-1LLVM\s0 target. This will permit the target name to be used with the +\&\fB\-march\fR option so that code can be generated for that target. +.SS "Tuning/Configuration Options" +.IX Subsection "Tuning/Configuration Options" +.IP "\fB\-\-print\-machineinstrs\fR" 4 +.IX Item "--print-machineinstrs" +Print generated machine code between compilation phases (useful for debugging). +.IP "\fB\-\-regalloc\fR=\fIallocator\fR" 4 +.IX Item "--regalloc=allocator" +Specify the register allocator to use. The default \fIallocator\fR is \fIlocal\fR. +Valid register allocators are: +.RS 4 +.IP "\fIsimple\fR" 4 +.IX Item "simple" +Very simple \*(L"always spill\*(R" register allocator +.IP "\fIlocal\fR" 4 +.IX Item "local" +Local register allocator +.IP "\fIlinearscan\fR" 4 +.IX Item "linearscan" +Linear scan global register allocator +.IP "\fIiterativescan\fR" 4 +.IX Item "iterativescan" +Iterative scan global register allocator +.RE +.RS 4 +.RE +.IP "\fB\-\-spiller\fR=\fIspiller\fR" 4 +.IX Item "--spiller=spiller" +Specify the spiller to use for register allocators that support it. Currently +this option is used only by the linear scan register allocator. The default +\&\fIspiller\fR is \fIlocal\fR. Valid spillers are: +.RS 4 +.IP "\fIsimple\fR" 4 +.IX Item "simple" +Simple spiller +.IP "\fIlocal\fR" 4 +.IX Item "local" +Local spiller +.RE +.RS 4 +.RE +.SS "Intel IA\-32\-specific Options" +.IX Subsection "Intel IA-32-specific Options" +.IP "\fB\-\-x86\-asm\-syntax=att|intel\fR" 4 +.IX Item "--x86-asm-syntax=att|intel" +Specify whether to emit assembly code in \s-1AT&T\s0 syntax (the default) or intel +syntax. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllc\fR succeeds, it will exit with 0. Otherwise, if an error occurs, +it will exit with a non-zero value. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +lli +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/lli/Makefile b/usr.bin/clang/lli/Makefile new file mode 100644 index 000000000000..665c6d9afecd --- /dev/null +++ b/usr.bin/clang/lli/Makefile @@ -0,0 +1,35 @@ +# $FreeBSD$ + +PROG_CXX=lli + +SRCDIR= tools/lli +SRCS= lli.cpp + +LIBDEPS=llvmasmparser \ + llvmbitreader \ + llvmx86codegen \ + llvmx86desc \ + llvmx86info \ + llvmx86instprinter \ + llvmx86utils \ + llvmselectiondag \ + llvmasmprinter \ + llvmmcparser \ + llvminterpreter \ + llvmjit \ + llvmcodegen \ + llvmscalaropts \ + llvminstcombine \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmmcjit \ + llvmruntimedyld \ + llvmobject \ + llvmexecutionengine \ + llvmtarget \ + llvmmc \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/lli/lli.1 b/usr.bin/clang/lli/lli.1 new file mode 100644 index 000000000000..f90a6521d00f --- /dev/null +++ b/usr.bin/clang/lli/lli.1 @@ -0,0 +1,310 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLI 1" +.TH LLI 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +lli \- directly execute programs from LLVM bitcode +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBlli\fR [\fIoptions\fR] [\fIfilename\fR] [\fIprogram args\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBlli\fR directly executes programs in \s-1LLVM\s0 bitcode format. It takes a program +in \s-1LLVM\s0 bitcode format and executes it using a just-in-time compiler, if one is +available for the current architecture, or an interpreter. \fBlli\fR takes all of +the same code generator options as llc, but they are only effective when +\&\fBlli\fR is using the just-in-time compiler. +.PP +If \fIfilename\fR is not specified, then \fBlli\fR reads the \s-1LLVM\s0 bitcode for the +program from standard input. +.PP +The optional \fIargs\fR specified on the command line are passed to the program as +arguments. +.SH "GENERAL OPTIONS" +.IX Header "GENERAL OPTIONS" +.IP "\fB\-fake\-argv0\fR=\fIexecutable\fR" 4 +.IX Item "-fake-argv0=executable" +Override the \f(CW\*(C`argv[0]\*(C'\fR value passed into the executing program. +.IP "\fB\-force\-interpreter\fR=\fI{false,true}\fR" 4 +.IX Item "-force-interpreter={false,true}" +If set to true, use the interpreter even if a just-in-time compiler is available +for this architecture. Defaults to false. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-load\fR=\fIpuginfilename\fR" 4 +.IX Item "-load=puginfilename" +Causes \fBlli\fR to load the plugin (shared object) named \fIpluginfilename\fR and use +it for optimization. +.IP "\fB\-stats\fR" 4 +.IX Item "-stats" +Print statistics from the code-generation passes. This is only meaningful for +the just-in-time compiler, at present. +.IP "\fB\-time\-passes\fR" 4 +.IX Item "-time-passes" +Record the amount of time needed for each code-generation pass and print it to +standard error. +.IP "\fB\-version\fR" 4 +.IX Item "-version" +Print out the version of \fBlli\fR and exit without doing anything else. +.SH "TARGET OPTIONS" +.IX Header "TARGET OPTIONS" +.IP "\fB\-mtriple\fR=\fItarget triple\fR" 4 +.IX Item "-mtriple=target triple" +Override the target triple specified in the input bitcode file with the +specified string. This may result in a crash if you pick an +architecture which is not compatible with the current system. +.IP "\fB\-march\fR=\fIarch\fR" 4 +.IX Item "-march=arch" +Specify the architecture for which to generate assembly, overriding the target +encoded in the bitcode file. See the output of \fBllc \-help\fR for a list of +valid architectures. By default this is inferred from the target triple or +autodetected to the current architecture. +.IP "\fB\-mcpu\fR=\fIcpuname\fR" 4 +.IX Item "-mcpu=cpuname" +Specify a specific chip in the current architecture to generate code for. +By default this is inferred from the target triple and autodetected to +the current architecture. For a list of available CPUs, use: +\&\fBllvm-as < /dev/null | llc \-march=xyz \-mcpu=help\fR +.IP "\fB\-mattr\fR=\fIa1,+a2,\-a3,...\fR" 4 +.IX Item "-mattr=a1,+a2,-a3,..." +Override or control specific attributes of the target, such as whether \s-1SIMD\s0 +operations are enabled or not. The default set of attributes is set by the +current \s-1CPU\s0. For a list of available attributes, use: +\&\fBllvm-as < /dev/null | llc \-march=xyz \-mattr=help\fR +.SH "FLOATING POINT OPTIONS" +.IX Header "FLOATING POINT OPTIONS" +.IP "\fB\-disable\-excess\-fp\-precision\fR" 4 +.IX Item "-disable-excess-fp-precision" +Disable optimizations that may increase floating point precision. +.IP "\fB\-enable\-no\-infs\-fp\-math\fR" 4 +.IX Item "-enable-no-infs-fp-math" +Enable optimizations that assume no Inf values. +.IP "\fB\-enable\-no\-nans\-fp\-math\fR" 4 +.IX Item "-enable-no-nans-fp-math" +Enable optimizations that assume no \s-1NAN\s0 values. +.IP "\fB\-enable\-unsafe\-fp\-math\fR" 4 +.IX Item "-enable-unsafe-fp-math" +Causes \fBlli\fR to enable optimizations that may decrease floating point +precision. +.IP "\fB\-soft\-float\fR" 4 +.IX Item "-soft-float" +Causes \fBlli\fR to generate software floating point library calls instead of +equivalent hardware instructions. +.SH "CODE GENERATION OPTIONS" +.IX Header "CODE GENERATION OPTIONS" +.IP "\fB\-code\-model\fR=\fImodel\fR" 4 +.IX Item "-code-model=model" +Choose the code model from: +.Sp +.Vb 5 +\& default: Target default code model +\& small: Small code model +\& kernel: Kernel code model +\& medium: Medium code model +\& large: Large code model +.Ve +.IP "\fB\-disable\-post\-RA\-scheduler\fR" 4 +.IX Item "-disable-post-RA-scheduler" +Disable scheduling after register allocation. +.IP "\fB\-disable\-spill\-fusing\fR" 4 +.IX Item "-disable-spill-fusing" +Disable fusing of spill code into instructions. +.IP "\fB\-enable\-correct\-eh\-support\fR" 4 +.IX Item "-enable-correct-eh-support" +Make the \-lowerinvoke pass insert expensive, but correct, \s-1EH\s0 code. +.IP "\fB\-jit\-enable\-eh\fR" 4 +.IX Item "-jit-enable-eh" +Exception handling should be enabled in the just-in-time compiler. +.IP "\fB\-join\-liveintervals\fR" 4 +.IX Item "-join-liveintervals" +Coalesce copies (default=true). +.IP "\fB\-nozero\-initialized\-in\-bss\fR Don't place zero-initialized symbols into the \s-1BSS\s0 section." 4 +.IX Item "-nozero-initialized-in-bss Don't place zero-initialized symbols into the BSS section." +.PD 0 +.IP "\fB\-pre\-RA\-sched\fR=\fIscheduler\fR" 4 +.IX Item "-pre-RA-sched=scheduler" +.PD +Instruction schedulers available (before register allocation): +.Sp +.Vb 7 +\& =default: Best scheduler for the target +\& =none: No scheduling: breadth first sequencing +\& =simple: Simple two pass scheduling: minimize critical path and maximize processor utilization +\& =simple\-noitin: Simple two pass scheduling: Same as simple except using generic latency +\& =list\-burr: Bottom\-up register reduction list scheduling +\& =list\-tdrr: Top\-down register reduction list scheduling +\& =list\-td: Top\-down list scheduler \-print\-machineinstrs \- Print generated machine code +.Ve +.IP "\fB\-regalloc\fR=\fIallocator\fR" 4 +.IX Item "-regalloc=allocator" +Register allocator to use (default=linearscan) +.Sp +.Vb 3 +\& =bigblock: Big\-block register allocator +\& =linearscan: linear scan register allocator =local \- local register allocator +\& =simple: simple register allocator +.Ve +.IP "\fB\-relocation\-model\fR=\fImodel\fR" 4 +.IX Item "-relocation-model=model" +Choose relocation model from: +.Sp +.Vb 3 +\& =default: Target default relocation model +\& =static: Non\-relocatable code =pic \- Fully relocatable, position independent code +\& =dynamic\-no\-pic: Relocatable external references, non\-relocatable code +.Ve +.IP "\fB\-spiller\fR" 4 +.IX Item "-spiller" +Spiller to use (default=local) +.Sp +.Vb 2 +\& =simple: simple spiller +\& =local: local spiller +.Ve +.IP "\fB\-x86\-asm\-syntax\fR=\fIsyntax\fR" 4 +.IX Item "-x86-asm-syntax=syntax" +Choose style of code to emit from X86 backend: +.Sp +.Vb 2 +\& =att: Emit AT&T\-style assembly +\& =intel: Emit Intel\-style assembly +.Ve +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBlli\fR fails to load the program, it will exit with an exit code of 1. +Otherwise, it will return the exit code of the program it executes. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +llc +.SH "AUTHOR" +.IX Header "AUTHOR" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-ar/Makefile b/usr.bin/clang/llvm-ar/Makefile new file mode 100644 index 000000000000..97ad058204d0 --- /dev/null +++ b/usr.bin/clang/llvm-ar/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ + +PROG_CXX=llvm-ar + +SRCDIR= tools/llvm-ar +SRCS= llvm-ar.cpp +LLVM_REQUIRES_EH= + +LIBDEPS=llvmarchive \ + llvmbitreader \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-ar/llvm-ar.1 b/usr.bin/clang/llvm-ar/llvm-ar.1 new file mode 100644 index 000000000000..4939f339357b --- /dev/null +++ b/usr.bin/clang/llvm-ar/llvm-ar.1 @@ -0,0 +1,461 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-AR 1" +.TH LLVM-AR 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-ar \- LLVM archiver +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-ar\fR [\-]{dmpqrtx}[Rabfikouz] [relpos] [count] [files...] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllvm-ar\fR command is similar to the common Unix utility, \f(CW\*(C`ar\*(C'\fR. It +archives several files together into a single file. The intent for this is +to produce archive libraries by \s-1LLVM\s0 bitcode that can be linked into an +\&\s-1LLVM\s0 program. However, the archive can contain any kind of file. By default, +\&\fBllvm-ar\fR generates a symbol table that makes linking faster because +only the symbol table needs to be consulted, not each individual file member +of the archive. +.PP +The \fBllvm-ar\fR command can be used to \fIread\fR both \s-1SVR4\s0 and \s-1BSD\s0 style archive +files. However, it cannot be used to write them. While the \fBllvm-ar\fR command +produces files that are \fIalmost\fR identical to the format used by other \f(CW\*(C`ar\*(C'\fR +implementations, it has two significant departures in order to make the +archive appropriate for \s-1LLVM\s0. The first departure is that \fBllvm-ar\fR only +uses \s-1BSD4\s0.4 style long path names (stored immediately after the header) and +never contains a string table for long names. The second departure is that the +symbol table is formated for efficient construction of an in-memory data +structure that permits rapid (red-black tree) lookups. Consequently, archives +produced with \fBllvm-ar\fR usually won't be readable or editable with any +\&\f(CW\*(C`ar\*(C'\fR implementation or useful for linking. Using the \f(CW\*(C`f\*(C'\fR modifier to flatten +file names will make the archive readable by other \f(CW\*(C`ar\*(C'\fR implementations +but not for linking because the symbol table format for \s-1LLVM\s0 is unique. If an +\&\s-1SVR4\s0 or \s-1BSD\s0 style archive is used with the \f(CW\*(C`r\*(C'\fR (replace) or \f(CW\*(C`q\*(C'\fR (quick +update) operations, the archive will be reconstructed in \s-1LLVM\s0 format. This +means that the string table will be dropped (in deference to \s-1BSD\s0 4.4 long names) +and an \s-1LLVM\s0 symbol table will be added (by default). The system symbol table +will be retained. +.PP +Here's where \fBllvm-ar\fR departs from previous \f(CW\*(C`ar\*(C'\fR implementations: +.IP "\fISymbol Table\fR" 4 +.IX Item "Symbol Table" +Since \fBllvm-ar\fR is intended to archive bitcode files, the symbol table +won't make much sense to anything but \s-1LLVM\s0. Consequently, the symbol table's +format has been simplified. It consists simply of a sequence of pairs +of a file member index number as an \s-1LSB\s0 4byte integer and a null-terminated +string. +.IP "\fILong Paths\fR" 4 +.IX Item "Long Paths" +Some \f(CW\*(C`ar\*(C'\fR implementations (\s-1SVR4\s0) use a separate file member to record long +path names (> 15 characters). \fBllvm-ar\fR takes the \s-1BSD\s0 4.4 and Mac \s-1OS\s0 X +approach which is to simply store the full path name immediately preceding +the data for the file. The path name is null terminated and may contain the +slash (/) character. +.IP "\fICompression\fR" 4 +.IX Item "Compression" +\&\fBllvm-ar\fR can compress the members of an archive to save space. The +compression used depends on what's available on the platform and what choices +the \s-1LLVM\s0 Compressor utility makes. It generally favors bzip2 but will select +between \*(L"no compression\*(R" or bzip2 depending on what makes sense for the +file's content. +.IP "\fIDirectory Recursion\fR" 4 +.IX Item "Directory Recursion" +Most \f(CW\*(C`ar\*(C'\fR implementations do not recurse through directories but simply +ignore directories if they are presented to the program in the \fIfiles\fR +option. \fBllvm-ar\fR, however, can recurse through directory structures and +add all the files under a directory, if requested. +.IP "\fI\s-1TOC\s0 Verbose Output\fR" 4 +.IX Item "TOC Verbose Output" +When \fBllvm-ar\fR prints out the verbose table of contents (\f(CW\*(C`tv\*(C'\fR option), it +precedes the usual output with a character indicating the basic kind of +content in the file. A blank means the file is a regular file. A 'Z' means +the file is compressed. A 'B' means the file is an \s-1LLVM\s0 bitcode file. An +\&'S' means the file is the symbol table. +.SH "OPTIONS" +.IX Header "OPTIONS" +The options to \fBllvm-ar\fR are compatible with other \f(CW\*(C`ar\*(C'\fR implementations. +However, there are a few modifiers (\fIzR\fR) that are not found in other +\&\f(CW\*(C`ar\*(C'\fRs. The options to \fBllvm-ar\fR specify a single basic operation to +perform on the archive, a variety of modifiers for that operation, the +name of the archive file, and an optional list of file names. These options +are used to determine how \fBllvm-ar\fR should process the archive file. +.PP +The Operations and Modifiers are explained in the sections below. The minimal +set of options is at least one operator and the name of the archive. Typically +archive files end with a \f(CW\*(C`.a\*(C'\fR suffix, but this is not required. Following +the \fIarchive-name\fR comes a list of \fIfiles\fR that indicate the specific members +of the archive to operate on. If the \fIfiles\fR option is not specified, it +generally means either \*(L"none\*(R" or \*(L"all\*(R" members, depending on the operation. +.SS "Operations" +.IX Subsection "Operations" +.IP "d" 4 +.IX Item "d" +Delete files from the archive. No modifiers are applicable to this operation. +The \fIfiles\fR options specify which members should be removed from the +archive. It is not an error if a specified file does not appear in the archive. +If no \fIfiles\fR are specified, the archive is not modified. +.IP "m[abi]" 4 +.IX Item "m[abi]" +Move files from one location in the archive to another. The \fIa\fR, \fIb\fR, and +\&\fIi\fR modifiers apply to this operation. The \fIfiles\fR will all be moved +to the location given by the modifiers. If no modifiers are used, the files +will be moved to the end of the archive. If no \fIfiles\fR are specified, the +archive is not modified. +.IP "p[k]" 4 +.IX Item "p[k]" +Print files to the standard output. The \fIk\fR modifier applies to this +operation. This operation simply prints the \fIfiles\fR indicated to the +standard output. If no \fIfiles\fR are specified, the entire archive is printed. +Printing bitcode files is ill-advised as they might confuse your terminal +settings. The \fIp\fR operation never modifies the archive. +.IP "q[Rfz]" 4 +.IX Item "q[Rfz]" +Quickly append files to the end of the archive. The \fIR\fR, \fIf\fR, and \fIz\fR +modifiers apply to this operation. This operation quickly adds the +\&\fIfiles\fR to the archive without checking for duplicates that should be +removed first. If no \fIfiles\fR are specified, the archive is not modified. +Because of the way that \fBllvm-ar\fR constructs the archive file, its dubious +whether the \fIq\fR operation is any faster than the \fIr\fR operation. +.IP "r[Rabfuz]" 4 +.IX Item "r[Rabfuz]" +Replace or insert file members. The \fIR\fR, \fIa\fR, \fIb\fR, \fIf\fR, \fIu\fR, and \fIz\fR +modifiers apply to this operation. This operation will replace existing +\&\fIfiles\fR or insert them at the end of the archive if they do not exist. If no +\&\fIfiles\fR are specified, the archive is not modified. +.IP "t[v]" 4 +.IX Item "t[v]" +Print the table of contents. Without any modifiers, this operation just prints +the names of the members to the standard output. With the \fIv\fR modifier, +\&\fBllvm-ar\fR also prints out the file type (B=bitcode, Z=compressed, S=symbol +table, blank=regular file), the permission mode, the owner and group, the +size, and the date. If any \fIfiles\fR are specified, the listing is only for +those files. If no \fIfiles\fR are specified, the table of contents for the +whole archive is printed. +.IP "x[oP]" 4 +.IX Item "x[oP]" +Extract archive members back to files. The \fIo\fR modifier applies to this +operation. This operation retrieves the indicated \fIfiles\fR from the archive +and writes them back to the operating system's file system. If no +\&\fIfiles\fR are specified, the entire archive is extract. +.SS "Modifiers (operation specific)" +.IX Subsection "Modifiers (operation specific)" +The modifiers below are specific to certain operations. See the Operations +section (above) to determine which modifiers are applicable to which operations. +.IP "[a]" 4 +.IX Item "[a]" +When inserting or moving member files, this option specifies the destination of +the new files as being \f(CW\*(C`a\*(C'\fRfter the \fIrelpos\fR member. If \fIrelpos\fR is not found, +the files are placed at the end of the archive. +.IP "[b]" 4 +.IX Item "[b]" +When inserting or moving member files, this option specifies the destination of +the new files as being \f(CW\*(C`b\*(C'\fRefore the \fIrelpos\fR member. If \fIrelpos\fR is not +found, the files are placed at the end of the archive. This modifier is +identical to the the \fIi\fR modifier. +.IP "[f]" 4 +.IX Item "[f]" +Normally, \fBllvm-ar\fR stores the full path name to a file as presented to it on +the command line. With this option, truncated (15 characters max) names are +used. This ensures name compatibility with older versions of \f(CW\*(C`ar\*(C'\fR but may also +thwart correct extraction of the files (duplicates may overwrite). If used with +the \fIR\fR option, the directory recursion will be performed but the file names +will all be \f(CW\*(C`f\*(C'\fRlattened to simple file names. +.IP "[i]" 4 +.IX Item "[i]" +A synonym for the \fIb\fR option. +.IP "[k]" 4 +.IX Item "[k]" +Normally, \fBllvm-ar\fR will not print the contents of bitcode files when the +\&\fIp\fR operation is used. This modifier defeats the default and allows the +bitcode members to be printed. +.IP "[N]" 4 +.IX Item "[N]" +This option is ignored by \fBllvm-ar\fR but provided for compatibility. +.IP "[o]" 4 +.IX Item "[o]" +When extracting files, this option will cause \fBllvm-ar\fR to preserve the +original modification times of the files it writes. +.IP "[P]" 4 +.IX Item "[P]" +use full path names when matching +.IP "[R]" 4 +.IX Item "[R]" +This modifier instructions the \fIr\fR option to recursively process directories. +Without \fIR\fR, directories are ignored and only those \fIfiles\fR that refer to +files will be added to the archive. When \fIR\fR is used, any directories specified +with \fIfiles\fR will be scanned (recursively) to find files to be added to the +archive. Any file whose name begins with a dot will not be added. +.IP "[u]" 4 +.IX Item "[u]" +When replacing existing files in the archive, only replace those files that have +a time stamp than the time stamp of the member in the archive. +.IP "[z]" 4 +.IX Item "[z]" +When inserting or replacing any file in the archive, compress the file first. +This +modifier is safe to use when (previously) compressed bitcode files are added to +the archive; the compressed bitcode files will not be doubly compressed. +.SS "Modifiers (generic)" +.IX Subsection "Modifiers (generic)" +The modifiers below may be applied to any operation. +.IP "[c]" 4 +.IX Item "[c]" +For all operations, \fBllvm-ar\fR will always create the archive if it doesn't +exist. Normally, \fBllvm-ar\fR will print a warning message indicating that the +archive is being created. Using this modifier turns off that warning. +.IP "[s]" 4 +.IX Item "[s]" +This modifier requests that an archive index (or symbol table) be added to the +archive. This is the default mode of operation. The symbol table will contain +all the externally visible functions and global variables defined by all the +bitcode files in the archive. Using this modifier is more efficient that using +llvm-ranlib which also creates the symbol table. +.IP "[S]" 4 +.IX Item "[S]" +This modifier is the opposite of the \fIs\fR modifier. It instructs \fBllvm-ar\fR to +not build the symbol table. If both \fIs\fR and \fIS\fR are used, the last modifier to +occur in the options will prevail. +.IP "[v]" 4 +.IX Item "[v]" +This modifier instructs \fBllvm-ar\fR to be verbose about what it is doing. Each +editing operation taken against the archive will produce a line of output saying +what is being done. +.SH "STANDARDS" +.IX Header "STANDARDS" +The \fBllvm-ar\fR utility is intended to provide a superset of the \s-1IEEE\s0 Std 1003.2 +(\s-1POSIX\s0.2) functionality for \f(CW\*(C`ar\*(C'\fR. \fBllvm-ar\fR can read both \s-1SVR4\s0 and \s-1BSD4\s0.4 (or +Mac \s-1OS\s0 X) archives. If the \f(CW\*(C`f\*(C'\fR modifier is given to the \f(CW\*(C`x\*(C'\fR or \f(CW\*(C`r\*(C'\fR operations +then \fBllvm-ar\fR will write \s-1SVR4\s0 compatible archives. Without this modifier, +\&\fBllvm-ar\fR will write \s-1BSD4\s0.4 compatible archives that have long names +immediately after the header and indicated using the \*(L"#1/ddd\*(R" notation for the +name in the header. +.SH "FILE FORMAT" +.IX Header "FILE FORMAT" +The file format for \s-1LLVM\s0 Archive files is similar to that of \s-1BSD\s0 4.4 or Mac \s-1OSX\s0 +archive files. In fact, except for the symbol table, the \f(CW\*(C`ar\*(C'\fR commands on those +operating systems should be able to read \s-1LLVM\s0 archive files. The details of the +file format follow. +.PP +Each archive begins with the archive magic number which is the eight printable +characters \*(L"!\en\*(R" where \en represents the newline character (0x0A). +Following the magic number, the file is composed of even length members that +begin with an archive header and end with a \en padding character if necessary +(to make the length even). Each file member is composed of a header (defined +below), an optional newline-terminated \*(L"long file name\*(R" and the contents of +the file. +.PP +The fields of the header are described in the items below. All fields of the +header contain only \s-1ASCII\s0 characters, are left justified and are right padded +with space characters. +.IP "name \- char[16]" 4 +.IX Item "name - char[16]" +This field of the header provides the name of the archive member. If the name is +longer than 15 characters or contains a slash (/) character, then this field +contains \f(CW\*(C`#1/nnn\*(C'\fR where \f(CW\*(C`nnn\*(C'\fR provides the length of the name and the \f(CW\*(C`#1/\*(C'\fR +is literal. In this case, the actual name of the file is provided in the \f(CW\*(C`nnn\*(C'\fR +bytes immediately following the header. If the name is 15 characters or less, it +is contained directly in this field and terminated with a slash (/) character. +.IP "date \- char[12]" 4 +.IX Item "date - char[12]" +This field provides the date of modification of the file in the form of a +decimal encoded number that provides the number of seconds since the epoch +(since 00:00:00 Jan 1, 1970) per Posix specifications. +.IP "uid \- char[6]" 4 +.IX Item "uid - char[6]" +This field provides the user id of the file encoded as a decimal \s-1ASCII\s0 string. +This field might not make much sense on non-Unix systems. On Unix, it is the +same value as the st_uid field of the stat structure returned by the \fIstat\fR\|(2) +operating system call. +.IP "gid \- char[6]" 4 +.IX Item "gid - char[6]" +This field provides the group id of the file encoded as a decimal \s-1ASCII\s0 string. +This field might not make much sense on non-Unix systems. On Unix, it is the +same value as the st_gid field of the stat structure returned by the \fIstat\fR\|(2) +operating system call. +.IP "mode \- char[8]" 4 +.IX Item "mode - char[8]" +This field provides the access mode of the file encoded as an octal \s-1ASCII\s0 +string. This field might not make much sense on non-Unix systems. On Unix, it +is the same value as the st_mode field of the stat structure returned by the +\&\fIstat\fR\|(2) operating system call. +.IP "size \- char[10]" 4 +.IX Item "size - char[10]" +This field provides the size of the file, in bytes, encoded as a decimal \s-1ASCII\s0 +string. If the size field is negative (starts with a minus sign, 0x02D), then +the archive member is stored in compressed form. The first byte of the archive +member's data indicates the compression type used. A value of 0 (0x30) indicates +that no compression was used. A value of 2 (0x32) indicates that bzip2 +compression was used. +.IP "fmag \- char[2]" 4 +.IX Item "fmag - char[2]" +This field is the archive file member magic number. Its content is always the +two characters back tick (0x60) and newline (0x0A). This provides some measure +utility in identifying archive files that have been corrupted. +.PP +The \s-1LLVM\s0 symbol table has the special name \*(L"#_LLVM_SYM_TAB_#\*(R". It is presumed +that no regular archive member file will want this name. The \s-1LLVM\s0 symbol table +is simply composed of a sequence of triplets: byte offset, length of symbol, +and the symbol itself. Symbols are not null or newline terminated. Here are +the details on each of these items: +.IP "offset \- vbr encoded 32\-bit integer" 4 +.IX Item "offset - vbr encoded 32-bit integer" +The offset item provides the offset into the archive file where the bitcode +member is stored that is associated with the symbol. The offset value is 0 +based at the start of the first \*(L"normal\*(R" file member. To derive the actual +file offset of the member, you must add the number of bytes occupied by the file +signature (8 bytes) and the symbol tables. The value of this item is encoded +using variable bit rate encoding to reduce the size of the symbol table. +Variable bit rate encoding uses the high bit (0x80) of each byte to indicate +if there are more bytes to follow. The remaining 7 bits in each byte carry bits +from the value. The final byte does not have the high bit set. +.IP "length \- vbr encoded 32\-bit integer" 4 +.IX Item "length - vbr encoded 32-bit integer" +The length item provides the length of the symbol that follows. Like this +\&\fIoffset\fR item, the length is variable bit rate encoded. +.IP "symbol \- character array" 4 +.IX Item "symbol - character array" +The symbol item provides the text of the symbol that is associated with the +\&\fIoffset\fR. The symbol is not terminated by any character. Its length is provided +by the \fIlength\fR field. Note that is allowed (but unwise) to use non-printing +characters (even 0x00) in the symbol. This allows for multiple encodings of +symbol names. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-ar\fR succeeds, it will exit with 0. A usage error, results +in an exit code of 1. A hard (file system typically) error results in an +exit code of 2. Miscellaneous or unknown errors result in an +exit code of 3. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +llvm-ranlib, \fIar\fR\|(1) +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-as/Makefile b/usr.bin/clang/llvm-as/Makefile new file mode 100644 index 000000000000..7e90878bb129 --- /dev/null +++ b/usr.bin/clang/llvm-as/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ + +PROG_CXX=llvm-as + +SRCDIR= tools/llvm-as +SRCS= llvm-as.cpp +LLVM_REQUIRES_EH= + +LIBDEPS=llvmbitwriter \ + llvmasmparser \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-as/llvm-as.1 b/usr.bin/clang/llvm-as/llvm-as.1 new file mode 100644 index 000000000000..662d06a3b2d6 --- /dev/null +++ b/usr.bin/clang/llvm-as/llvm-as.1 @@ -0,0 +1,182 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-AS 1" +.TH LLVM-AS 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-as \- LLVM assembler +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-as\fR [\fIoptions\fR] [\fIfilename\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBllvm-as\fR is the \s-1LLVM\s0 assembler. It reads a file containing human-readable +\&\s-1LLVM\s0 assembly language, translates it to \s-1LLVM\s0 bitcode, and writes the result +into a file or to standard output. +.PP +If \fIfilename\fR is omitted or is \f(CW\*(C`\-\*(C'\fR, then \fBllvm-as\fR reads its input from +standard input. +.PP +If an output file is not specified with the \fB\-o\fR option, then +\&\fBllvm-as\fR sends its output to a file or standard output by following +these rules: +.IP "\(bu" 4 +If the input is standard input, then the output is standard output. +.IP "\(bu" 4 +If the input is a file that ends with \f(CW\*(C`.ll\*(C'\fR, then the output file is of +the same name, except that the suffix is changed to \f(CW\*(C`.bc\*(C'\fR. +.IP "\(bu" 4 +If the input is a file that does not end with the \f(CW\*(C`.ll\*(C'\fR suffix, then the +output file has the same name as the input file, except that the \f(CW\*(C`.bc\*(C'\fR +suffix is appended. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-f\fR" 4 +.IX Item "-f" +Enable binary output on terminals. Normally, \fBllvm-as\fR will refuse to +write raw bitcode output if the output stream is a terminal. With this option, +\&\fBllvm-as\fR will write raw bitcode regardless of the output device. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-o\fR \fIfilename\fR" 4 +.IX Item "-o filename" +Specify the output file name. If \fIfilename\fR is \f(CW\*(C`\-\*(C'\fR, then \fBllvm-as\fR +sends its output to standard output. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-as\fR succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +llvm-dis, gccas +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-bcanalyzer/Makefile b/usr.bin/clang/llvm-bcanalyzer/Makefile new file mode 100644 index 000000000000..27788cc0a8b5 --- /dev/null +++ b/usr.bin/clang/llvm-bcanalyzer/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +PROG_CXX=llvm-bcanalyzer + +SRCDIR= tools/llvm-bcanalyzer +SRCS= llvm-bcanalyzer.cpp +LLVM_REQUIRES_EH= + +LIBDEPS=llvmbitreader \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-bcanalyzer/llvm-bcanalyzer.1 b/usr.bin/clang/llvm-bcanalyzer/llvm-bcanalyzer.1 new file mode 100644 index 000000000000..26777abaabb4 --- /dev/null +++ b/usr.bin/clang/llvm-bcanalyzer/llvm-bcanalyzer.1 @@ -0,0 +1,370 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-BCANALYZER 1" +.TH LLVM-BCANALYZER 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-bcanalyzer \- LLVM bitcode analyzer +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-bcanalyzer\fR [\fIoptions\fR] [\fIfilename\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllvm-bcanalyzer\fR command is a small utility for analyzing bitcode files. +The tool reads a bitcode file (such as generated with the \fBllvm-as\fR tool) and +produces a statistical report on the contents of the bitcode file. The tool +can also dump a low level but human readable version of the bitcode file. +This tool is probably not of much interest or utility except for those working +directly with the bitcode file format. Most \s-1LLVM\s0 users can just ignore +this tool. +.PP +If \fIfilename\fR is omitted or is \f(CW\*(C`\-\*(C'\fR, then \fBllvm-bcanalyzer\fR reads its input +from standard input. This is useful for combining the tool into a pipeline. +Output is written to the standard output. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-nodetails\fR" 4 +.IX Item "-nodetails" +Causes \fBllvm-bcanalyzer\fR to abbreviate its output by writing out only a module +level summary. The details for individual functions are not displayed. +.IP "\fB\-dump\fR" 4 +.IX Item "-dump" +Causes \fBllvm-bcanalyzer\fR to dump the bitcode in a human readable format. This +format is significantly different from \s-1LLVM\s0 assembly and provides details about +the encoding of the bitcode file. +.IP "\fB\-verify\fR" 4 +.IX Item "-verify" +Causes \fBllvm-bcanalyzer\fR to verify the module produced by reading the +bitcode. This ensures that the statistics generated are based on a consistent +module. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-bcanalyzer\fR succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value, usually 1. +.SH "SUMMARY OUTPUT DEFINITIONS" +.IX Header "SUMMARY OUTPUT DEFINITIONS" +The following items are always printed by llvm-bcanalyzer. They comprize the +summary output. +.IP "\fBBitcode Analysis Of Module\fR" 4 +.IX Item "Bitcode Analysis Of Module" +This just provides the name of the module for which bitcode analysis is being +generated. +.IP "\fBBitcode Version Number\fR" 4 +.IX Item "Bitcode Version Number" +The bitcode version (not \s-1LLVM\s0 version) of the file read by the analyzer. +.IP "\fBFile Size\fR" 4 +.IX Item "File Size" +The size, in bytes, of the entire bitcode file. +.IP "\fBModule Bytes\fR" 4 +.IX Item "Module Bytes" +The size, in bytes, of the module block. Percentage is relative to File Size. +.IP "\fBFunction Bytes\fR" 4 +.IX Item "Function Bytes" +The size, in bytes, of all the function blocks. Percentage is relative to File +Size. +.IP "\fBGlobal Types Bytes\fR" 4 +.IX Item "Global Types Bytes" +The size, in bytes, of the Global Types Pool. Percentage is relative to File +Size. This is the size of the definitions of all types in the bitcode file. +.IP "\fBConstant Pool Bytes\fR" 4 +.IX Item "Constant Pool Bytes" +The size, in bytes, of the Constant Pool Blocks Percentage is relative to File +Size. +.IP "\fBModule Globals Bytes\fR" 4 +.IX Item "Module Globals Bytes" +Ths size, in bytes, of the Global Variable Definitions and their initializers. +Percentage is relative to File Size. +.IP "\fBInstruction List Bytes\fR" 4 +.IX Item "Instruction List Bytes" +The size, in bytes, of all the instruction lists in all the functions. +Percentage is relative to File Size. Note that this value is also included in +the Function Bytes. +.IP "\fBCompaction Table Bytes\fR" 4 +.IX Item "Compaction Table Bytes" +The size, in bytes, of all the compaction tables in all the functions. +Percentage is relative to File Size. Note that this value is also included in +the Function Bytes. +.IP "\fBSymbol Table Bytes\fR" 4 +.IX Item "Symbol Table Bytes" +The size, in bytes, of all the symbol tables in all the functions. Percentage is +relative to File Size. Note that this value is also included in the Function +Bytes. +.IP "\fBDependent Libraries Bytes\fR" 4 +.IX Item "Dependent Libraries Bytes" +The size, in bytes, of the list of dependent libraries in the module. Percentage +is relative to File Size. Note that this value is also included in the Module +Global Bytes. +.IP "\fBNumber Of Bitcode Blocks\fR" 4 +.IX Item "Number Of Bitcode Blocks" +The total number of blocks of any kind in the bitcode file. +.IP "\fBNumber Of Functions\fR" 4 +.IX Item "Number Of Functions" +The total number of function definitions in the bitcode file. +.IP "\fBNumber Of Types\fR" 4 +.IX Item "Number Of Types" +The total number of types defined in the Global Types Pool. +.IP "\fBNumber Of Constants\fR" 4 +.IX Item "Number Of Constants" +The total number of constants (of any type) defined in the Constant Pool. +.IP "\fBNumber Of Basic Blocks\fR" 4 +.IX Item "Number Of Basic Blocks" +The total number of basic blocks defined in all functions in the bitcode file. +.IP "\fBNumber Of Instructions\fR" 4 +.IX Item "Number Of Instructions" +The total number of instructions defined in all functions in the bitcode file. +.IP "\fBNumber Of Long Instructions\fR" 4 +.IX Item "Number Of Long Instructions" +The total number of long instructions defined in all functions in the bitcode +file. Long instructions are those taking greater than 4 bytes. Typically long +instructions are GetElementPtr with several indices, \s-1PHI\s0 nodes, and calls to +functions with large numbers of arguments. +.IP "\fBNumber Of Operands\fR" 4 +.IX Item "Number Of Operands" +The total number of operands used in all instructions in the bitcode file. +.IP "\fBNumber Of Compaction Tables\fR" 4 +.IX Item "Number Of Compaction Tables" +The total number of compaction tables in all functions in the bitcode file. +.IP "\fBNumber Of Symbol Tables\fR" 4 +.IX Item "Number Of Symbol Tables" +The total number of symbol tables in all functions in the bitcode file. +.IP "\fBNumber Of Dependent Libs\fR" 4 +.IX Item "Number Of Dependent Libs" +The total number of dependent libraries found in the bitcode file. +.IP "\fBTotal Instruction Size\fR" 4 +.IX Item "Total Instruction Size" +The total size of the instructions in all functions in the bitcode file. +.IP "\fBAverage Instruction Size\fR" 4 +.IX Item "Average Instruction Size" +The average number of bytes per instruction across all functions in the bitcode +file. This value is computed by dividing Total Instruction Size by Number Of +Instructions. +.IP "\fBMaximum Type Slot Number\fR" 4 +.IX Item "Maximum Type Slot Number" +The maximum value used for a type's slot number. Larger slot number values take +more bytes to encode. +.IP "\fBMaximum Value Slot Number\fR" 4 +.IX Item "Maximum Value Slot Number" +The maximum value used for a value's slot number. Larger slot number values take +more bytes to encode. +.IP "\fBBytes Per Value\fR" 4 +.IX Item "Bytes Per Value" +The average size of a Value definition (of any type). This is computed by +dividing File Size by the total number of values of any type. +.IP "\fBBytes Per Global\fR" 4 +.IX Item "Bytes Per Global" +The average size of a global definition (constants and global variables). +.IP "\fBBytes Per Function\fR" 4 +.IX Item "Bytes Per Function" +The average number of bytes per function definition. This is computed by +dividing Function Bytes by Number Of Functions. +.IP "\fB# of \s-1VBR\s0 32\-bit Integers\fR" 4 +.IX Item "# of VBR 32-bit Integers" +The total number of 32\-bit integers encoded using the Variable Bit Rate +encoding scheme. +.IP "\fB# of \s-1VBR\s0 64\-bit Integers\fR" 4 +.IX Item "# of VBR 64-bit Integers" +The total number of 64\-bit integers encoded using the Variable Bit Rate encoding +scheme. +.IP "\fB# of \s-1VBR\s0 Compressed Bytes\fR" 4 +.IX Item "# of VBR Compressed Bytes" +The total number of bytes consumed by the 32\-bit and 64\-bit integers that use +the Variable Bit Rate encoding scheme. +.IP "\fB# of \s-1VBR\s0 Expanded Bytes\fR" 4 +.IX Item "# of VBR Expanded Bytes" +The total number of bytes that would have been consumed by the 32\-bit and 64\-bit +integers had they not been compressed with the Variable Bit Rage encoding +scheme. +.IP "\fBBytes Saved With \s-1VBR\s0\fR" 4 +.IX Item "Bytes Saved With VBR" +The total number of bytes saved by using the Variable Bit Rate encoding scheme. +The percentage is relative to # of \s-1VBR\s0 Expanded Bytes. +.SH "DETAILED OUTPUT DEFINITIONS" +.IX Header "DETAILED OUTPUT DEFINITIONS" +The following definitions occur only if the \-nodetails option was not given. +The detailed output provides additional information on a per-function basis. +.IP "\fBType\fR" 4 +.IX Item "Type" +The type signature of the function. +.IP "\fBByte Size\fR" 4 +.IX Item "Byte Size" +The total number of bytes in the function's block. +.IP "\fBBasic Blocks\fR" 4 +.IX Item "Basic Blocks" +The number of basic blocks defined by the function. +.IP "\fBInstructions\fR" 4 +.IX Item "Instructions" +The number of instructions defined by the function. +.IP "\fBLong Instructions\fR" 4 +.IX Item "Long Instructions" +The number of instructions using the long instruction format in the function. +.IP "\fBOperands\fR" 4 +.IX Item "Operands" +The number of operands used by all instructions in the function. +.IP "\fBInstruction Size\fR" 4 +.IX Item "Instruction Size" +The number of bytes consumed by instructions in the function. +.IP "\fBAverage Instruction Size\fR" 4 +.IX Item "Average Instruction Size" +The average number of bytes consumed by the instructions in the function. This +value is computed by dividing Instruction Size by Instructions. +.IP "\fBBytes Per Instruction\fR" 4 +.IX Item "Bytes Per Instruction" +The average number of bytes used by the function per instruction. This value is +computed by dividing Byte Size by Instructions. Note that this is not the same +as Average Instruction Size. It computes a number relative to the total function +size not just the size of the instruction list. +.IP "\fBNumber of \s-1VBR\s0 32\-bit Integers\fR" 4 +.IX Item "Number of VBR 32-bit Integers" +The total number of 32\-bit integers found in this function (for any use). +.IP "\fBNumber of \s-1VBR\s0 64\-bit Integers\fR" 4 +.IX Item "Number of VBR 64-bit Integers" +The total number of 64\-bit integers found in this function (for any use). +.IP "\fBNumber of \s-1VBR\s0 Compressed Bytes\fR" 4 +.IX Item "Number of VBR Compressed Bytes" +The total number of bytes in this function consumed by the 32\-bit and 64\-bit +integers that use the Variable Bit Rate encoding scheme. +.IP "\fBNumber of \s-1VBR\s0 Expanded Bytes\fR" 4 +.IX Item "Number of VBR Expanded Bytes" +The total number of bytes in this function that would have been consumed by +the 32\-bit and 64\-bit integers had they not been compressed with the Variable +Bit Rate encoding scheme. +.IP "\fBBytes Saved With \s-1VBR\s0\fR" 4 +.IX Item "Bytes Saved With VBR" +The total number of bytes saved in this function by using the Variable Bit +Rate encoding scheme. The percentage is relative to # of \s-1VBR\s0 Expanded Bytes. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +llvm-dis, +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-diff/Makefile b/usr.bin/clang/llvm-diff/Makefile new file mode 100644 index 000000000000..aedaff02a996 --- /dev/null +++ b/usr.bin/clang/llvm-diff/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +PROG_CXX=llvm-diff + +SRCDIR= tools/llvm-diff +SRCS= llvm-diff.cpp \ + DiffConsumer.cpp \ + DiffLog.cpp \ + DifferenceEngine.cpp + +LIBDEPS=llvmbitreader \ + llvmasmparser \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-diff/llvm-diff.1 b/usr.bin/clang/llvm-diff/llvm-diff.1 new file mode 100644 index 000000000000..00110ff6b721 --- /dev/null +++ b/usr.bin/clang/llvm-diff/llvm-diff.1 @@ -0,0 +1,175 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-DIFF 1" +.TH LLVM-DIFF 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-diff \- LLVM structural 'diff' +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-diff\fR [\fIoptions\fR] \fImodule 1\fR \fImodule 2\fR [\fIglobal name ...\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBllvm-diff\fR compares the structure of two \s-1LLVM\s0 modules, primarily +focusing on differences in function definitions. Insignificant +differences, such as changes in the ordering of globals or in the +names of local values, are ignored. +.PP +An input module will be interpreted as an assembly file if its name +ends in '.ll'; otherwise it will be read in as a bitcode file. +.PP +If a list of global names is given, just the values with those names +are compared; otherwise, all global values are compared, and +diagnostics are produced for globals which only appear in one module +or the other. +.PP +\&\fBllvm-diff\fR compares two functions by comparing their basic blocks, +beginning with the entry blocks. If the terminators seem to match, +then the corresponding successors are compared; otherwise they are +ignored. This algorithm is very sensitive to changes in control flow, +which tend to stop any downstream changes from being detected. +.PP +\&\fBllvm-diff\fR is intended as a debugging tool for writers of \s-1LLVM\s0 +passes and frontends. It does not have a stable output format. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-diff\fR finds no differences between the modules, it will exit +with 0 and produce no output. Otherwise it will exit with a non-zero +value. +.SH "BUGS" +.IX Header "BUGS" +Many important differences, like changes in linkage or function +attributes, are not diagnosed. +.PP +Changes in memory behavior (for example, coalescing loads) can cause +massive detected differences in blocks. +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-dis/Makefile b/usr.bin/clang/llvm-dis/Makefile new file mode 100644 index 000000000000..831bdbe3aa21 --- /dev/null +++ b/usr.bin/clang/llvm-dis/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +PROG_CXX=llvm-dis + +SRCDIR= tools/llvm-dis +SRCS= llvm-dis.cpp +LLVM_REQUIRES_EH= + +TGHDRS= Intrinsics +LIBDEPS=llvmanalysis \ + llvmtarget \ + llvmmc \ + llvmbitreader \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-dis/llvm-dis.1 b/usr.bin/clang/llvm-dis/llvm-dis.1 new file mode 100644 index 000000000000..ee119c0dd5a7 --- /dev/null +++ b/usr.bin/clang/llvm-dis/llvm-dis.1 @@ -0,0 +1,175 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-DIS 1" +.TH LLVM-DIS 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-dis \- LLVM disassembler +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-dis\fR [\fIoptions\fR] [\fIfilename\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllvm-dis\fR command is the \s-1LLVM\s0 disassembler. It takes an \s-1LLVM\s0 +bitcode file and converts it into human-readable \s-1LLVM\s0 assembly language. +.PP +If filename is omitted or specified as \f(CW\*(C`\-\*(C'\fR, \fBllvm-dis\fR reads its +input from standard input. +.PP +If the input is being read from standard input, then \fBllvm-dis\fR +will send its output to standard output by default. Otherwise, the +output will be written to a file named after the input file, with +a \f(CW\*(C`.ll\*(C'\fR suffix added (any existing \f(CW\*(C`.bc\*(C'\fR suffix will first be +removed). You can override the choice of output file using the +\&\fB\-o\fR option. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-f\fR" 4 +.IX Item "-f" +Enable binary output on terminals. Normally, \fBllvm-dis\fR will refuse to +write raw bitcode output if the output stream is a terminal. With this option, +\&\fBllvm-dis\fR will write raw bitcode regardless of the output device. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-o\fR \fIfilename\fR" 4 +.IX Item "-o filename" +Specify the output file name. If \fIfilename\fR is \-, then the output is sent +to standard output. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-dis\fR succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +llvm-as +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-extract/Makefile b/usr.bin/clang/llvm-extract/Makefile new file mode 100644 index 000000000000..ffedee406050 --- /dev/null +++ b/usr.bin/clang/llvm-extract/Makefile @@ -0,0 +1,22 @@ +# $FreeBSD$ + +PROG_CXX=llvm-extract + +SRCDIR= tools/llvm-extract +SRCS= llvm-extract.cpp + +LIBDEPS=llvmasmparser \ + llvmbitwriter \ + llvmbitreader \ + llvmipo \ + llvmscalaropts \ + llvminstcombine \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmmc \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-extract/llvm-extract.1 b/usr.bin/clang/llvm-extract/llvm-extract.1 new file mode 100644 index 000000000000..de8d34227c8f --- /dev/null +++ b/usr.bin/clang/llvm-extract/llvm-extract.1 @@ -0,0 +1,195 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-EXTRACT 1" +.TH LLVM-EXTRACT 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-extract \- extract a function from an LLVM module +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-extract\fR [\fIoptions\fR] \fB\-\-func\fR \fIfunction-name\fR [\fIfilename\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllvm-extract\fR command takes the name of a function and extracts it from +the specified \s-1LLVM\s0 bitcode file. It is primarily used as a debugging tool to +reduce test cases from larger programs that are triggering a bug. +.PP +In addition to extracting the bitcode of the specified function, +\&\fBllvm-extract\fR will also remove unreachable global variables, prototypes, and +unused types. +.PP +The \fBllvm-extract\fR command reads its input from standard input if filename is +omitted or if filename is \-. The output is always written to standard output, +unless the \fB\-o\fR option is specified (see below). +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-f\fR" 4 +.IX Item "-f" +Enable binary output on terminals. Normally, \fBllvm-extract\fR will refuse to +write raw bitcode output if the output stream is a terminal. With this option, +\&\fBllvm-extract\fR will write raw bitcode regardless of the output device. +.IP "\fB\-\-func\fR \fIfunction-name\fR" 4 +.IX Item "--func function-name" +Extract the function named \fIfunction-name\fR from the \s-1LLVM\s0 bitcode. May be +specified multiple times to extract multiple functions at once. +.IP "\fB\-\-rfunc\fR \fIfunction-regular-expr\fR" 4 +.IX Item "--rfunc function-regular-expr" +Extract the function(s) matching \fIfunction-regular-expr\fR from the \s-1LLVM\s0 bitcode. +All functions matching the regular expression will be extracted. May be +specified multiple times. +.IP "\fB\-\-glob\fR \fIglobal-name\fR" 4 +.IX Item "--glob global-name" +Extract the global variable named \fIglobal-name\fR from the \s-1LLVM\s0 bitcode. May be +specified multiple times to extract multiple global variables at once. +.IP "\fB\-\-rglob\fR \fIglob-regular-expr\fR" 4 +.IX Item "--rglob glob-regular-expr" +Extract the global variable(s) matching \fIglobal-regular-expr\fR from the \s-1LLVM\s0 +bitcode. All global variables matching the regular expression will be extracted. +May be specified multiple times. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-o\fR \fIfilename\fR" 4 +.IX Item "-o filename" +Specify the output filename. If filename is \*(L"\-\*(R" (the default), then +\&\fBllvm-extract\fR sends its output to standard output. +.IP "\fB\-S\fR" 4 +.IX Item "-S" +Write output in \s-1LLVM\s0 intermediate language (instead of bitcode). +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-extract\fR succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +bugpoint +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-ld/Makefile b/usr.bin/clang/llvm-ld/Makefile new file mode 100644 index 000000000000..d9c0bbae906b --- /dev/null +++ b/usr.bin/clang/llvm-ld/Makefile @@ -0,0 +1,25 @@ +# $FreeBSD$ + +PROG_CXX=llvm-ld + +SRCDIR= tools/llvm-ld +SRCS= Optimize.cpp \ + llvm-ld.cpp + +TGHDRS= Intrinsics +LIBDEPS=llvmbitwriter \ + llvmlinker \ + llvmarchive \ + llvmbitreader \ + llvmipo \ + llvmscalaropts \ + llvminstcombine \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmmc \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-ld/llvm-ld.1 b/usr.bin/clang/llvm-ld/llvm-ld.1 new file mode 100644 index 000000000000..451c446b0d5d --- /dev/null +++ b/usr.bin/clang/llvm-ld/llvm-ld.1 @@ -0,0 +1,319 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-LD 1" +.TH LLVM-LD 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-ld \- LLVM linker +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-ld\fR +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllvm-ld\fR tool takes a set of \s-1LLVM\s0 bitcode files and links them +together into a single \s-1LLVM\s0 bitcode file. The output bitcode file can be +another bitcode file or an executable bitcode program. Using additional +options, \fBllvm-ld\fR is able to produce native code executables. +.PP +The \fBllvm-ld\fR tool is the main linker for \s-1LLVM\s0. It is used to link together +the output of \s-1LLVM\s0 front-end compilers and run \*(L"link time\*(R" optimizations (mostly +the inter-procedural kind). +.PP +The \fBllvm-ld\fR tools attempts to mimic the interface provided by the default +system linker so that it can act as a \fIdrop-in\fR replacement. +.SS "Search Order" +.IX Subsection "Search Order" +When looking for objects specified on the command line, \fBllvm-ld\fR will search +for the object first in the current directory and then in the directory +specified by the \fB\s-1LLVM_LIB_SEARCH_PATH\s0\fR environment variable. If it cannot +find the object, it fails. +.PP +When looking for a library specified with the \fB\-l\fR option, \fBllvm-ld\fR first +attempts to load a file with that name from the current directory. If that +fails, it looks for lib\fIlibrary\fR.bc, lib\fIlibrary\fR.a, or lib\fIlibrary\fR.\fIshared +library extension\fR, in that order, in each directory added to the library search +path with the \fB\-L\fR option. These directories are searched in the order they +are specified. If the library cannot be located, then \fBllvm-ld\fR looks in the +directory specified by the \fB\s-1LLVM_LIB_SEARCH_PATH\s0\fR environment variable. If it +does not find a library there, it fails. +.PP +The \fIshared library extension\fR may be \fI.so\fR, \fI.dyld\fR, \fI.dll\fR, or something +different, depending upon the system. +.PP +The \fB\-L\fR option is global. It does not matter where it is specified in the +list of command line arguments; the directory is simply added to the search path +and is applied to all libraries, preceding or succeeding, in the command line. +.SS "Link order" +.IX Subsection "Link order" +All object and bitcode files are linked first in the order they were +specified on the command line. All library files are linked next. +Some libraries may not be linked into the object program; see below. +.SS "Library Linkage" +.IX Subsection "Library Linkage" +Object files and static bitcode objects are always linked into the output +file. Library archives (.a files) load only the objects within the archive +that define symbols needed by the output file. Hence, libraries should be +listed after the object files and libraries which need them; otherwise, the +library may not be linked in, and the dependent library will not have its +undefined symbols defined. +.SS "Native code generation" +.IX Subsection "Native code generation" +The \fBllvm-ld\fR program has limited support for native code generation, when +using the \fB\-native\fR or \fB\-native\-cbe\fR options. Native code generation is +performed by converting the linked bitcode into native assembly (.s) or C code +and running the system compiler (typically gcc) on the result. +.SH "OPTIONS" +.IX Header "OPTIONS" +.SS "General Options" +.IX Subsection "General Options" +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-v\fR" 4 +.IX Item "-v" +Specifies verbose mode. In this mode the linker will print additional +information about the actions it takes, programs it executes, etc. +.IP "\fB\-stats\fR" 4 +.IX Item "-stats" +Print statistics. +.IP "\fB\-time\-passes\fR" 4 +.IX Item "-time-passes" +Record the amount of time needed for each pass and print it to standard +error. +.SS "Input/Output Options" +.IX Subsection "Input/Output Options" +.IP "\fB\-o\fR \fIfilename\fR" 4 +.IX Item "-o filename" +This overrides the default output file and specifies the name of the file that +should be generated by the linker. By default, \fBllvm-ld\fR generates a file named +\&\fIa.out\fR for compatibility with \fBld\fR. The output will be written to +\&\fIfilename\fR. +.IP "\fB\-b\fR \fIfilename\fR" 4 +.IX Item "-b filename" +This option can be used to override the output bitcode file name. By default, +the name of the bitcode output file is one more \*(L".bc\*(R" suffix added to the name +specified by \fB\-o filename\fR option. +.IP "\fB\-l\fR\fIname\fR" 4 +.IX Item "-lname" +This option specifies the \fIname\fR of a library to search when resolving symbols +for the program. Only the base name should be specified as \fIname\fR, without a +\&\fIlib\fR prefix or any suffix. +.IP "\fB\-L\fR\fIPath\fR" 4 +.IX Item "-LPath" +This option tells \fBllvm-ld\fR to look in \fIPath\fR to find any library subsequently +specified with the \fB\-l\fR option. The paths will be searched in the order in +which they are specified on the command line. If the library is still not found, +a small set of system specific directories will also be searched. Note that +libraries specified with the \fB\-l\fR option that occur \fIbefore\fR any \fB\-L\fR options +will not search the paths given by the \fB\-L\fR options following it. +.IP "\fB\-link\-as\-library\fR" 4 +.IX Item "-link-as-library" +Link the bitcode files together as a library, not an executable. In this mode, +undefined symbols will be permitted. +.IP "\fB\-r\fR" 4 +.IX Item "-r" +An alias for \-link\-as\-library. +.IP "\fB\-native\fR" 4 +.IX Item "-native" +Generate a native machine code executable. +.Sp +When generating native executables, \fBllvm-ld\fR first checks for a bitcode +version of the library and links it in, if necessary. If the library is +missing, \fBllvm-ld\fR skips it. Then, \fBllvm-ld\fR links in the same +libraries as native code. +.Sp +In this way, \fBllvm-ld\fR should be able to link in optimized bitcode +subsets of common libraries and then link in any part of the library that +hasn't been converted to bitcode. +.IP "\fB\-native\-cbe\fR" 4 +.IX Item "-native-cbe" +Generate a native machine code executable with the \s-1LLVM\s0 C backend. +.Sp +This option is identical to the \fB\-native\fR option, but uses the +C backend to generate code for the program instead of an \s-1LLVM\s0 native +code generator. +.SS "Optimization Options" +.IX Subsection "Optimization Options" +.IP "\fB\-disable\-inlining\fR" 4 +.IX Item "-disable-inlining" +Do not run the inlining pass. Functions will not be inlined into other +functions. +.IP "\fB\-disable\-opt\fR" 4 +.IX Item "-disable-opt" +Completely disable optimization. +.IP "\fB\-disable\-internalize\fR" 4 +.IX Item "-disable-internalize" +Do not mark all symbols as internal. +.IP "\fB\-verify\-each\fR" 4 +.IX Item "-verify-each" +Run the verification pass after each of the passes to verify intermediate +results. +.IP "\fB\-strip\-all\fR" 4 +.IX Item "-strip-all" +Strip all debug and symbol information from the executable to make it smaller. +.IP "\fB\-strip\-debug\fR" 4 +.IX Item "-strip-debug" +Strip all debug information from the executable to make it smaller. +.IP "\fB\-s\fR" 4 +.IX Item "-s" +An alias for \fB\-strip\-all\fR. +.IP "\fB\-S\fR" 4 +.IX Item "-S" +An alias for \fB\-strip\-debug\fR. +.IP "\fB\-export\-dynamic\fR" 4 +.IX Item "-export-dynamic" +An alias for \fB\-disable\-internalize\fR +.IP "\fB\-post\-link\-opt\fR\fIPath\fR" 4 +.IX Item "-post-link-optPath" +Run post-link optimization program. After linking is completed a bitcode file +will be generated. It will be passed to the program specified by \fIPath\fR as the +first argument. The second argument to the program will be the name of a +temporary file into which the program should place its optimized output. For +example, the \*(L"no-op optimization\*(R" would be a simple shell script: +.Sp +.Vb 2 +\& #!/bin/bash +\& cp $1 $2 +.Ve +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-ld\fR succeeds, it will exit with 0 return code. If an error occurs, +it will exit with a non-zero return code. +.SH "ENVIRONMENT" +.IX Header "ENVIRONMENT" +The \f(CW\*(C`LLVM_LIB_SEARCH_PATH\*(C'\fR environment variable is used to find bitcode +libraries. Any paths specified in this variable will be searched after the \f(CW\*(C`\-L\*(C'\fR +options. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +llvm-link +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-link/Makefile b/usr.bin/clang/llvm-link/Makefile new file mode 100644 index 000000000000..25d33131b69f --- /dev/null +++ b/usr.bin/clang/llvm-link/Makefile @@ -0,0 +1,21 @@ +# $FreeBSD$ + +PROG_CXX=llvm-link + +SRCDIR= tools/llvm-link +SRCS= llvm-link.cpp + +LIBDEPS=llvmasmparser \ + llvmbitwriter \ + llvmlinker \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmmc \ + llvmarchive \ + llvmbitreader \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-link/llvm-link.1 b/usr.bin/clang/llvm-link/llvm-link.1 new file mode 100644 index 000000000000..fec826aea9e4 --- /dev/null +++ b/usr.bin/clang/llvm-link/llvm-link.1 @@ -0,0 +1,190 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-LINK 1" +.TH LLVM-LINK 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-link \- LLVM linker +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-link\fR [\fIoptions\fR] \fIfilename ...\fR +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBllvm-link\fR takes several \s-1LLVM\s0 bitcode files and links them together into a +single \s-1LLVM\s0 bitcode file. It writes the output file to standard output, unless +the \fB\-o\fR option is used to specify a filename. +.PP +\&\fBllvm-link\fR attempts to load the input files from the current directory. If +that fails, it looks for each file in each of the directories specified by the +\&\fB\-L\fR options on the command line. The library search paths are global; each +one is searched for every input file if necessary. The directories are searched +in the order they were specified on the command line. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-L\fR \fIdirectory\fR" 4 +.IX Item "-L directory" +Add the specified \fIdirectory\fR to the library search path. When looking for +libraries, \fBllvm-link\fR will look in path name for libraries. This option can be +specified multiple times; \fBllvm-link\fR will search inside these directories in +the order in which they were specified on the command line. +.IP "\fB\-f\fR" 4 +.IX Item "-f" +Enable binary output on terminals. Normally, \fBllvm-link\fR will refuse to +write raw bitcode output if the output stream is a terminal. With this option, +\&\fBllvm-link\fR will write raw bitcode regardless of the output device. +.IP "\fB\-o\fR \fIfilename\fR" 4 +.IX Item "-o filename" +Specify the output file name. If \fIfilename\fR is \f(CW\*(C`\-\*(C'\fR, then \fBllvm-link\fR will +write its output to standard output. +.IP "\fB\-S\fR" 4 +.IX Item "-S" +Write output in \s-1LLVM\s0 intermediate language (instead of bitcode). +.IP "\fB\-d\fR" 4 +.IX Item "-d" +If specified, \fBllvm-link\fR prints a human-readable version of the output +bitcode file to standard error. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-v\fR" 4 +.IX Item "-v" +Verbose mode. Print information about what \fBllvm-link\fR is doing. This +typically includes a message for each bitcode file linked in and for each +library found. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-link\fR succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +gccld +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-mc/Makefile b/usr.bin/clang/llvm-mc/Makefile new file mode 100644 index 000000000000..337218264412 --- /dev/null +++ b/usr.bin/clang/llvm-mc/Makefile @@ -0,0 +1,46 @@ +# $FreeBSD$ + +PROG_CXX=llvm-mc +NO_MAN= + +SRCDIR= tools/llvm-mc +SRCS= llvm-mc.cpp \ + Disassembler.cpp + +LIBDEPS=llvmmcdisassembler \ + llvmarmdisassembler \ + llvmarmasmparser \ + llvmarmcodegen \ + llvmarmdesc \ + llvmarminstprinter \ + llvmarminfo \ + llvmmipscodegen \ + llvmmipsdesc \ + llvmmipsinstprinter \ + llvmmipsinfo \ + llvmpowerpccodegen \ + llvmpowerpcdesc \ + llvmpowerpcinstprinter \ + llvmpowerpcinfo \ + llvmx86disassembler \ + llvmx86asmparser \ + llvmx86codegen \ + llvmx86desc \ + llvmselectiondag \ + llvmasmprinter \ + llvmmcparser \ + llvmcodegen \ + llvmscalaropts \ + llvminstcombine \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmx86instprinter \ + llvmx86utils \ + llvmcore \ + llvmx86info \ + llvmmc \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-nm/Makefile b/usr.bin/clang/llvm-nm/Makefile new file mode 100644 index 000000000000..1ac3a3d5d59a --- /dev/null +++ b/usr.bin/clang/llvm-nm/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ + +PROG_CXX=llvm-nm + +SRCDIR= tools/llvm-nm +SRCS= llvm-nm.cpp + +LIBDEPS=llvmobject \ + llvmarchive \ + llvmbitreader \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-nm/llvm-nm.1 b/usr.bin/clang/llvm-nm/llvm-nm.1 new file mode 100644 index 000000000000..c72e3bb33754 --- /dev/null +++ b/usr.bin/clang/llvm-nm/llvm-nm.1 @@ -0,0 +1,219 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-NM 1" +.TH LLVM-NM 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-nm \- list LLVM bitcode file's symbol table +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-nm\fR [\fIoptions\fR] [\fIfilenames...\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllvm-nm\fR utility lists the names of symbols from the \s-1LLVM\s0 bitcode files, +or \fBar\fR archives containing \s-1LLVM\s0 bitcode files, named on the command line. +Each symbol is listed along with some simple information about its provenance. +If no file name is specified, or \fI\-\fR is used as a file name, \fBllvm-nm\fR will +process a bitcode file on its standard input stream. +.PP +\&\fBllvm-nm\fR's default output format is the traditional \s-1BSD\s0 \fBnm\fR output format. +Each such output record consists of an (optional) 8\-digit hexadecimal address, +followed by a type code character, followed by a name, for each symbol. One +record is printed per line; fields are separated by spaces. When the address is +omitted, it is replaced by 8 spaces. +.PP +Type code characters currently supported, and their meanings, are as follows: +.IP "U" 4 +.IX Item "U" +Named object is referenced but undefined in this bitcode file +.IP "C" 4 +.IX Item "C" +Common (multiple definitions link together into one def) +.IP "W" 4 +.IX Item "W" +Weak reference (multiple definitions link together into zero or one definitions) +.IP "t" 4 +.IX Item "t" +Local function (text) object +.IP "T" 4 +.IX Item "T" +Global function (text) object +.IP "d" 4 +.IX Item "d" +Local data object +.IP "D" 4 +.IX Item "D" +Global data object +.IP "?" 4 +Something unrecognizable +.PP +Because \s-1LLVM\s0 bitcode files typically contain objects that are not considered to +have addresses until they are linked into an executable image or dynamically +compiled \*(L"just-in-time\*(R", \fBllvm-nm\fR does not print an address for any symbol, +even symbols which are defined in the bitcode file. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-P\fR" 4 +.IX Item "-P" +Use \s-1POSIX\s0.2 output format. Alias for \fB\-\-format=posix\fR. +.IP "\fB\-B\fR (default)" 4 +.IX Item "-B (default)" +Use \s-1BSD\s0 output format. Alias for \fB\-\-format=bsd\fR. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command-line options and their meanings. +.IP "\fB\-\-defined\-only\fR" 4 +.IX Item "--defined-only" +Print only symbols defined in this bitcode file (as opposed to +symbols which may be referenced by objects in this file, but not +defined in this file.) +.IP "\fB\-\-extern\-only\fR, \fB\-g\fR" 4 +.IX Item "--extern-only, -g" +Print only symbols whose definitions are external; that is, accessible +from other bitcode files. +.IP "\fB\-\-undefined\-only\fR, \fB\-u\fR" 4 +.IX Item "--undefined-only, -u" +Print only symbols referenced but not defined in this bitcode file. +.IP "\fB\-\-format=\fR\fIfmt\fR, \fB\-f\fR" 4 +.IX Item "--format=fmt, -f" +Select an output format; \fIfmt\fR may be \fIsysv\fR, \fIposix\fR, or \fIbsd\fR. The +default is \fIbsd\fR. +.SH "BUGS" +.IX Header "BUGS" +\&\fBllvm-nm\fR cannot demangle \*(C+ mangled names, like \s-1GNU\s0 \fBnm\fR can. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +\&\fBllvm-nm\fR exits with an exit code of zero. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +llvm-dis, \fIar\fR\|(1), \fInm\fR\|(1) +.SH "AUTHOR" +.IX Header "AUTHOR" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-objdump/Makefile b/usr.bin/clang/llvm-objdump/Makefile new file mode 100644 index 000000000000..a98cae506674 --- /dev/null +++ b/usr.bin/clang/llvm-objdump/Makefile @@ -0,0 +1,49 @@ +# $FreeBSD$ + +PROG_CXX=llvm-objdump +NO_MAN= + +SRCDIR= tools/llvm-objdump +SRCS= llvm-objdump.cpp \ + MachODump.cpp \ + MCFunction.cpp \ + +LIBDEPS=llvmobject \ + llvmmcdisassembler \ + llvmdebuginfo \ + llvmarmdisassembler \ + llvmarmasmparser \ + llvmarmcodegen \ + llvmarmdesc \ + llvmarminstprinter \ + llvmarminfo \ + llvmmipscodegen \ + llvmmipsdesc \ + llvmmipsinstprinter \ + llvmmipsinfo \ + llvmpowerpccodegen \ + llvmpowerpcdesc \ + llvmpowerpcinstprinter \ + llvmpowerpcinfo \ + llvmx86disassembler \ + llvmx86asmparser \ + llvmx86codegen \ + llvmx86desc \ + llvmselectiondag \ + llvmasmprinter \ + llvmmcparser \ + llvmcodegen \ + llvmscalaropts \ + llvminstcombine \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmx86instprinter \ + llvmx86utils \ + llvmcore \ + llvmx86info \ + llvmmc \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-prof/Makefile b/usr.bin/clang/llvm-prof/Makefile new file mode 100644 index 000000000000..fbe5df957254 --- /dev/null +++ b/usr.bin/clang/llvm-prof/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +PROG_CXX=llvm-prof + +SRCDIR= tools/llvm-prof +SRCS= llvm-prof.cpp + +LIBDEPS=llvmanalysis \ + llvmtarget \ + llvmmc \ + llvmbitreader \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-prof/llvm-prof.1 b/usr.bin/clang/llvm-prof/llvm-prof.1 new file mode 100644 index 000000000000..f7659fb62dc1 --- /dev/null +++ b/usr.bin/clang/llvm-prof/llvm-prof.1 @@ -0,0 +1,173 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-PROF 1" +.TH LLVM-PROF 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-prof \- print execution profile of LLVM program +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-prof\fR [\fIoptions\fR] [\fIbitcode file\fR] [\fIllvmprof.out\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllvm-prof\fR tool reads in an \fIllvmprof.out\fR file (which can +optionally use a specific file with the third program argument), a bitcode file +for the program, and produces a human readable report, suitable for determining +where the program hotspots are. +.PP +This program is often used in conjunction with the \fIutils/profile.pl\fR +script. This script automatically instruments a program, runs it with the \s-1JIT\s0, +then runs \fBllvm-prof\fR to format a report. To get more information about +\&\fIutils/profile.pl\fR, execute it with the \fB\-help\fR option. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-\-annotated\-llvm\fR or \fB\-A\fR" 4 +.IX Item "--annotated-llvm or -A" +In addition to the normal report printed, print out the code for the +program, annotated with execution frequency information. This can be +particularly useful when trying to visualize how frequently basic blocks +are executed. This is most useful with basic block profiling +information or better. +.IP "\fB\-\-print\-all\-code\fR" 4 +.IX Item "--print-all-code" +Using this option enables the \fB\-\-annotated\-llvm\fR option, but it +prints the entire module, instead of just the most commonly executed +functions. +.IP "\fB\-\-time\-passes\fR" 4 +.IX Item "--time-passes" +Record the amount of time needed for each pass and print it to standard +error. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +\&\fBllvm-prof\fR returns 1 if it cannot load the bitcode file or the profile +information. Otherwise, it exits with zero. +.SH "AUTHOR" +.IX Header "AUTHOR" +\&\fBllvm-prof\fR is maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-ranlib/Makefile b/usr.bin/clang/llvm-ranlib/Makefile new file mode 100644 index 000000000000..80e495cfb531 --- /dev/null +++ b/usr.bin/clang/llvm-ranlib/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ + +PROG_CXX=llvm-ranlib + +SRCDIR= tools/llvm-ranlib +SRCS= llvm-ranlib.cpp +LLVM_REQUIRES_EH= + +LIBDEPS=llvmarchive \ + llvmbitreader \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-ranlib/llvm-ranlib.1 b/usr.bin/clang/llvm-ranlib/llvm-ranlib.1 new file mode 100644 index 000000000000..08a3ef0eafd9 --- /dev/null +++ b/usr.bin/clang/llvm-ranlib/llvm-ranlib.1 @@ -0,0 +1,167 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "LLVM-RANLIB 1" +.TH LLVM-RANLIB 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +llvm\-ranlib \- Generate index for LLVM archive +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBllvm-ranlib\fR [\-\-version] [\-help] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBllvm-ranlib\fR command is similar to the common Unix utility, \f(CW\*(C`ranlib\*(C'\fR. It +adds or updates the symbol table in an \s-1LLVM\s0 archive file. Note that using the +\&\fBllvm-ar\fR modifier \fIs\fR is usually more efficient than running \fBllvm-ranlib\fR +which is only provided only for completness and compatibility. Unlike other +implementations of \f(CW\*(C`ranlib\*(C'\fR, \fBllvm-ranlib\fR indexes \s-1LLVM\s0 bitcode files, not +native object modules. You can list the contents of the symbol table with the +\&\f(CW\*(C`llvm\-nm \-s\*(C'\fR command. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fIarchive-file\fR" 4 +.IX Item "archive-file" +Specifies the archive-file to which the symbol table is added or updated. +.IP "\fI\-\-version\fR" 4 +.IX Item "--version" +Print the version of \fBllvm-ranlib\fR and exit without building a symbol table. +.IP "\fI\-help\fR" 4 +.IX Item "-help" +Print usage help for \fBllvm-ranlib\fR and exit without building a symbol table. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBllvm-ranlib\fR succeeds, it will exit with 0. If an error occurs, a non-zero +exit code will be returned. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +llvm-ar, \fIranlib\fR\|(1) +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/clang/llvm-rtdyld/Makefile b/usr.bin/clang/llvm-rtdyld/Makefile new file mode 100644 index 000000000000..489307a8644e --- /dev/null +++ b/usr.bin/clang/llvm-rtdyld/Makefile @@ -0,0 +1,48 @@ +# $FreeBSD$ + +PROG_CXX=llvm-rtdyld +NO_MAN= + +SRCDIR= tools/llvm-rtdyld +SRCS= llvm-rtdyld.cpp + +LIBDEPS=llvmjit \ + llvmexecutionengine \ + llvmruntimedyld \ + llvmobject \ + llvmarmdisassembler \ + llvmarmasmparser \ + llvmarmcodegen \ + llvmarmdesc \ + llvmarminstprinter \ + llvmarminfo \ + llvmmipscodegen \ + llvmmipsdesc \ + llvmmipsinstprinter \ + llvmmipsinfo \ + llvmpowerpccodegen \ + llvmpowerpcdesc \ + llvmpowerpcinstprinter \ + llvmpowerpcinfo \ + llvmx86disassembler \ + llvmx86asmparser \ + llvmx86codegen \ + llvmx86desc \ + llvmselectiondag \ + llvmasmprinter \ + llvmmcparser \ + llvmcodegen \ + llvmscalaropts \ + llvminstcombine \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmx86instprinter \ + llvmx86utils \ + llvmcore \ + llvmx86info \ + llvmmc \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/llvm-stub/Makefile b/usr.bin/clang/llvm-stub/Makefile new file mode 100644 index 000000000000..56e76605aa6f --- /dev/null +++ b/usr.bin/clang/llvm-stub/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PROG= llvm-stub +NO_MAN= + +SRCDIR= tools/llvm-stub +SRCS= llvm-stub.c + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/macho-dump/Makefile b/usr.bin/clang/macho-dump/Makefile new file mode 100644 index 000000000000..cb170d651f3b --- /dev/null +++ b/usr.bin/clang/macho-dump/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +PROG_CXX=macho-dump +NO_MAN= + +SRCDIR= tools/macho-dump +SRCS= macho-dump.cpp + +LIBDEPS=llvmobject \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/opt/Makefile b/usr.bin/clang/opt/Makefile new file mode 100644 index 000000000000..50d0c8831ad1 --- /dev/null +++ b/usr.bin/clang/opt/Makefile @@ -0,0 +1,27 @@ +# $FreeBSD$ + +PROG_CXX=opt + +SRCDIR= tools/opt +SRCS= AnalysisWrappers.cpp \ + GraphPrinters.cpp \ + PrintSCC.cpp \ + opt.cpp + +TGHDRS= Intrinsics +LIBDEPS=llvmipo \ + llvmscalaropts \ + llvminstcombine \ + llvminstrumentation \ + llvmtransformutils \ + llvmipa \ + llvmanalysis \ + llvmtarget \ + llvmmc \ + llvmasmparser \ + llvmbitwriter \ + llvmbitreader \ + llvmcore \ + llvmsupport + +.include "../clang.prog.mk" diff --git a/usr.bin/clang/opt/opt.1 b/usr.bin/clang/opt/opt.1 new file mode 100644 index 000000000000..95fdd076e1d7 --- /dev/null +++ b/usr.bin/clang/opt/opt.1 @@ -0,0 +1,250 @@ +.\" $FreeBSD$ +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "OPT 1" +.TH OPT 1 "2011-10-17" "LLVM 3.0" "LLVM Command Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +opt \- LLVM optimizer +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBopt\fR [\fIoptions\fR] [\fIfilename\fR] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \fBopt\fR command is the modular \s-1LLVM\s0 optimizer and analyzer. It takes \s-1LLVM\s0 +source files as input, runs the specified optimizations or analyses on it, and then +outputs the optimized file or the analysis results. The function of +\&\fBopt\fR depends on whether the \fB\-analyze\fR option is given. +.PP +When \fB\-analyze\fR is specified, \fBopt\fR performs various analyses of the input +source. It will usually print the results on standard output, but in a few +cases, it will print output to standard error or generate a file with the +analysis output, which is usually done when the output is meant for another +program. +.PP +While \fB\-analyze\fR is \fInot\fR given, \fBopt\fR attempts to produce an optimized +output file. The optimizations available via \fBopt\fR depend upon what +libraries were linked into it as well as any additional libraries that have +been loaded with the \fB\-load\fR option. Use the \fB\-help\fR option to determine +what optimizations you can use. +.PP +If \fIfilename\fR is omitted from the command line or is \fI\-\fR, \fBopt\fR reads its +input from standard input. Inputs can be in either the \s-1LLVM\s0 assembly language +format (.ll) or the \s-1LLVM\s0 bitcode format (.bc). +.PP +If an output filename is not specified with the \fB\-o\fR option, \fBopt\fR +writes its output to the standard output. +.SH "OPTIONS" +.IX Header "OPTIONS" +.IP "\fB\-f\fR" 4 +.IX Item "-f" +Enable binary output on terminals. Normally, \fBopt\fR will refuse to +write raw bitcode output if the output stream is a terminal. With this option, +\&\fBopt\fR will write raw bitcode regardless of the output device. +.IP "\fB\-help\fR" 4 +.IX Item "-help" +Print a summary of command line options. +.IP "\fB\-o\fR \fIfilename\fR" 4 +.IX Item "-o filename" +Specify the output filename. +.IP "\fB\-S\fR" 4 +.IX Item "-S" +Write output in \s-1LLVM\s0 intermediate language (instead of bitcode). +.IP "\fB\-{passname}\fR" 4 +.IX Item "-{passname}" +\&\fBopt\fR provides the ability to run any of \s-1LLVM\s0's optimization or analysis passes +in any order. The \fB\-help\fR option lists all the passes available. The order in +which the options occur on the command line are the order in which they are +executed (within pass constraints). +.IP "\fB\-std\-compile\-opts\fR" 4 +.IX Item "-std-compile-opts" +This is short hand for a standard list of \fIcompile time optimization\fR passes. +This is typically used to optimize the output from the llvm-gcc front end. It +might be useful for other front end compilers as well. To discover the full set +of options available, use the following command: +.Sp +.Vb 1 +\& llvm\-as < /dev/null | opt \-std\-compile\-opts \-disable\-output \-debug\-pass=Arguments +.Ve +.IP "\fB\-disable\-inlining\fR" 4 +.IX Item "-disable-inlining" +This option is only meaningful when \fB\-std\-compile\-opts\fR is given. It simply +removes the inlining pass from the standard list. +.IP "\fB\-disable\-opt\fR" 4 +.IX Item "-disable-opt" +This option is only meaningful when \fB\-std\-compile\-opts\fR is given. It disables +most, but not all, of the \fB\-std\-compile\-opts\fR. The ones that remain are +\&\fB\-verify\fR, \fB\-lower\-setjmp\fR, and \fB\-funcresolve\fR. +.IP "\fB\-strip\-debug\fR" 4 +.IX Item "-strip-debug" +This option causes opt to strip debug information from the module before +applying other optimizations. It is essentially the same as \fB\-strip\fR but it +ensures that stripping of debug information is done first. +.IP "\fB\-verify\-each\fR" 4 +.IX Item "-verify-each" +This option causes opt to add a verify pass after every pass otherwise specified +on the command line (including \fB\-verify\fR). This is useful for cases where it +is suspected that a pass is creating an invalid module but it is not clear which +pass is doing it. The combination of \fB\-std\-compile\-opts\fR and \fB\-verify\-each\fR +can quickly track down this kind of problem. +.IP "\fB\-profile\-info\-file\fR \fIfilename\fR" 4 +.IX Item "-profile-info-file filename" +Specify the name of the file loaded by the \-profile\-loader option. +.IP "\fB\-stats\fR" 4 +.IX Item "-stats" +Print statistics. +.IP "\fB\-time\-passes\fR" 4 +.IX Item "-time-passes" +Record the amount of time needed for each pass and print it to standard +error. +.IP "\fB\-debug\fR" 4 +.IX Item "-debug" +If this is a debug build, this option will enable debug printouts +from passes which use the \fI\s-1\fIDEBUG\s0()\fI\fR macro. See the \fB\s-1LLVM\s0 Programmer's +Manual\fR, section \fI#DEBUG\fR for more information. +.IP "\fB\-load\fR=\fIplugin\fR" 4 +.IX Item "-load=plugin" +Load the dynamic object \fIplugin\fR. This object should register new optimization +or analysis passes. Once loaded, the object will add new command line options to +enable various optimizations or analyses. To see the new complete list of +optimizations, use the \fB\-help\fR and \fB\-load\fR options together. For example: +.Sp +.Vb 1 +\& opt \-load=plugin.so \-help +.Ve +.IP "\fB\-p\fR" 4 +.IX Item "-p" +Print module after each transformation. +.SH "EXIT STATUS" +.IX Header "EXIT STATUS" +If \fBopt\fR succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. +.SH "AUTHORS" +.IX Header "AUTHORS" +Maintained by the \s-1LLVM\s0 Team (). diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c index 9acb50390b38..99ae8bf07ab8 100644 --- a/usr.bin/elfdump/elfdump.c +++ b/usr.bin/elfdump/elfdump.c @@ -904,7 +904,6 @@ elf_print_note(Elf32_Ehdr *e, void *sh) u_int64_t name; u_int32_t namesz; u_int32_t descsz; - u_int32_t type; u_int32_t desc; char *n, *s; @@ -916,7 +915,6 @@ elf_print_note(Elf32_Ehdr *e, void *sh) while (n < ((char *)e + offset + size)) { namesz = elf_get_word(e, n, N_NAMESZ); descsz = elf_get_word(e, n, N_DESCSZ); - type = elf_get_word(e, n, N_TYPE); s = n + sizeof(Elf_Note); desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0); fprintf(out, "\t%s %d\n", s, desc); diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c index 6014dddc47c2..9401ef8ce0e8 100644 --- a/usr.bin/fstat/fstat.c +++ b/usr.bin/fstat/fstat.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -224,28 +225,53 @@ static void print_file_info(struct procstat *procstat, struct filestat *fst, const char *uname, const char *cmd, int pid) { + struct sockstat sock; struct vnstat vn; DEVS *d; const char *filename; int error, fsmatch = 0; char errbuf[_POSIX2_LINE_MAX]; + error = 0; filename = NULL; if (checkfile != 0) { - if (fst->fs_type != PS_FST_TYPE_VNODE && - fst->fs_type != PS_FST_TYPE_FIFO) + switch (fst->fs_type) { + case PS_FST_TYPE_VNODE: + case PS_FST_TYPE_FIFO: + error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); + break; + case PS_FST_TYPE_SOCKET: + error = procstat_get_socket_info(procstat, fst, &sock, errbuf); + break; + default: return; - error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); + } if (error != 0) return; for (d = devs; d != NULL; d = d->next) - if (d->fsid == vn.vn_fsid) { - fsmatch = 1; - if ((unsigned)d->ino == vn.vn_fileid) { - filename = d->name; - break; + switch (fst->fs_type) { + case PS_FST_TYPE_VNODE: + case PS_FST_TYPE_FIFO: + if (d->fsid == vn.vn_fsid) { + fsmatch = 1; + if ((unsigned)d->ino == vn.vn_fileid) { + filename = d->name; + break; + } } + break; + case PS_FST_TYPE_SOCKET: + if (sock.dom_family == AF_UNIX) { + fsmatch = 1; + if (strcmp(((struct sockaddr_un *) + (&sock.sa_local))->sun_path, + d->name) == 0) { + filename = d->name; + break; + } + } + break; } if (fsmatch == 0 || (filename == NULL && fsflg == 0)) return; diff --git a/usr.bin/gencat/gencat.c b/usr.bin/gencat/gencat.c index 2ac5828a344e..40d68fc3dc76 100644 --- a/usr.bin/gencat/gencat.c +++ b/usr.bin/gencat/gencat.c @@ -462,89 +462,6 @@ MCParse(int fd) } } -void -MCReadCat(int fd) -{ - fd = 0; -#if 0 - MCHeaderT mcHead; - MCMsgT mcMsg; - MCSetT mcSet; - msgT *msg; - setT *set; - int i; - char *data; - - /* XXX init sethead? */ - - if (read(fd, &mcHead, sizeof(mcHead)) != sizeof(mcHead)) - CORRUPT(); - if (strncmp(mcHead.magic, MCMagic, MCMagicLen) != 0) - CORRUPT(); - if (mcHead.majorVer != MCMajorVer) - error("unrecognized catalog version"); - if ((mcHead.flags & MCGetByteOrder()) == 0) - error("wrong byte order"); - - if (lseek(fd, mcHead.firstSet, SEEK_SET) == -1) - CORRUPT(); - - for (;;) { - if (read(fd, &mcSet, sizeof(mcSet)) != sizeof(mcSet)) - CORRUPT(); - if (mcSet.invalid) - continue; - - set = xmalloc(sizeof(setT)); - memset(set, '\0', sizeof(*set)); - if (cat->first) { - cat->last->next = set; - set->prev = cat->last; - cat->last = set; - } else - cat->first = cat->last = set; - - set->setId = mcSet.setId; - - /* Get the data */ - if (mcSet.dataLen) { - data = xmalloc(mcSet.dataLen); - if (lseek(fd, mcSet.data.off, SEEK_SET) == -1) - CORRUPT(); - if (read(fd, data, mcSet.dataLen) != mcSet.dataLen) - CORRUPT(); - if (lseek(fd, mcSet.u.firstMsg, SEEK_SET) == -1) - CORRUPT(); - - for (i = 0; i < mcSet.numMsgs; ++i) { - if (read(fd, &mcMsg, sizeof(mcMsg)) != sizeof(mcMsg)) - CORRUPT(); - if (mcMsg.invalid) { - --i; - continue; - } - msg = xmalloc(sizeof(msgT)); - memset(msg, '\0', sizeof(*msg)); - if (set->first) { - set->last->next = msg; - msg->prev = set->last; - set->last = msg; - } else - set->first = set->last = msg; - - msg->msgId = mcMsg.msgId; - msg->str = xstrdup((char *) (data + mcMsg.msg.off)); - } - free(data); - } - if (!mcSet.nextSet) - break; - if (lseek(fd, mcSet.nextSet, SEEK_SET) == -1) - CORRUPT(); - } -#endif -} - /* * Write message catalog. * diff --git a/usr.bin/login/login_fbtab.c b/usr.bin/login/login_fbtab.c index ad64e4fad948..f642ea7e7f5b 100644 --- a/usr.bin/login/login_fbtab.c +++ b/usr.bin/login/login_fbtab.c @@ -100,17 +100,17 @@ login_fbtab(char *tty, uid_t uid, gid_t gid) if ((cp = devname = strtok(buf, WSPACE)) == 0) continue; /* empty or comment */ if (strncmp(devname, _PATH_DEV, sizeof _PATH_DEV - 1) != 0 - || (cp = strtok((char *) 0, WSPACE)) == 0 + || (cp = strtok(NULL, WSPACE)) == 0 || *cp != '0' || sscanf(cp, "%o", &prot) == 0 || prot == 0 || (prot & 0777) != prot - || (cp = strtok((char *) 0, WSPACE)) == 0) { + || (cp = strtok(NULL, WSPACE)) == 0) { syslog(LOG_ERR, "%s: bad entry: %s", table, cp ? cp : "(null)"); continue; } if (strcmp(devname + 5, tty) == 0) { - for (cp = strtok(cp, ":"); cp; cp = strtok((char *) 0, ":")) { + for (cp = strtok(cp, ":"); cp; cp = strtok(NULL, ":")) { login_protect(table, cp, prot, uid, gid); } } diff --git a/usr.bin/m4/lib/ohash_interval.3 b/usr.bin/m4/lib/ohash_interval.3 index 53d3a85b394c..12e762036ff5 100644 --- a/usr.bin/m4/lib/ohash_interval.3 +++ b/usr.bin/m4/lib/ohash_interval.3 @@ -28,7 +28,7 @@ .Fd #include .Fd #include .Fd #include -.Ft u_int32_t +.Ft uint32_t .Fn ohash_interval "const char *start" "const char **pend" .Ft "void *" .Fn ohash_create_entry "struct ohash_info *info" "const char *start" "const char **pend" diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c index 2798181d8527..bc1d6a076494 100644 --- a/usr.bin/make/job.c +++ b/usr.bin/make/job.c @@ -954,17 +954,19 @@ JobFinish(Job *job, int *status) lastNode = job->node; } fprintf(out, - "*** Completed successfully\n"); + "*** [%s] Completed successfully\n", + job->node->name); } } else { if (usePipes && job->node != lastNode) { MESSAGE(out, job->node); lastNode = job->node; } - fprintf(out, "*** Error code %d%s\n", + fprintf(out, "*** [%s] Error code %d%s\n", + job->node->name, WEXITSTATUS(*status), (job->flags & JOB_IGNERR) ? - "(ignored)" : ""); + " (ignored)" : ""); if (job->flags & JOB_IGNERR) { *status = 0; @@ -1005,7 +1007,8 @@ JobFinish(Job *job, int *status) MESSAGE(out, job->node); lastNode = job->node; } - fprintf(out, "*** Continued\n"); + fprintf(out, "*** [%s] Continued\n", + job->node->name); } if (!(job->flags & JOB_CONTINUING)) { DEBUGF(JOB, ("Warning: process %jd was not " @@ -1029,7 +1032,8 @@ JobFinish(Job *job, int *status) lastNode = job->node; } fprintf(out, - "*** Signal %d\n", WTERMSIG(*status)); + "*** [%s] Signal %d\n", job->node->name, + WTERMSIG(*status)); fflush(out); } } @@ -1056,7 +1060,8 @@ JobFinish(Job *job, int *status) MESSAGE(out, job->node); lastNode = job->node; } - fprintf(out, "*** Stopped -- signal %d\n", WSTOPSIG(*status)); + fprintf(out, "*** [%s] Stopped -- signal %d\n", + job->node->name, WSTOPSIG(*status)); job->flags |= JOB_RESUME; TAILQ_INSERT_TAIL(&stoppedJobs, job, link); fflush(out); @@ -3034,13 +3039,15 @@ Compat_RunCommand(LstNode *cmdNode, GNode *gn) if (status == 0) { return (0); } else { - printf("*** Error code %d", status); + printf("*** [%s] Error code %d", + gn->name, status); } } else if (WIFSTOPPED(reason)) { status = WSTOPSIG(reason); } else { status = WTERMSIG(reason); - printf("*** Signal %d", status); + printf("*** [%s] Signal %d", + gn->name, status); } if (ps.errCheck) { diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c index c9b2e7af8330..a54c3e996c01 100644 --- a/usr.bin/rpcgen/rpc_main.c +++ b/usr.bin/rpcgen/rpc_main.c @@ -75,13 +75,8 @@ static void s_output(int, const char **, const char *, const char *, int, const #define EXTEND 1 /* alias for TRUE */ #define DONT_EXTEND 0 /* alias for FALSE */ -#define SVR4_CPP "/usr/ccs/lib/cpp" -#define SUNOS_CPP "/usr/bin/cpp" - -static int cppDefined = 0; /* explicit path for C preprocessor */ - static const char *svcclosetime = "120"; -static const char *CPP = SVR4_CPP; +static const char *CPP = NULL; static const char CPPFLAGS[] = "-C"; static char pathbuf[MAXPATHLEN + 1]; static const char *allv[] = { @@ -97,7 +92,7 @@ static int allnc = sizeof (allnv)/sizeof (allnv[0]); * machinations for handling expanding argument list */ static void addarg(const char *); /* add another argument to the list */ -static void putarg(int, const char *); /* put argument at specified location */ +static void insarg(int, const char *); /* insert arg at specified location */ static void clear_args(void); /* clear argument list */ static void checkfiles(const char *, const char *); /* check if out file already exists */ @@ -105,7 +100,7 @@ static void checkfiles(const char *, const char *); #define ARGLISTLEN 20 -#define FIXEDARGS 2 +#define FIXEDARGS 0 static char *arglist[ARGLISTLEN]; static int argcount = FIXEDARGS; @@ -288,24 +283,29 @@ clear_args(void) argcount = FIXEDARGS; } -/* make sure that a CPP exists */ +/* prepend C-preprocessor and flags before arguments */ static void -find_cpp(void) +prepend_cpp(void) { - struct stat buf; + int idx = 1; + const char *var; + char *dupvar, *s, *t; - if (stat(CPP, &buf) < 0) { /* SVR4 or explicit cpp does not exist */ - if (cppDefined) { - warnx("cannot find C preprocessor: %s", CPP); - crash(); - } else { /* try the other one */ - CPP = SUNOS_CPP; - if (stat(CPP, &buf) < 0) { /* can't find any cpp */ - warnx("cannot find C preprocessor: %s", CPP); - crash(); - } + if (CPP != NULL) + insarg(0, CPP); + else if ((var = getenv("RPCGEN_CPP")) == NULL) + insarg(0, "/usr/bin/cpp"); + else { + /* Parse command line in a rudimentary way */ + dupvar = xstrdup(var); + for (s = dupvar, idx = 0; (t = strsep(&s, " \t")) != NULL; ) { + if (t[0]) + insarg(idx++, t); } + free(dupvar); } + + insarg(idx, CPPFLAGS); } /* @@ -320,9 +320,7 @@ open_input(const char *infile, const char *define) (void) pipe(pd); switch (childpid = fork()) { case 0: - find_cpp(); - putarg(0, CPP); - putarg(1, CPPFLAGS); + prepend_cpp(); addarg(define); if (infile) addarg(infile); @@ -330,8 +328,8 @@ open_input(const char *infile, const char *define) (void) close(1); (void) dup2(pd[1], 1); (void) close(pd[0]); - execv(arglist[0], arglist); - err(1, "execv"); + execvp(arglist[0], arglist); + err(1, "execvp %s", arglist[0]); case -1: err(1, "fork"); } @@ -934,18 +932,26 @@ addarg(const char *cp) } +/* + * Insert an argument at the specified location + */ static void -putarg(int place, const char *cp) +insarg(int place, const char *cp) { - if (place >= ARGLISTLEN) { - warnx("arglist coding error"); + int i; + + if (argcount >= ARGLISTLEN) { + warnx("too many defines"); crash(); /*NOTREACHED*/ } - if (cp != NULL) - arglist[place] = xstrdup(cp); - else - arglist[place] = NULL; + + /* Move up existing arguments */ + for (i = argcount - 1; i >= place; i--) + arglist[i + 1] = arglist[i]; + + arglist[place] = xstrdup(cp); + argcount++; } /* @@ -1125,14 +1131,15 @@ parseargs(int argc, const char *argv[], struct commandline *cmd) if (++i == argc) { return (0); } - (void) strlcpy(pathbuf, argv[i], sizeof(pathbuf)); - if (strlcat(pathbuf, "/cpp", sizeof(pathbuf)) - >= sizeof(pathbuf)) { + if (strlcpy(pathbuf, argv[i], + sizeof(pathbuf)) >= sizeof(pathbuf) + || strlcat(pathbuf, "/cpp", + sizeof(pathbuf)) >= + sizeof(pathbuf)) { warnx("argument too long"); return (0); } CPP = pathbuf; - cppDefined = 1; goto nextarg; diff --git a/usr.bin/rpcgen/rpcgen.1 b/usr.bin/rpcgen/rpcgen.1 index 2a4a25ecc51b..1389adf007fa 100644 --- a/usr.bin/rpcgen/rpcgen.1 +++ b/usr.bin/rpcgen/rpcgen.1 @@ -490,6 +490,11 @@ Give the name of the directory where .Nm will start looking for the C-preprocessor. .El +.Sh ENVIRONMENT +If the +.Ev RPCGEN_CPP +environment variable is set, its value is used as the command line of the +C preprocessor to be run on the input file. .Sh EXAMPLES The following example: .Dl example% rpcgen -T prot.x diff --git a/usr.bin/systat/icmp.c b/usr.bin/systat/icmp.c index 4a5a36cf91a5..e3a528047f7b 100644 --- a/usr.bin/systat/icmp.c +++ b/usr.bin/systat/icmp.c @@ -277,4 +277,3 @@ fetchicmp(void) if (sysctl(name, 4, &icmpstat, &len, 0, 0) < 0) return; } - diff --git a/usr.bin/systat/ifstat.c b/usr.bin/systat/ifstat.c index 77d4a3431d86..fc853b0c87b4 100644 --- a/usr.bin/systat/ifstat.c +++ b/usr.bin/systat/ifstat.c @@ -58,7 +58,6 @@ static const int col3 = C3; static const int col4 = C4; static const int col5 = C5; - SLIST_HEAD(, if_stat) curlist; SLIST_HEAD(, if_stat_disp) displist; @@ -85,7 +84,7 @@ static void sort_interface_list(void); static u_int getifnum(void); #define IFSTAT_ERR(n, s) do { \ - putchar(' '); \ + putchar('\014'); \ closeifstat(wnd); \ err((n), (s)); \ } while (0) @@ -143,7 +142,6 @@ static u_int getifnum(void); mvprintw(p->if_ypos+1, col2-3, "%s", (const char *)"out"); \ } while (0) - WINDOW * openifstat(void) { @@ -170,7 +168,6 @@ closeifstat(WINDOW *w) return; } - void labelifstat(void) { @@ -254,7 +251,6 @@ fetchifstat(void) IFSTAT_ERR(2, "error getting time of day"); (void)getifmibdata(ifp->if_row, &ifp->if_mib); - new_inb = ifp->if_mib.ifmd_data.ifi_ibytes; new_outb = ifp->if_mib.ifmd_data.ifi_obytes; diff --git a/usr.bin/systat/iostat.c b/usr.bin/systat/iostat.c index cd9e038a9b8d..3384f1533623 100644 --- a/usr.bin/systat/iostat.c +++ b/usr.bin/systat/iostat.c @@ -254,7 +254,6 @@ barlabels(int row) return (row); } - void showiostat(void) { diff --git a/usr.bin/systat/ip.c b/usr.bin/systat/ip.c index 43ec1fc0ca56..cad79b7f7ab8 100644 --- a/usr.bin/systat/ip.c +++ b/usr.bin/systat/ip.c @@ -337,4 +337,3 @@ fetchip(void) if (sysctl(name, 4, &curstat.u, &len, 0, 0) < 0) return; } - diff --git a/usr.bin/systat/netcmds.c b/usr.bin/systat/netcmds.c index e627329cda5f..7ee8f15a2734 100644 --- a/usr.bin/systat/netcmds.c +++ b/usr.bin/systat/netcmds.c @@ -121,7 +121,6 @@ netcmd(const char *cmd, const char *args) return (0); } - static void changeitems(const char *args, int onoff) { diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c index a5e06083c1f6..bb1318da37c8 100644 --- a/usr.bin/systat/netstat.c +++ b/usr.bin/systat/netstat.c @@ -349,7 +349,6 @@ enter_sysctl(struct inpcb *inp, struct xsocket *so, int state, const char *proto } } - static struct netinfo * enter(struct inpcb *inp, int state, const char *proto) { @@ -437,7 +436,6 @@ enter(struct inpcb *inp, int state, const char *proto) #define SNDCC RCVCC+7 #define STATE SNDCC+7 - void labelnetstat(void) { diff --git a/usr.bin/systat/pigs.c b/usr.bin/systat/pigs.c index 987df03da8a9..a02a43fe542c 100644 --- a/usr.bin/systat/pigs.c +++ b/usr.bin/systat/pigs.c @@ -81,7 +81,6 @@ closepigs(WINDOW *w) delwin(w); } - void showpigs(void) { diff --git a/usr.bin/systat/tcp.c b/usr.bin/systat/tcp.c index 76981e251a66..134aa9af986a 100644 --- a/usr.bin/systat/tcp.c +++ b/usr.bin/systat/tcp.c @@ -324,4 +324,3 @@ fetchtcp(void) if (sysctl(name, 4, &curstat, &len, 0, 0) < 0) return; } - diff --git a/usr.bin/touch/touch.1 b/usr.bin/touch/touch.1 index 1f3b8c20bc17..c2b0a607fa2d 100644 --- a/usr.bin/touch/touch.1 +++ b/usr.bin/touch/touch.1 @@ -31,7 +31,7 @@ .\" @(#)touch.1 8.3 (Berkeley) 4/28/95 .\" $FreeBSD$ .\" -.Dd April 28, 1995 +.Dd February 4, 2012 .Dt TOUCH 1 .Os .Sh NAME @@ -40,7 +40,7 @@ .Sh SYNOPSIS .Nm .Op Fl A Ar [-][[hh]mm]SS -.Op Fl acfhm +.Op Fl achm .Op Fl r Ar file .Op Fl t Ar [[CC]YY]MMDDhhmm[.SS] .Ar @@ -109,9 +109,6 @@ The .Nm utility does not treat this as an error. No error messages are displayed and the exit value is not affected. -.It Fl f -Attempt to force the update, even if the file permissions do not -currently permit it. .It Fl h If the file is a symbolic link, change the times of the link itself rather than the file that the link points to. diff --git a/usr.bin/touch/touch.c b/usr.bin/touch/touch.c index ce507b525e9f..7a613e887d49 100644 --- a/usr.bin/touch/touch.c +++ b/usr.bin/touch/touch.c @@ -55,7 +55,6 @@ static const char sccsid[] = "@(#)touch.c 8.1 (Berkeley) 6/6/93"; #include #include -int rw(char *, struct stat *, int); void stime_arg1(char *, struct timeval *); void stime_arg2(char *, int, struct timeval *); void stime_file(char *, struct timeval *); @@ -69,12 +68,12 @@ main(int argc, char *argv[]) struct timeval tv[2]; int (*stat_f)(const char *, struct stat *); int (*utimes_f)(const char *, const struct timeval *); - int Aflag, aflag, cflag, fflag, mflag, ch, fd, len, rval, timeset; + int Aflag, aflag, cflag, mflag, ch, fd, len, rval, timeset; char *p; char *myname; myname = basename(argv[0]); - Aflag = aflag = cflag = fflag = mflag = timeset = 0; + Aflag = aflag = cflag = mflag = timeset = 0; stat_f = stat; utimes_f = utimes; if (gettimeofday(&tv[0], NULL)) @@ -92,7 +91,7 @@ main(int argc, char *argv[]) cflag = 1; break; case 'f': - fflag = 1; + /* No-op for compatibility. */ break; case 'h': cflag = 1; @@ -222,14 +221,8 @@ main(int argc, char *argv[]) if (!utimes_f(*argv, NULL)) continue; - /* Try reading/writing. */ - if (!S_ISLNK(sb.st_mode) && !S_ISDIR(sb.st_mode)) { - if (rw(*argv, &sb, fflag)) - rval = 1; - } else { - rval = 1; - warn("%s", *argv); - } + rval = 1; + warn("%s", *argv); } exit(rval); } @@ -368,59 +361,10 @@ stime_file(char *fname, struct timeval *tvp) TIMESPEC_TO_TIMEVAL(tvp + 1, &sb.st_mtim); } -int -rw(char *fname, struct stat *sbp, int force) -{ - int fd, needed_chmod, rval; - u_char byte; - - /* Try regular files. */ - if (!S_ISREG(sbp->st_mode)) { - warnx("%s: %s", fname, strerror(EFTYPE)); - return (1); - } - - needed_chmod = rval = 0; - if ((fd = open(fname, O_RDWR, 0)) == -1) { - if (!force || chmod(fname, DEFFILEMODE)) - goto err; - if ((fd = open(fname, O_RDWR, 0)) == -1) - goto err; - needed_chmod = 1; - } - - if (sbp->st_size != 0) { - if (read(fd, &byte, sizeof(byte)) != sizeof(byte)) - goto err; - if (lseek(fd, (off_t)0, SEEK_SET) == -1) - goto err; - if (write(fd, &byte, sizeof(byte)) != sizeof(byte)) - goto err; - } else { - if (write(fd, &byte, sizeof(byte)) != sizeof(byte)) { -err: rval = 1; - warn("%s", fname); - } else if (ftruncate(fd, (off_t)0)) { - rval = 1; - warn("%s: file modified", fname); - } - } - - if (close(fd) && rval != 1) { - rval = 1; - warn("%s", fname); - } - if (needed_chmod && chmod(fname, sbp->st_mode) && rval != 1) { - rval = 1; - warn("%s: permissions modified", fname); - } - return (rval); -} - void usage(char *myname) { - fprintf(stderr, "usage:\n" "%s [-A [-][[hh]mm]SS] [-acfhm] [-r file] " + fprintf(stderr, "usage:\n" "%s [-A [-][[hh]mm]SS] [-achm] [-r file] " "[-t [[CC]YY]MMDDhhmm[.SS]] file ...\n", myname); exit(1); } diff --git a/usr.bin/who/who.1 b/usr.bin/who/who.1 index aadee185b74d..d4e0da937957 100644 --- a/usr.bin/who/who.1 +++ b/usr.bin/who/who.1 @@ -28,7 +28,7 @@ .\" @(#)who.1 8.2 (Berkeley) 12/30/93 .\" $FreeBSD$ .\" -.Dd Oct 28, 2011 +.Dd February 11, 2012 .Dt WHO 1 .Os .Sh NAME @@ -36,7 +36,7 @@ .Nd display who is on the system .Sh SYNOPSIS .Nm -.Op Fl bHmqsTu +.Op Fl abHmqsTu .Op Cm am I .Op Ar file .Sh DESCRIPTION @@ -48,6 +48,11 @@ remote hostname if not local. .Pp The options are as follows: .Bl -tag -width indent +.It Fl a +Equivalent to +.Fl bTu , +with the exception that output isn't restricted to the time and date of +the last system reboot. .It Fl b Write the time and date of the last system reboot. .It Fl H diff --git a/usr.bin/who/who.c b/usr.bin/who/who.c index 18467f3c5a24..75493b189611 100644 --- a/usr.bin/who/who.c +++ b/usr.bin/who/who.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include static void heading(void); -static void boottime(void); static void process_utmp(void); static void quick(void); static void row(const struct utmpx *); @@ -57,6 +56,7 @@ static void usage(void); static void whoami(void); static int Hflag; /* Write column headings */ +static int aflag; /* Print all entries */ static int bflag; /* Show date of the last reboot */ static int mflag; /* Show info about current terminal */ static int qflag; /* "Quick" mode */ @@ -71,7 +71,7 @@ main(int argc, char *argv[]) setlocale(LC_TIME, ""); - while ((ch = getopt(argc, argv, "HTbmqsu")) != -1) { + while ((ch = getopt(argc, argv, "HTabmqsu")) != -1) { switch (ch) { case 'H': /* Write column headings */ Hflag = 1; @@ -79,6 +79,9 @@ main(int argc, char *argv[]) case 'T': /* Show terminal state */ Tflag = 1; break; + case 'a': /* Same as -bdlprtTu */ + aflag = bflag = Tflag = uflag = 1; + break; case 'b': /* Show date of the last reboot */ bflag = 1; break; @@ -126,8 +129,6 @@ main(int argc, char *argv[]) heading(); if (mflag) whoami(); - else if (bflag) - boottime(); else process_utmp(); } @@ -141,7 +142,7 @@ static void usage(void) { - fprintf(stderr, "usage: who [-bHmqsTu] [am I] [file]\n"); + fprintf(stderr, "usage: who [-abHmqsTu] [am I] [file]\n"); exit(1); } @@ -226,25 +227,13 @@ process_utmp(void) struct utmpx *utx; while ((utx = getutxent()) != NULL) { - if (utx->ut_type != USER_PROCESS) - continue; - if (ttystat(utx->ut_line) != 0) - continue; - row(utx); + if (((aflag || !bflag) && utx->ut_type == USER_PROCESS) || + (bflag && utx->ut_type == BOOT_TIME)) + if (ttystat(utx->ut_line) == 0) + row(utx); } } -static void -boottime(void) -{ - struct utmpx u1, *u2; - - u1.ut_type = BOOT_TIME; - if ((u2 = getutxid(&u1)) == NULL) - return; - row(u2); -} - static void quick(void) { diff --git a/usr.bin/write/write.1 b/usr.bin/write/write.1 index 84b501866caa..4aa92c0d3255 100644 --- a/usr.bin/write/write.1 +++ b/usr.bin/write/write.1 @@ -31,7 +31,7 @@ .\" @(#)write.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd July 17, 2004 +.Dd February 13, 2012 .Dt WRITE 1 .Os .Sh NAME @@ -107,7 +107,3 @@ setting is used to determine which characters are safe to write to a terminal, not the receiver's (which .Nm has no way of knowing). -.Pp -The -.Nm -utility does not recognize multibyte characters. diff --git a/usr.bin/write/write.c b/usr.bin/write/write.c index acf996aae28c..2008fd2d80fa 100644 --- a/usr.bin/write/write.c +++ b/usr.bin/write/write.c @@ -60,12 +60,14 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include void done(int); void do_write(char *, char *, uid_t); static void usage(void); int term_chk(char *, int *, time_t *, int); -void wr_fputs(unsigned char *s); +void wr_fputs(wchar_t *s); void search_utmp(char *, char *, char *, uid_t); int utmp_chk(char *, char *); @@ -243,7 +245,8 @@ do_write(char *tty, char *mytty, uid_t myuid) char *nows; struct passwd *pwd; time_t now; - char path[MAXPATHLEN], host[MAXHOSTNAMELEN], line[512]; + char path[MAXPATHLEN], host[MAXHOSTNAMELEN]; + wchar_t line[512]; /* Determine our login name before we reopen() stdout */ if ((login = getlogin()) == NULL) { @@ -269,7 +272,7 @@ do_write(char *tty, char *mytty, uid_t myuid) (void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n", login, host, mytty, nows + 11); - while (fgets(line, sizeof(line), stdin) != NULL) + while (fgetws(line, sizeof(line)/sizeof(wchar_t), stdin) != NULL) wr_fputs(line); } @@ -288,30 +291,20 @@ done(int n __unused) * turns \n into \r\n */ void -wr_fputs(unsigned char *s) +wr_fputs(wchar_t *s) { -#define PUTC(c) if (putchar(c) == EOF) err(1, NULL); +#define PUTC(c) if (putwchar(c) == WEOF) err(1, NULL); - for (; *s != '\0'; ++s) { - if (*s == '\n') { - PUTC('\r'); - } else if (((*s & 0x80) && *s < 0xA0) || - /* disable upper controls */ - (!isprint(*s) && !isspace(*s) && - *s != '\a' && *s != '\b') - ) { - if (*s & 0x80) { - *s &= ~0x80; - PUTC('M'); - PUTC('-'); - } - if (iscntrl(*s)) { - *s ^= 0x40; - PUTC('^'); - } + for (; *s != L'\0'; ++s) { + if (*s == L'\n') { + PUTC(L'\r'); + PUTC(L'\n'); + } else if (iswprint(*s) || iswspace(*s)) { + PUTC(*s); + } else { + wprintf(L"<0x%X>", *s); } - PUTC(*s); } return; #undef PUTC diff --git a/usr.sbin/IPXrouted/tables.c b/usr.sbin/IPXrouted/tables.c index fe816b2d9271..aebc792b9cf1 100644 --- a/usr.sbin/IPXrouted/tables.c +++ b/usr.sbin/IPXrouted/tables.c @@ -172,7 +172,6 @@ rtadd_clone(struct rt_entry *ort, struct sockaddr *dst, { struct afhash h; register struct rt_entry *rt; - struct rthash *rh; int af = dst->sa_family, flags; u_int hash; @@ -183,7 +182,6 @@ rtadd_clone(struct rt_entry *ort, struct sockaddr *dst, (*afswitch[af].af_hash)(dst, &h); flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0; hash = h.afh_nethash; - rh = &nethash[hash & ROUTEHASHMASK]; rt = (struct rt_entry *)malloc(sizeof (*rt)); if (rt == 0) return; @@ -213,7 +211,6 @@ rtchange(struct rt_entry *rt, struct sockaddr *gate, short metric, short ticks) { int doioctl = 0, metricchanged = 0; - struct rtuentry oldroute; FIXLEN(gate); /* @@ -281,7 +278,6 @@ rtchange(struct rt_entry *rt, struct sockaddr *gate, short metric, if (doioctl || metricchanged) { TRACE_ACTION("CHANGE FROM", rt); if (doioctl) { - oldroute = rt->rt_rt; rt->rt_router = *gate; } rt->rt_metric = metric; diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index b7ea932b84bf..fa9883d1e90c 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -306,7 +306,7 @@ SUBDIR+= usbdump .if ${MK_UTMPX} != "no" SUBDIR+= ac SUBDIR+= lastlogin -SUBDIR+= utxrm +SUBDIR+= utx .endif .if ${MK_WIRELESS} != "no" diff --git a/usr.sbin/acpi/Makefile.inc b/usr.sbin/acpi/Makefile.inc index d729ed8a988e..d6ce93b124d5 100644 --- a/usr.sbin/acpi/Makefile.inc +++ b/usr.sbin/acpi/Makefile.inc @@ -11,15 +11,15 @@ CFLAGS+= -I${.CURDIR}/../../../sys .PATH: ${ACPICA_DIR} \ ${ACPICA_DIR}/common \ ${ACPICA_DIR}/compiler \ - ${ACPICA_DIR}/debugger \ - ${ACPICA_DIR}/disassembler \ - ${ACPICA_DIR}/dispatcher \ - ${ACPICA_DIR}/events \ - ${ACPICA_DIR}/executer \ - ${ACPICA_DIR}/hardware \ - ${ACPICA_DIR}/namespace \ - ${ACPICA_DIR}/os_specific/service_layers \ - ${ACPICA_DIR}/parser \ - ${ACPICA_DIR}/resources \ - ${ACPICA_DIR}/tables \ - ${ACPICA_DIR}/utilities + ${ACPICA_DIR}/components/debugger \ + ${ACPICA_DIR}/components/disassembler \ + ${ACPICA_DIR}/components/dispatcher \ + ${ACPICA_DIR}/components/events \ + ${ACPICA_DIR}/components/executer \ + ${ACPICA_DIR}/components/hardware \ + ${ACPICA_DIR}/components/namespace \ + ${ACPICA_DIR}/components/parser \ + ${ACPICA_DIR}/components/resources \ + ${ACPICA_DIR}/components/tables \ + ${ACPICA_DIR}/components/utilities \ + ${ACPICA_DIR}/os_specific/service_layers diff --git a/usr.sbin/acpi/acpidb/Makefile b/usr.sbin/acpi/acpidb/Makefile index 5c48dc6f8c15..9d2d7ece430f 100644 --- a/usr.sbin/acpi/acpidb/Makefile +++ b/usr.sbin/acpi/acpidb/Makefile @@ -3,58 +3,58 @@ PROG= acpidb SRCS= acpidb.c -# debugger +# components/debugger SRCS+= dbcmds.c dbdisply.c dbexec.c dbfileio.c dbhistry.c \ dbinput.c dbmethod.c dbnames.c dbstats.c dbutils.c \ dbxface.c -# disassembler +# components/disassembler SRCS+= dmbuffer.c dmnames.c dmobject.c dmopcode.c dmresrc.c \ dmresrcl.c dmresrcl2.c dmresrcs.c dmutils.c dmwalk.c -# events -SRCS+= evevent.c evglock.c evgpe.c evgpeblk.c evgpeinit.c \ - evgpeutil.c evmisc.c evregion.c evrgnini.c evsci.c \ - evxface.c evxfevnt.c evxfregn.c - -# hardware -SRCS+= hwacpi.c hwgpe.c hwpci.c hwregs.c hwsleep.c hwvalid.c \ - hwxface.c - -# interpreter/dispatcher +# components/dispatcher SRCS+= dsargs.c dscontrol.c dsfield.c dsinit.c dsmethod.c \ dsmthdat.c dsobject.c dsopcode.c dsutils.c dswexec.c \ dswload.c dswload2.c dswscope.c dswstate.c -# interpreter/executer +# components/events +SRCS+= evevent.c evglock.c evgpe.c evgpeblk.c evgpeinit.c \ + evgpeutil.c evmisc.c evregion.c evrgnini.c evsci.c \ + evxface.c evxfevnt.c evxfregn.c + +# components/executer SRCS+= exconfig.c exconvrt.c excreate.c exdebug.c exdump.c \ exfield.c exfldio.c exmisc.c exmutex.c exnames.c \ exoparg1.c exoparg2.c exoparg3.c exoparg6.c exprep.c \ exregion.c exresnte.c exresolv.c exresop.c exstore.c \ exstoren.c exstorob.c exsystem.c exutils.c -# interpreter/parser -SRCS+= psargs.c psloop.c psopcode.c psparse.c psscope.c \ - pstree.c psutils.c pswalk.c psxface.c +# components/hardware +SRCS+= hwacpi.c hwesleep.c hwgpe.c hwpci.c hwregs.c hwsleep.c \ + hwvalid.c hwxface.c hwxfsleep.c -# namespace +# components/namespace SRCS+= nsaccess.c nsalloc.c nsdump.c nseval.c nsinit.c \ nsload.c nsnames.c nsobject.c nsparse.c nspredef.c \ nsrepair.c nsrepair2.c nssearch.c nsutils.c nswalk.c \ nsxfeval.c nsxfname.c nsxfobj.c -# os_specific/service_layers +# components/parser +SRCS+= psargs.c psloop.c psopcode.c psparse.c psscope.c \ + pstree.c psutils.c pswalk.c psxface.c + +# components/os_specific/service_layers SRCS+= osunixxf.c -# resources +# components/resources SRCS+= rsaddr.c rscalc.c rscreate.c rsdump.c rsinfo.c \ rsio.c rsirq.c rslist.c rsmemory.c rsmisc.c \ rsserial.c rsutils.c rsxface.c -# tables +# components/tables SRCS+= tbfadt.c tbfind.c tbinstal.c tbutils.c tbxface.c -# utilities +# components/utilities SRCS+= utaddress.c utalloc.c utcache.c utcopy.c utdebug.c \ utdecode.c utdelete.c uteval.c utglobal.c utids.c \ utinit.c utlock.c utmath.c utmisc.c utmutex.c \ diff --git a/usr.sbin/acpi/iasl/Makefile b/usr.sbin/acpi/iasl/Makefile index 32942a105f09..02b0efe42e74 100644 --- a/usr.sbin/acpi/iasl/Makefile +++ b/usr.sbin/acpi/iasl/Makefile @@ -22,44 +22,44 @@ SRCS+= aslanalyze.c aslbtypes.c aslcodegen.c aslcompile.c \ dtparserparse.c dtsubtable.c dttable.c dttemplate.c \ dtutils.c -# debugger +# components/debugger SRCS+= dbfileio.c -# disassembler +# components/disassembler SRCS+= dmbuffer.c dmnames.c dmopcode.c dmresrc.c dmresrcl.c \ dmresrcl2.c dmresrcs.c dmutils.c dmwalk.c -# interpreter/dispatcher +# components/dispatcher SRCS+= dsargs.c dscontrol.c dsfield.c dsobject.c dsopcode.c \ dsutils.c dswexec.c dswload.c dswload2.c dswscope.c \ dswstate.c -# interpreter/executer +# components/executer SRCS+= exconvrt.c excreate.c exdump.c exmisc.c exmutex.c \ exnames.c exoparg1.c exoparg2.c exoparg3.c exoparg6.c \ exprep.c exresnte.c exresolv.c exresop.c exstore.c \ exstoren.c exstorob.c exsystem.c exutils.c -# interpreter/parser +# components/parser SRCS+= psargs.c psloop.c psopcode.c psparse.c psscope.c \ pstree.c psutils.c pswalk.c -# namespace +# components/namespace SRCS+= nsaccess.c nsalloc.c nsdump.c nsnames.c nsobject.c \ nsparse.c nssearch.c nsutils.c nswalk.c -# os_specific/service_layers -SRCS+= osunixxf.c - -# tables +# components/tables SRCS+= tbfadt.c tbinstal.c tbutils.c tbxface.c -# utilities +# components/utilities SRCS+= utaddress.c utalloc.c utcache.c utcopy.c utdebug.c \ utdecode.c utdelete.c utglobal.c utinit.c utlock.c \ utmath.c utmisc.c utmutex.c utobject.c utresrc.c \ utstate.c utxface.c utxferror.c +# os_specific/service_layers +SRCS+= osunixxf.c + WARNS?= 2 MAN= iasl.8 diff --git a/usr.sbin/amd/Makefile.inc b/usr.sbin/amd/Makefile.inc index 1965ff933e4c..cc616f1592f8 100644 --- a/usr.sbin/amd/Makefile.inc +++ b/usr.sbin/amd/Makefile.inc @@ -36,7 +36,7 @@ LIBAMUDIR= ${.CURDIR}/../libamu .endif LIBAMU= ${LIBAMUDIR}/libamu.a -RPCCOM= rpcgen +RPCCOM= RPCGEN_CPP=${CPP:Q} rpcgen MOUNT_X= ${DESTDIR}/usr/include/rpcsvc/mount.x NFS_PROT_X= ${DESTDIR}/usr/include/rpcsvc/nfs_prot.x diff --git a/usr.sbin/boot0cfg/boot0cfg.8 b/usr.sbin/boot0cfg/boot0cfg.8 index 1efd3057cf23..f3c942bf27f7 100644 --- a/usr.sbin/boot0cfg/boot0cfg.8 +++ b/usr.sbin/boot0cfg/boot0cfg.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 7, 2011 +.Dd February 4, 2012 .Dt BOOT0CFG 8 .Os .Sh NAME @@ -114,6 +114,9 @@ Specify slices to be enabled/disabled, where .Ar mask is an integer between 0 (no slices enabled) and 0xf (all four slices enabled). +Each mask bit enables corresponding slice if set to 1. +The least significant bit of the mask corresponds to slice 1, +the most significant bit of the mask corresponds to slice 4. .It Fl o Ar options A comma-separated string of any of the following options may be specified (with @@ -172,9 +175,9 @@ To boot slice 2 on the next boot: .Pp .Dl "boot0cfg -s 2 ad0" .Pp -To enable just slices 1 and 2 in the menu: +To enable just slices 1 and 3 in the menu: .Pp -.Dl "boot0cfg -m 0x3 ad0" +.Dl "boot0cfg -m 0x5 ad0" .Pp To go back to non-interactive booting, use .Xr fdisk 8 diff --git a/usr.sbin/bootparamd/bootparamd/Makefile b/usr.sbin/bootparamd/bootparamd/Makefile index 5d2047b463cc..a5163a3873ab 100644 --- a/usr.sbin/bootparamd/bootparamd/Makefile +++ b/usr.sbin/bootparamd/bootparamd/Makefile @@ -18,12 +18,12 @@ CLEANFILES= ${GENSRCS} RPCSRC= ${DESTDIR}/usr/include/rpcsvc/bootparam_prot.x bootparam_prot_svc.c: ${RPCSRC} - rpcgen -C -m -o ${.TARGET} ${RPCSRC} + RPCGEN_CPP=${CPP:Q} rpcgen -C -m -o ${.TARGET} ${RPCSRC} bootparam_prot_xdr.c: ${RPCSRC} - rpcgen -C -c -o ${.TARGET} ${RPCSRC} + RPCGEN_CPP=${CPP:Q} rpcgen -C -c -o ${.TARGET} ${RPCSRC} bootparam_prot.h: ${RPCSRC} - rpcgen -C -h -o ${.TARGET} ${RPCSRC} + RPCGEN_CPP=${CPP:Q} rpcgen -C -h -o ${.TARGET} ${RPCSRC} .include diff --git a/usr.sbin/bootparamd/callbootd/Makefile b/usr.sbin/bootparamd/callbootd/Makefile index 5a08d608a4c8..0137407f818d 100644 --- a/usr.sbin/bootparamd/callbootd/Makefile +++ b/usr.sbin/bootparamd/callbootd/Makefile @@ -13,12 +13,12 @@ CLEANFILES= ${GENSRCS} RPCSRC= ${DESTDIR}/usr/include/rpcsvc/bootparam_prot.x bootparam_prot_clnt.c: ${RPCSRC} - rpcgen -C -l -o ${.TARGET} ${RPCSRC} + RPCGEN_CPP=${CPP:Q} rpcgen -C -l -o ${.TARGET} ${RPCSRC} bootparam_prot_xdr.c: ${RPCSRC} - rpcgen -C -c -o ${.TARGET} ${RPCSRC} + RPCGEN_CPP=${CPP:Q} rpcgen -C -c -o ${.TARGET} ${RPCSRC} bootparam_prot.h: ${RPCSRC} - rpcgen -C -h -o ${.TARGET} ${RPCSRC} + RPCGEN_CPP=${CPP:Q} rpcgen -C -h -o ${.TARGET} ${RPCSRC} .include diff --git a/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 b/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 index a7f99de59269..ceab05126a1e 100644 --- a/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 +++ b/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 @@ -78,7 +78,7 @@ .Ft typedef void .Fn ng_hook_f "const char *hook" "const u_char *mesg" "size_t len" "void *uarg" .Ft void * -.Fn ng_register_cookie "const struct lmodule *mod" "u_int32_t cookie" "ng_ID_t id" "ng_cookie_f *func" "void *uarg" +.Fn ng_register_cookie "const struct lmodule *mod" "uint32_t cookie" "ng_ID_t id" "ng_cookie_f *func" "void *uarg" .Ft void .Fn ng_unregister_cookie "void *reg" .Ft void * diff --git a/usr.sbin/gssd/Makefile b/usr.sbin/gssd/Makefile index 45d8de4d43fe..3fab810f0165 100644 --- a/usr.sbin/gssd/Makefile +++ b/usr.sbin/gssd/Makefile @@ -13,7 +13,7 @@ LDADD= -lgssapi CLEANFILES= gssd_svc.c gssd.h RPCSRC= ${.CURDIR}/../../sys/kgssapi/gssd.x -RPCGEN= rpcgen -L -C -M +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -L -C -M gssd_svc.c: ${RPCSRC} gssd.h ${RPCGEN} -m -o ${.TARGET} ${RPCSRC} diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8 index c5a2245b0a3d..5cd77fc705c3 100644 --- a/usr.sbin/jail/jail.8 +++ b/usr.sbin/jail/jail.8 @@ -34,7 +34,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 23, 2011 +.Dd February 9, 2012 .Dt JAIL 8 .Os .Sh NAME @@ -301,6 +301,17 @@ A jail never has a lower securelevel than the default system, but by setting this parameter it may have a higher one. If the system securelevel is changed, any jail securelevels will be at least as secure. +.It Va devfs_ruleset +The number of the devfs ruleset that is enforced for mounting devfs in +this jail and its descendants. A value of zero means no ruleset is enforced +or if set inside a jail for a descendant jail, the parent jails's devfs +ruleset enforcement is inherited. A value of -1 (default) means mounting a +devfs filesystem is not allowed. Mounting devfs inside a jail is possible +only if the +.Va allow.mount +permission is effective and +.Va enforce_statfs +is set to a value lower than 2. .It Va children.max The number of child jails allowed to be created by this jail (or by other jails under this jail). diff --git a/usr.sbin/keyserv/Makefile b/usr.sbin/keyserv/Makefile index 37a416f8dfc5..4308b40f2020 100644 --- a/usr.sbin/keyserv/Makefile +++ b/usr.sbin/keyserv/Makefile @@ -15,7 +15,7 @@ RPCDIR= ${DESTDIR}/usr/include/rpcsvc CLEANFILES= crypt_svc.c crypt.h -RPCGEN= rpcgen -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -C crypt_svc.c: ${RPCDIR}/crypt.x ${RPCGEN} -m -o ${.TARGET} ${RPCDIR}/crypt.x diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c index 287825f202cb..6118f47a287f 100644 --- a/usr.sbin/lpr/lpc/cmds.c +++ b/usr.sbin/lpr/lpc/cmds.c @@ -77,7 +77,7 @@ __FBSDID("$FreeBSD$"); static char *args2line(int argc, char **argv); static int doarg(char *_job); -static int doselect(struct dirent *_d); +static int doselect(const struct dirent *_d); static int kill_qtask(const char *lf); static int sortq(const void *_a, const void *_b); static int touch(struct jobqueue *_jq); @@ -376,7 +376,7 @@ upstat(struct printer *pp, const char *msg, int notifyuser) return; } (void) ftruncate(fd, 0); - if (msg == (char *)NULL) + if (msg == NULL) (void) write(fd, "\n", 1); else (void) write(fd, msg, strlen(msg)); @@ -451,7 +451,7 @@ static int cln_queuecnt; /* number of queues checked */ static int cln_testonly; /* remove-files vs just-print-info */ static int -doselect(struct dirent *d) +doselect(const struct dirent *d) { int c = d->d_name[0]; diff --git a/usr.sbin/periodic/periodic.sh b/usr.sbin/periodic/periodic.sh index ca954ea1f026..cfe61092e18f 100644 --- a/usr.sbin/periodic/periodic.sh +++ b/usr.sbin/periodic/periodic.sh @@ -14,6 +14,18 @@ usage () { exit 1 } +output_pipe() +{ + # Where's our output going ? + eval output=\$${1##*/}_output + case "$output" in + /*) pipe="cat >>$output";; + "") pipe=cat;; + *) pipe="mail -E -s '$host ${1##*/} run output' $output";; + esac + eval $pipe +} + if [ $# -lt 1 ] ; then usage fi @@ -27,83 +39,102 @@ fi host=`hostname` export host + +# If we were called normally, then create a lock file for each argument +# in turn and reinvoke ourselves with the LOCKED argument. This prevents +# very long running jobs from being overlapped by another run as this is +# will lead the system running progressivly slower and more and more jobs +# are run at once. +if [ $1 != "LOCKED" ]; then + ret=0 + for arg; do + lockfile=/var/run/periodic.${arg##*/}.lock + lockf -t 0 "${lockfile}" /bin/sh $0 LOCKED "$arg" + case $? in + 0) ;; + 73) #EX_CANTCREATE + echo "can't create ${lockfile}" | output_pipe $arg + ret=1 + ;; + 75) #EX_TEMPFAIL + echo "$host ${arg##*/} prior run still in progress" | \ + output_pipe $arg + ret=1 + ;; + *) + ret=1 + ;; + esac + done + exit $ret +fi + +if [ $# -ne 2 ]; then + usage +fi +shift +arg=$1 + tmp_output=`mktemp ${TMPDIR:-/tmp}/periodic.XXXXXXXXXX` # Execute each executable file in the directory list. If the x bit is not # set, assume the user didn't really want us to muck with it (it's a # README file or has been disabled). -for arg -do - # Where's our output going ? - eval output=\$${arg##*/}_output - case "$output" in - /*) pipe="cat >>$output";; - "") pipe=cat;; - *) pipe="mail -E -s '$host ${arg##*/} run output' $output";; +success=YES info=YES badconfig=NO empty_output=YES # Defaults when ${run}_* aren't YES/NO +for var in success info badconfig empty_output; do + case $(eval echo "\$${arg##*/}_show_$var") in + [Yy][Ee][Ss]) eval $var=YES;; + [Nn][Oo]) eval $var=NO;; esac +done - success=YES info=YES badconfig=NO empty_output=YES # Defaults when ${run}_* aren't YES/NO - for var in success info badconfig empty_output - do - case $(eval echo "\$${arg##*/}_show_$var") in - [Yy][Ee][Ss]) eval $var=YES;; - [Nn][Oo]) eval $var=NO;; - esac +case $arg in +/*) if [ -d "$arg" ]; then + dirlist="$arg" + else + echo "$0: $arg not found" >&2 + continue + fi + ;; +*) dirlist= + for top in /etc/periodic ${local_periodic}; do + [ -d $top/$arg ] && dirlist="$dirlist $top/$arg" done + ;; +esac - case $arg in - /*) if [ -d "$arg" ] - then - dirlist="$arg" - else - echo "$0: $arg not found" >&2 - continue - fi;; - *) dirlist= - for top in /etc/periodic ${local_periodic} - do - [ -d $top/$arg ] && dirlist="$dirlist $top/$arg" - done;; - esac - - { - empty=TRUE - processed=0 - for dir in $dirlist - do - for file in $dir/* - do - if [ -x $file -a ! -d $file ] - then - output=TRUE - processed=$(($processed + 1)) - $file $tmp_output 2>&1 - rc=$? - if [ -s $tmp_output ] - then - case $rc in - 0) [ $success = NO ] && output=FALSE;; - 1) [ $info = NO ] && output=FALSE;; - 2) [ $badconfig = NO ] && output=FALSE;; - esac - [ $output = TRUE ] && { cat $tmp_output; empty=FALSE; } - fi - cp /dev/null $tmp_output +{ + empty=TRUE + processed=0 + for dir in $dirlist; do + for file in $dir/*; do + if [ -x $file -a ! -d $file ]; then + output=TRUE + processed=$(($processed + 1)) + $file $tmp_output 2>&1 + rc=$? + if [ -s $tmp_output ]; then + case $rc in + 0) [ $success = NO ] && output=FALSE;; + 1) [ $info = NO ] && output=FALSE;; + 2) [ $badconfig = NO ] && output=FALSE;; + esac + [ $output = TRUE ] && { cat $tmp_output; empty=FALSE; } fi - done + cp /dev/null $tmp_output + fi done - if [ $empty = TRUE ] - then - if [ $empty_output = TRUE ] - then + done + if [ $empty = TRUE ]; then + if [ $empty_output = TRUE ]; then [ $processed = 1 ] && plural= || plural=s echo "No output from the $processed file$plural processed" - fi - else - echo "" - echo "-- End of $arg output --" fi - } | eval $pipe -done + else + echo "" + echo "-- End of $arg output --" + fi +} | output_pipe ${arg} + rm -f $tmp_output diff --git a/usr.sbin/pkg_install/create/perform.c b/usr.sbin/pkg_install/create/perform.c index 0834ecda9597..44095518b0e0 100644 --- a/usr.sbin/pkg_install/create/perform.c +++ b/usr.sbin/pkg_install/create/perform.c @@ -214,8 +214,12 @@ pkg_perform(char **pkgs) read_plist(&plist, pkg_in); /* Prefix should add an @cwd to the packing list */ - if (Prefix) - add_plist_top(&plist, PLIST_CWD, Prefix); + if (Prefix) { + char resolved_prefix[PATH_MAX]; + if (realpath(Prefix, resolved_prefix) == NULL) + err(EXIT_FAILURE, "couldn't resolve path for prefix: %s", Prefix); + add_plist_top(&plist, PLIST_CWD, resolved_prefix); + } /* Add the origin if asked, at the top */ if (Origin) @@ -260,7 +264,9 @@ pkg_perform(char **pkgs) /* mark_plist(&plist); */ /* Now put the release specific items in */ - add_plist(&plist, PLIST_CWD, "."); + if (!Prefix) { + add_plist(&plist, PLIST_CWD, "."); + } write_file(COMMENT_FNAME, Comment); add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, COMMENT_FNAME); diff --git a/usr.sbin/pw/cpdir.c b/usr.sbin/pw/cpdir.c index c5534e58d318..0fd671b049d5 100644 --- a/usr.sbin/pw/cpdir.c +++ b/usr.sbin/pw/cpdir.c @@ -84,7 +84,7 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0) copymkdir(dst, src, st.st_mode & _DEF_DIRMODE, uid, gid); chflags(dst, st.st_flags); /* propagate flags */ - } else if (S_ISLNK(st.st_mode) && (len = readlink(src, lnk, sizeof(lnk))) != -1) { + } else if (S_ISLNK(st.st_mode) && (len = readlink(src, lnk, sizeof(lnk) - 1)) != -1) { lnk[len] = '\0'; symlink(lnk, dst); lchown(dst, uid, gid); diff --git a/usr.sbin/rpc.lockd/Makefile b/usr.sbin/rpc.lockd/Makefile index e2185c8ad7e7..139f4bc661c8 100644 --- a/usr.sbin/rpc.lockd/Makefile +++ b/usr.sbin/rpc.lockd/Makefile @@ -15,7 +15,7 @@ LDADD= -lrpcsvc -lutil CLEANFILES= nlm_prot_svc.c nlm_prot.h test RPCSRC= ${DESTDIR}/usr/include/rpcsvc/nlm_prot.x -RPCGEN= rpcgen -L -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -L -C nlm_prot_svc.c: ${RPCSRC} ${RPCGEN} -m -o ${.TARGET} ${RPCSRC} diff --git a/usr.sbin/rpc.statd/Makefile b/usr.sbin/rpc.statd/Makefile index e69a9d6e2096..6fa2b1ed10da 100644 --- a/usr.sbin/rpc.statd/Makefile +++ b/usr.sbin/rpc.statd/Makefile @@ -13,7 +13,7 @@ LDADD= -lrpcsvc CLEANFILES= sm_inter_svc.c sm_inter.h RPCSRC= ${DESTDIR}/usr/include/rpcsvc/sm_inter.x -RPCGEN= rpcgen -L -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -L -C sm_inter_svc.c: ${RPCSRC} ${RPCGEN} -m -o ${.TARGET} ${RPCSRC} diff --git a/usr.sbin/rpc.yppasswdd/Makefile b/usr.sbin/rpc.yppasswdd/Makefile index b6a0a8c8630a..a9d3a75b333d 100644 --- a/usr.sbin/rpc.yppasswdd/Makefile +++ b/usr.sbin/rpc.yppasswdd/Makefile @@ -25,7 +25,7 @@ LDADD= -lrpcsvc -lcrypt -lutil CLEANFILES= ${GENSRCS} -RPCGEN= rpcgen -I -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -I -C # We need to remove the 'static' keyword from _rpcsvcstate so that # yppasswdd_main.c can see it. diff --git a/usr.sbin/rpc.ypupdated/Makefile b/usr.sbin/rpc.ypupdated/Makefile index fecb83760dd1..ffef7d493108 100644 --- a/usr.sbin/rpc.ypupdated/Makefile +++ b/usr.sbin/rpc.ypupdated/Makefile @@ -19,7 +19,7 @@ LDADD= -lrpcsvc CLEANFILES= ypupdate_prot_svc.c ypupdate_prot.h RPCDIR= ${DESTDIR}/usr/include/rpcsvc -RPCGEN= rpcgen -I -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -I -C # We need to remove the 'static' keyword from _rpcsvcstate so that # ypupdated_main.c can see it. diff --git a/usr.sbin/rpc.ypxfrd/Makefile b/usr.sbin/rpc.ypxfrd/Makefile index ee9e2425d1e9..05971b16bfd1 100644 --- a/usr.sbin/rpc.ypxfrd/Makefile +++ b/usr.sbin/rpc.ypxfrd/Makefile @@ -17,7 +17,7 @@ LDADD= -lrpcsvc CLEANFILES= ypxfrd_svc.c ypxfrd.h RPCDIR= ${.CURDIR}/../../include/rpcsvc -RPCGEN= rpcgen -I -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -I -C # We need to remove the 'static' keyword from _rpcsvcstate so that # ypxfrd_main.c can see it. diff --git a/usr.sbin/tzsetup/tzsetup.c b/usr.sbin/tzsetup/tzsetup.c index 5da9d7224a5d..97daa0bd51f0 100644 --- a/usr.sbin/tzsetup/tzsetup.c +++ b/usr.sbin/tzsetup/tzsetup.c @@ -723,7 +723,7 @@ install_zoneinfo_file(const char *zoneinfo_file) return (DITEM_FAILURE | DITEM_RECREATE); } - if (unlink(path_localtime) < 0) { + if (unlink(path_localtime) < 0 && errno != ENOENT) { snprintf(prompt, sizeof(prompt), "Could not unlink %s: %s", path_localtime, strerror(errno)); @@ -780,7 +780,7 @@ install_zoneinfo_file(const char *zoneinfo_file) fprintf(stderr, "%s\n", prompt); return (DITEM_FAILURE | DITEM_RECREATE); } - if (unlink(path_localtime) < 0) { + if (unlink(path_localtime) < 0 && errno != ENOENT) { snprintf(prompt, sizeof(prompt), "Could not unlink %s: %s", path_localtime, strerror(errno)); diff --git a/usr.sbin/usbdump/usbdump.8 b/usr.sbin/usbdump/usbdump.8 index 104c3b35231d..d95f4b9dada3 100644 --- a/usr.sbin/usbdump/usbdump.8 +++ b/usr.sbin/usbdump/usbdump.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 31, 2011 +.Dd February 16, 2012 .Dt USBDUMP 8 .Os .Sh NAME @@ -38,6 +38,7 @@ .Op Fl s Ar snaplen .Op Fl v .Op Fl w Ar file +.Op Fl f Ar filter .Sh DESCRIPTION The .Nm @@ -61,6 +62,16 @@ When defined multiple times the verbosity level increases. .It Fl w Ar file Write the raw packets to .Ar file . +.It Fl f Ar filter +The filter argument consists of either one or two numbers separated by a dot. +The first indicates the device unit number which should be traced. +The second number which is optional indicates the endpoint which should be traced. +To get all traffic for the control endpoint, two filters should be +created, one for endpoint 0 and one for endpoint 128. +If 128 is added to the endpoint number that means IN direction, else OUT direction is implied. +A device unit or endpoint value of -1 means ignore this field. +If no filters are specified, all packets are passed through using the default -1,-1 filter. +This option can be specified multiple times. .El .Sh EXAMPLES Capture the USB raw packets on usbus2: @@ -72,6 +83,11 @@ size limit: .Pp .Dl "usbdump -i usbus2 -s 0 -w /tmp/dump_pkts" .Pp +Dump the USB raw packets of usbus2, but only the control endpoint traffic +of device unit number 3: +.Pp +.Dl "usbdump -i usbus2 -s 0 -f 3.0 -f 3.128 -w /tmp/dump_pkts" +.Pp Read and display the USB raw packets from previous file: .Pp .Dl "usbdump -r /tmp/dump_pkts -v" diff --git a/usr.sbin/usbdump/usbdump.c b/usr.sbin/usbdump/usbdump.c index 582bf946b0e9..d7bbb7910e45 100644 --- a/usr.sbin/usbdump/usbdump.c +++ b/usr.sbin/usbdump/usbdump.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -45,12 +46,33 @@ #include #include #include +#include #include #include #include #include #include +#define BPF_STORE_JUMP(x,_c,_k,_jt,_jf) do { \ + (x).code = (_c); \ + (x).k = (_k); \ + (x).jt = (_jt); \ + (x).jf = (_jf); \ +} while (0) + +#define BPF_STORE_STMT(x,_c,_k) do { \ + (x).code = (_c); \ + (x).k = (_k); \ + (x).jt = 0; \ + (x).jf = 0; \ +} while (0) + +struct usb_filt { + STAILQ_ENTRY(usb_filt) entry; + int unit; + int endpoint; +}; + struct usbcap { int fd; /* fd for /dev/usbpf */ uint32_t bufsize; @@ -123,6 +145,114 @@ static const char *speed_table[USB_SPEED_MAX] = { [USB_SPEED_SUPER] = "SUPER", }; +static STAILQ_HEAD(,usb_filt) usb_filt_head = + STAILQ_HEAD_INITIALIZER(usb_filt_head); + +static void +add_filter(int usb_filt_unit, int usb_filt_ep) +{ + struct usb_filt *puf; + + puf = malloc(sizeof(struct usb_filt)); + if (puf == NULL) + errx(EX_SOFTWARE, "Out of memory."); + + puf->unit = usb_filt_unit; + puf->endpoint = usb_filt_ep; + + STAILQ_INSERT_TAIL(&usb_filt_head, puf, entry); +} + +static void +make_filter(struct bpf_program *pprog, int snapshot) +{ + struct usb_filt *puf; + struct bpf_insn *dynamic_insn; + int len; + + len = 0; + + STAILQ_FOREACH(puf, &usb_filt_head, entry) + len++; + + dynamic_insn = malloc(((len * 5) + 1) * sizeof(struct bpf_insn)); + + if (dynamic_insn == NULL) + errx(EX_SOFTWARE, "Out of memory."); + + len++; + + if (len == 1) { + /* accept all packets */ + + BPF_STORE_STMT(dynamic_insn[0], BPF_RET | BPF_K, snapshot); + + goto done; + } + + len = 0; + + STAILQ_FOREACH(puf, &usb_filt_head, entry) { + const int addr_off = (uintptr_t)&((struct usbpf_pkthdr *)0)->up_address; + const int addr_ep = (uintptr_t)&((struct usbpf_pkthdr *)0)->up_endpoint; + + if (puf->unit != -1) { + if (puf->endpoint != -1) { + BPF_STORE_STMT(dynamic_insn[len], + BPF_LD | BPF_B | BPF_ABS, addr_off); + len++; + BPF_STORE_JUMP(dynamic_insn[len], + BPF_JMP | BPF_JEQ | BPF_K, (uint8_t)puf->unit, 0, 3); + len++; + BPF_STORE_STMT(dynamic_insn[len], + BPF_LD | BPF_W | BPF_ABS, addr_ep); + len++; + BPF_STORE_JUMP(dynamic_insn[len], + BPF_JMP | BPF_JEQ | BPF_K, htobe32(puf->endpoint), 0, 1); + len++; + } else { + BPF_STORE_STMT(dynamic_insn[len], + BPF_LD | BPF_B | BPF_ABS, addr_off); + len++; + BPF_STORE_JUMP(dynamic_insn[len], + BPF_JMP | BPF_JEQ | BPF_K, (uint8_t)puf->unit, 0, 1); + len++; + } + } else { + if (puf->endpoint != -1) { + BPF_STORE_STMT(dynamic_insn[len], + BPF_LD | BPF_W | BPF_ABS, addr_ep); + len++; + BPF_STORE_JUMP(dynamic_insn[len], + BPF_JMP | BPF_JEQ | BPF_K, htobe32(puf->endpoint), 0, 1); + len++; + } + } + BPF_STORE_STMT(dynamic_insn[len], + BPF_RET | BPF_K, snapshot); + len++; + } + + BPF_STORE_STMT(dynamic_insn[len], BPF_RET | BPF_K, 0); + len++; + +done: + pprog->bf_len = len; + pprog->bf_insns = dynamic_insn; +} + +static void +free_filter(struct bpf_program *pprog) +{ + struct usb_filt *puf; + + while ((puf = STAILQ_FIRST(&usb_filt_head)) != NULL) { + STAILQ_REMOVE_HEAD(&usb_filt_head, entry); + free(puf); + } + free(pprog->bf_insns); +} + static void handle_sigint(int sig) { @@ -527,6 +657,7 @@ usage(void) #define FMT " %-14s %s\n" fprintf(stderr, "usage: usbdump [options]\n"); fprintf(stderr, FMT, "-i ", "Listen on USB bus interface"); + fprintf(stderr, FMT, "-f ", "Specify a device and endpoint filter"); fprintf(stderr, FMT, "-r ", "Read the raw packets from file"); fprintf(stderr, FMT, "-s ", "Snapshot bytes from each packet"); fprintf(stderr, FMT, "-v", "Increase the verbose level"); @@ -539,7 +670,6 @@ int main(int argc, char *argv[]) { struct timeval tv; - struct bpf_insn total_insn; struct bpf_program total_prog; struct bpf_stat us; struct bpf_version bv; @@ -547,12 +677,16 @@ main(int argc, char *argv[]) struct ifreq ifr; long snapshot = 192; uint32_t v; - int fd, o; + int fd; + int o; + int filt_unit; + int filt_ep; const char *optstring; + char *pp; memset(&uc, 0, sizeof(struct usbcap)); - optstring = "i:r:s:vw:"; + optstring = "i:r:s:vw:f:"; while ((o = getopt(argc, argv, optstring)) != -1) { switch (o) { case 'i': @@ -563,8 +697,10 @@ main(int argc, char *argv[]) init_rfile(p); break; case 's': - snapshot = strtol(optarg, NULL, 10); + snapshot = strtol(optarg, &pp, 10); errno = 0; + if (pp != NULL && *pp != 0) + usage(); if (snapshot == 0 && errno == EINVAL) usage(); /* snapeshot == 0 is special */ @@ -578,6 +714,20 @@ main(int argc, char *argv[]) w_arg = optarg; init_wfile(p); break; + case 'f': + filt_unit = strtol(optarg, &pp, 10); + filt_ep = -1; + if (pp != NULL) { + if (*pp == '.') { + filt_ep = strtol(pp + 1, &pp, 10); + if (pp != NULL && *pp != 0) + usage(); + } else if (*pp != 0) { + usage(); + } + } + add_filter(filt_unit, filt_ep); + break; default: usage(); /* NOTREACHED */ @@ -623,17 +773,13 @@ main(int argc, char *argv[]) if (p->buffer == NULL) errx(EX_SOFTWARE, "Out of memory."); - /* XXX no read filter rules yet so at this moment accept everything */ - total_insn.code = (u_short)(BPF_RET | BPF_K); - total_insn.jt = 0; - total_insn.jf = 0; - total_insn.k = snapshot; + make_filter(&total_prog, snapshot); - total_prog.bf_len = 1; - total_prog.bf_insns = &total_insn; if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) err(EXIT_FAILURE, "BIOCSETF ioctl failed"); + free_filter(&total_prog); + /* 1 second read timeout */ tv.tv_sec = 1; tv.tv_usec = 0; diff --git a/usr.sbin/utx/Makefile b/usr.sbin/utx/Makefile new file mode 100644 index 000000000000..a70c71c508e8 --- /dev/null +++ b/usr.sbin/utx/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PROG= utx +MAN= utx.8 + +LINKS= ${BINDIR}/utx ${BINDIR}/utxrm +MLINKS= utx.8 utxrm.8 + +.include diff --git a/usr.sbin/utxrm/utxrm.8 b/usr.sbin/utx/utx.8 similarity index 72% rename from usr.sbin/utxrm/utxrm.8 rename to usr.sbin/utx/utx.8 index 8b43f1aeaac4..d4e043989720 100644 --- a/usr.sbin/utxrm/utxrm.8 +++ b/usr.sbin/utx/utx.8 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2011 Ed Schouten +.\" Copyright (c) 2011-2012 Ed Schouten .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,20 +24,46 @@ .\" .\" $FreeBSD$ .\" -.Dd February 19, 2011 -.Dt UTXRM 8 +.Dd February 11, 2012 +.Dt UTX 8 .Os .Sh NAME +.Nm utx , .Nm utxrm -.Nd remove sessions from the user accounting database +.Nd manage the user accounting database .Sh SYNOPSIS .Nm +.Cm boot +.Nm +.Cm shutdown +.Nm +.Cm rm +.Ar identifier +.Ar ... +.Nm utxrm .Ar identifier .Ar ... .Sh DESCRIPTION The .Nm -utility can be used to remove stale sessions from the user accounting +utility can be used to perform operations on the user accounting +database, as done by +.Xr pututxline 3 . +.Pp +The first argument to +.Nm +indicates an action to be performed: +.Bl -tag -width ".Cm shutdown" +.It Cm boot +Write a boot time record to the user accounting database. +This option should typically only be used by +.Xr rc 8 . +.It Cm shutdown +Write a shutdown time record to the user accounting database. +This option should typically only be used by +.Xr rc 8 . +.It Cm rm +Remove stale sessions from the user accounting database, by referring to their .Ar identifier . Stale sessions can occur if a login service exits prematurely or fails @@ -57,6 +83,13 @@ Identifiers can either be supplied in hexadecimal form as displayed by .Xr getent 1 , or as a string if the identifier allows such a representation. .Pp +To remain backward compatible, this action can also be invoked directly +by using the +.Nm utxrm +command. +.El +.Pp +.Pp Because this utility requires write-access to the user accounting database, its use is limited to the super-user. .Sh SEE ALSO @@ -66,7 +99,9 @@ database, its use is limited to the super-user. .Sh HISTORY The .Nm -utility appeared in -.Fx 9.0 . +utility replaced +.Nm utxrm +in +.Fx 10.0 . .Sh AUTHORS .An Ed Schouten Aq ed@FreeBSD.org diff --git a/usr.sbin/utxrm/utxrm.c b/usr.sbin/utx/utx.c similarity index 65% rename from usr.sbin/utxrm/utxrm.c rename to usr.sbin/utx/utx.c index 3c2eadddef65..99d9591ff3fe 100644 --- a/usr.sbin/utxrm/utxrm.c +++ b/usr.sbin/utx/utx.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Ed Schouten + * Copyright (c) 2011-2012 Ed Schouten * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -47,38 +48,67 @@ b16_pton(const char *in, char *out, size_t len) return (0); } -int -main(int argc, char *argv[]) +static int +rm(char *id[]) { struct utmpx utx = { .ut_type = DEAD_PROCESS }; size_t len; - int i, ret = 0; + int ret = 0; - if (argc < 2) { - fprintf(stderr, "usage: utxrm identifier ...\n"); - return (1); - } - - gettimeofday(&utx.ut_tv, NULL); - for (i = 1; i < argc; i++) { - len = strlen(argv[i]); + (void)gettimeofday(&utx.ut_tv, NULL); + for (; *id != NULL; id++) { + len = strlen(*id); if (len <= sizeof(utx.ut_id)) { /* Identifier as string. */ - strncpy(utx.ut_id, argv[i], sizeof(utx.ut_id)); + strncpy(utx.ut_id, *id, sizeof(utx.ut_id)); } else if (len != sizeof(utx.ut_id) * 2 || - b16_pton(argv[i], utx.ut_id, sizeof(utx.ut_id)) != 0) { + b16_pton(*id, utx.ut_id, sizeof(utx.ut_id)) != 0) { /* Also not hexadecimal. */ - fprintf(stderr, "%s: Invalid identifier format\n", - argv[i]); + fprintf(stderr, "%s: Invalid identifier format\n", *id); ret = 1; continue; } /* Zap the entry. */ if (pututxline(&utx) == NULL) { - perror(argv[i]); + perror(*id); ret = 1; } } return (ret); } + +static int +boot(short type) +{ + struct utmpx utx = { .ut_type = type }; + + (void)gettimeofday(&utx.ut_tv, NULL); + if (pututxline(&utx) == NULL) { + perror("pututxline"); + return (1); + } + return (0); +} + +int +main(int argc, char *argv[]) +{ + + if (argc >= 2 && strcmp(getprogname(), "utxrm") == 0) + /* For compatibility. */ + return (rm(&argv[1])); + else if (argc == 2 && strcmp(argv[1], "boot") == 0) + return (boot(BOOT_TIME)); + else if (argc == 2 && strcmp(argv[1], "shutdown") == 0) + return (boot(SHUTDOWN_TIME)); + else if (argc >= 3 && strcmp(argv[1], "rm") == 0) + return (rm(&argv[2])); + + fprintf(stderr, + "usage: utx boot\n" + " utx shutdown\n" + " utx rm identifier ...\n" + " utxrm identifier ...\n"); + exit(1); +} diff --git a/usr.sbin/vipw/vipw.8 b/usr.sbin/vipw/vipw.8 index 7162baa5e4fc..69f884539646 100644 --- a/usr.sbin/vipw/vipw.8 +++ b/usr.sbin/vipw/vipw.8 @@ -28,7 +28,7 @@ .\" @(#)vipw.8 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd June 6, 1993 +.Dd February 14, 2012 .Dt VIPW 8 .Os .Sh NAME @@ -112,8 +112,11 @@ utility appeared in .Bx 4.0 . .Sh BUGS The mechanism for checking for password file modifications requires that +the modification time of the password file changes. +This means that in a default configuration where file system timestamps +are not calculated with sub-second precision, .Ev EDITOR -run for at least one second. +has to run for at least one second. Non-interactive editor scripts should invoke .Xr sleep 1 or equivalent to ensure this happens. diff --git a/usr.sbin/wpa/hostapd/hostapd.8 b/usr.sbin/wpa/hostapd/hostapd.8 index 7fb14d394d9d..7be2cbf15684 100644 --- a/usr.sbin/wpa/hostapd/hostapd.8 +++ b/usr.sbin/wpa/hostapd/hostapd.8 @@ -112,6 +112,7 @@ Store PID in .Xr ipw 4 , .Xr iwi 4 , .Xr ral 4 , +.Xr run 4 , .Xr ural 4 , .Xr wi 4 , .Xr hostapd.conf 5 , diff --git a/usr.sbin/yppush/Makefile b/usr.sbin/yppush/Makefile index 887a80b92d0a..510dc10f4ea8 100644 --- a/usr.sbin/yppush/Makefile +++ b/usr.sbin/yppush/Makefile @@ -14,7 +14,7 @@ CFLAGS+= -I. -I${.CURDIR}/../../libexec/ypxfr WARNS?= 2 -RPCGEN= rpcgen -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -C CLEANFILES= ${GENSRCS} diff --git a/usr.sbin/ypserv/Makefile b/usr.sbin/ypserv/Makefile index 73a6195db36e..cb24c43e71ee 100644 --- a/usr.sbin/ypserv/Makefile +++ b/usr.sbin/ypserv/Makefile @@ -17,7 +17,7 @@ LDADD= -lwrap CLEANFILES= yp_svc.c ypxfr_clnt.c yp.h -RPCGEN= rpcgen -I -C +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -I -C # We need to remove the 'static' keyword from _rpcsvcstate so that # yp_main.c can see it.