backdoor.cc revision 1805
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file
30 * Alpha Console Definition
31 */
32
33#include <cstddef>
34#include <cstdio>
35#include <string>
36
37#include "base/inifile.hh"
38#include "base/str.hh"
39#include "base/trace.hh"
40#include "cpu/base.hh"
41#include "cpu/exec_context.hh"
42#include "dev/alpha_console.hh"
43#include "dev/simconsole.hh"
44#include "dev/simple_disk.hh"
45#include "dev/tsunami_io.hh"
46#include "mem/bus/bus.hh"
47#include "mem/bus/pio_interface.hh"
48#include "mem/bus/pio_interface_impl.hh"
49#include "mem/functional/memory_control.hh"
50#include "mem/functional/physical.hh"
51#include "sim/builder.hh"
52#include "sim/sim_object.hh"
53#include "sim/system.hh"
54
55using namespace std;
56
57AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
58                           System *s, BaseCPU *c, Platform *p,
59                           int num_cpus, MemoryController *mmu, Addr a,
60                           HierParams *hier, Bus *bus)
61    : PioDevice(name, p), disk(d), console(cons), system(s), cpu(c), addr(a)
62{
63    mmu->add_child(this, RangeSize(addr, size));
64
65    if (bus) {
66        pioInterface = newPioInterface(name, hier, bus, this,
67                                       &AlphaConsole::cacheAccess);
68        pioInterface->addAddrRange(RangeSize(addr, size));
69    }
70
71    alphaAccess = new Access;
72    alphaAccess->last_offset = size - 1;
73
74    alphaAccess->version = ALPHA_ACCESS_VERSION;
75    alphaAccess->numCPUs = num_cpus;
76    alphaAccess->diskUnit = 1;
77
78    alphaAccess->diskCount = 0;
79    alphaAccess->diskPAddr = 0;
80    alphaAccess->diskBlock = 0;
81    alphaAccess->diskOperation = 0;
82    alphaAccess->outputChar = 0;
83    alphaAccess->inputChar = 0;
84    alphaAccess->bootStrapImpure = 0;
85    alphaAccess->bootStrapCPU = 0;
86    alphaAccess->align2 = 0;
87
88    system->setAlphaAccess(addr);
89}
90
91void
92AlphaConsole::init()
93{
94    alphaAccess->kernStart = system->getKernelStart();
95    alphaAccess->kernEnd = system->getKernelEnd();
96    alphaAccess->entryPoint = system->getKernelEntry();
97    alphaAccess->mem_size = system->physmem->size();
98    alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz
99    alphaAccess->intrClockFrequency = platform->intrFrequency();
100}
101
102Fault
103AlphaConsole::read(MemReqPtr &req, uint8_t *data)
104{
105    memset(data, 0, req->size);
106
107    Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
108
109    switch (req->size)
110    {
111        case sizeof(uint32_t):
112            DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
113                    *(uint32_t*)data);
114            switch (daddr)
115            {
116                case offsetof(AlphaAccess, last_offset):
117                    *(uint32_t*)data = alphaAccess->last_offset;
118                    break;
119                case offsetof(AlphaAccess, version):
120                    *(uint32_t*)data = alphaAccess->version;
121                    break;
122                case offsetof(AlphaAccess, numCPUs):
123                    *(uint32_t*)data = alphaAccess->numCPUs;
124                    break;
125                case offsetof(AlphaAccess, bootStrapCPU):
126                    *(uint32_t*)data = alphaAccess->bootStrapCPU;
127                    break;
128                case offsetof(AlphaAccess, intrClockFrequency):
129                    *(uint32_t*)data = alphaAccess->intrClockFrequency;
130                    break;
131                default:
132                    // Old console code read in everyting as a 32bit int
133                    *(uint32_t*)data = *(uint32_t*)(consoleData + daddr);
134
135            }
136            break;
137        case sizeof(uint64_t):
138            DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
139                    *(uint64_t*)data);
140            switch (daddr)
141            {
142                case offsetof(AlphaAccess, inputChar):
143                    *(uint64_t*)data = console->console_in();
144                    break;
145                case offsetof(AlphaAccess, cpuClock):
146                    *(uint64_t*)data = alphaAccess->cpuClock;
147                    break;
148                case offsetof(AlphaAccess, mem_size):
149                    *(uint64_t*)data = alphaAccess->mem_size;
150                    break;
151                case offsetof(AlphaAccess, kernStart):
152                    *(uint64_t*)data = alphaAccess->kernStart;
153                    break;
154                case offsetof(AlphaAccess, kernEnd):
155                    *(uint64_t*)data = alphaAccess->kernEnd;
156                    break;
157                case offsetof(AlphaAccess, entryPoint):
158                    *(uint64_t*)data = alphaAccess->entryPoint;
159                    break;
160                case offsetof(AlphaAccess, diskUnit):
161                    *(uint64_t*)data = alphaAccess->diskUnit;
162                    break;
163                case offsetof(AlphaAccess, diskCount):
164                    *(uint64_t*)data = alphaAccess->diskCount;
165                    break;
166                case offsetof(AlphaAccess, diskPAddr):
167                    *(uint64_t*)data = alphaAccess->diskPAddr;
168                    break;
169                case offsetof(AlphaAccess, diskBlock):
170                    *(uint64_t*)data = alphaAccess->diskBlock;
171                    break;
172                case offsetof(AlphaAccess, diskOperation):
173                    *(uint64_t*)data = alphaAccess->diskOperation;
174                    break;
175                case offsetof(AlphaAccess, outputChar):
176                    *(uint64_t*)data = alphaAccess->outputChar;
177                    break;
178                case offsetof(AlphaAccess, bootStrapImpure):
179                    *(uint64_t*)data = alphaAccess->bootStrapImpure;
180                    break;
181                default:
182                    panic("Unknown 64bit access, %#x\n", daddr);
183            }
184            break;
185        default:
186            return Machine_Check_Fault;
187    }
188
189    return No_Fault;
190}
191
192Fault
193AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
194{
195    uint64_t val;
196
197    switch (req->size) {
198      case sizeof(uint32_t):
199        val = *(uint32_t *)data;
200        break;
201
202      case sizeof(uint64_t):
203        val = *(uint64_t *)data;
204        break;
205      default:
206        return Machine_Check_Fault;
207    }
208
209    Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
210    ExecContext *other_xc;
211
212    switch (daddr) {
213      case offsetof(AlphaAccess, diskUnit):
214        alphaAccess->diskUnit = val;
215        break;
216
217      case offsetof(AlphaAccess, diskCount):
218        alphaAccess->diskCount = val;
219        break;
220
221      case offsetof(AlphaAccess, diskPAddr):
222        alphaAccess->diskPAddr = val;
223        break;
224
225      case offsetof(AlphaAccess, diskBlock):
226        alphaAccess->diskBlock = val;
227        break;
228
229      case offsetof(AlphaAccess, diskOperation):
230        if (val == 0x13)
231            disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
232                       alphaAccess->diskCount);
233        else
234            panic("Invalid disk operation!");
235
236        break;
237
238      case offsetof(AlphaAccess, outputChar):
239        console->out((char)(val & 0xff));
240        break;
241
242      case offsetof(AlphaAccess, bootStrapImpure):
243        alphaAccess->bootStrapImpure = val;
244        break;
245
246      case offsetof(AlphaAccess, bootStrapCPU):
247        warn("%d: Trying to launch another CPU!", curTick);
248        assert(val > 0 && "Must not access primary cpu");
249
250        other_xc = req->xc->system->execContexts[val];
251        other_xc->regs.intRegFile[16] = val;
252        other_xc->regs.ipr[TheISA::IPR_PALtemp16] = val;
253        other_xc->regs.intRegFile[0] = val;
254        other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure;
255        other_xc->activate(); //Start the cpu
256        break;
257
258      default:
259        return Machine_Check_Fault;
260    }
261
262    return No_Fault;
263}
264
265Tick
266AlphaConsole::cacheAccess(MemReqPtr &req)
267{
268    return curTick + 1000;
269}
270
271void
272AlphaConsole::Access::serialize(ostream &os)
273{
274    SERIALIZE_SCALAR(last_offset);
275    SERIALIZE_SCALAR(version);
276    SERIALIZE_SCALAR(numCPUs);
277    SERIALIZE_SCALAR(mem_size);
278    SERIALIZE_SCALAR(cpuClock);
279    SERIALIZE_SCALAR(intrClockFrequency);
280    SERIALIZE_SCALAR(kernStart);
281    SERIALIZE_SCALAR(kernEnd);
282    SERIALIZE_SCALAR(entryPoint);
283    SERIALIZE_SCALAR(diskUnit);
284    SERIALIZE_SCALAR(diskCount);
285    SERIALIZE_SCALAR(diskPAddr);
286    SERIALIZE_SCALAR(diskBlock);
287    SERIALIZE_SCALAR(diskOperation);
288    SERIALIZE_SCALAR(outputChar);
289    SERIALIZE_SCALAR(inputChar);
290    SERIALIZE_SCALAR(bootStrapImpure);
291    SERIALIZE_SCALAR(bootStrapCPU);
292}
293
294void
295AlphaConsole::Access::unserialize(Checkpoint *cp, const std::string &section)
296{
297    UNSERIALIZE_SCALAR(last_offset);
298    UNSERIALIZE_SCALAR(version);
299    UNSERIALIZE_SCALAR(numCPUs);
300    UNSERIALIZE_SCALAR(mem_size);
301    UNSERIALIZE_SCALAR(cpuClock);
302    UNSERIALIZE_SCALAR(intrClockFrequency);
303    UNSERIALIZE_SCALAR(kernStart);
304    UNSERIALIZE_SCALAR(kernEnd);
305    UNSERIALIZE_SCALAR(entryPoint);
306    UNSERIALIZE_SCALAR(diskUnit);
307    UNSERIALIZE_SCALAR(diskCount);
308    UNSERIALIZE_SCALAR(diskPAddr);
309    UNSERIALIZE_SCALAR(diskBlock);
310    UNSERIALIZE_SCALAR(diskOperation);
311    UNSERIALIZE_SCALAR(outputChar);
312    UNSERIALIZE_SCALAR(inputChar);
313    UNSERIALIZE_SCALAR(bootStrapImpure);
314    UNSERIALIZE_SCALAR(bootStrapCPU);
315}
316
317void
318AlphaConsole::serialize(ostream &os)
319{
320    alphaAccess->serialize(os);
321}
322
323void
324AlphaConsole::unserialize(Checkpoint *cp, const std::string &section)
325{
326    alphaAccess->unserialize(cp, section);
327}
328
329BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
330
331    SimObjectParam<SimConsole *> sim_console;
332    SimObjectParam<SimpleDisk *> disk;
333    Param<int> num_cpus;
334    SimObjectParam<MemoryController *> mmu;
335    Param<Addr> addr;
336    SimObjectParam<System *> system;
337    SimObjectParam<BaseCPU *> cpu;
338    SimObjectParam<Platform *> platform;
339    SimObjectParam<Bus*> io_bus;
340    Param<Tick> pio_latency;
341    SimObjectParam<HierParams *> hier;
342
343END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
344
345BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
346
347    INIT_PARAM(sim_console, "The Simulator Console"),
348    INIT_PARAM(disk, "Simple Disk"),
349    INIT_PARAM_DFLT(num_cpus, "Number of CPU's", 1),
350    INIT_PARAM(mmu, "Memory Controller"),
351    INIT_PARAM(addr, "Device Address"),
352    INIT_PARAM(system, "system object"),
353    INIT_PARAM(cpu, "Processor"),
354    INIT_PARAM(platform, "platform"),
355    INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
356    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
357    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
358
359END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
360
361CREATE_SIM_OBJECT(AlphaConsole)
362{
363    return new AlphaConsole(getInstanceName(), sim_console, disk,
364                            system, cpu, platform, num_cpus, mmu,
365                            addr, hier, io_bus);
366}
367
368REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole)
369