From f99b1f02b0a9a3457336949e086b863561d0fb76 Mon Sep 17 00:00:00 2001 From: Jan Sommer Date: Sun, 31 May 2020 16:22:52 +0200 Subject: bsp/pc386: Turn start16.S into a startAP.S start16.S is now only used for SMP configurations to start the application processors. This commit removes all unnecessary parts for this job, i.e. video conssole initalisation, A20 gate activation and all non-AP related code. Update #3335 --- bsps/i386/pc386/start/smp-imps.c | 14 +- bsps/i386/pc386/start/start16.S | 254 -------------------------------- bsps/i386/pc386/start/startAP.S | 145 ++++++++++++++++++ c/src/lib/libbsp/i386/pc386/Makefile.am | 4 +- 4 files changed, 159 insertions(+), 258 deletions(-) delete mode 100644 bsps/i386/pc386/start/start16.S create mode 100644 bsps/i386/pc386/start/startAP.S diff --git a/bsps/i386/pc386/start/smp-imps.c b/bsps/i386/pc386/start/smp-imps.c index 0543b17ec5..58d9178f90 100644 --- a/bsps/i386/pc386/start/smp-imps.c +++ b/bsps/i386/pc386/start/smp-imps.c @@ -308,6 +308,11 @@ boot_cpu(imps_processor *proc) } } + /* + * Wait until AP is in protected mode before starting the next AP + */ + while (reset[2] != 0); + /* * Generic CPU startup sequence ends here, the rest is cleanup. */ @@ -342,12 +347,17 @@ add_processor(imps_processor *proc) printk("#0 BootStrap Processor (BSP)\n"); return; } + /* Setup the apic/cpu maps before booting the APs + * otherwise calls to _Get_current_processor can deliver + * wrong values if the BSP gets interrupted + */ + imps_cpu_apic_map[imps_num_cpus] = apicid; + imps_apic_cpu_map[apicid] = imps_num_cpus; if (boot_cpu(proc)) { /* XXXXX add OS-specific setup for secondary CPUs here */ - imps_cpu_apic_map[imps_num_cpus] = apicid; - imps_apic_cpu_map[apicid] = imps_num_cpus; + /* AP booted successfully, increase number of available cores */ imps_num_cpus++; } } diff --git a/bsps/i386/pc386/start/start16.S b/bsps/i386/pc386/start/start16.S deleted file mode 100644 index 3d46f40ed6..0000000000 --- a/bsps/i386/pc386/start/start16.S +++ /dev/null @@ -1,254 +0,0 @@ -/*--------------------------------------------------------------------------+ - * start16.s v1.0 - PC386 BSP - 1998/04/13 - *--------------------------------------------------------------------------+ - * This file contains the entry point for the application. - * The name of this entry point is compiler dependent. - * It jumps to the BSP which is responsible for performing all initialization. - *--------------------------------------------------------------------------+ - * (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 - -/*---------------------------------------------------------------------------+ -| Constants -+----------------------------------------------------------------------------*/ - -#if defined(SMP_SECONDARY_CORE) -.set PROT_CODE_SEG, 0x08 # offset of code segment descriptor into GDT -#else -.set PROT_CODE_SEG, 0x0 # offset of code segment descriptor into GDT -#endif - -.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 -#if defined(SMP_SECONDARY_CORE) - .globl app_processor_start # entry point -app_processor_start: -#else - .globl _start16 # entry point - .globl start16 -start16: -_start16: -#endif - -.code16 - cli # DISABLE INTERRUPTS!!! -#if defined(SMP_SECONDARY_CORE) - jmp 1f - .align 4 -app_cpu_start: - .long 0 -app_cpu_stack: - .long 0 -1: -#endif - movw %cs, %ax # Initialize the rest of - movw %ax, %ds # segment registers - movw %ax, %es - movw %ax, %ss - -#if !defined(SMP_SECONDARY_CODE) && (RTEMS_VIDEO_80x50 == 1) - movl $0x0040,%eax # use 32 bit constant to ensure 16 MSB=0 - mov %ax,%es - movw %es:0x4a, %ax # get 16 bit number of columns - cmpw $0, %ax # or 0 if no video adapter - je 1f # if no video, skip touching it - /*---------------------------------------------------------------------+ - | Switch VGA video to 80 lines x 50 columns mode. Has to be done before - | turning protected mode on since it uses BIOS int 10h (video) services. - +---------------------------------------------------------------------*/ - - movw $0x0003, %ax # forced set - int $0x10 - movw $0x1112, %ax # use 8x8 font - xorb %bl, %bl - int $0x10 - movw $0x1201, %ax # turn off cursor emulation - movb $0x34, %bl - int $0x10 - movb $0x01, %ah # define cursor (scan lines 0 to 7) - movw $0x0007, %cx - int $0x10 -1: -#endif /* !SMP_SECONDARY_CODE and RTEMS_VIDEO_80x50 */ - - /*---------------------------------------------------------------------+ - | Bare PC machines boot in real mode! We have to turn protected mode on. - +---------------------------------------------------------------------*/ - -#if defined(SMP_SECONDARY_CORE) - lgdt gdtptr - app_processor_start # load Global Descriptor Table -#else - lgdt gdtptr - start16 # load Global Descriptor Table -#endif /* SMP_SECONDARY_CORE */ - - movl %cr0, %eax - orl $CR0_PE, %eax - movl %eax, %cr0 # turn on protected mode -#if defined(SMP_SECONDARY_CORE) - LJMPL $PROT_CODE_SEG, $2f # flush prefetch queue, and reload %cs -#else - LJMPL $PROT_CODE_SEG, $2f # flush prefetch queue, and reload %cs -#endif -.code32 -2: - - /*---------------------------------------------------------------------+ - | load the other segment registers - +---------------------------------------------------------------------*/ - movl $PROT_DATA_SEG, %eax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss -#if defined(SMP_SECONDARY_CORE) - movl app_cpu_stack, %esp # stack pointer - movl app_cpu_stack, %ebp # base pointer - #else - movl $start16 + STACKOFF, %esp # set up stack pointer - addl $start16 + STACKOFF, %ebp # set up stack pointer -#endif /* SMP_SECONDARY_CORE */ - - /*---------------------------------------------------------------------+ - | we have to enable A20 in order to access memory above 1MByte - +---------------------------------------------------------------------*/ - call empty_8042 - movb $0xD1, %al # command write - outb %al, $0x64 - call empty_8042 - movb $0xDF, %al # A20 on - outb %al, $0x60 - call empty_8042 - - call pc386_delay - call pc386_delay - call pc386_delay - -#if defined(SMP_SECONDARY_CORE) - movl app_cpu_start, %eax # jump to app CPU start -#else - movl %cs:HDRSTART + HDROFF, %eax # jump to start of 32 bit code -#endif /* SMP_SECONDARY_CORE */ - pushl %eax - ret - - -/*----------------------------------------------------------------------------+ -| pc386_delay -+------------------------------------------------------------------------------ -| Delay is needed after doing I/O. -| -| The outb version is OK on most machines BUT the loop version ... -| -| will delay for 1us on 1Gz machine, it will take a little bit -| longer on slower machines, however, it does not matter because we -| are going to call this function only a few times -! -| NOTE: Saving the content of the EAX register just in case. - Rosimildo. -+----------------------------------------------------------------------------*/ - .p2align 4 - .globl _pc386_delay - .globl pc386_delay -pc386_delay: -_pc386_delay: - pushl %eax -#if defined(USE_OUTB_FOR_DELAY) - outb %al, $0x80 # about 1uS delay on most machines - -#else - - movl $0x200, %eax -pc386_delay1: - dec %eax - jnz pc386_delay1 -#endif - popl %eax - ret - -/*----------------------------------------------------------------------------+ -| empty_8042 -+------------------------------------------------------------------------------ -| This routine checks that the keyboard command queue is empty (after emptying -| the output buffers). -| No timeout is used - if this hangs there is something wrong with the machine, -| and we probably couldn't proceed anyway. -+----------------------------------------------------------------------------*/ - .p2align 4 - .globl _empty_8042 - .globl empty_8042 -empty_8042: -_empty_8042: - call pc386_delay - inb $0x64, %al # 8042 status port - testb $0x01, %al # output buffer? - jz no_output - call pc386_delay - in $0x60, %al # read it - jmp empty_8042 -no_output: - test $0x02, %al # is input buffer full? - jnz empty_8042 # yes - loop - 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 - - .set gdtlen, . - gdtptr # length of GDT diff --git a/bsps/i386/pc386/start/startAP.S b/bsps/i386/pc386/start/startAP.S new file mode 100644 index 0000000000..0f81c03144 --- /dev/null +++ b/bsps/i386/pc386/start/startAP.S @@ -0,0 +1,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 + +/*---------------------------------------------------------------------------+ +| 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 diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am index 218e6bc065..c71f672063 100644 --- a/c/src/lib/libbsp/i386/pc386/Makefile.am +++ b/c/src/lib/libbsp/i386/pc386/Makefile.am @@ -114,8 +114,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/getcpuid.c librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/smp-imps.c project_lib_DATA += appstart.$(OBJEXT) -appcpustart.$(OBJEXT): ../../../../../../bsps/i386/pc386/start/start16.S - $(CPPASCOMPILE) $(AM_CPPFLAGS) -DSMP_SECONDARY_CORE -o $@ -c $< +appcpustart.$(OBJEXT): ../../../../../../bsps/i386/pc386/start/startAP.S + $(CPPASCOMPILE) $(AM_CPPFLAGS) -o $@ -c $< appstart.$(OBJEXT): appcpustart.$(OBJEXT) $(LD) -N \ -- cgit v1.2.3