int grant_gntalloc_mbuf_pool(struct rte_mempool *mpool, uint32_t pg_num, uint32_t *gref_arr, phys_addr_t *pa_arr, int mempool_idx) { char key_str[PATH_MAX] = {0}; char val_str[PATH_MAX] = {0}; void *mempool_obj_va; if (grant_node_create(pg_num, gref_arr, pa_arr, val_str, sizeof(val_str))) { return -1; } if (snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"MEMPOOL_XENSTORE_STR, mempool_idx) == -1) return -1; if (xenstore_write(key_str, val_str) == -1) return -1; if (snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"MEMPOOL_VA_XENSTORE_STR, mempool_idx) == -1) return -1; if (mpool->nb_mem_chunks != 1) { RTE_LOG(ERR, PMD, "mempool with more than 1 chunk is not supported\n"); return -1; } mempool_obj_va = STAILQ_FIRST(&mpool->mem_list)->addr; if (snprintf(val_str, sizeof(val_str), "%"PRIxPTR, (uintptr_t)mempool_obj_va) == -1) return -1; if (xenstore_write(key_str, val_str) == -1) return -1; return 0; }
//Exactly what it says on the tin. void write_battery_info_to_xenstore(unsigned int battery_index) { if (battery_slot_exists(battery_index) == NO || battery_index >= num_battery_structs_allocd) { xcpmd_log(LOG_INFO, "Detected removal of battery slot %d in info.\n", battery_index); cleanup_removed_battery(battery_index); return; } struct battery_info * info; char bif[1024], string_info[256], xenstore_path[128]; info = &last_info[battery_index]; memset(bif, 0, 1024); memset(string_info, 0, 256); // write 9 dwords (so 9*4) + length of 4 strings + 4 null terminators snprintf(bif, 3, "%02x", (unsigned int)(9*4 + strlen(info->model_number) + strlen(info->serial_number) + strlen(info->battery_type) + strlen(info->oem_info) + 4)); write_ulong_lsb_first(bif+2, info->power_unit); write_ulong_lsb_first(bif+10, info->design_capacity); write_ulong_lsb_first(bif+18, info->last_full_capacity); write_ulong_lsb_first(bif+26, info->battery_technology); write_ulong_lsb_first(bif+34, info->design_voltage); write_ulong_lsb_first(bif+42, info->design_capacity_warning); write_ulong_lsb_first(bif+50, info->design_capacity_low); write_ulong_lsb_first(bif+58, info->capacity_granularity_1); write_ulong_lsb_first(bif+66, info->capacity_granularity_2); snprintf(string_info, 256, "%02x%s%02x%s%02x%s%02x%s", (unsigned int)strlen(info->model_number), info->model_number, (unsigned int)strlen(info->serial_number), info->serial_number, (unsigned int)strlen(info->battery_type), info->battery_type, (unsigned int)strlen(info->oem_info), info->oem_info); strncat(bif+73, string_info, 1024-73-1); //Ensure the directory exists before trying to write the leaves make_xenstore_battery_dir(battery_index); //Now write the leaves. snprintf(xenstore_path, 255, "%s%i/%s", XS_BATTERY_PATH, battery_index, XS_BIF_LEAF); xenstore_write(bif, xenstore_path); //Here for compatibility--will be removed eventually if (battery_index == 0) xenstore_write(bif, XS_BIF); else xenstore_write(bif, XS_BIF1); }
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; }
int domain_setup(struct domain *d) { int rc; /* Allocate/Store the domain UUID in /struct domain/. */ domain_read_uuid(d); /* xc_getphysinfo to check if this domain is PV or HVM. */ domain_read_is_pv_domain(d); /* Assign the slot passed by the toostack through Xenstore to this domain. * - Slot read from /vm/<uuid>/slot (uuid needs to be known beforehand) * - Also setup relevant nodes in XenStore to manage that slot. */ rc = domain_assign_slot(d); if (rc) return rc; /* Slot 0 (UIVM) special case. * XXX: Stuff in here might be deprecated... */ if (d->slot == 0) { char path[128], perm[128]; xenstore_dom_write(d->domid, "http://1.0.0.0/auth.html", "login/url"); xenstore_dom_write(d->domid, "3", "login/state"); sprintf(perm, "n%d", d->domid); sprintf(path, "/local/domain/%d/report/state", d->domid); xenstore_write_int(3, path); xenstore_chmod(perm, 1, path); sprintf(path, "/local/domain/%d/report/url", d->domid); xenstore_write("http://1.0.0.0/create_report.html", path); xenstore_chmod(perm, 1, path); } /* Watch on node attr/desktopDimensions for resize events? * XXX: Isn't that HVM/Windows only ? */ if (!xenstore_dom_watch(d->domid, domain_calculate_abs_scaling, d, "attr/desktopDimensions")) warning("%s: Could not setup xenstore watch on switcher/command." " Slot will be static.", __func__); /* Handle PM events. * Setup watch on Xenstore node <dompath>/power-state. */ if (!xenstore_dom_watch(d->domid, domain_power_state, d, "power-state")) warning("%s: Could not setup xenstore watch on power-state." " Power-management event will not be handled properly.", __func__); domain_power_state("power-state", d); /* Initialise display position for mouse switching. * XXX: Uses <dompath>/switcher/<slot>/{left,right} and talks with * xenvm over dbus. */ domain_mouse_switch_config(d); d->initialised = true; return 0; }
char* clickos_read_handler(int domid, char *elem, char *attr) { char *ctrlpath = NULL, *elempath = NULL; char *rpath = NULL, *wpath = NULL; char *value; int err; unsigned int len = 0; struct pollfd fds[1]; if (!xs) { xenstore_init(domid); } asprintf(&ctrlpath, "/local/domain/%d/clickos/0/control", domid); asprintf(&elempath, "/local/domain/%d/clickos/0/elements", domid); asprintf(&wpath, "%s/read/%s/%s", ctrlpath, elem, attr); asprintf(&rpath, "%s/%s/%s", elempath, elem, attr); th = xs_transaction_start(xs); xenstore_write(wpath, " "); xs_transaction_end(xs, th, 0); err = xs_watch(xs, rpath, "lock"); if (!err) { printf("Error setting a watch\n"); return NULL; } fds[0].fd = xs_fileno(xs); fds[0].events = (POLLIN); while (len <= 0) { if (poll(fds, 1, 1000) <= 0) { continue; } retry_wh: th = xs_transaction_start(xs); //value = xenstore_read(rpath); value = xs_read(xs, XBT_NULL, rpath, &len); //printf("read: len %d value %s\n", len, value); if (!xs_transaction_end(xs, th, 0)) { if (errno == EAGAIN) goto retry_wh; } usleep(5000); } err = xs_unwatch(xs, rpath, "lock"); th = xs_transaction_start(xs); xs_write(xs, th, rpath, "", 0); err = xs_transaction_end(xs, th, 0); return value; }
//Remove a battery's entries from the xenstore. static void cleanup_removed_battery(unsigned int battery_index) { char path[256]; snprintf(path, 255, "%s%d", XS_BATTERY_PATH, battery_index); xenstore_rm(path); if (battery_index > 0) { xenstore_rm(XS_BST1); xenstore_rm(XS_BIF1); } else { xenstore_rm(XS_BST); xenstore_rm(XS_BIF); } if (get_num_batteries_present() == 0) xenstore_write("0", XS_BATTERY_PRESENT); else xenstore_write("1", XS_BATTERY_PRESENT); }
char* clickos_write_handler(int domid, char *elem, char *attr, char *value) { char *elempath = NULL; char *wpath = NULL; if (!xs) { xenstore_init(domid); } asprintf(&elempath, "/local/domain/%d/clickos/0/elements", domid); asprintf(&wpath, "%s/%s/%s", elempath, elem, attr); xenstore_write(wpath, value); return 0; }
int clickos_stop(int domid, int configid) { char *statuspath = NULL; if (!xs) { xenstore_init(domid); } asprintf(&statuspath, "/local/domain/%d/clickos/%d/status", domid, configid); retry_stop: th = xs_transaction_start(xs); xenstore_write(statuspath, "Halted"); if (!xs_transaction_end(xs, th, 0)) { if (errno == EAGAIN) goto retry_stop; } return 0; }
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; }
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; }
//Updates status and info of all batteries locally and in the xenstore. void update_batteries(void) { struct battery_status *old_status = NULL; struct battery_info *old_info = NULL; char path[256]; unsigned int old_num_batteries = 0; unsigned int num_batteries = 0; unsigned int i, new_array_size, old_array_size, num_batteries_to_update; bool present_batteries_changed = false; if ( pm_specs & PM_SPEC_NO_BATTERIES ) return; //Keep a copy of what the battery status/info used to be. old_status = (struct battery_status *)malloc(num_battery_structs_allocd * sizeof(struct battery_status)); old_info = (struct battery_info *)malloc(num_battery_structs_allocd * sizeof(struct battery_info)); if (last_status != NULL) memcpy(old_status, last_status, num_battery_structs_allocd * sizeof(struct battery_status)); else memset(old_status, 0, num_battery_structs_allocd * sizeof(struct battery_status)); if (last_info != NULL) memcpy(old_info, last_info, num_battery_structs_allocd * sizeof(struct battery_info)); else memset(old_info, 0, num_battery_structs_allocd * sizeof(struct battery_info)); old_array_size = num_battery_structs_allocd; //Resize the arrays if necessary. new_array_size = (unsigned int)(get_max_battery_index() + 1); if (new_array_size != old_array_size) { if (new_array_size == 0) { xcpmd_log(LOG_INFO, "All batteries removed.\n"); free(last_info); free(last_status); } else { last_info = (struct battery_info *)realloc(last_info, new_array_size * sizeof(struct battery_info)); last_status = (struct battery_status *)realloc(last_status, new_array_size * sizeof(struct battery_status)); memset(last_info, 0, new_array_size * sizeof(struct battery_info)); memset(last_status, 0, new_array_size * sizeof(struct battery_status)); } num_battery_structs_allocd = new_array_size; } num_batteries_to_update = (new_array_size > old_array_size) ? new_array_size : old_array_size; //Updating all status/info before writing to the xenstore prevents bad //calculations of aggregate data (e.g., warning level). for (i=0; i < num_batteries_to_update; ++i) { update_battery_status(i); update_battery_info(i); } //Write back to the xenstore and only send notifications if things have changed. for (i=0; i < num_batteries_to_update; ++i) { //No need to update status/info in Xenstore if there was no battery to begin with. // On some latops, batteries index are not contiguous. It is not a big // deal to have one or two empty array slot, but it should not be // reported as a removed battery (OXT-614). if (last_status[i].present || old_status[i].present) { write_battery_status_to_xenstore(i); write_battery_info_to_xenstore(i); } if (i < old_array_size && i < new_array_size) { if (memcmp(&old_info[i], &last_info[i], sizeof(struct battery_info))) { snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF); xenstore_write("1", path); } if (memcmp(&old_status[i], &last_status[i], sizeof(struct battery_status))) { snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF); xenstore_write("1", path); } if (old_status[i].present == YES) ++old_num_batteries; if (last_status[i].present == YES) ++num_batteries; if (old_status[i].present != last_status[i].present) present_batteries_changed = true; } else if (new_array_size > old_array_size) { //a battery has been added snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF); xenstore_write("1", path); snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF); xenstore_write("1", path); if (last_status[i].present == YES) ++num_batteries; if (i < old_array_size) { if (old_status[i].present != last_status[i].present) present_batteries_changed = true; } else { if (last_status[i].present == YES) present_batteries_changed = true; } } else if (new_array_size < old_array_size) { //a battery has been removed snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF); xenstore_write("1", path); snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF); xenstore_write("1", path); if (old_status[i].present == YES) ++old_num_batteries; if (i < new_array_size) { if (old_status[i].present != last_status[i].present) present_batteries_changed = true; } else { if (old_status[i].present == YES) present_batteries_changed = true; } } } if ((old_array_size != new_array_size) || (memcmp(old_info, last_info, new_array_size * sizeof(struct battery_info)))) { notify_com_citrix_xenclient_xcpmd_battery_info_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH); } if ((old_array_size != new_array_size) || (memcmp(old_status, last_status, new_array_size * sizeof(struct battery_status)))) { //Here for compatibility--should eventually be removed xenstore_write("1", XS_BATTERY_STATUS_CHANGE_EVENT_PATH); notify_com_citrix_xenclient_xcpmd_battery_status_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH); } if (present_batteries_changed) { notify_com_citrix_xenclient_xcpmd_num_batteries_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH); } free(old_info); free(old_status); }
//Exactly what it says on the tin. void write_battery_status_to_xenstore(unsigned int battery_index) { struct battery_status * status; char bst[35], xenstore_path[128]; int num_batteries, current_battery_level; if (battery_index >= num_battery_structs_allocd) { cleanup_removed_battery(battery_index); } num_batteries = get_num_batteries_present(); if (num_batteries == 0) { xenstore_write("0", XS_BATTERY_PRESENT); return; } else { xenstore_write("1", XS_BATTERY_PRESENT); } status = &last_status[battery_index]; //Delete the BST and reset the "present" flag if the battery is not currently present. if (status->present != YES) { snprintf(xenstore_path, 255, "%s%i/%s", XS_BATTERY_PATH, battery_index, XS_BST_LEAF); xenstore_rm(xenstore_path); snprintf(xenstore_path, 255, "%s%i/%s", XS_BATTERY_PATH, battery_index, XS_BATTERY_PRESENT_LEAF); xenstore_write("0", xenstore_path); return; } //Build the BST structure. memset(bst, 0, 35); snprintf(bst, 3, "%02x", 16); write_ulong_lsb_first(bst+2, status->state); write_ulong_lsb_first(bst+10, status->present_rate); write_ulong_lsb_first(bst+18, status->remaining_capacity); write_ulong_lsb_first(bst+26, status->present_voltage); //Ensure the directory exists before trying to write the leaves make_xenstore_battery_dir(battery_index); //Now write the leaves. snprintf(xenstore_path, 255, XS_BATTERY_PATH "%i/" XS_BST_LEAF, battery_index); xenstore_write(bst, xenstore_path); snprintf(xenstore_path, 255, "%s%i/%s", XS_BATTERY_PATH, battery_index, XS_BATTERY_PRESENT_LEAF); xenstore_write("1", xenstore_path); //Here for compatibility--will be removed eventually if (battery_index == 0) xenstore_write(bst, XS_BST); else xenstore_write(bst, XS_BST1); current_battery_level = get_current_battery_level(); if (current_battery_level == NORMAL || get_ac_adapter_status() == ON_AC) xenstore_rm(XS_CURRENT_BATTERY_LEVEL); else { xenstore_write_int(current_battery_level, XS_CURRENT_BATTERY_LEVEL); notify_com_citrix_xenclient_xcpmd_battery_level_notification(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH); xcpmd_log(LOG_ALERT, "Battery level below normal - %d!\n", current_battery_level); } #ifdef XCPMD_DEBUG xcpmd_log(LOG_DEBUG, "~Updated battery information in xenstore\n"); #endif }
static void switcher_domid(struct domain *d, uint32_t domid) { char perm[8]; char path[64]; char perms[128]; char *tmp = 0; int stubdom_domid; int slot; struct domain *d_pvm; if (domain_with(domid,&domid)) { error("domain %d already exists", domid); return; } d->domid = domid; domain_read_uuid(d); domain_read_is_pv_domain(d); slot = domain_read_slot(d); // Ensures that no "zombie" domains are taking up valuable switcher slots. // Ideally, this shouldn't be necessary-- but in development environments // it's possible for interesting things to happen (e.g. for a developer to // destroy a stub-domain without giving us notice of the termination.) // This safeguard function isn't strictly neccessary, but it's lightweight // and prevents some awful behavior (including huge delays) if developers do // manage to do fun things like kernel panic their stubdomains. if(slot_occupied_by_dead_domain(slot)) { warning("slot %d is held by a dead domain; cleaning up", slot); domain_gone(domain_with(slot, &slot)); } if (domain_with(slot,&slot) || (slot == -1)) { error("slot %d already taken (wanted by domain %d)",slot,domid); return; } d->slot = slot; info("New domain %d (slot %d)", domid, slot); /* init xenstore nodes and permissions for midori secure window and status report */ if (slot == 0) { xenstore_dom_write(domid, "http://1.0.0.0/auth.html", "login/url"); xenstore_dom_write(domid, "3", "login/state"); sprintf(perm, "n%d", domid); sprintf(path, "/local/domain/%d/report/state", domid); xenstore_write_int(3, path); xenstore_chmod(perm, 1, path); sprintf(path, "/local/domain/%d/report/url", domid); xenstore_write("http://1.0.0.0/create_report.html", path); xenstore_chmod (perm, 1, path); } xenstore_dom_write(domid, "", "switcher/command"); sprintf(perms, "r%d", domid); xenstore_dom_chmod(domid, perms, 1, "switcher/command"); if (!xenstore_dom_watch(domid, domain_command, d, "switcher/command")) warning("failed to install xenstore watch! switcher/command"); d->rel_x_mult = MAX_MOUSE_ABS_X / DEFAULT_RESOLUTION_X; d->rel_y_mult = MAX_MOUSE_ABS_Y / DEFAULT_RESOLUTION_Y; d->desktop_xres = d->desktop_yres = 0; if (!xenstore_dom_watch(d->domid, domain_calculate_abs_scaling, d, "attr/desktopDimensions")) warning("failed to install xenstore watch! attr/desktopDimensions"); d->is_pvm = 0; d->keyboard_led_code = 0; xenstore_dom_write_int(d->domid, 0, "switcher/have_gpu"); if (!xenstore_dom_watch(domid, domain_power_state, d, "power-state")) warning("failed to install xenstore watch! power-state"); domain_power_state("power-state",d); d_pvm = domain_with(is_pvm, &one); domain_surface_disabled_detect_init(d); xen_vkbd_backend_create(d); domain_read_has_secondary_gpu(d); domain_mouse_switch_config(d); focus_update_domain(d); /* call our callbacks*/ struct callbacklist* c = domainstart_callback; while (c) { c->callback(d); c = c->next; } /* we are ready to receive switch commands for this domain */ xenstore_dom_write(domid, "true", "switcher/ready"); }
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); }
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; }