xref: /plan9-contrib/sys/src/cmd/8a/l.s (revision 6520663fb7ebac8d17e4a1dbc55d10bf525f7b14)
1/*
2 * Memory and machine-specific definitions.  Used in C and assembler.
3 */
4
5/*
6 * Sizes
7 */
8#define	BI2BY		8			/* bits per byte */
9#define BI2WD		32			/* bits per word */
10#define	BY2WD		4			/* bytes per word */
11#define	BY2PG		4096			/* bytes per page */
12#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
13#define	PGSHIFT		12			/* log(BY2PG) */
14#define PGROUND(s)	(((s)+(BY2PG-1))&~(BY2PG-1))
15
16#define	MAXMACH		1			/* max # cpus system can run */
17
18/*
19 * Time
20 */
21#define	HZ		(20)			/* clock frequency */
22#define	MS2HZ		(1000/HZ)		/* millisec per clock tick */
23#define	TK2SEC(t)	((t)/HZ)		/* ticks to seconds */
24#define	TK2MS(t)	((((ulong)(t))*1000)/HZ)	/* ticks to milliseconds */
25#define	MS2TK(t)	((((ulong)(t))*HZ)/1000)	/* milliseconds to ticks */
26
27/*
28 * Fundamental addresses
29 */
30
31/*
32 *  Address spaces
33 *
34 *  User is at 0-2GB
35 *  Kernel is at 2GB-4GB
36 *
37 *  To avoid an extra page map, both the user stack (USTKTOP) and
38 *  the temporary user stack (TSTKTOP) should be in the the same
39 *  4 meg.
40 */
41#define	UZERO		0			/* base of user address space */
42#define	UTZERO		(UZERO+BY2PG)		/* first address in user text */
43#define	KZERO		0x80000000		/* base of kernel address space */
44#define	KTZERO		KZERO			/* first address in kernel text */
45#define	USERADDR	0xC0000000		/* struct User */
46#define	UREGADDR	(USERADDR+BY2PG-4*19)
47#define	TSTKTOP		USERADDR		/* end of new stack in sysexec */
48#define TSTKSIZ 10
49#define	USTKTOP		(TSTKTOP-TSTKSIZ*BY2PG)	/* byte just beyond user stack */
50#define	USTKSIZE	(16*1024*1024 - TSTKSIZ*BY2PG)	/* size of user stack */
51#define ROMBIOS		(KZERO|0xF0000)
52
53#define	MACHSIZE	4096
54
55#define isphys(x) (((ulong)x)&KZERO)
56
57/*
58 *  known 80386 segments (in GDT) and their selectors
59 */
60#define	NULLSEG	0	/* null segment */
61#define	KDSEG	1	/* kernel data/stack */
62#define	KESEG	2	/* kernel executable */
63#define	UDSEG	3	/* user data/stack */
64#define	UESEG	4	/* user executable */
65#define TSSSEG	5	/* task segment */
66
67#define SELGDT	(0<<3)	/* selector is in gdt */
68#define	SELLDT	(1<<3)	/* selector is in ldt */
69
70#define SELECTOR(i, t, p)	(((i)<<3) | (t) | (p))
71
72#define NULLSEL	SELECTOR(NULLSEG, SELGDT, 0)
73#define KESEL	SELECTOR(KESEG, SELGDT, 0)
74#define KDSEL	SELECTOR(KDSEG, SELGDT, 0)
75#define UESEL	SELECTOR(UESEG, SELGDT, 3)
76#define UDSEL	SELECTOR(UDSEG, SELGDT, 3)
77#define TSSSEL	SELECTOR(TSSSEG, SELGDT, 0)
78
79/*
80 *  fields in segment descriptors
81 */
82#define SEGDATA	(0x10<<8)	/* data/stack segment */
83#define SEGEXEC	(0x18<<8)	/* executable segment */
84#define	SEGTSS	(0x9<<8)	/* TSS segment */
85#define SEGCG	(0x0C<<8)	/* call gate */
86#define	SEGIG	(0x0E<<8)	/* interrupt gate */
87#define SEGTG	(0x0F<<8)	/* task gate */
88#define SEGTYPE	(0x1F<<8)
89
90#define SEGP	(1<<15)		/* segment present */
91#define SEGPL(x) ((x)<<13)	/* priority level */
92#define SEGB	(1<<22)		/* granularity 1==4k (for expand-down) */
93#define SEGG	(1<<23)		/* granularity 1==4k (for other) */
94#define SEGE	(1<<10)		/* expand down */
95#define SEGW	(1<<9)		/* writable (for data/stack) */
96#define	SEGR	(1<<9)		/* readable (for code) */
97#define SEGD	(1<<22)		/* default 1==32bit (for code) */
98
99/*
100 *  virtual MMU
101 */
102#define PTEMAPMEM	(1024*1024)	/* ??? */
103#define SEGMAPSIZE	16		/* ??? */
104#define	PTEPERTAB	(PTEMAPMEM/BY2PG)	/* ??? */
105#define PPN(x)		((x)&~(BY2PG-1))
106
107/*
108 *  physical MMU
109 */
110#define	PTEVALID	(1<<0)
111#define	PTEUNCACHED	0		/* everything is uncached */
112#define PTEWRITE	(1<<1)
113#define	PTERONLY	(0<<1)
114#define	PTEKERNEL	(0<<2)
115#define	PTEUSER		(1<<2)
116
117/*
118 *  flag register bits that we care about
119 */
120#define IFLAG	0x200
121
122#define OP16	BYTE	$0x66
123
124/*
125 *	about to walk all over ms/dos - turn off interrupts
126 */
127TEXT	origin(SB),$0
128
129	CLI
130
131#ifdef BOOT
132/*
133 *	This part of l.s is used only in the boot kernel.
134 *	It assumes that we are in real address mode, i.e.,
135 *	that we look like an 8086.
136 */
137/*
138 *	relocate everything to a half meg and jump there
139 *	- looks wierd because it is being assembled by a 32 bit
140 *	  assembler for a 16 bit world
141 */
142	MOVL	$0,BX
143	INCL	BX
144	SHLL	$15,BX
145	MOVL	BX,CX
146	MOVW	BX,ES
147	MOVL	$0,SI
148	MOVL	SI,DI
149	CLD; REP; MOVSL
150/*	JMPFAR	0X8000:$lowcore(SB) /**/
151	 BYTE	$0xEA
152	 WORD	$lowcore(SB)
153	 WORD	$0X8000
154
155TEXT	lowcore(SB),$0
156
157/*
158 *	now that we're in low core, update the DS
159 */
160
161	MOVW	BX,DS
162
163/*
164 * 	goto protected mode
165 */
166/*	MOVL	tgdtptr(SB),GDTR /**/
167	 BYTE	$0x0f
168	 BYTE	$0x01
169	 BYTE	$0x16
170	 WORD	$tgdtptr(SB)
171	MOVL	CR0,AX
172	ORL	$1,AX
173	MOVL	AX,CR0
174
175/*
176 *	clear prefetch queue (wierd code to avoid optimizations)
177 */
178	CLC
179	JCC	flush
180	MOVL	AX,AX
181flush:
182
183/*
184 *	set all segs
185 */
186/*	MOVW	$SELECTOR(1, SELGDT, 0),AX	/**/
187	 BYTE	$0xc7
188	 BYTE	$0xc0
189	 WORD	$SELECTOR(1, SELGDT, 0)
190	MOVW	AX,DS
191	MOVW	AX,SS
192	MOVW	AX,ES
193	MOVW	AX,FS
194	MOVW	AX,GS
195
196/*	JMPFAR	SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
197	 BYTE	$0x66
198	 BYTE	$0xEA
199	 LONG	$mode32bit-KZERO(SB)
200	 WORD	$SELECTOR(2, SELGDT, 0)
201
202TEXT	mode32bit(SB),$0
203
204#endif BOOT
205
206	/*
207	 * Clear BSS
208	 */
209	LEAL	edata-KZERO(SB),SI
210	MOVL	SI,DI
211	ADDL	$4,DI
212	MOVL	$0,AX
213	MOVL	AX,(SI)
214	LEAL	end-KZERO(SB),CX
215	SUBL	DI,CX
216	SHRL	$2,CX
217	CLD; REP; MOVSL
218
219	/*
220	 *  make a bottom level page table page that maps the first
221	 *  16 meg of physical memory
222	 */
223	LEAL	tpt-KZERO(SB),AX	/* get phys addr of temporary page table */
224	ADDL	$(BY2PG-1),AX		/* must be page aligned */
225	ANDL	$(~(BY2PG-1)),AX	/* ... */
226	MOVL	$(4*1024),CX		/* pte's per page */
227	MOVL	$((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
228setpte:
229	MOVL	BX,-4(AX)(CX*4)
230	SUBL	$(1<<PGSHIFT),BX
231	LOOP	setpte
232
233	/*
234	 *  make a top level page table page that maps the first
235	 *  16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
236	 */
237	MOVL	AX,BX
238	ADDL	$(4*BY2PG),AX
239	ADDL	$(PTEVALID|PTEKERNEL|PTEWRITE),BX
240	MOVL	BX,0(AX)
241	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
242	ADDL	$BY2PG,BX
243	MOVL	BX,4(AX)
244	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
245	ADDL	$BY2PG,BX
246	MOVL	BX,8(AX)
247	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
248	ADDL	$BY2PG,BX
249	MOVL	BX,12(AX)
250	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
251
252	/*
253	 *  point processor to top level page & turn on paging
254	 */
255	MOVL	AX,CR3
256	MOVL	CR0,AX
257	ORL	$0X80000000,AX
258	ANDL	$~(0x8|0x2),AX	/* TS=0, MP=0 */
259	MOVL	AX,CR0
260
261	/*
262	 *  use a jump to an absolute location to get the PC into
263	 *  KZERO.
264	 */
265	LEAL	tokzero(SB),AX
266	JMP*	AX
267
268TEXT	tokzero(SB),$0
269
270	/*
271	 *  stack and mach
272	 */
273	MOVL	$mach0(SB),SP
274	MOVL	SP,m(SB)
275	MOVL	$0,0(SP)
276	ADDL	$(MACHSIZE-4),SP	/* start stack under machine struct */
277	MOVL	$0, u(SB)
278
279	/*
280	 *  clear flags
281	 */
282	MOVL	$0,AX
283	PUSHL	AX
284	POPFL
285
286	CALL	main(SB)
287
288loop:
289	JMP	loop
290
291GLOBL	mach0+0(SB), $MACHSIZE
292GLOBL	u(SB), $4
293GLOBL	m(SB), $4
294GLOBL	tpt(SB), $(BY2PG*6)
295
296/*
297 *  gdt to get us to 32-bit/segmented/unpaged mode
298 */
299TEXT	tgdt(SB),$0
300
301	/* null descriptor */
302	LONG	$0
303	LONG	$0
304
305	/* data segment descriptor for 4 gigabytes (PL 0) */
306	LONG	$(0xFFFF)
307	LONG	$(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
308
309	/* exec segment descriptor for 4 gigabytes (PL 0) */
310	LONG	$(0xFFFF)
311	LONG	$(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
312
313/*
314 *  pointer to initial gdt
315 */
316TEXT	tgdtptr(SB),$0
317
318	WORD	$(3*8)
319	LONG	$tgdt-KZERO(SB)
320
321/*
322 *  input a byte
323 */
324TEXT	inb(SB),$0
325
326	MOVL	p+0(FP),DX
327	XORL	AX,AX
328	INB
329	RET
330
331/*
332 *  output a byte
333 */
334TEXT	outb(SB),$0
335
336	MOVL	p+0(FP),DX
337	MOVL	b+4(FP),AX
338	OUTB
339	RET
340
341/*
342 *  input a string of shorts from a port
343 */
344TEXT	inss(SB),$0
345	MOVL	p+0(FP),DX
346	MOVL	a+4(FP),DI
347	MOVL	c+8(FP),CX
348	CLD; REP; OP16; INSL
349	RET
350
351/*
352 *  output a string of shorts to a port
353 */
354TEXT	outss(SB),$0
355	MOVL	p+0(FP),DX
356	MOVL	a+4(FP),SI
357	MOVL	c+8(FP),CX
358	CLD; REP; OP16; OUTSL
359	RET
360
361/*
362 *  test and set
363 */
364TEXT	tas(SB),$0
365	MOVL	$0xdeadead,AX
366	MOVL	l+0(FP),BX
367	XCHGL	AX,(BX)
368	RET
369
370/*
371 *  routines to load/read various system registers
372 */
373GLOBL	idtptr(SB),$6
374TEXT	putidt(SB),$0		/* interrupt descriptor table */
375	MOVL	t+0(FP),AX
376	MOVL	AX,idtptr+2(SB)
377	MOVL	l+4(FP),AX
378	MOVW	AX,idtptr(SB)
379	MOVL	idtptr(SB),IDTR
380	RET
381
382GLOBL	gdtptr(SB),$6
383TEXT	putgdt(SB),$0		/* global descriptor table */
384	MOVL	t+0(FP),AX
385	MOVL	AX,gdtptr+2(SB)
386	MOVL	l+4(FP),AX
387	MOVW	AX,gdtptr(SB)
388	MOVL	gdtptr(SB),GDTR
389	RET
390
391TEXT	putcr3(SB),$0		/* top level page table pointer */
392	MOVL	t+0(FP),AX
393	MOVL	AX,CR3
394	RET
395
396TEXT	puttr(SB),$0		/* task register */
397	MOVL	t+0(FP),AX
398	MOVW	AX,TASK
399	RET
400
401TEXT	getcr0(SB),$0		/* coprocessor bits */
402	MOVL	CR0,AX
403	RET
404
405TEXT	getcr2(SB),$0		/* fault address */
406	MOVL	CR2,AX
407	RET
408
409#define	FPOFF\
410	WAIT;\
411	MOVL	CR0,AX;\
412	ORL	$0x4,AX		/* EM=1 */;\
413	MOVL	AX,CR0
414
415#define	FPON\
416	MOVL	CR0,AX;\
417	ANDL	$~0x4,AX	/* EM=0 */;\
418	MOVL	AX,CR0
419
420TEXT	fpoff(SB),$0		/* turn off floating point */
421	FPOFF
422	RET
423
424TEXT	fpinit(SB),$0		/* turn on & init the floating point */
425	FPON
426	FINIT
427	WAIT
428	PUSHW	$0x0330
429	FLDCW	0(SP)		/* ignore underflow/precision, signal others */
430	POPW	AX
431	WAIT
432	RET
433
434TEXT	fpsave(SB),$0		/* save floating point state and turn off */
435	MOVL	p+0(FP),AX
436	WAIT
437	FSAVE	0(AX)
438	FPOFF
439	RET
440
441TEXT	fprestore(SB),$0	/* turn on floating point and restore regs */
442	FPON
443	MOVL	p+0(FP),AX
444	FRSTOR	0(AX)
445	WAIT
446	RET
447
448TEXT	fpstatus(SB),$0		/* get floating point status */
449	FSTSW	AX
450	RET
451
452/*
453 *  special traps
454 */
455TEXT	intr0(SB),$0
456	PUSHL	$0
457	PUSHL	$0
458	JMP	intrcommon
459TEXT	intr1(SB),$0
460	PUSHL	$0
461	PUSHL	$1
462	JMP	intrcommon
463TEXT	intr2(SB),$0
464	PUSHL	$0
465	PUSHL	$2
466	JMP	intrcommon
467TEXT	intr3(SB),$0
468	PUSHL	$0
469	PUSHL	$3
470	JMP	intrcommon
471TEXT	intr4(SB),$0
472	PUSHL	$0
473	PUSHL	$4
474	JMP	intrcommon
475TEXT	intr5(SB),$0
476	PUSHL	$0
477	PUSHL	$5
478	JMP	intrcommon
479TEXT	intr6(SB),$0
480	PUSHL	$0
481	PUSHL	$6
482	JMP	intrcommon
483TEXT	intr7(SB),$0
484	PUSHL	$0
485	PUSHL	$7
486	JMP	intrcommon
487TEXT	intr8(SB),$0
488	PUSHL	$8
489	JMP	intrscommon
490TEXT	intr9(SB),$0
491	PUSHL	$0
492	PUSHL	$9
493	JMP	intrcommon
494TEXT	intr10(SB),$0
495	PUSHL	$10
496	JMP	intrscommon
497TEXT	intr11(SB),$0
498	PUSHL	$11
499	JMP	intrscommon
500TEXT	intr12(SB),$0
501	PUSHL	$12
502	JMP	intrscommon
503TEXT	intr13(SB),$0
504	PUSHL	$13
505	JMP	intrscommon
506TEXT	intr14(SB),$0
507	PUSHL	$14
508	JMP	intrscommon
509TEXT	intr15(SB),$0
510	PUSHL	$0
511	PUSHL	$15
512	JMP	intrcommon
513TEXT	intr16(SB),$0
514	PUSHL	$0
515	PUSHL	$16
516	JMP	intrcommon
517TEXT	intr24(SB),$0
518	PUSHL	$0
519	PUSHL	$24
520	JMP	intrcommon
521TEXT	intr25(SB),$0
522	PUSHL	$0
523	PUSHL	$25
524	JMP	intrcommon
525TEXT	intr26(SB),$0
526	PUSHL	$0
527	PUSHL	$26
528	JMP	intrcommon
529TEXT	intr27(SB),$0
530	PUSHL	$0
531	PUSHL	$27
532	JMP	intrcommon
533TEXT	intr28(SB),$0
534	PUSHL	$0
535	PUSHL	$28
536	JMP	intrcommon
537TEXT	intr29(SB),$0
538	PUSHL	$0
539	PUSHL	$29
540	JMP	intrcommon
541TEXT	intr30(SB),$0
542	PUSHL	$0
543	PUSHL	$30
544	JMP	intrcommon
545TEXT	intr31(SB),$0
546	PUSHL	$0
547	PUSHL	$31
548	JMP	intrcommon
549TEXT	intr32(SB),$0
550	PUSHL	$0
551	PUSHL	$16
552	JMP	intrcommon
553TEXT	intr33(SB),$0
554	PUSHL	$0
555	PUSHL	$33
556	JMP	intrcommon
557TEXT	intr34(SB),$0
558	PUSHL	$0
559	PUSHL	$34
560	JMP	intrcommon
561TEXT	intr35(SB),$0
562	PUSHL	$0
563	PUSHL	$35
564	JMP	intrcommon
565TEXT	intr36(SB),$0
566	PUSHL	$0
567	PUSHL	$36
568	JMP	intrcommon
569TEXT	intr37(SB),$0
570	PUSHL	$0
571	PUSHL	$37
572	JMP	intrcommon
573TEXT	intr38(SB),$0
574	PUSHL	$0
575	PUSHL	$38
576	JMP	intrcommon
577TEXT	intr39(SB),$0
578	PUSHL	$0
579	PUSHL	$39
580	JMP	intrcommon
581TEXT	intr64(SB),$0
582	PUSHL	$0
583	PUSHL	$64
584	JMP	intrcommon
585TEXT	intrbad(SB),$0
586	PUSHL	$0
587	PUSHL	$0x1ff
588	JMP	intrcommon
589
590intrcommon:
591	PUSHL	DS
592	PUSHL	ES
593	PUSHL	FS
594	PUSHL	GS
595	PUSHAL
596	MOVL	$(KDSEL),AX
597	MOVW	AX,DS
598	MOVW	AX,ES
599	LEAL	0(SP),AX
600	PUSHL	AX
601	CALL	trap(SB)
602	POPL	AX
603	POPAL
604	POPL	GS
605	POPL	FS
606	POPL	ES
607	POPL	DS
608	ADDL	$8,SP	/* error code and trap type */
609	IRETL
610
611intrscommon:
612	PUSHL	DS
613	PUSHL	ES
614	PUSHL	FS
615	PUSHL	GS
616	PUSHAL
617	MOVL	$(KDSEL),AX
618	MOVW	AX,DS
619	MOVW	AX,ES
620	LEAL	0(SP),AX
621	PUSHL	AX
622	CALL	trap(SB)
623	POPL	AX
624	POPAL
625	POPL	GS
626	POPL	FS
627	POPL	ES
628	POPL	DS
629	ADDL	$8,SP	/* error code and trap type */
630	IRETL
631
632/*
633 *  interrupt level is interrupts on or off
634 */
635TEXT	spllo(SB),$0
636	PUSHFL
637	POPL	AX
638	STI
639	RET
640
641TEXT	splhi(SB),$0
642	PUSHFL
643	POPL	AX
644	CLI
645	RET
646
647TEXT	splx(SB),$0
648	MOVL	s+0(FP),AX
649	PUSHL	AX
650	POPFL
651	RET
652
653/*
654 *  do nothing whatsoever till interrupt happens
655 */
656TEXT	idle(SB),$0
657	HLT
658	RET
659
660/*
661 *  label consists of a stack pointer and a PC
662 */
663TEXT	gotolabel(SB),$0
664	MOVL	l+0(FP),AX
665	MOVL	0(AX),SP	/* restore sp */
666	MOVL	4(AX),AX	/* put return pc on the stack */
667	MOVL	AX,0(SP)
668	MOVL	$1,AX		/* return 1 */
669	RET
670
671TEXT	setlabel(SB),$0
672	MOVL	l+0(FP),AX
673	MOVL	SP,0(AX)	/* store sp */
674	MOVL	0(SP),BX	/* store return pc */
675	MOVL	BX,4(AX)
676	MOVL	$0,AX		/* return 0 */
677	RET
678
679/*
680 *  Used to get to the first process.
681 *  Set up an interrupt return frame and IRET to user level.
682 */
683TEXT	touser(SB),$0
684	PUSHL	$(UDSEL)		/* old ss */
685	PUSHL	$(USTKTOP)		/* old sp */
686	PUSHFL				/* old flags */
687	PUSHL	$(UESEL)		/* old cs */
688	PUSHL	$(UTZERO+32)		/* old pc */
689	MOVL	$(UDSEL),AX
690	MOVW	AX,DS
691	MOVW	AX,ES
692	MOVW	AX,GS
693	MOVW	AX,FS
694	IRETL
695
696/*
697 *  set configuration register
698 */
699TEXT	config(SB),$0
700	MOVL	l+0(FP),AX
701	MOVL	$0x3F3,DX
702	OUTB
703	OUTB
704	RET
705