Skip to content

Attribute bits in stage 1/stage 2 block descriptors are not fully masked during AArch64 page table walks

In the aarch64 LPAE page table walk implemented in get_phys_addr_lpae once a non-table descriptor is reached (block descriptor for levels 1/2 or a page descriptor at level 3) the final physical address is calculated by extracting the descriptor address from the descriptor by masking it off with descaddrmask and then combining it with the vaddr offset.

This is incorrect however, as descaddrmask is based only on the translation granule size, which is correct for table descriptors and page descriptors, but not for block descriptors, for which the final address bits are determined based on the walk level. (See section D5.3.1 in the armv8 arm)

As a result, page table walks with a granule size of 4KB or 16KB which end on a block descriptor do not mask off enough attribute bits, meaning some RES0 bits are used as part of the final physical address, this is especially problematic as the nT bit is defined at bit 16, which is included in the final address as well.

A pseudocode implementation of correct block-descriptor base address extraction is available in the armv8 arm under aarch64/translation/vmsa_addrcalc/AArch64.BlockBase for reference.

Edited by Idan Horowitz
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information