[rtems commit] bsp/pc386: Update GDT to work for SMP

Chris Johns chrisj at rtems.org
Wed Jun 17 01:55:03 UTC 2020


Module:    rtems
Branch:    master
Commit:    85d6a760f57e6f53c72cf8d15be20e3e4eaf4734
Changeset: http://git.rtems.org/rtems/commit/?id=85d6a760f57e6f53c72cf8d15be20e3e4eaf4734

Author:    Jan Sommer <jan.sommer at dlr.de>
Date:      Sun May 31 16:22:53 2020 +0200

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

---

 bsps/i386/pc386/include/bsp/tblsizes.h    |  8 ++++++-
 bsps/i386/pc386/start/getcpuid.c          |  2 +-
 bsps/i386/pc386/start/ldsegs.S            |  4 +++-
 bsps/i386/pc386/start/smp-imps.c          | 15 ++++++++----
 bsps/i386/pc386/start/startAP.S           | 39 +++++--------------------------
 cpukit/score/cpu/i386/cpu_asm.S           | 11 +++++----
 cpukit/score/cpu/i386/include/rtems/asm.h | 26 +++++++++++++++++++++
 7 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/bsps/i386/pc386/include/bsp/tblsizes.h b/bsps/i386/pc386/include/bsp/tblsizes.h
index 13429dc..978cde2 100644
--- a/bsps/i386/pc386/include/bsp/tblsizes.h
+++ b/bsps/i386/pc386/include/bsp/tblsizes.h
@@ -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)
diff --git a/bsps/i386/pc386/start/getcpuid.c b/bsps/i386/pc386/start/getcpuid.c
index c5284d0..4918a2a 100644
--- a/bsps/i386/pc386/start/getcpuid.c
+++ b/bsps/i386/pc386/start/getcpuid.c
@@ -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))];
 }
 
diff --git a/bsps/i386/pc386/start/ldsegs.S b/bsps/i386/pc386/start/ldsegs.S
index b56bf83..9ed66ef 100644
--- a/bsps/i386/pc386/start/ldsegs.S
+++ b/bsps/i386/pc386/start/ldsegs.S
@@ -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)
diff --git a/bsps/i386/pc386/start/smp-imps.c b/bsps/i386/pc386/start/smp-imps.c
index 58d9178..6480c0d 100644
--- a/bsps/i386/pc386/start/smp-imps.c
+++ b/bsps/i386/pc386/start/smp-imps.c
@@ -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]);
   }
 }
 
diff --git a/bsps/i386/pc386/start/startAP.S b/bsps/i386/pc386/start/startAP.S
index 0f81c03..024c1f7 100644
--- a/bsps/i386/pc386/start/startAP.S
+++ b/bsps/i386/pc386/start/startAP.S
@@ -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 at 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/cpukit/score/cpu/i386/cpu_asm.S b/cpukit/score/cpu/i386/cpu_asm.S
index 6b609ab..9e1e848 100644
--- a/cpukit/score/cpu/i386/cpu_asm.S
+++ b/cpukit/score/cpu/i386/cpu_asm.S
@@ -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
 
 /*
diff --git a/cpukit/score/cpu/i386/include/rtems/asm.h b/cpukit/score/cpu/i386/include/rtems/asm.h
index 5db402c..5856f72 100644
--- a/cpukit/score/cpu/i386/include/rtems/asm.h
+++ b/cpukit/score/cpu/i386/include/rtems/asm.h
@@ -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



More information about the vc mailing list