/*******************************************************************************
 * This function prepare boot argument for kernel entrypoint
 ******************************************************************************/
void bl31_prepare_kernel_entry(uint64_t k32_64)
{
	entry_point_info_t *next_image_info;
	uint32_t image_type;

	/* Determine which image to execute next */
	/* image_type = bl31_get_next_image_type(); */
	image_type = NON_SECURE;

	/* Program EL3 registers to enable entry into the next EL */
	if (k32_64 == 0)
		next_image_info = bl31_plat_get_next_kernel32_ep_info();
	else
		next_image_info = bl31_plat_get_next_kernel64_ep_info();

	assert(next_image_info);
	assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));

	INFO("BL3-1: Preparing for EL3 exit to %s world, Kernel\n",
		(image_type == SECURE) ? "secure" : "normal");
	INFO("BL3-1: Next image address = 0x%llx\n",
		(unsigned long long) next_image_info->pc);
	INFO("BL3-1: Next image spsr = 0x%x\n", next_image_info->spsr);
	cm_init_context(read_mpidr_el1(), next_image_info);
	cm_prepare_el3_exit(image_type);
}
/*******************************************************************************
 * This function invokes the PSCI library interface to initialize the
 * non secure cpu context and copies the relevant cpu context register values
 * to smc context. These registers will get programmed during `smc_exit`.
 ******************************************************************************/
static void sp_min_prepare_next_image_entry(void)
{
	entry_point_info_t *next_image_info;
	cpu_context_t *ctx = cm_get_context(NON_SECURE);
	u_register_t ns_sctlr;

	/* Program system registers to proceed to non-secure */
	next_image_info = sp_min_plat_get_bl33_ep_info();
	assert(next_image_info);
	assert(NON_SECURE == GET_SECURITY_STATE(next_image_info->h.attr));

	INFO("SP_MIN: Preparing exit to normal world\n");

	psci_prepare_next_non_secure_ctx(next_image_info);
	smc_set_next_ctx(NON_SECURE);

	/* Copy r0, lr and spsr from cpu context to SMC context */
	copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
			smc_get_next_ctx());

	/* Temporarily set the NS bit to access NS SCTLR */
	write_scr(read_scr() | SCR_NS_BIT);
	isb();
	ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR);
	write_sctlr(ns_sctlr);
	isb();

	write_scr(read_scr() & ~SCR_NS_BIT);
	isb();
}
/*******************************************************************************
 * The following function initializes the cpu_context for a CPU specified by
 * its `cpu_idx` for first use, and sets the initial entrypoint state as
 * specified by the entry_point_info structure.
 ******************************************************************************/
void cm_init_context_by_index(unsigned int cpu_idx,
			      const entry_point_info_t *ep)
{
	cpu_context_t *ctx;
	ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr));
	cm_init_context_common(ctx, ep);
}
/*******************************************************************************
 * The following function initializes the cpu_context 'ctx' for
 * first use, and sets the initial entrypoint state as specified by the
 * entry_point_info structure.
 *
 * The security state to initialize is determined by the SECURE attribute
 * of the entry_point_info. The function returns a pointer to the initialized
 * context and sets this as the next context to return to.
 *
 * The EE and ST attributes are used to configure the endianness and secure
 * timer availability for the new execution context.
 *
 * To prepare the register state for entry call cm_prepare_el3_exit() and
 * el3_exit(). For Secure-EL1 cm_prepare_el3_exit() is equivalent to
 * cm_e1_sysreg_context_restore().
 ******************************************************************************/
