summaryrefslogtreecommitdiff
path: root/viengoos
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2009-02-21 21:14:41 +0100
committerNeal H. Walfield <neal@gnu.org>2009-02-21 21:14:41 +0100
commit759bcbda499afd29b8da5fd47f437b96a6c948cc (patch)
tree0530a6ff40977412aaf9ec126cfdf7e408ddccec /viengoos
parent52ce316a43952dbe15d6072b77f70bb121b3b872 (diff)
Add sleep and time support.
Diffstat (limited to 'viengoos')
-rw-r--r--viengoos/messenger.c116
-rw-r--r--viengoos/messenger.h26
-rw-r--r--viengoos/object.c52
-rw-r--r--viengoos/object.h13
-rw-r--r--viengoos/server.c48
-rw-r--r--viengoos/server.h2
-rw-r--r--viengoos/sysdeps/x86_64/idt.c1
-rw-r--r--viengoos/sysdeps/x86_64/syscall.c4
-rw-r--r--viengoos/sysdeps/x86_64/vm.c325
-rw-r--r--viengoos/thread.c7
-rw-r--r--viengoos/timer.c2
-rw-r--r--viengoos/timer.h20
-rw-r--r--viengoos/viengoos.c2
13 files changed, 446 insertions, 172 deletions
diff --git a/viengoos/messenger.c b/viengoos/messenger.c
index 4783154..7615567 100644
--- a/viengoos/messenger.c
+++ b/viengoos/messenger.c
@@ -22,11 +22,14 @@
#include <errno.h>
#include <assert.h>
#include <viengoos/cap.h>
+#include <viengoos/misc.h>
#include <hurd/as.h>
#include "messenger.h"
#include "object.h"
#include "thread.h"
+#include "timer.h"
+#include "activity.h"
/* When the kernel formulates relies, it does so in this buffer. */
static char reply_message_data[PAGESIZE] __attribute__ ((aligned (PAGESIZE)));
@@ -302,7 +305,14 @@ messenger_message_deliver (struct activity *activity,
struct messenger *messenger)
{
assert (messenger->blocked);
- assert (! messenger->wait_queue_p);
+ assertx (! messenger->wait_queue_p,
+ VG_OID_FMT" -> (h:%d)"VG_OID_FMT"(t:%d), reason: %d -> "VG_OID_FMT,
+ messenger->wait_queue.prev,
+ messenger->wait_queue_head,
+ object_oid ((struct vg_object *) messenger),
+ messenger->wait_queue_tail,
+ messenger->wait_reason,
+ messenger->wait_queue.next);
struct thread *thread
= (struct thread *) vg_cap_to_object (activity, &messenger->thread);
@@ -341,6 +351,109 @@ messenger_unblock (struct activity *activity, struct messenger *messenger)
break;
}
}
+
+struct vg_object *sleep_object;
+
+static struct timer sleep_timer;
+static bool sleep_timer_registered;
+
+#define TIME_FMT "%"PRId64".%03"PRId64
+#define TIME_PRINTF(t) \
+ ((t) / 1000 / 1000 / 1000), \
+ (((t) / 1000 / 1000) % 1000)
+
+static void
+wake_up (struct timer *timer)
+{
+ int d = 5;
+ debug (d, "Bzzz. Bzzz.");
+
+ assert (&sleep_timer == timer);
+ assert (sleep_timer_registered);
+
+ struct messenger *m;
+ while ((m = object_wait_queue_head (root_activity, sleep_object)))
+ {
+ debug (d, "Considering waking messenger "VG_OID_FMT". "
+ "now: "TIME_FMT"; wake: "TIME_FMT,
+ object_oid ((struct vg_object *) m),
+ TIME_PRINTF (time_data.ns_since_boot),
+ TIME_PRINTF (m->wait_reason_raw));
+
+ assert (m->wait_reason == MESSENGER_SLEEP);
+ if (m->wait_reason_raw <= time_data.ns_since_boot)
+ {
+ object_wait_queue_unlink (root_activity, m);
+ vg_sleep_reply (root_activity, m);
+ }
+ else
+ break;
+ }
+
+ if (m)
+ {
+ debug (d, "Registering timer callback at "TIME_FMT".",
+ TIME_PRINTF (m->wait_reason_raw));
+ sleep_timer.expire = m->wait_reason_raw;
+ timer_register (&sleep_timer);
+ }
+ else
+ sleep_timer_registered = false;
+}
+
+/* Enqueue the messenger MESSENGER on SLEEP_OBJECT and deliver it
+ after TIMEOUT nanoseconds. */
+void
+messenger_sleep (struct activity *activity,
+ struct messenger *messenger,
+ uint64_t timeout)
+{
+ int d = 5;
+
+ uint64_t deadline = time_data.ns_since_boot + timeout;
+
+ debug (d, VG_OID_FMT" to sleep for "TIME_FMT" seconds. "
+ "(now: "TIME_FMT"; wake: "TIME_FMT")",
+ object_oid ((struct vg_object *) messenger), TIME_PRINTF (timeout),
+ TIME_PRINTF (time_data.ns_since_boot), TIME_PRINTF (deadline));
+
+ messenger->wait_reason = MESSENGER_SLEEP;
+ messenger->wait_reason_raw = deadline;
+
+ struct messenger *last = NULL;
+ struct messenger *m;
+ object_wait_queue_for_each (activity, sleep_object, m)
+ {
+ assert (m->wait_reason == MESSENGER_SLEEP);
+ if (deadline < m->wait_reason_raw)
+ break;
+
+ last = m;
+ }
+
+ if (last)
+ {
+ object_wait_queue_insert_after (activity, sleep_object, last, messenger);
+ assert (sleep_timer_registered);
+ }
+ else
+ {
+ debug (d, "Adding messenger "VG_OID_FMT" to head of sleep queue",
+ object_oid ((struct vg_object *) messenger));
+ object_wait_queue_push (activity, sleep_object, messenger);
+
+ if (sleep_timer_registered)
+ {
+ debug (d, "Cancelling pending timer.");
+ timer_cancel (&sleep_timer);
+ }
+
+ sleep_timer.expire = deadline;
+ sleep_timer.callback = wake_up;
+ sleep_timer_registered = true;
+ timer_register (&sleep_timer);
+ }
+}
void
messenger_destroy (struct activity *activity, struct messenger *messenger)
@@ -349,4 +462,3 @@ messenger_destroy (struct activity *activity, struct messenger *messenger)
/* MESSENGER is attached to a wait queue. Detach it. */
object_wait_queue_unlink (activity, messenger);
}
-
diff --git a/viengoos/messenger.h b/viengoos/messenger.h
index 2ad0417..66adbc7 100644
--- a/viengoos/messenger.h
+++ b/viengoos/messenger.h
@@ -54,6 +54,9 @@ enum
/* The messenger is trying to transfer a message to another
messenger or to a thread. */
MESSENGER_WAIT_TRANSFER_MESSAGE,
+
+ /* Reply when TIME_DATA.NS_SINCE_BOOT >= WAIT_REASON_RAW. */
+ MESSENGER_SLEEP,
};
/* Messenger object. */
@@ -163,8 +166,19 @@ struct messenger
/* Why the messenger is on a wait queue. */
uint32_t wait_reason : 27;
/* Additional information about the reason. */
- uint32_t wait_reason_arg;
- uint32_t wait_reason_arg2;
+ struct
+ {
+ union
+ {
+ struct
+ {
+ uint32_t wait_reason_arg;
+ uint32_t wait_reason_arg2;
+ };
+
+ uint64_t wait_reason_raw;
+ };
+ };
#ifndef NDEBUG
/* Used for debugging futexes. */
@@ -211,4 +225,12 @@ extern void messenger_unblock (struct activity *activity,
extern void messenger_destroy (struct activity *activity,
struct messenger *messenger);
+extern struct vg_object *sleep_object;
+
+/* Enqueue the messenger MESSENGER on SLEEP_OBJECT and deliver it
+ after TIMEOUT nanoseconds. */
+extern void messenger_sleep (struct activity *activity,
+ struct messenger *messenger,
+ uint64_t timeout);
+
#endif
diff --git a/viengoos/object.c b/viengoos/object.c
index f682f9e..9b187c7 100644
--- a/viengoos/object.c
+++ b/viengoos/object.c
@@ -429,7 +429,7 @@ object_name (struct vg_object *object)
/* Allocate and set up a memory object. TYPE, OID and VERSION must
correspond to the values storage on disk. */
-static struct vg_object *
+struct vg_object *
memory_object_alloc (struct activity *activity,
enum vg_cap_type type,
vg_oid_t oid, uintptr_t version,
@@ -1597,6 +1597,56 @@ object_wait_queue_enqueue (struct activity *activity,
object_wait_queue_check (activity, messenger);
}
+void
+object_wait_queue_insert_after (struct activity *activity,
+ struct vg_object *object,
+ struct messenger *existing,
+ struct messenger *messenger)
+{
+ /* Existing better be one a queue. */
+ assert (existing->wait_queue_p);
+ object_wait_queue_check (activity, existing);
+
+ /* And, messenger better not be. */
+ assertx (! messenger->wait_queue_p,
+ VG_OID_FMT" -> (h:%d)"VG_OID_FMT"(t:%d), reason: %d -> "VG_OID_FMT,
+ messenger->wait_queue.prev,
+ messenger->wait_queue_head,
+ object_oid ((struct vg_object *) messenger),
+ messenger->wait_queue_tail,
+ messenger->wait_reason,
+ messenger->wait_queue.next);
+
+ /* If existing is the wait queue's tail, this is just an enqueue.
+ Reuse that code. */
+ if (existing->wait_queue_tail)
+ {
+ object_wait_queue_enqueue (activity, object, messenger);
+ return;
+ }
+ messenger->wait_queue_tail = false;
+
+ vg_oid_t existing_oid = object_oid ((struct vg_object *) existing);
+ vg_oid_t messenger_oid = object_oid ((struct vg_object *) messenger);
+
+ /* Look up the object following EXISTING. */
+ struct messenger *next = object_wait_queue_next (activity, existing);
+ assert (next->wait_queue.prev == existing_oid);
+
+ /* MESSENGER->NEXT = NEXT. NEXT->PREV = MESSENGER. */
+ messenger->wait_queue.next = existing->wait_queue.next;
+ next->wait_queue.prev = messenger_oid;
+
+ /* EXISTING->NEXT = MESSENGER. MESSENGER->PREV = EXISTING. */
+ existing->wait_queue.next = messenger_oid;
+ messenger->wait_queue.prev = existing_oid;
+
+ messenger->wait_queue_p = true;
+
+ object_wait_queue_check (activity, messenger);
+ object_wait_queue_check (activity, existing);
+}
+
/* Unlink messenger MESSENGER from its wait queue. */
void
object_wait_queue_unlink (struct activity *activity,
diff --git a/viengoos/object.h b/viengoos/object.h
index f5b215f..9452add 100644
--- a/viengoos/object.h
+++ b/viengoos/object.h
@@ -288,6 +288,13 @@ extern struct vg_object *object_find_soft (struct activity *activity,
vg_oid_t oid, int version,
struct vg_object_policy policy);
+/* Allocate and set up a memory object. TYPE, OID and VERSION must
+ correspond to the values stored on disk. */
+extern struct vg_object *memory_object_alloc (struct activity *activity,
+ enum vg_cap_type type,
+ vg_oid_t oid, uintptr_t version,
+ struct vg_object_policy policy);
+
/* Destroy the object OBJECT. Any changes must have already been
flushed to disk. LRU_LOCK must not be held, this function will
take it. Does NOT release the memory. It is the caller's
@@ -580,6 +587,12 @@ extern void object_wait_queue_enqueue (struct activity *activity,
struct vg_object *object,
struct messenger *messenger);
+/* Insert MESSENGER after EXISTING on OBJECT's wait queue. */
+extern void object_wait_queue_insert_after (struct activity *activity,
+ struct vg_object *object,
+ struct messenger *existing,
+ struct messenger *messenger);
+
/* Unlink messenger MESSENGER from its wait queue. */
extern void object_wait_queue_unlink (struct activity *activity,
struct messenger *messenger);
diff --git a/viengoos/server.c b/viengoos/server.c
index dd93d33..eca721f 100644
--- a/viengoos/server.c
+++ b/viengoos/server.c
@@ -45,6 +45,7 @@
#include "profile.h"
#include "sys.h"
#include "scheduler.h"
+#include "debug.h"
#ifndef NDEBUG
struct futex_waiter_list futex_waiters;
@@ -55,6 +56,30 @@ struct futex_waiter_list futex_waiters;
struct trace_buffer rpc_trace = TRACE_BUFFER_INIT ("rpcs", 0,
true, false, false);
+static void
+trace_buffer_command (int argc, char *argv[])
+{
+ if (argc > 2)
+ {
+ printf ("Usage: trace-buffer [COUNT=20]\n");
+ return;
+ }
+
+ int count = 20;
+ if (argc == 2)
+ count = strtol (argv[1], NULL, 0);
+
+ trace_buffer_dump (&rpc_trace, count);
+}
+
+static struct debug_command trace_buffer_debug =
+ {
+ .name = "trace-buffer",
+ .short_name = 0,
+ .help = "Display the contents of the trace buffer [count=20]",
+ .function = trace_buffer_command
+ };
+
/* Like debug but also prints the method id and saves to the trace
buffer if level is less than or equal to 4. */
# define DEBUG(level, format, args...) \
@@ -79,6 +104,14 @@ struct trace_buffer rpc_trace = TRACE_BUFFER_INIT ("rpcs", 0,
METHOD, METHOD_ID, ##args)
#endif
+void
+server_bootstrap (void)
+{
+#ifndef NDEBUG
+ debug_register (&trace_buffer_debug);
+#endif
+}
+
bool
page_fault_handler (struct thread *thread, uintptr_t fault, int access)
{
@@ -965,6 +998,21 @@ dispatcher (uintptr_t flags,
}
#endif
+ case VG_sleep:
+ {
+ uint64_t nanoseconds = 0;
+
+ err = vg_sleep_send_unmarshal (message, &nanoseconds, NULL);
+ if (err)
+ REPLY (err);
+
+ DEBUG (4, "%"PRIdPTR, nanoseconds);
+
+ messenger_sleep (principal, reply, nanoseconds);
+
+ break;
+ }
+
case VG_folio_alloc:
{
if (object_type (target) != vg_cap_activity_control)
diff --git a/viengoos/server.h b/viengoos/server.h
index b97961f..ed3200a 100644
--- a/viengoos/server.h
+++ b/viengoos/server.h
@@ -43,4 +43,6 @@ extern bool page_fault_handler (struct thread *thread,
extern void server_loop (void) __attribute__ ((noreturn));
#endif
+extern void server_bootstrap (void);
+
#endif
diff --git a/viengoos/sysdeps/x86_64/idt.c b/viengoos/sysdeps/x86_64/idt.c
index 4ceb4f1..7c9be01 100644
--- a/viengoos/sysdeps/x86_64/idt.c
+++ b/viengoos/sysdeps/x86_64/idt.c
@@ -514,6 +514,7 @@ handler (struct interrupt_context *t, bool from_kernel)
void fault_info (int d)
{
+ debug (d, "Fault at %"PRIxPTR, cr2);
if ((t->err & (1 << 0)) == 0)
debug (d, "Not present page");
debug (d, "%s fault.", write_fault ? "Write" : "Read");
diff --git a/viengoos/sysdeps/x86_64/syscall.c b/viengoos/sysdeps/x86_64/syscall.c
index 07bc295..6481538 100644
--- a/viengoos/sysdeps/x86_64/syscall.c
+++ b/viengoos/sysdeps/x86_64/syscall.c
@@ -27,10 +27,10 @@
static void __attribute__ ((used))
returner (void)
{
- bottom_half_run ();
-
for (;;)
{
+ bottom_half_run ();
+
schedule (NULL);
if (likely (current_thread))
break;
diff --git a/viengoos/sysdeps/x86_64/vm.c b/viengoos/sysdeps/x86_64/vm.c
index 074ace8..6e584b1 100644
--- a/viengoos/sysdeps/x86_64/vm.c
+++ b/viengoos/sysdeps/x86_64/vm.c
@@ -40,6 +40,12 @@
#include "activity.h"
#include "scheduler.h"
#include "debug.h"
+#include <viengoos/bits/sys.h>
+#include "timer.h"
+
+static struct page_table pml4;
+static struct page_table pdir[64];
+static struct page_table pdp;
/* Memory management: page tables are allocated out of a separate pool
of memory from objects. */
@@ -136,6 +142,7 @@ mapping_free (struct vm_mapping *mapping)
static inline void
page_table_check (struct page_table *pt, bool page_table)
{
+#ifndef NDEBUG
int i;
int c = 0;
for (i = 0; i < PTES; i ++)
@@ -172,131 +179,7 @@ page_table_check (struct page_table *pt, bool page_table)
debug (5, "%d present", i);
assertx (c == pt->allocated,
"%p: counted: %d; pt->allocated: %d", pt, c, pt->allocated);
-}
-
-static struct page_table pdir[64];
-static struct page_table pdp;
-static struct page_table pml4;
-
-static void page_table_dump (int argc, char *argv[]);
-
-static struct debug_command debug_command =
- {
- "page-tables",
- 'p',
- "Print a thread's page table structures",
- page_table_dump
- };
-
-void
-vm_init (void)
-{
- /* Enable global pages. */
- x86_64_load_cr4 (X86_64_CR4_PGE, true);
-
- /* Enable supervisor write protect. */
- x86_64_load_cr0 (X86_64_CR0_WP, true);
-
- /* Enable the execute protection bit. */
- x86_64_load_efer (X86_64_EFER_NX, true);
-
- int gb_pages = 0;
- if ((cpuid (0x80000001).edx & (1 << 26)))
- {
- gb_pages = cpuid (0x80000019).ebx;
- debug (0, "Support for %d 1GB pages found.", gb_pages);
- }
-
- /* Set up the kernel's page tables. */
- uint64_t gb = 1024 * 1024 * 1024;
- int j;
- uint64_t base;
- for (j = 0, base = j * gb;
- base <= kv_to_phys ((void *) last_frame)
- && j < sizeof (pdir) / sizeof (pdir[0]);
- j ++, base = j * gb)
- {
- if (gb_pages > 0)
- {
- PT_SET (&pdp, ADDR_PDP_INDEX (phys_to_kv (base)),
- pdpe (kv_to_phys (&pdir[j]), false, MEM_RWX,
- true, true));
- pdp.allocated ++;
-
- gb_pages --;
- }
- else
- {
- PT_SET (&pdp, ADDR_PDP_INDEX (phys_to_kv (base)),
- pdpe (kv_to_phys (&pdir[j]), false, MEM_RWX,
- false, false));
- pdp.allocated ++;
-
- /* XXX: Grub doesn't report all the memory in the system.
- This wouldn't be too bad except that it stores some of
- its data structures in that memory! Here we "round up"
- to the next gig. This gets all the memory. */
- uintptr_t last_frame_temp = last_frame;
- if (phys_to_kv (base) + gb - 1 > last_frame)
- {
- last_frame = phys_to_kv (base) + gb - 1;
- debug (0, "Setting last frame to %p -> %p",
- last_frame_temp, last_frame);
- }
-
- int i;
- for (i = 0;
- i < PTES && base <= kv_to_phys ((void *) last_frame);
- i ++, base += 1 << (9 + 12))
- {
- extern char _text, _etext;
- extern char _rodata, _erodata;
- extern char stack, stack_end;
-
- int access = MEM_RW;
-
- uintptr_t vbase = phys_to_kv (base);
- if (&_rodata <= vbase && vbase < &_erodata)
- access = MEM_READABLE;
- if (&_text <= vbase && vbase < &_etext)
- access = MEM_RX;
- if (&stack <= vbase && vbase < &stack_end)
- /* We need an executable stack. */
- access = MEM_RWX;
-
- PT_SET (&pdir[j], i, pde (base, false, access, true, true));
- pdir[j].allocated ++;
- }
-
- debug (0, "i: %d, base: %p, last_frame_phys: %p",
- i, base, kv_to_phys ((void *) last_frame));
-
- last_frame = last_frame_temp;
-
- page_table_check (&pdir[j], false);
- }
- }
-
- page_table_check (&pdp, false);
-
- PT_SET (&pml4, ADDR_PML4_INDEX (KERNEL_OFFSET),
- pml4e (kv_to_phys (&pdp), false, MEM_RWX));
- pml4.allocated ++;
-
- page_table_check (&pml4, false);
-
- asm ("mov %0, %%cr3" :: "r" (kv_to_phys (&pml4)));
-
- pool_init ();
-
- error_t err = hurd_slab_init (&mapping_slab,
- sizeof (struct vm_mapping), 0,
- mapping_slab_alloc,
- mapping_slab_dealloc,
- NULL, NULL, NULL);
- assert (! err);
-
- debug_register (&debug_command);
+#endif
}
static void
@@ -343,24 +226,19 @@ vm_as_install (struct thread *thread)
current_as = thread;
}
-void
-vm_thread_map (struct thread *thread, struct object_desc *desc,
- uintptr_t addr, uintptr_t access)
+struct map
{
- addr &= ~(PAGESIZE - 1);
-
- struct vg_object *object = object_desc_to_object (desc);
- uintptr_t page = kv_to_phys (object);
-
- debug (5, OBJECT_NAME_FMT": mapping %"PRIxPTR" -> %"PRIxPTR,
- OBJECT_NAME_PRINTF ((struct vg_object *) (thread)),
- addr, page);
-
- assert (addr + PAGESIZE < KERNEL_OFFSET);
-
- vm_as_maybe_init (thread);
+ struct page_table *pt;
+ int idx;
+};
- struct page_table *pt = thread->pml4;
+/* Return the PTE associated with ADDR building the page table up as
+ required. ON_BEHALF_OF is only used for debugging purposes. */
+static struct map
+vm_map (struct vg_object *on_behalf_of,
+ struct page_table *pml4, uintptr_t addr)
+{
+ struct page_table *pt = pml4;
struct pte *entry;
#define CONCAT(a, b) a##b
@@ -383,7 +261,8 @@ vm_thread_map (struct thread *thread, struct object_desc *desc,
\
debug (5, OBJECT_NAME_FMT": allocating at " #level "[%d]: " \
PTE_FMT " (%d allocated)", \
- OBJECT_NAME_PRINTF ((struct vg_object *) (thread)), \
+ OBJECT_NAME_PRINTF (on_behalf_of \
+ ?: (struct vg_object *) root_activity), \
idx, PTE_PRINTF (*entry), pt->allocated); \
\
page_table_check (pt, false); \
@@ -396,7 +275,8 @@ vm_thread_map (struct thread *thread, struct object_desc *desc,
\
debug (5, OBJECT_NAME_FMT": indexing " #level "[%d]: " \
PTE_FMT " (%d allocated)", \
- OBJECT_NAME_PRINTF ((struct vg_object *) (thread)), \
+ OBJECT_NAME_PRINTF (on_behalf_of \
+ ?: (struct vg_object *) root_activity), \
idx, PTE_PRINTF (*entry), pt->allocated); \
} \
\
@@ -411,7 +291,32 @@ vm_thread_map (struct thread *thread, struct object_desc *desc,
page_table_check (pt, true);
int idx = ADDR_PT_INDEX (addr);
- entry = &pt->entry[idx];
+ return (struct map) { pt, idx };
+}
+
+void
+vm_thread_map (struct thread *thread, struct object_desc *desc,
+ uintptr_t addr, uintptr_t access)
+{
+ addr &= ~(PAGESIZE - 1);
+
+ struct vg_object *object = object_desc_to_object (desc);
+ uintptr_t page = kv_to_phys (object);
+
+ debug (5, OBJECT_NAME_FMT": mapping %"PRIxPTR" -> %"PRIxPTR,
+ OBJECT_NAME_PRINTF ((struct vg_object *) (thread)),
+ addr, page);
+
+ assert (addr + PAGESIZE < KERNEL_OFFSET);
+
+ vm_as_maybe_init (thread);
+
+ struct map map = vm_map ((struct vg_object *) thread, thread->pml4, addr);
+ struct page_table *pt = map.pt;
+ int idx = map.idx;
+
+ struct pte *entry = &pt->entry[idx];
+ assert (entry);
if (entry->present)
/* There is already a page mapped here... */
@@ -686,6 +591,138 @@ vm_object_revoke (struct object_desc *desc, uintptr_t access)
}
}
+static void page_table_dump (int argc, char *argv[]);
+
+static struct debug_command debug_command =
+ {
+ "page-tables",
+ 'p',
+ "Print a thread's page table structures",
+ page_table_dump
+ };
+
+void
+vm_init (void)
+{
+ /* Enable global pages. */
+ x86_64_load_cr4 (X86_64_CR4_PGE, true);
+
+ /* Enable supervisor write protect. */
+ x86_64_load_cr0 (X86_64_CR0_WP, true);
+
+ /* Enable the execute protection bit. */
+ x86_64_load_efer (X86_64_EFER_NX, true);
+
+ int gb_pages = 0;
+ if ((cpuid (0x80000001).edx & (1 << 26)))
+ {
+ gb_pages = cpuid (0x80000019).ebx;
+ debug (0, "Support for %d 1GB pages found.", gb_pages);
+ }
+
+ /* Set up the kernel's page tables. */
+ uint64_t gb = 1024 * 1024 * 1024;
+ int j;
+ uint64_t base;
+ for (j = 0, base = j * gb;
+ base <= kv_to_phys ((void *) last_frame)
+ && j < sizeof (pdir) / sizeof (pdir[0]);
+ j ++, base = j * gb)
+ {
+ if (gb_pages > 0)
+ {
+ PT_SET (&pdp, ADDR_PDP_INDEX ((uintptr_t) phys_to_kv (base)),
+ pdpe (kv_to_phys (&pdir[j]), false, MEM_RWX,
+ true, true));
+ pdp.allocated ++;
+
+ gb_pages --;
+ }
+ else
+ {
+ PT_SET (&pdp, ADDR_PDP_INDEX ((uintptr_t) phys_to_kv (base)),
+ pdpe (kv_to_phys (&pdir[j]), false, MEM_RWX,
+ false, false));
+ pdp.allocated ++;
+
+ /* XXX: Grub doesn't report all the memory in the system.
+ This wouldn't be too bad except that it stores some of
+ its data structures in that memory! Here we "round up"
+ to the next gig. This gets all the memory. */
+ uintptr_t last_frame_temp = last_frame;
+ if ((uintptr_t) phys_to_kv ((uintptr_t) base) + gb - 1 > last_frame)
+ {
+ last_frame = (uintptr_t) phys_to_kv ((uintptr_t) base) + gb - 1;
+ debug (0, "Setting last frame to %"PRIxPTR" -> %"PRIxPTR,
+ last_frame_temp, last_frame);
+ }
+
+ int i;
+ for (i = 0;
+ i < PTES && base <= kv_to_phys ((void *) last_frame);
+ i ++, base += 1 << (9 + 12))
+ {
+ extern char _text, _etext;
+ extern char _rodata, _erodata;
+ extern char stack, stack_end;
+
+ int access = MEM_RW;
+
+ uintptr_t vbase = (uintptr_t) phys_to_kv (base);
+ if ((uintptr_t) &_rodata <= vbase
+ && vbase < (uintptr_t) &_erodata)
+ access = MEM_READABLE;
+ if ((uintptr_t) &_text <= vbase && vbase < (uintptr_t) &_etext)
+ access = MEM_RX;
+ if ((uintptr_t) &stack <= vbase
+ && vbase < (uintptr_t) &stack_end)
+ /* We need an executable stack. */
+ access = MEM_RWX;
+
+ PT_SET (&pdir[j], i, pde (base, false, access, true, true));
+ pdir[j].allocated ++;
+ }
+
+ debug (0, "i: %d, base: %"PRIxPTR", last_frame_phys: %"PRIxPTR,
+ i, base, kv_to_phys ((void *) last_frame));
+
+ last_frame = last_frame_temp;
+
+ page_table_check (&pdir[j], false);
+ }
+ }
+
+ page_table_check (&pdp, false);
+
+ PT_SET (&pml4, ADDR_PML4_INDEX (KERNEL_OFFSET),
+ pml4e (kv_to_phys (&pdp), false, MEM_RWX));
+ pml4.allocated ++;
+
+ page_table_check (&pml4, false);
+
+ asm ("mov %0, %%cr3" :: "r" (kv_to_phys (&pml4)));
+
+ pool_init ();
+
+ error_t err = hurd_slab_init (&mapping_slab,
+ sizeof (struct vm_mapping), 0,
+ mapping_slab_alloc,
+ mapping_slab_dealloc,
+ NULL, NULL, NULL);
+ assert (! err);
+
+ struct map map = vm_map (NULL, &pml4, (uintptr_t) VG_TIME);
+
+ struct pte *entry = &map.pt->entry[map.idx];
+ assert (! entry->present);
+
+ debug (0, DEBUG_BOLD ("Mapping time to %p"), VG_TIME);
+ PT_SET (map.pt, map.idx, pte (kv_to_phys (&time_data),
+ true, MEM_READABLE, true));
+
+ debug_register (&debug_command);
+}
+
void
vm_dump_from (struct page_table *pml4, uintptr_t start, uintptr_t end)
{
diff --git a/viengoos/thread.c b/viengoos/thread.c
index d5aa4ec..7f7a2cb 100644
--- a/viengoos/thread.c
+++ b/viengoos/thread.c
@@ -260,8 +260,11 @@ thread_activate (struct activity *activity,
if (utcb->activated_mode)
{
- debug (0, "Deferring exception delivery: thread in activated mode!"
- "(sp: %"PRIxPTR", ip: %"PRIxPTR")", sp, ip);
+ debug (0, "Deferring activation by "VG_OID_FMT": "
+ "thread "OBJECT_NAME_FMT" in activated mode! "
+ "(sp: %"PRIxPTR", ip: %"PRIxPTR")",
+ object_oid ((struct vg_object *) messenger),
+ OBJECT_NAME_PRINTF ((struct vg_object *) thread), sp, ip);
if (! may_block)
return false;
diff --git a/viengoos/timer.c b/viengoos/timer.c
index aa3de44..1e2e976 100644
--- a/viengoos/timer.c
+++ b/viengoos/timer.c
@@ -22,7 +22,7 @@
#include "timer-arch.h"
#include "bottom-half.h"
-volatile struct time_data time_data __attribute__ ((aligned (PAGESIZE)));
+volatile struct vg_time time_data __attribute__ ((aligned (PAGESIZE)));
void
timer_bootstrap (void)
diff --git a/viengoos/timer.h b/viengoos/timer.h
index f4dd066..37dabec 100644
--- a/viengoos/timer.h
+++ b/viengoos/timer.h
@@ -24,25 +24,9 @@
#include <stdint.h>
#include <stdbool.h>
#include <hurd/stddef.h>
+#include <viengoos/bits/sys.h>
-/* The number of ticks since boot (updated by the architecture
- dependency code). */
-struct time_data
-{
- union
- {
- struct
- {
- /* The number of nanoseconds since boot. */
- uint64_t ns_since_boot;
- /* The clocks frequency in Hz. */
- uint64_t frequency;
- };
- char raw[PAGESIZE];
- };
-};
-
-extern volatile struct time_data time_data;
+extern volatile struct vg_time time_data;
struct timer
{
diff --git a/viengoos/viengoos.c b/viengoos/viengoos.c
index e04869d..0e3b1fe 100644
--- a/viengoos/viengoos.c
+++ b/viengoos/viengoos.c
@@ -205,6 +205,8 @@ bootstrap (void)
timer_bootstrap ();
scheduler_bootstrap ();
thread_bootstrap ();
+
+ server_bootstrap ();
ager_bootstrap ();
}