github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/include/hw/vtd_hw_layer.h (about)

     1  /*
     2   * Copyright (c) 2013 Intel Corporation
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *     http://www.apache.org/licenses/LICENSE-2.0
     8   * Unless required by applicable law or agreed to in writing, software
     9   * distributed under the License is distributed on an "AS IS" BASIS,
    10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11   * See the License for the specific language governing permissions and
    12   * limitations under the License.
    13   */
    14  
    15  #ifndef _VTD_HW_LAYER
    16  #define _VTD_HW_LAYER
    17  
    18  #include "vtd.h"
    19  #include "hw_utils.h"
    20  
    21  #pragma warning(push)
    22  #pragma warning(disable:4214)
    23  
    24  typedef union _DMA_REMAPPING_ROOT_ENTRY_LOW
    25  {
    26      struct
    27      {
    28          UINT32
    29              present:1,
    30              reserved:11,
    31              context_entry_table_ptr_low:20;
    32          UINT32 context_entry_table_ptr_high;
    33      } bits;
    34      UINT64 uint64;
    35  } DMA_REMAPPING_ROOT_ENTRY_LOW;
    36  
    37  typedef union _DMA_REMAPPING_ROOT_ENTRY_HIGH
    38  {
    39      struct
    40      {
    41          UINT64 reserved;
    42      } bits;
    43      UINT64 uint64;
    44  } DMA_REMAPPING_ROOT_ENTRY_HIGH;
    45  
    46  typedef struct _DMA_REMAPPING_ROOT_ENTRY
    47  {
    48      DMA_REMAPPING_ROOT_ENTRY_LOW low;
    49      DMA_REMAPPING_ROOT_ENTRY_HIGH high;
    50  } DMA_REMAPPING_ROOT_ENTRY;
    51  
    52  typedef enum
    53  {
    54      TRANSLATION_TYPE_UNTRANSLATED_ADDRESS_ONLY = 0,
    55      TRANSLATION_TYPE_ALL,
    56      TRANSLATION_TYPE_PASSTHROUGH_UNTRANSLATED_ADDRESS
    57  } DMA_REMAPPING_TRANSLATION_TYPE;
    58  
    59  typedef enum
    60  {
    61      DMA_REMAPPING_GAW_30 = 0,
    62      DMA_REMAPPING_GAW_39,
    63      DMA_REMAPPING_GAW_48,
    64      DMA_REMAPPING_GAW_57,
    65      DMA_REMAPPING_GAW_64
    66  } DMA_REMAPPING_GUEST_ADDRESS_WIDTH;
    67  
    68  typedef union _DMA_REMAPPING_CONTEXT_ENTRY_LOW
    69  {
    70      struct
    71      {
    72          UINT32
    73              present:1,
    74              fault_processing_disable:1,
    75              translation_type:2,
    76              eviction_hint:1,             // 0 = default, 1 = eager eviction
    77              adress_locality_hint:1,      // 0 = default, 1 = requests have spatial locality
    78              reserved:6,
    79              address_space_root_low:20;
    80          UINT32 address_space_root_high;
    81      } bits;
    82      UINT64 uint64;
    83  } DMA_REMAPPING_CONTEXT_ENTRY_LOW;
    84  
    85  typedef union _DMA_REMAPPING_CONTEXT_ENTRY_HIGH
    86  {
    87      struct
    88      {
    89          UINT32
    90              address_width:3,
    91              available:4,
    92              reserved0:1,
    93              domain_id:16,
    94              reserved1:8;
    95          UINT32 reserved;
    96      } bits;
    97      UINT64 uint64;
    98  } DMA_REMAPPING_CONTEXT_ENTRY_HIGH;
    99  
   100  typedef struct _DMA_REMAPPING_CONTEXT_ENTRY
   101  {
   102      DMA_REMAPPING_CONTEXT_ENTRY_LOW low;
   103      DMA_REMAPPING_CONTEXT_ENTRY_HIGH high;
   104  } DMA_REMAPPING_CONTEXT_ENTRY;
   105  
   106  typedef union _DMA_REMAPPING_PAGE_TABLE_ENTRY
   107  {
   108      struct
   109      {
   110          UINT32
   111              read:1,
   112              write:1,
   113              available0:5,
   114              super_page:1,
   115              available:3,
   116              snoop_behavior:1, // 0 = default, 1 = treat as snooped
   117              address_low:20;
   118          UINT32
   119              address_high:30,
   120              transient_mapping:1,
   121              available1:1;
   122      } bits;
   123      UINT64 uint64;
   124  } DMA_REMAPPING_PAGE_TABLE_ENTRY;
   125  
   126  typedef union _DMA_REMAPPING_FAULT_RECORD_LOW
   127  {
   128      struct
   129      {
   130          UINT32
   131              reserved:12,
   132              fault_information_low:20;
   133          UINT32 fault_information_high;
   134      } bits;
   135      UINT64 uint64;
   136  } DMA_REMAPPING_FAULT_RECORD_LOW;
   137  
   138  typedef union _DMA_REMAPPING_FAULT_RECORD_HIGH
   139  {
   140      struct
   141      {
   142          UINT32
   143              source_id:16,
   144              reserved0:16;
   145          UINT32
   146              fault_reason:8,
   147              reserved1:20,
   148              address_type:2,
   149              access_type:1, // 0 = write, 1 = read
   150              reserved2:1;
   151      } bits;
   152      UINT64 uint64;
   153  } DMA_REMAPPING_FAULT_RECORD_HIGH;
   154  
   155  typedef struct _DMA_REMAPPING_FAULT_RECORD
   156  {
   157      DMA_REMAPPING_FAULT_RECORD_LOW low;
   158      DMA_REMAPPING_FAULT_RECORD_HIGH high;
   159  } DMA_REMAPPING_FAULT_RECORD;
   160  
   161  typedef enum
   162  {
   163      SOURCE_ID_QUALIFIER_ALL = 0,
   164      SOURCE_ID_QUALIFIER_IGNORE_FUNCTION_MSB,
   165      SOURCE_ID_QUALIFIER_IGNORE_2_FUNCTION_MSB,
   166      SOURCE_ID_QUALIFIER_IGNORE_FUNCTION
   167  } INTERRUPT_REMAPPING_SOURCE_ID_QUALIFIER;
   168  
   169  typedef enum
   170  {
   171      SOURCE_ID_VALIDATION_NONE,
   172      SOURCE_ID_VALIDATION_AS_BDF,
   173      SOURCE_ID_VALIDATION_BUS_IN_RANGE
   174  } INTERRUPT_REMAPPING_SOURCE_ID_VALIDATION_TYPE;
   175  
   176  typedef union _INTERRUPT_REMAPPING_TABLE_ENTRY_LOW
   177  {
   178      struct
   179      {
   180          UINT32
   181              present:1,
   182              fault_processing_disable:1,
   183              destination_mode:1, // 0 = physical APIC ID, 1 = logical APIC ID
   184              redirection_hint:1, // 0 = direct to CPU in destination id field, 1 = direct to one CPU from the group
   185              trigger_mode:1, // 0 = edge, 1 = level
   186              delivery_mode:1,
   187              available:4,
   188              reserved:4;
   189          UINT32 destination_id;
   190       } bits;
   191      UINT64 uint64;
   192  } INTERRUPT_REMAPPING_TABLE_ENTRY_LOW;
   193  
   194  typedef union _INTERRUPT_REMAPPING_TABLE_ENTRY_HIGH
   195  {
   196      struct
   197      {
   198          UINT32
   199              source_id:16,
   200              source_id_qualifier:2,
   201              source_validation_type:2,
   202              reserved0:12;
   203          UINT32 reserved1;
   204       } bits;
   205      UINT64 uint64;
   206  } INTERRUPT_REMAPPING_TABLE_ENTRY_HIGH;
   207  
   208  typedef struct _INTERRUPT_REMAPPING_TABLE_ENTRY
   209  {
   210      INTERRUPT_REMAPPING_TABLE_ENTRY_LOW low;
   211      INTERRUPT_REMAPPING_TABLE_ENTRY_HIGH high;
   212  } INTERRUPT_REMAPPING_TABLE_ENTRY;
   213  
   214  // vtd registers
   215  #define VTD_VERSION_REGISTER_OFFSET                                         0x0000
   216  #define VTD_CAPABILITY_REGISTER_OFFSET                                      0x0008
   217  #define VTD_EXTENDED_CAPABILITY_REGISTER_OFFSET                             0x0010
   218  #define VTD_GLOBAL_COMMAND_REGISTER_OFFSET                                  0x0018
   219  #define VTD_GLOBAL_STATUS_REGISTER_OFFSET                                   0x001C
   220  #define VTD_ROOT_ENTRY_TABLE_ADDRESS_REGISTER_OFFSET                        0x0020
   221  #define VTD_CONTEXT_COMMAND_REGISTER_OFFSET                                 0x0028
   222  #define VTD_FAULT_STATUS_REGISTER_OFFSET                                    0x0034
   223  #define VTD_FAULT_EVENT_CONTROL_REGISTER_OFFSET                             0x0038
   224  #define VTD_FAULT_EVENT_DATA_REGISTER_OFFSET                                0x003C
   225  #define VTD_FAULT_EVENT_ADDRESS_REGISTER_OFFSET                             0x0040
   226  #define VTD_FAULT_EVENT_ADDRESS_HIGH_REGISTER_OFFSET                        0x0044
   227  #define VTD_ADVANCED_FAULT_LOG_REGISTER_OFFSET                              0x0058
   228  #define VTD_PROTECTED_MEMORY_ENABLE_REGISTER_OFFSET                         0x0064
   229  #define VTD_PROTECTED_LOW_MEMORY_BASE_REGISTER_OFFSET                       0x0068
   230  #define VTD_PROTECTED_LOW_MEMORY_LIMIT_REGISTER_OFFSET                      0x006C
   231  #define VTD_PROTECTED_HIGH_MEMORY_BASE_REGISTER_OFFSET                      0x0070
   232  #define VTD_PROTECTED_HIGH_MEMORY_LIMIT_REGISTER_OFFSET                     0x0078
   233  #define VTD_INVALIDATION_QUEUE_HEAD_REGISTER_OFFSET                         0x0080
   234  #define VTD_INVALIDATION_QUEUE_TAIL_REGISTER_OFFSET                         0x0088
   235  #define VTD_INVALIDATION_QUEUE_ADDRESS_REGISTER_OFFSET                      0x0090
   236  #define VTD_INVALIDATION_COMPLETION_STATUS_REGISTER_OFFSET                  0x009C
   237  #define VTD_INVALIDATION_COMPLETION_EVENT_CONTROL_REGISTER_OFFSET           0x00A0
   238  #define VTD_INVALIDATION_COMPLETION_EVENT_DATA_REGISTER_OFFSET              0x00A4
   239  #define VTD_INVALIDATION_COMPLETION_EVENT_ADDRESS_REGISTER_OFFSET           0x00A8
   240  #define VTD_INVALIDATION_COMPLETION_EVENT_ADDRESS_HIGH_REGISTER_OFFSET      0x00AC
   241  #define VTD_INTERRUPT_REMAPPING_TABLE_ADDRESS_REGISTER_OFFSET               0x00A0
   242  
   243  // definition for "Snoop Behavior" and "Transient Mapping" filds in VT-d page tables
   244  #define VTD_SNPB_SNOOPED			1
   245  #define VTD_NON_SNPB_SNOOPED		0
   246  #define VTD_TRANSIENT_MAPPING		1
   247  #define VTD_NON_TRANSIENT_MAPPING	0
   248  
   249  typedef union
   250  {
   251      struct
   252      {
   253          UINT32 minor:4;
   254          UINT32 major:4;
   255          UINT32 reserved:24;
   256      } bits;
   257      UINT32 uint32;
   258  } VTD_VERSION_REGISTER;
   259  
   260  typedef enum
   261  {
   262      VTD_NUMBER_OF_SUPPORTED_DOMAINS_16 = 0,
   263      VTD_NUMBER_OF_SUPPORTED_DOMAINS_64,
   264      VTD_NUMBER_OF_SUPPORTED_DOMAINS_256,
   265      VTD_NUMBER_OF_SUPPORTED_DOMAINS_1024,
   266      VTD_NUMBER_OF_SUPPORTED_DOMAINS_4K,
   267      VTD_NUMBER_OF_SUPPORTED_DOMAINS_16K,
   268      VTD_NUMBER_OF_SUPPORTED_DOMAINS_64K
   269  } VTD_NUMBER_OF_SUPPORTED_DOMAINS;
   270  
   271  #define VTD_SUPER_PAGE_SUPPORT_21(sp_support)           ((sp_support) & 0x0001)
   272  #define VTD_SUPER_PAGE_SUPPORT_30(sp_support)           ((sp_support) & 0x0010)
   273  #define VTD_SUPER_PAGE_SUPPORT_39(sp_support)           ((sp_support) & 0x0100)
   274  #define VTD_SUPER_PAGE_SUPPORT_48(sp_support)           ((sp_support) & 0x1000)
   275  
   276  typedef union
   277  {
   278      struct
   279      {
   280          UINT32
   281              number_of_domains:3,
   282              advanced_fault_log:1,
   283              required_write_buffer_flush:1,
   284              protected_low_memory_region:1,   // 0 = not supported, 1 = supported
   285              protected_high_memory_region:1,  // 0 = not supported, 1 = supported
   286              caching_mode:1,
   287              adjusted_guest_address_width:5,
   288              reserved0:3,
   289              max_guest_address_width:6,
   290              zero_length_read:1,
   291              isochrony:1,
   292              fault_recording_register_offset_low:8;
   293          UINT32
   294              fault_recording_register_offset_high:2,
   295              super_page_support:4,
   296              reserved1:1,
   297              page_selective_invalidation:1, // 0 = not supported (only global and domain), 1 = supported
   298              number_of_fault_recording_registers:8,
   299              max_address_mask_value:6,
   300              dma_write_draining:1, // 0 = not supported, 1 = supported
   301              dma_read_draining:1, // 0 = not supported, 1 = supported
   302              reserved2:8;
   303      } bits;
   304      UINT64 uint64;
   305  } VTD_CAPABILITY_REGISTER;
   306  
   307  typedef union
   308  {
   309      struct
   310      {
   311          UINT32
   312              coherency:1, // 0 = not-snooped, 1 = snooped
   313              queued_invalidation:1, // 0 = not-supported, 1 = supported
   314              device_iotlb:1,
   315              interrupt_remapping:1,
   316              extended_interrupt_mode:1, // 0 = 8-bit APIC id, 1 = 16-bit (x2APIC)
   317              caching_hints:1,
   318              pass_through:1,
   319              snoop_control:1,
   320              iotlb_register_offset:10,
   321              reserved0:2,
   322              max_handle_mask_value:4,
   323              reserved1:8;
   324          UINT32 reserved2;
   325      } bits;
   326      UINT64 uint64;
   327  } VTD_EXTENDED_CAPABILITY_REGISTER;
   328  
   329  typedef union
   330  {
   331      struct
   332      {
   333          UINT32 reserved0:23;
   334          UINT32 compatibility_format_interrupt:1; // 0 = block; 1 = pass-through
   335          UINT32 set_interrupt_remap_table_ptr:1;
   336          UINT32 interrupt_remap_enable:1;
   337          UINT32 queued_invalidation_enable:1;
   338          UINT32 write_buffer_flush:1;
   339          UINT32 advanced_fault_log_enable:1;
   340          UINT32 set_advanced_fault_log_ptr:1;
   341          UINT32 set_root_table_ptr:1;
   342          UINT32 translation_enable:1;
   343      } bits;
   344      UINT32 uint32;
   345  } VTD_GLOBAL_COMMAND_REGISTER;
   346  
   347  typedef union
   348  {
   349      struct
   350      {
   351          UINT32 reserved0:23;
   352          UINT32 compatibility_format_interrupt_status:1;
   353          UINT32 interrupt_remap_table_ptr_status:1;
   354          UINT32 interrupt_remap_enable_status:1;
   355          UINT32 queued_invalidation_enable_status:1;
   356          UINT32 write_buffer_flush_status:1;
   357          UINT32 advanced_fault_log_enable_status:1;
   358          UINT32 advanced_fault_log_ptr_status:1;
   359          UINT32 root_table_ptr_status:1;
   360          UINT32 translation_enable_status:1;
   361      } bits;
   362      UINT32 uint32;
   363  } VTD_GLOBAL_STATUS_REGISTER;
   364  
   365  typedef union
   366  {
   367      struct
   368      {
   369          UINT32
   370              reserved:12,
   371              address_low:20;
   372          UINT32 address_high;
   373      } bits;
   374      UINT64 uint64;
   375  } VTD_ROOT_ENTRY_TABLE_ADDRESS_REGISTER;
   376  
   377  typedef enum
   378  {
   379      VTD_CONTEXT_INV_GRANULARITY_GLOBAL = 0x1,
   380      VTD_CONTEXT_INV_GRANULARITY_DOMAIN = 0x2,
   381      VTD_CONTEXT_INV_GRANULARITY_DEVICE = 0x3
   382  } VTD_CONTEXT_INV_GRANULARITY;
   383  
   384  typedef union
   385  {
   386      struct
   387      {
   388          UINT32
   389              domain_id:16,
   390              source_id:16;
   391          UINT32
   392              function_mask:2,
   393              reserved:25,
   394              context_actual_invld_granularity:2,
   395              context_invld_request_granularity:2,
   396              invalidate_context_cache:1;
   397      } bits;
   398      UINT64 uint64;
   399  } VTD_CONTEXT_COMMAND_REGISTER;
   400  
   401  typedef enum
   402  {
   403      VTD_IOTLB_INV_GRANULARITY_GLOBAL = 0x1,
   404      VTD_IOTLB_INV_GRANULARITY_DOMAIN = 0x2,
   405      VTD_IOTLB_INV_GRANULARITY_PAGE = 0x3
   406  } VTD_IOTLB_INV_GRANULARITY;
   407  
   408  typedef union
   409  {
   410      struct
   411      {
   412          UINT32 reserved0;
   413          UINT32 domain_id:16,
   414                 drain_writes:1,
   415                 drain_reads:1,
   416                 reserved1:7,
   417                 iotlb_actual_invld_granularity:3,
   418                 iotlb_invld_request_granularity:3,
   419                 invalidate_iotlb:1;
   420      } bits;
   421      UINT64 uint64;
   422  } VTD_IOTLB_INVALIDATE_REGISTER;
   423  
   424  typedef union
   425  {
   426      struct
   427      {
   428          UINT32
   429              address_mask:6,
   430              invalidation_hint:1,
   431              reserved:5,
   432              address_low:20;
   433          UINT32 address_high;
   434      } bits;
   435      UINT64 uint64;
   436  } VTD_INVALIDATE_ADDRESS_REGISTER;
   437  
   438  typedef union
   439  {
   440      struct
   441      {
   442          UINT32 fault_overflow:1;
   443          UINT32 primary_pending_fault:1;
   444          UINT32 advanced_fault_overflow:1;
   445          UINT32 advanced_pending_fault:1;
   446          UINT32 invalidation_queue_error:1;
   447          UINT32 invalidation_completion_error:1;
   448          UINT32 invalidation_timeout_error:1;
   449          UINT32 reserved0:1;
   450          UINT32 fault_record_index:8;
   451          UINT32 reserved1:16;
   452      } bits;
   453      UINT32 uint32;
   454  } VTD_FAULT_STATUS_REGISTER;
   455  
   456  typedef union
   457  {
   458      struct
   459      {
   460          UINT32 reserved:30;
   461          UINT32 interrupt_pending:1;
   462          UINT32 interrupt_mask:1;
   463      } bits;
   464      UINT32 uint32;
   465  } VTD_FAULT_EVENT_CONTROL_REGISTER;
   466  
   467  typedef union
   468  {
   469      struct
   470      {
   471          UINT32 vector:8;
   472          UINT32 delivery_mode:3; // 0 = fixed; 1=lowest priority
   473          UINT32 reserved:3;
   474          UINT32 trigger_mode_level:1;
   475          UINT32 trigger_mode:1;
   476          UINT32 reserved1:18;
   477      } bits;
   478      UINT32 uint32;
   479  } VTD_FAULT_EVENT_DATA_REGISTER;
   480  
   481  typedef union
   482  {
   483      struct
   484      {
   485          UINT32 reserved0:2;
   486          UINT32 destination_mode:1;
   487          UINT32 redirection_hint:1;
   488          UINT32 reserved1:8;
   489          UINT32 destination_id:8;
   490          UINT32 reserved2:12; // reserved to 0xfee
   491      } bits;
   492      UINT32 uint32;
   493  } VTD_FAULT_EVENT_ADDRESS_REGISTER;
   494  
   495  typedef struct
   496  {
   497      UINT32 reserved;
   498  } VTD_FAULT_EVENT_UPPER_ADDRESS_REGISTER;
   499  
   500  typedef union
   501  {
   502      struct
   503      {
   504          UINT32
   505              reserved:12,
   506              fault_info_low:20;
   507          UINT32 fault_info_high;
   508      } bits;
   509      UINT64 uint64;
   510  } VTD_FAULT_RECORDING_REGISTER_LOW;
   511  
   512  typedef union
   513  {
   514      struct
   515      {
   516          UINT32
   517              source_id:16,
   518              reserved0:16;
   519          UINT32
   520              fault_reason:8,
   521              reserved1:20,
   522              address_type:2,
   523              request_type:1, // 0 = write; 1 = read
   524              fault:1;
   525      } bits;
   526      UINT64 uint64;
   527  } VTD_FAULT_RECORDING_REGISTER_HIGH;
   528  
   529  typedef struct
   530  {
   531      VTD_FAULT_RECORDING_REGISTER_LOW low;
   532      VTD_FAULT_RECORDING_REGISTER_HIGH high;
   533  } VTD_FAULT_RECORDING_REGISTER;
   534  
   535  typedef union
   536  {
   537      struct
   538      {
   539          UINT32
   540              reserved:9,
   541              fault_log_size:3,
   542              fault_log_address_low:20;
   543          UINT32 fault_log_address_high;
   544      } bits;
   545      UINT64 uint64;
   546  } VTD_ADVANCED_FAULT_LOG_REGISTER;
   547  
   548  typedef union
   549  {
   550      struct
   551      {
   552          UINT32 protected_region_status:1;
   553          UINT32 reserved_p:30;
   554          UINT32 enable_protected_memory:1;
   555      } bits;
   556      UINT32 uint32;
   557  } VTD_PROTECTED_MEMORY_ENABLE_REGISTER;
   558  
   559  typedef union
   560  {
   561      struct
   562      {
   563          UINT32
   564              reserved0:4,
   565              queue_head:15, // 128-bit aligned
   566              reserved1:13;
   567          UINT32 reserved2;
   568      } bits;
   569      UINT64 uint64;
   570  } VTD_INVALIDATION_QUEUE_HEAD_REGISTER;
   571  
   572  typedef union
   573  {
   574      struct
   575      {
   576          UINT32
   577              reserved0:4,
   578              queue_tail:15, // 128-bit aligned
   579              reserved1:13;
   580          UINT32 reserved2;
   581      } bits;
   582      UINT64 uint64;
   583  } VTD_INVALIDATION_QUEUE_TAIL_REGISTER;
   584  
   585  typedef union
   586  {
   587      struct
   588      {
   589          UINT32
   590              queue_size:3,
   591              reserved:9,
   592              queue_base_low:20;
   593          UINT32 queue_base_high;
   594      } bits;
   595      UINT64 uint64;
   596  } VTD_INVALIDATION_QUEUE_ADDRESS_REGISTER;
   597  
   598  typedef union
   599  {
   600      struct
   601      {
   602          UINT32 wait_descriptor_complete:1;
   603          UINT32 reserved:31;
   604      } bits;
   605      UINT32 uint32;
   606  } VTD_INVALIDATION_COMPLETION_STATUS_REGISTER;
   607  
   608  typedef union
   609  {
   610      struct
   611      {
   612          UINT32 reserved:30;
   613          UINT32 interrupt_pending:1;
   614          UINT32 interrupt_mask:1;
   615      } bits;
   616      UINT32 uint32;
   617  } VTD_INVALIDATION_EVENT_CONTROL_REGISTER;
   618  
   619  typedef union
   620  {
   621      struct
   622      {
   623          UINT32 interrupt_message_data:16;
   624          UINT32 extended_interrupt_message_data:16;
   625      } bits;
   626      UINT32 uint32;
   627  } VTD_INVALIDATION_EVENT_DATA_REGISTER;
   628  
   629  typedef union
   630  {
   631      struct
   632      {
   633          UINT32 reserved:2;
   634          UINT32 message_address:30;
   635      } bits;
   636      UINT32 uint32;
   637  } VTD_INVALIDATION_EVENT_ADDRESS_REGISTER;
   638  
   639  typedef struct
   640  {
   641      UINT32 message_upper_address;
   642  } VTD_INVALIDATION_EVENT_UPPER_ADDRESS_REGISTER;
   643  
   644  typedef union
   645  {
   646      struct
   647      {
   648          UINT32
   649              size:4,
   650              reserved:7,
   651              extended_interrupt_mode_enable:1,
   652              address_low:20;
   653          UINT32 address_high;
   654      } bits;
   655      UINT64 uint64;
   656  } VTD_INTERRUPT_REMAPPING_TABLE_ADDRESS_REGISTER;
   657  
   658  #pragma warning(pop)
   659  
   660  typedef enum
   661  {
   662      VTD_POWER_ACTIVE,
   663      VTD_POWER_SUSPEND,
   664      VTD_POWER_RESUME
   665  } VTD_POWER_STATE;
   666  
   667  typedef struct _VTD_DMA_REMAPPING_HW_UNIT
   668  {
   669      UINT32                             id;
   670      VTD_DOMAIN_ID                      avail_domain_id;
   671      LIST_ELEMENT                       domain_list;
   672      UINT64                             register_base;
   673      UINT32                             num_devices;
   674      VMM_LOCK                           hw_lock;
   675      VTD_POWER_STATE                    power_state;
   676      VTD_CAPABILITY_REGISTER            capability;
   677      VTD_EXTENDED_CAPABILITY_REGISTER   extended_capability;
   678      DMAR_DEVICE                       *devices;
   679      DMA_REMAPPING_ROOT_ENTRY          *root_entry_table;
   680  } VTD_DMA_REMAPPING_HW_UNIT;
   681  
   682  BOOLEAN vtd_hw_set_root_entry_table(VTD_DMA_REMAPPING_HW_UNIT *dmar, DMA_REMAPPING_ROOT_ENTRY *root_entry_table);
   683  
   684  BOOLEAN vtd_hw_enable_translation(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   685  void vtd_hw_disable_translation(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   686  
   687  BOOLEAN vtd_hw_enable_interrupt_remapping(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   688  void vtd_hw_disable_interrupt_remapping(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   689  
   690  void vtd_hw_inv_context_cache_global(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   691  void vtd_hw_flush_write_buffers(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   692  void vtd_hw_inv_iotlb_global(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   693  void vtd_hw_inv_iotlb_page(VTD_DMA_REMAPPING_HW_UNIT *dmar,
   694                             ADDRESS addr,
   695                             size_t size,
   696                             VTD_DOMAIN_ID domain_id);
   697  
   698  UINT32 vtd_hw_get_protected_low_memory_base_alignment(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   699  UINT32 vtd_hw_get_protected_low_memory_limit_alignment(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   700  UINT64 vtd_hw_get_protected_high_memory_base_alignment(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   701  UINT64 vtd_hw_get_protected_high_memory_limit_alignment(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   702  BOOLEAN vtd_hw_setup_protected_low_memory(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT32 base, UINT32 limit);
   703  BOOLEAN vtd_hw_setup_protected_high_memory(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT64 base, UINT64 limit);
   704  BOOLEAN vtd_hw_enable_protected_memory(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   705  void vtd_hw_disable_protected_memory(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   706  BOOLEAN vtd_hw_is_protected_memory_enabled(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   707  
   708  // hw read/write
   709  UINT32 vtd_hw_read_reg32(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT64 reg);
   710  void vtd_hw_write_reg32(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT64 reg, UINT32 value);
   711  
   712  UINT64 vtd_hw_read_reg64(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT64 reg);
   713  void vtd_hw_write_reg64(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT64 reg, UINT64 value);
   714  
   715  // capabilities
   716  INLINE
   717  UINT32 vtd_hw_get_super_page_support(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   718  {
   719      return (UINT32) dmar->capability.bits.super_page_support;
   720  }
   721  
   722  INLINE
   723  UINT32 vtd_hw_get_supported_ajusted_guest_address_width(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   724  {
   725      return (UINT32) dmar->capability.bits.adjusted_guest_address_width;
   726  }
   727  
   728  INLINE
   729  UINT32 vtd_hw_get_max_guest_address_width(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   730  {
   731      return (UINT32) dmar->capability.bits.max_guest_address_width;
   732  }
   733  
   734  INLINE
   735  UINT32 vtd_hw_get_number_of_domains(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   736  {
   737      return (UINT32) dmar->capability.bits.number_of_domains;
   738  }
   739  
   740  INLINE
   741  UINT32 vtd_hw_get_caching_mode(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   742  {
   743      return (UINT32) dmar->capability.bits.caching_mode;
   744  }
   745  
   746  INLINE
   747  UINT32 vtd_hw_get_required_write_buffer_flush(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   748  {
   749      return (UINT32) dmar->capability.bits.required_write_buffer_flush;
   750  }
   751  
   752  INLINE
   753  UINT32 vtd_hw_get_coherency(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   754  {
   755      return (UINT32) dmar->extended_capability.bits.coherency;
   756  }
   757  
   758  INLINE
   759  UINT32 vtd_hw_get_protected_low_memory_support(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   760  {
   761      return (UINT32) dmar->capability.bits.protected_low_memory_region;
   762  }
   763  
   764  INLINE
   765  UINT32 vtd_hw_get_protected_high_memory_support(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   766  {
   767      return (UINT32) dmar->capability.bits.protected_high_memory_region;
   768  }
   769  
   770  // fault handling
   771  INLINE
   772  UINT32 vtd_hw_get_number_of_fault_recording_regs(VTD_DMA_REMAPPING_HW_UNIT *dmar)
   773  {
   774      return (UINT32) dmar->capability.bits.number_of_fault_recording_registers;
   775  }
   776  
   777  INLINE
   778  UINT64 vtd_hw_get_fault_recording_reg_offset(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT32 fault_record_index)
   779  {
   780  	UINT32 fault_recording_register_offset =
   781          dmar->capability.bits.fault_recording_register_offset_high << 8 |
   782          dmar->capability.bits.fault_recording_register_offset_low;
   783      return  (16 * fault_recording_register_offset)
   784              + (sizeof(VTD_FAULT_RECORDING_REGISTER) * fault_record_index);
   785  }
   786  
   787  void vtd_hw_mask_fault_interrupt(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   788  void vtd_hw_unmask_fault_interrupt(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   789  
   790  UINT32 vtd_hw_get_fault_overflow(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   791  UINT32 vtd_hw_get_primary_fault_pending(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   792  UINT32 vtd_hw_get_fault_record_index(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   793  
   794  void vtd_hw_set_fault_event_data(VTD_DMA_REMAPPING_HW_UNIT *dmar,
   795                                   UINT8 vector,
   796                                   UINT8 delivery_mode,
   797                                   UINT32 trigger_mode_level,
   798                                   UINT32 trigger_mode);
   799  
   800  void vtd_hw_set_fault_event_addr(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT8 dest_mode, UINT8 dest_id);
   801  void vtd_hw_clear_fault_overflow(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   802  UINT64 vtd_hw_read_fault_register(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT32 fault_record_index);
   803  UINT64 vtd_hw_read_fault_register_high(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT32 fault_record_index);
   804  void vtd_hw_clear_fault_register(VTD_DMA_REMAPPING_HW_UNIT *dmar, UINT32 fault_record_index);
   805  
   806  void vtd_hw_print_capabilities(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   807  void vtd_print_hw_status(VTD_DMA_REMAPPING_HW_UNIT *dmar);
   808  
   809  #endif