ia64/xen-unstable

changeset 23:6b1edd19b627

bitkeeper revision 1.10 (3df5fdf08iqVVKnjFD3pfq_hggDi2Q)

Merge boulderdash.cl.cam.ac.uk:/usr/groups/xeno/BK/xeno
into boulderdash.cl.cam.ac.uk:/local/scratch/smh22/xeno.bk
author smh22@boulderdash.cl.cam.ac.uk
date Tue Dec 10 14:45:04 2002 +0000 (2002-12-10)
parents 19dcb7010a45 c89b11899064
children 8ce741992076
files BitKeeper/etc/logging_ok xen-2.4.16/arch/i386/entry.S xen-2.4.16/arch/i386/i387.c xen-2.4.16/arch/i386/setup.c xen-2.4.16/arch/i386/traps.c xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h xenolinux-2.4.16-sparse/arch/xeno/kernel/process.c xenolinux-2.4.16-sparse/arch/xeno/kernel/signal.c xenolinux-2.4.16-sparse/arch/xeno/kernel/traps.c xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h
line diff
     1.1 --- a/BitKeeper/etc/logging_ok	Thu Dec 05 17:16:53 2002 +0000
     1.2 +++ b/BitKeeper/etc/logging_ok	Tue Dec 10 14:45:04 2002 +0000
     1.3 @@ -1,4 +1,5 @@
     1.4  akw27@boulderdash.cl.cam.ac.uk
     1.5 +kaf24@labyrinth.cl.cam.ac.uk
     1.6  kaf24@plym.cl.cam.ac.uk
     1.7  kaf24@striker.cl.cam.ac.uk
     1.8  smh22@boulderdash.cl.cam.ac.uk
     2.1 --- a/xen-2.4.16/arch/i386/entry.S	Thu Dec 05 17:16:53 2002 +0000
     2.2 +++ b/xen-2.4.16/arch/i386/entry.S	Tue Dec 10 14:45:04 2002 +0000
     2.3 @@ -302,6 +302,9 @@ FAULT11:movl %eax,4(%esi)
     2.4          movl EFLAGS+4(%esp),%eax
     2.5  FAULT12:movl %eax,8(%esi)
     2.6          /* Rewrite our stack frame and return to ring 1. */
     2.7 +        /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
     2.8 +        andl $0xfffcbeff,%eax
     2.9 +        movl %eax,EFLAGS+4(%esp)
    2.10          movl %ds,OLDSS+4(%esp)
    2.11          movl %esi,OLDESP+4(%esp)
    2.12          movzwl %es:GTB_CS(%edx),%eax
    2.13 @@ -521,6 +524,8 @@ ENTRY(hypervisor_call_table)
    2.14          .long SYMBOL_NAME(kill_domain)
    2.15          .long SYMBOL_NAME(do_dom0_op)
    2.16          .long SYMBOL_NAME(do_network_op)
    2.17 +        .long SYMBOL_NAME(do_set_debugreg)
    2.18 +        .long SYMBOL_NAME(do_get_debugreg)
    2.19          .rept NR_syscalls-(.-hypervisor_call_table)/4
    2.20          .long SYMBOL_NAME(sys_ni_syscall)
    2.21  	.endr
     3.1 --- a/xen-2.4.16/arch/i386/i387.c	Thu Dec 05 17:16:53 2002 +0000
     3.2 +++ b/xen-2.4.16/arch/i386/i387.c	Tue Dec 10 14:45:04 2002 +0000
     3.3 @@ -22,20 +22,26 @@ void init_fpu(void)
     3.4  
     3.5  static inline void __save_init_fpu( struct task_struct *tsk )
     3.6  {
     3.7 -	if ( cpu_has_fxsr ) {
     3.8 -		asm volatile( "fxsave %0 ; fnclex"
     3.9 -			      : "=m" (tsk->thread.i387.fxsave) );
    3.10 -	} else {
    3.11 -		asm volatile( "fnsave %0 ; fwait"
    3.12 -			      : "=m" (tsk->thread.i387.fsave) );
    3.13 -	}
    3.14 -	tsk->flags &= ~PF_USEDFPU;
    3.15 +    if ( cpu_has_fxsr ) {
    3.16 +        asm volatile( "fxsave %0 ; fnclex"
    3.17 +                      : "=m" (tsk->thread.i387.fxsave) );
    3.18 +    } else {
    3.19 +        asm volatile( "fnsave %0 ; fwait"
    3.20 +                      : "=m" (tsk->thread.i387.fsave) );
    3.21 +    }
    3.22 +    tsk->flags &= ~PF_USEDFPU;
    3.23  }
    3.24  
    3.25  void save_init_fpu( struct task_struct *tsk )
    3.26  {
    3.27 -	__save_init_fpu(tsk);
    3.28 -	stts();
    3.29 +    /*
    3.30 +     * The guest OS may have set the 'virtual STTS' flag.
    3.31 +     * This causes us to set the real flag, so we'll need
    3.32 +     * to temporarily clear it while saving f-p state.
    3.33 +     */
    3.34 +    if ( tsk->flags & PF_GUEST_STTS ) clts();
    3.35 +    __save_init_fpu(tsk);
    3.36 +    stts();
    3.37  }
    3.38  
    3.39  void restore_fpu( struct task_struct *tsk )
     4.1 --- a/xen-2.4.16/arch/i386/setup.c	Thu Dec 05 17:16:53 2002 +0000
     4.2 +++ b/xen-2.4.16/arch/i386/setup.c	Tue Dec 10 14:45:04 2002 +0000
     4.3 @@ -193,6 +193,9 @@ void __init cpu_init(void)
     4.4      /* No nested task. */
     4.5      __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
     4.6  
     4.7 +    /* Ensure FPU gets initialised for each domain. */
     4.8 +    stts();
     4.9 +
    4.10      /* Set up and load the per-CPU TSS and LDT. */
    4.11      t->ss0  = __HYPERVISOR_DS;
    4.12      t->esp0 = current->thread.esp0;
     5.1 --- a/xen-2.4.16/arch/i386/traps.c	Thu Dec 05 17:16:53 2002 +0000
     5.2 +++ b/xen-2.4.16/arch/i386/traps.c	Tue Dec 10 14:45:04 2002 +0000
     5.3 @@ -273,7 +273,26 @@ asmlinkage void do_general_protection(st
     5.4      if (!(regs->xcs & 3) || (error_code & 1))
     5.5          goto gp_in_kernel;
     5.6  
     5.7 -    if ( (error_code & 2) )
     5.8 +    /*
     5.9 +     * Cunning trick to allow arbitrary "INT n" handling.
    5.10 +     * 
    5.11 +     * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
    5.12 +     * instruction from trapping to the appropriate vector, when that might not 
    5.13 +     * be expected by Xen or the guest OS. For example, that entry might be for
    5.14 +     * a fault handler (unlike traps, faults don't increment EIP), or might
    5.15 +     * expect an error code on the stack (which a software trap never
    5.16 +     * provides), or might be a hardware interrupt handler that doesn't like
    5.17 +     * being called spuriously.  
    5.18 +     * 
    5.19 +     * Instead, a GPF occurs with the faulting IDT vector in the error code.
    5.20 +     * Bit 1 is set to indicate that an IDT entry caused the fault.
    5.21 +     * Bit 0 is clear to indicate that it's a software fault, not hardware.
    5.22 +     * 
    5.23 +     * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is okay
    5.24 +     * because they can only be triggered by an explicit DPL-checked instruction.
    5.25 +     * The DPL specified by the guest OS for these vectors is NOT CHECKED!!
    5.26 +     */
    5.27 +    if ( (error_code & 3) == 2 )
    5.28      {
    5.29          /* This fault must be due to <INT n> instruction. */
    5.30          ti = current->thread.traps + (error_code>>3);
    5.31 @@ -362,7 +381,8 @@ asmlinkage void do_nmi(struct pt_regs * 
    5.32  
    5.33  asmlinkage void math_state_restore(struct pt_regs *regs, long error_code)
    5.34  {
    5.35 -    __asm__ __volatile__("clts");
    5.36 +    /* Prevent recursion. */
    5.37 +    clts();
    5.38  
    5.39      if ( !(current->flags & PF_USEDFPU) )
    5.40      {
    5.41 @@ -384,53 +404,42 @@ asmlinkage void math_state_restore(struc
    5.42  }
    5.43  
    5.44  
    5.45 -/*
    5.46 - * Our handling of the processor debug registers is non-trivial.
    5.47 - * We do not clear them on entry and exit from the kernel. Therefore
    5.48 - * it is possible to get a watchpoint trap here from inside the kernel.
    5.49 - * However, the code in ./ptrace.c has ensured that the user can
    5.50 - * only set watchpoints on userspace addresses. Therefore the in-kernel
    5.51 - * watchpoint trap can only occur in code which is reading/writing
    5.52 - * from user space. Such code must not hold kernel locks (since it
    5.53 - * can equally take a page fault), therefore it is safe to call
    5.54 - * force_sig_info even though that claims and releases locks.
    5.55 - * 
    5.56 - * Code in ./signal.c ensures that the debug control register
    5.57 - * is restored before we deliver any signal, and therefore that
    5.58 - * user code runs with the correct debug control register even though
    5.59 - * we clear it here.
    5.60 - *
    5.61 - * Being careful here means that we don't have to be as careful in a
    5.62 - * lot of more complicated places (task switching can be a bit lazy
    5.63 - * about restoring all the debug state, and ptrace doesn't have to
    5.64 - * find every occurrence of the TF bit that could be saved away even
    5.65 - * by user code)
    5.66 - */
    5.67  asmlinkage void do_debug(struct pt_regs * regs, long error_code)
    5.68  {
    5.69      unsigned int condition;
    5.70      struct task_struct *tsk = current;
    5.71 +    struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
    5.72  
    5.73      __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
    5.74  
    5.75      /* Mask out spurious debug traps due to lazy DR7 setting */
    5.76 -    if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
    5.77 -        if (!tsk->thread.debugreg[7])
    5.78 -            goto clear_dr7;
    5.79 +    if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
    5.80 +         (tsk->thread.debugreg[7] == 0) )
    5.81 +    {
    5.82 +        __asm__("movl %0,%%db7" : : "r" (0));
    5.83 +        return;
    5.84      }
    5.85  
    5.86 -    /* Save debug status register where ptrace can see it */
    5.87 +    if ( (regs->xcs & 3) == 0 )
    5.88 +    {
    5.89 +        /* Clear TF just for absolute sanity. */
    5.90 +        regs->eflags &= ~EF_TF;
    5.91 +        /*
    5.92 +         * Basically, we ignore watchpoints when they trigger in
    5.93 +         * the hypervisor. This may happen when a buffer is passed
    5.94 +         * to us which previously had a watchpoint set on it.
    5.95 +         * No need to bump EIP; the only faulting trap is an
    5.96 +         * instruction breakpoint, which can't happen to us.
    5.97 +         */
    5.98 +        return;
    5.99 +    }
   5.100 +
   5.101 +    /* Save debug status register where guest OS can peek at it */
   5.102      tsk->thread.debugreg[6] = condition;
   5.103  
   5.104 -    panic("trap up to OS here, pehaps\n");
   5.105 -
   5.106 -    /* Disable additional traps. They'll be re-enabled when
   5.107 -     * the signal is delivered.
   5.108 -     */
   5.109 - clear_dr7:
   5.110 -    __asm__("movl %0,%%db7"
   5.111 -            : /* no output */
   5.112 -            : "r" (0));
   5.113 +    gtb->flags = GTBF_TRAP_NOCODE;
   5.114 +    gtb->cs    = tsk->thread.traps[1].cs;
   5.115 +    gtb->eip   = tsk->thread.traps[1].address;
   5.116  }
   5.117  
   5.118  
   5.119 @@ -515,9 +524,9 @@ void __init trap_init(void)
   5.120      set_trap_gate(0,&divide_error);
   5.121      set_trap_gate(1,&debug);
   5.122      set_intr_gate(2,&nmi);
   5.123 -    set_system_gate(3,&int3);	/* int3-5 can be called from all */
   5.124 -    set_system_gate(4,&overflow);
   5.125 -    set_system_gate(5,&bounds);
   5.126 +    set_system_gate(3,&int3);     /* usable from all privilege levels */
   5.127 +    set_system_gate(4,&overflow); /* usable from all privilege levels */
   5.128 +    set_trap_gate(5,&bounds);
   5.129      set_trap_gate(6,&invalid_op);
   5.130      set_trap_gate(7,&device_not_available);
   5.131      set_trap_gate(8,&double_fault);
   5.132 @@ -533,27 +542,6 @@ void __init trap_init(void)
   5.133      set_trap_gate(18,&machine_check);
   5.134      set_trap_gate(19,&simd_coprocessor_error);
   5.135  
   5.136 -    /*
   5.137 -     * Cunning trick to allow arbitrary "INT n" handling.
   5.138 -     * 
   5.139 -     * 1. 3 <= N <= 5 is trivial, as these are intended to be explicit.
   5.140 -     * 
   5.141 -     * 2. All others, we set gate DPL == 0. Any use of "INT n" will thus
   5.142 -     *    cause a GPF with CS:EIP pointing at the faulting instruction.
   5.143 -     *    We can then peek at the instruction at check if it is of the
   5.144 -     *    form "0xCD <imm8>". If so, we fake out an exception to the
   5.145 -     *    guest OS. If the protected read page faults, we patch that up as
   5.146 -     *    a page fault to the guest OS.
   5.147 -     *    [NB. Of course we check the "soft DPL" to check that guest OS
   5.148 -     *     wants to handle a particular 'n'. If not, we pass the GPF up
   5.149 -     *     to the guest OS untouched.]
   5.150 -     * 
   5.151 -     * 3. For efficiency, we may want to allow direct traps by the guest
   5.152 -     *    OS for certain critical vectors (eg. 0x80 in Linux). These must
   5.153 -     *    therefore not be mapped by hardware interrupts, and so we'd need
   5.154 -     *    a static list of them, which we add to on demand.
   5.155 -     */
   5.156 -
   5.157      /* Only ring 1 can access monitor services. */
   5.158      _set_gate(idt_table+HYPERVISOR_CALL_VECTOR,15,1,&hypervisor_call);
   5.159  
   5.160 @@ -593,3 +581,69 @@ long do_fpu_taskswitch(void)
   5.161      stts();
   5.162      return 0;
   5.163  }
   5.164 +
   5.165 +
   5.166 +long do_set_debugreg(int reg, unsigned long value)
   5.167 +{
   5.168 +    int i;
   5.169 +
   5.170 +    switch ( reg )
   5.171 +    {
   5.172 +    case 0: 
   5.173 +        if ( value > (PAGE_OFFSET-4) ) return -EPERM;
   5.174 +        __asm__ ( "movl %0, %%db0" : : "r" (value) );
   5.175 +        break;
   5.176 +    case 1: 
   5.177 +        if ( value > (PAGE_OFFSET-4) ) return -EPERM;
   5.178 +        __asm__ ( "movl %0, %%db1" : : "r" (value) );
   5.179 +        break;
   5.180 +    case 2: 
   5.181 +        if ( value > (PAGE_OFFSET-4) ) return -EPERM;
   5.182 +        __asm__ ( "movl %0, %%db2" : : "r" (value) );
   5.183 +        break;
   5.184 +    case 3:
   5.185 +        if ( value > (PAGE_OFFSET-4) ) return -EPERM;
   5.186 +        __asm__ ( "movl %0, %%db3" : : "r" (value) );
   5.187 +        break;
   5.188 +    case 6:
   5.189 +        /*
   5.190 +         * DR6: Bits 4-11,16-31 reserved (set to 1).
   5.191 +         *      Bit 12 reserved (set to 0).
   5.192 +         */
   5.193 +        value &= 0xffffefff; /* reserved bits => 0 */
   5.194 +        value |= 0xffff0ff0; /* reserved bits => 1 */
   5.195 +        __asm__ ( "movl %0, %%db6" : : "r" (value) );
   5.196 +        break;
   5.197 +    case 7:
   5.198 +        /*
   5.199 +         * DR7: Bit 10 reserved (set to 1).
   5.200 +         *      Bits 11-12,14-15 reserved (set to 0).
   5.201 +         * Privileged bits:
   5.202 +         *      GD (bit 13): must be 0.
   5.203 +         *      R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
   5.204 +         *      LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
   5.205 +         */
   5.206 +        /* DR7 == 0 => debugging disabled for this domain. */
   5.207 +        if ( value != 0 )
   5.208 +        {
   5.209 +            value &= 0xffff27ff; /* reserved bits => 0 */
   5.210 +            value |= 0x00000400; /* reserved bits => 1 */
   5.211 +            if ( (value & (1<<13)) != 0 ) return -EPERM;
   5.212 +            for ( i = 0; i < 16; i += 2 )
   5.213 +                if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
   5.214 +        }
   5.215 +        __asm__ ( "movl %0, %%db7" : : "r" (value) );
   5.216 +        break;
   5.217 +    default:
   5.218 +        return -EINVAL;
   5.219 +    }
   5.220 +
   5.221 +    current->thread.debugreg[reg] = value;
   5.222 +    return 0;
   5.223 +}
   5.224 +
   5.225 +unsigned long do_get_debugreg(int reg)
   5.226 +{
   5.227 +    if ( (reg < 0) || (reg > 7) ) return -EINVAL;
   5.228 +    return current->thread.debugreg[reg];
   5.229 +}
     6.1 --- a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h	Thu Dec 05 17:16:53 2002 +0000
     6.2 +++ b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h	Tue Dec 10 14:45:04 2002 +0000
     6.3 @@ -40,6 +40,8 @@ typedef struct
     6.4  #define __HYPERVISOR_exit            8
     6.5  #define __HYPERVISOR_dom0_op         9
     6.6  #define __HYPERVISOR_network_op     10
     6.7 +#define __HYPERVISOR_set_debugreg   11
     6.8 +#define __HYPERVISOR_get_debugreg   12
     6.9  
    6.10  #define TRAP_INSTR "int $0x82"
    6.11  
     7.1 --- a/xenolinux-2.4.16-sparse/arch/xeno/kernel/process.c	Thu Dec 05 17:16:53 2002 +0000
     7.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/kernel/process.c	Tue Dec 10 14:45:04 2002 +0000
     7.3 @@ -187,6 +187,7 @@ void flush_thread(void)
     7.4      struct task_struct *tsk = current;
     7.5  
     7.6      memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
     7.7 +
     7.8      /*
     7.9       * Forget coprocessor state..
    7.10       */
    7.11 @@ -307,14 +308,6 @@ void dump_thread(struct pt_regs * regs, 
    7.12  }
    7.13  
    7.14  /*
    7.15 - * This special macro can be used to load a debugging register
    7.16 - */
    7.17 -#define loaddebug(thread,register) \
    7.18 -		__asm__("movl %0,%%db" #register  \
    7.19 -			: /* no output */ \
    7.20 -			:"r" (thread->debugreg[register]))
    7.21 -
    7.22 -/*
    7.23   *	switch_to(x,yn) should switch tasks from x to y.
    7.24   *
    7.25   * We fsave/fwait so that an exception goes off at the right time
    7.26 @@ -359,20 +352,19 @@ void __switch_to(struct task_struct *pre
    7.27      loadsegment(fs, next->fs);
    7.28      loadsegment(gs, next->gs);
    7.29  
    7.30 -#if 0
    7.31      /*
    7.32       * Now maybe reload the debug registers
    7.33       */
    7.34 -    if (next->debugreg[7]){
    7.35 -        loaddebug(next, 0);
    7.36 -        loaddebug(next, 1);
    7.37 -        loaddebug(next, 2);
    7.38 -        loaddebug(next, 3);
    7.39 +    if ( next->debugreg[7] != 0 )
    7.40 +    {
    7.41 +        HYPERVISOR_set_debugreg(0, next->debugreg[0]);
    7.42 +        HYPERVISOR_set_debugreg(1, next->debugreg[1]);
    7.43 +        HYPERVISOR_set_debugreg(2, next->debugreg[2]);
    7.44 +        HYPERVISOR_set_debugreg(3, next->debugreg[3]);
    7.45          /* no 4 and 5 */
    7.46 -        loaddebug(next, 6);
    7.47 -        loaddebug(next, 7);
    7.48 +        HYPERVISOR_set_debugreg(6, next->debugreg[6]);
    7.49 +        HYPERVISOR_set_debugreg(7, next->debugreg[7]);
    7.50      }
    7.51 -#endif
    7.52  }
    7.53  
    7.54  asmlinkage int sys_fork(struct pt_regs regs)
     8.1 --- a/xenolinux-2.4.16-sparse/arch/xeno/kernel/signal.c	Thu Dec 05 17:16:53 2002 +0000
     8.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/kernel/signal.c	Tue Dec 10 14:45:04 2002 +0000
     8.3 @@ -693,6 +693,14 @@ int do_signal(struct pt_regs *regs, sigs
     8.4  			}
     8.5  		}
     8.6  
     8.7 +                /* Reenable any watchpoints before delivering the
     8.8 +                 * signal to user space. The processor register will
     8.9 +                 * have been cleared if the watchpoint triggered
    8.10 +                 * inside the kernel.
    8.11 +                 */
    8.12 +                if ( current->thread.debugreg[7] != 0 )
    8.13 +                    HYPERVISOR_set_debugreg(7, current->thread.debugreg[7]);
    8.14 +
    8.15  		/* Whee!  Actually deliver the signal.  */
    8.16  		handle_signal(signr, ka, &info, oldset, regs);
    8.17  		return 1;
     9.1 --- a/xenolinux-2.4.16-sparse/arch/xeno/kernel/traps.c	Thu Dec 05 17:16:53 2002 +0000
     9.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/kernel/traps.c	Tue Dec 10 14:45:04 2002 +0000
     9.3 @@ -324,11 +324,60 @@ gp_in_kernel:
     9.4  
     9.5  asmlinkage void do_debug(struct pt_regs * regs, long error_code)
     9.6  {
     9.7 -    /*
     9.8 -     * We don't mess with breakpoints, so the only way this exception
     9.9 -     * type can occur is through single-step mode.
    9.10 +    unsigned int condition;
    9.11 +    struct task_struct *tsk = current;
    9.12 +    siginfo_t info;
    9.13 +
    9.14 +    condition = HYPERVISOR_get_debugreg(6);
    9.15 +
    9.16 +    /* Mask out spurious debug traps due to lazy DR7 setting */
    9.17 +    if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
    9.18 +        if (!tsk->thread.debugreg[7])
    9.19 +            goto clear_dr7;
    9.20 +    }
    9.21 +
    9.22 +    /* Save debug status register where ptrace can see it */
    9.23 +    tsk->thread.debugreg[6] = condition;
    9.24 +
    9.25 +    /* Mask out spurious TF errors due to lazy TF clearing */
    9.26 +    if (condition & DR_STEP) {
    9.27 +        /*
    9.28 +         * The TF error should be masked out only if the current
    9.29 +         * process is not traced and if the TRAP flag has been set
    9.30 +         * previously by a tracing process (condition detected by
    9.31 +         * the PT_DTRACE flag); remember that the i386 TRAP flag
    9.32 +         * can be modified by the process itself in user mode,
    9.33 +         * allowing programs to debug themselves without the ptrace()
    9.34 +         * interface.
    9.35 +         */
    9.36 +        if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
    9.37 +            goto clear_TF;
    9.38 +    }
    9.39 +
    9.40 +    /* Ok, finally something we can handle */
    9.41 +    tsk->thread.trap_no = 1;
    9.42 +    tsk->thread.error_code = error_code;
    9.43 +    info.si_signo = SIGTRAP;
    9.44 +    info.si_errno = 0;
    9.45 +    info.si_code = TRAP_BRKPT;
    9.46 +        
    9.47 +    /* If this is a kernel mode trap, save the user PC on entry to 
    9.48 +     * the kernel, that's what the debugger can make sense of.
    9.49       */
    9.50 +    info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip : 
    9.51 +                                            (void *)regs->eip;
    9.52 +    force_sig_info(SIGTRAP, &info, tsk);
    9.53 +
    9.54 +    /* Disable additional traps. They'll be re-enabled when
    9.55 +     * the signal is delivered.
    9.56 +     */
    9.57 + clear_dr7:
    9.58 +    HYPERVISOR_set_debugreg(7, 0);
    9.59 +    return;
    9.60 +
    9.61 + clear_TF:
    9.62      regs->eflags &= ~TF_MASK;
    9.63 +    return;
    9.64  }
    9.65  
    9.66  
    10.1 --- a/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h	Thu Dec 05 17:16:53 2002 +0000
    10.2 +++ b/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h	Tue Dec 10 14:45:04 2002 +0000
    10.3 @@ -163,4 +163,26 @@ static inline int HYPERVISOR_network_op(
    10.4      return ret;
    10.5  }
    10.6  
    10.7 +static inline int HYPERVISOR_set_debugreg(int reg, unsigned long value)
    10.8 +{
    10.9 +    int ret;
   10.10 +    __asm__ __volatile__ (
   10.11 +        TRAP_INSTR
   10.12 +        : "=a" (ret) : "0" (__HYPERVISOR_set_debugreg),
   10.13 +        "b" (reg), "c" (value) );
   10.14 +
   10.15 +    return ret;
   10.16 +}
   10.17 +
   10.18 +static inline unsigned long HYPERVISOR_get_debugreg(int reg)
   10.19 +{
   10.20 +    unsigned long ret;
   10.21 +    __asm__ __volatile__ (
   10.22 +        TRAP_INSTR
   10.23 +        : "=a" (ret) : "0" (__HYPERVISOR_get_debugreg),
   10.24 +        "b" (reg) );
   10.25 +
   10.26 +    return ret;
   10.27 +}
   10.28 +
   10.29  #endif /* __HYPERVISOR_H__ */