File : s-bcprmu-8641d.adb


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                  GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                --
   4 --                                                                          --
   5 --              S Y S T E M . B B . C P U _ P R I M I T I V E S .           --
   6 --                       M U L T I P R O C E S S O R S                      --
   7 --                                                                          --
   8 --                                  B o d y                                 --
   9 --                                                                          --
  10 --                     Copyright (C) 2014-2015, AdaCore                     --
  11 --                                                                          --
  12 -- GNARL is free software; you can  redistribute it  and/or modify it under --
  13 -- terms of the  GNU General Public License as published  by the Free Soft- --
  14 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
  15 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
  16 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  17 -- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
  18 --                                                                          --
  19 --                                                                          --
  20 --                                                                          --
  21 --                                                                          --
  22 --                                                                          --
  23 -- You should have received a copy of the GNU General Public License and    --
  24 -- a copy of the GCC Runtime Library Exception along with this program;     --
  25 -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
  26 -- <http://www.gnu.org/licenses/>.                                          --
  27 --                                                                          --
  28 ------------------------------------------------------------------------------
  29 
  30 pragma Restrictions (No_Elaboration_Code);
  31 
  32 with Interfaces; use Interfaces;
  33 with System.Multiprocessors; use System.Multiprocessors;
  34 with System.BB.Interrupts; use System.BB.Interrupts;
  35 with System.BB.Protection;
  36 with System.BB.Board_Parameters; use System.BB.Board_Parameters;
  37 
  38 package body System.BB.CPU_Primitives.Multiprocessors is
  39 
  40    procedure Poke_Handler (Interrupt : Interrupts.Interrupt_ID);
  41 
  42    -----------------------------------------------------
  43    -- The PCR register in the Memory Coherency Module --
  44    -----------------------------------------------------
  45 
  46    MCM_PCR : Unsigned_32;
  47    for MCM_PCR'Address use System'To_Address (CCSRBAR + 16#1010#);
  48    pragma Import (Ada, MCM_PCR);
  49    --  Port configuration register
  50 
  51    -----------------
  52    -- Current_CPU --
  53    -----------------
  54 
  55    function Current_CPU return System.Multiprocessors.CPU is
  56       Cpu_Id : Unsigned_32;
  57       for Cpu_Id'Address use System'To_Address (CCSRBAR + 16#4_0090#);
  58       pragma Import (Ada, Cpu_Id);
  59       --  Per-CPU WHOAMI register
  60    begin
  61       return CPU_Range (Cpu_Id) + CPU'First;
  62    end Current_CPU;
  63 
  64    --------------
  65    -- Poke_CPU --
  66    --------------
  67 
  68    procedure Poke_CPU (CPU_Id : System.Multiprocessors.CPU) is
  69       Val : Unsigned_32;
  70 
  71       IPI : Unsigned_32;
  72       for IPI'Address use System'To_Address (CCSRBAR + 16#4_0040#);
  73       pragma Import (Ada, IPI);
  74       --  Per-CPU interproces interrupt dispatch register (IPIDR0)
  75    begin
  76       --  Send IPI0 to processor CPU_Id
  77       Val := Shift_Left (1, CPU_Range'Pos (CPU_Id - CPU'First));
  78       IPI := IPI or Val;
  79    end Poke_CPU;
  80 
  81    ---------------
  82    -- Start_CPU --
  83    ---------------
  84 
  85    procedure Start_CPU (CPU_Id : System.Multiprocessors.CPU) is
  86       Val : Unsigned_32;
  87    begin
  88       --  Enable processor CPU_Id
  89       Val := Shift_Left (1, 24 + CPU_Range'Pos (CPU_Id - CPU'First));
  90       MCM_PCR := MCM_PCR or Val;
  91    end Start_CPU;
  92 
  93    ------------------
  94    -- Poke_Handler --
  95    ------------------
  96 
  97    procedure Poke_Handler (Interrupt : Interrupts.Interrupt_ID) is
  98       Bogus : Unsigned_32;
  99       pragma Unreferenced (Bogus);
 100       IACK  : Unsigned_32;
 101       for IACK'Address use System'To_Address (CCSRBAR + 16#4_00a0#);
 102       pragma Import (Ada, IACK);
 103       EOI   : Unsigned_32;
 104       for EOI'Address use System'To_Address (CCSRBAR + 16#4_00b0#);
 105       pragma Import (Ada, EOI);
 106    begin
 107       --  Make sure we are handling the right interrupt
 108       pragma Assert (Interrupt = 1);
 109 
 110       --  Acknowledge the interrupt by reading the OpenPIC IACK register
 111       Bogus := IACK;
 112 
 113       --  Just so that we can call a Leave_Kernel
 114       Protection.Enter_Kernel;
 115 
 116       --  Leave_Kernel will handle served entries and wake up their calling
 117       --  threads
 118       Protection.Leave_Kernel;
 119 
 120       --  Disable interrupts in order to write to EOI register
 121       CPU_Primitives.Disable_Interrupts;
 122       EOI := 0;
 123 
 124    end Poke_Handler;
 125 
 126    --------------------
 127    -- Start_All_CPUs --
 128    --------------------
 129 
 130    procedure Start_All_CPUs is
 131       Val : Unsigned_32;
 132 
 133       IPIVPR : Unsigned_32;
 134       for IPIVPR'Address use System'To_Address (CCSRBAR + 16#4_10a0#);
 135       pragma Import (Ada, IPIVPR);
 136       --  IPI0 vector/priority register
 137 
 138       PCTP : Unsigned_32;
 139       for PCTP'Address use System'To_Address (CCSRBAR + 16#6_1080#);
 140       pragma Import (Ada, PCTP);
 141       --  Processor 1 current task priority register
 142 
 143    begin
 144       --  Nothing to do when there's only one CPU
 145 
 146       if System.Multiprocessors.Number_Of_CPUs = 1 then
 147          return;
 148       end if;
 149 
 150       Attach_Handler (Poke_Handler'Access, 1, Interrupt_Priority'First);
 151       PCTP := 0;
 152 
 153       --  Unask IPI, priority 15, vector #0
 154       IPIVPR := (IPIVPR or 16#000f_0000#) and (not 16#8000_0000#);
 155 
 156       --  Enable all CPUs
 157       Val := Shift_Left
 158         (Shift_Left (1, CPU_Range'Pos (Number_Of_CPUs)) - 1, 24);
 159       MCM_PCR := MCM_PCR or Val;
 160    end Start_All_CPUs;
 161 
 162 end System.BB.CPU_Primitives.Multiprocessors;