Intel-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Christian König" <christian.koenig@amd.com>
To: "Zhou, Xianrong" <Xianrong.Zhou@amd.com>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Cc: "lee@kernel.org" <lee@kernel.org>,
	"kherbst@redhat.com" <kherbst@redhat.com>,
	"nouveau@lists.freedesktop.org" <nouveau@lists.freedesktop.org>,
	"dave.hansen@linux.intel.com" <dave.hansen@linux.intel.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"Huang, Ray" <Ray.Huang@amd.com>, "hpa@zytor.com" <hpa@zytor.com>,
	"zack.rusin@broadcom.com" <zack.rusin@broadcom.com>,
	"airlied@gmail.com" <airlied@gmail.com>,
	"Zhang, GuoQing \(Sam\)" <GuoQing.Zhang@amd.com>,
	"Li, Huazeng" <Huazeng.Li@amd.com>,
	"x86@kernel.org" <x86@kernel.org>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>,
	"Xu, Colin" <Colin.Xu@amd.com>,
	"mingo@redhat.com" <mingo@redhat.com>,
	"dakr@redhat.com" <dakr@redhat.com>,
	"matthew.auld@intel.com" <matthew.auld@intel.com>,
	"bcm-kernel-feedback-list@broadcom.com"
	<bcm-kernel-feedback-list@broadcom.com>,
	"Yang, Philip" <Philip.Yang@amd.com>,
	"tzimmermann@suse.de" <tzimmermann@suse.de>,
	"intel-gfx@lists.freedesktop.org"
	<intel-gfx@lists.freedesktop.org>, "bp@alien8.de" <bp@alien8.de>,
	"mripard@kernel.org" <mripard@kernel.org>,
	"luto@kernel.org" <luto@kernel.org>,
	"rodrigo.vivi@intel.com" <rodrigo.vivi@intel.com>,
	"tglx@linutronix.de" <tglx@linutronix.de>,
	"Zhu, James" <James.Zhu@amd.com>,
	"surenb@google.com" <surenb@google.com>,
	"Liu, Monk" <Monk.Liu@amd.com>,
	"Kuehling, Felix" <Felix.Kuehling@amd.com>,
	"Pan, Xinhui" <Xinhui.Pan@amd.com>,
	"daniel@ffwll.ch" <daniel@ffwll.ch>,
	"Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"akpm@linux-foundation.org" <akpm@linux-foundation.org>,
	"SHANMUGAM, SRINIVASAN" <SRINIVASAN.SHANMUGAM@amd.com>,
	"nirmoy.das@intel.com" <nirmoy.das@intel.com>
Subject: Re: [PATCH] mm: Remove double faults once write a device pfn
Date: Tue, 23 Jan 2024 12:44:32 +0100	[thread overview]
Message-ID: <76c3658d-2256-49c6-8e4c-49555c0a350a@amd.com> (raw)
In-Reply-To: <MN2PR12MB4302C529B9F231F85539628EF1742@MN2PR12MB4302.namprd12.prod.outlook.com>

Am 23.01.24 um 09:33 schrieb Zhou, Xianrong:
> [AMD Official Use Only - General]
>
>>> The vmf_insert_pfn_prot could cause unnecessary double faults on a
>>> device pfn. Because currently the vmf_insert_pfn_prot does not make
>>> the pfn writable so the pte entry is normally read-only or dirty
>>> catching.
>> What? How do you got to this conclusion?
> Sorry. I did not mention that this problem only exists on arm64 platform.

Ok, that makes at least a little bit more sense.

> Because on arm64 platform the PTE_RDONLY is automatically attached to
> the userspace pte entries even through VM_WRITE + VM_SHARE.
> The  PTE_RDONLY needs to be cleared in vmf_insert_pfn_prot. However
> vmf_insert_pfn_prot do not make the pte writable passing false @mkwrite
> to insert_pfn.

Question is why is arm64 doing this? As far as I can see they must have 
some hardware reason for that.

The mkwrite parameter to insert_pfn() was added by commit b2770da642540 
to make insert_pfn() look more like insert_pfn_pmd() so that the DAX 
code can insert PTEs which are writable and dirty at the same time.

This is a completely different use case to what you try to use it here 
for and that looks extremely fishy to me.