static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t *ep)
{
    unsigned int security_state;
    uint32_t scr, sctlr;
    regs_t *reg_ctx;

    assert(ctx);

    security_state = GET_SECURITY_STATE(ep->h.attr);

    /* Clear any residual register values from the context */
    memset(ctx, 0, sizeof(*ctx));

    reg_ctx = get_regs_ctx(ctx);

    /*
     * Base the context SCR on the current value, adjust for entry point
     * specific requirements
     */
    scr = read_scr();
    scr &= ~(SCR_NS_BIT | SCR_HCE_BIT);

    if (security_state != SECURE)
        scr |= SCR_NS_BIT;

    /*
     * Set up SCTLR for the Non Secure context.
     * EE bit is taken from the entrypoint attributes
     * M, C and I bits must be zero (as required by PSCI specification)
     *
     * The target exception level is based on the spsr mode requested.
     * If execution is requested to hyp mode, HVC is enabled
     * via SCR.HCE.
     *
     * Always compute the SCTLR_EL1 value and save in the cpu_context
     * - the HYP registers are set up by cm_preapre_ns_entry() as they
     * are not part of the stored cpu_context
     *
     * TODO: In debug builds the spsr should be validated and checked
     * against the CPU support, security state, endianness and pc
     */
    if (security_state != SECURE) {
        sctlr = EP_GET_EE(ep->h.attr) ? SCTLR_EE_BIT : 0;
        sctlr |= SCTLR_RES1;
        write_ctx_reg(reg_ctx, CTX_NS_SCTLR, sctlr);
    }

    if (GET_M32(ep->spsr) == MODE32_hyp)
        scr |= SCR_HCE_BIT;

    write_ctx_reg(reg_ctx, CTX_SCR, scr);
    write_ctx_reg(reg_ctx, CTX_LR, ep->pc);
    write_ctx_reg(reg_ctx, CTX_SPSR, ep->spsr);

    /*
     * Store the r0-r3 value from the entrypoint into the context
     * Use memcpy as we are in control of the layout of the structures
     */
    memcpy((void *)reg_ctx, (void *)&ep->args, sizeof(aapcs32_params_t));
}
/*******************************************************************************
 * This function invokes the PSCI library interface to initialize the
 * non secure cpu context and copies the relevant cpu context register values
 * to smc context. These registers will get programmed during `smc_exit`.
 ******************************************************************************/
static void sp_min_prepare_next_image_entry(void)
{
	entry_point_info_t *next_image_info;

	/* Program system registers to proceed to non-secure */
	next_image_info = sp_min_plat_get_bl33_ep_info();
	assert(next_image_info);
	assert(NON_SECURE == GET_SECURITY_STATE(next_image_info->h.attr));

	INFO("SP_MIN: Preparing exit to normal world\n");

	psci_prepare_next_non_secure_ctx(next_image_info);
	smc_set_next_ctx(NON_SECURE);

	/* Copy r0, lr and spsr from cpu context to SMC context */
	copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
			smc_get_next_ctx());
}
/*******************************************************************************
 * This function is responsible for handling all SMCs in the Trusted OS/App
 * range from the non-secure state as defined in the SMC Calling Convention
 * Document. It is also responsible for communicating with the Secure payload
 * to delegate work and return results back to the non-secure state. Lastly it
 * will also return any information that the secure payload needs to do the
 * work assigned to it.
 ******************************************************************************/
uint64_t tspd_smc_handler(uint32_t smc_fid,
			 uint64_t x1,
			 uint64_t x2,
			 uint64_t x3,
			 uint64_t x4,
			 void *cookie,
			 void *handle,
			 uint64_t flags)
{
	cpu_context_t *ns_cpu_context;
	uint32_t linear_id = plat_my_core_pos(), ns;
	tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id];
	uint64_t rc;
#if TSP_INIT_ASYNC
	entry_point_info_t *next_image_info;
