예제 #1
0
void MemoryServer::reservePrivate(MemoryMessage *msg)
{
    Address *pageDir;
    
    /* Verify virtual addresses. */
    if (!(msg->virtualAddress >= 1024*1024*16))
    {
	msg->result = EINVAL;
	return;
    }
    /* Point page directory. */
    pageDir = (Address *) PAGETABADDR_FROM(PAGETABFROM,
					   PAGEUSERFROM);
    /* Map page directory. */
    VMCtl(msg->from, MapTables);

    /* Loop directory. Mark them reserved. */
    for (Address i = msg->virtualAddress;
		 i < msg->virtualAddress + msg->bytes;
	         i += (PAGESIZE * PAGETAB_MAX))
    {
	pageDir[DIRENTRY(i)] |= PAGE_RESERVED;
    }
    /* Unmap. */
    VMCtl(msg->from, UnMapTables);
    
    /* Done. */
    msg->result = ESUCCESS;
}
예제 #2
0
Address MemoryServer::findFreeRange(ProcessID procID, Size size)
{
    Address *pageDir, *pageTab, vaddr, vbegin;

    /* Initialize variables. */
    vbegin  = ZERO;
    vaddr   = 1024 * 1024 * 16;
    pageDir = PAGETABADDR_FROM(PAGETABFROM, PAGEUSERFROM);
    pageTab = PAGETABADDR_FROM(vaddr, PAGEUSERFROM);

    /* Map page tables. */
    VMCtl(procID, MapTables);

    /* Scan tables. */
    for (Size inc = PAGESIZE; DIRENTRY(vaddr) < PAGEDIR_MAX ; vaddr += inc)
    {
	/* Is the hole big enough? */
	if (vbegin && vaddr - vbegin >= size)
	{
	    break;
	}
	/* Increment per page table. */
	inc = PAGETAB_MAX * PAGESIZE;
	
	/* Try the current address. */
	if (pageDir[DIRENTRY(vaddr)] & PAGE_RESERVED)
	{
	    vbegin = ZERO; continue;
	}
	else if (pageDir[DIRENTRY(vaddr)] & PAGE_PRESENT)
	{
	    /* Look further into the page table. */
	    inc     = PAGESIZE;
	    pageTab = PAGETABADDR_FROM(vaddr, PAGEUSERFROM);
	
	    if (pageTab[TABENTRY(vaddr)] & PAGE_PRESENT)
	    {
		vbegin = ZERO; continue;
	    }
	}
	/* Reset start address if needed. */
	if (!vbegin)
	{
	    vbegin = vaddr;
	}
    }
    /* Clean up. */
    VMCtl(procID, UnMapTables);
    
    /* Done. */
    return vbegin;
}
예제 #3
0
CoreServer::Result CoreServer::clearPages(Address addr, Size size)
{
    Memory::Range range;

    range.phys = addr;
    range.virt = ZERO;
    range.size = size;
    range.access = Memory::User | Memory::Readable | Memory::Writable;
    VMCtl(SELF, Map, &range);

    MemoryBlock::set((void *) range.virt, 0, size);

    VMCtl(SELF, UnMap, &range);
    return Success;
}
예제 #4
0
Address VMCtlAllocator::allocate(Size *size)
{
    Address ret = heapStart + allocated;
    VirtualMemory::Range range;
    Size bytes;

    /* Start allocating. */
    for (bytes = 0; bytes < *size; bytes += PAGESIZE)
    {
        range.virt  = ret + bytes;
        range.phys  = ZERO;
        range.size  = PAGESIZE;
        range.access = VirtualMemory::Present |
                       VirtualMemory::User |
                       VirtualMemory::Readable |
                       VirtualMemory::Writable;
    
        VMCtl(SELF, Map, &range);
    }
    /* Update count. */
    allocated += bytes;

    /* Success. */
    *size = bytes;
    return ret;
}
예제 #5
0
파일: VGA.cpp 프로젝트: 0xbda2d2f8/FreeNOS
Error VGA::initialize()
{
    Memory::Range range;

    // Request VGA memory
    range.size   = PAGESIZE;
    range.access = Memory::User     |
                   Memory::Readable |
                   Memory::Writable;
    range.virt   = ZERO;
    range.phys   = VGA_PADDR;
    VMCtl(SELF, Map, &range);

    // Point to the VGA mapping
    vga = (u16 *) range.virt;

    // Clear screen
    for (uint i = 0; i < width * height; i++)
    {
        vga[i] = VGA_CHAR(' ', LIGHTGREY, BLACK);
    }

    // Disable hardware cursor
    WriteByte(VGA_IOADDR, 0x0a);
    WriteByte(VGA_IODATA, 1 << 5);

    // Successfull
    return ESUCCESS;
}
예제 #6
0
Address VMCtlAllocator::allocate(Size *size)
{
    Address ret = heapStart + allocated;
    MemoryRange range;
    Size bytes;

    /* Start allocating. */
    for (bytes = 0; bytes < *size; bytes += PAGESIZE)
    {
	range.virtualAddress  = ret + bytes;
	range.physicalAddress = ZERO;
	range.bytes = PAGESIZE;
    
	VMCtl(SELF, Map, &range);
    }
    /* Update end-of-heap pointer. */
    heapEnd = ret + bytes;

    /* Update count. */
    allocated += bytes;

    /* Success. */
    *size = bytes;
    return ret;
}
예제 #7
0
Allocator::Result PageAllocator::allocate(Size *size, Address *addr, Size align)
{
    Memory::Range range;
    
    // Set return address
    *addr = m_base + m_allocated;

    // TODO: sanity checks
    Size bytes  = *size > PAGEALLOC_MINIMUM ?
                  *size : PAGEALLOC_MINIMUM;

    // Align to pagesize
    bytes = aligned(bytes, PAGESIZE);

    // Fill in the message. */
    range.size   = bytes;
    range.access = Memory::User | Memory::Readable | Memory::Writable;
    range.virt   = m_base + m_allocated;
    range.phys   = ZERO;

    // TODO: #warning do we need to pass the region here too?
    //range.region = Memory::UserPrivate;
    VMCtl(SELF, Map, &range);

    // Clear the pages
    MemoryBlock::set((void *) range.virt, 0, range.size);

    // Update count
    m_allocated += range.size; 

    // Success
    *size = range.size;
    return Success;
}
예제 #8
0
void SMSC95xxUSB::writeStart()
{
    DEBUG("");

    if (m_txPacket)
    {
        ERROR("transmit already in progress");
        return;
    }

    m_txPacket = m_smsc->getTransmitQueue()->pop();
    if (!m_txPacket)
    {
        DEBUG("no transmit data packet available");
        return;
    }

    // Flush L1 cache
    VMCtl(SELF, CacheClean, 0);

    // Start bulk transfer
    Error err = beginTransfer(
        USBTransfer::Bulk,
        USBTransfer::Out,
        m_endpoints[1].endpointAddress & 0xf,
        m_txPacket->data,
        m_txPacket->size,
        m_endpoints[1].maxPacketSize,
        m_writeFinished
    );
}
예제 #9
0
파일: IO.cpp 프로젝트: 0xbda2d2f8/FreeNOS
IO::Result IO::map(Address phys, Size size, Memory::Access access)
{
    m_range.virt   = 0;
    m_range.phys   = phys;
    m_range.access = access;
    m_range.size   = size;

    if (!isKernel)
    {
        if (VMCtl(SELF, Map, &m_range) != API::Success)
            return MapFailure;
    }
    else
    {
        m_range.access &= ~Memory::User;

        MemoryContext *ctx = MemoryContext::getCurrent();
        if (!ctx)
            return MapFailure;

        if (ctx->findFree(size, MemoryMap::KernelPrivate, &m_range.virt) != MemoryContext::Success)
            return OutOfMemory;

        if (ctx->map(m_range.virt, phys, m_range.access) != MemoryContext::Success)
            return MapFailure;
    }
    m_base = m_range.virt;
    return Success;
}
예제 #10
0
파일: Main.cpp 프로젝트: Nano1994/freenos
int main(int argc, char **argv)
{
    u64 t1 = 0, t2 = 0;
    ProcessID pid = 0;
    ProcessInfo info;
    MemoryRange range;
    char *foo[128];

    t1 = timestamp();
    pid = ProcessCtl(SELF, GetPID);
    t2 = timestamp();
	
    printf("SystemCall (GetPID) Ticks: %u\r\n", t2 - t1);
	
    t1 = timestamp();
    ProcessCtl(SELF, InfoPID, (Address) &info);
    t2 = timestamp();

    printf("SystemCall (InfoPID) Ticks: %u\r\n", t2 - t1);

    t1 = timestamp();
    ProcessCtl(SELF, Schedule);
    t2 = timestamp();

    printf("SystemCall (Schedule) Ticks: %u\r\n", t2 - t1);
	
    range.virtualAddress = 0x80000000;
    range.bytes = PAGESIZE;
    
    t1 = timestamp();
    VMCtl(SELF, LookupVirtual, &range);
    t2 = timestamp();
	
    printf("SystemCall (VMCtl) Ticks: %u\r\n", t2 - t1);

    t1 = timestamp();
    getpid();
    t2 = timestamp();

    printf("IPC Ticks: %u\r\n", t2 - t1);
	
    t1 = timestamp();
    for (int i = 0; i < 128; i++)
        foo[i] = new char[16];
    t2 = timestamp();
	
    printf("allocate() Ticks: %u (%u AVG)\r\n",
    	    (u32)(t2 - t1), (u32)(t2 - t1) / 128);
	
    t1 = timestamp();
    for (int i = 0; i < 128; i++)
        delete foo[i];
    t2 = timestamp();
    printf("release() Ticks: %u (%u AVG)\r\n",
	(u32)(t2 - t1), (u32)(t2 - t1) / 128);

    /* Done. */
    return EXIT_SUCCESS;
}
예제 #11
0
SharedMemory * MemoryServer::insertShared(ProcessID procID,
					  char *key, Size size,
					  MemoryRange *range, bool *created)
{
    SharedMemory *obj = findShared(key);
    bool needCreate = obj == ZERO;

    if (needCreate)
        obj = new SharedMemory;

    range->virtualAddress  = findFreeRange(procID, size);
    range->bytes      = size;
    range->access     = Memory::Present | Memory::User | Memory::Readable | Memory::Writable | Memory::Pinned;

    /* Only create a new mapping, if non-existent. */
    if (needCreate)
    {
	range->physicalAddress = ZERO;	
	VMCtl(procID, Map, range);
	
	/* Create new shared memory object. */
	obj->size = size;
	obj->key  = key;
	obj->address = range->physicalAddress;

	/* Insert to the list. */
	shared.append(obj);
	
	/* We created a new mapping, flag that. */
	if (created) *created = true;
    }
    else
    {
	range->physicalAddress = obj->address;
	VMCtl(procID, Map, range);
	
	/* We didn't create a new mapping, flag that. */
	if (created) *created = false;
    }
    /* Done. */
    return obj;
}
예제 #12
0
파일: Assert.cpp 프로젝트: Esaud17/AmayaOS
int __assertWrite(Address addr)
{
    MemoryRange range;

    range.virtualAddress  = addr;
    range.physicalAddress = ZERO;
    range.bytes           = sizeof(Address);
    range.protection      = PAGE_PRESENT | PAGE_USER | PAGE_RW;

    return VMCtl(SELF, Access, &range);
}
예제 #13
0
Error MemoryServer::insertMapping(ProcessID procID, MemoryRange *range)
{
    MemoryRange tmp;
    Error result;
    
    tmp.virtualAddress = range->virtualAddress;
    tmp.access         = Memory::Present;
    tmp.bytes          = range->bytes;

    /* The given range must be free. */
    if (VMCtl(procID, Access, &tmp))
    {
	return EFAULT;
    }
    /* Perform mapping. */
    if ((result = VMCtl(procID, Map, range)) != 0)
    {
        return result;
    }
    /* Done! */
    return ESUCCESS;
}
예제 #14
0
SharedMemory * MemoryServer::insertShared(ProcessID procID,
					  char *key, Size size,
					  MemoryRange *range, bool *created)
{
    SharedMemory *obj;

    range->virtualAddress  = findFreeRange(procID, size);
    range->bytes      = size;
    range->protection = PAGE_PRESENT | PAGE_USER | PAGE_RW | PAGE_PINNED;

    /* Only create a new mapping, if non-existent. */
    if (!(obj = findShared(key)))
    {
	range->physicalAddress = ZERO;	
	VMCtl(procID, Map, range);
	
	/* Create new shared memory object. */
	obj = new SharedMemory;
	obj->size = size;
	obj->key  = new String(key);
	obj->address = range->physicalAddress;

	/* Insert to the list. */
	shared.insertTail(obj);
	
	/* We created a new mapping, flag that. */
	if (created) *created = true;
    }
    else
    {
	range->physicalAddress = obj->address;
	VMCtl(procID, Map, range);
	
	/* We didn't create a new mapping, flag that. */
	if (created) *created = false;
    }
    /* Done. */
    return obj;
}
예제 #15
0
파일: IO.cpp 프로젝트: 0xbda2d2f8/FreeNOS
IO::Result IO::unmap()
{
    if (!isKernel)
    {
        if (VMCtl(SELF, UnMap, &m_range) != API::Success)
            return MapFailure;
    }
    else
    {
        MemoryContext *ctx = MemoryContext::getCurrent();
        if (!ctx)
            return MapFailure;

        if (ctx->unmapRange(&m_range) != MemoryContext::Success)
            return MapFailure;
    }
    return Success;
}
예제 #16
0
void CoreServer::createPrivate(CoreMessage *msg)
{
    Memory::Range range;

    // Set mapping flags
    // TODO: only allow pinned pages for uid == 0!
    range.virt   = msg->virt & PAGEMASK;
    range.phys   = msg->phys;
    range.size   = msg->size;    
    range.access = msg->access;

    // Try to map the range
    VMCtl(msg->from, Map, &range);

    msg->virt = range.virt;
    msg->phys = range.phys;
    msg->result = ESUCCESS;
}
예제 #17
0
파일: MPI.cpp 프로젝트: Alexis97/FreeNOS
int MPI_Init(int *argc, char ***argv)
{
    SystemInformation info;
    FileSystemMessage msg;
    struct stat st;
    char *programName = (*argv)[0];
    char programPath[64];
    u8 *programBuffer;
    int fd;
    Memory::Range memChannelBase;

    // If we are master (node 0):
    if (info.coreId == 0)
    {
        msg.type   = ChannelMessage::Request;
        msg.action = ReadFile;
        msg.from = SELF;
        ChannelClient::instance->syncSendReceive(&msg, CORESRV_PID);

        // provide -n COUNT, --help and other stuff in here too.
        // to influence the launching of more MPI programs
        coreCount = msg.size;

        // Read our own ELF program to a buffer and pass it to CoreServer
        // for creating new programs on the remote core.
        if (strncmp(programName, "/bin/", 5) != 0)
            snprintf(programPath, sizeof(programPath), "/bin/%s", programName);
        else
            strlcpy(programPath, programName, sizeof(programPath));

        if (stat(programPath, &st) != 0)
        {
            printf("%s: failed to stat '%s': %s\n",
                    programName, programPath, strerror(errno));
            return MPI_ERR_BAD_FILE;
        }
        programBuffer = new u8[st.st_size];
        MemoryBlock::set(programBuffer, 0, st.st_size);

        // Read ELF program
        if ((fd = open(programPath, O_RDONLY)) == -1)
        {
            printf("%s: failed to open '%s': %s\n",
                    programName, programPath, strerror(errno));
            return MPI_ERR_BAD_FILE;
        }
        if (read(fd, programBuffer, st.st_size) != st.st_size)
        {
            printf("%s: failed to read '%s': %s\n",
                    programName, programPath, strerror(errno));
            return MPI_ERR_BAD_FILE;
        }
        if (close(fd) != 0)
        {
            printf("%s: failed to close '%s': %s\n",
                    programName, programPath, strerror(errno));
            return MPI_ERR_BAD_FILE;
        }

        // Allocate memory space on the local processor for the whole
        // UniChannel array, NxN communication with MPI.
        // Then pass the channel offset physical address as an argument -addr 0x.... to spawn()
        memChannelBase.size = (PAGESIZE * 2) * (msg.size * msg.size);
        memChannelBase.phys = 0;
        memChannelBase.virt = 0;
        memChannelBase.access = Memory::Readable | Memory::Writable | Memory::User;
        if (VMCtl(SELF, Map, &memChannelBase) != API::Success)
        {
            printf("%s: failed to allocate MemoryChannel\n",
                    programName);
            return MPI_ERR_NO_MEM;
        }
        printf("%s: MemoryChannel at physical address %x\n",
                programName, memChannelBase.phys);

        // Clear channel pages
        MemoryBlock::set((void *) memChannelBase.virt, 0, memChannelBase.size);

        // now create the slaves using coreservers.
        for (Size i = 1; i < coreCount; i++)
        {
            // TODO: check for cmd buffer size...
            char *cmd = new char[512];
            snprintf(cmd, 512, "%s -a %x -c %d",
                     programPath, memChannelBase.phys, coreCount);

            for (int j = 1; j < *argc; j++)
            {
                strcat(cmd, " ");
                strcat(cmd, (*argv)[j]);
            }

            msg.type   = ChannelMessage::Request;
            msg.action = CreateFile;
            msg.size   = i;
            msg.buffer = (char *) programBuffer;
            msg.offset = st.st_size;
            msg.path   = cmd;
            ChannelClient::instance->syncSendReceive(&msg, CORESRV_PID);

            if (msg.result != ESUCCESS)
            {
                printf("%s: failed to create process on core%d\n",
                        programName, i);
                return MPI_ERR_SPAWN;
            }
        }
    }
    else
    {
        // If we are slave (node N): 
        // read the -addr argument, and map the UniChannels into our address space.
        for (int i = 1; i < (*argc); i++)
        {
            if (!strcmp((*argv)[i], "--addr") ||
                !strcmp((*argv)[i], "-a"))
            {
                if ((*argc) < i+1)
                    return MPI_ERR_ARG;

                String s = (*argv)[i+1];
                memChannelBase.phys = s.toLong(Number::Hex);
                i++;
            }
            else if (!strcmp((*argv)[i], "--cores") ||
                     !strcmp((*argv)[i], "-c"))
            {
                if ((*argc) < i+1)
                    return MPI_ERR_ARG;
                coreCount = atoi((*argv)[i+1]);
                i++;
            }
            // Unknown MPI argument. Pass the rest to the user program.
            else
            {
                (*argc) -= (i-1);
                (*argv)[i-1] = (*argv)[0];
                (*argv) += (i-1);
                break;
            }
        }
    }

    // Create MemoryChannels
    readChannel  = new Index<MemoryChannel>(coreCount);
    writeChannel = new Index<MemoryChannel>(coreCount);

    // Fill read channels
    for (Size i = 0; i < coreCount; i++)
    {
        MemoryChannel *ch = new MemoryChannel();
        ch->setMode(MemoryChannel::Consumer);
        ch->setMessageSize(sizeof(MPIMessage));
        ch->setPhysical(MEMBASE(info.coreId) + (PAGESIZE * 2 * i),
                        MEMBASE(info.coreId) + (PAGESIZE * 2 * i) + PAGESIZE);
        readChannel->insert(i, *ch);

        if (info.coreId == 0)
        printf("%s: read: core%d: data=%x feedback=%x base%d=%x\n", (*argv)[0], i, 
            MEMBASE(info.coreId) + (PAGESIZE * 2 * i),
            MEMBASE(info.coreId) + (PAGESIZE * 2 * i) + PAGESIZE,
            i, MEMBASE(i));
    }

    // Fill write channels
    for (Size i = 0; i < coreCount; i++)
    {
        MemoryChannel *ch = new MemoryChannel();
        ch->setMode(MemoryChannel::Producer);
        ch->setMessageSize(sizeof(MPIMessage));
        ch->setPhysical(MEMBASE(i) + (PAGESIZE * 2 * info.coreId),
                        MEMBASE(i) + (PAGESIZE * 2 * info.coreId) + PAGESIZE);
        writeChannel->insert(i, *ch);

        if (info.coreId == 0)
        printf("%s: write: core%d: data=%x feedback=%x base%d=%x\n", (*argv)[0], i, 
            MEMBASE(i) + (PAGESIZE * 2 * info.coreId),
            MEMBASE(i) + (PAGESIZE * 2 * info.coreId) + PAGESIZE,
            i, MEMBASE(i));
    }

    return MPI_SUCCESS;
}
예제 #18
0
CoreServer::Result CoreServer::bootCore(uint coreId, CoreInfo *info,
                                        ExecutableFormat::Region *regions)
{
    SystemInformation sysInfo;
    DEBUG("Reserving: " << (void *)info->memory.phys << " size=" <<
            info->memory.size << " available=" << sysInfo.memoryAvail);

    // Claim the core's memory
    if (VMCtl(SELF, RemoveMem, &info->memory) != API::Success)
    {
        ERROR("failed to reserve memory for core" << coreId <<
              " at " << (void *)info->memory.phys);
        return OutOfMemory;
    }

    DEBUG("Starting core" << coreId << " with "
          << info->memory.size / 1024 / 1024 << "MB");

    // Map the kernel
    for (int i = 0; i < m_numRegions; i++)
    {
        Memory::Range range;
        range.phys = info->memory.phys + regions[i].virt;
        range.virt = 0;
        range.size = regions[i].size;
        range.access = Memory::Readable | Memory::Writable |
                       Memory::User;

        // Map the target kernel's memory for regions[i].size
        if (VMCtl(SELF, Map, &range) != 0)
        {
            // TODO: convert from API::Error to errno.
            //errno = EFAULT;
            return OutOfMemory;
        }
        // Copy the kernel to the target core's memory
#warning VMCopy should just return API::Result, not a Size
	Error r = VMCopy(SELF, API::Write, (Address) regions[i].data,
                                 range.virt,
                                 regions[i].size);
	if (r != regions[i].size)
	    return MemoryError;

        // Unmap the target kernel's memory
        if (VMCtl(SELF, Release, &range) != API::Success)
        {
            return MemoryError;
        }

        DEBUG(kernelPath << "[" << i << "] = " << (void *) m_regions[i].virt);
    }

    // Copy the BootImage after the kernel.
    Memory::Range range;
    range.phys = info->bootImageAddress;
    range.virt = 0;
    range.size = info->bootImageSize;
    range.access = Memory::Readable | Memory::Writable | Memory::User;

    // Map BootImage buffer
    if (VMCtl(SELF, Map, &range) != API::Success)
    {
        return OutOfMemory;
    }
    // Copy the BootImage
    Error r = VMCopy(SELF, API::Write, sysInfo.bootImageAddress,
                     range.virt, sysInfo.bootImageSize);
    if (r != (Error) sysInfo.bootImageSize)
        return MemoryError;

    // Unmap the BootImage
    if (VMCtl(SELF, Release, &range) != API::Success)
        return MemoryError;

#ifdef INTEL
    // Signal the core to boot
    if (m_mp.boot(info) != IntelMP::Success) {
        ERROR("failed to boot core" << coreId);
        return BootError;
    } else {
        NOTICE("core" << coreId << " started");
    }
#endif
    return Success;
}
예제 #19
0
void ProcessServer::spawnProcessHandler(ProcessMessage *msg)
{
    char path[PATHLEN], *tmp;
    FileSystemMessage fs;
    ExecutableFormat *fmt;
    MemoryRegion regions[16];
    MemoryRange range;
    Error numRegions, ret;
    Size size;
    ProcessID pid;
    Shared<FileDescriptor> *parentFd, *childFd;

    /* Read out the path to the executable. */
    if ((msg->result = VMCopy(msg->from, Read, (Address) path,
                             (Address) msg->path, PATHLEN) < 0))
    {
        return;
    }
    
    /* Attempt to read executable format. */
    if (!(fmt = ExecutableFormat::find(path))) {
        msg->result = errno;
        return;
    }
    
    /* Retrieve memory regions. */
    if ((numRegions = fmt->regions(regions, 16)) < 0) {
        msg->result = errno;
        return;
    }
    
    /* Create new process. */
    pid = ProcessCtl(ANY, Spawn, fmt->entry());

    /* Map program regions into virtual memory of the new process. */
    for (int i = 0; i < numRegions; i++) {
        /* Copy executable memory from this region. */
        for (Size j = 0; j < regions[i].size; j += PAGESIZE) {
            range.virtualAddress  = regions[i].virtualAddress + j;
            range.physicalAddress = ZERO;
            range.bytes = PAGESIZE;

            /* Create mapping first. */
            if ((ret = VMCtl(pid, Map, &range)) != 0) {
                msg->result = ret;
                return;
            }
            
            /* Copy bytes. */
            VMCopy(pid, Write, (Address) (regions[i].data) + j,
                regions[i].virtualAddress + j, PAGESIZE);
        }
    }
    
    /* Create mapping for command-line arguments. */
    range.virtualAddress  = ARGV_ADDR;
    range.physicalAddress = ZERO;
    range.bytes = PAGESIZE;
    VMCtl(pid, Map, &range);

    /* Allocate temporary variable. */
    tmp  = new char[PAGESIZE];
    memset(tmp, 0, PAGESIZE);

    /* Calculate number of bytes to copy. */
    size = msg->number * ARGV_SIZE < PAGESIZE ?
    msg->number * ARGV_SIZE : PAGESIZE;

    /* Copy arguments into the temporary variable. */    
    if ((msg->result = VMCopy(msg->from, Read, (Address) tmp,
                       (Address) msg->arguments, size)) < 0)
    {
        delete tmp;
        return;
    }
    
    /* Copy argc/argv into the new process. */
    if ((msg->result = VMCopy(pid, Write, (Address) tmp,
                       (Address) ARGV_ADDR, PAGESIZE)) < 0)
    {
        delete tmp;
        return;
    }
    
    /* Set command-line string. */
    snprintf(procs[pid]->command, COMMANDLEN,
             "%s", path);

    /* Copy the FileDescriptor table. */
    parentFd = getFileDescriptors(files, msg->from);
    childFd  = getFileDescriptors(files, pid);
    memcpy(**childFd, **parentFd, childFd->size());

    /* Inherit user and group identities. */
    procs[pid]->userID  = procs[msg->from]->userID;
    procs[pid]->groupID = procs[msg->from]->groupID;
    strncpy(procs[pid]->currentDirectory,
            procs[msg->from]->currentDirectory, PATHLEN);

    /* Begin execution. */
    ProcessCtl(pid, Resume);

    /* Success. */
    msg->number = pid;
    msg->result = ESUCCESS;
    
    /* Cleanup. */
    delete fmt;
    delete tmp;
}
예제 #20
0
CoreServer::CoreServer()
    : IPCServer<CoreServer, CoreMessage>(this)
{
    SystemInformation info;
    Memory::Range range;
    BootImage *image;
    BootSymbol *symbol;

    /* Register message handlers. */
    addIPCHandler(CreatePrivate,  &CoreServer::createPrivate);
    addIPCHandler(ReleasePrivate, &CoreServer::releasePrivate);
    addIPCHandler(ReadProcess,    &CoreServer::readProcessHandler);
    addIPCHandler(GetMounts,      &CoreServer::getMountsHandler);
    addIPCHandler(SetMount,       &CoreServer::setMountHandler);
    addIPCHandler(ExitProcess,    &CoreServer::exitProcessHandler,  false);
    addIPCHandler(SpawnProcess,   &CoreServer::spawnProcessHandler);
    addIPCHandler(WaitProcess,    &CoreServer::waitProcessHandler,  false);

    /* Allocate a user process table. */
    procs = new UserProcess[MAX_PROCS];
    memset(procs, 0, sizeof(UserProcess) * MAX_PROCS);

    /* Allocate FileSystemMounts table. */
    mounts = new FileSystemMount[FILESYSTEM_MAXMOUNTS];
    memset(mounts, 0, sizeof(FileSystemMount) * FILESYSTEM_MAXMOUNTS);

    /* We only guarantee that / and /dev, /proc are mounted. */
    strlcpy(mounts[0].path, "/dev", PATHLEN);
    strlcpy(mounts[1].path, "/", PATHLEN);
    strlcpy(mounts[2].path, "/proc", PATHLEN);
    mounts[0].procID  = DEVSRV_PID;
    mounts[0].options = ZERO;
    mounts[1].procID  = ROOTSRV_PID;
    mounts[1].options = ZERO;
    mounts[2].procID  = 13;
    mounts[2].options = ZERO;

    // Attempt to load the boot image
    range.virt    = ZERO;
    range.phys    = info.bootImageAddress;
    range.access  = Arch::Memory::Present | Arch::Memory::User | Arch::Memory::Readable;
    range.size    = info.bootImageSize;
    VMCtl(SELF, Map, &range);
    
    image = (BootImage *) range.virt;

    /* Loop all embedded programs. */
    for (Size j = 0; j < image->symbolTableCount; j++)
    {
        /* Read out the next program. */
        symbol = (BootSymbol *)(((Address)image) + image->symbolTableOffset);
        symbol += j;

        if (symbol->type != BootProgram)
            continue;

        /* Write commandline. */
        snprintf(procs[j].command, COMMANDLEN,
                "[%s]", symbol->name);

        /* Set user and group identities. */
        procs[j].userID  = 0;
        procs[j].groupID = 0;
    }
}
예제 #21
0
void CoreServer::createProcess(FileSystemMessage *msg)
{
    char cmd[128];
    Memory::Range range;

    if (m_info.coreId == 0)
    {
        MemoryChannel *ch = (MemoryChannel *) m_toSlave->get(msg->size);

        if (!ch)
        {
            ERROR("invalid coreId=" << msg->size);
            msg->result = EBADF;
            return;
        }

        // TODO:move in libmpi?
        range.virt = (Address) msg->buffer;
        VMCtl(msg->from, LookupVirtual, &range);
        msg->buffer = (char *) range.phys;

        range.virt = (Address) msg->path;
        VMCtl(msg->from, LookupVirtual, &range);
        msg->path = (char *) range.phys;

        if (ch->write(msg) != Channel::Success)
        {
            ERROR("failed to write channel on core"<<msg->size);
            msg->result = EBADF;
            return;
        }
        DEBUG("creating program at phys " << (void *) msg->buffer << " on core" << msg->size);

        ch = (MemoryChannel *) m_fromSlave->get(msg->size);
        if (!ch)
        {
            ERROR("cannot find read channel for core" << msg->size);
            msg->result = EBADF;
            return;
        }
        // TODO: replace with ChannelClient::syncReceiveFrom
        while (ch->read(msg) != Channel::Success);
        DEBUG("program created with result " << (int)msg->result << " at core" << msg->size);

        msg->result = ESUCCESS;
        //IPCMessage(msg->from, API::Send, msg, sizeof(*msg));
        ChannelClient::instance->syncSendTo(msg, msg->from);
    }
    else
    {
        VMCopy(SELF, API::ReadPhys, (Address) cmd, (Address) msg->path, sizeof(cmd));

        range.phys   = (Address) msg->buffer;
        range.virt   = 0;
        range.access = Memory::Readable | Memory::User;
        range.size   = msg->offset;
        VMCtl(SELF, Map, &range);

        pid_t pid = spawn(range.virt, msg->offset, cmd);
        int status;

        // reply to master
        msg->result = ESUCCESS;
        while (m_toMaster->write(msg) != Channel::Success);

        // TODO: temporary make coreserver waitpid() to save polling time
        waitpid(pid, &status, 0);
    }
}
예제 #22
0
파일: forkexec.cpp 프로젝트: xut226/FreeNOS
int forkexec(const char *path, const char *argv[])
{
    CoreMessage msg;
    ExecutableFormat *fmt;
    MemoryRegion regions[16];
    Memory::Range range;
    uint count = 0;
    pid_t pid = 0;
    int numRegions = 0;
    Vector<FileDescriptor> *fds = getFiles();

    // Attempt to read executable format
    if (!(fmt = ExecutableFormat::find(path)))
        return -1;

    // Retrieve memory regions
    if ((numRegions = fmt->regions(regions, 16)) < 0)
        return -1;

    // Create new process
    pid = ProcessCtl(ANY, Spawn, fmt->entry());

    // TODO: check the result of ProcessCtl()

    // TODO: make this much more efficient. perhaps let libexec write directly to the target buffer.
    // at least Map & copy in one shot.
    // TODO: move the memory administration updates to coreserver instead.
    // this process can read the libexec data once, and then let coreserver create a process for it.

    // Map program regions into virtual memory of the new process
    for (int i = 0; i < numRegions; i++)
    {
        // Copy executable memory from this region
        range.virt  = regions[i].virtualAddress;
        range.phys  = ZERO;
        range.size  = regions[i].size;
        range.access = Memory::Present |
                       Memory::User |
                       Memory::Readable |
                       Memory::Writable |
                       Memory::Executable;
        
        // Create mapping first
        if (VMCtl(pid, Map, &range) != 0)
        {
            // TODO: convert from API::Error to errno.
            errno = EFAULT;
            return -1;
        }
        // Copy bytes
        VMCopy(pid, API::Write, (Address) regions[i].data,
               regions[i].virtualAddress, regions[i].size);
    }
    /* Create mapping for command-line arguments. */
    range.virt  = ARGV_ADDR;
    range.phys  = ZERO;
    range.size  = PAGESIZE;
    VMCtl(pid, Map, &range);

    // Allocate arguments
    char *arguments = new char[PAGESIZE];
    memset(arguments, 0, PAGESIZE);

    // Fill in arguments
    while (argv[count] && count < PAGESIZE / ARGV_SIZE)
    {
        strlcpy(arguments + (ARGV_SIZE * count), argv[count], ARGV_SIZE);
        count++;
    }

    // Copy argc/argv into the new process
    if ((VMCopy(pid, API::Write, (Address) arguments,
               (Address) ARGV_ADDR, PAGESIZE)) < 0)
    {
        delete arguments;
        errno = EFAULT;
        return -1;
    }

    // Let the Child begin execution
    ProcessCtl(pid, Resume);

    // Send a pointer to our list of file descriptors to the child
    // TODO: ofcourse, insecure. To be fixed later.
    msg.type      = IPCType;
    msg.from      = SELF;
    msg.path = (char *) fds->vector();
    IPCMessage(pid, API::SendReceive, &msg, sizeof(msg));

    // Done. Cleanup.
    delete arguments;
    return pid;
}
예제 #23
0
MemoryServer::MemoryServer()
    : IPCServer<MemoryServer, MemoryMessage>(this)
{
    SystemInformation info;
    MemoryRange range;
    BootImage *image;
    BootProgram *program;

    /* Register message handlers. */
    addIPCHandler(CreatePrivate,  &MemoryServer::createPrivate);
    addIPCHandler(ReservePrivate, &MemoryServer::reservePrivate);
    addIPCHandler(ReleasePrivate, &MemoryServer::releasePrivate);
    addIPCHandler(CreateShared,   &MemoryServer::createShared);
    addIPCHandler(SystemMemory,   &MemoryServer::systemMemory);
    
    /* Allocate a user process table. */
    insertShared(SELF, USER_PROCESS_KEY,
		 sizeof(UserProcess) * MAX_PROCS, &range);

    /* Clear it. */
    procs = (UserProcess *) range.virtualAddress;
    memset(procs, 0, sizeof(UserProcess) * MAX_PROCS);

    /* Allocate FileSystemMounts table. */		 
    insertShared(SELF, FILE_SYSTEM_MOUNT_KEY,
		 sizeof(FileSystemMount) * MAX_MOUNTS, &range);
		 
    /* Also Clear it. */
    mounts = (FileSystemMount *) range.virtualAddress;
    memset(mounts, 0, sizeof(FileSystemMount) * MAX_MOUNTS);

    /* We only guarantee that / and /dev are mounted. */
    strlcpy(mounts[0].path, "/dev", PATHLEN);
    strlcpy(mounts[1].path, "/", PATHLEN);
    mounts[0].procID  = DEVSRV_PID;
    mounts[0].options = ZERO;
    mounts[1].procID  = ROOTSRV_PID;
    mounts[1].options = ZERO;

    /* Attempt to load the boot image. */
    for (Size i = 0; i < info.moduleCount; i++)
    {
        if (strcmp(info.modules[i].string, "/boot/boot.img.gz") == 0)
        {
	    range.virtualAddress  = findFreeRange(SELF, PAGESIZE * 2);
	    range.physicalAddress = info.modules[i].modStart;
	    range.access          = Memory::Present | Memory::User | Memory::Readable;
#warning Dangerous value for bytes here?
	    range.bytes           = PAGESIZE * 2;
	    VMCtl(SELF, Map, &range);
	    
	    image = (BootImage *) range.virtualAddress;
	    break;
	}
    }
    /* Loop all embedded programs. */
    for (Size j = 0; j < image->programsTableCount; j++)
    {
        /* Read out the next program. */
        program = (BootProgram *)(((Address)image) + image->programsTableOffset);
	program += j;

        /* Write commandline. */
        snprintf(procs[j].command, COMMANDLEN,
                "[%s]", program->path);

	/* Set current directory. */
	snprintf(procs[j].currentDirectory, PATHLEN, "/");

        /* Set user and group identities. */
        procs[j].userID  = 0;
        procs[j].groupID = 0;
    }
}