Changes in kernel/generic/src/ddi/ddi.c [2fa10f6:953bc1ef] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ddi/ddi.c
r2fa10f6 r953bc1ef 46 46 #include <mm/frame.h> 47 47 #include <mm/as.h> 48 #include <synch/ mutex.h>48 #include <synch/spinlock.h> 49 49 #include <syscall/copy.h> 50 50 #include <adt/btree.h> … … 52 52 #include <align.h> 53 53 #include <errno.h> 54 #include <trace.h>55 54 56 55 /** This lock protects the parea_btree. */ 57 static mutex_t parea_lock;56 SPINLOCK_INITIALIZE(parea_lock); 58 57 59 58 /** B+tree with enabled physical memory areas. */ 60 59 static btree_t parea_btree; 61 60 62 /** Initialize DDI. 63 * 64 */ 61 /** Initialize DDI. */ 65 62 void ddi_init(void) 66 63 { 67 64 btree_create(&parea_btree); 68 mutex_initialize(&parea_lock, MUTEX_PASSIVE);69 65 } 70 66 … … 76 72 void ddi_parea_register(parea_t *parea) 77 73 { 78 mutex_lock(&parea_lock); 74 ipl_t ipl = interrupts_disable(); 75 spinlock_lock(&parea_lock); 79 76 80 77 /* … … 83 80 btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL); 84 81 85 mutex_unlock(&parea_lock); 82 spinlock_unlock(&parea_lock); 83 interrupts_restore(ipl); 86 84 } 87 85 … … 100 98 * 101 99 */ 102 NO_TRACE static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages, 103 unsigned int flags) 100 static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages, int flags) 104 101 { 105 102 ASSERT(TASK); … … 118 115 backend_data.frames = pages; 119 116 117 ipl_t ipl = interrupts_disable(); 118 120 119 /* Find the zone of the physical memory */ 121 irq_spinlock_lock(&zones.lock, true);120 spinlock_lock(&zones.lock); 122 121 size_t znum = find_zone(ADDR2PFN(pf), pages, 0); 123 122 … … 126 125 * -> assume it is hardware device and allow mapping 127 126 */ 128 irq_spinlock_unlock(&zones.lock, true);127 spinlock_unlock(&zones.lock); 129 128 goto map; 130 129 } … … 132 131 if (zones.info[znum].flags & ZONE_FIRMWARE) { 133 132 /* Frames are part of firmware */ 134 irq_spinlock_unlock(&zones.lock, true);133 spinlock_unlock(&zones.lock); 135 134 goto map; 136 135 } 137 136 138 137 if (zone_flags_available(zones.info[znum].flags)) { 139 /* 140 * Frames are part of physical memory, check if the memory 138 /* Frames are part of physical memory, check if the memory 141 139 * region is enabled for mapping. 142 140 */ 143 irq_spinlock_unlock(&zones.lock, true);141 spinlock_unlock(&zones.lock); 144 142 145 mutex_lock(&parea_lock);143 spinlock_lock(&parea_lock); 146 144 btree_node_t *nodep; 147 145 parea_t *parea = (parea_t *) btree_search(&parea_btree, 148 146 (btree_key_t) pf, &nodep); 149 147 150 if ((!parea) || (parea->frames < pages)) { 151 mutex_unlock(&parea_lock); 148 if ((!parea) || (parea->frames < pages)) 152 149 goto err; 153 }154 150 155 mutex_unlock(&parea_lock);151 spinlock_unlock(&parea_lock); 156 152 goto map; 157 153 } 158 154 159 irq_spinlock_unlock(&zones.lock, true);160 161 155 err: 156 spinlock_unlock(&zones.lock); 157 interrupts_restore(ipl); 162 158 return ENOENT; 163 159 164 160 map: 161 spinlock_lock(&TASK->lock); 162 165 163 if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, 166 164 AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) { … … 169 167 * We report it using ENOMEM. 170 168 */ 169 spinlock_unlock(&TASK->lock); 170 interrupts_restore(ipl); 171 171 return ENOMEM; 172 172 } … … 175 175 * Mapping is created on-demand during page fault. 176 176 */ 177 178 spinlock_unlock(&TASK->lock); 179 interrupts_restore(ipl); 177 180 return 0; 178 181 } … … 188 191 * 189 192 */ 190 NO_TRACE static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, 191 size_t size) 193 static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size) 192 194 { 193 195 /* … … 198 200 return EPERM; 199 201 200 irq_spinlock_lock(&tasks_lock, true); 202 ipl_t ipl = interrupts_disable(); 203 spinlock_lock(&tasks_lock); 201 204 202 205 task_t *task = task_find_by_id(id); … … 208 211 * context. 209 212 */ 210 irq_spinlock_unlock(&tasks_lock, true); 213 spinlock_unlock(&tasks_lock); 214 interrupts_restore(ipl); 211 215 return ENOENT; 212 216 } 213 217 214 218 /* Lock the task and release the lock protecting tasks_btree. */ 215 irq_spinlock_exchange(&tasks_lock, &task->lock); 219 spinlock_lock(&task->lock); 220 spinlock_unlock(&tasks_lock); 216 221 217 222 int rc = ddi_iospace_enable_arch(task, ioaddr, size); 218 223 219 irq_spinlock_unlock(&task->lock, true); 224 spinlock_unlock(&task->lock); 225 interrupts_restore(ipl); 220 226 221 227 return rc; … … 258 264 } 259 265 266 /** Disable or enable preemption. 267 * 268 * @param enable If non-zero, the preemption counter will be decremented, 269 * leading to potential enabling of preemption. Otherwise 270 * the preemption counter will be incremented, preventing 271 * preemption from occurring. 272 * 273 * @return Zero on success or EPERM if callers capabilities are not sufficient. 274 * 275 */ 276 unative_t sys_preempt_control(int enable) 277 { 278 if (!(cap_get(TASK) & CAP_PREEMPT_CONTROL)) 279 return EPERM; 280 281 if (enable) 282 preemption_enable(); 283 else 284 preemption_disable(); 285 286 return 0; 287 } 288 289 /** Disable or enable specified interrupts. 290 * 291 * @param irq the interrupt to be enabled/disabled. 292 * @param enable if true enable the interrupt, disable otherwise. 293 * 294 * @retutn Zero on success, error code otherwise. 295 */ 296 unative_t sys_interrupt_enable(int irq, int enable) 297 { 298 cap_t task_cap = cap_get(TASK); 299 if (!(task_cap & CAP_PREEMPT_CONTROL) || !(task_cap & CAP_IRQ_REG)) 300 return EPERM; 301 302 if (irq < 0 || irq > 16) { 303 return EINVAL; 304 } 305 306 uint16_t irq_mask = (uint16_t)(1 << irq); 307 if (enable) { 308 trap_virtual_enable_irqs(irq_mask); 309 } else { 310 trap_virtual_disable_irqs(irq_mask); 311 } 312 313 return 0; 314 } 315 260 316 /** @} 261 317 */
Note:
See TracChangeset
for help on using the changeset viewer.