On Mon, 2015-11-09 at 14:17 +0100, Paolo Bonzini wrote: > > > static inline bool permission_fault(struct kvm_vcpu *vcpu, > > > struct kvm_mmu *mmu, > > > - unsigned pte_access, > > > unsigned pfec) > > > + unsigned pte_access, unsigned pte_pkeys, > > > unsigned pfec) > > > { > > > - int cpl = kvm_x86_ops->get_cpl(vcpu); > > > - unsigned long rflags = kvm_x86_ops->get_rflags(vcpu); > > > + unsigned long smap, rflags; > > > + u32 pkru; > > > + int cpl, index; > > > + bool wf, uf, pk, pkru_ad, pkru_wd; > > > + > > > + cpl = kvm_x86_ops->get_cpl(vcpu); > > > + rflags = kvm_x86_ops->get_rflags(vcpu); > > > + > > > + pkru = read_pkru(); > > > + > > > + /* > > > + * PKRU defines 32 bits, there are 16 domains and 2 > > > attribute bits per > > > + * domain in pkru, pkey is index to a defined domain, so > > > the value of > > > + * pkey * PKRU_ATTRS + R/W is offset of a defined domain > > > attribute. > > > + */ > > > + pkru_ad = (pkru >> (pte_pkeys * PKRU_ATTRS + PKRU_READ)) > > > & 1; > > > + pkru_wd = (pkru >> (pte_pkeys * PKRU_ATTRS + > > > PKRU_WRITE)) & 1; > > > + > > > + wf = pfec & PFERR_WRITE_MASK; > > > + uf = pfec & PFERR_USER_MASK; > > > + > > > + /* > > > + * PKeys 2nd and 6th conditions: > > > + * 2.EFER_LMA=1 > > > + * 6.PKRU.AD=1 > > > + * or The access is a data write and PKRU.WD=1 and > > > + * either CR0.WP=1 or it is a user mode > > > access > > > + */ > > > + pk = is_long_mode(vcpu) && (pkru_ad || > > > + (pkru_wd && wf && > > > (is_write_protection(vcpu) || uf))); > > A little more optimized: > > pkru_bits = (pkru >> (pte_pkeys * PKRU_ATTRS)) & 3; > > /* > * Ignore PKRU.WD if not relevant to this access (a read, > * or a supervisor mode access if CR0.WP=0). > */ > if (!wf || (!uf && !is_write_protection(vcpu))) > pkru_bits &= ~(1 << PKRU_WRITE); > > ... and then just check pkru_bits != 0. > > > > + /* > > > + * PK bit right value in pfec equal to > > > + * PK bit current value in pfec and pk value. > > > + */ > > > + pfec &= (pk << PFERR_PK_BIT) + ~PFERR_PK_MASK; > > > > PK is only applicable to guest page tables, but if you do not > > support > > PKRU without EPT (patch 9), none of this is necessary, is it? > > Doh. :( Sorry, this is of course needed for the emulation case. > > I think you should optimize this for the common case where pkru is > zero, > hence pk will always be zero. So something like > > pkru = is_long_mode(vcpu) ? read_pkru() : 0; > if (unlikely(pkru) && (pfec & PFERR_PK_MASK)) { > ... from above ... */ > > /* Flip PFERR_PK_MASK if pkru_bits is non-zero */ > pfec ^= -pkru_bits & PFERR_PK_MASK; If pkru_bits is zero, it means dynamically conditions is not met for protection-key violations, so pfec on PK bit should be flipped. So I guess it should be: pfec ^= pkru_bits ? 0 : PFERR_PK_MASK; > } > > Paolo > ��.n��������+%������w��{.n�����o�^n�r������&��z�ޗ�zf���h���~����������_��+v���)ߣ