4 * (C) Copyright IBM Corp. 2005
6 * SPU-side context save sequence outlined in
7 * Synergistic Processor Element Book IV
9 * Author: Mark Nutter <mnutter@us.ibm.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define LS_SIZE 0x40000 /* 256K (in bytes) */
32 typedef unsigned int u32
;
33 typedef unsigned long long u64
;
35 #include <spu_intrinsics.h>
36 #include <asm/spu_csa.h>
37 #include "spu_utils.h"
39 static inline void save_event_mask(void)
44 * Read the SPU_RdEventMsk channel and save to the LSCSA.
46 offset
= LSCSA_QW_OFFSET(event_mask
);
47 regs_spill
[offset
].slot
[0] = spu_readch(SPU_RdEventMask
);
50 static inline void save_tag_mask(void)
55 * Read the SPU_RdTagMsk channel and save to the LSCSA.
57 offset
= LSCSA_QW_OFFSET(tag_mask
);
58 regs_spill
[offset
].slot
[0] = spu_readch(MFC_RdTagMask
);
61 static inline void save_upper_240kb(addr64 lscsa_ea
)
63 unsigned int ls
= 16384;
64 unsigned int list
= (unsigned int)&dma_list
[0];
65 unsigned int size
= sizeof(dma_list
);
66 unsigned int tag_id
= 0;
67 unsigned int cmd
= 0x24; /* PUTL */
70 * Enqueue the PUTL command (tag 0) to the MFC SPU command
71 * queue to transfer the remaining 240 kb of LS to CSA.
73 spu_writech(MFC_LSA
, ls
);
74 spu_writech(MFC_EAH
, lscsa_ea
.ui
[0]);
75 spu_writech(MFC_EAL
, list
);
76 spu_writech(MFC_Size
, size
);
77 spu_writech(MFC_TagID
, tag_id
);
78 spu_writech(MFC_Cmd
, cmd
);
81 static inline void save_fpcr(void)
83 // vector unsigned int fpcr;
87 * Issue the floating-point status and control register
88 * read instruction, and save to the LSCSA.
90 offset
= LSCSA_QW_OFFSET(fpcr
);
91 regs_spill
[offset
].v
= spu_mffpscr();
94 static inline void save_decr(void)
99 * Read and save the SPU_RdDec channel data to
102 offset
= LSCSA_QW_OFFSET(decr
);
103 regs_spill
[offset
].slot
[0] = spu_readch(SPU_RdDec
);
106 static inline void save_srr0(void)
111 * Read and save the SPU_WSRR0 channel data to
114 offset
= LSCSA_QW_OFFSET(srr0
);
115 regs_spill
[offset
].slot
[0] = spu_readch(SPU_RdSRR0
);
118 static inline void spill_regs_to_mem(addr64 lscsa_ea
)
120 unsigned int ls
= (unsigned int)®s_spill
[0];
121 unsigned int size
= sizeof(regs_spill
);
122 unsigned int tag_id
= 0;
123 unsigned int cmd
= 0x20; /* PUT */
126 * Enqueue a PUT command (tag 0) to send the LSCSA
129 spu_writech(MFC_LSA
, ls
);
130 spu_writech(MFC_EAH
, lscsa_ea
.ui
[0]);
131 spu_writech(MFC_EAL
, lscsa_ea
.ui
[1]);
132 spu_writech(MFC_Size
, size
);
133 spu_writech(MFC_TagID
, tag_id
);
134 spu_writech(MFC_Cmd
, cmd
);
137 static inline void enqueue_sync(addr64 lscsa_ea
)
139 unsigned int tag_id
= 0;
140 unsigned int cmd
= 0xCC;
143 * Enqueue an MFC_SYNC command (tag 0).
145 spu_writech(MFC_TagID
, tag_id
);
146 spu_writech(MFC_Cmd
, cmd
);
149 static inline void save_complete(void)
152 * Issue a stop-and-signal instruction indicating
153 * "save complete". Note: This function will not
156 spu_stop(SPU_SAVE_COMPLETE
);
160 * main - entry point for SPU-side context save.
162 * This code deviates from the documented sequence as follows:
164 * 1. The EA for LSCSA is passed from PPE in the
165 * signal notification channels.
166 * 2. All 128 registers are saved by crt0.o.
172 lscsa_ea
.ui
[0] = spu_readch(SPU_RdSigNotify1
);
173 lscsa_ea
.ui
[1] = spu_readch(SPU_RdSigNotify2
);
175 /* Step 1: done by exit(). */
176 save_event_mask(); /* Step 2. */
177 save_tag_mask(); /* Step 3. */
178 set_event_mask(); /* Step 4. */
179 set_tag_mask(); /* Step 5. */
180 build_dma_list(lscsa_ea
); /* Step 6. */
181 save_upper_240kb(lscsa_ea
); /* Step 7. */
182 /* Step 8: done by exit(). */
183 save_fpcr(); /* Step 9. */
184 save_decr(); /* Step 10. */
185 save_srr0(); /* Step 11. */
186 enqueue_putllc(lscsa_ea
); /* Step 12. */
187 spill_regs_to_mem(lscsa_ea
); /* Step 13. */
188 enqueue_sync(lscsa_ea
); /* Step 14. */
189 set_tag_update(); /* Step 15. */
190 read_tag_status(); /* Step 16. */
191 read_llar_status(); /* Step 17. */
192 save_complete(); /* Step 18. */