Message ID | 20181031175745.18650-3-punit.agrawal@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: Support PUD hugepage at stage 2 | expand |
On 10/31/2018 11:27 PM, Punit Agrawal wrote: > Stage 2 fault handler marks a page as executable if it is handling an > execution fault or if it was a permission fault in which case the > executable bit needs to be preserved. > > The logic to decide if the page should be marked executable is > duplicated for PMD and PTE entries. To avoid creating another copy > when support for PUD hugepages is introduced refactor the code to > share the checks needed to mark a page table entry as executable. > > Signed-off-by: Punit Agrawal <punit.agrawal@arm.com> > Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> > Cc: Christoffer Dall <christoffer.dall@arm.com> > Cc: Marc Zyngier <marc.zyngier@arm.com> > --- > virt/kvm/arm/mmu.c | 28 +++++++++++++++------------- > 1 file changed, 15 insertions(+), 13 deletions(-) > > diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c > index 59595207c5e1..6912529946fb 100644 > --- a/virt/kvm/arm/mmu.c > +++ b/virt/kvm/arm/mmu.c > @@ -1475,7 +1475,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > unsigned long fault_status) > { > int ret; > - bool write_fault, exec_fault, writable, force_pte = false; > + bool write_fault, writable, force_pte = false; > + bool exec_fault, needs_exec; New line not required, still within 80 characters. > unsigned long mmu_seq; > gfn_t gfn = fault_ipa >> PAGE_SHIFT; > struct kvm *kvm = vcpu->kvm; > @@ -1598,19 +1599,25 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > if (exec_fault) > invalidate_icache_guest_page(pfn, vma_pagesize); > > + /* > + * If we took an execution fault we have made the > + * icache/dcache coherent above and should now let the s2 Coherent or invalidated with invalidate_icache_guest_page ? > + * mapping be executable. > + * > + * Write faults (!exec_fault && FSC_PERM) are orthogonal to > + * execute permissions, and we preserve whatever we have. > + */ Otherwise looks good.
On 03/12/2018 13:32, Anshuman Khandual wrote: > > > On 10/31/2018 11:27 PM, Punit Agrawal wrote: >> Stage 2 fault handler marks a page as executable if it is handling an >> execution fault or if it was a permission fault in which case the >> executable bit needs to be preserved. >> >> The logic to decide if the page should be marked executable is >> duplicated for PMD and PTE entries. To avoid creating another copy >> when support for PUD hugepages is introduced refactor the code to >> share the checks needed to mark a page table entry as executable. >> >> Signed-off-by: Punit Agrawal <punit.agrawal@arm.com> >> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> >> Cc: Christoffer Dall <christoffer.dall@arm.com> >> Cc: Marc Zyngier <marc.zyngier@arm.com> >> --- >> virt/kvm/arm/mmu.c | 28 +++++++++++++++------------- >> 1 file changed, 15 insertions(+), 13 deletions(-) >> >> diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c >> index 59595207c5e1..6912529946fb 100644 >> --- a/virt/kvm/arm/mmu.c >> +++ b/virt/kvm/arm/mmu.c >> @@ -1475,7 +1475,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, >> unsigned long fault_status) >> { >> int ret; >> - bool write_fault, exec_fault, writable, force_pte = false; >> + bool write_fault, writable, force_pte = false; >> + bool exec_fault, needs_exec; > > New line not required, still within 80 characters. > >> unsigned long mmu_seq; >> gfn_t gfn = fault_ipa >> PAGE_SHIFT; >> struct kvm *kvm = vcpu->kvm; >> @@ -1598,19 +1599,25 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, >> if (exec_fault) >> invalidate_icache_guest_page(pfn, vma_pagesize); >> >> + /* >> + * If we took an execution fault we have made the >> + * icache/dcache coherent above and should now let the s2 > > Coherent or invalidated with invalidate_icache_guest_page ? We also do clean_dcache above if needed. So that makes sure the data is coherent. Am I missing something here ? > >> + * mapping be executable. >> + * >> + * Write faults (!exec_fault && FSC_PERM) are orthogonal to >> + * execute permissions, and we preserve whatever we have. >> + */ > > Otherwise looks good. > Suzuki
On Mon, Dec 03, 2018 at 07:02:23PM +0530, Anshuman Khandual wrote: > > > On 10/31/2018 11:27 PM, Punit Agrawal wrote: > > Stage 2 fault handler marks a page as executable if it is handling an > > execution fault or if it was a permission fault in which case the > > executable bit needs to be preserved. > > > > The logic to decide if the page should be marked executable is > > duplicated for PMD and PTE entries. To avoid creating another copy > > when support for PUD hugepages is introduced refactor the code to > > share the checks needed to mark a page table entry as executable. > > > > Signed-off-by: Punit Agrawal <punit.agrawal@arm.com> > > Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> > > Cc: Christoffer Dall <christoffer.dall@arm.com> > > Cc: Marc Zyngier <marc.zyngier@arm.com> > > --- > > virt/kvm/arm/mmu.c | 28 +++++++++++++++------------- > > 1 file changed, 15 insertions(+), 13 deletions(-) > > > > diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c > > index 59595207c5e1..6912529946fb 100644 > > --- a/virt/kvm/arm/mmu.c > > +++ b/virt/kvm/arm/mmu.c > > @@ -1475,7 +1475,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > > unsigned long fault_status) > > { > > int ret; > > - bool write_fault, exec_fault, writable, force_pte = false; > > + bool write_fault, writable, force_pte = false; > > + bool exec_fault, needs_exec; > > New line not required, still within 80 characters. > He's trying to logically group the two variables. I don't see a problem with that. Thanks, Christoffer
On Wed, Dec 05, 2018 at 10:47:10AM +0000, Suzuki K Poulose wrote: > > > On 03/12/2018 13:32, Anshuman Khandual wrote: > > > > > >On 10/31/2018 11:27 PM, Punit Agrawal wrote: > >>Stage 2 fault handler marks a page as executable if it is handling an > >>execution fault or if it was a permission fault in which case the > >>executable bit needs to be preserved. > >> > >>The logic to decide if the page should be marked executable is > >>duplicated for PMD and PTE entries. To avoid creating another copy > >>when support for PUD hugepages is introduced refactor the code to > >>share the checks needed to mark a page table entry as executable. > >> > >>Signed-off-by: Punit Agrawal <punit.agrawal@arm.com> > >>Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> > >>Cc: Christoffer Dall <christoffer.dall@arm.com> > >>Cc: Marc Zyngier <marc.zyngier@arm.com> > >>--- > >> virt/kvm/arm/mmu.c | 28 +++++++++++++++------------- > >> 1 file changed, 15 insertions(+), 13 deletions(-) > >> > >>diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c > >>index 59595207c5e1..6912529946fb 100644 > >>--- a/virt/kvm/arm/mmu.c > >>+++ b/virt/kvm/arm/mmu.c > >>@@ -1475,7 +1475,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > >> unsigned long fault_status) > >> { > >> int ret; > >>- bool write_fault, exec_fault, writable, force_pte = false; > >>+ bool write_fault, writable, force_pte = false; > >>+ bool exec_fault, needs_exec; > > > >New line not required, still within 80 characters. > > > >> unsigned long mmu_seq; > >> gfn_t gfn = fault_ipa >> PAGE_SHIFT; > >> struct kvm *kvm = vcpu->kvm; > >>@@ -1598,19 +1599,25 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > >> if (exec_fault) > >> invalidate_icache_guest_page(pfn, vma_pagesize); > >>+ /* > >>+ * If we took an execution fault we have made the > >>+ * icache/dcache coherent above and should now let the s2 > > > >Coherent or invalidated with invalidate_icache_guest_page ? > > We also do clean_dcache above if needed. So that makes sure > the data is coherent. Am I missing something here ? > I think you've got it right. We have made the icache coherent with the data/instructions in the page by invalidating the icache. I think the comment is ok either way. Thanks, Christoffer
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index 59595207c5e1..6912529946fb 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -1475,7 +1475,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, unsigned long fault_status) { int ret; - bool write_fault, exec_fault, writable, force_pte = false; + bool write_fault, writable, force_pte = false; + bool exec_fault, needs_exec; unsigned long mmu_seq; gfn_t gfn = fault_ipa >> PAGE_SHIFT; struct kvm *kvm = vcpu->kvm; @@ -1598,19 +1599,25 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, if (exec_fault) invalidate_icache_guest_page(pfn, vma_pagesize); + /* + * If we took an execution fault we have made the + * icache/dcache coherent above and should now let the s2 + * mapping be executable. + * + * Write faults (!exec_fault && FSC_PERM) are orthogonal to + * execute permissions, and we preserve whatever we have. + */ + needs_exec = exec_fault || + (fault_status == FSC_PERM && stage2_is_exec(kvm, fault_ipa)); + if (vma_pagesize == PMD_SIZE) { pmd_t new_pmd = pfn_pmd(pfn, mem_type); new_pmd = pmd_mkhuge(new_pmd); if (writable) new_pmd = kvm_s2pmd_mkwrite(new_pmd); - if (exec_fault) { + if (needs_exec) new_pmd = kvm_s2pmd_mkexec(new_pmd); - } else if (fault_status == FSC_PERM) { - /* Preserve execute if XN was already cleared */ - if (stage2_is_exec(kvm, fault_ipa)) - new_pmd = kvm_s2pmd_mkexec(new_pmd); - } ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd); } else { @@ -1621,13 +1628,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, mark_page_dirty(kvm, gfn); } - if (exec_fault) { + if (needs_exec) new_pte = kvm_s2pte_mkexec(new_pte); - } else if (fault_status == FSC_PERM) { - /* Preserve execute if XN was already cleared */ - if (stage2_is_exec(kvm, fault_ipa)) - new_pte = kvm_s2pte_mkexec(new_pte); - } ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, flags); }