4 years agoAdd FD tap infrastructure (XCC)
Barret Rhoden [Thu, 30 Jul 2015 20:18:01 +0000 (16:18 -0400)]
Add FD tap infrastructure (XCC)

FD taps allow the user to receive events when certain things happen to
an FD's underlying disk/device file.  Think epoll/kqueue.  The specific
filters and commands are subject to change.

This commit adds a syscall and the device-independent infrastructure to
pass the command to the device and to deal with all of the issues
related to registration, removal, and other concurrent operations.

Unlike epoll, the FD tap is tracked on the FD and within the device (if
the device so chooses), and this leads to a certain amount of
complexity.  Check out the documentation for details.

Reinstall your kernel headers (make xcc-install-headers).

4 years agoReorganize the scheduler __core_request() loop
Valmon Leymarie [Wed, 23 Sep 2015 00:09:46 +0000 (17:09 -0700)]
Reorganize the scheduler __core_request() loop

Previously there was duplicated code to first loop through a proc's
prov_not_alloc list, and then loop through the idlecore list to find an
available core and allocate it to a proc. This commit consolidates these
loops into a single loop. It works by having a function called
find_best_core(), which always pulls from the prov_not_alloc list
first, only falling back to the idlecore list if the prov_not_alloc list
becomes empty.

