From 42e788885573d2294877c73f83dbf539e4bac10f Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 4 May 2011 20:38:28 -0500 Subject: ARM: Add support for loading the a bootloader and configuring parameters for it --- src/arch/arm/ArmSystem.py | 7 ++++++ src/arch/arm/linux/system.cc | 13 ++++------ src/arch/arm/system.cc | 57 ++++++++++++++++++++++++++++++++++++++++++-- src/arch/arm/system.hh | 15 +++++++++++- src/arch/arm/utility.cc | 3 +-- 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 #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("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(_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 -- cgit v1.2.3