Mistake on this page?
Report an issue in GitHub or email us

uVisor

Warning: uVisor is superseded by the Secure Partition Manager (SPM) defined in the ARM Platform Security Architecture (PSA). uVisor is deprecated as of Mbed OS 5.10, and being replaced by a native PSA-compliant implementation of SPM.

The uVisor is a self-contained software hypervisor that creates independent secure domains on ARM Cortex®-M3 and Cortex®-M4 microcontrollers. It increases resilience against malware and protects secrets from leaking even among different modules of the same application. For more information, download the high-level overview (Download PDF).

Note about interrupts: When the uVisor is enabled, all NVIC APIs are rerouted to the corresponding uVisor vIRQ APIs, which virtualize interrupts. The uVisor interrupt model has the following features:

  • The uVisor owns the interrupt vector table.
  • All ISRs are relocated to SRAM.
  • Code in a box can only change the state of an IRQ (enable it, change its priority and so on) if the box registered that IRQ with uVisor through an IRQ ACL.
  • You can only modify an IRQ that belongs to a box when that box context is active.

Although this behavior is different from that of the original NVIC, it is backward compatible. Legacy code (such as a device HAL) still works after uVisor is enabled.

Usage

  1. Include uVisor library in your application.
  2. Specify capabilities in mandatory access control list.
  3. Add and configure secure boxes, special compartments with exclusive access to peripherals, memories and interrupts.
  4. Create public entry points for your secure boxes.
  5. Compile your application with uVisor enabled.

For detailed usage guides and best practices, see the README

API

https://github.com/ARMmbed/uvisor/blob/master/docs/lib/API.md

Examples

This is a simple example to show how to write a uVisor-secured threaded application with IRQ support. One LED blinks periodically from the public box main thread. A secure box exclusively owns the second LED, which toggles you press the user button.

main.cpp

/*
 * Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "uvisor-lib/uvisor-lib.h"
#include "mbed.h"
#include "main-hw.h"
#include "mem_map.h"

#warning "Warning: uVisor is superseded by the Secure Partition Manager (SPM) defined in the ARM Platform Security Architecture (PSA). \
          uVisor is deprecated as of Mbed OS 5.10, and being replaced by a native PSA-compliant implementation of SPM."

/* Create ACLs for main box. */
MAIN_ACL(g_main_acl);

/* Enable uVisor. */
UVISOR_SET_MODE_ACL(UVISOR_ENABLED, g_main_acl);
UVISOR_SET_PAGE_HEAP(8 * 1024, 5);

static void example_halt_error(THaltError reason, const THaltInfo *halt_info);

UVISOR_PUBLIC_BOX_DEBUG_DRIVER(example_halt_error);

static void example_halt_error(THaltError reason, const THaltInfo *halt_info) {

	const MemMap * map = NULL;
	if (halt_info->bfar) {
		map = memory_map_name(halt_info->bfar);
	}

	printf("\n");
	printf("  Address:           0x%08X\n", halt_info->bfar);
	printf("  Region/Peripheral: %s\n", (map ? map->name : "[not available]"));
	printf("    Base address:    0x%08X\n", (map ? map->base : halt_info->bfar));
	printf("    End address:     0x%08X\n", (map ? map->end : halt_info->bfar));

	return;
}

/* Targets with an ARMv7-M MPU needs this space adjustment to prevent a runtime
 * memory overflow error. The code below has been output directly by uVisor. */
#if defined(TARGET_EFM32GG_STK3700) || defined(TARGET_DISCO_F429ZI)
uint8_t __attribute__((section(".keep.uvisor.bss.boxes"), aligned(32))) __boxes_overhead[8064];
#endif

int main(void)
{
    DigitalOut led(MAIN_LED);

    printf("\r\n***** IRQ blinky uVisor example *****\r\n");

    size_t count = 0;

    while (1) {
        printf("Main loop count: %d\r\n", count++);
        led = !led;

        /* Blink once per second. */
        Thread::wait(500);
    }

    return 0;
}

