Commit 3266e295 authored by Antônio Augusto Fröhlich's avatar Antônio Augusto Fröhlich
Browse files

This a part of Guto's solution to P3.

parent 7311811a
......@@ -9,7 +9,7 @@ __BEGIN_SYS
template<> struct Traits<Build>: public Traits_Tokens
{
// Basic configuration
static const unsigned int MODE = BUILTIN;
static const unsigned int MODE = KERNEL;
static const unsigned int ARCHITECTURE = ARMv7;
static const unsigned int MACHINE = Cortex;
static const unsigned int MODEL = Raspberry_Pi3;
......
// EPOS Semaphore Component Test Program
#include <machine/display.h>
#include <time.h>
#include <synchronizer.h>
#include <process.h>
......@@ -21,8 +20,6 @@ int philosopher(int n, int l, int c);
int main()
{
table.lock();
Display::clear();
Display::position(0, 0);
cout << "The Philosopher's Dinner:" << endl;
for(int i = 0; i < 5; i++)
......@@ -36,25 +33,12 @@ int main()
cout << "Philosophers are alive and hungry!" << endl;
Display::position(7, 44);
cout << '/';
Display::position(13, 44);
cout << '\\';
Display::position(16, 35);
cout << '|';
Display::position(13, 27);
cout << '/';
Display::position(7, 27);
cout << '\\';
Display::position(19, 0);
cout << "The dinner is served ..." << endl;
table.unlock();
for(int i = 0; i < 5; i++) {
int ret = phil[i]->join();
table.lock();
Display::position(20 + i, 0);
cout << "Philosopher " << i << " ate " << ret << " times " << endl;
table.unlock();
}
......@@ -77,30 +61,26 @@ int philosopher(int n, int l, int c)
for(int i = iterations; i > 0; i--) {
table.lock();
Display::position(l, c);
cout << "thinking";
cout << n << " thinking";
table.unlock();
Delay thinking(1000000);
table.lock();
Display::position(l, c);
cout << " hungry ";
cout << n << " hungry ";
table.unlock();
chopstick[first]->p(); // get first chopstick
chopstick[second]->p(); // get second chopstick
table.lock();
Display::position(l, c);
cout << " eating ";
cout << n << " eating ";
table.unlock();
Delay eating(500000);
table.lock();
Display::position(l, c);
cout << " sate ";
cout << n << " sate ";
table.unlock();
chopstick[first]->v(); // release first chopstick
......@@ -108,7 +88,6 @@ int philosopher(int n, int l, int c)
}
table.lock();
Display::position(l, c);
cout << " done ";
table.unlock();
......
......@@ -9,7 +9,7 @@ __BEGIN_SYS
template<> struct Traits<Build>: public Traits_Tokens
{
// Basic configuration
static const unsigned int MODE = BUILTIN;
static const unsigned int MODE = KERNEL;
static const unsigned int ARCHITECTURE = ARMv7;
static const unsigned int MACHINE = Cortex;
static const unsigned int MODEL = Raspberry_Pi3;
......
......@@ -9,7 +9,7 @@ __BEGIN_SYS
template<> struct Traits<Build>: public Traits_Tokens
{
// Basic configuration
static const unsigned int MODE = BUILTIN;
static const unsigned int MODE = KERNEL;
static const unsigned int ARCHITECTURE = ARMv7;
static const unsigned int MACHINE = Cortex;
static const unsigned int MODEL = Raspberry_Pi3;
......
......@@ -536,10 +536,15 @@ public:
static void switch_context(Context ** o, Context * n) __attribute__ ((naked));
template<typename ... Tn>
static Context * init_stack(Log_Addr usp, Log_Addr sp, void (* exit)(), int (* entry)(Tn ...), Tn ... an) {
sp -= sizeof(Context);
Context * ctx = new(sp) Context(entry, exit, usp); // init_stack is called with usp = 0 for kernel threads
static Context * init_stack(Log_Addr usp, Log_Addr ksp, void (* exit)(), int (* entry)(Tn ...), Tn ... an) {
ksp -= sizeof(Context);
Context * ctx = new(ksp) Context(entry, exit, usp); // init_stack is called with usp = 0 for kernel threads
init_stack_helper(&ctx->_r0, an ...);
if(multitask) {
// handle trampoline context here
}
return ctx;
}
......
// EPOS ARMv8 CPU Mediator Declarations
#ifndef __armv8_h
#define __armv8_h
#define __cpu_common_only__
#include <architecture/cpu.h>
#include <architecture/armv7/armv7_cpu.h>
#undef __cpu_common_only__
__BEGIN_SYS
class ARMv8_A: public ARMv7_A
{
protected:
ARMv8_A() {};
public:
static unsigned int cores() {
// Cortex A53 cannot execute "mrc p15, 4, r0, c15, c0, 0".
// The amount of cores booted is equal to the Traits value (defined at Raspberry_Pi3::pre_init::pre_init for instance, up to four)
return Traits<Build>::CPUS;
}
// We need to redefine because we also redefined cores()
static void smp_barrier(unsigned long cores = cores()) { CPU_Common::smp_barrier<&finc>(cores, id()); }
};
class CPU: private ARMv8_A
{
friend class Init_System;
private:
typedef ARMv8_A Base;
public:
// CPU Native Data Types
using CPU_Common::Reg8;
using CPU_Common::Reg16;
using CPU_Common::Reg32;
using CPU_Common::Reg64;
using Reg = CPU_Common::Reg32;
using Log_Addr = CPU_Common::Log_Addr<Reg>;
using Phy_Addr = CPU_Common::Phy_Addr<Reg>;
// CPU Context
class Context
{
public:
Context(){}
Context(Log_Addr entry, Log_Addr exit, Log_Addr usp): _flags(FLAG_DEFAULTS), _lr(exit | (thumb ? 1 : 0)), _pc(entry | (thumb ? 1 : 0)) {
if(Traits<Build>::hysterically_debugged || Traits<Thread>::trace_idle) {
_r0 = 0; _r1 = 1; _r2 = 2; _r3 = 3; _r4 = 4; _r5 = 5; _r6 = 6; _r7 = 7; _r8 = 8; _r9 = 9; _r10 = 10; _r11 = 11; _r12 = 12;
}
}
void save() volatile __attribute__ ((naked));
void load() const volatile;
friend Debug & operator<<(Debug & db, const Context & c) {
db << hex
<< "{r0=" << c._r0
<< ",r1=" << c._r1
<< ",r2=" << c._r2
<< ",r3=" << c._r3
<< ",r4=" << c._r4
<< ",r5=" << c._r5
<< ",r6=" << c._r6
<< ",r7=" << c._r7
<< ",r8=" << c._r8
<< ",r9=" << c._r9
<< ",r10=" << c._r10
<< ",r11=" << c._r11
<< ",r12=" << c._r12
<< ",sp=" << &c
<< ",lr=" << c._lr
<< ",pc=" << c._pc
<< ",psr=" << c._flags
<< "}" << dec;
return db;
}
public:
Reg32 _flags;
Reg32 _r0;
Reg32 _r1;
Reg32 _r2;
Reg32 _r3;
Reg32 _r4;
Reg32 _r5;
Reg32 _r6;
Reg32 _r7;
Reg32 _r8;
Reg32 _r9;
Reg32 _r10;
Reg32 _r11;
Reg32 _r12;
Reg32 _lr;
Reg32 _pc;
};
// I/O ports
typedef Reg16 IO_Irq;
// Interrupt Service Routines
typedef void (ISR)();
// Fault Service Routines (exception handlers)
typedef void (FSR)();
public:
CPU() {}
using Base::pc;
using Base::lr;
using Base::flags;
using Base::sp;
using Base::fr;
using Base::pdp;
using Base::id;
using Base::cores;
static Hertz clock() { return _cpu_clock; }
static void clock(const Hertz & frequency); // defined along with each machine's IOCtrl
static Hertz max_clock();
static Hertz min_clock();
static Hertz bus_clock() { return _bus_clock; }
using Base::int_enable;
using Base::int_disable;
using Base::int_enabled;
using Base::int_disabled;
using Base::halt;
using Base::tsl;
using Base::finc;
using Base::fdec;
using Base::cas;
using Base::smp_barrier;
using Base::msr12;
using Base::mrs12;
using Base::cpsr;
using Base::cpsrc;
using Base::spsr_cxsf;
using Base::elr_hyp;
using Base::r0;
using Base::r1;
using Base::ldmia;
using Base::stmia;
using Base::enable_fpu;
static void fpu_save() {
if(Traits<Build>::MODEL == Traits<Build>::Raspberry_Pi3)
ASM(" vpush {s0-s15} \n"
" vpush {s16-s31} \n");
}
static void fpu_restore() {
if(Traits<Build>::MODEL == Traits<Build>::Raspberry_Pi3)
ASM(" vpop {s0-s15} \n"
" vpop {s16-s31} \n");
}
static void switch_context(Context ** o, Context * n) __attribute__ ((naked));
template<typename ... Tn>
static Context * init_stack(Log_Addr usp, Log_Addr ksp, void (* exit)(), int (* entry)(Tn ...), Tn ... an) {
ksp -= sizeof(Context);
Context * ctx = new(ksp) Context(entry, exit, usp);
init_stack_helper(&ctx->_r0, an ...);
return ctx;
}
template<typename ... Tn>
static Log_Addr init_user_stack(Log_Addr usp, void (* exit)(), Tn ... an) {
usp -= sizeof(Context);
Context * ctx = new(usp) Context(0, exit, 0);
init_stack_helper(&ctx->_r0, an ...);
return usp;
}
static int syscall(void * message);
static void syscalled();
using CPU_Common::htole64;
using CPU_Common::htole32;
using CPU_Common::htole16;
using CPU_Common::letoh64;
using CPU_Common::letoh32;
using CPU_Common::letoh16;
using CPU_Common::htobe64;
using CPU_Common::htobe32;
using CPU_Common::htobe16;
using CPU_Common::betoh64;
using CPU_Common::betoh32;
using CPU_Common::betoh16;
using CPU_Common::htonl;
using CPU_Common::htons;
using CPU_Common::ntohl;
using CPU_Common::ntohs;
private:
template<typename Head, typename ... Tail>
static void init_stack_helper(Log_Addr sp, Head head, Tail ... tail) {
*static_cast<Head *>(sp) = head;
init_stack_helper(sp + sizeof(Head), tail ...);
}
static void init_stack_helper(Log_Addr sp) {}
static void init();
private:
static unsigned int _cpu_clock;
static unsigned int _bus_clock;
};
inline CPU::Reg64 htole64(CPU::Reg64 v) { return CPU::htole64(v); }
inline CPU::Reg32 htole32(CPU::Reg32 v) { return CPU::htole32(v); }
inline CPU::Reg16 htole16(CPU::Reg16 v) { return CPU::htole16(v); }
inline CPU::Reg64 letoh64(CPU::Reg64 v) { return CPU::letoh64(v); }
inline CPU::Reg32 letoh32(CPU::Reg32 v) { return CPU::letoh32(v); }
inline CPU::Reg16 letoh16(CPU::Reg16 v) { return CPU::letoh16(v); }
inline CPU::Reg64 htobe64(CPU::Reg64 v) { return CPU::htobe64(v); }
inline CPU::Reg32 htobe32(CPU::Reg32 v) { return CPU::htobe32(v); }
inline CPU::Reg16 htobe16(CPU::Reg16 v) { return CPU::htobe16(v); }
inline CPU::Reg64 betoh64(CPU::Reg64 v) { return CPU::betoh64(v); }
inline CPU::Reg32 betoh32(CPU::Reg32 v) { return CPU::betoh32(v); }
inline CPU::Reg16 betoh16(CPU::Reg16 v) { return CPU::betoh16(v); }
inline CPU::Reg32 htonl(CPU::Reg32 v) { return CPU::htonl(v); }
inline CPU::Reg16 htons(CPU::Reg16 v) { return CPU::htons(v); }
inline CPU::Reg32 ntohl(CPU::Reg32 v) { return CPU::ntohl(v); }
inline CPU::Reg16 ntohs(CPU::Reg16 v) { return CPU::ntohs(v); }
__END_SYS
#endif
// EPOS ARMv8 MMU Mediator Declarations
#ifndef __armv8_mmu_h
#define __armv8_mmu_h
#include <architecture/mmu.h>
#include <system/memory_map.h>
__BEGIN_SYS
class ARMv8_MMU: public MMU_Common<10, 10, 12>
{
friend class CPU;
private:
typedef Grouping_List<Frame> List;
static const bool colorful = Traits<MMU>::colorful;
static const unsigned int COLORS = Traits<MMU>::COLORS;
static const unsigned int MEM_BASE = Memory_Map::MEM_BASE;
static const unsigned int APP_LOW = Memory_Map::APP_LOW;
static const unsigned int PHY_MEM = Memory_Map::PHY_MEM;
public:
// Page Flags
class Page_Flags;
// Page_Table
class Page_Table;
// Page Directory
class Page_Directory;
// Chunk (for Segment)
class Chunk;
// Directory (for Address_Space)
class Directory;
// DMA_Buffer
class DMA_Buffer;
// Class Translation performs manual logical to physical address translations for debugging purposes only
class Translation;
public:
ARMv8_MMU() {}
static Phy_Addr alloc(unsigned int frames = 1, Color color = WHITE);
static Phy_Addr calloc(unsigned int frames = 1, Color color = WHITE);
static void free(Phy_Addr frame, int n = 1);
static void white_free(Phy_Addr frame, int n);
static unsigned int allocable(Color color = WHITE);
static Page_Directory * volatile current();
static Phy_Addr physical(Log_Addr addr);
static PT_Entry phy2pte(Phy_Addr frame, Page_Flags flags);
static Phy_Addr pte2phy(PT_Entry entry);
static PD_Entry phy2pde(Phy_Addr frame);
static Phy_Addr pde2phy(PD_Entry entry);
static void flush_tlb();
static void flush_tlb(Log_Addr addr);
static Log_Addr phy2log(Phy_Addr phy) { return Log_Addr((MEM_BASE == PHY_MEM) ? phy : (MEM_BASE > PHY_MEM) ? phy - (MEM_BASE - PHY_MEM) : phy + (PHY_MEM - MEM_BASE)); }
static Phy_Addr log2phy(Log_Addr log) { return Phy_Addr((MEM_BASE == PHY_MEM) ? log : (MEM_BASE > PHY_MEM) ? log + (MEM_BASE - PHY_MEM) : log - (PHY_MEM - MEM_BASE)); }
static Color phy2color(Phy_Addr phy);
static Color log2color(Log_Addr log);
private:
static void init();
private:
static List _free[colorful * COLORS + 1]; // +1 for WHITE
static Page_Directory * _master;
};
class MMU: public IF<Traits<System>::multitask, ARMv8_MMU, No_MMU>::Result {};
__END_SYS
#endif
// EPOS ARMv8 PMU Mediator Declarations
#ifndef __armv8_pmu_h
#define __armv8_pmu_h
#include <architecture/cpu.h>
#define __common_only__
#include <architecture/pmu.h>
#undef __common_only__
__BEGIN_SYS
class ARMv8_A_PMU: public PMU_Common
{
private:
typedef CPU::Reg32 Reg32;
protected:
static const unsigned int CHANNELS = 6;
static const unsigned int FIXED = 0;
static const unsigned int EVENTS = 54;
public:
// Useful bits in the PMCR register
enum { // Description Type Value after reset
PMCR_E = 1 << 0, // Enable all counters r/w
PMCR_P = 1 << 1, // Reset event counters r/w
PMCR_C = 1 << 2, // Cycle counter reset r/w
PMCR_D = 1 << 3, // Enable cycle counter prescale (1/64) r/w
PMCR_X = 1 << 4, // Export events r/w
};
// Useful bits in the PMCNTENSET register
enum { // Description Type Value after reset
PMCNTENSET_C = 1 << 31, // Cycle counter enable r/w
};
// Useful bits in the PMOVSR register
enum { // Description Type Value after reset
PMOVSR_C = 1 << 31, // Cycle counter overflow clear r/w
};
// Predefined architectural performance events
enum {
// Event
L1I_REFILL = 0x01,
L1I_TLB_REFILL = 0x02,
L1D_REFILL = 0x03,
L1D_ACCESS = 0x04,
L1D_TLB_REFILL = 0x05,
INSTRUCTIONS_ARCHITECTURALLY_EXECUTED = 0x08,
EXCEPTION_TAKEN = 0x09,
BRANCHES_ARCHITECTURALLY_EXECUTED = 0x0c,
IMMEDIATE_BRANCH = 0X0d,
UNALIGNED_LOAD_STORE = 0X0f,
MISPREDICTED_BRANCH = 0x10,
CYCLE = 0x11,
PREDICTABLE_BRANCH_EXECUTED = 0x12,
DATA_MEMORY_ACCESS = 0x13,
L1I_ACCESS = 0x14,
L1D_WRITEBACK = 0x15,
L2D_ACCESS = 0x16,
L2D_REFILL = 0x17,
L2D_WRITEBACK = 0x18,
BUS_ACCESS = 0x19,
LOCAL_MEMORY_ERROR = 0x1a,
INSTRUCTION_SPECULATIVELY_EXECUTED = 0x1b,
BUS_CYCLE = 0x1d,
CHAIN = 0x1e,
// Cortex A-53 specific events
BUS_ACCESS_LD = 0x60,
BUS_ACCESS_ST = 0x61,
BR_INDIRECT_SPEC = 0x7a,
EXC_IRQ = 0x86,
EXC_FIQ = 0x87,
EXTERNAL_MEM_REQUEST = 0xc0,
EXTERNAL_MEM_REQUEST_NON_CACHEABLE = 0xc1,
PREFETCH_LINEFILL = 0xc2,
ICACHE_THROTTLE = 0xc3,
ENTER_READ_ALLOC_MODE = 0xc4,
READ_ALLOC_MODE = 0xc5,
PRE_DECODE_ERROR = 0xc6,
DATA_WRITE_STALL_ST_BUFFER_FULL = 0xc7,
SCU_SNOOPED_DATA_FROM_OTHER_CPU = 0xc8,
CONDITIONAL_BRANCH_EXECUTED = 0xc9,
IND_BR_MISP = 0xca,
IND_BR_MISP_ADDRESS_MISCOMPARE = 0xcb,
CONDITIONAL_BRANCH_MISP = 0xcc,
L1_ICACHE_MEM_ERROR = 0xd0,
L1_DCACHE_MEM_ERROR = 0xd1,
TLB_MEM_ERROR = 0xd2,
EMPTY_DPU_IQ_NOT_GUILTY = 0xe0,
EMPTY_DPU_IQ_ICACHE_MISS = 0xe1,
EMPTY_DPU_IQ_IMICRO_TLB_MISS = 0xe2,
EMPTY_DPU_IQ_PRE_DECODE_ERROR = 0xe3,
INTERLOCK_CYCLE_NOT_GUILTY = 0xe4,
INTERLOCK_CYCLE_LD_ST_WAIT_AGU_ADDRESS= 0xe5,
INTERLOCK_CYCLE_ADV_SIMD_FP_INST = 0xe6,
INTERLOCK_CYCLE_WR_STAGE_STALL_BC_MISS= 0xe7,
INTERLOCK_CYCLE_WR_STAGE_STALL_BC_STR = 0xe8
};
public:
ARMv8_A_PMU() {}
static void config(Channel channel, Event event, Flags flags = NONE) {
assert((static_cast<unsigned int>(channel) < CHANNELS) && (static_cast<unsigned int>(event) < EVENTS));
db<PMU>(TRC) << "PMU::config(c=" << channel << ",e=" << event << ",f=" << flags << ")" << endl;
pmselr(channel);
pmxevtyper(_events[event]);
start(channel);
}
static Count read(Channel channel) {
db<PMU>(TRC) << "PMU::read(c=" << channel << ")" << endl;
pmselr(channel);
return pmxevcntr();
}
static void write(Channel channel, Count count) {
db<PMU>(TRC) << "PMU::write(ch=" << channel << ",ct=" << count << ")" << endl;
pmselr(channel);
pmxevcntr(count);
}
static void start(Channel channel) {
db<PMU>(TRC) << "PMU::start(c=" << channel << ")" << endl;
pmcntenset(pmcntenset() | (1 << channel));
}
static void stop(Channel channel) {
db<PMU>(TRC) << "PMU::stop(c=" << channel << ")" << endl;