|
|
1.1 root 1: #include "mem.h"
2:
3: #define OP16 BYTE $0x66
4:
5: /*
6: * Some horrid macros for writing 16-bit code.
7: */
8: #define rAX 0 /* rX */
9: #define rCX 1
10: #define rDX 2
11: #define rBX 3
12: #define rSP 4 /* SP */
13: #define rBP 5 /* BP */
14: #define rSI 6 /* SI */
15: #define rDI 7 /* DI */
16:
17: #define rAL 0 /* rL */
18: #define rCL 1
19: #define rDL 2
20: #define rBL 3
21: #define rAH 4 /* rH */
22: #define rCH 5
23: #define rDH 6
24: #define rBH 7
25:
26: #define rES 0 /* rS */
27: #define rCS 1
28: #define rSS 2
29: #define rDS 3
30: #define rFS 4
31: #define rGS 5
32:
33: #define rCR0 0 /* rC */
34: #define rCR2 2
35: #define rCR3 3
36: #define rCR4 4
37:
38: #define OP(o, m, r, rm) BYTE $o; /* op + modr/m byte */ \
39: BYTE $((m<<6)|(r<<3)|rm)
40: #define OPrr(o, r0, r1) OP(o, 0x03, r0, r1); /* general r -> r */
41:
42: #define LWI(i, rX) BYTE $(0xB8+rX); /* i -> rX */ \
43: WORD $i;
44: #define LBI(i, rB) BYTE $(0xB0+rB); /* i -> r[HL] */ \
45: BYTE $i
46:
47: #define MFSR(rS, rX) OPrr(0x8C, rS, rX) /* rS -> rX */
48: #define MTSR(rX, rS) OPrr(0x8E, rS, rX) /* rX -> rS */
49: #define MFCR(rC, rX) BYTE $0x0F; /* rC -> rX */ \
50: OP(0x20, 0x03, rC, rX)
51: #define MTCR(rX, rC) BYTE $0x0F; /* rX -> rC */ \
52: OP(0x22, 0x03, rC, rX)
53:
54: #define ANDI(i, r) OP(0x81, 0x03, 0x04, r);/* i & r -> r */ \
55: WORD $i;
56: #define CLR(r) OPrr(0x31, r, r) /* r^r -> r */
57:
58: #define FARJUMP(s, o) BYTE $0xEA; /* far jump to s:o */ \
59: WORD $o; WORD $s
60: #define DELAY BYTE $0xEB; /* jmp .+2 */ \
61: BYTE $0x00
62: #define OUTb(p, d) LBI(d, rAL); /* d -> I/O port p */ \
63: BYTE $0xE6; \
64: BYTE $p; DELAY
65:
66: TEXT origin(SB), $0
67: /*
68: * This part of l.s is used only in the boot kernel.
69: * It assumes that we are in real address mode, i.e.,
70: * that we look like an 8086.
71: *
72: * Make sure the segments are reasonable.
73: * If we were started directly from the BIOS
74: * (i.e. no MS-DOS) then DS may not be
75: * right.
76: */
77: MOVW CS, AX
78: MOVW AX, DS
79:
80: /*
81: * Get the current video mode. If it isn't mode 3,
82: * set text mode 3.
83: */
84: XORL AX, AX
85: MOVB $0x0F, AH
86: INT $0x10 /* get current video mode in AL */
87: CMPB AL, $03
88: JEQ _BIOSputs
89: XORL AX, AX
90: MOVB $0x03, AL
91: INT $0x10 /* set video mode in AL */
92:
93: _BIOSputs:
94: MOVW $hello(SB), SI
95: XORL BX, BX
96: _BIOSputsloop:
97: LODSB
98: ORB AL, AL
99: JEQ _BIOSputsret
100:
101: MOVB $0x0E, AH
102: INT $0x10
103: JMP _BIOSputsloop
104:
105: _BIOSputsret:
106:
107: /*
108: * relocate everything to a half meg and jump there
109: * - looks weird because it is being assembled by a 32 bit
110: * assembler for a 16 bit world
111: */
112: MOVL $0,BX
113: INCL BX
114: SHLL $15,BX
115: MOVL BX,CX
116: MOVW BX,ES
117: MOVL $0,SI
118: MOVL SI,DI
119: CLD
120: REP
121: MOVSL
122:
123: /*
124: * Jump to the copied image;
125: * fix up the DS for the new location.
126: */
127: FARJUMP(0x8000, _start8000(SB))
128:
129: TEXT _start8000(SB), $0
130: MFSR(rCS, rAX) /* fix up DS (0x8000) */
131: MTSR(rAX, rDS)
132:
133: /*
134: * If we are already in protected mode, have to get back
135: * to real mode before trying any priveleged operations
136: * (like going into protected mode...).
137: * Try to reset with a restart vector.
138: */
139: MFCR(rCR0, rAX) /* are we in protected mode? */
140: ANDI(0x0001, rAX)
141: JEQ _real
142:
143: CLR(rBX)
144: MTSR(rBX, rES)
145:
146: LWI(0x0467, rBX) /* reset entry point */
147: LWI(_start8000(SB), rAX) /* offset within segment */
148: BYTE $0x26
149: BYTE $0x89
150: BYTE $0x07 /* MOVW AX, ES:[BX] */
151: LBI(0x69, rBL)
152: MFSR(rCS, rAX) /* segment */
153: BYTE $0x26
154: BYTE $0x89
155: BYTE $0x07 /* MOVW AX, ES:[BX] */
156:
157: CLR(rDX)
158: OUTb(0x70, 0x8F)
159: OUTb(0x71, 0x0A)
160:
161: FARJUMP(0xFFFF, 0x0000) /* reset */
162:
163: _real:
164:
165: /*
166: * turn off interrupts
167: */
168: CLI
169:
170: /*
171: * goto protected mode
172: */
173: /* MOVL tgdtptr(SB),GDTR /**/
174: BYTE $0x0f
175: BYTE $0x01
176: BYTE $0x16
177: WORD $tgdtptr(SB)
178: MOVL CR0,AX
179: ORL $1,AX
180: MOVL AX,CR0
181:
182: /*
183: * clear prefetch queue (weird code to avoid optimizations)
184: */
185: CLC
186: JCC flush
187: MOVL AX,AX
188: flush:
189:
190: /*
191: * set all segs
192: */
193: /* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
194: BYTE $0xc7
195: BYTE $0xc0
196: WORD $SELECTOR(1, SELGDT, 0)
197: MOVW AX,DS
198: MOVW AX,SS
199: MOVW AX,ES
200: MOVW AX,FS
201: MOVW AX,GS
202:
203: /* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
204: BYTE $0x66
205: BYTE $0xEA
206: LONG $mode32bit-KZERO(SB)
207: WORD $SELECTOR(2, SELGDT, 0)
208:
209: TEXT mode32bit(SB),$0
210:
211:
212: /*
213: * Clear BSS
214: */
215: LEAL edata-KZERO(SB),SI
216: MOVL SI,DI
217: ADDL $4,DI
218: MOVL $0,AX
219: MOVL AX,(SI)
220: LEAL end-KZERO(SB),CX
221: SUBL DI,CX
222: SHRL $2,CX
223: REP
224: MOVSL
225:
226: /*
227: * make a bottom level page table page that maps the first
228: * 16 meg of physical memory
229: */
230: LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */
231: ADDL $(BY2PG-1),AX /* must be page aligned */
232: ANDL $(~(BY2PG-1)),AX /* ... */
233: MOVL $(4*1024),CX /* pte's per page */
234: MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
235: setpte:
236: MOVL BX,-4(AX)(CX*4)
237: SUBL $(1<<PGSHIFT),BX
238: LOOP setpte
239:
240: /*
241: * make a top level page table page that maps the first
242: * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
243: */
244: MOVL AX,BX
245: ADDL $(4*BY2PG),AX
246: ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
247: MOVL BX,0(AX)
248: MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
249: ADDL $BY2PG,BX
250: MOVL BX,4(AX)
251: MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
252: ADDL $BY2PG,BX
253: MOVL BX,8(AX)
254: MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
255: ADDL $BY2PG,BX
256: MOVL BX,12(AX)
257: MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
258:
259: /*
260: * point processor to top level page & turn on paging
261: */
262: MOVL AX,CR3
263: MOVL CR0,AX
264: ORL $0X80000000,AX
265: MOVL AX,CR0
266:
267: /*
268: * use a jump to an absolute location to get the PC into
269: * KZERO.
270: */
271: LEAL tokzero(SB),AX
272: JMP* AX
273:
274: TEXT tokzero(SB),$0
275:
276: /*
277: * stack and mach
278: */
279: MOVL $mach0(SB),SP
280: MOVL SP,m(SB)
281: MOVL $0,0(SP)
282: ADDL $(MACHSIZE-4),SP /* start stack above machine struct */
283:
284: CALL main(SB)
285:
286: loop:
287: JMP loop
288:
289: GLOBL mach0+0(SB), $MACHSIZE
290: GLOBL m(SB), $4
291: GLOBL tpt(SB), $(BY2PG*6)
292:
293: /*
294: * gdt to get us to 32-bit/segmented/unpaged mode
295: */
296: TEXT tgdt(SB),$0
297:
298: /* null descriptor */
299: LONG $0
300: LONG $0
301:
302: /* data segment descriptor for 4 gigabytes (PL 0) */
303: LONG $(0xFFFF)
304: LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
305:
306: /* exec segment descriptor for 4 gigabytes (PL 0) */
307: LONG $(0xFFFF)
308: LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
309:
310: /*
311: * pointer to initial gdt
312: */
313: TEXT tgdtptr(SB),$0
314:
315: WORD $(3*8)
316: LONG $tgdt-KZERO(SB)
317:
318: /*
319: * input a byte
320: */
321: TEXT inb(SB),$0
322:
323: MOVL p+0(FP),DX
324: XORL AX,AX
325: INB
326: RET
327:
328: /*
329: * input a short from a port
330: */
331: TEXT ins(SB), $0
332:
333: MOVL p+0(FP), DX
334: XORL AX, AX
335: OP16; INL
336: RET
337:
338: /*
339: * input a long from a port
340: */
341: TEXT inl(SB), $0
342:
343: MOVL p+0(FP), DX
344: XORL AX, AX
345: INL
346: RET
347:
348: /*
349: * output a byte
350: */
351: TEXT outb(SB),$0
352:
353: MOVL p+0(FP),DX
354: MOVL b+4(FP),AX
355: OUTB
356: RET
357:
358: /*
359: * output a short to a port
360: */
361: TEXT outs(SB), $0
362: MOVL p+0(FP), DX
363: MOVL s+4(FP), AX
364: OP16; OUTL
365: RET
366:
367: /*
368: * output a long to a port
369: */
370: TEXT outl(SB), $0
371: MOVL p+0(FP), DX
372: MOVL s+4(FP), AX
373: OUTL
374: RET
375:
376: /*
377: * input a string of bytes from a port
378: */
379: TEXT insb(SB),$0
380:
381: MOVL p+0(FP),DX
382: MOVL a+4(FP),DI
383: MOVL c+8(FP),CX
384: CLD; REP; INSB
385: RET
386:
387: /*
388: * input a string of shorts from a port
389: */
390: TEXT inss(SB),$0
391: MOVL p+0(FP),DX
392: MOVL a+4(FP),DI
393: MOVL c+8(FP),CX
394: CLD
395: REP; OP16; INSL
396: RET
397:
398: /*
399: * output a string of bytes to a port
400: */
401: TEXT outsb(SB),$0
402:
403: MOVL p+0(FP),DX
404: MOVL a+4(FP),SI
405: MOVL c+8(FP),CX
406: CLD; REP; OUTSB
407: RET
408:
409: /*
410: * output a string of shorts to a port
411: */
412: TEXT outss(SB),$0
413: MOVL p+0(FP),DX
414: MOVL a+4(FP),SI
415: MOVL c+8(FP),CX
416: CLD
417: REP; OP16; OUTSL
418: RET
419:
420: /*
421: * input a string of longs from a port
422: */
423: TEXT insl(SB),$0
424:
425: MOVL p+0(FP),DX
426: MOVL a+4(FP),DI
427: MOVL c+8(FP),CX
428: CLD; REP; INSL
429: RET
430:
431: /*
432: * output a string of longs to a port
433: */
434: TEXT outsl(SB),$0
435:
436: MOVL p+0(FP),DX
437: MOVL a+4(FP),SI
438: MOVL c+8(FP),CX
439: CLD; REP; OUTSL
440: RET
441:
442: /*
443: * routines to load/read various system registers
444: */
445: GLOBL idtptr(SB),$6
446: TEXT putidt(SB),$0 /* interrupt descriptor table */
447: MOVL t+0(FP),AX
448: MOVL AX,idtptr+2(SB)
449: MOVL l+4(FP),AX
450: MOVW AX,idtptr(SB)
451: MOVL idtptr(SB),IDTR
452: RET
453:
454: TEXT putcr3(SB),$0 /* top level page table pointer */
455: MOVL t+0(FP),AX
456: MOVL AX,CR3
457: RET
458:
459: TEXT getcr0(SB),$0 /* coprocessor bits */
460: MOVL CR0,AX
461: RET
462:
463: TEXT getcr2(SB),$0 /* fault address */
464: MOVL CR2,AX
465: RET
466:
467: TEXT getcr3(SB),$0 /* page directory base */
468: MOVL CR3,AX
469: RET
470:
471: /*
472: * special traps
473: */
474: TEXT intr0(SB),$0
475: PUSHL $0
476: PUSHL $0
477: JMP intrcommon
478: TEXT intr1(SB),$0
479: PUSHL $0
480: PUSHL $1
481: JMP intrcommon
482: TEXT intr2(SB),$0
483: PUSHL $0
484: PUSHL $2
485: JMP intrcommon
486: TEXT intr3(SB),$0
487: PUSHL $0
488: PUSHL $3
489: JMP intrcommon
490: TEXT intr4(SB),$0
491: PUSHL $0
492: PUSHL $4
493: JMP intrcommon
494: TEXT intr5(SB),$0
495: PUSHL $0
496: PUSHL $5
497: JMP intrcommon
498: TEXT intr6(SB),$0
499: PUSHL $0
500: PUSHL $6
501: JMP intrcommon
502: TEXT intr7(SB),$0
503: PUSHL $0
504: PUSHL $7
505: JMP intrcommon
506: TEXT intr8(SB),$0
507: PUSHL $8
508: JMP intrcommon
509: TEXT intr9(SB),$0
510: PUSHL $0
511: PUSHL $9
512: JMP intrcommon
513: TEXT intr10(SB),$0
514: PUSHL $10
515: JMP intrcommon
516: TEXT intr11(SB),$0
517: PUSHL $11
518: JMP intrcommon
519: TEXT intr12(SB),$0
520: PUSHL $12
521: JMP intrcommon
522: TEXT intr13(SB),$0
523: PUSHL $13
524: JMP intrcommon
525: TEXT intr14(SB),$0
526: PUSHL $14
527: JMP intrcommon
528: TEXT intr15(SB),$0
529: PUSHL $0
530: PUSHL $15
531: JMP intrcommon
532: TEXT intr16(SB),$0
533: PUSHL $0
534: PUSHL $16
535: JMP intrcommon
536: TEXT intr24(SB),$0
537: PUSHL $0
538: PUSHL $24
539: JMP intrcommon
540: TEXT intr25(SB),$0
541: PUSHL $0
542: PUSHL $25
543: JMP intrcommon
544: TEXT intr26(SB),$0
545: PUSHL $0
546: PUSHL $26
547: JMP intrcommon
548: TEXT intr27(SB),$0
549: PUSHL $0
550: PUSHL $27
551: JMP intrcommon
552: TEXT intr28(SB),$0
553: PUSHL $0
554: PUSHL $28
555: JMP intrcommon
556: TEXT intr29(SB),$0
557: PUSHL $0
558: PUSHL $29
559: JMP intrcommon
560: TEXT intr30(SB),$0
561: PUSHL $0
562: PUSHL $30
563: JMP intrcommon
564: TEXT intr31(SB),$0
565: PUSHL $0
566: PUSHL $31
567: JMP intrcommon
568: TEXT intr32(SB),$0
569: PUSHL $0
570: PUSHL $32
571: JMP intrcommon
572: TEXT intr33(SB),$0
573: PUSHL $0
574: PUSHL $33
575: JMP intrcommon
576: TEXT intr34(SB),$0
577: PUSHL $0
578: PUSHL $34
579: JMP intrcommon
580: TEXT intr35(SB),$0
581: PUSHL $0
582: PUSHL $35
583: JMP intrcommon
584: TEXT intr36(SB),$0
585: PUSHL $0
586: PUSHL $36
587: JMP intrcommon
588: TEXT intr37(SB),$0
589: PUSHL $0
590: PUSHL $37
591: JMP intrcommon
592: TEXT intr38(SB),$0
593: PUSHL $0
594: PUSHL $38
595: JMP intrcommon
596: TEXT intr39(SB),$0
597: PUSHL $0
598: PUSHL $39
599: JMP intrcommon
600: TEXT intr64(SB),$0
601: PUSHL $0
602: PUSHL $64
603: JMP intrcommon
604: TEXT intrbad(SB),$0
605: PUSHL $0
606: PUSHL $0x1ff
607: JMP intrcommon
608:
609: intrcommon:
610: PUSHL DS
611: PUSHL ES
612: PUSHL FS
613: PUSHL GS
614: PUSHAL
615: MOVL $(KDSEL),AX
616: MOVW AX,DS
617: MOVW AX,ES
618: LEAL 0(SP),AX
619: PUSHL AX
620: CALL trap(SB)
621: POPL AX
622: POPAL
623: POPL GS
624: POPL FS
625: POPL ES
626: POPL DS
627: ADDL $8,SP /* error code and trap type */
628: IRETL
629:
630:
631: /*
632: * interrupt level is interrupts on or off
633: */
634: TEXT spllo(SB),$0
635: PUSHFL
636: POPL AX
637: STI
638: RET
639:
640: TEXT splhi(SB),$0
641: PUSHFL
642: POPL AX
643: CLI
644: RET
645:
646: TEXT splx(SB),$0
647: MOVL s+0(FP),AX
648: PUSHL AX
649: POPFL
650: RET
651:
652: /*
653: * do nothing whatsoever till interrupt happens
654: */
655: TEXT idle(SB),$0
656: HLT
657: RET
658:
659: /*
660: * return cpu type (586 == pentium or better)
661: */
662: TEXT x86(SB),$0
663:
664: PUSHFL
665: MOVL 0(SP),AX
666: XORL $0x240000,AX
667: PUSHL AX
668: POPFL
669: PUSHFL
670: MOVL 0(SP),AX
671: XORL 4(SP),AX
672: MOVL AX, BX
673: ANDL $0x40000,BX /* on 386 we can't change this bit */
674: JZ is386
675: ANDL $0x200000,AX /* if we can't change this, there's no CPUID */
676: JZ is486
677: MOVL $1,AX
678: /* CPUID */
679: BYTE $0x0F
680: BYTE $0xA2
681: SHLL $20,AX
682: SHRL $28,AX
683: CMPL AX, $4
684: JEQ is486
685: MOVL $586,AX
686: JMP done
687: is486:
688: MOVL $486,AX
689: JMP done
690: is386:
691: MOVL $386,AX
692: done:
693: POPL BX
694: POPFL
695: RET
696:
697: /*
698: * basic timing loop to determine CPU frequency
699: */
700: TEXT aamloop(SB),$0
701:
702: MOVL c+0(FP),CX
703: aaml1:
704: AAM
705: LOOP aaml1
706: RET
707:
708: /*
709: * The DP8390 ethernet chip needs some time between
710: * successive chip selects, so we force a jump into
711: * the instruction stream to break the pipeline.
712: */
713: TEXT dp8390inb(SB), $0
714: MOVL p+0(FP),DX
715: XORL AX,AX /* CF = 0 */
716: INB
717:
718: JCC _dp8390inb0 /* always true */
719: MOVL AX,AX
720:
721: _dp8390inb0:
722: RET
723:
724: TEXT dp8390outb(SB), $0
725: MOVL p+0(FP),DX
726: MOVL b+4(FP),AX
727: OUTB
728:
729: CLC /* CF = 0 */
730: JCC _dp8390outb0 /* always true */
731: MOVL AX,AX
732:
733: _dp8390outb0:
734: RET
735:
736: GLOBL hello(SB), $0x18
737: DATA hello+0x00(SB)/8, $"Plan 9 f"
738: DATA hello+0x08(SB)/8, $"rom Bell"
739: DATA hello+0x10(SB)/8, $" Labs\r\n\z"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.