akaros.git
4 months agoSanitize vcoreid from untrusted sources
Barret Rhoden [Thu, 11 Apr 2019 00:57:15 +0000 (20:57 -0400)]
Sanitize vcoreid from untrusted sources

Reported-by: syzbot+a21358b54760bd84b850@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agomm: check for valid prot settings (XCC)
Barret Rhoden [Tue, 9 Apr 2019 00:31:44 +0000 (20:31 -0400)]
mm: check for valid prot settings (XCC)

Prior to this commit, we were not checking 'prot' in mmap() and
mprotect() for extra bits.  The user could put arbitrary bits into a
VMR's prot.  We only checked the valid bits, since commit ee6bef89ffdb
("mm: fix checks for PROT_NONE").

One potential issue is buggy programs that had been passing extra bits.
Those will fail early now.

Tested with ssh and get_html.

Reinstall your kernel headers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agomm: remove unused MAP_ and PROT_ flags (XCC)
Barret Rhoden [Mon, 8 Apr 2019 23:41:01 +0000 (19:41 -0400)]
mm: remove unused MAP_ and PROT_ flags (XCC)

mmap() and mprotect() have a bunch of flags that we don't use, such as
PROT_GROWSDOWN and MAP_DENYWRITE.  These only existed in the kernel
interface, yet we never actually use them.

This commit removes those flags from the kernel interface.  Userspace
can still pass them to us - they can pass anything after all.  We won't
honor them and may throw errors if we get them.  I'd rather not export
definitions for the kernel interface that the kernel doesn't know about.

Note that glibc still has these common flags in
glibc-2.19-akaros/sysdeps/akaros/bits/mman.h, which is Linux's glibc
header.  Replacing that outright at the moment needs some work.  For
instance, malloc calls __madvise() and whatnot.

Reinstall your kernel headers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agomm: fix checks for PROT_NONE
Barret Rhoden [Mon, 8 Apr 2019 23:30:19 +0000 (19:30 -0400)]
mm: fix checks for PROT_NONE

You gotta love PROT_NONE, O_RDONLY, and any of these flags whose value
is zero.

The old code assumed that the only options for 'prot' were mutually
exclusive with PROT_NONE, such that we could check prot == PROT_NONE
when we really meant "has no access".  We checked for equality, since we
can't do (prot & PROT_NONE), since PROT_NONE == 0.

However, checking prot == PROT_NONE is wrong: we have other flags, like
PROT_GROWSDOWN.  Arguably, we shouldn't use those flags - I'll remove
them shortly.  Regardless, using a helper cleans up the code.

Reported-by: syzbot+aafc3433b89c900f8fe1@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agoRemove getcallerpc()
Barret Rhoden [Mon, 8 Apr 2019 13:42:28 +0000 (09:42 -0400)]
Remove getcallerpc()

It did nothing and was just confusing.  For example, the panic message
for a double-close was just: "cclose 0x0000000000000000".

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agoFix refcounting problem in walk_symlink()
Barret Rhoden [Mon, 8 Apr 2019 13:19:16 +0000 (09:19 -0400)]
Fix refcounting problem in walk_symlink()

The old code would double-close 'symlink' if it ever got into the "walk
succeeded but we were still on a symlink" case.

Recall that walk_symlink() either walks all the way, or not at all.  If
the old code (deleted) failed, we were supposed to close symlink.
However, there was a case where walk_symlink would fail, but it would
also close the chan passed in: when the sub-walk succeeded, but
walk_symlink() still failed.  How could that fail?  With a symlink loop.

If that sounds confusing, it's because it is.  There are actually two
spots of recursion, which might not even have been clear to me when I
wrote this.  The main recursive path is walk -> walk_symlink -> walk ->
walk_symlink.  We normally never got to the "walk succeeded, then call
walk_symlink" (deleted).  We usually only called walk_symlink() from
*within* walk itself.

You could trigger this situation with a no_follow symlink
(rename/remove, flags Aremove, flags no_follow).  Syzkaller basically
did this:
ln -s x x
rename x/x whatever
So we were walking the first x, had no_follow set, so walk ->
walk_symlink for the first x.  Since there were more names in the
main/outer namec, we'd get past the first no_follow.  Then that second
walk() would be for "../x", where no_follow would kick in, since there
were no longer any names left.  That walk_symlink() would return the
syml passed in, which appeared to walk to be a success (which it was).

Anyway, this was calling the buggy post-successful-walk() part of
walk_symlink().  The first fix I had was to only cclose(symlink) when that
interior walk_symlink() succeeded.  Although that fixed the bug
(walk_symlink either succeeds xor closes, so don't close on success),
the real problem was having that code at all.

If walk() lands on a symlink, walk itself should try to deal with it (by
calling walk_symlink()).  If walk returns (success or failure), we
should consider the walking of that symlink to be done, one way or
another.  If it is no_follow, we might be on a symlink (if last in the
path).  If it was a mount_point, we could be on a symlink too.

That whole "we're still on a symlink, let's walk it again" was busted,
and it would break when we had no_follow set globally and tried to
follow a legit intermediate symlink that had more than one link to
follow (but not 8 - the max).  And it was confusing.  Hopefully this
code makes a little more sense - esp when realizing that walk() sorts
out symlinks by calling walk_symlink().  walk_symlink() shouldn't call
itself, but it can call walk().  Up to 8 times.

Reported-by: syzbot+9eec51df84779065d6de@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agoClean up and clarify slim_setjmp() / waserror()
Barret Rhoden [Wed, 3 Apr 2019 19:21:15 +0000 (15:21 -0400)]
Clean up and clarify slim_setjmp() / waserror()

Any time you use a variable inside a waserror() block that has been
written since the waserror() / setjmp(), that variable must be marked
volatile.

The bool err; in slim_setjmp served little purpose, other than
confusion.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agoRemove unnecessary panic() in rread()
Barret Rhoden [Wed, 3 Apr 2019 03:34:33 +0000 (23:34 -0400)]
Remove unnecessary panic() in rread()

Ultimately, we throw an error when attempting to do a short read on a
directory.

Reported-by: syzbot+fbc1784c73dfdf878652@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agox86: Make the MP tables and IOAPIC output slightly more useful
Barret Rhoden [Thu, 28 Mar 2019 19:46:45 +0000 (15:46 -0400)]
x86: Make the MP tables and IOAPIC output slightly more useful

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agox86: Try to fix MP table I/O interrupt assignment entries
Barret Rhoden [Thu, 28 Mar 2019 19:40:43 +0000 (15:40 -0400)]
x86: Try to fix MP table I/O interrupt assignment entries

I have a desktop PC with two IOAPICs, 8 and 9, and the IOINTR entries do
not specify valid APIC IDs (0 and 2).  ACPI agrees the IOAPIC ids are 8
and 9.

This method works at least for the lower IOAPIC (id = 8) on my deskop.

You'd have to have broken MP tables to even get this far.  Prior to this
commit, PCI devices would complain about not being able to set up an IOAPIC
route.

These changes will make those busted IOINTRs appear to be correct ones,
but there's no guarantee that the hardware is actually wired that way.
might think you're using an IOAPIC route when you're actually using the
wrong one.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agox86: Make an editable copy of the MP tables
Barret Rhoden [Thu, 28 Mar 2019 19:39:31 +0000 (15:39 -0400)]
x86: Make an editable copy of the MP tables

I have a machine that appears to have some bad entries.  I'd like to
just edit the table in place, but there's no guarantee the tables are in
actual RAM.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agoSet up git blame to ignore the "8-space-tab commits"
Barret Rhoden [Wed, 27 Mar 2019 22:01:02 +0000 (18:01 -0400)]
Set up git blame to ignore the "8-space-tab commits"

If you're using git hyper-blame, the .git-blame-ignore-revs file should
work; that is their default.

If you're using my patches for upstream Git, the git config settings
will work.  If the interface for my upstream stuff changes, or an
alternate version gets implemented, I'll update the script.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agoAdd scripts/one-time-setup.sh
Barret Rhoden [Wed, 27 Mar 2019 21:42:30 +0000 (17:42 -0400)]
Add scripts/one-time-setup.sh

This will contain sanity checks and steps that should run once per git
clone.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agoFix 8 space tab formatting for non-C files
Barret Rhoden [Tue, 26 Mar 2019 21:34:41 +0000 (17:34 -0400)]
Fix 8 space tab formatting for non-C files

I missed all of these files when I handled the .c and .h files.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
4 months agoTreat tabs as having eight spaces instead of four
Barret Rhoden [Tue, 12 Mar 2019 23:41:50 +0000 (19:41 -0400)]
Treat tabs as having eight spaces instead of four

For whatever bad reason, we chose to treat tabs as four spaces instead
of eight.  e.g. in vim, tabstop=4.

That's a huge pain - both when dealing with other tools and when
switching between projects.  I don't particularly like having
per-project vim settings and whatnot.  Plus, that's a bit harder for
other people who look at our code and have their vim/emacs set to 8
space tabs.

I had regretted that for a long time, but I didn't want to make the
change for two reasons:

1) With other people working on the project, changes of this sort can
lead to merge conflicts.  Since I'm the only one working on it, for the
most part, this isn't a concern.