Regards,
Christian.

>
>>> The first fault only sets up the pte entry which actually is dirty
>>> catching. And the second immediate fault to the pfn due to first dirty
>>> catching when the cpu re-execute the store instruction.
>> It could be that this is done to work around some hw behavior, but not
>> because of dirty catching.
>>
>>> Normally if the drivers call vmf_insert_pfn_prot and also supply
>>> 'pfn_mkwrite' callback within vm_operations_struct which requires the
>>> pte to be dirty catching then the vmf_insert_pfn_prot and the double
>>> fault are reasonable. It is not a problem.
>> Well, as far as I can see that behavior absolutely doesn't make sense.
>>
>> When pfn_mkwrite is requested then the driver should use PAGE_COPY, which
>> is exactly what VMWGFX (the only driver using dirty tracking) is doing.
>>
>> Everybody else uses PAGE_SHARED which should make the pte writeable
>> immediately.
>>
>> Regards,
>> Christian.
>>
>>> However the most of drivers calling vmf_insert_pfn_prot do not supply
>>> the 'pfn_mkwrite' callback so that the second fault is unnecessary.
>>>
>>> So just like vmf_insert_mixed and vmf_insert_mixed_mkwrite pair, we
>>> should also supply vmf_insert_pfn_mkwrite for drivers as well.
>>>
>>> Signed-off-by: Xianrong Zhou <Xianrong.Zhou@amd.com>
>>> ---
>>>    arch/x86/entry/vdso/vma.c                  |  3 ++-
>>>    drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c    |  2 +-
>>>    drivers/gpu/drm/i915/gem/i915_gem_ttm.c    |  2 +-
>>>    drivers/gpu/drm/nouveau/nouveau_gem.c      |  2 +-
>>>    drivers/gpu/drm/radeon/radeon_gem.c        |  2 +-
>>>    drivers/gpu/drm/ttm/ttm_bo_vm.c            |  8 +++++---
>>>    drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c |  8 +++++---
>>>    include/drm/ttm/ttm_bo.h                   |  3 ++-
>>>    include/linux/mm.h                         |  2 +-
>>>    mm/memory.c                                | 14 +++++++++++---
>>>    10 files changed, 30 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
>>> index 7645730dc228..dd2431c2975f 100644
>>> --- a/arch/x86/entry/vdso/vma.c
>>> +++ b/arch/x86/entry/vdso/vma.c
>>> @@ -185,7 +185,8 @@ static vm_fault_t vvar_fault(const struct
>> vm_special_mapping *sm,
>>>              if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK))
>> {
>>>                      return vmf_insert_pfn_prot(vma, vmf->address,
>>>                                      __pa(pvti) >> PAGE_SHIFT,
>>> -                                   pgprot_decrypted(vma-
>>> vm_page_prot));
>>> +                                   pgprot_decrypted(vma-
>>> vm_page_prot),
>>> +                                   true);
>>>              }
>>>      } else if (sym_offset == image->sym_hvclock_page) {
>>>              pfn = hv_get_tsc_pfn();
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
>>> index 49a5f1c73b3e..adcb20d9e624 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
>>> @@ -64,7 +64,7 @@ static vm_fault_t amdgpu_gem_fault(struct vm_fault
>> *vmf)
>>>              }
>>>
>>>              ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma-
>>> vm_page_prot,
>>> -                                          TTM_BO_VM_NUM_PREFAULT);
>>> +                                          TTM_BO_VM_NUM_PREFAULT,
>> true);
>>>              drm_dev_exit(idx);
>>>      } else {
>>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> index 9227f8146a58..c6f13ae6c308 100644
>>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>>> @@ -1114,7 +1114,7 @@ static vm_fault_t vm_fault_ttm(struct vm_fault
>>> *vmf)
>>>
>>>      if (drm_dev_enter(dev, &idx)) {
>>>              ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma-
>>> vm_page_prot,
>>> -                                          TTM_BO_VM_NUM_PREFAULT);
>>> +                                          TTM_BO_VM_NUM_PREFAULT,
>> true);
>>>              drm_dev_exit(idx);
>>>      } else {
>>>              ret = ttm_bo_vm_dummy_page(vmf, vmf->vma-
>>> vm_page_prot); diff
>>> --git a/drivers/gpu/drm/nouveau/nouveau_gem.c
>>> b/drivers/gpu/drm/nouveau/nouveau_gem.c
>>> index 49c2bcbef129..7e1453762ec9 100644
>>> --- a/drivers/gpu/drm/nouveau/nouveau_gem.c
>>> +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
>>> @@ -56,7 +56,7 @@ static vm_fault_t nouveau_ttm_fault(struct vm_fault
>>> *vmf)
>>>
>>>      nouveau_bo_del_io_reserve_lru(bo);
>>>      prot = vm_get_page_prot(vma->vm_flags);
>>> -   ret = ttm_bo_vm_fault_reserved(vmf, prot,
>> TTM_BO_VM_NUM_PREFAULT);
>>> +   ret = ttm_bo_vm_fault_reserved(vmf, prot,
>> TTM_BO_VM_NUM_PREFAULT,
>>> +true);
>>>      nouveau_bo_add_io_reserve_lru(bo);
>>>      if (ret == VM_FAULT_RETRY && !(vmf->flags &
>> FAULT_FLAG_RETRY_NOWAIT))
>>>              return ret;
>>> diff --git a/drivers/gpu/drm/radeon/radeon_gem.c
>>> b/drivers/gpu/drm/radeon/radeon_gem.c
>>> index 3fec3acdaf28..b21cf00ae162 100644
>>> --- a/drivers/gpu/drm/radeon/radeon_gem.c
>>> +++ b/drivers/gpu/drm/radeon/radeon_gem.c
>>> @@ -62,7 +62,7 @@ static vm_fault_t radeon_gem_fault(struct vm_fault
>> *vmf)
>>>              goto unlock_resv;
>>>
>>>      ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
>>> -                                  TTM_BO_VM_NUM_PREFAULT);
>>> +                                  TTM_BO_VM_NUM_PREFAULT, true);
>>>      if (ret == VM_FAULT_RETRY && !(vmf->flags &
>> FAULT_FLAG_RETRY_NOWAIT))
>>>              goto unlock_mclk;
>>>
>>> diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c
>>> b/drivers/gpu/drm/ttm/ttm_bo_vm.c index
>> 4212b8c91dd4..7d14a7d267aa
>>> 100644
>>> --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
>>> +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
>>> @@ -167,6 +167,7 @@ EXPORT_SYMBOL(ttm_bo_vm_reserve);
>>>     * @num_prefault: Maximum number of prefault pages. The caller may
>> want to
>>>     * specify this based on madvice settings and the size of the GPU object
>>>     * backed by the memory.
>>> + * @mkwrite: make the pfn or page writable
>>>     *
>>>     * This function inserts one or more page table entries pointing to the
>>>     * memory backing the buffer object, and then returns a return code
>>> @@ -180,7 +181,8 @@ EXPORT_SYMBOL(ttm_bo_vm_reserve);
>>>     */
>>>    vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
>>>                                  pgprot_t prot,
>>> -                               pgoff_t num_prefault)
>>> +                               pgoff_t num_prefault,
>>> +                               bool mkwrite)
>>>    {
>>>      struct vm_area_struct *vma = vmf->vma;
>>>      struct ttm_buffer_object *bo = vma->vm_private_data; @@ -263,7
>>> +265,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
>>>               * at arbitrary times while the data is mmap'ed.
>>>               * See vmf_insert_pfn_prot() for a discussion.
>>>               */
>>> -           ret = vmf_insert_pfn_prot(vma, address, pfn, prot);
>>> +           ret = vmf_insert_pfn_prot(vma, address, pfn, prot, mkwrite);
>>>
>>>              /* Never error on prefaulted PTEs */
>>>              if (unlikely((ret & VM_FAULT_ERROR))) { @@ -312,7 +314,7
>> @@
>>> vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot)
>>>      /* Prefault the entire VMA range right away to avoid further faults */
>>>      for (address = vma->vm_start; address < vma->vm_end;
>>>           address += PAGE_SIZE)
>>> -           ret = vmf_insert_pfn_prot(vma, address, pfn, prot);
>>> +           ret = vmf_insert_pfn_prot(vma, address, pfn, prot, true);
>>>
>>>      return ret;
>>>    }
>>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
>>> b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
>>> index 74ff2812d66a..bb8e4b641681 100644
>>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
>>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
>>> @@ -452,12 +452,14 @@ vm_fault_t vmw_bo_vm_fault(struct vm_fault
>> *vmf)
>>>       * sure the page protection is write-enabled so we don't get
>>>       * a lot of unnecessary write faults.
>>>       */
>>> -   if (vbo->dirty && vbo->dirty->method == VMW_BO_DIRTY_MKWRITE)
>>> +   if (vbo->dirty && vbo->dirty->method == VMW_BO_DIRTY_MKWRITE)
>> {
>>>              prot = vm_get_page_prot(vma->vm_flags & ~VM_SHARED);
>>> -   else
>>> +           ret = ttm_bo_vm_fault_reserved(vmf, prot, num_prefault,
>> false);
>>> +   } else {
>>>              prot = vm_get_page_prot(vma->vm_flags);
>>> +           ret = ttm_bo_vm_fault_reserved(vmf, prot, num_prefault,
>> true);
>>> +   }
>>>
>>> -   ret = ttm_bo_vm_fault_reserved(vmf, prot, num_prefault);
>>>      if (ret == VM_FAULT_RETRY && !(vmf->flags &
>> FAULT_FLAG_RETRY_NOWAIT))
>>>              return ret;
>>>
>>> diff --git a/include/drm/ttm/ttm_bo.h b/include/drm/ttm/ttm_bo.h index
>>> 0223a41a64b2..66e293db69ee 100644
>>> --- a/include/drm/ttm/ttm_bo.h
>>> +++ b/include/drm/ttm/ttm_bo.h
>>> @@ -386,7 +386,8 @@ vm_fault_t ttm_bo_vm_reserve(struct
>> ttm_buffer_object *bo,
>>>                           struct vm_fault *vmf);
>>>    vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
>>>                                  pgprot_t prot,
>>> -                               pgoff_t num_prefault);
>>> +                               pgoff_t num_prefault,
>>> +                               bool mkwrite);
>>>    vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf);
>>>    void ttm_bo_vm_open(struct vm_area_struct *vma);
>>>    void ttm_bo_vm_close(struct vm_area_struct *vma); diff --git
>>> a/include/linux/mm.h b/include/linux/mm.h index
>>> f5a97dec5169..f8868e28ea04 100644
>>> --- a/include/linux/mm.h
>>> +++ b/include/linux/mm.h
>>> @@ -3553,7 +3553,7 @@ int vm_map_pages_zero(struct vm_area_struct
>> *vma, struct page **pages,
>>>    vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma, unsigned long
>> addr,
>>>                      unsigned long pfn);
>>>    vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned
>> long addr,
>>> -                   unsigned long pfn, pgprot_t pgprot);
>>> +                   unsigned long pfn, pgprot_t pgprot, bool mkwrite);
>>>    vm_fault_t vmf_insert_mixed(struct vm_area_struct *vma, unsigned long
>> addr,
>>>                      pfn_t pfn);
>>>    vm_fault_t vmf_insert_mixed_mkwrite(struct vm_area_struct *vma, diff
>>> --git a/mm/memory.c b/mm/memory.c index 7e1f4849463a..2c28f1a349ff
>>> 100644
>>> --- a/mm/memory.c
>>> +++ b/mm/memory.c
>>> @@ -2195,6 +2195,7 @@ static vm_fault_t insert_pfn(struct
>> vm_area_struct *vma, unsigned long addr,
>>>     * @addr: target user address of this page
>>>     * @pfn: source kernel pfn
>>>     * @pgprot: pgprot flags for the inserted page
>>> + * @mkwrite: make the pfn writable
>>>     *
>>>     * This is exactly like vmf_insert_pfn(), except that it allows drivers
>>>     * to override pgprot on a per-page basis.
>>> @@ -2223,7 +2224,7 @@ static vm_fault_t insert_pfn(struct
>> vm_area_struct *vma, unsigned long addr,
>>>     * Return: vm_fault_t value.
>>>     */
>>>    vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned
>> long addr,
>>> -                   unsigned long pfn, pgprot_t pgprot)
>>> +                   unsigned long pfn, pgprot_t pgprot, bool mkwrite)
>>>    {
>>>      /*
>>>       * Technically, architectures with pte_special can avoid all these
>>> @@ -2246,7 +2247,7 @@ vm_fault_t vmf_insert_pfn_prot(struct
>> vm_area_struct *vma, unsigned long addr,
>>>      track_pfn_insert(vma, &pgprot, __pfn_to_pfn_t(pfn, PFN_DEV));
>>>
>>>      return insert_pfn(vma, addr, __pfn_to_pfn_t(pfn, PFN_DEV), pgprot,
>>> -                   false);
>>> +                   mkwrite);
>>>    }
>>>    EXPORT_SYMBOL(vmf_insert_pfn_prot);
>>>
>>> @@ -2273,10 +2274,17 @@ EXPORT_SYMBOL(vmf_insert_pfn_prot);
>>>    vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma, unsigned long
>> addr,
>>>                      unsigned long pfn)
>>>    {
>>> -   return vmf_insert_pfn_prot(vma, addr, pfn, vma->vm_page_prot);
>>> +   return vmf_insert_pfn_prot(vma, addr, pfn, vma->vm_page_prot,
>>> +false);
>>>    }
>>>    EXPORT_SYMBOL(vmf_insert_pfn);
>>>
>>> +vm_fault_t vmf_insert_pfn_mkwrite(struct vm_area_struct *vma, unsigned
>> long addr,
>>> +                   unsigned long pfn)
>>> +{
>>> +   return vmf_insert_pfn_prot(vma, addr, pfn, vma->vm_page_prot,
>> true);
>>> +} EXPORT_SYMBOL(vmf_insert_pfn_mkwrite);
>>> +
>>>    static bool vm_mixed_ok(struct vm_area_struct *vma, pfn_t pfn)
>>>    {
>>>      /* these checks mirror the abort conditions in vm_normal_page */


  reply	other threads:[~2024-01-23 11:44 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20240122033210.713530-1-Xianrong.Zhou@amd.com>
2024-01-22  9:18 ` [PATCH] mm: Remove double faults once write a device pfn Christian König
2024-01-23  8:33   ` Zhou, Xianrong
2024-01-23 11:44     ` Christian König [this message]
2024-01-24  2:43       ` Zhou, Xianrong
2024-01-24  7:29         ` Christian König
2024-01-24  9:38           ` Zhou, Xianrong
2024-01-24 11:04             ` Alistair Popple
2024-01-25 14:26               ` Christian König
2024-01-26  5:10                 ` Zhou, Xianrong

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=76c3658d-2256-49c6-8e4c-49555c0a350a@amd.com \
    --to=christian.koenig@amd.com \
    --cc=Alexander.Deucher@amd.com \
    --cc=Colin.Xu@amd.com \
    --cc=Felix.Kuehling@amd.com \
    --cc=GuoQing.Zhang@amd.com \
    --cc=Huazeng.Li@amd.com \
    --cc=James.Zhu@amd.com \
    --cc=Monk.Liu@amd.com \
    --cc=Philip.Yang@amd.com \
    --cc=Ray.Huang@amd.com \
    --cc=SRINIVASAN.SHANMUGAM@amd.com \
    --cc=Xianrong.Zhou@amd.com \
    --cc=Xinhui.Pan@amd.com \
    --cc=airlied@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=bcm-kernel-feedback-list@broadcom.com \
    --cc=bp@alien8.de \
    --cc=dakr@redhat.com \
    --cc=daniel@ffwll.ch \
    --cc=dave.hansen@linux.intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hpa@zytor.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=kherbst@redhat.com \
    --cc=lee@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=luto@kernel.org \
    --cc=matthew.auld@intel.com \
    --cc=mingo@redhat.com \
    --cc=mripard@kernel.org \
    --cc=nirmoy.das@intel.com \
    --cc=nouveau@lists.freedesktop.org \
    --cc=rodrigo.vivi@intel.com \
    --cc=surenb@google.com \
    --cc=tglx@linutronix.de \
    --cc=tzimmermann@suse.de \
    --cc=x86@kernel.org \
    --cc=zack.rusin@broadcom.com \
    /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