blob: 94a9722fb41c4b9c8bdcbebbe01508a8823354fe [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:
Andrew Scull4f170f52018-07-19 12:58:20 +010041 dlog("Unknown sync exception pc=0x%x, esr=0x%x, ec=0x%x\n", elr,
42 esr, esr >> 26);
Andrew Scull7364a8e2018-07-19 15:39:29 +010043 for (;;) {
44 /* do nothing */
45 }
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010046 }
Andrew Scull7364a8e2018-07-19 15:39:29 +010047 for (;;) {
48 /* do nothing */
49 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010050}
51
Wedson Almeida Filho87009642018-07-02 10:20:07 +010052struct hvc_handler_return hvc_handler(size_t arg0, size_t arg1, size_t arg2,
53 size_t arg3)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010054{
Andrew Scull020ae692018-07-19 16:20:14 +010055 (void)arg3;
56
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010057 struct hvc_handler_return ret;
58
Wedson Almeida Filho87009642018-07-02 10:20:07 +010059 ret.new = NULL;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010060
Wedson Almeida Filho87009642018-07-02 10:20:07 +010061 switch (arg0) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010062 case 0x84000000: /* PSCI_VERSION */
63 ret.user_ret = 2;
64 break;
65
66 case 0x84000006: /* PSCI_MIGRATE */
67 ret.user_ret = 2;
68 break;
69
Wedson Almeida Filho87009642018-07-02 10:20:07 +010070 case HF_VM_GET_COUNT:
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +010071 ret.user_ret = api_vm_get_count();
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010072 break;
Wedson Almeida Filho87009642018-07-02 10:20:07 +010073
74 case HF_VCPU_GET_COUNT:
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +010075 ret.user_ret = api_vcpu_get_count(arg1);
Wedson Almeida Filho87009642018-07-02 10:20:07 +010076 break;
77
78 case HF_VCPU_RUN:
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +010079 ret.user_ret = api_vcpu_run(arg1, arg2, &ret.new);
Wedson Almeida Filho87009642018-07-02 10:20:07 +010080 break;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010081
82 default:
83 ret.user_ret = -1;
84 }
85
86 return ret;
87}
88
Wedson Almeida Filho87009642018-07-02 10:20:07 +010089struct vcpu *irq_lower(void)
90{
91 /* TODO: Only switch if we know the interrupt was not for the secondary
92 * VM. */
93
94 /* Switch back to primary VM, interrupts will be handled there. */
95 arch_set_vm_mm(&primary_vm.page_table);
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +010096 return &primary_vm.vcpus[cpu_index(cpu())];
Wedson Almeida Filho87009642018-07-02 10:20:07 +010097}
98
99struct vcpu *sync_lower_exception(uint64_t esr)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100100{
101 struct cpu *c = cpu();
102 struct vcpu *vcpu = c->current;
103
104 switch (esr >> 26) {
105 case 0x01: /* EC = 000001, WFI or WFE. */
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100106 /* Check TI bit of ISS, 0 = WFI, 1 = WFE. */
Andrew Scull7364a8e2018-07-19 15:39:29 +0100107 if (esr & 1) {
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100108 return NULL;
Andrew Scull7364a8e2018-07-19 15:39:29 +0100109 }
Wedson Almeida Filho3fcbcff2018-07-10 23:53:39 +0100110 return api_wait_for_interrupt();
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100111
112 case 0x24: /* EC = 100100, Data abort. */
Andrew Scull4f170f52018-07-19 12:58:20 +0100113 dlog("Data abort: pc=0x%x, esr=0x%x, ec=0x%x", vcpu->regs.pc,
114 esr, esr >> 26);
Andrew Scull7364a8e2018-07-19 15:39:29 +0100115 if (!(esr & (1u << 10))) { /* Check FnV bit. */
Andrew Scull4f170f52018-07-19 12:58:20 +0100116 dlog(", far=0x%x, hpfar=0x%x", read_msr(far_el2),
117 read_msr(hpfar_el2) << 8);
Andrew Scull7364a8e2018-07-19 15:39:29 +0100118 } else {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100119 dlog(", far=invalid");
Andrew Scull7364a8e2018-07-19 15:39:29 +0100120 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100121
122 dlog("\n");
Andrew Scull7364a8e2018-07-19 15:39:29 +0100123 for (;;) {
124 /* do nothing */
125 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100126
127 default:
Andrew Scull4f170f52018-07-19 12:58:20 +0100128 dlog("Unknown sync exception pc=0x%x, esr=0x%x, ec=0x%x\n",
129 vcpu->regs.pc, esr, esr >> 26);
Andrew Scull7364a8e2018-07-19 15:39:29 +0100130 for (;;) {
131 /* do nothing */
132 }
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100133 }
134
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100135 return NULL;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100136}