From: Paolo Bonzini <pbonzini@redhat.com>
To: Huaitong Han <huaitong.han@intel.com>, gleb@kernel.org
Cc: kvm@vger.kernel.org, guangrong.xiao@linux.intel.com
Subject: Re: [PATCH V5 5/9] KVM, pkeys: introduce pkru_mask to cache conditions
Date: Mon, 21 Mar 2016 18:43:13 +0100 [thread overview]
Message-ID: <56F032B1.4090201@redhat.com> (raw)
In-Reply-To: <1458554760-4374-6-git-send-email-huaitong.han@intel.com>
Just some editing of the comments:
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 44adbb8..8df2581 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -326,6 +326,15 @@ struct kvm_mmu {
> */
> u8 permissions[16];
>
> + /*
> + * PKRU bitmap mask indicates if pkey (ADi/WDi) check is needed
> + *
> + * There are 16 domains which are indexed by page fault error
> + * code [4:1] and the PFEC.RSVD is replaced by ACC_USER_MASK,
> + * each domain has 2 bits which indicate AD and WD of pkey.
+ * The pkru_mask indicates if protection key checks are needed. It
+ * consists of 16 domains indexed by page fault error code bits [4:1],
+ * with PFEC.RSVD replaced by ACC_USER_MASK from the page tables.
+ * Each domain has 2 bits which are ANDed with AD and WD from PKRU.
> + */
> + u32 pkru_mask;
> +
> u64 *pae_root;
> u64 *lm_root;
>
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 0e20230..e5604d1 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -3836,6 +3836,72 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
> }
> }
>
> +/*
> +* PKU:additional mechanism by which the paging controls access to user-mode
> +* addresses based on the value in the PKRU register. A fault is considered
> +* as a PKU violation if all of the following conditions are true:
> +* 1.CR4_PKE=1.
> +* 2.EFER_LMA=1.
> +* 3.page is present with no reserved bit violations.
> +* 4.the access is not an instruction fetch.
> +* 5.the access is to a user page.
> +* 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 access.
> +*
> +* PKRU bitmask is produced according to the conditions above.
+* PKU is an additional mechanism by which the paging controls access to
+* user-mode addresses based on the value in the PKRU register. Protection
+* key violations are reported through a bit in the page fault error code.
+* Unlike other bits of the error code, the PK bit is not known at the
+* call site of e.g. gva_to_gpa; it must be computed directly in
+* permission_fault based on two bits of PKRU, on some machine state (CR4,
+* CR0, EFER, CPL), and on other bits of the error code and the page tables.
*
-* PKRU bitmask is produced according to the conditions above.
+* In particular the following conditions come from the error code, the
+* page tables and the machine state:
+* - PK is always zero unless CR4.PKE=1 and EFER.LMA=1
+* - PK is always zero if RSVD=1 (reserved bit set) or F=1 (instruction fetch)
+* - PK is always zero if U=0 in the page tables
+* - PKRU.WD is ignored if CR0.WP=0 and the access is a supervisor access.
+*
+* The PKRU bitmask caches the result of these four conditions. The error
+* code (minus the P bit) and the page table's U bit form an index into the
+* PKRU bitmask. Two bits of the PKRU bitmask are then extracted and ANDed
+* with the two bits of the PKRU register corresponding to the protection key.
+* For the first three conditions above the bits will be 00, thus masking
+* away both AD and WD. For the last condition, only WD will be masked away.
Thanks,
Paolo
> +*/
> +static void update_pkru_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
> + bool ept)
> +{
> + unsigned bit;
> + bool wp;
> +
> + if (ept) {
> + mmu->pkru_mask = 0;
> + return;
> + }
> +
> + /* PKEY is enabled only if CR4.PKE and EFER.LMA are both set. */
> + if (!kvm_read_cr4_bits(vcpu, X86_CR4_PKE) || !is_long_mode(vcpu)) {
> + mmu->pkru_mask = 0;
> + return;
> + }
> +
> + wp = is_write_protection(vcpu);
> +
> + for (bit = 0; bit < ARRAY_SIZE(mmu->permissions); ++bit) {
> + unsigned pfec, pkey_bits;
> + bool check_pkey, check_write, ff, uf, wf, pte_user;
> +
> + pfec = bit << 1;
> + ff = pfec & PFERR_FETCH_MASK;
> + uf = pfec & PFERR_USER_MASK;
> + wf = pfec & PFERR_WRITE_MASK;
> +
> + /* PFEC.RSVD is replaced by ACC_USER_MASK. */
> + pte_user = pfec & PFERR_RSVD_MASK;
> +
> + /*
> + * Only need to check the access which is not an
> + * instruction fetch and is to a user page.
> + */
> + check_pkey = (!ff && pte_user);
> + /*
> + * write access is controlled by PKRU if it is a
> + * user access or CR0.WP = 1.
> + */
> + check_write = check_pkey && wf && (uf || wp);
> +
> + /* PKRU.AD stops both read and write access. */
> + pkey_bits = !!check_pkey;
> + /* PKRU.WD stops write access. */
> + pkey_bits |= (!!check_write) << 1;
> +
> + mmu->pkru_mask |= (pkey_bits & 3) << pfec;
> + }
> +}
> +
> static void update_last_nonleaf_level(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu)
> {
> unsigned root_level = mmu->root_level;
> @@ -3863,6 +3929,7 @@ static void paging64_init_context_common(struct kvm_vcpu *vcpu,
>
> reset_rsvds_bits_mask(vcpu, context);
> update_permission_bitmask(vcpu, context, false);
> + update_pkru_bitmask(vcpu, context, false);
> update_last_nonleaf_level(vcpu, context);
>
> MMU_WARN_ON(!is_pae(vcpu));
> @@ -3890,6 +3957,7 @@ static void paging32_init_context(struct kvm_vcpu *vcpu,
>
> reset_rsvds_bits_mask(vcpu, context);
> update_permission_bitmask(vcpu, context, false);
> + update_pkru_bitmask(vcpu, context, false);
> update_last_nonleaf_level(vcpu, context);
>
> context->page_fault = paging32_page_fault;
> @@ -3948,6 +4016,7 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
> }
>
> update_permission_bitmask(vcpu, context, false);
> + update_pkru_bitmask(vcpu, context, false);
> update_last_nonleaf_level(vcpu, context);
> reset_tdp_shadow_zero_bits_mask(vcpu, context);
> }
> @@ -4000,6 +4069,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly)
> context->direct_map = false;
>
> update_permission_bitmask(vcpu, context, true);
> + update_pkru_bitmask(vcpu, context, true);
> reset_rsvds_bits_mask_ept(vcpu, context, execonly);
> reset_ept_shadow_zero_bits_mask(vcpu, context, execonly);
> }
> @@ -4054,6 +4124,7 @@ static void init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
> }
>
> update_permission_bitmask(vcpu, g_context, false);
> + update_pkru_bitmask(vcpu, g_context, false);
> update_last_nonleaf_level(vcpu, g_context);
> }
>
>
next prev parent reply other threads:[~2016-03-21 17:43 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-21 10:05 [PATCH V5 0/9] KVM, pkeys: add memory protection-key support Huaitong Han
2016-03-21 10:05 ` [PATCH V5 1/9] KVM, pkeys: disable pkeys for guests in non-paging mode Huaitong Han
2016-03-21 10:05 ` [PATCH V5 2/9] KVM, pkeys: add pkeys support for xsave state Huaitong Han
2016-03-21 10:05 ` [PATCH V5 3/9] x86: pkey: introduce write_pkru() for KVM Huaitong Han
2016-03-21 10:05 ` [PATCH V5 4/9] KVM, pkeys: save/restore PKRU when guest/host switches Huaitong Han
2016-03-21 10:28 ` Paolo Bonzini
2016-03-21 10:37 ` Han, Huaitong
2016-03-21 10:05 ` [PATCH V5 5/9] KVM, pkeys: introduce pkru_mask to cache conditions Huaitong Han
2016-03-21 17:43 ` Paolo Bonzini [this message]
2016-03-21 10:05 ` [PATCH V5 6/9] KVM, pkeys: add pkeys support for permission_fault logic Huaitong Han
2016-03-21 10:55 ` Paolo Bonzini
2016-03-21 12:41 ` Han, Huaitong
2016-03-21 10:05 ` [PATCH V5 7/9] KVM, pkeys: expose CPUID/CR4 to guest Huaitong Han
2016-03-21 11:36 ` Paolo Bonzini
2016-03-21 11:56 ` Han, Huaitong
2016-03-21 12:08 ` Paolo Bonzini
2016-03-21 10:05 ` [PATCH V5 8/9] KVM, pkeys: disable PKU feature without ept Huaitong Han
2016-03-21 11:01 ` Paolo Bonzini
2016-03-21 10:06 ` [PATCH V5 9/9] Revert "KVM: MMU: precompute page fault error code" Huaitong Han
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56F032B1.4090201@redhat.com \
--to=pbonzini@redhat.com \
--cc=gleb@kernel.org \
--cc=guangrong.xiao@linux.intel.com \
--cc=huaitong.han@intel.com \
--cc=kvm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox