105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter/* 205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * spu_save.c 305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * (C) Copyright IBM Corp. 2005 505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * SPU-side context save sequence outlined in 705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Synergistic Processor Element Book IV 805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Author: Mark Nutter <mnutter@us.ibm.com> 1005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 1105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * This program is free software; you can redistribute it and/or modify 1205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * it under the terms of the GNU General Public License as published by 1305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * the Free Software Foundation; either version 2, or (at your option) 1405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * any later version. 1505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 1605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * This program is distributed in the hope that it will be useful, 1705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * but WITHOUT ANY WARRANTY; without even the implied warranty of 1805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * GNU General Public License for more details. 2005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 2105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * You should have received a copy of the GNU General Public License 2205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * along with this program; if not, write to the Free Software 2305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 2505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 2605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 2705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 2805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#ifndef LS_SIZE 2905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#define LS_SIZE 0x40000 /* 256K (in bytes) */ 3005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#endif 3105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 3205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nuttertypedef unsigned int u32; 3305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nuttertypedef unsigned long long u64; 3405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 3505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#include <spu_intrinsics.h> 3605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#include <asm/spu_csa.h> 3705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#include "spu_utils.h" 3805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 3905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void save_event_mask(void) 4005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 4105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 4205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 4305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 2: 4405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Read the SPU_RdEventMsk channel and save to the LSCSA. 4505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 4605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(event_mask); 477a896dc5f4a369193256653535aa7e2b521c611dSebastian Siewior regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask); 4805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 4905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 5005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void save_tag_mask(void) 5105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 5205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 5305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 5405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 3: 5505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Read the SPU_RdTagMsk channel and save to the LSCSA. 5605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 5705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(tag_mask); 5805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter regs_spill[offset].slot[0] = spu_readch(MFC_RdTagMask); 5905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 6005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 6105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void save_upper_240kb(addr64 lscsa_ea) 6205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 6305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int ls = 16384; 6405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int list = (unsigned int)&dma_list[0]; 6505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int size = sizeof(dma_list); 6605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int tag_id = 0; 6705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int cmd = 0x24; /* PUTL */ 6805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 6905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 7: 7005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Enqueue the PUTL command (tag 0) to the MFC SPU command 7105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * queue to transfer the remaining 240 kb of LS to CSA. 7205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 7305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_LSA, ls); 7405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_EAH, lscsa_ea.ui[0]); 7505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_EAL, list); 7605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_Size, size); 7705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_TagID, tag_id); 7805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_Cmd, cmd); 7905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 8005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 8105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void save_fpcr(void) 8205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 8305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter // vector unsigned int fpcr; 8405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 8505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 8605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 9: 8705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Issue the floating-point status and control register 8805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * read instruction, and save to the LSCSA. 8905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 9005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(fpcr); 9105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter regs_spill[offset].v = spu_mffpscr(); 9205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 9305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 9405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void save_decr(void) 9505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 9605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 9705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 9805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 10: 9905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Read and save the SPU_RdDec channel data to 10005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * the LSCSA. 10105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 10205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(decr); 10305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter regs_spill[offset].slot[0] = spu_readch(SPU_RdDec); 10405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 10505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 10605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void save_srr0(void) 10705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 10805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 10905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 11005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 11: 11105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Read and save the SPU_WSRR0 channel data to 11205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * the LSCSA. 11305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 11405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(srr0); 11505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter regs_spill[offset].slot[0] = spu_readch(SPU_RdSRR0); 11605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 11705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 11805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void spill_regs_to_mem(addr64 lscsa_ea) 11905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 12005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int ls = (unsigned int)®s_spill[0]; 12105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int size = sizeof(regs_spill); 12205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int tag_id = 0; 12305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int cmd = 0x20; /* PUT */ 12405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 12505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 13: 12605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Enqueue a PUT command (tag 0) to send the LSCSA 12705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * to the CSA. 12805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 12905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_LSA, ls); 13005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_EAH, lscsa_ea.ui[0]); 13105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_EAL, lscsa_ea.ui[1]); 13205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_Size, size); 13305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_TagID, tag_id); 13405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_Cmd, cmd); 13505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 13605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 13705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void enqueue_sync(addr64 lscsa_ea) 13805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 13905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int tag_id = 0; 14005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int cmd = 0xCC; 14105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 14205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 14: 14305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Enqueue an MFC_SYNC command (tag 0). 14405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 14505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_TagID, tag_id); 14605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_Cmd, cmd); 14705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 14805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 14905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void save_complete(void) 15005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 15105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Save, Step 18: 15205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Issue a stop-and-signal instruction indicating 15305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * "save complete". Note: This function will not 15405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * return!! 15505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 15605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_stop(SPU_SAVE_COMPLETE); 15705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 15805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 15905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter/** 16005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * main - entry point for SPU-side context save. 16105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 16205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * This code deviates from the documented sequence as follows: 16305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 16405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 1. The EA for LSCSA is passed from PPE in the 16505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * signal notification channels. 16605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 2. All 128 registers are saved by crt0.o. 16705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 16805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterint main() 16905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 17005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter addr64 lscsa_ea; 17105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 17205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter lscsa_ea.ui[0] = spu_readch(SPU_RdSigNotify1); 17305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter lscsa_ea.ui[1] = spu_readch(SPU_RdSigNotify2); 17405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 17505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Step 1: done by exit(). */ 17605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter save_event_mask(); /* Step 2. */ 17705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter save_tag_mask(); /* Step 3. */ 17805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter set_event_mask(); /* Step 4. */ 17905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter set_tag_mask(); /* Step 5. */ 18005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter build_dma_list(lscsa_ea); /* Step 6. */ 18105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter save_upper_240kb(lscsa_ea); /* Step 7. */ 18205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Step 8: done by exit(). */ 18305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter save_fpcr(); /* Step 9. */ 18405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter save_decr(); /* Step 10. */ 18505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter save_srr0(); /* Step 11. */ 18605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter enqueue_putllc(lscsa_ea); /* Step 12. */ 18705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spill_regs_to_mem(lscsa_ea); /* Step 13. */ 18805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter enqueue_sync(lscsa_ea); /* Step 14. */ 18905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter set_tag_update(); /* Step 15. */ 19005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter read_tag_status(); /* Step 16. */ 19105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter read_llar_status(); /* Step 17. */ 19205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter save_complete(); /* Step 18. */ 19305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 19405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter return 0; 19505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 196