summaryrefslogtreecommitdiff
path: root/libhurd-mm/exceptions.c
diff options
context:
space:
mode:
authorneal <neal>2008-05-29 20:45:47 +0000
committerneal <neal>2008-05-29 20:45:47 +0000
commitd9d50cb6998f5d0e12e7166d7662c465a148b7f2 (patch)
tree0ef0d4c51a51b820fedacecdbfa7f15796bae076 /libhurd-mm/exceptions.c
parentfa71889d35e497a7d729e3f7b9f8fe7708b632a7 (diff)
libhurd-mm/
2008-05-29 Neal H. Walfield <neal@gnu.org> * exceptions.c (exception_handler_activated): Assume the fault is on the stack if it is one page above or three pages below the stack pointer. (exception_handler_init): Allocate an area of address space EXCEPTION_STACK_SIZE bytes larges. Fill it with pages. Set the first page as the thread's exception page and the top of the area minus one word as the stack pointer. Set the last word to the location of the exception page. * ia32-exception-entry.S: Include <hurd/exceptions.h>. (PAGESIZE): Don't define. (_exception_handler_entry): Rewrite to not assume that the exception page is at the start of the page in which the stack pointer is, but at the location stored in the word after the bottom of the stack. * Makefile.am (libhurd_mm_a_CCASFLAGS): New variable. * pager.c (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE - PAGESIZE bytes large. Write to each page. libpthread/ 2008-05-29 Neal H. Walfield <neal@gnu.org> * sysdeps/l4/hurd/pt-sysdep.h Include <hurd/exceptions.h>. (EXCEPTION_AREA_SIZE): Define. (EXCEPTION_AREA_SIZE_LOG2): Likewise. (EXCEPTION_PAGE): Likewise. (PTHREAD_SYSDEP_MEMBERS): Change object's type to an addr_t. Update users. Remove field exception_page, replace with exception_area. Add field exception_area_va. * sysdeps/l4/hurd/pt-thread-alloc.c: Include <hurd/as.h> and <hurd/addr.h>. (__pthread_thread_alloc): Allocate EXCEPTION_AREA_SIZE bytes of address space. Save it in THREAD->EXCEPTION_AREA_VA. Allocate a page for each page in that area. Save them in THREAD->EXCEPTION_AREA. * sysdeps/l4/hurd/ia32/pt-setup.c (__pthread_setup): Set EXCEPTION_PAGE->EXCEPTION_HANDLER_SP to the end of EXCEPTION_PAGE->EXCEPTION_HANDLER_SP minus one word, in which we save the address of the exception page. * sysdeps/l4/hurd/pt-thread-start.c (__pthread_thread_start): Set IN.EXCEPTION_PAGE to the first page in THREAD->EXCEPTION_AREA_VA. * sysdeps/l4/hurd/pt-thread-halt.c: Include <hurd/mutex.h>, <hurd/as.h> and <hurd/addr.h>. (saved_object_lock): New variable. (__pthread_thread_halt): Lock SAVED_OBJECT_LOCK when accessing SAVED_OBJECT. Free the address space used by the exception area (THREAD->EXCEPTION_AREA_VA) and its associated storage (THREAD->EXCEPTION_AREA). hurd/ 2008-05-29 Neal H. Walfield <neal@gnu.org> * exceptions.h: Include <hurd/stddef.h>. [ASM]: Only define relevant macros. (EXCEPTION_STACK_SIZE_LOG2): Define. (EXCEPTION_STACK_SIZE): Define. * stddef.h [ASM]: Only define relevant macros. (PAGESIZE): Don't append C type specifier. (PAGESIZE_LOG2): Likewise. viengoos/ 2008-05-29 Neal H. Walfield <neal@gnu.org> * as.c: Include <hurd/exceptions.h>. (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE - PAGESIZE bytes large. Write to each page. * cap-lookup.c: Include <hurd/exceptions.h>. (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE - PAGESIZE bytes large. Write to each page. * zalloc.c (ZONE_SIZE): Add suffix the 1 with a U type qualifier. (ZONES): Include one less zone.
Diffstat (limited to 'libhurd-mm/exceptions.c')
-rw-r--r--libhurd-mm/exceptions.c62
1 files changed, 46 insertions, 16 deletions
diff --git a/libhurd-mm/exceptions.c b/libhurd-mm/exceptions.c
index ecf7ce5..3631893 100644
--- a/libhurd-mm/exceptions.c
+++ b/libhurd-mm/exceptions.c
@@ -241,8 +241,7 @@ exception_handler_activated (struct exception_page *exception_page)
= exception_frame_alloc (exception_page);
utcb_state_save (exception_frame);
- debug (5, "Exception handler called (0x%x.%x, exception_page: %p)",
- l4_thread_no (l4_myself ()), l4_version (l4_myself ()),
+ debug (5, "Exception handler called (exception_page: %p)",
exception_page);
#ifndef NDEBUG
@@ -271,12 +270,14 @@ exception_handler_activated (struct exception_page *exception_page)
/* XXX: We assume that the stack grows down here. */
uintptr_t f = (uintptr_t) ADDR_TO_PTR (fault);
- if ((f & ~(PAGESIZE - 1)) == ((sp - 1) & ~(PAGESIZE - 1))
- || (f & ~(PAGESIZE - 1)) == (sp & ~(PAGESIZE - 1)))
- /* The fault occurs on the same page as the last byte of the
- interrupted SP. It has got to be a stack fault. Handle
- it here. */
+ if (sp - PAGESIZE <= f && f <= sp + PAGESIZE * 4)
+ /* The fault occurs within four pages of the stack pointer.
+ It has got to be a stack fault. Handle it here. */
{
+ debug (5, "Handling fault at " ADDR_FMT " in activated mode "
+ "(ip: %x, sp: %x).",
+ ADDR_PRINTF (fault), ip, sp);
+
bool r = pager_fault (fault, ip, info);
if (! r)
{
@@ -307,6 +308,10 @@ exception_handler_activated (struct exception_page *exception_page)
return NULL;
}
+ debug (5, "Handling fault at " ADDR_FMT " in normal mode "
+ "(ip: %x, sp: %x).",
+ ADDR_PRINTF (fault), ip, sp);
+
break;
}
@@ -336,25 +341,50 @@ exception_handler_init (void)
extern struct hurd_startup_data *__hurd_startup_data;
- struct storage storage = storage_alloc (ADDR_VOID, cap_page,
- STORAGE_LONG_LIVED,
- OBJECT_POLICY_DEFAULT, ADDR_VOID);
+ /* We use the start of the area (lowest address) as the exception page. */
+ addr_t stack_area = as_alloc (EXCEPTION_STACK_SIZE_LOG2, 1, true);
+ void *stack_area_base
+ = ADDR_TO_PTR (addr_extend (stack_area, 0, EXCEPTION_STACK_SIZE_LOG2));
+
+ debug (5, "Exception area: %x-%x",
+ stack_area_base, stack_area_base + EXCEPTION_STACK_SIZE - 1);
+
+ void *page;
+ for (page = stack_area_base;
+ page < stack_area_base + EXCEPTION_STACK_SIZE;
+ page += PAGESIZE)
+ {
+ addr_t slot = addr_chop (PTR_TO_ADDR (page), PAGESIZE_LOG2);
+
+ as_slot_ensure (slot);
+
+ struct storage storage;
+ storage = storage_alloc (ADDR_VOID, cap_page,
+ STORAGE_LONG_LIVED,
+ OBJECT_POLICY_DEFAULT,
+ slot);
- if (ADDR_IS_VOID (storage.addr))
- panic ("Failed to allocate page for exception state");
+ if (ADDR_IS_VOID (storage.addr))
+ panic ("Failed to allocate page for exception state");
+ }
- struct exception_page *exception_page
- = ADDR_TO_PTR (addr_extend (storage.addr, 0, PAGESIZE_LOG2));
+ struct exception_page *exception_page = stack_area_base;
/* XXX: We assume the stack grows down! SP is set to the end of the
exception page. */
- exception_page->exception_handler_sp = (l4_word_t) exception_page + PAGESIZE;
+ exception_page->exception_handler_sp
+ = (uintptr_t) stack_area_base + EXCEPTION_STACK_SIZE;
+
+ /* The word beyond the base of the stack is a pointer to the
+ exception page. */
+ exception_page->exception_handler_sp -= sizeof (void *);
+ * (void **) exception_page->exception_handler_sp = exception_page;
exception_page->exception_handler_ip = (l4_word_t) &exception_handler_entry;
exception_page->exception_handler_end = (l4_word_t) &exception_handler_end;
struct hurd_thread_exregs_in in;
- in.exception_page = storage.addr;
+ in.exception_page = addr_chop (PTR_TO_ADDR (exception_page), PAGESIZE_LOG2);
struct hurd_thread_exregs_out out;
err = rm_thread_exregs (ADDR_VOID, __hurd_startup_data->thread,