summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2011-05-04 20:38:28 -0500
committerAli Saidi <Ali.Saidi@ARM.com>2011-05-04 20:38:28 -0500
commit42e788885573d2294877c73f83dbf539e4bac10f (patch)
treeb0014c8ed48e9b1b6e07cf008a8379c1aca113a4 /src
parent1b505f529142882fa191f1be23e17ee37b6885c9 (diff)
downloadgem5-42e788885573d2294877c73f83dbf539e4bac10f.tar.xz
ARM: Add support for loading the a bootloader and configuring parameters for it
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/ArmSystem.py7
-rw-r--r--src/arch/arm/linux/system.cc13
-rw-r--r--src/arch/arm/system.cc57
-rw-r--r--src/arch/arm/system.hh15
-rw-r--r--src/arch/arm/utility.cc3
5 files changed, 82 insertions, 13 deletions
diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py
index 14eba9f07..e23ffd5a0 100644
--- a/src/arch/arm/ArmSystem.py
+++ b/src/arch/arm/ArmSystem.py
@@ -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/")
+
+
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
index 1190a7f3a..445fa2f19 100644
--- a/src/arch/arm/linux/system.cc
+++ b/src/arch/arm/linux/system.cc
@@ -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()
diff --git a/src/arch/arm/system.cc b/src/arch/arm/system.cc
index d61db4cfe..8431bfff2 100644
--- a/src/arch/arm/system.cc
+++ b/src/arch/arm/system.cc
@@ -43,20 +43,73 @@
#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;
}
diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh
index e63d5c0ed..4898d433c 100644
--- a/src/arch/arm/system.hh
+++ b/src/arch/arm/system.hh
@@ -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
diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc
index 6bca63291..bbba38d2b 100644
--- a/src/arch/arm/utility.cc
+++ b/src/arch/arm/utility.cc
@@ -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