ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / um / include / sysdep-i386 / frame_user.h
1 /* 
2  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3  * Licensed under the GPL
4  */
5
6 #ifndef __FRAME_USER_I386_H
7 #define __FRAME_USER_I386_H
8
9 #include <asm/page.h>
10 #include "sysdep/frame.h"
11
12 /* This stuff is to calculate the size of the fp state struct at runtime
13  * because it has changed between 2.2 and 2.4 and it would be good for a
14  * UML compiled on one to work on the other.
15  * So, setup_arch_frame_raw fills in the arch struct with the raw data, which
16  * just contains the address of the end of the sigcontext.  This is invoked
17  * from the signal handler.
18  * setup_arch_frame uses that data to figure out what 
19  * arch_frame_data.fpstate_size should be.  It really has no idea, since it's
20  * not allowed to do sizeof(struct fpstate) but it's safe to consider that it's
21  * everything from the end of the sigcontext up to the top of the stack.  So,
22  * it masks off the page number to get the offset within the page and subtracts
23  * that from the page size, and that's how big the fpstate struct will be
24  * considered to be.
25  */
26
27 static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data,
28                                         void *end, unsigned long srp)
29 {
30         unsigned long sr = *((unsigned long *) srp);
31
32         data->fp_start = (unsigned long) end;
33         if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK))
34                 data->sr = sr;
35         else data->sr = 0;
36 }
37
38 static inline void setup_arch_frame(struct arch_frame_data_raw *in, 
39                                     struct arch_frame_data *out)
40 {
41         unsigned long fpstate_start = in->fp_start;
42
43         if(in->sr == 0){
44                 fpstate_start &= ~PAGE_MASK;
45                 out->fpstate_size = PAGE_SIZE - fpstate_start;
46         }
47         else {
48                 out->fpstate_size = in->sr - fpstate_start;
49         }
50 }
51
52 /* This figures out where on the stack the SA_RESTORER function address
53  * is stored.  For i386, it's the signal handler return address, so it's
54  * located next to the frame pointer.
55  * This is inlined, so __builtin_frame_address(0) is correct.  Otherwise,
56  * it would have to be __builtin_frame_address(1).
57  */
58
59 static inline unsigned long frame_restorer(void)
60 {
61         unsigned long *fp;
62
63         fp = __builtin_frame_address(0);
64         return((unsigned long) (fp + 1));
65 }
66
67 /* Similarly, this returns the value of sp when the handler was first
68  * entered.  This is used to calculate the proper sp when delivering
69  * signals.
70  */
71
72 static inline unsigned long frame_sp(void)
73 {
74         unsigned long *fp;
75
76         fp = __builtin_frame_address(0);
77         return((unsigned long) (fp + 1));
78 }
79
80 #endif
81
82 /*
83  * Overrides for Emacs so that we follow Linus's tabbing style.
84  * Emacs will notice this stuff at the end of the file and automatically
85  * adjust the settings for this buffer only.  This must remain at the end
86  * of the file.
87  * ---------------------------------------------------------------------------
88  * Local variables:
89  * c-file-style: "linux"
90  * End:
91  */