2) The bigger reason is that major reformatting changes break git blame.
However, there are tools that can ignore commits when running git blame.
Chromium has git hyper-blame.  I thought that feature ought to be baked
into git, so I have a patchset out for git to do so.  Either way, I'll
either have my own patched git or the feature will get merged.  In a
future commit, I'll have instructions for how to use that feature.

A lot of our files didn't need too much attention, due to our old
"spaces for formatting" policy.  I didn't change those to use tabs
instead of spaces for the formatting either.  I expect newer code will
just do whatever people's editors do.  I didn't want to change more
lines than were needed, and the code looks the same either way.

The biggest offenders were indented comments.  Structs with
column-aligned members needed some work too.  I did most of that stuff
manually, since the tools do a mediocre job.

Since I was making changes, I also fixed up the switch-case indenting:
don't do an extra level of indentation for the case keywords.  Doing
this now actually helped with the 8-space tab change, since switch
statements got a few spaces to work with.

A few of the kernel's C files were so badly messed up that I just used
clang-format on them.  Same for Plan 9 files that had been
clang-formatted before and hadn't been heavily modified by us.
Clang-format caused a few problems with its "alphabetized headers"
policy.  That was fun.

Higher-quality (subjectively) code didn't need as much work as older,
poorer code.  Specifically, code with way too many levels of indentation
looks even worse than before - that's actually a benefit of 8-space
tabs: it tells you when your code is bad.  A lot of that older code
needs a more serious refactoring, which this commit does not do.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
5 months agoCheck event_queue pointer addresses
Barret Rhoden [Wed, 6 Mar 2019 16:47:29 +0000 (11:47 -0500)]
Check event_queue pointer addresses

We had a couple checks in send_event(), mostly warnings and prints.
This commit changes those warnings to one panic, and pushes the error
handling closer to userspace.

Note that there's not much we can do about a bad pointer in a syscall
struct, other than "silently" fail.  It's almost always a bad user bug,
hence the informational print.

Also note that the kernel can still fault on an unmapped, paged out
address in userspace.  None of that is sorted.  This is just the sanity
checks to make sure we aren't give a kernel pointer.  It also catches
any very low pointers, below the MMAP_LIM.  (So null pointers and
friends).

Reported-by: syzbot+ab67ae285c93a8d288a7@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
5 months agodevproc: check for #mnt instead of #M
Barret Rhoden [Wed, 6 Mar 2019 16:43:04 +0000 (11:43 -0500)]
devproc: check for #mnt instead of #M

We missed this when changing the names of all of the devices.  All 9ns
device names are strings, not single characters.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
5 months agoFix data leak in fs_file_write()
Barret Rhoden [Sat, 2 Mar 2019 01:13:31 +0000 (20:13 -0500)]
Fix data leak in fs_file_write()

The user could give write() the valid address of a non-resident page,
particularly one in a file-backed region.  The kernel would fail to read
from it, and thus not write any data into the page cache.  The page
cache page is uninitialized, and thus contains arbitrary kernel data.

This is a stopgap, until I sort out handling page faults in the kernel -
particularly on file-backed virtual addresses.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
5 months agoCheck read() and write() for offset + count wraparound
Barret Rhoden [Sat, 2 Mar 2019 00:50:43 +0000 (19:50 -0500)]
Check read() and write() for offset + count wraparound

If you gave a file a very large count and the sum offset + count wrapped
around, you could confuse the system into thinking you had a smaller
file.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
5 months agoCheck safety of user pointer syscall arguments
Barret Rhoden [Sat, 2 Mar 2019 00:43:19 +0000 (19:43 -0500)]
Check safety of user pointer syscall arguments

Most arguments, such as a path name, are copied into the kernel.
Buffers used in read() and write() are passed deeper into the kernel
as-is.  Later on, the devices are supposed to check the pointers, often
doing a safe operation such as copy_from_user().

fs_file_write() was doing that, however the assertion at the end of the
loop was failing.  If buf + count wrapped around, we'd skip the loop
entirely and trigger a panic.

For safety's sake, we ought to just check the range early on.  The
is_user_r{,w}addr() checks can handle wraparound as well as making sure
the region is safe.

There were a few other syscalls that didn't have checks or didn't have
errstrs for the message.  This commit fixes them all.

Reported-by: syzbot+7a8e2903ce1233ffcd3d@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
5 months agoHave abort_sysc() take a uintptr_t instead of a struct sysc pointer
Barret Rhoden [Sat, 2 Mar 2019 00:40:46 +0000 (19:40 -0500)]
Have abort_sysc() take a uintptr_t instead of a struct sysc pointer

The struct sysc pointer is not dereferenced.  By making it a uintptr_t,
it is more clear that the value is used as a number, not a pointer.
abort_sysc() uses it for a pointer equality check.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
6 months agoPin ktasks to core 0
Barret Rhoden [Wed, 30 Jan 2019 17:03:13 +0000 (12:03 -0500)]
Pin ktasks to core 0

Kthreads can migrate due to the hardcoded policy of "run kthreads on
whichever core woke them up."  This is technically a source of
interference for any MCP - consider a process that does as SYS_block /
kthread_usleep on core 6, then yields.  The alarm goes off on that core
and interferes with whoever is there.  The core timer IRQ is one issue,
and the kthread scheduling is another.

That kthread scheduling issue is worse for ktasks, since they are long
running.

This commit ensures that ktasks only run on core 0.  Eventually, we will
probably want ktasks to run on all sorts of cores - consider polling the
NIC / driving the NAPI stack on a dedicated core.  The kernel alarm
service was briefly (out-of-tree) done with per-core ktasks.  For now,
think of ktasks as having affinity to core 0.

This is all a scheduling choice, so arguably we should be calling out to
sched.c.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
7 months agoFix builds without CONFIG_SEMAPHORE_DEBUG
Barret Rhoden [Thu, 10 Jan 2019 22:02:13 +0000 (17:02 -0500)]
Fix builds without CONFIG_SEMAPHORE_DEBUG

Earlier, I moved to using empty C functions instead of macros for the
cases where we have debugging turned off.  However, I still had the
CVs/SEMs conditionally including the 'db' struct.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agoAdd a monitor debug function for rendez waiters
Barret Rhoden [Tue, 18 Dec 2018 20:56:58 +0000 (15:56 -0500)]
Add a monitor debug function for rendez waiters

When debugging, it's helpful to be able to tell what is waiting on a
particular rendez.  "db rv 0xWAITER" will do the trick.

Like many monitor commands, this is dangerous.  Not only will it cast
whatever you pass it to an alarm_waiter, but even if you don't mess up,
there's no telling that the alarm isn't currently firing and unwinding
the stack.  That being said, it's been useful for me.

Usage:

(akaros) / $ m alarm pcpu
PCPU Chains:  It is now [    189.392342216]
Chain 0xffffffffcc683c48:  earliest: [    189.399452912] latest: [    482.049028825]
Waiter 0xffffffffcc683ac0, time [    189.399452912] (0x0000008cc62c95fa), func 0xffffffffc205a740 (__ksched_tick)
Waiter 0xfffffff000097dd8, time [    189.416393761] (0x0000008cc965c92b), func 0xffffffffc20586e0 (rendez_alarm_handler)
Waiter 0xfffffff0000a9c98, time [    482.049028825] (0x000001664a5eef19), func 0xffffffffc20586e0 (rendez_alarm_handler)
Chain 0xffffffffcc683f08:  earliest: [    189.477399144] latest: [    189.477399144]
Waiter 0xfffffff0000a6cb8, time [    189.477399144] (0x0000008cd50165fa), func 0xffffffffc20586e0 (rendez_alarm_handler)

(akaros) / $ m db rv 0xfffffff0000a6cb8
-------- kth #I0tcpack ----------

Backtrace of kernel context on Core 0:
 #01 [<0xffffffffc20145ab>] in cv_wait_and_unlock
 #02 [<0xffffffffc2014651>] in cv_wait
 #03 [<0xffffffffc20585cd>] in rendez_sleep_timeout
 #04 [<0xffffffffc2013d72>] in kthread_usleep
 #05 [<0xffffffffc20327a4>] in tcpackproc
 #06 [<0xffffffffc2013274>] in __ktask_wrapper
 #07 [<0xffffffffc2063bad>] in process_routine_kmsg
 #08 [<0xffffffffc205d59e>] in __smp_idle
-----------------

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agoparlib: Fix the use-after-func issue
Barret Rhoden [Tue, 18 Dec 2018 18:35:29 +0000 (13:35 -0500)]
parlib: Fix the use-after-func issue

Same as in the kernel, the parlib alarm service was touching the waiter
struct after the function ran.  We were doing this to know when the
function was complete when we were unsetting the alarm.  However, this
complicates the code of any client, since the completion of the function
isn't proof that the struct won't be reused.

