Re: [PATCH v2] Remove the memory encryption mask to obtain the true physical address

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



在 2019年01月28日 22:24, Lendacky, Thomas 写道:
> On 1/27/19 11:46 PM, Lianbo Jiang wrote:
>> For AMD machine with SME feature, if SME is enabled in the first
>> kernel, the crashed kernel's page table(pgd/pud/pmd/pte) contains
>> the memory encryption mask, so makedumpfile needs to remove the
>> memory encryption mask to obtain the true physical address.
>>
>> Signed-off-by: Lianbo Jiang <lijiang@xxxxxxxxxx>
>> ---
>> Changes since v1:
>> 1. Merge them into a patch.
>> 2. The sme_mask is not an enum number, remove it.
>> 3. Sanity check whether the sme_mask is in vmcoreinfo.
>> 4. Deal with the huge pages case.
>> 5. Cover the 5-level path.
>>
>>  arch/x86_64.c  | 30 +++++++++++++++++-------------
>>  makedumpfile.c |  4 ++++
>>  makedumpfile.h |  1 +
>>  3 files changed, 22 insertions(+), 13 deletions(-)
>>
>> diff --git a/arch/x86_64.c b/arch/x86_64.c
>> index 537fb78..7b3ed10 100644
>> --- a/arch/x86_64.c
>> +++ b/arch/x86_64.c
>> @@ -291,6 +291,7 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable)
>>  	unsigned long page_dir, pgd, pud_paddr, pud_pte, pmd_paddr, pmd_pte;
>>  	unsigned long pte_paddr, pte;
>>  	unsigned long p4d_paddr, p4d_pte;
>> +	unsigned long sme_me_mask = ~0UL;
>>  
>>  	/*
>>  	 * Get PGD.
>> @@ -302,6 +303,9 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable)
>>  			return NOT_PADDR;
>>  	}
>>  
>> +	if (NUMBER(sme_mask) != NOT_FOUND_NUMBER)
>> +		sme_me_mask = ~(NUMBER(sme_mask));
> 
> This is a bit confusing since this isn't the sme_me_mask any more, but the
> complement. Might want to somehow rename this so that it doesn't cause any
> confusion.
>
Thanks for your comment.

I will change the sme_me_mask to entry_mask in patch v3.
 
>> +
>>  	if (check_5level_paging()) {
>>  		page_dir += pgd5_index(vaddr) * sizeof(unsigned long);
>>  		if (!readmem(PADDR, page_dir, &pgd, sizeof pgd)) {
>> @@ -309,7 +313,7 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable)
>>  			return NOT_PADDR;
>>  		}
>>  		if (info->vaddr_for_vtop == vaddr)
>> -			MSG("  PGD : %16lx => %16lx\n", page_dir, pgd);
>> +			MSG("  PGD : %16lx => %16lx\n", page_dir, (pgd & sme_me_mask));
> 
> No need to remove the mask here.  You're just printing out the value of
> the entry. It might be nice to know whether the encryption bit is set or
> not - after all, ENTRY_MASK is still part of this value.
> 

Ok, i will remove it in patch v3.

>>  
>>  		if (!(pgd & _PAGE_PRESENT)) {
>>  			ERRMSG("Can't get a valid pgd.\n");
>> @@ -318,20 +322,20 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable)
>>  		/*
>>  		 * Get P4D.
>>  		 */
>> -		p4d_paddr  = pgd & ENTRY_MASK;
>> +		p4d_paddr  = pgd & ENTRY_MASK & sme_me_mask;
> 
> This goes back to my original comment that you should just make a local
> variable that is "ENTRY_MASK & ~(NUMBER(sme_mask))" since you are
> performing this ANDing everywhere ENTRY_MASK is used - except then you
> miss the one at the very end of this routine on the return statement.
> 

Ok, i will improve them in patch v3.

