forked from Imagelibrary/rtems
bsp/pc386: Update GDT to work for SMP
Create a GS segment in the GDT for each processor for storing TLS. This makes the GDT in startAP.S obsolete as all processors now share the same GDT, which is passed to each AP at startup. The correct segment for each processor is calculated in cpu_asm.S. Update #3335
This commit is contained in:
@@ -20,5 +20,11 @@
|
||||
#include <bspopts.h>
|
||||
|
||||
#define IDT_SIZE (256)
|
||||
#define NUM_SYSTEM_GDT_DESCRIPTORS 4
|
||||
/* We have 3 fixed segments (NULL, text, data) + a GS segment for TLS */
|
||||
#ifdef RTEMS_SMP
|
||||
/* Need one GS segment for each processor (x86 can have up to 256 processors) */
|
||||
#define NUM_SYSTEM_GDT_DESCRIPTORS 3+256
|
||||
#else
|
||||
#define NUM_SYSTEM_GDT_DESCRIPTORS 3+1
|
||||
#endif
|
||||
#define GDT_SIZE (NUM_SYSTEM_GDT_DESCRIPTORS + NUM_APP_DRV_GDT_DESCRIPTORS)
|
||||
|
||||
@@ -17,6 +17,6 @@ unsigned imps_lapic_addr = ((unsigned)(&lapic_dummy)) - LAPIC_ID;
|
||||
|
||||
uint32_t _CPU_SMP_Get_current_processor( void )
|
||||
{
|
||||
return APIC_ID(IMPS_LAPIC_READ(LAPIC_ID));
|
||||
return imps_apic_cpu_map[APIC_ID(IMPS_LAPIC_READ(LAPIC_ID))];
|
||||
}
|
||||
|
||||
|
||||
@@ -191,9 +191,11 @@ SYM (_Global_descriptor_table):
|
||||
.word 0xffff, 0
|
||||
.byte 0, 0x92, 0xcf, 0
|
||||
|
||||
/* gs segment */
|
||||
/* gs segment(s) */
|
||||
.rept (NUM_SYSTEM_GDT_DESCRIPTORS - 3)
|
||||
.word 0xffff, 0
|
||||
.byte 0, 0x92, 0xcf, 0
|
||||
.endr
|
||||
|
||||
/* allocated space for user segments */
|
||||
.rept (GDT_SIZE - NUM_SYSTEM_GDT_DESCRIPTORS)
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
extern void _pc386_delay(void);
|
||||
extern uint32_t* gdtdesc;
|
||||
|
||||
/* #define KERNEL_PRINT(_format) printk(_format) */
|
||||
|
||||
@@ -258,10 +259,10 @@ boot_cpu(imps_processor *proc)
|
||||
* under the 1MB boundary.
|
||||
*/
|
||||
|
||||
uint32_t *reset;
|
||||
volatile uint32_t *reset;
|
||||
|
||||
bootaddr = (512-64)*1024;
|
||||
reset= (uint32_t *)bootaddr;
|
||||
reset= (volatile uint32_t *)bootaddr;
|
||||
|
||||
memcpy(
|
||||
(char *) bootaddr,
|
||||
@@ -269,9 +270,14 @@ boot_cpu(imps_processor *proc)
|
||||
(size_t)_binary_appstart_bin_size
|
||||
);
|
||||
|
||||
/* Pass start function, stack region and gdtdescr to AP
|
||||
* see startAP.S for location */
|
||||
reset[1] = (uint32_t)secondary_cpu_initialize;
|
||||
reset[2] = (uint32_t)_Per_CPU_Get_by_index(apicid)->interrupt_stack_high;
|
||||
|
||||
memcpy(
|
||||
(char*) &reset[3],
|
||||
&gdtdesc,
|
||||
6);
|
||||
/*
|
||||
* Generic CPU startup sequence starts here.
|
||||
*/
|
||||
@@ -325,8 +331,6 @@ boot_cpu(imps_processor *proc)
|
||||
CMOS_WRITE_BYTE(CMOS_RESET_CODE, 0);
|
||||
*((volatile unsigned *) bios_reset_vector) = 0;
|
||||
|
||||
printk("\n");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -359,6 +363,7 @@ add_processor(imps_processor *proc)
|
||||
|
||||
/* AP booted successfully, increase number of available cores */
|
||||
imps_num_cpus++;
|
||||
printk("#%d Application Processor (AP)\n", imps_apic_cpu_map[apicid]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,9 +73,12 @@ app_processor_start:
|
||||
*/
|
||||
.align 4
|
||||
app_cpu_start:
|
||||
.long 0
|
||||
.long 0
|
||||
app_cpu_stack:
|
||||
.long 0
|
||||
.long 0
|
||||
app_gdt_descr:
|
||||
.word 0 /* GDT size */
|
||||
.long 0 /* GDT location */
|
||||
|
||||
setup_processor:
|
||||
movw %cs, %ax # Initialize the rest of
|
||||
@@ -87,7 +90,7 @@ setup_processor:
|
||||
| Bare PC machines boot in real mode! We have to turn protected mode on.
|
||||
+---------------------------------------------------------------------*/
|
||||
|
||||
lgdt gdtptr - app_processor_start # load Global Descriptor Table
|
||||
lgdt app_gdt_descr - app_processor_start # load Global Descriptor Table
|
||||
|
||||
movl %cr0, %eax
|
||||
orl $CR0_PE, %eax
|
||||
@@ -113,33 +116,3 @@ start_32bit:
|
||||
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
|
||||
|
||||
@@ -85,12 +85,13 @@ restore:
|
||||
movl REG_EBX(eax),ebx /* restore ebx */
|
||||
movl REG_ESI(eax),esi /* restore source register */
|
||||
movl REG_EDI(eax),edi /* restore destination register */
|
||||
movl REG_GS_0(eax), ecx /* restore gs segment */
|
||||
GET_CPU_ID ecx
|
||||
movl REG_GS_0(eax), edx /* restore gs segment */
|
||||
movl edx, _Global_descriptor_table+24(,ecx,8)
|
||||
movl REG_GS_1(eax), edx
|
||||
movl ecx, _Global_descriptor_table + 24
|
||||
movl edx, _Global_descriptor_table + 28
|
||||
movl $24, ecx
|
||||
mov ecx, gs
|
||||
movl edx, _Global_descriptor_table+28(,ecx,8)
|
||||
leal 24(,ecx,8), edx
|
||||
movl edx, gs
|
||||
ret
|
||||
|
||||
/*
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#endif
|
||||
#include <rtems/score/cpuopts.h>
|
||||
#include <rtems/score/i386.h>
|
||||
#include <rtems/score/percpu.h>
|
||||
|
||||
/**
|
||||
* @defgroup RTEMSScoreCPUi386ASM i386 Assembler Support
|
||||
@@ -146,6 +147,31 @@
|
||||
#define PUBLIC(sym) .globl SYM (sym)
|
||||
#define EXTERN(sym) .globl SYM (sym)
|
||||
|
||||
#ifdef RTEMS_SMP
|
||||
.macro GET_CPU_ID REG
|
||||
.set LAPIC_ID, 0x20
|
||||
.set LAPIC_ID_SHIFT, 0x18L
|
||||
movl imps_lapic_addr,\REG
|
||||
movl LAPIC_ID(\REG),\REG
|
||||
shrl $LAPIC_ID_SHIFT,\REG /* LAPIC_ID in REG */
|
||||
movb imps_apic_cpu_map(\REG),\REG /* CPU ID in REG */
|
||||
.endm
|
||||
|
||||
.macro GET_SELF_CPU_CONTROL REG
|
||||
GET_CPU_ID \REG
|
||||
shll $PER_CPU_CONTROL_SIZE_LOG2,\REG /* Calculate offset for CPU structure */
|
||||
leal _Per_CPU_Information(\REG),\REG /* Address of info for current CPU in REG */
|
||||
.endm
|
||||
#else
|
||||
.macro GET_CPU_ID REG
|
||||
movl $0,\REG
|
||||
.endm
|
||||
|
||||
.macro GET_SELF_CPU_CONTROL REG
|
||||
leal _Per_CPU_Information, \REG
|
||||
.endm
|
||||
#endif
|
||||
|
||||
/**@}**/
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user