SC_CACHECLEARE syscall implementation
[AROS.git] / arch / arm-native / kernel / syscall.c
blob908f3ac42c9f311c5f94864d99bd8d4ec760c657
1 /*
2 Copyright © 2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <inttypes.h>
7 #include <aros/kernel.h>
8 #include <aros/libcall.h>
10 #include <aros/arm/cpucontext.h>
12 #include <stddef.h>
13 #include <string.h>
15 #include <proto/exec.h>
16 #include <proto/kernel.h>
18 #include "kernel_cpu.h"
19 #include "kernel_intern.h"
20 #include "kernel_scheduler.h"
21 #include "kernel_intr.h"
22 #include "kernel_syscall.h"
24 extern char * __text_start;
25 extern char * __text_end;
27 #ifndef _CUSTOM
28 #define _CUSTOM NULL
29 #endif
31 #define DREGS(x)
32 #define D(x)
35 __vectorhand_swi:
37 this code currently assumes the caller is in user mode (and will break from any other mode)
39 r0 = passed to c handler, r1/r2 = temp
41 asm (
42 ".globl __vectorhand_swi \n"
43 ".type __vectorhand_swi,%function \n"
44 "__vectorhand_swi: \n"
45 VECTCOMMON_START
46 " add r1, r0, #13*4 \n" // store sp^ in ctx_sp
47 " stm r1, {sp}^ \n"
48 " add r1, r0, #14*4 \n" // store lr^ in ctx_lr
49 " stm r1, {lr}^ \n"
50 " mov fp, #0 \n" // clear fp(??)
52 " bl handle_syscall \n"
53 VECTCOMMON_END
56 void cache_clear_e(void *addr, uint32_t length, uint32_t flags)
58 uint32_t count = 0;
60 if (addr == NULL && length == 0xffffffff)
62 count = 0x8000000;
64 else
66 void *end_addr = ((uintptr_t)addr + length + 31) & ~31;
67 addr = (void *)((uintptr_t)addr & ~31);
68 count = (uintptr_t)(end_addr - addr) >> 5;
71 D(bug("[KRN] CacheClearE from %p length %d count %d, flags %x\n", addr, length, count, flags));
73 while (count--)
75 if (flags & CACRF_ClearD)
77 __asm__ __volatile__("mcr p15, 0, %0, c7, c14, 1"::"r"(addr));
79 if (flags & CACRF_ClearI)
81 __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 1"::"r"(addr));
83 if (flags & CACRF_InvalidateD)
85 __asm__ __volatile__("mcr p15, 0, %0, c7, c6, 1"::"r"(addr));
88 addr += 32;
91 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
94 void handle_syscall(void *regs)
96 register unsigned int addr;
97 register unsigned int swi_no;
99 /* We determine the SWI number by reading in "tasks"
100 program counter, subtract the instruction from it and
101 obtain the value from there. we also use this to check if
102 we have been called from outwith the kernel's code (illegal!)
105 addr = ((uint32_t *)regs)[15];
106 addr -= 4;
107 swi_no = *((unsigned int *)addr) & 0x00ffffff;
109 D(bug("[KRN] ## SWI %d @ 0x%p\n", swi_no, addr));
111 if (((char*)addr < &__text_start) || ((char*)addr >= &__text_end))
113 D(bug("[KRN] ## SWI : ILLEGAL ACCESS!\n"));
114 return;
116 if (swi_no <= 0x0b || swi_no == 0x100)
118 DREGS(cpu_DumpRegs(regs));
120 switch (swi_no)
122 case SC_CLI:
124 D(bug("[KRN] ## CLI...\n"));
125 ((uint32_t *)regs)[16] |= 0x80;
126 break;
129 case SC_STI:
131 D(bug("[KRN] ## STI...\n"));
132 ((uint32_t *)regs)[16] &= ~0x80;
133 break;
136 case SC_SUPERSTATE:
138 D(bug("[KRN] ## SUPERSTATE... (0x%p ->", ((uint32_t *)regs)[16]));
139 ((uint32_t *)regs)[16] &= ~CPUMODE_MASK;
140 ((uint32_t *)regs)[16] |= (0x80 | CPUMODE_SUPERVISOR);
141 D(bug(" 0x%p)\n", ((uint32_t *)regs)[16]));
142 break;
145 case SC_ISSUPERSTATE:
147 D(bug("[KRN] ## ISSUPERSTATE... "));
148 ((uint32_t *)regs)[0] = !(((((uint32_t *)regs)[16] & CPUMODE_MASK) == CPUMODE_USER) || ((((uint32_t *)regs)[16] & CPUMODE_MASK) == CPUMODE_SYSTEM));
149 D(bug("%d\n", ((uint32_t *)regs)[0]));
150 break;
153 case SC_REBOOT:
155 D(bug("[KRN] ## REBOOT...\n"));
156 asm volatile ("mov pc, #0\n"); // Jump to the reset vector..
157 break;
160 case SC_CACHECLEARE:
162 D(bug("[KRN] ## CACHECLEARE...\n"));
163 void * address = ((void **)regs)[0];
164 uint32_t length = ((uint32_t *)regs)[1];
165 uint32_t flags = ((uint32_t *)regs)[2];
167 cache_clear_e(address, length, flags);
169 break;
171 default:
172 core_SysCall(swi_no, regs);
173 break;
176 else
178 D(bug("[KRN] ## SWI : ILLEGAL SWI!\n"));
179 return;
182 D(bug("[KRN] ## SWI returning ..\n"));