The logic to preempt a core stays the same because we know that the
spc_i->alloc_proc field will *only* be set if the core we are
considering is provisioned to the proc, but allocated to someone else
(due to the invariant maintained by the proc's prov_not_alloc list). In
all other cases, we want to simply take the core selected by
find_best_core() and allocate it to the proc using the same logic
regardless of whether it was pulled from its prov_not_alloc list or the
idlecore list.

4 years agoConsolidate track_(de)alloc() with idlecore mgmt.
Valmon Leymarie [Wed, 23 Sep 2015 00:09:38 +0000 (17:09 -0700)]
Consolidate track_(de)alloc() with idlecore mgmt.

Every instance of __prov_track_alloc() and __prov_track_dealloc() were
previously called with a subsequent call to REMOVE a core from the idle
core list or INSERT a core to the idle core list respectively.  This
commit consolidates these calls such that __prov_track_alloc() and
__prov_track_dealloc() now manage adding and removing cores from the
idle core list themselves.

As part of this, the internal __put_idle_cores() function can be
removed, because it was always called in sequence with a call to
__prov_track_dealloc_bulk(), which reinserts the cores into the idlecore
list itself now.

This consolidation helps to narrow the interface for providing alternate
core allocation strategies (which will be forthcoming in a future

4 years agoRename get_this_idle_core ->get_specific_idle_core
Valmon Leymarie [Mon, 21 Sep 2015 22:22:23 +0000 (15:22 -0700)]
Rename get_this_idle_core ->get_specific_idle_core

The name get_specific* is more understandable than get_this* (especially
when compared to the get_any* function it is paired with).

This change is in preparation for a refactoring of the scheduler code
that will come in a subsequent commit.

4 years agoClean up awkward code sequences in ether driver.
Dan Cross [Thu, 24 Sep 2015 01:20:06 +0000 (21:20 -0400)]
Clean up awkward code sequences in ether driver.

Rework two awkward code sequences in the ethernet driver to
make the logic easier to follow.

In the first case, put explicit freeb() and early returns
into etheroq in the cases where we are looping a frame back
up the stack.

In the second, change the loop in etheriq to use 'guard'
conditions and early continues to make the logic linear.

4 years agoAdd a monitor command gfp to get free pages
Xiao Jia [Thu, 17 Sep 2015 03:38:45 +0000 (20:38 -0700)]
Add a monitor command gfp to get free pages

This was useful in debugging buffer allocations in the mlx4 driver.

4 years agoAdd name to pci_device
Xiao Jia [Thu, 17 Sep 2015 03:34:17 +0000 (20:34 -0700)]
Add name to pci_device

4 years agoAllow check_poison() to be called w/o cur_kthread
Barret Rhoden [Wed, 23 Sep 2015 20:04:30 +0000 (16:04 -0400)]
Allow check_poison() to be called w/o cur_kthread

If you called snprintf() or any other function that calls check_poison()
before smp init occurs, then we'd fail the assertion.  It's reasonable
to make those checks early on, so the assertion is now part of the 'if'.

4 years agomlx4: RX path
Xiao Jia [Thu, 17 Sep 2015 03:27:08 +0000 (20:27 -0700)]
mlx4: RX path

After this change, ping works!

4 years agomlx4: TX path
Xiao Jia [Thu, 17 Sep 2015 03:17:16 +0000 (20:17 -0700)]
mlx4: TX path

Critical path was copied from mlx4_en_xmit() to mlx4_send_packet() as a
separate function so we only port what we actually need.

After this change, ifconfig can complete.

4 years agomlx4: Implement ether_attach to start port
Xiao Jia [Thu, 17 Sep 2015 03:09:19 +0000 (20:09 -0700)]
mlx4: Implement ether_attach to start port

4 years agomlx4: Add ether callbacks
Xiao Jia [Thu, 17 Sep 2015 03:01:41 +0000 (20:01 -0700)]
mlx4: Add ether callbacks

4 years agomlx4: Initialize ConnectX HCA Ethernet driver (mlx4_en)
Xiao Jia [Thu, 17 Sep 2015 02:58:08 +0000 (19:58 -0700)]
mlx4: Initialize ConnectX HCA Ethernet driver (mlx4_en)

4 years agomlx4: Initialize ConnectX core driver (mlx4_core)
Xiao Jia [Thu, 17 Sep 2015 01:19:20 +0000 (18:19 -0700)]
mlx4: Initialize ConnectX core driver (mlx4_core)

4 years agomlx4: Clean up to make it compile
Xiao Jia [Thu, 17 Sep 2015 00:58:00 +0000 (17:58 -0700)]
mlx4: Clean up to make it compile

4 years agomlx4: Clean up #include's in headers
Xiao Jia [Thu, 17 Sep 2015 00:15:12 +0000 (17:15 -0700)]
mlx4: Clean up #include's in headers

4 years agoClean up imported rdma headers to compile mlx4
Xiao Jia [Thu, 17 Sep 2015 00:09:01 +0000 (17:09 -0700)]
Clean up imported rdma headers to compile mlx4

4 years agomlx4: Exclude en_ethtool.c for now
Xiao Jia [Thu, 17 Sep 2015 00:05:03 +0000 (17:05 -0700)]
mlx4: Exclude en_ethtool.c for now

4 years agoAdd to_delayed_work() to taskqueue.h
Xiao Jia [Thu, 17 Sep 2015 00:02:21 +0000 (17:02 -0700)]
Add to_delayed_work() to taskqueue.h

4 years agoFix a typo in taskqueue.h
Xiao Jia [Thu, 17 Sep 2015 00:01:59 +0000 (17:01 -0700)]
Fix a typo in taskqueue.h

4 years agoPort scatterlist from Linux
Xiao Jia [Thu, 17 Sep 2015 00:01:18 +0000 (17:01 -0700)]
Port scatterlist from Linux

[brho: added the copyright from Linux's lib/scatterlist.c]

4 years agoPort dmapool from Linux
Xiao Jia [Thu, 17 Sep 2015 00:01:02 +0000 (17:01 -0700)]
Port dmapool from Linux

4 years agoAdd compat layer for mlx4 driver
Xiao Jia [Wed, 16 Sep 2015 23:33:56 +0000 (16:33 -0700)]
Add compat layer for mlx4 driver

Currently I put this compat layer at linux/compat_todo.h so it's treated
as a large piece of hack.  As the mlx4 driver becomes more stable, I'll
gradually move from this file to linux_compat.h in small pieces.

I tested that bnx2x still compiles after this change.

[brho: added copyright header]

4 years agoUpdate linux_compat.h so mlx4 could compile later
Xiao Jia [Wed, 16 Sep 2015 23:23:29 +0000 (16:23 -0700)]
Update linux_compat.h so mlx4 could compile later

I tested that the bnx2x driver still compiles after this change.

4 years agoImport errno.h from Linux 4.1
Xiao Jia [Wed, 16 Sep 2015 23:16:02 +0000 (16:16 -0700)]
Import errno.h from Linux 4.1

The file is actually a result of concatenating multiple files to avoid
pulling in the whole directory structure of Linux.  The file is simply
a series of #define's, so there's no need to spatch it.

[brho: edited to use ros/errno.h for the common #defines]

4 years agomlx4: Apply spatch to files imported from Linux
Xiao Jia [Wed, 16 Sep 2015 23:08:11 +0000 (16:08 -0700)]
mlx4: Apply spatch to files imported from Linux

The following commands were executed repeatedly until convergence.

scripts/spatch/spatch-me.sh scripts/spatch/linux/scalar.cocci yes kern/drivers/net/mlx4/
scripts/spatch/spatch-me.sh scripts/spatch/linux/scalar.cocci yes kern/include/linux/
scripts/spatch/spatch-me.sh scripts/spatch/linux/sync.cocci yes kern/drivers/net/mlx4/
scripts/spatch/spatch-me.sh scripts/spatch/linux/sync.cocci yes kern/include/linux/
scripts/spatch/spatch-me.sh scripts/spatch/linux/memory.cocci yes kern/drivers/net/mlx4/
scripts/spatch/spatch-me.sh scripts/spatch/linux/memory.cocci yes kern/include/linux/
scripts/spatch/spatch-me.sh scripts/spatch/linux/funcs.cocci yes kern/drivers/net/mlx4/
scripts/spatch/spatch-me.sh scripts/spatch/linux/funcs.cocci yes kern/include/linux/
scripts/spatch/spatch-me.sh scripts/spatch/linux/io_funcs.cocci yes kern/drivers/net/mlx4/
scripts/spatch/spatch-me.sh scripts/spatch/linux/io_funcs.cocci yes kern/include/linux/

4 years agoUpdate spatch/linux/*.cocci
Xiao Jia [Wed, 16 Sep 2015 22:53:43 +0000 (15:53 -0700)]
Update spatch/linux/*.cocci

4 years agoImport rdma headers from Linux 4.1
Xiao Jia [Wed, 16 Sep 2015 22:47:54 +0000 (15:47 -0700)]
Import rdma headers from Linux 4.1

4 years agoAdd mlx4 to build process
Xiao Jia [Fri, 26 Jun 2015 00:12:04 +0000 (17:12 -0700)]
Add mlx4 to build process

4 years agoImport mlx4 files from Linux 4.1
Xiao Jia [Tue, 8 Sep 2015 23:26:58 +0000 (16:26 -0700)]
Import mlx4 files from Linux 4.1

4 years agoAdd fls_long() to bitops
Xiao Jia [Fri, 26 Jun 2015 00:10:23 +0000 (17:10 -0700)]
Add fls_long() to bitops

4 years agoUpdate GETTING_STARTED for the new mailing list
Barret Rhoden [Tue, 22 Sep 2015 19:45:15 +0000 (15:45 -0400)]
Update GETTING_STARTED for the new mailing list

The minor ugliness is due to Github/markdown not dealing the the +
nicely.  If you just do <akaros+subscribe@googlegroups.com>, you'll get
nothing.  If you do <mailto:akaros+subscribe@googlegroups.com>, you'll
get a nice looking link, but some browsers will turn the + into a ' '
when sending it to your mail client.  This way looks right (for
copy/paste) and works when I click on it.

4 years agox86: Change idt_init() to not clobber num_cores
Barret Rhoden [Tue, 15 Sep 2015 18:11:09 +0000 (14:11 -0400)]
x86: Change idt_init() to not clobber num_cores

idt_init() uses some Plan 9 techniques to check the MP tables and ACPI
to determine the number of cores.  It was clobbering the value computed
by the topology.  These values should not differ - if they do, there may
be something wrong with MP/ACPI, or we're lacking ACPI at all.

4 years agoUpdate akaros to hook in the new topology stuff
Kevin Klues [Mon, 14 Sep 2015 21:04:50 +0000 (14:04 -0700)]
Update akaros to hook in the new topology stuff

To test the topology you can kfunc print_cpu_topology

[brho: touched up a foo(void) ]

4 years agoBuild topology from cpuid in topology.c
Kevin Klues [Thu, 3 Sep 2015 23:09:01 +0000 (16:09 -0700)]
Build topology from cpuid in topology.c

This is the first commit to introduce the notion of CPU toology in
Akaros. Previously we relied on a flat topology of cores, with no
concept of hierarchy between hyperthreaded cores, sockets, or numa
domains.  With this commit we begin using the x86 cpuid instruction to
build out structures that are aware of the actual topology underneath.
We also use the ACPI tables to detect our numa structure.

Nothing is actually hooked in yet. We just bring the files in.

[brho: minor touchups, foo(void)s and comments ]

4 years agotlb_flush_global() needs to call core_id_early()
Kevin Klues [Tue, 4 Aug 2015 03:30:32 +0000 (20:30 -0700)]
tlb_flush_global() needs to call core_id_early()

Previously it just called core_id(), but it is used inside vm_init()
early on in the boot process. As we begin to upgrade the way we discover
our topology, it is important to make sure we use the core_id_early() to
make sure we read 0 early on, and not some bogus value from our
topology data structure if it has not yet been properly initialized.

4 years agoRename node_id -> numa_id
Kevin Klues [Tue, 4 Aug 2015 00:26:25 +0000 (17:26 -0700)]
Rename node_id -> numa_id

It's less confusing to talk about a numa id than a node id.  Node
implies a completely different machine and has connotations with a
datacenter node rather than a single machine.

4 years agoPut a safety catch in compat_todo.h
Barret Rhoden [Mon, 14 Sep 2015 17:47:18 +0000 (13:47 -0400)]
Put a safety catch in compat_todo.h

It should only ever be included from linux_compat.h, directly.  This
catch won't catch everything (you could include it manually after
including linux_compat), but it might catch casual users.

4 years agoMake akaros_compat.h a kernel header
Barret Rhoden [Mon, 14 Sep 2015 17:39:31 +0000 (13:39 -0400)]
Make akaros_compat.h a kernel header

And renames it to linux_compat.h.  This way, other Linux drivers or code
can benefit from the compatibility shims.

I also moved the compat_todo.h, which is basically an even hackier part
of linux_compat.h - the things that are *really* bad.

4 years agoAdd disable-canonical flags for cross-compiler build.
Dan Cross [Mon, 14 Sep 2015 15:57:23 +0000 (11:57 -0400)]
Add disable-canonical flags for cross-compiler build.

This is used in some environments to avoid canonicalizing
programs the compiler invokes to an absolute directory path.

4 years agoFix LICENSE-plan9 hlink in README.md
Barret Rhoden [Wed, 9 Sep 2015 15:27:26 +0000 (11:27 -0400)]
Fix LICENSE-plan9 hlink in README.md

4 years agoRename LICENSE-PLAN9 -> LICENSE-plan9
Barret Rhoden [Tue, 8 Sep 2015 17:40:52 +0000 (13:40 -0400)]

4 years agoClean up licensing
Barret Rhoden [Tue, 8 Sep 2015 15:37:08 +0000 (11:37 -0400)]
Clean up licensing

At the very least, we should have an explanation of how the software is
licensed and provide copies of the licenses in the repo.

4 years agoAdd top level README file
Kevin Klues [Thu, 3 Sep 2015 04:03:56 +0000 (21:03 -0700)]
Add top level README file

This file is markdown compliant and links to our GETTING_STARTED and
Contribution files.  It also gives a brief overview of Akaros includes
instructions on our mailing list, the contribution process, etc.

4 years agoMake *.md files markdown compliant
Kevin Klues [Thu, 3 Sep 2015 04:02:33 +0000 (21:02 -0700)]
Make *.md files markdown compliant

4 years agoRename Contributing and GETTING_STARTED files
Kevin Klues [Thu, 3 Sep 2015 04:01:01 +0000 (21:01 -0700)]
Rename Contributing and GETTING_STARTED files

Add *.md extensions in preparation fo a subsequent commit where I make
these files markdown compliant.

4 years agoAdd static storage for bounded # of dtls keys/vals
Kevin Klues [Tue, 25 Aug 2015 01:18:27 +0000 (18:18 -0700)]
Add static storage for bounded # of dtls keys/vals

Storage for up to NUM_STATIC_KEYS is now statically allocated for dtls
keys. Likewise, per-thread storage for the values associated with these
keys is allocated as part of a thread's static TLS data (in an array
called 'early_values').  By statically allocating this data, we avoid
having to dynamically allocate memory for a small number of DTLS keys
and their associated values.  Moreover, we have a faster lookup time for
these key/value pairs because we know exactly where to look for their
values by indexing into an array instead of searching through a linked

Realistically, dtls keys will likely go unused in most apps today, in
favor of compiler supported TLS via __thread. For this reason, we chose
to only optimize for a small number of keys since it's likely that we
won't every go beyond this value in a real application.  If we do, we
can revisit this implementation and do something more sophisticated
along the lines of what glibc does in its pthread_key_create() and
pthread_get/setspecific() calls (i.e. use a 2-level array structure with
a finite bound on the number of keys).  For now, what we have is
sufficient for the apps we've encountered.

Overall, it may seem weird to store the dtls early_values array inside
of a __thread variable (since the whole point of dtls is to enable
dynamically allocated TLS when compiler supported TLS is unavailable),
but we mostly only provide dtls for backwards compatibility and plan to
always enable compiler supported TLS for apps that require TLS of any

4 years agoImplement __set_dtls() in terms of __get_dtls()
Kevin Klues [Tue, 25 Aug 2015 00:49:11 +0000 (17:49 -0700)]
Implement __set_dtls() in terms of __get_dtls()

The functionality contained in __get_dtls() was being duplicated in
__set_dtls().  This commit consolidates them.

4 years agoRename dtls_lib_init() -> dtls_cache_init()
Kevin Klues [Mon, 24 Aug 2015 22:42:27 +0000 (15:42 -0700)]
Rename dtls_lib_init() -> dtls_cache_init()

The only initialization that needs to happen here is in support of
allocing/freeing from the caches, so it's not really a "lib" init in
that sense (it's more of a cache init). As part of this, we make sure
that __alloc_dtls_key() call triggers the initialization rather than the
dtls_key_create() call.

4 years agoAbstract out alloc/free from the key/value caches
Kevin Klues [Mon, 24 Aug 2015 22:35:11 +0000 (15:35 -0700)]
Abstract out alloc/free from the key/value caches

Now none of the core logic cares about how the keys are alloced or
freed, it just uses the keys/values handed to it by these helper
functions.  This will become important in a subsequent commit that
optimizes the process of allocating keys/values for a small number of

4 years agoRemove all spinlocks
Kevin Klues [Mon, 24 Aug 2015 21:42:57 +0000 (14:42 -0700)]
Remove all spinlocks

The spinlock in the dtls struct is unnecessary, because the only field
it matters for is the refcount, which we can increment and decrement
using atomic ops.  The setting of the valid field to false (which was
previously protected by the lock) is inherently racy when used to decide
whether a destructor function should be run. Removing the lock when
setting this value doesn't make it any less racy. As the comment
suggests though, any reasonable usage of DTLS should not be deleting a
key until it knows that all threads have ran their destructors anyway
(or at least aren't currently in the process of running their

Moreover the global __dtls_lock is unnecessary, as it only protects
access to the slab allocator functions, which have pdr locks

As part of this, we are now able to move the atomic decrement into our
call for __maybe_free_dlts_key(), fixing a race condition on reading the
keys refcount in the process. We use a __sync_add_and_fetch instead of a
__sync_fetch_and_add to grab the new value atomically, before comparing
it to 0.

4 years agoFix do_mkdir on root directories
Barret Rhoden [Thu, 27 Aug 2015 02:58:15 +0000 (22:58 -0400)]
Fix do_mkdir on root directories

mkdir / should fail with EEXIST, not ENOENT.  The problem, pointed out
by Kevin, was that the parent check happened before the existence check,
and root directories (also for chroots) do not have parents.

This failure caused things like mkdir -p /foo/bar to fail.

Note that the VFS stack is racy, and concurrent mkdirs will probably
cause a lot of trouble.

4 years agoAtomically set current_uthread and a 2LS sched ops
Barret Rhoden [Mon, 24 Aug 2015 14:05:22 +0000 (10:05 -0400)]
Atomically set current_uthread and a 2LS sched ops

When initializing a 2LS, we are setting up both a current_uthread and a
2LS sched ops.  These must be in sync any time that a 2LS op is called.

Say we change the sched ops, but not the pointer, and then we receive a
notif (or do anything that triggers a 2LS op).  Then we're using the
sched_ops sched_entry on the wrong type of uthread.  If we have the
pointer change first, then the sched_ops operation is performed on the
wrong uthread (even if it's a thread0 op, we could be have the wrong
values or something).

This change splits manage_thread0 into its two components: init and
track.  Tracking the uthread in the vcore's current_uthread is done
"atomically" with setting the sched ops, with respect to notifs and
blocking syscalls.  These are the source of unexpected scheduler ops
calls.  If there are more sources in the future, we'll have to disable
them here.

4 years agoPass sched_ops to uthread_2ls_init()
Barret Rhoden [Mon, 24 Aug 2015 14:03:21 +0000 (10:03 -0400)]
Pass sched_ops to uthread_2ls_init()

This is necessary so that in a later commit we can "atomically" set the
2LS ops and change current_uthread.  Ops like signal_ops aren't as
critical in this regard.

4 years agoIncrease pthread's default stack size
Barret Rhoden [Wed, 29 Jul 2015 16:05:59 +0000 (12:05 -0400)]
Increase pthread's default stack size

We had a bug where cs would occasionally fail service lookups.  It
appeared that cs's threads were running on the small stack and probably
clobbering some memory, leading to the failure.

Increasing the stack size is not ideal - ideally, we'd have applications
and schedulers that were smarter.  Otherwise, we'll be back again the
next time we have some weird corruption due to various library calls.

For this commit, I turned up the size to 4 MB.  Since we don't want to
actually allocate that much per thread, we no longer MAP_POPULATE it.
But we do fault in the first (top) page of the stack.  This prevents us
from taking the page fault later on, when we could be measuring things.

Again, smarter schedulers and applications can do something more

Another option is to implement guard pages in pthreads.  I'm a little
reluctant to do that, since it means the number of VMRs in the kernel is
O(nr_pthreads).  Every stack would take two VMRs, one for the stack and
one for the guard.

Perhaps we can make guard pages an option, turned on by default for
'legacy' apps and turned off for high-perf apps, similar to how we deal
with TLS.

4 years agoUpdate GETTING_STARTED for newer QEMUs
Barret Rhoden [Tue, 28 Jul 2015 14:33:52 +0000 (10:33 -0400)]
Update GETTING_STARTED for newer QEMUs

The biggest change is that more recent versions of QEMU (e.g. 2.3.0)
will complain if you just give it mnt/hdd.img as a device.

To get rid of the warning, you can run something like this:
-drive file=mnt/hdd.img,index=0,media=disk,format=raw

I also cover a few more options that I run, as well as a tip to avoid
the pain of CTRL-C killing your VM.

4 years agoUse compressed kernel images for QEMU and USB
Barret Rhoden [Tue, 28 Jul 2015 14:13:32 +0000 (10:13 -0400)]
Use compressed kernel images for QEMU and USB

Compressing the kernel will improve the boot time for VMs.  On more
recent versions of QEMU (2.3.0) on one of my machines, qemu took nearly
2 minutes to boot a 75MB kernel image (including KFS, etc).  Compressing
it down to 20MB decreased the time to about 10 seconds.  Well worth it,
considering the compression is fast.

I don't know if the boot time on hardware improves by using a compressed
kernel image, but it does speed up the transfer to the USB device.

All of these settings are optional.  The Makelocal.template is just a
suggestion.  I recommend you follow the suggestion.

4 years agoFix FD table's next/hint FD
Barret Rhoden [Mon, 27 Jul 2015 18:22:36 +0000 (14:22 -0400)]
Fix FD table's next/hint FD

The purpose of next_fd was to track the next available FD, to decrease
the pain of scanning the entire FD space.  The old version was not used
and was incorrectly updated.

It is now a hint too, instead of the definitive minimum available FD.
Imagine FDs 0-10 are in use; the min/hint is 11.  Then close FD 5.  The
min/hint is now 5.  Then open a new FD and get 5, with a min of 6.  6 is
not actually available.

If we wanted to maintain the hint as the actual FD, we'd have to scan
the FD space when 5 opens to find the next zero bit.  If we later close
4, we'd need to update the min again, and somewhat wasted the effort of
scanning.  It's simpler to treat it as a hint that is <= the minimum
available FD.

4 years agoFix pipeclose()'s wild write
Barret Rhoden [Fri, 24 Jul 2015 22:54:35 +0000 (18:54 -0400)]
Fix pipeclose()'s wild write

The qunlock after decref is broken, since it uses the pointer after
freeing the memory.  It'd pop up as a wild write, where suddenly we're
writing a 0 somewhere.

It's also just weird to unlock in the release method.

4 years agoClean up FD support code
Barret Rhoden [Fri, 24 Jul 2015 20:39:11 +0000 (16:39 -0400)]
Clean up FD support code

All of the get_, put_ and claim_fd() functions are no longer called,
since they were part of the 9ns hack.

Also, there's no need for __claim_fd().  It does a similar job as
__get_fd(), and can be implemented within __get_fd() easily.

4 years agoRemove all fgrp code
Barret Rhoden [Fri, 24 Jul 2015 19:38:45 +0000 (15:38 -0400)]
Remove all fgrp code

Now that we're using the fd table for everything, there's no need to
keep the fgrp around.

4 years agoImplement 9ns FD functions with fd tables
Barret Rhoden [Fri, 24 Jul 2015 15:55:43 +0000 (11:55 -0400)]
Implement 9ns FD functions with fd tables

Now the 9ns and VFS share the FD table, instead of using separate tables
(e.g. the fgrp).

4 years agoMake newfd() take an int
Barret Rhoden [Fri, 24 Jul 2015 15:48:00 +0000 (11:48 -0400)]
Make newfd() take an int

We want to pass the open flags, not a bool that says whether or not
there are any open flags.

Seeing this made me worry a bit about passing ints to functions that
take bools.  If we do e.g. oflags & O_CLOEXEC, that's actually an
integer greater than 256.  A bool is only 8 bits; are we then losing out
on the upper bits?

It turns out that things aren't as insane as they could be.  The compiler
converts an int to a bool:

void xme(int y)
    extern void foo(bool x);

ffffffffc200ae80:   55                      push   %rbp
ffffffffc200ae81:   85 ff                   test   %edi,%edi
ffffffffc200ae83:   40 0f 95 c7             setne  %dil
ffffffffc200ae87:   48 89 e5                mov    %rsp,%rbp
ffffffffc200ae8a:   40 0f b6 ff             movzbl %dil,%edi
ffffffffc200ae8e:   5d                      pop    %rbp
ffffffffc200ae8f:   e9 7c 5d 04 00          jmpq   ffffffffc2050c10 <foo>

But not if it's a uint8!

void xme(int y)
    extern void foo(uint8_t x);

ffffffffc200ae80:   55                      push   %rbp
ffffffffc200ae81:   40 0f b6 ff             movzbl %dil,%edi
ffffffffc200ae85:   48 89 e5                mov    %rsp,%rbp
ffffffffc200ae88:   5d                      pop    %rbp
ffffffffc200ae89:   e9 72 5d 04 00          jmpq   ffffffffc2050c00 <foo>

Good times.

4 years agoDecref file/chan outside of the fd_table lock
Barret Rhoden [Fri, 24 Jul 2015 15:10:44 +0000 (11:10 -0400)]
Decref file/chan outside of the fd_table lock

Decreffing can often lead to a lot of other work, including sleeping.
cclose(), specifically, can sleep.  This does make the group closures
more of a pain, due to the kmalloc, but that's on proc creation and
destruction.  If cloexec is off, we could close the group and then just
unlock, then decref inline too.

4 years agoRemove the "dup2" option from sysdup
Barret Rhoden [Fri, 24 Jul 2015 13:36:46 +0000 (09:36 -0400)]
Remove the "dup2" option from sysdup

The second parameter to sysdup was meant to signal a dup2 style of
operation.  We weren't using it, it wasn't implemented, and we have
dup_to (not dup2!) elsewhere.

4 years agoMake fd tables work for files or chans
Barret Rhoden [Fri, 24 Jul 2015 12:30:18 +0000 (08:30 -0400)]
Make fd tables work for files or chans

The guts of insert_file, {get,put}_file_from_fd are reworked for
fd_tables such that they can handle either files or chans.  Whether you
use files or chans will be choosen mostly by the wrapper function (e.g.
insert_file for the VFS).

The invariant is that if a bit is set in the fdset, then file XOR chan
is set.

For operations like clone and close_fdt (closes all open files), we
don't really need wrappers, since that code is called from
VFS/9ns-independent parts of the kernel.

Note that clone_fdt has the chan incref commented out, but close_fdt
does not.  Since these aren't actually used by 9ns yet, the invariant
mentioned above isn't true yet.  I'll remove that shortly.

4 years agoMove p->fgrp into p->open_files
Barret Rhoden [Thu, 23 Jul 2015 16:17:52 +0000 (12:17 -0400)]
Move p->fgrp into p->open_files

Working on removing fgrp completely.  For now, this is mostly an
interface change.  By putting the fgrp inside open_files, functions that
took an fgrp can take an fd_table.

4 years agoRemove repeated entires in ns.h
Barret Rhoden [Thu, 23 Jul 2015 15:47:59 +0000 (11:47 -0400)]
Remove repeated entires in ns.h

There may be more, and that entire file needs an overhaul.  But I don't
want to bother changing functions in multiple locations.

4 years agoRename files_struct -> fd_table
Barret Rhoden [Thu, 23 Jul 2015 15:23:14 +0000 (11:23 -0400)]
Rename files_struct -> fd_table

Getting ready to use it for chans too.

Rename done with spatch (didn't work for env.h and the definition of

identifier d;
-struct files_struct
+struct fd_table

identifier d;
-struct files_struct *
+struct fd_table *

-struct files_struct
+struct fd_table

4 years agoFixes LD_LIBRARY_PATH typo
Barret Rhoden [Mon, 27 Jul 2015 14:57:59 +0000 (10:57 -0400)]

Introduced in e31b0478977f "Unexport LD_LIBARY_PATH before building xcc"

4 years agoiplib: Support O_NONBLOCK in helper functions
Barret Rhoden [Wed, 22 Jul 2015 12:06:48 +0000 (08:06 -0400)]
iplib: Support O_NONBLOCK in helper functions

Applications can now use the iplib helpers and get non-blocking

dial9(), announce9(), and listen9() all take a flags parameter.  For
now, O_NONBLOCK in that flags parameter will be passed directly to the
underlying open calls that create new conversations.  For dial9 and
announce9, those calls are to open a clone.  For listen9, that call is
opening a listen.

4 years agoAllow listened conversations to be non-blocking
Barret Rhoden [Wed, 22 Jul 2015 12:02:45 +0000 (08:02 -0400)]
Allow listened conversations to be non-blocking

If you listen with O_NONBLOCK, the new conversation you get back is
already set to non-blocking.  In the same way that you open "clone" and
get a ctl fd for the new conversation, so too you open "listen" and get
back a ctl.  The flags to open affect the new conversation.

In the case of listen, opening listen with O_NONBLOCK does not make
listen non-blocking; it makes the *new* conv non-blocking.  To make the
listen non-blocking, you either use a ctl message or open the *clone*
for that conversation with O_NONBLOCK.

4 years agoAllow fcntl() to handle O_NONBLOCK (XCC)
Barret Rhoden [Tue, 21 Jul 2015 20:23:09 +0000 (16:23 -0400)]
Allow fcntl() to handle O_NONBLOCK (XCC)

Unfortunately, the only way to change the non-blocking nature of a BSD
socket is with fcntl.  You can't use setsockopt() for some reason.

This commit allows fcntl() to intercept O_NONBLOCK in setfl and getfl,
handling it in userspace for socket FDs.

This will have no effect on regular files, so if you try to do a
O_NONBLOCK on, say, a regular #I FD that wasn't created with the socket
shims, the kernel will give you an error: use a ctl message.  The
purpose of this change is to provide BSD sockets compatibility, not to
provide an alternative interface to #I.

Note that the initial ctl from a cloned conversation (i.e. freshly
created) may have O_NONBLOCK set on it's chan flags, and you can read
this via getfl().  If you do a read-modify-write on the flags, the
kernel will not complain.  It only complains when you try to *change*
O_NONBLOCK on a file/chan.

Rebuild glibc.

4 years agoSplit fcntl() into __fcntl() and fcntl() (XCC)
Barret Rhoden [Tue, 21 Jul 2015 20:15:55 +0000 (16:15 -0400)]
Split fcntl() into __fcntl() and fcntl() (XCC)

Upcoming changes to fcntl() will require the Plan 9 sockets.  Building
fcntl with dependencies on e.g. plan9_socket.c will bring in snprintf,
which ultimately triggers the dreaded multiple libcs error.  E.g.

     x86_64-ucb-akaros-gcc   -nostdlib -nostartfiles -r -o
-lgcc '-Wl,-)'
multiple definition of `__libc_multiple_libcs'
first defined here

What's going on is that rtld can't stand to have certain parts of glibc
brought in.  This has happened previously with werrstr.  If you look at
the librtld.mapT file, you'll see bits about snprintf in there - that's
what I think pulls in an extra "__libc_multiple_libc".

The fix, according to
https://sourceware.org/ml/libc-help/2012-04/msg00043.html, is to look
into the map file and try and figure out what is pulling in what.

Ultimately, fcntl is used by rtld, so we can't have anything in fcntl.c,
even if only __fcntl is being called, that depends on things like
snprintf (as does all of the 9ns sockets stuff).

The solution is to have a separate C file for the external fcntl file
that will appear in the final libc.so, but not used internally.  I put
it in the sockets sysdep, since that subdir already includes the Plan 9
sockets stuff, and that is what is causing the incompatibility with
rtld.  Might as well keep everything "tainted" in that manner in one

Rebuild glibc, etc.

4 years agoUse __fcntl() exclusively within glibc (XCC)
Barret Rhoden [Tue, 21 Jul 2015 20:11:30 +0000 (16:11 -0400)]
Use __fcntl() exclusively within glibc (XCC)

In an upcoming commit, I'll need to have two versions of fcntl, one used
internally in glibc, and one used outside.  This makes it such that
glibc only uses __fcntl.

I needed to bring in some sysdeps.  In future versions of glibc, some
files may use fcntl(), and some of these sysdeps may start using
__fcntl.  We just need to be on the lookout.

Rebuild glibc.

4 years agoModernize 9ns networking function declarations
Barret Rhoden [Tue, 21 Jul 2015 09:51:17 +0000 (05:51 -0400)]
Modernize 9ns networking function declarations

The naming collision between Plan 9 and BSD sockets needs to go.  If you
write a sockets program, but link in iplib, you'll get Plan 9's listen()
instead of the listen() in glibc.

When searching for a name, Ron came up with listen9 and accept9.  I love
it.  Hypothetical conversation:
"Is that the 9th version of the accept call?"
"Is it because it has 9 arguments?"
"Is it because you belong in the 9th layer of hell?"

While we're changing the functions, I also added flags variables for
dial, announce, and listen.  I have uses for them later.

4 years agoAdd shims for {get,set}sockopt() (XCC)
Barret Rhoden [Tue, 21 Jul 2015 09:35:35 +0000 (05:35 -0400)]
Add shims for {get,set}sockopt() (XCC)

Only supports SOL_SOCKET->SO_TYPE for now.  Note that setsockopt() can't
change the type.

Rebuild glibc.

4 years agoAllow socket() to accept SOCK_NONBLOCK (XCC)
Barret Rhoden [Mon, 20 Jul 2015 19:53:37 +0000 (15:53 -0400)]
Allow socket() to accept SOCK_NONBLOCK (XCC)

We're only supporting SOCK_NONBLOCK for the IP stack.

Rebuild glibc.

4 years agoSplit socket()'s type into two Rock fields (XCC)
Barret Rhoden [Mon, 20 Jul 2015 14:17:57 +0000 (10:17 -0400)]
Split socket()'s type into two Rock fields (XCC)

The type is overloaded in Linux to include options, such as
SOCK_NONBLOCK.  Previously, if anyone was trying to open a
SOCK_NONBLOCK socket, the type detection should fail.

Rebuild glibc.

4 years agoiplib: Support non-blocking listens
Barret Rhoden [Mon, 20 Jul 2015 12:12:18 +0000 (08:12 -0400)]
iplib: Support non-blocking listens

We want to pass the -1 through but not treat it like a full error and
print out something, since non-blocking is a legitimate usage.

4 years agoiplib: Add a trailing \n to the error output
Barret Rhoden [Mon, 20 Jul 2015 12:11:04 +0000 (08:11 -0400)]
iplib: Add a trailing \n to the error output

Otherwise the output looks messy.

4 years agoAllow non-blocking listens
Barret Rhoden [Mon, 20 Jul 2015 11:36:13 +0000 (07:36 -0400)]
Allow non-blocking listens

Plan 9 listens (accept() in the sockets world) can now be set to

I didn't build in suport for accept4()-type SOCK_NONBLOCK, which sets
the *new* conversation/socket to non-blocking, saving a syscall.  Our
accept()s and listen()s are already super slow, and we will need a
faster interface.  We already use seven syscalls for the accept() shim,
and a normal Plan 9 listen takes three or four (depending on whether or
not you keep the ctlfd around).  That's way too much.  We can build
something like accept4() natively (still going through #I, but not using
open(), or at least not the traditional open().

4 years agoSupport O_NONBLOCK when opening #I chans
Barret Rhoden [Sun, 19 Jul 2015 13:41:13 +0000 (09:41 -0400)]
Support O_NONBLOCK when opening #I chans

Applications can set O_NONBLOCK when cloning and can getfl() to see
O_NONBLOCK, but they cannot toggle O_NONBLOCK via setfl().  Getting via
getfl() is of dubious value, since only the cloned chan will have the
mark.  To dynamically change, they need to use the ctl message.  I
wasn't interested in having device ops that translate a setfl() call or
something.  That's the purpose of the ctls, after all.

It's up to individual devices if they want to handle O_NONBLOCK when a
chan is opened.  They are free to throw an error() from dev->open.

Note that dial() currently does not support open flags to pass through
to the clone.  If you want to play around with this, you'll need send
the ctl message.

Also note that the non-blocking nature of the chan is part of the conv
(the queues in this case), and not really part of the chan.  If a
process writes a "nonblock" ctl message into the conv, all other chans
will now behave in a O_NONBLOCK-ing manner, since the underlying conv
changed.  This is different than the unix way of dealing with
O_NONBLOCK, where each socket/chan can be treated differently.

It's tempting to just remove the O_NONBLOCK completely and only allow a
ctl message, and fake O_NONBLOCK in userspace (e.g. in open() or the 9ns
networking shims in glibc), but that's at least one extra syscall for
every opened connection, both for clones and (in future commits) for

I strongly considered allowing O_NONBLOCK to set "nonblock on" for *any*
 #I file, specifically ctl and data files.  That way, you could just do:

open("/net/tcp/6/data", O_RDWR | O_NONBLOCK);

and then have non-blocking I/O.  It's what a user might expect from
open() with O_NONBLOCK.  The deciding point against this was that I
didn't want data to have any control side-effects, even on open().  This
is only really important if you drop a file in #s, and then someone who
is allowed to read/write to it could suddenly change the nonblocking

Finally, note that these changes support non-blocking qio in #I,
specifically on conversation inbound and outbound queues.  Depending on
your medium, you could still block *below* the IP stack on a write().
For instance, ipoput4() calls the various bwrites, and eventually
etheroq().  It is possible to block there, unless the Ethernet device is
set to nonblocking.  Check out etherwrite() for specifics.

4 years agoPass mode = 0 for O_CREATE open() calls (XCC)
Barret Rhoden [Sat, 18 Jul 2015 21:13:05 +0000 (17:13 -0400)]
Pass mode = 0 for O_CREATE open() calls (XCC)

Previously, we were passing gibberish, whatever was on the stack.  The
kernel ignores it, but it complicates parsing syscall traces.

Rebuild glibc for the fix, but feel free to ignore it.

4 years agoChange Chan flags to match open() file flags
Barret Rhoden [Sun, 19 Jul 2015 13:35:19 +0000 (09:35 -0400)]
Change Chan flags to match open() file flags

Like with many parts of the VFS and 9ns, certain flags hold different
sets of flags.  omode has the mode (O_RDWR) as well as file/chan flags.
c->flag has some internal flags, such as COPEN, as well as some
file/chan flags that came in from open().

Now, the chan flags are explicitly split between these groups, such that
the internal and external flags are separate.  Further, the external
flags use the same values with 9ns as are used in the kernel interface.
This way, we can more easily set and get the flags.

Note that this also fixes a slight bug in setfl where we were not
clearing O_APPEND, in case someone was trying to toggle it off.

9ns CLOEXEC still needs some work.  I don't know think the device needs
to know about it, but I could be wrong.

4 years agoProcess omode/VFS open flags before dev->open
Barret Rhoden [Sat, 18 Jul 2015 20:28:41 +0000 (16:28 -0400)]
Process omode/VFS open flags before dev->open

By converting the flags and putting them on the chan before calling the
device's open, the device has a chance to prepare for the flags or error

4 years agoqio: Add non-blocking queues
Barret Rhoden [Thu, 16 Jul 2015 17:25:23 +0000 (13:25 -0400)]
qio: Add non-blocking queues

These queues are non-blocking in the O_NONBLOCK sense, which is distinct
from the old Plan 9 style of where data blocks get dropped when a writer
overflows the queue.

Conversation readers and writers will get an errno of EAGAIN with an
appropriate errstr, such as "queue full".

Userspace can't set O_NONBLOCK yet.

4 years agoqio: Change qwait to throw errors
Barret Rhoden [Thu, 16 Jul 2015 17:22:02 +0000 (13:22 -0400)]
qio: Change qwait to throw errors

It was always capable of throwing errors, for instance on a rendez_sleep
that is cancelled.  For real errors, like the multiple eof reads, we'll
actually throw an error.

4 years agoqio: Track Qdropoverflow as a state
Barret Rhoden [Thu, 16 Jul 2015 16:28:58 +0000 (12:28 -0400)]
qio: Track Qdropoverflow as a state

Instead of a bool.

4 years agoqio: Rename qnoblock -> qdropoverflow
Barret Rhoden [Thu, 16 Jul 2015 16:17:22 +0000 (12:17 -0400)]
qio: Rename qnoblock -> qdropoverflow

"No block" would not block, but unlike other non-blocking I/O, it
doesn't just return, it drops the overflowed block.  It also doesn't
work for reads.

4 years agoHandle ERANGE and retvals for getcwd and fd2path
Barret Rhoden [Sat, 18 Jul 2015 19:53:13 +0000 (15:53 -0400)]
Handle ERANGE and retvals for getcwd and fd2path

Both of these functions involve copying paths out to userspace.  We
actually don't need to check PATH_MAX in getcwd; the kernel will copy
out as much as is needed, up to what the user asks for.  If the buffer
isn't big enough, we return ERANGE.

The user could actually use a reasonably sized buffer, then only work up
to PATH_MAX if it gets ERANGE.  We don't do this in glibc.

Also note that fd2path returns 0, not the length of the string, on

4 years agoMake snprintf() return full strlen when truncating
Barret Rhoden [Sat, 18 Jul 2015 19:17:18 +0000 (15:17 -0400)]
Make snprintf() return full strlen when truncating

Previously, we would only return the amount of bytes written, excluding
null.  This is what glibc does too, for success.  But although we always
returned that amount, when the buffer is too small and the string is
truncated, glibc returns the total that *would* be written.

This change brings our snprintf() more in line with glibc; though I
still prefer not returning errors and just returning 0.

Note that this common pattern still works:

  l += snprintf(p + l, READSTR - l, "ierrs %d\n", ctlr->ierrs);
  l += snprintf(p + l, READSTR - l, "etxth %d\n", ctlr->etxth);
  l += snprintf(p + l, READSTR - l, "taligned %d\n", ctlr->taligned);

If we overrun the buffer, READSTR - l will be negative, at which point
snprintf() does not print into the buffer (and returns 0 for us).

4 years agoTest for flex & bison when building the toolchain
Barret Rhoden [Fri, 17 Jul 2015 15:33:56 +0000 (11:33 -0400)]
Test for flex & bison when building the toolchain

Installing at least one of them fixes errors such as:

../../binutils-2.24/gold/script-c.h:221:7: error: ‘YYSTYPE’ was not
declared in this scope
../../binutils-2.24/gold/script-c.h:221:15: error: expected
primary-expression before ‘,’ token
 yylex(YYSTYPE*, void* closure);
You will need to make clean after installing flex and bison.

4 years agoTest for g++ when building the toolchain
Barret Rhoden [Fri, 17 Jul 2015 15:19:57 +0000 (11:19 -0400)]
Test for g++ when building the toolchain

It's possible to have gcc but not g++, resulting in an error like this
while making binutils:

checking for x86_64-unknown-linux-gnu-gcc... gcc
configure: error: in
configure: error: C++ preprocessor "/lib/cpp" fails sanity check
See `config.log' for more details.
checking for C compiler default output file name... yes
checking whether declaration is required for errno... yes
make[4]: *** [configure-gold] Error 1
make[4]: *** Waiting for unfinished jobs....
(many other lines)

4 years agox86: Use ACPI/MP for num_cores detection
Barret Rhoden [Thu, 23 Jul 2015 08:47:32 +0000 (04:47 -0400)]
x86: Use ACPI/MP for num_cores detection

Previously, we'd use whatever booted up to determine the num_cores.  But
we would not know how many cores there should have been, and which may
be responding to SIPIs still.

That info is in the ACPI/MP tables.  Now, we can detect if the wrong
number of cores come online, and if the right number booted, we can free
the trapoline without any guesswork.

A couple other things:

The volatile on num_cores was probably due to early versions of the boot
code where C code needed to worry that assembly code was concurrently
incrementing num_cores/num_cpus.  That doesn't seem to be needed for
x86_num_cores_booted, let alone num_cores.

The u32 vs int for num_cores might also be for old code, where I didn't
want the variable to be negative ever.  Or more likely it was a
scalability joke.  Now that it's an int, we just went from 4 billion to
2 billion cores!  Oh no!

Setting num_cores to 1 in entry64.S, while its value in .data was 0xee
was just crazy.

4 years agox86: Remove ncleft initialization in mpinit
Barret Rhoden [Fri, 24 Jul 2015 06:51:31 +0000 (02:51 -0400)]
x86: Remove ncleft initialization in mpinit

The intent of this code is probably to say "give me how many cores
total, and I'll take away some and return how many I didn't account
for".  It would do that, except in error conditions, it would return
254, which currently is maxcores - 1.  So on error, it would say it
found one core, which seems buggy.

Incidentally, a little while ago I saw a machine that we thought had 9
cores.  Possibly its MP tables were messed up, and it only had 8 cores?
The reported value could have been 8 + (buggy) 1 in that case.

4 years agoChange all references of num_cpus -> num_cores
Kevin Klues [Tue, 21 Jul 2015 03:10:13 +0000 (20:10 -0700)]
Change all references of num_cpus -> num_cores

As we start to integrate more sophisticated cputopology information into
the kernel, we will need to be careful about our naming of these
variables.  CPUs are different than cores (on a hyperthreaded machine,
there are at least 2 cores per cpu), so we need to be more consistent
with our naming to avoid confusion.  Moreover, as we add more
cputopology information, we will likey want to know the actual num_cpus
in addition to the num_cores, so we want to make sure we have the right
semantics for these variables before this change is introduced.

4 years agoRemove env_entry from struct proc
Barret Rhoden [Wed, 22 Jul 2015 19:32:44 +0000 (15:32 -0400)]
Remove env_entry from struct proc

No need for it, now that the actual entry point is just set in elf.c and
that the vcore entry point is set in VCPD.

4 years agoRename transition_stack -> vcore_stack (XCC)
Barret Rhoden [Wed, 22 Jul 2015 19:30:28 +0000 (15:30 -0400)]
Rename transition_stack -> vcore_stack (XCC)

The name 'transition' predates vcores.  Might as well keep the
vcore_stack in line with vcore_entry and vcore_tls_desc.

Reinstall your kernel headers.

4 years agoAdd vcore_entry to vcpd (XCC) (2/2)
Kevin Klues [Sat, 18 Jul 2015 17:01:26 +0000 (10:01 -0700)]
Add vcore_entry to vcpd (XCC) (2/2)

In this commit we finalize the migration of vcore_entry into the vcpd.
As part of this, a significant amount of cleanup has been done.  In
addition to removing all system dependent startup code from glibc, we
also now only initialize __vcore_id, __vcore_context, and only call
__ctype_init() once when a vcore's TLS is first allocated.

Currently, the vcore entry point is set to point to a static function
called __kernel_vcore_entry, whose sole job is to grab the vcore_id of
the vcore passed in by the kernel, and set up the vcore's TLS by
extracting it from the vcpd for that vcore.  It then calls the real
vcore_entry of the application.  In the future, if we decide to
standardize on the kernel setting up our vcore TLS for us (as it does
for x86_64), then this level of indirection can be avoided.

Although not currenlty utilized, one nice property of this approach (in
addition to removing our reliance on making _start reentrant), is that
different vcore_entry() points can be set up for different vcores,
potentially providing a fast path for critical code running on those
vcores that doesn't need to run through the standard vcore_entry()
sequence.  Such functionality may provie useful in the future.

[brho: moved vcore_entry's in VCPD adjacent to stack and tls_desc, added
comment and __vcore_entry = TRUE in __kernel_vcore_entry() ]