@@ -519,7 +519,7 @@ impl File {
519519
520520 match data. op {
521521 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 ) ,
523523 uapi:: drm_asahi_bind_op_ASAHI_BIND_OP_UNBIND_ALL => {
524524 Self :: do_gem_unbind_all ( device, data, file)
525525 }
@@ -609,6 +609,66 @@ impl File {
609609 Ok ( 0 )
610610 }
611611
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+
612672 pub ( crate ) fn unbind_gem_object ( file : & DrmFile , bo : & gem:: Object ) -> Result {
613673 let mut index = 0 ;
614674 loop {
@@ -865,6 +925,39 @@ impl File {
865925 Ok ( _) => Ok ( 0 ) ,
866926 }
867927 }
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+ }
868961}
869962
870963impl Drop for File {
0 commit comments