diff options
-rw-r--r-- | hurd/ChangeLog | 5 | ||||
-rw-r--r-- | hurd/thread.h | 27 | ||||
-rw-r--r-- | libhurd-mm/ChangeLog | 19 | ||||
-rw-r--r-- | libhurd-mm/exceptions.c | 123 | ||||
-rw-r--r-- | libhurd-mm/ia32-exception-entry.S | 20 |
5 files changed, 126 insertions, 68 deletions
diff --git a/hurd/ChangeLog b/hurd/ChangeLog index 9ea2d29..0353b77 100644 --- a/hurd/ChangeLog +++ b/hurd/ChangeLog @@ -1,3 +1,8 @@ +2008-01-02 Neal H. Walfield <neal@gnu.org> + + * thread.h (struct exception_page): Make mode bits a union thereby + providing straightforward access to the raw bits. Add field crc. + 2008-01-01 Neal H. Walfield <neal@gnu.org> * stddef.h (do_debug) [DEBUG_ELIDE]: Make a proper conditional. diff --git a/hurd/thread.h b/hurd/thread.h index a963d1b..c721044 100644 --- a/hurd/thread.h +++ b/hurd/thread.h @@ -1,5 +1,5 @@ /* thread.h - Thread definitions. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2008 Free Software Foundation, Inc. Written by Neal H. Walfield <neal@gnu.org>. GNU Hurd is free software: you can redistribute it and/or modify it @@ -63,14 +63,21 @@ struct exception_page this structure **** */ struct { - /* Whether the thread is in activated mode. */ - l4_word_t activated_mode : 1; - /* Set by the kernel to indicated that there is a pending - message. */ - l4_word_t pending_message : 1; - /* Set by the kernel to indicate whether the thread was - interrupted while the EIP is in the transition range. */ - l4_word_t interrupt_in_transition : 1; + union + { + struct + { + /* Whether the thread is in activated mode. */ + l4_word_t activated_mode : 1; + /* Set by the kernel to indicated that there is a pending + message. */ + l4_word_t pending_message : 1; + /* Set by the kernel to indicate whether the thread was + interrupted while the EIP is in the transition range. */ + l4_word_t interrupt_in_transition : 1; + }; + l4_word_t mode; + }; /* The value of the IP and SP when the thread was running. */ l4_word_t saved_ip; @@ -89,6 +96,8 @@ struct exception_page /* The exception. */ l4_msg_t exception; + + l4_word_t crc; }; char data[PAGESIZE]; }; diff --git a/libhurd-mm/ChangeLog b/libhurd-mm/ChangeLog index 5fbfb56..bbdb347 100644 --- a/libhurd-mm/ChangeLog +++ b/libhurd-mm/ChangeLog @@ -1,3 +1,22 @@ +2008-01-02 Neal H. Walfield <neal@gnu.org> + + * exceptions.c (crc) [! NDEBUG]: New function. + (exception_handler_activated) [! NDEBUG]: After saving the frame + state, calculate the crc of the header. Check it before + returning. + + (exception_frame_slab_alloc): Save the UTCB state before calling + storage_alloc and restore it before returning. + + (exception_handler_activated): Assert that + EXCEPTION_PAGE->ACTIVATED_MODE is set. + + (exception_handler_normal): If we fail to handle the fault, panic. + (exception_handler_activated): Likewise. + + * ia32-exception-entry.S (_exception_handler_entry): Correctly + test and set the flags. + 2007-12-25 Neal H. Walfield <neal@gnu.org> * as.h: Change VISIT's signature: pass a struct cap_properties diff --git a/libhurd-mm/exceptions.c b/libhurd-mm/exceptions.c index fa6da30..a5395c7 100644 --- a/libhurd-mm/exceptions.c +++ b/libhurd-mm/exceptions.c @@ -1,23 +1,22 @@ /* exceptions.c - Exception handler implementation. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2008 Free Software Foundation, Inc. Written by Neal H. Walfield <neal@gnu.org>. This file is part of the GNU Hurd. - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + GNU Hurd is free software: you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. - The GNU Hurd is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + License along with GNU Hurd. If not, see + <http://www.gnu.org/licenses/>. */ #include <hurd/startup.h> #include <hurd/stddef.h> @@ -32,6 +31,36 @@ extern struct hurd_startup_data *__hurd_startup_data; +static void +utcb_state_save (struct exception_frame *exception_frame) +{ + l4_word_t *utcb = _L4_utcb (); + + exception_frame->saved_sender = utcb[_L4_UTCB_SENDER]; + exception_frame->saved_receiver = utcb[_L4_UTCB_RECEIVER]; + exception_frame->saved_timeout = utcb[_L4_UTCB_TIMEOUT]; + exception_frame->saved_error_code = utcb[_L4_UTCB_ERROR_CODE]; + exception_frame->saved_flags = utcb[_L4_UTCB_FLAGS]; + exception_frame->saved_br0 = utcb[_L4_UTCB_BR0]; + memcpy (&exception_frame->saved_message, + utcb, L4_NUM_MRS * sizeof (l4_word_t)); +} + +static void +utcb_state_restore (struct exception_frame *exception_frame) +{ + l4_word_t *utcb = _L4_utcb (); + + utcb[_L4_UTCB_SENDER] = exception_frame->saved_sender; + utcb[_L4_UTCB_RECEIVER] = exception_frame->saved_receiver; + utcb[_L4_UTCB_TIMEOUT] = exception_frame->saved_timeout; + utcb[_L4_UTCB_ERROR_CODE] = exception_frame->saved_error_code; + utcb[_L4_UTCB_FLAGS] = exception_frame->saved_flags; + utcb[_L4_UTCB_BR0] = exception_frame->saved_br0; + memcpy (utcb, &exception_frame->saved_message, + L4_NUM_MRS * sizeof (l4_word_t)); +} + static struct hurd_slab_space exception_frame_slab; static error_t @@ -39,11 +68,16 @@ exception_frame_slab_alloc (void *hook, size_t size, void **ptr) { assert (size == PAGESIZE); + struct exception_frame frame; + utcb_state_save (&frame); + struct storage storage = storage_alloc (meta_data_activity, cap_page, STORAGE_EPHEMERAL, ADDR_VOID); *ptr = ADDR_TO_PTR (addr_extend (storage.addr, 0, PAGESIZE_LOG2)); + utcb_state_restore (&frame); + return 0; } @@ -102,36 +136,6 @@ exception_frame_alloc (struct exception_page *exception_page) return exception_frame; } -static void -utcb_state_save (struct exception_frame *exception_frame) -{ - l4_word_t *utcb = _L4_utcb (); - - exception_frame->saved_sender = utcb[_L4_UTCB_SENDER]; - exception_frame->saved_receiver = utcb[_L4_UTCB_RECEIVER]; - exception_frame->saved_timeout = utcb[_L4_UTCB_TIMEOUT]; - exception_frame->saved_error_code = utcb[_L4_UTCB_ERROR_CODE]; - exception_frame->saved_flags = utcb[_L4_UTCB_FLAGS]; - exception_frame->saved_br0 = utcb[_L4_UTCB_BR0]; - memcpy (&exception_frame->saved_message, - utcb, L4_NUM_MRS * sizeof (l4_word_t)); -} - -static void -utcb_state_restore (struct exception_frame *exception_frame) -{ - l4_word_t *utcb = _L4_utcb (); - - utcb[_L4_UTCB_SENDER] = exception_frame->saved_sender; - utcb[_L4_UTCB_RECEIVER] = exception_frame->saved_receiver; - utcb[_L4_UTCB_TIMEOUT] = exception_frame->saved_timeout; - utcb[_L4_UTCB_ERROR_CODE] = exception_frame->saved_error_code; - utcb[_L4_UTCB_FLAGS] = exception_frame->saved_flags; - utcb[_L4_UTCB_BR0] = exception_frame->saved_br0; - memcpy (utcb, &exception_frame->saved_message, - L4_NUM_MRS * sizeof (l4_word_t)); -} - /* Fetch an exception. */ void exception_fetch_exception (void) @@ -185,11 +189,9 @@ exception_handler_normal (struct exception_frame *exception_frame) bool r = pager_fault (fault, ip, info); if (! r) { - debug (1, "Failed to handle fault at " ADDR_FMT " (ip=%x)", - ADDR_PRINTF (fault), ip); /* XXX: Should raise SIGSEGV. */ - for (;;) - l4_yield (); + panic ("Failed to handle fault at " ADDR_FMT " (ip=%x)", + ADDR_PRINTF (fault), ip); } break; @@ -202,9 +204,24 @@ exception_handler_normal (struct exception_frame *exception_frame) utcb_state_restore (exception_frame); } +#ifndef NDEBUG +static l4_word_t +crc (struct exception_page *exception_page) +{ + l4_word_t crc = 0; + l4_word_t *p; + for (p = (l4_word_t *) exception_page; p < &exception_page->crc; p ++) + crc += *p; + + return crc; +} +#endif + struct exception_frame * exception_handler_activated (struct exception_page *exception_page) { + assert (exception_page->activated_mode); + debug (5, "Exception handler called (0x%x.%x, exception_page: %p)", l4_thread_no (l4_myself ()), l4_version (l4_myself ()), exception_page); @@ -212,9 +229,12 @@ exception_handler_activated (struct exception_page *exception_page) /* Allocate an exception frame. */ struct exception_frame *exception_frame = exception_frame_alloc (exception_page); - utcb_state_save (exception_frame); +#ifndef NDEBUG + exception_page->crc = crc (exception_page); +#endif + l4_msg_t *msg = &exception_page->exception; l4_msg_tag_t msg_tag = l4_msg_msg_tag (*msg); @@ -246,15 +266,19 @@ exception_handler_activated (struct exception_page *exception_page) bool r = pager_fault (fault, ip, info); if (! r) { - debug (1, "Failed to handle fault at " ADDR_FMT " (ip=%x)", + panic ("Failed to handle fault at " ADDR_FMT " (ip=%x)", ADDR_PRINTF (fault), ip); /* XXX: Should raise SIGSEGV. */ - for (;;) - l4_yield (); } + assert (exception_page->crc == crc (exception_page)); utcb_state_restore (exception_frame); - assert (exception_page->exception_stack == exception_frame); + + assert (exception_page->crc == crc (exception_page)); + assertx (exception_page->exception_stack == exception_frame, + "%p != %p", + exception_page->exception_stack, exception_frame); + exception_page->exception_stack = exception_page->exception_stack->next; return NULL; @@ -273,6 +297,7 @@ exception_handler_activated (struct exception_page *exception_page) memcpy (&exception_frame->exception, msg, (1 + l4_untyped_words (msg_tag)) * sizeof (l4_word_t)); + assert (exception_page->crc == crc (exception_page)); return exception_frame; } diff --git a/libhurd-mm/ia32-exception-entry.S b/libhurd-mm/ia32-exception-entry.S index f511563..7f185ba 100644 --- a/libhurd-mm/ia32-exception-entry.S +++ b/libhurd-mm/ia32-exception-entry.S @@ -6,8 +6,8 @@ The GNU Hurd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. The GNU Hurd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,8 +15,8 @@ General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + along with this program. If not, see + <http://www.gnu.org/licenses/>. */ .text @@ -70,7 +70,7 @@ _exception_handler_entry: and $0xfffff000, %edx /* Now check if the interrupt in transition flag is set. */ - bt $0x2, MODE(%edx) + bt $0x4, MODE(%edx) jc after_save /* Nope; we need to save the current EAX, ECX and eflags. */ @@ -93,7 +93,7 @@ after_adjust: our pointer to the exception page on the stack. */ pushl %edx - /* The exception handler function takes a single arguments: + /* The exception handler function takes a single argument: the exception page. */ /* Push the exception page. */ @@ -148,7 +148,7 @@ after_adjust: /* Check for pending messages. This does not need to be atomic as if we get interrupted here, we automatically transition back to activated mode. */ - bt $0x1, MODE(%edx) + bt $0x2, MODE(%edx) jc process_pending /* Restore the user stack. */ @@ -223,7 +223,7 @@ exception_frame_run: exception_handler_end: _exception_handler_end: - /* We have now left the protected mode. We've saved all the + /* We have now left activated mode. We've saved all the state we need to return to the interrupted state in the exception frame and ESP points to the normal stack. If a fault now occurs, nothing bad can happend. */ @@ -243,9 +243,9 @@ _exception_handler_end: /* Remove the argument. */ add $4, %esp - /* Restore the exception page pointer and the exception frame - pointer. */ + /* Restore the exception frame pointer. */ popl %eax + /* And restore the exception page pointer. */ popl %edx /* Restore the user state. */ |