See commit 47c2cf2efd4e ("futex: Call unset_alarm() before freeing the
awaiter") for a bug caused by this, and commit c62a28c78976 ("alarm:
Force unset_alarm to grab the CV lock")

The fix is the same as in the kernel - use the tchain->running variable
to track when a handler is running.

We're using the CV lock directly - userspace CVs don't have the same
interface as the kernel where you can tell it to use another lock.  And
we don't really need that interface, especially given that userspace CVs
are typically used for mutexes.

Given the slight nastiness associated with signalling a uth CV that uses
the CV lock, specifically that we want to unlock before waking the
uthread, I tried skipping the CV completely and just yielding - in
effect a busy-wait with a uthread_yield (sched_yield actually, which is
safe since we're an MCP if we ever unset during an alarm handler,
assuming one never unsets during their *own* alarm handle)).  However,
at least in qemu for some Go tests, some tests timed out too frequently.
My guess is that alarms were delayed too much by the busy waiting.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agoalarm: Make the debugging output useful
Barret Rhoden [Mon, 17 Dec 2018 18:35:53 +0000 (13:35 -0500)]
alarm: Make the debugging output useful

TSC ticks are great and all, but it really helps to have it in a more
decipherable scale, such as seconds/nsec since boot.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agokth: Remove irq_state from sem_.*irqsave's interface
Barret Rhoden [Mon, 17 Dec 2018 16:04:57 +0000 (11:04 -0500)]
kth: Remove irq_state from sem_.*irqsave's interface

If disable_irqsave() and enable_irqsave() are in the same function, you
don't need to have the state passed in.

I stumbled on this while looking into whether or not CVs could drop the
irqstate as well.  The short version is 'no'.

Our kernel CVs just use spinlocks.  The particular lock and use case of
the CVs is up to our caller, so whether or not that lock is used from
IRQ context is beyond our control.

It would be nice to be able to use the functionality of
spin_lock_irqsave() to track whether or not we need to restore IRQs when
we return.  However, we unlock and relock that spinlock during the
process of waiting and restarting.  At that point, any information about
whether or not we should reenable IRQs is gone.  Thus we need to track
it with irqstate.

Note that the cv_wait code tracks whether or not IRQs were enabled *at
the moment*, but we also need to know if IRQs were enabled at the point
of the cv_lock_irqsave() and to carry that information over to
cv_unlock_irqsave().

Also, none of the CV callers are from IRQ ctx anymore.  At most, all are
from RKMs.  When analyzing CVs, we only care about the wakeup side too
- you're not allowed to sleep from IRQ context.  And no one even calls
sem_.*irqsave().

I considered removing the CV irqsave functions (and sems), but given the
flux in alarm code, there might come a time where we kick CVs from IRQ
context again, to include immediate kernel messages.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agokth: Remove irq_okay from sems and CVs
Barret Rhoden [Fri, 14 Dec 2018 22:46:11 +0000 (17:46 -0500)]
kth: Remove irq_okay from sems and CVs

It wasn't necessary.  The only use for it was one assertion.  If that
assert would have failed, then the spinlock code will also fail
(assuming SPINLOCK_DEBUG is on).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agoalarm: Handle the tchain in RKM context
Barret Rhoden [Tue, 13 Nov 2018 02:34:41 +0000 (21:34 -0500)]
alarm: Handle the tchain in RKM context

The root issue is that we can't touch the alarm after it finished, yet
we also want to know when it has completed.  The way to do this is with
a layer of indirection!  (sort of - just with a pointer).  We can keep a
pointer that tracks the handler we're working on.

Don't forget - we want to run the handlers without holding the lock too,
which makes setting an alarm from a handler easier.  And it might avoid
deadlocks, such as the ones we saw in userspace with futexes.

To do all of this, we need to synchronize on that pointer, and it's
basically part of the tchain.  We want to manipulate the handlers and
the tchain while holding the lock, and run with the pointer set.  This
couples the execution of the locks with the processing of the tchain.
The old code just fired off a bunch of RKMs and forgot about them - we
can't forget now.

The answer here is to run the tchain handler as an RKM itself.  The
easiest way is to have __trigger_tchain send the core an RKM to
run_tchain.  Initially had a per-core ktask that looped and slept on a
CV, and the IRQ kicked the CV.  Just using the RKM directly is a little
faster and simpler.  It also means we won't have to worry about it if we
ever do special things with ktasks, like scheduling, priority, affinity,
etc.  The one slight downside is we might get multiple RKMs on the same
core to run the tchain.  That's pretty minor, and harmless from a
correctness perspective.

Also, since we're not touching the lock in IRQ ctx, we probably can make
it a non-irqsave one.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agoalarm: Add a alarm_expired()
Barret Rhoden [Tue, 13 Nov 2018 02:18:57 +0000 (21:18 -0500)]
alarm: Add a alarm_expired()

The rendez code was looking at on_tchain to determine if it had expired
or not.  It is possible for the alarm to have expired even though the
handler hasn't run yet.  If an alarm runs as an RKM, its time might
have come, but it is still on the tchain.  In these cases, we want to
timeout the rendez instead of waiting for the alarm service.

Note that this is safe in regards to the alarm's memory.  I was briefly
worried that we're breaking out of the rendez loop before the alarm
handler runs.  But we do that all the time, such as when a condition
fires, and we handle it by calling unset_alarm().

I noticed this when trying to debug a potential livelock.  We might be
able to go back to on_tchain or something else if that read_tsc() is a
problem.  In that case, we'll just change the helper.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agokth: Rename db sem to db blk
Barret Rhoden [Wed, 7 Nov 2018 20:42:40 +0000 (15:42 -0500)]
kth: Rename db sem to db blk

The old "db sem" will keep working for a while.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agokth: Clean up sem/cv debugging
Barret Rhoden [Wed, 7 Nov 2018 20:32:43 +0000 (15:32 -0500)]
kth: Clean up sem/cv debugging

The old debug code was specific to semaphores, but it also suffered due
to lock inversion.  The old lock order was list_lock->sem_lock.  That
was to avoid issues when printing.  However, we can just use a trylock.
I might not have had that when I wrote the DB code.  This is more
important now, since cv_wait() is called with the lock already held.

The old DB code also was called regardless of whether or not we blocked.
Instead, we can just track when we actually block - which is *always*
for the CVs.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agokth: Implement CVs without semaphores
Barret Rhoden [Wed, 7 Nov 2018 16:02:59 +0000 (11:02 -0500)]
kth: Implement CVs without semaphores

Implementing CVs with semaphores was possible, at least when you peer
inside the sem, but it was a minor pain and conflicted with some
upcoming features.

Notably, sem_down() *may* sleep.  cv_wait() *will* sleep.  This makes
the CV code a lot cleaner.

It does break db sem, in the sense that CVs aren't semaphores yet.  I'll
clean that up shortly.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agokth: Break up sem_down()
Barret Rhoden [Wed, 7 Nov 2018 15:57:39 +0000 (10:57 -0500)]
kth: Break up sem_down()

sem_down() is a bit of a beast.  The main purpose here is to split out
the guts of blocking a kthread from the semaphore itself so that we can
make CVs not rely on semaphores.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agoparlib: Fix u32/u64 issue with pvcalarm
Barret Rhoden [Fri, 14 Dec 2018 22:01:30 +0000 (17:01 -0500)]
parlib: Fix u32/u64 issue with pvcalarm

vcore_account_uptime_ticks() returns a u64.  By making it a u32, we'll
eventually make diff 'negative'/'very large' once a vcore's uptime
passes 32 bits, which would break things.

This never popped up, but I noticed it while hunting down other
alarm/time bugs.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agofutex: Fix buggy timeout
Barret Rhoden [Fri, 14 Dec 2018 21:49:19 +0000 (16:49 -0500)]
futex: Fix buggy timeout

We were sending the abs_timeout timespec in all cases, even if we
weren't passed a timeout.  That means we were signing up for a timespec
from uninitialized data!  Who knows when that will go off.  If it is far
in the future, we're likely to never notice.  If it happens to go off,
we'll have futexes timing out that shouldn't time out - chaos!

I had a VM that was up long enough that these timers were going off, and
I noticed really old alarms in the "alarm pcpu" output.  They would fire
instantly too.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
8 months agonet: tcp: Don't respond to FIN-less ACKs during TIME-WAIT
Barret Rhoden [Fri, 14 Dec 2018 19:46:50 +0000 (14:46 -0500)]
net: tcp: Don't respond to FIN-less ACKs during TIME-WAIT

Under the normal close sequence, when we receive a FIN|ACK, we enter
TIME-WAIT and respond to that LAST-ACK with an ACK.  Our TCP stack would
send an ACK in response to *any* ACK, which included FIN|ACK but also
included regular ACKs.  (Or PSH|ACKs, which is what we were actually
getting/sending).

That was more ACKs than is necessary and results in an endless ACK storm
if we were under the simultaneous close sequence.  In that scenario,
both sides of a connection are in TIME-WAIT.  Both sides receive
FIN|ACK, and both respond with an ACK.  Then both sides receive *those*
ACKs, and respond again.  This continues until the TIME-WAIT wait period
elapses and each side's TCP timers (in the Plan 9 / Akaros case) shut
down.

The fix for this is to only respond to a FIN|ACK when we are in
TIME-WAIT.

The way I noticed this was when a Go test simultaneously closed both
ends of a loopback connection.  All of the packets went through the
looback interface and were handled by the loopbackread() ktask.  On
occasion, the tcpackproc() ktask would get scheduled on the same core as
loopbackread(), so the timers would not fire until loopbackread()
yielded (Akaros is non-preemptive).  However, loopbackread() would
always have packets, since for every ACK received, it sent another.
loopbackread() would then receive that packet, since it receives every
packet on both sides of a connection on the loopback interface.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agoalarm: Do not allow callbacks to block
Barret Rhoden [Fri, 2 Nov 2018 02:34:17 +0000 (22:34 -0400)]
alarm: Do not allow callbacks to block

