root/drivers/gpu/drm/amd/display/modules/vmid/vmid.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. add_ptb_to_table
  2. clear_entry_from_vmid_table
  3. evict_vmids
  4. get_existing_vmid_for_ptb
  5. get_next_available_vmid
  6. mod_vmid_get_for_ptb
  7. mod_vmid_reset
  8. mod_vmid_create
  9. mod_vmid_destroy

   1 /*
   2  * Copyright 2019 Advanced Micro Devices, Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  * Authors: AMD
  23  *
  24  */
  25 
  26 #include "mod_vmid.h"
  27 
  28 struct core_vmid {
  29         struct mod_vmid public;
  30         struct dc *dc;
  31 
  32         unsigned int num_vmid;
  33         unsigned int num_vmids_available;
  34         uint64_t ptb_assigned_to_vmid[MAX_VMID];
  35         struct dc_virtual_addr_space_config base_config;
  36 };
  37 
  38 #define MOD_VMID_TO_CORE(mod_vmid)\
  39                 container_of(mod_vmid, struct core_vmid, public)
  40 
  41 static void add_ptb_to_table(struct core_vmid *core_vmid, unsigned int vmid, uint64_t ptb)
  42 {
  43         core_vmid->ptb_assigned_to_vmid[vmid] = ptb;
  44         core_vmid->num_vmids_available--;
  45 }
  46 
  47 static void clear_entry_from_vmid_table(struct core_vmid *core_vmid, unsigned int vmid)
  48 {
  49         core_vmid->ptb_assigned_to_vmid[vmid] = 0;
  50         core_vmid->num_vmids_available++;
  51 }
  52 
  53 static void evict_vmids(struct core_vmid *core_vmid)
  54 {
  55         int i;
  56         uint16_t ord = dc_get_vmid_use_vector(core_vmid->dc);
  57 
  58         // At this point any positions with value 0 are unused vmids, evict them
  59         for (i = 1; i < core_vmid->num_vmid; i++) {
  60                 if (ord & (1u << i))
  61                         clear_entry_from_vmid_table(core_vmid, i);
  62         }
  63 }
  64 
  65 // Return value of -1 indicates vmid table unitialized or ptb dne in the table
  66 static int get_existing_vmid_for_ptb(struct core_vmid *core_vmid, uint64_t ptb)
  67 {
  68         int i;
  69 
  70         for (i = 0; i < core_vmid->num_vmid; i++) {
  71                 if (core_vmid->ptb_assigned_to_vmid[i] == ptb)
  72                         return i;
  73         }
  74 
  75         return -1;
  76 }
  77 
  78 // Expected to be called only when there's an available vmid
  79 static int get_next_available_vmid(struct core_vmid *core_vmid)
  80 {
  81         int i;
  82 
  83         for (i = 1; i < core_vmid->num_vmid; i++) {
  84                 if (core_vmid->ptb_assigned_to_vmid[i] == 0)
  85                         return i;
  86         }
  87 
  88         return -1;
  89 }
  90 
  91 uint8_t mod_vmid_get_for_ptb(struct mod_vmid *mod_vmid, uint64_t ptb)
  92 {
  93         struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid);
  94         unsigned int vmid = 0;
  95 
  96         // Physical address gets vmid 0
  97         if (ptb == 0)
  98                 return 0;
  99 
 100         vmid = get_existing_vmid_for_ptb(core_vmid, ptb);
 101 
 102         if (vmid == -1) {
 103                 struct dc_virtual_addr_space_config va_config = core_vmid->base_config;
 104 
 105                 va_config.page_table_base_addr = ptb;
 106 
 107                 if (core_vmid->num_vmids_available == 0)
 108                         evict_vmids(core_vmid);
 109 
 110                 vmid = get_next_available_vmid(core_vmid);
 111                 add_ptb_to_table(core_vmid, vmid, ptb);
 112 
 113                 dc_setup_vm_context(core_vmid->dc, &va_config, vmid);
 114         }
 115 
 116         return vmid;
 117 }
 118 
 119 void mod_vmid_reset(struct mod_vmid *mod_vmid)
 120 {
 121         struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid);
 122 
 123         core_vmid->num_vmids_available = core_vmid->num_vmid - 1;
 124         memset(core_vmid->ptb_assigned_to_vmid, 0, sizeof(core_vmid->ptb_assigned_to_vmid[0]) * MAX_VMID);
 125 }
 126 
 127 struct mod_vmid *mod_vmid_create(
 128                 struct dc *dc,
 129                 unsigned int num_vmid,
 130                 struct dc_virtual_addr_space_config *va_config)
 131 {
 132         struct core_vmid *core_vmid;
 133 
 134         if (num_vmid <= 1)
 135                 goto fail_no_vm_ctx;
 136 
 137         if (dc == NULL)
 138                 goto fail_dc_null;
 139 
 140         core_vmid = kzalloc(sizeof(struct core_vmid), GFP_KERNEL);
 141 
 142         if (core_vmid == NULL)
 143                 goto fail_alloc_context;
 144 
 145         core_vmid->dc = dc;
 146         core_vmid->num_vmid = num_vmid;
 147         core_vmid->num_vmids_available = num_vmid - 1;
 148         core_vmid->base_config = *va_config;
 149 
 150         memset(core_vmid->ptb_assigned_to_vmid, 0, sizeof(core_vmid->ptb_assigned_to_vmid[0]) * MAX_VMID);
 151 
 152         return &core_vmid->public;
 153 
 154 fail_no_vm_ctx:
 155 fail_alloc_context:
 156 fail_dc_null:
 157         return NULL;
 158 }
 159 
 160 void mod_vmid_destroy(struct mod_vmid *mod_vmid)
 161 {
 162         if (mod_vmid != NULL) {
 163                 struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid);
 164 
 165                 kfree(core_vmid);
 166         }
 167 }

/* [<][>][^][v][top][bottom][index][help] */