base-hw: Add basic Zynq-7000 support (QEMU)

Ref #1599
This commit is contained in:
Johannes Schlatow
2015-09-02 13:59:31 +02:00
committed by Christian Helmuth
parent 458b4d6fc4
commit 40b31876d2
18 changed files with 655 additions and 90 deletions

View File

@ -0,0 +1,100 @@
/*
* \brief L2 outer cache controller ARM PL310
* \author Johannes Schlatow
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2014-06-02
*/
/*
* Copyright (C) 2014-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _SPEC__ARM__PL310_H_
#define _SPEC__ARM__PL310_H_
/* Genode includes */
#include <util/mmio.h>
namespace Arm
{
using Genode::addr_t;
class Pl310;
}
/**
* L2 outer cache controller
*/
class Arm::Pl310 : Genode::Mmio
{
protected:
struct Control : Register <0x100, 32>
{
struct Enable : Bitfield<0,1> { };
};
struct Aux : Register<0x104, 32>
{
struct Associativity : Bitfield<16,1> { };
struct Way_size : Bitfield<17,3> { };
struct Share_override : Bitfield<22,1> { };
struct Reserved : Bitfield<25,1> { };
struct Ns_lockdown : Bitfield<26,1> { };
struct Ns_irq_ctrl : Bitfield<27,1> { };
struct Data_prefetch : Bitfield<28,1> { };
struct Inst_prefetch : Bitfield<29,1> { };
struct Early_bresp : Bitfield<30,1> { };
static access_t init_value()
{
access_t v = 0;
Associativity::set(v, 1);
Way_size::set(v, 3);
Share_override::set(v, 1);
Reserved::set(v, 1);
Ns_lockdown::set(v, 1);
Ns_irq_ctrl::set(v, 1);
Data_prefetch::set(v, 1);
Inst_prefetch::set(v, 1);
Early_bresp::set(v, 1);
return v;
}
};
struct Irq_mask : Register <0x214, 32> { };
struct Irq_clear : Register <0x220, 32> { };
struct Cache_sync : Register <0x730, 32> { };
struct Invalidate_by_way : Register <0x77c, 32> { };
struct Clean_invalidate_by_way : Register <0x7fc, 32> { };
inline void _sync() { while (read<Cache_sync>()) ; }
void _init()
{
write<Irq_mask>(0);
write<Irq_clear>(~0);
}
public:
Pl310(addr_t const base) : Mmio(base) { }
void flush()
{
write<Clean_invalidate_by_way>((1 << 16) - 1);
_sync();
}
void invalidate()
{
write<Invalidate_by_way>((1 << 16) - 1);
_sync();
}
};
#endif /* _SPEC__ARM__PL310_H_ */

View File

