Adjust memory layout for 2.6.22+ kernels with 32KB setup code
[mknbi.git] / startmenu.S
1 /*
2  * Converted to use Eric Biederman's _real_call routine which frees
3  * the 16 bit code from running in the same 64kB segment as the
4  * 32 bit code's stack.
5  */
6
7 /* #defines because ljmp wants a number, probably gas bug */
8 /*      .equ    KERN_CODE_SEG,_pmcs-_gdt        */
9 #define KERN_CODE_SEG   0x08
10         .equ    KERN_DATA_SEG,_pmds-_gdt
11 /*      .equ    REAL_CODE_SEG,_rmcs-_gdt        */
12 #define REAL_CODE_SEG   0x18
13         .equ    REAL_DATA_SEG,_rmds-_gdt
14         .equ    CR0_PE,1
15
16 #ifdef  GAS291
17 #define DATA32 data32;
18 #define ADDR32 addr32;
19 #define LJMPI(x)        ljmp    x
20 #else
21 #define DATA32 data32
22 #define ADDR32 addr32
23 /* newer GAS295 require #define LJMPI(x)        ljmp    *x */
24 #define LJMPI(x)        ljmp    x
25 #endif
26
27 #define DO_REAL_CALL    pushl $10f; pushl $20f-10f; call _real_call; .section ".text16"; 10: .code16
28 #define DO_REAL_RETURN  ret; 20: .code32; .previous
29
30         .section        ".text"
31         .section        ".text16","ax",@progbits
32         .previous
33         .code32
34         .arch   i386
35
36 /*
37  * NOTE: if you write a subroutine that is called from C code (gcc/egcs),
38  * then you only have to take care of %ebx, %esi, %edi and %ebp.  These
39  * registers must not be altered under any circumstance.  All other registers
40  * may be clobbered without any negative side effects.  If you don't follow
41  * this rule then you'll run into strange effects that only occur on some
42  * gcc versions (because the register allocator may use different registers).
43  *
44  * All the data32 prefixes for the ljmp instructions are necessary, because
45  * the assembler emits code with a relocation address of 0.  This means that
46  * all destinations are initially negative, which the assembler doesn't grok,
47  * because for some reason negative numbers don't fit into 16 bits. The addr32
48  * prefixes are there for the same reasons, because otherwise the memory
49  * references are only 16 bit wide.  Theoretically they are all superfluous.
50  */
51
52 /**************************************************************************
53 START - Where all the fun begins....
54 **************************************************************************/
55 /* this must be the first thing in the file because we enter from the top */
56         .global _start
57 _start:
58 /* We have to use our own GDT when running in our segment because the old
59    GDT will have the wrong descriptors for the real code segments */
60         sgdt    gdtsave         /* save old GDT */
61         lgdt    gdtarg          /* load ours */
62         /* reload the segment registers */
63         movl    $KERN_DATA_SEG,%eax
64         movl    %eax,%ds
65         movl    %eax,%es
66         movl    %eax,%ss
67         movl    %eax,%fs
68         movl    %eax,%gs
69         /* flush prefetch queue, and reload %cs:%eip */
70         ljmp    $KERN_CODE_SEG,$1f
71 1:
72         /* save the stack pointer and call the routine */
73         movl    %esp,%eax
74         movl    %eax,initsp
75         movl    $RELOC+0x20000,%esp     /* change stack */
76         pushl   12(%eax)        /* replicate args on new stack */
77         pushl   8(%eax)
78         pushl   4(%eax)
79         call    menu
80 _exit:
81 /*      we reset sp to the location just before entering first
82         instead of relying on the return from menu because exit
83         could have been called from anywhere */
84         movl    initsp,%ebx
85         movl    %ebx,%esp
86         lgdt    gdtsave         /* restore old GDT */
87         ret
88
89         .globl  exit
90 exit:   movl    4(%esp),%eax
91         jmp     _exit
92
93 /**************************************************************************
94 SET_SEG_BASE - Set the base address of a segment register
95 Stolen from Etherboot 5.1. With thanks to Eric Biederman
96 **************************************************************************/
97         /* .globl set_seg_base */
98 set_seg_base:
99         /* Low half of the gdt base */
100         movl    4(%esp), %eax
101         shll    $16, %eax
102
103         /* High half of the gdt base */ 
104         movl    4(%esp), %ecx
105         shrl    $16, %ecx
106         andl    $0xff, %ecx
107
108         movl    4(%esp), %edx
109         andl    $0xff000000, %edx
110         orl     %edx, %ecx
111
112         movl    8(%esp), %edx
113
114         /* Fixup the code segment */
115         andl    $0x0000ffff,  0(%edx)
116         orl     %eax       ,  0(%edx)
117         andl    $0x00ffff00,  4(%edx)
118         orl     %ecx       ,  4(%edx)
119
120         /* Fixup the data segment */
121         andl    $0x0000ffff,  8(%edx)
122         orl     %eax       ,  8(%edx)
123         andl    $0x00ffff00, 12(%edx)
124         orl     %ecx       , 12(%edx)
125
126         ret
127
128 /**************************************************************************
129 _REAL_CALL - Run some code in real mode.
130 Stolen from Etherboot 5.1. With thanks to Eric Biederman
131 **************************************************************************/
132         /* MAX_REAL_MODE_STACK is carefully tuned to work
133          * with the stack bottom at 0x7c00 while not chancing
134          * overwriting data below 0x500.
135          */
136 #define MAX_REAL_MODE_STACK 29696
137 #define RADDR(sym)      (((sym) - _end16) + MAX_REAL_MODE_STACK)
138
139         .balign 4
140         /* .globl real_mode_stack */
141 real_mode_stack:
142         .long 0x7c00  /* Put the stack just below the dos load address */
143 real_stack_top:
144         .long 0
145 _save_esp:
146         .long 0
147
148         /* .globl _real_call */
149 _real_call:
150         /* Save the original %esp value */
151         movl    %esp, _save_esp
152
153         /* Save the temporary registers I use */
154         pushl   $0
155         pushl   %ebx
156         pushl   %ecx
157         pushl   %edx
158         pushl   %esi
159         pushl   %edi
160         pushl   %ebp
161
162         /* Load up the registers */
163         movl    32(%esp), %ecx          /* The 16bit code len */
164         movl    36(%esp), %esi          /* The 16bit code start */
165         movl    virt_offset, %ebp       /* The virtual offset */
166
167         /* stack top = phys_to_virt(real_mode_stack - MAX_REAL_MODE_STACK) */
168         movl    real_mode_stack, %ebx   /* The stack top */
169         subl    $MAX_REAL_MODE_STACK, %ebx
170         movl    %ebx, real_stack_top
171         subl    %ebp, %ebx
172
173         /* Save the real mode stack top */
174         movl    %ebx, 24(%esp)
175
176         /* Compute where the copied code goes */
177         leal    RADDR(__real_call)(%ebx), %edi
178         subl    %ecx, %edi
179         andl    $0xfffffffc, %edi       /* 4 byte aligned */
180
181         /* Remember where the code is executed */
182         movl    %edi, %eax
183         subl    %ebx, %eax
184         movw    %ax, real_ip
185
186         /* Copy the user code onto the real mode stack */
187         rep
188         movsb
189
190         /* Copy the trampoline onto the stack */
191         movl    $__real_call, %esi
192         movl    $_end16 - __real_call, %ecx
193         leal    RADDR(__real_call)(%ebx), %edi
194         rep
195         movsb
196
197         /* Fixup real_gdtarg */
198         leal    _gdt(%ebp), %eax
199         movl    %eax, RADDR(real_gdtarg +2)(%ebx)
200
201         /* Fixup the gdt */
202         pushl   $_rmcs
203         leal    0(%ebx, %ebp), %eax
204         pushl   %eax
205         call    set_seg_base
206         addl    $8, %esp
207
208         /* Restore the saved registers */
209         popl    %ebp
210         popl    %edi
211         popl    %esi
212         popl    %edx
213         popl    %ecx
214         popl    %ebx
215
216         /* And switch stacks */
217         popl    %esp
218         movzwl  RADDR(real_ip)(%esp), %eax
219         addl    %eax, %esp
220
221         /* Setup for jump to real mode */
222         movl    real_stack_top, %eax
223         shrl    $4, %eax
224         pushw   %ax
225         pushw   $RADDR(real16)
226
227         /* Switch stack from %esp 32bit virtual to %sp 16bit physical */
228         addl    virt_offset, %esp
229         subl    real_stack_top, %esp
230
231         /* Jump to 16bit code */
232         ljmp    $REAL_CODE_SEG, $RADDR(code16)  /* jump to a 16 bit segment */
233 _real_call_ret:
234         /* reload  segment registers */
235         movl    $KERN_DATA_SEG,%eax
236         movl    %eax,%ds
237         movl    %eax,%es
238         movl    %eax,%ss
239         movl    %eax,%fs
240         movl    %eax,%gs
241
242         /* Restore the stack */
243         movl    _save_esp, %esp
244
245         /* Restore the direction flag */
246         cld
247
248         /* Get the real mode stack pointer */
249         movl    real_stack_top, %eax
250         subl    virt_offset, %eax
251         pushl   %eax
252         movzwl  RADDR(real_sp)(%eax), %eax
253         addl    0(%esp), %eax
254         addl    $4, %esp
255
256         /* Return to my caller */
257         ret     $8
258
259
260         .balign 16
261 __real_call:
262 real_sp:
263         .word 0
264 real_ip:
265         .word 0
266 real_gdtarg:
267         .word   _gdt_end - _gdt - 1     /* limit */
268         .long   _gdt                    /* addr */
269         .code16
270 code16:
271         /* Load 16bit segment descriptors to force 16bit segment limit */
272         movw    $REAL_DATA_SEG, %ax
273         movw    %ax,%ds
274         movw    %ax,%ss
275         movw    %ax,%es
276         movw    %ax,%fs
277         movw    %ax,%gs
278
279         /* clear the PE bit of CR0 */
280         movl    %cr0,%eax
281         andb    $0!CR0_PE,%al
282         movl    %eax,%cr0
283
284         /* make intersegment jmp to flush the processor pipeline
285          * and reload %cs:%eip (to clear upper 16 bits of %eip).
286          */
287         lret
288 real16: 
289         /* we are in real mode now
290          * set up the real mode segment registers : %ds, $ss, %es
291          */
292         movw    %cs, %ax
293         movw    %ax, %ss
294         movw    %ax, %ds
295         movw    %ax, %fs
296         movw    %ax, %gs
297
298         /* Enable interrupts */
299         sti
300
301         /* Call the user supplied code */
302         call    *RADDR(real_ip)
303
304         /* Save the stack pointer */
305         /* Reload %ds */
306         movw    %cs, %ax
307         movw    %ax, %ds
308         movw    %sp, RADDR(real_sp)
309
310         /* Disable interrupts */
311         cli
312
313         /* Switch back to protected mode */
314         cs
315         DATA32 lgdt RADDR(real_gdtarg)
316         movl    %cr0, %eax
317         orb     $CR0_PE, %al
318         movl    %eax, %cr0      /* turn on protected mode */
319
320         /* flush prefetch queue, and reload %cs:%eip */
321         DATA32 ljmp     $KERN_CODE_SEG, $_real_call_ret
322         .code32
323 __end16:
324         .balign 16
325 _end16:
326         .code32
327
328 /**************************************************************************
329 CURRTICKS - Get Time
330 Use direct memory access to BIOS variables, longword 0040:006C (ticks
331 today) and byte 0040:0070 (midnight crossover flag) instead of calling
332 timeofday BIOS interrupt.
333 **************************************************************************/
334         .globl  currticks
335 currticks:
336         pushl   %ebp
337         pushl   %ebx
338         pushl   %esi
339         pushl   %edi
340
341         DO_REAL_CALL
342         DO_REAL_RETURN
343
344         movl    virt_offset,%ebp
345         negl    %ebp
346         movl    0x46C(%ebp), %eax
347         movb    0x470(%ebp), %bl
348         cmpb    $0, %bl
349         je      notmidnite
350         movb    $0, 0x470(%ebp)         /* clear the flag */
351         addl    $0x1800b0,days          /* 0x1800b0 ticks per day */
352 notmidnite:
353         addl    days,%eax
354         popl    %edi
355         popl    %esi
356         popl    %ebx
357         popl    %ebp
358         ret
359
360 /**************************************************************************
361 console_cls()
362 BIOS call "INT 10H Function 0Fh" to get current video mode
363         Call with       %ah = 0x0f
364         Returns         %al = (video mode)
365                         %bh = (page number)
366 BIOS call "INT 10H Function 00h" to set the video mode (clears screen)
367         Call with       %ah = 0x00
368                         %al = (video mode)
369 **************************************************************************/
370         .globl  console_cls
371 console_cls:
372         pushl   %ebx
373         pushl   %esi
374         pushl   %edi
375
376         DO_REAL_CALL
377         movb    $0xf, %ah
378         int     $0x10                   /* Get Current Video mode */
379         xorb    %ah, %ah
380         int     $0x10                   /* Set Video mode (clears screen) */
381         DO_REAL_RETURN
382
383         popl    %edi
384         popl    %esi
385         popl    %ebx
386         ret
387
388 /**************************************************************************
389 console_nocursor()
390 BIOS call "INT 10H Function 01h" to set cursor type
391         Call with       %ah = 0x01
392                         %ch = cursor starting scanline
393                         %cl = cursor ending scanline
394 **************************************************************************/
395         .globl  console_nocursor
396 console_nocursor:
397         pushl   %ebx
398         pushl   %esi
399         pushl   %edi
400
401         DO_REAL_CALL
402         movw    $0x2000, %cx
403         movb    $0x1, %ah
404         int     $0x10 
405         DO_REAL_RETURN
406
407         popl    %edi
408         popl    %esi
409         popl    %ebx
410         ret
411
412 /**************************************************************************
413 console_getxy()
414 BIOS call "INT 10H Function 03h" to get cursor position
415         Call with       %ah = 0x03
416                         %bh = page
417         Returns         %ch = starting scan line
418                         %cl = ending scan line
419                         %dh = row (0 is top)
420                         %dl = column (0 is left)
421 **************************************************************************/
422         .globl  console_getxy
423 console_getxy:
424         pushl   %ebx
425         pushl   %esi
426         pushl   %edi
427
428         DO_REAL_CALL
429         xorb    %bh, %bh                /* set page to 0 */
430         movb    $0x3, %ah
431         int     $0x10                   /* get cursor position */
432         DO_REAL_RETURN
433
434         xor     %eax, %eax
435         movb    %dl, %ah
436         movb    %dh, %al
437
438         popl    %edi
439         popl    %esi
440         popl    %ebx
441         ret
442
443
444 /**************************************************************************
445 console_gotoxy(x,y)
446 BIOS call "INT 10H Function 02h" to set cursor position
447         Call with       %ah = 0x02
448                         %bh = page
449                         %dh = row (0 is top)
450                         %dl = column (0 is left)
451 **************************************************************************/
452         .globl  console_gotoxy
453 console_gotoxy:
454         pushl   %ebp
455         movl    %esp,%ebp
456         pushl   %ebx
457         pushl   %esi
458         pushl   %edi
459
460         movb    0x8(%ebp), %dl           /* %dl = x */
461         movb    0xC(%ebp), %dh           /* %dh = y */
462
463         DO_REAL_CALL
464         xorb    %bh, %bh                /* set page to 0 */
465         movb    $0x2, %ah
466         int     $0x10                   /* set cursor position */
467         DO_REAL_RETURN
468
469         popl    %edi
470         popl    %esi
471         popl    %ebx
472         popl    %ebp
473         ret
474
475
476 /**************************************************************************
477  * console_setattrib(attr) :  Sets the character attributes for character at
478  *              current cursor position.
479  *
480  *  Bitfields for character's display attribute:
481  *  Bit(s)      Description
482  *   7          foreground blink
483  *   6-4        background color
484  *   3          foreground bright
485  *   2-0        foreground color
486  *
487  *  Values for character color:
488  *              Normal          Bright
489  *   000b       black           dark gray
490  *   001b       blue            light blue
491  *   010b       green           light green
492  *   011b       cyan            light cyan
493  *   100b       red             light red
494  *   101b       magenta         light magenta
495  *   110b       brown           yellow
496  *   111b       light gray      white
497  *
498  * BIOS call "INT 10H Function 08h" to read character and attribute data
499  *      Call with       %ah = 0x08
500  *                      %bh = page
501  *      Returns         %ah = character attribute
502  *                      %al = character value
503  * BIOS call "INT 10H Function 09h" to write character and attribute data
504  *      Call with       %ah = 0x09
505  *                      %al = character value
506  *                      %bh = page
507  *                      %bl = character attribute
508  *                      %cx = count to display (???, possible side-effects!!)
509 **************************************************************************/
510         .globl  console_setattrib
511 console_setattrib:
512         pushl   %ebp
513         movl    %esp,%ebp
514         pushl   %ebx
515         pushl   %esi
516         pushl   %edi
517
518         movl    0x8(%ebp), %ecx
519         xorl    %ebx, %ebx
520
521         DO_REAL_CALL
522         movb    $0x8, %ah
523         int     $0x10
524         movb    $0x9, %ah
525         movb    %cl, %bl
526         movw    $1, %cx
527         int     $0x10
528         DO_REAL_RETURN
529
530         popl    %edi
531         popl    %esi
532         popl    %ebx
533         popl    %ebp
534         ret
535
536
537 /**************************************************************************
538 CONSOLE_PUTC - Print a character on console
539 **************************************************************************/
540         .globl  console_putc
541 console_putc:
542         pushl   %ebp
543         movl    %esp,%ebp
544         pushl   %ebx
545         pushl   %esi
546         pushl   %edi
547         movb    8(%ebp),%cl
548
549         DO_REAL_CALL
550         movl    $1,%ebx
551         movb    $0x0e,%ah
552         movb    %cl,%al
553         int     $0x10
554         DO_REAL_RETURN
555
556         popl    %edi
557         popl    %esi
558         popl    %ebx
559         popl    %ebp
560         ret
561
562 /**************************************************************************
563 CONSOLE_GETC - Get a character from console
564  **************************************************************************/
565         .globl  console_getc
566 console_getc:
567         pushl   %ebx
568         pushl   %esi
569         pushl   %edi
570
571         DO_REAL_CALL
572         movb    $0x0,%ah
573         int     $0x16
574         movb    %al,%bl
575         DO_REAL_RETURN
576
577         xor     %eax,%eax
578         movzbl  %bl,%eax
579         popl    %edi
580         popl    %esi
581         popl    %ebx
582         ret
583
584 /**************************************************************************
585 console_getkey()
586 BIOS call "INT 16H Function 00H" to read character from keyboard
587 Call with       %ah = 0x10
588 Return:         %ah = keyboard scan code
589                 %al = ASCII character
590  **************************************************************************/
591         .globl  console_getkey
592 console_getkey:
593         pushl   %ebx
594         pushl   %esi
595         pushl   %edi
596
597         DO_REAL_CALL
598         movb    $0x0,%ah
599         int     $0x16
600         movw    %ax, %bx
601         DO_REAL_RETURN
602
603         movzwl  %bx, %eax
604         popl    %edi
605         popl    %esi
606         popl    %ebx
607         ret
608
609
610 /**************************************************************************
611 console_checkkey()
612 if there is a character pending, return it; otherwise return -1
613 BIOS call "INT 16H Function 01H" to check whether a character is pending
614 Call with       %ah = 0x1
615 Return:
616                 If key waiting to be input:
617                 %ah = keyboard scan code
618                 %al = ASCII character
619                 Zero flag = clear
620         else
621                 Zero flag = set
622  **************************************************************************/
623         .globl  console_checkkey
624 console_checkkey:
625         pushl   %ebx
626         pushl   %esi
627         pushl   %edi
628         xorl    %ebx, %ebx
629
630         DO_REAL_CALL
631         movb    $0x1, %ah
632         int     $0x16
633         jz      1f
634         movzwl  %ax, %ebx
635         jmp     2f
636 1:
637         movl    $0xFFFFFFFF, %ebx
638 2:
639         DO_REAL_RETURN
640
641         movl    %ebx, %eax
642         popl    %edi
643         popl    %esi
644         popl    %ebx
645         ret
646
647 /**************************************************************************
648 ISCHAR - Check for keyboard interrupt
649 **************************************************************************/
650         .globl  console_ischar
651 console_ischar:
652         pushl   %ebx
653         pushl   %esi
654         pushl   %edi
655
656         DO_REAL_CALL
657         xorw    %bx,%bx
658         movb    $0x1,%ah
659         int     $0x16
660         jz      2f
661         movb    %al,%bl
662 2:      
663         DO_REAL_RETURN
664
665         movzbl  %bl,%eax
666         popl    %edi
667         popl    %esi
668         popl    %ebx
669         ret
670
671 /**************************************************************************
672 GETSHIFT - Get keyboard shift state
673 **************************************************************************/
674         .globl  console_getshift
675 console_getshift:
676         pushl   %ebx
677         pushl   %esi
678         pushl   %edi
679
680         DO_REAL_CALL
681         movb    $2,%ah
682         int     $0x16
683         andb    $0xdf,%al
684         movw    %ax,%bx
685         DO_REAL_RETURN
686
687         movzbl  %bl,%eax
688         popl    %edi
689         popl    %esi
690         popl    %ebx
691         ret
692
693 /**************************************************************************
694 INT10 - Call Interrupt 0x10
695 **************************************************************************/
696         .globl  _int10
697 _int10:
698         push    %ebp
699         mov     %esp,%ebp
700         push    %ebx
701         push    %esi
702         push    %edi
703         movw    8(%ebp),%si
704         movw    10(%ebp),%bx
705         movw    12(%ebp),%cx
706         movw    14(%ebp),%dx
707
708         DO_REAL_CALL
709         movw    %si,%ax
710         int     $0x10
711         movw    %ax,%si
712         DO_REAL_RETURN
713
714         movl    %esi,%eax
715         andl    $0xFFFF,%eax
716         movw    %ax,int10ret
717         movw    %bx,int10ret+2
718         shl     $16,%ebx
719         orl     %ebx,%eax
720         movw    %cx,int10ret+4
721         movw    %dx,int10ret+6
722         pop     %edi
723         pop     %esi
724         pop     %ebx
725         pop     %ebp
726         ret
727
728         .globl  int10ret
729 int10ret:
730         .word   0,0,0,0
731
732 /**************************************************************************
733 CPU_NAP - Save power by halting the CPU until the next interrupt
734 **************************************************************************/
735         .globl  cpu_nap
736 cpu_nap:
737         pushl   %ebx
738         pushl   %esi
739         pushl   %edi
740
741         DO_REAL_CALL
742         hlt
743         DO_REAL_RETURN
744
745         popl    %edi
746         popl    %esi
747         popl    %ebx
748         ret
749
750 /**************************************************************************
751 SETJMP - Save stack context for non-local goto
752 **************************************************************************/
753         .globl  setjmp
754 setjmp:
755         movl    4(%esp),%ecx
756         movl    0(%esp),%edx
757         movl    %edx,0(%ecx)
758         movl    %ebx,4(%ecx)
759         movl    %esp,8(%ecx)
760         movl    %ebp,12(%ecx)
761         movl    %esi,16(%ecx)
762         movl    %edi,20(%ecx)
763         movl    %eax,24(%ecx)
764         movl    $0,%eax
765         ret
766
767 /**************************************************************************
768 LONGJMP - Non-local jump to a saved stack context
769 **************************************************************************/
770         .globl  longjmp
771 longjmp:
772         movl    4(%esp),%edx
773         movl    8(%esp),%eax
774         movl    0(%edx),%ecx
775         movl    4(%edx),%ebx
776         movl    8(%edx),%esp
777         movl    12(%edx),%ebp
778         movl    16(%edx),%esi
779         movl    20(%edx),%edi
780         cmpl    $0,%eax
781         jne     1f
782         movl    $1,%eax
783 1:      movl    %ecx,0(%esp)
784         ret
785
786 /**************************************************************************
787 GLOBAL DESCRIPTOR TABLE
788 **************************************************************************/
789         .align  4
790 _gdt:
791 gdtarg:
792         .word   0x27                    /* limit */
793         .long   _gdt                    /* addr */
794         .byte   0,0
795
796 _pmcs:
797         /* 32 bit protected mode code segment */
798         .word   0xffff,0
799         .byte   0,0x9f,0xcf,0
800
801 _pmds:
802         /* 32 bit protected mode data segment */
803         .word   0xffff,0
804         .byte   0,0x93,0xcf,0
805
806 _rmcs:
807         /* 16 bit real mode code segment */
808         .word   0xffff,(0&0xffff)
809         .byte   (0>>16),0x9b,0x00,(0>>24)
810
811 _rmds:
812         /* 16 bit real mode data segment */
813         .word   0xffff,(0&0xffff)
814         .byte   (0>>16),0x93,0x00,(0>>24)
815
816 _gdt_end:
817
818 gdtsave:        .long   0,0,0                   /* previous GDT */
819
820 virt_offset:
821         .long   0
822
823 initsp: .long   0
824 days:   .long   0