Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/trusty/trusty/kernel/lib/sm/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 7 kB image not shown  

Quelle  smcall.c

  Sprache: C
 

/*
 * Copyright (c) 2013-2016 Google Inc. All rights reserved
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */


/* Reference:
 * ARM document DEN 0028A: SMC CALLING CONVENTION
 * version: 0.9.0
 */


#include <arch/ops.h>
#include <compiler.h>
#include <debug.h>
#include <err.h>
#include <kernel/mutex.h>
#include <lib/sm.h>
#include <lib/sm/sm_err.h>
#include <lib/sm/smcall.h>
#include <lib/sm/trusty_sched_share_api.h>
#include <lk/init.h>
#include <string.h>
#include <trace.h>
#include <version.h>

#define LOCAL_TRACE 1

static mutex_t smc_table_lock = MUTEX_INITIAL_VALUE(smc_table_lock);

#define TRACE_SMC(msg, args)                                                \
    do {                                                                    \
        u_int _i;                                                           \
        LTRACEF("%s\n", msg);                                               \
        LTRACEF("SMC: 0x%x (%s entity %d function 0x%x)\n", (args)->smc_nr, \
                SMC_IS_FASTCALL(args->smc_nr) ? "Fastcall" : "Stdcall",     \
                SMC_ENTITY(args->smc_nr), SMC_FUNCTION(args->smc_nr));      \
        for (_i = 0; _i < SMC_NUM_PARAMS; _i++)                             \
            LTRACEF("param%d: 0x%x\n", _i, (args)->params[_i]);             \
    } while (0)

long smc_undefined(struct smc32_args* args) {
    TRACE_SMC("Undefined monitor call!", args);
    return SM_ERR_UNDEFINED_SMC;
}

/* Restarts should never be dispatched like this */
static long smc_restart_stdcall(struct smc32_args* args) {
    TRACE_SMC("Unexpected stdcall restart!", args);
    return SM_ERR_UNEXPECTED_RESTART;
}

/*
 * Switch to secure mode and return. This function does no work on its own,
 * but if an interrupt is pending, it will be handled, and can in turn trigger a
 * context switch that will perform other secure work.
 */

static long smc_nop_stdcall(struct smc32_args* args) {
    return 0;
}

/*
 * parameterized nop call handler
 */

static long smc_nop_secure_monitor(struct smc32_args* args) {
    return (!args->params[0]) ? 0 : SM_ERR_UNDEFINED_SMC;
}

static smc32_handler_t sm_stdcall_function_table[] = {
        [SMC_FUNCTION(SMC_SC_RESTART_LAST)] = smc_restart_stdcall,
        [SMC_FUNCTION(SMC_SC_LOCKED_NOP)] = smc_nop_stdcall,
        [SMC_FUNCTION(SMC_SC_RESTART_FIQ)] = smc_restart_stdcall,
        [SMC_FUNCTION(SMC_SC_SCHED_SHARE_REGISTER)] =
                smc_trusty_sched_share_register,
        [SMC_FUNCTION(SMC_SC_SCHED_SHARE_UNREGISTER)] =
                smc_trusty_sched_share_unregister,
        /* reserve slot in table, not called */
        [SMC_FUNCTION(SMC_SC_NOP)] = smc_undefined,
};

static long smc_stdcall_secure_monitor(struct smc32_args* args) {
    u_int function = SMC_FUNCTION(args->smc_nr);
    smc32_handler_t handler_fn = NULL;

    if (function < countof(sm_stdcall_function_table))
        handler_fn = sm_stdcall_function_table[function];

    if (!handler_fn)
        handler_fn = smc_undefined;

    return handler_fn(args);
}

static long smc_fiq_enter(struct smc32_args* args) {
    return sm_intc_fiq_enter();
}

#if !WITH_LIB_SM_MONITOR
static long smc_cpu_suspend(struct smc32_args* args) {
    lk_init_level_all(args->params[0] ? LK_INIT_FLAG_CPU_OFF
                                      : LK_INIT_FLAG_CPU_ENTER_IDLE);

    return 0;
}

static long smc_cpu_resume(struct smc32_args* args) {
    lk_init_level_all(args->params[0] ? LK_INIT_FLAG_CPU_ON
                                      : LK_INIT_FLAG_CPU_EXIT_IDLE);

    return 0;
}
#endif

