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
> 

Reply via email to