@@ -14,15 +14,16 @@ use core::fmt::Debug;
1414use core:: mem:: size_of;
1515use core:: num:: NonZeroUsize ;
1616use core:: ops:: Range ;
17- use core:: ptr:: NonNull ;
1817use core:: sync:: atomic:: { fence, AtomicU32 , AtomicU64 , AtomicU8 , Ordering } ;
1918use core:: time:: Duration ;
2019
2120use kernel:: {
2221 addr:: PhysicalAddr ,
23- bindings , c_str, delay, device, drm,
22+ c_str, delay, device, drm,
2423 drm:: { gem:: BaseObject , gpuvm, mm} ,
25- error:: { to_result, Result } ,
24+ error:: Result ,
25+ io,
26+ io:: resource:: Resource ,
2627 prelude:: * ,
2728 static_lock_class,
2829 sync:: {
@@ -86,7 +87,7 @@ pub(crate) const IOVA_USER_USABLE_RANGE: Range<u64> = IOVA_USER_BASE..IOVA_UNK_P
8687/// A pre-allocated memory region for UAT management
8788struct UatRegion {
8889 base : PhysicalAddr ,
89- map : NonNull < core :: ffi :: c_void > ,
90+ map : io :: mem :: Mem ,
9091}
9192
9293/// It's safe to share UAT region records across threads.
@@ -769,13 +770,13 @@ impl UatShared {
769770 /// Returns the handoff region area
770771 fn handoff ( & self ) -> & Handoff {
771772 // SAFETY: pointer is non-null per the type invariant
772- unsafe { ( self . handoff_rgn . map . as_ptr ( ) as * mut Handoff ) . as_ref ( ) } . unwrap ( )
773+ unsafe { ( self . handoff_rgn . map . ptr ( ) as * mut Handoff ) . as_ref ( ) } . unwrap ( )
773774 }
774775
775776 /// Returns the TTBAT area
776777 fn ttbs ( & self ) -> & [ SlotTTBS ; UAT_NUM_CTX ] {
777778 // SAFETY: pointer is non-null per the type invariant
778- unsafe { ( self . ttbs_rgn . map . as_ptr ( ) as * mut [ SlotTTBS ; UAT_NUM_CTX ] ) . as_ref ( ) } . unwrap ( )
779+ unsafe { ( self . ttbs_rgn . map . ptr ( ) as * mut [ SlotTTBS ; UAT_NUM_CTX ] ) . as_ref ( ) } . unwrap ( )
779780 }
780781}
781782
@@ -815,13 +816,6 @@ pub(crate) struct Uat {
815816 kernel_lower_vm : Vm ,
816817}
817818
818- impl Drop for UatRegion {
819- fn drop ( & mut self ) {
820- // SAFETY: the pointer is valid by the type invariant
821- unsafe { bindings:: memunmap ( self . map . as_ptr ( ) ) } ;
822- }
823- }
824-
825819impl Handoff {
826820 /// Lock the handoff region from firmware access
827821 fn lock ( & self ) {
@@ -1309,33 +1303,23 @@ impl Drop for VmInner {
13091303}
13101304
13111305impl Uat {
1312- fn get_region ( dev : & device:: Device , name : & CStr ) -> Result < ( PhysicalAddr , usize ) > {
1313- let mut res = core:: mem:: MaybeUninit :: < bindings:: resource > :: uninit ( ) ;
1314-
1315- let res = unsafe {
1316- let dev_node = dev. of_node ( ) . ok_or ( EINVAL ) ?;
1317- let node = dev_node. parse_phandle_by_name (
1318- c_str ! ( "memory-region" ) ,
1319- c_str ! ( "memory-region-names" ) ,
1320- name,
1321- ) ;
1322- if node. is_none ( ) {
1323- dev_err ! ( dev, "Missing {} region\n " , name) ;
1324- return Err ( EINVAL ) ;
1325- }
1326- let ret = bindings:: of_address_to_resource ( node. unwrap ( ) . as_raw ( ) , 0 , res. as_mut_ptr ( ) ) ;
1306+ fn get_region ( dev : & device:: Device , name : & CStr ) -> Result < Resource > {
1307+ let dev_node = dev. of_node ( ) . ok_or ( EINVAL ) ?;
13271308
1328- if ret < 0 {
1329- dev_err ! ( dev, "Failed to get {} region\n " , name) ;
1330- to_result ( ret) ?
1331- }
1332-
1333- res. assume_init ( )
1309+ let node = dev_node. parse_phandle_by_name (
1310+ c_str ! ( "memory-region" ) ,
1311+ c_str ! ( "memory-region-names" ) ,
1312+ name,
1313+ ) ;
1314+ let Some ( node) = node else {
1315+ dev_err ! ( dev, "Missing {} region\n " , name) ;
1316+ return Err ( EINVAL ) ;
13341317 } ;
1318+ let res = node. address_as_resource ( 0 ) . inspect_err ( |_| {
1319+ dev_err ! ( dev, "Failed to get {} region\n " , name) ;
1320+ } ) ?;
13351321
1336- let rgn_size: usize = unsafe { bindings:: resource_size ( & res) } as usize ;
1337-
1338- Ok ( ( res. start , rgn_size) )
1322+ Ok ( res)
13391323 }
13401324
13411325 /// Map a bootloader-preallocated memory region
@@ -1345,34 +1329,36 @@ impl Uat {
13451329 size : usize ,
13461330 cached : bool ,
13471331 ) -> Result < UatRegion > {
1348- let ( start, rgn_size) = Self :: get_region ( dev, name) ?;
1332+ let res = Self :: get_region ( dev, name) ?;
1333+ let base = res. start ( ) ;
1334+ let res_size = res. size ( ) . try_into ( ) ?;
13491335
1350- if size > rgn_size {
1336+ if size > res_size {
13511337 dev_err ! (
13521338 dev,
13531339 "Region {} is too small (expected {}, got {})\n " ,
13541340 name,
13551341 size,
1356- rgn_size
1342+ res_size
13571343 ) ;
13581344 return Err ( ENOMEM ) ;
13591345 }
13601346
13611347 let flags = if cached {
1362- bindings :: MEMREMAP_WB
1348+ io :: mem :: MemFlags :: WB
13631349 } else {
1364- bindings :: MEMREMAP_WC
1350+ io :: mem :: MemFlags :: WC
13651351 } ;
1366- let map = unsafe { bindings:: memremap ( start, rgn_size, flags. into ( ) ) } ;
1367- let map = NonNull :: new ( map) ;
13681352
1369- match map {
1370- None => {
1371- dev_err ! ( dev, "Failed to remap {} region\n " , name) ;
1372- Err ( ENOMEM )
1373- }
1374- Some ( map) => Ok ( UatRegion { base : start, map } ) ,
1375- }
1353+ // SAFETY: The safety of this operation hinges on the correctness of
1354+ // much of this file and also the `pgtable` module, so it is difficult
1355+ // to prove in a single safety comment. Such is life with raw GPU
1356+ // page table management...
1357+ let map = unsafe { io:: mem:: Mem :: try_new ( res, flags) } . inspect_err ( |_| {
1358+ dev_err ! ( dev, "Failed to remap {} mem resource\n " , name) ;
1359+ } ) ?;
1360+
1361+ Ok ( UatRegion { base, map } )
13761362 }
13771363
13781364 /// Returns a reference to the global kernel (upper half) `Vm`
@@ -1476,7 +1462,7 @@ impl Uat {
14761462 let handoff_rgn = Self :: map_region ( dev. as_ref ( ) , c_str ! ( "handoff" ) , HANDOFF_SIZE , true ) ?;
14771463 let ttbs_rgn = Self :: map_region ( dev. as_ref ( ) , c_str ! ( "ttbs" ) , SLOTS_SIZE , true ) ?;
14781464
1479- let handoff = unsafe { & ( handoff_rgn. map . as_ptr ( ) as * mut Handoff ) . as_ref ( ) . unwrap ( ) } ;
1465+ let handoff = unsafe { & ( handoff_rgn. map . ptr ( ) as * mut Handoff ) . as_ref ( ) . unwrap ( ) } ;
14801466
14811467 dev_info ! ( dev. as_ref( ) , "MMU: Initializing kernel page table\n " ) ;
14821468
@@ -1510,7 +1496,10 @@ impl Uat {
15101496
15111497 let inner = Self :: make_inner ( dev) ?;
15121498
1513- let ( ttb1, ttb1size) = Self :: get_region ( dev. as_ref ( ) , c_str ! ( "pagetables" ) ) ?;
1499+ let res = Self :: get_region ( dev. as_ref ( ) , c_str ! ( "pagetables" ) ) ?;
1500+ let ttb1 = res. start ( ) ;
1501+ let ttb1size: usize = res. size ( ) . try_into ( ) ?;
1502+
15141503 if ttb1size < PAGETABLES_SIZE {
15151504 dev_err ! ( dev. as_ref( ) , "MMU: Pagetables region is too small\n " ) ;
15161505 return Err ( ENOMEM ) ;
0 commit comments