ARM: Add support for loading the a bootloader and configuring parameters for it
authorAli Saidi <Ali.Saidi@ARM.com>
Thu, 5 May 2011 01:38:28 +0000 (20:38 -0500)
committerAli Saidi <Ali.Saidi@ARM.com>
Thu, 5 May 2011 01:38:28 +0000 (20:38 -0500)
src/arch/arm/ArmSystem.py
src/arch/arm/linux/system.cc
src/arch/arm/system.cc
src/arch/arm/system.hh
src/arch/arm/utility.cc

index 14eba9f07c59d4344bcca03d2ea9e910d384f6b7..e23ffd5a04bb74a2d55f04ddaf5f5de94ee2583b 100644 (file)
@@ -46,9 +46,16 @@ class ArmMachineType(Enum):
 class ArmSystem(System):
     type = 'ArmSystem'
     load_addr_mask = 0xffffffff
+    boot_loader = Param.String("", "File that contains the boot loader code if any")
+    boot_loader_mem = Param.PhysicalMemory(NULL,
+                          "Memory object that boot loader is to be loaded into")
+    gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface")
+    flags_addr = Param.Addr(0, "Address of the flags register for MP booting")
 
 class LinuxArmSystem(ArmSystem):
     type = 'LinuxArmSystem'
     load_addr_mask = 0x0fffffff
     machine_type = Param.ArmMachineType('RealView_PBX',
         "Machine id from http://www.arm.linux.org.uk/developer/machines/")
+
+
index 1190a7f3a0f7e273acda53ab105abfc1d923e8ec..445fa2f195cd6bf93c6c09baf29d6f35b9458414 100644 (file)
@@ -123,15 +123,12 @@ void
 LinuxArmSystem::initState()
 {
     ArmSystem::initState();
-    ThreadContext *tc = threadContexts[0];
 
-    // Set the initial PC to be at start of the kernel code
-    tc->pcState(tc->getSystemPtr()->kernelEntry & loadAddrMask);
-
-    // Setup the machine type
-    tc->setIntReg(0, 0);
-    tc->setIntReg(1, params()->machine_type);
-    tc->setIntReg(2, ParamsList);
+    for (int i = 0; i < threadContexts.size(); i++) {
+        threadContexts[i]->setIntReg(0, 0);
+        threadContexts[i]->setIntReg(1, params()->machine_type);
+        threadContexts[i]->setIntReg(2, ParamsList);
+    }
 }
 
 LinuxArmSystem::~LinuxArmSystem()
index d61db4cfe952398f11fbf37a2fec4d12f3dbe556..8431bfff23400001dc7fbb640155a4a6029e948a 100644 (file)
 #include <iostream>
 
 #include "arch/arm/system.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/thread_context.hh"
+#include "mem/physical.hh"
 
 using namespace std;
 using namespace Linux;
 
 ArmSystem::ArmSystem(Params *p)
-    : System(p)
+    : System(p), bootldr(NULL)
 {
     debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
 
+    if ((p->boot_loader == "") != (p->boot_loader_mem == NULL))
+        fatal("If boot_loader is specifed, memory to load it must be also.\n");
+
+    if (p->boot_loader != "") {
+        bootldr = createObjectFile(p->boot_loader);
+
+        if (!bootldr)
+            fatal("Could not read bootloader: %s\n", p->boot_loader);
+
+        Port *mem_port;
+        FunctionalPort fp(name() + "-fport");
+        mem_port = p->boot_loader_mem->getPort("functional");
+        fp.setPeer(mem_port);
+        mem_port->setPeer(&fp);
+
+        bootldr->loadSections(&fp);
+        bootldr->loadGlobalSymbols(debugSymbolTable);
+
+        uint8_t jump_to_bl[] =
+        {
+            0x07, 0xf0, 0xa0, 0xe1  // branch to r7
+        };
+        functionalPort->writeBlob(0x0, jump_to_bl, sizeof(jump_to_bl));
+
+        inform("Using bootloader at address %#x\n", bootldr->entryPoint());
+    }
+}
+
+void
+ArmSystem::initState()
+{
+    System::initState();
+    if (bootldr) {
+        // Put the address of the boot loader into r7 so we know
+        // where to branch to after the reset fault
+        // All other values needed by the boot loader to know what to do
+        for (int i = 0; i < threadContexts.size(); i++) {
+            threadContexts[i]->setIntReg(3, kernelEntry & loadAddrMask);
+            threadContexts[i]->setIntReg(4, params()->gic_cpu_addr);
+            threadContexts[i]->setIntReg(5, params()->flags_addr);
+            threadContexts[i]->setIntReg(7, bootldr->entryPoint());
+        }
+        if (!params()->gic_cpu_addr || !params()->flags_addr)
+            fatal("gic_cpu_addr && flags_addr must be set with bootloader\n");
+    } else {
+        // Set the initial PC to be at start of the kernel code
+        threadContexts[0]->pcState(kernelEntry & loadAddrMask);
+    }
 }
 
 ArmSystem::~ArmSystem()
 {
-    delete debugPrintkEvent;
+    if (debugPrintkEvent)
+        delete debugPrintkEvent;
 }
 
 
index e63d5c0ed75328a5caf869df88c1734e061a59ad..4898d433cb7ebfd4c260009d46c3fe9ae5a7eb5d 100644 (file)
@@ -60,11 +60,24 @@ class ArmSystem : public System
      */
     Linux::DebugPrintkEvent *debugPrintkEvent;
 
+    /**
+     * Pointer to the bootloader object
+     */
+    ObjectFile *bootldr;
+
   public:
     typedef ArmSystemParams Params;
+    const Params *
+    params() const
+    {
+        return dynamic_cast<const Params *>(_params);
+    }
+
     ArmSystem(Params *p);
     ~ArmSystem();
-    
+
+    void initState();
+
     virtual Addr fixFuncEventAddr(Addr addr)
     {
         // Remove the low bit that thumb symbols have set
index 6bca632915506a745e2496858cbbf9902f585c14..bbba38d2b7fa8434f2d47b1b38614438fe3f77d4 100644 (file)
@@ -60,8 +60,7 @@ initCPU(ThreadContext *tc, int cpuId)
     // FPEXC.EN = 0
     
     static Fault reset = new Reset;
-    if (cpuId == 0)
-        reset->invoke(tc);
+    reset->invoke(tc);
 }
 
 uint64_t