main-hw.h

/*
 * Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __UVISOR_HELLOWORLD_MAIN_HW_H__
#define __UVISOR_HELLOWORLD_MAIN_HW_H__

#if defined(TARGET_K64F)

#define MAIN_LED           LED1
#define SECURE_LED         LED2
#define LED_ON             false
#define LED_OFF            true
#define SECURE_SWITCH      SW2
#define SECURE_SWITCH_PULL PullUp

#define MAIN_ACL(acl_list_name) \
    static const UvisorBoxAclItem acl_list_name[] = {     \
        {SIM,    sizeof(*SIM),    UVISOR_TACLDEF_PERIPH}, \
        {OSC,    sizeof(*OSC),    UVISOR_TACLDEF_PERIPH}, \
        {MCG,    sizeof(*MCG),    UVISOR_TACLDEF_PERIPH}, \
        {PORTA,  sizeof(*PORTA),  UVISOR_TACLDEF_PERIPH}, \
        {PORTB,  sizeof(*PORTB),  UVISOR_TACLDEF_PERIPH}, \
        {PORTC,  sizeof(*PORTC),  UVISOR_TACLDEF_PERIPH}, \
        {PORTD,  sizeof(*PORTD),  UVISOR_TACLDEF_PERIPH}, \
        {PORTE,  sizeof(*PORTE),  UVISOR_TACLDEF_PERIPH}, \
        {RTC,    sizeof(*RTC),    UVISOR_TACLDEF_PERIPH}, \
        {LPTMR0, sizeof(*LPTMR0), UVISOR_TACLDEF_PERIPH}, \
        {PIT,    sizeof(*PIT),    UVISOR_TACLDEF_PERIPH}, \
        {SMC,    sizeof(*SMC),    UVISOR_TACLDEF_PERIPH}, \
        {UART0,  sizeof(*UART0),  UVISOR_TACLDEF_PERIPH}, \
        {I2C0,   sizeof(*I2C0),   UVISOR_TACLDEF_PERIPH}, \
        {SPI0,   sizeof(*SPI0),   UVISOR_TACLDEF_PERIPH}, \
    }

#elif defined(TARGET_EFM32GG_STK3700)

#define MAIN_LED           LED1
#define SECURE_LED         LED2
#define LED_ON             true
#define LED_OFF            false
#define SECURE_SWITCH      SW0
#define SECURE_SWITCH_PULL PullUp

#define MAIN_ACL(acl_list_name) \
    static const UvisorBoxAclItem acl_list_name[] = {     \
        {CMU,                 sizeof(*CMU),    UVISOR_TACLDEF_PERIPH}, \
        {MSC,                 sizeof(*MSC),    UVISOR_TACLDEF_PERIPH}, \
        {GPIO,                sizeof(*GPIO),   UVISOR_TACLDEF_PERIPH}, \
        {TIMER0,              sizeof(*TIMER0), UVISOR_TACLDEF_PERIPH}, \
        {UART0,               sizeof(*UART0),  UVISOR_TACLDEF_PERIPH}, \
        {(void *) 0x0FE08000, 0x1000,          UVISOR_TACLDEF_PERIPH}, \
        {(void *) 0x42000000, 0x2000000,       UVISOR_TACLDEF_PERIPH}, \
    }

#elif defined(TARGET_DISCO_F429ZI)

#define MAIN_LED           LED1
#define SECURE_LED         LED2
#define LED_ON             true
#define LED_OFF            false
#define SECURE_SWITCH      USER_BUTTON
#define SECURE_SWITCH_PULL PullDown

#define MAIN_ACL(acl_list_name) \
    static const UvisorBoxAclItem acl_list_name[] = {     \
        {GPIOA,               sizeof(*GPIOA),  UVISOR_TACLDEF_PERIPH}, \
        {GPIOB,               sizeof(*GPIOB),  UVISOR_TACLDEF_PERIPH}, \
        {GPIOC,               sizeof(*GPIOC),  UVISOR_TACLDEF_PERIPH}, \
        {GPIOD,               sizeof(*GPIOD),  UVISOR_TACLDEF_PERIPH}, \
        {GPIOE,               sizeof(*GPIOE),  UVISOR_TACLDEF_PERIPH}, \
        {RTC,                 sizeof(*RTC),    UVISOR_TACLDEF_PERIPH}, \
        {TIM5,                sizeof(*TIM5),   UVISOR_TACLDEF_PERIPH}, \
        {USART1,              sizeof(*USART1), UVISOR_TACLDEF_PERIPH}, \
        {I2C1,                sizeof(*I2C1),   UVISOR_TACLDEF_PERIPH}, \
        {SPI1,                sizeof(*SPI1),   UVISOR_TACLDEF_PERIPH}, \
        {RCC,                 sizeof(*RCC),    UVISOR_TACLDEF_PERIPH}, \
        {FLASH,               sizeof(*FLASH),  UVISOR_TACLDEF_PERIPH}, \
        {PWR,                 sizeof(*PWR),    UVISOR_TACLDEF_PERIPH}, \
        {EXTI,                sizeof(*EXTI),   UVISOR_TACLDEF_PERIPH}, \
        {GPIOG,               sizeof(*GPIOG),  UVISOR_TACLDEF_PERIPH}, \
        {SYSCFG,              sizeof(*SYSCFG), UVISOR_TACLDEF_PERIPH}, \
        {(void *) 0x42000000, 0x01000000,      UVISOR_TACLDEF_PERIPH}, \
    }

#else /* Target-specific settings */

