(&mut self, _base: u64, offset: u64, data: &[u8])
| 3236 | } |
| 3237 | |
| 3238 | fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { |
| 3239 | match offset { |
| 3240 | Self::CPU_SELECTION_OFFSET => { |
| 3241 | assert!(data.len() >= core::mem::size_of::<u32>()); |
| 3242 | self.selected_cpu = |
| 3243 | u32::from_le_bytes(data[0..core::mem::size_of::<u32>()].try_into().unwrap()); |
| 3244 | } |
| 3245 | Self::CPU_STATUS_OFFSET => { |
| 3246 | if self.selected_cpu < self.max_vcpus { |
| 3247 | // This structure is not shared with the vCPU thread, therefore, holding the |
| 3248 | // lock for the entire function doesn't cause any deadlock. |
| 3249 | let mut vcpu_states = self.vcpu_states.lock().unwrap(); |
| 3250 | let state = &mut vcpu_states[usize::try_from(self.selected_cpu).unwrap()]; |
| 3251 | // The ACPI code writes back a 1 to acknowledge the insertion |
| 3252 | if (data[0] & (1 << Self::CPU_INSERTING_FLAG) == 1 << Self::CPU_INSERTING_FLAG) |
| 3253 | && state.inserting |
| 3254 | { |
| 3255 | state.inserting = false; |
| 3256 | } |
| 3257 | // Ditto for removal |
| 3258 | if (data[0] & (1 << Self::CPU_REMOVING_FLAG) == 1 << Self::CPU_REMOVING_FLAG) |
| 3259 | && state.removing |
| 3260 | { |
| 3261 | state.removing = false; |
| 3262 | } |
| 3263 | // Trigger removal of vCPU: |
| 3264 | if data[0] & (1 << Self::CPU_EJECT_FLAG) == 1 << Self::CPU_EJECT_FLAG |
| 3265 | && let Err(e) = Self::remove_vcpu(self.selected_cpu, state) |
| 3266 | { |
| 3267 | error!("Error removing vCPU: {e:?}"); |
| 3268 | } |
| 3269 | } else { |
| 3270 | warn!("Out of range vCPU id: {}", self.selected_cpu); |
| 3271 | } |
| 3272 | } |
| 3273 | _ => { |
| 3274 | warn!("Unexpected offset for accessing CPU manager device: {offset:#}"); |
| 3275 | } |
| 3276 | } |
| 3277 | None |
| 3278 | } |
| 3279 | } |
| 3280 | |
| 3281 | #[cfg(all(feature = "kvm", target_arch = "x86_64"))] |
no test coverage detected