#endif

	/* Determine which security state this SMC originated from */
	ns = is_caller_non_secure(flags);

	switch (smc_fid) {

	/*
	 * This function ID is used by TSP to indicate that it was
	 * preempted by a normal world IRQ.
	 *
	 */
	case TSP_PREEMPTED:
		if (ns)
			SMC_RET1(handle, SMC_UNK);

		return tspd_handle_sp_preemption(handle);

	/*
	 * This function ID is used only by the TSP to indicate that it has
	 * finished handling a S-EL1 FIQ interrupt. Execution should resume
	 * in the normal world.
	 */
	case TSP_HANDLED_S_EL1_FIQ:
		if (ns)
			SMC_RET1(handle, SMC_UNK);

		assert(handle == cm_get_context(SECURE));

		/*
		 * Restore the relevant EL3 state which saved to service
		 * this SMC.
		 */
		if (get_std_smc_active_flag(tsp_ctx->state)) {
			SMC_SET_EL3(&tsp_ctx->cpu_ctx,
				    CTX_SPSR_EL3,
				    tsp_ctx->saved_spsr_el3);
			SMC_SET_EL3(&tsp_ctx->cpu_ctx,
				    CTX_ELR_EL3,
				    tsp_ctx->saved_elr_el3);
#if TSPD_ROUTE_IRQ_TO_EL3
			/*
			 * Need to restore the previously interrupted
			 * secure context.
			 */
			memcpy(&tsp_ctx->cpu_ctx, &tsp_ctx->sp_ctx,
				TSPD_SP_CTX_SIZE);
#endif
		}

		/* Get a reference to the non-secure context */
		ns_cpu_context = cm_get_context(NON_SECURE);
		assert(ns_cpu_context);

		/*
		 * Restore non-secure state. There is no need to save the
		 * secure system register context since the TSP was supposed
		 * to preserve it during S-EL1 interrupt handling.
		 */
		cm_el1_sysregs_context_restore(NON_SECURE);
		cm_set_next_eret_context(NON_SECURE);

		SMC_RET0((uint64_t) ns_cpu_context);


	/*
	 * This function ID is used only by the TSP to indicate that it was
	 * interrupted due to a EL3 FIQ interrupt. Execution should resume
	 * in the normal world.
	 */
	case TSP_EL3_FIQ:
		if (ns)
			SMC_RET1(handle, SMC_UNK);

		assert(handle == cm_get_context(SECURE));

		/* Assert that standard SMC execution has been preempted */
		assert(get_std_smc_active_flag(tsp_ctx->state));

		/* Save the secure system register state */
		cm_el1_sysregs_context_save(SECURE);

		/* Get a reference to the non-secure context */
		ns_cpu_context = cm_get_context(NON_SECURE);
		assert(ns_cpu_context);

		/* Restore non-secure state */
		cm_el1_sysregs_context_restore(NON_SECURE);
		cm_set_next_eret_context(NON_SECURE);

		SMC_RET1(ns_cpu_context, TSP_EL3_FIQ);


	/*
	 * This function ID is used only by the SP to indicate it has
	 * finished initialising itself after a cold boot
	 */
	case TSP_ENTRY_DONE:
		if (ns)
			SMC_RET1(handle, SMC_UNK);

		/*
		 * Stash the SP entry points information. This is done
		 * only once on the primary cpu
		 */
		assert(tsp_vectors == NULL);
		tsp_vectors = (tsp_vectors_t *) x1;

		if (tsp_vectors) {
			set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON);

			/*
			 * TSP has been successfully initialized. Register power
			 * managemnt hooks with PSCI
			 */
			psci_register_spd_pm_hook(&tspd_pm);

			/*
			 * Register an interrupt handler for S-EL1 interrupts
			 * when generated during code executing in the
			 * non-secure state.
			 */
			flags = 0;
			set_interrupt_rm_flag(flags, NON_SECURE);
			rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
						tspd_sel1_interrupt_handler,
						flags);
			if (rc)
				panic();

#if TSPD_ROUTE_IRQ_TO_EL3
			/*
			 * Register an interrupt handler for NS interrupts when
			 * generated during code executing in secure state are
			 * routed to EL3.
			 */
			flags = 0;
			set_interrupt_rm_flag(flags, SECURE);

			rc = register_interrupt_type_handler(INTR_TYPE_NS,
						tspd_ns_interrupt_handler,
						flags);
			if (rc)
				panic();

			/*
			 * Disable the interrupt NS locally since it will be enabled globally
			 * within cm_init_my_context.
			 */
			disable_intr_rm_local(INTR_TYPE_NS, SECURE);
#endif
		}


#if TSP_INIT_ASYNC
		/* Save the Secure EL1 system register context */
		assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx);
		cm_el1_sysregs_context_save(SECURE);

		/* Program EL3 registers to enable entry into the next EL */
		next_image_info = bl31_plat_get_next_image_ep_info(NON_SECURE);
		assert(next_image_info);
		assert(NON_SECURE ==
				GET_SECURITY_STATE(next_image_info->h.attr));

		cm_init_my_context(next_image_info);
		cm_prepare_el3_exit(NON_SECURE);
		SMC_RET0(cm_get_context(NON_SECURE));
#else
		/*
		 * SP reports completion. The SPD must have initiated
		 * the original request through a synchronous entry
		 * into the SP. Jump back to the original C runtime
		 * context.
		 */
		tspd_synchronous_sp_exit(tsp_ctx, x1);
