From 7298b000131926f4b328e33e221a9a50ca78c9a1 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Fri, 11 Sep 2020 14:43:29 +0200 Subject: [PATCH] base-hw: make ARMv7/v8 hypervisor smp ready * Introduce hypervisor-stack per CPU * Introduce host world context per CPU * Mark EL2 translation table memory as inner shareable * The VMID is not bound to a single VCPU, but to the Vm_session as a whole * Set affinity of the VCPU accordingly * Add VMPIDR to VM state Ref #3926 --- .../spec/arm/cpu/vm_state_virtualization.h | 1 + .../bootstrap/spec/arm_64/cortex_a53_mmu.cc | 13 +- .../bootstrap/spec/imx7d_sabre/platform.cc | 16 +- .../src/bootstrap/spec/virt_qemu/platform.cc | 13 +- repos/base-hw/src/core/kernel/vm.h | 24 +- repos/base-hw/src/core/kernel/vm_thread_on.cc | 2 +- .../virtualization/vm_session_component.cc | 22 +- .../core/spec/arm_v7/trustzone/kernel/vm.cc | 15 +- .../arm_v7/trustzone/vm_session_component.cc | 29 +- .../arm_v7/virtualization/exception_vector.s | 316 +++++++++--------- .../spec/arm_v7/virtualization/kernel/vm.cc | 83 ++--- .../spec/arm_v8/virtualization/kernel/vm.cc | 81 ++--- .../base-hw/src/core/spec/imx7d_sabre/board.h | 2 +- repos/base-hw/src/core/spec/imx8q_evk/board.h | 2 +- repos/base-hw/src/core/spec/virt_qemu/board.h | 2 +- .../src/core/spec/x86_64/muen/kernel/vm.cc | 9 +- .../spec/x86_64/muen/vm_session_component.cc | 18 +- .../base-hw/src/core/vm_session_component.cc | 13 +- repos/base-hw/src/core/vm_session_component.h | 3 +- repos/base-hw/src/include/hw/spec/arm/cpu.h | 3 + .../src/lib/hw/spec/32bit/memory_map.cc | 2 +- .../src/lib/hw/spec/64bit/memory_map.cc | 2 +- 22 files changed, 350 insertions(+), 321 deletions(-) diff --git a/repos/base-hw/include/spec/arm/cpu/vm_state_virtualization.h b/repos/base-hw/include/spec/arm/cpu/vm_state_virtualization.h index 3fce06d50d..ed49e04645 100644 --- a/repos/base-hw/include/spec/arm/cpu/vm_state_virtualization.h +++ b/repos/base-hw/include/spec/arm/cpu/vm_state_virtualization.h @@ -50,6 +50,7 @@ struct Genode::Vm_state : Genode::Cpu_state_modes Genode::uint32_t tls2 { 0 }; Genode::uint32_t tls3 { 0 }; Genode::uint32_t cpacr { 0 }; + Genode::uint32_t vmpidr { 0 }; /** * Fpu registers diff --git a/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc b/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc index e39618f639..9f9a354b81 100644 --- a/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc +++ b/repos/base-hw/src/bootstrap/spec/arm_64/cortex_a53_mmu.cc @@ -58,7 +58,8 @@ static inline void prepare_non_secure_world() } -static inline void prepare_hypervisor(Cpu::Ttbr::access_t const ttbr) +static inline void prepare_hypervisor(Cpu::Ttbr::access_t const ttbr, + unsigned cpu_id) { using namespace Hw::Mm; @@ -80,7 +81,7 @@ static inline void prepare_hypervisor(Cpu::Ttbr::access_t const ttbr) /* set hypervisor exception vector */ Cpu::Vbar_el2::write(el2_addr(hypervisor_exception_vector().base)); Genode::addr_t const stack_el2 = el2_addr(hypervisor_stack().base + - hypervisor_stack().size); + (cpu_id+1) * 0x1000); /* set hypervisor's translation table */ Cpu::Ttbr0_el2::write(ttbr); @@ -89,7 +90,7 @@ static inline void prepare_hypervisor(Cpu::Ttbr::access_t const ttbr) Cpu::Tcr_el2::T0sz::set(tcr_el2, 25); Cpu::Tcr_el2::Irgn0::set(tcr_el2, 1); Cpu::Tcr_el2::Orgn0::set(tcr_el2, 1); - Cpu::Tcr_el2::Sh0::set(tcr_el2, 0b10); + Cpu::Tcr_el2::Sh0::set(tcr_el2, 0b11); /* prepare MMU usage by hypervisor code */ Cpu::Tcr_el2::write(tcr_el2); @@ -141,6 +142,8 @@ unsigned Bootstrap::Platform::enable_mmu() bool primary = primary_cpu; if (primary) primary_cpu = false; + unsigned cpu_id = (Cpu::Mpidr::read() & 0xff); + Cpu::Ttbr::access_t ttbr = Cpu::Ttbr::Baddr::masked((Genode::addr_t)core_pd->table_base); @@ -152,7 +155,7 @@ unsigned Bootstrap::Platform::enable_mmu() prepare_non_secure_world(); } else { ::Board::Pic pic __attribute__((unused)) {}; - prepare_hypervisor(ttbr); + prepare_hypervisor(ttbr, cpu_id); } } @@ -201,5 +204,5 @@ unsigned Bootstrap::Platform::enable_mmu() Cpu::Sctlr::Uct::set(sctlr, 1); Cpu::Sctlr_el1::write(sctlr); - return (Cpu::Mpidr::read() & 0xff); + return cpu_id; } diff --git a/repos/base-hw/src/bootstrap/spec/imx7d_sabre/platform.cc b/repos/base-hw/src/bootstrap/spec/imx7d_sabre/platform.cc index e8c251531b..f3b4b6e048 100644 --- a/repos/base-hw/src/bootstrap/spec/imx7d_sabre/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/imx7d_sabre/platform.cc @@ -12,11 +12,11 @@ */ #include +#include #include #include -extern "C" void * _start_setup_stack; /* entrypoint for non-boot CPUs */ -static unsigned char hyp_mode_stack[1024]; /* hypervisor mode's kernel stack */ +extern "C" void * _start_setup_stack; /* entrypoint for non-boot CPUs */ using namespace Board; @@ -161,7 +161,7 @@ Bootstrap::Platform::Board::Board() } -static inline void switch_to_supervisor_mode() +static inline void switch_to_supervisor_mode(unsigned cpu_id) { using Cpsr = Hw::Arm_cpu::Psr; @@ -170,6 +170,9 @@ static inline void switch_to_supervisor_mode() Cpsr::F::set(cpsr, 1); Cpsr::I::set(cpsr, 1); + Genode::addr_t const stack = Hw::Mm::hypervisor_stack().base + + (cpu_id+1) * 0x1000; + asm volatile ( "msr sp_svc, sp \n" /* copy current mode's sp */ "msr lr_svc, lr \n" /* copy current mode's lr */ @@ -178,7 +181,7 @@ static inline void switch_to_supervisor_mode() "msr spsr_cxfs, %[cpsr] \n" /* set psr for supervisor mode */ "adr lr, 1f \n" /* load exception return address */ "eret \n" /* exception return */ - "1:":: [cpsr] "r" (cpsr), [stack] "r" (&hyp_mode_stack)); + "1:":: [cpsr] "r" (cpsr), [stack] "r" (stack)); } @@ -186,13 +189,14 @@ unsigned Bootstrap::Platform::enable_mmu() { static volatile bool primary_cpu = true; static unsigned long timer_freq = Cpu::Cntfrq::read(); + unsigned cpu = Cpu::Mpidr::Aff_0::get(Cpu::Mpidr::read()); /* locally initialize interrupt controller */ ::Board::Pic pic { }; prepare_nonsecure_world(timer_freq); prepare_hypervisor((addr_t)core_pd->table_base); - switch_to_supervisor_mode(); + switch_to_supervisor_mode(cpu); Cpu::Sctlr::init(); Cpu::Cpsr::init(); @@ -206,7 +210,7 @@ unsigned Bootstrap::Platform::enable_mmu() Cpu::enable_mmu_and_caches((Genode::addr_t)core_pd->table_base); - return Cpu::Mpidr::Aff_0::get(Cpu::Mpidr::read()); + return cpu; } diff --git a/repos/base-hw/src/bootstrap/spec/virt_qemu/platform.cc b/repos/base-hw/src/bootstrap/spec/virt_qemu/platform.cc index 0ee53b746d..d99e2a2fcc 100644 --- a/repos/base-hw/src/bootstrap/spec/virt_qemu/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/virt_qemu/platform.cc @@ -15,7 +15,6 @@ #include extern "C" void * _start_setup_stack; /* entrypoint for non-boot CPUs */ -static unsigned char hyp_mode_stack[1024]; /* hypervisor mode's kernel stack */ using namespace Board; @@ -31,7 +30,7 @@ Bootstrap::Platform::Board::Board() Cpu_mmio::IRQ_CONTROLLER_VT_CTRL_SIZE }) {} -static inline void switch_to_supervisor_mode() +static inline void switch_to_supervisor_mode(unsigned cpu_id) { using Cpsr = Hw::Arm_cpu::Psr; @@ -40,6 +39,9 @@ static inline void switch_to_supervisor_mode() Cpsr::F::set(cpsr, 1); Cpsr::I::set(cpsr, 1); + Genode::addr_t const stack = Hw::Mm::hypervisor_stack().base + + (cpu_id+1) * 0x1000; + asm volatile ( "msr sp_svc, sp \n" /* copy current mode's sp */ "msr lr_svc, lr \n" /* copy current mode's lr */ @@ -48,13 +50,14 @@ static inline void switch_to_supervisor_mode() "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)); + "1:":: [cpsr] "r" (cpsr), [stack] "r" (stack)); } unsigned Bootstrap::Platform::enable_mmu() { static volatile bool primary_cpu = true; + unsigned cpu = Cpu::Mpidr::Aff_0::get(Cpu::Mpidr::read()); /* locally initialize interrupt controller */ ::Board::Pic pic { }; @@ -67,14 +70,14 @@ unsigned Bootstrap::Platform::enable_mmu() } prepare_hypervisor((addr_t)core_pd->table_base); - switch_to_supervisor_mode(); + switch_to_supervisor_mode(cpu); Cpu::Sctlr::init(); Cpu::Cpsr::init(); Cpu::enable_mmu_and_caches((Genode::addr_t)core_pd->table_base); - return Cpu::Mpidr::Aff_0::get(Cpu::Mpidr::read()); + return cpu; } diff --git a/repos/base-hw/src/core/kernel/vm.h b/repos/base-hw/src/core/kernel/vm.h index 073510fe88..2e23731316 100644 --- a/repos/base-hw/src/core/kernel/vm.h +++ b/repos/base-hw/src/core/kernel/vm.h @@ -35,6 +35,14 @@ namespace Kernel class Kernel::Vm : private Kernel::Object, public Cpu_job { + public: + + struct Identity + { + unsigned const id; + void * const table; + }; + private: using State = Board::Vm_state; @@ -48,10 +56,9 @@ class Kernel::Vm : private Kernel::Object, public Cpu_job enum Scheduler_state { ACTIVE, INACTIVE }; Object _kernel_object { *this }; - unsigned _id = 0; State & _state; Signal_context & _context; - void * const _table; + Identity const _id; Scheduler_state _scheduled = INACTIVE; Board::Vcpu_context _vcpu_context; @@ -60,16 +67,14 @@ class Kernel::Vm : private Kernel::Object, public Cpu_job /** * Constructor * + * \param cpu cpu affinity * \param state initial CPU state * \param context signal for VM exceptions other than interrupts - * \param table translation table for guest to host physical memory */ Vm(unsigned cpu, State & state, Signal_context & context, - void * const table); - - ~Vm(); + Identity & id); /** * Inject an interrupt to this VM @@ -85,8 +90,7 @@ class Kernel::Vm : private Kernel::Object, public Cpu_job * \param dst memory donation for the VM object * \param state location of the CPU state of the VM * \param signal_context_id kernel name of the signal context for VM events - * \param table guest-physical to host-physical translation - * table pointer + * \param id VM identity * * \retval cap id when successful, otherwise invalid cap id */ @@ -94,10 +98,10 @@ class Kernel::Vm : private Kernel::Object, public Cpu_job unsigned cpu, void * const state, capid_t const signal_context_id, - void * const table) + Identity & id) { return call(call_id_new_vm(), (Call_arg)&vm, (Call_arg)cpu, - (Call_arg)state, (Call_arg)table, signal_context_id); + (Call_arg)state, (Call_arg)&id, signal_context_id); } /** diff --git a/repos/base-hw/src/core/kernel/vm_thread_on.cc b/repos/base-hw/src/core/kernel/vm_thread_on.cc index 34e2711d97..f551bfa8da 100644 --- a/repos/base-hw/src/core/kernel/vm_thread_on.cc +++ b/repos/base-hw/src/core/kernel/vm_thread_on.cc @@ -25,7 +25,7 @@ void Kernel::Thread::_call_new_vm() } _call_new((unsigned)user_arg_2(), *(Board::Vm_state*)user_arg_3(), - *context, (void*)user_arg_4()); + *context, *(Vm::Identity*)user_arg_4()); } diff --git a/repos/base-hw/src/core/spec/arm/virtualization/vm_session_component.cc b/repos/base-hw/src/core/spec/arm/virtualization/vm_session_component.cc index c80d4dc47a..fe32b075cb 100644 --- a/repos/base-hw/src/core/spec/arm/virtualization/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm/virtualization/vm_session_component.cc @@ -80,6 +80,22 @@ void * Vm_session_component::_alloc_table() } +using Vmid_allocator = Genode::Bit_allocator<256>; + +static Vmid_allocator &alloc() +{ + static Vmid_allocator * allocator = nullptr; + if (!allocator) { + allocator = unmanaged_singleton(); + + /* reserve VM ID 0 for the hypervisor */ + unsigned id = allocator->alloc(); + assert (id == 0); + } + return *allocator; +} + + Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep, Resources resources, Label const &, @@ -96,7 +112,8 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep, _region_map(region_map), _table(*construct_at(_alloc_table())), _table_array(*(new (cma()) Board::Vm_page_table_array([this] (void * virt) { - return (addr_t)cma().phys_addr(virt);}))) + return (addr_t)cma().phys_addr(virt);}))), + _id({(unsigned)alloc().alloc(), cma().phys_addr(&_table)}) { /* configure managed VM area */ _map.add_range(0, 0UL - 0x1000); @@ -117,7 +134,7 @@ Vm_session_component::~Vm_session_component() } /* free region in allocator */ - for (unsigned i = 0; i < _id_alloc; i++) { + for (unsigned i = 0; i < _vcpu_id_alloc; i++) { Vcpu & vcpu = _vcpus[i]; if (vcpu.ds_cap.valid()) { _region_map.detach(vcpu.ds_addr); @@ -128,4 +145,5 @@ Vm_session_component::~Vm_session_component() /* free guest-to-host page tables */ destroy(platform().core_mem_alloc(), &_table); destroy(platform().core_mem_alloc(), &_table_array); + alloc().free(_id.id); } diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc index 67f295654a..cecf01d1a8 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc @@ -23,21 +23,18 @@ using namespace Kernel; Kernel::Vm::Vm(unsigned, Genode::Vm_state & state, Kernel::Signal_context & context, - void * const) + Identity & id) : Kernel::Object { *this }, - Cpu_job(Cpu_priority::MIN, 0), - _state(state), - _context(context), - _table(0), - _vcpu_context(cpu_pool().primary_cpu()) + Cpu_job(Cpu_priority::MIN, 0), + _state(state), + _context(context), + _id(id), + _vcpu_context(cpu_pool().primary_cpu()) { affinity(cpu_pool().primary_cpu()); } -Kernel::Vm::~Vm() {} - - void Vm::exception(Cpu & cpu) { switch(_state.cpu_exception) { diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc index 08ec48d9d9..dfc619ef26 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc @@ -48,6 +48,9 @@ void * Vm_session_component::_alloc_table() } +static unsigned id_alloc = 0; + + Vm_session_component::Vm_session_component(Rpc_entrypoint &ep, Resources resources, Label const &, @@ -55,15 +58,21 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ep, Ram_allocator &ram_alloc, Region_map ®ion_map, unsigned, Trace::Source_registry &) -: - Ram_quota_guard(resources.ram_quota), - Cap_quota_guard(resources.cap_quota), - _ep(ep), - _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), - _sliced_heap(_constrained_md_ram_alloc, region_map), - _region_map(region_map), +: Ram_quota_guard(resources.ram_quota), + Cap_quota_guard(resources.cap_quota), + _ep(ep), + _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), + _sliced_heap(_constrained_md_ram_alloc, region_map), + _region_map(region_map), _table(*construct_at(_alloc_table())), - _table_array(dummy_array()) { } + _table_array(dummy_array()), + _id({id_alloc++, nullptr}) +{ + if (_id.id) { + error("Only one TrustZone VM available!"); + throw Service_denied(); + } +} Vm_session_component::~Vm_session_component() @@ -79,11 +88,13 @@ Vm_session_component::~Vm_session_component() } /* free region in allocator */ - for (unsigned i = 0; i < _id_alloc; i++) { + for (unsigned i = 0; i < _vcpu_id_alloc; i++) { Vcpu & vcpu = _vcpus[i]; if (vcpu.ds_cap.valid()) { _region_map.detach(vcpu.ds_addr); _constrained_md_ram_alloc.free(vcpu.ds_cap); } } + + id_alloc--; } diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s b/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s index c104988917..837483f817 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s @@ -11,34 +11,12 @@ * under the terms of the GNU Affero General Public License version 3. */ -.set USR_MODE, 16 -.set FIQ_MODE, 17 -.set IRQ_MODE, 18 -.set SVC_MODE, 19 -.set ABT_MODE, 23 -.set UND_MODE, 27 -.set SYS_MODE, 31 - -.macro _save_bank mode - cps #\mode /* switch to given mode */ - mrs r1, spsr /* store mode-specific spsr */ - stmia r0!, {r1,sp,lr} /* store mode-specific sp and lr */ -.endm /* _save_bank mode */ - -.macro _restore_bank mode - cps #\mode /* switch to given mode */ - ldmia r0!, {r1,sp,lr} /* load mode-specific sp, lr, and spsr into r1 */ - msr spsr_cxfs, r1 /* load mode-specific spsr */ -.endm - .macro _vm_exit exception_type - str r0, [sp] + push { r0 } mrc p15, 4, r0, c1, c1, 0 /* read HCR register */ tst r0, #1 /* check VM bit */ - ldreq r0, [sp] beq _host_to_vm mov r0, #\exception_type - str r0, [sp, #17*4] b _vm_to_host .endm /* _vm_exit */ @@ -70,146 +48,176 @@ _vt_irq_entry: _vm_exit 6 _vt_trp_entry: _vm_exit 8 _host_to_vm: - msr elr_hyp, r2 - msr spsr_cxfs, r3 /* load cpsr */ - mcrr p15, 6, r5, r6, c2 /* write VTTBR */ - mcr p15, 0, r7, c1, c0, 0 /* write SCTRL */ - mcr p15, 4, r8, c1, c1, 3 /* write HSTR */ - mcr p15, 4, r9, c1, c1, 0 /* write HCR register */ - mcr p15, 0, r12, c2, c0, 2 /* write TTBRC */ - sub sp, r0, #46*4 - ldm r0!, {r1-r12} - mcr p15, 0, r1, c2, c0, 0 /* write TTBR0 */ - mcr p15, 0, r2, c2, c0, 1 /* write TTBR1 */ - mcr p15, 0, r3, c10, c2, 0 /* write PRRR */ - mcr p15, 0, r4, c10, c2, 1 /* write NMRR */ - mcr p15, 0, r5, c3, c0, 0 /* write DACR */ - mcr p15, 0, r6, c5, c0, 0 /* write DFSR */ - mcr p15, 0, r7, c5, c0, 1 /* write IFSR */ - mcr p15, 0, r8, c5, c1, 0 /* write ADFSR */ - mcr p15, 0, r9, c5, c1, 1 /* write AIFSR */ - mcr p15, 0, r10, c6, c0, 0 /* write DFAR */ - mcr p15, 0, r11, c6, c0, 2 /* write IFAR */ - mcr p15, 0, r12, c13, c0, 1 /* write CIDR */ - ldm r0!, {r1-r4} - mcr p15, 0, r1, c13, c0, 2 /* write TLS1 */ - mcr p15, 0, r2, c13, c0, 3 /* write TLS2 */ - mcr p15, 0, r3, c13, c0, 4 /* write TLS3 */ - mcr p15, 0, r4, c1, c0, 2 /* write CPACR */ - ldr r1, [r0] - vmsr fpscr, r1 - 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 */ + push { r1 } + ldr r0, [sp, #1*4] + add r0, r0, #13*4 + ldmia r0!, { r1-r5 } + msr sp_usr, r1 + mov lr, r2 + msr elr_hyp, r3 + msr spsr_cxfs, r4 + ldmia r0!, { r1-r12 } + msr spsr_und, r1 + msr sp_und, r2 + msr lr_und, r3 + msr spsr_svc, r4 + msr sp_svc, r5 + msr lr_svc, r6 + msr spsr_abt, r7 + msr sp_abt, r8 + msr lr_abt, r9 + msr spsr_irq, r10 + msr sp_irq, r11 + msr lr_irq, r12 + ldmia r0!, {r5 - r12} + msr spsr_fiq, r5 + msr sp_fiq, r6 + msr lr_fiq, r7 + msr r8_fiq, r8 + msr r9_fiq, r9 + msr r10_fiq, r10 + msr r11_fiq, r11 + msr r12_fiq, r12 + ldmia r0!, {r1 - r12} + mcrr p15, 6, r1, r2, c2 /* write VTTBR */ + mcr p15, 0, r3, c1, c0, 0 /* write SCTRL */ + mcr p15, 4, r4, c1, c1, 3 /* write HSTR */ + mcr p15, 4, r5, c1, c1, 0 /* write HCR register */ + mcr p15, 0, r8, c2, c0, 2 /* write TTBRC */ + mcr p15, 0, r9, c2, c0, 0 /* write TTBR0 */ + mcr p15, 0, r10, c2, c0, 1 /* write TTBR1 */ + mcr p15, 0, r11, c10, c2, 0 /* write PRRR */ + mcr p15, 0, r12, c10, c2, 1 /* write NMRR */ + ldmia r0!, {r1-r12} + mcr p15, 0, r1, c3, c0, 0 /* write DACR */ + mcr p15, 0, r2, c5, c0, 0 /* write DFSR */ + mcr p15, 0, r3, c5, c0, 1 /* write IFSR */ + mcr p15, 0, r4, c5, c1, 0 /* write ADFSR */ + mcr p15, 0, r5, c5, c1, 1 /* write AIFSR */ + mcr p15, 0, r6, c6, c0, 0 /* write DFAR */ + mcr p15, 0, r7, c6, c0, 2 /* write IFAR */ + mcr p15, 0, r8, c13, c0, 1 /* write CIDR */ + mcr p15, 0, r9, c13, c0, 2 /* write TLS1 */ + mcr p15, 0, r10, c13, c0, 3 /* write TLS2 */ + mcr p15, 0, r11, c13, c0, 4 /* write TLS3 */ + mcr p15, 0, r12, c1, c0, 2 /* write CPACR */ + ldmia r0!, {r1-r2} + mcr p15, 4, r1, c0, c0, 5 /* write VMPIDR */ + vmsr fpscr, r2 + vldm r0!, {d0-d15} + vldm r0!, {d16-d31} + ldmia r0!, {r1-r6} + mcrr p15, 4, r1, r2, c14 /* write cntvoff */ + mcrr p15, 3, r3, r4, c14 /* write cntv_cval */ + mcr p15, 0, r5, c14, c3, 1 /* write cntv_ctl */ + mcr p15, 0, r6, c14, c1, 0 /* write cntkctl */ + ldr r0, [sp, #1*4] + ldmia r0, {r0-r12} /* load vm's r0-r12 */ eret _vm_to_host: - add r0, sp, #1*4 - stmia r0, {r1-r12} /* save regs r1-r12 */ - mov r1, #0 - 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 */ + push { r0 } /* push cpu excep. */ + ldr r0, [sp, #3*4] /* load vm state ptr */ + add r0, r0, #1*4 /* skip r0 */ + stmia r0!, {r1-r12} /* save regs r1-r12 */ + pop { r5 } /* pop cpu excep. */ + pop { r1 } /* pop r0 */ + str r1, [r0, #-13*4] /* save r0 */ + mrs r1, sp_usr /* read USR sp */ + mov r2, lr /* read USR lr */ + mrs r3, elr_hyp /* read ip */ + mrs r4, spsr /* read cpsr */ + mrs r6, spsr_und + mrs r7, sp_und + mrs r8, lr_und + mrs r9, spsr_svc + mrs r10, sp_svc + mrs r11, lr_svc + mrs r12, spsr_abt + stmia r0!, {r1-r12} + mrs r1, sp_abt + mrs r2, lr_abt + mrs r3, spsr_irq + mrs r4, sp_irq + mrs r5, lr_irq + mrs r6, spsr_fiq + mrs r7, sp_fiq + mrs r8, lr_fiq + mrs r9, r8_fiq + mrs r10, r9_fiq + mrs r11, r10_fiq + mrs r12, r11_fiq + stmia r0!, {r1-r12} + mrs r1, r12_fiq + str r1, [r0] + add r0, r0, #3*4 /* skip VTTBR */ + mrc p15, 0, r1, c1, c0, 0 /* read SCTRL */ + mrc p15, 4, r2, c5, c2, 0 /* read HSR */ + mrc p15, 4, r3, c6, c0, 4 /* read HPFAR */ + mrc p15, 4, r4, c6, c0, 0 /* read HDFAR */ + mrc p15, 4, r5, c6, c0, 2 /* read HIFAR */ + mrc p15, 0, r6, c2, c0, 2 /* read TTBRC */ + mrc p15, 0, r7, c2, c0, 0 /* read TTBR0 */ + mrc p15, 0, r8, c2, c0, 1 /* read TTBR1 */ + mrc p15, 0, r9, c10, c2, 0 /* read PRRR */ + mrc p15, 0, r10, c10, c2, 1 /* read NMRR */ + mrc p15, 0, r11, c3, c0, 0 /* read DACR */ + mrc p15, 0, r12, c5, c0, 0 /* read DFSR */ + stmia r0!, {r1-r12} + mrc p15, 0, r1, c5, c0, 1 /* read IFSR */ + mrc p15, 0, r2, c5, c1, 0 /* read ADFSR */ + mrc p15, 0, r3, c5, c1, 1 /* read AIFSR */ + mrc p15, 0, r4, c6, c0, 0 /* read DFAR */ + mrc p15, 0, r5, c6, c0, 2 /* read IFAR */ + mrc p15, 0, r6, c13, c0, 1 /* read CIDR */ + mrc p15, 0, r7, c13, c0, 2 /* read TLS1 */ + mrc p15, 0, r8, c13, c0, 3 /* read TLS2 */ + mrc p15, 0, r9, c13, c0, 4 /* read TLS3 */ + mrc p15, 0, r10, c1, c0, 2 /* read CPACR */ + mrc p15, 4, r11, c0, c0, 5 /* read VMPIDR */ + stmia r0!, {r1-r11} + mov r1, #1 /* clear fpu excep. state */ + lsl r1, #30 + vmsr fpexc, r1 + vmrs r12, fpscr + stmia r0!, {r12} + vstm r0!, {d0-d15} + vstm r0!, {d16-d31} + mrrc p15, 4, r1, r2, c14 /* read cntvoff */ + mrrc p15, 3, r3, r4, c14 /* read cntv_cval */ + mrc p15, 0, r5, c14, c3, 1 /* read cntv_ctl */ + mrc p15, 0, r6, c14, c1, 0 /* read cntkctl */ + stmia r0!, {r1-r6} - mrs r1, ELR_hyp /* read ip */ - mrs r2, spsr /* read cpsr */ - mrc p15, 0, r3, c1, c0, 0 /* read SCTRL */ - mrc p15, 4, r4, c5, c2, 0 /* read HSR */ - mrc p15, 4, r5, c6, c0, 4 /* read HPFAR */ - mrc p15, 4, r6, c6, c0, 0 /* read HDFAR */ - mrc p15, 4, r7, c6, c0, 2 /* read HIFAR */ - 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-r12} - 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} + clrex + dsb sy + isb sy - mov r3, #0xf - lsl r3, #20 - mcr p15, 0, r3, c1, c0, 2 /* write CPACR */ + /************************** + ** Restore host context ** + **************************/ - mov r3, #1 /* clear fpu exception state */ - lsl r3, #30 - vmsr fpexc, r3 - vmrs r4, fpscr - 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] - add r3, r3, #2*4 - ldm r3, {r4-r11} - mcrr p15, 0, r6, r7, c2 - mcrr p15, 1, r6, r7, c2 - mcr p15, 0, r8, c1, c0, 0 /* write SCTRL */ - mcr p15, 0, r9, c2, c0, 2 /* write TTBRC */ - mcr p15, 0, r10, c10, c2, 0 /* write MAIR0 */ - mcr p15, 0, r11, c3, c0, 0 /* write DACR */ - mov r10, #7 - lsl r10, #6 - add r10, r10, #SVC_MODE - msr spsr_cxsf, r10 - adr r10, _svc_mode_ret - msr ELR_hyp, r10 + pop { r0, r1 } + ldmia r0!, {r1-r12} + mcrr p15, 6, r1, r2, c2 /* write VTTBR */ + mcr p15, 4, r3, c1, c1, 0 /* write HCR register */ + mcr p15, 4, r4, c1, c1, 3 /* write HSTR register */ + mcr p15, 0, r5, c1, c0, 2 /* write CPACR */ + msr sp_svc, r6 + msr elr_hyp, r7 + msr spsr_cxfs, r8 + mcrr p15, 0, r9, r10, c2 /* write TTBR0 */ + mcrr p15, 1, r11, r12, c2 /* write TTBR1 */ + ldmia r0, {r1-r5} + mcr p15, 0, r1, c1, c0, 0 /* write SCTRL */ + mcr p15, 0, r2, c2, c0, 2 /* write TTBRC */ + mcr p15, 0, r3, c10, c2, 0 /* write MAIR0 */ + mcr p15, 0, r4, c3, c0, 0 /* write DACR */ + mcr p15, 4, r5, c0, c0, 5 /* write VMPIDR */ eret -_svc_mode_ret: - stmia r0, {r13-r14}^ /* save user regs sp,lr */ - add r0, r0, #2*4 - stmia r0!, {r1-r2} /* save ip, cpsr */ - add r0, r0, #1*4 - _save_bank UND_MODE /* save undefined banks */ - _save_bank SVC_MODE /* save supervisor banks */ - _save_bank ABT_MODE /* save abort banks */ - _save_bank IRQ_MODE /* save irq banks */ - _save_bank FIQ_MODE /* save fiq banks */ - stmia r0!, {r8-r12} /* save fiq r8-r12 */ - cps #SVC_MODE - ldr r0, _vt_host_context_ptr - ldm r0, {sp,pc} + /* host kernel must jump to this point to switch to a vm */ .global hypervisor_enter_vm hypervisor_enter_vm: - add r0, r0, #13*4 - ldm r0, {r13 - r14}^ - add r0, r0, #2*4 - ldmia r0!, {r2 - r4} - _restore_bank UND_MODE - _restore_bank SVC_MODE - _restore_bank ABT_MODE - _restore_bank IRQ_MODE - _restore_bank FIQ_MODE - ldmia r0!, {r8 - r12} - cps #SVC_MODE - ldm r0!, {r5 - r12} hvc #0 - -_vt_host_context_ptr: .long vt_host_context diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc index e1d9c99a0b..e9e43c9cb4 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc @@ -39,22 +39,53 @@ namespace Kernel using namespace Kernel; -extern "C" void kernel(); -extern void * kernel_stack; -extern "C" void hypervisor_enter_vm(Genode::Vm_state&); - struct Host_context { + Cpu::Ttbr_64bit::access_t vttbr; + Cpu::Hcr::access_t hcr; + Cpu::Hstr::access_t hstr; + Cpu::Cpacr::access_t cpacr; addr_t sp; addr_t ip; + addr_t spsr; Cpu::Ttbr_64bit::access_t ttbr0; Cpu::Ttbr_64bit::access_t ttbr1; Cpu::Sctlr::access_t sctlr; Cpu::Ttbcr::access_t ttbcr; Cpu::Mair0::access_t mair0; Cpu::Dacr::access_t dacr; + Cpu::Vmpidr::access_t vmpidr; } vt_host_context; +extern "C" void kernel(); +extern "C" void hypervisor_enter_vm(Genode::Vm_state&, Host_context&); + + +static Host_context & host_context(Cpu & cpu) +{ + static Genode::Constructible host_context[NR_OF_CPUS]; + if (!host_context[cpu.id()].constructed()) { + host_context[cpu.id()].construct(); + Host_context & c = *host_context[cpu.id()]; + c.sp = cpu.stack_start(); + c.ttbr0 = Cpu::Ttbr0_64bit::read(); + c.ttbr1 = Cpu::Ttbr1_64bit::read(); + c.sctlr = Cpu::Sctlr::read(); + c.ttbcr = Cpu::Ttbcr::read(); + c.mair0 = Cpu::Mair0::read(); + c.dacr = Cpu::Dacr::read(); + c.vmpidr = Cpu::Mpidr::read(); + c.ip = (addr_t) &kernel; + c.vttbr = 0; + c.hcr = 0; + c.hstr = 0; + c.cpacr = 0xf00000; + c.spsr = 0x1d3; + } + return *host_context[cpu.id()]; +} + + Board::Vcpu_context::Vm_irq::Vm_irq(unsigned const irq, Cpu & cpu) : Kernel::Irq(irq, cpu.irq_pool()) { } @@ -92,50 +123,22 @@ void Board::Vcpu_context::Virtual_timer_irq::disable() asm volatile("mcr p15, 0, %0, c14, c1, 0" :: "r" (0b11)); } -using Vmid_allocator = Genode::Bit_allocator<256>; -static Vmid_allocator &alloc() -{ - static Vmid_allocator * allocator = nullptr; - if (!allocator) { - allocator = unmanaged_singleton(); - - /* reserve VM ID 0 for the hypervisor */ - unsigned id = allocator->alloc(); - assert (id == 0); - } - return *allocator; -} - - -Kernel::Vm::Vm(unsigned, /* FIXME: smp support */ +Kernel::Vm::Vm(unsigned cpu, Genode::Vm_state & state, Kernel::Signal_context & context, - void * const table) + Identity & id) : Kernel::Object { *this }, Cpu_job(Cpu_priority::MIN, 0), - _id(alloc().alloc()), _state(state), _context(context), - _table(table), - _vcpu_context(cpu_pool().primary_cpu()) + _id(id), + _vcpu_context(cpu_pool().cpu(cpu)) { - affinity(cpu_pool().primary_cpu()); - - vt_host_context.sp = _cpu->stack_start(); - vt_host_context.ttbr0 = Cpu::Ttbr0_64bit::read(); - vt_host_context.ttbr1 = Cpu::Ttbr1_64bit::read(); - vt_host_context.sctlr = Cpu::Sctlr::read(); - vt_host_context.ttbcr = Cpu::Ttbcr::read(); - vt_host_context.mair0 = Cpu::Mair0::read(); - vt_host_context.dacr = Cpu::Dacr::read(); - vt_host_context.ip = (addr_t) &kernel; + affinity(cpu_pool().cpu(cpu)); } -Kernel::Vm::~Vm() { alloc().free(_id); } - - void Kernel::Vm::exception(Cpu & cpu) { switch(_state.cpu_exception) { @@ -163,8 +166,8 @@ void Kernel::Vm::proceed(Cpu & cpu) /* * the following values have to be enforced by the hypervisor */ - _state.vttbr = Cpu::Ttbr_64bit::Ba::masked((Cpu::Ttbr_64bit::access_t)_table); - Cpu::Ttbr_64bit::Asid::set(_state.vttbr, _id); + _state.vttbr = Cpu::Ttbr_64bit::Ba::masked((Cpu::Ttbr_64bit::access_t)_id.table); + Cpu::Ttbr_64bit::Asid::set(_state.vttbr, _id.id); /* * use the following report fields not needed for loading the context @@ -174,7 +177,7 @@ void Kernel::Vm::proceed(Cpu & cpu) _state.esr_el2 = Cpu::Hstr::init(); _state.hpfar_el2 = Cpu::Hcr::init(); - hypervisor_enter_vm(_state); + hypervisor_enter_vm(_state, host_context(cpu)); } diff --git a/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc index 8d16e271d0..ca8302c382 100644 --- a/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc @@ -32,32 +32,34 @@ extern "C" void hypervisor_enter_vm(addr_t vm, addr_t host, addr_t pic, addr_t guest_table); -static Genode::Vm_state & host_context() +static Genode::Vm_state & host_context(Cpu & cpu) { - static Genode::Constructible host_context; - if (!host_context.constructed()) { - host_context.construct(); - host_context->ip = (addr_t) &kernel; - host_context->pstate = 0; - Cpu::Spsr::Sp::set(host_context->pstate, 1); /* select non-el0 stack pointer */ - Cpu::Spsr::El::set(host_context->pstate, Cpu::Current_el::EL1); - Cpu::Spsr::F::set(host_context->pstate, 1); - Cpu::Spsr::I::set(host_context->pstate, 1); - Cpu::Spsr::A::set(host_context->pstate, 1); - Cpu::Spsr::D::set(host_context->pstate, 1); - host_context->fpcr = Cpu::Fpcr::read(); - host_context->fpsr = 0; - host_context->sctlr_el1 = Cpu::Sctlr_el1::read(); - host_context->actlr_el1 = Cpu::Actlr_el1::read(); - host_context->vbar_el1 = Cpu::Vbar_el1::read(); - host_context->cpacr_el1 = Cpu::Cpacr_el1::read(); - host_context->ttbr0_el1 = Cpu::Ttbr0_el1::read(); - host_context->ttbr1_el1 = Cpu::Ttbr1_el1::read(); - host_context->tcr_el1 = Cpu::Tcr_el1::read(); - host_context->mair_el1 = Cpu::Mair_el1::read(); - host_context->amair_el1 = Cpu::Amair_el1::read(); + static Genode::Constructible host_context[NR_OF_CPUS]; + if (!host_context[cpu.id()].constructed()) { + host_context[cpu.id()].construct(); + Genode::Vm_state & c = *host_context[cpu.id()]; + c.sp_el1 = cpu.stack_start(); + c.ip = (addr_t) &kernel; + c.pstate = 0; + Cpu::Spsr::Sp::set(c.pstate, 1); /* select non-el0 stack pointer */ + Cpu::Spsr::El::set(c.pstate, Cpu::Current_el::EL1); + Cpu::Spsr::F::set(c.pstate, 1); + Cpu::Spsr::I::set(c.pstate, 1); + Cpu::Spsr::A::set(c.pstate, 1); + Cpu::Spsr::D::set(c.pstate, 1); + c.fpcr = Cpu::Fpcr::read(); + c.fpsr = 0; + c.sctlr_el1 = Cpu::Sctlr_el1::read(); + c.actlr_el1 = Cpu::Actlr_el1::read(); + c.vbar_el1 = Cpu::Vbar_el1::read(); + c.cpacr_el1 = Cpu::Cpacr_el1::read(); + c.ttbr0_el1 = Cpu::Ttbr0_el1::read(); + c.ttbr1_el1 = Cpu::Ttbr1_el1::read(); + c.tcr_el1 = Cpu::Tcr_el1::read(); + c.mair_el1 = Cpu::Mair_el1::read(); + c.amair_el1 = Cpu::Amair_el1::read(); } - return *host_context; + return *host_context[cpu.id()]; } @@ -99,32 +101,15 @@ void Board::Vcpu_context::Virtual_timer_irq::disable() } -using Vmid_allocator = Genode::Bit_allocator<256>; - -static Vmid_allocator &alloc() -{ - static Vmid_allocator * allocator = nullptr; - if (!allocator) { - allocator = unmanaged_singleton(); - - /* reserve VM ID 0 for the hypervisor */ - unsigned id = allocator->alloc(); - assert (id == 0); - } - return *allocator; -} - - Vm::Vm(unsigned cpu, Genode::Vm_state & state, Kernel::Signal_context & context, - void * const table) + Identity & id) : Kernel::Object { *this }, Cpu_job(Cpu_priority::MIN, 0), - _id(alloc().alloc()), _state(state), _context(context), - _table(table), + _id(id), _vcpu_context(cpu_pool().cpu(cpu)) { affinity(cpu_pool().cpu(cpu)); @@ -158,9 +143,6 @@ Vm::Vm(unsigned cpu, } -Vm::~Vm() { alloc().free(_id); } - - void Vm::exception(Cpu & cpu) { switch (_state.exception_type) { @@ -198,12 +180,11 @@ void Vm::proceed(Cpu & cpu) * the following values have to be enforced by the hypervisor */ Cpu::Vttbr_el2::access_t vttbr_el2 = - Cpu::Vttbr_el2::Ba::masked((Cpu::Vttbr_el2::access_t)_table); - Cpu::Vttbr_el2::Asid::set(vttbr_el2, _id); + Cpu::Vttbr_el2::Ba::masked((Cpu::Vttbr_el2::access_t)_id.table); + Cpu::Vttbr_el2::Asid::set(vttbr_el2, _id.id); addr_t guest = Hw::Mm::el2_addr(&_state); addr_t pic = Hw::Mm::el2_addr(&_vcpu_context.pic); - addr_t host = Hw::Mm::el2_addr(&host_context()); - host_context().sp_el1 = cpu.stack_start(); + addr_t host = Hw::Mm::el2_addr(&host_context(cpu)); hypervisor_enter_vm(guest, host, pic, vttbr_el2); } diff --git a/repos/base-hw/src/core/spec/imx7d_sabre/board.h b/repos/base-hw/src/core/spec/imx7d_sabre/board.h index 8fce4163aa..c44902a7d2 100644 --- a/repos/base-hw/src/core/spec/imx7d_sabre/board.h +++ b/repos/base-hw/src/core/spec/imx7d_sabre/board.h @@ -25,7 +25,7 @@ namespace Board { struct Virtual_local_pic {}; - enum { TIMER_IRQ = 30, VCPU_MAX = 1 }; + enum { TIMER_IRQ = 30, VCPU_MAX = 16 }; } #endif /* _CORE__SPEC__IMX7_SABRELITE__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/imx8q_evk/board.h b/repos/base-hw/src/core/spec/imx8q_evk/board.h index 7f34b0f920..9143a9746a 100644 --- a/repos/base-hw/src/core/spec/imx8q_evk/board.h +++ b/repos/base-hw/src/core/spec/imx8q_evk/board.h @@ -27,7 +27,7 @@ namespace Board { TIMER_IRQ = 14 + 16, VT_TIMER_IRQ = 11 + 16, VT_MAINTAINANCE_IRQ = 9 + 16, - VCPU_MAX = 4 + VCPU_MAX = 16 }; }; diff --git a/repos/base-hw/src/core/spec/virt_qemu/board.h b/repos/base-hw/src/core/spec/virt_qemu/board.h index 48cce8e3ea..eb93acf57b 100644 --- a/repos/base-hw/src/core/spec/virt_qemu/board.h +++ b/repos/base-hw/src/core/spec/virt_qemu/board.h @@ -31,7 +31,7 @@ namespace Board { TIMER_IRQ = 30 /* PPI IRQ 14 */, VT_TIMER_IRQ = 27, VT_MAINTAINANCE_IRQ = 25, - VCPU_MAX = 1 + VCPU_MAX = 16 }; }; diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc index 43ac8c040b..bd6dcd04a4 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc @@ -19,23 +19,20 @@ #include Kernel::Vm::Vm(unsigned, - Board::Vm_state & state, + Board::Vm_state & state, Kernel::Signal_context & context, - void * const) + Identity & id) : Kernel::Object { *this }, Cpu_job(Cpu_priority::MIN, 0), _state(state), _context(context), - _table(nullptr), + _id(id), _vcpu_context(cpu_pool().primary_cpu()) { affinity(cpu_pool().primary_cpu()); } -Kernel::Vm::~Vm() { } - - void Kernel::Vm::exception(Cpu & cpu) { pause(); diff --git a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.cc b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.cc index 265bf60972..77c757f997 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.cc @@ -55,15 +55,15 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ep, Ram_allocator &ram_alloc, Region_map ®ion_map, unsigned, Trace::Source_registry &) -: - Ram_quota_guard(resources.ram_quota), - Cap_quota_guard(resources.cap_quota), - _ep(ep), - _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), - _sliced_heap(_constrained_md_ram_alloc, region_map), - _region_map(region_map), +: Ram_quota_guard(resources.ram_quota), + Cap_quota_guard(resources.cap_quota), + _ep(ep), + _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), + _sliced_heap(_constrained_md_ram_alloc, region_map), + _region_map(region_map), _table(*construct_at(_alloc_table())), - _table_array(dummy_array()) { } + _table_array(dummy_array()), + _id({0, nullptr}) { } Vm_session_component::~Vm_session_component() @@ -79,7 +79,7 @@ Vm_session_component::~Vm_session_component() } /* free region in allocator */ - for (unsigned i = 0; i < _id_alloc; i++) { + for (unsigned i = 0; i < _vcpu_id_alloc; i++) { Vcpu & vcpu = _vcpus[i]; if (vcpu.ds_cap.valid()) { _region_map.detach(vcpu.ds_addr); diff --git a/repos/base-hw/src/core/vm_session_component.cc b/repos/base-hw/src/core/vm_session_component.cc index d0117c065b..a4d159e476 100644 --- a/repos/base-hw/src/core/vm_session_component.cc +++ b/repos/base-hw/src/core/vm_session_component.cc @@ -23,10 +23,6 @@ using namespace Genode; -static Core_mem_allocator & cma() { - return static_cast(platform().core_mem_alloc()); } - - size_t Vm_session_component::_ds_size() { return align_addr(sizeof(Board::Vm_state), get_page_size_log2()); } @@ -70,8 +66,7 @@ void Vm_session_component::_exception_handler(Signal_context_capability handler, unsigned const cpu = vcpu.location.valid() ? vcpu.location.xpos() : 0; - if (!vcpu.kobj.create(cpu, vcpu.ds_addr, Capability_space::capid(handler), - cma().phys_addr(&_table))) + if (!vcpu.kobj.create(cpu, vcpu.ds_addr, Capability_space::capid(handler), _id)) Genode::warning("Cannot instantiate vm kernel object, ", "invalid signal context?"); } @@ -81,7 +76,7 @@ Vm_session::Vcpu_id Vm_session_component::_create_vcpu(Thread_capability tcap) { using namespace Genode; - if (_id_alloc == Board::VCPU_MAX) return Vcpu_id{Vcpu_id::INVALID}; + if (_vcpu_id_alloc == Board::VCPU_MAX) return Vcpu_id{Vcpu_id::INVALID}; Affinity::Location vcpu_location; auto lambda = [&] (Cpu_thread_component *ptr) { @@ -90,7 +85,7 @@ Vm_session::Vcpu_id Vm_session_component::_create_vcpu(Thread_capability tcap) }; _ep.apply(tcap, lambda); - Vcpu & vcpu = _vcpus[_id_alloc]; + Vcpu & vcpu = _vcpus[_vcpu_id_alloc]; vcpu.ds_cap = _constrained_md_ram_alloc.alloc(_ds_size(), Cache_attribute::UNCACHED); try { @@ -101,7 +96,7 @@ Vm_session::Vcpu_id Vm_session_component::_create_vcpu(Thread_capability tcap) } vcpu.location = vcpu_location; - return Vcpu_id { _id_alloc++ }; + return Vcpu_id { _vcpu_id_alloc++ }; } diff --git a/repos/base-hw/src/core/vm_session_component.h b/repos/base-hw/src/core/vm_session_component.h index 1339fd765b..3477267af5 100644 --- a/repos/base-hw/src/core/vm_session_component.h +++ b/repos/base-hw/src/core/vm_session_component.h @@ -65,7 +65,8 @@ class Genode::Vm_session_component Region_map &_region_map; Board::Vm_page_table &_table; Board::Vm_page_table_array &_table_array; - unsigned _id_alloc { 0 }; + Kernel::Vm::Identity _id; + unsigned _vcpu_id_alloc { 0 }; static size_t _ds_size(); bool _valid_id(Vcpu_id id) { return id.id < Board::VCPU_MAX; } diff --git a/repos/base-hw/src/include/hw/spec/arm/cpu.h b/repos/base-hw/src/include/hw/spec/arm/cpu.h index 95508266e8..6b85e0b98c 100644 --- a/repos/base-hw/src/include/hw/spec/arm/cpu.h +++ b/repos/base-hw/src/include/hw/spec/arm/cpu.h @@ -36,6 +36,9 @@ struct Hw::Arm_cpu struct Me : Bitfield<31, 1> { }; /* multiprocessing extension */ ); + /* Virtual Multiprocessor Affinity Register */ + ARM_CP15_REGISTER_32BIT(Vmpidr, c0, c0, 4, 5); + /* System Control Register */ ARM_CP15_REGISTER_32BIT(Sctlr, c1, c0, 0, 0, struct M : Bitfield<0,1> { }; /* enable MMU */ diff --git a/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc b/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc index a572e3f4b2..f1482762fb 100644 --- a/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc +++ b/repos/base-hw/src/lib/hw/spec/32bit/memory_map.cc @@ -46,7 +46,7 @@ Memory_region const Hw::Mm::hypervisor_exception_vector() { return Memory_region(0xfff10000UL, 0x1000UL); } Memory_region const Hw::Mm::hypervisor_stack() { - return Memory_region(0xfff12000UL, 0x1000UL); } + return Memory_region(0xfff20000UL, 0x10000UL); } Memory_region const Hw::Mm::boot_info() { return Memory_region(0xfffe0000UL, 0x1000UL); } diff --git a/repos/base-hw/src/lib/hw/spec/64bit/memory_map.cc b/repos/base-hw/src/lib/hw/spec/64bit/memory_map.cc index cf5c8a8c10..2c77ec90d5 100644 --- a/repos/base-hw/src/lib/hw/spec/64bit/memory_map.cc +++ b/repos/base-hw/src/lib/hw/spec/64bit/memory_map.cc @@ -51,7 +51,7 @@ Memory_region const Hw::Mm::hypervisor_exception_vector() { return Memory_region(0xffffffe050000000UL, 0x2000UL); } Memory_region const Hw::Mm::hypervisor_stack() { - return Memory_region(0xffffffe050003000UL, 0x1000UL); } + return Memory_region(0xffffffe060000000UL, 0x10000UL); } Memory_region const Hw::Mm::supervisor_exception_vector() { return Memory_region(KERNEL_START, 0x1000UL); }