int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
        uint64_t max_addr,
        uint64_t alignment,
        char *name,
        uint32_t flags)
{
    int64_t addr_allocated;
    struct cvmx_bootmem_named_block_desc *named_block_desc_ptr;

#ifdef DEBUG
    cvmx_dprintf("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: "
                 "0x%llx, max: 0x%llx, align: 0x%llx, name: %s\n",
                 (unsigned long long)size,
                 (unsigned long long)min_addr,
                 (unsigned long long)max_addr,
                 (unsigned long long)alignment,
                 name);
#endif
    if (cvmx_bootmem_desc->major_version != 3) {
        cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: "
                     "%d.%d at addr: %p\n",
                     (int)cvmx_bootmem_desc->major_version,
                     (int)cvmx_bootmem_desc->minor_version,
                     cvmx_bootmem_desc);
        return -1;
    }

    if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
        cvmx_spinlock_lock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));


    named_block_desc_ptr =
        cvmx_bootmem_phy_named_block_find(NULL,
                                          flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);

    if (cvmx_bootmem_phy_named_block_find(name,
                                          flags | CVMX_BOOTMEM_FLAG_NO_LOCKING) || !named_block_desc_ptr) {
        if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
            cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
        return -1;
    }


    size = ALIGN(size, CVMX_BOOTMEM_ALIGNMENT_SIZE);

    addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr,
                                            alignment,
                                            flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);
    if (addr_allocated >= 0) {
        named_block_desc_ptr->base_addr = addr_allocated;
        named_block_desc_ptr->size = size;
        strncpy(named_block_desc_ptr->name, name,
                cvmx_bootmem_desc->named_block_name_len);
        named_block_desc_ptr->name[cvmx_bootmem_desc->named_block_name_len - 1] = 0;
    }

    if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
        cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
    return addr_allocated;
}
Пример #2
0
void *hfa_bootmem_alloc (uint64_t size, uint64_t alignment)
{
    int64_t address;

    address = cvmx_bootmem_phy_alloc(size, 0, 0, alignment, 0);

    if (address > 0)
        return cvmx_phys_to_ptr(address);
    else
        return NULL;
}
void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment,
                               uint64_t min_addr, uint64_t max_addr)
{
    int64_t address;
    address =
        cvmx_bootmem_phy_alloc(size, min_addr, max_addr, alignment, 0);

    if (address > 0)
        return cvmx_phys_to_ptr(address);
    else
        return NULL;
}
Пример #4
0
static void
octeon_memory_init(void)
{
	vm_paddr_t phys_end;
	int64_t addr;
	unsigned i, j;

	phys_end = round_page(MIPS_KSEG0_TO_PHYS((vm_offset_t)&end));

	if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) {
		/* Simulator we limit to 96 meg */
		phys_avail[0] = phys_end;
		phys_avail[1] = 96 << 20;

		dump_avail[0] = phys_avail[0];
		dump_avail[1] = phys_avail[1];

		realmem = physmem = btoc(phys_avail[1] - phys_avail[0]);
		return;
	}

	/*
	 * Allocate memory from bootmem 1MB at a time and merge
	 * adjacent entries.
	 */
	i = 0;
	while (i < PHYS_AVAIL_ENTRIES) {
		/*
		 * If there is less than 2MB of memory available in 128-byte
		 * blocks, do not steal any more memory.  We need to leave some
		 * memory for the command queues to be allocated out of.
		 */
		if (cvmx_bootmem_available_mem(128) < 2 << 20)
			break;

		addr = cvmx_bootmem_phy_alloc(1 << 20, phys_end,
					      ~(vm_paddr_t)0, PAGE_SIZE, 0);
		if (addr == -1)
			break;

		/*
		 * The SDK needs to be able to easily map any memory that might
		 * come to it e.g. in the form of an mbuf.  Because on !n64 we
		 * can't direct-map some addresses and we don't want to manage
		 * temporary mappings within the SDK, don't feed memory that
		 * can't be direct-mapped to the kernel.
		 */
#if !defined(__mips_n64)
		if (!MIPS_DIRECT_MAPPABLE(addr + (1 << 20) - 1))
			continue;
#endif

		physmem += btoc(1 << 20);

		if (i > 0 && phys_avail[i - 1] == addr) {
			phys_avail[i - 1] += 1 << 20;
			continue;
		}

		phys_avail[i + 0] = addr;
		phys_avail[i + 1] = addr + (1 << 20);

		i += 2;
	}

	for (j = 0; j < i; j++)
		dump_avail[j] = phys_avail[j];

	realmem = physmem;
}
Пример #5
0
int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
					   uint64_t max_addr,
					   uint64_t alignment,
					   char *name,
					   uint32_t flags)
{
	int64_t addr_allocated;
	struct cvmx_bootmem_named_block_desc *named_block_desc_ptr;

#ifdef DEBUG
	cvmx_dprintf("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: "
		     "0x%llx, max: 0x%llx, align: 0x%llx, name: %s\n",
		     (unsigned long long)size,
		     (unsigned long long)min_addr,
		     (unsigned long long)max_addr,
		     (unsigned long long)alignment,
		     name);
#endif
	if (cvmx_bootmem_desc->major_version != 3) {
		cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: "
			     "%d.%d at addr: %p\n",
			     (int)cvmx_bootmem_desc->major_version,
			     (int)cvmx_bootmem_desc->minor_version,
			     cvmx_bootmem_desc);
		return -1;
	}

	/*
	 * Take lock here, as name lookup/block alloc/name add need to
	 * be atomic.
	 */
	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
		cvmx_spinlock_lock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));

	/* Get pointer to first available named block descriptor */
	named_block_desc_ptr =
		cvmx_bootmem_phy_named_block_find(NULL,
						  flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);

	/*
	 * Check to see if name already in use, return error if name
	 * not available or no more room for blocks.
	 */
	if (cvmx_bootmem_phy_named_block_find(name,
					      flags | CVMX_BOOTMEM_FLAG_NO_LOCKING) || !named_block_desc_ptr) {
		if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
			cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
		return -1;
	}


	/*
	 * Round size up to mult of minimum alignment bytes We need
	 * the actual size allocated to allow for blocks to be
	 * coallesced when they are freed.  The alloc routine does the
	 * same rounding up on all allocations.
	 */
	size = ALIGN(size, CVMX_BOOTMEM_ALIGNMENT_SIZE);

	addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr,
						alignment,
						flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);
	if (addr_allocated >= 0) {
		named_block_desc_ptr->base_addr = addr_allocated;
		named_block_desc_ptr->size = size;
		strncpy(named_block_desc_ptr->name, name,
			cvmx_bootmem_desc->named_block_name_len);
		named_block_desc_ptr->name[cvmx_bootmem_desc->named_block_name_len - 1] = 0;
	}

	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
		cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
	return addr_allocated;
}