On 1/27/2021 2:16 AM, Paolo Bonzini wrote:
On 07/08/20 10:48, Chenyi Qiang wrote:
* index of the protection domain, so pte_pkey * 2 is
* is the index of the first bit for the domain.
*/
- pkr_bits = (vcpu->arch.pkru >> (pte_pkey * 2)) & 3;
+ if (pte_access & PT_USER_MASK)
+ pkr_bits = (vcpu->arch.pkru >> (pte_pkey * 2)) & 3;
+ else
+ pkr_bits = 0;
- /* clear present bit, replace PFEC.RSVD with ACC_USER_MASK. */
- offset = (pfec & ~1) +
- ((pte_access & PT_USER_MASK) << (PFERR_RSVD_BIT -
PT_USER_SHIFT));
+ /* clear present bit */
+ offset = (pfec & ~1);
pkr_bits &= mmu->pkr_mask >> offset;
errcode |= -pkr_bits & PFERR_PK_MASK;
I think this is incorrect. mmu->pkr_mask must cover both clear and set
ACC_USER_MASK, in to cover all combinations of CR4.PKE and CR4.PKS.
Right now, check_pkey is !ff && pte_user, but you need to make it
something like
check_pkey = !ff && (pte_user ? cr4_pke : cr4_pks);
Paolo
Oh, I didn't distinguish the cr4_pke/cr4_pks check. Will fix this issue.