1 /* 2 * SPU file system 3 * 4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 5 * 6 * Author: Arnd Bergmann <arndb@de.ibm.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2, or (at your option) 11 * any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 #ifndef SPUFS_H 23 #define SPUFS_H 24 25 #include <linux/kref.h> 26 #include <linux/mutex.h> 27 #include <linux/spinlock.h> 28 #include <linux/fs.h> 29 #include <linux/cpumask.h> 30 31 #include <asm/spu.h> 32 #include <asm/spu_csa.h> 33 #include <asm/spu_info.h> 34 35 /* The magic number for our file system */ 36 enum { 37 SPUFS_MAGIC = 0x23c9b64e, 38 }; 39 40 struct spu_context_ops; 41 struct spu_gang; 42 43 /* ctx->sched_flags */ 44 enum { 45 SPU_SCHED_NOTIFY_ACTIVE, 46 SPU_SCHED_WAS_ACTIVE, /* was active upon spu_acquire_saved() */ 47 }; 48 49 struct spu_context { 50 struct spu *spu; /* pointer to a physical SPU */ 51 struct spu_state csa; /* SPU context save area. */ 52 spinlock_t mmio_lock; /* protects mmio access */ 53 struct address_space *local_store; /* local store mapping. */ 54 struct address_space *mfc; /* 'mfc' area mappings. */ 55 struct address_space *cntl; /* 'control' area mappings. */ 56 struct address_space *signal1; /* 'signal1' area mappings. */ 57 struct address_space *signal2; /* 'signal2' area mappings. */ 58 struct address_space *mss; /* 'mss' area mappings. */ 59 struct address_space *psmap; /* 'psmap' area mappings. */ 60 struct mutex mapping_lock; 61 u64 object_id; /* user space pointer for oprofile */ 62 63 enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; 64 struct mutex state_mutex; 65 struct mutex run_mutex; 66 67 struct mm_struct *owner; 68 69 struct kref kref; 70 wait_queue_head_t ibox_wq; 71 wait_queue_head_t wbox_wq; 72 wait_queue_head_t stop_wq; 73 wait_queue_head_t mfc_wq; 74 struct fasync_struct *ibox_fasync; 75 struct fasync_struct *wbox_fasync; 76 struct fasync_struct *mfc_fasync; 77 u32 tagwait; 78 struct spu_context_ops *ops; 79 struct work_struct reap_work; 80 unsigned long flags; 81 unsigned long event_return; 82 83 struct list_head gang_list; 84 struct spu_gang *gang; 85 struct kref *prof_priv_kref; 86 void ( * prof_priv_release) (struct kref *kref); 87 88 /* owner thread */ 89 pid_t tid; 90 91 /* scheduler fields */ 92 struct list_head rq; 93 unsigned int time_slice; 94 unsigned long sched_flags; 95 cpumask_t cpus_allowed; 96 int policy; 97 int prio; 98 99 /* statistics */ 100 struct { 101 /* updates protected by ctx->state_mutex */ 102 enum spu_utilization_state util_state; 103 unsigned long long tstamp; /* time of last state switch */ 104 unsigned long long times[SPU_UTIL_MAX]; 105 unsigned long long vol_ctx_switch; 106 unsigned long long invol_ctx_switch; 107 unsigned long long min_flt; 108 unsigned long long maj_flt; 109 unsigned long long hash_flt; 110 unsigned long long slb_flt; 111 unsigned long long slb_flt_base; /* # at last ctx switch */ 112 unsigned long long class2_intr; 113 unsigned long long class2_intr_base; /* # at last ctx switch */ 114 unsigned long long libassist; 115 } stats; 116 117 struct list_head aff_list; 118 int aff_head; 119 int aff_offset; 120 }; 121 122 struct spu_gang { 123 struct list_head list; 124 struct mutex mutex; 125 struct kref kref; 126 int contexts; 127 128 struct spu_context *aff_ref_ctx; 129 struct list_head aff_list_head; 130 struct mutex aff_mutex; 131 int aff_flags; 132 struct spu *aff_ref_spu; 133 atomic_t aff_sched_count; 134 }; 135 136 /* Flag bits for spu_gang aff_flags */ 137 #define AFF_OFFSETS_SET 1 138 #define AFF_MERGED 2 139 140 struct mfc_dma_command { 141 int32_t pad; /* reserved */ 142 uint32_t lsa; /* local storage address */ 143 uint64_t ea; /* effective address */ 144 uint16_t size; /* transfer size */ 145 uint16_t tag; /* command tag */ 146 uint16_t class; /* class ID */ 147 uint16_t cmd; /* command opcode */ 148 }; 149 150 151 /* SPU context query/set operations. */ 152 struct spu_context_ops { 153 int (*mbox_read) (struct spu_context * ctx, u32 * data); 154 u32(*mbox_stat_read) (struct spu_context * ctx); 155 unsigned int (*mbox_stat_poll)(struct spu_context *ctx, 156 unsigned int events); 157 int (*ibox_read) (struct spu_context * ctx, u32 * data); 158 int (*wbox_write) (struct spu_context * ctx, u32 data); 159 u32(*signal1_read) (struct spu_context * ctx); 160 void (*signal1_write) (struct spu_context * ctx, u32 data); 161 u32(*signal2_read) (struct spu_context * ctx); 162 void (*signal2_write) (struct spu_context * ctx, u32 data); 163 void (*signal1_type_set) (struct spu_context * ctx, u64 val); 164 u64(*signal1_type_get) (struct spu_context * ctx); 165 void (*signal2_type_set) (struct spu_context * ctx, u64 val); 166 u64(*signal2_type_get) (struct spu_context * ctx); 167 u32(*npc_read) (struct spu_context * ctx); 168 void (*npc_write) (struct spu_context * ctx, u32 data); 169 u32(*status_read) (struct spu_context * ctx); 170 char*(*get_ls) (struct spu_context * ctx); 171 u32 (*runcntl_read) (struct spu_context * ctx); 172 void (*runcntl_write) (struct spu_context * ctx, u32 data); 173 void (*master_start) (struct spu_context * ctx); 174 void (*master_stop) (struct spu_context * ctx); 175 int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); 176 u32 (*read_mfc_tagstatus)(struct spu_context * ctx); 177 u32 (*get_mfc_free_elements)(struct spu_context *ctx); 178 int (*send_mfc_command)(struct spu_context * ctx, 179 struct mfc_dma_command * cmd); 180 void (*dma_info_read) (struct spu_context * ctx, 181 struct spu_dma_info * info); 182 void (*proxydma_info_read) (struct spu_context * ctx, 183 struct spu_proxydma_info * info); 184 void (*restart_dma)(struct spu_context *ctx); 185 }; 186 187 extern struct spu_context_ops spu_hw_ops; 188 extern struct spu_context_ops spu_backing_ops; 189 190 struct spufs_inode_info { 191 struct spu_context *i_ctx; 192 struct spu_gang *i_gang; 193 struct inode vfs_inode; 194 int i_openers; 195 }; 196 #define SPUFS_I(inode) \ 197 container_of(inode, struct spufs_inode_info, vfs_inode) 198 199 extern struct tree_descr spufs_dir_contents[]; 200 extern struct tree_descr spufs_dir_nosched_contents[]; 201 202 /* system call implementation */ 203 extern struct spufs_calls spufs_calls; 204 long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status); 205 long spufs_create(struct nameidata *nd, unsigned int flags, 206 mode_t mode, struct file *filp); 207 /* ELF coredump callbacks for writing SPU ELF notes */ 208 extern int spufs_coredump_extra_notes_size(void); 209 extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset); 210 211 extern const struct file_operations spufs_context_fops; 212 213 /* gang management */ 214 struct spu_gang *alloc_spu_gang(void); 215 struct spu_gang *get_spu_gang(struct spu_gang *gang); 216 int put_spu_gang(struct spu_gang *gang); 217 void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx); 218 void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx); 219 220 /* fault handling */ 221 int spufs_handle_class1(struct spu_context *ctx); 222 223 /* affinity */ 224 struct spu *affinity_check(struct spu_context *ctx); 225 226 /* context management */ 227 extern atomic_t nr_spu_contexts; 228 static inline void spu_acquire(struct spu_context *ctx) 229 { 230 mutex_lock(&ctx->state_mutex); 231 } 232 233 static inline void spu_release(struct spu_context *ctx) 234 { 235 mutex_unlock(&ctx->state_mutex); 236 } 237 238 struct spu_context * alloc_spu_context(struct spu_gang *gang); 239 void destroy_spu_context(struct kref *kref); 240 struct spu_context * get_spu_context(struct spu_context *ctx); 241 int put_spu_context(struct spu_context *ctx); 242 void spu_unmap_mappings(struct spu_context *ctx); 243 244 void spu_forget(struct spu_context *ctx); 245 int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags); 246 void spu_acquire_saved(struct spu_context *ctx); 247 void spu_release_saved(struct spu_context *ctx); 248 249 int spu_activate(struct spu_context *ctx, unsigned long flags); 250 void spu_deactivate(struct spu_context *ctx); 251 void spu_yield(struct spu_context *ctx); 252 void spu_switch_notify(struct spu *spu, struct spu_context *ctx); 253 void spu_set_timeslice(struct spu_context *ctx); 254 void spu_update_sched_info(struct spu_context *ctx); 255 void __spu_update_sched_info(struct spu_context *ctx); 256 int __init spu_sched_init(void); 257 void spu_sched_exit(void); 258 259 extern char *isolated_loader; 260 261 /* 262 * spufs_wait 263 * Same as wait_event_interruptible(), except that here 264 * we need to call spu_release(ctx) before sleeping, and 265 * then spu_acquire(ctx) when awoken. 266 */ 267 268 #define spufs_wait(wq, condition) \ 269 ({ \ 270 int __ret = 0; \ 271 DEFINE_WAIT(__wait); \ 272 for (;;) { \ 273 prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \ 274 if (condition) \ 275 break; \ 276 if (signal_pending(current)) { \ 277 __ret = -ERESTARTSYS; \ 278 break; \ 279 } \ 280 spu_release(ctx); \ 281 schedule(); \ 282 spu_acquire(ctx); \ 283 } \ 284 finish_wait(&(wq), &__wait); \ 285 __ret; \ 286 }) 287 288 size_t spu_wbox_write(struct spu_context *ctx, u32 data); 289 size_t spu_ibox_read(struct spu_context *ctx, u32 *data); 290 291 /* irq callback funcs. */ 292 void spufs_ibox_callback(struct spu *spu); 293 void spufs_wbox_callback(struct spu *spu); 294 void spufs_stop_callback(struct spu *spu); 295 void spufs_mfc_callback(struct spu *spu); 296 void spufs_dma_callback(struct spu *spu, int type); 297 298 extern struct spu_coredump_calls spufs_coredump_calls; 299 struct spufs_coredump_reader { 300 char *name; 301 ssize_t (*read)(struct spu_context *ctx, 302 char __user *buffer, size_t size, loff_t *pos); 303 u64 (*get)(struct spu_context *ctx); 304 size_t size; 305 }; 306 extern struct spufs_coredump_reader spufs_coredump_read[]; 307 extern int spufs_coredump_num_notes; 308 309 /* 310 * This function is a little bit too large for an inline, but 311 * as fault.c is built into the kernel we can't move it out of 312 * line. 313 */ 314 static inline void spuctx_switch_state(struct spu_context *ctx, 315 enum spu_utilization_state new_state) 316 { 317 unsigned long long curtime; 318 signed long long delta; 319 struct timespec ts; 320 struct spu *spu; 321 enum spu_utilization_state old_state; 322 323 ktime_get_ts(&ts); 324 curtime = timespec_to_ns(&ts); 325 delta = curtime - ctx->stats.tstamp; 326 327 WARN_ON(!mutex_is_locked(&ctx->state_mutex)); 328 WARN_ON(delta < 0); 329 330 spu = ctx->spu; 331 old_state = ctx->stats.util_state; 332 ctx->stats.util_state = new_state; 333 ctx->stats.tstamp = curtime; 334 335 /* 336 * Update the physical SPU utilization statistics. 337 */ 338 if (spu) { 339 ctx->stats.times[old_state] += delta; 340 spu->stats.times[old_state] += delta; 341 spu->stats.util_state = new_state; 342 spu->stats.tstamp = curtime; 343 } 344 } 345 346 #endif 347