diff options
author | Neal H. Walfield <neal@gnu.org> | 2009-02-21 21:14:41 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@gnu.org> | 2009-02-21 21:14:41 +0100 |
commit | 759bcbda499afd29b8da5fd47f437b96a6c948cc (patch) | |
tree | 0530a6ff40977412aaf9ec126cfdf7e408ddccec /viengoos | |
parent | 52ce316a43952dbe15d6072b77f70bb121b3b872 (diff) |
Add sleep and time support.
Diffstat (limited to 'viengoos')
-rw-r--r-- | viengoos/messenger.c | 116 | ||||
-rw-r--r-- | viengoos/messenger.h | 26 | ||||
-rw-r--r-- | viengoos/object.c | 52 | ||||
-rw-r--r-- | viengoos/object.h | 13 | ||||
-rw-r--r-- | viengoos/server.c | 48 | ||||
-rw-r--r-- | viengoos/server.h | 2 | ||||
-rw-r--r-- | viengoos/sysdeps/x86_64/idt.c | 1 | ||||
-rw-r--r-- | viengoos/sysdeps/x86_64/syscall.c | 4 | ||||
-rw-r--r-- | viengoos/sysdeps/x86_64/vm.c | 325 | ||||
-rw-r--r-- | viengoos/thread.c | 7 | ||||
-rw-r--r-- | viengoos/timer.c | 2 | ||||
-rw-r--r-- | viengoos/timer.h | 20 | ||||
-rw-r--r-- | viengoos/viengoos.c | 2 |
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 (); } |