blob: 1844e374ae4e21e46bf124fa3c4fd6b429f01da4 [file] [log] [blame]
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01001#include "cpu.h"
2#include "dlog.h"
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +01003#include "vm.h"
4
5#include "msr.h"
6
7struct hvc_handler_return {
Wedson Almeida Filho87009642018-07-02 10:20:07 +01008 long user_ret;
9 struct vcpu *new;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010010};
11
12void irq_current(void)
13{
14 dlog("IRQ from current\n");
15 for (;;);
16}
17
18void sync_current_exception(uint64_t esr, uint64_t elr)
19{
20 dlog("Exception: esr=%#x, elr=%#x\n", esr, elr);
21 for (;;);
22}
23
Wedson Almeida Filho87009642018-07-02 10:20:07 +010024/* TODO: Define constants below according to spec. */
25#define HF_VCPU_RUN 0xff00
26#define HF_VM_GET_COUNT 0xff01
27#define HF_VCPU_GET_COUNT 0xff02
28
29/* TODO: Move these decl elsewhere. */
30extern struct vm secondary_vm[MAX_VMS];
31extern uint32_t secondary_vm_count;
32extern struct vm primary_vm;
33extern struct cpu cpus[];
34
35struct hvc_handler_return hvc_handler(size_t arg0, size_t arg1, size_t arg2,
36 size_t arg3)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010037{
38 struct hvc_handler_return ret;
39
Wedson Almeida Filho87009642018-07-02 10:20:07 +010040 ret.new = NULL;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010041
Wedson Almeida Filho87009642018-07-02 10:20:07 +010042 switch (arg0) {
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010043 case 0x84000000: /* PSCI_VERSION */
44 ret.user_ret = 2;
45 break;
46
47 case 0x84000006: /* PSCI_MIGRATE */
48 ret.user_ret = 2;
49 break;
50
Wedson Almeida Filho87009642018-07-02 10:20:07 +010051 case HF_VM_GET_COUNT:
52 ret.user_ret = secondary_vm_count;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010053 break;
Wedson Almeida Filho87009642018-07-02 10:20:07 +010054
55 case HF_VCPU_GET_COUNT:
56 if (arg1 >= secondary_vm_count)
57 ret.user_ret = -1;
58 else
59 ret.user_ret = secondary_vm[arg1].vcpu_count;
60 break;
61
62 case HF_VCPU_RUN:
63 /* TODO: Make sure we don't allow secondary VMs to make this
64 * hvc call. */
65 ret.user_ret = 1; /* WFI */
66 if (arg1 < secondary_vm_count &&
67 arg2 < secondary_vm[arg1].vcpu_count &&
68 secondary_vm[arg1].vcpus[arg2].is_on) {
69 arch_set_vm_mm(&secondary_vm[arg1].page_table);
70 /* TODO: Update the virtual memory. */
71 ret.new = secondary_vm[arg1].vcpus + arg2;
72 ret.user_ret = 0;
73 }
74 break;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010075
76 default:
77 ret.user_ret = -1;
78 }
79
80 return ret;
81}
82
Wedson Almeida Filho87009642018-07-02 10:20:07 +010083struct vcpu *irq_lower(void)
84{
85 /* TODO: Only switch if we know the interrupt was not for the secondary
86 * VM. */
87
88 /* Switch back to primary VM, interrupts will be handled there. */
89 arch_set_vm_mm(&primary_vm.page_table);
90 return &primary_vm.vcpus[cpus - cpu()];
91}
92
93struct vcpu *sync_lower_exception(uint64_t esr)
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +010094{
95 struct cpu *c = cpu();
96 struct vcpu *vcpu = c->current;
97
98 switch (esr >> 26) {
99 case 0x01: /* EC = 000001, WFI or WFE. */
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100100 /* Check TI bit of ISS, 0 = WFI, 1 = WFE. */
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100101 if (esr & 1)
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100102 return NULL;
103
104 /* Switch back to primary VM. */
105 arch_set_vm_mm(&primary_vm.page_table);
106 vcpu = &primary_vm.vcpus[cpus - cpu()];
107
108 dlog("Returning due to WFI\n");
109
110 /* TODO: Use constant. */
111 /* Set return value to 1, indicating to primary VM that this
112 * vcpu blocked on a WFI. */
113 arch_regs_set_retval(&vcpu->regs, 1);
114 return vcpu;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100115
116 case 0x24: /* EC = 100100, Data abort. */
117 dlog("Data abort: pc=0x%x, esr=0x%x, ec=0x%x", vcpu->regs.pc, esr, esr >> 26);
118 if (!(esr & (1u << 10))) /* Check FnV bit. */
119 dlog(", far=0x%x, hpfar=0x%x", read_msr(far_el2), read_msr(hpfar_el2) << 8);
120 else
121 dlog(", far=invalid");
122
123 dlog("\n");
124 for (;;);
125
126 default:
127 dlog("Unknown sync exception pc=0x%x, esr=0x%x, ec=0x%x\n", vcpu->regs.pc, esr, esr >> 26);
128 for (;;);
129 }
130
Wedson Almeida Filho87009642018-07-02 10:20:07 +0100131 return NULL;
Wedson Almeida Filho987c0ff2018-06-20 16:34:38 +0100132}