|
|
1.1 root 1: /*
2: * Cisco 7200 (Predator) simulation platform.
3: * Copyright (c) 2005,2006 Christophe Fillot ([email protected])
4: *
5: * Many thanks to Nicolas Szalay for his patch
6: * for the command line parsing and virtual machine
7: * settings (RAM, ROM, NVRAM, ...)
8: */
9:
10: #include <stdio.h>
11: #include <stdlib.h>
12: #include <unistd.h>
13: #include <string.h>
14: #include <sys/types.h>
15: #include <sys/stat.h>
16: #include <sys/mman.h>
17: #include <signal.h>
18: #include <fcntl.h>
19: #include <assert.h>
20:
21: #include ARCH_INC_FILE
22:
23: #include "rbtree.h"
24: #include "cp0.h"
25: #include "memory.h"
26: #include "cpu.h"
27: #include "device.h"
28: #include "mips64_exec.h"
29: #include "dev_c7200.h"
30: #include "dev_c7200_bay.h"
31: #include "dev_vtty.h"
32: #include "ptask.h"
33: #include "atm.h"
1.1.1.2 ! root 34: #include "crc.h"
! 35: #include "net_io.h"
1.1 root 36: #include "net_io_bridge.h"
37:
1.1.1.2 ! root 38: #ifdef GEN_ETH
! 39: #include "gen_eth.h"
! 40: #endif
! 41:
1.1 root 42: #ifdef PROFILE
43: #include "profiler.h"
44: #endif
45:
46: /* Default name for logfile */
47: #define LOGFILE_DEFAULT_NAME "pred_log0.txt"
48:
49: /* Software version */
1.1.1.2 ! root 50: static const char *sw_version = "0.2.3c-"JIT_ARCH;
1.1 root 51:
52: /* Log file */
53: FILE *log_file = NULL;
54:
55: /* Instruction block trace (produces tons of logs!) */
56: int insn_itrace = 0;
57:
58: /* JIT use */
59: int jit_use = JIT_SUPPORT;
60:
61: /* VM flags */
62: volatile int vm_save_state = 0;
63: volatile int vm_running = 0;
64:
65: /* Cisco 7200 router instance */
66: c7200_t c7200_router;
67:
68: /* By default, use embedded ROM */
69: char *rom_filename = NULL;
70:
71: /* RAM size (in Mb, by default 256) */
72: u_int ram_size = 256;
73:
74: /* ROM size (in Mb, by default 4) */
75: u_int rom_size = 4;
76:
77: /* NVRAM size (in Kb, by default 128) */
78: u_int nvram_size = 128;
79:
80: /* Config register */
81: u_int conf_reg = 0x2102;
82:
83: /* Clock divisor (see cp0.c) */
84: u_int clock_divisor = 2;
85:
86: /* Port Adapter descriptions */
87: static char *pa_desc[MAX_PA_BAYS];
88: static int pa_index = 0;
89:
90: /* Console port VTTY type and parameters */
91: int vtty_con_type = VTTY_TYPE_TERM;
92: int vtty_con_tcp_port;
93:
94: /* AUX port VTTY type and parameters */
95: int vtty_aux_type = VTTY_TYPE_NONE;
96: int vtty_aux_tcp_port;
97:
98: /* Symbols */
99: rbtree_tree *sym_tree = NULL;
100:
101: /* ELF entry point */
102: m_uint32_t ios_entry_point;
103:
104: /* Symbol lookup */
105: struct symbol *sym_lookup(m_uint64_t addr)
106: {
107: return(rbtree_lookup(sym_tree,&addr));
108: }
109:
110: /* Insert a new symbol */
111: struct symbol *sym_insert(char *name,m_uint64_t addr)
112: {
113: struct symbol *sym;
114: size_t len;
115:
116: len = strlen(name);
117:
118: if (!(sym = malloc(len + sizeof(*sym))))
119: return NULL;
120:
121: memcpy(sym->name,name,len+1);
122: sym->addr = addr;
123:
124: if (rbtree_insert(sym_tree,sym,sym) == -1) {
125: free(sym);
126: return NULL;
127: }
128:
129: return sym;
130: }
131:
132: /* Symbol comparison function */
133: static int sym_compare(m_uint64_t *a1,struct symbol *sym)
134: {
135: if (*a1 > sym->addr)
136: return(1);
137:
138: if (*a1 < sym->addr)
139: return(-1);
140:
141: return(0);
142: }
143:
144: /* Create the symbol tree */
145: int sym_create_tree(void)
146: {
147: sym_tree = rbtree_create((tree_fcompare)sym_compare,NULL);
148: return(sym_tree ? 0 : -1);
149: }
150:
151: /* Generic signal handler */
152: void signal_gen_handler(int sig)
153: {
154: switch(sig) {
155: case SIGHUP:
156: insn_itrace = 1 - insn_itrace;
157: printf("Instruction block trace %sabled\n",
158: insn_itrace ? "en" : "dis");
159: break;
160:
161: case SIGQUIT:
162: /* save VM context */
163: vm_save_state = TRUE;
164: vm_running = FALSE;
165: break;
166:
167: default:
168: fprintf(stderr,"Unhandled signal %d\n",sig);
169: }
170: }
171:
172: /* Setups signals */
173: static void setup_signals(void)
174: {
175: struct sigaction act;
176:
177: memset(&act,0,sizeof(act));
178: act.sa_handler = signal_gen_handler;
179: act.sa_flags = SA_RESTART;
180: sigaction(SIGHUP,&act,NULL);
181: sigaction(SIGQUIT,&act,NULL);
182: }
183:
184: /* Load a raw image into the simulated memory */
185: int load_raw_image(cpu_mips_t *cpu,char *filename,m_uint64_t vaddr)
186: {
187: struct stat file_info;
188: size_t len,clen;
189: void *haddr;
190: FILE *bfd;
191:
192: if (!(bfd = fopen(filename,"r"))) {
193: perror("fopen");
194: return(-1);
195: }
196:
197: if (fstat(fileno(bfd),&file_info) == -1) {
198: perror("stat");
199: return(-1);
200: }
201:
202: len = file_info.st_size;
203:
204: printf("Loading RAW file '%s' at virtual address 0x%llx (size=%lu)\n",
205: filename,vaddr,(u_long)len);
206:
207: while(len > 0)
208: {
209: haddr = cpu->mem_op_lookup(cpu,vaddr);
210:
211: if (!haddr) {
212: fprintf(stderr,"load_raw_image: invalid load address 0x%llx\n",
213: vaddr);
214: return(-1);
215: }
216:
217: if (len > MIPS_MIN_PAGE_SIZE)
218: clen = MIPS_MIN_PAGE_SIZE;
219: else
220: clen = len;
221:
222: clen = fread((u_char *)haddr,clen,1,bfd);
223:
224: if (clen != 1)
225: break;
226:
227: vaddr += MIPS_MIN_PAGE_SIZE;
228: len -= clen;
229: }
230:
231: fclose(bfd);
232: return(0);
233: }
234:
235: /* Load an ELF image into the simulated memory */
236: int load_elf_image(cpu_mips_t *cpu,char *filename,m_uint32_t *entry_point)
237: {
238: m_uint64_t vaddr;
239: void *haddr;
240: Elf32_Ehdr *ehdr;
241: Elf32_Phdr *phdr;
242: Elf *img_elf;
243: size_t len,clen;
244: int i,fd;
245: FILE *bfd;
246:
247: if ((fd = open(filename,O_RDONLY)) == -1)
248: return(-1);
249:
250: if (elf_version(EV_CURRENT) == EV_NONE) {
251: fprintf(stderr,"load_elf_image: library out of date\n");
252: return(-1);
253: }
254:
255: if (!(img_elf = elf_begin(fd,ELF_C_READ,NULL))) {
256: fprintf(stderr,"load_elf_image: elf_begin: %s\n",
257: elf_errmsg(elf_errno()));
258: return(-1);
259: }
260:
261: if (!(phdr = elf32_getphdr(img_elf))) {
262: fprintf(stderr,"load_elf_image: elf32_getphdr: %s\n",
263: elf_errmsg(elf_errno()));
264: return(-1);
265: }
266:
267: ehdr = elf32_getehdr(img_elf);
268: phdr = elf32_getphdr(img_elf);
269:
270: printf("Loading ELF file '%s'...\n",filename);
271: bfd = fdopen(fd,"rb");
272:
273: if (!bfd) {
274: perror("load_elf_image: fdopen");
275: return(-1);
276: }
277:
278: for(i=0;i<ehdr->e_phnum;i++,phdr++)
279: {
280: fseek(bfd,phdr->p_offset,SEEK_SET);
281:
282: vaddr = (m_uint64_t)phdr->p_vaddr;
283: len = phdr->p_filesz;
284:
285: printf(" * Adding section at virtual address 0x%llx\n",vaddr);
286:
287: while(len > 0)
288: {
289: haddr = cpu->mem_op_lookup(cpu,vaddr);
290:
291: if (!haddr) {
292: fprintf(stderr,"load_elf_image: invalid load address 0x%llx\n",
293: vaddr);
294: return(-1);
295: }
296:
297: if (len > MIPS_MIN_PAGE_SIZE)
298: clen = MIPS_MIN_PAGE_SIZE;
299: else
300: clen = len;
301:
302: clen = fread((u_char *)haddr,clen,1,bfd);
303:
304: if (clen != 1)
305: break;
306:
307: vaddr += MIPS_MIN_PAGE_SIZE;
308: len -= clen;
309: }
310: }
311:
312: printf("ELF entry point: 0x%x\n",ehdr->e_entry);
313:
314: if (entry_point)
315: *entry_point = ehdr->e_entry;
316:
317: return(0);
318: }
319:
320: /* Load a symbol file */
321: int load_sym_file(char *filename)
322: {
323: char buffer[4096],func_name[128];
324: m_uint64_t addr;
325: char sym_type;
326: FILE *fd;
327:
328: if ((!sym_tree) && (sym_create_tree() == -1)) {
329: fprintf(stderr,"Unable to create symbol tree.\n");
330: return(-1);
331: }
332:
333: if (!(fd = fopen(filename,"r"))) {
334: perror("load_sym_file: fopen");
335: return(-1);
336: }
337:
338: while(!feof(fd)) {
339: fgets(buffer,sizeof(buffer),fd);
340:
341: if (sscanf(buffer,"%llx %c %s",&addr,&sym_type,func_name) == 3) {
342: sym_insert(func_name,addr);
343: }
344: }
345:
346: fclose(fd);
347: return(0);
348: }
349:
350: /* Display the command line use */
351: static void show_usage(int argc,char *argv[])
352: {
353: printf("Usage: %s [options] <ios_image>\n\n",argv[0]);
354:
355: printf("Available options:\n"
356: " -r <ram_size> : Set the virtual RAM size (default is %d Mb)\n"
357: " -o <rom_size> : Set the virtual ROM size (default is %d Mb)\n"
358: " -n <nvram_size> : Set the NVRAM size (default is %d Kb)\n"
359: " -l <log_file> : Set logging file (default is %s)\n"
360: " -C <cfg_file> : Import an IOS configuration file into NVRAM\n"
361: " -R <rom_file> : Load an alternate ROM (default is embedded)\n"
362: " -s <sym_file> : Load symbol file\n"
363: " -c <conf_reg> : Set the configuration register "
364: "(default is 0x%04x)\n"
365: " -m <mac_addr> : Set the MAC address of the chassis "
366: "(IOS chooses default)\n"
367: " -k <clock_div> : Set the clock divisor (default is %d)\n"
368: " -T <port> : Console is on TCP <port> "
369: "(default is on the terminal)\n"
370: " -A <port> : AUX is on TCP <port> (default is no AUX port)\n"
371: " -i : Instruction block trace, very slow\n"
372: " -j : Disable the JIT compiler, very slow\n"
373: " -t <npe_type> : Select NPE type\n"
374: " -M <midplane> : Select Midplane (\"std\" or \"vxr\")\n"
375: " -p <pa_desc> : Define a Port Adapter\n"
376: " -a <cfg_file> : Virtual ATM switch configuration file\n"
377: " -b <cfg_file> : Virtual bridge configuration file\n"
1.1.1.2 ! root 378: " -e : Show network device list\n"
1.1 root 379: "\n",
380: ram_size,rom_size,nvram_size,LOGFILE_DEFAULT_NAME,
381: conf_reg,clock_divisor);
382:
383: printf("<pa_desc> format:\n"
384: " \"slot:pa_driver:netio_type{:netio_parameters}\"\n"
385: "\n");
386:
387: /* Show the possible NPE drivers */
388: c7200_npe_show_drivers();
389:
390: /* Show the possible PA drivers */
391: c7200_pa_show_drivers();
392:
393: /* Show the possible NETIO types */
394: netio_show_types();
395: }
396:
397: int main(int argc,char *argv[])
398: {
1.1.1.2 ! root 399: char *options_list = "r:o:n:c:m:l:C:ijt:p:k:T:A:a:b:s:R:M:e";
1.1 root 400: char *log_file_name = NULL;
401: char *ios_image_name;
402: char *ios_cfg_file = NULL;
403: char *mac_addr = NULL;
404: int option;
405: cpu_mips_t *cpu0;
406: m_uint32_t rom_entry_point;
407:
408: #ifdef PROFILE
409: atexit(profiler_savestat);
410: #endif
411:
412: printf("Cisco 7200 Simulation Platform (version %s)\n",sw_version);
413: printf("Copyright (c) 2005,2006 Christophe Fillot.\n\n");
414:
415: memset(&c7200_router,0,sizeof(c7200_router));
416:
1.1.1.2 ! root 417: /* Initialize CRC functions */
! 418: crc_init();
! 419:
1.1 root 420: /* Initialize ATM code */
421: atm_init();
422:
423: /* Command line arguments : early try */
424: opterr = 0;
425:
426: while((option = getopt(argc,argv,options_list)) != -1) {
427: switch(option)
428: {
429: /* RAM size */
430: case 'r':
431: ram_size = strtol(optarg, NULL, 10);
432: printf("Virtual RAM size set to %d MB.\n",ram_size);
433: break;
434:
435: /* ROM size */
436: case 'o':
437: rom_size = strtol(optarg, NULL, 10);
438: printf("Virtual ROM size set to %d MB.\n",rom_size);
439: break;
440:
441: /* NVRAM size */
442: case 'n':
443: nvram_size = strtol(optarg, NULL, 10);
444: printf("NVRAM size set to %d KB.\n", nvram_size);
445: break;
446:
447: /* Config Register */
448: case 'c':
449: conf_reg = strtol(optarg, NULL, 0);
450: printf("Config. Register set to 0x%x.\n",conf_reg);
451: break;
452:
453: /* Set the base MAC address */
454: case 'm':
455: mac_addr = optarg;
456: printf("MAC address set to '%s'.\n",mac_addr);
457: break;
458:
459: /* Log file */
460: case 'l':
461: if (!(log_file_name = malloc(strlen(optarg)+1))) {
462: fprintf(stderr,"Unable to set log file name.\n");
463: exit(EXIT_FAILURE);
464: }
465: strcpy(log_file_name, optarg);
466: printf("Log file: writing to %s\n",log_file_name);
467: break;
468:
469: /* IOS configuration file */
470: case 'C':
471: ios_cfg_file = optarg;
472: break;
473:
474: /* Alternate ROM */
475: case 'R':
476: rom_filename = optarg;
477: break;
478:
479: /* Symbol file */
480: case 's':
481: load_sym_file(optarg);
482: break;
483:
484: /* Instruction block trace */
485: case 'i':
486: insn_itrace = TRUE;
487: break;
488:
489: /* Disable JIT */
490: case 'j':
491: jit_use = FALSE;
492: break;
493:
494: /* NPE type */
495: case 't':
496: c7200_router.npe_type = optarg;
497: break;
498:
499: /* Midplane type */
500: case 'M':
501: c7200_router.midplane_type = optarg;
502: break;
503:
504: /* PA settings */
505: case 'p':
506: if (pa_index == MAX_PA_BAYS)
507: fprintf(stderr,"All PA slots are filled.\n");
508: else
509: pa_desc[pa_index++] = optarg;
510: break;
511:
512: /* Clock divisor */
513: case 'k':
514: clock_divisor = atoi(optarg);
515:
516: if (!clock_divisor) {
517: fprintf(stderr,"Invalid Clock Divisor specified!\n");
518: exit(EXIT_FAILURE);
519: }
520:
521: printf("Using a clock divisor of %d.\n",clock_divisor);
522: break;
523:
524: /* TCP server for Console Port */
525: case 'T':
526: vtty_con_type = VTTY_TYPE_TCP;
527: vtty_con_tcp_port = atoi(optarg);
528: break;
529:
530: /* TCP server for AUX Port */
531: case 'A':
532: vtty_aux_type = VTTY_TYPE_TCP;
533: vtty_aux_tcp_port = atoi(optarg);
534: break;
535:
536: /* Virtual ATM switch */
537: case 'a':
538: if (atmsw_start(optarg) == -1)
539: exit(EXIT_FAILURE);
540: break;
541:
542: /* Virtual bridge */
543: case 'b':
544: if (netio_bridge_start(optarg) == -1)
545: exit(EXIT_FAILURE);
546: break;
547:
1.1.1.2 ! root 548: #ifdef GEN_ETH
! 549: /* Ethernet device list */
! 550: case 'e':
! 551: gen_eth_show_dev_list();
! 552: exit(EXIT_SUCCESS);
! 553: #endif
! 554:
1.1 root 555: /* Oops ! */
556: case '?':
557: show_usage(argc,argv);
558: exit(EXIT_FAILURE);
559: }
560: }
561:
562: /* Last argument, this is the IOS filename */
563: if (optind == (argc - 1)) {
564: /* setting IOS image file */
565: ios_image_name = argv[optind];
566: printf("IOS image file: %s\n\n", ios_image_name);
567: } else {
568: /* IOS missing */
569: fprintf(stderr,"Please specify an IOS image filename\n");
570: show_usage(argc,argv);
571: exit(EXIT_FAILURE);
572: }
573:
574: /* Set the default value of the log file name */
575: if (!log_file_name) {
576: if (!(log_file_name = malloc(strlen(LOGFILE_DEFAULT_NAME)+1))) {
577: fprintf(stderr,"Unable to set log file name.\n");
578: exit(EXIT_FAILURE);
579: }
580: strcpy(log_file_name,LOGFILE_DEFAULT_NAME);
581: }
582:
583: if (!(log_file = fopen(log_file_name,"w"))) {
584: fprintf(stderr,"Unable to create log file.\n");
585: exit(EXIT_FAILURE);
586: }
587:
588: /* Periodic tasks initialization */
589: if (ptask_init(0) == -1)
590: exit(EXIT_FAILURE);
591:
592: /* Create instruction lookup tables */
593: mips64_jit_create_ilt();
594: mips64_exec_create_ilt();
595:
596: /* Create a CPU group */
597: sys_cpu_group = cpu_group_create("System CPU Group");
598:
599: /* Initialize the virtual MIPS processor */
600: if (!(cpu0 = cpu_create(0))) {
601: fprintf(stderr,"Unable to create CPU0!\n");
602: exit(EXIT_FAILURE);
603: }
604:
605: /* Add this CPU to the system CPU group */
606: cpu_group_add(sys_cpu_group,cpu0);
607: c7200_router.cpu_group = sys_cpu_group;
608:
609: /* Initialize the C7200 platform */
610: if (c7200_init_platform(&c7200_router,pa_desc,mac_addr) == -1) {
611: fprintf(stderr,"Unable to initialize the C7200 platform hardware.\n");
612: exit(EXIT_FAILURE);
613: }
614:
615: /* Load IOS configuration file */
616: if (ios_cfg_file != NULL) {
617: dev_nvram_push_config(sys_cpu_group,ios_cfg_file);
618: conf_reg &= ~0x40;
619: }
620:
621: /* Load ROM (ELF image or embedded) */
622: rom_entry_point = 0xbfc00000;
623:
624: if (rom_filename) {
625: if (load_elf_image(cpu0,rom_filename,&rom_entry_point) < 0) {
626: fprintf(stderr,"Unable to load alternate ROM '%s', "
627: "fallback to embedded ROM.\n\n",rom_filename);
628: rom_filename = NULL;
629: }
630: }
631:
632: /* Load IOS image */
633: if (load_elf_image(cpu0,ios_image_name,&ios_entry_point) < 0) {
634: fprintf(stderr,"Cisco IOS load failed.\n");
635: exit(EXIT_FAILURE);
636: }
637:
638: cpu0->pc = sign_extend(rom_entry_point,32);
639: cpu0->cp0.reg[MIPS_CP0_PRID] = 0x2012ULL;
640: cpu0->cp0.reg[MIPS_CP0_CONFIG] = 0x00c08ff0ULL;
641:
642: setup_signals();
643:
644: /* Launch the simulation */
645: printf("\nStarting simulation (CPU0 PC=0x%llx), JIT is %sabled.\n",
646: cpu0->pc,jit_use ? "en":"dis");
647:
648: cpu_start(cpu0);
649:
650: /* Run until all CPU of the system CPU group are halted */
651: while(!cpu_group_check_state(sys_cpu_group,MIPS_CPU_HALTED))
652: usleep(200000);
653:
654: printf("\n\nSimulation halted (CPU0 PC=0x%llx).\n\n",cpu0->pc);
655: return(0);
656: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.