iommutsb.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/iommutsb.h>
#include <sys/sysmacros.h>
#include <sys/bootconf.h>
#include <sys/platform_module.h>
/*
* The interfaces provided by this file will eventually no longer
* be required once a physically contiguous memory allocator
* is available.
*/
/*
* The TSB size and consequently the DVMA range is appropriated proportional
* to the physical memory size.
*
* phys_mem_size iommu TSB size DVMA size
* <= 32MB 64KB 64MB
* <= 128MB 256KB 256MB
* <= 512MB 512KB 512MB
* > 512MB 1MB 1GB
*
* NOTE: The original Solaris 8 FCS allocations must be used with
* 32-bit kernels.
*
*/
static uint_t
{
if (phys_mem_size <= 0x1000)
return (0x10000);
else if (phys_mem_size <= 0x4000)
return (0x40000);
else if (phys_mem_size <= 0x10000)
return (0x80000);
else
return (0x100000);
}
/* TSB size must be a power of 2 between the minimum and the maximum. */
#define MIN_TSB_BYTES 0x2000
#define MAX_TSB_BYTES 0x100000
/*
* Use boot to allocate the physically contiguous memory needed for the
* IOMMU's TSB arrays until there is an interface for dynamically
* allocated, physically contiguous memory.
* The number IOMMUs at boot, niommu_tsbs, is set as a side effect
* of map_wellknown_devices(). The number of TSBs allocated is
* at least niommu_tsbs. On platforms supporting Dynamic Reconfiguration
* the platmod routine set_platform_tsb_spares() returns the
* maximum total number of TSBs expected. The final number of TSBs
* allocated is set in iommu_tsb_num.
*
* WARNING - since this routine uses boot to allocate memory, it MUST
* be called before the kernel takes over memory allocation from boot.
*/
#define MAX_IOMMU_PER_AGENT 2
static kmutex_t iommu_tsb_avail_lock;
#define IOMMU_TSB_INUSE 0x8000u
static uint_t iommu_tsb_num;
#ifdef DEBUG
static uint_t iommu_tsb_nfree;
#endif /* DEBUG */
static caddr_t iommu_tsb_base;
static uint_t iommu_tsb_size;
/*
* The following variables can be patched to override the auto-selection
* of dvma space based on the amount of installed physical memory.
* is called.
*/
{
/*
* determine the amount of physical memory required for the TSB arrays
*
* assumes niommu_tsbs has already been initialized, i.e.
* map_wellknown_devices()
*
* TSB space is allocated proportional to memory size (see
* resolve_tsb_size) but later constained by the limit obtained
* from get_dvma_property_limit in the nexus attach.
*/
/* Ensure that min and max are powers of two. */
/* guaranteed min and max are both between MIN/MAX_TSB_BYTES */
/* empty */;
/* empty */;
/* guaranteed min still <= max */
} else
"iommutsb: bad iommu_tsb_size_min/max value pair");
if (&set_platform_tsb_spares)
else
ntsbs = 0;
if (total_size == 0)
return (alloc_base);
/*
* allocate the physical memory for the TSB arrays
*/
#ifdef DEBUG
#endif /* DEBUG */
return (base + total_size);
}
/*
* External allocation interface to the nexus drivers (sbus, pci).
* As an aid to debugging, the upaid or portid is recorded against
* an allocation.
*/
{
uint_t i;
for (i = 0; i < iommu_tsb_num; i++) {
if (iommu_tsb_avail[i] == 0) {
#ifdef DEBUG
ASSERT(iommu_tsb_nfree != 0);
#endif /* DEBUG */
break;
}
}
return (tsbc);
}
void
{
if (iommu_tsb_avail[tsbc] == 0) {
}
iommu_tsb_avail[tsbc] = 0;
#ifdef DEBUG
#endif /* DEBUG */
}
/*ARGSUSED*/
{
return (iommu_tsb_size);
}
uint64_t *
{
}