32 |
#include "dev_c3725.h" |
#include "dev_c3725.h" |
33 |
#include "dev_c3745.h" |
#include "dev_c3745.h" |
34 |
#include "dev_c2600.h" |
#include "dev_c2600.h" |
35 |
#include "dev_msfc1.h" |
#include "dev_c1700.h" |
36 |
|
#include "dev_c6msfc1.h" |
37 |
|
#include "dev_c6sup1.h" |
38 |
#include "ppc32_vmtest.h" |
#include "ppc32_vmtest.h" |
39 |
#include "dev_vtty.h" |
#include "dev_vtty.h" |
40 |
#include "ptask.h" |
#include "ptask.h" |
41 |
#include "timer.h" |
#include "timer.h" |
42 |
|
#include "plugin.h" |
43 |
#include "registry.h" |
#include "registry.h" |
44 |
#include "hypervisor.h" |
#include "hypervisor.h" |
45 |
#include "net_io.h" |
#include "net_io.h" |
63 |
const char *sw_version = DYNAMIPS_VERSION"-"JIT_ARCH; |
const char *sw_version = DYNAMIPS_VERSION"-"JIT_ARCH; |
64 |
|
|
65 |
/* Software version tag */ |
/* Software version tag */ |
66 |
const char *sw_version_tag = "2007042500"; |
const char *sw_version_tag = "2007050300"; |
67 |
|
|
68 |
/* Hypervisor */ |
/* Hypervisor */ |
69 |
int hypervisor_mode = 0; |
int hypervisor_mode = 0; |
70 |
int hypervisor_tcp_port = 0; |
int hypervisor_tcp_port = 0; |
71 |
|
char *hypervisor_ip_address = NULL; |
72 |
|
|
73 |
/* Log file */ |
/* Log file */ |
74 |
char *log_file_name = NULL; |
char *log_file_name = NULL; |
77 |
/* VM flags */ |
/* VM flags */ |
78 |
volatile int vm_save_state = 0; |
volatile int vm_save_state = 0; |
79 |
|
|
80 |
|
/* Default platform */ |
81 |
|
static char *default_platform = "7200"; |
82 |
|
|
83 |
/* Generic signal handler */ |
/* Generic signal handler */ |
84 |
void signal_gen_handler(int sig) |
void signal_gen_handler(int sig) |
85 |
{ |
{ |
161 |
} |
} |
162 |
|
|
163 |
/* Display the command line use */ |
/* Display the command line use */ |
164 |
static void show_usage(int argc,char *argv[],int platform) |
static void show_usage(vm_instance_t *vm,int argc,char *argv[]) |
165 |
{ |
{ |
|
u_int def_ram_size,def_rom_size,def_nvram_size; |
|
|
u_int def_conf_reg,def_clock_div; |
|
|
u_int def_disk0_size = 0,def_disk1_size = 0; |
|
|
u_int def_nm_iomem_size = 0; |
|
|
|
|
|
switch(platform) { |
|
|
case VM_TYPE_C7200: |
|
|
def_ram_size = C7200_DEFAULT_RAM_SIZE; |
|
|
def_rom_size = C7200_DEFAULT_ROM_SIZE; |
|
|
def_nvram_size = C7200_DEFAULT_NVRAM_SIZE; |
|
|
def_conf_reg = C7200_DEFAULT_CONF_REG; |
|
|
def_clock_div = C7200_DEFAULT_CLOCK_DIV; |
|
|
def_disk0_size = C7200_DEFAULT_DISK0_SIZE; |
|
|
def_disk1_size = C7200_DEFAULT_DISK1_SIZE; |
|
|
break; |
|
|
case VM_TYPE_C3600: |
|
|
def_ram_size = C3600_DEFAULT_RAM_SIZE; |
|
|
def_rom_size = C3600_DEFAULT_ROM_SIZE; |
|
|
def_nvram_size = C3600_DEFAULT_NVRAM_SIZE; |
|
|
def_conf_reg = C3600_DEFAULT_CONF_REG; |
|
|
def_clock_div = C3600_DEFAULT_CLOCK_DIV; |
|
|
def_disk0_size = C3600_DEFAULT_DISK0_SIZE; |
|
|
def_disk1_size = C3600_DEFAULT_DISK1_SIZE; |
|
|
def_nm_iomem_size = C3600_DEFAULT_IOMEM_SIZE; |
|
|
break; |
|
|
case VM_TYPE_C2691: |
|
|
def_ram_size = C2691_DEFAULT_RAM_SIZE; |
|
|
def_rom_size = C2691_DEFAULT_ROM_SIZE; |
|
|
def_nvram_size = C2691_DEFAULT_NVRAM_SIZE; |
|
|
def_conf_reg = C2691_DEFAULT_CONF_REG; |
|
|
def_clock_div = C2691_DEFAULT_CLOCK_DIV; |
|
|
def_disk0_size = C2691_DEFAULT_DISK0_SIZE; |
|
|
def_disk1_size = C2691_DEFAULT_DISK1_SIZE; |
|
|
def_nm_iomem_size = C2691_DEFAULT_IOMEM_SIZE; |
|
|
break; |
|
|
case VM_TYPE_C3725: |
|
|
def_ram_size = C3725_DEFAULT_RAM_SIZE; |
|
|
def_rom_size = C3725_DEFAULT_ROM_SIZE; |
|
|
def_nvram_size = C3725_DEFAULT_NVRAM_SIZE; |
|
|
def_conf_reg = C3725_DEFAULT_CONF_REG; |
|
|
def_clock_div = C3725_DEFAULT_CLOCK_DIV; |
|
|
def_disk0_size = C3725_DEFAULT_DISK0_SIZE; |
|
|
def_disk1_size = C3725_DEFAULT_DISK1_SIZE; |
|
|
def_nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE; |
|
|
break; |
|
|
case VM_TYPE_C3745: |
|
|
def_ram_size = C3745_DEFAULT_RAM_SIZE; |
|
|
def_rom_size = C3745_DEFAULT_ROM_SIZE; |
|
|
def_nvram_size = C3745_DEFAULT_NVRAM_SIZE; |
|
|
def_conf_reg = C3745_DEFAULT_CONF_REG; |
|
|
def_clock_div = C3745_DEFAULT_CLOCK_DIV; |
|
|
def_disk0_size = C3745_DEFAULT_DISK0_SIZE; |
|
|
def_disk1_size = C3745_DEFAULT_DISK1_SIZE; |
|
|
def_nm_iomem_size = C3745_DEFAULT_IOMEM_SIZE; |
|
|
break; |
|
|
case VM_TYPE_C2600: |
|
|
def_ram_size = C2600_DEFAULT_RAM_SIZE; |
|
|
def_rom_size = C2600_DEFAULT_ROM_SIZE; |
|
|
def_nvram_size = C2600_DEFAULT_NVRAM_SIZE; |
|
|
def_conf_reg = C2600_DEFAULT_CONF_REG; |
|
|
def_clock_div = C2600_DEFAULT_CLOCK_DIV; |
|
|
def_disk0_size = C2600_DEFAULT_DISK0_SIZE; |
|
|
def_disk1_size = C2600_DEFAULT_DISK1_SIZE; |
|
|
def_nm_iomem_size = C2600_DEFAULT_IOMEM_SIZE; |
|
|
break; |
|
|
case VM_TYPE_MSFC1: |
|
|
def_ram_size = MSFC1_DEFAULT_RAM_SIZE; |
|
|
def_rom_size = MSFC1_DEFAULT_ROM_SIZE; |
|
|
def_nvram_size = MSFC1_DEFAULT_NVRAM_SIZE; |
|
|
def_conf_reg = MSFC1_DEFAULT_CONF_REG; |
|
|
def_clock_div = MSFC1_DEFAULT_CLOCK_DIV; |
|
|
break; |
|
|
case VM_TYPE_PPC32_TEST: |
|
|
def_ram_size = PPC32_VMTEST_DEFAULT_RAM_SIZE; |
|
|
default: |
|
|
fprintf(stderr,"show_usage: invalid platform.\n"); |
|
|
return; |
|
|
} |
|
|
|
|
166 |
printf("Usage: %s [options] <ios_image>\n\n",argv[0]); |
printf("Usage: %s [options] <ios_image>\n\n",argv[0]); |
167 |
|
|
168 |
printf("Available options:\n" |
printf("Available options:\n" |
169 |
" -H <tcp_port> : Run in hypervisor mode\n\n" |
" -H [<ip_address>:]<tcp_port> : Run in hypervisor mode\n\n" |
170 |
" -P <platform> : Platform to emulate (7200, 3600, " |
" -P <platform> : Platform to emulate (7200, 3600, " |
171 |
"2691, 3725 or 3745) " |
"2691, 3725, 3745, 2600 or 1700) " |
172 |
"(default: 7200)\n\n" |
"(default: 7200)\n\n" |
173 |
" -l <log_file> : Set logging file (default is %s)\n" |
" -l <log_file> : Set logging file (default is %s)\n" |
174 |
" -j : Disable the JIT compiler, very slow\n" |
" -j : Disable the JIT compiler, very slow\n" |
207 |
"(default: %u Mb)\n" |
"(default: %u Mb)\n" |
208 |
"\n", |
"\n", |
209 |
LOGFILE_DEFAULT_NAME,MIPS_EXEC_AREA_SIZE,VM_TIMER_IRQ_CHECK_ITV, |
LOGFILE_DEFAULT_NAME,MIPS_EXEC_AREA_SIZE,VM_TIMER_IRQ_CHECK_ITV, |
210 |
def_ram_size,def_rom_size,def_nvram_size,def_conf_reg, |
vm->ram_size,vm->rom_size,vm->nvram_size,vm->conf_reg_setup, |
211 |
def_clock_div,def_disk0_size,def_disk1_size); |
vm->clock_divisor,vm->pcmcia_disk_size[0],vm->pcmcia_disk_size[1]); |
212 |
|
|
213 |
switch(platform) { |
if (vm->platform->cli_show_options != NULL) |
214 |
case VM_TYPE_C7200: |
vm->platform->cli_show_options(vm); |
|
printf(" -t <npe_type> : Select NPE type (default: \"%s\")\n" |
|
|
" -M <midplane> : Select Midplane (\"std\" or \"vxr\")\n" |
|
|
" -p <pa_desc> : Define a Port Adapter\n" |
|
|
" -s <pa_nio> : Bind a Network IO interface to a " |
|
|
"Port Adapter\n", |
|
|
C7200_DEFAULT_NPE_TYPE); |
|
|
break; |
|
|
|
|
|
case VM_TYPE_C3600: |
|
|
printf(" -t <chassis_type> : Select Chassis type " |
|
|
"(default: \"%s\")\n" |
|
|
" --iomem-size <val> : IO memory (in percents, default: %u)\n" |
|
|
" -p <nm_desc> : Define a Network Module\n" |
|
|
" -s <nm_nio> : Bind a Network IO interface to a " |
|
|
"Network Module\n", |
|
|
C3600_DEFAULT_CHASSIS,def_nm_iomem_size); |
|
|
break; |
|
|
|
|
|
case VM_TYPE_C2691: |
|
|
printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n" |
|
|
" -p <nm_desc> : Define a Network Module\n" |
|
|
" -s <nm_nio> : Bind a Network IO interface to a " |
|
|
"Network Module\n", |
|
|
def_nm_iomem_size); |
|
|
break; |
|
|
|
|
|
case VM_TYPE_C3725: |
|
|
printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n" |
|
|
" -p <nm_desc> : Define a Network Module\n" |
|
|
" -s <nm_nio> : Bind a Network IO interface to a " |
|
|
"Network Module\n", |
|
|
def_nm_iomem_size); |
|
|
break; |
|
|
|
|
|
case VM_TYPE_C3745: |
|
|
printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n" |
|
|
" -p <nm_desc> : Define a Network Module\n" |
|
|
" -s <nm_nio> : Bind a Network IO interface to a " |
|
|
"Network Module\n", |
|
|
def_nm_iomem_size); |
|
|
break; |
|
|
|
|
|
case VM_TYPE_C2600: |
|
|
printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n" |
|
|
" -p <nm_desc> : Define a Network Module\n" |
|
|
" -s <nm_nio> : Bind a Network IO interface to a " |
|
|
"Network Module\n", |
|
|
def_nm_iomem_size); |
|
|
break; |
|
|
|
|
|
case VM_TYPE_MSFC1: |
|
|
printf(" -s <pa_nio> : Bind a Network IO interface to a " |
|
|
"Port Adapter\n"); |
|
|
break; |
|
|
|
|
|
} |
|
215 |
|
|
216 |
printf("\n" |
printf("\n" |
217 |
#if DEBUG_SYM_TREE |
#if DEBUG_SYM_TREE |
230 |
" \"device{:baudrate{:databits{:parity{:stopbits{:hwflow}}}}}}\"\n" |
" \"device{:baudrate{:databits{:parity{:stopbits{:hwflow}}}}}}\"\n" |
231 |
"\n"); |
"\n"); |
232 |
|
|
233 |
switch(platform) { |
switch(vm->slots_type) { |
234 |
case VM_TYPE_C7200: |
case CISCO_CARD_TYPE_PA: |
235 |
printf("<pa_desc> format:\n" |
printf("<pa_desc> format:\n" |
236 |
" \"slot:pa_driver\"\n" |
" \"slot:sub_slot:pa_driver\"\n" |
237 |
"\n"); |
"\n"); |
238 |
|
|
239 |
printf("<pa_nio> format:\n" |
printf("<pa_nio> format:\n" |
240 |
" \"slot:port:netio_type{:netio_parameters}\"\n" |
" \"slot:port:netio_type{:netio_parameters}\"\n" |
241 |
"\n"); |
"\n"); |
|
|
|
|
/* Show the possible NPE drivers */ |
|
|
c7200_npe_show_drivers(); |
|
|
|
|
|
/* Show the possible PA drivers */ |
|
|
c7200_pa_show_drivers(); |
|
|
break; |
|
|
|
|
|
case VM_TYPE_C3600: |
|
|
printf("<nm_desc> format:\n" |
|
|
" \"slot:nm_driver\"\n" |
|
|
"\n"); |
|
|
|
|
|
printf("<nm_nio> format:\n" |
|
|
" \"slot:port:netio_type{:netio_parameters}\"\n" |
|
|
"\n"); |
|
|
|
|
|
/* Show the possible chassis types for C3600 platform */ |
|
|
c3600_chassis_show_drivers(); |
|
|
|
|
|
/* Show the possible NM drivers */ |
|
|
c3600_nm_show_drivers(); |
|
242 |
break; |
break; |
243 |
|
|
244 |
case VM_TYPE_C2691: |
case CISCO_CARD_TYPE_NM: |
245 |
printf("<nm_desc> format:\n" |
printf("<nm_desc> format:\n" |
246 |
" \"slot:nm_driver\"\n" |
" \"slot:sub_slot:nm_driver\"\n" |
247 |
"\n"); |
"\n"); |
248 |
|
|
249 |
printf("<nm_nio> format:\n" |
printf("<nm_nio> format:\n" |
250 |
" \"slot:port:netio_type{:netio_parameters}\"\n" |
" \"slot:port:netio_type{:netio_parameters}\"\n" |
251 |
"\n"); |
"\n"); |
|
|
|
|
/* Show the possible NM drivers */ |
|
|
c2691_nm_show_drivers(); |
|
252 |
break; |
break; |
253 |
|
|
254 |
case VM_TYPE_C3725: |
case CISCO_CARD_TYPE_WIC: |
255 |
printf("<nm_desc> format:\n" |
printf("<wic_desc> format:\n" |
256 |
" \"slot:nm_driver\"\n" |
" \"slot:wic_driver\"\n" |
257 |
"\n"); |
"\n"); |
258 |
|
|
259 |
printf("<nm_nio> format:\n" |
printf("<wic_nio> format:\n" |
260 |
" \"slot:port:netio_type{:netio_parameters}\"\n" |
" \"slot:port:netio_type{:netio_parameters}\"\n" |
261 |
"\n"); |
"\n"); |
|
|
|
|
/* Show the possible NM drivers */ |
|
|
c3725_nm_show_drivers(); |
|
262 |
break; |
break; |
263 |
|
} |
264 |
|
|
265 |
case VM_TYPE_C3745: |
if (vm->platform->show_spec_drivers != NULL) |
266 |
printf("<nm_desc> format:\n" |
vm->platform->show_spec_drivers(); |
|
" \"slot:nm_driver\"\n" |
|
|
"\n"); |
|
|
|
|
|
printf("<nm_nio> format:\n" |
|
|
" \"slot:port:netio_type{:netio_parameters}\"\n" |
|
|
"\n"); |
|
|
|
|
|
/* Show the possible NM drivers */ |
|
|
c3745_nm_show_drivers(); |
|
|
break; |
|
|
|
|
|
case VM_TYPE_C2600: |
|
|
printf("<nm_desc> format:\n" |
|
|
" \"slot:nm_driver\"\n" |
|
|
"\n"); |
|
|
|
|
|
printf("<nm_nio> format:\n" |
|
|
" \"slot:port:netio_type{:netio_parameters}\"\n" |
|
|
"\n"); |
|
|
|
|
|
/* Show the possible chassis types for C2600 platform */ |
|
|
c2600_mainboard_show_drivers(); |
|
267 |
|
|
268 |
/* Show the possible NM drivers */ |
/* Show possible slot drivers */ |
269 |
c2600_nm_show_drivers(); |
vm_slot_show_drivers(vm); |
|
break; |
|
|
} |
|
270 |
|
|
271 |
/* Show the possible NETIO types */ |
/* Show the possible NETIO types */ |
272 |
netio_show_types(); |
netio_show_types(); |
296 |
return NULL; |
return NULL; |
297 |
} |
} |
298 |
|
|
299 |
|
/* Load plugins */ |
300 |
|
static void cli_load_plugins(int argc,char *argv[]) |
301 |
|
{ |
302 |
|
char *str; |
303 |
|
int i; |
304 |
|
|
305 |
|
for(i=1;i<argc;i++) { |
306 |
|
if (!strncmp(argv[i],"-L",2)) { |
307 |
|
if (argv[i][2] != 0) |
308 |
|
str = &argv[i][2]; |
309 |
|
else { |
310 |
|
if (argv[i+1] != NULL) |
311 |
|
str = argv[i+1]; |
312 |
|
else { |
313 |
|
fprintf(stderr,"Plugin error: no argument specified.\n"); |
314 |
|
exit(EXIT_FAILURE); |
315 |
|
} |
316 |
|
} |
317 |
|
|
318 |
|
if (!plugin_load(str)) |
319 |
|
fprintf(stderr,"Unable to load plugin '%s'!\n",str); |
320 |
|
} |
321 |
|
} |
322 |
|
} |
323 |
|
|
324 |
/* Determine the platform (Cisco 3600, 7200). Default is Cisco 7200 */ |
/* Determine the platform (Cisco 3600, 7200). Default is Cisco 7200 */ |
325 |
static int cli_get_platform_type(int argc,char *argv[]) |
static vm_platform_t *cli_get_platform_type(int argc,char *argv[]) |
326 |
{ |
{ |
327 |
int vm_type = VM_TYPE_C7200; |
vm_platform_t *platform; |
328 |
char *str; |
char *str; |
329 |
|
|
330 |
if ((str = cli_find_option(argc,argv,"-P"))) { |
if (!(str = cli_find_option(argc,argv,"-P"))) |
331 |
if (!strcmp(str,"3600")) |
str = default_platform; |
332 |
vm_type = VM_TYPE_C3600; |
|
333 |
else if (!strcmp(str,"7200")) |
if (!(platform = vm_platform_find_cli_name(str))) |
|
vm_type = VM_TYPE_C7200; |
|
|
else if (!strcmp(str,"2691")) |
|
|
vm_type = VM_TYPE_C2691; |
|
|
else if (!strcmp(str,"3725")) |
|
|
vm_type = VM_TYPE_C3725; |
|
|
else if (!strcmp(str,"3745")) |
|
|
vm_type = VM_TYPE_C3745; |
|
|
else if (!strcmp(str,"2600")) |
|
|
vm_type = VM_TYPE_C2600; |
|
|
else if (!strcmp(str,"MSFC1")) |
|
|
vm_type = VM_TYPE_MSFC1; |
|
|
else if (!strcmp(str,"PPC32_TEST")) |
|
|
vm_type = VM_TYPE_PPC32_TEST; |
|
|
else |
|
334 |
fprintf(stderr,"Invalid platform type '%s'\n",str); |
fprintf(stderr,"Invalid platform type '%s'\n",str); |
|
} |
|
335 |
|
|
336 |
return(vm_type); |
return platform; |
337 |
} |
} |
338 |
|
|
|
/* Command Line long options */ |
|
|
#define OPT_DISK0_SIZE 0x100 |
|
|
#define OPT_DISK1_SIZE 0x101 |
|
|
#define OPT_EXEC_AREA 0x102 |
|
|
#define OPT_IDLE_PC 0x103 |
|
|
#define OPT_TIMER_ITV 0x104 |
|
|
#define OPT_VM_DEBUG 0x105 |
|
|
#define OPT_IOMEM_SIZE 0x106 |
|
|
#define OPT_SPARSE_MEM 0x107 |
|
|
|
|
339 |
static struct option cmd_line_lopts[] = { |
static struct option cmd_line_lopts[] = { |
340 |
{ "disk0" , 1, NULL, OPT_DISK0_SIZE }, |
{ "disk0" , 1, NULL, OPT_DISK0_SIZE }, |
341 |
{ "disk1" , 1, NULL, OPT_DISK1_SIZE }, |
{ "disk1" , 1, NULL, OPT_DISK1_SIZE }, |
348 |
{ NULL , 0, NULL, 0 }, |
{ NULL , 0, NULL, 0 }, |
349 |
}; |
}; |
350 |
|
|
|
/* Parse specific options for the Cisco 7200 platform */ |
|
|
static int cli_parse_c7200_options(vm_instance_t *vm,int option) |
|
|
{ |
|
|
c7200_t *router; |
|
|
|
|
|
router = VM_C7200(vm); |
|
|
|
|
|
switch(option) { |
|
|
/* NPE type */ |
|
|
case 't': |
|
|
c7200_npe_set_type(router,optarg); |
|
|
break; |
|
|
|
|
|
/* Midplane type */ |
|
|
case 'M': |
|
|
c7200_midplane_set_type(router,optarg); |
|
|
break; |
|
|
|
|
|
/* Set the base MAC address */ |
|
|
case 'm': |
|
|
if (!c7200_midplane_set_mac_addr(router,optarg)) |
|
|
printf("MAC address set to '%s'.\n",optarg); |
|
|
break; |
|
|
|
|
|
/* PA settings */ |
|
|
case 'p': |
|
|
return(c7200_cmd_pa_create(router,optarg)); |
|
|
|
|
|
/* PA NIO settings */ |
|
|
case 's': |
|
|
return(c7200_cmd_add_nio(router,optarg)); |
|
|
|
|
|
/* Unknown option */ |
|
|
default: |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Parse specific options for the Cisco 3600 platform */ |
|
|
static int cli_parse_c3600_options(vm_instance_t *vm,int option) |
|
|
{ |
|
|
c3600_t *router; |
|
|
|
|
|
router = VM_C3600(vm); |
|
|
|
|
|
switch(option) { |
|
|
/* chassis type */ |
|
|
case 't': |
|
|
c3600_chassis_set_type(router,optarg); |
|
|
break; |
|
|
|
|
|
/* IO memory reserved for NMs (in percents!) */ |
|
|
case OPT_IOMEM_SIZE: |
|
|
router->nm_iomem_size = 0x8000 | atoi(optarg); |
|
|
break; |
|
|
|
|
|
/* NM settings */ |
|
|
case 'p': |
|
|
return(c3600_cmd_nm_create(router,optarg)); |
|
|
|
|
|
/* NM NIO settings */ |
|
|
case 's': |
|
|
return(c3600_cmd_add_nio(router,optarg)); |
|
|
|
|
|
/* Unknown option */ |
|
|
default: |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Parse specific options for the Cisco 2691 platform */ |
|
|
static int cli_parse_c2691_options(vm_instance_t *vm,int option) |
|
|
{ |
|
|
c2691_t *router; |
|
|
|
|
|
router = VM_C2691(vm); |
|
|
|
|
|
switch(option) { |
|
|
/* IO memory reserved for NMs (in percents!) */ |
|
|
case OPT_IOMEM_SIZE: |
|
|
router->nm_iomem_size = 0x8000 | atoi(optarg); |
|
|
break; |
|
|
|
|
|
/* NM settings */ |
|
|
case 'p': |
|
|
return(c2691_cmd_nm_create(router,optarg)); |
|
|
|
|
|
/* NM NIO settings */ |
|
|
case 's': |
|
|
return(c2691_cmd_add_nio(router,optarg)); |
|
|
|
|
|
/* Unknown option */ |
|
|
default: |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Parse specific options for the Cisco 3725 platform */ |
|
|
static int cli_parse_c3725_options(vm_instance_t *vm,int option) |
|
|
{ |
|
|
c3725_t *router; |
|
|
|
|
|
router = VM_C3725(vm); |
|
|
|
|
|
switch(option) { |
|
|
/* IO memory reserved for NMs (in percents!) */ |
|
|
case OPT_IOMEM_SIZE: |
|
|
router->nm_iomem_size = 0x8000 | atoi(optarg); |
|
|
break; |
|
|
|
|
|
/* NM settings */ |
|
|
case 'p': |
|
|
return(c3725_cmd_nm_create(router,optarg)); |
|
|
|
|
|
/* NM NIO settings */ |
|
|
case 's': |
|
|
return(c3725_cmd_add_nio(router,optarg)); |
|
|
|
|
|
/* Unknown option */ |
|
|
default: |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Parse specific options for the Cisco 3745 platform */ |
|
|
static int cli_parse_c3745_options(vm_instance_t *vm,int option) |
|
|
{ |
|
|
c3745_t *router; |
|
|
|
|
|
router = VM_C3745(vm); |
|
|
|
|
|
switch(option) { |
|
|
/* IO memory reserved for NMs (in percents!) */ |
|
|
case OPT_IOMEM_SIZE: |
|
|
router->nm_iomem_size = 0x8000 | atoi(optarg); |
|
|
break; |
|
|
|
|
|
/* NM settings */ |
|
|
case 'p': |
|
|
return(c3745_cmd_nm_create(router,optarg)); |
|
|
|
|
|
/* NM NIO settings */ |
|
|
case 's': |
|
|
return(c3745_cmd_add_nio(router,optarg)); |
|
|
|
|
|
/* Unknown option */ |
|
|
default: |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Parse specific options for the Cisco 2600 platform */ |
|
|
static int cli_parse_c2600_options(vm_instance_t *vm,int option) |
|
|
{ |
|
|
c2600_t *router; |
|
|
|
|
|
router = VM_C2600(vm); |
|
|
|
|
|
switch(option) { |
|
|
/* IO memory reserved for NMs (in percents!) */ |
|
|
case OPT_IOMEM_SIZE: |
|
|
router->nm_iomem_size = 0x8000 | atoi(optarg); |
|
|
break; |
|
|
|
|
|
/* Mainboard type */ |
|
|
case 't': |
|
|
c2600_mainboard_set_type(router,optarg); |
|
|
break; |
|
|
|
|
|
/* NM settings */ |
|
|
case 'p': |
|
|
return(c2600_cmd_nm_create(router,optarg)); |
|
|
|
|
|
/* NM NIO settings */ |
|
|
case 's': |
|
|
return(c2600_cmd_add_nio(router,optarg)); |
|
|
|
|
|
/* Unknown option */ |
|
|
default: |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Parse specific options for the MSFC1 platform */ |
|
|
static int cli_parse_msfc1_options(vm_instance_t *vm,int option) |
|
|
{ |
|
|
msfc1_t *router; |
|
|
|
|
|
router = VM_MSFC1(vm); |
|
|
|
|
|
switch(option) { |
|
|
/* PA NIO settings */ |
|
|
case 's': |
|
|
return(msfc1_cmd_add_nio(router,optarg)); |
|
|
|
|
|
/* Unknown option */ |
|
|
default: |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
351 |
/* Create a router instance */ |
/* Create a router instance */ |
352 |
static vm_instance_t *cli_create_instance(char *name,int platform_type, |
static vm_instance_t *cli_create_instance(char *name,char *platform_name, |
353 |
int instance_id) |
int instance_id) |
354 |
{ |
{ |
355 |
vm_instance_t *vm; |
vm_instance_t *vm; |
|
c7200_t *c7200; |
|
|
c3600_t *c3600; |
|
|
c2691_t *c2691; |
|
|
c3725_t *c3725; |
|
|
c3745_t *c3745; |
|
|
c2600_t *c2600; |
|
|
msfc1_t *msfc1; |
|
|
|
|
|
switch(platform_type) { |
|
|
case VM_TYPE_C7200: |
|
|
if (!(c7200 = c7200_create_instance(name,instance_id))) { |
|
|
fprintf(stderr,"C7200: unable to create instance!\n"); |
|
|
return NULL; |
|
|
} |
|
|
return(c7200->vm); |
|
356 |
|
|
357 |
case VM_TYPE_C3600: |
vm = vm_create_instance(name,instance_id,platform_name); |
358 |
if (!(c3600 = c3600_create_instance(name,instance_id))) { |
|
359 |
fprintf(stderr,"C3600: unable to create instance!\n"); |
if (vm == NULL) { |
360 |
return NULL; |
fprintf(stderr,"C7200: unable to create instance!\n"); |
361 |
} |
return NULL; |
|
return(c3600->vm); |
|
|
|
|
|
case VM_TYPE_C2691: |
|
|
if (!(c2691 = c2691_create_instance(name,instance_id))) { |
|
|
fprintf(stderr,"C2691: unable to create instance!\n"); |
|
|
return NULL; |
|
|
} |
|
|
return(c2691->vm); |
|
|
|
|
|
case VM_TYPE_C3725: |
|
|
if (!(c3725 = c3725_create_instance(name,instance_id))) { |
|
|
fprintf(stderr,"C3725: unable to create instance!\n"); |
|
|
return NULL; |
|
|
} |
|
|
return(c3725->vm); |
|
|
|
|
|
case VM_TYPE_C3745: |
|
|
if (!(c3745 = c3745_create_instance(name,instance_id))) { |
|
|
fprintf(stderr,"C3745: unable to create instance!\n"); |
|
|
return NULL; |
|
|
} |
|
|
return(c3745->vm); |
|
|
|
|
|
case VM_TYPE_C2600: |
|
|
if (!(c2600 = c2600_create_instance(name,instance_id))) { |
|
|
fprintf(stderr,"C2600: unable to create instance!\n"); |
|
|
return NULL; |
|
|
} |
|
|
return(c2600->vm); |
|
|
|
|
|
case VM_TYPE_MSFC1: |
|
|
if (!(msfc1 = msfc1_create_instance(name,instance_id))) { |
|
|
fprintf(stderr,"MSFC1: unable to create instance!\n"); |
|
|
return NULL; |
|
|
} |
|
|
return(msfc1->vm); |
|
|
|
|
|
case VM_TYPE_PPC32_TEST: |
|
|
if (!(vm = ppc32_vmtest_create_instance(name,instance_id))) { |
|
|
fprintf(stderr,"PPC32_TEST: unable to create instance!\n"); |
|
|
return NULL; |
|
|
} |
|
|
return(vm); |
|
|
|
|
|
default: |
|
|
fprintf(stderr,"Unknown platform type '%d'!\n",platform_type); |
|
|
return NULL; |
|
362 |
} |
} |
363 |
|
|
364 |
|
return vm; |
365 |
} |
} |
366 |
|
|
367 |
/* Parse the command line */ |
/* Parse the command line */ |
368 |
static int parse_std_cmd_line(int argc,char *argv[],int *platform) |
static int parse_std_cmd_line(int argc,char *argv[]) |
369 |
{ |
{ |
370 |
char *options_list = |
char *options_list = |
371 |
"r:o:n:c:m:l:C:i:jt:p:s:k:T:U:A:B:a:f:E:b:S:R:M:eXP:N:G:g:"; |
"r:o:n:c:m:l:C:i:jt:p:s:k:T:U:A:B:a:f:E:b:S:R:M:eXP:N:G:g:L:"; |
372 |
|
vm_platform_t *platform; |
373 |
vm_instance_t *vm; |
vm_instance_t *vm; |
374 |
int instance_id; |
int instance_id; |
375 |
int res,option; |
int option; |
376 |
char *str; |
char *str; |
377 |
|
|
378 |
/* Get the instance ID */ |
/* Get the instance ID */ |
381 |
/* Use the old VM file naming type */ |
/* Use the old VM file naming type */ |
382 |
vm_file_naming_type = 1; |
vm_file_naming_type = 1; |
383 |
|
|
384 |
|
cli_load_plugins(argc,argv); |
385 |
|
|
386 |
if ((str = cli_find_option(argc,argv,"-i"))) { |
if ((str = cli_find_option(argc,argv,"-i"))) { |
387 |
instance_id = atoi(str); |
instance_id = atoi(str); |
388 |
printf("Instance ID set to %d.\n",instance_id); |
printf("Instance ID set to %d.\n",instance_id); |
392 |
vm_file_naming_type = atoi(str); |
vm_file_naming_type = atoi(str); |
393 |
|
|
394 |
/* Get the platform type */ |
/* Get the platform type */ |
395 |
*platform = cli_get_platform_type(argc,argv); |
if (!(platform = cli_get_platform_type(argc,argv))) |
396 |
|
exit(EXIT_FAILURE); |
397 |
|
|
398 |
/* Create the default instance */ |
/* Create the default instance */ |
399 |
if (!(vm = cli_create_instance("default",*platform,instance_id))) |
if (!(vm = cli_create_instance("default",platform->name,instance_id))) |
400 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
401 |
|
|
402 |
opterr = 0; |
opterr = 0; |
569 |
} |
} |
570 |
break; |
break; |
571 |
|
|
572 |
|
/* Port settings */ |
573 |
|
case 'p': |
574 |
|
vm_slot_cmd_create(vm,optarg); |
575 |
|
break; |
576 |
|
|
577 |
|
/* NIO settings */ |
578 |
|
case 's': |
579 |
|
vm_slot_cmd_add_nio(vm,optarg); |
580 |
|
break; |
581 |
|
|
582 |
/* Virtual ATM switch */ |
/* Virtual ATM switch */ |
583 |
case 'a': |
case 'a': |
584 |
if (atmsw_start(optarg) == -1) |
if (atmsw_start(optarg) == -1) |
610 |
exit(EXIT_SUCCESS); |
exit(EXIT_SUCCESS); |
611 |
#endif |
#endif |
612 |
|
|
613 |
|
/* Load plugin (already handled) */ |
614 |
|
case 'L': |
615 |
|
break; |
616 |
|
|
617 |
/* Oops ! */ |
/* Oops ! */ |
618 |
case '?': |
case '?': |
619 |
show_usage(argc,argv,*platform); |
show_usage(vm,argc,argv); |
620 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
621 |
|
|
622 |
/* Parse options specific to the platform */ |
/* Parse options specific to the platform */ |
623 |
default: |
default: |
624 |
res = 0; |
if (vm->platform->cli_parse_options != NULL) |
625 |
|
if (vm->platform->cli_parse_options(vm,option) == -1) |
626 |
switch(vm->type) { |
exit(EXIT_FAILURE); |
|
case VM_TYPE_C7200: |
|
|
res = cli_parse_c7200_options(vm,option); |
|
|
break; |
|
|
case VM_TYPE_C3600: |
|
|
res = cli_parse_c3600_options(vm,option); |
|
|
break; |
|
|
case VM_TYPE_C2691: |
|
|
res = cli_parse_c2691_options(vm,option); |
|
|
break; |
|
|
case VM_TYPE_C3725: |
|
|
res = cli_parse_c3725_options(vm,option); |
|
|
break; |
|
|
case VM_TYPE_C3745: |
|
|
res = cli_parse_c3745_options(vm,option); |
|
|
break; |
|
|
case VM_TYPE_C2600: |
|
|
res = cli_parse_c2600_options(vm,option); |
|
|
break; |
|
|
case VM_TYPE_MSFC1: |
|
|
res = cli_parse_msfc1_options(vm,option); |
|
|
break; |
|
|
} |
|
|
|
|
|
if (res == -1) |
|
|
exit(EXIT_FAILURE); |
|
627 |
} |
} |
628 |
} |
} |
629 |
|
|
635 |
} else { |
} else { |
636 |
/* IOS missing */ |
/* IOS missing */ |
637 |
fprintf(stderr,"Please specify an IOS image filename\n"); |
fprintf(stderr,"Please specify an IOS image filename\n"); |
638 |
show_usage(argc,argv,*platform); |
show_usage(vm,argc,argv); |
639 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
640 |
} |
} |
641 |
|
|
649 |
*/ |
*/ |
650 |
static int run_hypervisor(int argc,char *argv[]) |
static int run_hypervisor(int argc,char *argv[]) |
651 |
{ |
{ |
652 |
char *options_list = "H:l:hN:"; |
char *options_list = "H:l:hN:L:"; |
653 |
int i,option; |
int i,option; |
654 |
|
char *index; |
655 |
|
size_t len; |
656 |
|
|
657 |
for(i=1;i<argc;i++) |
for(i=1;i<argc;i++) |
658 |
if (!strcmp(argv[i],"-H")) { |
if (!strcmp(argv[i],"-H")) { |
664 |
if (!hypervisor_mode) |
if (!hypervisor_mode) |
665 |
return(FALSE); |
return(FALSE); |
666 |
|
|
667 |
|
cli_load_plugins(argc,argv); |
668 |
|
|
669 |
opterr = 0; |
opterr = 0; |
670 |
while((option = getopt(argc,argv,options_list)) != -1) { |
while((option = getopt(argc,argv,options_list)) != -1) { |
671 |
switch(option) |
switch(option) |
672 |
{ |
{ |
673 |
/* Hypervisor TCP port */ |
/* Hypervisor TCP port */ |
674 |
case 'H': |
case 'H': |
675 |
hypervisor_tcp_port = atoi(optarg); |
index = strrchr(optarg,':'); |
676 |
|
|
677 |
|
if (!index) { |
678 |
|
hypervisor_tcp_port = atoi(optarg); |
679 |
|
} else { |
680 |
|
len = index - optarg; |
681 |
|
hypervisor_ip_address = malloc(len + 1); |
682 |
|
|
683 |
|
if (!hypervisor_ip_address) { |
684 |
|
fprintf(stderr,"Unable to set hypervisor IP address!\n"); |
685 |
|
exit(EXIT_FAILURE); |
686 |
|
} |
687 |
|
|
688 |
|
memcpy(hypervisor_ip_address,optarg,len); |
689 |
|
hypervisor_ip_address[len] = '\0'; |
690 |
|
} |
691 |
break; |
break; |
692 |
|
|
693 |
/* Log file */ |
/* Log file */ |
694 |
case 'l': |
case 'l': |
695 |
if (!(log_file_name = malloc(strlen(optarg)+1))) { |
if (!(log_file_name = malloc(strlen(optarg)+1))) { |
696 |
fprintf(stderr,"Unable to set log file name.\n"); |
fprintf(stderr,"Unable to set log file name!\n"); |
697 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
698 |
} |
} |
699 |
strcpy(log_file_name, optarg); |
strcpy(log_file_name, optarg); |
704 |
case 'N': |
case 'N': |
705 |
vm_file_naming_type = atoi(optarg); |
vm_file_naming_type = atoi(optarg); |
706 |
break; |
break; |
707 |
|
|
708 |
|
/* Load plugin (already handled) */ |
709 |
|
case 'L': |
710 |
|
break; |
711 |
|
|
712 |
/* Oops ! */ |
/* Oops ! */ |
713 |
case '?': |
case '?': |
714 |
show_usage(argc,argv,VM_TYPE_C7200); |
//show_usage(argc,argv,VM_TYPE_C7200); |
715 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
716 |
} |
} |
717 |
} |
} |
725 |
printf("Shutdown in progress...\n"); |
printf("Shutdown in progress...\n"); |
726 |
|
|
727 |
/* Delete all virtual router instances */ |
/* Delete all virtual router instances */ |
728 |
c7200_delete_all_instances(); |
vm_delete_all_instances(); |
|
c3600_delete_all_instances(); |
|
|
c2691_delete_all_instances(); |
|
|
c3725_delete_all_instances(); |
|
|
c3745_delete_all_instances(); |
|
|
c2600_delete_all_instances(); |
|
|
msfc1_delete_all_instances(); |
|
|
ppc32_vmtest_delete_all_instances(); |
|
729 |
|
|
730 |
/* Delete ATM and Frame-Relay switches + bridges */ |
/* Delete ATM and Frame-Relay switches + bridges */ |
731 |
netio_bridge_delete_all(); |
netio_bridge_delete_all(); |
739 |
printf("Shutdown completed.\n"); |
printf("Shutdown completed.\n"); |
740 |
} |
} |
741 |
|
|
742 |
|
/* Default platforms */ |
743 |
|
static int (*platform_register[])(void) = { |
744 |
|
c7200_platform_register, |
745 |
|
c3600_platform_register, |
746 |
|
c3725_platform_register, |
747 |
|
c3745_platform_register, |
748 |
|
c2691_platform_register, |
749 |
|
c2600_platform_register, |
750 |
|
c1700_platform_register, |
751 |
|
c6sup1_platform_register, |
752 |
|
c6msfc1_platform_register, |
753 |
|
NULL, |
754 |
|
}; |
755 |
|
|
756 |
|
/* Register default platforms */ |
757 |
|
static void register_default_platforms(void) |
758 |
|
{ |
759 |
|
int i; |
760 |
|
|
761 |
|
for(i=0;platform_register[i];i++) |
762 |
|
platform_register[i](); |
763 |
|
} |
764 |
|
|
765 |
int main(int argc,char *argv[]) |
int main(int argc,char *argv[]) |
766 |
{ |
{ |
767 |
vm_instance_t *vm; |
vm_instance_t *vm; |
|
int platform,res; |
|
|
|
|
|
/* Default emulation: Cisco 7200 */ |
|
|
platform = VM_TYPE_C7200; |
|
768 |
|
|
769 |
#ifdef PROFILE |
#ifdef PROFILE |
770 |
atexit(profiler_savestat); |
atexit(profiler_savestat); |
774 |
printf("Copyright (c) 2005-2007 Christophe Fillot.\n"); |
printf("Copyright (c) 2005-2007 Christophe Fillot.\n"); |
775 |
printf("Build date: %s %s\n\n",__DATE__,__TIME__); |
printf("Build date: %s %s\n\n",__DATE__,__TIME__); |
776 |
|
|
777 |
|
/* Register platforms */ |
778 |
|
register_default_platforms(); |
779 |
|
|
780 |
/* Initialize timers */ |
/* Initialize timers */ |
781 |
timer_init(); |
timer_init(); |
782 |
|
|
800 |
|
|
801 |
/* Parse standard command line */ |
/* Parse standard command line */ |
802 |
if (!run_hypervisor(argc,argv)) |
if (!run_hypervisor(argc,argv)) |
803 |
parse_std_cmd_line(argc,argv,&platform); |
parse_std_cmd_line(argc,argv); |
804 |
|
|
805 |
/* Create general log file */ |
/* Create general log file */ |
806 |
create_log_file(); |
create_log_file(); |
814 |
mips64_exec_create_ilt(); |
mips64_exec_create_ilt(); |
815 |
ppc32_jit_create_ilt(); |
ppc32_jit_create_ilt(); |
816 |
ppc32_exec_create_ilt(); |
ppc32_exec_create_ilt(); |
817 |
|
|
818 |
setup_signals(); |
setup_signals(); |
819 |
|
|
820 |
if (!hypervisor_mode) { |
if (!hypervisor_mode) { |
822 |
vm = vm_acquire("default"); |
vm = vm_acquire("default"); |
823 |
assert(vm != NULL); |
assert(vm != NULL); |
824 |
|
|
825 |
switch(platform) { |
if (vm->platform->init_instance(vm) == -1) { |
|
case VM_TYPE_C7200: |
|
|
res = c7200_init_instance(VM_C7200(vm)); |
|
|
break; |
|
|
case VM_TYPE_C3600: |
|
|
res = c3600_init_instance(VM_C3600(vm)); |
|
|
break; |
|
|
case VM_TYPE_C2691: |
|
|
res = c2691_init_instance(VM_C2691(vm)); |
|
|
break; |
|
|
case VM_TYPE_C3725: |
|
|
res = c3725_init_instance(VM_C3725(vm)); |
|
|
break; |
|
|
case VM_TYPE_C3745: |
|
|
res = c3745_init_instance(VM_C3745(vm)); |
|
|
break; |
|
|
case VM_TYPE_C2600: |
|
|
res = c2600_init_instance(VM_C2600(vm)); |
|
|
break; |
|
|
case VM_TYPE_MSFC1: |
|
|
res = msfc1_init_instance(VM_MSFC1(vm)); |
|
|
break; |
|
|
case VM_TYPE_PPC32_TEST: |
|
|
res = ppc32_vmtest_init_instance(vm); |
|
|
break; |
|
|
default: |
|
|
res = -1; |
|
|
} |
|
|
|
|
|
if (res == -1) { |
|
826 |
fprintf(stderr,"Unable to initialize router instance.\n"); |
fprintf(stderr,"Unable to initialize router instance.\n"); |
827 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
828 |
} |
} |
829 |
|
|
830 |
#if (DEBUG_INSN_PERF_CNT > 0) || (DEBUG_BLOCK_PERF_CNT > 0) |
#if (DEBUG_INSN_PERF_CNT > 0) || (DEBUG_BLOCK_PERF_CNT > 0) |
831 |
{ |
{ |
832 |
m_uint64_t counter,prev = 0,delta; |
m_uint32_t counter,prev = 0,delta; |
833 |
while(vm->status == VM_STATUS_RUNNING) { |
while(vm->status == VM_STATUS_RUNNING) { |
834 |
counter = cpu_get_perf_counter(vm->boot_cpu); |
counter = cpu_get_perf_counter(vm->boot_cpu); |
835 |
delta = counter - prev; |
delta = counter - prev; |
836 |
prev = counter; |
prev = counter; |
837 |
printf("delta = %llu\n",delta); |
printf("delta = %u\n",delta); |
838 |
sleep(1); |
sleep(1); |
839 |
} |
} |
840 |
} |
} |
846 |
/* Free resources used by instance */ |
/* Free resources used by instance */ |
847 |
vm_release(vm); |
vm_release(vm); |
848 |
} else { |
} else { |
849 |
hypervisor_tcp_server(hypervisor_tcp_port); |
hypervisor_tcp_server(hypervisor_ip_address,hypervisor_tcp_port); |
850 |
} |
} |
851 |
|
|
852 |
dynamips_reset(); |
dynamips_reset(); |