aboutsummaryrefslogtreecommitdiff
path: root/demo_functionality.c
blob: 3cf5b8fba4dc177e0694c79323bbbca9c0120936 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "io.h"
#include "psr.h"
#include "memory.h"
#include "translation_table_descriptors.h"
#include "ramfs.h"
#include "strings.h"
#include "paging.h"

void demo_paging_support(void)
{
  uint32_t ID_MMFR0;
  // get contents of coprocessor register to check for paging support
  asm("mrc p15, 0, %0, c0, c1, 4" : "=r" (ID_MMFR0));
  
  char *paging;
  
  switch(ID_MMFR0 & 0xf) /* lowest 4 bits indicate VMSA support */
    {
    case 0 : paging = "no paging"; break;
    case 1 : paging = "implementation defined paging"; break;
    case 2 : paging = "VMSAv6, with cache and TLB type registers"; break;
    case 3 : paging = "VMSAv7, with support for remapping and access flag"; break;
    case 4 : paging = "VMSAv7 with PXN bit supported"; break;
    case 5 : paging = "VMSAv7, PXN and long format descriptors. EPAE is supported."; break;
    default : paging = "?_? unknown paging ?_?";
    }
  
  puts(paging);
}

void demo_current_mode(void)
{

  // get content of current program status register to check the current
  // processor mode (should be system, as we set it in boot.S)
  PSR_t CPSR = read_CPSR();

  char *mode_name;
  
  switch(CPSR.fields.PSR_MODE_4_0)
    {
    case MODE_USER       : mode_name = "User (PL0)"; break;
    case MODE_FIQ        : mode_name = "FIQ (PL1)"; break;
    case MODE_IRQ        : mode_name = "IRQ (PL1)"; break;
    case MODE_SUPERVISOR : mode_name = "Supervisor (PL1)"; break;
    case MODE_MONITOR    : mode_name = "Monitor (PL1)"; break;
    case MODE_ABORT      : mode_name = "Abort (PL1)"; break;
    case MODE_HYPERVISOR : mode_name = "Hyp (PL2)"; break;
    case MODE_UNDEFINED  : mode_name = "Undefined (PL1)"; break;
    case MODE_SYSTEM     : mode_name = "System (PL1)"; break;
    default : mode_name = "Unknown mode"; break;
    }

  prints("current mode: ");
  puts(mode_name);
}

#define TRANSLATION_TABLE					     \
  ((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE)

extern char
  _binary_ramfs_img_start,
  _binary_ramfs_img_end,
  _binary_ramfs_img_size;

void demo_setup_PL0(void)
{
  // find PL_0_test.img im ramfs
  struct ramfile PL_0_test_img;

  if (find_file(&_binary_ramfs_img_start, "PL_0_test.img",
		&PL_0_test_img))
    {
      puts("PL_0_test.img not found :(");
      asm volatile ("wfi");
    }

  // dummy value 5 for now, as we haven't implemented processes yet  
  uint16_t physical_section_number = claim_and_map_section
    ((void*) 5, PL0_SECTION_NUMBER, AP_2_0_MODEL_RW_ALL);
  
  if (physical_section_number == SECTION_NULL)
    {
      puts("Couldn't claim memory section for unprivileged code :(");
      while(1);
    }
  
  size_t physical_section_start =
    (((size_t) physical_section_number) << 20);
    
  // check that translation works... by copying a string using one
  // mapping and reading it using other :D
  char str_part1[] = "mapped section for PL0 code (0x";
  char str_part2[] = " -> 0x";
  char str_part3[] = ")";

  char *string_end = (char*) physical_section_start;

  memcpy(string_end, str_part1, sizeof(str_part1) - 1);
  uint32_to_hex(VIRTUAL_PL0_MEMORY_START,
		string_end += sizeof(str_part1) - 1);
  memcpy(string_end += 8, str_part2, sizeof(str_part2) - 1);
  uint32_to_hex(physical_section_start,
		string_end += sizeof(str_part2) - 1);
  memcpy(string_end += 8, str_part3, sizeof(str_part3));

  puts((char*) VIRTUAL_PL0_MEMORY_START);

  // now paste a userspace program to that section
  memcpy((void*) VIRTUAL_PL0_MEMORY_START,
	 PL_0_test_img.file_contents, PL_0_test_img.file_size);

  puts("copied PL0 code to it's section");
}

void demo_go_unprivileged(void)
{
  uint32_t PL0_regs[14] = {0};
  PL0_regs[13] = VIRTUAL_PL0_MEMORY_START; // the new pc

  PSR_t new_SPSR = read_CPSR();
  new_SPSR.fields.PSR_MODE_4_0 = MODE_USER;
  write_SPSR(new_SPSR);

  puts("All ready, jumping to PL0 code");

  asm volatile("cps %[sysmode]\n\r"
	       "mov sp, %[stackaddr]\n\r"
	       "cps %[supmode]\n\r"
	       "ldm %[contextaddr], {r0 - r12, pc} ^" ::
	       [sysmode]"I" (MODE_SYSTEM),
	       [supmode]"I" (MODE_SUPERVISOR),
	       [stackaddr]"r" ((PL0_SECTION_NUMBER + 1) << 20),
	       [contextaddr]"r" (PL0_regs) : "memory");

  __builtin_unreachable();
}