/* Machine dependent routines for UFS
   Copyright (C) 1992 Free Software Foundation

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 General Public License as published by
the Free Software Foundation; either version 2, 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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with the GNU Hurd; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by Michael I. Bushnell.  */

#include "ufs.h"

/* Faulting threads have their PC displaced here when they encounter a
   memory fault in a recorded area.  */
static void
take_fault (void)
{
  error_t err;
  struct thread_stuff *tmp;
  /* To avoid clobbering eax, don't declare anything or do anything
     above this point...unless you want nonsense error codes... */

  /* The error gets stuck in eax when we get control */
  asm ("movl %%eax,%0" : "=g" (err));

  tmp = (struct thread_stuff *) cthread_data (cthread_self ());
  if (!tmp)
    panic ("take_fault");
  
  cthread_set_data (cthread_self (), (any_t)tmp->link);
  longjmp (tmp->buf, err);
}

void
report_memory_fault (thread_t thread,
		     int code)
{
  struct i386_thread_state ts;
  u_int size = i386_THREAD_STATE_COUNT;
  
  thread_get_state (thread, i386_THREAD_STATE, (int *)&ts, &size);
  if (size != i386_THREAD_STATE_COUNT)
    panic ("report_memory_fault");

  /* Stick the error code in eax for take_fault above to get it */
  ts.eax = code;
  ts.eip = (unsigned int) take_fault;
  
  thread_set_state (thread, i386_THREAD_STATE, (int *)&ts, size);
}

int
thread_pc (thread_t thread)
{
  struct i386_thread_state ts;
  
  u_int size = i386_THREAD_STATE_COUNT;
  
  thread_get_state (thread, i386_THREAD_STATE, (int *)&ts, &size);
  if (size != i386_THREAD_STATE_COUNT)
    panic ("report_memory_fault");

  return ts.eip;
}
