Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grub-core/loader/i386/txt/txt.c: Use MAXPHYADDR in MTRR masks #23

Open
wants to merge 2 commits into
base: intel-txt-aem-2.06
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 51 additions & 14 deletions grub-core/loader/i386/txt/txt.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,21 @@ fls (int mask)
return (mask == 0 ? mask : (int)bsrl ((grub_uint32_t)mask) + 1);
}

static grub_uint32_t cpu_phys_addr(void)
{
grub_uint32_t eax, ebx, ecx, edx;
grub_uint32_t phys_bits = 36;
/* Find the physical address size for this CPU. */
grub_cpuid (0x80000000, eax, ebx, ecx, edx);
if ( eax >= 0x80000008 )
{
grub_cpuid (0x80000008, eax, ebx, ecx, edx);
phys_bits = eax & 0xFF;
}

return phys_bits;
}

/*
* set the memory type for specified range (base to base+size)
* to mem_type and everything else to UC
Expand All @@ -360,9 +375,10 @@ set_mtrr_mem_type (const grub_uint8_t *base, grub_uint32_t size,
{
grub_uint64_t mtrr_def_type;
grub_uint64_t mtrr_cap;
grub_uint64_t mtrr_mask;
union mtrr_physbase_t mtrr_physbase;
union mtrr_physmask_t mtrr_physmask;
grub_uint32_t vcnt, pages_in_range;
grub_uint32_t vcnt, pages_in_range, sinit_caps;
unsigned long ndx, base_v;
int i = 0, j, num_pages, mtrr_s;

Expand All @@ -376,6 +392,16 @@ set_mtrr_mem_type (const grub_uint8_t *base, grub_uint32_t size,
mtrr_cap = grub_rdmsr (GRUB_MSR_X86_MTRRCAP);
vcnt = (mtrr_cap & GRUB_MSR_X86_VCNT_MASK);

sinit_caps = grub_txt_get_sinit_capabilities ((struct grub_txt_acm_header *)base);
if (!(sinit_caps & GRUB_TXT_CAPS_MAXPHYSADDR_SUPPORT)) {
/* Legacy 36bit mask */
mtrr_mask = SINIT_MTRR_MASK;
} else {
/* Calculate the MTRR mask because MAXPHYADDR is used per SINIT caps */
mtrr_mask = ((1ull << cpu_phys_addr()) - 1) & ~((1ull << 12) - 1);
mtrr_mask = mtrr_mask >> GRUB_PAGE_SHIFT;
}

for ( ndx = 0; ndx < vcnt; ndx++ )
{
mtrr_physmask.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSMASK (ndx));
Expand Down Expand Up @@ -411,13 +437,12 @@ set_mtrr_mem_type (const grub_uint8_t *base, grub_uint32_t size,
while ( num_pages >= mtrr_s )
{
mtrr_physbase.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSBASE (ndx));
mtrr_physbase.base = ((unsigned long)base >> GRUB_PAGE_SHIFT) &
SINIT_MTRR_MASK;
mtrr_physbase.base = ((unsigned long)base >> GRUB_PAGE_SHIFT) & mtrr_mask;
mtrr_physbase.type = mem_type;
grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSBASE (ndx), mtrr_physbase.raw);

mtrr_physmask.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSMASK (ndx));
mtrr_physmask.mask = ~(mtrr_s - 1) & SINIT_MTRR_MASK;
mtrr_physmask.mask = ~(mtrr_s - 1) & mtrr_mask;
mtrr_physmask.v = 1;
grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSMASK (ndx), mtrr_physmask.raw);

Expand All @@ -433,8 +458,7 @@ set_mtrr_mem_type (const grub_uint8_t *base, grub_uint32_t size,
{
/* Set the base of the current MTRR */
mtrr_physbase.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSBASE (ndx));
mtrr_physbase.base = ((unsigned long)base >> GRUB_PAGE_SHIFT) &
SINIT_MTRR_MASK;
mtrr_physbase.base = ((unsigned long)base >> GRUB_PAGE_SHIFT) & mtrr_mask;
mtrr_physbase.type = mem_type;
grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSBASE (ndx), mtrr_physbase.raw);

Expand All @@ -446,7 +470,7 @@ set_mtrr_mem_type (const grub_uint8_t *base, grub_uint32_t size,
pages_in_range = 1 << (fls (num_pages) - 1);

mtrr_physmask.raw = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSMASK (ndx));
mtrr_physmask.mask = ~(pages_in_range - 1) & SINIT_MTRR_MASK;
mtrr_physmask.mask = ~(pages_in_range - 1) & mtrr_mask;
mtrr_physmask.v = 1;
grub_wrmsr (GRUB_MSR_X86_MTRR_PHYSMASK (ndx), mtrr_physmask.raw);

Expand Down Expand Up @@ -740,6 +764,15 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header
*/
os_sinit_data->capabilities = GRUB_TXT_CAPS_TPM_12_AUTH_PCR_USAGE;

/* CBnT must set bits 4 and 5 */
if (sinit_caps & GRUB_TXT_CAPS_CBNT_SUPPORT)
{
os_sinit_data->capabilities |= GRUB_TXT_CAPS_CBNT_SUPPORT;

if (sinit_caps & GRUB_TXT_CAPS_TPM_12_NO_LEGACY_PCR_USAGE)
os_sinit_data->capabilities |= GRUB_TXT_CAPS_TPM_12_NO_LEGACY_PCR_USAGE;
}

if (grub_get_tpm_ver () == GRUB_TPM_20)
{
if ((sinit_caps & os_sinit_data->capabilities) != os_sinit_data->capabilities)
Expand All @@ -749,16 +782,20 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header
else
{
if (!(sinit_caps & GRUB_TXT_CAPS_TPM_12_AUTH_PCR_USAGE))
{
grub_dprintf ("slaunch", "Details/authorities PCR usage is not supported. Trying legacy");
if (sinit_caps & GRUB_TXT_CAPS_TPM_12_NO_LEGACY_PCR_USAGE)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("Not a single PCR usage available in SINIT capabilities"));
{
grub_dprintf ("slaunch", "Details/authorities PCR usage is not supported. Trying legacy");
if (sinit_caps & GRUB_TXT_CAPS_TPM_12_NO_LEGACY_PCR_USAGE)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("Not a single PCR usage available in SINIT capabilities"));

os_sinit_data->capabilities = 0;
}
os_sinit_data->capabilities = 0;
}
}

/* Use MAXPHYADDR for MTRR masks if available */
if (sinit_caps & GRUB_TXT_CAPS_MAXPHYSADDR_SUPPORT)
os_sinit_data->capabilities |= GRUB_TXT_CAPS_MAXPHYSADDR_SUPPORT;

/*
* APs (application processors) can't be brought up by usual INIT-SIPI-SIPI
* sequence after Measured Launch, otherwise the MLE integrity is lost.
Expand Down