105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter/* 205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * spu_restore.c 305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * (C) Copyright IBM Corp. 2005 505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * SPU-side context restore 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 Nutter#define BR_INSTR 0x327fff80 /* br -4 */ 4005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#define NOP_INSTR 0x40200000 /* nop */ 4105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#define HEQ_INSTR 0x7b000000 /* heq $0, $0 */ 4205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#define STOP_INSTR 0x00000000 /* stop 0x0 */ 4305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#define ILLEGAL_INSTR 0x00800000 /* illegal instr */ 4405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter#define RESTORE_COMPLETE 0x00003ffc /* stop 0x3ffc */ 4505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 4605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void fetch_regs_from_mem(addr64 lscsa_ea) 4705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 4805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int ls = (unsigned int)®s_spill[0]; 4905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int size = sizeof(regs_spill); 5005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int tag_id = 0; 5105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int cmd = 0x40; /* GET */ 5205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 5305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_LSA, ls); 5405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_EAH, lscsa_ea.ui[0]); 5505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_EAL, lscsa_ea.ui[1]); 5605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_Size, size); 5705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_TagID, tag_id); 5805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_Cmd, cmd); 5905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 6005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 6105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void restore_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 = 0x44; /* GETL */ 6805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 6905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Restore, Step 4: 7005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Enqueue the GETL command (tag 0) to the MFC SPU command 7105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * queue to transfer the upper 240 kb of LS from 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 restore_decr(void) 8205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 8305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 8405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int decr_running; 8505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int decr; 8605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 87ca53da3abb1d49748931ff2acb66d5a6eeeba2a1Masato Noguchi /* Restore, Step 6(moved): 8805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * If the LSCSA "decrementer running" flag is set 8905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * then write the SPU_WrDec channel with the 9005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * decrementer value from LSCSA. 9105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 9205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(decr_status); 931cfc0f86eb0348dd04ace8c2171642ebe9cd87bbMasato Noguchi decr_running = regs_spill[offset].slot[0] & SPU_DECR_STATUS_RUNNING; 9405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter if (decr_running) { 9505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(decr); 9605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter decr = regs_spill[offset].slot[0]; 9705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(SPU_WrDec, decr); 9805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter } 9905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 10005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 10105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void write_ppu_mb(void) 10205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 10305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 10405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int data; 10505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 10605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Restore, Step 11: 10705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Write the MFC_WrOut_MB channel with the PPU_MB 10805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * data from LSCSA. 10905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 11005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(ppu_mb); 11105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter data = regs_spill[offset].slot[0]; 11205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(SPU_WrOutMbox, data); 11305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 11405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 11505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void write_ppuint_mb(void) 11605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 11705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 11805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int data; 11905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 12005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Restore, Step 12: 12105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Write the MFC_WrInt_MB channel with the PPUINT_MB 12205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * data from LSCSA. 12305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 12405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(ppuint_mb); 12505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter data = regs_spill[offset].slot[0]; 12605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(SPU_WrOutIntrMbox, data); 12705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 12805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 12905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void restore_fpcr(void) 13005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 13105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 13205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter vector unsigned int fpcr; 13305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 13405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Restore, Step 13: 13505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Restore the floating-point status and control 13605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * register from the LSCSA. 13705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 13805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(fpcr); 13905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter fpcr = regs_spill[offset].v; 14005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_mtfpscr(fpcr); 14105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 14205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 14305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void restore_srr0(void) 14405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 14505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 14605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int srr0; 14705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 14805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Restore, Step 14: 14905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Restore the SPU SRR0 data from the LSCSA. 15005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 15105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(srr0); 15205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter srr0 = regs_spill[offset].slot[0]; 15305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(SPU_WrSRR0, srr0); 15405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 15505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 15605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void restore_event_mask(void) 15705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 15805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 15905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int event_mask; 16005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 16105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Restore, Step 15: 16205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Restore the SPU_RdEventMsk data from the LSCSA. 16305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 16405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(event_mask); 16505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter event_mask = regs_spill[offset].slot[0]; 16605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(SPU_WrEventMask, event_mask); 16705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 16805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 16905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void restore_tag_mask(void) 17005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 17105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 17205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int tag_mask; 17305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 17405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Restore, Step 16: 17505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Restore the SPU_RdTagMsk data from the LSCSA. 17605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 17705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(tag_mask); 17805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter tag_mask = regs_spill[offset].slot[0]; 17905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_writech(MFC_WrTagMask, tag_mask); 18005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 18105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 18205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterstatic inline void restore_complete(void) 18305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 18405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter extern void exit_fini(void); 18505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int *exit_instrs = (unsigned int *)exit_fini; 18605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int offset; 18705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int stopped_status; 18805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter unsigned int stopped_code; 18905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 19005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Restore, Step 18: 19105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Issue a stop-and-signal instruction with 19205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * "good context restore" signal value. 19305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 19405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Restore, Step 19: 19505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * There may be additional instructions placed 19605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * here by the PPE Sequence for SPU Context 19705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * Restore in order to restore the correct 19805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * "stopped state". 19905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 20005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * This step is handled here by analyzing the 20105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * LSCSA.stopped_status and then modifying the 20205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * exit() function to behave appropriately. 20305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 20405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 20505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter offset = LSCSA_QW_OFFSET(stopped_status); 20605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter stopped_status = regs_spill[offset].slot[0]; 20705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter stopped_code = regs_spill[offset].slot[1]; 20805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 20905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter switch (stopped_status) { 21005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_P_I: 21105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[P,I]=1. Add illegal instruction 21205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * followed by stop-and-signal instruction after 21305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * end of restore code. 21405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 21505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 21605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = ILLEGAL_INSTR; 21705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[2] = STOP_INSTR | stopped_code; 21805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 21905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_P_H: 22005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[P,H]=1. Add 'heq $0, $0' followed 22105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * by stop-and-signal instruction after end of 22205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * restore code. 22305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 22405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 22505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = HEQ_INSTR; 22605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[2] = STOP_INSTR | stopped_code; 22705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 22805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_S_P: 22905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[S,P]=1. Add nop instruction 23005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * followed by 'br -4' after end of restore 23105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * code. 23205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 23305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 23405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = STOP_INSTR | stopped_code; 23505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[2] = NOP_INSTR; 23605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[3] = BR_INSTR; 23705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 23805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_S_I: 23905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[S,I]=1. Add illegal instruction 24005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * followed by 'br -4' after end of restore code. 24105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 24205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 24305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = ILLEGAL_INSTR; 24405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[2] = NOP_INSTR; 24505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[3] = BR_INSTR; 24605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 24705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_I: 24805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[I]=1. Add illegal instruction followed 24905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * by infinite loop after end of restore sequence. 25005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 25105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 25205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = ILLEGAL_INSTR; 25305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[2] = NOP_INSTR; 25405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[3] = BR_INSTR; 25505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 25605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_S: 25705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[S]=1. Add two 'nop' instructions. */ 25805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 25905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = NOP_INSTR; 26005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[2] = NOP_INSTR; 26105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[3] = BR_INSTR; 26205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 26305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_H: 26405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[H]=1. Add 'heq $0, $0' instruction 26505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * after end of restore code. 26605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 26705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 26805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = HEQ_INSTR; 26905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[2] = NOP_INSTR; 27005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[3] = BR_INSTR; 27105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 27205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_P: 27305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[P]=1. Add stop-and-signal instruction 27405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * after end of restore code. 27505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 27605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 27705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = STOP_INSTR | stopped_code; 27805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 27905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter case SPU_STOPPED_STATUS_R: 28005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* SPU_Status[I,S,H,P,R]=0. Add infinite loop. */ 28105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[0] = RESTORE_COMPLETE; 28205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[1] = NOP_INSTR; 28305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[2] = NOP_INSTR; 28405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter exit_instrs[3] = BR_INSTR; 28505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 28605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter default: 28725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* SPU_Status[R]=1. No additional instructions. */ 28805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter break; 28905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter } 29005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter spu_sync(); 29105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 29205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 29305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter/** 29405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * main - entry point for SPU-side context restore. 29505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 29605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * This code deviates from the documented sequence in the 29705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * following aspects: 29805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 2997022543ee404880aab5c641e4983e237815edc35Jeremy Kerr * 1. The EA for LSCSA is passed from PPE in the 30005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * signal notification channels. 30105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 2. The register spill area is pulled by SPU 30205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * into LS, rather than pushed by PPE. 30305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 3. All 128 registers are restored by exit(). 30405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * 4. The exit() function is modified at run 30505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * time in order to properly restore the 30605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter * SPU_Status register. 30705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter */ 30805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutterint main() 30905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter{ 31005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter addr64 lscsa_ea; 31105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 31205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter lscsa_ea.ui[0] = spu_readch(SPU_RdSigNotify1); 31305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter lscsa_ea.ui[1] = spu_readch(SPU_RdSigNotify2); 31405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter fetch_regs_from_mem(lscsa_ea); 31505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 31605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter set_event_mask(); /* Step 1. */ 31705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter set_tag_mask(); /* Step 2. */ 31805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter build_dma_list(lscsa_ea); /* Step 3. */ 31905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter restore_upper_240kb(lscsa_ea); /* Step 4. */ 32005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Step 5: done by 'exit'. */ 32105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter enqueue_putllc(lscsa_ea); /* Step 7. */ 32205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter set_tag_update(); /* Step 8. */ 32305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter read_tag_status(); /* Step 9. */ 324ca53da3abb1d49748931ff2acb66d5a6eeeba2a1Masato Noguchi restore_decr(); /* moved Step 6. */ 32505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter read_llar_status(); /* Step 10. */ 32605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter write_ppu_mb(); /* Step 11. */ 32705b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter write_ppuint_mb(); /* Step 12. */ 32805b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter restore_fpcr(); /* Step 13. */ 32905b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter restore_srr0(); /* Step 14. */ 33005b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter restore_event_mask(); /* Step 15. */ 33105b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter restore_tag_mask(); /* Step 16. */ 33205b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter /* Step 17. done by 'exit'. */ 33305b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter restore_complete(); /* Step 18. */ 33405b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter 33505b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter return 0; 33605b841174c289ca62a6b42d883b8791d9ac3a4bdMark Nutter} 337