ARM: Add support for loading the a bootloader and configuring parameters for it

This commit is contained in:
Ali Saidi 2011-05-04 20:38:28 -05:00
parent 1b505f5291
commit 42e7888855
5 changed files with 82 additions and 13 deletions

View file

@ -46,9 +46,16 @@ class ArmMachineType(Enum):
class ArmSystem(System): class ArmSystem(System):
type = 'ArmSystem' type = 'ArmSystem'
load_addr_mask = 0xffffffff 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): class LinuxArmSystem(ArmSystem):
type = 'LinuxArmSystem' type = 'LinuxArmSystem'
load_addr_mask = 0x0fffffff load_addr_mask = 0x0fffffff
machine_type = Param.ArmMachineType('RealView_PBX', machine_type = Param.ArmMachineType('RealView_PBX',
"Machine id from http://www.arm.linux.org.uk/developer/machines/") "Machine id from http://www.arm.linux.org.uk/developer/machines/")

View file

@ -123,15 +123,12 @@ void
LinuxArmSystem::initState() LinuxArmSystem::initState()
{ {
ArmSystem::initState(); ArmSystem::initState();
ThreadContext *tc = threadContexts[0];
// Set the initial PC to be at start of the kernel code for (int i = 0; i < threadContexts.size(); i++) {
tc->pcState(tc->getSystemPtr()->kernelEntry & loadAddrMask); threadContexts[i]->setIntReg(0, 0);
threadContexts[i]->setIntReg(1, params()->machine_type);
// Setup the machine type threadContexts[i]->setIntReg(2, ParamsList);
tc->setIntReg(0, 0); }
tc->setIntReg(1, params()->machine_type);
tc->setIntReg(2, ParamsList);
} }
LinuxArmSystem::~LinuxArmSystem() LinuxArmSystem::~LinuxArmSystem()

View file

@ -43,20 +43,73 @@
#include <iostream> #include <iostream>
#include "arch/arm/system.hh" #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 std;
using namespace Linux; using namespace Linux;
ArmSystem::ArmSystem(Params *p) ArmSystem::ArmSystem(Params *p)
: System(p) : System(p), bootldr(NULL)
{ {
debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk"); 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() ArmSystem::~ArmSystem()
{ {
delete debugPrintkEvent; if (debugPrintkEvent)
delete debugPrintkEvent;
} }

View file

@ -60,11 +60,24 @@ class ArmSystem : public System
*/ */
Linux::DebugPrintkEvent *debugPrintkEvent; Linux::DebugPrintkEvent *debugPrintkEvent;
/**
* Pointer to the bootloader object
*/
ObjectFile *bootldr;
public: public:
typedef ArmSystemParams Params; typedef ArmSystemParams Params;
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
ArmSystem(Params *p); ArmSystem(Params *p);
~ArmSystem(); ~ArmSystem();
void initState();
virtual Addr fixFuncEventAddr(Addr addr) virtual Addr fixFuncEventAddr(Addr addr)
{ {
// Remove the low bit that thumb symbols have set // Remove the low bit that thumb symbols have set

View file

@ -60,8 +60,7 @@ initCPU(ThreadContext *tc, int cpuId)
// FPEXC.EN = 0 // FPEXC.EN = 0
static Fault reset = new Reset; static Fault reset = new Reset;
if (cpuId == 0) reset->invoke(tc);
reset->invoke(tc);
} }
uint64_t uint64_t