1 /* SPDX-License-Identifier: BSD-2-Clause */
8 // definition in STM spec
10 #define STM_SPEC_VERSION_MAJOR 1
11 #define STM_SPEC_VERSION_MINOR 0
15 #define STM_HARDWARE_FIELD_FILL_TO_2K (2048 - sizeof(uint32_t) * 8)
17 uint32_t stm_header_revision
;
18 uint32_t monitor_features
;
20 uint32_t gdtr_base_offset
;
25 uint8_t reserved
[STM_HARDWARE_FIELD_FILL_TO_2K
];
26 } HARDWARE_STM_HEADER
;
28 #define STM_FEATURES_IA32E 0x1
31 uint32_t intel_64mode_supported
: 1;
32 uint32_t ept_supported
: 1;
37 uint8_t stm_spec_ver_major
;
38 uint8_t stm_pec_ver_minor
;
40 uint32_t static_image_size
;
41 uint32_t per_proc_dynamic_memory_size
;
42 uint32_t additional_dynamic_memory_size
;
43 STM_FEAT stm_features
;
44 uint32_t number_of_rev_ids
;
45 uint32_t stm_smm_rev_id
[];
47 // The total STM_HEADER should be 4K.
48 } SOFTWARE_STM_HEADER
;
51 HARDWARE_STM_HEADER hw_stm_hdr
;
52 SOFTWARE_STM_HEADER sw_stm_hdr
;
58 uint64_t bios_component_base
;
60 uint32_t hash_algorithm
; // SHA1 or SHA256
62 } TXT_BIOS_COMPONENT_STATUS
;
64 #define PAGE_SIZE 4096
68 uint64_t image_page_base
[]; //[NumberOfPages];
69 } TXT_BIOS_COMPONENT_UPDATE
;
75 uint16_t page_violation_exception
: 1;
76 uint16_t msr_violation_exception
: 1;
77 uint16_t register_violation_exception
: 1;
78 uint16_t io_violation_exception
: 1;
79 uint16_t pci_violation_exception
: 1;
80 uint16_t reserved1
: 11;
82 } STM_PROTECTION_EXCEPTION_HANDLER
;
85 uint8_t execution_disable_outside_smrr
: 1;
86 uint8_t intel_64mode
: 1;
89 uint8_t reserved1
: 4;
90 } STM_SMM_ENTRY_STATE
;
93 uint8_t smram_to_vmcs_restore_required
: 1; // BIOS restore hint
94 uint8_t reinitialize_vmcs_required
: 1; // BIOS request
95 uint8_t reserved2
: 6;
96 } STM_SMM_RESUME_STATE
;
99 uint8_t domain_type
: 4; // STM input to BIOS on each SM
100 uint8_t x_state_policy
: 2; // STM input to BIOS on each SMI
101 uint8_t ept_enabled
: 1;
102 uint8_t reserved3
: 1;
108 uint8_t smm_descriptor_ver_major
;
109 uint8_t smm_descriptor_ver_minor
;
110 uint32_t local_apic_id
;
111 STM_SMM_ENTRY_STATE smm_entry_state
;
112 STM_SMM_RESUME_STATE smm_resume_state
;
113 STM_SMM_STATE stm_smm_state
;
118 uint16_t smm_other_segment
;
122 uint64_t smm_stm_setup_rip
;
123 uint64_t smm_stm_teardown_rip
;
124 uint64_t smm_smi_handler_rip
;
125 uint64_t smm_smi_handler_rsp
;
126 uint64_t smm_gdt_ptr
;
127 uint32_t smm_gdt_size
;
128 uint32_t required_stm_smm_rev_id
;
129 STM_PROTECTION_EXCEPTION_HANDLER stm_protection_exception_handler
;
131 uint64_t bios_hw_resource_requirements_ptr
;
134 uint8_t physical_address_bits
;
135 } TXT_PROCESSOR_SMM_DESCRIPTOR
;
137 #define TXT_PROCESSOR_SMM_DESCRIPTOR_SIGNATURE "TXTPSSIG"
138 #define TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MAJOR 1
139 #define TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MINOR 0
141 #define SMM_PSD_OFFSET 0xfb00
144 TxtSmmPageViolation
= 1,
146 TxtSmmRegisterViolation
,
149 } TXT_SMM_PROTECTION_EXCEPTION_TYPE
;
162 uint32_t vmcs_exit_instruction_info
;
163 uint32_t vmcs_exit_instruction_length
;
164 uint64_t vmcs_exit_qualification
;
165 uint32_t error_code
; // TXT_SMM_PROTECTION_EXCEPTION_TYPE
171 } STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32
;
193 uint64_t vmcs_exit_instruction_info
;
194 uint64_t vmcs_exit_instruction_length
;
195 uint64_t vmcs_exit_qualification
;
196 uint64_t error_code
; // TXT_SMM_PROTECTION_EXCEPTION_TYPE
202 } STM_PROTECTION_EXCEPTION_STACK_FRAME_X64
;
205 STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32
*ia32_stack_frame
;
206 STM_PROTECTION_EXCEPTION_STACK_FRAME_X64
*x64_stack_frame
;
207 } STM_PROTECTION_EXCEPTION_STACK_FRAME
;
209 #define STM_SMM_REV_ID 0x80010100
211 typedef struct _STM_SMM_CPU_STATE
{ // Writable?
212 uint8_t reserved1
[0x1d0]; // fc00h
213 uint32_t gdt_base_hi_dword
; // fdd0h : NO
214 uint32_t ldt_base_hi_dword
; // fdd4h : NO
215 uint32_t idt_base_hi_dword
; // fdd8h : NO
216 uint8_t reserved2
[0x4]; // fddch
217 uint64_t io_rdi
; // fde0h : NO
219 uint64_t io_eip
; // fde8h : YES
220 uint64_t io_rcx
; // fdf0h : NO
222 uint64_t io_rsi
; // fdf8h : NO
224 uint8_t reserved3
[0x40]; // fe00h
225 uint32_t cr4
; // fe40h : NO
226 uint8_t reserved4
[0x48]; // fe44h
227 uint32_t gdt_base_lo_dword
; // fe8ch : NO
228 uint32_t gdt_limit
; // fe90h : NO
230 uint32_t idt_base_lo_dword
; // fe94h : NO
231 uint32_t idt_limit
; // fe98h : NO
233 uint32_t ldt_base_lo_dword
; // fe9ch : NO
234 uint32_t ldt_limit
; // fea0h : NO
236 uint32_t ldt_info
; // fea4h : NO
238 uint8_t reserved5
[0x30]; // fea8h
239 uint64_t eptp
; // fed8h : NO
240 uint32_t enabled_ept
; // fee0h : NO
241 uint8_t reserved6
[0x14]; // fee4h
242 uint32_t smbase
; // fef8h : YES
244 uint32_t smm_rev_id
; // fefch : NO
245 uint16_t io_restart
; // ff00h : YES
246 uint16_t auto_halt_restart
; // ff02h : YES
247 uint8_t reserved7
[0x18]; // ff04h
248 uint64_t r15
; // ff1ch : YES
249 uint64_t r14
; // ff24h : YES
250 uint64_t r13
; // ff2ch : YES
251 uint64_t r12
; // ff34h : YES
252 uint64_t r11
; // ff3ch : YES
253 uint64_t r10
; // ff44h : YES
254 uint64_t r9
; // ff4ch : YES
255 uint64_t r8
; // ff54h : YES
256 uint64_t rax
; // ff5ch : YES
257 uint64_t rcx
; // ff64h : YES
258 uint64_t rdx
; // ff6ch : YES
259 uint64_t rbx
; // ff74h : YES
260 uint64_t rsp
; // ff7ch : YES
261 uint64_t rbp
; // ff84h : YES
262 uint64_t rsi
; // ff8ch : YES
263 uint64_t rdi
; // ff94h : YES
264 uint64_t io_mem_addr
; // ff9ch : NO
265 uint32_t io_misc
; // ffa4h : NO
266 uint32_t es
; // ffa8h : NO
267 uint32_t cs
; // ffach : NO
268 uint32_t ss
; // ffb0h : NO
269 uint32_t ds
; // ffb4h : NO
270 uint32_t fs
; // ffb8h : NO
271 uint32_t gs
; // ffbch : NO
272 uint32_t ldtr
; // ffc0h : NO
273 uint32_t tr
; // ffc4h : NO
274 uint64_t dr7
; // ffc8h : NO
275 uint64_t dr6
; // ffd0h : NO
276 uint64_t rip
; // ffd8h : YES
277 uint64_t ia32_efer
; // ffe0h : YES
279 uint64_t rflags
; // ffe8h : YES
280 uint64_t cr3
; // fff0h : NO
281 uint64_t cr0
; // fff8h : NO
286 uint64_t physical_address
;
287 uint64_t virtual_ddress
;
289 uint32_t Pat_cache_type
;
290 } STM_MAP_ADDRESS_RANGE_DESCRIPTOR
;
298 #define FOLLOW_MTRR 0xFFFFFFFF
301 uint64_t virtual_address
;
303 } STM_UNMAP_ADDRESS_RANGE_DESCRIPTOR
;
306 uint64_t interrupted_guest_virtual_address
;
308 uint64_t interrupted_cr3
;
309 uint64_t interrupted_eptp
;
310 uint32_t map_to_smm_guest
: 2;
311 uint32_t interrupted_cr4_pae
: 1;
312 uint32_t interrupted_cr4_pse
: 1;
313 uint32_t interrupted_ia32e_mode
: 1;
314 uint32_t reserved1
: 27;
316 uint64_t physical_address
;
317 uint64_t smm_guest_virtual_address
;
318 } STM_ADDRESS_LOOKUP_DESCRIPTOR
;
322 #define VIRTUAL_ADDRESS_SPECIFIED 3
325 #define END_OF_RESOURCES 0
329 #define MACHINE_SPECIFIC_REG 4
330 #define PCI_CFG_RANGE 5
331 #define TRAPPED_IO_RANGE 6
332 #define ALL_RESOURCES 7
333 #define REGISTER_VIOLATION 8
334 #define MAX_DESC_TYPE 8
339 uint16_t return_status
: 1;
340 uint16_t reserved
: 14;
341 uint16_t ignore_resource
: 1;
342 } STM_RSC_DESC_HEADER
;
345 STM_RSC_DESC_HEADER Hdr
;
346 uint64_t resource_list_continuation
;
349 // byte granular Memory range support
350 #define STM_RSC_BGM 0x4
353 STM_RSC_DESC_HEADER hdr
;
356 uint32_t rwx_attributes
: 3;
357 uint32_t reserved
: 29;
361 #define STM_RSC_MEM_R 0x1
362 #define STM_RSC_MEM_W 0x2
363 #define STM_RSC_MEM_X 0x4
366 STM_RSC_DESC_HEADER hdr
;
372 // byte granular MMIO range support
373 #define STM_RSC_BGI 0x2
376 STM_RSC_DESC_HEADER hdr
;
379 uint32_t rwx_attributes
: 3;
380 uint32_t reserved
: 29;
384 #define STM_RSC_MMIO_R 0x1
385 #define STM_RSC_MMIO_W 0x2
386 #define STM_RSC_MMIO_X 0x4
389 STM_RSC_DESC_HEADER hdr
;
391 uint32_t kernel_mode_processing
: 1;
392 uint32_t reserved
: 31;
397 // bit granular MSR resource support
398 #define STM_RSC_MSR 0x8
401 uint8_t type
; // must be 1, indicating Hardware Device Path
402 uint8_t subtype
; // must be 1, indicating PCI
403 uint16_t length
; // sizeof(STM_PCI_DEVICE_PATH_NODE) which is 6
404 uint8_t pci_function
;
406 } STM_PCI_DEVICE_PATH_NODE
;
409 STM_RSC_DESC_HEADER hdr
;
410 uint16_t rw_attributes
: 2;
411 uint16_t reserved
: 14;
414 uint8_t originating_bus_number
;
415 uint8_t last_node_index
;
416 STM_PCI_DEVICE_PATH_NODE pci_device_path
[];
417 // STM_PCI_DEVICE_PATH_NODE PciDevicePath[LastNodeIndex + 1];
418 } STM_RSC_PCI_CFG_DESC
;
420 #define STM_RSC_PCI_CFG_R 0x1
421 #define STM_RSC_PCI_CFG_W 0x2
424 STM_RSC_DESC_HEADER hdr
;
430 uint16_t reserved1
: 13;
432 } STM_RSC_TRAPPED_IO_DESC
;
435 STM_RSC_DESC_HEADER hdr
;
436 } STM_RSC_ALL_RESOURCES_DESC
;
439 STM_RSC_DESC_HEADER hdr
;
440 uint32_t register_type
;
444 } STM_REGISTER_VIOLATION_DESC
;
453 } STM_REGISTER_VIOLATION_TYPE
;
456 STM_RSC_DESC_HEADER header
;
458 STM_RSC_MEM_DESC mem
;
460 STM_RSC_MMIO_DESC mmio
;
461 STM_RSC_MSR_DESC msr
;
462 STM_RSC_PCI_CFG_DESC pci_cfg
;
463 STM_RSC_TRAPPED_IO_DESC trapped_io
;
464 STM_RSC_ALL_RESOURCES_DESC all
;
465 STM_REGISTER_VIOLATION_DESC register_violation
;
469 #define STM_VMCS_DATABASE_REQUEST_ADD 1
470 #define STM_VMCS_DATABASE_REQUEST_REMOVE 0
472 // Values for DomainType
473 // Interpreter of DomainType
474 #define DOMAIN_DISALLOWED_IO_OUT (1u << 0)
475 #define DOMAIN_DISALLOWED_IO_IN (1u << 1)
476 #define DOMAIN_INTEGRITY (1u << 2)
477 #define DOMAIN_CONFIDENTIALITY (1u << 3)
479 #define DOMAIN_UNPROTECTED 0x00
480 #define DOMAIN_INTEGRITY_PROT_OUT_IN (DOMAIN_INTEGRITY)
481 #define DOMAIN_FULLY_PROT_OUT_IN (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY)
482 #define DOMAIN_FULLY_PROT \
483 (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_IN \
484 | DOMAIN_DISALLOWED_IO_OUT)
486 // Values for XStatePolicy
487 #define XSTATE_READWRITE 0x00
488 #define XSTATE_READONLY 0x01
489 #define XSTATE_SCRUB 0x03
492 uint64_t vmcs_phys_pointer
; // bits 11:0 are reserved and must be 0
493 uint32_t domain_type
: 4;
494 uint32_t x_state_policy
: 2;
495 uint32_t degradation_policy
: 4;
496 uint32_t reserved1
: 22; // Must be 0
497 uint32_t add_or_remove
;
498 } STM_VMCS_DATABASE_REQUEST
;
502 #define CONFIGURE_LOG 2
510 evt_log_invalid_parameter_detected
,
511 evt_handled_protection_exception
,
512 // unhandled protection exceptions result in reset & cannot be logged
513 evt_bios_access_to_unclaimed_resource
,
514 evt_mle_resource_protection_granted
,
515 evt_mle_resource_protection_denied
,
516 evt_mle_resource_unprotect
,
517 evt_mle_resource_unprotect_error
,
518 evt_mle_domain_type_degraded
,
522 evt_invalid
= 0xFFFFFFFF,
527 uint64_t pages
[]; // number of elements is PageCount
528 } STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA_LOG_BUFFER
;
531 STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA_LOG_BUFFER log_buffer
;
532 uint32_t event_enable_bitmap
; // bitmap of EVENT_TYPE
533 } STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA
;
536 uint32_t sub_functionindex
;
537 STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA data
;
538 } STM_EVENT_LOG_MANAGEMENT_REQUEST
;
540 // VMCALL API Numbers
542 // API number convention: BIOS facing VMCALL interfaces have bit 16 clear
543 #define STM_API_MAP_ADDRESS_RANGE 0x00000001
544 #define STM_API_UNMAP_ADDRESS_RANGE 0x00000002
545 #define STM_API_ADDRESS_LOOKUP 0x00000003
546 #define STM_API_RETURN_FROM_PROTECTION_EXCEPTION 0x00000004
548 // API number convention: MLE facing VMCALL interfaces have bit 16 set
550 // The STM configuration lifecycle is as follows:
551 // 1. SENTER->SINIT->MLE: MLE begins execution with SMI disabled (masked).
552 // 2. MLE invokes InitializeProtectionVMCALL() to prepare STM for setup of
553 // initial protection profile. This is done on a single CPU and has global
555 // 3. MLE invokes ProtectResourceVMCALL() to define the initial protection
556 // profile. The protection profile is global across all CPUs.
557 // 4. MLE invokes StartStmVMCALL() to enable the STM to begin receiving SMI
558 // events. This must be done on every logical CPU.
559 // 5. MLE may invoke ProtectResourceVMCALL() or UnProtectResourceVMCALL()
560 // during runtime as many times as necessary.
561 // 6. MLE invokes StopStmVMCALL() to disable the STM. SMI is again masked
562 // following StopStmVMCALL().
564 #define STM_API_START 0x00010001
565 #define STM_API_STOP 0x00010002
566 #define STM_API_PROTECT_RESOURCE 0x00010003
567 #define STM_API_UNPROTECT_RESOURCE 0x00010004
568 #define STM_API_GET_BIOS_RESOURCES 0x00010005
569 #define STM_API_MANAGE_VMCS_DATABASE 0x00010006
570 #define STM_API_INITIALIZE_PROTECTION 0x00010007
571 #define STM_API_MANAGE_EVENT_LOG 0x00010008
574 typedef uint32_t STM_STATUS
;
576 #define STM_SUCCESS 0x00000000
577 #define SMM_SUCCESS 0x00000000
578 // all error codes have bit 31 set
579 // STM errors have bit 16 set
580 #define ERROR_STM_SECURITY_VIOLATION 0x80010001
581 #define ERROR_STM_CACHE_TYPE_NOT_SUPPORTED 0x80010002
582 #define ERROR_STM_PAGE_NOT_FOUND 0x80010003
583 #define ERROR_STM_BAD_CR3 0x80010004
584 #define ERROR_STM_PHYSICAL_OVER_4G 0x80010005
585 #define ERROR_STM_VIRTUAL_SPACE_TOO_SMALL 0x80010006
586 #define ERROR_STM_UNPROTECTABLE_RESOURCE 0x80010007
587 #define ERROR_STM_ALREADY_STARTED 0x80010008
588 #define ERROR_STM_WITHOUT_SMX_UNSUPPORTED 0x80010009
589 #define ERROR_STM_STOPPED 0x8001000A
590 #define ERROR_STM_BUFFER_TOO_SMALL 0x8001000B
591 #define ERROR_STM_INVALID_VMCS_DATABASE 0x8001000C
592 #define ERROR_STM_MALFORMED_RESOURCE_LIST 0x8001000D
593 #define ERROR_STM_INVALID_PAGECOUNT 0x8001000E
594 #define ERROR_STM_LOG_ALLOCATED 0x8001000F
595 #define ERROR_STM_LOG_NOT_ALLOCATED 0x80010010
596 #define ERROR_STM_LOG_NOT_STOPPED 0x80010011
597 #define ERROR_STM_LOG_NOT_STARTED 0x80010012
598 #define ERROR_STM_RESERVED_BIT_SET 0x80010013
599 #define ERROR_STM_NO_EVENTS_ENABLED 0x80010014
600 #define ERROR_STM_OUT_OF_RESOURCES 0x80010015
601 #define ERROR_STM_FUNCTION_NOT_SUPPORTED 0x80010016
602 #define ERROR_STM_UNPROTECTABLE 0x80010017
603 #define ERROR_STM_UNSUPPORTED_MSR_BIT 0x80010018
604 #define ERROR_STM_UNSPECIFIED 0x8001FFFF
606 // SMM errors have bit 17 set
607 #define ERROR_SMM_BAD_BUFFER 0x80020001
608 #define ERROR_SMM_INVALID_RSC 0x80020004
609 #define ERROR_SMM_INVALID_BUFFER_SIZE 0x80020005
610 #define ERROR_SMM_BUFFER_TOO_SHORT 0x80020006
611 #define ERROR_SMM_INVALID_LIST 0x80020007
612 #define ERROR_SMM_OUT_OF_MEMORY 0x80020008
613 #define ERROR_SMM_AFTER_INIT 0x80020009
614 #define ERROR_SMM_UNSPECIFIED 0x8002FFFF
616 // Errors that apply to both have bits 15, 16, and 17 set
617 #define ERROR_INVALID_API 0x80038001
618 #define ERROR_INVALID_PARAMETER 0x80038002
620 // STM TXT.ERRORCODE codes
621 #define STM_CRASH_PROTECTION_EXCEPTION 0xC000F001
622 #define STM_CRASH_PROTECTION_EXCEPTION_FAILURE 0xC000F002
623 #define STM_CRASH_DOMAIN_DEGRADATION_FAILURE 0xC000F003
624 #define STM_CRASH_BIOS_PANIC 0xC000E000
627 uint32_t event_serial_number
;
631 uint16_t read_by_mle
: 1;
632 uint16_t wrapped
: 1;
633 uint16_t reserved
: 12;
638 } ENTRY_EVT_LOG_STARTED
;
642 } ENTRY_EVT_LOG_STOPPED
;
645 uint32_t vmcall_api_number
;
646 } ENTRY_EVT_LOG_INVALID_PARAM
;
650 } ENTRY_EVT_LOG_HANDLED_PROTECTION_EXCEPTION
;
654 } ENTRY_EVT_BIOS_ACCESS_UNCLAIMED_RSC
;
658 } ENTRY_EVT_MLE_RSC_PROT_GRANTED
;
662 } ENTRY_EVT_MLE_RSC_PROT_DENIED
;
666 } ENTRY_EVT_MLE_RSC_UNPROT
;
670 } ENTRY_EVT_MLE_RSC_UNPROT_ERROR
;
673 uint64_t vmcs_phys_pointer
;
674 uint8_t expected_domain_type
;
675 uint8_t degraded_domain_type
;
676 } ENTRY_EVT_MLE_DOMAIN_TYPE_DEGRADED
;
679 ENTRY_EVT_LOG_STARTED started
;
680 ENTRY_EVT_LOG_STOPPED stopped
;
681 ENTRY_EVT_LOG_INVALID_PARAM invalid_param
;
682 ENTRY_EVT_LOG_HANDLED_PROTECTION_EXCEPTION
683 handled_protection_exception
;
684 ENTRY_EVT_BIOS_ACCESS_UNCLAIMED_RSC bios_unclaimed_rsc
;
685 ENTRY_EVT_MLE_RSC_PROT_GRANTED mle_rsc_prot_granted
;
686 ENTRY_EVT_MLE_RSC_PROT_DENIED mle_rsc_prot_denied
;
687 ENTRY_EVT_MLE_RSC_UNPROT mle_rsc_unprot
;
688 ENTRY_EVT_MLE_RSC_UNPROT_ERROR mle_rsc_unprot_error
;
689 ENTRY_EVT_MLE_DOMAIN_TYPE_DEGRADED mle_domain_type_degraded
;
693 LOG_ENTRY_HEADER hdr
;
697 #define STM_LOG_ENTRY_SIZE 256
698 #define STM_CONFIG_SMI_UNBLOCKING_BY_VMX_OFF 0x1
701 #define SW_SMI_STM_ADD_RUNTIME_RESOURCES_SUB_FUNC 0
702 #define SW_SMI_STM_READ_BIOS_RESOURCES_SUB_FUNC 1
703 #define SW_SMI_STM_REPLACE_BIOS_RESOURCES_SUB_FUNC 2
706 uint32_t buffer_size
;