#error "Unsupported target. Checkout the README.md file for the list of supported targets for this app."

#endif /* Target-specific settings */

#endif /* __UVISOR_HELLOWORLD_MAIN_HW_H__ */

led.cpp

/*
 * Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "uvisor-lib/uvisor-lib.h"
#include "mbed.h"
#include "main-hw.h"

typedef struct {
    InterruptIn * sw;
    DigitalOut * led;
} my_box_context;

static const UvisorBoxAclItem acl[] = {
};

static void my_box_main(const void *);

/* Box configuration
 * We need 1kB of stack both in the main and interrupt threads as both of them
 * use printf. */
UVISOR_BOX_NAMESPACE(NULL);
UVISOR_BOX_HEAPSIZE(3072);
UVISOR_BOX_MAIN(my_box_main, osPriorityNormal, 1024);
UVISOR_BOX_CONFIG(my_box, acl, 1024, my_box_context);

#define uvisor_ctx ((my_box_context *) __uvisor_ctx)

static void my_box_switch_irq(void)
{
    /* Flip LED state. */
    *uvisor_ctx->led = !*uvisor_ctx->led;

    /* Print LED state on serial port. */
    printf("\r\nPressed switch, printing from interrupt - LED now %s.\r\n\r\n",
           (int) (*uvisor_ctx->led) == LED_ON ? "on" : "off");
}

static void my_box_main(const void *)
{
    /* Allocate a box-specific LED. */
    if (!(uvisor_ctx->led = new DigitalOut(SECURE_LED))) {
        printf("ERROR: failed to allocate memories for LED\r\n");
    } else {
        /* Turn LED off by default */
        *uvisor_ctx->led = LED_OFF;

        /* Allocate a box-specific switch handler. */
        if (!(uvisor_ctx->sw = new InterruptIn(SECURE_SWITCH))) {
            printf("ERROR: failed to allocate memories for switch\r\n");
        } else {
            /* Register handler for switch. */
            uvisor_ctx->sw->mode(SECURE_SWITCH_PULL);
            uvisor_ctx->sw->fall(my_box_switch_irq);

            /* No problem to return here as everything is initialized. */
            return;
        }
        delete uvisor_ctx->led;
    }
}

Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.