This isn't perfect, but it will catch any alarm callbacks that *attempt*
to block.

We have a bunch of issues with alarms.  One of them that affects
userspace, but not the kernel, is alarms that block will delay the
execution of other alarms.  Right now, the kernel just sends kernel
messages, so it's not a big deal.

In upcoming patches, I'm going to need to run all of the alarms in
closer coordination with the tchain so that I can safely tell if unset
works - specifically, the tchain will track which alarm it's running.
To do that, we'll need to serialize alarms on a tchain, which means if
an alarm blocks, it might block all future alarms.  That could deadlock.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agoRename RCU CB context to 'cannot block' context
Barret Rhoden [Fri, 2 Nov 2018 02:10:11 +0000 (22:10 -0400)]
Rename RCU CB context to 'cannot block' context

RCU needed to be able to turn on assertions to check if we're blocking
or not.  It's no surprise that we can use that elsewhere, since the
concept is more general than just being an RCU callback.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agoalarm: Remove IRQ alarms
Barret Rhoden [Fri, 2 Nov 2018 01:40:45 +0000 (21:40 -0400)]
alarm: Remove IRQ alarms

The alarm code has some issues, and dealing with it will be easier with
only one type of alarm.

Right now, the tchain and the alarm RKMs are disconnected, but I think
we'll need to synchronize them a bit more.  It'll be simpler with just
one mechanism that runs outside of IRQ context.

We only had one user, so remove it isn't a big deal.  If we need IRQ
alarms, we can add them back in the future.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agorendez: Use a regular alarm instead of an IRQ alarm
Barret Rhoden [Fri, 2 Nov 2018 01:27:14 +0000 (21:27 -0400)]
rendez: Use a regular alarm instead of an IRQ alarm

This was the only user of IRQ alarms.  To resolve some issues with
alarms, it'd be easier to not have IRQ alarms at all.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agoRemove STAB info
Barret Rhoden [Fri, 2 Nov 2018 01:50:50 +0000 (21:50 -0400)]
Remove STAB info

This was old debugging information.  We haven't used it in years.  All
of our kernel PC-to-name lookups use the reflected symbol table.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agoFix assumption of current != NULL
Barret Rhoden [Thu, 25 Oct 2018 13:13:37 +0000 (09:13 -0400)]
Fix assumption of current != NULL

This goes back to the root cause of commit 38346732733e ("Clear current
before calling proc_decref()").  We needed to clear current back when we
abandon_core().  However, the kthread still thought it needed to save
the address space / context of the process and would try to incref a
NULL pointer.

The root issue is that the kthread was a process kthread, but it lost
its connection to the process during the execution of a syscall (or
trap).  The syscall doesn't even need to be the one that did the
killing.  We just needed to be a non-ktask/RKM.

We could also change up the way the kthread flags work, but I wanted to
highlight the existence of this bug.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agoalarm: Force unset_alarm to grab the CV lock
Barret Rhoden [Tue, 16 Oct 2018 14:20:40 +0000 (10:20 -0400)]
alarm: Force unset_alarm to grab the CV lock

The issue here is that unset_alarm() is now used to mean "is the alarm
service done with the alarm."  Previously, it was "has the function run
yet."

This all is overly fucked up, due to a bunch of things:
- The alarm callbacks allegedly can block.  Not sure if any of them
  actually need that.
- Unset blocks until a CB is done, meaning it might sleep.
- So we need the CV and flags, and need to do things *after* the
  function pointer runs.
- That means the caller/user needs to be aware of the alarm service, and
  can't reuse/free the alarm right away.
- Alarms can re-arm from within their callbacks, and the service doesn't
  know about it.  Hell, what if they put themselves on another timer
chain?

Even with this change, we still have some issues.  Say you set_alarm()
from within a callback.  Then that alarm fires and runs before the alarm
service finishes it's CV work?  This could easily happen with a global
tchain (like parlib provides).  It could also happen with a per-core
timer chain, if the callback calls set_alarm() and then blocks.  Anyway,
under this situation, we could have *two* contexts trying to finish the
same alarm at the same time, where one of them clears is_running while
the other is still running.

Oh, and if an alarm CB blocks, under the current implementation, it'll
block the other unrelated alarms after it.  Not ideal.

The longer term fix might be to not allow alarm CBs to block (in
userspace, this means no uthread mutexes, which is actually already the
case since they run in vcore context).  This actually makes it a lot
more like Linux's timer stuff: they run in softirq context only (not
hard irq), though their del_timer_sync is a bit nasty.  They allow
mod_timer() to be called from within the CB, though maybe a little
discipline could help out with some of the corner cases.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agofutex: Disable notifs when waking waiters
Barret Rhoden [Mon, 15 Oct 2018 20:48:26 +0000 (16:48 -0400)]
futex: Disable notifs when waking waiters

When you call cpu_relax_vc() as a uthread, it simply spins, with the
assumption that we'd find out about the preemption via a
notification/IPI.  Although that is true, parlib will only prioritize
vcore context code.  A 2LS won't know to run particular uthread, since
the "spinning-on" relationship is unknown to the 2LS.

By putting the thread that is the target of the busy-wait in vcore
context (or pretending to, with notifs disabled), we get the behavior we
want.

Note the old version of futex code also had this problem when we
busy-waited on awaiter.data = NULL.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
9 months agofutex: Implement futexes with CVs
Barret Rhoden [Mon, 15 Oct 2018 20:24:50 +0000 (16:24 -0400)]
futex: Implement futexes with CVs

This version is similar to the old one in that we still have a single
futex_element per futex_wait call, and there is a linked list of these
elements.  Future versions could use a hash table or something.

You could even consider having M:1 waiters to addresses, with those
structs in a hash table.  If you do this, consider keeping the futex
elements forever.

The thing to be careful of is the lifetime of the futex element.  This
is something the old code had a hard time with, and this new code is no
exception.

The old version had hand-rolled the timeout.  Although the new code
avoids the duplicated issues there, the one benefit of the timeout was
that it yanked 'e' off the list, such that if the futex_wait() uthread
was running, then we knew it was off the list.  In the current version,
we must yank it off the list, and then wait for any users (futex_wake())
to be done with it.  Fun with shared memory synchronization!  The
current approach is similar to the old awaiter.data = NULL approach, but
this is more explicit.

Here are a few other things I considered:
- Put the futex element in the uthread/pthread: our thread could exit,
  instead of just unwinding the stack, so this is broken.  It's still a
use-after-free issue.

- Have a custom timeout with the CV, and have the timeout just do
  futex_wake: Not a bad idea.  I wanted to use the CV infrastructure
instead of rolling our own.  We'd also need a bit to signal that the
wakeup was a timeout.  Also, in future versions, I want to use a single
CV for multiple waiters, and this would break that.

- Never have the waker yank the CV element, just kick the CV: We still
  have the lifetime issues.  Even if we know we didn't timeout, we still
could have another waker (consider multiple threads calling
futex_wake()).  The root cause here is that the waker kicks the CVs
outside the futex lock, which was an attempt to cut down on the number
of locks held across 2LS ops.  Though note the CV lock *is* held across
some 2LS ops (has_blocked).

- Have the waker grab the CV lock while holding the futex lock, in an
  attempt to transfer the lock.  The rule is to hold both locks when
adding/removing an element from the list: That would work, but would
require the waiter to do a trylock (lock ordering), and handling the
fallback (unlock CV, then lock for real).  I'd like to avoid gratuitous
global locking.

- Don't have elements at all, use a single CV: we want to wake based on
  uaddr, which would require knowing the waiters that waited on a
specific addr.  A CV per addr works.  (Right now, we have a CV per
waiter).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agofutex: Call unset_alarm() before freeing the awaiter
Barret Rhoden [Fri, 12 Oct 2018 15:10:05 +0000 (11:10 -0400)]
futex: Call unset_alarm() before freeing the awaiter

The old 'awaiter->data = NULL' was a signal that we were done with the
awaiter.  The race was that the uthread that called futex_wait() was
restarted before everyone was done with the awaiter - where 'everyone'
means the timeout handler and futex_wake().  The last thing you do to
the awaiter was unblock it.

