?? monitor.c
字號(hào):
if (!CO_OK(rc)) { num_pages = i; scan_address = address; for (i=0; i < num_pages; i++) { co_monitor_free_and_unmap_page(cmon, scan_address); scan_address += CO_ARCH_PAGE_SIZE; } } return rc;}static void incoming_message(co_monitor_t *cmon, co_message_t *message){ co_manager_open_desc_t opened; co_rc_t rc; if (message->to == CO_MODULE_CONET0) co_debug_lvl(network, 14, "message received: %p %p", cmon, message); co_os_mutex_acquire(cmon->connected_modules_write_lock); opened = cmon->connected_modules[message->to]; if (opened != NULL) rc = co_manager_open_ref(opened); else rc = CO_RC(ERROR); co_os_mutex_release(cmon->connected_modules_write_lock); if (CO_OK(rc)) { co_manager_send(cmon->manager, opened, message); co_manager_close(cmon->manager, opened); } if (message->to == CO_MODULE_CONET0) co_debug_lvl(network, 14, "message received end: %p %p", cmon, message); switch (message->to) { case CO_MODULE_CONSOLE: if (message->from == CO_MODULE_LINUX) { co_console_op(cmon->console, (co_console_message_t *)message->data); } break; default: break; }}co_rc_t co_monitor_message_from_user(co_monitor_t *monitor, co_manager_open_desc_t opened, co_message_t *message){ co_rc_t rc = CO_RC(OK); if (message->to == CO_MODULE_LINUX) { co_os_mutex_acquire(monitor->linux_message_queue_mutex); rc = co_message_dup_to_queue(message, &monitor->linux_message_queue); co_os_mutex_release(monitor->linux_message_queue_mutex); co_os_wait_wakeup(monitor->idle_wait); } else { rc = CO_RC(ERROR); } return rc;}/* * iteration - returning PTRUE means that the driver will return * immediately to Linux instead of returning to the host's * userspace and only then to Linux. */static bool_t iteration(co_monitor_t *cmon){ switch (co_passage_page->operation) { case CO_OPERATION_FORWARD_INTERRUPT: case CO_OPERATION_IDLE: callback_return(cmon); break; } co_debug_lvl(context_switch, 14, "switching to linux (%ld)", co_passage_page->operation); co_host_switch_wrapper(cmon); if (co_passage_page->operation == CO_OPERATION_FORWARD_INTERRUPT) co_monitor_arch_real_hardware_interrupt(cmon); else co_monitor_arch_enable_interrupts(); switch (co_passage_page->operation) { case CO_OPERATION_FREE_PAGES: { co_free_pages(cmon, co_passage_page->params[0], co_passage_page->params[1]); return PTRUE; } case CO_OPERATION_ALLOC_PAGES: { co_rc_t rc; rc = co_alloc_pages(cmon, co_passage_page->params[0], co_passage_page->params[1]); co_passage_page->params[4] = (unsigned long)(rc); return PTRUE; } case CO_OPERATION_FORWARD_INTERRUPT: { co_debug_lvl(context_switch, 15, "switching from linux (CO_OPERATION_FORWARD_INTERRUPT), %d", cmon->timer_interrupt); if (cmon->timer_interrupt) { cmon->timer_interrupt = PFALSE; /* Return to userspace once in a while */ return PFALSE; } return PTRUE; } case CO_OPERATION_TERMINATE: return co_terminate(cmon); case CO_OPERATION_IDLE: return co_idle(cmon); case CO_OPERATION_MESSAGE_TO_MONITOR: { co_message_t *message; co_debug_lvl(context_switch, 14, "switching from linux (CO_OPERATION_MESSAGE_TO_MONITOR)"); message = (co_message_t *)cmon->io_buffer->buffer; if (message && message->to < CO_MONITOR_MODULES_COUNT) incoming_message(cmon, message); cmon->io_buffer->messages_waiting = 0; return PTRUE; } case CO_OPERATION_PRINTK: { unsigned long size = co_passage_page->params[0]; char *ptr = (char *)&co_passage_page->params[1]; co_message_t *co_message; if (size > 200) size = 200; /* sanity, see co_terminal_printv */ co_message = co_os_malloc(1 + size + sizeof(*co_message)); if (co_message) { co_message->from = CO_MODULE_LINUX; co_message->to = CO_MODULE_PRINTK; co_message->priority = CO_PRIORITY_DISCARDABLE; co_message->type = CO_MESSAGE_TYPE_STRING; co_message->size = size + 1; co_memcpy(co_message->data, ptr, size + 1); incoming_message(cmon, co_message); co_os_free(co_message); } return PTRUE; } case CO_OPERATION_DEVICE: { unsigned long device = co_passage_page->params[0]; co_debug_lvl(context_switch, 14, "switching from linux (CO_OPERATION_DEVICE)"); return device_request(cmon, device, &co_passage_page->params[1]); } case CO_OPERATION_GET_TIME: { co_debug_lvl(context_switch, 14, "switching from linux (CO_OPERATION_GET_TIME)"); co_passage_page->params[0] = co_os_get_time(); return PTRUE; } case CO_OPERATION_GET_HIGH_PREC_TIME: { co_os_get_timestamp_freq((co_timestamp_t *)&co_passage_page->params[0], (co_timestamp_t *)&co_passage_page->params[2]); return PTRUE; } case CO_OPERATION_DEBUG_LINE: case CO_OPERATION_TRACE_POINT: return PTRUE; default: co_debug_lvl(context_switch, 5, "unknown operation %ld not handled", co_passage_page->operation); return PFALSE; } return PTRUE;}static void free_file_blockdevice(co_monitor_t *cmon, co_block_dev_t *dev){ co_monitor_file_block_dev_t *fdev = (co_monitor_file_block_dev_t *)dev; co_monitor_file_block_shutdown(fdev); co_monitor_free(cmon, dev);}static co_rc_t load_configuration(co_monitor_t *cmon){ co_rc_t rc = CO_RC_OK; unsigned int i; for (i=0; i < CO_MODULE_MAX_COBD; i++) { co_monitor_file_block_dev_t *dev; co_block_dev_desc_t *conf_dev = &cmon->config.block_devs[i]; if (!conf_dev->enabled) continue; rc = co_monitor_malloc(cmon, sizeof(co_monitor_file_block_dev_t), (void **)&dev); if (!CO_OK(rc)) goto error_1; rc = co_monitor_file_block_init(dev, &conf_dev->pathname); if (CO_OK(rc)) { dev->dev.conf = conf_dev; co_debug("cobd%d: enabled (%p)", i, dev); co_monitor_block_register_device(cmon, i, (co_block_dev_t *)dev); dev->dev.free = free_file_blockdevice; } else { co_monitor_free(cmon, dev); co_debug_error("cobd%d: cannot enable (%08x)", i, (int)rc); goto error_1; } } for (i = 0; i < CO_MODULE_MAX_COFS; i++) { co_cofsdev_desc_t *desc = &cmon->config.cofs_devs[i]; if (!desc->enabled) continue; rc = co_monitor_file_system_init(cmon, i, desc); if (!CO_OK(rc)) goto error_2; } return rc;error_2: co_monitor_unregister_filesystems(cmon);error_1: co_monitor_unregister_and_free_block_devices(cmon); return rc;}static void timer_callback(void *data){ co_monitor_t *cmon = (co_monitor_t *)data; cmon->timer_interrupt = PTRUE; co_os_wait_wakeup(cmon->idle_wait);}static void free_pseudo_physical_memory(co_monitor_t *monitor){ int i, j; if (!monitor->pp_pfns) return; co_debug("freeing page frames for pseudo physical RAM"); for (i=0; i < PTRS_PER_PGD; i++) { if (!monitor->pp_pfns[i]) continue; for (j=0; j < PTRS_PER_PTE; j++) if (monitor->pp_pfns[i][j] != 0) co_os_put_page(monitor->manager, monitor->pp_pfns[i][j]); co_monitor_free(monitor, monitor->pp_pfns[i]); } co_monitor_free(monitor, monitor->pp_pfns); monitor->pp_pfns = NULL; co_debug("done freeing");}static co_rc_t alloc_pp_ram_mapping(co_monitor_t *monitor){ co_rc_t rc; unsigned long full_page_tables_size; unsigned long partial_page_table_size; co_debug("allocating page frames for pseudo physical RAM"); rc = co_monitor_malloc(monitor, sizeof(co_pfn_t *)*PTRS_PER_PGD, (void **)&monitor->pp_pfns); if (!CO_OK(rc)) return rc; co_memset(monitor->pp_pfns, 0, sizeof(co_pfn_t *)*PTRS_PER_PGD); full_page_tables_size = CO_ARCH_PAGE_SIZE * (monitor->memory_size >> CO_ARCH_PMD_SHIFT); partial_page_table_size = sizeof(unsigned long) * ((monitor->memory_size & ~CO_ARCH_PMD_MASK) >> (CO_ARCH_PAGE_SHIFT)); rc = co_monitor_scan_and_create_pfns( monitor, CO_VPTR_PSEUDO_RAM_PAGE_TABLES, full_page_tables_size); if (CO_OK(rc)) { if (partial_page_table_size) { rc = co_monitor_scan_and_create_pfns( monitor, CO_VPTR_PSEUDO_RAM_PAGE_TABLES + full_page_tables_size, partial_page_table_size); } } if (!CO_OK(rc)) { free_pseudo_physical_memory(monitor); } return rc;}static co_rc_t alloc_shared_page(co_monitor_t *cmon){ co_rc_t rc = CO_RC_OK; cmon->shared = co_os_alloc_pages(1); if (!cmon->shared) return CO_RC(ERROR); rc = co_os_userspace_map(cmon->shared, 1, &cmon->shared_user_address, &cmon->shared_handle); if (!CO_OK(rc)) { co_os_free_pages(cmon->shared, 1); return rc; } return rc;}static void free_shared_page(co_monitor_t *cmon){ if (cmon->shared_user_address) { co_os_userspace_unmap(cmon->shared_user_address, cmon->shared_handle, 1); } co_os_free_pages(cmon->shared, 1);}static co_rc_t load_section(co_monitor_t *cmon, co_monitor_ioctl_load_section_t *params){ co_rc_t rc = CO_RC(OK); if (cmon->state != CO_MONITOR_STATE_INITIALIZED) return CO_RC(ERROR); if (params->user_ptr) { co_debug("loading section at 0x%lx (0x%lx bytes)", params->address, params->size); rc = co_monitor_copy_region(cmon, params->address, params->size, params->buf); } else { rc = co_monitor_copy_region(cmon, params->address, params->size, NULL); } return rc;}static co_rc_t load_initrd(co_monitor_t *cmon, co_monitor_ioctl_load_initrd_t *params){ co_rc_t rc = CO_RC(OK); unsigned long address, pages; if (cmon->state != CO_MONITOR_STATE_INITIALIZED) return CO_RC(ERROR); pages = ((params->size + CO_ARCH_PAGE_SIZE) >> CO_ARCH_PAGE_SHIFT); /* * Put initrd at the end of the address space. */ address = CO_ARCH_KERNEL_OFFSET + cmon->memory_size - (pages << CO_ARCH_PAGE_SHIFT); co_debug("initrd address: %lx (0x%lx pages)", address, pages); if (address <= cmon->core_end + 0x100000) { co_debug_error("initrd is too close to the kernel code, not enough memory)"); /* We are too close to the kernel code, not enough memory */ return CO_RC(ERROR); } rc = co_monitor_copy_region(cmon, address, params->size, params->buf); if (!CO_OK(rc)) { co_debug_error("initrd copy failed (%x)", (int)rc); return rc; } cmon->initrd_address = address; cmon->initrd_size = params->size; return rc;}static co_rc_t start(co_monitor_t *cmon){ co_rc_t rc; co_boot_params_t *params; if (cmon->state != CO_MONITOR_STATE_INITIALIZED) { co_debug_error("invalid state"); return CO_RC(ERROR); } rc = guest_address_space_init(cmon); if (!CO_OK(rc)) { co_debug_error("error %08x initializing coLinux context", (int)rc); return rc; } co_os_get_timestamp_freq(&cmon->timestamp, &cmon->timestamp_freq); co_os_timer_activate(cmon->timer); co_passage_page->operation = CO_OPERATION_START; params = (co_boot_params_t *)co_passage_page->params; params->co_core_end = cmon->core_end; params->co_memory_size = cmon->memory_size; params->co_initrd = (void *)cmon->initrd_address; params->co_initrd_size = cmon->initrd_size; params->co_cpu_khz = co_os_get_cpu_khz(); co_memcpy(¶ms->co_boot_parameters, cmon->config.boot_parameters_line, sizeof(cmon->config.boot_parameters_line)); cmon->state = CO_MONITOR_STATE_STARTED; return CO_RC(OK);}static co_rc_t run(co_monitor_t *cmon, co_monitor_ioctl_run_t *params, unsigned long out_size, unsigned long *return_size)
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -