1 /*
2 * Copyright (C) 2019-2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <asm/guest/vm.h>
8 #include <asm/io.h>
9 #include <asm/host_pm.h>
10 #include <logmsg.h>
11 #include <asm/per_cpu.h>
12 #include <asm/guest/vm_reset.h>
13 #include <vm_event.h>
14
15 /**
16 * @pre vm != NULL
17 */
triple_fault_shutdown_vm(struct acrn_vcpu * vcpu)18 void triple_fault_shutdown_vm(struct acrn_vcpu *vcpu)
19 {
20 struct acrn_vm *vm = vcpu->vm;
21 struct vm_event trp_event;
22
23 if (is_postlaunched_vm(vm)) {
24 struct io_request *io_req = &vcpu->req;
25
26 /* Device model emulates PM1A for post-launched VMs */
27 io_req->io_type = ACRN_IOREQ_TYPE_PORTIO;
28 io_req->reqs.pio_request.direction = ACRN_IOREQ_DIR_WRITE;
29 io_req->reqs.pio_request.address = VIRTUAL_PM1A_CNT_ADDR;
30 io_req->reqs.pio_request.size = 2UL;
31 io_req->reqs.pio_request.value = (VIRTUAL_PM1A_SLP_EN | (5U << 10U));
32
33 /* Send the tripple fault event to DM. */
34 trp_event.type = VM_EVENT_TRIPLE_FAULT;
35 (void)send_vm_event(vcpu->vm, &trp_event);
36
37 /* Inject pm1a S5 request to Service VM to shut down the guest */
38 (void)emulate_io(vcpu, io_req);
39 } else {
40 if (is_service_vm(vm)) {
41 uint16_t vm_id;
42
43 /* Shut down all non real time post-launched VMs */
44 for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {
45 struct acrn_vm *pl_vm = get_vm_from_vmid(vm_id);
46
47 get_vm_lock(pl_vm);
48 if (!is_poweroff_vm(pl_vm) && is_postlaunched_vm(pl_vm) && !is_rt_vm(pl_vm)) {
49 pause_vm(pl_vm);
50 (void)shutdown_vm(pl_vm);
51 }
52 put_vm_lock(pl_vm);
53 }
54 }
55
56 /* Either Service VM or pre-launched VMs */
57 get_vm_lock(vm);
58 poweroff_if_rt_vm(vm);
59 pause_vm(vm);
60 put_vm_lock(vm);
61
62 bitmap_set_nolock(vm->vm_id,
63 &per_cpu(shutdown_vm_bitmap, pcpuid_from_vcpu(vcpu)));
64 make_shutdown_vm_request(pcpuid_from_vcpu(vcpu));
65 }
66 }
67
68 /**
69 * @pre vcpu != NULL
70 * @pre vcpu->vm != NULL
71 */
handle_reset_reg_read(struct acrn_vcpu * vcpu,__unused uint16_t addr,__unused size_t bytes)72 static bool handle_reset_reg_read(struct acrn_vcpu *vcpu, __unused uint16_t addr,
73 __unused size_t bytes)
74 {
75 bool ret = true;
76 struct acrn_vm *vm = vcpu->vm;
77
78 if (is_postlaunched_vm(vm)) {
79 /* re-inject to DM */
80 ret = false;
81 } else {
82 vcpu->req.reqs.pio_request.value = vm->reset_control;
83 }
84
85 return ret;
86 }
87
88 /**
89 * @pre vm != NULL
90 */
handle_common_reset_reg_write(struct acrn_vcpu * vcpu,bool reset,bool warm)91 static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset, bool warm)
92 {
93 struct acrn_vm *vm = vcpu->vm;
94 bool ret = true;
95
96 get_vm_lock(vm);
97 if (reset) {
98 poweroff_if_rt_vm(vm);
99
100 if (get_highest_severity_vm(true) == vm) {
101 reset_host(warm);
102 } else if (is_postlaunched_vm(vm)) {
103 /* re-inject to DM */
104 ret = false;
105 } else {
106 /*
107 * If it's Service VM reset while RTVM is still alive
108 * or pre-launched VM reset,
109 * ACRN doesn't support re-launch, just shutdown the guest.
110 */
111 pause_vm(vm);
112 bitmap_set_nolock(vm->vm_id,
113 &per_cpu(shutdown_vm_bitmap, pcpuid_from_vcpu(vcpu)));
114 make_shutdown_vm_request(pcpuid_from_vcpu(vcpu));
115 }
116 } else {
117 if (is_postlaunched_vm(vm)) {
118 /* If post-launched VM write none reset value, re-inject to DM */
119 ret = false;
120 }
121 /*
122 * Ignore writes from Service VM and pre-launched VM.
123 * Equivalent to hiding this port from the guest.
124 */
125 }
126 put_vm_lock(vm);
127
128 return ret;
129 }
130
131 /**
132 * @pre vcpu != NULL
133 * @pre vcpu->vm != NULL
134 */
handle_kb_write(struct acrn_vcpu * vcpu,__unused uint16_t addr,size_t bytes,uint32_t val)135 static bool handle_kb_write(struct acrn_vcpu *vcpu, __unused uint16_t addr, size_t bytes, uint32_t val)
136 {
137 /* ignore commands other than system reset */
138 return handle_common_reset_reg_write(vcpu, ((bytes == 1U) && (val == 0xfeU)), false);
139 }
140
handle_kb_read(struct acrn_vcpu * vcpu,uint16_t addr,size_t bytes)141 static bool handle_kb_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes)
142 {
143 if (is_service_vm(vcpu->vm) && (bytes == 1U)) {
144 /* In case i8042 is defined as ACPI PNP device in BIOS, HV need expose physical 0x64 port. */
145 vcpu->req.reqs.pio_request.value = pio_read8(addr);
146 } else {
147 /* ACRN will not expose kbd controller to the guest in this case. */
148 vcpu->req.reqs.pio_request.value = ~0U;
149 }
150 return true;
151 }
152
153
154 /*
155 * Reset Control register at I/O port 0xcf9.
156 * Bit 1 - 0: "soft" reset. Force processor begin execution at power-on reset vector.
157 * 1: "hard" reset. e.g. assert PLTRST# (if implemented) to do a host reset.
158 * Bit 2 - initiates a system reset when it transitions from 0 to 1.
159 * Bit 3 - 1: full reset (aka code reset), SLP_S3#/4#/5# or similar pins are asserted for full power cycle.
160 * 0: will be dropped if system in S3/S4/S5.
161 */
162 /**
163 * @pre vcpu != NULL
164 * @pre vcpu->vm != NULL
165 */
handle_cf9_write(struct acrn_vcpu * vcpu,__unused uint16_t addr,size_t bytes,uint32_t val)166 static bool handle_cf9_write(struct acrn_vcpu *vcpu, __unused uint16_t addr, size_t bytes, uint32_t val)
167 {
168 struct acrn_vm *vm = vcpu->vm;
169
170 vm->reset_control = val & 0xeU;
171 return handle_common_reset_reg_write(vcpu,
172 ((bytes == 1U) && ((val & 0x4U) == 0x4U) && ((val & 0xaU) != 0U)),
173 ((val & 0x8U) == 0U));
174 }
175
176 /**
177 * @pre vcpu != NULL
178 * @pre vcpu->vm != NULL
179 */
handle_reset_reg_write(struct acrn_vcpu * vcpu,uint16_t addr,size_t bytes,uint32_t val)180 static bool handle_reset_reg_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes, uint32_t val)
181 {
182 bool ret = true;
183
184 if (bytes == 1U) {
185 struct acpi_reset_reg *reset_reg = get_host_reset_reg_data();
186
187 if (val == reset_reg->val) {
188 ret = handle_common_reset_reg_write(vcpu, true, false);
189 } else {
190 /*
191 * ACPI defines the reset value but doesn't specify the meaning of other values.
192 * in the case the reset register (e.g. PIO 0xB2) has other purpose other than reset,
193 * we can't ignore the write with other values.
194 */
195 pio_write8((uint8_t)val, addr);
196 }
197 }
198
199 return ret;
200 }
201
202 /**
203 * @pre vm != NULL
204 */
register_reset_port_handler(struct acrn_vm * vm)205 void register_reset_port_handler(struct acrn_vm *vm)
206 {
207 /* Don't support Service VM and pre-launched VM re-launch for now. */
208 if (!is_postlaunched_vm(vm) || is_rt_vm(vm)) {
209 struct acpi_reset_reg *reset_reg = get_host_reset_reg_data();
210 struct acrn_acpi_generic_address *gas = &(reset_reg->reg);
211
212 struct vm_io_range io_range = {
213 .len = 1U
214 };
215
216 io_range.base = 0x64U;
217 register_pio_emulation_handler(vm, KB_PIO_IDX, &io_range, handle_kb_read, handle_kb_write);
218
219 /* ACPI reset register is fixed at 0xcf9 for post-launched and pre-launched VMs */
220 io_range.base = 0xcf9U;
221 register_pio_emulation_handler(vm, CF9_PIO_IDX, &io_range, handle_reset_reg_read, handle_cf9_write);
222
223 /*
224 * - here is taking care of Service VM only:
225 * Don't support MMIO or PCI based reset register for now.
226 * ACPI Spec: Register_Bit_Width must be 8 and Register_Bit_Offset must be 0.
227 */
228 if (is_service_vm(vm) &&
229 (gas->space_id == SPACE_SYSTEM_IO) &&
230 (gas->bit_width == 8U) && (gas->bit_offset == 0U) &&
231 (gas->address != 0xcf9U) && (gas->address != 0x64U)) {
232
233 io_range.base = (uint16_t)reset_reg->reg.address;
234 register_pio_emulation_handler(vm, PIO_RESET_REG_IDX, &io_range,
235 handle_reset_reg_read, handle_reset_reg_write);
236 }
237 }
238 }
239
shutdown_vm_from_idle(uint16_t pcpu_id)240 void shutdown_vm_from_idle(uint16_t pcpu_id)
241 {
242 uint16_t vm_id;
243 uint64_t *vms = &per_cpu(shutdown_vm_bitmap, pcpu_id);
244 struct acrn_vm *vm;
245
246 for (vm_id = fls64(*vms); vm_id < CONFIG_MAX_VM_NUM; vm_id = fls64(*vms)) {
247 vm = get_vm_from_vmid(vm_id);
248 get_vm_lock(vm);
249 if (is_paused_vm(vm)) {
250 (void)shutdown_vm(vm);
251 }
252 put_vm_lock(vm);
253 bitmap_clear_nolock(vm_id, vms);
254 }
255 }
256