However, since commit 9969434fee6b ("parlib: Run alarm handlers outside
the tchain lock"), the alarm service is not done with the awaiter until
is_running == false and the condvar is unlocked.  The awaiter->data ==
NULL check was no longer sufficient.

Unsetting the alarm fixes this, just like the CV code does.  Though I
have broader concerns about this and other uses of set_alarm().  In
particular, it's a little lousy to unset alarms you know have completed,
since 'unset' is how you know the alarm is done.

The specific bug was a deadlock.  The alarm service ran the timeout
handler, but didn't grab the CV lock in the awaiter yet.  The uthread
that called futex_wake() unblocked, was run, returned, and then called
other functions (from Go / KenC btw).  That clobbered the awaiter, which
was on the stack.  The VC that ran the alarm handler then tried to grab
the CV lock, which happened to be clobbered with a function return
address.  The actual clobber was to set the lock 0, which meant that VC
0 was the lockholder.  VC 1 would just spin, checking that VC 0 was not
preempted.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoalarm: Clean up condition variable usage
Barret Rhoden [Thu, 11 Oct 2018 20:33:14 +0000 (16:33 -0400)]
alarm: Clean up condition variable usage

The while loop is the classic Mesa-semantic use of a CV.  For some
reason, the old version was a tortured while loop with breaks and
whatnot.  The new version is simpler, easier to read, classically
correct, and has a nicer personality.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agonet: Clear stale synth_buf pointer
Barret Rhoden [Thu, 11 Oct 2018 20:30:49 +0000 (16:30 -0400)]
net: Clear stale synth_buf pointer

No one should use synth_buf that did not set it, but this prevents
reusing the pointer.  Or at least it prevents reusing a non-NULL
pointer.  =)

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agomem: Don't make assertions about c->synth_buf
Barret Rhoden [Thu, 11 Oct 2018 20:27:55 +0000 (16:27 -0400)]
mem: Don't make assertions about c->synth_buf

Old chans may have that set, even ones that aren't from this device,
though they shouldn't.  If we want to check for that, we can do it
elsewhere.

Qslab_trace was using c->synth_buf in older versions, and this check was
left behind.  Now that we aren't using it, let's not keep old references
around.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agocs: Fix leaked pthreads
Barret Rhoden [Tue, 9 Oct 2018 19:45:56 +0000 (15:45 -0400)]
cs: Fix leaked pthreads

We were leaking pthreads, once for each job request.  This was a major
culprit in leaking memory when running go tests.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoslab: Add an interface for slab tracing
Barret Rhoden [Tue, 9 Oct 2018 21:35:44 +0000 (17:35 -0400)]
slab: Add an interface for slab tracing

Usage:

(akaros) / $ echo start kpages_8192 > \#mem/slab_trace

(run some test)

(akaros) / $ echo stop kpages_8192 > \#mem/slab_trace
(akaros) / $ echo print kpages_8192 > \#mem/slab_trace
(akaros) / $ cat \#mem/slab_trace

Dumping outstanding allocs from kpages_8192
-------------------------
Obj 0xffff8000042be000, from PID 28 /bin/cs: (null), 0x00003000003059cb:
----
 #01 [<0xffffffffc205c541>] in kmem_cache_alloc
 #02 [<0xffffffffc2002297>] in arena_alloc
 #03 [<0xffffffffc204ec75>] in kpages_alloc
 #04 [<0xffffffffc2126098>] in __pml_walk
 #05 [<0xffffffffc2126126>] in __pml_walk
 #06 [<0xffffffffc2126126>] in __pml_walk
 #07 [<0xffffffffc2126be1>] in pgdir_walk
 #08 [<0xffffffffc20159e9>] in map_page_at_addr
 #09 [<0xffffffffc2016820>] in __hpf
 #10 [<0xffffffffc2017a7e>] in handle_page_fault
 #11 [<0xffffffffc212a6c3>] in trap

etc.

There should be one user of slab_trace at a time.  If you have multiple
users, you might not get the results you want and could lose your trace
data.  Under the hood, the data buffer is tied to slab_trace, not to an
FD.  If we attach it to an FD, then you can't access it easily from the
console, since you'd need to pass that FD between the shell's
sub-processes - not worth the effort.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoslab: Add tracing infrastructure for allocs and frees
Barret Rhoden [Tue, 9 Oct 2018 21:23:02 +0000 (17:23 -0400)]
slab: Add tracing infrastructure for allocs and frees

When tracking down memory leaks, it is helpful to know if we have
allocated anything that was not freed.

Kmem tracing tracks all allocations (and their backtraces) and drops
those traces when the object is freed.  This tracing happens *above* the
magazine layer, so you're seeing the actual allocs/frees.  You don't
need to worry about objects hanging out in the depots.  Although
stranding resources in depots is a memory management concern, it's not a
memory leak from the user of the allocator.

You can target specific caches (slab allocators) for a more fine-grained
trace - and one that may avoid false positives.

In general, you watch #men/kmemstat or slab_stats to find what is
growing that you don't expect.  Then you trace it, run a test that
shouldn't increase the memory load, stop the trace, and dump the info.

You can expect a trace to not increase the load if all new processes are
destroyed and all files are either already in the page cache or are
flushed.  For the most part, a single go test does this.  You might get
a few kstack allocations, since kernel stacks aren't bound to particular
processes.

Note that we locklessly peek at kmc->flags.  That global memory access
happens on every alloc and free, including the per-core allocations,
even when tracing is off.  I'd prefer it to be as lightweight as
possible so we're less inclined to build with tracing turned off.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoslab: Warn when creating multiple caches with the same name
Barret Rhoden [Tue, 9 Oct 2018 20:12:16 +0000 (16:12 -0400)]
slab: Warn when creating multiple caches with the same name

Tracing infrastructure will look up caches by name.  If there is a
collision, we will only be able to trace the first one.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoAdd sza_print_backtrace_list()
Barret Rhoden [Tue, 9 Oct 2018 20:08:35 +0000 (16:08 -0400)]
Add sza_print_backtrace_list()

This is for generating backtrace text that can be easily exported to
userspace via 9ns device files.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoIntegrate 'sofar' into sized_allocs
Barret Rhoden [Mon, 8 Oct 2018 19:28:08 +0000 (15:28 -0400)]
Integrate 'sofar' into sized_allocs

