static long xenstore_setkey(char *key, char *val, size_t val_len) { uint32_t req_id, key_len, res, type; char *outbuf, *resbuf; /* convert our inputs into KEY0VAL */ key_len = strlen(key); outbuf = malloc(key_len + 1 + val_len); memcpy(outbuf, key, key_len); memcpy(outbuf + key_len + 1, val, val_len); outbuf[key_len] = 0; req_id = xenstore_write(XS_WRITE, key_len + 1 + val_len, outbuf); res = xenstore_read(req_id, &type, (void**)&resbuf); if(type == XS_ERROR) { printf("PROFILING: Error writing key |%s|: %s\n", key, resbuf); res = 0; } else if(type != XS_WRITE) { printf("PROFILING: Error writing key |%s|: %d\n", key, type); res = 0; } else res = 1; free(outbuf); free(resbuf); return res; }
static char *xenstore_getkey(char *key) { uint32_t req_id, type, len; char *res, *buffer; req_id = xenstore_write(XS_READ, strlen(key) + 1, key); len = xenstore_read(req_id, &type, (void**)&buffer); if(type == XS_ERROR) { printf("PROFILING: Error reading key |%s|: %s\n", key, buffer); free(buffer); return NULL; } if(type != XS_READ) { printf("PROFILING: Error reading key |%s|: %d\n", key, type); free(buffer); return NULL; } /* the Xenstore doesn't send back 0-terminated values on reads, so make our result zero terminated */ res = malloc(len + 1); memcpy(res, buffer, len); res[len] = 0; free(buffer); return res; }
/** * Fetch MAC address * * @v netfront Netfront device * @v hw_addr Hardware address to fill in * @ret rc Return status code */ static int netfront_read_mac ( struct netfront_nic *netfront, void *hw_addr ) { struct xen_device *xendev = netfront->xendev; struct xen_hypervisor *xen = xendev->xen; char *mac; int len; int rc; /* Fetch MAC address */ if ( ( rc = xenstore_read ( xen, &mac, xendev->key, "mac", NULL ) )!=0){ DBGC ( netfront, "NETFRONT %s could not read MAC address: %s\n", xendev->key, strerror ( rc ) ); goto err_xenstore_read; } DBGC2 ( netfront, "NETFRONT %s has MAC address \"%s\"\n", xendev->key, mac ); /* Decode MAC address */ len = hex_decode ( mac, ':', hw_addr, ETH_ALEN ); if ( len < 0 ) { rc = len; DBGC ( netfront, "NETFRONT %s could not decode MAC address " "\"%s\": %s\n", xendev->key, mac, strerror ( rc ) ); goto err_decode; } /* Success */ rc = 0; err_decode: free ( mac ); err_xenstore_read: return rc; }
static void print_xenstore_values(void) { const char *keys[] = { "device/vif/0/mac", "device/vif/0/handle", "device/vif/0/protocol", "device/vif/0/backend-id", "device/vif/0/state", "device/vif/0/backend", 0 }; //const char *keys[] = { "domid", // "name", // "memory/target", // "nonexistent", // "cpu/0/availability", // 0 }; char value[256]; printk("xenstore info:\r\n"); const char **pkeys = keys; while (*pkeys) { const char *key = *pkeys++; int r = xenstore_read(key, value, sizeof(value)); if (r == 0) printk(" [%s]=%s\r\n", key, value); else printk(" [%s] *** xenstore_read() returns %d\r\n", key, r); } }
int uuid_of_domid(char *buf, int domid) { char *path, *uuid; path = xenstore_read( "/local/domain/%d/vm", domid ); if (!path) { return 0; } uuid = xenstore_read( "%s/uuid", path ); if (!uuid) { free( path ); return 0; } free( path ); strncpy(buf, uuid, 64); free( uuid ); return 1; }
static int construct_passthrough_tables(unsigned long *table_ptrs, int nr_tables) { const char *s; uint8_t *acpi_pt_addr; uint32_t acpi_pt_length; struct acpi_header *header; int nr_added; int nr_max = (ACPI_MAX_SECONDARY_TABLES - nr_tables - 1); uint32_t total = 0; uint8_t *buffer; s = xenstore_read(HVM_XS_ACPI_PT_ADDRESS, NULL); if ( s == NULL ) return 0; acpi_pt_addr = (uint8_t*)(uint32_t)strtoll(s, NULL, 0); if ( acpi_pt_addr == NULL ) return 0; s = xenstore_read(HVM_XS_ACPI_PT_LENGTH, NULL); if ( s == NULL ) return 0; acpi_pt_length = (uint32_t)strtoll(s, NULL, 0); for ( nr_added = 0; nr_added < nr_max; nr_added++ ) { if ( (acpi_pt_length - total) < sizeof(struct acpi_header) ) break; header = (struct acpi_header*)acpi_pt_addr; buffer = mem_alloc(header->length, 16); if ( buffer == NULL ) break; memcpy(buffer, header, header->length); table_ptrs[nr_tables++] = (unsigned long)buffer; total += header->length; acpi_pt_addr += header->length; } return nr_added; }
void domain_read_uuid(struct domain *d) { char *tmp; if (!(tmp = xenstore_dom_read(d->domid, "vm"))) return; d->uuid = xenstore_read("%s/uuid", tmp); free(tmp); }
static void domain_active_adapter_node_watch(const char *path, void *opaque) { struct domain *d = opaque; char *buff = NULL; int i, disabled_surface = 0; char **whitelist_drivers = NULL; buff = xenstore_dom_read(d->domid, "switcher/have_gpu"); if (buff && strlen(buff) && strtol(buff, NULL, 0) == 1) goto out; whitelist_drivers = domain_get_whitelist_drivers(); buff = xenstore_read(path); if (!buff || strlen(buff) == 0) goto out; for (i = 0; whitelist_drivers[i]; ++i) { if (strcasestr(buff, whitelist_drivers[i])) break; } if (whitelist_drivers[i] == NULL) { /* Only disable the surface if it's not handled as a surfman VGPU * Take care of calling surfman only one */ if (d->vgpu_enabled == -1) com_citrix_xenclient_surfman_has_vgpu_(xcbus_conn, SURFMAN_SERVICE, SURFMAN_PATH, d->domid, &d->vgpu_enabled); if (!d->vgpu_enabled) disabled_surface = 1; } if (d->disabled_surface != disabled_surface) { d->disabled_surface = disabled_surface; if (d->disabled_surface) { /* Write "" to xenstore so the blanker will pic the best * resolution (nvidia pass through scenario). */ xenstore_dom_write(d->domid, "", "switcher/display_size"); } switcher_switch_graphic(disabled_surface ? domain_uivm() : 0, 0); } out: free(buff); }
static const struct bios_config *detect_bios(void) { const struct bios_info *b; const char *bios; bios = xenstore_read("hvmloader/bios", "rombios"); for ( b = &bios_configs[0]; b->key != NULL; b++ ) if ( !strcmp(bios, b->key) ) return b->bios; printf("Unknown BIOS %s, no ROM image found\n", bios); BUG(); return NULL; }
static void domain_calculate_abs_scaling(const char *path, void *opaque) { struct domain *d = opaque; char *buff = NULL; int xres = 0, yres = 0; if (d == NULL || path == NULL) return; d->rel_x_mult = MAX_MOUSE_ABS_X / DEFAULT_RESOLUTION_X; d->rel_y_mult = MAX_MOUSE_ABS_Y / DEFAULT_RESOLUTION_Y; buff = xenstore_read(path); if (!buff || strlen(buff) == 0) { info("No desktopDimensions node for domain %d", d->domid); /* These might have been previously set, so need to clear the value. */ d->desktop_xres = d->desktop_yres = 0; free(buff); return; } if ((sscanf(buff, "%d %d", &xres, &yres) != 2) || (xres <= 0) || (yres <= 0)) { info("Invalid desktopDimensions node for domain %d, value is %s", d->domid, buff); /* These might have been previously set, so need to clear the value. */ d->desktop_xres = d->desktop_yres = 0; free(buff); return; } info("Found valid desktopDimensions node for domain %d, xres is %d, yres is %d", d->domid, xres, yres); free(buff); d->rel_x_mult = (double) MAX_MOUSE_ABS_X / (double) xres; d->rel_y_mult = (double) MAX_MOUSE_ABS_Y / (double) yres; /* If the desktop dimensions have changed, need to adjust the mouse position. */ input_domain_handle_resolution_change(d, xres, yres); d->desktop_xres = xres; d->desktop_yres = yres; }
static void domain_power_state(const char *path, void *opaque) { struct domain *d = opaque; char *tmp = 0; int state = 0; if (!d) { error("No domain in switcher_power_state!\n"); return; } tmp = xenstore_read(path); if (!tmp || strlen(tmp) == 0) { free(tmp); return; } state = strtol(tmp, NULL, 10); free(tmp); info("domain id=%d power-state now %d",d->domid,state); if (state == 3) { info("domain id=%d entered s3",d->domid); d->is_in_s3 = 1; gettimeofday(&d->time_of_s3, NULL); /* If a domain goes to sleep, then reset its previous keyboard domain so that on wakeup, the domain itself will have the keyboard. */ info("reset previous keyboard domain for domain %d\n", d->domid); d->prev_keyb_domain_ptr = NULL; d->prev_keyb_domid = -1; /* If a domain goes to sleep, then reset the previous keyboard domain for all domains that have given the keyboard to this domain. */ reset_prev_keyb_domain(d); switcher_s3(d); } }
/** * Dump XenStore directory contents (for debugging) * * @v xen Xen hypervisor * @v key Key */ void xenstore_dump ( struct xen_hypervisor *xen, const char *key ) { char *value; char *children; char *child; char *child_key; size_t len; int rc; /* Try to dump current key as a value */ if ( ( rc = xenstore_read ( xen, &value, key, NULL ) ) == 0 ) { DBGC ( xen, "%s = \"%s\"\n", key, value ); free ( value ); } /* Try to recurse into each child in turn */ if ( ( rc = xenstore_directory ( xen, &children, &len, key, NULL ) ) == 0 ) { for ( child = children ; child < ( children + len ) ; child += ( strlen ( child ) + 1 /* NUL */ ) ) { /* Construct child key */ asprintf ( &child_key, "%s/%s", key, child ); if ( ! child_key ) { DBGC ( xen, "XENSTORE could not allocate child " "key \"%s/%s\"\n", key, child ); rc = -ENOMEM; break; } /* Recurse into child key, continuing on error */ xenstore_dump ( xen, child_key ); free ( child_key ); } free ( children ); } }
int main(void) { const struct bios_config *bios; int acpi_enabled; /* Initialise hypercall stubs with RET, rendering them no-ops. */ memset((void *)HYPERCALL_PHYSICAL_ADDRESS, 0xc3 /* RET */, PAGE_SIZE); printf("HVM Loader\n"); init_hypercalls(); xenbus_setup(); bios = detect_bios(); printf("System requested %s\n", bios->name); printf("CPU speed is %u MHz\n", get_cpu_mhz()); apic_setup(); pci_setup(); smp_initialise(); perform_tests(); if ( bios->bios_info_setup ) bios->bios_info_setup(); if ( bios->create_smbios_tables ) { printf("Writing SMBIOS tables ...\n"); bios->create_smbios_tables(); } printf("Loading %s ...\n", bios->name); if ( bios->bios_load ) bios->bios_load(bios); else { BUG_ON(bios->bios_address + bios->image_size > HVMLOADER_PHYSICAL_ADDRESS); memcpy((void *)bios->bios_address, bios->image, bios->image_size); } if ( (hvm_info->nr_vcpus > 1) || hvm_info->apic_mode ) { if ( bios->create_mp_tables ) bios->create_mp_tables(); if ( bios->create_pir_tables ) bios->create_pir_tables(); } if ( bios->load_roms ) bios->load_roms(); acpi_enabled = !strncmp(xenstore_read("platform/acpi", "1"), "1", 1); if ( acpi_enabled ) { init_vnuma_info(); if ( bios->acpi_build_tables ) { printf("Loading ACPI ...\n"); bios->acpi_build_tables(); } acpi_enable_sci(); hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 1); } init_vm86_tss(); cmos_write_memory_size(); printf("BIOS map:\n"); if ( SCRATCH_PHYSICAL_ADDRESS != scratch_start ) printf(" %05x-%05lx: Scratch space\n", SCRATCH_PHYSICAL_ADDRESS, scratch_start); printf(" %05x-%05x: Main BIOS\n", bios->bios_address, bios->bios_address + bios->image_size - 1); if ( bios->e820_setup ) bios->e820_setup(); if ( bios->bios_info_finish ) bios->bios_info_finish(); xenbus_shutdown(); printf("Invoking %s ...\n", bios->name); return 0; }
static void domain_command(const char *path, void *opaque) { struct domain *d = opaque; char *tmp; int slot; int domid; tmp = xenstore_read(path); if (!tmp) return; if (!*tmp) { free(tmp); return; } info("Command \"%s\", domid %d\n", tmp, d->domid); if (strcmp(tmp, "switch") == 0) { switcher_switch(d, 0, 0); } else if (sscanf(tmp, "switch slot %d", &slot) == 1) { struct domain *s = domain_with_slot(slot); if (!s) { error("slot %d doesn't exist", slot); return; } info("try to switch to slot %d", slot); switcher_switch(s, 0, 0); } else if (sscanf(tmp, "switch domid %d", &domid) == 1) { struct domain *s = domain_with(domid, &domid); if (!s) { error("domain %d doesn't exist", domid); return; } switcher_switch(s, 0, 0); } else if (strcmp("keyboard take", tmp) == 0) { input_give_keyboard(d); } else if (sscanf(tmp, "keyboard take %d", &domid) == 1) { struct domain *src_domain = domain_with(domid, &domid); if (!src_domain) { error("domain %d doesn't exist", domid); return; } input_give_keyboard_from_domain(src_domain, d); } else if (strcmp("keyboard release", tmp) == 0) { input_return_keyboard(d); } else if (sscanf(tmp, "keyboard release %d", &domid) == 1) { struct domain *dest_domain = domain_with(domid, &domid); if (!dest_domain) { error("domain %d doesn't exist", domid); return; } input_return_keyboard_to_domain(dest_domain, d); } xenstore_write("", path); free(tmp); }
FILE *profile_fopen(const char *fname, const char *mode) { char *key = NULL, *val = NULL, *rsp = NULL, *domStr = NULL, *diskname = NULL; uint32_t req, rsptype, rsplen, domId; XenStorePaths *xsp = NULL; uint64_t store_mptr; FILE *retval = NULL; int vallen; long res; if(strncmp(mode, "w", 1) != 0) goto fail; if(strncmp(fname, "HaLVM.prof", 11) == 0) diskname = "xvdp1"; if(strncmp(fname, "HaLVM.hp", 9) == 0) diskname = "xvdp2"; if(!diskname) goto fail; store_mptr = (uint64_t)system_start_info->store_mfn << 12; unmask_channel(system_start_info->store_evtchn); xsint = (struct xenstore_domain_interface*)machine_to_virtual(store_mptr); if(!xsint) { printf("PROFILING ERROR: Could not map XenStore page.\n"); goto fail; } /* Try to run "ls devices/vbd" */ req = xenstore_write(XS_DIRECTORY, strlen("device/vbd") + 1, "device/vbd"); rsplen = xenstore_read(req, &rsptype, (void**)&rsp); if(rsptype == XS_ERROR) { printf("PROFILING: XenStore read error. Did you forget to add a disk?\n"); goto fail; } if(rsptype != XS_DIRECTORY) { printf("PROFILING: XenStore has gone weird. Giving up.\n"); goto fail; } /* Find the XenStore paths associated with the disk we want */ xsp = find_xs_paths(diskname, rsp, rsplen); if(!xsp) { printf("PROFILING: Couldn't find file to open.\n"); goto fail; } /* Pull out the other's domId */ key = malloc(256); snprintf(key, 256, "%s/backend-id", xsp->feDir); domStr = xenstore_getkey(key); domId = atoi(domStr); /* allocate the return structure and buffers */ retval = malloc(sizeof(FILE)); if(!retval) goto fail; memset(retval, 0, sizeof(FILE)); retval->cur_block_num = 1; retval->block = runtime_alloc(NULL, 4096, PROT_READ|PROT_WRITE); if(!retval->block) goto fail; assert( (((uintptr_t)retval->block) & 4095) == 0 ); retval->ring.sring = runtime_alloc(NULL, 4096, PROT_READ|PROT_WRITE); if(!retval->ring.sring) goto fail; assert( (((uintptr_t)retval->ring.sring) & 4095) == 0 ); SHARED_RING_INIT(retval->ring.sring); FRONT_RING_INIT(&(retval->ring), retval->ring.sring, 4096); /* get the device handle */ snprintf(key, 256, "%s/virtual-device", xsp->feDir); val = xenstore_getkey(key); retval->disk_handle = atoi(val); /* allocate the grant references and event channel */ res = alloc_grant(domId, retval->ring.sring, 4096, 0, &retval->ring_grant); if(res) { printf("PROFILING: Failed to allocate ring grant reference: %d\n", res); goto fail; } res = alloc_grant(domId, retval->block, 4096, 0, &retval->block_grant); if(res) { printf("PROFILING: Failed to allocate block grant reference: %d\n", res); goto fail; } res = channel_alloc(DOMID_SELF, domId); if(res < 0) { printf("PROFILING: Failed to allocate grant reference: %d\n", res); goto fail; } retval->chan = (uint32_t)res; set_c_handler(retval->chan, handler); /* write them into our tree */ val = malloc(256); /* */ snprintf(key, 256, "%s/ring-ref", xsp->feDir); vallen = snprintf(val, 256, "%d", retval->ring_grant); if(!xenstore_setkey(key, val, vallen)) goto fail; /* */ snprintf(key, 256, "%s/event-channel", xsp->feDir); vallen = snprintf(val, 256, "%d", retval->chan); if(!xenstore_setkey(key, val, vallen)) goto fail; /* */ snprintf(key, 256, "%s/state", xsp->feDir); vallen = snprintf(val, 256, "%d", XenbusStateInitialised); if(!xenstore_setkey(key, val, vallen)) goto fail; /* wait for the other side to sync up */ do { char *state; runtime_block(1); snprintf(key, 256, "%s/state", xsp->beDir); state = xenstore_getkey(key); res = atoi(state); free(state); } while(res != XenbusStateConnected); /* write out that we're good */ /* */ snprintf(key, 256, "%s/state", xsp->feDir); vallen = snprintf(val, 256, "%d", XenbusStateConnected); if(!xenstore_setkey(key, val, vallen)) goto fail; return retval; fail: if(key) free(key); if(val) free(val); if(rsp) free(rsp); if(xsp) { free(xsp->feDir); free(xsp->beDir); free(xsp); } if(domStr) free(domStr); if(retval) { if(retval->block_grant) end_grant(retval->block_grant); if(retval->ring_grant) end_grant(retval->ring_grant); if(retval->block) runtime_free(retval->block, 4096); if(retval->ring.sring) runtime_free(retval->ring.sring, 4096); if(retval->chan) channel_close(retval->chan); free(retval); } errno = -EACCES; return NULL; }
// 从汇编阶段,进入C语言的阶段,传承了Unix的典型思想 // 汇编只负责引导和必要的硬件打交道的阶段 void start_ling(start_info_t *si) { //-------- init phase 1 -------- // //start_info包含的是xen的初始化信息 //是xen在启动GuestOS的时候,放在特定的地方 memcpy(&start_info, si, sizeof(*si)); phys_to_machine_mapping = (unsigned long *)start_info.mfn_list; HYPERVISOR_update_va_mapping((unsigned long)&shared_info, __pte(start_info.shared_info | 7), UVMF_INVLPG); HYPERVISOR_shared_info = &shared_info; //进行时钟初始化 time_init(); // sets start_of_day_wall_clock // use the time value to seed PRNG mt_seed(start_of_day_wall_clock); #if defined(__x86_64__) HYPERVISOR_set_callbacks(0, 0, 0); #else /* __x86_64__ */ HYPERVISOR_set_callbacks(0, 0, 0, 0); #endif mm_init(start_info.nr_pages, start_info.pt_base, start_info.nr_pt_frames); nalloc_init(); events_init(); grants_init(); console_init(mfn_to_virt(start_info.console.domU.mfn), start_info.console.domU.evtchn); xenstore_init(mfn_to_virt(start_info.store_mfn), start_info.store_evtchn); xenstore_read("name", my_domain_name, sizeof(my_domain_name)); //print_xenstore_values(); if (disk_vbd_is_present()) disk_init(); lwip_init(); netfe_init(); //-------- init phase 2 -------- // if (nalloc_no_memory()) fatal_error("init phase 2: no memory"); sys_stats_init(); atoms_init(); embed_init(); code_base_init(); scheduler_init(); ets_init(); pcre_init(); counters_init(); //print_start_info(); //print_xenmem_info(); //run_alloc_tests(); //run_mm_tests(); //print_xenstore_values(); //run_bignum_tests(); //printk("\r\nLing %s is here\r\n", quote_and_expand(LING_VER)); proc_main(0); // preliminary run spawn_init_start(start_info.cmd_line); //while (1) // HYPERVISOR_sched_op(SCHEDOP_block, 0); /* UNREACHABLE */ }
int clickos_start(int domid, const char *name, const char *script) { const char *clickos_config_path_tail = "/config/"; char clickos_script_chunk[1501]; char *clickos_root_path = NULL; char *clickos_elem_path = NULL; char *clickos_ctl_path = NULL; char *clickos_config_name_path = NULL; char *clickos_config_path = NULL; char *clickos_status_path = NULL; char *clickos_router_path = NULL; int clickos_config_id = 0; default_domain_perms.id = domid; default_domain_perms.perms = XS_PERM_READ | XS_PERM_WRITE; if (!xs) { xenstore_init(domid); } retry_clickos: // Transaction for ClickOS th = xs_transaction_start(xs); asprintf(&domain_root_path, "/local/domain/%d", domid); do { asprintf(&clickos_root_path, "%s/clickos/%d", domain_root_path, clickos_config_id); clickos_router_path = xenstore_read(clickos_root_path); if (clickos_router_path) clickos_config_id++; } while (clickos_router_path != NULL); asprintf(&clickos_elem_path, "%s/elements", clickos_root_path); asprintf(&clickos_ctl_path, "%s/control", clickos_root_path); asprintf(&clickos_config_name_path, "%s/config_name", clickos_root_path); asprintf(&clickos_status_path, "%s/status", clickos_root_path); xenstore_write(clickos_elem_path, ""); xenstore_write(clickos_ctl_path, ""); xenstore_chmod(clickos_elem_path, &default_domain_perms); xenstore_chmod(clickos_ctl_path, &default_domain_perms); xenstore_write(clickos_config_name_path, name); // we need one character for each chunk int config_path_len = strlen(clickos_root_path) + strlen(clickos_config_path_tail) + 1; clickos_config_path = malloc(config_path_len + 1); int chunk = 0; int scriptSize = strlen(script); int remainingScriptSize = scriptSize; do { snprintf(clickos_config_path, config_path_len + 1, "%s%s%d", clickos_root_path, clickos_config_path_tail, chunk); int chunkSize = MAX_CHUNK_LENGTH; if (remainingScriptSize < MAX_CHUNK_LENGTH) { chunkSize = remainingScriptSize; } memcpy(clickos_script_chunk, script + (chunk * MAX_CHUNK_LENGTH), chunkSize); clickos_script_chunk[chunkSize] = '\0'; xenstore_write(clickos_config_path, clickos_script_chunk); chunk++; remainingScriptSize -= chunkSize; } while (remainingScriptSize > 0); if (!xs_transaction_end(xs, th, 0)) { if (errno == EAGAIN) goto retry_clickos; } retry_status: // Transaction for ClickOS state th = xs_transaction_start(xs); xenstore_write(clickos_status_path, "Running"); if (!xs_transaction_end(xs, th, 0)) { if (errno == EAGAIN) goto retry_status; } return 0; }
int main(void) { const struct bios_config *bios; int acpi_enabled; const struct hvm_modlist_entry *bios_module; /* Initialise hypercall stubs with RET, rendering them no-ops. */ memset((void *)HYPERCALL_PHYSICAL_ADDRESS, 0xc3 /* RET */, PAGE_SIZE); printf("HVM Loader\n"); BUG_ON(hvm_start_info->magic != XEN_HVM_START_MAGIC_VALUE); init_hypercalls(); memory_map_setup(); xenbus_setup(); bios = detect_bios(); printf("System requested %s\n", bios->name); printf("CPU speed is %u MHz\n", get_cpu_mhz()); apic_setup(); pci_setup(); smp_initialise(); perform_tests(); if ( bios->bios_info_setup ) bios->bios_info_setup(); if ( bios->create_smbios_tables ) { printf("Writing SMBIOS tables ...\n"); bios->create_smbios_tables(); } printf("Loading %s ...\n", bios->name); bios_module = get_module_entry(hvm_start_info, "firmware"); if ( bios_module ) { uint32_t paddr = bios_module->paddr; bios->bios_load(bios, (void*)paddr, bios_module->size); } #ifdef ENABLE_ROMBIOS else if ( bios == &rombios_config ) { bios->bios_load(bios, NULL, 0); } #endif else { /* * If there is no BIOS module supplied and if there is no embeded BIOS * image, then we failed. Only rombios might have an embedded bios blob. */ printf("no BIOS ROM image found\n"); BUG(); } if ( (hvm_info->nr_vcpus > 1) || hvm_info->apic_mode ) { if ( bios->create_mp_tables ) bios->create_mp_tables(); if ( bios->create_pir_tables ) bios->create_pir_tables(); } if ( bios->load_roms ) bios->load_roms(); acpi_enabled = !strncmp(xenstore_read("platform/acpi", "1"), "1", 1); if ( acpi_enabled ) { init_vnuma_info(); if ( bios->acpi_build_tables ) { printf("Loading ACPI ...\n"); bios->acpi_build_tables(); } acpi_enable_sci(); hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 1); } init_vm86_tss(); cmos_write_memory_size(); printf("BIOS map:\n"); if ( SCRATCH_PHYSICAL_ADDRESS != scratch_start ) printf(" %05x-%05lx: Scratch space\n", SCRATCH_PHYSICAL_ADDRESS, scratch_start); printf(" %05x-%05x: Main BIOS\n", bios->bios_address, bios->bios_address + bios->image_size - 1); if ( bios->e820_setup ) bios->e820_setup(); if ( bios->bios_info_finish ) bios->bios_info_finish(); xenbus_shutdown(); printf("Invoking %s ...\n", bios->name); return 0; }
static int construct_secondary_tables(unsigned long *table_ptrs, struct acpi_info *info) { int nr_tables = 0; struct acpi_20_madt *madt; struct acpi_20_hpet *hpet; struct acpi_20_waet *waet; struct acpi_20_tcpa *tcpa; unsigned char *ssdt; static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001}; uint16_t *tis_hdr; void *lasa; /* MADT. */ if ( (hvm_info->nr_vcpus > 1) || hvm_info->apic_mode ) { madt = construct_madt(info); if (!madt) return -1; table_ptrs[nr_tables++] = (unsigned long)madt; } /* HPET. */ if ( hpet_exists(ACPI_HPET_ADDRESS) ) { hpet = construct_hpet(); if (!hpet) return -1; table_ptrs[nr_tables++] = (unsigned long)hpet; } /* WAET. */ waet = construct_waet(); if (!waet) return -1; table_ptrs[nr_tables++] = (unsigned long)waet; if ( battery_port_exists() ) { ssdt = mem_alloc(sizeof(ssdt_pm), 16); if (!ssdt) return -1; memcpy(ssdt, ssdt_pm, sizeof(ssdt_pm)); table_ptrs[nr_tables++] = (unsigned long)ssdt; } if ( !strncmp(xenstore_read("platform/acpi_s3", "1"), "1", 1) ) { ssdt = mem_alloc(sizeof(ssdt_s3), 16); if (!ssdt) return -1; memcpy(ssdt, ssdt_s3, sizeof(ssdt_s3)); table_ptrs[nr_tables++] = (unsigned long)ssdt; } else { printf("S3 disabled\n"); } if ( !strncmp(xenstore_read("platform/acpi_s4", "1"), "1", 1) ) { ssdt = mem_alloc(sizeof(ssdt_s4), 16); if (!ssdt) return -1; memcpy(ssdt, ssdt_s4, sizeof(ssdt_s4)); table_ptrs[nr_tables++] = (unsigned long)ssdt; } else { printf("S4 disabled\n"); } /* TPM TCPA and SSDT. */ tis_hdr = (uint16_t *)0xFED40F00; if ( (tis_hdr[0] == tis_signature[0]) && (tis_hdr[1] == tis_signature[1]) && (tis_hdr[2] == tis_signature[2]) ) { ssdt = mem_alloc(sizeof(ssdt_tpm), 16); if (!ssdt) return -1; memcpy(ssdt, ssdt_tpm, sizeof(ssdt_tpm)); table_ptrs[nr_tables++] = (unsigned long)ssdt; tcpa = mem_alloc(sizeof(struct acpi_20_tcpa), 16); if (!tcpa) return -1; memset(tcpa, 0, sizeof(*tcpa)); table_ptrs[nr_tables++] = (unsigned long)tcpa; tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE; tcpa->header.length = sizeof(*tcpa); tcpa->header.revision = ACPI_2_0_TCPA_REVISION; fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID); fixed_strcpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID); tcpa->header.oem_revision = ACPI_OEM_REVISION; tcpa->header.creator_id = ACPI_CREATOR_ID; tcpa->header.creator_revision = ACPI_CREATOR_REVISION; if ( (lasa = mem_alloc(ACPI_2_0_TCPA_LAML_SIZE, 16)) != NULL ) { tcpa->lasa = virt_to_phys(lasa); tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE; memset(lasa, 0, tcpa->laml); set_checksum(tcpa, offsetof(struct acpi_header, checksum), tcpa->header.length); }
void netfe_init(void) { int index = 0; netfe_t **link = &net_front_ends; while (1) { int n; char xs_key[256]; snprintf(xs_key, sizeof(xs_key), "device/vif/%d/backend-id", index); int rs = xenstore_read_int(&n, xs_key); if (rs != 0) break; // FE/(index) is present domid_t backend_id = (domid_t)n; netfe_t *fe = (netfe_t *)mm_alloc_pages(PSIZE(sizeof(netfe_t))); memset(fe, 0, sizeof(*fe)); // setup shared rings fe->rxs = (netif_rx_sring_t *)mm_alloc_page(); assert(fe->rxs != 0); fe->txs = (netif_tx_sring_t *)mm_alloc_page(); assert(fe->txs != 0); SHARED_RING_INIT(fe->rxs); SHARED_RING_INIT(fe->txs); FRONT_RING_INIT(&fe->rx_ring, fe->rxs, PAGE_SIZE); FRONT_RING_INIT(&fe->tx_ring, fe->txs, PAGE_SIZE); grants_allow_access(&fe->rx_ref, backend_id, virt_to_mfn(fe->rxs)); grants_allow_access(&fe->tx_ref, backend_id, virt_to_mfn(fe->txs)); // set up receive buffers for (int i = 0; i < NR_RX_BUFFERS; i++) { fe->rx_buffers[i] = mm_alloc_page(); assert(fe->rx_buffers[i] != 0); unsigned long mfn = virt_to_mfn(fe->rx_buffers[i]); grants_allow_access(&fe->rx_buf_refs[i], backend_id, mfn); } // set up send buffers fe->free_tx_head = NO_TX_BUFFER; for (int i = 0; i < NR_TX_BUFFERS; i++) { fe->tx_buffers[i] = mm_alloc_page(); assert(fe->tx_buffers[i] != 0); unsigned long mfn = virt_to_mfn(fe->tx_buffers[i]); grants_allow_access(&fe->tx_buf_refs[i], backend_id, mfn); fe->free_tx_bufs[i] = fe->free_tx_head; fe->free_tx_head = i; } // set up interrupt fe->evtchn = event_alloc_unbound(backend_id); event_bind(fe->evtchn, netfe_int, (void *)fe); snprintf(xs_key, sizeof(xs_key), "device/vif/%d/rx-ring-ref", index); rs = xenstore_write_uint(xs_key, fe->rx_ref); assert(rs == 0); snprintf(xs_key, sizeof(xs_key), "device/vif/%d/tx-ring-ref", index); rs = xenstore_write_uint(xs_key, fe->tx_ref); assert(rs == 0); snprintf(xs_key, sizeof(xs_key), "device/vif/%d/event-channel", index); rs = xenstore_write_uint(xs_key, fe->evtchn); assert(rs == 0); snprintf(xs_key, sizeof(xs_key), "device/vif/%d/request-rx-copy", index); rs = xenstore_write(xs_key, "1"); assert(rs == 0); snprintf(xs_key, sizeof(xs_key), "device/vif/%d/feature-no-csum-offload", index); rs = xenstore_write(xs_key, "1"); assert(rs == 0); snprintf(xs_key, sizeof(xs_key), "device/vif/%d/feature-rx-notify", index); rs = xenstore_write(xs_key, "1"); assert(rs == 0); snprintf(xs_key, sizeof(xs_key), "device/vif/%d/state", index); rs = xenstore_write(xs_key, "4"); // XenbusStateConnected assert(rs == 0); // read MAC address char buf[64]; snprintf(xs_key, sizeof(xs_key), "device/vif/%d/mac", index); rs = xenstore_read(xs_key, buf, sizeof(buf)); assert(rs == 0); rs = parse_mac(buf, fe->mac); assert(rs == 0); fe->mac_len = ETH_ALEN; printk("\reth%d: MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", index, fe->mac[0], fe->mac[1], fe->mac[2], fe->mac[3], fe->mac[4], fe->mac[5]); // // Publish EXT_RX_BUFFERS requests only and replenish then to this number // during each interrupt handler invocation. // for (int i = 0; i < EXT_RX_BUFFERS; i++) { netif_rx_request_t *req = RING_GET_REQUEST(&fe->rx_ring, fe->rx_ring.req_prod_pvt); req->id = i; //rx_id++; req->gref = fe->rx_buf_refs[i]; fe->rx_ring.req_prod_pvt++; } RING_PUSH_REQUESTS(&fe->rx_ring); event_kick(fe->evtchn); fe->index = index++; //fe->next = 0; //fe->attached_lwip_netif = 0; //fe->attached_outlet = 0; // add to net_front_ends list *link = fe; link = &fe->next; } num_net_front_ends = index; }