hw: enable eager FPU context switch for ARM
* Add an ieee754 FPU test * Remove simple fpu test Fix #2822
This commit is contained in:
committed by
Christian Helmuth
parent
4b4247f412
commit
d7fa4cfb8b
@@ -51,6 +51,11 @@ struct Genode::Vm_state : Genode::Cpu_state_modes
|
||||
Genode::uint32_t tls3;
|
||||
Genode::uint32_t cpacr;
|
||||
|
||||
/**
|
||||
* Fpu registers
|
||||
*/
|
||||
Genode::uint32_t fpscr;
|
||||
Genode::uint64_t d0_d31[32];
|
||||
|
||||
/**
|
||||
* Timer related registers
|
||||
|
||||
@@ -31,6 +31,13 @@ struct Genode::Vm_state : Genode::Cpu_state_modes
|
||||
Genode::addr_t dfar;
|
||||
Genode::addr_t ttbr[2];
|
||||
Genode::addr_t ttbrc;
|
||||
|
||||
/**
|
||||
* Fpu registers
|
||||
*/
|
||||
Genode::uint32_t fpscr;
|
||||
Genode::uint64_t d0_d31[32];
|
||||
|
||||
Genode::addr_t irq_injection;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,5 +16,7 @@ SRC_CC += spec/arm/kernel/thread_update_pd.cc
|
||||
SRC_CC += kernel/vm_thread_off.cc
|
||||
SRC_CC += kernel/kernel.cc
|
||||
|
||||
SRC_S += spec/arm/vfpv2.s
|
||||
|
||||
# include less specific configuration
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm/core-hw.inc
|
||||
|
||||
@@ -11,5 +11,7 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/arm_v7
|
||||
SRC_CC += spec/arm_v7/cpu.cc
|
||||
SRC_CC += spec/arm_v7/perf_counter.cc
|
||||
|
||||
SRC_S += spec/arm/vfpv3-d32.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/spec/arm/core-hw.inc
|
||||
|
||||
@@ -13,6 +13,6 @@ NR_OF_CPUS = 2
|
||||
# we need more specific compiler hints for some 'special' assembly code
|
||||
# override -march=armv7-a because it conflicts with -mcpu=cortex-a15
|
||||
#
|
||||
CC_MARCH = -mcpu=cortex-a15
|
||||
CC_MARCH = -mcpu=cortex-a15 -mfpu=vfpv3 -mfloat-abi=softfp
|
||||
|
||||
include $(REP_DIR)/lib/mk/bootstrap-hw.inc
|
||||
|
||||
@@ -25,7 +25,7 @@ NR_OF_CPUS = 2
|
||||
# we need more specific compiler hints for some 'special' assembly code
|
||||
# override -march=armv7-a because it conflicts with -mcpu=cortex-a15
|
||||
#
|
||||
CC_MARCH = -mcpu=cortex-a15
|
||||
CC_MARCH = -mcpu=cortex-a15 -mfpu=vfpv3 -mfloat-abi=softfp
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/spec/exynos5/core-hw.inc
|
||||
|
||||
@@ -10,7 +10,6 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/arm_gic
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/cortex_a9/kernel/cpu.cc
|
||||
SRC_CC += spec/cortex_a9/fpu.cc
|
||||
SRC_CC += spec/cortex_a9/board.cc
|
||||
SRC_CC += spec/cortex_a9/timer.cc
|
||||
SRC_CC += spec/arm/smp/kernel/thread_update_pd.cc
|
||||
|
||||
@@ -9,6 +9,6 @@ SRC_CC += hw/spec/arm/arm_v7_cpu.cc
|
||||
SRC_CC += hw/spec/32bit/memory_map.cc
|
||||
SRC_S += bootstrap/spec/arm/crt0.s
|
||||
|
||||
CC_MARCH = -mcpu=cortex-a9
|
||||
CC_MARCH = -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp
|
||||
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc
|
||||
|
||||
@@ -13,7 +13,7 @@ SRC_CC += platform_services.cc
|
||||
|
||||
NR_OF_CPUS += 2
|
||||
|
||||
CC_MARCH = -mcpu=cortex-a9
|
||||
CC_MARCH = -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/spec/cortex_a9/core-hw.inc
|
||||
|
||||
@@ -62,6 +62,22 @@
|
||||
add sp, r0, r1
|
||||
|
||||
|
||||
/****************
|
||||
** Enable VFP **
|
||||
****************/
|
||||
|
||||
mov r0, #0xf
|
||||
lsl r0, #20
|
||||
mcr p15, 0, r0, c1, c0, 2 /* write to CPACR to enable VFP access */
|
||||
mcr p15, 0, r0, c7, c5, 4 /* deprecated ISB instruction <= ARMv6 */
|
||||
|
||||
vmrs r0, fpexc /* enable the VFP by read/write fpexc */
|
||||
mov r1, #1 /* enable bit 30 */
|
||||
lsl r1, #30
|
||||
orr r0, r1
|
||||
vmsr fpexc, r0
|
||||
|
||||
|
||||
/************************************
|
||||
** Jump to high-level entry point **
|
||||
************************************/
|
||||
|
||||
@@ -58,7 +58,13 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
|
||||
}
|
||||
};
|
||||
|
||||
struct alignas(4) Context : Cpu_state
|
||||
struct Fpu_context
|
||||
{
|
||||
uint32_t fpscr { 1UL << 24 }; /* VFP/SIMD - status/control register */
|
||||
uint64_t d0_d31[32]; /* VFP/SIMD - general purpose registers */
|
||||
};
|
||||
|
||||
struct alignas(4) Context : Cpu_state, Fpu_context
|
||||
{
|
||||
Context(bool privileged);
|
||||
};
|
||||
@@ -146,8 +152,6 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
|
||||
** Dummies **
|
||||
*************/
|
||||
|
||||
bool retry_undefined_instr(Context&) { return false; }
|
||||
|
||||
/**
|
||||
* Return kernel name of the executing CPU
|
||||
*/
|
||||
|
||||
@@ -115,6 +115,17 @@
|
||||
stmia r0!, {r1-r3} /* save pc, cpsr and exception type */
|
||||
clrex /* clear exclusive access needed for cmpxchg */
|
||||
cps #SVC_MODE
|
||||
|
||||
mov r1, #1 /* clear exception state of the VFP */
|
||||
lsl r1, #30
|
||||
vmsr fpexc, r1
|
||||
adr r1, _fpu_save
|
||||
ldr r1, [r1]
|
||||
blx r1
|
||||
|
||||
/*
|
||||
* Go to kernel entry code
|
||||
*/
|
||||
adr lr, _kernel_entry
|
||||
ldr lr, [lr]
|
||||
bx lr
|
||||
@@ -122,6 +133,9 @@
|
||||
_kernel_entry:
|
||||
.long kernel
|
||||
|
||||
_fpu_save:
|
||||
.long vfp_save_fpu_context
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
@@ -133,3 +147,21 @@
|
||||
idle_thread_main:
|
||||
wfi
|
||||
b idle_thread_main
|
||||
|
||||
|
||||
/*****************************
|
||||
** kernel to userland switch **
|
||||
*******************************/
|
||||
|
||||
.global kernel_to_user_context_switch
|
||||
kernel_to_user_context_switch:
|
||||
push { r0 }
|
||||
mov r0, r1
|
||||
bl vfp_load_fpu_context
|
||||
pop { r0 }
|
||||
mov sp, r0
|
||||
ldr lr, [sp, #15*4]
|
||||
ldr r1, [sp, #16*4]
|
||||
msr spsr_cxsf, r1
|
||||
ldm sp, {r0-r14}^
|
||||
subs pc, lr, #0
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
* \brief ARM-specific FPU driver for core
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin stein
|
||||
* \date 2016-01-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 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__FPU_H_
|
||||
#define _CORE__SPEC__ARM__FPU_H_
|
||||
|
||||
#include <util/register.h>
|
||||
|
||||
namespace Genode { class Fpu; }
|
||||
|
||||
/**
|
||||
* FPU driver for the ARM VFPv3-D16 architecture
|
||||
*/
|
||||
class Genode::Fpu
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Floating-point Status and Control Register
|
||||
*/
|
||||
struct Fpscr : Register<32>
|
||||
{
|
||||
/**
|
||||
* Read register value
|
||||
*/
|
||||
static access_t read()
|
||||
{
|
||||
/* FIXME: See annotation 1. */
|
||||
access_t v;
|
||||
asm volatile ("mrc p10, 7, %[v], cr1, cr0, 0" : [v] "=r" (v) ::);
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override register value
|
||||
*
|
||||
* \param v write value
|
||||
*/
|
||||
static void write(access_t const v)
|
||||
{
|
||||
/* FIXME: See annotation 1. */
|
||||
asm volatile ("mcr p10, 7, %[v], cr1, cr0, 0" :: [v] "r" (v) :);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Floating-Point Exception Control register
|
||||
*/
|
||||
struct Fpexc : Register<32>
|
||||
{
|
||||
struct En : Bitfield<30, 1> { };
|
||||
|
||||
/**
|
||||
* Read register value
|
||||
*/
|
||||
static access_t read()
|
||||
{
|
||||
/* FIXME: See annotation 1. */
|
||||
access_t v;
|
||||
asm volatile ("mrc p10, 7, %[v], cr8, cr0, 0" : [v] "=r" (v) ::);
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override register value
|
||||
*
|
||||
* \param v write value
|
||||
*/
|
||||
static void write(access_t const v)
|
||||
{
|
||||
/* FIXME: See annotation 1. */
|
||||
asm volatile ("mcr p10, 7, %[v], cr8, cr0, 0" :: [v] "r" (v) :);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
class Context
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Context(Context const &);
|
||||
Context &operator = (Context const &);
|
||||
|
||||
friend class Fpu;
|
||||
|
||||
struct
|
||||
{
|
||||
/* advanced FP/SIMD - system registers */
|
||||
uint32_t fpscr;
|
||||
uint32_t fpexc;
|
||||
|
||||
/* advanced FP/SIMD - general purpose registers d0-d15 */
|
||||
uint64_t d0, d1, d2, d3, d4, d5, d6, d7;
|
||||
uint64_t d8, d9, d10, d11, d12, d13, d14, d15;
|
||||
};
|
||||
|
||||
Fpu * _fpu = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
Context() : fpexc(Fpexc::En::bits(1)) { }
|
||||
|
||||
~Context() { if (_fpu) _fpu->unset(*this); }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Context * _context = nullptr;
|
||||
|
||||
/**
|
||||
* Enable FPU
|
||||
*/
|
||||
void _enable()
|
||||
{
|
||||
Fpexc::access_t fpexc = Fpexc::read();
|
||||
Fpexc::En::set(fpexc, 1);
|
||||
Fpexc::write(fpexc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable FPU
|
||||
*/
|
||||
void _disable()
|
||||
{
|
||||
Fpexc::access_t fpexc = Fpexc::read();
|
||||
Fpexc::En::set(fpexc, 0);
|
||||
Fpexc::write(fpexc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save FPU context
|
||||
*/
|
||||
void _save()
|
||||
{
|
||||
/* save system registers */
|
||||
_context->fpexc = Fpexc::read();
|
||||
_context->fpscr = Fpscr::read();
|
||||
|
||||
/*
|
||||
* Save D0 - D15
|
||||
*
|
||||
* FIXME: See annotation 2.
|
||||
*/
|
||||
void * const d0_d15_base = &_context->d0;
|
||||
asm volatile (
|
||||
"stc p11, cr0, [%[d0_d15_base]], #128"
|
||||
:: [d0_d15_base] "r" (d0_d15_base) : );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load context to FPU
|
||||
*/
|
||||
void _load()
|
||||
{
|
||||
/* load system registers */
|
||||
Fpexc::write(_context->fpexc);
|
||||
Fpscr::write(_context->fpscr);
|
||||
|
||||
/*
|
||||
* Load D0 - D15
|
||||
*
|
||||
* FIXME: See annotation 2.
|
||||
*/
|
||||
void * const d0_d15_base = &_context->d0;
|
||||
asm volatile (
|
||||
"ldc p11, cr0, [%[d0_d15_base]], #128"
|
||||
:: [d0_d15_base] "r" (d0_d15_base) : );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return wether the FPU is enabled
|
||||
*/
|
||||
bool _enabled()
|
||||
{
|
||||
Fpexc::access_t fpexc = Fpexc::read();
|
||||
return Fpexc::En::get(fpexc);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Initialize FPU
|
||||
*/
|
||||
void init();
|
||||
|
||||
void switch_to(Context & context)
|
||||
{
|
||||
if (_context == &context) return;
|
||||
_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return wether the FPU fault can be solved
|
||||
*
|
||||
* \param state CPU state of the user
|
||||
*/
|
||||
bool fault(Context & context)
|
||||
{
|
||||
if (_enabled()) { return false; }
|
||||
_enable();
|
||||
if (_context != &context) {
|
||||
if (_context) {
|
||||
_save();
|
||||
_context->_fpu = nullptr;
|
||||
}
|
||||
_context = &context;
|
||||
_context->_fpu = this;
|
||||
_load();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset FPU context
|
||||
*/
|
||||
void unset(Context &context) {
|
||||
if (_context == &context) _context = nullptr; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Annotation 1
|
||||
*
|
||||
* According to the ARMv7 manual this should be done via vmsr/vmrs instruction
|
||||
* but it seems that binutils 2.22 doesn't fully support this yet. Hence, we
|
||||
* use a co-processor instruction instead. The parameters to target the
|
||||
* register this way can be determined via 'sys/arm/include/vfp.h' and
|
||||
* 'sys/arm/arm/vfp.c' of the FreeBSD head branch as from 2014.04.17.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Annotation 2
|
||||
*
|
||||
* According to the ARMv7 manual this should be done via vldm/vstm instruction
|
||||
* but it seems that binutils 2.22 doesn't fully support this yet. Hence, we
|
||||
* use a co-processor instruction instead. The parameters to target the
|
||||
* register this way can be determined via 'sys/arm/arm/vfp.c' of the FreeBSD
|
||||
* head branch as from 2014.04.17.
|
||||
*/
|
||||
|
||||
#endif /* _CORE__SPEC__ARM__FPU_H_ */
|
||||
@@ -19,6 +19,9 @@
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
extern "C" void kernel_to_user_context_switch(Cpu::Context*, Cpu::Fpu_context*);
|
||||
|
||||
|
||||
void Thread::exception(Cpu & cpu)
|
||||
{
|
||||
switch (regs->cpu_exception) {
|
||||
@@ -34,7 +37,6 @@ void Thread::exception(Cpu & cpu)
|
||||
_interrupt(cpu.id());
|
||||
return;
|
||||
case Cpu::Context::UNDEFINED_INSTRUCTION:
|
||||
if (_cpu->retry_undefined_instr(*regs)) { return; }
|
||||
Genode::warning(*this, ": undefined instruction at ip=",
|
||||
Genode::Hex(regs->ip));
|
||||
_die();
|
||||
@@ -106,14 +108,8 @@ void Thread::proceed(Cpu & cpu)
|
||||
cpu.switch_to(*regs, pd()->mmu_regs);
|
||||
|
||||
regs->cpu_exception = cpu.stack_start();
|
||||
|
||||
asm volatile("mov sp, %0 \n"
|
||||
"msr spsr_cxsf, %1 \n"
|
||||
"mov lr, %2 \n"
|
||||
"ldm sp, {r0-r14}^ \n"
|
||||
"subs pc, lr, #0 \n"
|
||||
:: "r" (static_cast<Cpu::Context*>(&*regs)),
|
||||
"r" (regs->cpsr), "r" (regs->ip));
|
||||
kernel_to_user_context_switch((static_cast<Cpu::Context*>(&*regs)),
|
||||
(static_cast<Cpu::Fpu_context*>(&*regs)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
31
repos/base-hw/src/core/spec/arm/vfpv2.s
Normal file
31
repos/base-hw/src/core/spec/arm/vfpv2.s
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* \brief VFPv2 context load/store
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2018-05-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
.section .text
|
||||
|
||||
.global vfp_save_fpu_context
|
||||
vfp_save_fpu_context:
|
||||
vmrs r1, fpscr
|
||||
stmia r0!, {r1}
|
||||
vstm r0!, {d0-d15}
|
||||
mov pc, lr
|
||||
|
||||
|
||||
.global vfp_load_fpu_context
|
||||
vfp_load_fpu_context:
|
||||
push { r1, lr }
|
||||
ldr r1, [r0]
|
||||
vmsr fpscr, r1
|
||||
add r1, r0, #4
|
||||
vldm r1!, {d0-d15}
|
||||
pop { r1, pc }
|
||||
34
repos/base-hw/src/core/spec/arm/vfpv3-d32.s
Normal file
34
repos/base-hw/src/core/spec/arm/vfpv3-d32.s
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* \brief VFPv3-D32 context load/store
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2018-05-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
.section .text
|
||||
|
||||
.global vfp_save_fpu_context
|
||||
vfp_save_fpu_context:
|
||||
push { r1, lr }
|
||||
vmrs r1, fpscr
|
||||
stmia r0!, {r1}
|
||||
vstm r0!, {d0-d15}
|
||||
vstm r0!, {d16-d31}
|
||||
pop { r1, pc }
|
||||
|
||||
|
||||
.global vfp_load_fpu_context
|
||||
vfp_load_fpu_context:
|
||||
push { r1, lr }
|
||||
ldr r1, [r0]
|
||||
vmsr fpscr, r1
|
||||
add r1, r0, #4
|
||||
vldm r1!, {d0-d15}
|
||||
vldm r1!, {d16-d31}
|
||||
pop { r1, pc }
|
||||
@@ -69,10 +69,14 @@ monitor_mode_exception_vector:
|
||||
_nonsecure_kernel_entry:
|
||||
ldr lr, [sp, #17*4] /* load kernel sp from vm context */
|
||||
stmia r0!, {r1-r2} /* save spsr, and exception reason */
|
||||
mov r1, #1 /* clear exception state of the VFP */
|
||||
lsl r1, #30
|
||||
vmsr fpexc, r1
|
||||
mrc p15, 0, r3, c6, c0, 0 /* move DFAR to r3 */
|
||||
mrc p15, 0, r4, c2, c0, 0 /* move TTBR0 to r4 */
|
||||
mrc p15, 0, r5, c2, c0, 1 /* move TTBR1 to r5 */
|
||||
mrc p15, 0, r6, c2, c0, 2 /* move TTBRC to r6 */
|
||||
vmrs r7, fpscr /* move FPU ctrl to r7 */
|
||||
mov r1, #0
|
||||
mcr p15, 0, r1, c1, c1, 0 /* disable non-secure bit */
|
||||
.irp mode,27,19,23,18,17 /* save mode specific registers */
|
||||
@@ -81,7 +85,9 @@ monitor_mode_exception_vector:
|
||||
stmia r0!, {r1,sp,lr} /* store mode-specific sp and lr */
|
||||
.endr
|
||||
stmia r0!, {r8-r12} /* save fiq r8-r12 */
|
||||
stmia r0!, {r3-r6} /* save MMU registers */
|
||||
stmia r0!, {r3-r7} /* save MMU registers */
|
||||
vstm r0!, {d0-d15} /* save FPU registers */
|
||||
vstm r0!, {d16-d31}
|
||||
cps #22 /* switch back to monitor mode */
|
||||
mov r0, #0b111010011 /* spsr to SVC mode, irqs masked */
|
||||
msr spsr_cxsf, r0
|
||||
@@ -109,6 +115,12 @@ monitor_mode_enter_normal_world:
|
||||
msr spsr_cxfs, r2 /* load mode's spsr */
|
||||
.endr
|
||||
ldmia r0!, {r8 - r12} /* load fiq r8-r12 */
|
||||
add r0, r0, #4*4
|
||||
ldr r1, [r0]
|
||||
vmsr fpscr, r1
|
||||
add r1, r0, #4
|
||||
vldm r1!, {d0-d15}
|
||||
vldm r1!, {d16-d31}
|
||||
cps #22 /* switch to monitor mode */
|
||||
ldmia sp, {r0-lr}^ /* load user r0-r12,sp,lr */
|
||||
str lr, [sp, #17*4] /* store kernel sp in vm context */
|
||||
|
||||
@@ -91,11 +91,16 @@ _host_to_vm:
|
||||
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}
|
||||
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}
|
||||
ldmia sp, {r0-r12} /* load vm's r0-r12 */
|
||||
eret
|
||||
|
||||
@@ -106,6 +111,8 @@ _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 */
|
||||
@@ -130,7 +137,15 @@ _vm_to_host:
|
||||
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}
|
||||
stm r0!, {r3-r12}
|
||||
add r0, r0, #4
|
||||
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}
|
||||
add r0, sp, #13*4
|
||||
ldr r3, _vt_host_context_ptr
|
||||
ldr sp, [r3]
|
||||
|
||||
@@ -135,13 +135,6 @@ class Genode::Cpu : public Arm_v7_cpu
|
||||
if (mmu_context.id() && (Ttbr0_64bit::read() != mmu_context.ttbr0))
|
||||
Ttbr0_64bit::write(mmu_context.ttbr0);
|
||||
}
|
||||
|
||||
|
||||
/*************
|
||||
** Dummies **
|
||||
*************/
|
||||
|
||||
bool retry_undefined_instr(Context&) { return false; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__CORTEX_A15__CPU_H_ */
|
||||
|
||||
@@ -16,75 +16,43 @@
|
||||
#define _CORE__SPEC__CORTEX_A9__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <spec/arm/fpu.h>
|
||||
#include <spec/arm_v7/cpu_support.h>
|
||||
#include <board.h>
|
||||
|
||||
namespace Genode { class Cpu; }
|
||||
namespace Genode { struct Cpu; }
|
||||
|
||||
class Genode::Cpu : public Arm_v7_cpu
|
||||
struct Genode::Cpu : Arm_v7_cpu
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Write back dirty cache lines and invalidate whole data cache
|
||||
*/
|
||||
void clean_invalidate_data_cache()
|
||||
{
|
||||
clean_invalidate_inner_data_cache();
|
||||
Board::l2_cache().clean_invalidate();
|
||||
}
|
||||
|
||||
Fpu _fpu { };
|
||||
/**
|
||||
* Invalidate whole data cache
|
||||
*/
|
||||
void invalidate_data_cache()
|
||||
{
|
||||
invalidate_inner_data_cache();
|
||||
Board::l2_cache().invalidate();
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Clean and invalidate data-cache for virtual region
|
||||
* 'base' - 'base + size'
|
||||
*/
|
||||
void clean_invalidate_data_cache_by_virt_region(addr_t base,
|
||||
size_t const size)
|
||||
{
|
||||
Arm_cpu::clean_invalidate_data_cache_by_virt_region(base, size);
|
||||
Board::l2_cache().clean_invalidate();
|
||||
}
|
||||
|
||||
struct Context : Arm_cpu::Context, Fpu::Context
|
||||
{
|
||||
Context(bool privileged)
|
||||
: Arm_cpu::Context(privileged) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Next cpu context to switch to
|
||||
*
|
||||
* \param context context to switch to
|
||||
*/
|
||||
void switch_to(Context & context, Mmu_context & mmu_context)
|
||||
{
|
||||
Arm_cpu::switch_to(context, mmu_context);
|
||||
_fpu.switch_to(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return wether to retry an undefined user instruction after this call
|
||||
*
|
||||
* \param state CPU state of the user
|
||||
*/
|
||||
bool retry_undefined_instr(Context & context) {
|
||||
return _fpu.fault(context); }
|
||||
|
||||
/**
|
||||
* Write back dirty cache lines and invalidate whole data cache
|
||||
*/
|
||||
void clean_invalidate_data_cache()
|
||||
{
|
||||
clean_invalidate_inner_data_cache();
|
||||
Board::l2_cache().clean_invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate whole data cache
|
||||
*/
|
||||
void invalidate_data_cache()
|
||||
{
|
||||
invalidate_inner_data_cache();
|
||||
Board::l2_cache().invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean and invalidate data-cache for virtual region
|
||||
* 'base' - 'base + size'
|
||||
*/
|
||||
void clean_invalidate_data_cache_by_virt_region(addr_t base,
|
||||
size_t const size)
|
||||
{
|
||||
Arm_cpu::clean_invalidate_data_cache_by_virt_region(base, size);
|
||||
Board::l2_cache().clean_invalidate();
|
||||
}
|
||||
|
||||
static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); }
|
||||
static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); }
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__CORTEX_A9__CPU_H_ */
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* \brief CPU driver for core
|
||||
* \author Martin stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2016-01-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 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 <cpu.h>
|
||||
|
||||
void Genode::Fpu::init()
|
||||
{
|
||||
Cpu::Cpacr::access_t cpacr = Cpu::Cpacr::read();
|
||||
Cpu::Cpacr::Cp10::set(cpacr, 3);
|
||||
Cpu::Cpacr::Cp11::set(cpacr, 3);
|
||||
Cpu::Cpacr::write(cpacr);
|
||||
_disable();
|
||||
}
|
||||
@@ -23,8 +23,6 @@
|
||||
|
||||
void Kernel::Cpu::init(Kernel::Pic &pic)
|
||||
{
|
||||
_fpu.init();
|
||||
|
||||
{
|
||||
Lock::Guard guard(data_lock());
|
||||
|
||||
|
||||
@@ -116,11 +116,6 @@ class Genode::Cpu : public Hw::X86_64_cpu
|
||||
|
||||
Fpu & fpu() { return _fpu; }
|
||||
|
||||
/**
|
||||
* Return wether to retry an undefined user instruction after this call
|
||||
*/
|
||||
bool retry_undefined_instr(Context&) { return false; }
|
||||
|
||||
/**
|
||||
* Return kernel name of the executing CPU
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user