⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 switch.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	spu_int_mask_set(spu, 0, csa->priv1.int_mask_class0_RW);	spu_int_mask_set(spu, 1, csa->priv1.int_mask_class1_RW);	spu_int_mask_set(spu, 2, csa->priv1.int_mask_class2_RW);	spin_unlock_irq(&spu->register_lock);}static int quiece_spu(struct spu_state *prev, struct spu *spu){	/*	 * Combined steps 2-18 of SPU context save sequence, which	 * quiesce the SPU state (disable SPU execution, MFC command	 * queues, decrementer, SPU interrupts, etc.).	 *	 * Returns      0 on success.	 *              2 if failed step 2.	 *              6 if failed step 6.	 */	if (check_spu_isolate(prev, spu)) {	/* Step 2. */		return 2;	}	disable_interrupts(prev, spu);	        /* Step 3. */	set_watchdog_timer(prev, spu);	        /* Step 4. */	inhibit_user_access(prev, spu);	        /* Step 5. */	if (check_spu_isolate(prev, spu)) {	/* Step 6. */		return 6;	}	set_switch_pending(prev, spu);	        /* Step 7. */	save_mfc_cntl(prev, spu);		/* Step 8. */	save_spu_runcntl(prev, spu);	        /* Step 9. */	save_mfc_sr1(prev, spu);	        /* Step 10. */	save_spu_status(prev, spu);	        /* Step 11. */	save_mfc_decr(prev, spu);	        /* Step 12. */	halt_mfc_decr(prev, spu);	        /* Step 13. */	save_timebase(prev, spu);		/* Step 14. */	remove_other_spu_access(prev, spu);	/* Step 15. */	do_mfc_mssync(prev, spu);	        /* Step 16. */	issue_mfc_tlbie(prev, spu);	        /* Step 17. */	handle_pending_interrupts(prev, spu);	/* Step 18. */	return 0;}static void save_csa(struct spu_state *prev, struct spu *spu){	/*	 * Combine steps 19-44 of SPU context save sequence, which	 * save regions of the privileged & problem state areas.	 */	save_mfc_queues(prev, spu);	/* Step 19. */	save_ppu_querymask(prev, spu);	/* Step 20. */	save_ppu_querytype(prev, spu);	/* Step 21. */	save_ppu_tagstatus(prev, spu);  /* NEW.     */	save_mfc_csr_tsq(prev, spu);	/* Step 22. */	save_mfc_csr_cmd(prev, spu);	/* Step 23. */	save_mfc_csr_ato(prev, spu);	/* Step 24. */	save_mfc_tclass_id(prev, spu);	/* Step 25. */	set_mfc_tclass_id(prev, spu);	/* Step 26. */	purge_mfc_queue(prev, spu);	/* Step 27. */	wait_purge_complete(prev, spu);	/* Step 28. */	setup_mfc_sr1(prev, spu);	/* Step 30. */	save_spu_npc(prev, spu);	/* Step 31. */	save_spu_privcntl(prev, spu);	/* Step 32. */	reset_spu_privcntl(prev, spu);	/* Step 33. */	save_spu_lslr(prev, spu);	/* Step 34. */	reset_spu_lslr(prev, spu);	/* Step 35. */	save_spu_cfg(prev, spu);	/* Step 36. */	save_pm_trace(prev, spu);	/* Step 37. */	save_mfc_rag(prev, spu);	/* Step 38. */	save_ppu_mb_stat(prev, spu);	/* Step 39. */	save_ppu_mb(prev, spu);	        /* Step 40. */	save_ppuint_mb(prev, spu);	/* Step 41. */	save_ch_part1(prev, spu);	/* Step 42. */	save_spu_mb(prev, spu);	        /* Step 43. */	save_mfc_cmd(prev, spu);	/* Step 44. */	reset_ch(prev, spu);	        /* Step 45. */}static void save_lscsa(struct spu_state *prev, struct spu *spu){	/*	 * Perform steps 46-57 of SPU context save sequence,	 * which save regions of the local store and register	 * file.	 */	resume_mfc_queue(prev, spu);	/* Step 46. */	setup_mfc_slbs(prev, spu);	/* Step 47. */	set_switch_active(prev, spu);	/* Step 48. */	enable_interrupts(prev, spu);	/* Step 49. */	save_ls_16kb(prev, spu);	/* Step 50. */	set_spu_npc(prev, spu);	        /* Step 51. */	set_signot1(prev, spu);		/* Step 52. */	set_signot2(prev, spu);		/* Step 53. */	send_save_code(prev, spu);	/* Step 54. */	set_ppu_querymask(prev, spu);	/* Step 55. */	wait_tag_complete(prev, spu);	/* Step 56. */	wait_spu_stopped(prev, spu);	/* Step 57. */}static void force_spu_isolate_exit(struct spu *spu){	struct spu_problem __iomem *prob = spu->problem;	struct spu_priv2 __iomem *priv2 = spu->priv2;	/* Stop SPE execution and wait for completion. */	out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);	iobarrier_rw();	POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);	/* Restart SPE master runcntl. */	spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK);	iobarrier_w();	/* Initiate isolate exit request and wait for completion. */	out_be64(&priv2->spu_privcntl_RW, 4LL);	iobarrier_w();	out_be32(&prob->spu_runcntl_RW, 2);	iobarrier_rw();	POLL_WHILE_FALSE((in_be32(&prob->spu_status_R)				& SPU_STATUS_STOPPED_BY_STOP));	/* Reset load request to normal. */	out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL);	iobarrier_w();}/** * stop_spu_isolate *	Check SPU run-control state and force isolated *	exit function as necessary. */static void stop_spu_isolate(struct spu *spu){	struct spu_problem __iomem *prob = spu->problem;	if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) {		/* The SPU is in isolated state; the only way		 * to get it out is to perform an isolated		 * exit (clean) operation.		 */		force_spu_isolate_exit(spu);	}}static void harvest(struct spu_state *prev, struct spu *spu){	/*	 * Perform steps 2-25 of SPU context restore sequence,	 * which resets an SPU either after a failed save, or	 * when using SPU for first time.	 */	disable_interrupts(prev, spu);	        /* Step 2.  */	inhibit_user_access(prev, spu);	        /* Step 3.  */	terminate_spu_app(prev, spu);	        /* Step 4.  */	set_switch_pending(prev, spu);	        /* Step 5.  */	stop_spu_isolate(spu);			/* NEW.     */	remove_other_spu_access(prev, spu);	/* Step 6.  */	suspend_mfc_and_halt_decr(prev, spu);	/* Step 7.  */	wait_suspend_mfc_complete(prev, spu);	/* Step 8.  */	if (!suspend_spe(prev, spu))	        /* Step 9.  */		clear_spu_status(prev, spu);	/* Step 10. */	do_mfc_mssync(prev, spu);	        /* Step 11. */	issue_mfc_tlbie(prev, spu);	        /* Step 12. */	handle_pending_interrupts(prev, spu);	/* Step 13. */	purge_mfc_queue(prev, spu);	        /* Step 14. */	wait_purge_complete(prev, spu);	        /* Step 15. */	reset_spu_privcntl(prev, spu);	        /* Step 16. */	reset_spu_lslr(prev, spu);              /* Step 17. */	setup_mfc_sr1(prev, spu);	        /* Step 18. */	spu_invalidate_slbs(spu);		/* Step 19. */	reset_ch_part1(prev, spu);	        /* Step 20. */	reset_ch_part2(prev, spu);	        /* Step 21. */	enable_interrupts(prev, spu);	        /* Step 22. */	set_switch_active(prev, spu);	        /* Step 23. */	set_mfc_tclass_id(prev, spu);	        /* Step 24. */	resume_mfc_queue(prev, spu);	        /* Step 25. */}static void restore_lscsa(struct spu_state *next, struct spu *spu){	/*	 * Perform steps 26-40 of SPU context restore sequence,	 * which restores regions of the local store and register	 * file.	 */	set_watchdog_timer(next, spu);	        /* Step 26. */	setup_spu_status_part1(next, spu);	/* Step 27. */	setup_spu_status_part2(next, spu);	/* Step 28. */	restore_mfc_rag(next, spu);	        /* Step 29. */	setup_mfc_slbs(next, spu);	        /* Step 30. */	set_spu_npc(next, spu);	                /* Step 31. */	set_signot1(next, spu);	                /* Step 32. */	set_signot2(next, spu);	                /* Step 33. */	setup_decr(next, spu);	                /* Step 34. */	setup_ppu_mb(next, spu);	        /* Step 35. */	setup_ppuint_mb(next, spu);	        /* Step 36. */	send_restore_code(next, spu);	        /* Step 37. */	set_ppu_querymask(next, spu);	        /* Step 38. */	wait_tag_complete(next, spu);	        /* Step 39. */	wait_spu_stopped(next, spu);	        /* Step 40. */}static void restore_csa(struct spu_state *next, struct spu *spu){	/*	 * Combine steps 41-76 of SPU context restore sequence, which	 * restore regions of the privileged & problem state areas.	 */	restore_spu_privcntl(next, spu);	/* Step 41. */	restore_status_part1(next, spu);	/* Step 42. */	restore_status_part2(next, spu);	/* Step 43. */	restore_ls_16kb(next, spu);	        /* Step 44. */	wait_tag_complete(next, spu);	        /* Step 45. */	suspend_mfc(next, spu);	                /* Step 46. */	wait_suspend_mfc_complete(next, spu);	/* Step 47. */	issue_mfc_tlbie(next, spu);	        /* Step 48. */	clear_interrupts(next, spu);	        /* Step 49. */	restore_mfc_queues(next, spu);	        /* Step 50. */	restore_ppu_querymask(next, spu);	/* Step 51. */	restore_ppu_querytype(next, spu);	/* Step 52. */	restore_mfc_csr_tsq(next, spu);	        /* Step 53. */	restore_mfc_csr_cmd(next, spu);	        /* Step 54. */	restore_mfc_csr_ato(next, spu);	        /* Step 55. */	restore_mfc_tclass_id(next, spu);	/* Step 56. */	set_llr_event(next, spu);	        /* Step 57. */	restore_decr_wrapped(next, spu);	/* Step 58. */	restore_ch_part1(next, spu);	        /* Step 59. */	restore_ch_part2(next, spu);	        /* Step 60. */	restore_spu_lslr(next, spu);	        /* Step 61. */	restore_spu_cfg(next, spu);	        /* Step 62. */	restore_pm_trace(next, spu);	        /* Step 63. */	restore_spu_npc(next, spu);	        /* Step 64. */	restore_spu_mb(next, spu);	        /* Step 65. */	check_ppu_mb_stat(next, spu);	        /* Step 66. */	check_ppuint_mb_stat(next, spu);	/* Step 67. */	spu_invalidate_slbs(spu);		/* Modified Step 68. */	restore_mfc_sr1(next, spu);	        /* Step 69. */	restore_other_spu_access(next, spu);	/* Step 70. */	restore_spu_runcntl(next, spu);	        /* Step 71. */	restore_mfc_cntl(next, spu);	        /* Step 72. */	enable_user_access(next, spu);	        /* Step 73. */	reset_switch_active(next, spu);	        /* Step 74. */	reenable_interrupts(next, spu);	        /* Step 75. */}static int __do_spu_save(struct spu_state *prev, struct spu *spu){	int rc;	/*	 * SPU context save can be broken into three phases:	 *	 *     (a) quiesce [steps 2-16].	 *     (b) save of CSA, performed by PPE [steps 17-42]	 *     (c) save of LSCSA, mostly performed by SPU [steps 43-52].	 *	 * Returns      0 on success.	 *              2,6 if failed to quiece SPU	 *              53 if SPU-side of save failed.	 */	rc = quiece_spu(prev, spu);	        /* Steps 2-16. */	switch (rc) {	default:	case 2:	case 6:		harvest(prev, spu);		return rc;		break;	case 0:		break;	}	save_csa(prev, spu);	                /* Steps 17-43. */	save_lscsa(prev, spu);	                /* Steps 44-53. */	return check_save_status(prev, spu);	/* Step 54.     */}static int __do_spu_restore(struct spu_state *next, struct spu *spu){	int rc;	/*	 * SPU context restore can be broken into three phases:	 *	 *    (a) harvest (or reset) SPU [steps 2-24].	 *    (b) restore LSCSA [steps 25-40], mostly performed by SPU.	 *    (c) restore CSA [steps 41-76], performed by PPE.	 *	 * The 'harvest' step is not performed here, but rather	 * as needed below.	 */	restore_lscsa(next, spu);	        /* Steps 24-39. */	rc = check_restore_status(next, spu);	/* Step 40.     */	switch (rc) {	default:		/* Failed. Return now. */		return rc;		break;	case 0:		/* Fall through to next step. */		break;	}	restore_csa(next, spu);	return 0;}/** * spu_save - SPU context save, with locking. * @prev: pointer to SPU context save area, to be saved. * @spu: pointer to SPU iomem structure. * * Acquire locks, perform the save operation then return. */int spu_save(struct spu_state *prev, struct spu *spu){	int rc;	acquire_spu_lock(spu);	        /* Step 1.     */	prev->dar = spu->dar;	prev->dsisr = spu->dsisr;	spu->dar = 0;	spu->dsisr = 0;	rc = __do_spu_save(prev, spu);	/* Steps 2-53. */	release_spu_lock(spu);	if (rc != 0 && rc != 2 && rc != 6) {		panic("%s failed on SPU[%d], rc=%d.\n",		      __func__, spu->number, rc);	}	return 0;}EXPORT_SYMBOL_GPL(spu_save);/** * spu_restore - SPU context restore, with harvest and locking. * @new: pointer to SPU context save area, to be restored. * @spu: pointer to SPU iomem structure. * * Perform harvest + restore, as we may not be coming * from a previous successful save operation, and the * hardware state is unknown. */int spu_restore(struct spu_state *new, struct spu *spu){	int rc;	acquire_spu_lock(spu);	harvest(NULL, spu);	spu->slb_replace = 0;	new->dar = 0;	new->dsisr = 0;	spu->class_0_pending = 0;	rc = __do_spu_restore(new, spu);	release_spu_lock(spu);	if (rc) {		panic("%s failed on SPU[%d] rc=%d.\n",		       __func__, spu->number, rc);	}	return rc;}EXPORT_SYMBOL_GPL(spu_restore);static void init_prob(struct spu_state *csa){	csa->spu_chnlcnt_RW[9] = 1;	csa->spu_chnlcnt_RW[21] = 16;	csa->spu_chnlcnt_RW[23] = 1;	csa->spu_chnlcnt_RW[28] = 1;	csa->spu_chnlcnt_RW[30] = 1;	csa->prob.spu_runcntl_RW = SPU_RUNCNTL_STOP;	csa->prob.mb_stat_R = 0x000400;}static void init_priv1(struct spu_state *csa){	/* Enable decode, relocate, tlbie response, master runcntl. */	csa->priv1.mfc_sr1_RW = MFC_STATE1_LOCAL_STORAGE_DECODE_MASK |	    MFC_STATE1_MASTER_RUN_CONTROL_MASK |	    MFC_STATE1_PROBLEM_STATE_MASK |	    MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK;	/* Enable OS-specific set of interrupts. */	csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR |	    CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR |	    CLASS0_ENABLE_SPU_ERROR_INTR;	csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR |	    CLASS1_ENABLE_STORAGE_FAULT_INTR;	csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR |	    CLASS2_ENABLE_SPU_HALT_INTR |	    CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR;}static void init_priv2(struct spu_state *csa){	csa->priv2.spu_lslr_RW = LS_ADDR_MASK;	csa->priv2.mfc_control_RW = MFC_CNTL_RESUME_DMA_QUEUE |	    MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION |	    MFC_CNTL_DMA_QUEUES_EMPTY_MASK;}/** * spu_alloc_csa - allocate and initialize an SPU context save area. * * Allocate and initialize the contents of an SPU context save area. * This includes enabling address translation, interrupt masks, etc., * as appropriate for the given OS environment. * * Note that storage for the 'lscsa' is allocated separately, * as it is by far the largest of the context save regions, * and may need to be pinned or otherwise specially aligned. */int spu_init_csa(struct spu_state *csa){	int rc;	if (!csa)		return -EINVAL;	memset(csa, 0, sizeof(struct spu_state));	rc = spu_alloc_lscsa(csa);	if (rc)		return rc;	spin_lock_init(&csa->register_lock);	init_prob(csa);	init_priv1(csa);	init_priv2(csa);	return 0;}EXPORT_SYMBOL_GPL(spu_init_csa);void spu_fini_csa(struct spu_state *csa){	spu_free_lscsa(csa);}EXPORT_SYMBOL_GPL(spu_fini_csa);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -