1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
  
     | 
    
      	.globl	entry, __switch_context, __exit_context, halt, init_exceptions
	.text
	.align	4
/*
 * Entry point
 * We start execution from here.
 * It is assumed that CPU is in 32-bit protected mode and
 * all segments are 4GB and base zero (flat model).
 */
entry:
	/* Save boot context and switch to our main context.
	 * Main context is statically defined in C.
	 */
	pushl	%cs
	call	__switch_context
	/* We get here when the main context switches back to
	 * the boot context.
	 * Return to previous bootloader.
	 */
	ret
/*
 * Switch execution context
 * This saves registers, segments, and GDT in the stack, then
 * switches the stack, and restores everything from the new stack.
 * This function takes no argument. New stack pointer is
 * taken from global variable __context, and old stack pointer
 * is also saved to __context. This way we can just jump to
 * this routine to get back to the original context.
 *
 * Call this routine with lcall or pushl %cs; call.
 */
__switch_context:
	/* Save everything in current stack */
	pushfl		    /* 56 */
	pushl	%ds	    /* 52 */
	pushl	%es	    /* 48 */
	pushl	%fs	    /* 44 */
	pushl	%gs	    /* 40 */
	pushal		    /* 8 */
	subl	$8, %esp
	movw	%ss, (%esp) /* 0 */
	sgdt	2(%esp)	    /* 2 */
#if 0
	/* Swap %cs and %eip on the stack, so lret will work */
	movl	60(%esp), %eax
	xchgl	%eax, 64(%esp)
	movl	%eax, 60(%esp)
#endif
	/* At this point we don't know if we are on flat segment
	 * or relocated. So compute the address offset from %eip.
	 * Assuming CS.base==DS.base==SS.base.
	 */
	call	1f
1:	popl	%ebx
	subl	$1b, %ebx
	/* Interrupts are not allowed... */
	cli
	/* Current context pointer is our stack pointer */
	movl	%esp, %esi
	/* Normalize the ctx pointer */
	subl	%ebx, %esi
	/* Swap it with new value */
	xchgl	%esi, __context(%ebx)
	/* Adjust new ctx pointer for current address offset */
	addl	%ebx, %esi
	/* Load new %ss and %esp to temporary */
	movzwl	(%esi), %edx
	movl	20(%esi), %eax
	/* Load new GDT */
	lgdt	2(%esi)
	/* Load new stack segment with new GDT */
	movl	%edx, %ss
	/* Set new stack pointer, but we have to adjust it because
	 * pushal saves %esp value before pushal, and we want the value
	 * after pushal.
	 */
	leal	-32(%eax), %esp
	/* Load the rest from new stack */
	popal
	popl	%gs
	popl	%fs
	popl	%es
	popl	%ds
	popfl
	/* Finally, load new %cs and %eip */
	lret
__exit_context:
	/* Get back to the original context */
	pushl	%cs
	call	__switch_context
	/* We get here if the other context attempt to switch to this
	 * dead context. This should not happen. */
halt:
	cli
	hlt
	jmp	halt
/*
 * initialize exception handler. All exceptions end up in the same
 * C function.
 */
init_exceptions:
	pushl	%ebx
	pushl	%edi
        /* Initialize the Interrupt Descriptor table */
        leal    _idt, %edi
        leal    vec0, %ebx
        movl    $(0x08 << 16), %eax     /* cs selector */
1:      movw    %bx, %ax
        movl    %ebx, %edx
        movw    $0x8E00, %dx            /* Interrupt gate - dpl=0, present */
        movl    %eax, 0(%edi)
        movl    %edx, 4(%edi)
        addl    $6, %ebx
        addl    $8, %edi
        cmpl    $_idt_end, %edi
        jne     1b
        /* Load the Interrupt descriptor table */
        lidt    idtarg
	movl 	$0, %eax
	popl	%edi
	popl	%ebx
	ret
vec0:
        pushl   $0 /* error code */
        pushl   $0 /* vector */
        jmp int_hand
vec1:
        pushl   $0 /* error code */
        pushl   $1 /* vector */
        jmp int_hand
vec2:
        pushl   $0 /* error code */
        pushl   $2 /* vector */
        jmp int_hand
vec3:
        pushl   $0 /* error code */
        pushl   $3 /* vector */
        jmp     int_hand
vec4:
        pushl   $0 /* error code */
        pushl   $4 /* vector */
        jmp     int_hand
vec5:
        pushl   $0 /* error code */
        pushl   $5 /* vector */
        jmp     int_hand
vec6:
        pushl   $0 /* error code */
        pushl   $6 /* vector */
        jmp     int_hand
vec7:
        pushl   $0 /* error code */
        pushl   $7 /* vector */
        jmp     int_hand
vec8:
        /* error code */
        pushl   $8 /* vector */
        jmp     int_hand
        .word   0x9090
vec9:
        pushl   $0 /* error code */
        pushl   $9 /* vector */
        jmp int_hand
vec10:
        /* error code */
        pushl   $10 /* vector */
        jmp     int_hand
        .word   0x9090
vec11:
        /* error code */
        pushl   $11 /* vector */
        jmp     int_hand
        .word   0x9090
vec12:
        /* error code */
        pushl   $12 /* vector */
        jmp     int_hand
        .word   0x9090
vec13:
        /* error code */
        pushl   $13 /* vector */
        jmp     int_hand
        .word   0x9090
vec14:
        /* error code */
        pushl   $14 /* vector */
        jmp     int_hand
        .word   0x9090
vec15:
        pushl   $0 /* error code */
        pushl   $15 /* vector */
        jmp     int_hand
vec16:
        pushl   $0 /* error code */
        pushl   $16 /* vector */
        jmp     int_hand
vec17:
        /* error code */
        pushl   $17 /* vector */
        jmp     int_hand
        .word   0x9090
vec18:
        pushl   $0 /* error code */
        pushl   $18 /* vector */
        jmp     int_hand
vec19:
        pushl   $0 /* error code */
        pushl   $19 /* vector */
        jmp     int_hand
__divide_error:
        pushl   $0 /* error code */
        pushl   $20 /* vector */
        jmp     int_hand
        .global __divide_error
int_hand:
        /* At this point on the stack there is:
         *  0(%esp) vector
         *  4(%esp) error code
         *  8(%esp) eip
         * 12(%esp) cs
         * 16(%esp) eflags
         */
        pushl   %edi
        pushl   %esi
        pushl   %ebp
        /* Original stack pointer */
        leal    32(%esp), %ebp
        pushl   %ebp
        pushl   %ebx
        pushl   %edx
        pushl   %ecx
        pushl   %eax
        pushl   %esp    /* Pointer to structure on the stack */
        call    x86_exception
        pop     %eax    /* Drop the pointer */
        popl    %eax
        popl    %ecx
        popl    %edx
        popl    %ebx
        popl    %ebp /* Ignore saved %esp value */
        popl    %ebp
        popl    %esi
        popl    %edi
        addl    $8, %esp /* pop of the vector and error code */
        iret
idtarg:
        .word   _idt_end - _idt - 1     /* limit */
        .long   _idt
        .word   0
_idt:
        .fill   20, 8, 0        # idt is unitiailzed
_idt_end:
        .globl  arch_nvram_size, arch_nvram_get, arch_nvram_put
arch_nvram_size:
        xor     %eax, %eax
        ret
arch_nvram_get:
        ret
arch_nvram_put:
        ret
 
     |