1use isr_macros::Field;
2use zerocopy::{FromBytes, Immutable, IntoBytes};
3
4use super::session::VmiSession;
5use crate::{
6 AccessContext, AddressContext, Architecture, Pa, Registers, Va, VcpuId, VmiCore, VmiError,
7 VmiRead, VmiWrite,
8 driver::VmiSetRegisters,
9 os::{NoOS, VmiOs},
10};
11
12pub struct VmiState<'a, Os>
18where
19 Os: VmiOs,
20{
21 session: VmiSession<'a, Os>,
23
24 registers: &'a <Os::Architecture as Architecture>::Registers,
26}
27
28impl<Os> Clone for VmiState<'_, Os>
29where
30 Os: VmiOs,
31{
32 fn clone(&self) -> Self {
33 *self
34 }
35}
36
37impl<Os> Copy for VmiState<'_, Os> where Os: VmiOs {}
38
39impl<'a, Os> std::ops::Deref for VmiState<'a, Os>
40where
41 Os: VmiOs,
42{
43 type Target = VmiSession<'a, Os>;
44
45 fn deref(&self) -> &Self::Target {
46 &self.session
47 }
48}
49
50impl<'a, Os> VmiState<'a, Os>
51where
52 Os: VmiOs,
53{
54 pub fn new(
56 session: &'a VmiSession<'a, Os>,
57 registers: &'a <Os::Architecture as Architecture>::Registers,
58 ) -> Self {
59 Self {
60 session: *session,
61 registers,
62 }
63 }
64
65 pub fn with_registers(
67 &'a self,
68 registers: &'a <Os::Architecture as Architecture>::Registers,
69 ) -> Self {
70 Self {
71 session: self.session,
72 registers,
73 }
74 }
75
76 pub fn without_os(&self) -> VmiState<'a, NoOS<Os::Driver>> {
78 VmiState {
79 session: self.session.without_os(),
80 registers: self.registers,
81 }
82 }
83
84 pub fn session(&self) -> &VmiSession<'a, Os> {
88 &self.session
89 }
90
91 pub fn registers(&self) -> &'a <Os::Architecture as Architecture>::Registers {
93 self.registers
94 }
95
96 pub fn os(&self) -> VmiOsState<'a, Os> {
98 VmiOsState(*self)
99 }
100
101 pub fn access_context(&self, address: Va) -> AccessContext {
103 self.registers().access_context(address)
104 }
105
106 pub fn address_context(&self, address: Va) -> AddressContext {
108 self.registers().address_context(address)
109 }
110
111 pub fn translation_root(&self, va: Va) -> Pa {
114 self.registers().translation_root(va)
115 }
116}
117
118impl<'a, Os> VmiState<'a, Os>
123where
124 Os: VmiOs,
125 Os::Driver: VmiRead,
126{
127 pub fn return_address(&self) -> Result<Va, VmiError> {
129 self.registers().return_address(self.core())
130 }
131
132 pub fn return_from_function(
135 &self,
136 value: u64,
137 ) -> Result<<<Os::Architecture as Architecture>::Registers as Registers>::GpRegisters, VmiError>
138 {
139 self.registers().return_from_function(self.core(), value)
140 }
141
142 pub fn translate_address(&self, va: Va) -> Result<Pa, VmiError> {
144 self.core().translate_address(self.address_context(va))
145 }
146
147 pub fn read(&self, address: Va, buffer: &mut [u8]) -> Result<(), VmiError> {
151 self.read_in(self.access_context(address), buffer)
152 }
153
154 pub fn read_u8(&self, address: Va) -> Result<u8, VmiError> {
156 self.read_u8_in(self.access_context(address))
157 }
158
159 pub fn read_u16(&self, address: Va) -> Result<u16, VmiError> {
161 self.read_u16_in(self.access_context(address))
162 }
163
164 pub fn read_u32(&self, address: Va) -> Result<u32, VmiError> {
166 self.read_u32_in(self.access_context(address))
167 }
168
169 pub fn read_u64(&self, address: Va) -> Result<u64, VmiError> {
171 self.read_u64_in(self.access_context(address))
172 }
173
174 pub fn read_uint(&self, address: Va, size: usize) -> Result<u64, VmiError> {
182 self.read_uint_in(self.access_context(address), size)
183 }
184
185 pub fn read_field(&self, base_address: Va, field: &Field) -> Result<u64, VmiError> {
194 self.read_field_in(self.access_context(base_address), field)
195 }
196
197 pub fn read_address(&self, address: Va) -> Result<u64, VmiError> {
199 self.read_address_in(self.access_context(address))
200 }
201
202 pub fn read_address_native(&self, address: Va) -> Result<u64, VmiError> {
204 self.read_address_native_in(self.access_context(address))
205 }
206
207 pub fn read_address32(&self, address: Va) -> Result<u64, VmiError> {
209 self.read_address32_in(self.access_context(address))
210 }
211
212 pub fn read_address64(&self, address: Va) -> Result<u64, VmiError> {
214 self.read_address64_in(self.access_context(address))
215 }
216
217 pub fn read_va(&self, address: Va) -> Result<Va, VmiError> {
219 self.read_va_in(self.access_context(address))
220 }
221
222 pub fn read_va_native(&self, address: Va) -> Result<Va, VmiError> {
224 self.read_va_native_in(self.access_context(address))
225 }
226
227 pub fn read_va32(&self, address: Va) -> Result<Va, VmiError> {
229 self.read_va32_in(self.access_context(address))
230 }
231
232 pub fn read_va64(&self, address: Va) -> Result<Va, VmiError> {
234 self.read_va64_in(self.access_context(address))
235 }
236
237 pub fn read_string_bytes_limited(
240 &self,
241 address: Va,
242 limit: usize,
243 ) -> Result<Vec<u8>, VmiError> {
244 self.read_string_bytes_limited_in(self.access_context(address), limit)
245 }
246
247 pub fn read_string_bytes(&self, address: Va) -> Result<Vec<u8>, VmiError> {
249 self.read_string_bytes_in(self.access_context(address))
250 }
251
252 pub fn read_string_utf16_bytes_limited(
255 &self,
256 address: Va,
257 limit: usize,
258 ) -> Result<Vec<u16>, VmiError> {
259 self.read_string_utf16_bytes_limited_in(self.access_context(address), limit)
260 }
261
262 pub fn read_string_utf16_bytes(&self, address: Va) -> Result<Vec<u16>, VmiError> {
264 self.read_string_utf16_bytes_in(self.access_context(address))
265 }
266
267 pub fn read_string_limited(&self, address: Va, limit: usize) -> Result<String, VmiError> {
270 self.read_string_limited_in(self.access_context(address), limit)
271 }
272
273 pub fn read_string(&self, address: Va) -> Result<String, VmiError> {
275 self.read_string_in(self.access_context(address))
276 }
277
278 pub fn read_string_utf16_limited(&self, address: Va, limit: usize) -> Result<String, VmiError> {
281 self.read_string_utf16_limited_in(self.access_context(address), limit)
282 }
283
284 pub fn read_string_utf16(&self, address: Va) -> Result<String, VmiError> {
286 self.read_string_utf16_in(self.access_context(address))
287 }
288
289 pub fn read_struct<T>(&self, address: Va) -> Result<T, VmiError>
291 where
292 T: IntoBytes + FromBytes,
293 {
294 self.read_struct_in(self.access_context(address))
295 }
296
297 pub fn read_in(
303 &self,
304 ctx: impl Into<AccessContext>,
305 buffer: &mut [u8],
306 ) -> Result<(), VmiError> {
307 self.core().read(ctx, buffer)
308 }
309
310 pub fn read_u8_in(&self, ctx: impl Into<AccessContext>) -> Result<u8, VmiError> {
312 self.core().read_u8(ctx)
313 }
314
315 pub fn read_u16_in(&self, ctx: impl Into<AccessContext>) -> Result<u16, VmiError> {
317 self.core().read_u16(ctx)
318 }
319
320 pub fn read_u32_in(&self, ctx: impl Into<AccessContext>) -> Result<u32, VmiError> {
322 self.core().read_u32(ctx)
323 }
324
325 pub fn read_u64_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
327 self.core().read_u64(ctx)
328 }
329
330 pub fn read_uint_in(
338 &self,
339 ctx: impl Into<AccessContext>,
340 size: usize,
341 ) -> Result<u64, VmiError> {
342 self.core().read_uint(ctx, size)
343 }
344
345 pub fn read_field_in(
354 &self,
355 ctx: impl Into<AccessContext>,
356 field: &Field,
357 ) -> Result<u64, VmiError> {
358 self.core().read_field(ctx, field)
359 }
360
361 pub fn read_address_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
363 self.core()
364 .read_address(ctx, self.registers().effective_address_width())
365 }
366
367 pub fn read_address_native_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
369 self.core()
370 .read_address(ctx, self.registers().address_width())
371 }
372
373 pub fn read_address32_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
375 self.core().read_address32(ctx)
376 }
377
378 pub fn read_address64_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
380 self.core().read_address64(ctx)
381 }
382
383 pub fn read_va_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
385 self.core()
386 .read_va(ctx, self.registers().effective_address_width())
387 }
388
389 pub fn read_va_native_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
391 self.core().read_va(ctx, self.registers().address_width())
392 }
393
394 pub fn read_va32_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
396 self.core().read_va32(ctx)
397 }
398
399 pub fn read_va64_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
401 self.core().read_va64(ctx)
402 }
403
404 pub fn read_string_bytes_limited_in(
407 &self,
408 ctx: impl Into<AccessContext>,
409 limit: usize,
410 ) -> Result<Vec<u8>, VmiError> {
411 self.core().read_string_bytes_limited(ctx, limit)
412 }
413
414 pub fn read_string_bytes_in(&self, ctx: impl Into<AccessContext>) -> Result<Vec<u8>, VmiError> {
416 self.core().read_string_bytes(ctx)
417 }
418
419 pub fn read_string_utf16_bytes_limited_in(
422 &self,
423 ctx: impl Into<AccessContext>,
424 limit: usize,
425 ) -> Result<Vec<u16>, VmiError> {
426 self.core().read_string_utf16_bytes_limited(ctx, limit)
427 }
428
429 pub fn read_string_utf16_bytes_in(
431 &self,
432 ctx: impl Into<AccessContext>,
433 ) -> Result<Vec<u16>, VmiError> {
434 self.core().read_string_utf16_bytes(ctx)
435 }
436
437 pub fn read_string_limited_in(
440 &self,
441 ctx: impl Into<AccessContext>,
442 limit: usize,
443 ) -> Result<String, VmiError> {
444 self.core().read_string_limited(ctx, limit)
445 }
446
447 pub fn read_string_in(&self, ctx: impl Into<AccessContext>) -> Result<String, VmiError> {
449 self.core().read_string(ctx)
450 }
451
452 pub fn read_string_utf16_limited_in(
455 &self,
456 ctx: impl Into<AccessContext>,
457 limit: usize,
458 ) -> Result<String, VmiError> {
459 self.core().read_string_utf16_limited(ctx, limit)
460 }
461
462 pub fn read_string_utf16_in(&self, ctx: impl Into<AccessContext>) -> Result<String, VmiError> {
464 self.core().read_string_utf16(ctx)
465 }
466
467 pub fn read_struct_in<T>(&self, ctx: impl Into<AccessContext>) -> Result<T, VmiError>
469 where
470 T: IntoBytes + FromBytes,
471 {
472 self.core().read_struct(ctx)
473 }
474
475 }
477
478impl<'a, Os> VmiState<'a, Os>
483where
484 Os: VmiOs,
485 Os::Driver: VmiRead + VmiWrite,
486{
487 pub fn write(&self, address: Va, buffer: &[u8]) -> Result<(), VmiError> {
489 self.write_in(self.access_context(address), buffer)
490 }
491
492 pub fn write_in(&self, ctx: impl Into<AccessContext>, buffer: &[u8]) -> Result<(), VmiError> {
494 self.core().write(ctx, buffer)
495 }
496
497 pub fn write_u8(&self, address: Va, value: u8) -> Result<(), VmiError> {
499 self.core().write_u8(self.access_context(address), value)
500 }
501
502 pub fn write_u16(&self, address: Va, value: u16) -> Result<(), VmiError> {
504 self.core().write_u16(self.access_context(address), value)
505 }
506
507 pub fn write_u32(&self, address: Va, value: u32) -> Result<(), VmiError> {
509 self.core().write_u32(self.access_context(address), value)
510 }
511
512 pub fn write_u64(&self, address: Va, value: u64) -> Result<(), VmiError> {
514 self.core().write_u64(self.access_context(address), value)
515 }
516
517 pub fn write_struct<T>(&self, address: Va, value: T) -> Result<(), VmiError>
519 where
520 T: FromBytes + IntoBytes + Immutable,
521 {
522 self.core()
523 .write_struct(self.access_context(address), value)
524 }
525}
526
527impl<'a, Os> VmiState<'a, Os>
532where
533 Os: VmiOs,
534 Os::Driver: VmiSetRegisters,
535{
536 pub fn set_registers(
538 &self,
539 vcpu: VcpuId,
540 registers: <Os::Architecture as Architecture>::Registers,
541 ) -> Result<(), VmiError> {
542 self.core().set_registers(vcpu, registers)
543 }
544}
545
546pub struct VmiOsState<'a, Os>(VmiState<'a, Os>)
548where
549 Os: VmiOs;
550
551impl<'a, Os> VmiOsState<'a, Os>
552where
553 Os: VmiOs,
554{
555 pub fn core(&self) -> &'a VmiCore<Os::Driver> {
557 self.0.core()
558 }
559
560 pub fn underlying_os(&self) -> &'a Os {
562 self.0.underlying_os()
563 }
564
565 pub fn session(&self) -> &VmiSession<'a, Os> {
567 self.0.session()
568 }
569
570 pub fn state(&self) -> VmiState<'a, Os> {
572 self.0
573 }
574
575 pub fn registers(&self) -> &<Os::Architecture as Architecture>::Registers {
577 self.0.registers()
578 }
579
580 pub fn function_argument_for_registers(
583 &self,
584 registers: &<Os::Architecture as Architecture>::Registers,
585 index: u64,
586 ) -> Result<u64, VmiError> {
587 Os::function_argument(self.0.with_registers(registers), index)
588 }
589
590 pub fn function_return_value_for_registers(
592 &self,
593 registers: &<Os::Architecture as Architecture>::Registers,
594 ) -> Result<u64, VmiError> {
595 Os::function_return_value(self.0.with_registers(registers))
596 }
597}