On Fri, Oct 26, 2018 at 09:47:51PM +0200, Mark Kettenis wrote:
> Diff below adds support to uvm to create wtite-combining mappings and
> uses this to implement support for the I915_MMAP_WC flag in
> inteldrm(4). With this diff I can re-enable support for the
> I915_PARAM_MMAP_VERSION.
>
> Please test.
Defining PMAP_WC like that in uvm headers will make
pgprot_writecombine() in dev/pci/drm/drm_linux.h take the wrong path
on archs without PMAP_WC.
static inline pgprot_t
pgprot_writecombine(pgprot_t prot)
{
#ifdef PMAP_WC
return prot | PMAP_WC;
#else
return prot | PMAP_NOCACHE;
#endif
}
Should it instead be #if defined(PMAP_WC) && PMAP_WC > 0
or just #if PMAP_WC > 0 here?
>
>
> Index: dev/pci/drm/i915/i915_dma.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_dma.c,v
> retrieving revision 1.27
> diff -u -p -r1.27 i915_dma.c
> --- dev/pci/drm/i915/i915_dma.c 25 Oct 2018 20:29:38 -0000 1.27
> +++ dev/pci/drm/i915/i915_dma.c 26 Oct 2018 19:22:17 -0000
> @@ -156,11 +156,9 @@ static int i915_getparam(struct drm_devi
> case I915_PARAM_HAS_COHERENT_PHYS_GTT:
> value = 1;
> break;
> -#ifdef notyet
> case I915_PARAM_MMAP_VERSION:
> value = 1;
> break;
> -#endif
> case I915_PARAM_SUBSLICE_TOTAL:
> value = INTEL_INFO(dev)->subslice_total;
> if (!value)
> Index: dev/pci/drm/i915/i915_gem.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_gem.c,v
> retrieving revision 1.113
> diff -u -p -r1.113 i915_gem.c
> --- dev/pci/drm/i915/i915_gem.c 13 Sep 2018 03:38:15 -0000 1.113
> +++ dev/pci/drm/i915/i915_gem.c 26 Oct 2018 19:22:17 -0000
> @@ -1987,7 +1987,8 @@ i915_gem_mmap_ioctl(struct drm_device *d
> addr = 0;
> ret = -uvm_map(&curproc->p_vmspace->vm_map, &addr, size,
> obj->uao, args->offset, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE,
> - PROT_READ | PROT_WRITE, MAP_INHERIT_SHARE, MADV_RANDOM, 0));
> + PROT_READ | PROT_WRITE, MAP_INHERIT_SHARE, MADV_RANDOM,
> + (args->flags & I915_MMAP_WC) ? UVM_FLAG_WC : 0));
> if (ret == 0)
> uao_reference(obj->uao);
> drm_gem_object_unreference_unlocked(obj);
> Index: uvm/uvm.h
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm.h,v
> retrieving revision 1.62
> diff -u -p -r1.62 uvm.h
> --- uvm/uvm.h 12 Apr 2018 17:13:44 -0000 1.62
> +++ uvm/uvm.h 26 Oct 2018 19:22:18 -0000
> @@ -82,14 +82,15 @@ struct uvm {
> * vm_map_entry etype bits:
> */
>
> -#define UVM_ET_OBJ 0x01 /* it is a uvm_object */
> -#define UVM_ET_SUBMAP 0x02 /* it is a vm_map submap */
> -#define UVM_ET_COPYONWRITE 0x04 /* copy_on_write */
> -#define UVM_ET_NEEDSCOPY 0x08 /* needs_copy */
> -#define UVM_ET_HOLE 0x10 /* no backend */
> -#define UVM_ET_NOFAULT 0x20 /* don't fault */
> -#define UVM_ET_STACK 0x40 /* this is a stack */
> -#define UVM_ET_FREEMAPPED 0x80 /* map entry is on free list (DEBUG) */
> +#define UVM_ET_OBJ 0x0001 /* it is a uvm_object */
> +#define UVM_ET_SUBMAP 0x0002 /* it is a vm_map submap */
> +#define UVM_ET_COPYONWRITE 0x0004 /* copy_on_write */
> +#define UVM_ET_NEEDSCOPY 0x0008 /* needs_copy */
> +#define UVM_ET_HOLE 0x0010 /* no backend */
> +#define UVM_ET_NOFAULT 0x0020 /* don't fault */
> +#define UVM_ET_STACK 0x0040 /* this is a stack */
> +#define UVM_ET_WC 0x0080 /* write combining */
> +#define UVM_ET_FREEMAPPED 0x8000 /* map entry is on free list (DEBUG) */
>
> #define UVM_ET_ISOBJ(E) (((E)->etype & UVM_ET_OBJ) != 0)
> #define UVM_ET_ISSUBMAP(E) (((E)->etype & UVM_ET_SUBMAP) != 0)
> @@ -98,6 +99,7 @@ struct uvm {
> #define UVM_ET_ISHOLE(E) (((E)->etype & UVM_ET_HOLE) != 0)
> #define UVM_ET_ISNOFAULT(E) (((E)->etype & UVM_ET_NOFAULT) != 0)
> #define UVM_ET_ISSTACK(E) (((E)->etype & UVM_ET_STACK) != 0)
> +#define UVM_ET_ISWC(E) (((E)->etype & UVM_ET_WC) != 0)
>
> #ifdef _KERNEL
>
> Index: uvm/uvm_extern.h
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_extern.h,v
> retrieving revision 1.143
> diff -u -p -r1.143 uvm_extern.h
> --- uvm/uvm_extern.h 12 Apr 2018 17:13:44 -0000 1.143
> +++ uvm/uvm_extern.h 26 Oct 2018 19:22:18 -0000
> @@ -112,6 +112,7 @@ typedef int vm_prot_t;
> #define UVM_FLAG_NOFAULT 0x0800000 /* don't fault */
> #define UVM_FLAG_UNMAP 0x1000000 /* unmap to make space */
> #define UVM_FLAG_STACK 0x2000000 /* page may contain a stack */
> +#define UVM_FLAG_WC 0x4000000 /* write combining */
>
> /* macros to extract info */
> #define UVM_PROTECTION(X) ((X) & PROT_MASK)
> Index: uvm/uvm_fault.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_fault.c,v
> retrieving revision 1.93
> diff -u -p -r1.93 uvm_fault.c
> --- uvm/uvm_fault.c 12 Apr 2018 17:13:44 -0000 1.93
> +++ uvm/uvm_fault.c 26 Oct 2018 19:22:18 -0000
> @@ -497,7 +497,7 @@ uvm_fault(vm_map_t orig_map, vaddr_t vad
> int npages, nback, nforw, centeridx, result, lcv, gotpages, ret;
> vaddr_t startva, currva;
> voff_t uoff;
> - paddr_t pa;
> + paddr_t pa, pa_flags;
> struct vm_amap *amap;
> struct uvm_object *uobj;
> struct vm_anon *anons_store[UVM_MAXRANGE], **anons, *anon, *oanon;
> @@ -545,6 +545,7 @@ ReFault:
> */
>
> enter_prot = ufi.entry->protection;
> + pa_flags = UVM_ET_ISWC(ufi.entry) ? PMAP_WC : 0;
> wired = VM_MAPENT_ISWIRED(ufi.entry) || (fault_type == VM_FAULT_WIRE);
> if (wired)
> access_type = enter_prot; /* full access for wired */
> @@ -688,7 +689,7 @@ ReFault:
> * that we enter these right now.
> */
> (void) pmap_enter(ufi.orig_map->pmap, currva,
> - VM_PAGE_TO_PHYS(anon->an_page),
> + VM_PAGE_TO_PHYS(anon->an_page) | pa_flags,
> (anon->an_ref > 1) ? (enter_prot & ~PROT_WRITE) :
> enter_prot,
> PMAP_CANFAIL |
> @@ -789,7 +790,7 @@ ReFault:
> * enter these right now.
> */
> (void) pmap_enter(ufi.orig_map->pmap, currva,
> - VM_PAGE_TO_PHYS(pages[lcv]),
> + VM_PAGE_TO_PHYS(pages[lcv]) | pa_flags,
> enter_prot & MASK(ufi.entry),
> PMAP_CANFAIL |
> (wired ? PMAP_WIRED : 0));
> @@ -935,9 +936,9 @@ ReFault:
> * suspect since some other thread could blast the page out from
> * under us between the unlock and the pmap_enter.
> */
> - if (pmap_enter(ufi.orig_map->pmap, ufi.orig_rvaddr, VM_PAGE_TO_PHYS(pg),
> - enter_prot, access_type | PMAP_CANFAIL | (wired ? PMAP_WIRED : 0))
> - != 0) {
> + if (pmap_enter(ufi.orig_map->pmap, ufi.orig_rvaddr,
> + VM_PAGE_TO_PHYS(pg) | pa_flags, enter_prot,
> + access_type | PMAP_CANFAIL | (wired ? PMAP_WIRED : 0)) != 0) {
> /*
> * No need to undo what we did; we can simply think of
> * this as the pmap throwing away the mapping information.
> @@ -1211,9 +1212,9 @@ Case2:
> * all resources are present. we can now map it in and free our
> * resources.
> */
> - if (pmap_enter(ufi.orig_map->pmap, ufi.orig_rvaddr, VM_PAGE_TO_PHYS(pg),
> - enter_prot, access_type | PMAP_CANFAIL | (wired ? PMAP_WIRED : 0))
> - != 0) {
> + if (pmap_enter(ufi.orig_map->pmap, ufi.orig_rvaddr,
> + VM_PAGE_TO_PHYS(pg) | pa_flags, enter_prot,
> + access_type | PMAP_CANFAIL | (wired ? PMAP_WIRED : 0)) != 0) {
> /*
> * No need to undo what we did; we can simply think of
> * this as the pmap throwing away the mapping information.
> Index: uvm/uvm_map.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_map.c,v
> retrieving revision 1.238
> diff -u -p -r1.238 uvm_map.c
> --- uvm/uvm_map.c 22 Jul 2018 14:33:44 -0000 1.238
> +++ uvm/uvm_map.c 26 Oct 2018 19:22:18 -0000
> @@ -1343,6 +1343,8 @@ uvm_map(struct vm_map *map, vaddr_t *add
> entry->etype |= UVM_ET_HOLE;
> if (flags & UVM_FLAG_NOFAULT)
> entry->etype |= UVM_ET_NOFAULT;
> + if (flags & UVM_FLAG_WC)
> + entry->etype |= UVM_ET_WC;
> if (flags & UVM_FLAG_COPYONW) {
> entry->etype |= UVM_ET_COPYONWRITE;
> if ((flags & UVM_FLAG_OVERLAY) == 0)
> Index: uvm/uvm_pmap.h
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_pmap.h,v
> retrieving revision 1.27
> diff -u -p -r1.27 uvm_pmap.h
> --- uvm/uvm_pmap.h 19 Oct 2016 08:28:19 -0000 1.27
> +++ uvm/uvm_pmap.h 26 Oct 2018 19:22:18 -0000
> @@ -97,6 +97,10 @@ typedef struct pmap_statistics *pmap_sta
> #define PMAP_MD2 0x00000100 /* Machine dependant */
> #define PMAP_MD3 0x00000200 /* Machine dependant */
>
> +#ifndef PMAP_WC
> +#define PMAP_WC 0
> +#endif
> +
> #ifndef PMAP_EXCLUDE_DECLS /* Used in Sparc port to virtualize pmap mod */
> #ifdef _KERNEL
> __BEGIN_DECLS
>