|
|
1.1 root 1: /* (lgl-
2: * COHERENT Version 4.0
3: * Copyright (c) 1982, 1992.
4: * An unpublished work by Mark Williams Company, Chicago.
5: * All rights reserved.
6: -lgl) */
7:
8: #include <common/_gregset.h>
9: #include <kernel/systab.h>
10:
11: #include <sys/coherent.h>
12: #include <sys/errno.h>
13: #include <sys/proc.h>
14: #include <sys/seg.h>
15: #include <signal.h>
16:
17: /* opcodes recognized, and partially emulated, in gp fault handler */
18: #define READ_CR0 1
19: #define WRITE_CR0 2
20: #define READ_CR2 3
21: #define READ_CR3 4
22: #define WRITE_CR3 5
23: #define HALT 6
24: #define IRET 7
25: #define READ_DR0 8
26: #define READ_DR1 9
27: #define READ_DR2 10
28: #define READ_DR3 11
29: #define READ_DR6 12
30: #define READ_DR7 13
31: #define WRITE_DR0 14
32: #define WRITE_DR1 15
33: #define WRITE_DR2 16
34: #define WRITE_DR3 17
35: #define WRITE_DR6 18
36: #define WRITE_DR7 19
37:
38: #define ENTER_OP 0xC8 /* Opcode for 'enter' instruction. */
39: #define IRET_RETRY_LIM 10
40: #define RESUME_FLAG 0x10000 /* RF bit in PSW */
41: #define TRAP_FLAG 0x00100 /* TF bit in PSW */
42:
43: extern unsigned char selkcopy();
44: extern unsigned int DR0,DR1,DR2,DR3,DR7;
45: static int trap_op();
46:
47:
48: /*
49: * Global symbols from kernel text.
50: */
51:
52: extern unsigned int _Idle;
53: extern unsigned int __xtrap_break__;
54: extern unsigned int __xtrap_off__;
55: extern unsigned int __xtrap_on__;
56: extern unsigned int sig32;
57: extern unsigned int syc32;
58:
59: /*
60: * iret_flt is set when first bad iret is detected.
61: */
62: static int iret_flt;
63:
64: /*
65: * Trap handler.
66: * The arguments are the registers,
67: * saved on the stack by machine code. This call
68: * is different from most C calls in that the registers
69: * get copied back; if you change a "trap" parameter then
70: * the machine register will be altered when the trap is
71: * dismissed.
72: *
73: * Argument "trapno" is the return eip for the code calling tsave().
74: */
75:
76: void
77: trap (regset)
78: gregset_t regset;
79: {
80: register struct systab *stp;
81: register int sigcode;
82: extern int trapcode;
83: extern *mmdata[], mminit;
84: cseg_t *pp;
85: register SEG *segp;
86: int splo, datahi;
87: unsigned int txtlo, txthi;
88: unsigned int cr2 = 0;
89: unsigned int cpl = regset._i386._cs & SEG_PL;
90:
91: if (regset._i386._err == SINMI) {
92: printf ("Parity error\n");
93: curr_register_dump (& regset);
94: #if 0
95: panic("...");
96: #else
97: return;
98: #endif
99: }
100:
101: /*
102: * Expect this to never happen!
103: */
104: if (SELF->p_flags & PFKERN) {
105: panic ("pid%d: kernel process trap: err=%x, ip=%x ax=%d",
106: SELF->p_pid, regset._i386._err, regset._i386._eip,
107: regset._i386._eax);
108: }
109:
110: T_HAL (0x4000, printf ("T%d ", regset._i386._err));
111: sigcode = 0;
112:
113: #if 0
114: u.u_regl = & regset; /* hook in register set for consave/conrest */
115: #endif
116:
117: switch (regset._i386._err) {
118: case SIOSYS:
119: /*
120: * 286 System call.
121: */
122: sigcode = oldsys (& regset);
123: break;
124:
125: case SISYS: {
126: long args [MSACOUNT];
127: unsigned callnum;
128:
129: /*
130: * 386 System call.
131: */
132: u.u_error = 0;
133: callnum = regset._i386._eax;
134:
135: T_PIGGY (4, printf ("{%d", callnum));
136:
137: if (callnum < NMICALL)
138: stp = sysitab + callnum;
139: else if (callnum == COHCALL)
140: stp = & cohcall;
141: else if ((callnum & 0xFF) == 0x28 &&
142: (callnum >> 8) <= H28CALL)
143: stp = h28itab + (callnum >> 8) - 1;
144: else {
145: sigcode = SIGSYS;
146: goto trapend;
147: }
148:
149: ukcopy (regset._i386._uesp + sizeof (long), args,
150: stp->s_nargs * sizeof (long));
151:
152: if (u.u_error) {
153: sigcode = SIGSYS;
154: goto trapend;
155: }
156:
157: /*
158: * NIGEL: This is sleazy and stupid, and must go ASAP. We
159: * must learn to initialize structures properly.
160: */
161:
162: #if 0
163: u.u_io.io_seg = IOUSR;
164: #endif
165:
166: if (envsave (& u.u_sigenv)) {
167: u.u_error = EINTR;
168: } else {
169: regset._i386._eax = __DOSYSCALL (stp->s_nargs,
170: stp->s_func, args,
171: & regset);
172: regset._i386._edx = u.u_rval2;
173: }
174:
175: if (u.u_error) {
176: regset._i386._eax = u.u_error;
177: regset._i386._eflags |= MFCBIT;
178: } else /* clear carry flag in return efl */
179: regset._i386._eflags &= ~ MFCBIT;
180:
181: T_PIGGY (0x04, printf ("=%x}", regset._i386._eax));
182: break;
183: } /* end block */
184:
185: /*
186: * Trap.
187: */
188: case SIDIV:
189: #ifdef TRACER
190: printf ("Integer divide by zero");
191: curr_register_dump (& regset);
192: #endif
193: sigcode = SIGFPE;
194: break;
195:
196: case SISST:
197: sigcode = SIGTRAP;
198: break;
199:
200: case SIBPT:
201: sigcode = SIGTRAP;
202: break;
203:
204: case SIOVF:
205: sigcode = SIGEMT;
206: break;
207:
208: case SIBND:
209: /*
210: * Bound
211: */
212: sigcode = SIGIOT;
213: break;
214:
215: case SIOP:
216: /*
217: * Invalid opcode
218: */
219: if (cpl < 2) {
220: int * ip = (int *) regset._i386._eip;
221:
222: curr_register_dump (& regset);
223: printf ("(eip)=%x %x %x ", ip [0], ip [1], ip [2]);
224: panic ("Invalid Opcode");
225: }
226: sigcode = SIGILL;
227: break;
228:
229: #if 0
230: case SIXNP:
231: /*
232: * Processor extension not available
233: */
234: if (int11() & 2) /* NDP present */
235: ndpNewOwner();
236: else
237: sigcode = SIGFPE;
238: break;
239: #endif
240:
241: case SIDBL:
242: /*
243: * Double exception
244: */
245: panic ("double exception: cs=%x ip=%x", regset._i386._cs,
246: regset._i386._eip);
247: sigcode = SIGSEGV;
248: break;
249:
250: case SIXS:
251: /*
252: * Processor extension segment overrun
253: */
254: sigcode = SIGSEGV;
255: break;
256:
257: case SITS:
258: /*
259: * Invalid task state segment
260: */
261: panic ("invalid tss: cs=%x ip=%x", regset._i386._cs,
262: regset._i386._eip);
263: sigcode = SIGSEGV;
264: break;
265:
266: case SINP:
267: /*
268: * Segment not present
269: */
270: sigcode = SIGSEGV;
271: break;
272:
273: case SISS:
274: /*
275: * Stack segment overrun/not present
276: */
277: sigcode = SIGKILL;
278: break;
279:
280: default:
281: curr_register_dump (& regset);
282: panic("Fatal Trap");
283: }
284:
285: trapend:
286: /*
287: * Send user a signal.
288: * If not a breakpoint, do console register dump.
289: */
290: if (sigcode) {
291: if (sigcode != SIGTRAP) {
292: curr_register_dump (& regset);
293: printf("sigcode=#%d User Trap\n", sigcode);
294: }
295: sendsig (sigcode, SELF);
296: }
297: }
298:
299: /*
300: * trap_op()
301: *
302: * Look at the trapped instruction.
303: * If it's one of a select few, recognize and return the type.
304: * Otherwise, return 0.
305: *
306: * This could be fancier, but all we want to look for is:
307: * (for CRx and DRx, second operand is limited to %eax).
308: * 0F 20 C0 READ_CR0
309: * 0F 22 C0 WRITE_CR0
310: * 0F 20 D0 READ_CR2
311: * 0F 20 D8 READ_CR3
312: * 0F 22 D8 WRITE_CR3
313: * CF IRET
314: * F4 HALT
315: * 0F 23 C0 WRITE_DR0
316: * 0F 23 C8 WRITE_DR1
317: * 0F 23 D0 WRITE_DR2
318: * 0F 23 D8 WRITE_DR3
319: * 0F 23 F0 WRITE_DR6
320: * 0F 23 F8 WRITE_DR7
321: * 0F 21 C0 READ_DR0
322: * 0F 21 C8 READ_DR1
323: * 0F 21 D0 READ_DR2
324: * 0F 21 D8 READ_DR3
325: * 0F 21 F0 READ_DR6
326: * 0F 21 F8 READ_DR7
327: */
328: static int
329: trap_op(cs,eip)
330: unsigned int cs, eip;
331: {
332: int ret = 0;
333:
334: switch (ffbyte (eip, cs)) {
335: case 0x0F:
336: switch (ffbyte (eip + 1, cs)) {
337: case 0x20:
338: switch (ffbyte (eip + 2, cs)) {
339: case 0xC0:
340: ret = READ_CR0;
341: break;
342: case 0xD0:
343: ret = READ_CR2;
344: break;
345: case 0xD8:
346: ret = READ_CR3;
347: break;
348: }
349: break;
350: case 0x21:
351: switch (ffbyte (eip + 2, cs)) {
352: case 0xC0:
353: ret = READ_DR0;
354: break;
355: case 0xC8:
356: ret = READ_DR1;
357: break;
358: case 0xD0:
359: ret = READ_DR2;
360: break;
361: case 0xD8:
362: ret = READ_DR3;
363: break;
364: case 0xF0:
365: ret = READ_DR6;
366: break;
367: case 0xF8:
368: ret = READ_DR7;
369: break;
370: }
371: break;
372: case 0x22:
373: switch (ffbyte (eip + 2, cs)) {
374: case 0xC0:
375: ret = WRITE_CR0;
376: break;
377: case 0xD8:
378: ret = WRITE_CR3;
379: break;
380: }
381: break;
382: case 0x23:
383: switch (ffbyte (eip + 2, cs)) {
384: case 0xC0:
385: ret = WRITE_DR0;
386: break;
387: case 0xC8:
388: ret = WRITE_DR1;
389: break;
390: case 0xD0:
391: ret = WRITE_DR2;
392: break;
393: case 0xD8:
394: ret = WRITE_DR3;
395: break;
396: case 0xF0:
397: ret = WRITE_DR6;
398: break;
399: case 0xF8:
400: ret = WRITE_DR7;
401: break;
402: }
403: break;
404: }
405: break;
406: case 0xF4:
407: ret = HALT;
408: break;
409: case 0xCF:
410: ret = IRET;
411: break;
412: }
413: return ret;
414: }
415:
416: /*
417: * Kernel debugger.
418: *
419: * Runs in ring 0.
420: */
421:
422: void
423: __debug_ker__ (regset)
424: gregset_t regset;
425: {
426: unsigned int dr6 = read_dr6 ();
427: unsigned cpl = regset._i386._cs & SEG_PL;
428: int do_rdump = 1;
429:
430: if (dr6 & 0xf) { /* report breakpoint exception(s) */
431: printf("Breakpoint ");
432: if (dr6 & 1)
433: printf("DR0=%x ", DR0);
434: if (dr6 & 2)
435: printf("DR1=%x ", DR1);
436: if (dr6 & 4)
437: printf("DR2=%x ", DR2);
438: if (dr6 & 8)
439: printf("DR3=%x ", DR3);
440: printf("DR7=%x\n", DR7);
441: }
442:
443: if (dr6 & 0xf000) { /* report other debug exception(s) */
444: if (dr6 & 0x8000)
445: printf("Switch to debugged task\n");
446:
447: if (dr6 & 0x4000) {
448: /* Single Step */
449: switch (cpl) {
450: /*
451: * If user code trapped, send signal
452: * and suppress console register dump.
453: */
454: case DPL_1:
455: /*
456: * Turn off single-stepping when entering
457: * Ring 1.
458: */
459: if (regset._i386._eip == & syc32 ||
460: regset._i386._eip == & sig32) {
461: do_rdump = 0;
462: } else {
463: printf("\nefl=%x No single stepping the kernel.\n", regset._i386._eflags);
464: }
465: regset._i386._eflags &= ~TRAP_FLAG;
466: break;
467: case DPL_3:
468: do_rdump = 0;
469: T_HAL(0x20000, printf ("Kernel SSTEP eip=%x efl=%x ", regset._i386._eip,
470: regset._i386._eflags));
471: sendsig (SIGTRAP, SELF);
472: break;
473: }
474: }
475: if (dr6 & 0x2000) {
476: printf("ICE in use\n");
477: regset._i386._eip += 3;
478: }
479: }
480:
481: if (do_rdump)
482: curr_register_dump (& regset);
483:
484: write_dr6 (0);
485: regset._i386._eflags |= RESUME_FLAG;
486: return;
487: }
488:
489: /*
490: * General protection fault handler.
491: * Entered via a ring 0 gate.
492: */
493:
494: void
495: gpfault (regset)
496: gregset_t regset;
497: {
498: unsigned cpl = regset._i386._cs & SEG_PL;
499:
500: /*
501: * Switch on CPL of code that trapped.
502: */
503:
504: switch(cpl) {
505: case DPL_0:
506: /*
507: * Ring 0 should not gp fault.
508: */
509: curr_register_dump (& regset);
510: panic ("System GP Fault from Ring 0");
511: break;
512:
513: case DPL_1:
514: /*
515: * If ring 1 faulted on a valid request, emulate the
516: * request while running in ring 0.
517: */
518: switch (trap_op (regset._i386._cs, regset._i386._eip)) {
519: case READ_CR0:
520: regset._i386._eax = read_cr0 ();
521: regset._i386._eip += 3;
522: break;
523: #if 0
524: case WRITE_CR0:
525: if (eax & 4)
526: setfpe (0);
527: else
528: setfpe (1);
529: eip += 3;
530: break;
531: #endif
532: case READ_CR2:
533: regset._i386._eax = read_cr2 ();
534: regset._i386._eip += 3;
535: break;
536:
537: case READ_CR3:
538: regset._i386._eax = read_cr3 ();
539: regset._i386._eip += 3;
540: break;
541: #if 0
542: case WRITE_CR3:
543: mmuupdnR0 ();
544: eip += 3;
545: break;
546: #endif
547: case IRET:
548: /*
549: * Some CPU's wrongly generate GP faults on IRET
550: * from inner ring to ring 3.
551: * Fix is to retry the instruction a few times.
552: */
553: if (! iret_flt) {
554: iret_flt = 1;
555: printf ("CPU Bug: "
556: "Spurious GP Fault on Iret to Ring 3.\n");
557: }
558: break;
559:
560: case READ_DR0:
561: regset._i386._eax = read_dr0 ();
562: regset._i386._eip += 3;
563: break;
564:
565: case READ_DR1:
566: regset._i386._eax = read_dr1 ();
567: regset._i386._eip += 3;
568: break;
569:
570: case READ_DR2:
571: regset._i386._eax = read_dr2 ();
572: regset._i386._eip += 3;
573: break;
574:
575: case READ_DR3:
576: regset._i386._eax = read_dr3 ();
577: regset._i386._eip += 3;
578: break;
579:
580: case READ_DR6:
581: regset._i386._eax = read_dr6 ();
582: regset._i386._eip += 3;
583: break;
584:
585: case READ_DR7:
586: regset._i386._eax = read_dr7 ();
587: regset._i386._eip += 3;
588: break;
589:
590: case WRITE_DR0:
591: write_dr0 (regset._i386._eax);
592: regset._i386._eip += 3;
593: break;
594:
595: case WRITE_DR1:
596: write_dr1 (regset._i386._eax);
597: regset._i386._eip += 3;
598: break;
599:
600: case WRITE_DR2:
601: write_dr2 (regset._i386._eax);
602: regset._i386._eip += 3;
603: break;
604:
605: case WRITE_DR3:
606: write_dr3 (regset._i386._eax);
607: regset._i386._eip += 3;
608: break;
609:
610: case WRITE_DR6:
611: write_dr6 (regset._i386._eax);
612: regset._i386._eip += 3;
613: break;
614:
615: case WRITE_DR7:
616: write_dr7 (regset._i386._eax);
617: regset._i386._eip += 3;
618: break;
619:
620: case HALT:
621: halt ();
622: break;
623: #if 0
624: case WRITE_DR7:
625: /*
626: * Expect breakpoint info in globals DR0-3,DR7.
627: */
628: printf("Setting DR0=%x DR1=%x DR2=%x DR3=%x DR7=%x\n",
629: DR0, DR1, DR2, DR3, DR7);
630: write_dr0 (DR0);
631: write_dr1 (DR1);
632: write_dr2 (DR2);
633: write_dr3 (DR3);
634: write_dr7 (DR7);
635: regset._i386._eip += 3;
636: break;
637: #endif
638: default:
639: if (regset._i386._eip >= & __xtrap_on__ &&
640: regset._i386._eip < & __xtrap_off__) {
641: #ifdef TRACER
642: curr_register_dump (& regset);
643: printf ("copy fault called from %x\n",
644: * (int *) regset._i386._edx);
645: #endif
646: SET_U_ERROR (EFAULT, "copy gp");
647: regset._i386._eip = & __xtrap_break__;
648: } else {
649: curr_register_dump (& regset);
650: panic ("System GP Fault from Ring 1");
651: }
652: }
653: goto gpdone;
654: break;
655:
656: case DPL_2:
657: /*
658: * Nothing should be running in Ring 2.
659: */
660:
661: case DPL_3:
662: /*
663: * Ring 3 gp fault means errant user process.
664: */
665: curr_register_dump (& regset);
666: printf ("User GP Violation\n");
667: sendsig (SIGSEGV, SELF);
668: break;
669: }
670: gpdone:
671: return;
672: }
673:
674:
675: /*
676: * User debugger.
677: *
678: * Runs in ring 1.
679: */
680:
681: void
682: __debug_usr__ (regset)
683: gregset_t regset;
684: {
685: unsigned int dr6 = read_dr6();
686: unsigned cpl = regset._i386._cs & SEG_PL;
687: int do_rdump = 1;
688:
689: if (dr6 & 0xf) { /* report breakpoint exception(s) */
690: printf("Breakpoint ");
691: if (dr6 & 1)
692: printf("DR0=%x ", DR0);
693: if (dr6 & 2)
694: printf("DR1=%x ", DR1);
695: if (dr6 & 4)
696: printf("DR2=%x ", DR2);
697: if (dr6 & 8)
698: printf("DR3=%x ", DR3);
699: printf("DR7=%x\n", DR7);
700: }
701:
702: if (dr6 & 0xf000) { /* report other debug exception(s) */
703: if (dr6 & 0x8000)
704: printf("Switch to debugged task\n");
705:
706: if (dr6 & 0x4000) {
707: /* Single Step */
708: switch(cpl) {
709: /*
710: * If user code trapped, send signal
711: * and suppress console register dump.
712: */
713: case DPL_1:
714: /*
715: * Turn off single-stepping when entering
716: * Ring 1.
717: */
718: if (regset._i386._eip == & syc32 ||
719: regset._i386._eip == & sig32) {
720: do_rdump = 0;
721: } else {
722: printf("/nefl=%x No single stepping the kernel.\n", regset._i386._eflags);
723: }
724: regset._i386._eflags &= ~TRAP_FLAG;
725: break;
726:
727: case DPL_3:
728: do_rdump = 0;
729: T_HAL(0x20000, printf ("User SSTEP eip=%x efl=%x ", regset._i386._eip,
730: regset._i386._eflags));
731: sendsig (SIGTRAP, SELF);
732: break;
733: }
734: }
735: if (dr6 & 0x2000) {
736: printf("ICE in use\n");
737: regset._i386._eip += 3;
738: }
739: }
740:
741: if (do_rdump)
742: curr_register_dump (& regset);
743:
744: write_dr6 (0);
745: regset._i386._eflags |= RESUME_FLAG;
746: return;
747: }
748:
749: irqblab (regset)
750: gregset_t regset;
751: {
752: puts("*ip=");
753: print32 (regset._i386._eip);
754: puts(" *err=");
755: print32 (regset._i386._err);
756:
757: if ((regset._i386._err & 0xff) == 0x40) {
758: int irqno = (regset._i386._err >> 8) & 0xFF;
759: print8 (irqno);
760: } else if (regset._i386._err == 2)
761: puts("NMI ");
762: }
763:
764: void
765: pagefault (regset)
766: gregset_t regset;
767: {
768: register struct systab *stp;
769: register int callnum;
770: register int sigcode;
771: extern int trapcode;
772: extern *mmdata[], mminit;
773: cseg_t *pp;
774: register SEG *segp;
775: int splo, datahi;
776: unsigned int txtlo, txthi;
777: unsigned long newsp; /* Anticipated value for stack pointer. */
778: unsigned int cr2 = 0;
779: unsigned int cpl = regset._i386._cs & SEG_PL;
780:
781: /*
782: * Expect this to never happen!
783: */
784:
785: if (SELF->p_flags & PFKERN) {
786: panic ("pid%d: kernel process trap: err=%x, ip=%x ax=%d",
787: SELF->p_pid, regset._i386._err, regset._i386._eip,
788: regset._i386._eax);
789: }
790:
791: T_HAL (0x4000, printf("T%d ", regset._i386._err));
792: sigcode = 0;
793:
794: #if 0
795: u.u_regl = &gs; /* hook in register set for consave/conrest */
796: #endif
797:
798: /*
799: * Page fault
800: */
801:
802: cr2 = read_cr2 ();
803: if (cpl < 2) {
804: /*
805: * If page fault during Ring 1 copy service routine,
806: * such as kucopy or ukcopy, set u_error and abort
807: * the copy, but don't send signal to the user.
808: */
809:
810: if (regset._i386._eip >= & __xtrap_on__ &&
811: regset._i386._eip < & __xtrap_off__) {
812:
813: T_HAL (0x1000, printf ("copy trapped "));
814: #ifdef TRACER
815: curr_register_dump (& regset);
816: printf ("copy fault called from %x\n",
817: * (int *) regset._i386._edx);
818: #endif
819: SET_U_ERROR (EFAULT, "copy service");
820: regset._i386._eip = & __xtrap_break__;
821: goto pf_end;
822: } else {
823: printf ("cr2=%x", cr2);
824: curr_register_dump (& regset);
825: panic ("Kernel Page Fault");
826: }
827: }
828:
829: /* Check for stack underflow. */
830:
831: /*
832: * I think 'splo' is being calculated in a bass-ackwards way,
833: * and that 'datahi' is just wrong, but I'm not certain,
834: * so the fixes are #if 0'd out. -piggy
835: *
836: * I'll take out the 0 some day and test these changes.
837: */
838: segp = u.u_segl [SISTACK].sr_segp;
839: #if 0
840: splo = u.u_segl [SISTACK].sr_base - segp->s_size;
841: datahi = u.u_segl [SIPDATA].sr_base + u.u_segl [SIPDATA].sr_size;
842: #else
843: splo = __xmode_286 (& regset) ? ISP_286 : ISP_386;
844: splo -= segp->s_size;
845: datahi = u.u_segl [SIPDATA].sr_size;
846: #endif /* 0 */
847:
848: /*
849: * Catch bad function pointer here - don't want to restart
850: * the user instruction and get runaway segv's.
851: *
852: * For 286 executables, eip starts at 0, but cs points to
853: * descriptor SEG_286_UII which adds 0x400000 (UII_BASE).
854: */
855:
856: txtlo = u.u_segl [SISTEXT].sr_base;
857: if (__xmode_286 (& regset))
858: txtlo -= UII_BASE;
859:
860: txthi = txtlo + u.u_segl [SISTEXT].sr_size;
861: if (regset._i386._eip < txtlo ||
862: regset._i386._eip > txthi) {
863: T_HAL (0x1000, printf ("Bad eip, txtlo=%x txthi=%x\n",
864: txtlo, txthi));
865: goto bad_pf;
866: }
867:
868: /*
869: * If we trapped on an 'enter' instruction, the stack
870: * pointer (uesp) has not yet been decremented. In
871: * order to correctly process such a stack overflow,
872: * we must look at the _expected_ value for uesp.
873: * NB: We COPY uesp, because that arg gets loaded back
874: * into the real esp--when we return from the trap the
875: * enter instruction will decrement the esp.
876: */
877:
878: newsp = __xmode_286 (& regset) ? regset._i286._usp :
879: regset._i386._uesp;
880:
881: if (ffbyte (regset._i386._eip, regset._i386._cs) == ENTER_OP) {
882: /*
883: * Adjust the sp by the argument of the ENTER
884: * instruction.
885: */
886:
887: newsp -= ffword (regset._i386._eip + 1, regset._i386._cs);
888: }
889:
890: if (cr2 <= splo && newsp <= splo && newsp > datahi &&
891: btoc (datahi) < btocrd (splo)) {
892:
893: pp = c_extend(segp->s_vmem, btoc(segp->s_size));
894: if (pp==0) {
895: T_HAL (0x1000, printf ("c_extend(%x,%x)=0 ",
896: segp->s_vmem,
897: btoc(segp->s_size)));
898: goto bad_pf;
899: }
900:
901: segp->s_vmem = pp;
902: segp->s_size += NBPC;
903:
904: if (sproto (0) == 0) {
905: T_HAL(0x1000, printf("sproto(0)=0 "));
906: goto bad_pf;
907: }
908:
909: segload ();
910: goto pf_end;
911: }
912:
913: /*
914: * Catch bad data pointer here - don't want to restart
915: * the user instruction and get runaway segv's.
916: */
917:
918: {
919: T_HAL(0x1000, printf ("Bad data, splo=%x datahi=%x\n",
920: splo, datahi));
921: }
922:
923: bad_pf:
924: /*
925: * User generated unacceptable page fault.
926: */
927:
928: sigcode = SIGSEGV;
929: printf("\ncr2=%x ", cr2);
930:
931: pf_end:
932: /*
933: * Send user a signal.
934: * If not segload ();
935: * If not a breakpoint, do console register dump.
936: */
937:
938: if (sigcode) {
939: curr_register_dump (& regset);
940: printf ("sigcode=#%d User Page Fault\n", sigcode);
941: sendsig (sigcode, SELF);
942: }
943: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.