Browse Source

Fix up interrupt handling.

This gets us much further in interrupt handling, kills the unused
ds, es, fs, gs 16-bit references once and for all, and gets us
to the next set of failures

It's not perfect, but it's way better.

Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Ronald G. Minnich 9 years ago
parent
commit
6ab2e16c9f
4 changed files with 72 additions and 58 deletions
  1. 7 4
      amd64/include/ureg.h
  2. 64 39
      sys/src/9/k10/l64idt.S
  3. 1 3
      sys/src/9/k10/syscall.c
  4. 0 12
      sys/src/9/k10/trap.c

+ 7 - 4
amd64/include/ureg.h

@@ -24,10 +24,13 @@ struct Ureg {
 	uint64_t	r14;
 	uint64_t	r15;
 
-	uint16_t	ds;
-	uint16_t	es;
-	uint16_t	fs;
-	uint16_t	gs;
+  // these are pointless and I don't want to waste a second on them.
+  // I'm sure it will break something but let's see.
+  // Not pushing them simplifies the interrupt handler a lot.
+  //	uint16_t	ds;
+  //	uint16_t	es;
+  //	uint16_t	fs;
+  //	uint16_t	gs;
 
 	uint64_t	type;
 	uint64_t	error;				/* error code (or zero) */

+ 64 - 39
sys/src/9/k10/l64idt.S

@@ -5,42 +5,74 @@
 
 .code64
 
-// _intrp and _intre make the stack look the same to the C code and intrcommon. 
+	/* Interrupts.  * Let's just talk about hardware
+	* interrupts. What has to happen is that we save enough state to
+	* return to where we were, and that's all we do. Hardware needs a stack,
+	* so it pushes SS and %rsp. Hardware has to
+	* clear If, which means we have to save the flags. We might be
+	* in user mode, so we need to change CS, so we need to save
+	* CS. Finally, we have to know where we were, so we need to save
+	* the RIP. And that's all get saved.
+	* Further, if you look at idthandlers below, you see a call to intrp.
+	* So on entry to intrp, the stack looks like this:
+	* EFLAGS 24(%rsp)
+	* CS	16(%rsp)
+	* EIP of interrupted code 8(%rsp)
+	* EIP from the call from the idthandlers. (%rsp)
+	* We, finally, need to push the error code and type.,
+	* then the registers. 
+	* Why the call from IDThandlers? So we can get a way to point
+	* to the type. We don't need to save 0(%rsp), we just need
+	* it to get the type. We can pop it and throw it away when
+	* needed.
+	* What does the C level function need?
+	* It needs a pointer to the Uregs, as defined in ureg.h
+	* The other problem: all the regs have to be saved, so
+	* Plan 9 code can see them all.
+	* Finally, if it's a nested interrupt, we need to know that
+	* so we don't swapgs at the wrong time.
+	* Finally, this is utterly different from how Plan 9 does it, because
+	* all args are on the stack in Plan 9. We need %rdi for the pointer.
+	* And, the final x86 mess: for some things, the error code pointer
+	* is on the stack. For others, it's not. To make the stacks
+	* look identical for the common code and exit we save %rax and line things up.
+	*/
+	
+// When we enter: 
+// registers are NOT saved. We need to save them all.
+// return PC is on the stat8(%rsp). It should be left there.
+// @ (%rsp) is the PC from the vector table. 
+// So indirecting on that will get us the interrupt #.
+// We need to get what the return PC is pointing to into %rdi.
+// We no longer need to make the stack look the same as in Plan 9
+// because the arg is in %rdi
 .globl _intrp
 _intrp:
-	PUSHQ	%rax				/* save AX */
-	MOVQ	8(%rsp), %rax			/* idthandlers(SB) PC */
+	pushq	%rax // bogus error code. Makes stack look like intre.
+	MOVQ	8(%rsp), %rax
 	JMP	_intrcommon
 
+// or intre, I guess %rax has an interrupt number. I'm a little unsure on this
+// part.
 .globl _intre
 _intre:
-	XCHGQ	%rax, (%rsp)
-_intrcommon:
-	//MOVBQZX	(%rax), %rAX
-	MOVL	%eax, %eax
+	// The error code has been pushed. How I love the x86.
 	XCHGQ	%rax, (%rsp)
 
-	SUBQ	$24, %rsp				/* R1[45], [DEFG]S */
-	CMPW	$SSEL(SiCS, SsTIGDT|SsRPL0), 48(%rsp) 	/* old CS */
+// At this point, %rax is at TOS and all is well.
+// If this is nested we need to not do a swapgs.
+_intrcommon:
+	MOVQ	(%rax), %rax
+	// restore the rax you saved earlier.
+	XCHGQ	%rax, 0(%rsp)
+	CMPW	$SSEL(SiCS, SsTIGDT|SsRPL0), 24(%rsp) 	/* old CS */
 	JE	_intrnested
 
-#if 0 // skip this stuff -- not needed?
-	MOVQ	RUSER, 0(SP)
-	MOVQ	RMACH, 8(SP)
-	MOVW	DS, 16(SP)
-	MOVW	ES, 18(SP)
-	MOVW	FS, 20(SP)
-	MOVW	GS, 22(SP)
-#endif
-
 	SWAPGS
-#if 0
-	// no longer used.
-	BYTE $0x65; MOVQ 0, RMACH		/* m-> (MOVQ GS:0x0, R15) */
-	MOVQ	16(RMACH), RUSER		/* up */
-#endif
 
 _intrnested:
+	PUSHQ	%r15
+	PUSHQ	%r14
 	PUSHQ	%r13
 	PUSHQ	%r12
 	PUSHQ	%r11
@@ -49,20 +81,17 @@ _intrnested:
 	PUSHQ	%r8
 	PUSHQ	%rBP
 	PUSHQ	%rDI
+	PUSHQ	%rdi
 	PUSHQ	%rSI
 	PUSHQ	%rDX
 	PUSHQ	%rCX
 	PUSHQ	%rbx
 	PUSHQ	%rax
 
-	MOVQ	%rsp, %rdi
-	PUSHQ	%rSP
+	MOVQ	%rsp, %rdi // it's ok, we saved %rdi.
 	CALL	_trap
-
 .globl _intrr
 _intrr:
-	POPQ	%rax
-
 	POPQ	%rax
 	POPQ	%rbx
 	POPQ	%rCX
@@ -76,23 +105,19 @@ _intrr:
 	POPQ	%r11
 	POPQ	%r12
 	POPQ	%r13
+	POPQ	%r14
+	POPQ	%r15
 
-	CMPW	$SSEL(SiCS, SsTIGDT|SsRPL0), 48(%rsp) 	/* old CS */
+	CMPW	$SSEL(SiCS, SsTIGDT|SsRPL0), 24(%rsp) 	/* old CS */
 	JE	_iretnested
 
 	SWAPGS
-	/*	per the architecture manual, moving 16 bits to FS can zero it. Bad ... 
-	 *	not restoring it gives back the bad segment selector bug
-	MOVW	22(SP), GS
-	MOVW	20(SP), FS
-	MOVW	18(SP), ES
-	MOVW	16(SP), DS
-	MOVQ	8(SP), RMACH
-	MOVQ	0(SP), RUSER
-	 */
 
 _iretnested:
-	ADDQ	$40, %rsp
+	// Throw away:
+	// The %rax you pushed (error code)
+	// EIP from the vector table.
+	ADDQ	$16, %rsp
 	retq
 
 .globl idthandlers

+ 1 - 3
sys/src/9/k10/syscall.c

@@ -63,9 +63,7 @@ noted(Ureg* cur, uintptr_t arg0)
 	 * Check the segment selectors are all valid.
 	 */
 	nur = &nf->ureg;
-	if(nur->cs != SSEL(SiUCS, SsRPL3) || nur->ss != SSEL(SiUDS, SsRPL3)
-	|| nur->ds != SSEL(SiUDS, SsRPL3) || nur->es != SSEL(SiUDS, SsRPL3)
-	|| nur->fs != SSEL(SiUDS, SsRPL3) || nur->gs != SSEL(SiUDS, SsRPL3)){
+	if(nur->cs != SSEL(SiUCS, SsRPL3) || nur->ss != SSEL(SiUDS, SsRPL3)) {
 		qunlock(&up->debug);
 		pprint("suicide: bad segment selector in noted\n");
 		pexit("Suicide", 0);

+ 0 - 12
sys/src/9/k10/trap.c

@@ -476,9 +476,6 @@ dumpgpr(Ureg* ureg)
 	iprint("r13\t%#16.16llux\n", ureg->r13);
 	iprint("r14\t%#16.16llux\n", ureg->r14);
 	iprint("r15\t%#16.16llux\n", ureg->r15);
-	iprint("ds  %#4.4ux   es  %#4.4ux   fs  %#4.4ux   gs  %#4.4ux\n",
-		ureg->ds, ureg->es, ureg->fs, ureg->gs);
-	iprint("ureg fs\t%#ux\n", *(unsigned int *)&ureg->ds);
 	iprint("type\t%#llux\n", ureg->type);
 	iprint("error\t%#llux\n", ureg->error);
 	iprint("pc\t%#llux\n", ureg->ip);
@@ -677,20 +674,11 @@ void
 setregisters(Ureg* ureg, char* pureg, char* uva, int n)
 {
 	uint64_t cs, flags, ss;
-	uint16_t ds, es, fs, gs;
 
 	ss = ureg->ss;
 	flags = ureg->flags;
 	cs = ureg->cs;
-	gs = ureg->cs;
-	fs = ureg->cs;
-	es = ureg->cs;
-	ds = ureg->cs;
 	memmove(pureg, uva, n);
-	ureg->ds = ds;
-	ureg->es = es;
-	ureg->fs = fs;
-	ureg->gs = gs;
 	ureg->cs = cs;
 	ureg->flags = (ureg->flags & 0x00ff) | (flags & 0xff00);
 	ureg->ss = ss;