A sized_alloc is often (and only) used for accumulating info in a
buffer.   It contained a size, but the user of the sza (#proc and #mem)
needed to manage the 'sofar' variable, which tracks how much of the
space we already used.

Instead of everyone having to manage this, 'sofar' is now built in to
the sza.  Use it, if you like.

In fact, printing to an sza is so common that we have a helper, which
does the snprintf stuff - which you can see was boilerplate used 100
times.  No need for that.  Note Akaros's snprintf()'s return value is
not the same as glibcs.  sza_printf() hids this to some extent.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoReplace GET_FRAME_START with get_caller_fp()
Barret Rhoden [Tue, 9 Oct 2018 20:07:28 +0000 (16:07 -0400)]
Replace GET_FRAME_START with get_caller_fp()

We already had get_caller_pc() and just needed to get the caller's frame
pointer for backtraces.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoMake SYS_chdir affect other processes
Barret Rhoden [Tue, 2 Oct 2018 19:55:13 +0000 (15:55 -0400)]
Make SYS_chdir affect other processes

Our chdir() takes a pid.  A controlling process (e.g. a parent) can change
the directory of a child.  This is meant to be done after proc_create and
before proc_run; the parent can set up the child before it starts running,
which avoids all sorts of nasty issues that happen in the fork() world.

Unfortunately, our chdir wasn't doing that since we got rid of the VFS.
This fixes a Go test that we had always skipped (TestStartProcess).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoUnset CC for apps-install makes
Barret Rhoden [Tue, 2 Oct 2018 17:38:49 +0000 (13:38 -0400)]
Unset CC for apps-install makes

If the user overrides CC on the commandline, that was getting passed
through to the make apps-install commands.  Even though we compute CC in
our top-level Makefile, we were not passing it along, and the one from the
shell's environment makes it through.

Additionally, we can't export CC directly, which is what I tried at first.
That will break other things (binutils, actually).  The safest thing is to
not export it.

This came up as a problem with travis, which sets its own CC variable, and
ends up using the wrong compiler for the applications.  For instance, here
are some entries from bash's install log:

gcc -c -DHAVE_CONFIG_H -DSHELL   -I. ... etc
x86_64-ucb-akaros-ar cr libreadline.a readline.o ... etc

It knew to use our toolchain prefix in some cases, but it used the CC
override.  If you dig into ./configure, you can see where it makes this
decision (or check ./configure --help).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agotravis: Dump build logs on failure
Barret Rhoden [Mon, 1 Oct 2018 16:18:32 +0000 (12:18 -0400)]
travis: Dump build logs on failure

Hopefully this will make the travis build failures easier to debug.
When/if we add testing, it won't help as much.  Maybe we'll need to remove
the logs on success, or otherwise communicate that we shouldn't dump the
logs.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoAdd EPLAN9 to the error list (XCC)
Barret Rhoden [Mon, 1 Oct 2018 01:49:03 +0000 (21:49 -0400)]
Add EPLAN9 to the error list (XCC)

This will help simplify the Go port, where we have some .go files that
are almost identical to Plan 9's, but for the different errno.

I went with one of the old error strings for EGREG to keep that whole
story rolling along.

Rebuild glibc if you want to use it.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agobash: Fix errstr
Barret Rhoden [Mon, 1 Oct 2018 01:27:12 +0000 (21:27 -0400)]
bash: Fix errstr

The old stuff wasn't working, at least not for echo, which calls bash's
internal error function (builtin_error).  It looks like that
USE_AKAROS_STRERROR wasn't defined.

Now we just tack on errstr after printing the error message and
strerror.  It's not perfect, since the IO stream isn't locked, but it's
good enough.  Additionally, there's a change we're printing an old
errstr, same as with other apps.

Regardless, bash's now reports error strings:

$ echo garbage > /prof/mpstat
bash: echo: write error: Generic Failure, Bad mpstat option (reset|ipi|on|off)

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agobash: Handle errors in echo
Barret Rhoden [Mon, 1 Oct 2018 01:15:30 +0000 (21:15 -0400)]
bash: Handle errors in echo

Our echo patch was ignoring the return of write.  That meant that we
would never know if we echoed a bad value into a device file.  For
example, if you echo garbage > /prof/mpstat, errno and errstr are set.
Bash's echo would silently ignore the failure.  As of this commit, we
see the failure, but don't have errstr yet.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agobash: Split up and order the akaros-patches
Barret Rhoden [Mon, 1 Oct 2018 01:08:41 +0000 (21:08 -0400)]
bash: Split up and order the akaros-patches

This ensures the patches are applied in order and it is easier to work
on various parts of the patch.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoPrint errstr() in glibc's error() (XCC)
Barret Rhoden [Sat, 29 Sep 2018 22:14:50 +0000 (18:14 -0400)]
Print errstr() in glibc's error() (XCC)

Glibc has a bunch of error reporting helpers, such as error().  These
take an int errnum, usually a failed errno, and a few other things to
print out, similar to perror().  Internally, these functions do a
strerror and print out a text description of the errno.

We'd also like to print out errstr.  However, the caller is typically an
external package, such as 'grep'.  We could provide an alternative
family of error() function that takes the saved errstr, but it's
largely not worth the churn.

Most of the time, the errstr is the one that corresponds to the error,
so this gets us a 90% solution.  Often when there is no error, it was
zeroed, so the only time we'll get an old errstr was when there were
multiple errors.  Probably.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoAdd GNU grep to sys-apps
Barret Rhoden [Fri, 28 Sep 2018 20:29:52 +0000 (16:29 -0400)]
Add GNU grep to sys-apps

This will get built and installed with the other apps.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoUse readstr() for #device text buffers
Barret Rhoden [Fri, 28 Sep 2018 20:12:06 +0000 (16:12 -0400)]
Use readstr() for #device text buffers

These two follow the sized_kmalloc pattern for generating buffers.  They
generate text, not raw data, and it should be readstr, not readmem.
Otherwise, we'll return extra bytes (zeros).

Note that our snprintf() (which creates the data in these cases) enforces
null-termination, so there's no concern with running off the end of the
sza.

Also note that our snprintf() returns the amount written, not the amount of
space needed, which is non-standard.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoDrop the \0 from readstr()
Barret Rhoden [Fri, 28 Sep 2018 20:10:57 +0000 (16:10 -0400)]
Drop the \0 from readstr()

Userspace can handle determining the length by the return value.  Some
tools (e.g. GNU grep) don't like the \0 and think the contents are binary.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoThrow an error on bad statchecks
Barret Rhoden [Tue, 25 Sep 2018 03:38:53 +0000 (23:38 -0400)]
Throw an error on bad statchecks

statcheck() was returning -1, and both of its callers would throw an
error.  We might as well report the specific error and squelch the
warning.

Reported-by: syzbot+0068960e94fbc67ffab4@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
10 months agoClear current before calling proc_decref()
Barret Rhoden [Tue, 25 Sep 2018 01:19:37 +0000 (21:19 -0400)]
Clear current before calling proc_decref()

'current,' aka pcpui->cur_proc, is a counted reference that is viewable
from code other than the code that is clearing the ref.  Even though
it's a per-core data structure, it's just like a ref in a global data
structure.

In this case, if you decref current when you are not guaranteed to have
an extra ref, you could have dropped the final reference.  Anyone who
uses 'current' after that is basically a use-after-free bug.

Here's a specific backtrace of the bug.  A process was exiting and the
final ref was dropped in __abandon_core(), but not cleared from current.
The process had a chan that was decreffed in __proc_free(), and that
chan eventually needed to block.  sem_down() saw 'current' and attempted
to save a reference to it, even though the process was basically freed.

 Stack Backtrace on Core 0:
 #01 [<0xffffffffc200a00c>] in backtrace
 #02 [<0xffffffffc20097fd>] in _panic
 #03 [<0xffffffffc2048ef6>] in kref_get
 #04 [<0xffffffffc200ba71>] in sem_down
 #05 [<0xffffffffc200bdbb>] in sem_down_bulk
 #06 [<0xffffffffc2050189>] in rcu_barrier
 #07 [<0xffffffffc2041ec6>] in tf_dfs_purge
 #08 [<0xffffffffc2041f90>] in tf_dfs_purge
 #09 [<0xffffffffc2041f90>] in tf_dfs_purge
 #10 [<0xffffffffc2041f90>] in tf_dfs_purge
 #11 [<0xffffffffc2041f90>] in tf_dfs_purge
 #12 [<0xffffffffc2079050>] in gtfs_release
 #13 [<0xffffffffc2078deb>] in kref_put
 #14 [<0xffffffffc20315d0>] in chan_release
 #15 [<0xffffffffc2030cfb>] in kref_put
 #16 [<0xffffffffc2048b1a>] in __proc_free
 #17 [<0xffffffffc2048a6b>] in kref_put
 #18 [<0xffffffffc20a6f21>] in __abandon_core
 #19 [<0xffffffffc204c8b9>] in abandon_core
 #20 [<0xffffffffc20539cd>] in __smp_idle

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
11 months agoAdd /tmp to KFS
Barret Rhoden [Wed, 12 Sep 2018 19:41:43 +0000 (15:41 -0400)]
Add /tmp to KFS

It is needed by the Go tests.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
11 months agoUse two-page stacks
Barret Rhoden [Wed, 12 Sep 2018 15:23:35 +0000 (11:23 -0400)]
Use two-page stacks

This was an option before, but with all of the 9p/#gtfs stuff, we're
running off a single stack page.

I'm not as worried about two-page stacks anymore, due to our arena
allocator.  We're currently grabbing two physically contiguous pages,
which we can always change if it becomes a problem - kernel stacks are
virtually mapped.

Also, the guard page at the end of the kernel stacks still works.  =)

For those curious, here is an example backtrace with frame pointers to
show the stack consumption.  None are egregious, but there are a few
large ones.

 01 [<0xffffffffc2002292>] FP 0xfffffff000075048 in arena_alloc
 02 [<0xffffffffc20533c4>] FP 0xfffffff000075098 in __kmem_alloc_from_slab
 03 [<0xffffffffc2053bea>] FP 0xfffffff0000750d8 in kmem_cache_alloc
 04 [<0xffffffffc200a272>] FP 0xfffffff0000750f8 in kmalloc
 05 [<0xffffffffc2030308>] FP 0xfffffff000075118 in block_alloc
 06 [<0xffffffffc203b165>] FP 0xfffffff000075158 in copyblock
 07 [<0xffffffffc203b2ab>] FP 0xfffffff000075178 in linearizeblock
 08 [<0xffffffffc20ee840>] FP 0xfffffff0000751a8 in etheroq
 09 [<0xffffffffc20eed23>] FP 0xfffffff000075248 in etherbwrite
 10 [<0xffffffffc201a272>] FP 0xfffffff0000752b8 in etherbwrite
 11 [<0xffffffffc201d4a5>] FP 0xfffffff000075388 in ipoput4
 12 [<0xffffffffc202b9b6>] FP 0xfffffff000075478 in tcpoutput
 13 [<0xffffffffc202bed0>] FP 0xfffffff0000754f8 in tcpkick
 14 [<0xffffffffc203aa8e>] FP 0xfffffff000075538 in __qbwrite
 15 [<0xffffffffc203acd0>] FP 0xfffffff0000755d8 in __qwrite
 16 [<0xffffffffc203c2b7>] FP 0xfffffff0000755e8 in qwrite
 17 [<0xffffffffc201676c>] FP 0xfffffff0000756a8 in ipwrite
 18 [<0xffffffffc20f4d0c>] FP 0xfffffff000075728 in mountio
 19 [<0xffffffffc20f4fc5>] FP 0xfffffff000075748 in mountrpc
 20 [<0xffffffffc20f6394>] FP 0xfffffff0000757e8 in mntstat
 21 [<0xffffffffc203dd0d>] FP 0xfffffff000075888 in chandirstat
 22 [<0xffffffffc20f08f8>] FP 0xfffffff0000758b8 in gtfs_tf_couple_backend
 23 [<0xffffffffc20f09e3>] FP 0xfffffff0000758e8 in gtfs_tf_lookup
 24 [<0xffffffffc205c7b3>] FP 0xfffffff000075978 in lookup_child_entry
 25 [<0xffffffffc2042a4e>] FP 0xfffffff000075a38 in tree_file_walk
 26 [<0xffffffffc2042af4>] FP 0xfffffff000075a68 in tree_chan_walk
 27 [<0xffffffffc20f0bf1>] FP 0xfffffff000075a88 in gtfs_walk
 28 [<0xffffffffc20324ad>] FP 0xfffffff000075b38 in walk
 29 [<0xffffffffc2032f19>] FP 0xfffffff000075ca8 in __namec_from
 30 [<0xffffffffc2033aff>] FP 0xfffffff000075d18 in namec
 31 [<0xffffffffc203c926>] FP 0xfffffff000075db8 in __stat
 32 [<0xffffffffc203dad9>] FP 0xfffffff000075de8 in sysstatakaros
 33 [<0xffffffffc2055ebc>] FP 0xfffffff000075e28 in stat_helper
 34 [<0xffffffffc2055f6f>] FP 0xfffffff000075e38 in sys_lstat
 35 [<0xffffffffc20596d9>] FP 0xfffffff000075ee8 in syscall
 36 [<0xffffffffc20598d4>] FP 0xfffffff000075f58 in run_local_syscall
 37 [<0xffffffffc2059e09>] FP 0xfffffff000075f78 in prep_syscalls
 38 [<0xffffffffc212206a>] FP 0xfffffff000075f98 in sysenter_callwrapper

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
11 months agoSet up go function pointer table
Brian Wheatman [Tue, 28 Aug 2018 14:49:49 +0000 (10:49 -0400)]
Set up go function pointer table

