Path: blob/master/arch/powerpc/platforms/cell/spufs/spu_save.c
26498 views
// SPDX-License-Identifier: GPL-2.0-or-later1/*2* spu_save.c3*4* (C) Copyright IBM Corp. 20055*6* SPU-side context save sequence outlined in7* Synergistic Processor Element Book IV8*9* Author: Mark Nutter <[email protected]>10*/111213#ifndef LS_SIZE14#define LS_SIZE 0x40000 /* 256K (in bytes) */15#endif1617typedef unsigned int u32;18typedef unsigned long long u64;1920#include <spu_intrinsics.h>21#include <asm/spu_csa.h>22#include "spu_utils.h"2324static inline void save_event_mask(void)25{26unsigned int offset;2728/* Save, Step 2:29* Read the SPU_RdEventMsk channel and save to the LSCSA.30*/31offset = LSCSA_QW_OFFSET(event_mask);32regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask);33}3435static inline void save_tag_mask(void)36{37unsigned int offset;3839/* Save, Step 3:40* Read the SPU_RdTagMsk channel and save to the LSCSA.41*/42offset = LSCSA_QW_OFFSET(tag_mask);43regs_spill[offset].slot[0] = spu_readch(MFC_RdTagMask);44}4546static inline void save_upper_240kb(addr64 lscsa_ea)47{48unsigned int ls = 16384;49unsigned int list = (unsigned int)&dma_list[0];50unsigned int size = sizeof(dma_list);51unsigned int tag_id = 0;52unsigned int cmd = 0x24; /* PUTL */5354/* Save, Step 7:55* Enqueue the PUTL command (tag 0) to the MFC SPU command56* queue to transfer the remaining 240 kb of LS to CSA.57*/58spu_writech(MFC_LSA, ls);59spu_writech(MFC_EAH, lscsa_ea.ui[0]);60spu_writech(MFC_EAL, list);61spu_writech(MFC_Size, size);62spu_writech(MFC_TagID, tag_id);63spu_writech(MFC_Cmd, cmd);64}6566static inline void save_fpcr(void)67{68// vector unsigned int fpcr;69unsigned int offset;7071/* Save, Step 9:72* Issue the floating-point status and control register73* read instruction, and save to the LSCSA.74*/75offset = LSCSA_QW_OFFSET(fpcr);76regs_spill[offset].v = spu_mffpscr();77}7879static inline void save_decr(void)80{81unsigned int offset;8283/* Save, Step 10:84* Read and save the SPU_RdDec channel data to85* the LSCSA.86*/87offset = LSCSA_QW_OFFSET(decr);88regs_spill[offset].slot[0] = spu_readch(SPU_RdDec);89}9091static inline void save_srr0(void)92{93unsigned int offset;9495/* Save, Step 11:96* Read and save the SPU_WSRR0 channel data to97* the LSCSA.98*/99offset = LSCSA_QW_OFFSET(srr0);100regs_spill[offset].slot[0] = spu_readch(SPU_RdSRR0);101}102103static inline void spill_regs_to_mem(addr64 lscsa_ea)104{105unsigned int ls = (unsigned int)®s_spill[0];106unsigned int size = sizeof(regs_spill);107unsigned int tag_id = 0;108unsigned int cmd = 0x20; /* PUT */109110/* Save, Step 13:111* Enqueue a PUT command (tag 0) to send the LSCSA112* to the CSA.113*/114spu_writech(MFC_LSA, ls);115spu_writech(MFC_EAH, lscsa_ea.ui[0]);116spu_writech(MFC_EAL, lscsa_ea.ui[1]);117spu_writech(MFC_Size, size);118spu_writech(MFC_TagID, tag_id);119spu_writech(MFC_Cmd, cmd);120}121122static inline void enqueue_sync(addr64 lscsa_ea)123{124unsigned int tag_id = 0;125unsigned int cmd = 0xCC;126127/* Save, Step 14:128* Enqueue an MFC_SYNC command (tag 0).129*/130spu_writech(MFC_TagID, tag_id);131spu_writech(MFC_Cmd, cmd);132}133134static inline void save_complete(void)135{136/* Save, Step 18:137* Issue a stop-and-signal instruction indicating138* "save complete". Note: This function will not139* return!!140*/141spu_stop(SPU_SAVE_COMPLETE);142}143144/**145* main - entry point for SPU-side context save.146*147* This code deviates from the documented sequence as follows:148*149* 1. The EA for LSCSA is passed from PPE in the150* signal notification channels.151* 2. All 128 registers are saved by crt0.o.152*/153int main()154{155addr64 lscsa_ea;156157lscsa_ea.ui[0] = spu_readch(SPU_RdSigNotify1);158lscsa_ea.ui[1] = spu_readch(SPU_RdSigNotify2);159160/* Step 1: done by exit(). */161save_event_mask(); /* Step 2. */162save_tag_mask(); /* Step 3. */163set_event_mask(); /* Step 4. */164set_tag_mask(); /* Step 5. */165build_dma_list(lscsa_ea); /* Step 6. */166save_upper_240kb(lscsa_ea); /* Step 7. */167/* Step 8: done by exit(). */168save_fpcr(); /* Step 9. */169save_decr(); /* Step 10. */170save_srr0(); /* Step 11. */171enqueue_putllc(lscsa_ea); /* Step 12. */172spill_regs_to_mem(lscsa_ea); /* Step 13. */173enqueue_sync(lscsa_ea); /* Step 14. */174set_tag_update(); /* Step 15. */175read_tag_status(); /* Step 16. */176read_llar_status(); /* Step 17. */177save_complete(); /* Step 18. */178179return 0;180}181182183