From: Lai Jiangshan <jiangshan.ljs@xxxxxxxxxxxx> For most cases, mmu->root_role.direct is true and mmu->root_role.level is not PT32E_ROOT_LEVEL which means using_local_root_page() is often checking for all the three test which is not good in fast paths. Morph the conditions in using_local_root_page() to an equivalent one to reduce a check. Signed-off-by: Lai Jiangshan <jiangshan.ljs@xxxxxxxxxxxx> --- arch/x86/kvm/mmu/mmu.c | 45 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 624b6d2473f7..240ebe589caf 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -1716,11 +1716,52 @@ static void drop_parent_pte(struct kvm_mmu_page *sp, * * (There is no "mmu->root_role.level > PT32E_ROOT_LEVEL" here, because it is * already ensured that mmu->root_role.level >= PT32E_ROOT_LEVEL) + * + * But mmu->root_role.direct is normally true and mmu->root_role.level is + * normally not PT32E_ROOT_LEVEL. To reduce a check for the fast path of + * fast_pgd_switch() in mormal case, mmu->root_role.direct is checked first. + * + * The return value is: + * mmu->root_role.level == PT32E_ROOT_LEVEL || + * (!mmu->root_role.direct && mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL) + * => + * (mmu->root_role.direct && mmu->root_role.level == PT32E_ROOT_LEVEL) || + * (!mmu->root_role.direct && mmu->root_role.level == PT32E_ROOT_LEVEL) || + * (!mmu->root_role.direct && mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL) + * => + * (mmu->root_role.direct && mmu->root_role.level == PT32E_ROOT_LEVEL) || + * (!mmu->root_role.direct && + * (mmu->root_role.level == PT32E_ROOT_LEVEL || + * mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL)) + * => (for !direct, mmu->root_role.level == PT32E_ROOT_LEVEL implies + * mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL) + * => + * (mmu->root_role.direct && mmu->root_role.level == PT32E_ROOT_LEVEL) || + * (!mmu->root_role.direct && mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL) + * + * In other words: + * + * For the first and third cases, it is + * mmu->root_role.direct && mmu->root_role.level == PT32E_ROOT_LEVEL + * And if this condition is true, it must be one of the two cases. + * + * For the 2nd, 4th and 5th cases, it is + * !mmu->root_role.direct && mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL + * And if this condition is true, it must be one of the three cases although + * it is not so intuitive. It can be split into: + * mmu->root_role.level == PT32E_ROOT_LEVEL && + * (!mmu->root_role.direct && mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL) + * which is for the 2nd and 4th cases and + * mmu->root_role.level > PT32E_ROOT_LEVEL && + * !mmu->root_role.direct && mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL + * which is the last case. */ static bool using_local_root_page(struct kvm_mmu *mmu) { - return mmu->root_role.level == PT32E_ROOT_LEVEL || - (!mmu->root_role.direct && mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL); + if (mmu->root_role.direct) + return mmu->root_role.level == PT32E_ROOT_LEVEL; + else + return mmu->cpu_role.base.level <= PT32E_ROOT_LEVEL; } static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, int direct) -- 2.19.1.6.gb485710b