1use isr_macros::Field;
2use zerocopy::{FromBytes, Immutable, IntoBytes};
3
4use super::session::VmiSession;
5use crate::{
6 AccessContext, AddressContext, Architecture, Pa, Registers as _, 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 translate_address(&self, va: Va) -> Result<Pa, VmiError> {
134 self.core().translate_address(self.address_context(va))
135 }
136
137 pub fn read(&self, address: Va, buffer: &mut [u8]) -> Result<(), VmiError> {
141 self.read_in(self.access_context(address), buffer)
142 }
143
144 pub fn read_u8(&self, address: Va) -> Result<u8, VmiError> {
146 self.read_u8_in(self.access_context(address))
147 }
148
149 pub fn read_u16(&self, address: Va) -> Result<u16, VmiError> {
151 self.read_u16_in(self.access_context(address))
152 }
153
154 pub fn read_u32(&self, address: Va) -> Result<u32, VmiError> {
156 self.read_u32_in(self.access_context(address))
157 }
158
159 pub fn read_u64(&self, address: Va) -> Result<u64, VmiError> {
161 self.read_u64_in(self.access_context(address))
162 }
163
164 pub fn read_uint(&self, address: Va, size: usize) -> Result<u64, VmiError> {
172 self.read_uint_in(self.access_context(address), size)
173 }
174
175 pub fn read_field(&self, base_address: Va, field: &Field) -> Result<u64, VmiError> {
184 self.read_field_in(self.access_context(base_address), field)
185 }
186
187 pub fn read_address(&self, address: Va) -> Result<u64, VmiError> {
189 self.read_address_in(self.access_context(address))
190 }
191
192 pub fn read_address_native(&self, address: Va) -> Result<u64, VmiError> {
194 self.read_address_native_in(self.access_context(address))
195 }
196
197 pub fn read_address32(&self, address: Va) -> Result<u64, VmiError> {
199 self.read_address32_in(self.access_context(address))
200 }
201
202 pub fn read_address64(&self, address: Va) -> Result<u64, VmiError> {
204 self.read_address64_in(self.access_context(address))
205 }
206
207 pub fn read_va(&self, address: Va) -> Result<Va, VmiError> {
209 self.read_va_in(self.access_context(address))
210 }
211
212 pub fn read_va_native(&self, address: Va) -> Result<Va, VmiError> {
214 self.read_va_native_in(self.access_context(address))
215 }
216
217 pub fn read_va32(&self, address: Va) -> Result<Va, VmiError> {
219 self.read_va32_in(self.access_context(address))
220 }
221
222 pub fn read_va64(&self, address: Va) -> Result<Va, VmiError> {
224 self.read_va64_in(self.access_context(address))
225 }
226
227 pub fn read_string_bytes_limited(
230 &self,
231 address: Va,
232 limit: usize,
233 ) -> Result<Vec<u8>, VmiError> {
234 self.read_string_bytes_limited_in(self.access_context(address), limit)
235 }
236
237 pub fn read_string_bytes(&self, address: Va) -> Result<Vec<u8>, VmiError> {
239 self.read_string_bytes_in(self.access_context(address))
240 }
241
242 pub fn read_string_utf16_bytes_limited(
245 &self,
246 address: Va,
247 limit: usize,
248 ) -> Result<Vec<u16>, VmiError> {
249 self.read_string_utf16_bytes_limited_in(self.access_context(address), limit)
250 }
251
252 pub fn read_string_utf16_bytes(&self, address: Va) -> Result<Vec<u16>, VmiError> {
254 self.read_string_utf16_bytes_in(self.access_context(address))
255 }
256
257 pub fn read_string_limited(&self, address: Va, limit: usize) -> Result<String, VmiError> {
260 self.read_string_limited_in(self.access_context(address), limit)
261 }
262
263 pub fn read_string(&self, address: Va) -> Result<String, VmiError> {
265 self.read_string_in(self.access_context(address))
266 }
267
268 pub fn read_string_utf16_limited(&self, address: Va, limit: usize) -> Result<String, VmiError> {
271 self.read_string_utf16_limited_in(self.access_context(address), limit)
272 }
273
274 pub fn read_string_utf16(&self, address: Va) -> Result<String, VmiError> {
276 self.read_string_utf16_in(self.access_context(address))
277 }
278
279 pub fn read_struct<T>(&self, address: Va) -> Result<T, VmiError>
281 where
282 T: IntoBytes + FromBytes,
283 {
284 self.read_struct_in(self.access_context(address))
285 }
286
287 pub fn read_in(
293 &self,
294 ctx: impl Into<AccessContext>,
295 buffer: &mut [u8],
296 ) -> Result<(), VmiError> {
297 self.core().read(ctx, buffer)
298 }
299
300 pub fn read_u8_in(&self, ctx: impl Into<AccessContext>) -> Result<u8, VmiError> {
302 self.core().read_u8(ctx)
303 }
304
305 pub fn read_u16_in(&self, ctx: impl Into<AccessContext>) -> Result<u16, VmiError> {
307 self.core().read_u16(ctx)
308 }
309
310 pub fn read_u32_in(&self, ctx: impl Into<AccessContext>) -> Result<u32, VmiError> {
312 self.core().read_u32(ctx)
313 }
314
315 pub fn read_u64_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
317 self.core().read_u64(ctx)
318 }
319
320 pub fn read_uint_in(
328 &self,
329 ctx: impl Into<AccessContext>,
330 size: usize,
331 ) -> Result<u64, VmiError> {
332 self.core().read_uint(ctx, size)
333 }
334
335 pub fn read_field_in(
344 &self,
345 ctx: impl Into<AccessContext>,
346 field: &Field,
347 ) -> Result<u64, VmiError> {
348 self.core().read_field(ctx, field)
349 }
350
351 pub fn read_address_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
353 self.core()
354 .read_address(ctx, self.registers().effective_address_width())
355 }
356
357 pub fn read_address_native_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
359 self.core()
360 .read_address(ctx, self.registers().address_width())
361 }
362
363 pub fn read_address32_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
365 self.core().read_address32(ctx)
366 }
367
368 pub fn read_address64_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
370 self.core().read_address64(ctx)
371 }
372
373 pub fn read_va_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
375 self.core()
376 .read_va(ctx, self.registers().effective_address_width())
377 }
378
379 pub fn read_va_native_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
381 self.core().read_va(ctx, self.registers().address_width())
382 }
383
384 pub fn read_va32_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
386 self.core().read_va32(ctx)
387 }
388
389 pub fn read_va64_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
391 self.core().read_va64(ctx)
392 }
393
394 pub fn read_string_bytes_limited_in(
397 &self,
398 ctx: impl Into<AccessContext>,
399 limit: usize,
400 ) -> Result<Vec<u8>, VmiError> {
401 self.core().read_string_bytes_limited(ctx, limit)
402 }
403
404 pub fn read_string_bytes_in(&self, ctx: impl Into<AccessContext>) -> Result<Vec<u8>, VmiError> {
406 self.core().read_string_bytes(ctx)
407 }
408
409 pub fn read_string_utf16_bytes_limited_in(
412 &self,
413 ctx: impl Into<AccessContext>,
414 limit: usize,
415 ) -> Result<Vec<u16>, VmiError> {
416 self.core().read_string_utf16_bytes_limited(ctx, limit)
417 }
418
419 pub fn read_string_utf16_bytes_in(
421 &self,
422 ctx: impl Into<AccessContext>,
423 ) -> Result<Vec<u16>, VmiError> {
424 self.core().read_string_utf16_bytes(ctx)
425 }
426
427 pub fn read_string_limited_in(
430 &self,
431 ctx: impl Into<AccessContext>,
432 limit: usize,
433 ) -> Result<String, VmiError> {
434 self.core().read_string_limited(ctx, limit)
435 }
436
437 pub fn read_string_in(&self, ctx: impl Into<AccessContext>) -> Result<String, VmiError> {
439 self.core().read_string(ctx)
440 }
441
442 pub fn read_string_utf16_limited_in(
445 &self,
446 ctx: impl Into<AccessContext>,
447 limit: usize,
448 ) -> Result<String, VmiError> {
449 self.core().read_string_utf16_limited(ctx, limit)
450 }
451
452 pub fn read_string_utf16_in(&self, ctx: impl Into<AccessContext>) -> Result<String, VmiError> {
454 self.core().read_string_utf16(ctx)
455 }
456
457 pub fn read_struct_in<T>(&self, ctx: impl Into<AccessContext>) -> Result<T, VmiError>
459 where
460 T: IntoBytes + FromBytes,
461 {
462 self.core().read_struct(ctx)
463 }
464
465 }
467
468impl<'a, Os> VmiState<'a, Os>
473where
474 Os: VmiOs,
475 Os::Driver: VmiRead + VmiWrite,
476{
477 pub fn write(&self, address: Va, buffer: &[u8]) -> Result<(), VmiError> {
479 self.write_in(self.access_context(address), buffer)
480 }
481
482 pub fn write_in(&self, ctx: impl Into<AccessContext>, buffer: &[u8]) -> Result<(), VmiError> {
484 self.core().write(ctx, buffer)
485 }
486
487 pub fn write_u8(&self, address: Va, value: u8) -> Result<(), VmiError> {
489 self.core().write_u8(self.access_context(address), value)
490 }
491
492 pub fn write_u16(&self, address: Va, value: u16) -> Result<(), VmiError> {
494 self.core().write_u16(self.access_context(address), value)
495 }
496
497 pub fn write_u32(&self, address: Va, value: u32) -> Result<(), VmiError> {
499 self.core().write_u32(self.access_context(address), value)
500 }
501
502 pub fn write_u64(&self, address: Va, value: u64) -> Result<(), VmiError> {
504 self.core().write_u64(self.access_context(address), value)
505 }
506
507 pub fn write_struct<T>(&self, address: Va, value: T) -> Result<(), VmiError>
509 where
510 T: FromBytes + IntoBytes + Immutable,
511 {
512 self.core()
513 .write_struct(self.access_context(address), value)
514 }
515}
516
517impl<'a, Os> VmiState<'a, Os>
522where
523 Os: VmiOs,
524 Os::Driver: VmiSetRegisters,
525{
526 pub fn set_registers(
528 &self,
529 vcpu: VcpuId,
530 registers: <Os::Architecture as Architecture>::Registers,
531 ) -> Result<(), VmiError> {
532 self.core().set_registers(vcpu, registers)
533 }
534}
535
536pub struct VmiOsState<'a, Os>(VmiState<'a, Os>)
538where
539 Os: VmiOs;
540
541impl<'a, Os> VmiOsState<'a, Os>
542where
543 Os: VmiOs,
544{
545 pub fn core(&self) -> &'a VmiCore<Os::Driver> {
547 self.0.core()
548 }
549
550 pub fn underlying_os(&self) -> &'a Os {
552 self.0.underlying_os()
553 }
554
555 pub fn session(&self) -> &VmiSession<'a, Os> {
557 self.0.session()
558 }
559
560 pub fn state(&self) -> VmiState<'a, Os> {
562 self.0
563 }
564
565 pub fn registers(&self) -> &<Os::Architecture as Architecture>::Registers {
567 self.0.registers()
568 }
569
570 pub fn function_argument_for_registers(
573 &self,
574 registers: &<Os::Architecture as Architecture>::Registers,
575 index: u64,
576 ) -> Result<u64, VmiError> {
577 Os::function_argument(self.0.with_registers(registers), index)
578 }
579
580 pub fn function_return_value_for_registers(
582 &self,
583 registers: &<Os::Architecture as Architecture>::Registers,
584 ) -> Result<u64, VmiError> {
585 Os::function_return_value(self.0.with_registers(registers))
586 }
587}