>>  		p4d_paddr += p4d_index(vaddr) * sizeof(unsigned long);
>>  		if (!readmem(PADDR, p4d_paddr, &p4d_pte, sizeof p4d_pte)) {
>>  			ERRMSG("Can't get p4d_pte (p4d_paddr:%lx).\n", p4d_paddr);
>>  			return NOT_PADDR;
>>  		}
>>  		if (info->vaddr_for_vtop == vaddr)
>> -			MSG("  P4D : %16lx => %16lx\n", p4d_paddr, p4d_pte);
>> +			MSG("  P4D : %16lx => %16lx\n", p4d_paddr, (p4d_pte & sme_me_mask));
>>  
>>  		if (!(p4d_pte & _PAGE_PRESENT)) {
>>  			ERRMSG("Can't get a valid p4d_pte.\n");
>>  			return NOT_PADDR;
>>  		}
>> -		pud_paddr  = p4d_pte & ENTRY_MASK;
>> +		pud_paddr  = p4d_pte & ENTRY_MASK & sme_me_mask;
>>  	}else {
>>  		page_dir += pgd_index(vaddr) * sizeof(unsigned long);
>>  		if (!readmem(PADDR, page_dir, &pgd, sizeof pgd)) {
>> @@ -339,13 +343,13 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable)
>>  			return NOT_PADDR;
>>  		}
>>  		if (info->vaddr_for_vtop == vaddr)
>> -			MSG("  PGD : %16lx => %16lx\n", page_dir, pgd);
>> +			MSG("  PGD : %16lx => %16lx\n", page_dir, (pgd & sme_me_mask));
>>  
>>  		if (!(pgd & _PAGE_PRESENT)) {
>>  			ERRMSG("Can't get a valid pgd.\n");
>>  			return NOT_PADDR;
>>  		}
>> -		pud_paddr  = pgd & ENTRY_MASK;
>> +		pud_paddr  = pgd & ENTRY_MASK & sme_me_mask;
>>  	}
>>  
>>  	/*
>> @@ -357,47 +361,47 @@ __vtop4_x86_64(unsigned long vaddr, unsigned long pagetable)
>>  		return NOT_PADDR;
>>  	}
>>  	if (info->vaddr_for_vtop == vaddr)
>> -		MSG("  PUD : %16lx => %16lx\n", pud_paddr, pud_pte);
>> +		MSG("  PUD : %16lx => %16lx\n", pud_paddr, (pud_pte & sme_me_mask));
>>  
>>  	if (!(pud_pte & _PAGE_PRESENT)) {
>>  		ERRMSG("Can't get a valid pud_pte.\n");
>>  		return NOT_PADDR;
>>  	}
>>  	if (pud_pte & _PAGE_PSE)	/* 1GB pages */
>> -		return (pud_pte & ENTRY_MASK & PUD_MASK) +
>> +		return (pud_pte & ENTRY_MASK & PUD_MASK & sme_me_mask) +
>>  			(vaddr & ~PUD_MASK);
>>  
>>  	/*
>>  	 * Get PMD.
>>  	 */
>> -	pmd_paddr  = pud_pte & ENTRY_MASK;
>> +	pmd_paddr  = pud_pte & ENTRY_MASK & sme_me_mask;
>>  	pmd_paddr += pmd_index(vaddr) * sizeof(unsigned long);
>>  	if (!readmem(PADDR, pmd_paddr, &pmd_pte, sizeof pmd_pte)) {
>>  		ERRMSG("Can't get pmd_pte (pmd_paddr:%lx).\n", pmd_paddr);
>>  		return NOT_PADDR;
>>  	}
>>  	if (info->vaddr_for_vtop == vaddr)
>> -		MSG("  PMD : %16lx => %16lx\n", pmd_paddr, pmd_pte);
>> +		MSG("  PMD : %16lx => %16lx\n", pmd_paddr, (pmd_pte & sme_me_mask));
>>  
>>  	if (!(pmd_pte & _PAGE_PRESENT)) {
>>  		ERRMSG("Can't get a valid pmd_pte.\n");
>>  		return NOT_PADDR;
>>  	}
>>  	if (pmd_pte & _PAGE_PSE)	/* 2MB pages */
>> -		return (pmd_pte & ENTRY_MASK & PMD_MASK) +
>> +		return (pmd_pte & ENTRY_MASK & PMD_MASK & sme_me_mask) +
>>  			(vaddr & ~PMD_MASK);
>>  
>>  	/*
>>  	 * Get PTE.
>>  	 */
>> -	pte_paddr  = pmd_pte & ENTRY_MASK;
>> +	pte_paddr  = pmd_pte & ENTRY_MASK & sme_me_mask;
>>  	pte_paddr += pte_index(vaddr) * sizeof(unsigned long);
>>  	if (!readmem(PADDR, pte_paddr, &pte, sizeof pte)) {
>>  		ERRMSG("Can't get pte (pte_paddr:%lx).\n", pte_paddr);
>>  		return NOT_PADDR;
>>  	}
>>  	if (info->vaddr_for_vtop == vaddr)
>> -		MSG("  PTE : %16lx => %16lx\n", pte_paddr, pte);
>> +		MSG("  PTE : %16lx => %16lx\n", pte_paddr, (pte & sme_me_mask));
>>  
>>  	if (!(pte & _PAGE_PRESENT)) {
>>  		ERRMSG("Can't get a valid pte.\n");
> 
> Just after here is where I think an "& sme_me_mask" is missing...
> 

Ok. Thank you for pointing out my mistake. I will improve them in patch v3.


Regards,
Lianbo

> Thanks,
> Tom
> 
>> diff --git a/makedumpfile.c b/makedumpfile.c
>> index 8923538..2237eb8 100644
>> --- a/makedumpfile.c
>> +++ b/makedumpfile.c
>> @@ -977,6 +977,8 @@ next_page:
>>  	read_size = MIN(info->page_size - PAGEOFFSET(paddr), size);
>>  
>>  	pgaddr = PAGEBASE(paddr);
>> +	if (NUMBER(sme_mask) != NOT_FOUND_NUMBER)
>> +		pgaddr = pgaddr & ~(NUMBER(sme_mask));
>>  	pgbuf = cache_search(pgaddr, read_size);
>>  	if (!pgbuf) {
>>  		++cache_miss;
>> @@ -2276,6 +2278,7 @@ write_vmcoreinfo_data(void)
>>  	WRITE_NUMBER("NR_FREE_PAGES", NR_FREE_PAGES);
>>  	WRITE_NUMBER("N_ONLINE", N_ONLINE);
>>  	WRITE_NUMBER("pgtable_l5_enabled", pgtable_l5_enabled);
>> +	WRITE_NUMBER("sme_mask", sme_mask);
>>  
>>  	WRITE_NUMBER("PG_lru", PG_lru);
>>  	WRITE_NUMBER("PG_private", PG_private);
>> @@ -2672,6 +2675,7 @@ read_vmcoreinfo(void)
>>  	READ_NUMBER("NR_FREE_PAGES", NR_FREE_PAGES);
>>  	READ_NUMBER("N_ONLINE", N_ONLINE);
>>  	READ_NUMBER("pgtable_l5_enabled", pgtable_l5_enabled);
>> +	READ_NUMBER("sme_mask", sme_mask);
>>  
>>  	READ_NUMBER("PG_lru", PG_lru);
>>  	READ_NUMBER("PG_private", PG_private);
>> diff --git a/makedumpfile.h b/makedumpfile.h
>> index 73813ed..e97b2e7 100644
>> --- a/makedumpfile.h
>> +++ b/makedumpfile.h
>> @@ -1912,6 +1912,7 @@ struct number_table {
>>  	long	NR_FREE_PAGES;
>>  	long	N_ONLINE;
>>  	long	pgtable_l5_enabled;
>> +	long	sme_mask;
>>  
>>  	/*
>>   	* Page flags
>>

_______________________________________________
kexec mailing list
kexec@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/kexec




[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux