Skip to content

xen/arch/x86: add TPR (TXT Protected Range) DMA protection support#29

Open
accek-itl wants to merge 4 commits into
TrenchBoot:aem-staging-2026-03-13from
accek-itl:txt-tpr
Open

xen/arch/x86: add TPR (TXT Protected Range) DMA protection support#29
accek-itl wants to merge 4 commits into
TrenchBoot:aem-staging-2026-03-13from
accek-itl:txt-tpr

Conversation

@accek-itl
Copy link
Copy Markdown

Assisted-by: Claude:claude-opus-4-6

@macpijan macpijan requested a review from SergiiDmytruk April 30, 2026 09:39
Comment thread xen/arch/x86/include/asm/intel-txt.h Outdated
* Find the TPR request element in the TXT heap extended data.
*/
static inline const struct txt_heap_tpr_req_element *
txt_find_tpr_req_element(const struct txt_os_sinit_data *os_sinit)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you'll make this function take data element type as a parameter, it will be possible to reuse the function in tpm.c which is the only other place that searches for a data element.

P.S. Looks like tpm.c is actually doing it wrong: it interprets size relative to the data field which matches the comment on txt_ext_data_element in this file but contradicts the SDM. So it shouldn't actually work there and likely doesn't.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch; it works by accident, because the event log element is the first one. I split this commit into multiple ones to separately extract the common os_sinit element search and apply it in TPM case. Only then add TPR support.

Comment thread xen/arch/x86/include/asm/intel-txt.h Outdated
{
const struct txt_heap_tpr_req_element *tpr_req;

tpr_req = txt_find_tpr_req_element(os_sinit);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment that txt_verify_dma_protection() has already validated presence and contents of the element.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread xen/arch/x86/include/asm/intel-txt.h Outdated

tpr_req = txt_find_tpr_req_element(os_sinit);
lo_size = tpr_req->ranges[0].base + tpr_req->ranges[0].size;
if ( tpr_req->count >= 2 )
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ( tpr_req->count >= 2 )
if ( tpr_req->count == 2 )

or

Suggested change
if ( tpr_req->count >= 2 )
if ( tpr_req->count > 1 )

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* txt_verify_pmr_ranges() makes sure the low range always starts at 0, so
* its size is also end address.
* txt_verify_dma_protection() makes sure the low range always starts at
* 0, so its size is also end address.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should be in the else-branch above and the variable name should be lo_end instead of lo_size to make sense for both branches.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept the assumption that lo_base is always 0, also in TPR flow, so keeping the comment here.
Adjusted the if-branch to just assign the size.

Comment thread xen/arch/x86/include/asm/intel-txt.h Outdated
0x100000000ULL )
txt_reset(SLAUNCH_ERROR_TPR_INVALID);

if ( tpr_req->count >= 2 )
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ( tpr_req->count >= 2 )
if ( tpr_req->count == 2 )

or

Suggested change
if ( tpr_req->count >= 2 )
if ( tpr_req->count > 1 )

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* 0, so its size is also end address.
*/
if ( base + size <= os_sinit->vtd_pmr_lo_size )
if ( base + size <= lo_size )
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check makes sense only if lo_base is guaranteed to be zero. But it can't be with TPR due to overlaps with MMIO or something else, right? Then need to check lower bound too.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I currently boot with lo TPR base hardcoded in grub to 0, just like it's for PMR path.
Tboot uses lowest region from e820, rounded down to 2M boundary, both for PMR and TPR, which in practice should be 0.
So I adjusted this code to assume and check that. Now both PMR and TPR branches have the same logic.
I think we can add non-zero base support later, if needed.
Do you know any reason/platform that needs non-zero lo_base?

Comment thread xen/arch/x86/boot/head.S
.long 0x42b651cb /* UUID3 */
.long (.Lmle_header_end - mle_header) /* MLE header size */
.long 0x00020002 /* MLE version 2.2 */
.long 0x00020003 /* MLE version 2.3 */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope this won't cause older SINITs to refuse processing this MLE.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, me too. There's only min_mle_hdr_ver specified by SDG, so technically anything newer should always be compatible.

Comment on lines +460 to +461
if ( tpr_req->ranges[1].base + tpr_req->ranges[1].size <=
0x100000000ULL )
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/* Hi range must start at or above 4G. */ check above leaves no chance for this condition to be true unless an integer overflow occurs.

Speaking of integer overflows, PMR code checks for them.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

Comment thread xen/arch/x86/include/asm/intel-txt.h Outdated
if ( tpr_req->count > 2 )
txt_reset(SLAUNCH_ERROR_TPR_UNSUPPORTED);

/* Lo range must not exceed 4G. */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* Lo range must not exceed 4G. */
/* Low range must not exceed 4G. */

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed, mimicing PMR logic

@accek-itl accek-itl force-pushed the txt-tpr branch 2 times, most recently from a45708d to f7ebce8 Compare May 15, 2026 13:28
@accek-itl accek-itl requested a review from SergiiDmytruk May 15, 2026 13:28
accek-itl added 4 commits May 15, 2026 15:32
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Szymon Acedański <accek@invisiblethingslab.com>
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Szymon Acedański <accek@invisiblethingslab.com>
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Szymon Acedański <accek@invisiblethingslab.com>
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Szymon Acedański <accek@invisiblethingslab.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants