6
6
use crate :: bindings:: * ;
7
7
#[ cfg( feature = "with-serde" ) ]
8
8
use serde_derive:: { Deserialize , Serialize } ;
9
- use std:: cmp ;
9
+ use std:: convert :: TryFrom ;
10
10
use std:: fmt;
11
11
use std:: ptr;
12
12
use vmm_sys_util:: errno;
13
13
use zerocopy:: { AsBytes , FromBytes , FromZeroes } ;
14
14
15
+ pub const HV_PAGE_SIZE : usize = HV_HYP_PAGE_SIZE as usize ;
16
+
15
17
#[ repr( C ) ]
16
18
#[ derive( Debug , Default , Copy , Clone , Eq , PartialEq , AsBytes , FromBytes , FromZeroes ) ]
17
19
#[ cfg_attr( feature = "with-serde" , derive( Deserialize , Serialize ) ) ]
@@ -463,7 +465,7 @@ impl Buffer {
463
465
Ok ( buf)
464
466
}
465
467
466
- pub fn dealloc ( self ) {
468
+ pub fn dealloc ( & mut self ) {
467
469
// SAFETY: buf was allocated with layout
468
470
unsafe {
469
471
std:: alloc:: dealloc ( self . buf , self . layout ) ;
@@ -477,15 +479,13 @@ impl Buffer {
477
479
478
480
impl Drop for Buffer {
479
481
fn drop ( & mut self ) {
480
- // SAFETY: buf was allocated with layout
481
- unsafe {
482
- std:: alloc:: dealloc ( self . buf , self . layout ) ;
483
- }
482
+ self . dealloc ( ) ;
484
483
}
485
484
}
486
485
487
486
#[ repr( C ) ]
488
487
#[ derive( Copy , Clone , Debug , AsBytes , FromBytes , FromZeroes ) ]
488
+ /// Fixed buffer for lapic state
489
489
pub struct LapicState {
490
490
pub regs : [ :: std:: os:: raw:: c_char ; 1024usize ] ,
491
491
}
@@ -494,25 +494,12 @@ impl Default for LapicState {
494
494
unsafe { :: std:: mem:: zeroed ( ) }
495
495
}
496
496
}
497
- /*
498
- impl Default for hv_register_value {
499
- fn default() -> Self {
500
- unsafe { ::std::mem::zeroed() }
501
- }
502
- } */
497
+
503
498
#[ repr( C ) ]
504
499
#[ derive( Copy , Clone , Debug , AsBytes , FromBytes , FromZeroes ) ]
505
- /// This struct normalizes the actual mhsv XSave structure
506
- /// XSave only used in save and restore functionalities, serilization and
507
- /// deserialization are needed. Putting all the fields into a single buffer makes
508
- /// it easier to serialize and deserialize
509
- /// Total buffer size: 4120
510
- /// flags: 8 bytes
511
- /// states: 8 bytes
512
- /// data_size: 8 bytes
513
- /// Actual xsave buffer: 4096 bytes
500
+ /// Fixed buffer for xsave state
514
501
pub struct XSave {
515
- pub buffer : [ :: std :: os :: raw :: c_char ; 4120usize ] ,
502
+ pub buffer : [ u8 ; 4096usize ] ,
516
503
}
517
504
518
505
impl Default for XSave {
@@ -521,69 +508,45 @@ impl Default for XSave {
521
508
}
522
509
}
523
510
524
- impl From < mshv_vp_state > for XSave {
525
- fn from ( reg : mshv_vp_state ) -> Self {
526
- let ret = XSave {
511
+ impl TryFrom < Buffer > for XSave {
512
+ type Error = errno:: Error ;
513
+ fn try_from ( buf : Buffer ) -> Result < Self , Self :: Error > {
514
+ let mut ret = XSave {
527
515
..Default :: default ( )
528
516
} ;
529
- let mut bs = reg. xsave . flags . to_le_bytes ( ) ;
530
- unsafe {
531
- ptr:: copy (
532
- bs. as_ptr ( ) as * mut u8 ,
533
- ret. buffer . as_ptr ( ) . offset ( 0 ) as * mut u8 ,
534
- 8 ,
535
- )
536
- } ;
537
- bs = unsafe { reg. xsave . states . as_uint64 . to_le_bytes ( ) } ;
538
- unsafe {
539
- ptr:: copy (
540
- bs. as_ptr ( ) as * mut u8 ,
541
- ret. buffer . as_ptr ( ) . offset ( 8 ) as * mut u8 ,
542
- 8 ,
543
- )
544
- } ;
545
- bs = reg. buf_size . to_le_bytes ( ) ;
546
- unsafe {
547
- ptr:: copy (
548
- bs. as_ptr ( ) as * mut u8 ,
549
- ret. buffer . as_ptr ( ) . offset ( 16 ) as * mut u8 ,
550
- 8 ,
551
- )
552
- } ;
553
- let min: usize = cmp:: min ( 4096 , reg. buf_size as u32 ) as usize ;
554
- unsafe {
555
- ptr:: copy (
556
- reg. buf . bytes ,
557
- ret. buffer . as_ptr ( ) . offset ( 24 ) as * mut u8 ,
558
- min,
559
- )
560
- } ;
561
- ret
517
+ let ret_size = std:: mem:: size_of_val ( & ret. buffer ) ;
518
+ if ret_size < buf. size ( ) {
519
+ return Err ( errno:: Error :: new ( libc:: EINVAL ) ) ;
520
+ }
521
+ // SAFETY: ret is large enough to hold buffer
522
+ unsafe { ptr:: copy ( buf. buf , ret. buffer . as_mut_ptr ( ) , buf. size ( ) ) } ;
523
+ Ok ( ret)
562
524
}
563
525
}
564
526
565
- impl From < XSave > for mshv_vp_state {
566
- fn from ( reg : XSave ) -> Self {
567
- let flags = reg. flags ( ) ;
568
- let states = reg. states ( ) ;
569
- let buffer_size = reg. data_size ( ) ;
570
- let mut ret = mshv_vp_state {
571
- type_ : hv_get_set_vp_state_type_HV_GET_SET_VP_STATE_XSAVE,
572
- buf_size : buffer_size,
573
- ..Default :: default ( )
574
- } ;
575
- ret. xsave . flags = flags;
576
- ret. xsave . states . as_uint64 = states;
577
- ret. buf . bytes = reg. data_buffer ( ) as * mut u8 ;
578
- ret
527
+ impl TryFrom < & XSave > for Buffer {
528
+ type Error = errno:: Error ;
529
+ fn try_from ( reg : & XSave ) -> Result < Self , Self :: Error > {
530
+ let reg_size = std:: mem:: size_of_val ( & reg. buffer ) ;
531
+ let num_pages = ( reg_size + HV_PAGE_SIZE - 1 ) >> HV_HYP_PAGE_SHIFT ;
532
+ let buffer = Buffer :: new ( num_pages * HV_PAGE_SIZE , HV_PAGE_SIZE ) ?;
533
+ // SAFETY: buffer is large enough to hold reg
534
+ unsafe { ptr:: copy ( reg. buffer . as_ptr ( ) , buffer. buf , reg_size) } ;
535
+ Ok ( buffer)
579
536
}
580
537
}
581
- impl From < mshv_vp_state > for LapicState {
582
- fn from ( reg : mshv_vp_state ) -> Self {
538
+
539
+ impl TryFrom < Buffer > for LapicState {
540
+ type Error = errno:: Error ;
541
+ fn try_from ( buf : Buffer ) -> Result < Self , Self :: Error > {
583
542
let mut ret: LapicState = LapicState :: default ( ) ;
584
543
let state = ret. regs . as_mut_ptr ( ) ;
585
- let hv_state = unsafe { * reg. buf . lapic } ;
544
+ if buf. size ( ) < std:: mem:: size_of :: < hv_local_interrupt_controller_state > ( ) {
545
+ return Err ( errno:: Error :: new ( libc:: EINVAL ) ) ;
546
+ }
547
+ // SAFETY: buf is large enough for hv_local_interrupt_controller_state
586
548
unsafe {
549
+ let hv_state = & * ( buf. buf as * const hv_local_interrupt_controller_state ) ;
587
550
* ( state. offset ( LOCAL_APIC_OFFSET_APIC_ID ) as * mut u32 ) = hv_state. apic_id ;
588
551
* ( state. offset ( LOCAL_APIC_OFFSET_VERSION ) as * mut u32 ) = hv_state. apic_version ;
589
552
* ( state. offset ( LOCAL_APIC_OFFSET_REMOTE_READ ) as * mut u32 ) = hv_state. apic_remote_read ;
@@ -605,45 +568,46 @@ impl From<mshv_vp_state> for LapicState {
605
568
hv_state. apic_counter_value ;
606
569
* ( state. offset ( LOCAL_APIC_OFFSET_DIVIDER ) as * mut u32 ) =
607
570
hv_state. apic_divide_configuration ;
608
- }
609
571
610
- /* vectors ISR TMR IRR */
611
- for i in 0 ..8 {
612
- unsafe {
572
+ /* vectors ISR TMR IRR */
573
+ for i in 0 ..8 {
613
574
* ( state. offset ( LOCAL_APIC_OFFSET_ISR + i * 16 ) as * mut u32 ) =
614
575
hv_state. apic_isr [ i as usize ] ;
615
576
* ( state. offset ( LOCAL_APIC_OFFSET_TMR + i * 16 ) as * mut u32 ) =
616
577
hv_state. apic_tmr [ i as usize ] ;
617
578
* ( state. offset ( LOCAL_APIC_OFFSET_IRR + i * 16 ) as * mut u32 ) =
618
579
hv_state. apic_irr [ i as usize ] ;
619
580
}
620
- }
621
581
622
- // Highest priority interrupt (isr = in service register) this is how WHP computes it
623
- let mut isrv: u32 = 0 ;
624
- for i in ( 0 ..8 ) . rev ( ) {
625
- let val: u32 = hv_state. apic_isr [ i as usize ] ;
626
- if val != 0 {
627
- isrv = 31 - val. leading_zeros ( ) ; // index of most significant set bit
628
- isrv += i * 4 * 8 ; // i don't know
629
- break ;
582
+ // Highest priority interrupt (isr = in service register) this is how WHP computes it
583
+ let mut isrv: u32 = 0 ;
584
+ for i in ( 0 ..8 ) . rev ( ) {
585
+ let val: u32 = hv_state. apic_isr [ i as usize ] ;
586
+ if val != 0 {
587
+ isrv = 31 - val. leading_zeros ( ) ; // index of most significant set bit
588
+ isrv += i * 4 * 8 ; // i don't know
589
+ break ;
590
+ }
630
591
}
631
- }
632
592
633
- // TODO This is meant to be max(tpr, isrv), but tpr is not populated!
634
- unsafe {
593
+ // TODO This is meant to be max(tpr, isrv), but tpr is not populated!
635
594
* ( state. offset ( LOCAL_APIC_OFFSET_PPR ) as * mut u32 ) = isrv;
636
595
}
637
- ret
596
+ Ok ( ret)
638
597
}
639
598
}
640
599
641
- impl From < LapicState > for mshv_vp_state {
642
- fn from ( reg : LapicState ) -> Self {
643
- let state = reg. regs . as_ptr ( ) ;
644
- let mut vp_state: mshv_vp_state = mshv_vp_state:: default ( ) ;
600
+ impl TryFrom < & LapicState > for Buffer {
601
+ type Error = errno:: Error ;
602
+ fn try_from ( reg : & LapicState ) -> Result < Self , Self :: Error > {
603
+ let hv_state_size = std:: mem:: size_of :: < hv_local_interrupt_controller_state > ( ) ;
604
+ let num_pages = ( hv_state_size + HV_PAGE_SIZE - 1 ) >> HV_HYP_PAGE_SHIFT ;
605
+ let buffer = Buffer :: new ( num_pages * HV_PAGE_SIZE , HV_PAGE_SIZE ) ?;
606
+ // SAFETY: buf is large enough for hv_local_interrupt_controller_state
645
607
unsafe {
646
- let mut lapic_state = hv_local_interrupt_controller_state {
608
+ let state = reg. regs . as_ptr ( ) ;
609
+ let hv_state = & mut * ( buffer. buf as * mut hv_local_interrupt_controller_state ) ;
610
+ * hv_state = hv_local_interrupt_controller_state {
647
611
apic_id : * ( state. offset ( LOCAL_APIC_OFFSET_APIC_ID ) as * mut u32 ) ,
648
612
apic_version : * ( state. offset ( LOCAL_APIC_OFFSET_VERSION ) as * mut u32 ) ,
649
613
apic_remote_read : * ( state. offset ( LOCAL_APIC_OFFSET_REMOTE_READ ) as * mut u32 ) ,
@@ -671,75 +635,30 @@ impl From<LapicState> for mshv_vp_state {
671
635
672
636
/* vectors ISR TMR IRR */
673
637
for i in 0 ..8 {
674
- lapic_state . apic_isr [ i as usize ] =
638
+ hv_state . apic_isr [ i as usize ] =
675
639
* ( state. offset ( LOCAL_APIC_OFFSET_ISR + i * 16 ) as * mut u32 ) ;
676
- lapic_state . apic_tmr [ i as usize ] =
640
+ hv_state . apic_tmr [ i as usize ] =
677
641
* ( state. offset ( LOCAL_APIC_OFFSET_TMR + i * 16 ) as * mut u32 ) ;
678
- lapic_state . apic_irr [ i as usize ] =
642
+ hv_state . apic_irr [ i as usize ] =
679
643
* ( state. offset ( LOCAL_APIC_OFFSET_IRR + i * 16 ) as * mut u32 ) ;
680
644
}
681
- vp_state. type_ =
682
- hv_get_set_vp_state_type_HV_GET_SET_VP_STATE_LOCAL_INTERRUPT_CONTROLLER_STATE;
683
- vp_state. buf_size = 1024 ;
684
- let boxed_obj = Box :: new ( lapic_state) ;
685
- vp_state. buf . lapic = Box :: into_raw ( boxed_obj) ;
686
645
}
687
- vp_state
646
+
647
+ Ok ( buffer)
688
648
}
689
649
}
650
+
690
651
// implement `Display` for `XSave`
691
652
impl fmt:: Display for XSave {
692
653
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
693
654
write ! (
694
655
f,
695
- "flags: {}, states: {}, buffer_size: {}, buffer: {:?}\n data: {:02X?}" ,
696
- self . flags( ) ,
697
- self . states( ) ,
698
- self . data_size( ) ,
699
- self . data_buffer( ) ,
656
+ "buffer: {:?}\n data: {:02X?}" ,
657
+ self . buffer. as_ptr( ) ,
700
658
self . buffer,
701
659
)
702
660
}
703
661
}
704
- // Implement XSave to retrieve each field from the buffer
705
- impl XSave {
706
- pub fn flags ( & self ) -> u64 {
707
- let array: [ u8 ; 8 ] = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
708
- unsafe {
709
- ptr:: copy (
710
- self . buffer . as_ptr ( ) . offset ( 0 ) as * mut u8 ,
711
- array. as_ptr ( ) as * mut u8 ,
712
- 8 ,
713
- )
714
- } ;
715
- u64:: from_le_bytes ( array)
716
- }
717
- pub fn states ( & self ) -> u64 {
718
- let array: [ u8 ; 8 ] = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
719
- unsafe {
720
- ptr:: copy (
721
- self . buffer . as_ptr ( ) . offset ( 8 ) as * mut u8 ,
722
- array. as_ptr ( ) as * mut u8 ,
723
- 8 ,
724
- )
725
- } ;
726
- u64:: from_le_bytes ( array)
727
- }
728
- pub fn data_size ( & self ) -> u64 {
729
- let array: [ u8 ; 8 ] = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
730
- unsafe {
731
- ptr:: copy (
732
- self . buffer . as_ptr ( ) . offset ( 16 ) as * mut u8 ,
733
- array. as_ptr ( ) as * mut u8 ,
734
- 8 ,
735
- )
736
- } ;
737
- u64:: from_le_bytes ( array)
738
- }
739
- pub fn data_buffer ( & self ) -> * const u8 {
740
- unsafe { self . buffer . as_ptr ( ) . offset ( 24 ) as * mut u8 }
741
- }
742
- }
743
662
744
663
#[ repr( C ) ]
745
664
#[ derive( Debug , Default , Copy , Clone , Eq , PartialEq , AsBytes , FromBytes , FromZeroes ) ]
0 commit comments