mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-23 04:12:02 +00:00
Add some more MMIO, smcCpuOn
This commit is contained in:
parent
5c24f58402
commit
a800c3c2e7
10 changed files with 204 additions and 3 deletions
56
exosphere/cpu_context.c
Normal file
56
exosphere/cpu_context.c
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "utils.h"
|
||||||
|
#include "pmc.h"
|
||||||
|
|
||||||
|
saved_cpu_context_t g_cpu_contexts[NUM_CPU_CORES] = {0};
|
||||||
|
|
||||||
|
void set_core_entrypoint_and_context_id(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id) {
|
||||||
|
g_cpu_contexts[core].ELR_EL3 = entrypoint_addr;
|
||||||
|
g_cpu_contexts[core].context_id = context_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t cpu_on(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id) {
|
||||||
|
/* Is core valid? */
|
||||||
|
if (core >= NUM_CPU_CORES) {
|
||||||
|
return 0xFFFFFFFE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is core already on? */
|
||||||
|
if (g_cpu_contexts[core].is_active) {
|
||||||
|
return 0xFFFFFFFC;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_core_entrypoint_and_context_id(core, entrypoint_addr, context_id);
|
||||||
|
|
||||||
|
const uint32_t status_masks[NUM_CPU_CORES] = {0x4000, 0x200, 0x400, 0x800};
|
||||||
|
const uint32_t toggle_vals[NUM_CPU_CORES] = {0xE, 0x9, 0xA, 0xB};
|
||||||
|
|
||||||
|
/* Check if we're already in the correct state. */
|
||||||
|
if ((APBDEV_PMC_PWRGATE_STATUS_0 & status_masks[core]) != status_masks[core]) {
|
||||||
|
uint32_t counter = 5001;
|
||||||
|
|
||||||
|
/* Poll the start bit until 0 */
|
||||||
|
while (APBDEV_PMC_PWRGATE_TOGGLE_0 & 0x100) {
|
||||||
|
wait(1);
|
||||||
|
counter--;
|
||||||
|
if (counter < 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Program PWRGATE_TOGGLE with the START bit set to 1, selecting CE[N] */
|
||||||
|
APBDEV_PMC_PWRGATE_TOGGLE_0 = toggle_vals[core] | 0x100;
|
||||||
|
|
||||||
|
/* Poll until we're in the correct state. */
|
||||||
|
counter = 5001;
|
||||||
|
while (counter > 0) {
|
||||||
|
if ((APBDEV_PMC_PWRGATE_STATUS_0 & status_masks[core]) == status_masks[core]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wait(1);
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
54
exosphere/cpu_context.h
Normal file
54
exosphere/cpu_context.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef EXOSPHERE_CPU_CTX_H
|
||||||
|
#define EXOSPHERE_CPU_CTX_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Exosphere CPU Management functionality. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t context_id;
|
||||||
|
uint64_t ELR_EL3;
|
||||||
|
int is_active;
|
||||||
|
int is_saved;
|
||||||
|
uint32_t OSDTRRX_EL1;
|
||||||
|
uint32_t OSDTRTX_EL1;
|
||||||
|
uint32_t MDSCR_EL1;
|
||||||
|
uint32_t OSECCR_EL1;
|
||||||
|
uint32_t MDCCINT_EL1;
|
||||||
|
uint32_t DBGCLAIMCLR_EL1;
|
||||||
|
uint32_t DBGVCR32_EL2;
|
||||||
|
uint32_t SDER32_EL3;
|
||||||
|
uint32_t MDCR_EL2;
|
||||||
|
uint32_t MDCR_EL3;
|
||||||
|
uint64_t DBGBVR0_EL1;
|
||||||
|
uint64_t DBGBCR0_EL1;
|
||||||
|
uint64_t DBGBVR1_EL1;
|
||||||
|
uint64_t DBGBCR1_EL1;
|
||||||
|
uint64_t DBGBVR2_EL1;
|
||||||
|
uint64_t DBGBCR2_EL1;
|
||||||
|
uint64_t DBGBVR3_EL1;
|
||||||
|
uint64_t DBGBCR3_EL1;
|
||||||
|
uint64_t DBGBVR4_EL1;
|
||||||
|
uint64_t DBGBCR4_EL1;
|
||||||
|
uint64_t DBGBVR5_EL1;
|
||||||
|
uint64_t DBGBCR5_EL1;
|
||||||
|
uint64_t DBGWVR0_EL1;
|
||||||
|
uint64_t DBGWCR0_EL1;
|
||||||
|
uint64_t DBGWVR1_EL1;
|
||||||
|
uint64_t DBGWCR1_EL1;
|
||||||
|
uint64_t DBGWVR2_EL1;
|
||||||
|
uint64_t DBGWCR2_EL1;
|
||||||
|
uint64_t DBGWVR3_EL1;
|
||||||
|
uint64_t DBGWCR3_EL1;
|
||||||
|
} saved_cpu_context_t;
|
||||||
|
|
||||||
|
#define NUM_CPU_CORES 4
|
||||||
|
|
||||||
|
void set_core_entrypoint_and_context_id(uint64_t entrypoint_addr, uint64_t context_id);
|
||||||
|
|
||||||
|
uint32_t cpu_on(uint32_t core, uint64_t entrypoint_addr, uint64_t context_id);
|
||||||
|
uint32_t cpu_off(void);
|
||||||
|
uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint_addr, uint64_t context_id);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
11
exosphere/pmc.c
Normal file
11
exosphere/pmc.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "pmc.h"
|
||||||
|
|
||||||
|
volatile void *g_pmc_registers = NULL;
|
||||||
|
|
||||||
|
void set_pmc_address(void *pmc_base) {
|
||||||
|
g_pmc_registers = pmc_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *get_pmc_address(void) {
|
||||||
|
return g_pmc_registers;
|
||||||
|
}
|
14
exosphere/pmc.h
Normal file
14
exosphere/pmc.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef EXOSPHERE_PMC_H
|
||||||
|
#define EXOSPHERE_PMC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Exosphere register definitions for the Tegra X1 PMC. */
|
||||||
|
|
||||||
|
void set_pmc_address(void *pmc_base);
|
||||||
|
void *get_pmc_address(void); /* This is inlined in pmc.c */
|
||||||
|
|
||||||
|
#define APBDEV_PMC_PWRGATE_TOGGLE_0 (*((volatile uint32_t *)(get_pmc_address() + 0x430)))
|
||||||
|
#define APBDEV_PMC_PWRGATE_STATUS_0 (*((volatile uint32_t *)(get_pmc_address() + 0x438)))
|
||||||
|
|
||||||
|
#endif
|
|
@ -7,7 +7,7 @@ void trigger_se_rsa_op(void *buf, unsigned int size);
|
||||||
void trigger_se_aes_op(unsigned int op, char *dst, unsigned int dst_size, const unsigned char *src, unsigned int src_size);
|
void trigger_se_aes_op(unsigned int op, char *dst, unsigned int dst_size, const unsigned char *src, unsigned int src_size);
|
||||||
|
|
||||||
/* Globals for driver. */
|
/* Globals for driver. */
|
||||||
security_engine_t *g_security_engine;
|
volatile security_engine_t *g_security_engine;
|
||||||
|
|
||||||
unsigned int (*g_se_callback)(void);
|
unsigned int (*g_se_callback)(void);
|
||||||
|
|
||||||
|
@ -19,6 +19,11 @@ void set_security_engine_address(security_engine_t *security_engine) {
|
||||||
g_security_engine = security_engine;
|
g_security_engine = security_engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the global security engine pointer. */
|
||||||
|
security_engine_t *get_security_engine_address(void) {
|
||||||
|
return g_security_engine;
|
||||||
|
}
|
||||||
|
|
||||||
void set_security_engine_callback(unsigned int (*callback)(void)) {
|
void set_security_engine_callback(unsigned int (*callback)(void)) {
|
||||||
if (callback == NULL || g_se_callback != NULL) {
|
if (callback == NULL || g_se_callback != NULL) {
|
||||||
panic();
|
panic();
|
||||||
|
|
|
@ -92,7 +92,8 @@ typedef struct security_engine {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void set_security_engine_address(void *security_engine);
|
void set_security_engine_address(security_engine_t *security_engine);
|
||||||
|
security_engine_t *get_security_engine_address(void);
|
||||||
|
|
||||||
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags);
|
void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags);
|
||||||
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags);
|
void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "cpu_context.h"
|
||||||
#include "smc_api.h"
|
#include "smc_api.h"
|
||||||
#include "smc_user.h"
|
#include "smc_user.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
@ -223,5 +224,23 @@ uint32_t smc_get_result(smc_args_t *) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t smc_load_aes_key(smc_args_t *args) {
|
uint32_t smc_load_aes_key(smc_args_t *args) {
|
||||||
smc_wrapper_sync(args, user_load_aes_key);
|
return smc_wrapper_sync(args, user_load_aes_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t smc_cpu_on(smc_args_t *args) {
|
||||||
|
return cpu_on((uint32_t)args->X[1], args->X[2], args->X[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t smc_cpu_off(smc_args_t *args) {
|
||||||
|
return cpu_off();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrapper for cpu_suspend */
|
||||||
|
uint32_t cpu_suspend_wrapper(smc_args_t *args) {
|
||||||
|
return cpu_suspend(args->X[1], args->X[2], args->X[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t smc_cpu_suspend(smc_args_t *args) {
|
||||||
|
return smc_wrapper_sync(args, cpu_suspend_wrapper);
|
||||||
}
|
}
|
18
exosphere/timers.c
Normal file
18
exosphere/timers.c
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
|
volatile void *g_timer_registers = NULL;
|
||||||
|
|
||||||
|
void set_timer_address(void *timer_base) {
|
||||||
|
g_timer_registers = timer_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *get_timer_address(void) {
|
||||||
|
return g_timer_registers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait(uint32_t microseconds) {
|
||||||
|
uint32_t old_time = TIMERUS_CNTR_1US_0;
|
||||||
|
while (TIMERUS_CNTR_1US_0 - old_time <= result) {
|
||||||
|
/* Spin-lock. */
|
||||||
|
}
|
||||||
|
}
|
15
exosphere/timers.h
Normal file
15
exosphere/timers.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef EXOSPHERE_TIMERS_H
|
||||||
|
#define EXOSPHERE_TIMERS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Exosphere driver for the Tegra X1 Timers. */
|
||||||
|
|
||||||
|
void set_timer_address(void *timer_base);
|
||||||
|
void *get_timer_address(void); /* This is inlined in timers.c */
|
||||||
|
|
||||||
|
#define TIMERUS_CNTR_1US_0 (*((volatile uint32_t *)(get_timer_address() + 0x10)))
|
||||||
|
|
||||||
|
void wait(uint32_t microseconds);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,9 +1,17 @@
|
||||||
#ifndef EXOSPHERE_UTILS_H
|
#ifndef EXOSPHERE_UTILS_H
|
||||||
#define EXOSPHERE_UTILS_H
|
#define EXOSPHERE_UTILS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void panic(void);
|
void panic(void);
|
||||||
|
|
||||||
unsigned int read32le(const unsigned char *dword, unsigned int offset);
|
unsigned int read32le(const unsigned char *dword, unsigned int offset);
|
||||||
unsigned int read32be(const unsigned char *dword, unsigned int offset);
|
unsigned int read32be(const unsigned char *dword, unsigned int offset);
|
||||||
|
|
||||||
|
static inline uint32_t get_core_id(void) {
|
||||||
|
uint32_t core_id;
|
||||||
|
asm volatile("mrs %0, MPIDR_EL1" : "=r"(core_id));
|
||||||
|
return core_id;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue