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/")
+
+
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()
#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;
}