aboutsummaryrefslogtreecommitdiff
path: root/src/demo/demo_functionality.c
blob: 14e37f2f64a65caecc6b1b2f5217ac0e875007f6 (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
#include "utils/io.h"
#include "psr.h"
#include "memory.h"
#include "translation_table_descriptors.h"
#include "ramfs.h"
#include "utils/strings.h"
#include "paging.h"
#include "armclock.h"
#include "scheduler.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 __attribute__((noreturn)) 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");

  puts("All ready! scheduling!");

  schedule_new(VIRTUAL_PL0_MEMORY_START, // the new pc
	       VIRTUAL_PL0_MEMORY_END);  // the new sp
}