@@ -519,7 +519,7 @@ impl File {
519
519
520
520
match data. op {
521
521
uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_BIND => Self :: do_gem_bind ( device, data, file) ,
522
- uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_UNBIND => Err ( ENOTSUPP ) ,
522
+ uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_UNBIND => Self :: do_gem_unbind ( device , data , file ) ,
523
523
uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_UNBIND_ALL => {
524
524
Self :: do_gem_unbind_all ( device, data, file)
525
525
}
@@ -609,6 +609,66 @@ impl File {
609
609
Ok ( 0 )
610
610
}
611
611
612
+ pub ( crate ) fn do_gem_unbind (
613
+ _device : & AsahiDevice ,
614
+ data : & mut uapi:: drm_asahi_gem_bind ,
615
+ file : & DrmFile ,
616
+ ) -> Result < u32 > {
617
+ if data. offset != 0 || data. flags != 0 || data. handle != 0 {
618
+ cls_pr_debug ! ( Errors , "gem_unbind: offset/flags/handle not zero\n " ) ;
619
+ return Err ( EINVAL ) ;
620
+ }
621
+
622
+ if ( data. addr | data. range ) as usize & mmu:: UAT_PGMSK != 0 {
623
+ cls_pr_debug ! (
624
+ Errors ,
625
+ "gem_bind: Addr/range/offset not page aligned: {:#x} {:#x}\n " ,
626
+ data. addr,
627
+ data. range
628
+ ) ;
629
+ return Err ( EINVAL ) ; // Must be page aligned
630
+ }
631
+
632
+ let start = data. addr ;
633
+ let end = data. addr . checked_add ( data. range ) . ok_or ( EINVAL ) ?;
634
+ let range = start..end;
635
+
636
+ if !VM_USER_RANGE . is_superset ( range. clone ( ) ) {
637
+ cls_pr_debug ! (
638
+ Errors ,
639
+ "gem_bind: Invalid unmap range {:#x}..{:#x} (not contained in user range)\n " ,
640
+ start,
641
+ end
642
+ ) ;
643
+ return Err ( EINVAL ) ; // Invalid map range
644
+ }
645
+
646
+ let guard = file
647
+ . inner ( )
648
+ . vms ( )
649
+ . get ( data. vm_id . try_into ( ) ?)
650
+ . ok_or ( ENOENT ) ?;
651
+
652
+ // Clone it immediately so we aren't holding the XArray lock
653
+ let vm = guard. borrow ( ) . vm . clone ( ) ;
654
+ let kernel_range = guard. borrow ( ) . kernel_range . clone ( ) ;
655
+ core:: mem:: drop ( guard) ;
656
+
657
+ if kernel_range. overlaps ( range. clone ( ) ) {
658
+ cls_pr_debug ! (
659
+ Errors ,
660
+ "gem_bind: Invalid unmap range {:#x}..{:#x} (intrudes in kernel range)\n " ,
661
+ start,
662
+ end
663
+ ) ;
664
+ return Err ( EINVAL ) ;
665
+ }
666
+
667
+ vm. unmap_range ( range. start , range. range ( ) ) ?;
668
+
669
+ Ok ( 0 )
670
+ }
671
+
612
672
pub ( crate ) fn unbind_gem_object ( file : & DrmFile , bo : & gem:: Object ) -> Result {
613
673
let mut index = 0 ;
614
674
loop {
@@ -865,6 +925,39 @@ impl File {
865
925
Ok ( _) => Ok ( 0 ) ,
866
926
}
867
927
}
928
+
929
+ /// IOCTL: get_time: Get the current GPU timer value.
930
+ pub ( crate ) fn get_time (
931
+ device : & AsahiDevice ,
932
+ data : & mut uapi:: drm_asahi_get_time ,
933
+ file : & DrmFile ,
934
+ ) -> Result < u32 > {
935
+
936
+ if data. extensions != 0 || data. flags != 0 {
937
+ cls_pr_debug ! ( Errors , "get_time: Unexpected extensions or flags\n " ) ;
938
+ return Err ( EINVAL ) ;
939
+ }
940
+
941
+ let mut tp: kernel:: bindings:: timespec64 = Default :: default ( ) ;
942
+ let mut gputime: u64 = 0 ;
943
+
944
+ // TODO: bindings
945
+ // SAFETY: These functions are safe to call as long as the argument pointer is valid
946
+ unsafe {
947
+ core:: arch:: asm!(
948
+ "mrs {x}, CNTPCT_EL0" ,
949
+ x = out( reg) gputime
950
+ ) ;
951
+ kernel:: bindings:: ktime_get_raw_ts64 ( & mut tp) ;
952
+ kernel:: bindings:: timens_add_monotonic ( & mut tp) ;
953
+ }
954
+
955
+ data. gpu_timestamp = gputime;
956
+ data. tv_sec = tp. tv_sec ;
957
+ data. tv_nsec = tp. tv_nsec ;
958
+
959
+ Ok ( 0 )
960
+ }
868
961
}
869
962
870
963
impl Drop for File {
0 commit comments