diff options
| author | wangxiaoyao <[email protected]> | 2023-02-20 13:44:20 +0800 |
|---|---|---|
| committer | guo <[email protected]> | 2023-02-21 08:48:49 +0800 |
| commit | 855aef9c9c59df12102d6ddfe43ef02c05171036 (patch) | |
| tree | f055f1f3d0ca5d3812b4e565b00107cdbf3a901c /components/mm | |
| parent | ed58f6676d074ec9f66ea78e23d1e1657c9fef20 (diff) | |
[mm] distinguish NULL and MAP_FAILED
Diffstat (limited to 'components/mm')
| -rw-r--r-- | components/mm/ioremap.c | 114 | ||||
| -rw-r--r-- | components/mm/ioremap.h | 31 | ||||
| -rw-r--r-- | components/mm/mm_aspace.c | 31 | ||||
| -rw-r--r-- | components/mm/mm_aspace.h | 16 |
4 files changed, 173 insertions, 19 deletions
diff --git a/components/mm/ioremap.c b/components/mm/ioremap.c new file mode 100644 index 0000000000..a24672a9f2 --- /dev/null +++ b/components/mm/ioremap.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-06 Jesven first version + */ +#include <rthw.h> +#include <rtthread.h> + +#include <mmu.h> +#include <mm_aspace.h> +#include <ioremap.h> + +void *rt_ioremap_start; +size_t rt_ioremap_size; + +#ifdef RT_USING_SMART + +#include <lwp_mm.h> +#define DBG_TAG "mm.ioremap" +#define DBG_LVL DBG_LOG +#include <rtdbg.h> + +enum ioremap_type +{ + MM_AREA_TYPE_PHY, + MM_AREA_TYPE_PHY_CACHED +}; + +static void *_ioremap_type(void *paddr, size_t size, enum ioremap_type type) +{ + void *v_addr = NULL; + size_t attr; + size_t lo_off; + int err; + + lo_off = (uintptr_t)paddr & ARCH_PAGE_MASK; + + struct rt_mm_va_hint hint = { + .prefer = RT_NULL, + .map_size = RT_ALIGN(size + lo_off, ARCH_PAGE_SIZE), + .flags = 0, + .limit_start = rt_ioremap_start, + .limit_range_size = rt_ioremap_size, + }; + + switch (type) + { + case MM_AREA_TYPE_PHY: + attr = MMU_MAP_K_DEVICE; + break; + case MM_AREA_TYPE_PHY_CACHED: + attr = MMU_MAP_K_RWCB; + break; + default: + return v_addr; + } + err = rt_aspace_map_phy(&rt_kernel_space, &hint, attr, MM_PA_TO_OFF(paddr), &v_addr); + + if (err) + { + LOG_W("IOREMAP 0x%lx failed", paddr); + v_addr = NULL; + } + else + { + v_addr = v_addr + lo_off; + } + return v_addr; +} + +void *rt_ioremap(void *paddr, size_t size) +{ + return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY); +} + +void *rt_ioremap_nocache(void *paddr, size_t size) +{ + return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY); +} + +void *rt_ioremap_cached(void *paddr, size_t size) +{ + return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY_CACHED); +} + +void rt_iounmap(volatile void *vaddr) +{ + rt_aspace_unmap(&rt_kernel_space, (void *)vaddr, 1); +} + +#else +void *rt_ioremap(void *paddr, size_t size) +{ + return paddr; +} + +void *rt_ioremap_nocache(void *paddr, size_t size) +{ + return paddr; +} + +void *rt_ioremap_cached(void *paddr, size_t size) +{ + return paddr; +} + +void rt_iounmap(volatile void *vaddr) +{ +} +#endif diff --git a/components/mm/ioremap.h b/components/mm/ioremap.h new file mode 100644 index 0000000000..2611b3a520 --- /dev/null +++ b/components/mm/ioremap.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-06 Jesven first version + */ +#ifndef __IOREMAP_H__ +#define __IOREMAP_H__ + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +void *rt_ioremap(void *paddr, size_t size); +void *rt_ioremap_nocache(void *paddr, size_t size); +void *rt_ioremap_cached (void *paddr, size_t size); +void rt_iounmap(volatile void *addr); + +extern void *rt_ioremap_start; +extern size_t rt_ioremap_size; + +#ifdef __cplusplus +} +#endif + +#endif /*__LWP_IOREMAP_H__*/ diff --git a/components/mm/mm_aspace.c b/components/mm/mm_aspace.c index 6a969074dc..aadf36e06b 100644 --- a/components/mm/mm_aspace.c +++ b/components/mm/mm_aspace.c @@ -204,10 +204,12 @@ static int _do_prefetch(rt_aspace_t aspace, rt_varea_t varea, void *start, LOG_W("%s: MMU mapping failed for va %p to %p of %lx", __func__, vaddr, store + PV_OFFSET, store_sz); } + else + { + rt_hw_tlb_invalidate_range(aspace, vaddr, store_sz, ARCH_PAGE_SIZE); + } vaddr += store_sz; off += store_sz >> ARCH_PAGE_SHIFT; - - rt_hw_tlb_invalidate_range(aspace, vaddr, store_sz, ARCH_PAGE_SIZE); } else { @@ -235,7 +237,7 @@ int _varea_install(rt_aspace_t aspace, rt_varea_t varea, rt_mm_va_hint_t hint) /* TODO try merge surrounding regions to optimize memory footprint */ - if (alloc_va != ARCH_MAP_FAILED) + if (alloc_va != RT_NULL) { varea->start = alloc_va; _aspace_bst_insert(aspace, varea); @@ -285,9 +287,10 @@ static int _mm_aspace_map(rt_aspace_t aspace, rt_varea_t varea, rt_size_t attr, static inline int _not_in_range(void *start, rt_size_t length, void *limit_start, rt_size_t limit_size) { - LOG_D("%s: [%p : %p] [%p : %p]", __func__, start, length, limit_start, limit_size); + if (start != RT_NULL) + LOG_D("%s: [%p : %p] [%p : %p]", __func__, start, length, limit_start, limit_size); /* assuming (base + length) will not overflow except (0) */ - return start != ARCH_MAP_FAILED + return start != RT_NULL ? ((length > (0ul - (uintptr_t)start)) || start < limit_start || (length + (rt_size_t)(start - limit_start)) > limit_size) : length > limit_size; @@ -295,7 +298,7 @@ static inline int _not_in_range(void *start, rt_size_t length, static inline int _not_align(void *start, rt_size_t length, rt_size_t mask) { - return (start != ARCH_MAP_FAILED) && + return (start != RT_NULL) && (((uintptr_t)start & mask) || (length & mask)); } @@ -438,7 +441,7 @@ int _mm_aspace_map_phy(rt_aspace_t aspace, rt_varea_t varea, if (err == RT_EOK) *ret_va = vaddr; else - *ret_va = ARCH_MAP_FAILED; + *ret_va = RT_NULL; } return err; @@ -511,8 +514,7 @@ void _aspace_unmap(rt_aspace_t aspace, void *addr, rt_size_t length) WR_UNLOCK(aspace); rt_hw_mmu_unmap(aspace, varea->start, varea->size); - rt_hw_tlb_invalidate_range(aspace, varea->start, varea->size, - ARCH_PAGE_SIZE); + rt_hw_tlb_invalidate_range(aspace, varea->start, varea->size, ARCH_PAGE_SIZE); rt_free(varea); varea = _aspace_bst_search_overlap(aspace, range); @@ -552,7 +554,7 @@ static inline void *_align(void *va, rt_ubase_t align_mask) static void *_ascending_search(rt_varea_t varea, rt_size_t req_size, rt_ubase_t align_mask, struct _mm_range limit) { - void *ret = ARCH_MAP_FAILED; + void *ret = RT_NULL; while (varea && varea->start < limit.end) { void *candidate = varea->start + varea->size; @@ -586,7 +588,7 @@ static void *_find_head_and_asc_search(rt_aspace_t aspace, rt_size_t req_size, rt_ubase_t align_mask, struct _mm_range limit) { - void *va = ARCH_MAP_FAILED; + void *va = RT_NULL; rt_varea_t varea = _aspace_bst_search_exceed(aspace, limit.start); if (varea) @@ -638,7 +640,7 @@ static void *_find_free(rt_aspace_t aspace, void *prefer, rt_size_t req_size, mm_flag_t flags) { rt_varea_t varea = NULL; - void *va = ARCH_MAP_FAILED; + void *va = RT_NULL; struct _mm_range limit = {limit_start, limit_start + limit_size - 1}; rt_ubase_t align_mask = ~0ul; @@ -647,7 +649,7 @@ static void *_find_free(rt_aspace_t aspace, void *prefer, rt_size_t req_size, align_mask = ~((1 << MMF_GET_ALIGN(flags)) - 1); } - if (prefer != ARCH_MAP_FAILED) + if (prefer != RT_NULL) { prefer = _align(prefer, align_mask); struct _mm_range range = {prefer, prefer + req_size - 1}; @@ -659,11 +661,12 @@ static void *_find_free(rt_aspace_t aspace, void *prefer, rt_size_t req_size, } else if (flags & MMF_MAP_FIXED) { + /* OVERLAP */ } else { va = _ascending_search(varea, req_size, align_mask, limit); - if (va == ARCH_MAP_FAILED) + if (va == RT_NULL) { limit.end = varea->start - 1; va = _find_head_and_asc_search(aspace, req_size, align_mask, diff --git a/components/mm/mm_aspace.h b/components/mm/mm_aspace.h index 8687f9a093..79986efe52 100644 --- a/components/mm/mm_aspace.h +++ b/components/mm/mm_aspace.h @@ -30,11 +30,11 @@ typedef rt_spinlock_t mm_spinlock; #define MM_PGTBL_UNLOCK(aspace) (rt_hw_spin_unlock(&((aspace)->pgtbl_lock))) #else -typedef rt_hw_spinlock_t mm_spinlock; +typedef struct rt_spinlock mm_spinlock; -#define MM_PGTBL_LOCK_INIT(aspace) (rt_hw_spin_lock_init(&((aspace)->pgtbl_lock))) -#define MM_PGTBL_LOCK(aspace) (rt_hw_spin_lock(&((aspace)->pgtbl_lock))) -#define MM_PGTBL_UNLOCK(aspace) (rt_hw_spin_unlock(&((aspace)->pgtbl_lock))) +#define MM_PGTBL_LOCK_INIT(aspace) (rt_spin_lock_init(&((aspace)->pgtbl_lock))) +#define MM_PGTBL_LOCK(aspace) (rt_spin_lock(&((aspace)->pgtbl_lock))) +#define MM_PGTBL_UNLOCK(aspace) (rt_spin_unlock(&((aspace)->pgtbl_lock))) #endif /* RT_USING_SMP */ @@ -108,6 +108,8 @@ enum rt_mmu_cntl { MMU_CNTL_NONCACHE, MMU_CNTL_CACHE, + MMU_CNTL_READONLY, + MMU_CNTL_READWRITE, MMU_CNTL_DUMMY_END, }; @@ -135,7 +137,7 @@ void rt_aspace_detach(rt_aspace_t aspace); /** * @brief Memory Map on Virtual Address Space to Mappable Object * *INFO There is no restriction to use NULL address(physical/virtual). - * Vaddr passing in addr must be page aligned. If vaddr is MM_MAP_FAILED, + * Vaddr passing in addr must be page aligned. If vaddr is RT_NULL, * a suitable address will be chose automatically. * * @param aspace target virtual address space @@ -206,4 +208,8 @@ rt_ubase_t rt_kmem_pvoff(void); void rt_kmem_pvoff_set(rt_ubase_t pvoff); +int rt_kmem_map_phy(void *va, void *pa, rt_size_t length, rt_size_t attr); + +void *rt_kmem_v2p(void *vaddr); + #endif /* __MM_ASPACE_H__ */ |