static long smc_get_version_str(struct smc32_args* args) {
    int32_t index = (int32_t)args->params[0];
    size_t version_len = strlen(lk_version);

    if (index == -1)
        return version_len;

    if (index < 0 || (size_t)index >= version_len)
        return SM_ERR_INVALID_PARAMETERS;

    return lk_version[index];
}

static smc32_handler_t sm_fastcall_function_table[] = {
        [SMC_FUNCTION(SMC_FC_GET_NEXT_IRQ)] = smc_intc_get_next_irq,
        [SMC_FUNCTION(SMC_FC_FIQ_ENTER)] = smc_fiq_enter,
#if !WITH_LIB_SM_MONITOR
        [SMC_FUNCTION(SMC_FC_CPU_SUSPEND)] = smc_cpu_suspend,
        [SMC_FUNCTION(SMC_FC_CPU_RESUME)] = smc_cpu_resume,
#endif
        [SMC_FUNCTION(SMC_FC_GET_VERSION_STR)] = smc_get_version_str,
        [SMC_FUNCTION(SMC_FC_API_VERSION)] = smc_sm_api_version,
        [SMC_FUNCTION(SMC_FC_GET_SMP_MAX_CPUS)] = smc_get_smp_max_cpus,
};

static long smc_fastcall_secure_monitor(struct smc32_args* args) {
    smc32_handler_t func = NULL;
    uint16_t index = SMC_FUNCTION(args->smc_nr);

    if (index < countof(sm_fastcall_function_table)) {
        func = sm_fastcall_function_table[index];
    }

    if (func == NULL) {
        func = smc_undefined;
    }

    return func(args);
}

/* SMC dispatch tables */
smc32_handler_t sm_fastcall_table[SMC_NUM_ENTITIES] = {
        [0 ... SMC_ENTITY_SECURE_MONITOR - 1] = smc_undefined,
        [SMC_ENTITY_SECURE_MONITOR] = smc_fastcall_secure_monitor,
        [SMC_ENTITY_SECURE_MONITOR + 1 ... SMC_NUM_ENTITIES - 1] =
                smc_undefined};

smc32_handler_t sm_nopcall_table[SMC_NUM_ENTITIES] = {
        [0] = smc_nop_secure_monitor,
        [1 ... SMC_NUM_ENTITIES - 1] = smc_undefined};

smc32_handler_t sm_stdcall_table[SMC_NUM_ENTITIES] = {
        [0 ... SMC_ENTITY_SECURE_MONITOR - 1] = smc_undefined,
        [SMC_ENTITY_SECURE_MONITOR] = smc_stdcall_secure_monitor,
        [SMC_ENTITY_SECURE_MONITOR + 1 ... SMC_NUM_ENTITIES - 1] =
                smc_undefined};

status_t sm_register_entity(uint entity_nr, struct smc32_entity* entity) {
    status_t err = NO_ERROR;

    if (entity_nr >= SMC_NUM_ENTITIES)
        return ERR_INVALID_ARGS;

    if (entity_nr >= SMC_ENTITY_RESERVED && entity_nr < SMC_ENTITY_TRUSTED_APP)
        return ERR_NOT_ALLOWED;

    if (!entity)
        return ERR_INVALID_ARGS;

    if (!entity->fastcall_handler && !entity->stdcall_handler &&
        !entity->nopcall_handler)
        return ERR_NOT_VALID;

    mutex_acquire(&smc_table_lock);

    /* Check if entity is already claimed */
    if (sm_fastcall_table[entity_nr] != smc_undefined ||
        sm_nopcall_table[entity_nr] != smc_undefined ||
        sm_stdcall_table[entity_nr] != smc_undefined) {
        err = ERR_ALREADY_EXISTS;
        goto unlock;
    }

    if (entity->fastcall_handler)
        sm_fastcall_table[entity_nr] = entity->fastcall_handler;

    if (entity->nopcall_handler)
        sm_nopcall_table[entity_nr] = entity->nopcall_handler;

    if (entity->stdcall_handler)
        sm_stdcall_table[entity_nr] = entity->stdcall_handler;
unlock:
    mutex_release(&smc_table_lock);
    return err;
}

Messung V0.5 in Prozent
C=91 H=95 G=92

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.