m5.c revision 8229
1/*
2 * Copyright (c) 2003-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 * Authors: Nathan Binkert
29 */
30
31#ifdef linux
32#define _GNU_SOURCE
33#include <sched.h>
34#endif
35
36#include <err.h>
37#include <fcntl.h>
38#include <inttypes.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
44#include "m5op.h"
45
46char *progname;
47char *command = "unspecified";
48void usage();
49
50void
51parse_int_args(int argc, char *argv[], uint64_t ints[], int len)
52{
53    if (argc > len)
54        usage();
55
56    int i;
57    for (i = 0; i < len; ++i)
58        ints[i] = (i < argc) ? strtoul(argv[i], NULL, 0) : 0;
59}
60
61int
62read_file(int dest_fid)
63{
64    char buf[256*1024];
65    int offset = 0;
66    int len;
67
68    // Touch all buffer pages to ensure they are mapped in the
69    // page table. This is required in the case of X86_FS, where
70    // Linux does demand paging.
71    memset(buf, 0, sizeof(buf));
72
73    while ((len = m5_readfile(buf, sizeof(buf), offset)) > 0) {
74        write(dest_fid, buf, len);
75        offset += len;
76    }
77}
78
79void
80do_exit(int argc, char *argv[])
81{
82    if (argc > 1)
83        usage();
84
85    m5_exit((argc > 0) ? strtoul(argv[0], NULL, 0) : 0);
86}
87
88void
89do_reset_stats(int argc, char *argv[])
90{
91    uint64_t ints[2];
92    parse_int_args(argc, argv, ints, 2);
93    m5_reset_stats(ints[0], ints[1]);
94}
95
96void
97do_dump_stats(int argc, char *argv[])
98{
99    uint64_t ints[2];
100    parse_int_args(argc, argv, ints, 2);
101    m5_dump_stats(ints[0], ints[1]);
102}
103
104void
105do_dump_reset_stats(int argc, char *argv[])
106{
107    uint64_t ints[2];
108    parse_int_args(argc, argv, ints, 2);
109    m5_dumpreset_stats(ints[0], ints[1]);
110}
111
112void
113do_read_file(int argc, char *argv[])
114{
115    if (argc > 0)
116        usage();
117
118    read_file(STDOUT_FILENO);
119}
120
121void
122do_exec_file(int argc, char *argv[])
123{
124    if (argc > 0)
125        usage();
126
127    const char *destname = "/tmp/execfile";
128
129    int fid = open(destname, O_WRONLY, 0777);
130    int len = read_file(fid);
131    close(fid);
132    if (len > 0) {
133        execl(destname, "execfile", NULL);
134        err(1, "execl failed!");
135    }
136}
137
138void
139do_checkpoint(int argc, char *argv[])
140{
141    uint64_t ints[2];
142    parse_int_args(argc, argv, ints, 2);
143    m5_checkpoint(ints[0], ints[1]);
144}
145
146void
147do_load_symbol(int argc, char *argv[])
148{
149    if (argc != 2)
150        usage();
151
152    uint64_t addr = strtoul(argv[0], NULL, 0);
153    char *symbol = argv[1];
154    m5_loadsymbol(addr, symbol);
155}
156
157void
158do_initparam(int argc, char *argv[])
159{
160    if (argc != 0)
161        usage();
162
163
164    printf("%ld", m5_initparam());
165}
166
167void
168do_sw99param(int argc, char *argv[])
169{
170    if (argc != 0)
171        usage();
172
173    uint64_t param = m5_initparam();
174
175    // run-time, rampup-time, rampdown-time, warmup-time, connections
176    printf("%d %d %d %d %d", (param >> 48) & 0xfff,
177           (param >> 36) & 0xfff, (param >> 24) & 0xfff,
178           (param >> 12) & 0xfff, (param >> 0) & 0xfff);
179}
180
181#ifdef linux
182void
183do_pin(int argc, char *argv[])
184{
185    if (argc < 2)
186        usage();
187
188    cpu_set_t mask;
189    CPU_ZERO(&mask);
190
191    const char *sep = ",";
192    char *target = strtok(argv[0], sep);
193    while (target) {
194        CPU_SET(atoi(target), &mask);
195        target = strtok(NULL, sep);
196    }
197
198    if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) < 0)
199        err(1, "setaffinity");
200
201    execvp(argv[1], &argv[1]);
202    err(1, "execvp failed!");
203}
204#endif
205
206struct MainFunc
207{
208    char *name;
209    void (*func)(int argc, char *argv[]);
210    char *usage;
211};
212
213struct MainFunc mainfuncs[] = {
214    { "exit",           do_exit,             "[delay]" },
215    { "resetstats",     do_reset_stats,      "[delay [period]]" },
216    { "dumpstats",      do_dump_stats,       "[delay [period]]" },
217    { "dumpresetstats", do_dump_reset_stats, "[delay [period]]" },
218    { "readfile",       do_read_file,        "[filename]" },
219    { "execfile",       do_exec_file,        "<filename>" },
220    { "checkpoint",     do_checkpoint,       "[delay [period]]" },
221    { "loadsymbol",     do_load_symbol,      "<address> <symbol>" },
222    { "initparam",      do_initparam,        "" },
223    { "sw99param",      do_sw99param,        "" },
224#ifdef linux
225    { "pin",            do_pin,              "<cpu> <program> [args ...]" }
226#endif
227};
228int numfuncs = sizeof(mainfuncs) / sizeof(mainfuncs[0]);
229
230void
231usage()
232{
233    int i;
234
235    for (i = 0; i < numfuncs; ++i) {
236        char *header = i ? "" : "usage:";
237        fprintf(stderr, "%-6s %s %s %s\n",
238                header, progname, mainfuncs[i].name, mainfuncs[i].usage);
239    }
240    fprintf(stderr, "\n");
241    fprintf(stderr, "All times in nanoseconds!\n");
242
243    exit(1);
244}
245
246int
247main(int argc, char *argv[])
248{
249    progname = argv[0];
250    if (argc < 2)
251        usage(1);
252
253    command = argv[1];
254
255    argv += 2;
256    argc -= 2;
257
258    int i;
259    for (i = 0; i < numfuncs; ++i) {
260        if (strcmp(command, mainfuncs[i].name) != 0)
261            continue;
262
263        mainfuncs[i].func(argc, argv);
264        exit(0);
265    }
266
267    usage(1);
268}
269