1 |
/* |
/* |
2 |
* Cisco 7200 (Predator) simulation platform. |
* Cisco router simulation platform. |
3 |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
4 |
* |
* |
5 |
* Virtual console TTY. |
* Virtual console TTY. |
27 |
|
|
28 |
#include <arpa/telnet.h> |
#include <arpa/telnet.h> |
29 |
|
|
30 |
#include "mips64.h" |
#include "utils.h" |
|
#include "cp0.h" |
|
31 |
#include "cpu.h" |
#include "cpu.h" |
32 |
|
#include "vm.h" |
33 |
#include "dynamips.h" |
#include "dynamips.h" |
34 |
#include "mips64_exec.h" |
#include "mips64_exec.h" |
35 |
|
#include "ppc32_exec.h" |
36 |
#include "device.h" |
#include "device.h" |
37 |
#include "memory.h" |
#include "memory.h" |
38 |
#include "dev_c7200.h" |
#include "dev_c7200.h" |
39 |
#include "dev_c3600.h" |
#include "dev_c3600.h" |
40 |
|
#include "dev_c2691.h" |
41 |
|
#include "dev_c3725.h" |
42 |
|
#include "dev_c3745.h" |
43 |
|
#include "dev_c2600.h" |
44 |
#include "dev_vtty.h" |
#include "dev_vtty.h" |
|
#include "vm.h" |
|
|
#include "utils.h" |
|
45 |
|
|
46 |
/* VTTY list */ |
/* VTTY list */ |
47 |
static pthread_mutex_t vtty_list_mutex = PTHREAD_MUTEX_INITIALIZER; |
static pthread_mutex_t vtty_list_mutex = PTHREAD_MUTEX_INITIALIZER; |
239 |
return(0); |
return(0); |
240 |
} |
} |
241 |
|
|
242 |
#if defined(__CYGWIN__) |
#if defined(__CYGWIN__) || defined(SUNOS) |
243 |
void cfmakeraw(struct termios *termios_p) { |
void cfmakeraw(struct termios *termios_p) { |
244 |
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP| |
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP| |
245 |
INLCR|IGNCR|ICRNL|IXON); |
INLCR|IGNCR|ICRNL|IXON); |
499 |
return(0); |
return(0); |
500 |
} |
} |
501 |
|
|
502 |
|
/* Store a string in the FIFO buffer */ |
503 |
|
int vtty_store_str(vtty_t *vtty,char *str) |
504 |
|
{ |
505 |
|
if (!vtty) |
506 |
|
return(0); |
507 |
|
|
508 |
|
while(*str != 0) { |
509 |
|
if (vtty_store(vtty,*str) == -1) |
510 |
|
return(-1); |
511 |
|
|
512 |
|
str++; |
513 |
|
} |
514 |
|
|
515 |
|
vtty->input_pending = TRUE; |
516 |
|
return(0); |
517 |
|
} |
518 |
|
|
519 |
/* Store CTRL+C in buffer */ |
/* Store CTRL+C in buffer */ |
520 |
int vtty_store_ctrlc(vtty_t *vtty) |
int vtty_store_ctrlc(vtty_t *vtty) |
521 |
{ |
{ |
592 |
return(-1); |
return(-1); |
593 |
} |
} |
594 |
|
|
595 |
|
/* Remote control for MIPS64 processors */ |
596 |
|
static int remote_control_mips64(vtty_t *vtty,char c,cpu_mips_t *cpu) |
597 |
|
{ |
598 |
|
switch(c) { |
599 |
|
/* Show information about JIT compiled pages */ |
600 |
|
case 'b': |
601 |
|
printf("\nCPU0: %u JIT compiled pages [Exec Area Pages: %lu/%lu]\n", |
602 |
|
cpu->compiled_pages, |
603 |
|
(u_long)cpu->exec_page_alloc, |
604 |
|
(u_long)cpu->exec_page_count); |
605 |
|
break; |
606 |
|
|
607 |
|
/* Non-JIT mode statistics */ |
608 |
|
case 'j': |
609 |
|
mips64_dump_stats(cpu); |
610 |
|
break; |
611 |
|
|
612 |
|
default: |
613 |
|
return(FALSE); |
614 |
|
} |
615 |
|
|
616 |
|
return(TRUE); |
617 |
|
} |
618 |
|
|
619 |
|
/* Remote control for PPC32 processors */ |
620 |
|
static int remote_control_ppc32(vtty_t *vtty,char c,cpu_ppc_t *cpu) |
621 |
|
{ |
622 |
|
switch(c) { |
623 |
|
/* Show information about JIT compiled pages */ |
624 |
|
case 'b': |
625 |
|
printf("\nCPU0: %u JIT compiled pages [Exec Area Pages: %lu/%lu]\n", |
626 |
|
cpu->compiled_pages, |
627 |
|
(u_long)cpu->exec_page_alloc, |
628 |
|
(u_long)cpu->exec_page_count); |
629 |
|
break; |
630 |
|
|
631 |
|
/* Non-JIT mode statistics */ |
632 |
|
case 'j': |
633 |
|
ppc32_dump_stats(cpu); |
634 |
|
break; |
635 |
|
|
636 |
|
default: |
637 |
|
return(FALSE); |
638 |
|
} |
639 |
|
|
640 |
|
return(TRUE); |
641 |
|
} |
642 |
|
|
643 |
/* Process remote control char */ |
/* Process remote control char */ |
644 |
static void remote_control(vtty_t *vtty,u_char c) |
static void remote_control(vtty_t *vtty,u_char c) |
645 |
{ |
{ |
646 |
vm_instance_t *vm = vtty->vm; |
vm_instance_t *vm = vtty->vm; |
647 |
cpu_mips_t *cpu0 = cpu_group_find_id(vm->cpu_group,0); |
cpu_gen_t *cpu0; |
648 |
|
|
649 |
|
cpu0 = vm->boot_cpu; |
650 |
|
|
651 |
|
/* Specific commands for the different CPU models */ |
652 |
|
if (cpu0) { |
653 |
|
switch(cpu0->type) { |
654 |
|
case CPU_TYPE_MIPS64: |
655 |
|
if (remote_control_mips64(vtty,c,CPU_MIPS64(cpu0))) |
656 |
|
return; |
657 |
|
break; |
658 |
|
case CPU_TYPE_PPC32: |
659 |
|
if (remote_control_ppc32(vtty,c,CPU_PPC32(cpu0))) |
660 |
|
return; |
661 |
|
break; |
662 |
|
} |
663 |
|
} |
664 |
|
|
665 |
switch(c) { |
switch(c) { |
666 |
/* Show the object list */ |
/* Show the object list */ |
667 |
case 'o': |
case 'o': |
675 |
|
|
676 |
/* Reboot the C7200 */ |
/* Reboot the C7200 */ |
677 |
case 'k': |
case 'k': |
678 |
c7200_boot_ios(VM_C7200(vm)); |
#if 0 |
679 |
|
if (vm->type == VM_TYPE_C7200) |
680 |
|
c7200_boot_ios(VM_C7200(vm)); |
681 |
|
#endif |
682 |
break; |
break; |
683 |
|
|
684 |
/* Show the device list */ |
/* Show the device list */ |
687 |
pci_dev_show_list(vm->pci_bus[0]); |
pci_dev_show_list(vm->pci_bus[0]); |
688 |
pci_dev_show_list(vm->pci_bus[1]); |
pci_dev_show_list(vm->pci_bus[1]); |
689 |
break; |
break; |
690 |
|
|
691 |
|
/* Show info about Port Adapters or Network Modules */ |
692 |
|
case 'p': |
693 |
|
switch(vm->type) { |
694 |
|
case VM_TYPE_C3600: |
695 |
|
c3600_nm_show_all_info(VM_C3600(vm)); |
696 |
|
break; |
697 |
|
case VM_TYPE_C7200: |
698 |
|
c7200_pa_show_all_info(VM_C7200(vm)); |
699 |
|
break; |
700 |
|
case VM_TYPE_C2691: |
701 |
|
c2691_nm_show_all_info(VM_C2691(vm)); |
702 |
|
break; |
703 |
|
case VM_TYPE_C3725: |
704 |
|
c3725_nm_show_all_info(VM_C3725(vm)); |
705 |
|
break; |
706 |
|
case VM_TYPE_C3745: |
707 |
|
c3745_nm_show_all_info(VM_C3745(vm)); |
708 |
|
break; |
709 |
|
case VM_TYPE_C2600: |
710 |
|
c2600_nm_show_all_info(VM_C2600(vm)); |
711 |
|
break; |
712 |
|
} |
713 |
|
break; |
714 |
|
|
715 |
/* Dump the MIPS registers */ |
/* Dump the MIPS registers */ |
716 |
case 'r': |
case 'r': |
717 |
if (cpu0) mips64_dump_regs(cpu0); |
if (cpu0) cpu0->reg_dump(cpu0); |
718 |
break; |
break; |
719 |
|
|
720 |
/* Dump the latest memory accesses */ |
/* Dump the latest memory accesses */ |
721 |
case 'm': |
case 'm': |
722 |
if (cpu0) memlog_dump(cpu0); |
if (cpu0) memlog_dump(cpu0); |
723 |
break; |
break; |
724 |
|
|
725 |
/* Suspend CPU emulation */ |
/* Suspend CPU emulation */ |
726 |
case 's': |
case 's': |
727 |
vm_suspend(vm); |
vm_suspend(vm); |
732 |
vm_resume(vm); |
vm_resume(vm); |
733 |
break; |
break; |
734 |
|
|
735 |
/* Dump the MIPS TLB */ |
/* Dump the MMU information */ |
736 |
case 't': |
case 't': |
737 |
if (cpu0) tlb_dump(cpu0); |
if (cpu0) cpu0->mmu_dump(cpu0); |
738 |
break; |
break; |
739 |
|
|
740 |
/* Show information about JIT compiled pages */ |
/* Dump the MMU information (raw mode) */ |
741 |
case 'b': |
case 'z': |
742 |
if (cpu0) { |
if (cpu0) cpu0->mmu_raw_dump(cpu0); |
|
printf("\nCPU0: %u JIT compiled pages " |
|
|
"[Exec Area Pages: %lu/%lu]\n", |
|
|
cpu0->compiled_pages, |
|
|
(u_long)cpu0->exec_page_alloc, |
|
|
(u_long)cpu0->exec_page_count); |
|
|
} |
|
743 |
break; |
break; |
744 |
|
|
745 |
/* MTS64 cache statistics */ |
/* Memory translation cache statistics */ |
746 |
case 'l': |
case 'l': |
747 |
if (cpu0) { |
if (cpu0) cpu0->mts_show_stats(cpu0); |
|
mts64_show_stats(cpu0); |
|
|
} |
|
748 |
break; |
break; |
749 |
|
|
750 |
/* Extract the configuration from the NVRAM */ |
/* Extract the configuration from the NVRAM */ |
751 |
case 'c': |
case 'c': |
752 |
vm_ios_save_config(vm); |
vm_ios_save_config(vm); |
753 |
break; |
break; |
754 |
|
|
|
/* Non-JIT mode statistics */ |
|
|
case 'j': |
|
|
if (cpu0) mips64_dump_stats(cpu0); |
|
|
break; |
|
|
|
|
755 |
/* Determine an idle pointer counter */ |
/* Determine an idle pointer counter */ |
756 |
case 'i': |
case 'i': |
757 |
if (cpu0) { |
if (cpu0) |
758 |
mips64_get_idling_pc(cpu0); |
cpu0->get_idling_pc(cpu0); |
|
} |
|
759 |
break; |
break; |
760 |
|
|
761 |
/* Experimentations / Tests */ |
/* Experimentations / Tests */ |
762 |
case 'x': |
case 'x': |
763 |
if (cpu0) { |
if (cpu0) { |
764 |
/* IRQ triggering */ |
/* IRQ triggering */ |
765 |
mips64_set_irq(cpu0,2/*C7200_PA_MGMT_IRQ*/); |
vm_set_irq(vm,2); |
766 |
} |
} |
767 |
break; |
break; |
768 |
|
|
769 |
|
case 'y': |
770 |
|
if (cpu0) { |
771 |
|
/* IRQ clearing */ |
772 |
|
vm_clear_irq(vm,2); |
773 |
|
} |
774 |
|
break; |
775 |
|
|
776 |
/* Twice Ctrl + ']' (0x1d, 29), or Alt-Gr + '*' (0xb3, 179) */ |
/* Twice Ctrl + ']' (0x1d, 29), or Alt-Gr + '*' (0xb3, 179) */ |
777 |
case 0x1d: |
case 0x1d: |
778 |
case 0xb3: |
case 0xb3: |
784 |
|
|
785 |
printf("o - Show the VM object list\n" |
printf("o - Show the VM object list\n" |
786 |
"d - Show the device list\n" |
"d - Show the device list\n" |
787 |
"r - Dump MIPS CPU registers\n" |
"r - Dump CPU registers\n" |
788 |
"t - Dump MIPS TLB entries\n" |
"t - Dump MMU information\n" |
789 |
|
"z - Dump MMU information (raw mode)\n" |
790 |
"m - Dump the latest memory accesses\n" |
"m - Dump the latest memory accesses\n" |
791 |
"s - Suspend CPU emulation\n" |
"s - Suspend CPU emulation\n" |
792 |
"u - Resume CPU emulation\n" |
"u - Resume CPU emulation\n" |
793 |
"q - Quit the emulator\n" |
"q - Quit the emulator\n" |
794 |
"k - Reboot the virtual machine\n" |
"k - Reboot the virtual machine\n" |
795 |
"b - Show info about JIT compiled pages\n" |
"b - Show info about JIT compiled pages\n" |
796 |
"l - MTS64 cache statistics\n" |
"l - MTS cache statistics\n" |
797 |
"c - Write IOS configuration to disk\n" |
"c - Write IOS configuration to disk\n" |
798 |
"j - Non-JIT mode statistics\n" |
"j - Non-JIT mode statistics\n" |
799 |
"i - Determine an idling pointer counter\n" |
"i - Determine an idling pointer counter\n" |
986 |
return(res); |
return(res); |
987 |
} |
} |
988 |
|
|
989 |
/* put char to vtty */ |
/* Put char to vtty */ |
990 |
void vtty_put_char(vtty_t *vtty, char ch) |
void vtty_put_char(vtty_t *vtty, char ch) |
991 |
{ |
{ |
992 |
switch(vtty->type) { |
switch(vtty->type) { |
1019 |
} |
} |
1020 |
} |
} |
1021 |
|
|
1022 |
|
/* Put a buffer to vtty */ |
1023 |
|
void vtty_put_buffer(vtty_t *vtty,char *buf,size_t len) |
1024 |
|
{ |
1025 |
|
size_t i; |
1026 |
|
|
1027 |
|
for(i=0;i<len;i++) |
1028 |
|
vtty_put_char(vtty,buf[i]); |
1029 |
|
} |
1030 |
|
|
1031 |
/* Flush VTTY output */ |
/* Flush VTTY output */ |
1032 |
void vtty_flush(vtty_t *vtty) |
void vtty_flush(vtty_t *vtty) |
1033 |
{ |
{ |
1098 |
|
|
1099 |
if (FD_ISSET(fd,&rfds)) { |
if (FD_ISSET(fd,&rfds)) { |
1100 |
vtty_read_and_store(vtty); |
vtty_read_and_store(vtty); |
1101 |
|
vtty->input_pending = TRUE; |
1102 |
|
} |
1103 |
|
|
1104 |
|
if (vtty->input_pending) { |
1105 |
if (vtty->read_notifier != NULL) |
if (vtty->read_notifier != NULL) |
1106 |
vtty->read_notifier(vtty); |
vtty->read_notifier(vtty); |
1107 |
|
|
1108 |
|
vtty->input_pending = FALSE; |
1109 |
} |
} |
1110 |
|
|
1111 |
/* Flush any pending output */ |
/* Flush any pending output */ |