/* Mapping a segment is a four step process: * (1) xemem_get/attach the seg into our aspace * (2) invoke aspace_virt_to_phys on the attached region to generate a page * frame list * (3) invoke aspace_map_region on the target region in the target * aspace * (4) detach the xemem attachment (hold onto the apid) */ static int __map_hio_segment(hio_segment_t * seg, id_t aspace_id) { xemem_apid_t apid; void * local_attach; uint32_t nr_pages, page_size, i, j; int status; if (aspace_id == MY_ID) aspace_get_myid(&aspace_id); /* (1) xemem get/attach */ { struct xemem_addr addr; apid = xemem_get(seg->segid, XEMEM_RDWR); if (apid == -1) { printf("Could not get xemem segid %li\n", seg->segid); return -1; } addr.apid = apid; addr.offset = 0; local_attach = xemem_attach(addr, seg->size, NULL); if (local_attach == MAP_FAILED) { printf("Could not attach xemem apid %li (%s)\n", addr.apid, strerror(errno)); goto out_attach; } } /* (2) figure out the pfns and (3) map them to the target aspace */ { vaddr_t local_vaddr, target_vaddr; paddr_t paddr; struct pmem_region region; page_size = seg->page_size; nr_pages = seg->size / seg->page_size; for (i = 0; i < nr_pages; i++) { local_vaddr = (addr_t)local_attach + (seg->page_size * i); target_vaddr = (addr_t)seg->vaddr + (seg->page_size * i); /* (2) */ status = aspace_virt_to_phys(MY_ID, local_vaddr, &paddr); if (status != 0) { printf("aspace_virt_to_phys failed (%s)\n", strerror(errno)); goto out_virt_to_phys; } /* Temporary hack: add umem so we can use aspace_map_region below. * (the kernel won't let us map non-umem memory) */ { memset(®ion, 0, sizeof(struct pmem_region)); region.start = paddr; region.end = paddr + seg->page_size; region.type_is_set = true; region.type = PMEM_TYPE_UMEM; region.allocated_is_set = true; region.allocated = true; status = pmem_add(®ion); if (status != 0) { printf("pmem_add failed (%s)\n", strerror(errno)); goto out_umem; } } /* (3) */ status = aspace_map_region( aspace_id, target_vaddr, seg->page_size, VM_READ | VM_WRITE | VM_USER, seg->page_size, "hio", paddr ); if (status != 0) { printf("aspace_map_region failed (%d) (%s)\n", status, strerror(errno)); goto out_map_pmem; } /* Remove umem now. Unclear how to do it later */ pmem_free_umem(®ion); pmem_del(®ion); } } /* (4) teardown local mapping */ xemem_detach(local_attach); return 0; out_map_pmem: out_umem: out_virt_to_phys: for (j = 0; j < i; j++) { aspace_unmap_region( aspace_id, (addr_t)seg->vaddr + (j * seg->page_size), seg->page_size ); } xemem_detach(local_attach); out_attach: xemem_release(apid); return -1; }
bool App::run( int rankThisNode, id_t pid, uint cpu_id, user_cpumask_t cpumask ) { start_state_t start_state; Debug( App, "pid=%d cpu_id=%d\n", pid, cpu_id ); Debug( App, "argv=%s\n",m_cmdAddr); //Debug( App, "envp=%s\n",m_envAddr); #if DEBUG if ( elf_check_hdr( ( elfhdr*) elf_image ) == 0 ) { elf_print_elfhdr( (elfhdr*) elf_image ); } #endif std::string argv = m_cmdAddr; std::string name = argv.substr( 0, argv.find(" ") ); argv = argv.substr( name.size(), argv.size() ); start_state.cpu_id = cpu_id; start_state.task_id = pid; start_state.user_id = 1; start_state.group_id = 1; start_state.user_id = m_uid; start_state.group_id = m_gid; //start_state.cpumask = cpumask; sprintf(start_state.task_name, "user-%d", pid ); int rc; if ( ( rc = elf_load( m_elfAddr, name.c_str(), pid, // aspace id is the same as the pid PAGE_SIZE, m_heap_len, m_stack_len, (char*) argv.data(), m_envAddrV[rankThisNode], &start_state, (uintptr_t) &m_allocQ, pmem_alloc) ) ) { Warn( App, "elf_load() failed\n"); return rc; } if ( aspace_map_region( pid, (vaddr_t) m_runTimeInfo, m_runTimeInfoLen, (VM_USER|VM_READ), PAGE_SIZE, "NidPidMap", mem_paddr( (void*) m_runTimeInfo ) ) ) { Warn( App, "failed to map nidpidmap in to aspace\n"); return -1; } id_t gotId; rc = task_create( &start_state, &gotId ); if ( rc || pid != gotId ) { Warn( App, "task_create() failed\n"); return -1; } return 0; }