#endif

	/*
	 * These function IDs is used only by the SP to indicate it has
	 * finished:
	 * 1. turning itself on in response to an earlier psci
	 *    cpu_on request
	 * 2. resuming itself after an earlier psci cpu_suspend
	 *    request.
	 */
	case TSP_ON_DONE:
	case TSP_RESUME_DONE:

	/*
	 * These function IDs is used only by the SP to indicate it has
	 * finished:
	 * 1. suspending itself after an earlier psci cpu_suspend
	 *    request.
	 * 2. turning itself off in response to an earlier psci
	 *    cpu_off request.
	 */
	case TSP_OFF_DONE:
	case TSP_SUSPEND_DONE:
	case TSP_SYSTEM_OFF_DONE:
	case TSP_SYSTEM_RESET_DONE:
		if (ns)
			SMC_RET1(handle, SMC_UNK);

		/*
		 * SP reports completion. The SPD must have initiated the
		 * original request through a synchronous entry into the SP.
		 * Jump back to the original C runtime context, and pass x1 as
		 * return value to the caller
		 */
		tspd_synchronous_sp_exit(tsp_ctx, x1);

		/*
		 * Request from non-secure client to perform an
		 * arithmetic operation or response from secure
		 * payload to an earlier request.
		 */
	case TSP_FAST_FID(TSP_ADD):
	case TSP_FAST_FID(TSP_SUB):
	case TSP_FAST_FID(TSP_MUL):
	case TSP_FAST_FID(TSP_DIV):

	case TSP_STD_FID(TSP_ADD):
	case TSP_STD_FID(TSP_SUB):
	case TSP_STD_FID(TSP_MUL):
	case TSP_STD_FID(TSP_DIV):
		if (ns) {
			/*
			 * This is a fresh request from the non-secure client.
			 * The parameters are in x1 and x2. Figure out which
			 * registers need to be preserved, save the non-secure
			 * state and send the request to the secure payload.
			 */
			assert(handle == cm_get_context(NON_SECURE));

			/* Check if we are already preempted */
			if (get_std_smc_active_flag(tsp_ctx->state))
				SMC_RET1(handle, SMC_UNK);

			cm_el1_sysregs_context_save(NON_SECURE);

			/* Save x1 and x2 for use by TSP_GET_ARGS call below */
			store_tsp_args(tsp_ctx, x1, x2);

			/*
			 * We are done stashing the non-secure context. Ask the
			 * secure payload to do the work now.
			 */

			/*
			 * Verify if there is a valid context to use, copy the
			 * operation type and parameters to the secure context
			 * and jump to the fast smc entry point in the secure
			 * payload. Entry into S-EL1 will take place upon exit
			 * from this function.
			 */
			assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE));

			/* Set appropriate entry for SMC.
			 * We expect the TSP to manage the PSTATE.I and PSTATE.F
			 * flags as appropriate.
			 */
			if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) {
				cm_set_elr_el3(SECURE, (uint64_t)
						&tsp_vectors->fast_smc_entry);
			} else {
				set_std_smc_active_flag(tsp_ctx->state);
				cm_set_elr_el3(SECURE, (uint64_t)
						&tsp_vectors->std_smc_entry);
#if TSPD_ROUTE_IRQ_TO_EL3
				/*
				 * Enable the routing of NS interrupts to EL3
				 * during STD SMC processing on this core.
				 */
				enable_intr_rm_local(INTR_TYPE_NS, SECURE);
#endif
			}

			cm_el1_sysregs_context_restore(SECURE);
			cm_set_next_eret_context(SECURE);
			SMC_RET3(&tsp_ctx->cpu_ctx, smc_fid, x1, x2);
		} else {
			/*
			 * This is the result from the secure client of an
			 * earlier request. The results are in x1-x3. Copy it
			 * into the non-secure context, save the secure state
			 * and return to the non-secure state.
			 */
			assert(handle == cm_get_context(SECURE));
			cm_el1_sysregs_context_save(SECURE);

			/* Get a reference to the non-secure context */
			ns_cpu_context = cm_get_context(NON_SECURE);
			assert(ns_cpu_context);

			/* Restore non-secure state */
			cm_el1_sysregs_context_restore(NON_SECURE);
			cm_set_next_eret_context(NON_SECURE);
			if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_STD) {
				clr_std_smc_active_flag(tsp_ctx->state);
#if TSPD_ROUTE_IRQ_TO_EL3
				/*
				 * Disable the routing of NS interrupts to EL3
				 * after STD SMC processing is finished on this
				 * core.
				 */
				disable_intr_rm_local(INTR_TYPE_NS, SECURE);
#endif
			}

			SMC_RET3(ns_cpu_context, x1, x2, x3);
		}

		break;

		/*
		 * Request from non secure world to resume the preempted
		 * Standard SMC call.
		 */
	case TSP_FID_RESUME:
		/* RESUME should be invoked only by normal world */
		if (!ns) {
			assert(0);
			break;
		}

		/*
		 * This is a resume request from the non-secure client.
		 * save the non-secure state and send the request to
		 * the secure payload.
		 */
		assert(handle == cm_get_context(NON_SECURE));

		/* Check if we are already preempted before resume */
		if (!get_std_smc_active_flag(tsp_ctx->state))
			SMC_RET1(handle, SMC_UNK);

		cm_el1_sysregs_context_save(NON_SECURE);

		/*
		 * We are done stashing the non-secure context. Ask the
		 * secure payload to do the work now.
		 */
