Exemple #1
0
Handle ExtendedStates::AllocateNew(void * & state)
{
    Handle res = ExtendedStatesAllocator.AllocateObject(state);

    if (!res.IsOkayResult())
        return res;

    if (templateState != nullptr)
        ::memcpy(state, templateState, ExtendedStatesAllocator.ObjectSize);

    return HandleResult::Okay;
}
Exemple #2
0
Handle ExtendedStates::AllocateTemplate(void * & state)
{
    if (templateState != nullptr || !ExtendedStates::Initialized)
        return HandleResult::UnsupportedOperation;

    Handle res = ExtendedStatesAllocator.AllocateObject(state);

    if (!res.IsOkayResult())
        return res;

    templateState = state;

    ::memset(state, 0, ExtendedStatesAllocator.ObjectSize);
    //  Clear all the bits, for the cheap (f)xsave implementations that just
    //  leave the reserved bits/bytes/whatever unchanged.

    return HandleResult::Okay;
}
Exemple #3
0
void TestCmdo()
{
    CMDO(1, "a", "alpha", String);
    CMDO(2, "b", "beta", String);
    CMDO(3, "c", "gamma", String);

    CMDO(4, "s", "sierra", BooleanByPresence);
    CMDO(5, "x", "xenulol", BooleanByPresence);
    CMDO(6, "y", "york", BooleanByPresence);

    Handle res;

    res = parser.StartParsing(OptionsString1);

    ASSERT(res.IsOkayResult()
        , "Failed to start parsing command-line options: %H"
        , res);

    // for (size_t i = 0; i < parser.Length; ++i)
    //     if (parser.InputString[i] == '\0')
    //         parser.InputString[i] = '_';

    // msg("Length of \"%S\" is: %us.%n", parser.Length, parser.InputString, parser.Length);

    ASSERT(parser.TokenCount == 7
        , "Parser should have identified %us tokens, not %us."
        , (size_t)7, parser.TokenCount);

    PARSE_OPT(1);
    PARSE_OPT(2);
    PARSE_OPT(3);
    PARSE_OPT(4);
    PARSE_OPT(5);
    PARSE_OPT(6);

    CHECK_STR(1, "test a");
    CHECK_STR(2, "yada yada");
    CHECK_STR(3, "rada");
    CHECK_BOL(4, true);
    CHECK_BOL(5, true);
    CHECK_BOL(6, false);

    //  AND NOW ROUND 2!

    new (&parser) CommandLineOptionParser();

    res = parser.StartParsing(OptionsString2);

    ASSERT(res.IsOkayResult()
        , "Failed to start parsing command-line options: %H"
        , res);

    // for (size_t i = 0; i < parser.Length; ++i)
    //     if (parser.InputString[i] == '\0')
    //         parser.InputString[i] = '_';

    // msg("Length of \"%S\" is: %us.%n", parser.Length, parser.InputString, parser.Length);

    ASSERT(parser.TokenCount == 6
        , "Parser should have identified %us tokens, not %us."
        , (size_t)6, parser.TokenCount);

    PARSE_OPT(1);
    PARSE_OPT(2);
    PARSE_OPT(3);
    PARSE_OPT(4);
    PARSE_OPT(5);
    PARSE_OPT(6);

    CHECK_STR(1, "test a");
    CHECK_STR(2, "yada yada");
    CHECK_STR(3, "rada");
    CHECK_BOL(4, true);
    CHECK_BOL(5, true);
    CHECK_BOL(6, false);

    //  AND NOW ROUND 3!

    CMDO(a, "1", "one", SignedInteger);
    CMDO(b, "2", "two", SignedInteger);
    CMDO(c, "3", "three", SignedInteger);
    CMDO(d, "4", "four", SignedInteger);
    CMDO(e, "BT", "BT", BooleanExplicit);
    CMDO(f, "BF", "BF", BooleanExplicit);

    new (&parser) CommandLineOptionParser();

    res = parser.StartParsing(OptionsString3);

    ASSERT(res.IsOkayResult()
        , "Failed to start parsing command-line options: %H"
        , res);

    // for (size_t i = 0; i < parser.Length; ++i)
    //     if (parser.InputString[i] == '\0')
    //         parser.InputString[i] = '_';

    // msg("Length of \"%S\" is: %us.%n", parser.Length, parser.InputString, parser.Length);

    ASSERT(parser.TokenCount == 11
        , "Parser should have identified %us tokens, not %us."
        , (size_t)11, parser.TokenCount);

    PARSE_OPT(a);
    PARSE_OPT(b);
    PARSE_OPT(c);
    PARSE_OPT(d);
    PARSE_OPT(e);
    PARSE_OPT(f);

    CHECK_SINT(a, -0x60);
    CHECK_SINT(b, -987);
    CHECK_SINT(c, 0123);
    CHECK_SINT(d, 0xCA);
    CHECK_BOL(e, true);
    CHECK_BOL(f, false);

    //  AND FINALLY ROUND 4!

    CMDO(01, "a", "aaa", String);
    CMDO_LINKED(02, "b", "bbb", String, 01);
    CMDO_LINKED(03, "c", "ccc", String, 02);
    CMDO_LINKED(04, "d", "ddd", BooleanByPresence, 03);
    CMDO_LINKED(05, "e", "eee", BooleanByPresence, 04);
    CMDO_LINKED(06, "freud", "booohoooo", BooleanByPresence, 05);
    CMDO_LINKED(07, "g", "ggg", BooleanByPresence, 06);

    new (&parser) CommandLineOptionParser();

    res = parser.StartParsing(OptionsString4);

    ASSERT(res.IsOkayResult()
        , "Failed to start parsing command-line options: %H"
        , res);

    ASSERT(parser.TokenCount == 8
        , "Parser should have identified %us tokens, not %us."
        , (size_t)8, parser.TokenCount);

    CommandLineOptionBatchState batch;

    ASSERT(!batch.IsValid(), "Batch should be invalid.");

    res = parser.StartBatch(batch, &CMDO_07);

    ASSERT(batch.IsValid(), "Batch should be valid.");
    ASSERT(!batch.IsFinished(), "Batch should not be finished.");

    ASSERT(res.IsOkayResult()
        , "Failed to start batch for processing command-line options: %H"
        , res);
    //  This shan't ever happen.

    size_t counter = 0;

    while (!(res = batch.Next()).IsResult(HandleResult::UnsupportedOperation))
    {
        // msg("?? %H ??%n", res);

        if (counter < 5 || counter == 6)
        {
            ASSERT(res.IsOkayResult()
                , "Failed batch step #%us of command-line options processing: %H"
                , counter, res);
        }
        else
        {
            ASSERT(counter == 5
                , "Counter shouldn't exceed 6! It is %us."
                , counter);

            ASSERT(res.IsResult(HandleResult::NotFound)
                , "Failed batch step #%us of command-line options processing: %H"
                , counter, res);
        }

        ASSERT(batch.IsFinished() == (counter == 6)
            , "Batch should only be finished on step 6; current step is %us."
            , counter);

        ++counter;
    }

    ASSERT(batch.IsFinished(), "Batch should be finished.");

    CHECK_PARSED(01);
    CHECK_PARSED(02);
    CHECK_PARSED(03);
    CHECK_PARSED(04);
    CHECK_PARSED(06);
    CHECK_PARSED(07);

    CHECK_STR(01, "1");
    CHECK_STR(02, "2");
    CHECK_STR(03, "3");
    CHECK_BOL(04, true);
    CHECK_BOL(05, false);
    CHECK_BOL(06, true);
    CHECK_BOL(07, true);
}
Exemple #4
0
void TestApplication()
{
    //  First get the loadtest app's location.

    ASSERT(InitRd::Loaded);

    Handle file = InitRd::FindItem("/apps/loadtest.exe");

    ASSERT(file.IsType(HandleType::InitRdFile)
        , "Failed to find loadtest app in InitRD: %H.", file);

    FileBoundaries bnd = InitRd::GetFileBoundaries(file);

    ASSERT(bnd.Start != 0 && bnd.Size != 0);

    //  Then attempt parsing it.

    Handle res = HandleLoadtest(bnd.Start, bnd.Size);

    ASSERT(res.IsOkayResult(), "Error in handling loadtest app: %H.", res);

    //  Then prepare the necessary processes and threads.

    TestRegionLock.Reset();
    TestRegionLock.Acquire();

    new (&testProcess) Process();

    Vmm::Initialize(&testProcess);

    new (&testThread) Thread(&testProcess);
    new (&testWatcher) Thread(&testProcess);

    // DEBUG_TERM_ << "Created app test process and threads." << Terminals::EndLine;

    //  Then the test thread.

    uintptr_t stackVaddr = nullvaddr;

    res = Vmm::AllocatePages(nullptr, 3 * PageSize
        , MemoryAllocationOptions::Commit   | MemoryAllocationOptions::VirtualKernelHeap
        | MemoryAllocationOptions::GuardLow | MemoryAllocationOptions::GuardHigh
        , MemoryFlags::Global | MemoryFlags::Writable
        , MemoryContent::ThreadStack
        , stackVaddr);

    ASSERT(res.IsOkayResult()
        , "Failed to allocate stack for test userland thread: %H."
        , res);

    testThread.KernelStackTop = stackVaddr + 3 * PageSize;
    testThread.KernelStackBottom = stackVaddr;

    testThread.EntryPoint = &JumpToRing3;

    InitializeThreadState(&testThread);
    //  This sets up the thread so it goes directly to the entry point when switched to.

    withInterrupts (false)
        BootstrapThread.IntroduceNext(&testThread);

    // DEBUG_TERM_ << "Initialized app test main thread." << Terminals::EndLine;

    //  Then the watcher thread.

    stackVaddr = nullvaddr;

    res = Vmm::AllocatePages(nullptr, 3 * PageSize
        , MemoryAllocationOptions::Commit   | MemoryAllocationOptions::VirtualKernelHeap
        | MemoryAllocationOptions::GuardLow | MemoryAllocationOptions::GuardHigh
        , MemoryFlags::Global | MemoryFlags::Writable
        , MemoryContent::ThreadStack
        , stackVaddr);

    ASSERT(res.IsOkayResult()
        , "Failed to allocate stack for test watcher thread: %H."
        , res);

    testWatcher.KernelStackTop = stackVaddr + 3 * PageSize;
    testWatcher.KernelStackBottom = stackVaddr;

    testWatcher.EntryPoint = &WatchTestThread;

    InitializeThreadState(&testWatcher);
    //  This sets up the thread so it goes directly to the entry point when switched to.

    withInterrupts (false)
        testThread.IntroduceNext(&testWatcher);

    // DEBUG_TERM_ << "Initialized app test watcher thread." << Terminals::EndLine;

    //  That's all, folks. The other threads finish the work.
}
Exemple #5
0
void * JumpToRing3(void * arg)
{
    (void)arg;

    Handle res;

    //  First, the userland stack page.

    uintptr_t userStackBottom = nullvaddr;

    res = Vmm::AllocatePages(&testProcess
        , userStackPageCount * PageSize
        , MemoryAllocationOptions::AllocateOnDemand | MemoryAllocationOptions::VirtualUser
        | MemoryAllocationOptions::GuardLow         | MemoryAllocationOptions::GuardHigh
        , MemoryFlags::Userland | MemoryFlags::Writable
        , MemoryContent::ThreadStack
        , userStackBottom);

    ASSERT(res.IsOkayResult()
        , "Failed to allocate userland stack for app test thread: %H."
        , res);

    uintptr_t userStackTop = userStackBottom + userStackPageCount * PageSize;

    // DEBUG_TERM_ << "Initialized userland stack for app test main thread." << Terminals::EndLine;

    //  Then, deploy the runtime.

    StartupData * stdat = nullptr;

    res = Runtime64::Deploy(rtlib_base, stdat);

    ASSERT(res.IsOkayResult()
        , "Failed to deploy runtime64 library into test app process: %H."
        , res);

    ASSERT(stdat != nullptr);

    //  Then pass on the app image.

    res = Vmm::AllocatePages(nullptr
        , RoundUp(loadtestEnd - loadtestStart, PageSize)
        , MemoryAllocationOptions::Commit | MemoryAllocationOptions::VirtualUser
        , MemoryFlags::Userland | MemoryFlags::Writable
        , MemoryContent::Generic
        , appVaddr);

    ASSERT(res.IsOkayResult()
        , "Failed to allocate pages for test app image: %H."
        , res);

    memmove(reinterpret_cast<void *>(appVaddr)
        , reinterpret_cast<void const *>(loadtestStart)
        , loadtestEnd - loadtestStart);

    stdat->MemoryImageStart = appVaddr;
    stdat->MemoryImageEnd = loadtestEnd - loadtestStart + appVaddr;

    // DEBUG_TERM_ << "Deployed 64-bit runtime for app test process." << Terminals::EndLine;

    //  Finally, a region for test incrementation.

    vaddr_t testRegVaddr = 0x300000000000;

    res = Vmm::AllocatePages(&testProcess
        , 0x30000
        , MemoryAllocationOptions::AllocateOnDemand | MemoryAllocationOptions::VirtualUser
        , MemoryFlags::Userland | MemoryFlags::Writable
        , MemoryContent::Generic
        , testRegVaddr);

    ASSERT(res.IsOkayResult()
        , "Failed to allocate app test region in userland: %H.%n"
          "Stack is between %Xp and %Xp."
        , res, userStackBottom, userStackTop);

    // DEBUG_TERM_ << "Created test region for app test process." << Terminals::EndLine;

    TestRegionLock.Release();

    //  And finish by going to ring 3.

    // DEBUG_TERM_ << "About to go to ring 3!" << EndLine;

    CpuInstructions::InvalidateTlb(reinterpret_cast<void const *>(rtlib_base + Runtime64::Template.GetEntryPoint()));

    GoToRing3_64(rtlib_base + Runtime64::Template.GetEntryPoint(), userStackTop);
}