コード例 #1
0
ファイル: mlock.c プロジェクト: TUM-LIS/optimsoc-sourceware
/**
 * Recursive lock of the malloc
 */
void __malloc_lock(struct _reent *ptr) {
    uint32_t timerenable, interruptenable;
    uint32_t id, old_owner;

    // Disable timer and interrupt exception, store TEE and IEE flag temporarily
    // to restore them later on unlock
    timerenable = or1k_timer_disable();
    interruptenable = or1k_interrupts_disable();

    // Now we cannot be disturbed by an interrupt or timer exception

    id = (uint32_t) ptr; // Our id is the address of the reentrancy data

    do {
        do {
            // Read current lock owner
            old_owner = or1k_sync_ll(&_malloc_lock_own);
            // .. and spin while it is locked and we are not the owner
        } while (old_owner && (old_owner != id));
    } while (!or1k_sync_sc(&_malloc_lock_own, id));

    // Store the TEE and IEE flags for later restore
    _malloc_lock_restore_timer = timerenable;
    _malloc_lock_restore_interrupts = interruptenable;

    // Increment counter. The lock may be accessed recursively
    _malloc_lock_cnt++;

    return;
}
コード例 #2
0
ファイル: vmm.c プロジェクト: imphil/sources
int optimsoc_vmm_map(optimsoc_page_dir_t directory, uint32_t vaddr,
                     uint32_t paddr) {
    optimsoc_pte_t dirpte;
    optimsoc_page_table_t table;
    optimsoc_pte_t pte;

    // Verify input
    VERIFY_DIR_ADDR(directory);

    // Address of the table's pte from the directory base
    void *taddr = (void*) &directory[OR1K_ADDR_L1_INDEX_GET(vaddr)];

    // Load-linked the pointer, as we may change it
    dirpte = or1k_sync_ll(taddr);

    // Check if table is present
    if (OR1K_PTE_PRESENT_GET(dirpte) == 0) {
        // There is no page table, allocate and map one
        table = _optimsoc_vmm_create_page_table();
        assert(table);

        // We now try to set this as te new table by updating the pte. As other
        // cores may have set a table at the same index concurrently, we do
        // a store-conditional.
        while (1) {
            // Set table present
            dirpte = OR1K_PTE_PRESENT_SET(dirpte, 1);
            // Set the physical page number, that is the table base address
            dirpte = OR1K_PTE_PPN_SET(dirpte, OR1K_PTE_PPN_GET(table));

            // Try to store this pte
            if (or1k_sync_sc(taddr,dirpte) == 1) {
                // The operation was successful
                break;
            } else {
                // There has been a write access to this PTE

                // Load the pte again. It may have been changed after we loaded
                // it or there was another LL call in between.
                dirpte = or1k_sync_ll(taddr);

                // Check if someone else modified or the store failed for other
                // reasons.
                if (OR1K_PTE_PRESENT_GET(dirpte) == 1) {
                    // Another core added this table. Simply free our
                    // table and continue.
                    free(table);
                    break;
                }
                // Otherwise we simply retry, do the operation again
            }
        }
    } else {
        // There already is a page, load base
        table = (optimsoc_page_table_t) OR1K_PTABLE(dirpte);
    }

    // This is a huge table what we do not support for now
    assert(OR1K_PTE_LAST_GET(dirpte) == 0);

    // Load the address of the pte in the page table
    void *pteaddr = (void*) &table[OR1K_ADDR_L2_INDEX_GET(vaddr)];

    // Load this entry
    pte = or1k_sync_ll(pteaddr);

    if (OR1K_PTE_PRESENT_GET(pte) == 1) {
        // There already is a page mapped
        return 0;
    }

    // Try to set this entry
    while (1) {
        // Get PN from physical address
        uint32_t ppn = OR1K_PTE_PPN_GET(paddr);

        // Assemble pte
        pte = OR1K_PTE_PPN_SET(0, ppn);
        pte = OR1K_PTE_PRESENT_SET(pte, 1);

        // TODO: Allow to set page policies
        // Allow all page accesses
        uint32_t ppi = (1 << OR1K_PTE_PPI_USER_BIT) | \
                (1 << OR1K_PTE_PPI_WRITE_BIT) | (1 << OR1K_PTE_PPI_EXEC_BIT);

        pte = OR1K_PTE_PPI_SET(pte, ppi);

        // Try to write pte
        if (or1k_sync_sc(pteaddr, pte) == 1) {
            // Operation was successful
            break;
        } else {
            // Another write occured
            pte = or1k_sync_ll(pteaddr);

            // Check why this failed
            if (OR1K_PTE_PRESENT_GET(pte) == 1) {
                // Another core added the same address
                return 0;
            }
            // Otherwise just retry
        }
    }

    return 1;
}