[PATCH -V1 09/24] powerpc: Decode the pte-lp-encoding bits correctly.
Aneesh Kumar K.V
aneesh.kumar at linux.vnet.ibm.com
Tue Mar 5 05:11:01 EST 2013
"Aneesh Kumar K.V" <aneesh.kumar at linux.vnet.ibm.com> writes:
> Paul Mackerras <paulus at samba.org> writes:
>
>> On Tue, Feb 26, 2013 at 01:34:59PM +0530, Aneesh Kumar K.V wrote:
>>> From: "Aneesh Kumar K.V" <aneesh.kumar at linux.vnet.ibm.com>
>>>
>>> +static inline int hpte_actual_psize(struct hash_pte *hptep, int psize)
>>> +{
>>> + unsigned int mask;
>>> + int i, penc, shift;
>>> + /* Look at the 8 bit LP value */
>>> + unsigned int lp = (hptep->r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
>>> +
>>> + penc = 0;
>>> + for (i = 0; i < MMU_PAGE_COUNT; i++) {
>>> + /* valid entries have a shift value */
>>> + if (!mmu_psize_defs[i].shift)
>>> + continue;
>>> +
>>> + /* encoding bits per actual page size */
>>> + shift = mmu_psize_defs[i].shift - 11;
>>> + if (shift > 9)
>>> + shift = 9;
>>> + mask = (1 << shift) - 1;
>>> + if ((lp & mask) == mmu_psize_defs[psize].penc[i])
>>> + return i;
>>> + }
>>> + return -1;
>>> +}
>>
>> This doesn't look right to me. First, it's not clear what the 11 and
>> 9 refer to, and I think the 9 should be LP_BITS (i.e. 8). Secondly,
>> the mask for the comparison needs to depend on the actual page size
>> not the base page size.
>
> How about the below. I am yet to test this in user space.
I needed to special case 4K case. This seems to work fine with the test.
static inline int hpte_actual_psize(struct hash_pte *hptep, int psize)
{
unsigned int mask;
int i, penc, shift;
/* Look at the 8 bit LP value */
unsigned int lp = (hptep->r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
/* First check if it is large page */
if (!(hptep->v & HPTE_V_LARGE))
return MMU_PAGE_4K;
penc = 0;
for (i = 1; i < MMU_PAGE_COUNT; i++) {
/* valid entries have a shift value */
if (!mmu_psize_defs[i].shift)
continue;
/*
* encoding bits per actual page size
* PTE LP actual page size
* rrrr rrrz ≥8KB
* rrrr rrzz ≥16KB
* rrrr rzzz ≥32KB
* rrrr zzzz ≥64KB
* .......
*/
shift = mmu_psize_defs[i].shift -
mmu_psize_defs[MMU_PAGE_4K].shift;
if (shift > LP_BITS)
shift = LP_BITS;
mask = (1 << shift) - 1;
if ((lp & mask) == mmu_psize_defs[psize].penc[i])
return i;
}
return -1;
}
More information about the Linuxppc-dev
mailing list