mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-19 15:43:56 +00:00
committed by
Christian Helmuth
parent
74e75d7fbc
commit
941e918b46
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* \brief Parts of platform that are specific to ARM virtualization
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2020-04-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
static inline void prepare_nonsecure_world(unsigned long timer_freq)
|
||||
{
|
||||
using Cpu = Hw::Arm_cpu;
|
||||
|
||||
/* if we are already in HYP mode we're done (depends on u-boot version) */
|
||||
if (Cpu::Psr::M::get(Cpu::Cpsr::read()) == Cpu::Psr::M::HYP)
|
||||
return;
|
||||
|
||||
/* ARM generic timer counter freq needs to be set in secure mode */
|
||||
Cpu::Cntfrq::write(timer_freq);
|
||||
|
||||
/*
|
||||
* enable coprocessor 10 + 11 access and SMP bit access in auxiliary control
|
||||
* register for non-secure world
|
||||
*/
|
||||
Cpu::Nsacr::access_t nsacr = 0;
|
||||
Cpu::Nsacr::Cpnsae10::set(nsacr, 1);
|
||||
Cpu::Nsacr::Cpnsae11::set(nsacr, 1);
|
||||
Cpu::Nsacr::Ns_smp::set(nsacr, 1);
|
||||
Cpu::Nsacr::write(nsacr);
|
||||
|
||||
asm volatile (
|
||||
"msr sp_mon, sp \n" /* copy current mode's sp */
|
||||
"msr lr_mon, lr \n" /* copy current mode's lr */
|
||||
"cps #22 \n" /* switch to monitor mode */
|
||||
);
|
||||
|
||||
Cpu::Scr::access_t scr = 0;
|
||||
Cpu::Scr::Ns::set(scr, 1);
|
||||
Cpu::Scr::Fw::set(scr, 1);
|
||||
Cpu::Scr::Aw::set(scr, 1);
|
||||
Cpu::Scr::Scd::set(scr, 1);
|
||||
Cpu::Scr::Hce::set(scr, 1);
|
||||
Cpu::Scr::Sif::set(scr, 1);
|
||||
Cpu::Scr::write(scr);
|
||||
}
|
||||
|
||||
|
||||
static inline void prepare_hypervisor(Genode::addr_t table)
|
||||
{
|
||||
using Cpu = Hw::Arm_cpu;
|
||||
|
||||
/* set hypervisor exception vector */
|
||||
Cpu::Hvbar::write(Hw::Mm::hypervisor_exception_vector().base);
|
||||
|
||||
/* set hypervisor's translation table */
|
||||
Cpu::Httbr_64bit::write(table);
|
||||
|
||||
Cpu::Ttbcr::access_t ttbcr = 0;
|
||||
Cpu::Ttbcr::Irgn0::set(ttbcr, 1);
|
||||
Cpu::Ttbcr::Orgn0::set(ttbcr, 1);
|
||||
Cpu::Ttbcr::Sh0::set(ttbcr, 2);
|
||||
Cpu::Ttbcr::Eae::set(ttbcr, 1);
|
||||
|
||||
/* prepare MMU usage by hypervisor code */
|
||||
Cpu::Htcr::write(ttbcr);
|
||||
|
||||
/* don't trap on cporocessor 10 + 11, but all others */
|
||||
Cpu::Hcptr::access_t hcptr = 0;
|
||||
Cpu::Hcptr::Tcp<0>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<1>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<2>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<3>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<4>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<5>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<6>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<7>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<8>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<9>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<12>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<13>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tta::set(hcptr, 1);
|
||||
Cpu::Hcptr::write(hcptr);
|
||||
|
||||
enum Memory_attributes {
|
||||
DEVICE_MEMORY = 0x04,
|
||||
NORMAL_MEMORY_UNCACHED = 0x44,
|
||||
NORMAL_MEMORY_CACHED = 0xff,
|
||||
};
|
||||
|
||||
Cpu::Mair0::access_t mair0 = 0;
|
||||
Cpu::Mair0::Attr0::set(mair0, NORMAL_MEMORY_UNCACHED);
|
||||
Cpu::Mair0::Attr1::set(mair0, DEVICE_MEMORY);
|
||||
Cpu::Mair0::Attr2::set(mair0, NORMAL_MEMORY_CACHED);
|
||||
Cpu::Mair0::Attr3::set(mair0, DEVICE_MEMORY);
|
||||
Cpu::Hmair0::write(mair0);
|
||||
|
||||
Cpu::Vtcr::access_t vtcr = ttbcr;
|
||||
Cpu::Vtcr::Sl0::set(vtcr, 1); /* set to starting level 1 */
|
||||
Cpu::Vtcr::write(vtcr);
|
||||
|
||||
Cpu::Sctlr::access_t sctlr = Cpu::Sctlr::read();
|
||||
Cpu::Sctlr::C::set(sctlr, 1);
|
||||
Cpu::Sctlr::I::set(sctlr, 1);
|
||||
Cpu::Sctlr::V::set(sctlr, 1);
|
||||
Cpu::Sctlr::M::set(sctlr, 1);
|
||||
Cpu::Sctlr::Z::set(sctlr, 1);
|
||||
Cpu::Hsctlr::write(sctlr);
|
||||
}
|
@ -11,6 +11,7 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <spec/arm/cortex_a7_a15_virtualization.h>
|
||||
#include <platform.h>
|
||||
|
||||
extern "C" void * _start_setup_stack; /* entrypoint for non-boot CPUs */
|
||||
@ -25,110 +26,6 @@ Bootstrap::Platform::Board::Board()
|
||||
Memory_region { UART_2_MMIO_BASE, UART_2_MMIO_SIZE }) { }
|
||||
|
||||
|
||||
static inline void prepare_nonsecure_world()
|
||||
{
|
||||
using Cpu = Hw::Arm_cpu;
|
||||
|
||||
/* if we are already in HYP mode we're done (depends on u-boot version) */
|
||||
if (Cpu::Psr::M::get(Cpu::Cpsr::read()) == Cpu::Psr::M::HYP)
|
||||
return;
|
||||
|
||||
/* ARM generic timer counter freq needs to be set in secure mode */
|
||||
volatile unsigned long * mct_control = (unsigned long*) 0x101C0240;
|
||||
*mct_control = 0x100;
|
||||
Cpu::Cntfrq::write(24000000);
|
||||
|
||||
/*
|
||||
* enable coprocessor 10 + 11 access and SMP bit access in auxiliary control
|
||||
* register for non-secure world
|
||||
*/
|
||||
Cpu::Nsacr::access_t nsacr = 0;
|
||||
Cpu::Nsacr::Cpnsae10::set(nsacr, 1);
|
||||
Cpu::Nsacr::Cpnsae11::set(nsacr, 1);
|
||||
Cpu::Nsacr::Ns_smp::set(nsacr, 1);
|
||||
Cpu::Nsacr::write(nsacr);
|
||||
|
||||
asm volatile (
|
||||
"msr sp_mon, sp \n" /* copy current mode's sp */
|
||||
"msr lr_mon, lr \n" /* copy current mode's lr */
|
||||
"cps #22 \n" /* switch to monitor mode */
|
||||
);
|
||||
|
||||
Cpu::Scr::access_t scr = 0;
|
||||
Cpu::Scr::Ns::set(scr, 1);
|
||||
Cpu::Scr::Fw::set(scr, 1);
|
||||
Cpu::Scr::Aw::set(scr, 1);
|
||||
Cpu::Scr::Scd::set(scr, 1);
|
||||
Cpu::Scr::Hce::set(scr, 1);
|
||||
Cpu::Scr::Sif::set(scr, 1);
|
||||
Cpu::Scr::write(scr);
|
||||
}
|
||||
|
||||
|
||||
static inline void prepare_hypervisor(Genode::addr_t table)
|
||||
{
|
||||
using Cpu = Hw::Arm_cpu;
|
||||
|
||||
/* set hypervisor exception vector */
|
||||
Cpu::Hvbar::write(Hw::Mm::hypervisor_exception_vector().base);
|
||||
|
||||
/* set hypervisor's translation table */
|
||||
Cpu::Httbr_64bit::write(table);
|
||||
|
||||
Cpu::Ttbcr::access_t ttbcr = 0;
|
||||
Cpu::Ttbcr::Irgn0::set(ttbcr, 1);
|
||||
Cpu::Ttbcr::Orgn0::set(ttbcr, 1);
|
||||
Cpu::Ttbcr::Sh0::set(ttbcr, 2);
|
||||
Cpu::Ttbcr::Eae::set(ttbcr, 1);
|
||||
|
||||
/* prepare MMU usage by hypervisor code */
|
||||
Cpu::Htcr::write(ttbcr);
|
||||
|
||||
/* don't trap on cporocessor 10 + 11, but all others */
|
||||
Cpu::Hcptr::access_t hcptr = 0;
|
||||
Cpu::Hcptr::Tcp<0>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<1>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<2>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<3>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<4>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<5>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<6>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<7>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<8>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<9>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<12>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<13>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tta::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcpac::set(hcptr, 1);
|
||||
Cpu::Hcptr::write(hcptr);
|
||||
|
||||
enum Memory_attributes {
|
||||
DEVICE_MEMORY = 0x04,
|
||||
NORMAL_MEMORY_UNCACHED = 0x44,
|
||||
NORMAL_MEMORY_CACHED = 0xff,
|
||||
};
|
||||
|
||||
Cpu::Mair0::access_t mair0 = 0;
|
||||
Cpu::Mair0::Attr0::set(mair0, NORMAL_MEMORY_UNCACHED);
|
||||
Cpu::Mair0::Attr1::set(mair0, DEVICE_MEMORY);
|
||||
Cpu::Mair0::Attr2::set(mair0, NORMAL_MEMORY_CACHED);
|
||||
Cpu::Mair0::Attr3::set(mair0, DEVICE_MEMORY);
|
||||
Cpu::Hmair0::write(mair0);
|
||||
|
||||
Cpu::Vtcr::access_t vtcr = ttbcr;
|
||||
Cpu::Vtcr::Sl0::set(vtcr, 1); /* set to starting level 1 */
|
||||
Cpu::Vtcr::write(vtcr);
|
||||
|
||||
Cpu::Sctlr::access_t sctlr = Cpu::Sctlr::read();
|
||||
Cpu::Sctlr::C::set(sctlr, 1);
|
||||
Cpu::Sctlr::I::set(sctlr, 1);
|
||||
Cpu::Sctlr::V::set(sctlr, 1);
|
||||
Cpu::Sctlr::M::set(sctlr, 1);
|
||||
Cpu::Sctlr::Z::set(sctlr, 1);
|
||||
Cpu::Hsctlr::write(sctlr);
|
||||
}
|
||||
|
||||
|
||||
static inline void switch_to_supervisor_mode()
|
||||
{
|
||||
using Cpsr = Hw::Arm_cpu::Psr;
|
||||
@ -152,24 +49,24 @@ static inline void switch_to_supervisor_mode()
|
||||
|
||||
unsigned Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
using namespace ::Board;
|
||||
|
||||
static volatile bool primary_cpu = true;
|
||||
static unsigned long timer_freq = 24000000;
|
||||
|
||||
/* locally initialize interrupt controller */
|
||||
::Board::Pic pic { };
|
||||
|
||||
prepare_nonsecure_world();
|
||||
volatile unsigned long * mct_control = (unsigned long*) 0x101C0240;
|
||||
*mct_control = 0x100;
|
||||
prepare_nonsecure_world(timer_freq);
|
||||
prepare_hypervisor((addr_t)core_pd->table_base);
|
||||
switch_to_supervisor_mode();
|
||||
|
||||
Cpu::Sctlr::init();
|
||||
Cpu::Cpsr::init();
|
||||
|
||||
Cpu::invalidate_data_cache();
|
||||
|
||||
/* primary cpu wakes up all others */
|
||||
if (primary_cpu && NR_OF_CPUS > 1) {
|
||||
Cpu::invalidate_data_cache();
|
||||
primary_cpu = false;
|
||||
Cpu::wake_up_all_cpus(&_start_setup_stack);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <platform.h>
|
||||
#include <spec/arm/imx_aipstz.h>
|
||||
#include <spec/arm/cortex_a7_a15_virtualization.h>
|
||||
|
||||
extern "C" void * _start_setup_stack; /* entrypoint for non-boot CPUs */
|
||||
static unsigned char hyp_mode_stack[1024]; /* hypervisor mode's kernel stack */
|
||||
@ -160,108 +161,6 @@ Bootstrap::Platform::Board::Board()
|
||||
}
|
||||
|
||||
|
||||
static inline void prepare_nonsecure_world(unsigned long timer_freq)
|
||||
{
|
||||
using Cpu = Hw::Arm_cpu;
|
||||
|
||||
/* if we are already in HYP mode we're done (depends on u-boot version) */
|
||||
if (Cpu::Psr::M::get(Cpu::Cpsr::read()) == Cpu::Psr::M::HYP)
|
||||
return;
|
||||
|
||||
/* ARM generic timer counter freq needs to be set in secure mode */
|
||||
Cpu::Cntfrq::write(timer_freq);
|
||||
|
||||
/*
|
||||
* enable coprocessor 10 + 11 access and SMP bit access in auxiliary control
|
||||
* register for non-secure world
|
||||
*/
|
||||
Cpu::Nsacr::access_t nsacr = 0;
|
||||
Cpu::Nsacr::Cpnsae10::set(nsacr, 1);
|
||||
Cpu::Nsacr::Cpnsae11::set(nsacr, 1);
|
||||
Cpu::Nsacr::Ns_smp::set(nsacr, 1);
|
||||
Cpu::Nsacr::write(nsacr);
|
||||
|
||||
asm volatile (
|
||||
"msr sp_mon, sp \n" /* copy current mode's sp */
|
||||
"msr lr_mon, lr \n" /* copy current mode's lr */
|
||||
"cps #22 \n" /* switch to monitor mode */
|
||||
);
|
||||
|
||||
Cpu::Scr::access_t scr = 0;
|
||||
Cpu::Scr::Ns::set(scr, 1);
|
||||
Cpu::Scr::Fw::set(scr, 1);
|
||||
Cpu::Scr::Aw::set(scr, 1);
|
||||
Cpu::Scr::Scd::set(scr, 1);
|
||||
Cpu::Scr::Hce::set(scr, 1);
|
||||
Cpu::Scr::Sif::set(scr, 1);
|
||||
Cpu::Scr::write(scr);
|
||||
}
|
||||
|
||||
|
||||
static inline void prepare_hypervisor(Genode::addr_t table)
|
||||
{
|
||||
using Cpu = Hw::Arm_cpu;
|
||||
|
||||
/* set hypervisor exception vector */
|
||||
Cpu::Hvbar::write(Hw::Mm::hypervisor_exception_vector().base);
|
||||
|
||||
/* set hypervisor's translation table */
|
||||
Cpu::Httbr_64bit::write(table);
|
||||
|
||||
Cpu::Ttbcr::access_t ttbcr = 0;
|
||||
Cpu::Ttbcr::Irgn0::set(ttbcr, 1);
|
||||
Cpu::Ttbcr::Orgn0::set(ttbcr, 1);
|
||||
Cpu::Ttbcr::Sh0::set(ttbcr, 2);
|
||||
Cpu::Ttbcr::Eae::set(ttbcr, 1);
|
||||
|
||||
/* prepare MMU usage by hypervisor code */
|
||||
Cpu::Htcr::write(ttbcr);
|
||||
|
||||
/* don't trap on cporocessor 10 + 11, but all others */
|
||||
Cpu::Hcptr::access_t hcptr = 0;
|
||||
Cpu::Hcptr::Tcp<0>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<1>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<2>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<3>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<4>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<5>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<6>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<7>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<8>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<9>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<12>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<13>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tta::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcpac::set(hcptr, 1);
|
||||
Cpu::Hcptr::write(hcptr);
|
||||
|
||||
enum Memory_attributes {
|
||||
DEVICE_MEMORY = 0x04,
|
||||
NORMAL_MEMORY_UNCACHED = 0x44,
|
||||
NORMAL_MEMORY_CACHED = 0xff,
|
||||
};
|
||||
|
||||
Cpu::Mair0::access_t mair0 = 0;
|
||||
Cpu::Mair0::Attr0::set(mair0, NORMAL_MEMORY_UNCACHED);
|
||||
Cpu::Mair0::Attr1::set(mair0, DEVICE_MEMORY);
|
||||
Cpu::Mair0::Attr2::set(mair0, NORMAL_MEMORY_CACHED);
|
||||
Cpu::Mair0::Attr3::set(mair0, DEVICE_MEMORY);
|
||||
Cpu::Hmair0::write(mair0);
|
||||
|
||||
Cpu::Vtcr::access_t vtcr = ttbcr;
|
||||
Cpu::Vtcr::Sl0::set(vtcr, 1); /* set to starting level 1 */
|
||||
Cpu::Vtcr::write(vtcr);
|
||||
|
||||
Cpu::Sctlr::access_t sctlr = Cpu::Sctlr::read();
|
||||
Cpu::Sctlr::C::set(sctlr, 1);
|
||||
Cpu::Sctlr::I::set(sctlr, 1);
|
||||
Cpu::Sctlr::V::set(sctlr, 1);
|
||||
Cpu::Sctlr::M::set(sctlr, 1);
|
||||
Cpu::Sctlr::Z::set(sctlr, 1);
|
||||
Cpu::Hsctlr::write(sctlr);
|
||||
}
|
||||
|
||||
|
||||
static inline void switch_to_supervisor_mode()
|
||||
{
|
||||
using Cpsr = Hw::Arm_cpu::Psr;
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include <platform.h>
|
||||
#include <spec/arm/cortex_a7_a15_virtualization.h>
|
||||
|
||||
extern "C" void * _start_setup_stack; /* entrypoint for non-boot CPUs */
|
||||
static unsigned char hyp_mode_stack[1024]; /* hypervisor mode's kernel stack */
|
||||
@ -30,108 +31,6 @@ Bootstrap::Platform::Board::Board()
|
||||
Cpu_mmio::IRQ_CONTROLLER_VT_CTRL_SIZE }) {}
|
||||
|
||||
|
||||
static inline void prepare_nonsecure_world(unsigned long timer_freq)
|
||||
{
|
||||
using Cpu = Hw::Arm_cpu;
|
||||
|
||||
/* if we are already in HYP mode we're done (depends on u-boot version) */
|
||||
if (Cpu::Psr::M::get(Cpu::Cpsr::read()) == Cpu::Psr::M::HYP)
|
||||
return;
|
||||
|
||||
/* ARM generic timer counter freq needs to be set in secure mode */
|
||||
Cpu::Cntfrq::write(timer_freq);
|
||||
|
||||
/*
|
||||
* enable coprocessor 10 + 11 access and SMP bit access in auxiliary control
|
||||
* register for non-secure world
|
||||
*/
|
||||
Cpu::Nsacr::access_t nsacr = 0;
|
||||
Cpu::Nsacr::Cpnsae10::set(nsacr, 1);
|
||||
Cpu::Nsacr::Cpnsae11::set(nsacr, 1);
|
||||
Cpu::Nsacr::Ns_smp::set(nsacr, 1);
|
||||
Cpu::Nsacr::write(nsacr);
|
||||
|
||||
asm volatile (
|
||||
"msr sp_mon, sp \n" /* copy current mode's sp */
|
||||
"msr lr_mon, lr \n" /* copy current mode's lr */
|
||||
"cps #22 \n" /* switch to monitor mode */
|
||||
);
|
||||
|
||||
Cpu::Scr::access_t scr = 0;
|
||||
Cpu::Scr::Ns::set(scr, 1);
|
||||
Cpu::Scr::Fw::set(scr, 1);
|
||||
Cpu::Scr::Aw::set(scr, 1);
|
||||
Cpu::Scr::Scd::set(scr, 1);
|
||||
Cpu::Scr::Hce::set(scr, 1);
|
||||
Cpu::Scr::Sif::set(scr, 1);
|
||||
Cpu::Scr::write(scr);
|
||||
}
|
||||
|
||||
|
||||
static inline void prepare_hypervisor(Genode::addr_t table)
|
||||
{
|
||||
using Cpu = Hw::Arm_cpu;
|
||||
|
||||
/* set hypervisor exception vector */
|
||||
Cpu::Hvbar::write(Hw::Mm::hypervisor_exception_vector().base);
|
||||
|
||||
/* set hypervisor's translation table */
|
||||
Cpu::Httbr_64bit::write(table);
|
||||
|
||||
Cpu::Ttbcr::access_t ttbcr = 0;
|
||||
Cpu::Ttbcr::Irgn0::set(ttbcr, 1);
|
||||
Cpu::Ttbcr::Orgn0::set(ttbcr, 1);
|
||||
Cpu::Ttbcr::Sh0::set(ttbcr, 2);
|
||||
Cpu::Ttbcr::Eae::set(ttbcr, 1);
|
||||
|
||||
/* prepare MMU usage by hypervisor code */
|
||||
Cpu::Htcr::write(ttbcr);
|
||||
|
||||
/* don't trap on cporocessor 10 + 11, but all others */
|
||||
Cpu::Hcptr::access_t hcptr = 0;
|
||||
Cpu::Hcptr::Tcp<0>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<1>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<2>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<3>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<4>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<5>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<6>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<7>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<8>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<9>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<12>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcp<13>::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tta::set(hcptr, 1);
|
||||
Cpu::Hcptr::Tcpac::set(hcptr, 1);
|
||||
Cpu::Hcptr::write(hcptr);
|
||||
|
||||
enum Memory_attributes {
|
||||
DEVICE_MEMORY = 0x04,
|
||||
NORMAL_MEMORY_UNCACHED = 0x44,
|
||||
NORMAL_MEMORY_CACHED = 0xff,
|
||||
};
|
||||
|
||||
Cpu::Mair0::access_t mair0 = 0;
|
||||
Cpu::Mair0::Attr0::set(mair0, NORMAL_MEMORY_UNCACHED);
|
||||
Cpu::Mair0::Attr1::set(mair0, DEVICE_MEMORY);
|
||||
Cpu::Mair0::Attr2::set(mair0, NORMAL_MEMORY_CACHED);
|
||||
Cpu::Mair0::Attr3::set(mair0, DEVICE_MEMORY);
|
||||
Cpu::Hmair0::write(mair0);
|
||||
|
||||
Cpu::Vtcr::access_t vtcr = ttbcr;
|
||||
Cpu::Vtcr::Sl0::set(vtcr, 1); /* set to starting level 1 */
|
||||
Cpu::Vtcr::write(vtcr);
|
||||
|
||||
Cpu::Sctlr::access_t sctlr = Cpu::Sctlr::read();
|
||||
Cpu::Sctlr::C::set(sctlr, 1);
|
||||
Cpu::Sctlr::I::set(sctlr, 1);
|
||||
Cpu::Sctlr::V::set(sctlr, 1);
|
||||
Cpu::Sctlr::M::set(sctlr, 1);
|
||||
Cpu::Sctlr::Z::set(sctlr, 1);
|
||||
Cpu::Hsctlr::write(sctlr);
|
||||
}
|
||||
|
||||
|
||||
static inline void switch_to_supervisor_mode()
|
||||
{
|
||||
using Cpsr = Hw::Arm_cpu::Psr;
|
||||
@ -146,7 +45,7 @@ static inline void switch_to_supervisor_mode()
|
||||
"msr lr_svc, lr \n" /* copy current mode's lr */
|
||||
"adr lr, 1f \n" /* load exception return address */
|
||||
"msr elr_hyp, lr \n" /* copy current mode's lr to hyp lr */
|
||||
"mov sp, %[stack] \n" /* copy to hyp stack pointer */
|
||||
"mov sp, %[stack] \n" /* copy to hyp stack pointer */
|
||||
"msr spsr_cxfs, %[cpsr] \n" /* set psr for supervisor mode */
|
||||
"eret \n" /* exception return */
|
||||
"1:":: [cpsr] "r" (cpsr), [stack] "r" (&hyp_mode_stack));
|
||||
@ -156,7 +55,6 @@ static inline void switch_to_supervisor_mode()
|
||||
unsigned Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
static volatile bool primary_cpu = true;
|
||||
static unsigned long timer_freq = Cpu::Cntfrq::read();
|
||||
|
||||
/* locally initialize interrupt controller */
|
||||
::Board::Pic pic { };
|
||||
@ -168,7 +66,6 @@ unsigned Bootstrap::Platform::enable_mmu()
|
||||
Cpu::wake_up_all_cpus(&_start_setup_stack);
|
||||
}
|
||||
|
||||
if (false) prepare_nonsecure_world(timer_freq);
|
||||
prepare_hypervisor((addr_t)core_pd->table_base);
|
||||
switch_to_supervisor_mode();
|
||||
|
||||
|
74
repos/base-hw/src/core/spec/arm/virtualization/board.h
Normal file
74
repos/base-hw/src/core/spec/arm/virtualization/board.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* \brief Board wirh ARM virtualization support
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-11-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__SPEC__ARM__VIRTUALIZATION__BOARD_H_
|
||||
#define _CORE__SPEC__ARM__VIRTUALIZATION__BOARD_H_
|
||||
|
||||
#include <translation_table.h>
|
||||
#include <kernel/configuration.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
namespace Board {
|
||||
using Vm_page_table = Hw::Level_1_stage_2_translation_table;
|
||||
using Vm_page_table_array =
|
||||
Vm_page_table::Allocator::Array<Kernel::DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
struct Vcpu_context;
|
||||
|
||||
using Vm_state = Genode::Vm_state;
|
||||
};
|
||||
|
||||
namespace Kernel {
|
||||
class Cpu;
|
||||
class Vm;
|
||||
};
|
||||
|
||||
struct Board::Vcpu_context
|
||||
{
|
||||
struct Vm_irq : Kernel::Irq
|
||||
{
|
||||
Vm_irq(unsigned const irq, Kernel::Cpu &);
|
||||
virtual ~Vm_irq() {};
|
||||
|
||||
virtual void handle(Kernel::Cpu &, Kernel::Vm & vm, unsigned irq);
|
||||
void occurred() override;
|
||||
};
|
||||
|
||||
|
||||
struct Pic_maintainance_irq : Vm_irq
|
||||
{
|
||||
Pic_maintainance_irq(Kernel::Cpu &);
|
||||
|
||||
void handle(Kernel::Cpu &, Kernel::Vm &, unsigned) override { }
|
||||
};
|
||||
|
||||
|
||||
struct Virtual_timer_irq
|
||||
{
|
||||
Vm_irq irq;
|
||||
|
||||
Virtual_timer_irq(Kernel::Cpu &);
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
};
|
||||
|
||||
Vcpu_context(Kernel::Cpu & cpu)
|
||||
: pic_irq(cpu), vtimer_irq(cpu) {}
|
||||
|
||||
Pic::Virtual_context pic {};
|
||||
Pic_maintainance_irq pic_irq;
|
||||
Virtual_timer_irq vtimer_irq;
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__ARM__VIRTUALIZATION__BOARD_H_ */
|
@ -101,6 +101,11 @@ _host_to_vm:
|
||||
add r1, r0, #4
|
||||
vldm r1!, {d0-d15}
|
||||
vldm r1!, {d16-d31}
|
||||
ldm r1!, {r2-r7}
|
||||
mcrr p15, 4, r2, r3, c14 /* write cntvoff */
|
||||
mcrr p15, 3, r4, r5, c14 /* write cntv_cval */
|
||||
mcr p15, 0, r6, c14, c3, 1 /* write cntv_ctl */
|
||||
mcr p15, 0, r7, c14, c1, 0 /* write cntkctl */
|
||||
ldmia sp, {r0-r12} /* load vm's r0-r12 */
|
||||
eret
|
||||
|
||||
@ -111,9 +116,7 @@ _vm_to_host:
|
||||
mcrr p15, 6, r1, r1, c2 /* write VTTBR */
|
||||
mcr p15, 4, r1, c1, c1, 0 /* write HCR register */
|
||||
mcr p15, 4, r1, c1, c1, 3 /* write HSTR register */
|
||||
mov r1, #0xf
|
||||
lsl r1, #20
|
||||
mcr p15, 0, r1, c1, c0, 2 /* write CPACR */
|
||||
|
||||
mrs r1, ELR_hyp /* read ip */
|
||||
mrs r2, spsr /* read cpsr */
|
||||
mrc p15, 0, r3, c1, c0, 0 /* read SCTRL */
|
||||
@ -124,21 +127,29 @@ _vm_to_host:
|
||||
mrc p15, 0, r8, c2, c0, 2 /* read TTBRC */
|
||||
mrc p15, 0, r9, c2, c0, 0 /* read TTBR0 */
|
||||
mrc p15, 0, r10, c2, c0, 1 /* read TTBR1 */
|
||||
mrc p15, 0, r11, c10, c2, 0 /* read PRRR */
|
||||
mrc p15, 0, r12, c10, c2, 1 /* read NMRR */
|
||||
add r0, sp, #40*4 /* offset SCTRL */
|
||||
stm r0!, {r3-r10}
|
||||
add r0, r0, #3*4
|
||||
mrc p15, 0, r3, c5, c0, 0 /* read DFSR */
|
||||
mrc p15, 0, r4, c5, c0, 1 /* read IFSR */
|
||||
mrc p15, 0, r5, c5, c1, 0 /* read ADFSR */
|
||||
mrc p15, 0, r6, c5, c1, 1 /* read AIFSR */
|
||||
mrc p15, 0, r7, c6, c0, 0 /* read DFAR */
|
||||
mrc p15, 0, r8, c6, c0, 2 /* read IFAR */
|
||||
mrc p15, 0, r9, c13, c0, 1 /* read CIDR */
|
||||
mrc p15, 0, r10, c13, c0, 2 /* read TLS1 */
|
||||
mrc p15, 0, r11, c13, c0, 3 /* read TLS2 */
|
||||
mrc p15, 0, r12, c13, c0, 4 /* read TLS3 */
|
||||
stm r0!, {r3-r12}
|
||||
add r0, r0, #4
|
||||
mrc p15, 0, r3, c3, c0, 0 /* read DACR */
|
||||
mrc p15, 0, r4, c5, c0, 0 /* read DFSR */
|
||||
mrc p15, 0, r5, c5, c0, 1 /* read IFSR */
|
||||
mrc p15, 0, r6, c5, c1, 0 /* read ADFSR */
|
||||
mrc p15, 0, r7, c5, c1, 1 /* read AIFSR */
|
||||
mrc p15, 0, r8, c6, c0, 0 /* read DFAR */
|
||||
mrc p15, 0, r9, c6, c0, 2 /* read IFAR */
|
||||
mrc p15, 0, r10, c13, c0, 1 /* read CIDR */
|
||||
mrc p15, 0, r11, c13, c0, 2 /* read TLS1 */
|
||||
mrc p15, 0, r12, c13, c0, 3 /* read TLS2 */
|
||||
stm r0!, {r3-r12}
|
||||
mrc p15, 0, r3, c13, c0, 4 /* read TLS3 */
|
||||
mrc p15, 0, r4, c1, c0, 2 /* read CPACR */
|
||||
stm r0!, {r3, r4}
|
||||
|
||||
mov r3, #0xf
|
||||
lsl r3, #20
|
||||
mcr p15, 0, r3, c1, c0, 2 /* write CPACR */
|
||||
|
||||
mov r3, #1 /* clear fpu exception state */
|
||||
lsl r3, #30
|
||||
vmsr fpexc, r3
|
||||
@ -146,6 +157,11 @@ _vm_to_host:
|
||||
stmia r0!, {r4}
|
||||
vstm r0!, {d0-d15}
|
||||
vstm r0!, {d16-d31}
|
||||
mrrc p15, 4, r3, r4, c14 /* read cntvoff */
|
||||
mrrc p15, 3, r5, r6, c14 /* read cntv_cval */
|
||||
mrc p15, 0, r7, c14, c3, 1 /* write cntv_ctl */
|
||||
mrc p15, 0, r8, c14, c1, 0 /* write cntkctl */
|
||||
stm r0!, {r3-r8}
|
||||
add r0, sp, #13*4
|
||||
ldr r3, _vt_host_context_ptr
|
||||
ldr sp, [r3]
|
||||
|
@ -55,139 +55,42 @@ struct Host_context {
|
||||
} vt_host_context;
|
||||
|
||||
|
||||
struct Kernel::Vm_irq : Kernel::Irq
|
||||
Board::Vcpu_context::Vm_irq::Vm_irq(unsigned const irq, Cpu & cpu)
|
||||
: Kernel::Irq(irq, cpu.irq_pool())
|
||||
{ }
|
||||
|
||||
|
||||
void Board::Vcpu_context::Vm_irq::handle(Cpu &, Vm & vm, unsigned irq) {
|
||||
vm.inject_irq(irq); }
|
||||
|
||||
|
||||
void Board::Vcpu_context::Vm_irq::occurred()
|
||||
{
|
||||
Vm_irq(unsigned const irq)
|
||||
:
|
||||
Kernel::Irq(irq, cpu_pool().executing_cpu().irq_pool())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* A VM interrupt gets injected into the VM scheduled on the current CPU
|
||||
*/
|
||||
void occurred() override
|
||||
{
|
||||
Cpu_job & job = cpu_pool().executing_cpu().scheduled_job();
|
||||
Vm *vm = dynamic_cast<Vm*>(&job);
|
||||
if (!vm)
|
||||
Genode::raw("VM timer interrupt while VM is not runnning!");
|
||||
else
|
||||
vm->inject_irq(_irq_nr);
|
||||
}
|
||||
};
|
||||
Cpu & cpu = Kernel::cpu_pool().executing_cpu();
|
||||
Vm *vm = dynamic_cast<Vm*>(&cpu.scheduled_job());
|
||||
if (!vm) Genode::raw("VM interrupt while VM is not runnning!");
|
||||
else handle(cpu, *vm, _irq_nr);
|
||||
}
|
||||
|
||||
|
||||
struct Kernel::Virtual_pic : Genode::Mmio
|
||||
Board::Vcpu_context::Pic_maintainance_irq::Pic_maintainance_irq(Cpu & cpu)
|
||||
: Board::Vcpu_context::Vm_irq(Board::VT_MAINTAINANCE_IRQ, cpu) {
|
||||
//FIXME Irq::enable only enables caller cpu
|
||||
cpu.pic().unmask(_irq_nr, cpu.id()); }
|
||||
|
||||
Board::Vcpu_context::Virtual_timer_irq::Virtual_timer_irq(Cpu & cpu)
|
||||
: irq(Board::VT_TIMER_IRQ, cpu) {}
|
||||
|
||||
|
||||
void Board::Vcpu_context::Virtual_timer_irq::enable() { irq.enable(); }
|
||||
|
||||
|
||||
void Board::Vcpu_context::Virtual_timer_irq::disable()
|
||||
{
|
||||
struct Gich_hcr : Register<0x00, 32> { };
|
||||
struct Gich_vmcr : Register<0x08, 32> { };
|
||||
struct Gich_misr : Register<0x10, 32> { };
|
||||
struct Gich_eisr0 : Register<0x20, 32> { };
|
||||
struct Gich_elrsr0 : Register<0x30, 32> { };
|
||||
struct Gich_apr : Register<0xf0, 32> { };
|
||||
|
||||
template <unsigned SLOT>
|
||||
struct Gich_lr : Register<0x100 + SLOT*4, 32> { };
|
||||
|
||||
Vm_irq irq { Board::VT_MAINTAINANCE_IRQ };
|
||||
|
||||
Virtual_pic()
|
||||
: Genode::Mmio(Genode::Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_VT_CTRL_BASE)) { }
|
||||
|
||||
static Virtual_pic& pic()
|
||||
{
|
||||
static Virtual_pic vgic;
|
||||
return vgic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the virtual interrupt controller state to VM state
|
||||
*/
|
||||
static void save (Genode::Vm_state &s)
|
||||
{
|
||||
s.gic_hcr = pic().read<Gich_hcr >();
|
||||
s.gic_misr = pic().read<Gich_misr >();
|
||||
s.gic_vmcr = pic().read<Gich_vmcr >();
|
||||
s.gic_apr = pic().read<Gich_apr >();
|
||||
s.gic_eisr = pic().read<Gich_eisr0 >();
|
||||
s.gic_elrsr0 = pic().read<Gich_elrsr0>();
|
||||
s.gic_lr[0] = pic().read<Gich_lr<0> >();
|
||||
s.gic_lr[1] = pic().read<Gich_lr<1> >();
|
||||
s.gic_lr[2] = pic().read<Gich_lr<2> >();
|
||||
s.gic_lr[3] = pic().read<Gich_lr<3> >();
|
||||
|
||||
/* disable virtual PIC CPU interface */
|
||||
pic().write<Gich_hcr>(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the virtual interrupt controller state from VM state
|
||||
*/
|
||||
static void load (Genode::Vm_state &s)
|
||||
{
|
||||
pic().write<Gich_hcr >(s.gic_hcr );
|
||||
pic().write<Gich_misr >(s.gic_misr);
|
||||
pic().write<Gich_vmcr >(s.gic_vmcr);
|
||||
pic().write<Gich_apr >(s.gic_apr );
|
||||
pic().write<Gich_elrsr0>(s.gic_elrsr0);
|
||||
pic().write<Gich_lr<0> >(s.gic_lr[0]);
|
||||
pic().write<Gich_lr<1> >(s.gic_lr[1]);
|
||||
pic().write<Gich_lr<2> >(s.gic_lr[2]);
|
||||
pic().write<Gich_lr<3> >(s.gic_lr[3]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Kernel::Virtual_timer
|
||||
{
|
||||
Vm_irq irq { Board::VT_TIMER_IRQ };
|
||||
|
||||
/**
|
||||
* Return virtual timer object of currently executing cpu
|
||||
*
|
||||
* FIXME: remove this when re-designing the CPU (issue #1252)
|
||||
*/
|
||||
static Virtual_timer& timer()
|
||||
{
|
||||
static Virtual_timer timer[NR_OF_CPUS];
|
||||
return timer[Cpu::executing_id()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the virtual timer, thereby it disables its interrupt
|
||||
*/
|
||||
static void reset()
|
||||
{
|
||||
timer().irq.disable();
|
||||
asm volatile("mcr p15, 0, %0, c14, c3, 1 \n"
|
||||
"mcr p15, 0, %0, c14, c3, 0" :: "r" (0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the virtual timer state to VM state
|
||||
*/
|
||||
static void save(Genode::Vm_state &s)
|
||||
{
|
||||
asm volatile("mrc p15, 0, %0, c14, c3, 0 \n"
|
||||
"mrc p15, 0, %1, c14, c3, 1" :
|
||||
"=r" (s.timer_val), "=r" (s.timer_ctrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the virtual timer state from VM state
|
||||
*/
|
||||
static void load(Genode::Vm_state &s)
|
||||
{
|
||||
if (s.timer_irq) timer().irq.enable();
|
||||
|
||||
asm volatile("mcr p15, 0, %0, c14, c3, 1 \n"
|
||||
"mcr p15, 0, %1, c14, c3, 0 \n"
|
||||
"mcr p15, 0, %2, c14, c3, 1" ::
|
||||
"r" (0),
|
||||
"r" (s.timer_val), "r" (s.timer_ctrl));
|
||||
}
|
||||
};
|
||||
|
||||
irq.disable();
|
||||
asm volatile("mcr p15, 0, %0, c14, c3, 1" :: "r" (0));
|
||||
asm volatile("mcr p15, 0, %0, c14, c1, 0" :: "r" (0b11));
|
||||
}
|
||||
|
||||
using Vmid_allocator = Genode::Bit_allocator<256>;
|
||||
|
||||
@ -217,7 +120,6 @@ Kernel::Vm::Vm(unsigned, /* FIXME: smp support */
|
||||
_vcpu_context(cpu_pool().primary_cpu())
|
||||
{
|
||||
affinity(cpu_pool().primary_cpu());
|
||||
Virtual_pic::pic().irq.enable();
|
||||
|
||||
vt_host_context.sp = _cpu->stack_start();
|
||||
vt_host_context.ttbr0 = Cpu::Ttbr0_64bit::read();
|
||||
@ -235,12 +137,9 @@ Kernel::Vm::~Vm() { alloc().free(_id); }
|
||||
|
||||
void Kernel::Vm::exception(Cpu & cpu)
|
||||
{
|
||||
Virtual_timer::save(_state);
|
||||
|
||||
switch(_state.cpu_exception) {
|
||||
case Genode::Cpu_state::INTERRUPT_REQUEST:
|
||||
case Genode::Cpu_state::FAST_INTERRUPT_REQUEST:
|
||||
_state.gic_irq = Board::VT_MAINTAINANCE_IRQ;
|
||||
_interrupt(cpu.id());
|
||||
break;
|
||||
default:
|
||||
@ -248,13 +147,18 @@ void Kernel::Vm::exception(Cpu & cpu)
|
||||
_context.submit(1);
|
||||
}
|
||||
|
||||
Virtual_pic::save(_state);
|
||||
Virtual_timer::reset();
|
||||
if (cpu.pic().ack_virtual_irq(_vcpu_context.pic))
|
||||
inject_irq(Board::VT_MAINTAINANCE_IRQ);
|
||||
_vcpu_context.vtimer_irq.disable();
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Vm::proceed(Cpu &)
|
||||
void Kernel::Vm::proceed(Cpu & cpu)
|
||||
{
|
||||
if (_state.timer.irq) _vcpu_context.vtimer_irq.enable();
|
||||
|
||||
cpu.pic().insert_virtual_irq(_vcpu_context.pic, _state.irqs.virtual_irq);
|
||||
|
||||
/*
|
||||
* the following values have to be enforced by the hypervisor
|
||||
*/
|
||||
@ -266,11 +170,8 @@ void Kernel::Vm::proceed(Cpu &)
|
||||
* to transport the HSTR and HCR register descriptions into the assembler
|
||||
* path in a dense way
|
||||
*/
|
||||
_state.hsr = Cpu::Hstr::init();
|
||||
_state.hpfar = Cpu::Hcr::init();
|
||||
|
||||
Virtual_pic::load(_state);
|
||||
Virtual_timer::load(_state);
|
||||
_state.esr_el2 = Cpu::Hstr::init();
|
||||
_state.hpfar_el2 = Cpu::Hcr::init();
|
||||
|
||||
hypervisor_enter_vm(_state);
|
||||
}
|
||||
@ -278,7 +179,7 @@ void Kernel::Vm::proceed(Cpu &)
|
||||
|
||||
void Vm::inject_irq(unsigned irq)
|
||||
{
|
||||
_state.gic_irq = irq;
|
||||
_state.irqs.last_irq = irq;
|
||||
pause();
|
||||
_context.submit(1);
|
||||
}
|
||||
|
@ -14,28 +14,20 @@
|
||||
#ifndef _CORE__SPEC__ARNDALE__BOARD_H_
|
||||
#define _CORE__SPEC__ARNDALE__BOARD_H_
|
||||
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
#include <spec/arm/virtualization/gicv2.h>
|
||||
#include <hw/spec/arm/arndale_board.h>
|
||||
#include <spec/arm/exynos_mct.h>
|
||||
#include <spec/arm/cpu/vm_state_virtualization.h>
|
||||
#include <translation_table.h>
|
||||
#include <kernel/configuration.h>
|
||||
#include <spec/arm/virtualization/board.h>
|
||||
|
||||
namespace Kernel { class Cpu; }
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Arndale_board;
|
||||
|
||||
using Pic = Hw::Gicv2;
|
||||
struct Virtual_local_pic {};
|
||||
|
||||
enum { VCPU_MAX = 1 };
|
||||
|
||||
using Vm_state = Genode::Vm_state;
|
||||
using Vm_page_table = Hw::Level_1_stage_2_translation_table;
|
||||
using Vm_page_table_array =
|
||||
Vm_page_table::Allocator::Array<Kernel::DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
struct Vcpu_context { Vcpu_context(Kernel::Cpu &) {} };
|
||||
}
|
||||
|
||||
#endif /* _CORE__SPEC__ARNDALE__BOARD_H_ */
|
||||
|
@ -41,18 +41,10 @@ class Genode::Cpu : public Arm_v7_cpu
|
||||
static access_t init()
|
||||
{
|
||||
/*
|
||||
* allow cache (7), TLB (8) maintenance, and performance
|
||||
* monitor (9), process/thread ID register (13) and timer (14)
|
||||
* access.
|
||||
* allow everything except c0, c11, c12, and c15 accesses.
|
||||
*/
|
||||
access_t v = 0;
|
||||
T<0>::set(v, 1);
|
||||
T<1>::set(v, 1);
|
||||
T<2>::set(v, 1);
|
||||
T<3>::set(v, 1);
|
||||
T<5>::set(v, 1);
|
||||
T<6>::set(v, 1);
|
||||
T<10>::set(v, 1);
|
||||
T<11>::set(v, 1);
|
||||
T<12>::set(v, 1);
|
||||
T<15>::set(v, 1);
|
||||
@ -73,7 +65,6 @@ class Genode::Cpu : public Arm_v7_cpu
|
||||
struct Twe : Bitfield<14, 1> {}; /* trap on WFE instruction */
|
||||
struct Tidcp : Bitfield<20, 1> {}; /* trap lockdown */
|
||||
struct Tac : Bitfield<21, 1> {}; /* trap ACTLR accesses */
|
||||
struct Tvm : Bitfield<26, 1> {}; /* trap virtual memory ctrls */
|
||||
|
||||
static access_t init()
|
||||
{
|
||||
@ -86,7 +77,6 @@ class Genode::Cpu : public Arm_v7_cpu
|
||||
Twe::set(v, 1);
|
||||
Tidcp::set(v, 1);
|
||||
Tac::set(v, 1);
|
||||
Tvm::set(v, 1);
|
||||
return v;
|
||||
};
|
||||
};
|
||||
|
@ -18,10 +18,7 @@
|
||||
#include <spec/arm/virtualization/gicv2.h>
|
||||
#include <spec/arm/generic_timer.h>
|
||||
#include <spec/arm/cpu/vm_state_virtualization.h>
|
||||
#include <translation_table.h>
|
||||
#include <kernel/configuration.h>
|
||||
|
||||
namespace Kernel { class Cpu; }
|
||||
#include <spec/arm/virtualization/board.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Imx7d_sabre_board;
|
||||
@ -29,13 +26,6 @@ namespace Board {
|
||||
struct Virtual_local_pic {};
|
||||
|
||||
enum { TIMER_IRQ = 30, VCPU_MAX = 1 };
|
||||
|
||||
using Vm_state = Genode::Vm_state;
|
||||
using Vm_page_table = Hw::Level_1_stage_2_translation_table;
|
||||
using Vm_page_table_array =
|
||||
Vm_page_table::Allocator::Array<Kernel::DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
struct Vcpu_context { Vcpu_context(Kernel::Cpu &) {} };
|
||||
}
|
||||
|
||||
#endif /* _CORE__SPEC__IMX7_SABRELITE__BOARD_H_ */
|
||||
|
@ -18,9 +18,7 @@
|
||||
#include <spec/arm/generic_timer.h>
|
||||
#include <spec/arm/virtualization/gicv3.h>
|
||||
#include <spec/arm_64/cpu/vm_state_virtualization.h>
|
||||
#include <translation_table.h>
|
||||
#include <kernel/configuration.h>
|
||||
#include <kernel/irq.h>
|
||||
#include <spec/arm/virtualization/board.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Imx8q_evk_board;
|
||||
@ -29,59 +27,8 @@ namespace Board {
|
||||
TIMER_IRQ = 14 + 16,
|
||||
VT_TIMER_IRQ = 11 + 16,
|
||||
VT_MAINTAINANCE_IRQ = 9 + 16,
|
||||
VCPU_MAX = 16
|
||||
VCPU_MAX = 4
|
||||
};
|
||||
|
||||
using Vm_page_table = Hw::Level_1_stage_2_translation_table;
|
||||
using Vm_page_table_array =
|
||||
Vm_page_table::Allocator::Array<Kernel::DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
struct Vcpu_context;
|
||||
|
||||
using Vm_state = Genode::Vm_state;
|
||||
};
|
||||
|
||||
namespace Kernel {
|
||||
class Cpu;
|
||||
class Vm;
|
||||
};
|
||||
|
||||
struct Board::Vcpu_context
|
||||
{
|
||||
struct Vm_irq : Kernel::Irq
|
||||
{
|
||||
Vm_irq(unsigned const irq, Kernel::Cpu &);
|
||||
virtual ~Vm_irq() {};
|
||||
|
||||
virtual void handle(Kernel::Cpu &, Kernel::Vm & vm, unsigned irq);
|
||||
void occurred() override;
|
||||
};
|
||||
|
||||
|
||||
struct Pic_maintainance_irq : Vm_irq
|
||||
{
|
||||
Pic_maintainance_irq(Kernel::Cpu &);
|
||||
|
||||
void handle(Kernel::Cpu &, Kernel::Vm &, unsigned) override { }
|
||||
};
|
||||
|
||||
|
||||
struct Virtual_timer_irq
|
||||
{
|
||||
Vm_irq irq;
|
||||
|
||||
Virtual_timer_irq(Kernel::Cpu &);
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
};
|
||||
|
||||
Vcpu_context(Kernel::Cpu & cpu)
|
||||
: pic_irq(cpu), vtimer_irq(cpu) {}
|
||||
|
||||
Pic::Virtual_context pic {};
|
||||
Pic_maintainance_irq pic_irq;
|
||||
Virtual_timer_irq vtimer_irq;
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__IMX8Q_EVK__BOARD_H_ */
|
||||
|
@ -18,8 +18,7 @@
|
||||
#include <spec/arm/virtualization/gicv2.h>
|
||||
#include <spec/arm/generic_timer.h>
|
||||
#include <spec/arm/cpu/vm_state_virtualization.h>
|
||||
#include <translation_table.h>
|
||||
#include <kernel/configuration.h>
|
||||
#include <spec/arm/virtualization/board.h>
|
||||
|
||||
namespace Kernel { class Cpu; }
|
||||
|
||||
@ -34,13 +33,6 @@ namespace Board {
|
||||
VT_MAINTAINANCE_IRQ = 25,
|
||||
VCPU_MAX = 1
|
||||
};
|
||||
|
||||
using Vm_state = Genode::Vm_state;
|
||||
using Vm_page_table = Hw::Level_1_stage_2_translation_table;
|
||||
using Vm_page_table_array =
|
||||
Vm_page_table::Allocator::Array<Kernel::DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
struct Vcpu_context { Vcpu_context(Kernel::Cpu &) {} };
|
||||
};
|
||||
|
||||
#endif /* _SRC__CORE__SPEC__VIRT__QEMU_H_ */
|
||||
|
@ -250,7 +250,7 @@ class Hw::Long_translation_table
|
||||
| Attribute_index::create(f)
|
||||
| Not_global::bits(!f.global)
|
||||
| Base::Shareability::bits(
|
||||
Base::Shareability::OUTER_SHAREABLE)
|
||||
Base::Shareability::INNER_SHAREABLE)
|
||||
| Base::Output_address::masked(pa)
|
||||
| Base::Access_flag::bits(1)
|
||||
| Descriptor::Valid::bits(1)
|
||||
@ -270,7 +270,7 @@ class Hw::Long_translation_table
|
||||
addr_t const pa)
|
||||
{
|
||||
return Base::Shareability::bits(
|
||||
Base::Shareability::NON_SHAREABLE)
|
||||
Base::Shareability::INNER_SHAREABLE)
|
||||
| Base::Output_address::masked(pa)
|
||||
| Base::Access_flag::bits(1)
|
||||
| Descriptor::Valid::bits(1)
|
||||
|
Reference in New Issue
Block a user