1 /* Bare metal PPC KVM app, for libre-soc simulator comparison purposes
2 Copyright (C) 2021 Lauri Kasanen
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, version 3 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/kvm.h>
27 #include <sys/ioctl.h>
29 #include <sys/types.h>
34 static void nukenewline(char buf
[]) {
36 for (i
= 0; buf
[i
]; i
++) {
44 static void help(const char argv0
[]) {
46 printf("Usage: %s [args] -i file.bin\n\n"
48 "-i --binary file Raw, bare metal executable\n"
49 "-g --intregs file Text file setting up GPRs\n"
50 "-f --fpregs file Text file setting up FPRs\n"
51 "-s --spregs file Text file setting up SPRs (unnecessary if only LR is needed)\n"
52 "-l --load file:addr Load this binary to RAM\n"
53 "-d --dump file:addr:len Save this RAM area after running\n"
54 "-t --trace file Save a full trace to this file\n"
55 "-h --help This help\n\n"
57 "Load and dump may be given multiple times. GPR/FPR are numbered,\n"
58 "SPRs are named.\n", argv0
);
63 static void parseregs(const char name
[], const uint8_t gpr
) {
65 FILE *f
= fopen(name
, "r");
67 printf("Can't open %s\n", name
);
73 while (fgets(buf
, 256, f
)) {
78 const uint8_t reg
= strtol(buf
, NULL
, 0);
79 const char *ptr
= strchr(buf
+ 1, ' ');
81 printf("Invalid line '%s'\n", buf
);
85 const uint64_t val
= strtol(ptr
, NULL
, 0);
96 static void parsesprs(const char name
[]) {
98 FILE *f
= fopen(name
, "r");
100 printf("Can't open %s\n", name
);
106 while (fgets(buf
, 256, f
)) {
113 #define check(a) if (!strncasecmp(buf, a, sizeof(a) - 1))
122 printf("Unknown (unimplemented?) SPR register '%s'\n",
127 const char *ptr
= strchr(buf
+ 1, ' ');
129 printf("Invalid line '%s'\n", buf
);
133 const uint64_t val
= strtol(ptr
, NULL
, 0);
141 static void load(const char arg
[]) {
144 const char *ptr
= strchr(arg
, ':');
146 printf("Invalid load\n");
150 const unsigned namelen
= ptr
- arg
;
152 strncpy(name
, arg
, namelen
);
153 name
[namelen
] = '\0';
155 const uint64_t addr
= strtol(ptr
+ 1, NULL
, 0);
157 FILE *f
= fopen(name
, "r");
159 printf("Can't open %s\n", name
);
163 fseek(f
, 0, SEEK_END
);
164 const unsigned len
= ftell(f
);
172 int main(int argc
, char **argv
) {
174 const struct option longopts
[] = {
175 { "binary", 1, NULL
, 'i' },
176 { "intregs", 1, NULL
, 'g' },
177 { "fpregs", 1, NULL
, 'f' },
178 { "spregs", 1, NULL
, 's' },
179 { "load", 1, NULL
, 'l' },
180 { "dump", 1, NULL
, 'd' },
181 { "trace", 1, NULL
, 't' },
182 { "help", 0, NULL
, 'h' },
185 const char opts
[] = "i:g:f:s:l:d:t:h";
188 FILE *binary
= NULL
, *trace
= NULL
;
189 char dumps
[MAXDUMPS
][PATH_MAX
];
190 unsigned num_dumps
= 0;
193 const int c
= getopt_long(argc
, argv
, opts
, longopts
, NULL
);
200 printf("Only one binary allowed\n");
204 binary
= fopen(optarg
, "r");
206 printf("Failed to open %s\n", optarg
);
211 parseregs(optarg
, 1);
214 parseregs(optarg
, 0);
223 if (num_dumps
>= MAXDUMPS
) {
224 printf("Too many dumps\n");
228 strncpy(dumps
[num_dumps
], optarg
, PATH_MAX
);
229 dumps
[num_dumps
][PATH_MAX
- 1] = '\0';
234 printf("Only one trace allowed\n");
238 trace
= fopen(optarg
, "w");
240 printf("Failed to open %s\n", optarg
);
255 fseek(binary
, 0, SEEK_END
);
256 const unsigned binlen
= ftell(binary
);
259 printf("Loading binary %u bytes\n", binlen
); // TODO
261 kvm
= open("/dev/kvm", O_RDWR
| O_CLOEXEC
);
263 printf("Failed to open kvm, perhaps you lack permissions?\n");
268 ret
= ioctl(kvm
, KVM_GET_API_VERSION
, NULL
);
269 if (ret
== -1 || ret
!= 12) abort();