To use usys in go we cause a GP fault which is then caught with known
high 16 bits.

The lower 48 bits are used to specify the address of a jump table which
go will use for usys function calls

Change-Id: Id0698f04b784a9d3376c10dd8fcbaebf8633cf50
Signed-off-by: Brian Wheatman <wheatman@google.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoDon't cache pcpui in sys_fork()
Barret Rhoden [Tue, 14 Aug 2018 18:27:46 +0000 (14:27 -0400)]
Don't cache pcpui in sys_fork()

There wasn't a bug here, yet, but this cuts down on the number of places
that could accidentally cache pcpui and access it after a migration.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoFix stale pcpui in sys_exec()
Barret Rhoden [Tue, 14 Aug 2018 17:55:49 +0000 (13:55 -0400)]
Fix stale pcpui in sys_exec()

sys_exec() can block.  It might resume on another core, perhaps due to a
file system operation or qio that unblocked due to an MCP's syscall.
Before this patch, it would use the pcpui of its original core - core 0.
That would cause it to finish whatever syscall was running on that core,
which could be a nightmare.

We caught this when free_sysc_str() tried to free a ktask's name, which is
the kthread->name.  free_sysc_str() expects to be called targeting a
kthread executing a syscall, but instead it hit whatever was on core 0 -
etherread4 in this case.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoparlib: Run alarm handlers outside the tchain lock
Barret Rhoden [Tue, 14 Aug 2018 14:54:44 +0000 (10:54 -0400)]
parlib: Run alarm handlers outside the tchain lock

This follows the same pattern as the kernel's alarm service.  Note the use
of uth_cond_var_lock(), since our tchain is kicked from vcore context.

Anyone calling __set_alarm() needs to just call set_alarm().  The old
special casing of code that was run from an alarm handler is gone.

This should resolve a deadlock between the futex code and the alarm code.
__futex_block() holds the futex's spinlock and tries to set an alarm, which
grabs the alarm's tchain lock.  The lock ordering is futex -> alarm/tchain.
__futex_timeout(), which is an alarm handler, grabs the futex lock.  Prior
to this patch, alarm handlers held the tchain lock.  That required a lock
ordering of alarm/tchain->futex, which causes a deadlock.  Alarm handlers
no longer hold the tchain lock, which breaks the circular wait.

Fun tidbit: the alarm utest failed on hardware, since the time was exactly
right (rounded to the nearest usec).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoparlib: Support mutex-less condition variables
Barret Rhoden [Mon, 13 Aug 2018 22:26:19 +0000 (18:26 -0400)]
parlib: Support mutex-less condition variables

If we want to signal or broadcast a condition variable, typically we also
want to have grabbed (and possibly released) the mutex that was protecting
whatever state the sleeper cares about.  See my notes in mutex.c for an
example.

Event handlers and other vcore context code cannot grab mutexes, however
they can grab spinlocks.  "Mutex-less" CVs use the CV's spinlock for
synchronization.  These locks can be grabbed in any context, and thus we
can kick the CVs from vcore context.

This is the same solution I came up with for the kernel's CVs, and probably
for the same reasons.  Both deal with interrupt context that can't block,
and both interact with threads that do block.

Whether or not mutex-less CVs are the best way to deal with the issue, they
work.  By comparison, the POSIX pthread_cond_var functions are not even
signal safe, let alone the mutexes that you'll often want to grab.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoparlib: Fix panic output
Barret Rhoden [Mon, 13 Aug 2018 22:25:30 +0000 (18:25 -0400)]
parlib: Fix panic output

It would print panic.c:37, instead of the source of the panic.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoalarm: Do not hold the tchain lock during handlers
Barret Rhoden [Mon, 13 Aug 2018 20:38:21 +0000 (16:38 -0400)]
alarm: Do not hold the tchain lock during handlers

It's a bad idea to hold the tchain lock when running handlers.  For the
kernel's alarms, this was the case for IRQ handlers.

The main issue is deadlock between the handler and set/unset.  You can see
how we tried to avoid this in the past - alarm handlers were allowed to
set_alarm(), since we'd track 'holds_tchain_lock'.  That flag would turn
off lock checking for set_alarm(), but only for that strcut alarm_waiter.
However, we could have a situation where the alarm handler spins on a lock
held by someone else who is trying to set an alarm.  Something similar
happened in userspace with futexes and the alarm service.  (Though
userspace didn't have the 'holds_tchain_lock').

We already had the ability to run alarm handlers outside the tchain lock
for RKM alarms, which IIRC are newer than 'holds_tchain_lock'.  Now IRQ
alarms are treated the same way.

I was also able to break the lock ordering between the waiter's CV lock and
the tchain lock, as well as clean up a few other cases.  For the most part,
IRQ handlers differ from RKM only in when they run and the type of the
function pointer.

Also, rendez peaks directly at on_tchain.  That's still OK, but a little
suspect.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoAdd dmesg to the monitor
Barret Rhoden [Mon, 13 Aug 2018 20:32:00 +0000 (16:32 -0400)]
Add dmesg to the monitor

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoparlib: Fix alarm_abort_sysc() leak
Barret Rhoden [Tue, 7 Aug 2018 15:10:30 +0000 (11:10 -0400)]
parlib: Fix alarm_abort_sysc() leak

It was possible to set an alarm to abort a syscall and break out of the
alarm handler while blocked on an abortable syscall.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agostrace: Coalesce a common case statement
Barret Rhoden [Tue, 31 Jul 2018 20:12:33 +0000 (16:12 -0400)]
strace: Coalesce a common case statement

SYS_write was doing the same thing that other syscalls were doing; no need
for two cases.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agostrace: Fix SYS_chdir data parsing
Barret Rhoden [Tue, 31 Jul 2018 20:09:44 +0000 (16:09 -0400)]
strace: Fix SYS_chdir data parsing

I broke this a few commits back.  Our chdir syscall takes a pid for the
first argument, unlike the man page for chdir.

Fixes: 27f971ff2d4e ("strace: Fix issues with a few syscalls")

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoparlib: Basic implementation of sigaltstack
Brian Wheatman [Fri, 20 Jul 2018 17:38:30 +0000 (13:38 -0400)]
parlib: Basic implementation of sigaltstack

Change-Id: Iab287b7a14873fcf77063b4dd98fb98d4c32f75d
Signed-off-by: Brian Wheatman <wheatman@google.com>
[Added 'parlib' to the title]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoAdd backtrace helpers
Barret Rhoden [Mon, 30 Jul 2018 20:00:00 +0000 (16:00 -0400)]
Add backtrace helpers

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoMake proc_restartcore() call smp_idle()
Barret Rhoden [Mon, 30 Jul 2018 19:46:52 +0000 (15:46 -0400)]
Make proc_restartcore() call smp_idle()

Maybe we should just remove proc_restartcore().  They both did similar
things, and proc_restartcore() could call smp_idle.  PRKM calls smp_idle()
if it handles a message, which is built for how smp_idle works, but then it
ignores proc_restartcore().

It's not a big deal either way.  Though by having a single function that
deals with all of the RCU / halting / PRKM / abandon_core issues is a lot
simpler.

The old proc_restartcore() actually had an RCU bug too - it reported the
quiescent state after checking PRKM, which means the rcu_gp_ktask could
have been delayed from starting up.  This wouldn't usually show up as a
deadlock or anything, since there was a process on that core which would
eventually either block or die, at which point we'd run our kernel
messages.  You'd have needed a process to be stuck in a while(1), waiting
for an event that was triggered by RCU.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoFix abandon_core()'s halting-with-KMSG bug
Barret Rhoden [Mon, 30 Jul 2018 19:31:25 +0000 (15:31 -0400)]
Fix abandon_core()'s halting-with-KMSG bug

This seemed like an RCU problem, but I think it was just an MCP + strace
bug.  Here's the scenario:

- straced MCP exits while another core executes a syscall that eventually
  calls smp_idle.
- There are a few cases where we can get in smp_idle, PRKM and get a
  __death, and still have current set (a process kref).
- PRKM, then try_run_proc(), then abandon_core().  If we had the last kref
  for the proc, we __proc_free().
- If the process was straced, __proc_free() will hangup the qio, which
  sends a message to the calling core to wake strace.
- When abandon_core() returns, it halts.

The code was built assuming (perhaps implicitly) that abandon_core() won't
trigger a kernel message.  That is no longer true.  strace is just one
example.  We could have others due to the cclose() called on 'dot.'
(perhaps if the process CD'd into a directory, of which there were no other
references, and the devtab.close method did something special).

You could trigger this with a bunch of different syscalls too.  We were
running a Go test, so I saw calls like proc_yield (slight red herring
there), poke_ksched, block, etc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoAdd print_lock() protection to prov -s
Barret Rhoden [Mon, 30 Jul 2018 15:40:58 +0000 (11:40 -0400)]
Add print_lock() protection to prov -s

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months ago9ns: Add CCTL_DEBUG
Barret Rhoden [Mon, 30 Jul 2018 15:35:07 +0000 (11:35 -0400)]
9ns: Add CCTL_DEBUG

This allows the user to dump the contents of the TFS, via printk.  I've
been maintaining hokey kfuncs out of tree to do this, and it's getting old.

If you dump a directory, it'll dump all of the contents of the directory,
recursively.  So to see the entire TFS, run chan_debug on the mount point.

Note that the mount order matters (mount -b to put your device first).
Otherwise, you'll chan_debug the directory in e.g. #kfs instead of #gtfs.

Also note that the TFS only maintains the frontend of the filesystem: the
stuff we have in RAM.  For #kfs, this is everything.  But for #gtfs (and
future disk filesystems), this is just a cache.  For example:

