Skip to content

Commit 7157dd6

Browse files
committed
refactor(vmm/aarch64): updated utility methods for vcpufd
- Updated utility methods for vcpufd - Removed duplicated methods from VcpuFd and KvmVcpu. - Removed unnecessary `core` registers code. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent ad2fd73 commit 7157dd6

File tree

3 files changed

+65
-183
lines changed

3 files changed

+65
-183
lines changed

src/vmm/src/arch/aarch64/regs.rs

Lines changed: 49 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,6 @@ const PSR_D_BIT: u64 = 0x0000_0200;
6969
// Taken from arch/arm64/kvm/inject_fault.c.
7070
const PSTATE_FAULT_BITS_64: u64 = PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | PSR_I_BIT | PSR_D_BIT;
7171

72-
// Number of general purpose registers (i.e X0..X31)
73-
const NR_GP_REGS: usize = 31;
74-
// Number of FP_VREG registers.
75-
const NR_FP_VREGS: usize = 32;
76-
7772
// Following are macros that help with getting the ID of a aarch64 core register.
7873
// The core register are represented by the user_pt_regs structure. Look for it in
7974
// arch/arm64/include/uapi/asm/ptrace.h.
@@ -169,8 +164,8 @@ arm64_sys_reg!(KVM_REG_ARM_TIMER_CNT, 3, 3, 14, 3, 2);
169164
///
170165
/// * `state` - Array slice of [`Aarch64Register`] structures, representing the registers of a VCPU
171166
/// state.
172-
pub fn get_manufacturer_id_from_state(state: &[Aarch64Register]) -> Result<u32, Error> {
173-
let midr_el1 = state.iter().find(|reg| reg.id == MIDR_EL1);
167+
pub fn get_manufacturer_id_from_state(regs: &[Aarch64Register]) -> Result<u32, Error> {
168+
let midr_el1 = regs.iter().find(|reg| reg.id == MIDR_EL1);
174169
match midr_el1 {
175170
Some(register) => Ok(register.value as u32 >> 24),
176171
None => Err(Error::GetMidrEl1(
@@ -199,12 +194,11 @@ pub fn get_manufacturer_id_from_host() -> Result<u32, Error> {
199194
///
200195
/// # Arguments
201196
///
202-
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
203197
/// * `cpu_id` - Index of current vcpu.
204198
/// * `boot_ip` - Starting instruction pointer.
205199
/// * `mem` - Reserved DRAM for current VM.
206200
pub fn setup_boot_regs(
207-
vcpu: &VcpuFd,
201+
vcpufd: &VcpuFd,
208202
cpu_id: u8,
209203
boot_ip: u64,
210204
mem: &GuestMemoryMmap,
@@ -214,15 +208,17 @@ pub fn setup_boot_regs(
214208
// Get the register index of the PSTATE (Processor State) register.
215209
let pstate = offset__of!(user_pt_regs, pstate) + kreg_off;
216210
let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate);
217-
vcpu.set_one_reg(id, PSTATE_FAULT_BITS_64.into())
211+
vcpufd
212+
.set_one_reg(id, PSTATE_FAULT_BITS_64.into())
218213
.map_err(|err| Error::SetOneReg(id, err))?;
219214

220215
// Other vCPUs are powered off initially awaiting PSCI wakeup.
221216
if cpu_id == 0 {
222217
// Setting the PC (Processor Counter) to the current program address (kernel address).
223218
let pc = offset__of!(user_pt_regs, pc) + kreg_off;
224219
let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, pc);
225-
vcpu.set_one_reg(id, boot_ip.into())
220+
vcpufd
221+
.set_one_reg(id, boot_ip.into())
226222
.map_err(|err| Error::SetOneReg(id, err))?;
227223

228224
// Last mandatory thing to set -> the address pointing to the FDT (also called DTB).
@@ -231,132 +227,47 @@ pub fn setup_boot_regs(
231227
// We are choosing to place it the end of DRAM. See `get_fdt_addr`.
232228
let regs0 = offset__of!(user_pt_regs, regs) + kreg_off;
233229
let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0);
234-
vcpu.set_one_reg(id, get_fdt_addr(mem).into())
230+
vcpufd
231+
.set_one_reg(id, get_fdt_addr(mem).into())
235232
.map_err(|err| Error::SetOneReg(id, err))?;
236233
}
237234
Ok(())
238235
}
239236

240237
/// Read the MPIDR - Multiprocessor Affinity Register.
241-
///
242-
/// # Arguments
243-
///
244-
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
245-
pub fn read_mpidr(vcpu: &VcpuFd) -> Result<u64, Error> {
246-
match vcpu.get_one_reg(MPIDR_EL1) {
238+
pub fn get_mpidr(vcpufd: &VcpuFd) -> Result<u64, Error> {
239+
match vcpufd.get_one_reg(MPIDR_EL1) {
247240
Err(err) => Err(Error::GetOneReg(MPIDR_EL1, err)),
248241
// MPIDR register is 64 bit wide on aarch64, this expect cannot fail
249242
// on supported architectures
250243
Ok(val) => Ok(val.try_into().expect("MPIDR register to be 64 bit")),
251244
}
252245
}
253246

254-
/// Returns ids of core registers
255-
pub fn get_core_registers_ids() -> Vec<u64> {
256-
let mut ids = vec![];
257-
let mut off = offset__of!(user_pt_regs, regs);
258-
// There are 31 user_pt_regs:
259-
// https://elixir.free-electrons.com/linux/v4.14.174/source/arch/arm64/include/uapi/asm/ptrace.h#L72
260-
// These actually are the general-purpose registers of the Armv8-a
261-
// architecture (i.e x0-x30 if used as a 64bit register or w0-w30 when used as a 32bit
262-
// register).
263-
for _ in 0..NR_GP_REGS {
264-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U64, off));
265-
off += std::mem::size_of::<u64>();
266-
}
267-
268-
// We are now entering the "Other register" section of the ARMv8-a architecture.
269-
// First one, stack pointer.
270-
let off = offset__of!(user_pt_regs, sp);
271-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U64, off));
272-
273-
// Second one, the program counter.
274-
let off = offset__of!(user_pt_regs, pc);
275-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U64, off));
276-
277-
// Next is the processor state.
278-
let off = offset__of!(user_pt_regs, pstate);
279-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U64, off));
280-
281-
// The stack pointer associated with EL1.
282-
let off = offset__of!(kvm_regs, sp_el1);
283-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U64, off));
284-
285-
// Exception Link Register for EL1, when taking an exception to EL1, this register
286-
// holds the address to which to return afterwards.
287-
let off = offset__of!(kvm_regs, elr_el1);
288-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U64, off));
289-
290-
// Saved Program Status Registers, there are 5 of them used in the kernel.
291-
let mut off = offset__of!(kvm_regs, spsr);
292-
for _ in 0..KVM_NR_SPSR {
293-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U64, off));
294-
off += std::mem::size_of::<u64>();
295-
}
296-
297-
// Now moving on to floating point registers which are stored in the user_fpsimd_state in
298-
// the kernel: https://elixir.free-electrons.com/linux/v4.9.62/source/arch/arm64/include/uapi/asm/kvm.h#L53
299-
let mut off = offset__of!(kvm_regs, fp_regs) + offset__of!(user_fpsimd_state, vregs);
300-
for _ in 0..NR_FP_VREGS {
301-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U128, off));
302-
off += std::mem::size_of::<u128>();
303-
}
304-
305-
// Floating-point Status Register.
306-
let off = offset__of!(kvm_regs, fp_regs) + offset__of!(user_fpsimd_state, fpsr);
307-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U32, off));
308-
309-
// Floating-point Control Register.
310-
let off = offset__of!(kvm_regs, fp_regs) + offset__of!(user_fpsimd_state, fpcr);
311-
ids.push(arm64_core_reg_id!(KVM_REG_SIZE_U32, off));
312-
313-
ids
314-
}
315-
316-
/// Saves the states of the core registers into `state`.
317-
///
318-
/// # Arguments
319-
///
320-
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
321-
/// * `state` - Input/Output vector of registers states.
322-
pub fn save_core_registers(vcpu: &VcpuFd, state: &mut Vec<Aarch64Register>) -> Result<(), Error> {
323-
save_registers(vcpu, &get_core_registers_ids(), state)
324-
}
325-
326247
/// Saves the states of the system registers into `state`.
327248
///
328249
/// # Arguments
329250
///
330-
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
331-
/// * `state` - Input/Output vector of registers states.
332-
pub fn save_all_registers(vcpu: &VcpuFd, state: &mut Vec<Aarch64Register>) -> Result<(), Error> {
333-
// Call KVM_GET_REG_LIST to get all registers available to the guest. For ArmV8 there are
334-
// less than 500 registers.
335-
let mut reg_list = RegList::new(500).map_err(Error::Fam)?;
336-
vcpu.get_reg_list(&mut reg_list)
337-
.map_err(Error::GetRegList)?;
338-
339-
save_registers(vcpu, reg_list.as_slice(), state)?;
340-
341-
Ok(())
251+
/// * `regs` - Input/Output vector of registers.
252+
pub fn get_all_registers(vcpufd: &VcpuFd, state: &mut Vec<Aarch64Register>) -> Result<(), Error> {
253+
get_registers(vcpufd, &get_all_registers_ids(vcpufd)?, state)
342254
}
343255

344256
/// Saves states of registers into `state`.
345257
///
346258
/// # Arguments
347259
///
348-
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
349260
/// * `ids` - Slice of registers ids to save.
350-
/// * `state` - Input/Output vector of registers states.
351-
pub fn save_registers(
352-
vcpu: &VcpuFd,
261+
/// * `regs` - Input/Output vector of registers.
262+
pub fn get_registers(
263+
vcpufd: &VcpuFd,
353264
ids: &[u64],
354-
state: &mut Vec<Aarch64Register>,
265+
regs: &mut Vec<Aarch64Register>,
355266
) -> Result<(), Error> {
356267
for id in ids.iter() {
357-
state.push(Aarch64Register {
268+
regs.push(Aarch64Register {
358269
id: *id,
359-
value: vcpu
270+
value: vcpufd
360271
.get_one_reg(*id)
361272
.map_err(|e| Error::GetOneReg(*id, e))?,
362273
});
@@ -365,15 +276,26 @@ pub fn save_registers(
365276
Ok(())
366277
}
367278

279+
/// Returns all registers ids, including core and system
280+
pub fn get_all_registers_ids(vcpufd: &VcpuFd) -> Result<Vec<u64>, Error> {
281+
// Call KVM_GET_REG_LIST to get all registers available to the guest. For ArmV8 there are
282+
// less than 500 registers.
283+
let mut reg_list = RegList::new(500).map_err(Error::Fam)?;
284+
vcpufd
285+
.get_reg_list(&mut reg_list)
286+
.map_err(Error::GetRegList)?;
287+
Ok(reg_list.as_slice().to_vec())
288+
}
289+
368290
/// Set the state of the system registers.
369291
///
370292
/// # Arguments
371293
///
372-
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
373-
/// * `state` - Structure containing the state of the system registers.
374-
pub fn restore_registers(vcpu: &VcpuFd, state: &[Aarch64Register]) -> Result<(), Error> {
375-
for reg in state {
376-
vcpu.set_one_reg(reg.id, reg.value)
294+
/// * `regs` - Slice of registers to be set.
295+
pub fn set_registers(vcpufd: &VcpuFd, regs: &[Aarch64Register]) -> Result<(), Error> {
296+
for reg in regs {
297+
vcpufd
298+
.set_one_reg(reg.id, reg.value)
377299
.map_err(|e| Error::SetOneReg(reg.id, e))?;
378300
}
379301
Ok(())
@@ -384,8 +306,8 @@ pub fn restore_registers(vcpu: &VcpuFd, state: &[Aarch64Register]) -> Result<(),
384306
/// # Arguments
385307
///
386308
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
387-
pub fn get_mpstate(vcpu: &VcpuFd) -> Result<kvm_mp_state, Error> {
388-
vcpu.get_mp_state().map_err(Error::GetMp)
309+
pub fn get_mpstate(vcpufd: &VcpuFd) -> Result<kvm_mp_state, Error> {
310+
vcpufd.get_mp_state().map_err(Error::GetMp)
389311
}
390312

391313
/// Set the state of the system registers.
@@ -394,8 +316,8 @@ pub fn get_mpstate(vcpu: &VcpuFd) -> Result<kvm_mp_state, Error> {
394316
///
395317
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
396318
/// * `state` - Structure for returning the state of the system registers.
397-
pub fn set_mpstate(vcpu: &VcpuFd, state: kvm_mp_state) -> Result<(), Error> {
398-
vcpu.set_mp_state(state).map_err(Error::SetMp)
319+
pub fn set_mpstate(vcpufd: &VcpuFd, state: kvm_mp_state) -> Result<(), Error> {
320+
vcpufd.set_mp_state(state).map_err(Error::SetMp)
399321
}
400322

401323
#[cfg(test)]
@@ -425,7 +347,7 @@ mod tests {
425347
vm.get_preferred_target(&mut kvi).unwrap();
426348
vcpu.vcpu_init(&kvi).unwrap();
427349

428-
setup_boot_regs(&vcpu, 0, 0x0, &mem).unwrap();
350+
assert!(setup_boot_regs(&vcpu, 0, 0x0, &mem).is_ok());
429351
}
430352
#[test]
431353
fn test_read_mpidr() {
@@ -436,49 +358,42 @@ mod tests {
436358
vm.get_preferred_target(&mut kvi).unwrap();
437359

438360
// Must fail when vcpu is not initialized yet.
439-
let res = read_mpidr(&vcpu);
361+
let res = get_mpidr(&vcpu);
440362
assert_eq!(
441363
res.unwrap_err(),
442364
Error::GetOneReg(MPIDR_EL1, kvm_ioctls::Error::new(8))
443365
);
444366

445367
vcpu.vcpu_init(&kvi).unwrap();
446-
assert_eq!(read_mpidr(&vcpu).unwrap(), 0x8000_0000);
368+
assert_eq!(get_mpidr(&vcpu).unwrap(), 0x8000_0000);
447369
}
448370

449371
#[test]
450-
fn test_save_restore_regs() {
372+
fn test_get_set_regs() {
451373
let kvm = Kvm::new().unwrap();
452374
let vm = kvm.create_vm().unwrap();
453375
let vcpu = vm.create_vcpu(0).unwrap();
454376
let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
455377
vm.get_preferred_target(&mut kvi).unwrap();
456378

457379
// Must fail when vcpu is not initialized yet.
458-
let mut state = Vec::new();
459-
let res = save_core_registers(&vcpu, &mut state);
460-
assert_eq!(
461-
res.unwrap_err(),
462-
Error::GetOneReg(6931039826524241920, kvm_ioctls::Error::new(8))
463-
);
464-
465-
let res = save_all_registers(&vcpu, &mut state);
380+
let mut regs = Vec::new();
381+
let res = get_all_registers(&vcpu, &mut regs);
466382
assert_eq!(
467383
res.unwrap_err(),
468384
Error::GetRegList(kvm_ioctls::Error::new(8))
469385
);
470386

471387
vcpu.vcpu_init(&kvi).unwrap();
472-
save_core_registers(&vcpu, &mut state).unwrap();
473-
save_all_registers(&vcpu, &mut state).unwrap();
388+
get_all_registers(&vcpu, &mut regs).unwrap();
474389

475-
restore_registers(&vcpu, &state).unwrap();
390+
set_registers(&vcpu, &regs).unwrap();
476391
let off = offset__of!(user_pt_regs, pstate);
477392
let id = arm64_core_reg_id!(KVM_REG_SIZE_U64, off);
478393
let pstate = vcpu
479394
.get_one_reg(id)
480395
.expect("Failed to call kvm get one reg");
481-
assert!(state.contains(&Aarch64Register { id, value: pstate }));
396+
assert!(regs.contains(&Aarch64Register { id, value: pstate }));
482397
}
483398

484399
#[test]

src/vmm/src/builder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -836,9 +836,9 @@ pub fn configure_system_for_boot(
836836

837837
#[cfg(target_arch = "aarch64")]
838838
let cpu_config = {
839-
let regs = vcpus[0]
840-
.kvm_vcpu
841-
.get_regs(&cpu_template.reg_list())
839+
use crate::arch::aarch64::regs::get_registers;
840+
let mut regs = vec![];
841+
get_registers(&vcpus[0].kvm_vcpu.fd, &cpu_template.reg_list(), &mut regs)
842842
.map_err(GuestConfigError)?;
843843
CpuConfiguration { regs }
844844
};

0 commit comments

Comments
 (0)