kernel/arch/riscv64/vcpu/
mod.rs

1//! VCPU module for RISC-V 64-bit architecture.
2//!
3//! This module provides the virtual CPU (VCPU) abstraction for the RISC-V 64-bit
4//! architecture. The VCPU is responsible for executing instructions and managing
5//! the state of the CPU.
6
7use crate::arch::Trapframe;
8
9use super::IntRegisters;
10use super::fpu::{FpuContext, VectorContext};
11
12use alloc::boxed::Box;
13
14#[derive(Debug, Clone, Copy, PartialEq)]
15pub enum Mode {
16    User,
17    Kernel,
18}
19
20#[derive(Debug, Clone)]
21pub struct Vcpu {
22    pub iregs: IntRegisters,
23    /// Floating-point register context (F/D extensions)
24    pub fpu: FpuContext,
25    /// Whether this task has ever used the FPU (F/D).
26    pub fpu_used: bool,
27    /// Vector register context (V extension)
28    pub vector: Option<Box<VectorContext>>,
29    /// Whether this task has ever used the Vector extension (V).
30    pub vector_used: bool,
31    pc: u64,
32    asid: usize,
33    mode: Mode,
34}
35
36impl Vcpu {
37    pub fn new(mode: Mode) -> Self {
38        Vcpu {
39            iregs: IntRegisters::new(),
40            fpu: FpuContext::new(),
41            fpu_used: false,
42            vector: None,
43            vector_used: false,
44            pc: 0,
45            asid: 0,
46            mode,
47        }
48    }
49
50    pub fn set_asid(&mut self, asid: usize) {
51        self.asid = asid;
52    }
53
54    pub fn set_pc(&mut self, pc: u64) {
55        self.pc = pc;
56    }
57
58    pub fn get_pc(&self) -> u64 {
59        self.pc
60    }
61
62    pub fn set_sp(&mut self, sp: usize) {
63        self.iregs.reg[2] = sp;
64    }
65
66    pub fn get_mode(&self) -> Mode {
67        self.mode
68    }
69
70    pub fn reset_iregs(&mut self) {
71        self.iregs = IntRegisters::new();
72    }
73
74    pub fn copy_iregs_to(&self, iregs: &mut IntRegisters) {
75        *iregs = self.iregs;
76    }
77
78    pub fn copy_iregs_from(&mut self, iregs: &IntRegisters) {
79        self.iregs = *iregs;
80    }
81
82    /// Clone the entire VCPU state to another VCPU
83    ///
84    /// This copies all registers including general-purpose registers, FPU context,
85    /// Vector context, and PC.
86    pub fn clone_to(&self, other: &mut Vcpu) {
87        other.iregs = self.iregs;
88        other.fpu = self.fpu.clone();
89        other.fpu_used = self.fpu_used;
90        other.vector = self.vector.clone();
91        other.vector_used = self.vector_used;
92        other.pc = self.pc;
93    }
94
95    pub fn store(&mut self, trapframe: &Trapframe) {
96        self.iregs = trapframe.regs;
97        self.pc = trapframe.epc;
98    }
99
100    pub fn switch(&mut self, trapframe: &mut Trapframe) {
101        trapframe.regs = self.iregs;
102        trapframe.epc = self.pc;
103    }
104
105    /// Get the TLS (Thread Local Storage) pointer for this task
106    ///
107    /// On RISC-V, TLS is stored in the tp register (x4).
108    #[inline]
109    pub fn get_tls_pointer(&self) -> usize {
110        self.iregs.get_tp()
111    }
112
113    /// Set the TLS (Thread Local Storage) pointer for this task
114    ///
115    /// On RISC-V, TLS is stored in the tp register (x4).
116    #[inline]
117    pub fn set_tls_pointer(&mut self, ptr: usize) {
118        self.iregs.set_tp(ptr);
119    }
120}