summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2023-10-27 20:15:09 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-10-27 20:15:09 +0200
commitce113c4aa7acb5c228ad0bf5bdf8856bd968ffe0 (patch)
tree68a23a11a17907be5d2ea486b46b88cfacd06283
parent9854a7f9c393c16bf107118f82362bfb14d256ef (diff)
locore: Also factorize segment management on i386
and harmonize i386/x86_64. This btw fixes not using dx in 32-on-64's alltraps.
-rw-r--r--i386/i386/locore.S124
-rw-r--r--x86_64/locore.S44
2 files changed, 74 insertions, 94 deletions
diff --git a/i386/i386/locore.S b/i386/i386/locore.S
index 846f5567..be412af0 100644
--- a/i386/i386/locore.S
+++ b/i386/i386/locore.S
@@ -40,6 +40,44 @@
#include <i386/xen.h>
/*
+ * Note that we have to load the kernel segment registers even if this
+ * is a trap from the kernel, because the kernel uses user segment
+ * registers for copyin/copyout.
+ * (XXX Would it be smarter just to use fs or gs for that?)
+ */
+#define PUSH_SEGMENTS \
+ pushl %ds ;\
+ pushl %es ;\
+ pushl %fs ;\
+ pushl %gs
+
+#define POP_SEGMENTS \
+ popl %gs ;\
+ popl %fs ;\
+ popl %es ;\
+ popl %ds
+
+#define PUSH_SEGMENTS_ISR \
+ pushl %ds ;\
+ pushl %es ;\
+ pushl %fs ;\
+ pushl %gs
+
+#define POP_SEGMENTS_ISR \
+ popl %gs ;\
+ popl %fs ;\
+ popl %es ;\
+ popl %ds
+
+#define SET_KERNEL_SEGMENTS(reg) \
+ mov %ss,reg /* switch to kernel segments */ ;\
+ mov reg,%ds /* (same as kernel stack segment) */ ;\
+ mov reg,%es ;\
+ mov reg,%fs ;\
+ mov $(PERCPU_DS),reg ;\
+ mov reg,%gs
+
+/*
* Fault recovery.
*/
#define RECOVER_TABLE_START \
@@ -456,22 +494,8 @@ ENTRY(t_page_fault)
ENTRY(alltraps)
pusha /* save the general registers */
trap_push_segs:
- pushl %ds /* and the segment registers */
- pushl %es
- pushl %fs
- pushl %gs
-
- /* Note that we have to load the segment registers
- even if this is a trap from the kernel,
- because the kernel uses user segment registers for copyin/copyout.
- (XXX Would it be smarter just to use fs or gs for that?) */
- mov %ss,%ax /* switch to kernel data segment */
- mov %ax,%ds /* (same as kernel stack segment) */
- mov %ax,%es
- mov %ax,%fs
- mov $(PERCPU_DS),%ax
- movw %ax,%gs
-
+ PUSH_SEGMENTS /* and the segment registers */
+ SET_KERNEL_SEGMENTS(%ax) /* switch to kernel data segment */
trap_set_segs:
cld /* clear direction flag */
testl $(EFL_VM),R_EFLAGS(%esp) /* in V86 mode? */
@@ -680,16 +704,8 @@ ENTRY(all_intrs)
cmpl %ss:CX(EXT(int_stack_base),%ecx),%edx
je int_from_intstack /* if not: */
- pushl %ds /* save segment registers */
- pushl %es
- pushl %fs
- pushl %gs
- mov %ss,%dx /* switch to kernel segments */
- mov %dx,%ds
- mov %dx,%es
- mov %dx,%fs
- mov $(PERCPU_DS),%dx
- movw %dx,%gs
+ PUSH_SEGMENTS_ISR /* save segment registers */
+ SET_KERNEL_SEGMENTS(%dx) /* switch to kernel segments */
CPU_NUMBER(%edx)
@@ -737,10 +753,7 @@ LEXT(return_to_iret) /* to find the return from calling interrupt) */
cmpl $0,CX(EXT(need_ast),%edx)
jnz ast_from_interrupt /* take it if so */
1:
- pop %gs /* restore segment regs */
- pop %fs
- pop %es
- pop %ds
+ POP_SEGMENTS_ISR /* restore segment regs */
pop %edx
pop %ecx
pop %eax
@@ -777,27 +790,15 @@ stack_overflowed:
* ss
*/
ast_from_interrupt:
- pop %gs /* restore all registers ... */
- pop %fs
- pop %es
- pop %ds
+ POP_SEGMENTS_ISR /* restore all registers ... */
popl %edx
popl %ecx
popl %eax
pushl $0 /* zero code */
pushl $0 /* zero trap number */
pusha /* save general registers */
- push %ds /* save segment registers */
- push %es
- push %fs
- push %gs
- mov %ss,%dx /* switch to kernel segments */
- mov %dx,%ds
- mov %dx,%es
- mov %dx,%fs
- mov $(PERCPU_DS),%dx
- movw %dx,%gs
-
+ PUSH_SEGMENTS_ISR /* save segment registers */
+ SET_KERNEL_SEGMENTS(%dx) /* switch to kernel segments */
CPU_NUMBER(%edx)
TIME_TRAP_UENTRY
@@ -924,19 +925,13 @@ kdb_from_iret_i: /* on interrupt stack */
pushl $0 /* zero error code */
pushl $0 /* zero trap number */
pusha /* save general registers */
- push %ds /* save segment registers */
- push %es
- push %fs
- push %gs
+ PUSH_SEGMENTS /* save segment registers */
pushl %esp /* pass regs, */
pushl $0 /* code, */
pushl $-1 /* type to kdb */
call EXT(kdb_trap)
addl $12,%esp /* remove parameters */
- pop %gs /* restore segment registers */
- pop %fs
- pop %es
- pop %ds
+ POP_SEGMENTS /* restore segment registers */
popa /* restore general registers */
addl $8,%esp
iret
@@ -1006,19 +1001,13 @@ ttd_from_iret_i: /* on interrupt stack */
pushl $0 /* zero error code */
pushl $0 /* zero trap number */
pusha /* save general registers */
- push %ds /* save segment registers */
- push %es
- push %fs
- push %gs
+ PUSH_SEGMENTS_ISR /* save segment registers */
pushl %esp /* pass regs, */
pushl $0 /* code, */
pushl $-1 /* type to kdb */
call _kttd_trap
addl $12,%esp /* remove parameters */
- pop %gs /* restore segment registers */
- pop %fs
- pop %es
- pop %ds
+ POP_SEGMENTS_ISR /* restore segment registers */
popa /* restore general registers */
addl $8,%esp
iret
@@ -1046,17 +1035,8 @@ syscall_entry_2:
pushl $0 /* clear trap number slot */
pusha /* save the general registers */
- pushl %ds /* and the segment registers */
- pushl %es
- pushl %fs
- pushl %gs
-
- mov %ss,%dx /* switch to kernel data segment */
- mov %dx,%ds
- mov %dx,%es
- mov %dx,%fs
- mov $(PERCPU_DS),%dx
- movw %dx,%gs
+ PUSH_SEGMENTS /* and the segment registers */
+ SET_KERNEL_SEGMENTS(%dx) /* switch to kernel data segment */
/*
* Shuffle eflags,eip,cs into proper places
diff --git a/x86_64/locore.S b/x86_64/locore.S
index 3a829a73..ed10665b 100644
--- a/x86_64/locore.S
+++ b/x86_64/locore.S
@@ -135,15 +135,15 @@
#endif
#ifdef USER32
-#define SET_KERNEL_SEGMENTS \
- mov %ss,%dx /* switch to kernel segments */ ;\
- mov %dx,%ds ;\
- mov %dx,%es ;\
- mov %dx,%fs ;\
- mov $(PERCPU_DS),%dx ;\
- mov %dx,%gs
+#define SET_KERNEL_SEGMENTS(reg) \
+ mov %ss,reg /* switch to kernel segments */ ;\
+ mov reg,%ds /* (same as kernel stack segment) */ ;\
+ mov reg,%es ;\
+ mov reg,%fs ;\
+ mov $(PERCPU_DS),reg ;\
+ mov reg,%gs
#else
-#define SET_KERNEL_SEGMENTS
+#define SET_KERNEL_SEGMENTS(reg)
#endif
/*
@@ -582,8 +582,8 @@ ENTRY(t_page_fault)
ENTRY(alltraps)
pusha /* save the general registers */
trap_push_segs:
- PUSH_SEGMENTS(%rax)
- SET_KERNEL_SEGMENTS
+ PUSH_SEGMENTS(%rax) /* and the segment registers */
+ SET_KERNEL_SEGMENTS(%rax) /* switch to kernel data segment */
trap_set_segs:
cld /* clear direction flag */
#ifdef USER32
@@ -800,14 +800,14 @@ ENTRY(all_intrs)
pushq %r11
cld /* clear direction flag */
- PUSH_SEGMENTS_ISR(%rdx)
+ PUSH_SEGMENTS_ISR(%rdx) /* save segment registers */
movq %rsp,%rdx /* on an interrupt stack? */
and $(~(INTSTACK_SIZE-1)),%rdx
cmpq %ss:EXT(int_stack_base),%rdx
je int_from_intstack /* if not: */
- SET_KERNEL_SEGMENTS
+ SET_KERNEL_SEGMENTS(%rdx) /* switch to kernel segments */
CPU_NUMBER(%edx)
@@ -857,7 +857,7 @@ LEXT(return_to_iret) /* to find the return from calling interrupt) */
cmpq $0,CX(EXT(need_ast),%rdx)
jnz ast_from_interrupt /* take it if so */
1:
- POP_SEGMENTS_ISR(%rdx)
+ POP_SEGMENTS_ISR(%rdx) /* restore segment regs */
pop %r11
pop %r10
pop %r9
@@ -908,7 +908,7 @@ stack_overflowed:
* ss
*/
ast_from_interrupt:
- POP_SEGMENTS_ISR(%rdx)
+ POP_SEGMENTS_ISR(%rdx) /* restore all registers ... */
popq %r11
popq %r10
popq %r9
@@ -921,8 +921,8 @@ ast_from_interrupt:
pushq $0 /* zero code */
pushq $0 /* zero trap number */
pusha /* save general registers */
- PUSH_SEGMENTS_ISR(%rdx)
- SET_KERNEL_SEGMENTS
+ PUSH_SEGMENTS_ISR(%rdx) /* save segment registers */
+ SET_KERNEL_SEGMENTS(%rdx) /* switch to kernel segments */
CPU_NUMBER(%edx)
TIME_TRAP_UENTRY
@@ -1040,12 +1040,12 @@ kdb_from_iret_i: /* on interrupt stack */
pushq $0 /* zero error code */
pushq $0 /* zero trap number */
pusha /* save general registers */
- PUSH_SEGMENTS(%rdx)
+ PUSH_SEGMENTS(%rdx) /* save segment registers */
movq %rsp,%rdx /* pass regs, */
movq $0,%rsi /* code, */
movq $-1,%rdi /* type to kdb */
call EXT(kdb_trap)
- POP_SEGMENTS(%rdx)
+ POP_SEGMENTS(%rdx) /* restore segment registers */
popa /* restore general registers */
addq $16,%rsp
@@ -1120,13 +1120,13 @@ ttd_from_iret_i: /* on interrupt stack */
pushq $0 /* zero error code */
pushq $0 /* zero trap number */
pusha /* save general registers */
- PUSH_SEGMENTS_ISR(%rdx)
+ PUSH_SEGMENTS_ISR(%rdx) /* save segment registers */
ud2 // TEST it
movq %rsp,%rdx /* pass regs, */
movq $0,%rsi /* code, */
movq $-1,%rdi /* type to kdb */
call _kttd_trap
- POP_SEGMENTS_ISR(%rdx)
+ POP_SEGMENTS_ISR(%rdx) /* restore segment registers */
popa /* restore general registers */
addq $16,%rsp
@@ -1159,8 +1159,8 @@ syscall_entry_2:
pushq $0 /* clear trap number slot */
pusha /* save the general registers */
- PUSH_SEGMENTS(%rdx)
- SET_KERNEL_SEGMENTS
+ PUSH_SEGMENTS(%rdx) /* and the segment registers */
+ SET_KERNEL_SEGMENTS(%rdx) /* switch to kernel data segment */
/*
* Shuffle eflags,eip,cs into proper places