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