backdoor.cc revision 2512
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 "arch/alpha/system.hh"
38#include "base/inifile.hh"
39#include "base/str.hh"
40#include "base/trace.hh"
41#include "cpu/base.hh"
42#include "cpu/exec_context.hh"
43#include "dev/alpha_console.hh"
44#include "dev/simconsole.hh"
45#include "dev/simple_disk.hh"
46#include "dev/tsunami_io.hh"
47#include "sim/builder.hh"
48#include "sim/sim_object.hh"
49
50using namespace std;
51using namespace AlphaISA;
52
53AlphaConsole::AlphaConsole(Params *p)
54    : PioDevice(p->name, p->platform), disk(p->disk),
55      console(params()->cons), system(params()->sys), cpu(params()->cpu),
56      pioSize(sizeof(struct alphaAccess))
57{
58
59    alphaAccess = new Access;
60    alphaAccess->last_offset = size - 1;
61
62    alphaAccess->version = ALPHA_ACCESS_VERSION;
63    alphaAccess->diskUnit = 1;
64
65    alphaAccess->diskCount = 0;
66    alphaAccess->diskPAddr = 0;
67    alphaAccess->diskBlock = 0;
68    alphaAccess->diskOperation = 0;
69    alphaAccess->outputChar = 0;
70    alphaAccess->inputChar = 0;
71    bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack));
72
73    system->setAlphaAccess(addr);
74}
75
76void
77AlphaConsole::startup()
78{
79    alphaAccess->numCPUs = system->getNumCPUs();
80    alphaAccess->kernStart = system->getKernelStart();
81    alphaAccess->kernEnd = system->getKernelEnd();
82    alphaAccess->entryPoint = system->getKernelEntry();
83    alphaAccess->mem_size = system->physmem->size();
84    alphaAccess->cpuClock = cpu->frequency() / 1000000; // In MHz
85    alphaAccess->intrClockFrequency = platform->intrFrequency();
86}
87
88Tick
89AlphaConsole::read(Packet &pkt)
90{
91    pkt.time = curTick + pioDelay;
92
93    /** XXX Do we want to push the addr munging to a bus brige or something? So
94     * the device has it's physical address and then the bridge adds on whatever
95     * machine dependent address swizzle is required?
96     */
97
98    assert(pkt.result == Unknown);
99    assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
100    Addr daddr = req.addr - pioAddr;
101
102    switch (req.size)
103    {
104        case sizeof(uint32_t):
105            if (!pkt.data) pkt.pkt.data = new uint32_t;
106            switch (daddr)
107            {
108                case offsetof(AlphaAccess, last_offset):
109                    *(uint32_t*)pkt.data = alphaAccess->last_offset;
110                    break;
111                case offsetof(AlphaAccess, version):
112                    *(uint32_t*)pkt.data = alphaAccess->version;
113                    break;
114                case offsetof(AlphaAccess, numCPUs):
115                    *(uint32_t*)pkt.data = alphaAccess->numCPUs;
116                    break;
117                case offsetof(AlphaAccess, intrClockFrequency):
118                    *(uint32_t*)pkt.data = alphaAccess->intrClockFrequency;
119                    break;
120                default:
121                    /* Old console code read in everyting as a 32bit int
122                     * we now break that for better error checking.
123                     */
124                    pkt.result = BadAddress;
125            }
126            DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
127                    *(uint32_t*)pkt.data);
128            break;
129        case sizeof(uint64_t):
130            if (!pkt.data) pkt.pkt.data = new uint64_t;
131            switch (daddr)
132            {
133                case offsetof(AlphaAccess, inputChar):
134                    *(uint64_t*)pkt.data = console->console_in();
135                    break;
136                case offsetof(AlphaAccess, cpuClock):
137                    *(uint64_t*)pkt.data = alphaAccess->cpuClock;
138                    break;
139                case offsetof(AlphaAccess, mem_size):
140                    *(uint64_t*)pkt.data = alphaAccess->mem_size;
141                    break;
142                case offsetof(AlphaAccess, kernStart):
143                    *(uint64_t*)pkt.data = alphaAccess->kernStart;
144                    break;
145                case offsetof(AlphaAccess, kernEnd):
146                    *(uint64_t*)pkt.data = alphaAccess->kernEnd;
147                    break;
148                case offsetof(AlphaAccess, entryPoint):
149                    *(uint64_t*)pkt.data = alphaAccess->entryPoint;
150                    break;
151                case offsetof(AlphaAccess, diskUnit):
152                    *(uint64_t*)pkt.data = alphaAccess->diskUnit;
153                    break;
154                case offsetof(AlphaAccess, diskCount):
155                    *(uint64_t*)pkt.data = alphaAccess->diskCount;
156                    break;
157                case offsetof(AlphaAccess, diskPAddr):
158                    *(uint64_t*)pkt.data = alphaAccess->diskPAddr;
159                    break;
160                case offsetof(AlphaAccess, diskBlock):
161                    *(uint64_t*)pkt.data = alphaAccess->diskBlock;
162                    break;
163                case offsetof(AlphaAccess, diskOperation):
164                    *(uint64_t*)pkt.data = alphaAccess->diskOperation;
165                    break;
166                case offsetof(AlphaAccess, outputChar):
167                    *(uint64_t*)pkt.data = alphaAccess->outputChar;
168                    break;
169                default:
170                    int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
171                                 sizeof(alphaAccess->cpuStack[0]);
172
173                    if (cpunum >= 0 && cpunum < 64)
174                        *(uint64_t*)pkt.data = alphaAccess->cpuStack[cpunum];
175                    else
176                        panic("Unknown 64bit access, %#x\n", daddr);
177            }
178            DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
179                    *(uint64_t*)data);
180            break;
181        default:
182            pkt.result = BadAddress;
183    }
184    if (pkt.result == Unknown) pkt.result = Success;
185    return pioDelay;
186}
187
188Tick
189AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
190{
191    pkt.time = curTick + pioDelay;
192
193    assert(pkt.result == Unknown);
194    assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
195    Addr daddr = req.addr - pioAddr;
196
197    uint64_t val = *(uint64_t *)data;
198    assert(pkt.size == sizeof(uint64_t));
199
200    switch (daddr) {
201      case offsetof(AlphaAccess, diskUnit):
202        alphaAccess->diskUnit = val;
203        break;
204
205      case offsetof(AlphaAccess, diskCount):
206        alphaAccess->diskCount = val;
207        break;
208
209      case offsetof(AlphaAccess, diskPAddr):
210        alphaAccess->diskPAddr = val;
211        break;
212
213      case offsetof(AlphaAccess, diskBlock):
214        alphaAccess->diskBlock = val;
215        break;
216
217      case offsetof(AlphaAccess, diskOperation):
218        if (val == 0x13)
219            disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
220                       alphaAccess->diskCount);
221        else
222            panic("Invalid disk operation!");
223
224        break;
225
226      case offsetof(AlphaAccess, outputChar):
227        console->out((char)(val & 0xff));
228        break;
229
230      default:
231        int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
232                     sizeof(alphaAccess->cpuStack[0]);
233        warn("%d: Trying to launch CPU number %d!", curTick, cpunum);
234        assert(val > 0 && "Must not access primary cpu");
235        if (cpunum >= 0 && cpunum < 64)
236            alphaAccess->cpuStack[cpunum] = val;
237        else
238            panic("Unknown 64bit access, %#x\n", daddr);
239    }
240
241    pkt.result = Success;
242
243    return pioDelay;
244}
245
246void
247AlphaConsole::Access::serialize(ostream &os)
248{
249    SERIALIZE_SCALAR(last_offset);
250    SERIALIZE_SCALAR(version);
251    SERIALIZE_SCALAR(numCPUs);
252    SERIALIZE_SCALAR(mem_size);
253    SERIALIZE_SCALAR(cpuClock);
254    SERIALIZE_SCALAR(intrClockFrequency);
255    SERIALIZE_SCALAR(kernStart);
256    SERIALIZE_SCALAR(kernEnd);
257    SERIALIZE_SCALAR(entryPoint);
258    SERIALIZE_SCALAR(diskUnit);
259    SERIALIZE_SCALAR(diskCount);
260    SERIALIZE_SCALAR(diskPAddr);
261    SERIALIZE_SCALAR(diskBlock);
262    SERIALIZE_SCALAR(diskOperation);
263    SERIALIZE_SCALAR(outputChar);
264    SERIALIZE_SCALAR(inputChar);
265    SERIALIZE_ARRAY(cpuStack,64);
266}
267
268void
269AlphaConsole::Access::unserialize(Checkpoint *cp, const std::string &section)
270{
271    UNSERIALIZE_SCALAR(last_offset);
272    UNSERIALIZE_SCALAR(version);
273    UNSERIALIZE_SCALAR(numCPUs);
274    UNSERIALIZE_SCALAR(mem_size);
275    UNSERIALIZE_SCALAR(cpuClock);
276    UNSERIALIZE_SCALAR(intrClockFrequency);
277    UNSERIALIZE_SCALAR(kernStart);
278    UNSERIALIZE_SCALAR(kernEnd);
279    UNSERIALIZE_SCALAR(entryPoint);
280    UNSERIALIZE_SCALAR(diskUnit);
281    UNSERIALIZE_SCALAR(diskCount);
282    UNSERIALIZE_SCALAR(diskPAddr);
283    UNSERIALIZE_SCALAR(diskBlock);
284    UNSERIALIZE_SCALAR(diskOperation);
285    UNSERIALIZE_SCALAR(outputChar);
286    UNSERIALIZE_SCALAR(inputChar);
287    UNSERIALIZE_ARRAY(cpuStack, 64);
288}
289
290void
291AlphaConsole::serialize(ostream &os)
292{
293    alphaAccess->serialize(os);
294}
295
296void
297AlphaConsole::unserialize(Checkpoint *cp, const std::string &section)
298{
299    alphaAccess->unserialize(cp, section);
300}
301
302BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
303
304    SimObjectParam<SimConsole *> sim_console;
305    SimObjectParam<SimpleDisk *> disk;
306    SimObjectParam<MemoryController *> mmu;
307    Param<Addr> addr;
308    SimObjectParam<AlphaSystem *> system;
309    SimObjectParam<BaseCPU *> cpu;
310    SimObjectParam<Platform *> platform;
311    SimObjectParam<Bus*> pio_bus;
312    Param<Tick> pio_latency;
313    SimObjectParam<HierParams *> hier;
314
315END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
316
317BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
318
319    INIT_PARAM(sim_console, "The Simulator Console"),
320    INIT_PARAM(disk, "Simple Disk"),
321    INIT_PARAM(mmu, "Memory Controller"),
322    INIT_PARAM(addr, "Device Address"),
323    INIT_PARAM(system, "system object"),
324    INIT_PARAM(cpu, "Processor"),
325    INIT_PARAM(platform, "platform"),
326    INIT_PARAM(pio_bus, "The IO Bus to attach to"),
327    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
328    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
329
330END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
331
332CREATE_SIM_OBJECT(AlphaConsole)
333{
334    return new AlphaConsole(getInstanceName(), sim_console, disk,
335                            system, cpu, platform, mmu, addr, hier, pio_bus);
336}
337
338REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole)
339