Xen Test Framework
asm.S
Go to the documentation of this file.
1 #include <xtf/asm_macros.h>
2 #include <xtf/extable.h>
3 #include <arch/segment.h>
4 
5  .section .text.user, "ax", @progbits
6 
7 .macro GEN_ABS_STUB seg load_seg
8 
9 ENTRY(stub_\seg\()_abs) /* exinfo_t stub_\seg_abs(unsigned long addr) */
10 #ifdef __i386__
11  /*
12  * Switch segment if necessary. The old segment is preserved on the
13  * stack for the duration of the test.
14  */
15  .local stack_adj
16  stack_adj = 0
17 
18  .if \load_seg
19  .ifeqs "\seg", "none"
20  push %ds
21  push $(GDTE_AVAIL1 << 3 | 3)
22  pop %ds
23  .else
24  push %\seg
25  push $(GDTE_AVAIL1 << 3 | 3)
26  pop %\seg
27  .endif
28  stack_adj = 1
29  .endif
30 #endif
31 
32  /* No exception if we don't fault. Also reused by the 64bit case. */
33  xor %eax, %eax
34 
35  /* The bottom bit of 'addr' encodes FEP. */
36 #ifdef __i386__
37  testb $1, (1 + stack_adj)*4(%esp)
38 #else
39  testb $1, %dil
40 #endif
41  jz 1f
42 
43  _ASM_XEN_FEP
44  .ifeqs "\seg", "none"
45 #ifdef __i386__
46 1: movb $0, 0xc0000000
47 #else
48 1: movabsb %al, 0x8000000040000000
49 #endif
50  .else
51 #ifdef __i386__
52 1: movb $0, %\seg:0xc0000000
53 #else
54 1: movabsb %al, %\seg:0x8000000040000000
55 #endif
56  .endif
57 
58 2:
59 #ifdef __i386__
60  /* Restore the old segment if necessary. */
61  .if \load_seg
62  .ifeqs "\seg", "none"
63  pop %ds
64  .else
65  pop %\seg
66  .endif
67  .endif
68 #endif
69 
70  ret
71 
72  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
73 ENDFUNC(stub_\seg\()_abs)
74 .endm
75 
76 .macro GEN_REG_STUB seg reg load_seg preserve_reg
77 
78 ENTRY(stub_\seg\()_\reg) /* exinfo_t stub_\seg_\reg(unsigned long addr) */
79 
80 #ifdef __i386__
81  /*
82  * Switch segment if necessary. The old segment is preserved on the
83  * stack for the duration of the test.
84  */
85  .local stack_adj
86  stack_adj = 0
87 
88  .if \load_seg
89  .ifeqs "\seg", "none"
90  push %ds
91  push $(GDTE_AVAIL1 << 3 | 3)
92  pop %ds
93  .else
94  push %\seg
95  push $(GDTE_AVAIL1 << 3 | 3)
96  pop %\seg
97  .endif
98  stack_adj = 1
99  .endif
100 #endif
101 
102  /* Preserve the subject register if necessary. */
103  .if \preserve_reg
104  mov %\reg, %_ASM_CX
105  .endif
106 
107  /* Move 'addr' into \reg */
108 #ifdef __i386__
109  mov (1 + stack_adj)*4(%esp), %\reg
110 #else
111  mov %rdi, %\reg
112 #endif
113 
114  /* The bottom bit of 'addr' encodes FEP. */
115  test $1, %\reg
116  jz 1f
117 
118  _ASM_XEN_FEP
119  .ifeqs "\seg", "none"
120 1: movb $0, (%\reg)
121  .else
122 1: movb $0, %\seg:(%\reg)
123  .endif
124 
125  /* No exception if we didn't fault. */
126  xor %eax, %eax
127 2:
128  /* Restore the register if necessary. */
129  .if \preserve_reg
130  mov %_ASM_CX, %\reg
131  .endif
132 
133 #ifdef __i386__
134  /* Restore the old segment if necessary. */
135  .if \load_seg
136  .ifeqs "\seg", "none"
137  pop %ds
138  .else
139  pop %\seg
140  .endif
141  .endif
142 #endif
143 
144  ret
145 
146  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_eax)
147 ENDFUNC(stub_\seg\()_\reg)
148 .endm
149 
150 /*
151  * Instantiate `GEN_ABS_STUB foreach segment` and `GEN_REG_STUB foreach
152  * segment, foreach register`, calculaing whether the segment needs loading
153  * (implicit %ds, explicit %{e,d,f,g}s), and whether the register needs
154  * preserving (depends on the calling ABI).
155  */
156 .local seg_mask, seg_idx, reg_mask, reg_idx
157 #ifdef __i386__
158  seg_mask = 0b1100111
159 #else
160  seg_mask = 0
161 #endif
162  seg_idx = 6
163 
164 .irp seg, none, es, cs, ss, ds, fs, gs
165 
166  GEN_ABS_STUB \seg, (seg_mask & (1 << seg_idx))
167 
168 #ifdef __i386__
169  reg_mask = 0b00011111
170  reg_idx = 7
171  .irp reg, eax, ecx, edx, ebx, esp, ebp, esi, edi
172 #else
173  reg_mask = 0b0001110000001111
174  reg_idx = 15
175  .irp reg, rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15
176 #endif
177 
178  GEN_REG_STUB \seg, \reg, (seg_mask & (1 << seg_idx)), (reg_mask & (1 << reg_idx))
179  reg_idx = reg_idx - 1
180 
181  .endr
182  seg_idx = seg_idx - 1
183 
184 .endr
185 
186 /*
187  * Local variables:
188  * tab-width: 8
189  * indent-tabs-mode: nil
190  * End:
191  */