blob: 3eec780d0d2c11d1cab0b4854afc9523eb706262 [file] [log] [blame]
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +01001#include "api.h"
2#include "arch_api.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01003#include "cpu.h"
4#include "dlog.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01005#include "vm.h"
6
7#include "msr.h"
8
9struct hvc_handler_return {
Wedson Almeida Filho87009642018-07-02 10:20:07 +010010 long user_ret;
11 struct vcpu *new;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010012};
13
14void irq_current(void)
15{
16 dlog("IRQ from current\n");
Andrew Scull7364a8e2018-07-19 15:39:29 +010017 for (;;) {
18 /* do nothing */
19 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010020}
21
22void sync_current_exception(uint64_t esr, uint64_t elr)
23{
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010024 switch (esr >> 26) {
25 case 0x25: /* EC = 100101, Data abort. */
Andrew Scull4f170f52018-07-19 12:58:20 +010026 dlog("Data abort: pc=0x%x, esr=0x%x, ec=0x%x", elr, esr,
27 esr >> 26);
Andrew Scull7364a8e2018-07-19 15:39:29 +010028 if (!(esr & (1u << 10))) { /* Check FnV bit. */
Andrew Scull4f170f52018-07-19 12:58:20 +010029 dlog(", far=0x%x, hpfar=0x%x", read_msr(far_el2),
30 read_msr(hpfar_el2) << 8);
Andrew Scull7364a8e2018-07-19 15:39:29 +010031 } else {
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010032 dlog(", far=invalid");
Andrew Scull7364a8e2018-07-19 15:39:29 +010033 }
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010034
35 dlog("\n");
Andrew Scull7364a8e2018-07-19 15:39:29 +010036 for (;;) {
37 /* do nothing */
38 }
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010039
40 default:
Wedson Almeida Filho2f94ec12018-07-26 16:00:48 +010041 dlog("Unknown current sync exception pc=0x%x, esr=0x%x, "
42 "ec=0x%x\n",
43 elr, esr, esr >> 26);
Andrew Scull7364a8e2018-07-19 15:39:29 +010044 for (;;) {
45 /* do nothing */
46 }
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010047 }
Andrew Scull7364a8e2018-07-19 15:39:29 +010048 for (;;) {
49 /* do nothing */
50 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010051}
52
Wedson Almeida Filho87009642018-07-02 10:20:07 +010053struct hvc_handler_return hvc_handler(size_t arg0, size_t arg1, size_t arg2,
54 size_t arg3)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010055{
Andrew Scull020ae692018-07-19 16:20:14 +010056 (void)arg3;
57
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010058 struct hvc_handler_return ret;
59
Wedson Almeida Filho87009642018-07-02 10:20:07 +010060 ret.new = NULL;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010061
Wedson Almeida Filho87009642018-07-02 10:20:07 +010062 switch (arg0) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010063 case 0x84000000: /* PSCI_VERSION */
64 ret.user_ret = 2;
65 break;
66
67 case 0x84000006: /* PSCI_MIGRATE */
68 ret.user_ret = 2;
69 break;
70
Wedson Almeida Filho87009642018-07-02 10:20:07 +010071 case HF_VM_GET_COUNT:
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +010072 ret.user_ret = api_vm_get_count();
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010073 break;
Wedson Almeida Filho87009642018-07-02 10:20:07 +010074
75 case HF_VCPU_GET_COUNT:
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +010076 ret.user_ret = api_vcpu_get_count(arg1);
Wedson Almeida Filho87009642018-07-02 10:20:07 +010077 break;
78
79 case HF_VCPU_RUN:
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +010080 ret.user_ret = api_vcpu_run(arg1, arg2, &ret.new);
Wedson Almeida Filho87009642018-07-02 10:20:07 +010081 break;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010082
Wedson Almeida Filho2f94ec12018-07-26 16:00:48 +010083 case HF_VM_CONFIGURE:
84 ret.user_ret = api_vm_configure(arg1, arg2);
85 break;
86
87 case HF_RPC_REQUEST:
88 ret.user_ret = api_rpc_request(arg1, arg2);
89 break;
90
91 case HF_RPC_READ_REQUEST:
92 ret.user_ret = api_rpc_read_request(arg1, &ret.new);
93 break;
94
95 case HF_RPC_ACK:
96 ret.user_ret = api_rpc_ack();
97 break;
98
99 case HF_RPC_REPLY:
100 ret.user_ret = api_rpc_reply(arg1, arg2, &ret.new);
101 break;
102
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100103 default:
104 ret.user_ret = -1;
105 }
106
107 return ret;
108}
109
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100110struct vcpu *irq_lower(void)
111{
112 /* TODO: Only switch if we know the interrupt was not for the secondary
113 * VM. */
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100114 /* Switch back to primary VM, interrupts will be handled there. */
Wedson Almeida Filho2f94ec12018-07-26 16:00:48 +0100115 return api_switch_to_primary(HF_VCPU_YIELD, vcpu_state_ready);
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100116}
117
118struct vcpu *sync_lower_exception(uint64_t esr)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100119{
120 struct cpu *c = cpu();
121 struct vcpu *vcpu = c->current;
122
123 switch (esr >> 26) {
124 case 0x01: /* EC = 000001, WFI or WFE. */
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100125 /* Check TI bit of ISS, 0 = WFI, 1 = WFE. */
Andrew Scull7364a8e2018-07-19 15:39:29 +0100126 if (esr & 1) {
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100127 return NULL;
Andrew Scull7364a8e2018-07-19 15:39:29 +0100128 }
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +0100129 return api_wait_for_interrupt();
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100130
131 case 0x24: /* EC = 100100, Data abort. */
Andrew Scull4f170f52018-07-19 12:58:20 +0100132 dlog("Data abort: pc=0x%x, esr=0x%x, ec=0x%x", vcpu->regs.pc,
133 esr, esr >> 26);
Andrew Scull7364a8e2018-07-19 15:39:29 +0100134 if (!(esr & (1u << 10))) { /* Check FnV bit. */
Andrew Scull4f170f52018-07-19 12:58:20 +0100135 dlog(", far=0x%x, hpfar=0x%x", read_msr(far_el2),
136 read_msr(hpfar_el2) << 8);
Andrew Scull7364a8e2018-07-19 15:39:29 +0100137 } else {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100138 dlog(", far=invalid");
Andrew Scull7364a8e2018-07-19 15:39:29 +0100139 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100140
141 dlog("\n");
Andrew Scull7364a8e2018-07-19 15:39:29 +0100142 for (;;) {
143 /* do nothing */
144 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100145
Wedson Almeida Filho2f94ec12018-07-26 16:00:48 +0100146 case 0x20: /* EC = 100000, Instruction abort. */
147 dlog("Instruction abort: pc=0x%x, esr=0x%x, ec=0x%x",
148 vcpu->regs.pc, esr, esr >> 26);
149 if (!(esr & (1u << 10))) { /* Check FnV bit. */
150 dlog(", far=0x%x, hpfar=0x%x", read_msr(far_el2),
151 read_msr(hpfar_el2) << 8);
152 } else {
153 dlog(", far=invalid");
154 }
155
156 dlog(", vttbr_el2=0x%x", read_msr(vttbr_el2));
157 dlog("\n");
158 for (;;) {
159 /* do nothing */
160 }
161
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100162 default:
Wedson Almeida Filho2f94ec12018-07-26 16:00:48 +0100163 dlog("Unknown lower sync exception pc=0x%x, esr=0x%x, "
164 "ec=0x%x\n",
Andrew Scull4f170f52018-07-19 12:58:20 +0100165 vcpu->regs.pc, esr, esr >> 26);
Andrew Scull7364a8e2018-07-19 15:39:29 +0100166 for (;;) {
167 /* do nothing */
168 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100169 }
170
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100171 return NULL;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100172}