1/*
2 * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
3 * All rights reserved.
4 *
5 * This software was developed by the University of Cambridge Computer
6 * Laboratory as part of the CTSRD Project, with support from the UK Higher
7 * Education Innovation Fund (HEIF).
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met: redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer;
13 * redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution;
16 * neither the name of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "arch/arm/freebsd/system.hh"
34
35#include "arch/arm/isa_traits.hh"
36#include "arch/arm/utility.hh"
37#include "arch/generic/freebsd/threadinfo.hh"
38#include "base/loader/dtb_object.hh"
39#include "base/loader/object_file.hh"
40#include "base/loader/symtab.hh"
41#include "cpu/base.hh"
42#include "cpu/pc_event.hh"
43#include "cpu/thread_context.hh"
44#include "debug/Loader.hh"
45#include "kern/freebsd/events.hh"
46#include "mem/fs_translating_port_proxy.hh"
47#include "mem/physical.hh"
48#include "sim/stat_control.hh"
49
50using namespace ArmISA;
51using namespace FreeBSD;
52
53FreebsdArmSystem::FreebsdArmSystem(Params *p)
54    : GenericArmSystem(p),
55      enableContextSwitchStatsDump(p->enable_context_switch_stats_dump),
56      taskFile(nullptr), kernelPanicEvent(nullptr), kernelOopsEvent(nullptr)
57{
58    if (p->panic_on_panic) {
59        kernelPanicEvent = addKernelFuncEventOrPanic<PanicPCEvent>(
60            "panic", "Kernel panic in simulated kernel");
61    } else {
62#ifndef NDEBUG
63        kernelPanicEvent = addKernelFuncEventOrPanic<BreakPCEvent>("panic");
64#endif
65    }
66
67    if (p->panic_on_oops) {
68        kernelOopsEvent = addKernelFuncEventOrPanic<PanicPCEvent>(
69            "oops_exit", "Kernel oops in guest");
70    }
71
72    uDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
73        "DELAY", "DELAY", 1000, 0);
74}
75
76void
77FreebsdArmSystem::initState()
78{
79    // Moved from the constructor to here since it relies on the
80    // address map being resolved in the interconnect
81
82    // Call the initialisation of the super class
83    GenericArmSystem::initState();
84
85    // Load symbols at physical address, we might not want
86    // to do this permanently, for but early bootup work
87    // it is helpful.
88    if (params()->early_kernel_symbols) {
89        kernel->loadGlobalSymbols(kernelSymtab, 0, 0, loadAddrMask);
90        kernel->loadGlobalSymbols(debugSymbolTable, 0, 0, loadAddrMask);
91    }
92
93    // Setup boot data structure
94    Addr addr = 0;
95
96    // Check if the kernel image has a symbol that tells us it supports
97    // device trees.
98    bool kernel_has_fdt_support =
99        kernelSymtab->findAddress("fdt_get_range", addr);
100    bool dtb_file_specified = params()->dtb_filename != "";
101
102    if (!dtb_file_specified)
103        fatal("dtb file is not specified\n");
104
105    if (!kernel_has_fdt_support)
106        fatal("kernel must have fdt support\n");
107
108    // Kernel supports flattened device tree and dtb file specified.
109    // Using Device Tree Blob to describe system configuration.
110    inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename,
111            params()->atags_addr + loadAddrOffset);
112
113    ObjectFile *dtb_file = createObjectFile(params()->dtb_filename, true);
114    if (!dtb_file) {
115        fatal("couldn't load DTB file: %s\n", params()->dtb_filename);
116    }
117
118    DtbObject *_dtb_file = dynamic_cast<DtbObject*>(dtb_file);
119
120    if (_dtb_file) {
121        if (!_dtb_file->addBootCmdLine(params()->boot_osflags.c_str(),
122                                       params()->boot_osflags.size())) {
123            warn("couldn't append bootargs to DTB file: %s\n",
124                 params()->dtb_filename);
125        }
126    } else {
127        warn("dtb_file cast failed; couldn't append bootargs "
128             "to DTB file: %s\n", params()->dtb_filename);
129    }
130
131    Addr ra = _dtb_file->findReleaseAddr();
132    if (ra)
133        bootReleaseAddr = ra & ~ULL(0x7F);
134
135    dtb_file->setTextBase(params()->atags_addr + loadAddrOffset);
136    dtb_file->loadSections(physProxy);
137    delete dtb_file;
138
139    // Kernel boot requirements to set up r0, r1 and r2 in ARMv7
140    for (int i = 0; i < threadContexts.size(); i++) {
141        threadContexts[i]->setIntReg(0, 0);
142        threadContexts[i]->setIntReg(1, params()->machine_type);
143        threadContexts[i]->setIntReg(2, params()->atags_addr + loadAddrOffset);
144    }
145}
146
147FreebsdArmSystem::~FreebsdArmSystem()
148{
149    if (uDelaySkipEvent)
150        delete uDelaySkipEvent;
151    if (constUDelaySkipEvent)
152        delete constUDelaySkipEvent;
153}
154
155FreebsdArmSystem *
156FreebsdArmSystemParams::create()
157{
158    return new FreebsdArmSystem(this);
159}
160
161void
162FreebsdArmSystem::startup()
163{
164}
165