summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2013-02-24 17:20:53 +0000
committerattilio <attilio@FreeBSD.org>2013-02-24 17:20:53 +0000
commit2ad8e10333f151d4744c8dfc21f28ed627d114f5 (patch)
tree8cedc9a41694cf97140c2cc2afc2cf935c94cdeb
parent1073a3600169d69ce8182282ee963464f30c3360 (diff)
parent084e5da56e3c4bc6f9c6ed314310a9b8af2c695b (diff)
downloadFreeBSD-src-2ad8e10333f151d4744c8dfc21f28ed627d114f5.zip
FreeBSD-src-2ad8e10333f151d4744c8dfc21f28ed627d114f5.tar.gz
MFC
-rw-r--r--bin/sh/eval.c2
-rw-r--r--bin/sh/jobs.c2
-rw-r--r--bin/sh/main.c2
-rw-r--r--bin/sh/trap.c35
-rw-r--r--bin/sh/trap.h2
-rw-r--r--contrib/llvm/lib/Target/X86/X86InstrCompiler.td14
-rw-r--r--lib/libelf/elf_update.c308
-rw-r--r--sbin/fsck_ffs/dir.c2
-rw-r--r--sbin/fsck_ffs/ea.c2
-rw-r--r--sbin/fsck_ffs/fsck.h38
-rw-r--r--sbin/fsck_ffs/fsutil.c141
-rw-r--r--sbin/fsck_ffs/inode.c45
-rw-r--r--sbin/fsck_ffs/main.c8
-rw-r--r--sbin/fsck_ffs/setup.c7
-rw-r--r--sys/arm/arm/machdep.c9
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_vcbus.h14
-rw-r--r--sys/boot/fdt/dts/bcm2835-rpi-b.dts73
-rw-r--r--sys/boot/fdt/fdt_loader_cmd.c29
-rw-r--r--sys/boot/uboot/lib/elf_freebsd.c2
-rw-r--r--sys/dev/fdt/fdt_common.h2
-rw-r--r--sys/ia64/conf/GENERIC2
-rw-r--r--tools/regression/bin/sh/builtins/wait4.012
-rw-r--r--tools/regression/bin/sh/builtins/wait5.012
23 files changed, 524 insertions, 239 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index b40fffd..0972b10 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -301,7 +301,7 @@ evaltree(union node *n, int flags)
} while (n != NULL);
out:
popstackmark(&smark);
- if (pendingsigs)
+ if (pendingsig)
dotrap();
if (eflag && exitstatus != 0 && do_etest)
exitshell(exitstatus);
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index c86394f..5a2790b 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -521,7 +521,7 @@ waitcmd(int argc, char **argv)
} while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1);
in_waitcmd--;
- return 0;
+ return pendingsig + 128;
}
diff --git a/bin/sh/main.c b/bin/sh/main.c
index 66e1335..5dc050f 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -196,7 +196,7 @@ cmdloop(int top)
TRACE(("cmdloop(%d) called\n", top));
setstackmark(&smark);
for (;;) {
- if (pendingsigs)
+ if (pendingsig)
dotrap();
inter = 0;
if (iflag && top) {
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index 521c511..0a9eb60 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$");
MKINIT char sigmode[NSIG]; /* current value of signal */
-int pendingsigs; /* indicates some signal received */
+volatile sig_atomic_t pendingsig; /* indicates some signal received */
int in_dotrap; /* do we execute in a trap handler? */
static char *volatile trap[NSIG]; /* trap handler commands */
static volatile sig_atomic_t gotsig[NSIG];
@@ -388,22 +388,25 @@ onsig(int signo)
return;
}
- if (signo != SIGCHLD || !ignore_sigchld)
- gotsig[signo] = 1;
- pendingsigs++;
-
/* If we are currently in a wait builtin, prepare to break it */
- if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
- breakwaitcmd = 1;
- /*
- * If a trap is set, not ignored and not the null command, we need
- * to make sure traps are executed even when a child blocks signals.
- */
- if (Tflag &&
- trap[signo] != NULL &&
- ! (trap[signo][0] == '\0') &&
- ! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
+ if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) {
breakwaitcmd = 1;
+ pendingsig = signo;
+ }
+
+ if (trap[signo] != NULL && trap[signo][0] != '\0' &&
+ (signo != SIGCHLD || !ignore_sigchld)) {
+ gotsig[signo] = 1;
+ pendingsig = signo;
+
+ /*
+ * If a trap is set, not ignored and not the null command, we
+ * need to make sure traps are executed even when a child
+ * blocks signals.
+ */
+ if (Tflag && !(trap[signo][0] == ':' && trap[signo][1] == '\0'))
+ breakwaitcmd = 1;
+ }
#ifndef NO_HISTORY
if (signo == SIGWINCH)
@@ -424,7 +427,7 @@ dotrap(void)
in_dotrap++;
for (;;) {
- pendingsigs = 0;
+ pendingsig = 0;
for (i = 1; i < NSIG; i++) {
if (gotsig[i]) {
gotsig[i] = 0;
diff --git a/bin/sh/trap.h b/bin/sh/trap.h
index 61a17ec..0a05d8d 100644
--- a/bin/sh/trap.h
+++ b/bin/sh/trap.h
@@ -33,7 +33,7 @@
* $FreeBSD$
*/
-extern int pendingsigs;
+extern volatile sig_atomic_t pendingsig;
extern int in_dotrap;
extern volatile sig_atomic_t gotwinch;
diff --git a/contrib/llvm/lib/Target/X86/X86InstrCompiler.td b/contrib/llvm/lib/Target/X86/X86InstrCompiler.td
index 9e6f279..0d9c81e 100644
--- a/contrib/llvm/lib/Target/X86/X86InstrCompiler.td
+++ b/contrib/llvm/lib/Target/X86/X86InstrCompiler.td
@@ -1076,12 +1076,14 @@ def : Pat<(X86cmp GR64:$src1, 0),
// inverted.
multiclass CMOVmr<PatLeaf InvertedCond, Instruction Inst16, Instruction Inst32,
Instruction Inst64> {
- def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, InvertedCond, EFLAGS),
- (Inst16 GR16:$src2, addr:$src1)>;
- def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, InvertedCond, EFLAGS),
- (Inst32 GR32:$src2, addr:$src1)>;
- def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, InvertedCond, EFLAGS),
- (Inst64 GR64:$src2, addr:$src1)>;
+ let Predicates = [HasCMov] in {
+ def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, InvertedCond, EFLAGS),
+ (Inst16 GR16:$src2, addr:$src1)>;
+ def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, InvertedCond, EFLAGS),
+ (Inst32 GR32:$src2, addr:$src1)>;
+ def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, InvertedCond, EFLAGS),
+ (Inst64 GR64:$src2, addr:$src1)>;
+ }
}
defm : CMOVmr<X86_COND_B , CMOVAE16rm, CMOVAE32rm, CMOVAE64rm>;
diff --git a/lib/libelf/elf_update.c b/lib/libelf/elf_update.c
index 5880c07..813d2bcb 100644
--- a/lib/libelf/elf_update.c
+++ b/lib/libelf/elf_update.c
@@ -41,89 +41,79 @@ __FBSDID("$FreeBSD$");
#include "_libelf.h"
/*
- * Update the internal data structures associated with an ELF object.
- * Returns the size in bytes the ELF object would occupy in its file
- * representation.
+ * Layout strategy:
*
- * After a successful call to this function, the following structures
- * are updated:
+ * - Case 1: ELF_F_LAYOUT is asserted
+ * In this case the application has full control over where the
+ * section header table, program header table, and section data
+ * will reside. The library only perform error checks.
*
- * - The ELF header is updated.
- * - All sections are sorted in order of ascending addresses and their
- * section header table entries updated. An error is signalled
- * if an overlap was detected among sections.
- * - All data descriptors associated with a section are sorted in order
- * of ascending addresses. Overlaps, if detected, are signalled as
- * errors. Other sanity checks for alignments, section types etc. are
- * made.
+ * - Case 2: ELF_F_LAYOUT is not asserted
*
- * After a resync_elf() successfully returns, the ELF descriptor is
- * ready for being handed over to _libelf_write_elf().
+ * The library will do the object layout using the following
+ * ordering:
+ * - The executable header is placed first, are required by the
+ * ELF specification.
+ * - The program header table is placed immediately following the
+ * executable header.
+ * - Section data, if any, is placed after the program header
+ * table, aligned appropriately.
+ * - The section header table, if needed, is placed last.
*
- * File alignments:
- * PHDR - Addr
- * SHDR - Addr
+ * There are two sub-cases to be taken care of:
*
- * XXX: how do we handle 'flags'.
+ * - Case 2a: e->e_cmd == ELF_C_READ or ELF_C_RDWR
+ *
+ * In this sub-case, the underlying ELF object may already have
+ * content in it, which the application may have modified. The
+ * library will retrieve content from the existing object as
+ * needed.
+ *
+ * - Case 2b: e->e_cmd == ELF_C_WRITE
+ *
+ * The ELF object is being created afresh in this sub-case;
+ * there is no pre-existing content in the underlying ELF
+ * object.
*/
/*
* Compute the extents of a section, by looking at the data
- * descriptors associated with it. The function returns zero if an
- * error was detected. `*rc' holds the maximum file extent seen so
- * far.
+ * descriptors associated with it. The function returns 1 if
+ * successful, or zero if an error was detected.
*/
static int
-_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc)
+_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
{
int ec;
- Elf_Data *d, *td;
+ size_t fsz, msz;
+ Elf_Data *d;
+ Elf32_Shdr *shdr32;
+ Elf64_Shdr *shdr64;
unsigned int elftype;
uint32_t sh_type;
uint64_t d_align;
uint64_t sh_align, sh_entsize, sh_offset, sh_size;
uint64_t scn_size, scn_alignment;
- /*
- * We need to recompute library private data structures if one
- * or more of the following is true:
- * - The underlying Shdr structure has been marked `dirty'. Significant
- * fields include: `sh_offset', `sh_type', `sh_size', `sh_addralign'.
- * - The Elf_Data structures part of this section have been marked
- * `dirty'. Affected members include `d_align', `d_offset', `d_type',
- * and `d_size'.
- * - The section as a whole is `dirty', e.g., it has been allocated
- * using elf_newscn(), or if a new Elf_Data structure was added using
- * elf_newdata().
- *
- * Each of these conditions would result in the ELF_F_DIRTY bit being
- * set on the section descriptor's `s_flags' field.
- */
-
ec = e->e_class;
+ shdr32 = &s->s_shdr.s_shdr32;
+ shdr64 = &s->s_shdr.s_shdr64;
if (ec == ELFCLASS32) {
- sh_type = s->s_shdr.s_shdr32.sh_type;
- sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
- sh_entsize = (uint64_t) s->s_shdr.s_shdr32.sh_entsize;
- sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
- sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
+ sh_type = shdr32->sh_type;
+ sh_align = (uint64_t) shdr32->sh_addralign;
+ sh_entsize = (uint64_t) shdr32->sh_entsize;
+ sh_offset = (uint64_t) shdr32->sh_offset;
+ sh_size = (uint64_t) shdr32->sh_size;
} else {
- sh_type = s->s_shdr.s_shdr64.sh_type;
- sh_align = s->s_shdr.s_shdr64.sh_addralign;
- sh_entsize = s->s_shdr.s_shdr64.sh_entsize;
- sh_offset = s->s_shdr.s_shdr64.sh_offset;
- sh_size = s->s_shdr.s_shdr64.sh_size;
+ sh_type = shdr64->sh_type;
+ sh_align = shdr64->sh_addralign;
+ sh_entsize = shdr64->sh_entsize;
+ sh_offset = shdr64->sh_offset;
+ sh_size = shdr64->sh_size;
}
- if (sh_type == SHT_NULL || sh_type == SHT_NOBITS)
- return (1);
-
- if ((s->s_flags & ELF_F_DIRTY) == 0) {
- if ((size_t) *rc < sh_offset + sh_size)
- *rc = sh_offset + sh_size;
- return (1);
- }
+ assert(sh_type != SHT_NULL && sh_type != SHT_NOBITS);
elftype = _libelf_xlate_shtype(sh_type);
if (elftype > ELF_T_LAST) {
@@ -131,15 +121,52 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc)
return (0);
}
- /*
- * Compute the extent of the data descriptors associated with
- * this section.
- */
- scn_alignment = 0;
if (sh_align == 0)
sh_align = _libelf_falign(elftype, ec);
- /* Compute the section alignment. */
+ /*
+ * Check the section's data buffers for sanity and compute the
+ * section's alignment.
+ * Compute the section's size and alignment using the data
+ * descriptors associated with the section.
+ */
+ if (STAILQ_EMPTY(&s->s_data)) {
+ /*
+ * The section's content (if any) has not been read in
+ * yet. If section is not dirty marked dirty, we can
+ * reuse the values in the 'sh_size' and 'sh_offset'
+ * fields of the section header.
+ */
+ if ((s->s_flags & ELF_F_DIRTY) == 0) {
+ /*
+ * If the library is doing the layout, then we
+ * compute the new start offset for the
+ * section based on the current offset and the
+ * section's alignment needs.
+ *
+ * If the application is doing the layout, we
+ * can use the value in the 'sh_offset' field
+ * in the section header directly.
+ */
+ if (e->e_flags & ELF_F_LAYOUT)
+ goto updatedescriptor;
+ else
+ goto computeoffset;
+ }
+
+ /*
+ * Otherwise, we need to bring in the section's data
+ * from the underlying ELF object.
+ */
+ if (e->e_cmd != ELF_C_WRITE && elf_getdata(s, NULL) == NULL)
+ return (0);
+ }
+
+ /*
+ * Loop through the section's data descriptors.
+ */
+ scn_size = 0L;
+ scn_alignment = 0L;
STAILQ_FOREACH(d, &s->s_data, d_next) {
if (d->d_type > ELF_T_LAST) {
LIBELF_SET_ERROR(DATA, 0);
@@ -153,23 +180,40 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc)
LIBELF_SET_ERROR(DATA, 0);
return (0);
}
- if (d_align > scn_alignment)
- scn_alignment = d_align;
- }
- scn_size = 0L;
+ /*
+ * The buffer's size should be a multiple of the
+ * memory size of the underlying type.
+ */
+ msz = _libelf_msize(d->d_type, ec, e->e_version);
+ if (d->d_size % msz) {
+ LIBELF_SET_ERROR(DATA, 0);
+ return (0);
+ }
- STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
+ /*
+ * Compute the section's size.
+ */
if (e->e_flags & ELF_F_LAYOUT) {
if ((uint64_t) d->d_off + d->d_size > scn_size)
scn_size = d->d_off + d->d_size;
} else {
scn_size = roundup2(scn_size, d->d_align);
d->d_off = scn_size;
- scn_size += d->d_size;
+ fsz = _libelf_fsize(d->d_type, ec, d->d_version,
+ d->d_size / msz);
+ scn_size += fsz;
}
+
+ /*
+ * The section's alignment is the maximum alignment
+ * needed for its data buffers.
+ */
+ if (d_align > scn_alignment)
+ scn_alignment = d_align;
}
+
/*
* If the application is requesting full control over the layout
* of the section, check its values for sanity.
@@ -180,46 +224,60 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc)
LIBELF_SET_ERROR(LAYOUT, 0);
return (0);
}
- } else {
- /*
- * Otherwise compute the values in the section header.
- */
+ goto updatedescriptor;
+ }
- if (scn_alignment > sh_align)
- sh_align = scn_alignment;
+ /*
+ * Otherwise compute the values in the section header.
+ *
+ * The section alignment is the maximum alignment for any of
+ * its contained data descriptors.
+ */
+ if (scn_alignment > sh_align)
+ sh_align = scn_alignment;
- /*
- * If the section entry size is zero, try and fill in an
- * appropriate entry size. Per the elf(5) manual page
- * sections without fixed-size entries should have their
- * 'sh_entsize' field set to zero.
- */
- if (sh_entsize == 0 &&
- (sh_entsize = _libelf_fsize(elftype, ec, e->e_version,
- (size_t) 1)) == 1)
- sh_entsize = 0;
+ /*
+ * If the section entry size is zero, try and fill in an
+ * appropriate entry size. Per the elf(5) manual page
+ * sections without fixed-size entries should have their
+ * 'sh_entsize' field set to zero.
+ */
+ if (sh_entsize == 0 &&
+ (sh_entsize = _libelf_fsize(elftype, ec, e->e_version,
+ (size_t) 1)) == 1)
+ sh_entsize = 0;
- sh_size = scn_size;
- sh_offset = roundup(*rc, sh_align);
+ sh_size = scn_size;
- if (ec == ELFCLASS32) {
- s->s_shdr.s_shdr32.sh_addralign = (uint32_t) sh_align;
- s->s_shdr.s_shdr32.sh_entsize = (uint32_t) sh_entsize;
- s->s_shdr.s_shdr32.sh_offset = (uint32_t) sh_offset;
- s->s_shdr.s_shdr32.sh_size = (uint32_t) sh_size;
- } else {
- s->s_shdr.s_shdr64.sh_addralign = sh_align;
- s->s_shdr.s_shdr64.sh_entsize = sh_entsize;
- s->s_shdr.s_shdr64.sh_offset = sh_offset;
- s->s_shdr.s_shdr64.sh_size = sh_size;
- }
- }
+computeoffset:
+ /*
+ * Compute the new offset for the section based on
+ * the section's alignment needs.
+ */
+ sh_offset = roundup(rc, sh_align);
- if ((size_t) *rc < sh_offset + sh_size)
- *rc = sh_offset + sh_size;
+ /*
+ * Update the section header.
+ */
+ if (ec == ELFCLASS32) {
+ shdr32->sh_addralign = (uint32_t) sh_align;
+ shdr32->sh_entsize = (uint32_t) sh_entsize;
+ shdr32->sh_offset = (uint32_t) sh_offset;
+ shdr32->sh_size = (uint32_t) sh_size;
+ } else {
+ shdr64->sh_addralign = sh_align;
+ shdr64->sh_entsize = sh_entsize;
+ shdr64->sh_offset = sh_offset;
+ shdr64->sh_size = sh_size;
+ }
+updatedescriptor:
+ /*
+ * Update the section descriptor.
+ */
s->s_size = sh_size;
s->s_offset = sh_offset;
+
return (1);
}
@@ -267,13 +325,16 @@ _libelf_insert_section(Elf *e, Elf_Scn *s)
return (1);
}
+/*
+ * Recompute section layout.
+ */
+
static off_t
_libelf_resync_sections(Elf *e, off_t rc)
{
int ec;
- off_t nrc;
+ Elf_Scn *s;
size_t sh_type, shdr_start, shdr_end;
- Elf_Scn *s, *ts;
ec = e->e_class;
@@ -281,13 +342,7 @@ _libelf_resync_sections(Elf *e, off_t rc)
* Make a pass through sections, computing the extent of each
* section. Order in increasing order of addresses.
*/
-
- nrc = rc;
- STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next)
- if (_libelf_compute_section_extents(e, s, &nrc) == 0)
- return ((off_t) -1);
-
- STAILQ_FOREACH_SAFE(s, &e->e_u.e_elf.e_scn, s_next, ts) {
+ STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) {
if (ec == ELFCLASS32)
sh_type = s->s_shdr.s_shdr32.sh_type;
else
@@ -296,21 +351,22 @@ _libelf_resync_sections(Elf *e, off_t rc)
if (sh_type == SHT_NOBITS || sh_type == SHT_NULL)
continue;
- if (s->s_offset < (uint64_t) rc) {
- if (s->s_offset + s->s_size < (uint64_t) rc) {
- /*
- * Try insert this section in the
- * correct place in the list,
- * detecting overlaps if any.
- */
- STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn,
- s_next);
- if (_libelf_insert_section(e, s) == 0)
- return ((off_t) -1);
- } else {
- LIBELF_SET_ERROR(LAYOUT, 0);
+ if (_libelf_compute_section_extents(e, s, rc) == 0)
+ return ((off_t) -1);
+
+ if (s->s_size == 0)
+ continue;
+
+ if (s->s_offset + s->s_size < (size_t) rc) {
+ /*
+ * Try insert this section in the
+ * correct place in the list,
+ * detecting overlaps if any.
+ */
+ STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn,
+ s_next);
+ if (_libelf_insert_section(e, s) == 0)
return ((off_t) -1);
- }
} else
rc = s->s_offset + s->s_size;
}
@@ -338,8 +394,6 @@ _libelf_resync_sections(Elf *e, off_t rc)
}
}
- assert(nrc == rc);
-
return (rc);
}
diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c
index 7815fe6..965e3e3 100644
--- a/sbin/fsck_ffs/dir.c
+++ b/sbin/fsck_ffs/dir.c
@@ -708,6 +708,6 @@ getdirblk(ufs2_daddr_t blkno, long size)
if (pdirbp != 0)
pdirbp->b_flags &= ~B_INUSE;
- pdirbp = getdatablk(blkno, size);
+ pdirbp = getdatablk(blkno, size, BT_DIRDATA);
return (pdirbp);
}
diff --git a/sbin/fsck_ffs/ea.c b/sbin/fsck_ffs/ea.c
index c1cf59d..3517011 100644
--- a/sbin/fsck_ffs/ea.c
+++ b/sbin/fsck_ffs/ea.c
@@ -73,7 +73,7 @@ eascan(struct inodesc *idesc, struct ufs2_dinode *dp)
else
blksiz = sblock.fs_bsize;
printf("blksiz = %ju\n", (intmax_t)blksiz);
- bp = getdatablk(dp->di_extb[0], blksiz);
+ bp = getdatablk(dp->di_extb[0], blksiz, BT_EXTATTR);
cp = (u_char *)bp->b_un.b_buf;
for (n = 0; n < blksiz; n++) {
printf("%02x", cp[n]);
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index dfb2ade..ef98fa2 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -138,6 +138,7 @@ struct bufarea {
int b_size;
int b_errs;
int b_flags;
+ int b_type;
union {
char *b_buf; /* buffer space */
ufs1_daddr_t *b_indir1; /* UFS1 indirect block */
@@ -165,6 +166,36 @@ struct bufarea {
* Buffer flags
*/
#define B_INUSE 0x00000001 /* Buffer is in use */
+/*
+ * Type of data in buffer
+ */
+#define BT_UNKNOWN 0 /* Buffer holds a superblock */
+#define BT_SUPERBLK 1 /* Buffer holds a superblock */
+#define BT_CYLGRP 2 /* Buffer holds a cylinder group map */
+#define BT_LEVEL1 3 /* Buffer holds single level indirect */
+#define BT_LEVEL2 4 /* Buffer holds double level indirect */
+#define BT_LEVEL3 5 /* Buffer holds triple level indirect */
+#define BT_EXTATTR 6 /* Buffer holds external attribute data */
+#define BT_INODES 7 /* Buffer holds external attribute data */
+#define BT_DIRDATA 8 /* Buffer holds directory data */
+#define BT_DATA 9 /* Buffer holds user data */
+#define BT_NUMBUFTYPES 10
+#define BT_NAMES { \
+ "unknown", \
+ "Superblock", \
+ "Cylinder Group", \
+ "Single Level Indirect", \
+ "Double Level Indirect", \
+ "Triple Level Indirect", \
+ "External Attribute", \
+ "Inode Block", \
+ "Directory Contents", \
+ "User Data" }
+long readcnt[BT_NUMBUFTYPES];
+long totalreadcnt[BT_NUMBUFTYPES];
+struct timespec readtime[BT_NUMBUFTYPES];
+struct timespec totalreadtime[BT_NUMBUFTYPES];
+struct timespec startprog;
struct bufarea sblk; /* file system superblock */
struct bufarea cgblk; /* cylinder group blocks */
@@ -177,10 +208,11 @@ struct bufarea *pbp; /* current inode block */
else \
(bp)->b_dirty = 1; \
} while (0)
-#define initbarea(bp) do { \
+#define initbarea(bp, type) do { \
(bp)->b_dirty = 0; \
(bp)->b_bno = (ufs2_daddr_t)-1; \
(bp)->b_flags = 0; \
+ (bp)->b_type = type; \
} while (0)
#define sbdirty() dirty(&sblk)
@@ -357,6 +389,7 @@ int dirscan(struct inodesc *);
int dofix(struct inodesc *, const char *msg);
int eascan(struct inodesc *, struct ufs2_dinode *dp);
void fileerror(ino_t cwd, ino_t ino, const char *errmesg);
+void finalIOstats(void);
int findino(struct inodesc *);
int findname(struct inodesc *);
void flush(int fd, struct bufarea *bp);
@@ -365,7 +398,7 @@ void freeino(ino_t ino);
void freeinodebuf(void);
int ftypeok(union dinode *dp);
void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size);
-struct bufarea *getdatablk(ufs2_daddr_t blkno, long size);
+struct bufarea *getdatablk(ufs2_daddr_t blkno, long size, int type);
struct inoinfo *getinoinfo(ino_t inumber);
union dinode *getnextinode(ino_t inumber, int rebuildcg);
void getpathname(char *namebuf, ino_t curdir, ino_t ino);
@@ -375,6 +408,7 @@ void alarmhandler(int sig);
void inocleanup(void);
void inodirty(void);
struct inostat *inoinfo(ino_t inum);
+void IOstats(char *what);
int linkup(ino_t orphan, ino_t parentdir, char *name);
int makeentry(ino_t parent, ino_t ino, const char *name);
void panic(const char *fmt, ...) __printflike(1, 2);
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index f3a640a..eef9bdc 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -56,19 +56,23 @@ __FBSDID("$FreeBSD$");
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
#include <unistd.h>
#include "fsck.h"
static void slowio_start(void);
static void slowio_end(void);
+static void printIOstats(void);
-long diskreads, totalreads; /* Disk cache statistics */
+static long diskreads, totaldiskreads, totalreads; /* Disk cache statistics */
+static struct timespec startpass, finishpass;
struct timeval slowio_starttime;
int slowio_delay_usec = 10000; /* Initial IO delay for background fsck */
int slowio_pollcnt;
static TAILQ_HEAD(buflist, bufarea) bufhead; /* head of buffer cache list */
static int numbufs; /* size of buffer cache */
+static char *buftype[BT_NUMBUFTYPES] = BT_NAMES;
int
ftypeok(union dinode *dp)
@@ -163,7 +167,7 @@ bufinit(void)
if (bufp == 0)
errx(EEXIT, "cannot allocate buffer pool");
cgblk.b_un.b_buf = bufp;
- initbarea(&cgblk);
+ initbarea(&cgblk, BT_CYLGRP);
TAILQ_INIT(&bufhead);
bufcnt = MAXBUFS;
if (bufcnt < MINBUFS)
@@ -178,16 +182,21 @@ bufinit(void)
}
bp->b_un.b_buf = bufp;
TAILQ_INSERT_HEAD(&bufhead, bp, b_list);
- initbarea(bp);
+ initbarea(bp, BT_UNKNOWN);
}
numbufs = i; /* save number of buffers */
+ for (i = 0; i < BT_NUMBUFTYPES; i++) {
+ readtime[i].tv_sec = totalreadtime[i].tv_sec = 0;
+ readtime[i].tv_nsec = totalreadtime[i].tv_nsec = 0;
+ readcnt[i] = totalreadcnt[i] = 0;
+ }
}
/*
* Manage a cache of directory blocks.
*/
struct bufarea *
-getdatablk(ufs2_daddr_t blkno, long size)
+getdatablk(ufs2_daddr_t blkno, long size, int type)
{
struct bufarea *bp;
@@ -199,26 +208,62 @@ getdatablk(ufs2_daddr_t blkno, long size)
break;
if (bp == NULL)
errx(EEXIT, "deadlocked buffer pool");
+ bp->b_type = type;
getblk(bp, blkno, size);
/* fall through */
foundit:
+ if (debug && bp->b_type != type)
+ printf("Buffer type changed from %s to %s\n",
+ buftype[bp->b_type], buftype[type]);
TAILQ_REMOVE(&bufhead, bp, b_list);
TAILQ_INSERT_HEAD(&bufhead, bp, b_list);
bp->b_flags |= B_INUSE;
return (bp);
}
+/*
+ * Timespec operations (from <sys/time.h>).
+ */
+#define timespecsub(vvp, uvp) \
+ do { \
+ (vvp)->tv_sec -= (uvp)->tv_sec; \
+ (vvp)->tv_nsec -= (uvp)->tv_nsec; \
+ if ((vvp)->tv_nsec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_nsec += 1000000000; \
+ } \
+ } while (0)
+#define timespecadd(vvp, uvp) \
+ do { \
+ (vvp)->tv_sec += (uvp)->tv_sec; \
+ (vvp)->tv_nsec += (uvp)->tv_nsec; \
+ if ((vvp)->tv_nsec >= 1000000000) { \
+ (vvp)->tv_sec++; \
+ (vvp)->tv_nsec -= 1000000000; \
+ } \
+ } while (0)
+
void
getblk(struct bufarea *bp, ufs2_daddr_t blk, long size)
{
ufs2_daddr_t dblk;
+ struct timespec start, finish;
- totalreads++;
dblk = fsbtodb(&sblock, blk);
- if (bp->b_bno != dblk) {
+ if (bp->b_bno == dblk) {
+ totalreads++;
+ } else {
flush(fswritefd, bp);
- diskreads++;
+ if (debug) {
+ readcnt[bp->b_type]++;
+ clock_gettime(CLOCK_REALTIME_PRECISE, &start);
+ }
bp->b_errs = blread(fsreadfd, bp->b_un.b_buf, dblk, size);
+ if (debug) {
+ clock_gettime(CLOCK_REALTIME_PRECISE, &finish);
+ timespecsub(&finish, &start);
+ timespecadd(&readtime[bp->b_type], &finish);
+ }
bp->b_bno = dblk;
bp->b_size = size;
}
@@ -292,8 +337,8 @@ ckfini(int markclean)
}
if (debug && totalreads > 0)
printf("cache with %d buffers missed %ld of %ld (%d%%)\n",
- numbufs, diskreads, totalreads,
- (int)(diskreads * 100 / totalreads));
+ numbufs, totaldiskreads, totalreads,
+ (int)(totaldiskreads * 100 / totalreads));
if (fswritefd < 0) {
(void)close(fsreadfd);
return;
@@ -347,6 +392,82 @@ ckfini(int markclean)
(void)close(fswritefd);
}
+/*
+ * Print out I/O statistics.
+ */
+void
+IOstats(char *what)
+{
+ int i;
+
+ if (debug == 0)
+ return;
+ if (diskreads == 0) {
+ printf("%s: no I/O\n\n", what);
+ return;
+ }
+ if (startpass.tv_sec == 0)
+ startpass = startprog;
+ printf("%s: I/O statistics\n", what);
+ printIOstats();
+ totaldiskreads += diskreads;
+ diskreads = 0;
+ for (i = 0; i < BT_NUMBUFTYPES; i++) {
+ timespecadd(&totalreadtime[i], &readtime[i]);
+ totalreadcnt[i] += readcnt[i];
+ readtime[i].tv_sec = readtime[i].tv_nsec = 0;
+ readcnt[i] = 0;
+ }
+ clock_gettime(CLOCK_REALTIME_PRECISE, &startpass);
+}
+
+void
+finalIOstats(void)
+{
+ int i;
+
+ if (debug == 0)
+ return;
+ printf("Final I/O statistics\n");
+ totaldiskreads += diskreads;
+ diskreads = totaldiskreads;
+ startpass = startprog;
+ for (i = 0; i < BT_NUMBUFTYPES; i++) {
+ timespecadd(&totalreadtime[i], &readtime[i]);
+ totalreadcnt[i] += readcnt[i];
+ readtime[i] = totalreadtime[i];
+ readcnt[i] = totalreadcnt[i];
+ }
+ printIOstats();
+}
+
+static void printIOstats(void)
+{
+ long long msec, totalmsec;
+ int i;
+
+ clock_gettime(CLOCK_REALTIME_PRECISE, &finishpass);
+ timespecsub(&finishpass, &startpass);
+ printf("Running time: %ld msec\n",
+ finishpass.tv_sec * 1000 + finishpass.tv_nsec / 1000000);
+ printf("buffer reads by type:\n");
+ for (totalmsec = 0, i = 0; i < BT_NUMBUFTYPES; i++)
+ totalmsec += readtime[i].tv_sec * 1000 +
+ readtime[i].tv_nsec / 1000000;
+ if (totalmsec == 0)
+ totalmsec = 1;
+ for (i = 0; i < BT_NUMBUFTYPES; i++) {
+ if (readcnt[i] == 0)
+ continue;
+ msec = readtime[i].tv_sec * 1000 + readtime[i].tv_nsec / 1000000;
+ printf("%21s:%8ld %2ld.%ld%% %8lld msec %2lld.%lld%%\n",
+ buftype[i], readcnt[i], readcnt[i] * 100 / diskreads,
+ (readcnt[i] * 1000 / diskreads) % 10, msec,
+ msec * 100 / totalmsec, (msec * 1000 / totalmsec) % 10);
+ }
+ printf("\n");
+}
+
int
blread(int fd, char *buf, ufs2_daddr_t blk, long size)
{
@@ -358,6 +479,8 @@ blread(int fd, char *buf, ufs2_daddr_t blk, long size)
offset *= dev_bsize;
if (bkgrdflag)
slowio_start();
+ totalreads++;
+ diskreads++;
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK BLK", blk);
else if (read(fd, buf, (int)size) == size) {
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
index 389150a..fd98575 100644
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$");
static ino_t startinum;
-static int iblock(struct inodesc *, long ilevel, off_t isize);
+static int iblock(struct inodesc *, long ilevel, off_t isize, int type);
int
ckinode(union dinode *dp, struct inodesc *idesc)
@@ -121,7 +121,7 @@ ckinode(union dinode *dp, struct inodesc *idesc)
sizepb *= NINDIR(&sblock);
if (DIP(&dino, di_ib[i])) {
idesc->id_blkno = DIP(&dino, di_ib[i]);
- ret = iblock(idesc, i + 1, remsize);
+ ret = iblock(idesc, i + 1, remsize, BT_LEVEL1 + i);
if (ret & STOP)
return (ret);
} else {
@@ -151,7 +151,7 @@ ckinode(union dinode *dp, struct inodesc *idesc)
}
static int
-iblock(struct inodesc *idesc, long ilevel, off_t isize)
+iblock(struct inodesc *idesc, long ilevel, off_t isize, int type)
{
struct bufarea *bp;
int i, n, (*func)(struct inodesc *), nif;
@@ -168,7 +168,7 @@ iblock(struct inodesc *idesc, long ilevel, off_t isize)
func = dirscan;
if (chkrange(idesc->id_blkno, idesc->id_numfrags))
return (SKIP);
- bp = getdatablk(idesc->id_blkno, sblock.fs_bsize);
+ bp = getdatablk(idesc->id_blkno, sblock.fs_bsize, type);
ilevel--;
for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
sizepb *= NINDIR(&sblock);
@@ -199,7 +199,7 @@ iblock(struct inodesc *idesc, long ilevel, off_t isize)
if (ilevel == 0)
n = (*func)(idesc);
else
- n = iblock(idesc, ilevel, isize);
+ n = iblock(idesc, ilevel, isize, type);
if (n & STOP) {
bp->b_flags &= ~B_INUSE;
return (n);
@@ -292,7 +292,7 @@ ginode(ino_t inumber)
iblk = ino_to_fsba(&sblock, inumber);
if (pbp != 0)
pbp->b_flags &= ~B_INUSE;
- pbp = getdatablk(iblk, sblock.fs_bsize);
+ pbp = getdatablk(iblk, sblock.fs_bsize, BT_INODES);
startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
}
if (sblock.fs_magic == FS_UFS1_MAGIC)
@@ -306,8 +306,8 @@ ginode(ino_t inumber)
* over all the inodes in numerical order.
*/
static ino_t nextino, lastinum, lastvalidinum;
-static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
-static caddr_t inodebuf;
+static long readcount, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
+static struct bufarea inobuf;
union dinode *
getnextinode(ino_t inumber, int rebuildcg)
@@ -315,7 +315,7 @@ getnextinode(ino_t inumber, int rebuildcg)
int j;
long size;
mode_t mode;
- ufs2_daddr_t ndb, dblk;
+ ufs2_daddr_t ndb, blk;
union dinode *dp;
static caddr_t nextinop;
@@ -323,9 +323,9 @@ getnextinode(ino_t inumber, int rebuildcg)
errx(EEXIT, "bad inode number %ju to nextinode",
(uintmax_t)inumber);
if (inumber >= lastinum) {
- readcnt++;
- dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum));
- if (readcnt % readpercg == 0) {
+ readcount++;
+ blk = ino_to_fsba(&sblock, lastinum);
+ if (readcount % readpercg == 0) {
size = partialsize;
lastinum += partialcnt;
} else {
@@ -333,14 +333,14 @@ getnextinode(ino_t inumber, int rebuildcg)
lastinum += fullcnt;
}
/*
- * If blread returns an error, it will already have zeroed
+ * If getblk encounters an error, it will already have zeroed
* out the buffer, so we do not need to do so here.
*/
- (void)blread(fsreadfd, inodebuf, dblk, size);
- nextinop = inodebuf;
+ getblk(&inobuf, blk, size);
+ nextinop = inobuf.b_un.b_buf;
}
dp = (union dinode *)nextinop;
- if (rebuildcg && nextinop == inodebuf) {
+ if (rebuildcg && nextinop == inobuf.b_un.b_buf) {
/*
* Try to determine if we have reached the end of the
* allocated inodes.
@@ -406,8 +406,8 @@ setinodebuf(ino_t inum)
startinum = 0;
nextino = inum;
lastinum = inum;
- readcnt = 0;
- if (inodebuf != NULL)
+ readcount = 0;
+ if (inobuf.b_un.b_buf != NULL)
return;
inobufsize = blkroundup(&sblock, INOBUFSIZE);
fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ?
@@ -422,7 +422,8 @@ setinodebuf(ino_t inum)
partialcnt = fullcnt;
partialsize = inobufsize;
}
- if ((inodebuf = malloc((unsigned)inobufsize)) == NULL)
+ initbarea(&inobuf, BT_INODES);
+ if ((inobuf.b_un.b_buf = malloc((unsigned)inobufsize)) == NULL)
errx(EEXIT, "cannot allocate space for inode buffer");
}
@@ -430,9 +431,9 @@ void
freeinodebuf(void)
{
- if (inodebuf != NULL)
- free((char *)inodebuf);
- inodebuf = NULL;
+ if (inobuf.b_un.b_buf != NULL)
+ free((char *)inobuf.b_un.b_buf);
+ inobuf.b_un.b_buf = NULL;
}
/*
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 69f157a..27f17db 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -424,7 +424,9 @@ checkfilesys(char *filesys)
printf("** Root file system\n");
printf("** Phase 1 - Check Blocks and Sizes\n");
}
+ clock_gettime(CLOCK_REALTIME_PRECISE, &startprog);
pass1();
+ IOstats("Pass1");
/*
* 1b: locate first references to duplicates, if any
@@ -437,6 +439,7 @@ checkfilesys(char *filesys)
usedsoftdep ? "softupdates" : "");
printf("** Phase 1b - Rescan For More DUPS\n");
pass1b();
+ IOstats("Pass1b");
}
/*
@@ -445,6 +448,7 @@ checkfilesys(char *filesys)
if (preen == 0)
printf("** Phase 2 - Check Pathnames\n");
pass2();
+ IOstats("Pass2");
/*
* 3: scan inodes looking for disconnected directories
@@ -452,6 +456,7 @@ checkfilesys(char *filesys)
if (preen == 0)
printf("** Phase 3 - Check Connectivity\n");
pass3();
+ IOstats("Pass3");
/*
* 4: scan inodes looking for disconnected files; check reference counts
@@ -459,6 +464,7 @@ checkfilesys(char *filesys)
if (preen == 0)
printf("** Phase 4 - Check Reference Counts\n");
pass4();
+ IOstats("Pass4");
/*
* 5: check and repair resource counts in cylinder groups
@@ -466,6 +472,7 @@ checkfilesys(char *filesys)
if (preen == 0)
printf("** Phase 5 - Check Cyl groups\n");
pass5();
+ IOstats("Pass5");
/*
* print out summary statistics
@@ -519,6 +526,7 @@ checkfilesys(char *filesys)
}
if (rerun)
resolved = 0;
+ finalIOstats();
/*
* Check to see if the file system is mounted read-write.
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index ae0ea05..32abeed 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -249,6 +249,7 @@ setup(char *dev)
for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
size = sblock.fs_cssize - i < sblock.fs_bsize ?
sblock.fs_cssize - i : sblock.fs_bsize;
+ readcnt[sblk.b_type]++;
if (blread(fsreadfd, (char *)sblock.fs_csp + i,
fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
size) != 0 && !asked) {
@@ -322,6 +323,7 @@ readsb(int listerr)
if (bflag) {
super = bflag;
+ readcnt[sblk.b_type]++;
if ((blread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE)))
return (0);
if (sblock.fs_magic == FS_BAD_MAGIC) {
@@ -337,6 +339,7 @@ readsb(int listerr)
} else {
for (i = 0; sblock_try[i] != -1; i++) {
super = sblock_try[i] / dev_bsize;
+ readcnt[sblk.b_type]++;
if ((blread(fsreadfd, (char *)&sblock, super,
(long)SBLOCKSIZE)))
return (0);
@@ -439,8 +442,8 @@ sblock_init(void)
fswritefd = -1;
fsmodified = 0;
lfdir = 0;
- initbarea(&sblk);
- initbarea(&asblk);
+ initbarea(&sblk, BT_SUPERBLK);
+ initbarea(&asblk, BT_SUPERBLK);
sblk.b_un.b_buf = malloc(SBLOCKSIZE);
asblk.b_un.b_buf = malloc(SBLOCKSIZE);
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index c1378e3..408493c 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -45,6 +45,7 @@
#include "opt_compat.h"
#include "opt_ddb.h"
#include "opt_platform.h"
+#include "opt_sched.h"
#include "opt_timer.h"
#include <sys/cdefs.h>
@@ -71,6 +72,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pcpu.h>
#include <sys/ptrace.h>
#include <sys/rwlock.h>
+#include <sys/sched.h>
#include <sys/signalvar.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
@@ -434,19 +436,24 @@ void
cpu_idle(int busy)
{
+ CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
+ busy, curcpu);
#ifndef NO_EVENTTIMERS
if (!busy) {
critical_enter();
cpu_idleclock();
}
#endif
- cpu_sleep(0);
+ if (!sched_runnable())
+ cpu_sleep(0);
#ifndef NO_EVENTTIMERS
if (!busy) {
cpu_activeclock();
critical_exit();
}
#endif
+ CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done",
+ busy, curcpu);
}
int
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
index 1d91046..cb871f2 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
+++ b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
@@ -34,14 +34,28 @@
#define _BCM2835_VCBUS_H_
#define BCM2835_VCBUS_SDRAM_CACHED 0x40000000
+#define BCM2835_VCBUS_IO_BASE 0x7E000000
#define BCM2835_VCBUS_SDRAM_UNCACHED 0xC0000000
+#define BCM2835_ARM_IO_BASE 0x20000000
+#define BCM2835_ARM_IO_SIZE 0x02000000
+
/*
* Convert physical address to VC bus address. Should be used
* when submitting address over mailbox interface
*/
#define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_CACHED)
+/* Check whether pa bellong top IO window */
+#define BCM2835_ARM_IS_IO(pa) (((pa) >= BCM2835_ARM_IO_BASE) && \
+ ((pa) < BCM2835_ARM_IO_BASE + BCM2835_ARM_IO_SIZE))
+
+/*
+ * Convert physical address in IO space to VC bus address.
+ */
+#define IO_TO_VCBUS(pa) ((pa - BCM2835_ARM_IO_BASE) + \
+ BCM2835_VCBUS_IO_BASE)
+
/*
* Convert address from VC bus space to physical. Should be used
* when address is returned by VC over mailbox interface. e.g.
diff --git a/sys/boot/fdt/dts/bcm2835-rpi-b.dts b/sys/boot/fdt/dts/bcm2835-rpi-b.dts
index d9357af..80bbef0 100644
--- a/sys/boot/fdt/dts/bcm2835-rpi-b.dts
+++ b/sys/boot/fdt/dts/bcm2835-rpi-b.dts
@@ -95,27 +95,6 @@
clock-frequency = <1000000>;
};
- dma: dma {
- compatible = "broadcom,bcm2835-dma", "broadcom,bcm2708-dma";
- reg = <0x7000 0x1000>, <0xE05000 0x1000>;
- interrupts = <
- 26 /* 2 */
- 27 /* 3 */
- >;
- interrupt-parent = <&intc>;
-
- broadcom,channels = <0>; /* Set by VideoCore */
- };
-
- sdhci {
- compatible = "broadcom,bcm2835-sdhci", "broadcom,bcm2708-sdhci";
- reg = <0x300000 0x100>;
- interrupts = <70>;
- interrupt-parent = <&intc>;
-
- clock-frequency = <50000000>; /* Set by VideoCore */
- };
-
armtimer {
/* Not AMBA compatible */
compatible = "broadcom,bcm2835-sp804", "arm,sp804";
@@ -124,23 +103,6 @@
interrupt-parent = <&intc>;
};
- vc_mbox: mbox {
- compatible = "broadcom,bcm2835-mbox", "broadcom,bcm2708-mbox";
- reg = <0xB880 0x40>;
- interrupts = <1>;
- interrupt-parent = <&intc>;
-
- /* Channels
- * 0: Power
- * 1: Frame buffer
- * 2: Virtual UART
- * 3: VCHIQ
- * 4: LEDs
- * 5: Buttons
- * 6: Touch screen
- */
- };
-
watchdog0 {
compatible = "broadcom,bcm2835-wdt", "broadcom,bcm2708-wdt";
reg = <0x10001c 0x0c>; /* 0x1c, 0x20, 0x24 */
@@ -461,6 +423,41 @@
};
};
+ dma: dma {
+ compatible = "broadcom,bcm2835-dma", "broadcom,bcm2708-dma";
+ reg = <0x7000 0x1000>, <0xE05000 0x1000>;
+ interrupts = <24 25 26 27 28 29 30 31 32 33 34 35 36>;
+ interrupt-parent = <&intc>;
+
+ broadcom,channels = <0>; /* Set by VideoCore */
+ };
+
+ vc_mbox: mbox {
+ compatible = "broadcom,bcm2835-mbox", "broadcom,bcm2708-mbox";
+ reg = <0xB880 0x40>;
+ interrupts = <1>;
+ interrupt-parent = <&intc>;
+
+ /* Channels
+ * 0: Power
+ * 1: Frame buffer
+ * 2: Virtual UART
+ * 3: VCHIQ
+ * 4: LEDs
+ * 5: Buttons
+ * 6: Touch screen
+ */
+ };
+
+ sdhci {
+ compatible = "broadcom,bcm2835-sdhci", "broadcom,bcm2708-sdhci";
+ reg = <0x300000 0x100>;
+ interrupts = <70>;
+ interrupt-parent = <&intc>;
+
+ clock-frequency = <50000000>; /* Set by VideoCore */
+ };
+
uart0: uart0 {
compatible = "broadcom,bcm2835-uart", "broadcom,bcm2708-uart", "arm,pl011", "arm,primecell";
reg = <0x201000 0x1000>;
diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c
index 37cf75d..0417c52 100644
--- a/sys/boot/fdt/fdt_loader_cmd.c
+++ b/sys/boot/fdt/fdt_loader_cmd.c
@@ -62,7 +62,9 @@ __FBSDID("$FreeBSD$");
#define CMD_REQUIRES_BLOB 0x01
-/* Local copy of FDT */
+/* Location of FDT yet to be loaded. */
+static struct fdt_header *fdt_to_load = NULL;
+/* Local copy of FDT on heap. */
static struct fdt_header *fdtp = NULL;
/* Size of FDT blob */
static size_t fdtp_size = 0;
@@ -252,13 +254,20 @@ fdt_setup_fdtp()
{
struct preloaded_file *bfp;
struct fdt_header *hdr;
- const char *s, *p;
+ const char *s;
+ char *p;
vm_offset_t va;
if ((bfp = file_findfile(NULL, "dtb")) != NULL) {
printf("Using DTB from loaded file.\n");
return fdt_load_dtb(bfp->f_addr);
- }
+ }
+
+ if (fdt_to_load != NULL) {
+ printf("Using DTB from memory address 0x%08X.\n",
+ (unsigned int)fdt_to_load);
+ return fdt_load_dtb_addr(fdt_to_load);
+ }
s = ub_env_get("fdtaddr");
if (s != NULL && *s != '\0') {
@@ -810,8 +819,12 @@ command_fdt_internal(int argc, char *argv[])
static int
fdt_cmd_addr(int argc, char *argv[])
{
+ struct preloaded_file *fp;
struct fdt_header *hdr;
- const char *addr, *cp;
+ const char *addr;
+ char *cp;
+
+ fdt_to_load = NULL;
if (argc > 2)
addr = argv[2];
@@ -820,15 +833,17 @@ fdt_cmd_addr(int argc, char *argv[])
return (CMD_ERROR);
}
- hdr = (struct fdt_header *)strtoul(addr, &cp, 0);
+ hdr = (struct fdt_header *)strtoul(addr, &cp, 16);
if (cp == addr) {
sprintf(command_errbuf, "Invalid address: %s", addr);
return (CMD_ERROR);
}
- if (fdt_load_dtb_addr(hdr) != 0)
- return (CMD_ERROR);
+ while ((fp = file_findfile(NULL, "dtb")) != NULL) {
+ file_discard(fp);
+ }
+ fdt_to_load = hdr;
return (CMD_OK);
}
diff --git a/sys/boot/uboot/lib/elf_freebsd.c b/sys/boot/uboot/lib/elf_freebsd.c
index 81407708..6b828d3 100644
--- a/sys/boot/uboot/lib/elf_freebsd.c
+++ b/sys/boot/uboot/lib/elf_freebsd.c
@@ -82,9 +82,9 @@ __elfN(uboot_exec)(struct preloaded_file *fp)
entry = uboot_vm_translate(e->e_entry);
printf("Kernel entry at 0x%x...\n", (unsigned)entry);
- printf("Kernel args: %s\n", fp->f_args);
dev_cleanup();
+ printf("Kernel args: %s\n", fp->f_args);
(*entry)((void *)mdp);
panic("exec returned");
diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h
index 68e3708..d244a17 100644
--- a/sys/dev/fdt/fdt_common.h
+++ b/sys/dev/fdt/fdt_common.h
@@ -39,7 +39,7 @@
#define FDT_MEM_REGIONS 8
-#define DI_MAX_INTR_NUM 8
+#define DI_MAX_INTR_NUM 32
struct fdt_pci_range {
u_long base_pci;
diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC
index 196e5be..810578f 100644
--- a/sys/ia64/conf/GENERIC
+++ b/sys/ia64/conf/GENERIC
@@ -44,7 +44,7 @@ options NFSLOCKD # Network Lock Manager
options NFSD # New Network Filesystem Server
options NFS_ROOT # NFS usable as root device
options P1003_1B_SEMAPHORES # POSIX-style semaphores
-#options PREEMPTION # Enable kernel thread preemption
+options PREEMPTION # Enable kernel thread preemption
options PRINTF_BUFR_SIZE=128 # Printf buffering to limit interspersion
options PROCFS # Process filesystem (/proc)
options PSEUDOFS # Pseudo-filesystem framework
diff --git a/tools/regression/bin/sh/builtins/wait4.0 b/tools/regression/bin/sh/builtins/wait4.0
new file mode 100644
index 0000000..7935131
--- /dev/null
+++ b/tools/regression/bin/sh/builtins/wait4.0
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX`
+trap 'rm -rf $T' 0
+cd $T || exit 3
+mkfifo fifo1
+trapped=
+trap trapped=1 QUIT
+{ kill -QUIT $$; sleep 1; exit 4; } >fifo1 &
+wait $! <fifo1
+r=$?
+[ "$r" -gt 128 ] && [ -n "$trapped" ]
diff --git a/tools/regression/bin/sh/builtins/wait5.0 b/tools/regression/bin/sh/builtins/wait5.0
new file mode 100644
index 0000000..6874bf6
--- /dev/null
+++ b/tools/regression/bin/sh/builtins/wait5.0
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX`
+trap 'rm -rf $T' 0
+cd $T || exit 3
+mkfifo fifo1
+trapped=
+trap trapped=1 QUIT
+{ kill -QUIT $$; sleep 1; exit 4; } >fifo1 &
+wait <fifo1
+r=$?
+[ "$r" -gt 128 ] && [ -n "$trapped" ]
OpenPOWER on IntegriCloud