summaryrefslogtreecommitdiff
path: root/trapasm.S
blob: fc71336173de39ca664d91c617213c062bc87ead (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "param.h"
#include "x86.h"	
#include "mmu.h"

# the offset of cs in trapframe (i.e., tf->cs - tf)
#define CSOFF  144
	
# vectors.S sends all traps here.
.globl alltraps
alltraps:
  # Build trap frame.
  push %r15
  push %r14
  push %r13
  push %r12
  push %r11
  push %r10
  push %r9
  push %r8
  push %rdi
  push %rsi
  push %rbp
  push %rdx
  push %rcx
  push %rbx
  push %rax

  cmpw $KCSEG, CSOFF(%rsp)   # compare to saved cs
  jz 1f 
  swapgs
  
1:mov  %rsp, %rdi  # frame in arg1
  call trap

# Return falls through to trapret...
.globl trapret
trapret:
  cli
  cmpw $KCSEG, CSOFF(%rsp)  # compare to saved cs
  jz 1f
  swapgs

1:pop %rax
  pop %rbx
  pop %rcx
  pop %rdx
  pop %rbp
  pop %rsi
  pop %rdi
  pop %r8
  pop %r9
  pop %r10
  pop %r11
  pop %r12
  pop %r13
  pop %r14
  pop %r15

  add $16, %rsp  # discard trapnum and errorcode
  iretq
#PAGEBREAK!

# syscall_entry jumps here after syscall instruction
.globl sysentry
sysentry:  # Build trap frame.
  // load kernel stack address
  swapgs
  movq  %rax, %gs:0  // save %rax in syscallno of cpu entry
  movq  %rsp, %gs:8  // user sp
  movq  %gs:16, %rax  // proc entry
  
  movq  %ss:0(%rax), %rax // load kstack from proc
  addq  $(KSTACKSIZE), %rax

  movq  %rax, %rsp
  movq  %gs:0, %rax  // restore rax

  // push usp to make a valid trapframe
  push $(UDSEG|0x3)
  push %gs:8
  // safe eflags and eip
  push %r11
  push $(UCSEG|0x3)
  push %rcx
  // push errno and trapno to make stack look like a trap
  push $0
  push $64

  // push values on kernel stack
  push %r15
  push %r14
  push %r13
  push %r12
  push %r11
  push %r10
  push %r9
  push %r8
  push %rdi
  push %rsi
  push %rbp
  push %rdx
  push %rcx
  push %rbx
  push %rax

  mov  %rsp, %rdi  # frame in arg1

  call trap
#PAGEBREAK!

# Return falls through to trapret...
.globl sysexit
sysexit:
  # to make sure we don't get any interrupts on the user stack while in
  # supervisor mode.  insufficient?  (see vunerability reports for sysret)
  cli
  
  pop %rax
  pop %rbx
  pop %rcx
  pop %rdx
  pop %rbp
  pop %rsi
  pop %rdi
  pop %r8
  pop %r9
  pop %r10
  pop %r11
  pop %r12
  pop %r13
  pop %r14
  pop %r15

  add $(5*8), %rsp  # discard trapnum, errorcode, rip, cs and rflags
  mov (%rsp),%rsp  # switch to the user stack
  # there are two more values on the stack, but we don't care about them	
  swapgs	

  sysretq