@@ -14,15 +14,15 @@ 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_mem:: { self , Resource } ,
2626 prelude:: * ,
2727 static_lock_class,
2828 sync:: {
@@ -86,7 +86,7 @@ pub(crate) const IOVA_USER_USABLE_RANGE: Range<u64> = IOVA_USER_BASE..IOVA_UNK_P
8686/// A pre-allocated memory region for UAT management
8787struct UatRegion {
8888 base : PhysicalAddr ,
89- map : NonNull < core :: ffi :: c_void > ,
89+ map : io_mem :: Mem ,
9090}
9191
9292/// It's safe to share UAT region records across threads.
@@ -769,13 +769,13 @@ impl UatShared {
769769 /// Returns the handoff region area
770770 fn handoff ( & self ) -> & Handoff {
771771 // SAFETY: pointer is non-null per the type invariant
772- unsafe { ( self . handoff_rgn . map . as_ptr ( ) as * mut Handoff ) . as_ref ( ) } . unwrap ( )
772+ unsafe { ( self . handoff_rgn . map . ptr ( ) as * mut Handoff ) . as_ref ( ) } . unwrap ( )
773773 }
774774
775775 /// Returns the TTBAT area
776776 fn ttbs ( & self ) -> & [ SlotTTBS ; UAT_NUM_CTX ] {
777777 // 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 ( )
778+ unsafe { ( self . ttbs_rgn . map . ptr ( ) as * mut [ SlotTTBS ; UAT_NUM_CTX ] ) . as_ref ( ) } . unwrap ( )
779779 }
780780}
781781
@@ -815,13 +815,6 @@ pub(crate) struct Uat {
815815 kernel_lower_vm : Vm ,
816816}
817817
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-
825818impl Handoff {
826819 /// Lock the handoff region from firmware access
827820 fn lock ( & self ) {
@@ -1309,33 +1302,24 @@ impl Drop for VmInner {
13091302}
13101303
13111304impl 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 ( ) ) ;
1305+ fn get_region ( dev : & device:: Device , name : & CStr ) -> Result < Resource > {
1306+ let dev_node = dev. of_node ( ) . ok_or ( EINVAL ) ?;
13271307
1328- if ret < 0 {
1329- dev_err ! ( dev, "Failed to get {} region\n " , name) ;
1330- to_result ( ret) ?
1331- }
1332-
1333- res. assume_init ( )
1308+ let node = dev_node. parse_phandle_by_name (
1309+ c_str ! ( "memory-region" ) ,
1310+ c_str ! ( "memory-region-names" ) ,
1311+ name,
1312+ ) ;
1313+ let Some ( node) = node else {
1314+ dev_err ! ( dev, "Missing {} region\n " , name) ;
1315+ return Err ( EINVAL ) ;
13341316 } ;
1317+ let res = node. address_as_resource ( 0 ) . map_err ( |e| {
1318+ dev_err ! ( dev, "Failed to get {} region\n " , name) ;
1319+ e
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,37 @@ 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) } . map_err ( |e| {
1358+ dev_err ! ( dev, "Failed to remap {} region\n " , name) ;
1359+ e
1360+ } ) ?;
1361+
1362+ Ok ( UatRegion { base, map } )
13761363 }
13771364
13781365 /// Returns a reference to the global kernel (upper half) `Vm`
@@ -1476,7 +1463,7 @@ impl Uat {
14761463 let handoff_rgn = Self :: map_region ( dev. as_ref ( ) , c_str ! ( "handoff" ) , HANDOFF_SIZE , true ) ?;
14771464 let ttbs_rgn = Self :: map_region ( dev. as_ref ( ) , c_str ! ( "ttbs" ) , SLOTS_SIZE , true ) ?;
14781465
1479- let handoff = unsafe { & ( handoff_rgn. map . as_ptr ( ) as * mut Handoff ) . as_ref ( ) . unwrap ( ) } ;
1466+ let handoff = unsafe { & ( handoff_rgn. map . ptr ( ) as * mut Handoff ) . as_ref ( ) . unwrap ( ) } ;
14801467
14811468 dev_info ! ( dev. as_ref( ) , "MMU: Initializing kernel page table\n " ) ;
14821469
@@ -1510,7 +1497,10 @@ impl Uat {
15101497
15111498 let inner = Self :: make_inner ( dev) ?;
15121499
1513- let ( ttb1, ttb1size) = Self :: get_region ( dev. as_ref ( ) , c_str ! ( "pagetables" ) ) ?;
1500+ let res = Self :: get_region ( dev. as_ref ( ) , c_str ! ( "pagetables" ) ) ?;
1501+ let ttb1 = res. start ( ) ;
1502+ let ttb1size: usize = res. size ( ) . try_into ( ) ?;
1503+
15141504 if ttb1size < PAGETABLES_SIZE {
15151505 dev_err ! ( dev. as_ref( ) , "MMU: Pagetables region is too small\n " ) ;
15161506 return Err ( ENOMEM ) ;
0 commit comments