⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iommu_acpi.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
                                    ivhd_block->cap_offset);    if ( !iommu )    {        amd_iov_error("IVHD Error: No IOMMU for Dev_Id 0x%x  Cap 0x%x\n",                ivhd_block->header.dev_id, ivhd_block->cap_offset);        return -ENODEV;    }    /* parse Device Entries */    block_length = sizeof(struct acpi_ivhd_block_header);    while ( ivhd_block->header.length >=            (block_length + sizeof(struct acpi_ivhd_device_header)) )    {        ivhd_device = (union acpi_ivhd_device *)            ((u8 *)ivhd_block + block_length);        amd_iov_info( "IVHD Device Entry:\n");        amd_iov_info( " Type 0x%x\n", ivhd_device->header.type);        amd_iov_info( " Dev_Id 0x%x\n", ivhd_device->header.dev_id);        amd_iov_info( " Flags 0x%x\n", ivhd_device->header.flags);        switch ( ivhd_device->header.type )        {        case AMD_IOMMU_ACPI_IVHD_DEV_U32_PAD:            dev_length = parse_ivhd_device_padding(                sizeof(u32),                ivhd_block->header.length, block_length);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_U64_PAD:            dev_length = parse_ivhd_device_padding(                sizeof(u64),                ivhd_block->header.length, block_length);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_SELECT:            dev_length = parse_ivhd_device_select(ivhd_device, iommu);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START:            dev_length = parse_ivhd_device_range(                ivhd_device,                ivhd_block->header.length, block_length, iommu);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT:            dev_length = parse_ivhd_device_alias(                ivhd_device,                ivhd_block->header.length, block_length, iommu);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE:            dev_length = parse_ivhd_device_alias_range(                ivhd_device,                ivhd_block->header.length, block_length, iommu);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT:            dev_length = parse_ivhd_device_extended(                ivhd_device,                ivhd_block->header.length, block_length, iommu);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE:            dev_length = parse_ivhd_device_extended_range(                ivhd_device,                ivhd_block->header.length, block_length, iommu);            break;        default:            amd_iov_error("IVHD Error: Invalid Device Type!\n");            dev_length = 0;            break;        }        block_length += dev_length;        if ( !dev_length )            return -ENODEV;    }    return 0;}static int __init parse_ivrs_block(struct acpi_ivrs_block_header *ivrs_block){    struct acpi_ivhd_block_header *ivhd_block;    struct acpi_ivmd_block_header *ivmd_block;    switch ( ivrs_block->type )    {    case AMD_IOMMU_ACPI_IVHD_TYPE:        ivhd_block = (struct acpi_ivhd_block_header *)ivrs_block;        return parse_ivhd_block(ivhd_block);    case AMD_IOMMU_ACPI_IVMD_ALL_TYPE:    case AMD_IOMMU_ACPI_IVMD_ONE_TYPE:    case AMD_IOMMU_ACPI_IVMD_RANGE_TYPE:    case AMD_IOMMU_ACPI_IVMD_IOMMU_TYPE:        ivmd_block = (struct acpi_ivmd_block_header *)ivrs_block;        return parse_ivmd_block(ivmd_block);    default:        amd_iov_error("IVRS Error: Invalid Block Type!\n");        return -ENODEV;    }    return 0;}static void __init dump_acpi_table_header(struct acpi_table_header *table){#ifdef AMD_IOV_DEBUG    int i;    amd_iov_info("ACPI Table:\n");    amd_iov_info(" Signature ");    for ( i = 0; i < ACPI_NAME_SIZE; i++ )        printk("%c", table->signature[i]);    printk("\n");    amd_iov_info(" Length 0x%x\n", table->length);    amd_iov_info(" Revision 0x%x\n", table->revision);    amd_iov_info(" CheckSum 0x%x\n", table->checksum);    amd_iov_info(" OEM_Id ");    for ( i = 0; i < ACPI_OEM_ID_SIZE; i++ )        printk("%c", table->oem_id[i]);    printk("\n");    amd_iov_info(" OEM_Table_Id ");    for ( i = 0; i < ACPI_OEM_TABLE_ID_SIZE; i++ )        printk("%c", table->oem_table_id[i]);    printk("\n");    amd_iov_info(" OEM_Revision 0x%x\n", table->oem_revision);    amd_iov_info(" Creator_Id ");    for ( i = 0; i < ACPI_NAME_SIZE; i++ )        printk("%c", table->asl_compiler_id[i]);    printk("\n");    amd_iov_info(" Creator_Revision 0x%x\n",           table->asl_compiler_revision);#endif}static int __init parse_ivrs_table(struct acpi_table_header *_table){    struct acpi_ivrs_block_header *ivrs_block;    unsigned long length;    int error = 0;    struct acpi_table_header *table = (struct acpi_table_header *)_table;    BUG_ON(!table);    dump_acpi_table_header(table);    /* parse IVRS blocks */    length = sizeof(struct acpi_ivrs_table_header);    while ( (error == 0) && (table->length > (length + sizeof(*ivrs_block))) )    {        ivrs_block = (struct acpi_ivrs_block_header *)            ((u8 *)table + length);        amd_iov_info("IVRS Block:\n");        amd_iov_info(" Type 0x%x\n", ivrs_block->type);        amd_iov_info(" Flags 0x%x\n", ivrs_block->flags);        amd_iov_info(" Length 0x%x\n", ivrs_block->length);        amd_iov_info(" Dev_Id 0x%x\n", ivrs_block->dev_id);        if ( table->length < (length + ivrs_block->length) )        {            amd_iov_error("IVRS Error: "                    "Table Length Exceeded: 0x%x -> 0x%lx\n",                    table->length,                    (length + ivrs_block->length));            return -ENODEV;        }        error = parse_ivrs_block(ivrs_block);        length += ivrs_block->length;    }    return error;}static int __init detect_iommu_acpi(struct acpi_table_header *_table){    struct acpi_ivrs_block_header *ivrs_block;    struct acpi_table_header *table = (struct acpi_table_header *)_table;    unsigned long i;    unsigned long length = sizeof(struct acpi_ivrs_table_header);    u8 checksum, *raw_table;    /* validate checksum: sum of entire table == 0 */    checksum = 0;    raw_table = (u8 *)table;    for ( i = 0; i < table->length; i++ )        checksum += raw_table[i];    if ( checksum )    {        amd_iov_error("IVRS Error: "                "Invalid Checksum 0x%x\n", checksum);        return -ENODEV;    }    while ( table->length > (length + sizeof(*ivrs_block)) )    {        ivrs_block = (struct acpi_ivrs_block_header *) ((u8 *)table + length);        if ( table->length < (length + ivrs_block->length) )            return -ENODEV;        if ( ivrs_block->type == AMD_IOMMU_ACPI_IVHD_TYPE )            if ( amd_iommu_detect_one_acpi((void*)ivrs_block) != 0 )                return -ENODEV;        length += ivrs_block->length;    }    return 0;}#define UPDATE_LAST_BDF(x) do {\   if ((x) > last_bdf) \       last_bdf = (x); \   } while(0);static int __init get_last_bdf_ivhd(void *ivhd){    union acpi_ivhd_device *ivhd_device;    u16 block_length, dev_length;    struct acpi_ivhd_block_header *ivhd_block;    ivhd_block = (struct acpi_ivhd_block_header *)ivhd;    if ( ivhd_block->header.length <         sizeof(struct acpi_ivhd_block_header) )    {        amd_iov_error("IVHD Error: Invalid Block Length!\n");        return -ENODEV;    }    block_length = sizeof(struct acpi_ivhd_block_header);    while ( ivhd_block->header.length >=            (block_length + sizeof(struct acpi_ivhd_device_header)) )    {        ivhd_device = (union acpi_ivhd_device *)            ((u8 *)ivhd_block + block_length);        switch ( ivhd_device->header.type )        {        case AMD_IOMMU_ACPI_IVHD_DEV_U32_PAD:            dev_length = sizeof(u32);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_U64_PAD:            dev_length = sizeof(u64);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_SELECT:            UPDATE_LAST_BDF(ivhd_device->header.dev_id);            dev_length = sizeof(struct acpi_ivhd_device_header);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT:            UPDATE_LAST_BDF(ivhd_device->header.dev_id);            dev_length = sizeof(struct acpi_ivhd_device_alias);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT:            UPDATE_LAST_BDF(ivhd_device->header.dev_id);            dev_length = sizeof(struct acpi_ivhd_device_extended);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START:            UPDATE_LAST_BDF(ivhd_device->range.trailer.dev_id);            dev_length = sizeof(struct acpi_ivhd_device_range);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE:            UPDATE_LAST_BDF(ivhd_device->alias_range.trailer.dev_id)            dev_length = sizeof(struct acpi_ivhd_device_alias_range);            break;        case AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE:            UPDATE_LAST_BDF(ivhd_device->extended_range.trailer.dev_id)            dev_length = sizeof(struct acpi_ivhd_device_extended_range);            break;        default:            amd_iov_error("IVHD Error: Invalid Device Type!\n");            dev_length = 0;            break;        }        block_length += dev_length;        if ( !dev_length )            return -ENODEV;    }    return 0;}static int __init get_last_bdf_acpi(struct acpi_table_header *_table){    struct acpi_ivrs_block_header *ivrs_block;    struct acpi_table_header *table = (struct acpi_table_header *)_table;    unsigned long length = sizeof(struct acpi_ivrs_table_header);    while ( table->length > (length + sizeof(*ivrs_block)) )    {        ivrs_block = (struct acpi_ivrs_block_header *) ((u8 *)table + length);        if ( table->length < (length + ivrs_block->length) )            return -ENODEV;        if ( ivrs_block->type == AMD_IOMMU_ACPI_IVHD_TYPE )            if ( get_last_bdf_ivhd((void*)ivrs_block) != 0 )                return -ENODEV;        length += ivrs_block->length;    }   return 0;}int __init amd_iommu_detect_acpi(void){    return acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, detect_iommu_acpi);}int __init amd_iommu_get_ivrs_dev_entries(void){    acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, get_last_bdf_acpi);    return last_bdf + 1;}int __init amd_iommu_update_ivrs_mapping_acpi(void){    return acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, parse_ivrs_table);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -