/* * Shutdown hardware resources used by a VM. * The CPU must have been stopped. */ static int vm_hardware_shutdown (vm_instance_t * vm) { //int i; if ((vm->status == VM_STATUS_HALTED) || !vm->cpu_group) { vm_log (vm, "VM", "trying to shutdown an inactive VM.\n"); return (-1); } vm_log (vm, "VM", "shutdown procedure engaged.\n"); /* Mark the VM as halted */ vm->status = VM_STATUS_HALTED; /* Disable NVRAM operations */ // vm->nvram_extract_config = NULL; // vm->nvram_push_config = NULL; /* Free the object list */ // vm_object_free_list(vm); /* Free resources used by PCI busses */ // vm_log(vm,"VM","removing PCI busses.\n"); // pci_io_data_remove(vm,vm->pci_io_space); // pci_bus_remove(vm->pci_bus[0]); // pci_bus_remove(vm->pci_bus[1]); // vm->pci_bus[0] = vm->pci_bus[1] = NULL; /* Free the PCI bus pool */ /* for(i=0;i<VM_PCI_POOL_SIZE;i++) { * if (vm->pci_bus_pool[i] != NULL) { * pci_bus_remove(vm->pci_bus_pool[i]); * vm->pci_bus_pool[i] = NULL; * } * } */ /* Remove the IRQ routing vectors */ vm->set_irq = NULL; vm->clear_irq = NULL; /* Delete the VTTY for Console and AUX ports */ vm_log (vm, "VM", "deleting VTTY.\n"); vm_delete_vtty (vm); /* Delete system CPU group */ vm_log (vm, "VM", "deleting system CPUs.\n"); cpu_group_delete (vm->cpu_group); vm->cpu_group = NULL; vm->boot_cpu = NULL; vm_log (vm, "VM", "shutdown procedure completed.\n"); return (0); }
/* Put char to vtty */ void vtty_put_char(vtty_t *vtty, char ch) { switch(vtty->type) { case VTTY_TYPE_NONE: break; case VTTY_TYPE_TERM: case VTTY_TYPE_SERIAL: if (write(vtty->fd_array[0],&ch,1) != 1) { vm_log(vtty->vm,"VTTY","%s: put char 0x%x failed (%s)\n", vtty->name,(int)ch,strerror(errno)); } break; case VTTY_TYPE_TCP: fd_pool_send(&vtty->fd_pool,&ch,1,0); break; default: vm_error(vtty->vm,"vtty_put_char: bad vtty type %d\n",vtty->type); exit(1); } /* store char for replay */ vtty->replay_buffer[vtty->replay_ptr] = ch; ++vtty->replay_ptr; if (vtty->replay_ptr == VTTY_BUFFER_SIZE) vtty->replay_ptr = 0; }
/* DMA transfer operation */ void physmem_dma_transfer(vm_instance_t *vm,m_uint64_t src,m_uint64_t dst, size_t len) { m_uint64_t dummy; u_char *sptr,*dptr; size_t clen,sl,dl; while(len > 0) { sptr = physmem_get_hptr(vm,src,0,MTS_READ,&dummy); dptr = physmem_get_hptr(vm,dst,0,MTS_WRITE,&dummy); if (!sptr || !dptr) { vm_log(vm,"DMA","unable to transfer from 0x%llx to 0x%llx\n",src,dst); return; } sl = VM_PAGE_SIZE - (src & VM_PAGE_IMASK); dl = VM_PAGE_SIZE - (dst & VM_PAGE_IMASK); clen = m_min(sl,dl); clen = m_min(clen,len); memcpy(dptr,sptr,clen); src += clen; dst += clen; len -= clen; } }
/* Boot the ELF image */ static int ppc32_vmtest_boot_elf(vm_instance_t *vm) { m_uint32_t rom_entry_point; cpu_ppc_t *cpu; if (!vm->boot_cpu) return(-1); /* Suspend CPU activity since we will restart directly from ROM */ vm_suspend(vm); /* Check that CPU activity is really suspended */ if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(-1); } /* Reset the boot CPU */ cpu = CPU_PPC32(vm->boot_cpu); ppc32_reset(cpu); /* Load ROM (ELF image or embedded) */ cpu = CPU_PPC32(vm->boot_cpu); rom_entry_point = (m_uint32_t)PPC32_ROM_START; if ((vm->rom_filename != NULL) && (ppc32_load_elf_image(cpu,vm->rom_filename,0,&rom_entry_point) < 0)) { vm_error(vm,"unable to load alternate ROM '%s', " "fallback to embedded ROM.\n\n",vm->rom_filename); vm->rom_filename = NULL; } /* Load ELF image */ if (ppc32_load_elf_image(cpu,vm->ios_image, (vm->ghost_status == VM_GHOST_RAM_USE), &vm->ios_entry_point) < 0) { vm_error(vm,"failed to load ELF image '%s'.\n",vm->ios_image); return(-1); } /* Launch the simulation */ printf("\nPPC32_VMTEST '%s': starting simulation (CPU0 IA=0x%8.8x), " "JIT %sabled.\n", vm->name,cpu->ia,vm->jit_use ? "en":"dis"); vm_log(vm,"PPC32_VMTEST_BOOT", "starting instance (CPU0 IA=0x%8.8x,JIT %s)\n", cpu->ia,vm->jit_use ? "on":"off"); /* Start main CPU */ if (vm->ghost_status != VM_GHOST_RAM_GENERATE) { vm->status = VM_STATUS_RUNNING; cpu_start(vm->boot_cpu); } else { vm->status = VM_STATUS_SHUTDOWN; } return(0); }
/* * dev_c7200_pa_8t_init() * * Add a PA-8T port adapter into specified slot. */ static int dev_c7200_pa_8t_init(vm_instance_t *vm,struct cisco_card *card) { struct pa8t_data *data; u_int slot = card->slot_id; /* Allocate the private data structure for the PA-8T */ if (!(data = malloc(sizeof(*data)))) { vm_log(vm,"%s: out of memory\n",card->dev_name); return(-1); } /* Set the PCI bus */ card->pci_bus = vm->slots_pci_bus[slot]; /* Set the EEPROM */ cisco_card_set_eeprom(vm,card,cisco_eeprom_find_pa("PA-8T")); c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom); /* Create the 1st Mueslix chip */ data->mueslix[0] = dev_mueslix_init(vm,card->dev_name,1, card->pci_bus,0, c7200_net_irq_for_slot_port(slot,0)); if (!data->mueslix[0]) return(-1); /* Create the 2nd Mueslix chip */ data->mueslix[1] = dev_mueslix_init(vm,card->dev_name,1, card->pci_bus,1, c7200_net_irq_for_slot_port(slot,1)); if (!data->mueslix[1]) return(-1); /* Store device info into the router structure */ card->drv_info = data; return(0); }
/* Boot the IOS image */ static int c1700_boot_ios(c1700_t *router) { vm_instance_t *vm = router->vm; cpu_ppc_t *cpu; if (!vm->boot_cpu) return(-1); /* Suspend CPU activity since we will restart directly from ROM */ vm_suspend(vm); /* Check that CPU activity is really suspended */ if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(-1); } /* Reset the boot CPU */ cpu = CPU_PPC32(vm->boot_cpu); ppc32_reset(cpu); /* Adjust stack pointer */ cpu->gpr[1] |= 0x80000000; /* Load BAT registers */ printf("Loading BAT registers\n"); ppc32_load_bat_array(cpu,bat_array); cpu->msr |= PPC32_MSR_IR|PPC32_MSR_DR; /* IRQ routing */ vm->set_irq = c1700_set_irq; vm->clear_irq = c1700_clear_irq; /* Load IOS image */ if (ppc32_load_elf_image(cpu,vm->ios_image, (vm->ghost_status == VM_GHOST_RAM_USE), &vm->ios_entry_point) < 0) { vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image); return(-1); } /* Launch the simulation */ printf("\nC1700 '%s': starting simulation (CPU0 IA=0x%8.8x), " "JIT %sabled.\n", vm->name,cpu->ia,vm->jit_use ? "en":"dis"); vm_log(vm,"C1700_BOOT", "starting instance (CPU0 PC=0x%8.8x,idle_pc=0x%8.8x,JIT %s)\n", cpu->ia,cpu->idle_pc,vm->jit_use ? "on":"off"); /* Start main CPU */ if (vm->ghost_status != VM_GHOST_RAM_GENERATE) { vm->status = VM_STATUS_RUNNING; cpu_start(vm->boot_cpu); } else { vm->status = VM_STATUS_SHUTDOWN; } return(0); }
/* Clear a Network IRQ for the specified slot/port */ void dev_c3600_iofpga_net_clear_irq(struct c3600_iofpga_data *d, u_int slot,u_int port) { struct net_irq_distrib *irq_dist; #if DEBUG_NET_IRQ vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n", slot,port); #endif irq_dist = &net_irq_dist[slot]; switch(c3600_chassis_get_id(d->router)) { case 3620: case 3640: d->net_irq_status[0] &= ~(1 << (irq_dist->c3620_c3640_offset + port)); dev_c3620_c3640_iofpga_net_update_irq(d); break; case 3660: d->net_irq_status[irq_dist->c3660_reg] &= ~(1 << (irq_dist->c3660_offset + port)); dev_c3660_iofpga_net_update_irq(d); break; } }
/* Physical memory dump (32-bit words) */ void physmem_dump_vm(vm_instance_t *vm,m_uint64_t paddr,m_uint32_t u32_count) { m_uint32_t i; for(i=0;i<u32_count;i++) { vm_log(vm,"physmem_dump","0x%8.8llx: 0x%8.8x\n", paddr+(i<<2),physmem_copy_u32_from_vm(vm,paddr+(i<<2))); } }
/* Accept a TCP connection */ static int vtty_tcp_conn_accept(vtty_t *vtty, int nsock) { int fd,*fd_slot; u_int i; if (fd_pool_get_free_slot(&vtty->fd_pool,&fd_slot) < 0) { vm_error(vtty->vm,"unable to create a new VTTY TCP connection\n"); return(-1); } if ((fd = accept(vtty->fd_array[nsock],NULL,NULL)) < 0) { vm_error(vtty->vm,"vtty_tcp_conn_accept: accept on port %d failed %s\n", vtty->tcp_port,strerror(errno)); return(-1); } /* Register the new FD */ *fd_slot = fd; vm_log(vtty->vm,"VTTY","%s is now connected (accept_fd=%d,conn_fd=%d)\n", vtty->name,vtty->fd_array[nsock],fd); /* Adapt Telnet settings */ if (vtty->terminal_support) { vtty_telnet_do_ttype(fd); vtty_telnet_will_echo(fd); vtty_telnet_will_suppress_go_ahead(fd); vtty_telnet_dont_linemode(fd); vtty->input_state = VTTY_INPUT_TEXT; } if (telnet_message_ok == 1) { fd_printf(fd,0, "Connected to Dynamips VM \"%s\" (ID %u, type %s) - %s\r\n" "Press ENTER to get the prompt.\r\n", vtty->vm->name, vtty->vm->instance_id, vm_get_type(vtty->vm), vtty->name); /* replay old text */ for (i = vtty->replay_ptr; i < VTTY_BUFFER_SIZE; i++) { if (vtty->replay_buffer[i] != 0) { send(fd,&vtty->replay_buffer[i],VTTY_BUFFER_SIZE-i,0); break; } } for (i = 0; i < vtty->replay_ptr; i++) { if (vtty->replay_buffer[i] != 0) { send(fd,&vtty->replay_buffer[i],vtty->replay_ptr-i,0); break; } } /* warn if not running */ if (vtty->vm->status != VM_STATUS_RUNNING) fd_printf(fd,0,"\r\n!!! WARNING - VM is not running, will be unresponsive (status=%d) !!!\r\n",vtty->vm->status); vtty_flush(vtty); } return(0); }
/* Wait for a TCP connection */ static int vtty_tcp_conn_wait(vtty_t *vtty) { struct sockaddr_in serv; int i; int one = 1; for(i=0;i<VTTY_MAX_FD;i++) vtty->fd_array[i] = -1; if ((vtty->fd_array[0] = socket(PF_INET,SOCK_STREAM,0)) < 0) { perror("vtty_tcp_waitcon: socket"); return(-1); } if (setsockopt(vtty->fd_array[0],SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one)) < 0) { perror("vtty_tcp_waitcon: setsockopt(SO_REUSEADDR)"); goto error; } if (setsockopt(vtty->fd_array[0],SOL_SOCKET,SO_KEEPALIVE,&one,sizeof(one)) < 0) { perror("vtty_tcp_waitcon: setsockopt(SO_KEEPALIVE)"); goto error; } // Send telnet packets asap. Dont wait to fill packets up if (setsockopt(vtty->fd_array[0],SOL_TCP,TCP_NODELAY,&one,sizeof(one)) < 0) { perror("vtty_tcp_waitcon: setsockopt(TCP_NODELAY)"); goto error; } memset(&serv,0,sizeof(serv)); serv.sin_family = AF_INET; serv.sin_addr.s_addr = htonl(INADDR_ANY); serv.sin_port = htons(vtty->tcp_port); if (bind(vtty->fd_array[0],(struct sockaddr *)&serv,sizeof(serv)) < 0) { perror("vtty_tcp_waitcon: bind"); goto error; } if (listen(vtty->fd_array[0],1) < 0) { perror("vtty_tcp_waitcon: listen"); goto error; } vm_log(vtty->vm,"VTTY","%s: waiting connection on tcp port %d (FD %d)\n", vtty->name,vtty->tcp_port,vtty->fd_array[0]); return(1); error: close(vtty->fd_array[0]); vtty->fd_array[0] = -1; return(-1); }
/* Clear a Network IRQ for the specified slot/port */ void dev_c2600_iofpga_net_clear_irq(struct c2600_iofpga_data *d, u_int slot,u_int port) { #if DEBUG_NET_IRQ vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n", slot,port); #endif d->net_irq_status &= ~(1 << (net_irq_dist[slot] + port)); dev_c2600_iofpga_net_update_irq(d); }
/* * Log a message with sprintf-style formatting */ void vm_log_fmt(VMG_ const char *fmt, ...) { /* format the message */ va_list args; va_start(args, fmt); char *str = t3vsprintf_alloc(fmt, args); va_end(args); /* log the message */ vm_log(vmg_ str, strlen(str)); /* done with the string */ t3free(str); }
/* Delete a virtual tty */ void vtty_delete(vtty_t *vtty) { int i; if (vtty != NULL) { if (vtty->pprev != NULL) { VTTY_LIST_LOCK(); if (vtty->next) vtty->next->pprev = vtty->pprev; *(vtty->pprev) = vtty->next; VTTY_LIST_UNLOCK(); } switch(vtty->type) { case VTTY_TYPE_TCP: for(i=0;i<vtty->fd_count;i++) if (vtty->fd_array[i] != -1) { vm_log(vtty->vm,"VTTY","%s: closing FD %d\n",vtty->name,vtty->fd_array[i]); close(vtty->fd_array[i]); } fd_pool_free(&vtty->fd_pool); vtty->fd_count = 0; break; default: /* We don't close FD 0 since it is stdin */ if (vtty->fd_array[0] > 0) { vm_log(vtty->vm,"VTTY","%s: closing FD %d\n",vtty->name,vtty->fd_array[0]); close(vtty->fd_array[0]); } } free(vtty); } }
/* Remove a device */ void dev_remove (vm_instance_t * vm, struct vdevice *dev) { if (dev == NULL) return; vm_unbind_device (vm, dev); vm_log (vm, "DEVICE", "Removal of device %s, fd=%d, host_addr=0x%" LL "x, flags=%d\n", dev->name, dev->fd, (m_uint64_t) dev->host_addr, dev->flags); if (dev->flags & VDEVICE_FLAG_REMAP) { dev_init (dev); return; } if (dev->fd != -1) { /* Unmap memory mapped file */ if (dev->host_addr) { vm_log (vm, "MMAP", "unmapping of device '%s', " "fd=%d, host_addr=0x%" LL "x, len=0x%x\n", dev->name, dev->fd, (m_uint64_t) dev->host_addr, dev->phys_len); munmap ((void *) dev->host_addr, dev->phys_len); } close (dev->fd); } else { /* Use of malloc'ed host memory: free it */ if (dev->host_addr) free ((void *) dev->host_addr); } /* reinitialize the device to a clean state */ dev_init (dev); }
/* Boot the IOS image */ static int c3725_boot_ios(c3725_t *router) { vm_instance_t *vm = router->vm; cpu_mips_t *cpu; if (!vm->boot_cpu) return(-1); /* Suspend CPU activity since we will restart directly from ROM */ vm_suspend(vm); /* Check that CPU activity is really suspended */ if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(-1); } /* Reset the boot CPU */ cpu = CPU_MIPS64(vm->boot_cpu); mips64_reset(cpu); /* Load IOS image */ if (mips64_load_elf_image(cpu,vm->ios_image, (vm->ghost_status == VM_GHOST_RAM_USE), &vm->ios_entry_point) < 0) { vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image); return(-1); } /* Launch the simulation */ printf("\nC3725 '%s': starting simulation (CPU0 PC=0x%llx), " "JIT %sabled.\n", vm->name,cpu->pc,vm->jit_use ? "en":"dis"); vm_log(vm,"C3725_BOOT", "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n", cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off"); /* Start main CPU */ if (vm->ghost_status != VM_GHOST_RAM_GENERATE) { vm->status = VM_STATUS_RUNNING; cpu_start(vm->boot_cpu); } else { vm->status = VM_STATUS_SHUTDOWN; } return(0); }
/* Boot the RAW image */ _unused static int ppc32_vmtest_boot_raw(vm_instance_t *vm) { cpu_ppc_t *cpu; if (!vm->boot_cpu) return(-1); /* Suspend CPU activity since we will restart directly from ROM */ vm_suspend(vm); /* Check that CPU activity is really suspended */ if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(-1); } /* Reset the boot CPU */ cpu = CPU_PPC32(vm->boot_cpu); ppc32_reset(cpu); /* Load RAW image */ if (ppc32_load_raw_image(cpu,vm->ios_image,0xFFF00000) < 0) { vm_error(vm,"failed to load RAW image '%s'.\n",vm->ios_image); return(-1); } cpu->ia = 0xFFF00100; cpu->gpr[1] = 0x2000; /* Launch the simulation */ printf("\nPPC32_VMTEST '%s': starting simulation (CPU0 IA=0x%8.8x), " "JIT %sabled.\n", vm->name,cpu->ia,vm->jit_use ? "en":"dis"); vm_log(vm,"PPC32_VMTEST_BOOT", "starting instance (CPU0 IA=0x%8.8x,JIT %s)\n", cpu->ia,vm->jit_use ? "on":"off"); /* Start main CPU */ if (vm->ghost_status != VM_GHOST_RAM_GENERATE) { vm->status = VM_STATUS_RUNNING; cpu_start(vm->boot_cpu); } else { vm->status = VM_STATUS_SHUTDOWN; } return(0); }
/* Shut down all objects of an instance */ void vm_object_free_list(vm_instance_t *vm) { vm_obj_t *obj,*next; for(obj=vm->vm_object_list;obj;obj=next) { next = obj->next; if (obj->shutdown != NULL) { #if DEBUG_VM vm_log(vm,"VM_OBJECT","Shutdown of object \"%s\"\n",obj->name); #endif obj->shutdown(vm,obj->data); } } vm->vm_object_list = NULL; }
/* Stop a test instance */ static int ppc32_vmtest_stop_instance(vm_instance_t *vm) { printf("\nPPC32_VMTEST '%s': stopping simulation.\n",vm->name); vm_log(vm,"PPC32_VMTEST_STOP","stopping simulation.\n"); /* Stop all CPUs */ if (vm->cpu_group != NULL) { vm_stop(vm); if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(-1); } } /* Free resources that were used during execution to emulate hardware */ vm_hardware_shutdown(vm); return(0); }
/* Stop a Cisco 3725 instance */ static int c3725_stop_instance(vm_instance_t *vm) { printf("\nC3725 '%s': stopping simulation.\n",vm->name); vm_log(vm,"C3725_STOP","stopping simulation.\n"); /* Stop all CPUs */ if (vm->cpu_group != NULL) { vm_stop(vm); if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(-1); } } /* Free resources that were used during execution to emulate hardware */ vm_slot_shutdown_all(vm); vm_hardware_shutdown(vm); /* Cleanup */ VM_C3725(vm)->iofpga_data = NULL; VM_C3725(vm)->gt_data = NULL; return(0); }
/* * dev_remote_control_access() */ void *dev_remote_control_access(cpu_gen_t *cpu,struct vdevice *dev, m_uint32_t offset,u_int op_size,u_int op_type, m_uint64_t *data) { vm_instance_t *vm = cpu->vm; struct remote_data *d = dev->priv_data; struct vdevice *storage_dev; size_t len; if (op_type == MTS_READ) *data = 0; #if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,"REMOTE","reading reg 0x%x at pc=0x%llx\n", offset,cpu_get_pc(cpu)); } else { cpu_log(cpu,"REMOTE","writing reg 0x%x at pc=0x%llx, data=0x%llx\n", offset,cpu_get_pc(cpu),*data); } #endif switch(offset) { /* ROM Identification tag */ case 0x000: if (op_type == MTS_READ) *data = ROM_ID; break; /* CPU ID */ case 0x004: if (op_type == MTS_READ) *data = cpu->id; break; /* Display CPU registers */ case 0x008: if (op_type == MTS_WRITE) cpu->reg_dump(cpu); break; /* Display CPU memory info */ case 0x00c: if (op_type == MTS_WRITE) cpu->mmu_dump(cpu); break; /* Reserved/Unused */ case 0x010: break; /* RAM size */ case 0x014: if (op_type == MTS_READ) *data = vm->ram_size; break; /* ROM size */ case 0x018: if (op_type == MTS_READ) *data = vm->rom_size; break; /* NVRAM size */ case 0x01c: if (op_type == MTS_READ) *data = vm->nvram_size; break; /* IOMEM size */ case 0x020: if (op_type == MTS_READ) *data = vm->iomem_size; break; /* Config Register */ case 0x024: if (op_type == MTS_READ) *data = vm->conf_reg; break; /* ELF entry point */ case 0x028: if (op_type == MTS_READ) *data = vm->ios_entry_point; break; /* ELF machine id */ case 0x02c: if (op_type == MTS_READ) *data = vm->elf_machine_id; break; /* Restart IOS Image */ case 0x030: /* not implemented */ break; /* Stop the virtual machine */ case 0x034: // FIXME: WTF is this for?!?!? //vm->status = VM_STATUS_SHUTDOWN; break; /* Debugging/Log message: /!\ physical address */ case 0x038: if (op_type == MTS_WRITE) { len = physmem_strlen(vm,*data); if (len < sizeof(d->con_buffer)) { physmem_copy_from_vm(vm,d->con_buffer,*data,len+1); vm_log(vm,"ROM",d->con_buffer); } } break; /* Console Buffering */ case 0x03c: if (op_type == MTS_WRITE) { if (d->con_buf_pos < (sizeof(d->con_buffer)-1)) { d->con_buffer[d->con_buf_pos++] = *data & 0xFF; d->con_buffer[d->con_buf_pos] = 0; if (d->con_buffer[d->con_buf_pos-1] == '\n') { vm_log(vm,"ROM","%s",d->con_buffer); d->con_buf_pos = 0; } } else d->con_buf_pos = 0; } break; /* Console output */ case 0x040: if (op_type == MTS_WRITE) vtty_put_char(vm->vtty_con,(char)*data); break; /* NVRAM address */ case 0x044: if (op_type == MTS_READ) { if ((storage_dev = dev_get_by_name(vm,"nvram"))) *data = storage_dev->phys_addr; if ((storage_dev = dev_get_by_name(vm,"ssa"))) *data = storage_dev->phys_addr; if (cpu->type == CPU_TYPE_MIPS64) *data += MIPS_KSEG1_BASE; } break; /* IO memory size for Smart-Init (C3600, others ?) */ case 0x048: if (op_type == MTS_READ) *data = vm->nm_iomem_size; break; /* Cookie position selector */ case 0x04c: if (op_type == MTS_READ) *data = d->cookie_pos; else d->cookie_pos = *data; break; /* Cookie data */ case 0x050: if ((op_type == MTS_READ) && (d->cookie_pos < 64)) *data = vm->chassis_cookie[d->cookie_pos]; break; /* ROMMON variable */ case 0x054: if (op_type == MTS_WRITE) { if (d->var_buf_pos < (sizeof(d->var_buffer)-1)) { d->var_buffer[d->var_buf_pos++] = *data & 0xFF; d->var_buffer[d->var_buf_pos] = 0; } else d->var_buf_pos = 0; } else { if (d->var_buf_pos < (sizeof(d->var_buffer)-1)) { *data = d->var_buffer[d->var_buf_pos++]; } else { d->var_buf_pos = 0; *data = 0; } } break; /* ROMMON variable command */ case 0x058: if (op_type == MTS_WRITE) { switch(*data & 0xFF) { case ROMMON_SET_VAR: d->var_status = rommon_var_add_str(&vm->rommon_vars, d->var_buffer); d->var_buf_pos = 0; break; case ROMMON_GET_VAR: d->var_status = rommon_var_get(&vm->rommon_vars, d->var_buffer, d->var_buffer, sizeof(d->var_buffer)); d->var_buf_pos = 0; break; case ROMMON_CLEAR_VAR_STAT: d->var_buf_pos = 0; break; default: d->var_status = -1; } } else { *data = d->var_status; } break; } return NULL; }
/* Rename a VM instance */ int vm_rename_instance(vm_instance_t *vm, char *name) { char *old_name; char *old_lock_file = NULL; FILE *old_lock_fd = NULL; glob_t globbuf; size_t i; char *pattern = NULL; char *filename; int do_rename = 0; if (name == NULL || vm == NULL) goto err_invalid; /* invalid argument */ if (vm->status != VM_STATUS_HALTED) goto err_not_stopped; /* VM is not stopped */ if (strcmp(vm->name, name) == 0) return(0); /* same name, done */ if (registry_exists(name,OBJ_TYPE_VM)) goto err_exists; /* name already exists */ old_name = vm->name; vm->name = NULL; if(!(vm->name = strdup(name))) goto err_strdup; /* out of memory */ /* get new lock */ do_rename = ( vm_file_naming_type != 1 ); if (do_rename) { old_lock_file = vm->lock_file; old_lock_fd = vm->lock_fd; vm->lock_file = NULL; vm->lock_fd = NULL; if (vm_get_lock(vm) == -1) goto err_lock; } if (registry_rename(old_name,name,OBJ_TYPE_VM)) goto err_registry; /* failed to rename */ vm_log(vm,"VM","renamed from '%s' to '%s'",old_name,vm->name); /* rename files (best effort) */ if (do_rename) { fclose(old_lock_fd); unlink(old_lock_file); free(old_lock_file); vm_close_log(vm); if ((pattern = dyn_sprintf("%s_%s_*",vm_get_type(vm),old_name)) == NULL) goto skip_rename; if (glob(pattern, GLOB_NOSORT, NULL, &globbuf) != 0) goto skip_rename; for (i = 0; i < globbuf.gl_pathc; i++) { if ((filename = dyn_sprintf("%s_%s_%s",vm_get_type(vm),vm->name,globbuf.gl_pathv[i] + strlen(pattern) - 1)) == NULL) break; /* out of memory */ rename(globbuf.gl_pathv[i], filename); free(filename); } globfree(&globbuf); skip_rename: free(pattern); vm_reopen_log(vm); } free(old_name); return(0); // done err_registry: err_lock: err_strdup: free(vm->name); vm->name = old_name; if (do_rename) { vm_release_lock(vm,TRUE); vm->lock_file = old_lock_file; vm->lock_fd = old_lock_fd; } err_exists: err_not_stopped: err_invalid: return(-1); }
/* Wait for a TCP connection */ static int vtty_tcp_conn_wait(vtty_t *vtty) { struct addrinfo hints,*res,*res0; char port_str[20],*addr,*proto; int i, nsock; int one = 1; for(i=0;i<VTTY_MAX_FD;i++) vtty->fd_array[i] = -1; memset(&hints,0,sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; snprintf(port_str,sizeof(port_str),"%d",vtty->tcp_port); addr = (binding_addr && strlen(binding_addr)) ? binding_addr : NULL; if (getaddrinfo(addr,port_str,&hints,&res0) != 0) { perror("vtty_tcp_waitcon: getaddrinfo"); return(-1); } nsock = 0; for (res=res0;(res && (nsock < VTTY_MAX_FD));res=res->ai_next) { if ((res->ai_family != PF_INET) && (res->ai_family != PF_INET6)) continue; vtty->fd_array[nsock] = socket(res->ai_family,res->ai_socktype, res->ai_protocol); if (vtty->fd_array[nsock] < 0) continue; if (setsockopt(vtty->fd_array[nsock],SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one)) < 0) perror("vtty_tcp_waitcon: setsockopt(SO_REUSEADDR)"); if (setsockopt(vtty->fd_array[nsock],SOL_SOCKET,SO_KEEPALIVE,&one,sizeof(one)) < 0) perror("vtty_tcp_waitcon: setsockopt(SO_KEEPALIVE)"); // Send telnet packets asap. Dont wait to fill packets up if (setsockopt(vtty->fd_array[nsock],SOL_TCP,TCP_NODELAY, &one,sizeof(one)) < 0) perror("vtty_tcp_waitcon: setsockopt(TCP_NODELAY)"); if ((bind(vtty->fd_array[nsock],res->ai_addr,res->ai_addrlen) < 0) || (listen(vtty->fd_array[nsock],1) < 0)) { close(vtty->fd_array[nsock]); vtty->fd_array[nsock] = -1; continue; } proto = (res->ai_family == PF_INET6) ? "IPv6" : "IPv4"; vm_log(vtty->vm,"VTTY","%s: waiting connection on tcp port %d for protocol %s (FD %d)\n", vtty->name,vtty->tcp_port,proto,vtty->fd_array[nsock]); nsock++; } freeaddrinfo(res0); return(nsock); }