summaryrefslogtreecommitdiffstats
path: root/bsps/i386/pc386/start/startAP.S
blob: 0f81c03144631052da4158ce8e2490035feda4d8 (plain) (blame)
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
/*--------------------------------------------------------------------------+
 * start16.s v1.0 - PC386 BSP - 1998/04/13
 * startAP.s 05/2019
 *--------------------------------------------------------------------------+
 * This file contains the initialization code for application processors (AP)
 * for i386 based board support packages in SMP configuration.
 * The APs start in 16 bit real mode. The goal is to:
 * 1. Initialize the CPU registers
 * 2. Load the global descriptor table
 * 3. Switch to protected mode
 * 4. Setup the stack pointers
 * 5. Switch to the higher level initialization routine
 *
 *--------------------------------------------------------------------------+
 * (C) Copyright 1997 -
 * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
 *
 * http://pandora.ist.utl.pt
 *
 * Instituto Superior Tecnico * Lisboa * PORTUGAL
 *--------------------------------------------------------------------------+
 * Disclaimer:
 *
 * This file is provided "AS IS" without warranty of any kind, either
 * expressed or implied.
 *--------------------------------------------------------------------------+
 */

/*
 *  COPYRIGHT (c) 2011.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */


#include <bspopts.h>

/*---------------------------------------------------------------------------+
| Constants
+----------------------------------------------------------------------------*/

.set PROT_CODE_SEG, 0x08        # offset of code segment descriptor into GDT
.set PROT_DATA_SEG, 0x10        # offset of code segment descriptor into GDT
.set CR0_PE,        1           # protected mode flag on CR0 register
.set HDRSTART,      HEADERADDR  # address of start of bin2boot header
.set HDROFF,        0x24        # offset into bin2boot header of start32 addr
.set STACKOFF,      0x200-0x10  # offset to load into %esp, from start of image

/* #define NEW_GAS */
#ifdef NEW_GAS
  #define LJMPL ljmpl
#else
  #define LJMPL ljmp
#endif

/*----------------------------------------------------------------------------+
| CODE section
+----------------------------------------------------------------------------*/

.text
        .globl app_processor_start                # entry point
app_processor_start:

.code16
        cli                     # DISABLE INTERRUPTS!!!
        jmp     setup_processor
/*
 * Placeholder to copy information from boot_cpu()
 * Do NOT move or add asm instruction before
 */
.align 4
app_cpu_start:
	.long   0
app_cpu_stack:
	.long   0

setup_processor:
        movw    %cs, %ax                   # Initialize the rest of
        movw    %ax, %ds                   #   segment registers
        movw    %ax, %es
        movw    %ax, %ss

        /*---------------------------------------------------------------------+
        | Bare PC machines boot in real mode! We have to turn protected mode on.
        +---------------------------------------------------------------------*/

        lgdt    gdtptr - app_processor_start  # load Global Descriptor Table

        movl    %cr0, %eax
        orl     $CR0_PE, %eax
        movl    %eax, %cr0              # turn on protected mode
        LJMPL   $PROT_CODE_SEG, $start_32bit     # flush prefetch queue, and reload %cs

.code32
start_32bit:

        /*---------------------------------------------------------------------+
        | load the other segment registers
        +---------------------------------------------------------------------*/
        movl    $PROT_DATA_SEG, %eax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %ss
        /* Prepare stack pointers */
        movl    app_cpu_stack, %esp            # stack pointer
        movl    app_cpu_stack, %ebp            # base pointer
        movl    app_cpu_start, %eax             # jump to app CPU start
        pushl   %eax
        /* Clear stack pointer to signal that the we jump to the kernel */
        movl    $0, app_cpu_stack
        /* Switch to the higher level initialization routines */
        ret

/*----------------------------------------------------------------------------+
| DATA section
+----------------------------------------------------------------------------*/

/**************************
* GLOBAL DESCRIPTOR TABLE *
**************************/

        .p2align 4
gdtptr:
        /* we use the NULL descriptor to store the GDT pointer - a trick quite
           nifty due to: Robert Collins (rcollins@x86.org) */
        .word   gdtlen - 1
        .long   gdtptr
        .word   0x0000

        /* code segment */
        .word   0xffff, 0
        .byte   0, 0x9f, 0xcf, 0

        /* data segment */
        .word   0xffff, 0
        .byte   0, 0x93, 0xcf, 0

     	/* gs segment */
        .word 0xffff, 0
        .byte 0, 0x92, 0xcf, 0

        .set    gdtlen, . - gdtptr      # length of GDT