]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/start.s
xnu-792.24.17.tar.gz
[apple/xnu.git] / osfmk / i386 / start.s
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
8f6c56a5 11 *
6601e61a
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25/*
26 * Mach Operating System
27 * Copyright (c) 1991,1990 Carnegie Mellon University
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
35 *
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50/*
51 */
52
53#include <platforms.h>
1c79356b
A
54#include <mach_kdb.h>
55
56#include <i386/asm.h>
57#include <i386/proc_reg.h>
91447636 58#include <i386/postcode.h>
1c79356b
A
59#include <assym.s>
60
1c79356b
A
61#define CX(addr,reg) addr(,reg,4)
62
55e303ae 63#include <i386/mp.h>
91447636 64#include <i386/mp_slave_boot.h>
1c79356b
A
65
66/*
67 * GAS won't handle an intersegment jump with a relocatable offset.
68 */
69#define LJMP(segment,address) \
70 .byte 0xea ;\
71 .long address ;\
72 .word segment
73
74
75
6601e61a
A
76#define KVTOPHYS (-KERNELBASE)
77#define KVTOLINEAR LINEAR_KERNELBASE
78
79
80#define PA(addr) ((addr)+KVTOPHYS)
81#define VA(addr) ((addr)-KVTOPHYS)
8f6c56a5 82
6601e61a
A
83 .data
84#if 0 /* Anyone need this? */
85 .align 2
86 .globl EXT(_kick_buffer_)
87EXT(_kick_buffer_):
88 .long 1
89 .long 3
90 .set .,.+16836
91#endif /* XXX */
1c79356b
A
92/*
93 * Interrupt and bootup stack for initial processor.
94 */
3a60a9f5 95 /* in the __HIB section since the hibernate restore code uses this stack. */
91447636 96 .section __HIB, __data
6601e61a 97 .align ALIGN
91447636 98
6601e61a
A
99 .globl EXT(intstack)
100EXT(intstack):
3a60a9f5
A
101 .globl EXT(gIOHibernateRestoreStack)
102EXT(gIOHibernateRestoreStack):
91447636 103
1c79356b 104 .set ., .+INTSTACK_SIZE
91447636 105
6601e61a
A
106 .globl EXT(eintstack)
107EXT(eintstack:)
3a60a9f5
A
108 .globl EXT(gIOHibernateRestoreStackEnd)
109EXT(gIOHibernateRestoreStackEnd):
1c79356b 110
91447636
A
111/*
112 * Pointers to GDT and IDT. These contain linear addresses.
113 */
114 .align ALIGN
115 .globl EXT(gdtptr)
116LEXT(gdtptr)
117 .word Times(8,GDTSZ)-1
6601e61a 118 .long EXT(gdt)
91447636
A
119
120 .align ALIGN
121 .globl EXT(idtptr)
122LEXT(idtptr)
123 .word Times(8,IDTSZ)-1
6601e61a 124 .long EXT(idt)
91447636 125
6601e61a 126 /* back to the regular __DATA section. */
91447636
A
127
128 .section __DATA, __data
1c79356b 129
1c79356b
A
130
131#if MACH_KDB
132/*
133 * Kernel debugger stack for each processor.
134 */
6601e61a 135 .align ALIGN
1c79356b
A
136 .globl EXT(db_stack_store)
137EXT(db_stack_store):
91447636 138 .set ., .+(INTSTACK_SIZE*MAX_CPUS)
1c79356b
A
139
140/*
141 * Stack for last-ditch debugger task for each processor.
142 */
6601e61a 143 .align ALIGN
1c79356b
A
144 .globl EXT(db_task_stack_store)
145EXT(db_task_stack_store):
91447636 146 .set ., .+(INTSTACK_SIZE*MAX_CPUS)
1c79356b
A
147
148/*
149 * per-processor kernel debugger stacks
150 */
151 .align ALIGN
152 .globl EXT(kgdb_stack_store)
153EXT(kgdb_stack_store):
91447636
A
154 .set ., .+(INTSTACK_SIZE*MAX_CPUS)
155#endif /* MACH_KDB */
1c79356b 156
1c79356b 157 .data
6601e61a
A
158 /*
159 * start_lock is very special. We initialize the
160 * lock at allocation time rather than at run-time.
161 * Although start_lock should be an instance of a
162 * hw_lock, we hand-code all manipulation of the lock
163 * because the hw_lock code may require function calls;
164 * and we'd rather not introduce another dependency on
165 * a working stack at this point.
166 */
167 .globl EXT(start_lock)
168EXT(start_lock):
169 .long 0 /* synchronizes processor startup */
170
171 .globl EXT(master_is_up)
172EXT(master_is_up):
173 .long 0 /* 1 when OK for other processors */
174 /* to start */
175 .globl EXT(mp_boot_pde)
176EXT(mp_boot_pde):
177 .long 0
178
179_KERNend: .long 0 /* phys addr end of kernel (just after bss) */
180physfree: .long 0 /* phys addr of next free page */
181
182 .globl _IdlePTD
183_IdlePTD: .long 0 /* phys addr of kernel PTD */
91447636 184#ifdef PAE
6601e61a
A
185 .globl _IdlePDPT
186_IdlePDPT: .long 0 /* phys addr of kernel PDPT */
91447636
A
187#endif
188
6601e61a
A
189 .globl _KPTphys
190
191_KPTphys: .long 0 /* phys addr of kernel page tables */
91447636
A
192
193
194/* Some handy macros */
195
6601e61a
A
196#define ALLOCPAGES(npages) \
197 movl PA(physfree), %esi ; \
198 movl $((npages) * PAGE_SIZE), %eax ; \
199 addl %esi, %eax ; \
200 movl %eax, PA(physfree) ; \
201 movl %esi, %edi ; \
202 movl $((npages) * PAGE_SIZE / 4),%ecx ; \
203 xorl %eax,%eax ; \
204 cld ; \
205 rep ; \
91447636
A
206 stosl
207
208/*
209 * fillkpt
210 * eax = page frame address
211 * ebx = index into page table
212 * ecx = how many pages to map
213 * base = base address of page dir/table
214 * prot = protection bits
215 */
216#define fillkpt(base, prot) \
6601e61a 217 shll $(PTEINDX),%ebx ; \
91447636
A
218 addl base,%ebx ; \
219 orl $(PTE_V) ,%eax ; \
220 orl prot,%eax ; \
2211: movl %eax,(%ebx) ; \
222 addl $(PAGE_SIZE),%eax ; /* increment physical address */ \
223 addl $(PTESIZE),%ebx ; /* next pte */ \
224 loop 1b
225
226/*
227 * fillkptphys(prot)
228 * eax = physical address
229 * ecx = how many pages to map
230 * prot = protection bits
231 */
232#define fillkptphys(prot) \
233 movl %eax, %ebx ; \
234 shrl $(PAGE_SHIFT), %ebx ; \
6601e61a 235 fillkpt(PA(EXT(KPTphys)), prot)
91447636 236
6601e61a 237
1c79356b 238/*
6601e61a 239 * All CPUs start here.
1c79356b
A
240 *
241 * Environment:
242 * protected mode, no paging, flat 32-bit address space.
243 * (Code/data/stack segments have base == 0, limit == 4G)
244 */
245 .text
246 .align ALIGN
6601e61a 247 .globl EXT(pstart)
1c79356b
A
248 .globl EXT(_start)
249LEXT(_start)
250LEXT(pstart)
6601e61a 251 mov %eax, %ebx /* save pointer to kernbootstruct */
91447636 252
6601e61a 253 POSTCODE(PSTART_ENTRY);
91447636 254
1c79356b
A
255 mov $0,%ax /* fs must be zeroed; */
256 mov %ax,%fs /* some bootstrappers don`t do this */
257 mov %ax,%gs
258
6601e61a
A
259 jmp 1f
2600: cmpl $0,PA(EXT(start_lock))
261 jne 0b
2621: movb $1,%eax
263 xchgl %eax,PA(EXT(start_lock)) /* locked */
264 testl %eax,%eax
265 jnz 0b
266
267 cmpl $0,PA(EXT(master_is_up)) /* are we first? */
268 jne EXT(slave_start) /* no -- system already up. */
269 movl $1,PA(EXT(master_is_up)) /* others become slaves */
270 jmp 3f
2713:
272
1c79356b
A
273/*
274 * Get startup parameters.
275 */
6601e61a
A
276
277 movl %ebx,PA(EXT(boot_args_start)) /* Save KERNBOOTSTRUCT */
278
91447636
A
279 movl KADDR(%ebx), %eax
280 addl KSIZE(%ebx), %eax
281 addl $(NBPG-1),%eax
282 andl $(-NBPG), %eax
6601e61a 283 movl %eax, PA(EXT(KERNend))
91447636
A
284 movl %eax, PA(physfree)
285 cld
1c79356b 286
91447636
A
287/* allocate kernel page table pages */
288 ALLOCPAGES(NKPT)
6601e61a 289 movl %esi,PA(EXT(KPTphys))
1c79356b 290
91447636
A
291#ifdef PAE
292/* allocate Page Table Directory Page */
293 ALLOCPAGES(1)
294 movl %esi,PA(EXT(IdlePDPT))
295#endif
1c79356b 296
91447636
A
297/* allocate kernel page directory page */
298 ALLOCPAGES(NPGPTD)
299 movl %esi,PA(EXT(IdlePTD))
1c79356b 300
91447636
A
301/* map from zero to end of kernel */
302 xorl %eax,%eax
303 movl PA(physfree),%ecx
304 shrl $(PAGE_SHIFT),%ecx
305 fillkptphys( $(PTE_W) )
306
307/* map page directory */
308#ifdef PAE
309 movl PA(EXT(IdlePDPT)), %eax
310 movl $1, %ecx
311 fillkptphys( $(PTE_W) )
312#endif
313 movl PA(EXT(IdlePTD)),%eax
314 movl $(NPGPTD), %ecx
315 fillkptphys( $(PTE_W) )
316
317/* install a pde for temp double map of bottom of VA */
6601e61a 318 movl PA(EXT(KPTphys)),%eax
91447636
A
319 xorl %ebx,%ebx
320 movl $(NKPT), %ecx
321 fillkpt(PA(EXT(IdlePTD)), $(PTE_W))
322
323/* install pde's for page tables */
6601e61a 324 movl PA(EXT(KPTphys)),%eax
91447636
A
325 movl $(KPTDI),%ebx
326 movl $(NKPT),%ecx
327 fillkpt(PA(EXT(IdlePTD)), $(PTE_W))
328
329/* install a pde recursively mapping page directory as a page table */
330 movl PA(EXT(IdlePTD)),%eax
331 movl $(PTDPTDI),%ebx
332 movl $(NPGPTD),%ecx
333 fillkpt(PA(EXT(IdlePTD)), $(PTE_W))
334
335#ifdef PAE
336 movl PA(EXT(IdlePTD)), %eax
337 xorl %ebx, %ebx
338 movl $(NPGPTD), %ecx
339 fillkpt(PA(EXT(IdlePDPT)), $0)
340#endif
1c79356b 341
91447636 342/* install a pde page for commpage use up in high memory */
1c79356b 343
91447636
A
344 movl PA(physfree),%eax /* grab next phys page */
345 movl %eax,%ebx
346 addl $(PAGE_SIZE),%ebx
347 movl %ebx,PA(physfree) /* show next free phys pg */
348 movl $(COMM_PAGE_BASE_ADDR),%ebx
349 shrl $(PDESHIFT),%ebx /* index into pde page */
350 movl $(1), %ecx /* # pdes to store */
351 fillkpt(PA(EXT(IdlePTD)), $(PTE_W|PTE_U)) /* user has access! */
1c79356b 352
91447636 353 movl PA(physfree),%edi
1c79356b
A
354 movl %edi,PA(EXT(first_avail)) /* save first available phys addr */
355
91447636 356#ifdef PAE
1c79356b 357/*
91447636
A
358 * We steal 0x4000 for a temp pdpt and 0x5000-0x8000
359 * for temp pde pages in the PAE case. Once we are
360 * running at the proper virtual address we switch to
361 * the PDPT/PDE's the master is using */
362
363 /* clear pdpt page to be safe */
364 xorl %eax, %eax
365 movl $(PAGE_SIZE),%ecx
366 movl $(0x4000),%edi
367 cld
368 rep
369 stosb
370
371 /* build temp pdpt */
372 movl $(0x5000), %eax
373 xorl %ebx, %ebx
374 movl $(NPGPTD), %ecx
375 fillkpt($(0x4000), $0)
376
377 /* copy the NPGPTD pages of pdes */
378 movl PA(EXT(IdlePTD)),%eax
379 movl $0x5000,%ebx
380 movl $((PTEMASK+1)*NPGPTD),%ecx
3811: movl 0(%eax),%edx
382 movl %edx,0(%ebx)
383 movl 4(%eax),%edx
384 movl %edx,4(%ebx)
385 addl $(PTESIZE),%eax
386 addl $(PTESIZE),%ebx
387 loop 1b
388#else
389/* create temp pde for slaves to use
390 use unused lomem page and copy in IdlePTD */
391 movl PA(EXT(IdlePTD)),%eax
392 movl $0x4000,%ebx
393 movl $(PTEMASK+1),%ecx
3941: movl 0(%eax),%edx
395 movl %edx,0(%ebx)
396 addl $(PTESIZE),%eax
397 addl $(PTESIZE),%ebx
398 loop 1b
399#endif
400
6601e61a 401 POSTCODE(PSTART_PAGE_TABLES);
1c79356b
A
402
403/*
404 * Fix initial descriptor tables.
405 */
6601e61a 406 lea PA(EXT(idt)),%esi /* fix IDT */
1c79356b
A
407 movl $(IDTSZ),%ecx
408 movl $(PA(fix_idt_ret)),%ebx
409 jmp fix_desc_common /* (cannot use stack) */
410fix_idt_ret:
411
6601e61a 412 lea PA(EXT(gdt)),%esi /* fix GDT */
1c79356b
A
413 movl $(GDTSZ),%ecx
414 movl $(PA(fix_gdt_ret)),%ebx
415 jmp fix_desc_common /* (cannot use stack) */
416fix_gdt_ret:
417
6601e61a 418 lea PA(EXT(ldt)),%esi /* fix LDT */
1c79356b
A
419 movl $(LDTSZ),%ecx
420 movl $(PA(fix_ldt_ret)),%ebx
421 jmp fix_desc_common /* (cannot use stack) */
422fix_ldt_ret:
423
424/*
91447636 425 *
1c79356b 426 */
1c79356b 427
91447636
A
428 lgdt PA(EXT(gdtptr)) /* load GDT */
429 lidt PA(EXT(idtptr)) /* load IDT */
1c79356b 430
6601e61a 431 POSTCODE(PSTART_BEFORE_PAGING);
1c79356b
A
432
433/*
91447636 434 * Turn on paging.
1c79356b 435 */
91447636
A
436#ifdef PAE
437 movl PA(EXT(IdlePDPT)), %eax
438 movl %eax, %cr3
439
440 movl %cr4, %eax
6601e61a 441 orl $(CR4_PAE), %eax
91447636
A
442 movl %eax, %cr4
443#else
444 movl PA(EXT(IdlePTD)), %eax
445 movl %eax,%cr3
446#endif
447
448 movl %cr0,%eax
449 orl $(CR0_PG|CR0_WP|CR0_PE),%eax
450 movl %eax,%cr0 /* to enable paging */
451
1c79356b
A
452 LJMP(KERNEL_CS,EXT(vstart)) /* switch to kernel code segment */
453
454/*
6601e61a 455 * Master is now running with correct addresses.
1c79356b
A
456 */
457LEXT(vstart)
91447636
A
458 POSTCODE(VSTART_ENTRY) ;
459
1c79356b
A
460 mov $(KERNEL_DS),%ax /* set kernel data segment */
461 mov %ax,%ds
462 mov %ax,%es
463 mov %ax,%ss
6601e61a 464 mov %ax,EXT(ktss)+TSS_SS0 /* set kernel stack segment */
1c79356b
A
465 /* for traps to kernel */
466#if MACH_KDB
6601e61a 467 mov %ax,EXT(dbtss)+TSS_SS0 /* likewise for debug task switch */
1c79356b 468 mov %cr3,%eax /* get PDBR into debug TSS */
6601e61a 469 mov %eax,EXT(dbtss)+TSS_PDBR
1c79356b
A
470 mov $0,%eax
471#endif
472
473 movw $(KERNEL_LDT),%ax /* get LDT segment */
474 lldt %ax /* load LDT */
475#if MACH_KDB
6601e61a
A
476 mov %ax,EXT(ktss)+TSS_LDT /* store LDT in two TSS, as well... */
477 mov %ax,EXT(dbtss)+TSS_LDT /* ...matters if we switch tasks */
1c79356b
A
478#endif
479 movw $(KERNEL_TSS),%ax
480 ltr %ax /* set up KTSS */
481
91447636 482 mov $(CPU_DATA_GS),%ax
1c79356b
A
483 mov %ax,%gs
484
6601e61a 485 POSTCODE(VSTART_STACK_SWITCH);
91447636 486
6601e61a
A
487 lea EXT(eintstack),%esp /* switch to the bootup stack */
488 call EXT(i386_preinit)
91447636 489
6601e61a 490 POSTCODE(VSTART_EXIT);
91447636 491
55e303ae 492 call EXT(i386_init) /* run C code */
1c79356b
A
493 /*NOTREACHED*/
494 hlt
495
6601e61a
A
496 .text
497 .globl __start
498 .set __start, PA(EXT(pstart))
8f6c56a5 499
6601e61a 500
8f6c56a5 501/*
6601e61a
A
502 * master_up is used by the master cpu to signify that it is done
503 * with the interrupt stack, etc. See the code in pstart and svstart
504 * that this interlocks with.
21362eb3
A
505 */
506 .align ALIGN
6601e61a
A
507 .globl EXT(master_up)
508LEXT(master_up)
509 pushl %ebp /* set up */
510 movl %esp,%ebp /* stack frame */
511 movl $0,%ecx /* unlock start_lock */
512 xchgl %ecx,EXT(start_lock) /* since we are no longer using */
513 /* bootstrap stack */
514 leave /* pop stack frame */
515 ret
516
517/*
518 * We aren't the first. Call slave_main to initialize the processor
519 * and get Mach going on it.
520 */
521 .align ALIGN
522 .globl EXT(slave_start)
523LEXT(slave_start)
1c79356b
A
524 cli /* disable interrupts, so we don`t */
525 /* need IDT for a while */
91447636 526
6601e61a 527 POSTCODE(SLAVE_START_ENTRY);
91447636
A
528/*
529 * Turn on paging.
530 */
6601e61a
A
531 movl $(EXT(spag_start)),%edx /* first paged code address */
532
91447636 533#ifdef PAE
6601e61a
A
534 movl $(0x4000), %eax
535 movl %eax, %cr3
536
91447636 537 movl %cr4, %eax
6601e61a 538 orl $(CR4_PAE), %eax
91447636 539 movl %eax, %cr4
6601e61a 540#else
91447636
A
541 movl $(0x4000),%eax /* tmp until we get mapped */
542 movl %eax,%cr3
6601e61a 543#endif
1c79356b
A
544
545 movl %cr0,%eax
91447636 546 orl $(CR0_PG|CR0_WP|CR0_PE),%eax
1c79356b
A
547 movl %eax,%cr0 /* to enable paging */
548
6601e61a 549 POSTCODE(SLAVE_START_EXIT);
91447636
A
550
551 jmp *%edx /* flush prefetch queue */
1c79356b
A
552
553/*
554 * We are now paging, and can run with correct addresses.
555 */
556LEXT(spag_start)
557
91447636
A
558 lgdt PA(EXT(gdtptr)) /* load GDT */
559 lidt PA(EXT(idtptr)) /* load IDT */
560
6601e61a 561 LJMP(KERNEL_CS,EXT(svstart)) /* switch to kernel code segment */
1c79356b 562
91447636 563
1c79356b
A
564/*
565 * Slave is now running with correct addresses.
566 */
6601e61a 567LEXT(svstart)
91447636 568
6601e61a 569 POSTCODE(SVSTART_ENTRY);
91447636
A
570
571#ifdef PAE
572 movl PA(EXT(IdlePDPT)), %eax
573 movl %eax, %cr3
574#else
575 movl PA(EXT(IdlePTD)), %eax
576 movl %eax, %cr3
577#endif
578
1c79356b
A
579 mov $(KERNEL_DS),%ax /* set kernel data segment */
580 mov %ax,%ds
581 mov %ax,%es
582 mov %ax,%ss
583
91447636
A
584 /*
585 * We're not quite through with the boot stack
586 * but we need to reset the stack pointer to the correct virtual
587 * address.
588 * And we need to offset above the address of pstart.
589 */
590 movl $(VA(MP_BOOTSTACK+MP_BOOT+4)), %esp
1c79356b
A
591
592/*
91447636 593 * Switch to the per-cpu descriptor tables
1c79356b 594 */
6601e61a 595 POSTCODE(SVSTART_DESC_INIT);
91447636
A
596
597 CPU_NUMBER_FROM_LAPIC(%eax)
598 movl CX(EXT(cpu_data_ptr),%eax),%ecx
6601e61a 599 movl CPU_DESC_TABLEP(%ecx), %ecx
1c79356b 600
1c79356b 601 movw $(GDTSZ*8-1),0(%esp) /* set GDT size in GDT descriptor */
6601e61a 602 leal MP_GDT(%ecx),%edx
91447636 603 movl %edx,2(%esp) /* point to local GDT (linear addr) */
1c79356b
A
604 lgdt 0(%esp) /* load new GDT */
605
606 movw $(IDTSZ*8-1),0(%esp) /* set IDT size in IDT descriptor */
6601e61a 607 leal MP_IDT(%ecx),%edx
91447636 608 movl %edx,2(%esp) /* point to local IDT (linear addr) */
1c79356b
A
609 lidt 0(%esp) /* load new IDT */
610
55e303ae
A
611 movw $(KERNEL_LDT),%ax /* get LDT segment */
612 lldt %ax /* load LDT */
613
1c79356b
A
614 movw $(KERNEL_TSS),%ax
615 ltr %ax /* load new KTSS */
616
91447636 617 mov $(CPU_DATA_GS),%ax
1c79356b
A
618 mov %ax,%gs
619
91447636
A
620/*
621 * Get stack top from pre-cpu data and switch
622 */
6601e61a 623 POSTCODE(SVSTART_STACK_SWITCH);
91447636
A
624
625 movl %gs:CPU_INT_STACK_TOP,%esp
626 xorl %ebp,%ebp /* for completeness */
627
6601e61a
A
628 movl $0,%eax /* unlock start_lock */
629 xchgl %eax,EXT(start_lock) /* since we are no longer using */
630 /* bootstrap stack */
631 POSTCODE(SVSTART_EXIT);
91447636
A
632
633 call EXT(i386_init_slave) /* start MACH */
1c79356b
A
634 /*NOTREACHED*/
635 hlt
1c79356b
A
636
637/*
638 * Convert a descriptor from fake to real format.
639 *
640 * Calls from assembly code:
641 * %ebx = return address (physical) CANNOT USE STACK
642 * %esi = descriptor table address (physical)
643 * %ecx = number of descriptors
644 *
645 * Calls from C:
646 * 0(%esp) = return address
647 * 4(%esp) = descriptor table address (physical)
648 * 8(%esp) = number of descriptors
649 *
650 * Fake descriptor format:
651 * bytes 0..3 base 31..0
652 * bytes 4..5 limit 15..0
653 * byte 6 access byte 2 | limit 19..16
654 * byte 7 access byte 1
655 *
656 * Real descriptor format:
657 * bytes 0..1 limit 15..0
658 * bytes 2..3 base 15..0
659 * byte 4 base 23..16
660 * byte 5 access byte 1
661 * byte 6 access byte 2 | limit 19..16
662 * byte 7 base 31..24
663 *
664 * Fake gate format:
665 * bytes 0..3 offset
666 * bytes 4..5 selector
667 * byte 6 word count << 4 (to match fake descriptor)
668 * byte 7 access byte 1
669 *
670 * Real gate format:
671 * bytes 0..1 offset 15..0
672 * bytes 2..3 selector
673 * byte 4 word count
674 * byte 5 access byte 1
675 * bytes 6..7 offset 31..16
676 */
677 .globl EXT(fix_desc)
678LEXT(fix_desc)
679 pushl %ebp /* set up */
680 movl %esp,%ebp /* stack frame */
681 pushl %esi /* save registers */
682 pushl %ebx
683 movl B_ARG0,%esi /* point to first descriptor */
684 movl B_ARG1,%ecx /* get number of descriptors */
685 lea 0f,%ebx /* get return address */
686 jmp fix_desc_common /* call internal routine */
6870: popl %ebx /* restore registers */
688 popl %esi
689 leave /* pop stack frame */
690 ret /* return */
691
692fix_desc_common:
6930:
694 movw 6(%esi),%dx /* get access byte */
695 movb %dh,%al
696 andb $0x14,%al
697 cmpb $0x04,%al /* gate or descriptor? */
698 je 1f
699
700/* descriptor */
701 movl 0(%esi),%eax /* get base in eax */
702 rol $16,%eax /* swap 15..0 with 31..16 */
703 /* (15..0 in correct place) */
704 movb %al,%dl /* combine bits 23..16 with ACC1 */
705 /* in dh/dl */
706 movb %ah,7(%esi) /* store bits 31..24 in correct place */
707 movw 4(%esi),%ax /* move limit bits 0..15 to word 0 */
708 movl %eax,0(%esi) /* store (bytes 0..3 correct) */
709 movw %dx,4(%esi) /* store bytes 4..5 */
710 jmp 2f
711
712/* gate */
7131:
714 movw 4(%esi),%ax /* get selector */
715 shrb $4,%dl /* shift word count to proper place */
716 movw %dx,4(%esi) /* store word count / ACC1 */
717 movw 2(%esi),%dx /* get offset 16..31 */
718 movw %dx,6(%esi) /* store in correct place */
719 movw %ax,2(%esi) /* store selector in correct place */
7202:
721 addl $8,%esi /* bump to next descriptor */
722 loop 0b /* repeat */
723 jmp *%ebx /* all done */
724
725/*
726 * put arg in kbd leds and spin a while
727 * eats eax, ecx, edx
728 */
729#define K_RDWR 0x60
730#define K_CMD_LEDS 0xed
731#define K_STATUS 0x64
732#define K_IBUF_FULL 0x02 /* input (to kbd) buffer full */
733#define K_OBUF_FULL 0x01 /* output (from kbd) buffer full */
734
735ENTRY(set_kbd_leds)
736 mov S_ARG0,%cl /* save led value */
737
7380: inb $(K_STATUS),%al /* get kbd status */
739 testb $(K_IBUF_FULL),%al /* input busy? */
740 jne 0b /* loop until not */
741
742 mov $(K_CMD_LEDS),%al /* K_CMD_LEDS */
743 outb %al,$(K_RDWR) /* to kbd */
744
7450: inb $(K_STATUS),%al /* get kbd status */
746 testb $(K_OBUF_FULL),%al /* output present? */
747 je 0b /* loop if not */
748
749 inb $(K_RDWR),%al /* read status (and discard) */
750
7510: inb $(K_STATUS),%al /* get kbd status */
752 testb $(K_IBUF_FULL),%al /* input busy? */
753 jne 0b /* loop until not */
754
755 mov %cl,%al /* move led value */
756 outb %al,$(K_RDWR) /* to kbd */
757
758 movl $10000000,%ecx /* spin */
7590: nop
760 nop
761 loop 0b /* a while */
762
763 ret