Exemplo n.º 1
0
/* Set up default SCR values. */
static void el3_init(void)
{
	uint32_t scr;

	if (get_current_el() != EL3)
		return;

	scr = raw_read_scr_el3();
	/* Default to non-secure EL1 and EL0. */
	scr &= ~(SCR_NS_MASK);
	scr |= SCR_NS_ENABLE;
	/* Disable IRQ, FIQ, and external abort interrupt routing. */
	scr &= ~(SCR_IRQ_MASK | SCR_FIQ_MASK | SCR_EA_MASK);
	scr |= SCR_IRQ_DISABLE | SCR_FIQ_DISABLE | SCR_EA_DISABLE;
	/* Enable HVC */
	scr &= ~(SCR_HVC_MASK);
	scr |= SCR_HVC_ENABLE;
	/* Disable SMC */
	scr &= ~(SCR_SMC_MASK);
	scr |= SCR_SMC_DISABLE;
	/* Disable secure instruction fetches. */
	scr &= ~(SCR_SIF_MASK);
	scr |= SCR_SIF_DISABLE;
	/* All lower exception levels 64-bit by default. */
	scr &= ~(SCR_RW_MASK);
	scr |= SCR_LOWER_AARCH64;
	/* Disable secure EL1 access to secure timer. */
	scr &= ~(SCR_ST_MASK);
	scr |= SCR_ST_DISABLE;
	/* Don't trap on WFE or WFI instructions. */
	scr &= ~(SCR_TWI_MASK | SCR_TWE_MASK);
	scr |= SCR_TWI_DISABLE | SCR_TWE_DISABLE;
	raw_write_scr_el3(scr);
	isb();
}
Exemplo n.º 2
0
void secmon_run(void (*entry)(void *), void *cb_tables)
{
	static struct secmon_runit runit;
	struct cpu_action action = {
		.run = secmon_start,
		.arg = &runit,
	};

	printk(BIOS_SPEW, "payload jump @ %p\n", entry);

	if (get_current_el() != EL3) {
		printk(BIOS_DEBUG, "Secmon Error: Can only be loaded in EL3\n");
		return;
	}

	runit.entry = secmon_load_rmodule();

	if (runit.entry == NULL)
		die("ARM64 Error: secmon load error");

	printk(BIOS_DEBUG, "ARM64: Loaded the el3 monitor...jumping to %p\n",
	       runit.entry);

	fill_secmon_params(&runit.params, entry, cb_tables);

	arch_run_on_all_cpus_but_self_async(&action);
	secmon_start(&runit);
}
Exemplo n.º 3
0
void transition(struct exc_state *exc_state)
{
	uint32_t scr_mask;
	uint64_t hcr_mask;
	uint64_t sctlr;
	uint32_t current_el = get_current_el();

	struct elx_state *elx = &exc_state->elx;
	struct regs *regs = &exc_state->regs;

	uint8_t elx_el = get_el_from_spsr(elx->spsr);

	/*
	 * Policies enforced:
	 * 1. We support only elx --> (elx - 1) transitions
	 * 2. We support transitions to Aarch64 mode only
	 *
	 * If any of the above conditions holds false, then we need a proper way
	 * to update SCR/HCR before removing the checks below
	 */
	if ((current_el - elx_el) != 1)
		die("ARM64 Error: Do not support transition\n");

	if (elx->spsr & SPSR_ERET_32)
		die("ARM64 Error: Do not support eret to Aarch32\n");
	else {
		scr_mask = SCR_LOWER_AARCH64;
		hcr_mask = HCR_LOWER_AARCH64;
	}

	/* SCR: Write to SCR if current EL is EL3 */
	if (current_el == EL3) {
		uint32_t scr = raw_read_scr_el3();
		scr |= scr_mask;
		raw_write_scr_el3(scr);
	}
	/* HCR: Write to HCR if current EL is EL2 */
	else if (current_el == EL2) {
		uint64_t hcr = raw_read_hcr_el2();
		hcr |= hcr_mask;
		raw_write_hcr_el2(hcr);
	}

	/* ELR/SPSR: Write entry point and processor state of program */
	raw_write_elr_current(elx->elr);
	raw_write_spsr_current(elx->spsr);

	/* SCTLR: Initialize EL with selected properties */
	sctlr = raw_read_sctlr(elx_el);
	sctlr &= SCTLR_MASK;
	raw_write_sctlr(sctlr, elx_el);

	/* SP_ELx: Initialize stack pointer */
	raw_write_sp_elx(elx->sp_elx, elx_el);

	/* Eret to the entry point */
	trans_switch(regs);
}
Exemplo n.º 4
0
/*
 * startup_save_cpu_data is used to save register values that need to be setup
 * when a CPU starts booting. This is used by secondary CPUs as well as resume
 * path to directly setup MMU and other related registers.
 */
void startup_save_cpu_data(void)
{
	save_element(MAIR_INDEX, raw_read_mair_current());
	save_element(TCR_INDEX, raw_read_tcr_current());
	save_element(TTBR0_INDEX, raw_read_ttbr0_current());
	save_element(VBAR_INDEX, raw_read_vbar_current());

	if (get_current_el() == EL3)
		save_element(SCR_INDEX, raw_read_scr_el3());

	dcache_clean_by_mva(_arm64_startup_data,
			    NUM_ELEMENTS * PER_ELEMENT_SIZE_BYTES);
}
Exemplo n.º 5
0
static void spintable_enter(void *unused)
{
	struct exc_state state;
	const struct spintable_attributes *attrs;
	int current_el;

	attrs = spintable_get_attributes();

	current_el = get_current_el();

	if (current_el != EL3)
		attrs->entry(attrs->addr);

	memset(&state, 0, sizeof(state));
	state.elx.spsr = get_eret_el(EL2, SPSR_USE_L);

	transition_with_entry(attrs->entry, attrs->addr, &state);
}
Exemplo n.º 6
0
void exc_entry(struct exc_state *exc_state, uint64_t id)
{
	struct elx_state *elx = &exc_state->elx;
	struct regs *regs = &exc_state->regs;
	uint8_t elx_mode, elx_el;

	elx->spsr = raw_read_spsr_current();
	elx_mode = get_mode_from_spsr(elx->spsr);
	elx_el = get_el_from_spsr(elx->spsr);

	if (elx_mode == SPSR_USE_H) {
		if (elx_el == get_current_el())
			regs->sp = (uint64_t)&exc_state[1];
		else
			regs->sp = raw_read_sp_elx(elx_el);
	} else {
		regs->sp = raw_read_sp_el0();
	}

	elx->elr = raw_read_elr_current();

	exc_dispatch(exc_state, id);
}