@ -1,11 +1,12 @@
/*
* \brief Board driver for core on pandaboard
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2014-06-02
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
* Copyright (C) 2014-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
@ -15,105 +16,69 @@
#define _BOARD_H_
/* core includes */
#include <util/mmio.h>
#include <spec/cortex_a9/board_support.h>
#include <spec/arm/pl310.h>
namespace Genode
{
struct Board : Cortex_a9::Board
{
/**
* L2 outer cache controller
*/
struct Pl310 : Mmio {
class Pl310;
class Board;
}
enum Trustzone_hypervisor_syscalls {
L2_CACHE_SET_DEBUG_REG = 0x100,
L2_CACHE_ENABLE_REG = 0x102,
L2_CACHE_AUX_REG = 0x109,
};
/**
* L2 outer cache controller
*/
class Genode::Pl310 : public Arm::Pl310
{
private:
static inline void
trustzone_hypervisor_call(addr_t func, addr_t val)
{
register addr_t _func asm("r12") = func;
register addr_t _val asm("r0") = val;
asm volatile("dsb; smc #0" :: "r" (_func), "r" (_val)
: "memory", "cc", "r1", "r2", "r3", "r4", "r5",
"r6", "r7", "r8", "r9", "r10", "r11");
}
struct Control : Register <0x100, 32>
{
struct Enable : Bitfield<0,1> {};
};
struct Aux : Register<0x104, 32>
{
struct Associativity : Bitfield<16,1> { };
struct Way_size : Bitfield<17,3> { };
struct Share_override : Bitfield<22,1> { };
struct Reserved : Bitfield<25,1> { };
struct Ns_lockdown : Bitfield<26,1> { };
struct Ns_irq_ctrl : Bitfield<27,1> { };
struct Data_prefetch : Bitfield<28,1> { };
struct Inst_prefetch : Bitfield<29,1> { };
struct Early_bresp : Bitfield<30,1> { };
static access_t init_value()
{
access_t v = 0;
Associativity::set(v, 1);
Way_size::set(v, 3);
Share_override::set(v, 1);
Reserved::set(v, 1);
Ns_lockdown::set(v, 1);
Ns_irq_ctrl::set(v, 1);
Data_prefetch::set(v, 1);
Inst_prefetch::set(v, 1);
Early_bresp::set(v, 1);
return v;
}
};
struct Irq_mask : Register <0x214, 32> {};
struct Irq_clear : Register <0x220, 32> {};
struct Cache_sync : Register <0x730, 32> {};
struct Invalidate_by_way : Register <0x77c, 32> {};
struct Clean_invalidate_by_way : Register <0x7fc, 32> {};
inline void sync() { while (read<Cache_sync>()) ; }
void invalidate()
{
write<Invalidate_by_way>((1 << 16) - 1);
sync();
}
void flush()
{
trustzone_hypervisor_call(L2_CACHE_SET_DEBUG_REG, 0x3);
write<Clean_invalidate_by_way>((1 << 16) - 1);
sync();
trustzone_hypervisor_call(L2_CACHE_SET_DEBUG_REG, 0x0);
}
Pl310(addr_t const base) : Mmio(base)
{
trustzone_hypervisor_call(L2_CACHE_AUX_REG,
Pl310::Aux::init_value());
trustzone_hypervisor_call(L2_CACHE_ENABLE_REG, 1);
write<Irq_mask>(0);
write<Irq_clear>(0xffffffff);
}
enum Secure_monitor_syscalls
{
L2_CACHE_SET_DEBUG_REG = 0x100,
L2_CACHE_ENABLE_REG = 0x102,
L2_CACHE_AUX_REG = 0x109,
};
static inline void _secure_monitor_call(addr_t func, addr_t val)
{
register addr_t _func asm("r12") = func;
register addr_t _val asm("r0") = val;
asm volatile(
"dsb; smc #0" ::
"r" (_func), "r" (_val) :
"memory", "cc", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11");
}
public:
void flush()
{
_secure_monitor_call(L2_CACHE_SET_DEBUG_REG, 0x3);
Arm::Pl310::flush();
_secure_monitor_call(L2_CACHE_SET_DEBUG_REG, 0x0);
}
Pl310(addr_t const base) : Arm::Pl310(base)
{
_secure_monitor_call(L2_CACHE_AUX_REG, Aux::init_value());
_secure_monitor_call(L2_CACHE_ENABLE_REG, 1);
_init();
}
};
/**
* Board driver for core
*/
class Genode::Board : public Cortex_a9::Board
{
public:
static void outer_cache_invalidate();
static void outer_cache_flush();
static void prepare_kernel();
static void secondary_cpus_ip(void * const ip) { }
static bool is_smp() { return true; }
};
}
};
#endif /* _BOARD_H_ */

View File

@ -0,0 +1,44 @@
/*
* \brief Serial output driver for core
* \author Johannes Schlatow
* \date 2014-12-15
*/
/*
* Copyright (C) 2014-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _SERIAL_H_
#define _SERIAL_H_
/* core includes */
#include <board.h>
/* Genode includes */
#include <drivers/uart/xilinx_uartps_base.h>
namespace Genode { class Serial; }
/**
* Serial output driver for core
*/
class Genode::Serial : public Xilinx_uartps_base
{
public:
/**
* Constructor
*
* \param baud_rate targeted transfer baud-rate
*/
Serial(unsigned const baud_rate)
:
Xilinx_uartps_base(Board::UART_0_MMIO_BASE,
Board::UART_CLOCK, baud_rate)
{ }
};
#endif /* _SERIAL_H_ */

View File

@ -0,0 +1,53 @@
/*
* \brief Board driver for core on Zynq
* \author Johannes Schlatow
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2014-06-02
*/
/*
* Copyright (C) 2014-2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
/* core includes */
#include <spec/cortex_a9/board_support.h>
#include <spec/arm/pl310.h>
namespace Genode
{
class Pl310;
class Board;
}
/**
* L2 outer cache controller
*/
class Genode::Pl310 : public Arm::Pl310
{
public:
Pl310(addr_t const base) : Arm::Pl310(base) { _init(); }
};
/**
* Board driver for core
*/
class Genode::Board : public Cortex_a9::Board
{
public:
static void outer_cache_invalidate();
static void outer_cache_flush();
static void prepare_kernel();
static void secondary_cpus_ip(void * const ip) { }
static bool is_smp() { return true; }
};
#endif /* _BOARD_H_ */

View File

@ -62,8 +62,8 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i)
}
static Board::Pl310 * l2_cache() {
return unmanaged_singleton<Board::Pl310>(Board::PL310_MMIO_BASE); }
static Genode::Pl310 * l2_cache() {
return unmanaged_singleton<Genode::Pl310>(Board::PL310_MMIO_BASE); }
void Board::outer_cache_invalidate() { l2_cache()->invalidate(); }

View File

@ -0,0 +1,75 @@
/*
* \brief Platform implementations specific for base-hw and Zynq
* \author Johannes Schlatow
* \date 2014-12-15
*/
/*
* Copyright (C) 2012-2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <platform.h>
#include <board.h>
#include <cpu.h>
#include <pic.h>
#include <unmanaged_singleton.h>
using namespace Genode;
Native_region * Platform::_ram_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Board::RAM_0_BASE, Board::RAM_0_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Board::MMIO_0_BASE, Board::MMIO_0_SIZE },
{ Board::MMIO_1_BASE, Board::MMIO_1_SIZE },
{ Board::QSPI_MMIO_BASE, Board::QSPI_MMIO_SIZE },
{ Board::OCM_MMIO_BASE, Board::OCM_MMIO_SIZE },
{ Board::AXI_0_MMIO_BASE, Board::AXI_0_MMIO_SIZE },
{ Board::AXI_1_MMIO_BASE, Board::AXI_1_MMIO_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* core timer and PIC */
{ Board::CORTEX_A9_PRIVATE_MEM_BASE,
Board::CORTEX_A9_PRIVATE_MEM_SIZE },
/* core UART */
{ Board::UART_0_MMIO_BASE, Board::UART_SIZE },
/* L2 cache controller */
{ Board::PL310_MMIO_BASE, Board::PL310_MMIO_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Cpu::User_context::User_context() { cpsr = Psr::init_user(); }
static Genode::Pl310 * l2_cache() {
return unmanaged_singleton<Genode::Pl310>(Board::PL310_MMIO_BASE); }
void Genode::Board::outer_cache_invalidate() { l2_cache()->invalidate(); }
void Genode::Board::outer_cache_flush() { l2_cache()->flush(); }
void Genode::Board::prepare_kernel() { l2_cache()->invalidate(); }