/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
*/
/*
* All rights reserved.
*/
/*
* Copyright (c) 2009, Intel Corporation.
* All rights reserved.
*/
#include <sys/archsystm.h>
#include <sys/sysmacros.h>
/* invalidation queue table entry size */
/* max value of Queue Size field of Invalidation Queue Address Register */
/* status data size of invalidation wait descriptor */
/* invalidation queue head and tail */
/* invalidation queue entry structure */
typedef struct qinv_inv_dsc {
} qinv_dsc_t;
/* physical contigous pages for invalidation queue */
typedef struct qinv_mem {
} qinv_mem_t;
/*
* invalidation queue state
* This structure describes the state information of the
* invalidation queue table and related status memeory for
* invalidation wait descriptor
*
* qinv_table - invalidation queue table
* qinv_sync - sync status memory for invalidation wait descriptor
*/
typedef struct qinv {
} qinv_t;
};
/* helper macro for making queue invalidation descriptor */
#define CC_INV_DSC_HIGH (0)
((uint64_t)(g) << 4) | \
1)
((uint64_t)(g) << 4) | \
2)
3)
#define IEC_INV_DSC_HIGH (0)
((uint64_t)(g) << 4) | \
4)
5)
/*
* QS field of Invalidation Queue Address Register
* the size of invalidation queue is 1 << (qinv_iqa_qs + 8)
*/
/*
* the invalidate desctiptor type of queued invalidation interface
*/
static char *qinv_dsc_type[] = {
"Reserved",
"Context Cache Invalidate Descriptor",
"IOTLB Invalidate Descriptor",
"Device-IOTLB Invalidate Descriptor",
"Interrupt Entry Cache Invalidate Descriptor",
"Invalidation Wait Descriptor",
"Incorrect queue invalidation type"
};
/*
* the queued invalidation interface functions
*/
/*LINTED*/
/* submit invalidation request descriptor to invalidation queue */
static void
{
#ifdef DEBUG
#endif
qinv_table->qinv_mem_tail = 0;
#ifdef DEBUG
count++;
#endif
/*
* inv queue table exhausted, wait hardware to fetch
* next descriptor
*/
}
}
/* queued invalidation interface -- invalidate context cache */
static void
{
}
/* queued invalidation interface -- invalidate iotlb */
static void
{
dr = 1;
dw = 1;
switch (type) {
case TLB_INV_G_PAGE:
addr & IMMU_PAGEOFFSET) {
goto qinv_ignore_psi;
}
break;
case TLB_INV_G_DOMAIN:
break;
case TLB_INV_G_GLOBAL:
break;
default:
return;
}
}
/* queued invalidation interface -- invalidate dev_iotlb */
static void
{
}
/* queued invalidation interface -- invalidate interrupt entry cache */
static void
{
}
/*
* queued invalidation interface -- invalidation wait descriptor
* wait until the invalidation request finished
*/
static void
{
#ifdef DEBUG
#endif
/*
* sdata = IMMU_INV_DATA_DONE, fence = 1, sw = 1, if = 0
* indicate the invalidation wait descriptor completion by
* performing a coherent DWORD write to the status address,
* not by generating an invalidation completion event
*/
#ifdef DEBUG
count = 0;
while (*status != IMMU_INV_DATA_DONE) {
count++;
ht_pause();
}
#else
while (*status != IMMU_INV_DATA_DONE)
ht_pause();
#endif
}
}
static void
{
#ifdef DEBUG
count = 0;
while (*status != IMMU_INV_DATA_DONE) {
count++;
ht_pause();
}
#else
while (*status != IMMU_INV_DATA_DONE)
ht_pause();
#endif
}
/*
* call ddi_dma_mem_alloc to allocate physical contigous
* pages for invalidation queue table
*/
static int
{
0U,
0xffffffffffffffffULL,
0xffffffffU,
MMU_PAGESIZE, /* page aligned */
0x1,
0x1,
0xffffffffU,
0xffffffffffffffffULL,
1,
4,
0
};
};
immu_qinv_enable == B_FALSE) {
return (DDI_SUCCESS);
}
if (qinv_iqa_qs > QINV_MAX_QUEUE_SIZE)
"alloc invalidation queue table handler failed");
}
"alloc invalidation queue sync mem handler failed");
goto sync_table_handle_failed;
}
/* alloc physical contiguous pages for invalidation queue */
size,
NULL,
&size,
"alloc invalidation queue table failed");
goto queue_table_mem_failed;
}
/* get the base physical address of invalidation request queue */
/* alloc status memory for invalidation wait descriptor */
size,
NULL,
&size,
"alloc invalidation queue sync mem failed");
goto sync_table_mem_failed;
}
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
/*
* ###########################################################################
*
* Functions exported by immu_qinv.c
*
* ###########################################################################
*/
/*
* initialize invalidation request queue structure.
*/
int
{
int nerr;
if (immu_qinv_enable == B_FALSE) {
return (DDI_FAILURE);
}
nerr = 0;
} else {
nerr++;
break;
}
}
}
void
{
return;
}
}
/*
* queued invalidation interface
* function based context cache invalidation
*/
void
{
}
/*
* queued invalidation interface
* domain based context cache invalidation
*/
void
{
}
/*
* queued invalidation interface
* invalidation global context cache
*/
void
{
}
/*
* queued invalidation interface
* paged based iotlb invalidation
*/
void
{
/* choose page specified invalidation */
<= ADDR_AM_MAX(am)) {
break;
}
am++;
}
}
/* choose domain invalidation */
} else {
0, hint, TLB_INV_G_DOMAIN);
}
}
/*
* queued invalidation interface
* domain based iotlb invalidation
*/
void
{
}
/*
* queued invalidation interface
* global iotlb invalidation
*/
void
{
}
/* queued invalidation interface -- global invalidate interrupt entry cache */
void
{
}
/* queued invalidation interface -- invalidate single interrupt entry cache */
void
{
}
/* queued invalidation interface -- invalidate interrupt entry caches */
void
{
/* requested interrupt count is not a power of 2 */
for (i = 0; i < cnt; i++) {
}
return;
}
mask++;
}
for (i = 0; i < cnt; i++) {
}
return;
}
}
void
{
/* access qinv data */
+ (head * QINV_ENTRY_SIZE));
/* report the error */
"generated a fault when fetching a descriptor from the"
"\tinvalidation queue, or detects that the fetched"
"\tdescriptor is invalid. The head register is "
"0x%" PRIx64
"\tthe type is %s",
head,
}