#if TSPD_ROUTE_IRQ_TO_EL3
		/*
		 * Enable the routing of NS interrupts to EL3 during resumption
		 * of STD SMC call on this core.
		 */
		enable_intr_rm_local(INTR_TYPE_NS, SECURE);
#endif



		/* We just need to return to the preempted point in
		 * TSP and the execution will resume as normal.
		 */
		cm_el1_sysregs_context_restore(SECURE);
		cm_set_next_eret_context(SECURE);
		SMC_RET0(&tsp_ctx->cpu_ctx);

		/*
		 * This is a request from the secure payload for more arguments
		 * for an ongoing arithmetic operation requested by the
		 * non-secure world. Simply return the arguments from the non-
		 * secure client in the original call.
		 */
	case TSP_GET_ARGS:
		if (ns)
			SMC_RET1(handle, SMC_UNK);

		get_tsp_args(tsp_ctx, x1, x2);
		SMC_RET2(handle, x1, x2);

	case TOS_CALL_COUNT:
		/*
		 * Return the number of service function IDs implemented to
		 * provide service to non-secure
		 */
		SMC_RET1(handle, TSP_NUM_FID);

	case TOS_UID:
		/* Return TSP UID to the caller */
		SMC_UUID_RET(handle, tsp_uuid);

	case TOS_CALL_VERSION:
		/* Return the version of current implementation */
		SMC_RET2(handle, TSP_VERSION_MAJOR, TSP_VERSION_MINOR);

	default:
		break;
	}

	SMC_RET1(handle, SMC_UNK);
}
Exemple #7
0
/*******************************************************************************
 * This function programs EL3 registers and performs other setup to enable entry
 * into the next image after BL31 at the next ERET.
 ******************************************************************************/
