summaryrefslogtreecommitdiff
path: root/libhurd-mm
diff options
context:
space:
mode:
Diffstat (limited to 'libhurd-mm')
-rw-r--r--libhurd-mm/ChangeLog9
-rw-r--r--libhurd-mm/exceptions.c26
-rw-r--r--libhurd-mm/ia32-exception-entry.S20
3 files changed, 45 insertions, 10 deletions
diff --git a/libhurd-mm/ChangeLog b/libhurd-mm/ChangeLog
index 5256ecc..7e59cca 100644
--- a/libhurd-mm/ChangeLog
+++ b/libhurd-mm/ChangeLog
@@ -1,3 +1,12 @@
+2007-12-13 Neal H. Walfield <neal@gnu.org>
+
+ * exceptions.c (exception_frame_alloc): When allocating the first
+ frame, set EXCEPTION_PAGE->EXCEPTION_STACK_BOTTOM.
+ (exception_page_cleanup): New function.
+
+ * ia32-exception-entry.S (_exception_handler_end): Correctly
+ adjust the exception page's exception stack.
+
2007-12-12 Neal H. Walfield <neal@gnu.org>
* mmap.c (munmap): Free the virtual addresses.
diff --git a/libhurd-mm/exceptions.c b/libhurd-mm/exceptions.c
index 47f9790..71eb16c 100644
--- a/libhurd-mm/exceptions.c
+++ b/libhurd-mm/exceptions.c
@@ -93,6 +93,10 @@ exception_frame_alloc (struct exception_page *exception_page)
exception_frame->next->prev = exception_frame;
exception_page->exception_stack = exception_frame;
+
+ if (! exception_page->exception_stack_bottom)
+ /* This is the first frame we've allocated. */
+ exception_page->exception_stack_bottom = exception_frame;
}
return exception_frame;
@@ -310,3 +314,25 @@ exception_handler_init (void)
if (err)
panic ("Failed to install exception page");
}
+
+void
+exception_page_cleanup (struct exception_page *exception_page)
+{
+ struct exception_frame *f;
+ struct exception_frame *prev = exception_page->exception_stack_bottom;
+
+ int count = 0;
+ while ((f = prev))
+ {
+ prev = f->prev;
+ hurd_slab_dealloc (&exception_frame_slab, f);
+ count ++;
+ }
+
+ assertx (count == exception_page->frame_count,
+ "count: %d, exception_page->frame_count: %d",
+ count, exception_page->frame_count);
+
+ debug (0, "Freed %d frames", count);
+}
+
diff --git a/libhurd-mm/ia32-exception-entry.S b/libhurd-mm/ia32-exception-entry.S
index 6b23c9f..f511563 100644
--- a/libhurd-mm/ia32-exception-entry.S
+++ b/libhurd-mm/ia32-exception-entry.S
@@ -116,9 +116,9 @@ after_adjust:
normal mode.
To return to normal mode, we need to restore the saved
- registers, including the saved EAX, saved ESP and saved EIP.
- On x86, there is no way to atomically restore ESP and EIP from
- user code. The solution we use is:
+ registers, including the saved general registers, saved ESP
+ and saved EIP. On x86, there is no way to atomically restore
+ ESP and EIP from user code. The solution we use is:
- save the saved EIP on the user stack
- restore the saved ESP minus 4
@@ -132,15 +132,15 @@ after_adjust:
kernel can transition us back to activated mode.
But this raises another problem: the IP and SP that the kernel
- see are not those that return us to user code. As this code
+ sees are not those that return us to user code. As this code
relies on the exception stack, a nested stack will leave us in
an inconsistent state. (This can also happen if we receive a
message before returning to user code.) To avoid this, we
register our restore to normal mode function with the kernel.
- If the kernel transitions us back to activated while the EIP
- is in this range, then it does not save the EIP and ESP and
- invokes the exception handler with the interrupt_in_transition
- flag set. */
+ If the kernel transitions us back to activated mode while the
+ EIP is in this range, then it does not save the EIP and ESP
+ and invokes the exception handler with the
+ interrupt_in_transition flag set. */
/* Reset the activation bit. */
and $0xfffffffe, MODE(%edx)
@@ -262,8 +262,8 @@ _exception_handler_end:
/* Remove our exception frame, which is at the top
of the exception frame stack. */
- mov EF_NEXT(%edx), %ecx
- lock mov %ecx, EXCEPTION_STACK(%eax)
+ mov EF_NEXT(%eax), %ecx
+ lock mov %ecx, EXCEPTION_STACK(%edx)
popl %eax
popl %ecx