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