void bl31_prepare_next_image_entry()
{
	entry_point_info_t *next_image_info;
	uint32_t scr, image_type;
	cpu_context_t *ctx;
	gp_regs_t *gp_regs;

	/* Determine which image to execute next */
	image_type = bl31_get_next_image_type();

	/*
	 * Setup minimal architectural state of the next highest EL to
	 * allow execution in it immediately upon entering it.
	 */
	bl31_next_el_arch_setup(image_type);

	/* Program EL3 registers to enable entry into the next EL */
	next_image_info = bl31_plat_get_next_image_ep_info(image_type);
	assert(next_image_info);
	assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));

	scr = read_scr();
	scr &= ~SCR_NS_BIT;
	if (image_type == NON_SECURE)
		scr |= SCR_NS_BIT;

	scr &= ~SCR_RW_BIT;
	if ((next_image_info->spsr & (1 << MODE_RW_SHIFT)) ==
				(MODE_RW_64 << MODE_RW_SHIFT))
	{
		scr |= SCR_RW_BIT;
		scr |= SCR_HCE_BIT;
	}
	else
	{
		scr &= ~(SCR_HCE_BIT);
	}

	/*
	 * FIXME: Need a configurable flag when we have hypervisor installed
	 * This is for PSCI CPU_UP api to work correctly
	 * PSCI uses scr.hce to determine the target CPU of CPU_UP
	 * returns to NS world with HYP mode(HCE is set) or SVC mode(HCE is not set)
	 * (refer to psci_set_ns_entry_info() in psci_common.c)
	 * since we don't have hypervisor installed for now, we need to
	 * enter linux with SVC mode.
	 */
	// FIXME: For 64bit kernel, we need return to normal world with EL2
	// Temporary comment out this to enable 64bit kernel smp.
	// Need a method to configure this for 32bit/64bit kernel
	//scr &= ~(SCR_HCE_BIT);

	/*
	 * Tell the context mgmt. library to ensure that SP_EL3 points to
	 * the right context to exit from EL3 correctly.
	 */
	cm_set_el3_eret_context(image_type,
			next_image_info->pc,
			next_image_info->spsr,
			scr);

	/*
	 * Save the args generated in BL2 for the image in the right context
	 * used on its entry
	 */
	ctx = cm_get_context(read_mpidr(), image_type);
	gp_regs = get_gpregs_ctx(ctx);
	memcpy(gp_regs, (void *)&next_image_info->args, sizeof(aapcs64_params_t));

	/* Finally set the next context */
	cm_set_next_eret_context(image_type);
}
Exemple #8
0
void bl31_prepare_k64_entry(void)
{
	entry_point_info_t *next_image_info;
	uint32_t scr, image_type;
	cpu_context_t *ctx;
	gp_regs_t *gp_regs;

	/* Determine which image to execute next */
	image_type = NON_SECURE; //bl31_get_next_image_type();

	/*
	 * Setup minimal architectural state of the next highest EL to
	 * allow execution in it immediately upon entering it.
	 */
	bl31_next_el_arch_setup(image_type);

	/* Program EL3 registers to enable entry into the next EL */
	next_image_info = bl31_plat_get_next_kernel_ep_info(image_type);


	assert(next_image_info);
	assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));


    /* check is set 64bit kernel*/
    printf("next_image_info->spsr = 0x%llx\n", next_image_info->spsr);

	scr = read_scr();
	scr &= ~SCR_NS_BIT;
	if (image_type == NON_SECURE)
		scr |= SCR_NS_BIT;

	scr &= ~SCR_RW_BIT;
	if ((next_image_info->spsr & (1 << MODE_RW_SHIFT)) ==
				(MODE_RW_64 << MODE_RW_SHIFT))
    {
		scr |= SCR_RW_BIT;

        printf("spsr is 64 bit\n");
    }

	scr |= SCR_HCE_BIT;

	/*
	 * Tell the context mgmt. library to ensure that SP_EL3 points to
	 * the right context to exit from EL3 correctly.
	 */
	cm_set_el3_eret_context(image_type,
			next_image_info->pc,
			next_image_info->spsr,
			scr);

	/*
	 * Save the args generated in BL2 for the image in the right context
	 * used on its entry
	 */
	ctx = cm_get_context(read_mpidr(), image_type);
	gp_regs = get_gpregs_ctx(ctx);
	memcpy(gp_regs, (void *)&next_image_info->args, sizeof(aapcs64_params_t));

    printf("Finally set the next context\n");

	/* Finally set the next context */
	cm_set_next_eret_context(image_type);
}
/******************************************************************************
 * PSCI Library interface to initialize the cpu context for the next non
 * secure image during cold boot. The relevant registers in the cpu context
 * need to be retrieved and programmed on return from this interface.
 *****************************************************************************/
void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info)
{
	assert(GET_SECURITY_STATE(next_image_info->h.attr) == NON_SECURE);
	cm_init_my_context(next_image_info);
	cm_prepare_el3_exit(NON_SECURE);
}
/*******************************************************************************
 * The following function initializes the cpu_context for the current CPU
 * for first use, and sets the initial entrypoint state as specified by the
 * entry_point_info structure.
 ******************************************************************************/
void cm_init_my_context(const entry_point_info_t *ep)
{
	cpu_context_t *ctx;
	ctx = cm_get_context(GET_SECURITY_STATE(ep->h.attr));
	cm_init_context_common(ctx, ep);
}