113d19498SJack Steiner /* 213d19498SJack Steiner * SN Platform GRU Driver 313d19498SJack Steiner * 413d19498SJack Steiner * GRU DRIVER TABLES, MACROS, externs, etc 513d19498SJack Steiner * 613d19498SJack Steiner * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. 713d19498SJack Steiner * 813d19498SJack Steiner * This program is free software; you can redistribute it and/or modify 913d19498SJack Steiner * it under the terms of the GNU General Public License as published by 1013d19498SJack Steiner * the Free Software Foundation; either version 2 of the License, or 1113d19498SJack Steiner * (at your option) any later version. 1213d19498SJack Steiner * 1313d19498SJack Steiner * This program is distributed in the hope that it will be useful, 1413d19498SJack Steiner * but WITHOUT ANY WARRANTY; without even the implied warranty of 1513d19498SJack Steiner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1613d19498SJack Steiner * GNU General Public License for more details. 1713d19498SJack Steiner * 1813d19498SJack Steiner * You should have received a copy of the GNU General Public License 1913d19498SJack Steiner * along with this program; if not, write to the Free Software 2013d19498SJack Steiner * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2113d19498SJack Steiner */ 2213d19498SJack Steiner 2313d19498SJack Steiner #ifndef __GRUTABLES_H__ 2413d19498SJack Steiner #define __GRUTABLES_H__ 2513d19498SJack Steiner 2613d19498SJack Steiner /* 279ca8e40cSJack Steiner * GRU Chiplet: 289ca8e40cSJack Steiner * The GRU is a user addressible memory accelerator. It provides 299ca8e40cSJack Steiner * several forms of load, store, memset, bcopy instructions. In addition, it 309ca8e40cSJack Steiner * contains special instructions for AMOs, sending messages to message 319ca8e40cSJack Steiner * queues, etc. 329ca8e40cSJack Steiner * 339ca8e40cSJack Steiner * The GRU is an integral part of the node controller. It connects 349ca8e40cSJack Steiner * directly to the cpu socket. In its current implementation, there are 2 359ca8e40cSJack Steiner * GRU chiplets in the node controller on each blade (~node). 369ca8e40cSJack Steiner * 379ca8e40cSJack Steiner * The entire GRU memory space is fully coherent and cacheable by the cpus. 389ca8e40cSJack Steiner * 399ca8e40cSJack Steiner * Each GRU chiplet has a physical memory map that looks like the following: 409ca8e40cSJack Steiner * 419ca8e40cSJack Steiner * +-----------------+ 429ca8e40cSJack Steiner * |/////////////////| 439ca8e40cSJack Steiner * |/////////////////| 449ca8e40cSJack Steiner * |/////////////////| 459ca8e40cSJack Steiner * |/////////////////| 469ca8e40cSJack Steiner * |/////////////////| 479ca8e40cSJack Steiner * |/////////////////| 489ca8e40cSJack Steiner * |/////////////////| 499ca8e40cSJack Steiner * |/////////////////| 509ca8e40cSJack Steiner * +-----------------+ 519ca8e40cSJack Steiner * | system control | 529ca8e40cSJack Steiner * +-----------------+ _______ +-------------+ 539ca8e40cSJack Steiner * |/////////////////| / | | 549ca8e40cSJack Steiner * |/////////////////| / | | 559ca8e40cSJack Steiner * |/////////////////| / | instructions| 569ca8e40cSJack Steiner * |/////////////////| / | | 579ca8e40cSJack Steiner * |/////////////////| / | | 589ca8e40cSJack Steiner * |/////////////////| / |-------------| 599ca8e40cSJack Steiner * |/////////////////| / | | 609ca8e40cSJack Steiner * +-----------------+ | | 619ca8e40cSJack Steiner * | context 15 | | data | 629ca8e40cSJack Steiner * +-----------------+ | | 639ca8e40cSJack Steiner * | ...... | \ | | 649ca8e40cSJack Steiner * +-----------------+ \____________ +-------------+ 659ca8e40cSJack Steiner * | context 1 | 669ca8e40cSJack Steiner * +-----------------+ 679ca8e40cSJack Steiner * | context 0 | 689ca8e40cSJack Steiner * +-----------------+ 699ca8e40cSJack Steiner * 709ca8e40cSJack Steiner * Each of the "contexts" is a chunk of memory that can be mmaped into user 719ca8e40cSJack Steiner * space. The context consists of 2 parts: 729ca8e40cSJack Steiner * 739ca8e40cSJack Steiner * - an instruction space that can be directly accessed by the user 749ca8e40cSJack Steiner * to issue GRU instructions and to check instruction status. 759ca8e40cSJack Steiner * 769ca8e40cSJack Steiner * - a data area that acts as normal RAM. 779ca8e40cSJack Steiner * 789ca8e40cSJack Steiner * User instructions contain virtual addresses of data to be accessed by the 799ca8e40cSJack Steiner * GRU. The GRU contains a TLB that is used to convert these user virtual 809ca8e40cSJack Steiner * addresses to physical addresses. 819ca8e40cSJack Steiner * 829ca8e40cSJack Steiner * The "system control" area of the GRU chiplet is used by the kernel driver 839ca8e40cSJack Steiner * to manage user contexts and to perform functions such as TLB dropin and 849ca8e40cSJack Steiner * purging. 859ca8e40cSJack Steiner * 869ca8e40cSJack Steiner * One context may be reserved for the kernel and used for cross-partition 879ca8e40cSJack Steiner * communication. The GRU will also be used to asynchronously zero out 889ca8e40cSJack Steiner * large blocks of memory (not currently implemented). 899ca8e40cSJack Steiner * 909ca8e40cSJack Steiner * 9113d19498SJack Steiner * Tables: 9213d19498SJack Steiner * 9313d19498SJack Steiner * VDATA-VMA Data - Holds a few parameters. Head of linked list of 9413d19498SJack Steiner * GTS tables for threads using the GSEG 9513d19498SJack Steiner * GTS - Gru Thread State - contains info for managing a GSEG context. A 9613d19498SJack Steiner * GTS is allocated for each thread accessing a 9713d19498SJack Steiner * GSEG. 9813d19498SJack Steiner * GTD - GRU Thread Data - contains shadow copy of GRU data when GSEG is 9913d19498SJack Steiner * not loaded into a GRU 10013d19498SJack Steiner * GMS - GRU Memory Struct - Used to manage TLB shootdowns. Tracks GRUs 10113d19498SJack Steiner * where a GSEG has been loaded. Similar to 10213d19498SJack Steiner * an mm_struct but for GRU. 10313d19498SJack Steiner * 10413d19498SJack Steiner * GS - GRU State - Used to manage the state of a GRU chiplet 10513d19498SJack Steiner * BS - Blade State - Used to manage state of all GRU chiplets 10613d19498SJack Steiner * on a blade 10713d19498SJack Steiner * 10813d19498SJack Steiner * 10913d19498SJack Steiner * Normal task tables for task using GRU. 11013d19498SJack Steiner * - 2 threads in process 11113d19498SJack Steiner * - 2 GSEGs open in process 11213d19498SJack Steiner * - GSEG1 is being used by both threads 11313d19498SJack Steiner * - GSEG2 is used only by thread 2 11413d19498SJack Steiner * 11513d19498SJack Steiner * task -->| 11613d19498SJack Steiner * task ---+---> mm ->------ (notifier) -------+-> gms 11713d19498SJack Steiner * | | 11813d19498SJack Steiner * |--> vma -> vdata ---> gts--->| GSEG1 (thread1) 11913d19498SJack Steiner * | | | 12013d19498SJack Steiner * | +-> gts--->| GSEG1 (thread2) 12113d19498SJack Steiner * | | 12213d19498SJack Steiner * |--> vma -> vdata ---> gts--->| GSEG2 (thread2) 12313d19498SJack Steiner * . 12413d19498SJack Steiner * . 12513d19498SJack Steiner * 12613d19498SJack Steiner * GSEGs are marked DONTCOPY on fork 12713d19498SJack Steiner * 12813d19498SJack Steiner * At open 12913d19498SJack Steiner * file.private_data -> NULL 13013d19498SJack Steiner * 13113d19498SJack Steiner * At mmap, 13213d19498SJack Steiner * vma -> vdata 13313d19498SJack Steiner * 13413d19498SJack Steiner * After gseg reference 13513d19498SJack Steiner * vma -> vdata ->gts 13613d19498SJack Steiner * 13713d19498SJack Steiner * After fork 13813d19498SJack Steiner * parent 13913d19498SJack Steiner * vma -> vdata -> gts 14013d19498SJack Steiner * child 14113d19498SJack Steiner * (vma is not copied) 14213d19498SJack Steiner * 14313d19498SJack Steiner */ 14413d19498SJack Steiner 14513d19498SJack Steiner #include <linux/rmap.h> 14613d19498SJack Steiner #include <linux/interrupt.h> 14713d19498SJack Steiner #include <linux/mutex.h> 14813d19498SJack Steiner #include <linux/wait.h> 14913d19498SJack Steiner #include <linux/mmu_notifier.h> 15013d19498SJack Steiner #include "gru.h" 15113d19498SJack Steiner #include "gruhandles.h" 15213d19498SJack Steiner 15313d19498SJack Steiner extern struct gru_stats_s gru_stats; 15413d19498SJack Steiner extern struct gru_blade_state *gru_base[]; 15513d19498SJack Steiner extern unsigned long gru_start_paddr, gru_end_paddr; 156e1c3219dSJack Steiner extern unsigned int gru_max_gids; 15713d19498SJack Steiner 15813d19498SJack Steiner #define GRU_MAX_BLADES MAX_NUMNODES 15913d19498SJack Steiner #define GRU_MAX_GRUS (GRU_MAX_BLADES * GRU_CHIPLETS_PER_BLADE) 16013d19498SJack Steiner 16113d19498SJack Steiner #define GRU_DRIVER_ID_STR "SGI GRU Device Driver" 16213d19498SJack Steiner #define GRU_DRIVER_VERSION_STR "0.80" 16313d19498SJack Steiner 16413d19498SJack Steiner /* 16513d19498SJack Steiner * GRU statistics. 16613d19498SJack Steiner */ 16713d19498SJack Steiner struct gru_stats_s { 16813d19498SJack Steiner atomic_long_t vdata_alloc; 16913d19498SJack Steiner atomic_long_t vdata_free; 17013d19498SJack Steiner atomic_long_t gts_alloc; 17113d19498SJack Steiner atomic_long_t gts_free; 17213d19498SJack Steiner atomic_long_t vdata_double_alloc; 17313d19498SJack Steiner atomic_long_t gts_double_allocate; 17413d19498SJack Steiner atomic_long_t assign_context; 17513d19498SJack Steiner atomic_long_t assign_context_failed; 17613d19498SJack Steiner atomic_long_t free_context; 17713d19498SJack Steiner atomic_long_t load_context; 17813d19498SJack Steiner atomic_long_t unload_context; 17913d19498SJack Steiner atomic_long_t steal_context; 18013d19498SJack Steiner atomic_long_t steal_context_failed; 18113d19498SJack Steiner atomic_long_t nopfn; 18213d19498SJack Steiner atomic_long_t break_cow; 18313d19498SJack Steiner atomic_long_t asid_new; 18413d19498SJack Steiner atomic_long_t asid_next; 18513d19498SJack Steiner atomic_long_t asid_wrap; 18613d19498SJack Steiner atomic_long_t asid_reuse; 18713d19498SJack Steiner atomic_long_t intr; 18843884604SJack Steiner atomic_long_t intr_mm_lock_failed; 18913d19498SJack Steiner atomic_long_t call_os; 19043884604SJack Steiner atomic_long_t call_os_offnode_reference; 19113d19498SJack Steiner atomic_long_t call_os_check_for_bug; 19213d19498SJack Steiner atomic_long_t call_os_wait_queue; 19313d19498SJack Steiner atomic_long_t user_flush_tlb; 19413d19498SJack Steiner atomic_long_t user_unload_context; 19513d19498SJack Steiner atomic_long_t user_exception; 19613d19498SJack Steiner atomic_long_t set_task_slice; 19713d19498SJack Steiner atomic_long_t migrate_check; 19813d19498SJack Steiner atomic_long_t migrated_retarget; 19913d19498SJack Steiner atomic_long_t migrated_unload; 20013d19498SJack Steiner atomic_long_t migrated_unload_delay; 20113d19498SJack Steiner atomic_long_t migrated_nopfn_retarget; 20213d19498SJack Steiner atomic_long_t migrated_nopfn_unload; 20313d19498SJack Steiner atomic_long_t tlb_dropin; 20413d19498SJack Steiner atomic_long_t tlb_dropin_fail_no_asid; 20513d19498SJack Steiner atomic_long_t tlb_dropin_fail_upm; 20613d19498SJack Steiner atomic_long_t tlb_dropin_fail_invalid; 20713d19498SJack Steiner atomic_long_t tlb_dropin_fail_range_active; 20813d19498SJack Steiner atomic_long_t tlb_dropin_fail_idle; 20913d19498SJack Steiner atomic_long_t tlb_dropin_fail_fmm; 210cd1334f0SJack Steiner atomic_long_t tlb_dropin_fail_no_exception; 211cd1334f0SJack Steiner atomic_long_t tlb_dropin_fail_no_exception_war; 21213d19498SJack Steiner atomic_long_t mmu_invalidate_range; 21313d19498SJack Steiner atomic_long_t mmu_invalidate_page; 21413d19498SJack Steiner atomic_long_t mmu_clear_flush_young; 21513d19498SJack Steiner atomic_long_t flush_tlb; 21613d19498SJack Steiner atomic_long_t flush_tlb_gru; 21713d19498SJack Steiner atomic_long_t flush_tlb_gru_tgh; 21813d19498SJack Steiner atomic_long_t flush_tlb_gru_zero_asid; 21913d19498SJack Steiner 22013d19498SJack Steiner atomic_long_t copy_gpa; 22113d19498SJack Steiner 22213d19498SJack Steiner atomic_long_t mesq_receive; 22313d19498SJack Steiner atomic_long_t mesq_receive_none; 22413d19498SJack Steiner atomic_long_t mesq_send; 22513d19498SJack Steiner atomic_long_t mesq_send_failed; 22613d19498SJack Steiner atomic_long_t mesq_noop; 22713d19498SJack Steiner atomic_long_t mesq_send_unexpected_error; 22813d19498SJack Steiner atomic_long_t mesq_send_lb_overflow; 22913d19498SJack Steiner atomic_long_t mesq_send_qlimit_reached; 23013d19498SJack Steiner atomic_long_t mesq_send_amo_nacked; 23113d19498SJack Steiner atomic_long_t mesq_send_put_nacked; 23213d19498SJack Steiner atomic_long_t mesq_qf_not_full; 23313d19498SJack Steiner atomic_long_t mesq_qf_locked; 23413d19498SJack Steiner atomic_long_t mesq_qf_noop_not_full; 23513d19498SJack Steiner atomic_long_t mesq_qf_switch_head_failed; 23613d19498SJack Steiner atomic_long_t mesq_qf_unexpected_error; 23713d19498SJack Steiner atomic_long_t mesq_noop_unexpected_error; 23813d19498SJack Steiner atomic_long_t mesq_noop_lb_overflow; 23913d19498SJack Steiner atomic_long_t mesq_noop_qlimit_reached; 24013d19498SJack Steiner atomic_long_t mesq_noop_amo_nacked; 24113d19498SJack Steiner atomic_long_t mesq_noop_put_nacked; 24213d19498SJack Steiner 24313d19498SJack Steiner }; 24413d19498SJack Steiner 245a24e5e1cSJack Steiner enum mcs_op {cchop_allocate, cchop_start, cchop_interrupt, cchop_interrupt_sync, 246a24e5e1cSJack Steiner cchop_deallocate, tghop_invalidate, mcsop_last}; 247a24e5e1cSJack Steiner 248e56484daSJack Steiner struct mcs_op_statistic { 249e56484daSJack Steiner atomic_long_t count; 250e56484daSJack Steiner atomic_long_t total; 251e56484daSJack Steiner unsigned long max; 252e56484daSJack Steiner }; 253e56484daSJack Steiner 254e56484daSJack Steiner extern struct mcs_op_statistic mcs_op_statistics[mcsop_last]; 255e56484daSJack Steiner 25613d19498SJack Steiner #define OPT_DPRINT 1 25713d19498SJack Steiner #define OPT_STATS 2 25813d19498SJack Steiner #define GRU_QUICKLOOK 4 25913d19498SJack Steiner 26013d19498SJack Steiner 26113d19498SJack Steiner #define IRQ_GRU 110 /* Starting IRQ number for interrupts */ 26213d19498SJack Steiner 26313d19498SJack Steiner /* Delay in jiffies between attempts to assign a GRU context */ 26413d19498SJack Steiner #define GRU_ASSIGN_DELAY ((HZ * 20) / 1000) 26513d19498SJack Steiner 26613d19498SJack Steiner /* 26713d19498SJack Steiner * If a process has it's context stolen, min delay in jiffies before trying to 26813d19498SJack Steiner * steal a context from another process. 26913d19498SJack Steiner */ 27013d19498SJack Steiner #define GRU_STEAL_DELAY ((HZ * 200) / 1000) 27113d19498SJack Steiner 27213d19498SJack Steiner #define STAT(id) do { \ 2739ca8e40cSJack Steiner if (gru_options & OPT_STATS) \ 27413d19498SJack Steiner atomic_long_inc(&gru_stats.id); \ 27513d19498SJack Steiner } while (0) 27613d19498SJack Steiner 27713d19498SJack Steiner #ifdef CONFIG_SGI_GRU_DEBUG 27813d19498SJack Steiner #define gru_dbg(dev, fmt, x...) \ 27913d19498SJack Steiner do { \ 2809ca8e40cSJack Steiner if (gru_options & OPT_DPRINT) \ 28113d19498SJack Steiner dev_dbg(dev, "%s: " fmt, __func__, x); \ 28213d19498SJack Steiner } while (0) 28313d19498SJack Steiner #else 28413d19498SJack Steiner #define gru_dbg(x...) 28513d19498SJack Steiner #endif 28613d19498SJack Steiner 28713d19498SJack Steiner /*----------------------------------------------------------------------------- 28813d19498SJack Steiner * ASID management 28913d19498SJack Steiner */ 29013d19498SJack Steiner #define MAX_ASID 0xfffff0 29113d19498SJack Steiner #define MIN_ASID 8 29213d19498SJack Steiner #define ASID_INC 8 /* number of regions */ 29313d19498SJack Steiner 29413d19498SJack Steiner /* Generate a GRU asid value from a GRU base asid & a virtual address. */ 29513d19498SJack Steiner #if defined CONFIG_IA64 29613d19498SJack Steiner #define VADDR_HI_BIT 64 2976a4ad39bSRandy Dunlap #elif defined CONFIG_X86_64 29813d19498SJack Steiner #define VADDR_HI_BIT 48 29913d19498SJack Steiner #else 30013d19498SJack Steiner #error "Unsupported architecture" 30113d19498SJack Steiner #endif 302fe5bb6b0SJack Steiner #define GRUREGION(addr) ((addr) >> (VADDR_HI_BIT - 3) & 3) 30313d19498SJack Steiner #define GRUASID(asid, addr) ((asid) + GRUREGION(addr)) 30413d19498SJack Steiner 30513d19498SJack Steiner /*------------------------------------------------------------------------------ 30613d19498SJack Steiner * File & VMS Tables 30713d19498SJack Steiner */ 30813d19498SJack Steiner 30913d19498SJack Steiner struct gru_state; 31013d19498SJack Steiner 31113d19498SJack Steiner /* 31213d19498SJack Steiner * This structure is pointed to from the mmstruct via the notifier pointer. 31313d19498SJack Steiner * There is one of these per address space. 31413d19498SJack Steiner */ 315fe5bb6b0SJack Steiner struct gru_mm_tracker { /* pack to reduce size */ 316fe5bb6b0SJack Steiner unsigned int mt_asid_gen:24; /* ASID wrap count */ 317fe5bb6b0SJack Steiner unsigned int mt_asid:24; /* current base ASID for gru */ 318fe5bb6b0SJack Steiner unsigned short mt_ctxbitmap:16;/* bitmap of contexts using 31913d19498SJack Steiner asid */ 320fe5bb6b0SJack Steiner } __attribute__ ((packed)); 32113d19498SJack Steiner 32213d19498SJack Steiner struct gru_mm_struct { 32313d19498SJack Steiner struct mmu_notifier ms_notifier; 32413d19498SJack Steiner atomic_t ms_refcnt; 32513d19498SJack Steiner spinlock_t ms_asid_lock; /* protects ASID assignment */ 32613d19498SJack Steiner atomic_t ms_range_active;/* num range_invals active */ 32713d19498SJack Steiner char ms_released; 32813d19498SJack Steiner wait_queue_head_t ms_wait_queue; 32913d19498SJack Steiner DECLARE_BITMAP(ms_asidmap, GRU_MAX_GRUS); 33013d19498SJack Steiner struct gru_mm_tracker ms_asids[GRU_MAX_GRUS]; 33113d19498SJack Steiner }; 33213d19498SJack Steiner 33313d19498SJack Steiner /* 33413d19498SJack Steiner * One of these structures is allocated when a GSEG is mmaped. The 33513d19498SJack Steiner * structure is pointed to by the vma->vm_private_data field in the vma struct. 33613d19498SJack Steiner */ 33713d19498SJack Steiner struct gru_vma_data { 33813d19498SJack Steiner spinlock_t vd_lock; /* Serialize access to vma */ 33913d19498SJack Steiner struct list_head vd_head; /* head of linked list of gts */ 34013d19498SJack Steiner long vd_user_options;/* misc user option flags */ 34113d19498SJack Steiner int vd_cbr_au_count; 34213d19498SJack Steiner int vd_dsr_au_count; 34313d19498SJack Steiner }; 34413d19498SJack Steiner 34513d19498SJack Steiner /* 34613d19498SJack Steiner * One of these is allocated for each thread accessing a mmaped GRU. A linked 34713d19498SJack Steiner * list of these structure is hung off the struct gru_vma_data in the mm_struct. 34813d19498SJack Steiner */ 34913d19498SJack Steiner struct gru_thread_state { 35013d19498SJack Steiner struct list_head ts_next; /* list - head at vma-private */ 35113d19498SJack Steiner struct mutex ts_ctxlock; /* load/unload CTX lock */ 35213d19498SJack Steiner struct mm_struct *ts_mm; /* mm currently mapped to 35313d19498SJack Steiner context */ 35413d19498SJack Steiner struct vm_area_struct *ts_vma; /* vma of GRU context */ 35513d19498SJack Steiner struct gru_state *ts_gru; /* GRU where the context is 35613d19498SJack Steiner loaded */ 35713d19498SJack Steiner struct gru_mm_struct *ts_gms; /* asid & ioproc struct */ 35813d19498SJack Steiner unsigned long ts_cbr_map; /* map of allocated CBRs */ 35913d19498SJack Steiner unsigned long ts_dsr_map; /* map of allocated DATA 36013d19498SJack Steiner resources */ 36113d19498SJack Steiner unsigned long ts_steal_jiffies;/* jiffies when context last 36213d19498SJack Steiner stolen */ 36313d19498SJack Steiner long ts_user_options;/* misc user option flags */ 36413d19498SJack Steiner pid_t ts_tgid_owner; /* task that is using the 36513d19498SJack Steiner context - for migration */ 3667b8274e9SJack Steiner unsigned short ts_sizeavail; /* Pagesizes in use */ 36713d19498SJack Steiner int ts_tsid; /* thread that owns the 36813d19498SJack Steiner structure */ 36913d19498SJack Steiner int ts_tlb_int_select;/* target cpu if interrupts 37013d19498SJack Steiner enabled */ 37113d19498SJack Steiner int ts_ctxnum; /* context number where the 37213d19498SJack Steiner context is loaded */ 37313d19498SJack Steiner atomic_t ts_refcnt; /* reference count GTS */ 37413d19498SJack Steiner unsigned char ts_dsr_au_count;/* Number of DSR resources 37513d19498SJack Steiner required for contest */ 37613d19498SJack Steiner unsigned char ts_cbr_au_count;/* Number of CBR resources 37713d19498SJack Steiner required for contest */ 378fe5bb6b0SJack Steiner char ts_blade; /* If >= 0, migrate context if 379fe5bb6b0SJack Steiner ref from diferent blade */ 3807b8274e9SJack Steiner char ts_force_cch_reload; 38113d19498SJack Steiner char ts_force_unload;/* force context to be unloaded 38213d19498SJack Steiner after migration */ 38313d19498SJack Steiner char ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each 38413d19498SJack Steiner allocated CB */ 38513d19498SJack Steiner unsigned long ts_gdata[0]; /* save area for GRU data (CB, 38613d19498SJack Steiner DS, CBE) */ 38713d19498SJack Steiner }; 38813d19498SJack Steiner 38913d19498SJack Steiner /* 39013d19498SJack Steiner * Threaded programs actually allocate an array of GSEGs when a context is 39113d19498SJack Steiner * created. Each thread uses a separate GSEG. TSID is the index into the GSEG 39213d19498SJack Steiner * array. 39313d19498SJack Steiner */ 39413d19498SJack Steiner #define TSID(a, v) (((a) - (v)->vm_start) / GRU_GSEG_PAGESIZE) 39513d19498SJack Steiner #define UGRUADDR(gts) ((gts)->ts_vma->vm_start + \ 39613d19498SJack Steiner (gts)->ts_tsid * GRU_GSEG_PAGESIZE) 39713d19498SJack Steiner 39813d19498SJack Steiner #define NULLCTX (-1) /* if context not loaded into GRU */ 39913d19498SJack Steiner 40013d19498SJack Steiner /*----------------------------------------------------------------------------- 40113d19498SJack Steiner * GRU State Tables 40213d19498SJack Steiner */ 40313d19498SJack Steiner 40413d19498SJack Steiner /* 40513d19498SJack Steiner * One of these exists for each GRU chiplet. 40613d19498SJack Steiner */ 40713d19498SJack Steiner struct gru_state { 40813d19498SJack Steiner struct gru_blade_state *gs_blade; /* GRU state for entire 40913d19498SJack Steiner blade */ 41013d19498SJack Steiner unsigned long gs_gru_base_paddr; /* Physical address of 41113d19498SJack Steiner gru segments (64) */ 41213d19498SJack Steiner void *gs_gru_base_vaddr; /* Virtual address of 41313d19498SJack Steiner gru segments (64) */ 414e1c3219dSJack Steiner unsigned short gs_gid; /* unique GRU number */ 415e1c3219dSJack Steiner unsigned short gs_blade_id; /* blade of GRU */ 41613d19498SJack Steiner unsigned char gs_tgh_local_shift; /* used to pick TGH for 41713d19498SJack Steiner local flush */ 41813d19498SJack Steiner unsigned char gs_tgh_first_remote; /* starting TGH# for 41913d19498SJack Steiner remote flush */ 42013d19498SJack Steiner spinlock_t gs_asid_lock; /* lock used for 42113d19498SJack Steiner assigning asids */ 42213d19498SJack Steiner spinlock_t gs_lock; /* lock used for 42313d19498SJack Steiner assigning contexts */ 42413d19498SJack Steiner 42513d19498SJack Steiner /* -- the following are protected by the gs_asid_lock spinlock ---- */ 42613d19498SJack Steiner unsigned int gs_asid; /* Next availe ASID */ 42713d19498SJack Steiner unsigned int gs_asid_limit; /* Limit of available 42813d19498SJack Steiner ASIDs */ 42913d19498SJack Steiner unsigned int gs_asid_gen; /* asid generation. 43013d19498SJack Steiner Inc on wrap */ 43113d19498SJack Steiner 43213d19498SJack Steiner /* --- the following fields are protected by the gs_lock spinlock --- */ 43313d19498SJack Steiner unsigned long gs_context_map; /* bitmap to manage 43413d19498SJack Steiner contexts in use */ 43513d19498SJack Steiner unsigned long gs_cbr_map; /* bitmap to manage CB 43613d19498SJack Steiner resources */ 43713d19498SJack Steiner unsigned long gs_dsr_map; /* bitmap used to manage 43813d19498SJack Steiner DATA resources */ 43913d19498SJack Steiner unsigned int gs_reserved_cbrs; /* Number of kernel- 44013d19498SJack Steiner reserved cbrs */ 44113d19498SJack Steiner unsigned int gs_reserved_dsr_bytes; /* Bytes of kernel- 44213d19498SJack Steiner reserved dsrs */ 44313d19498SJack Steiner unsigned short gs_active_contexts; /* number of contexts 44413d19498SJack Steiner in use */ 44513d19498SJack Steiner struct gru_thread_state *gs_gts[GRU_NUM_CCH]; /* GTS currently using 44613d19498SJack Steiner the context */ 44713d19498SJack Steiner }; 44813d19498SJack Steiner 44913d19498SJack Steiner /* 45013d19498SJack Steiner * This structure contains the GRU state for all the GRUs on a blade. 45113d19498SJack Steiner */ 45213d19498SJack Steiner struct gru_blade_state { 45313d19498SJack Steiner void *kernel_cb; /* First kernel 45413d19498SJack Steiner reserved cb */ 45513d19498SJack Steiner void *kernel_dsr; /* First kernel 45613d19498SJack Steiner reserved DSR */ 45713d19498SJack Steiner /* ---- the following are protected by the bs_lock spinlock ---- */ 45813d19498SJack Steiner spinlock_t bs_lock; /* lock used for 45913d19498SJack Steiner stealing contexts */ 46013d19498SJack Steiner int bs_lru_ctxnum; /* STEAL - last context 46113d19498SJack Steiner stolen */ 46213d19498SJack Steiner struct gru_state *bs_lru_gru; /* STEAL - last gru 46313d19498SJack Steiner stolen */ 46413d19498SJack Steiner 46513d19498SJack Steiner struct gru_state bs_grus[GRU_CHIPLETS_PER_BLADE]; 46613d19498SJack Steiner }; 46713d19498SJack Steiner 46813d19498SJack Steiner /*----------------------------------------------------------------------------- 46913d19498SJack Steiner * Address Primitives 47013d19498SJack Steiner */ 47113d19498SJack Steiner #define get_tfm_for_cpu(g, c) \ 47213d19498SJack Steiner ((struct gru_tlb_fault_map *)get_tfm((g)->gs_gru_base_vaddr, (c))) 47313d19498SJack Steiner #define get_tfh_by_index(g, i) \ 47413d19498SJack Steiner ((struct gru_tlb_fault_handle *)get_tfh((g)->gs_gru_base_vaddr, (i))) 47513d19498SJack Steiner #define get_tgh_by_index(g, i) \ 47613d19498SJack Steiner ((struct gru_tlb_global_handle *)get_tgh((g)->gs_gru_base_vaddr, (i))) 47713d19498SJack Steiner #define get_cbe_by_index(g, i) \ 47813d19498SJack Steiner ((struct gru_control_block_extended *)get_cbe((g)->gs_gru_base_vaddr,\ 47913d19498SJack Steiner (i))) 48013d19498SJack Steiner 48113d19498SJack Steiner /*----------------------------------------------------------------------------- 48213d19498SJack Steiner * Useful Macros 48313d19498SJack Steiner */ 48413d19498SJack Steiner 48513d19498SJack Steiner /* Given a blade# & chiplet#, get a pointer to the GRU */ 48613d19498SJack Steiner #define get_gru(b, c) (&gru_base[b]->bs_grus[c]) 48713d19498SJack Steiner 48813d19498SJack Steiner /* Number of bytes to save/restore when unloading/loading GRU contexts */ 48913d19498SJack Steiner #define DSR_BYTES(dsr) ((dsr) * GRU_DSR_AU_BYTES) 49013d19498SJack Steiner #define CBR_BYTES(cbr) ((cbr) * GRU_HANDLE_BYTES * GRU_CBR_AU_SIZE * 2) 49113d19498SJack Steiner 49213d19498SJack Steiner /* Convert a user CB number to the actual CBRNUM */ 49313d19498SJack Steiner #define thread_cbr_number(gts, n) ((gts)->ts_cbr_idx[(n) / GRU_CBR_AU_SIZE] \ 49413d19498SJack Steiner * GRU_CBR_AU_SIZE + (n) % GRU_CBR_AU_SIZE) 49513d19498SJack Steiner 49613d19498SJack Steiner /* Convert a gid to a pointer to the GRU */ 49713d19498SJack Steiner #define GID_TO_GRU(gid) \ 49813d19498SJack Steiner (gru_base[(gid) / GRU_CHIPLETS_PER_BLADE] ? \ 49913d19498SJack Steiner (&gru_base[(gid) / GRU_CHIPLETS_PER_BLADE]-> \ 50013d19498SJack Steiner bs_grus[(gid) % GRU_CHIPLETS_PER_BLADE]) : \ 50113d19498SJack Steiner NULL) 50213d19498SJack Steiner 50313d19498SJack Steiner /* Scan all active GRUs in a GRU bitmap */ 50413d19498SJack Steiner #define for_each_gru_in_bitmap(gid, map) \ 50513d19498SJack Steiner for ((gid) = find_first_bit((map), GRU_MAX_GRUS); (gid) < GRU_MAX_GRUS;\ 50613d19498SJack Steiner (gid)++, (gid) = find_next_bit((map), GRU_MAX_GRUS, (gid))) 50713d19498SJack Steiner 50813d19498SJack Steiner /* Scan all active GRUs on a specific blade */ 50913d19498SJack Steiner #define for_each_gru_on_blade(gru, nid, i) \ 51013d19498SJack Steiner for ((gru) = gru_base[nid]->bs_grus, (i) = 0; \ 51113d19498SJack Steiner (i) < GRU_CHIPLETS_PER_BLADE; \ 51213d19498SJack Steiner (i)++, (gru)++) 51313d19498SJack Steiner 514e1c3219dSJack Steiner /* Scan all GRUs */ 515e1c3219dSJack Steiner #define foreach_gid(gid) \ 516e1c3219dSJack Steiner for ((gid) = 0; (gid) < gru_max_gids; (gid)++) 517e1c3219dSJack Steiner 51813d19498SJack Steiner /* Scan all active GTSs on a gru. Note: must hold ss_lock to use this macro. */ 51913d19498SJack Steiner #define for_each_gts_on_gru(gts, gru, ctxnum) \ 52013d19498SJack Steiner for ((ctxnum) = 0; (ctxnum) < GRU_NUM_CCH; (ctxnum)++) \ 52113d19498SJack Steiner if (((gts) = (gru)->gs_gts[ctxnum])) 52213d19498SJack Steiner 52313d19498SJack Steiner /* Scan each CBR whose bit is set in a TFM (or copy of) */ 52413d19498SJack Steiner #define for_each_cbr_in_tfm(i, map) \ 52513d19498SJack Steiner for ((i) = find_first_bit(map, GRU_NUM_CBE); \ 52613d19498SJack Steiner (i) < GRU_NUM_CBE; \ 52713d19498SJack Steiner (i)++, (i) = find_next_bit(map, GRU_NUM_CBE, i)) 52813d19498SJack Steiner 52913d19498SJack Steiner /* Scan each CBR in a CBR bitmap. Note: multiple CBRs in an allocation unit */ 53013d19498SJack Steiner #define for_each_cbr_in_allocation_map(i, map, k) \ 53113d19498SJack Steiner for ((k) = find_first_bit(map, GRU_CBR_AU); (k) < GRU_CBR_AU; \ 53213d19498SJack Steiner (k) = find_next_bit(map, GRU_CBR_AU, (k) + 1)) \ 53313d19498SJack Steiner for ((i) = (k)*GRU_CBR_AU_SIZE; \ 53413d19498SJack Steiner (i) < ((k) + 1) * GRU_CBR_AU_SIZE; (i)++) 53513d19498SJack Steiner 53613d19498SJack Steiner /* Scan each DSR in a DSR bitmap. Note: multiple DSRs in an allocation unit */ 53713d19498SJack Steiner #define for_each_dsr_in_allocation_map(i, map, k) \ 53813d19498SJack Steiner for ((k) = find_first_bit((const unsigned long *)map, GRU_DSR_AU);\ 53913d19498SJack Steiner (k) < GRU_DSR_AU; \ 54013d19498SJack Steiner (k) = find_next_bit((const unsigned long *)map, \ 54113d19498SJack Steiner GRU_DSR_AU, (k) + 1)) \ 54213d19498SJack Steiner for ((i) = (k) * GRU_DSR_AU_CL; \ 54313d19498SJack Steiner (i) < ((k) + 1) * GRU_DSR_AU_CL; (i)++) 54413d19498SJack Steiner 54513d19498SJack Steiner #define gseg_physical_address(gru, ctxnum) \ 54613d19498SJack Steiner ((gru)->gs_gru_base_paddr + ctxnum * GRU_GSEG_STRIDE) 54713d19498SJack Steiner #define gseg_virtual_address(gru, ctxnum) \ 54813d19498SJack Steiner ((gru)->gs_gru_base_vaddr + ctxnum * GRU_GSEG_STRIDE) 54913d19498SJack Steiner 55013d19498SJack Steiner /*----------------------------------------------------------------------------- 55113d19498SJack Steiner * Lock / Unlock GRU handles 55213d19498SJack Steiner * Use the "delresp" bit in the handle as a "lock" bit. 55313d19498SJack Steiner */ 55413d19498SJack Steiner 55513d19498SJack Steiner /* Lock hierarchy checking enabled only in emulator */ 55613d19498SJack Steiner 5579cc9b056SJack Steiner /* 0 = lock failed, 1 = locked */ 5589cc9b056SJack Steiner static inline int __trylock_handle(void *h) 5599cc9b056SJack Steiner { 5609cc9b056SJack Steiner return !test_and_set_bit(1, h); 5619cc9b056SJack Steiner } 5629cc9b056SJack Steiner 56313d19498SJack Steiner static inline void __lock_handle(void *h) 56413d19498SJack Steiner { 56513d19498SJack Steiner while (test_and_set_bit(1, h)) 56613d19498SJack Steiner cpu_relax(); 56713d19498SJack Steiner } 56813d19498SJack Steiner 56913d19498SJack Steiner static inline void __unlock_handle(void *h) 57013d19498SJack Steiner { 57113d19498SJack Steiner clear_bit(1, h); 57213d19498SJack Steiner } 57313d19498SJack Steiner 5749cc9b056SJack Steiner static inline int trylock_cch_handle(struct gru_context_configuration_handle *cch) 5759cc9b056SJack Steiner { 5769cc9b056SJack Steiner return __trylock_handle(cch); 5779cc9b056SJack Steiner } 5789cc9b056SJack Steiner 57913d19498SJack Steiner static inline void lock_cch_handle(struct gru_context_configuration_handle *cch) 58013d19498SJack Steiner { 58113d19498SJack Steiner __lock_handle(cch); 58213d19498SJack Steiner } 58313d19498SJack Steiner 58413d19498SJack Steiner static inline void unlock_cch_handle(struct gru_context_configuration_handle 58513d19498SJack Steiner *cch) 58613d19498SJack Steiner { 58713d19498SJack Steiner __unlock_handle(cch); 58813d19498SJack Steiner } 58913d19498SJack Steiner 59013d19498SJack Steiner static inline void lock_tgh_handle(struct gru_tlb_global_handle *tgh) 59113d19498SJack Steiner { 59213d19498SJack Steiner __lock_handle(tgh); 59313d19498SJack Steiner } 59413d19498SJack Steiner 59513d19498SJack Steiner static inline void unlock_tgh_handle(struct gru_tlb_global_handle *tgh) 59613d19498SJack Steiner { 59713d19498SJack Steiner __unlock_handle(tgh); 59813d19498SJack Steiner } 59913d19498SJack Steiner 60013d19498SJack Steiner /*----------------------------------------------------------------------------- 60113d19498SJack Steiner * Function prototypes & externs 60213d19498SJack Steiner */ 60313d19498SJack Steiner struct gru_unload_context_req; 60413d19498SJack Steiner 60513d19498SJack Steiner extern struct vm_operations_struct gru_vm_ops; 60613d19498SJack Steiner extern struct device *grudev; 60713d19498SJack Steiner 60813d19498SJack Steiner extern struct gru_vma_data *gru_alloc_vma_data(struct vm_area_struct *vma, 60913d19498SJack Steiner int tsid); 61013d19498SJack Steiner extern struct gru_thread_state *gru_find_thread_state(struct vm_area_struct 61113d19498SJack Steiner *vma, int tsid); 61213d19498SJack Steiner extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct 61313d19498SJack Steiner *vma, int tsid); 614*d57c82b1SJack Steiner extern struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts, 615*d57c82b1SJack Steiner int blade); 616*d57c82b1SJack Steiner extern void gru_load_context(struct gru_thread_state *gts); 617*d57c82b1SJack Steiner extern void gru_steal_context(struct gru_thread_state *gts, int blade_id); 61813d19498SJack Steiner extern void gru_unload_context(struct gru_thread_state *gts, int savestate); 6197b8274e9SJack Steiner extern int gru_update_cch(struct gru_thread_state *gts, int force_unload); 62013d19498SJack Steiner extern void gts_drop(struct gru_thread_state *gts); 62113d19498SJack Steiner extern void gru_tgh_flush_init(struct gru_state *gru); 62213d19498SJack Steiner extern int gru_kservices_init(struct gru_state *gru); 62327ca8a7bSJack Steiner extern void gru_kservices_exit(struct gru_state *gru); 6249cc9b056SJack Steiner extern int gru_dump_chiplet_request(unsigned long arg); 62513d19498SJack Steiner extern irqreturn_t gru_intr(int irq, void *dev_id); 62613d19498SJack Steiner extern int gru_handle_user_call_os(unsigned long address); 62713d19498SJack Steiner extern int gru_user_flush_tlb(unsigned long arg); 62813d19498SJack Steiner extern int gru_user_unload_context(unsigned long arg); 62913d19498SJack Steiner extern int gru_get_exception_detail(unsigned long arg); 63013d19498SJack Steiner extern int gru_set_task_slice(long address); 63113d19498SJack Steiner extern int gru_cpu_fault_map_id(void); 63213d19498SJack Steiner extern struct vm_area_struct *gru_find_vma(unsigned long vaddr); 63313d19498SJack Steiner extern void gru_flush_all_tlb(struct gru_state *gru); 63413d19498SJack Steiner extern int gru_proc_init(void); 63513d19498SJack Steiner extern void gru_proc_exit(void); 63613d19498SJack Steiner 637364b76dfSJack Steiner extern struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma, 638364b76dfSJack Steiner int cbr_au_count, int dsr_au_count, int options, int tsid); 6399ca8e40cSJack Steiner extern unsigned long gru_reserve_cb_resources(struct gru_state *gru, 64013d19498SJack Steiner int cbr_au_count, char *cbmap); 6419ca8e40cSJack Steiner extern unsigned long gru_reserve_ds_resources(struct gru_state *gru, 64213d19498SJack Steiner int dsr_au_count, char *dsmap); 64313d19498SJack Steiner extern int gru_fault(struct vm_area_struct *, struct vm_fault *vmf); 64413d19498SJack Steiner extern struct gru_mm_struct *gru_register_mmu_notifier(void); 64513d19498SJack Steiner extern void gru_drop_mmu_notifier(struct gru_mm_struct *gms); 64613d19498SJack Steiner 64713d19498SJack Steiner extern void gru_flush_tlb_range(struct gru_mm_struct *gms, unsigned long start, 64813d19498SJack Steiner unsigned long len); 64913d19498SJack Steiner 6509ca8e40cSJack Steiner extern unsigned long gru_options; 65113d19498SJack Steiner 65213d19498SJack Steiner #endif /* __GRUTABLES_H__ */ 653