dmar_acpi.c revision 09011d400721fbca9dc5dfabd23419badcc06fc1
/*
* 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
*/
/*
* Portions Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2008, Intel Corporation.
* All rights reserved.
*/
#include <sys/sysmacros.h>
#include <sys/pci_cfgspace.h>
#include <sys/pci_impl.h>
#include <sys/bootconf.h>
#include <sys/int_fmtio.h>
#include <sys/dmar_acpi.h>
/*
* the following pci manipulate function pinter
* are defined in pci_cfgspace.h
*/
#define pci_getb (*pci_getb_func)
/*
* define for debug
*/
int intel_dmar_acpi_debug = 0;
/*
* global varables
*/
/*
* internal varables
*/
static void *dmart;
/*
* helper functions to release the allocated resources
* when failed
*/
static void
{
if (list_is_empty(lp))
return;
}
}
static void
release_drhd_info(void)
{
int i;
for (i = 0; i < DMAR_MAX_SEGMENT; i++) {
if (list_is_empty(lp))
break;
/*
* release the device scope
*/
}
}
}
static void
release_rmrr_info(void)
{
int i;
for (i = 0; i < DMAR_MAX_SEGMENT; i++) {
if (list_is_empty(lp))
break;
}
}
}
/*
* intel_iommu_release_dmar_info()
* global function, which is called to release dmar_info
* when the dmar_intel_iommu_supportinfo is not
* needed any more.
*/
void
{
int i;
/*
* destroy the drhd and rmrr list
*/
for (i = 0; i < DMAR_MAX_SEGMENT; i++) {
}
}
/*
* create_dmar_devi()
*
* create the dev_info node in the device tree,
* the info node is a nuxus child of the root
* nexus
*/
static void
create_dmar_devi(void)
{
struct ddi_parent_private_data *pdptr;
char nodename[64];
int i, j;
for (i = 0; i < DMAR_MAX_SEGMENT; i++) {
/*
* ignore the empty list
*/
break;
/*
* alloc dev_info per drhd unit
*/
j = 0;
DEVI_SID_NODEID, &dip);
reg.regspec_bustype = 0;
/*
* update the reg properties
*
* reg property will be used for register
* set access
*
* refer to the bus_map of root nexus driver
* I/O or memory mapping:
*
* <bustype=0, addr=x, len=x>: memory
* <bustype=1, addr=x, len=x>: i/o
* <bustype>1, addr=0, len=x>: x86-compatibility i/o
*/
sizeof (struct regspec) / sizeof (int));
pdptr = (struct ddi_parent_private_data *)
kmem_zalloc(sizeof (struct ddi_parent_private_data)
}
}
}
/*
* parse_dmar_dev_scope()
* parse the device scope attached to drhd or rmrr
*/
static int
{
int depth;
struct path_to_dev {
} *path;
while (--depth) {
path++;
}
sizeof (pci_dev_scope_t), KM_SLEEP);
return (PARSE_DMAR_SUCCESS);
}
/*
* parse_dmar_rmrr()
* parse the rmrr units in dmar table
*/
static int
{
/*
* for each rmrr, limiaddr must > baseaddr
*/
" baseaddr = 0x%" PRIx64
return (PARSE_DMAR_FAIL);
}
/*
* allocate and setup the device info structure
*/
KM_SLEEP);
/*
* parse the device scope
*/
!= PARSE_DMAR_SUCCESS) {
return (PARSE_DMAR_FAIL);
}
}
/*
* save this info structure
*/
return (PARSE_DMAR_SUCCESS);
}
/*
* parse_dmar_drhd()
* parse the drhd uints in dmar table
*/
static int
{
/*
* assert the segment boundary
*/
/*
* allocate and setup the info structure
*/
/*
* parse the device scope
*/
!= PARSE_DMAR_SUCCESS) {
return (PARSE_DMAR_FAIL);
}
}
return (PARSE_DMAR_SUCCESS);
}
/*
* parse_dmar()
* parse the dmar table
*/
static int
parse_dmar(void)
{
int i;
/*
* do a sanity check
*/
return (PARSE_DMAR_FAIL);
}
/*
* parse each unit
* only DRHD and RMRR are parsed, others are ignored
*/
case DMAR_UNIT_TYPE_DRHD:
if (parse_dmar_drhd(unit_head) !=
/*
* iommu_detect_parse() will release
* all drhd info structure, just
* return false here
*/
return (PARSE_DMAR_FAIL);
}
break;
case DMAR_UNIT_TYPE_RMRR:
if (parse_dmar_rmrr(unit_head) !=
return (PARSE_DMAR_FAIL);
break;
default:
}
((unsigned long)unit_head +
}
#ifdef DEBUG
/*
* make sure the include_all drhd is the
* last drhd in the list, this is only for
* debug
*/
for (i = 0; i < DMAR_MAX_SEGMENT; i++) {
break;
if (drhd->di_include_all &&
!= NULL) {
drhd);
"include_all drhd is adjusted\n");
}
}
}
#endif
return (PARSE_DMAR_SUCCESS);
}
/*
* detect_dmar()
* detect the dmar acpi table
*/
static boolean_t
detect_dmar(void)
{
int len;
char *intel_iommu;
/*
* if "intel-iommu = no" boot property is set,
* ignore intel iommu
*/
return (B_FALSE);
}
}
/*
* get dmar-table from system properties
*/
return (B_FALSE);
}
return (B_TRUE);
}
/*
* print dmar_info for debug
*/
static void
print_dmar_info(void)
{
int i;
/* print the title */
/* print drhd info list */
for (i = 0; i < DMAR_MAX_SEGMENT; i++) {
break;
drhd)) {
drhd->di_segment);
drhd->di_reg_base);
dev)) {
}
}
}
/* print rmrr info list */
for (i = 0; i < DMAR_MAX_SEGMENT; i++) {
break;
rmrr)) {
rmrr->ri_segment);
rmrr->ri_baseaddr);
rmrr->ri_limiaddr);
}
}
}
}
/*
* intel_iommu_probe_and_parse()
* called from rootnex driver
*/
void
{
int i, len;
char *opt;
/*
* retrieve the print-dmar-acpi boot option
*/
}
}
if (detect_dmar() == B_FALSE) {
return;
}
/*
* the platform has intel iommu, setup globals
*/
KM_SLEEP);
for (i = 0; i < DMAR_MAX_SEGMENT; i++) {
}
/*
* parse dmar acpi table
*/
if (parse_dmar() != PARSE_DMAR_SUCCESS) {
return;
}
/*
* create dev_info structure per hrhd
* and prepare it for binding driver
*/
/*
* print the dmar info if the debug
* is set
*/
}