don't dereference PC during trap entry
[akaros.git] / kern / arch / riscv / console.c
1 #include <arch/console.h>
2 #include <console.h>
3 #include <pmap.h>
4 #include <atomic.h>
5 #include <smp.h>
6
7 static volatile uint64_t magic_mem[MAX_NUM_CPUS][8] __attribute__((aligned(64)));
8
9 static bool fesvr_busy()
10 {
11         if (mfpcr(PCR_TOHOST))
12                 return true;
13         
14         volatile uint64_t* mm = magic_mem[core_id()];
15         if (mfpcr(PCR_FROMHOST) && mm[6])
16         {
17                 void (*func)(void*, uint64_t*) = (void*)(uintptr_t)mm[6];
18                 void* farg = (void*)(uintptr_t)mm[7];
19                 func(farg, (uint64_t*)mm);
20         }
21
22         return false;
23 }
24
25 int fesvr_syscall(long n, long a0, long a1, long a2, long a3,
26                   void (*continuation)(void*, uint64_t*), void* arg)
27 {
28         int ret = -1;
29         uintptr_t irq_state = disable_irq();
30
31         if (fesvr_busy())
32                 goto out;
33
34         volatile uint64_t* mm = magic_mem[core_id()];
35         mm[0] = n;
36         mm[1] = a0;
37         mm[2] = a1;
38         mm[3] = a2;
39         mm[4] = a3;
40         mm[6] = (uintptr_t)continuation;
41         mm[7] = (uintptr_t)arg;
42
43         mb();
44         mtpcr(PCR_TOHOST, PADDR(mm));
45   
46         ret = 0;
47 out:
48         restore_irq(irq_state);
49         return ret;
50 }
51
52 void
53 fesvr_die()
54 {
55         while (fesvr_syscall(FESVR_SYS_exit, 0, 0, 0, 0, 0, 0) < 0);
56 }
57
58 static void cons_polled(void* null, uint64_t* magic_mem)
59 {
60         for (int i = 0; i < (int)magic_mem[0]; i++)
61         {
62                 char c = ((char*)KADDR(magic_mem[2]))[i];
63                 if (c == 'G')
64                         send_kernel_message(core_id(), __run_mon, 0, 0, 0, KMSG_ROUTINE);
65                 else
66                         send_kernel_message(core_id(), __cons_add_char, (long)&cons_buf,
67                                             (long)c, 0, KMSG_ROUTINE);
68         }
69 }
70
71 static struct alarm_waiter keyboard_waiter;
72
73 static void cons_poll(struct alarm_waiter* awaiter)
74 {
75         static char buf[64] __attribute__((aligned(64)));
76         fesvr_syscall(FESVR_SYS_read, 0, PADDR(buf), sizeof(buf), 0, cons_polled, 0);
77
78         set_awaiter_rel(&keyboard_waiter, 10);
79         set_alarm(&per_cpu_info[core_id()].tchain, &keyboard_waiter);
80 }
81
82 // emulate keyboard input with an alarm
83 void keyboard_alarm_init()
84 {
85         init_awaiter(&keyboard_waiter, cons_poll);
86         set_awaiter_rel(&keyboard_waiter, 1);
87         set_alarm(&per_cpu_info[core_id()].tchain, &keyboard_waiter);
88 }
89
90 int cons_get_any_char(void)
91 {
92         assert(0);
93 }
94
95 void
96 cons_init(void)
97 {
98 }
99
100 // `High'-level console I/O.  Used by readline and cprintf.
101
102 void
103 cputbuf(const char* str, int len)
104 {
105         static char bufs[MAX_NUM_CPUS][1024] __attribute__((aligned(64)));
106         assert(len <= sizeof(bufs[0]));
107
108         char* buf = bufs[core_id()];
109         while (fesvr_busy());
110         memcpy(buf, str, len);
111         while (fesvr_syscall(FESVR_SYS_write, 1, PADDR(buf), len, 0, 0, 0) < 0);
112 }
113
114 // Low-level console I/O
115
116 void
117 cputchar(int c)
118 {
119         char ch = c;
120         cputbuf(&ch,1);
121 }
122
123 int
124 getchar(void)
125 {
126         char c;
127         kb_get_from_buf(&cons_buf, &c, 1);
128         return c;
129 }
130
131 int
132 iscons(int fdnum)
133 {
134         // used by readline
135         return 1;
136 }