| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright 2016-17 IBM Corp. |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or |
|---|
| 5 | | - * modify it under the terms of the GNU General Public License |
|---|
| 6 | | - * as published by the Free Software Foundation; either version |
|---|
| 7 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 8 | 4 | */ |
|---|
| 9 | 5 | |
|---|
| 10 | 6 | #ifndef _VAS_H |
|---|
| .. | .. |
|---|
| 105 | 101 | /* |
|---|
| 106 | 102 | * Initial per-process credits. |
|---|
| 107 | 103 | * Max send window credits: 4K-1 (12-bits in VAS_TX_WCRED) |
|---|
| 108 | | - * Max receive window credits: 64K-1 (16 bits in VAS_LRX_WCRED) |
|---|
| 109 | 104 | * |
|---|
| 110 | 105 | * TODO: Needs tuning for per-process credits |
|---|
| 111 | 106 | */ |
|---|
| 112 | | -#define VAS_RX_WCREDS_MAX ((64 << 10) - 1) |
|---|
| 113 | 107 | #define VAS_TX_WCREDS_MAX ((4 << 10) - 1) |
|---|
| 114 | 108 | #define VAS_WCREDS_DEFAULT (1 << 10) |
|---|
| 115 | 109 | |
|---|
| .. | .. |
|---|
| 300 | 294 | }; |
|---|
| 301 | 295 | |
|---|
| 302 | 296 | /* |
|---|
| 297 | + * NX can generate an interrupt for multiple faults and expects kernel |
|---|
| 298 | + * to process all of them. So read all valid CRB entries until find the |
|---|
| 299 | + * invalid one. So use pswid which is pasted by NX and ccw[0] (reserved |
|---|
| 300 | + * bit in BE) to check valid CRB. CCW[0] will not be touched by user |
|---|
| 301 | + * space. Application gets CRB formt error if it updates this bit. |
|---|
| 302 | + * |
|---|
| 303 | + * Invalidate FIFO during allocation and process all entries from last |
|---|
| 304 | + * successful read until finds invalid pswid and ccw[0] values. |
|---|
| 305 | + * After reading each CRB entry from fault FIFO, the kernel invalidate |
|---|
| 306 | + * it by updating pswid with FIFO_INVALID_ENTRY and CCW[0] with |
|---|
| 307 | + * CCW0_INVALID. |
|---|
| 308 | + */ |
|---|
| 309 | +#define FIFO_INVALID_ENTRY 0xffffffff |
|---|
| 310 | +#define CCW0_INVALID 1 |
|---|
| 311 | + |
|---|
| 312 | +/* |
|---|
| 303 | 313 | * One per instance of VAS. Each instance will have a separate set of |
|---|
| 304 | 314 | * receive windows, one per coprocessor type. |
|---|
| 305 | 315 | * |
|---|
| .. | .. |
|---|
| 316 | 326 | u64 uwc_bar_start; |
|---|
| 317 | 327 | u64 paste_base_addr; |
|---|
| 318 | 328 | u64 paste_win_id_shift; |
|---|
| 329 | + |
|---|
| 330 | + u64 irq_port; |
|---|
| 331 | + int virq; |
|---|
| 332 | + int fault_crbs; |
|---|
| 333 | + int fault_fifo_size; |
|---|
| 334 | + int fifo_in_progress; /* To wake up thread or return IRQ_HANDLED */ |
|---|
| 335 | + spinlock_t fault_lock; /* Protects fifo_in_progress update */ |
|---|
| 336 | + void *fault_fifo; |
|---|
| 337 | + struct vas_window *fault_win; /* Fault window */ |
|---|
| 319 | 338 | |
|---|
| 320 | 339 | struct mutex mutex; |
|---|
| 321 | 340 | struct vas_window *rxwin[VAS_COP_TYPE_MAX]; |
|---|
| .. | .. |
|---|
| 337 | 356 | bool user_win; /* True if user space window */ |
|---|
| 338 | 357 | void *hvwc_map; /* HV window context */ |
|---|
| 339 | 358 | void *uwc_map; /* OS/User window context */ |
|---|
| 340 | | - pid_t pid; /* Linux process id of owner */ |
|---|
| 359 | + struct pid *pid; /* Linux process id of owner */ |
|---|
| 360 | + struct pid *tgid; /* Thread group ID of owner */ |
|---|
| 361 | + struct mm_struct *mm; /* Linux process mm_struct */ |
|---|
| 341 | 362 | int wcreds_max; /* Window credits */ |
|---|
| 342 | 363 | |
|---|
| 343 | 364 | char *dbgname; |
|---|
| .. | .. |
|---|
| 362 | 383 | * is a container for the register fields in the window context. |
|---|
| 363 | 384 | */ |
|---|
| 364 | 385 | struct vas_winctx { |
|---|
| 365 | | - void *rx_fifo; |
|---|
| 386 | + u64 rx_fifo; |
|---|
| 366 | 387 | int rx_fifo_size; |
|---|
| 367 | 388 | int wcreds_max; |
|---|
| 368 | 389 | int rsvd_txbuf_count; |
|---|
| .. | .. |
|---|
| 410 | 431 | extern void vas_instance_init_dbgdir(struct vas_instance *vinst); |
|---|
| 411 | 432 | extern void vas_window_init_dbgdir(struct vas_window *win); |
|---|
| 412 | 433 | extern void vas_window_free_dbgdir(struct vas_window *win); |
|---|
| 434 | +extern int vas_setup_fault_window(struct vas_instance *vinst); |
|---|
| 435 | +extern irqreturn_t vas_fault_thread_fn(int irq, void *data); |
|---|
| 436 | +extern irqreturn_t vas_fault_handler(int irq, void *dev_id); |
|---|
| 437 | +extern void vas_return_credit(struct vas_window *window, bool tx); |
|---|
| 438 | +extern struct vas_window *vas_pswid_to_window(struct vas_instance *vinst, |
|---|
| 439 | + uint32_t pswid); |
|---|
| 440 | +extern void vas_win_paste_addr(struct vas_window *window, u64 *addr, |
|---|
| 441 | + int *len); |
|---|
| 442 | + |
|---|
| 443 | +static inline int vas_window_pid(struct vas_window *window) |
|---|
| 444 | +{ |
|---|
| 445 | + return pid_vnr(window->pid); |
|---|
| 446 | +} |
|---|
| 413 | 447 | |
|---|
| 414 | 448 | static inline void vas_log_write(struct vas_window *win, char *name, |
|---|
| 415 | 449 | void *regptr, u64 val) |
|---|
| .. | .. |
|---|
| 460 | 494 | */ |
|---|
| 461 | 495 | static inline u32 encode_pswid(int vasid, int winid) |
|---|
| 462 | 496 | { |
|---|
| 463 | | - u32 pswid = 0; |
|---|
| 464 | | - |
|---|
| 465 | | - pswid |= vasid << (31 - 7); |
|---|
| 466 | | - pswid |= winid; |
|---|
| 467 | | - |
|---|
| 468 | | - return pswid; |
|---|
| 497 | + return ((u32)winid | (vasid << (31 - 7))); |
|---|
| 469 | 498 | } |
|---|
| 470 | 499 | |
|---|
| 471 | 500 | static inline void decode_pswid(u32 pswid, int *vasid, int *winid) |
|---|