(akaros) / $ chan_debug /mnt/
Dumping tree_file info (frontend), dev gtfs, chan /mnt:

netroot   : Q: 15204682, R:  3, U eve, d755
---------------------

There's just the mountpoint (named netroot) so far.

(akaros) / $ ls /mnt/
foo.pdf               filepath              go_get_html
bar                   foo                   hello-go
bin                   g3.cpio               initramfs.cpio
dir1                  g3libs.cpio           somefile
(akaros) / $ chan_debug /mnt/
Dumping tree_file info (frontend), dev gtfs, chan /mnt:

netroot   : Q: 15204682, R: 15, U eve, d755
---------------------
    filepath  : Q: 19796349, R:  0, U eve, d750
    ---------------------
    dir1      : Q: 18750984, R:  0, U eve, d755
    ---------------------
    somefile  : Q: 15205606, R:  0, U eve, -777
    bar       : Q: 15205764, R:  0, U eve, -644
    hello-go  : Q: 15205604, R:  0, U eve, -777
    g3.cpio   : Q: 15204767, R:  0, U eve, -640
    g3libs.cpio: Q: 15205231, R:  0, U eve, -640
    initramfs.cpio: Q: 15222556, R:  0, U eve, -640
    bin       : Q: 20841102, R:  0, U eve, d750
    ---------------------
    go_get_html: Q: 15205603, R:  0, U eve, -777
    foo.pdf   : Q: 15206000, R:  0, U eve, -644
    foo       : Q: 24388167, R:  0, U eve, d755
    ---------------------

Once 'ls' brought the TFs/inodes into the TFS's cache, we were able to see
them when we dumped the directory.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months ago9ns: Add tree_chan_ctl()
Barret Rhoden [Mon, 30 Jul 2018 15:33:51 +0000 (11:33 -0400)]
9ns: Add tree_chan_ctl()

This provides a default operation (right now, just errors) for tree file
systems.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoAdd fd_chan_ctl() (XCC)
Barret Rhoden [Mon, 30 Jul 2018 14:37:19 +0000 (10:37 -0400)]
Add fd_chan_ctl() (XCC)

fcntl() supports the basic POSIX commands, like 'sync' and 'get flags'.  We
now use the same infrastructure to pass through other chan_ctl commands.
Some operations like sync and set_fl were already implemented with
chan_ctl, albeit with some device-independent work in the case of set_fl.

The way to think about it now is that fcntl() has a few special cases for
POSIX commands (e.g. F_SYNC), and both fcntl() and fd_chan_ctl() do some
interpretation/processing of the commands for things that the device is not
involved in (F_GETFD) or needs common support (flag checking for F_SETFL).

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoMake the syscall error detector a kernel header (XCC)
Barret Rhoden [Fri, 27 Jul 2018 20:14:46 +0000 (16:14 -0400)]
Make the syscall error detector a kernel header (XCC)

This information is part of the ABI.  It will help Go userspace determine
whether or not a syscall had an error and thus to extract errno/errstr.

Note that glibc sets errno and errstr based on the syscall->err field
(which is errno).  This means that errno and errstr are set on occasion
even though the syscall didn't have an error.  Glibc apps are expected to
only look at errno/errstr when they know the syscall had an error.

I considered changing glibc (ros_syscall_errno) to use this helper, but it
might be better to have the false positives of copying errno/errstr than to
go through the helper + switch table.  Benchmarks would help here - in lieu
of that I'll leave it as it is.

Reinstall your kernel headers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agostrace: Report correct core IDs
Barret Rhoden [Mon, 30 Jul 2018 20:00:27 +0000 (16:00 -0400)]
strace: Report correct core IDs

The coreid (pcoreid) was the core where the syscall was called, not where
the syscall's exit event was created.  Some calls start on one core and
finish on another.

The vcoreid for exit records can't be trusted, so I stopped reporting it.
Although it is usually the same as the entry record, there might not even
be a vcore where the syscall is running, particularly after a blocking
call.  The vcore might even be different than the one that issued the call.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agostrace: Fix issues with a few syscalls
Barret Rhoden [Fri, 27 Jul 2018 19:52:37 +0000 (15:52 -0400)]
strace: Fix issues with a few syscalls

SYS_getcwd wasn't part of the file set.  We were tracing the wrong
arguments for SYS_chdir and SYS_rmdir.  SYS_readlink had an unnecessary
check on retval.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agoMake SYS_getcwd return the string length
Barret Rhoden [Fri, 27 Jul 2018 19:51:43 +0000 (15:51 -0400)]
Make SYS_getcwd return the string length

Userspace doesn't use this, but it helps with strace.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agogtfs: Don't use a kernel message for destruction
Barret Rhoden [Fri, 27 Jul 2018 18:44:23 +0000 (14:44 -0400)]
gtfs: Don't use a kernel message for destruction

The decref only happens from the devtab->close() which is never called from
an RCU callback.  It used to be, until commit 99932a6cf527 ("Don't
chan_release() from an RCU callback").

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months ago9ns: Fix TF lookup code error cases
Barret Rhoden [Fri, 27 Jul 2018 18:05:43 +0000 (14:05 -0400)]
9ns: Fix TF lookup code error cases

I didn't run into these at runtime, but the old code looked like it would
panic if we'd ever have a lookup op throw, since 'next' was NULL.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months ago9ns: Fix dangling negative TFs
Barret Rhoden [Thu, 26 Jul 2018 20:55:35 +0000 (16:55 -0400)]
9ns: Fix dangling negative TFs

If you remove a directory that has negative entries (but not real children
- that would fail), those negative children would keep a reference on their
parent (the directory).  When you finally marked the directory
'disconnected', you'd have a positive refcnt, so we wouldn't free it.  We'd
have a ball of disconnected references, none of which would ever get freed.

Now that directory wasn't freed.  Same with its negative entries.  So far,
it's just wasted memory.  However, since we didn't __tf_free it, we also
kept a reference on *its parent.*  But that parent doesn't have a pointer
to the original directory (it is disconnected).  Now we're leaking
references on another directory.

Later, when you unmounted the filesystem and we tried to purge everything,
we'd hit that directory with the leaked references and panic.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months ago9ns: Fix issues with can_have_children
Barret Rhoden [Thu, 26 Jul 2018 20:24:13 +0000 (16:24 -0400)]
9ns: Fix issues with can_have_children

Two things:
1) We cleared can_have_children even when an rmdir failed.  Then subsequent
renames would fail, since it thought the directory was being removed.
2) We never checked can_have_children when creating files.  Maybe I had a
good reason for this, but it's not apparent.  In this case, you might be
able to add a file (or a negative dentry) to a directory while it is being
removed.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 months agomnt: Identify an RPC reader by kthread, not proc
Barret Rhoden [Wed, 25 Jul 2018 18:52:51 +0000 (14:52 -0400)]
mnt: Identify an RPC reader by kthread, not proc

This fixes the dreaded mnt mismatch, e.g.:

mnt: proc current->text 18446744072670166253: mismatch from /net/tcp/1/data
? rep 0x0xffff800009cee020 tag 4 fid 1625 T120 R117 rp 5

The old code assumed the struct proc pointer uniquely identified a kernel
thread that was trying to get a response from a mnt chan.  That was never
the case, since you could have the same proc issue multiple syscalls
concurrently.

We had this bug since the beginning, but it was hard to trigger.  Now that
we have RCU CBs to close chans, which kick off an RKM, the kthread that
actually closes the chan is much more likely to not be for the original
process.  In that case, we're able to get the RPC response from some other
kthread, resulting in the mismatch.

Using the struct kthread to identify the kthread that is waiting on an RPC
is much saner.

I left in using current->user.name for the auth/attach name.  In those
cases, we should be in a syscall (which I check for).  Similarly, when
aborting, we just need to bail out if we are handling a process's syscall -
not if we're some arbitrary kthread.  I think.  There might be issues with
that.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>