diff --git a/part12-wgt/boot/boot.S b/part12-wgt/boot/boot.S index b68fcd6..73ff435 100644 --- a/part12-wgt/boot/boot.S +++ b/part12-wgt/boot/boot.S @@ -1,3 +1,5 @@ +#include "sysregs.h" + #define LOCAL_CONTROL 0xff800000 #define LOCAL_PRESCALER 0xff800008 #define OSC_FREQ 54000000 @@ -40,10 +42,23 @@ _start: br x4 b 1b 2: // We're on the main core! + ldr x0, =SCTLR_VALUE_MMU_DISABLED + msr sctlr_el1, x0 - // Set stack to start somewhere safe - mov sp, #MAIN_STACK + ldr x0, =HCR_VALUE + msr hcr_el2, x0 + ldr x0, =SCR_VALUE + msr scr_el3, x0 + + ldr x0, =SPSR_VALUE + msr spsr_el3, x0 + + adr x0, el1_entry + msr elr_el3, x0 + + eret +el1_entry: // Clean the BSS section ldr x1, =__bss_start // Start address ldr w2, =__bss_size // Size of the section @@ -52,6 +67,9 @@ _start: sub w2, w2, #1 cbnz w2, 3b // Loop if non-zero + // Set stack to start somewhere safe + mov sp, #MAIN_STACK + // Jump to our main() routine in C (make sure it doesn't return) 4: bl main // In case it does return, halt the master core too @@ -78,3 +96,9 @@ spin_cpu2: .globl spin_cpu3 spin_cpu3: .quad 0 + +.globl get_el +get_el: + mrs x0, CurrentEL + lsr x0, x0, #2 + ret diff --git a/part12-wgt/boot/sysregs.h b/part12-wgt/boot/sysregs.h new file mode 100644 index 0000000..385cd79 --- /dev/null +++ b/part12-wgt/boot/sysregs.h @@ -0,0 +1,44 @@ +#ifndef _SYSREGS_H +#define _SYSREGS_H + +// *************************************** +// SCTLR_EL1, System Control Register (EL1), Page 2654 of AArch64-Reference-Manual. +// *************************************** + +#define SCTLR_RESERVED (3 << 28) | (3 << 22) | (1 << 20) | (1 << 11) +#define SCTLR_EE_LITTLE_ENDIAN (0 << 25) +#define SCTLR_EOE_LITTLE_ENDIAN (0 << 24) +#define SCTLR_I_CACHE_DISABLED (0 << 12) +#define SCTLR_D_CACHE_DISABLED (0 << 2) +#define SCTLR_I_CACHE_ENABLED (1 << 12) +#define SCTLR_D_CACHE_ENABLED (1 << 2) +#define SCTLR_MMU_DISABLED (0 << 0) +#define SCTLR_MMU_ENABLED (1 << 0) + +#define SCTLR_VALUE_MMU_DISABLED (SCTLR_RESERVED | SCTLR_EE_LITTLE_ENDIAN | SCTLR_I_CACHE_ENABLED | SCTLR_D_CACHE_ENABLED | SCTLR_MMU_DISABLED) + +// *************************************** +// HCR_EL2, Hypervisor Configuration Register (EL2), Page 2487 of AArch64-Reference-Manual. +// *************************************** + +#define HCR_RW (1 << 31) +#define HCR_VALUE HCR_RW + +// *************************************** +// SCR_EL3, Secure Configuration Register (EL3), Page 2648 of AArch64-Reference-Manual. +// *************************************** + +#define SCR_RESERVED (3 << 4) +#define SCR_RW (1 << 10) +#define SCR_NS (1 << 0) +#define SCR_VALUE (SCR_RESERVED | SCR_RW | SCR_NS) + +// *************************************** +// SPSR_EL3, Saved Program Status Register (EL3) Page 389 of AArch64-Reference-Manual. +// *************************************** + +#define SPSR_MASK_ALL (7 << 6) +#define SPSR_EL1h (5 << 0) +#define SPSR_VALUE (SPSR_MASK_ALL | SPSR_EL1h) + +#endif diff --git a/part12-wgt/examples/wgt03.c b/part12-wgt/examples/wgt03.c index 53b4904..8bbecbc 100644 --- a/part12-wgt/examples/wgt03.c +++ b/part12-wgt/examples/wgt03.c @@ -1,4 +1,6 @@ #include "wgt.h" +#include "include/mem.h" +#include "include/mb.h" // ######## REQUIRED FUNCTIONS ######## @@ -57,6 +59,8 @@ int clearcount; /* Counts the number of screen clears. */ int curx = 0; int cury = 0; +extern int get_el(void); + void debugstr(char *str) { if (curx + (strlen(str) * 8) >= 1920) { curx = 0; cury += 8; @@ -96,6 +100,64 @@ void debughex(unsigned int d) { debugstr(" "); } +int get_max_clock() +{ + mbox[0] = 8*4; // Length of message in bytes + mbox[1] = MBOX_REQUEST; + mbox[2] = MBOX_TAG_GETCLKMAXM; // Tag identifier + mbox[3] = 8; // Value size in bytes + mbox[4] = 0; // Value size in bytes + mbox[5] = 0x3; // Value + mbox[6] = 0; // Rate + mbox[7] = MBOX_TAG_LAST; + + if (mbox_call(MBOX_CH_PROP)) { + if (mbox[5] == 0x3) { + return mbox[6]; + } + } + return 0; +} + +int get_clock_rate() +{ + mbox[0] = 8*4; // Length of message in bytes + mbox[1] = MBOX_REQUEST; + mbox[2] = MBOX_TAG_GETCLKRATE; // Tag identifier + mbox[3] = 8; // Value size in bytes + mbox[4] = 0; // Value size in bytes + mbox[5] = 0x3; // Value + mbox[6] = 0; // Rate + mbox[7] = MBOX_TAG_LAST; + + if (mbox_call(MBOX_CH_PROP)) { + if (mbox[5] == 0x3) { + return mbox[6]; + } + } + return 0; +} + +int set_clock_rate(unsigned int rate) +{ + mbox[0] = 9*4; // Length of message in bytes + mbox[1] = MBOX_REQUEST; + mbox[2] = MBOX_TAG_SETCLKRATE; // Tag identifier + mbox[3] = 12; // Value size in bytes + mbox[4] = 0; // Value size in bytes + mbox[5] = 0x3; // Value + mbox[6] = rate; // Rate + mbox[7] = 0; // Rate + mbox[8] = MBOX_TAG_LAST; + + if (mbox_call(MBOX_CH_PROP)) { + if (mbox[5] == 0x3 && mbox[6] == rate) { + return 1; + } + } + return 0; +} + void timer_routine (void) { timer++; @@ -103,13 +165,20 @@ void timer_routine (void) void wgt03() { + mem_init(); vga256 (); /* Initialize WGT system */ debugstr ("WGT Example #3"); debugcrlf(); debugcrlf(); debugstr ("This program will use the wcls routine to clear the screen"); debugcrlf(); debugstr ("using random colors as fast as it can until you press a key."); debugcrlf(); debugstr ("It will then report the highest frame rate possible on your computer."); debugcrlf(); debugcrlf(); debugcrlf(); - debugstr ("Press any key to continue."); debugcrlf(); + + int el = get_el(); + debugstr("Exception level: "); debughex(el); debugcrlf(); + int setter = set_clock_rate(get_max_clock()); + debugstr("Set clock returned "); debughex(setter); debugcrlf(); debugcrlf(); debugcrlf(); + + debugstr ("Press any key to continue."); getch (); clearcount = 0; @@ -134,10 +203,17 @@ void wgt03() wcls(vgapal[0]); + int clock = get_clock_rate(); + debugstr("Clock rate: "); debughex(clock); debugcrlf(); + + int maxclock = get_max_clock(); + debugstr("Max clock rate: "); debughex(maxclock); debugcrlf(); + unsigned int fps = clearcount / (timer / TIMERSPEED); - debughex(fps); debugstr("frames per second"); debugcrlf(); + debughex(fps); debugstr("frames per second"); debugcrlf(); debugcrlf(); debugcrlf(); + debugstr ("This is the highest frame rate your computer can produce for full screen\n"); debugcrlf(); - debugstr ("animation."); debugcrlf(); + debugstr ("animation."); } void main() diff --git a/part12-wgt/include/mb.h b/part12-wgt/include/mb.h index 0e1861b..d2c1d16 100644 --- a/part12-wgt/include/mb.h +++ b/part12-wgt/include/mb.h @@ -1,3 +1,5 @@ +#pragma once + extern volatile unsigned int mbox[36]; enum { @@ -18,6 +20,9 @@ enum { enum { MBOX_TAG_SETPOWER = 0x28001, + + MBOX_TAG_GETCLKRATE = 0x30002, + MBOX_TAG_GETCLKMAXM = 0x30004, MBOX_TAG_SETCLKRATE = 0x38002, MBOX_TAG_SETPHYWH = 0x48003, diff --git a/part12-wgt/lib/mem.c b/part12-wgt/lib/mem.c index 4e772db..bb30414 100644 --- a/part12-wgt/lib/mem.c +++ b/part12-wgt/lib/mem.c @@ -2,8 +2,9 @@ extern unsigned char _end[]; // Define the heap -unsigned char *HEAP_START = &_end[0]; -unsigned int HEAP_SIZE = 0x30000000; // Max heap size is 768Mb +// unsigned char *HEAP_START = &_end[0]; // End of kernel +unsigned char *HEAP_START = (unsigned char *)0x400000; // Top of stack +unsigned int HEAP_SIZE = 0x30000000; // Max heap size is 764Mb unsigned char *HEAP_END; // Set up some globals