[커널 18차] 60주차
2022.07.16 22:20
dma 진행.
git : https://github.com/iamroot18/5.10/commit/fb9f4ae3f7c265ce8444728dfc720e4a73cade95
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 7fd836bea7eb..b7c82715954a 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -167,6 +167,13 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
extern void iounmap(volatile void __iomem *addr);
extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
+/*
+ * IAMROOT, 2022.07.16:
+ * - ioremap
+ * write through. 신뢰성있는 device.(ex register) mapping.
+ * - ioremap_np
+ * ack까지 확인.
+ */
#define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
#define ioremap_np(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRnE))
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index d1cf47554d58..ca7e766bb36f 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -62,6 +62,19 @@ extern bool arm64_use_ng_mappings;
#define PROT_DEFAULT (_PROT_DEFAULT | PTE_MAYBE_NG)
#define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_MAYBE_NG)
+/*
+ * IAMROOT, 2022.07.16:
+ * - PROT_DEVICE_nGnRE : ioremap.(write through)
+ * PROT_NORMAL_NC : ioremap_wc.(write combine)
+ * PROT_DEVICE_nGnRnE : ioremap_np.(가장 높은 strong order)
+ * ---
+ * G : gather
+ * R : reorder
+ * E : early ack
+ *
+ * - memory 속도
+ * wb > wt > wc > nc
+ */
#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE))
#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f28b41cb4b7f..6d05e5aa52a8 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -339,6 +339,10 @@ int pfn_valid(unsigned long pfn)
}
EXPORT_SYMBOL(pfn_valid);
+/*
+ * IAMROOT, 2022.07.16:
+ * - @pfn이 lm mapping되있는지 확인한다.
+ */
int pfn_is_map_memory(unsigned long pfn)
{
phys_addr_t addr = PFN_PHYS(pfn);
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index b7c81dacabf0..c75d68411792 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -17,6 +17,11 @@
#include <asm/fixmap.h>
#include <asm/tlbflush.h>
+/*
+ * IAMROOT, 2022.07.16:
+ * @return mapping된 va.
+ * @phys_addr, @size로 vmalloc에 mapping후 mapping된 va를 return한다.
+ */
static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
pgprot_t prot, void *caller)
{
@@ -46,9 +51,18 @@ static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
if (WARN_ON(pfn_is_map_memory(__phys_to_pfn(phys_addr))))
return NULL;
+/*
+ * IAMROOT, 2022.07.16:
+ * - vmalloc공간에 size를 VM_IOREMAP으로 area를 얻어온다.
+ */
area = get_vm_area_caller(size, VM_IOREMAP, caller);
if (!area)
return NULL;
+
+/*
+ * IAMROOT, 2022.07.16:
+ * - 얻어온 area에 mapping을 한다.
+ */
addr = (unsigned long)area->addr;
area->phys_addr = phys_addr;
@@ -61,6 +75,10 @@ static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
return (void __iomem *)(offset + addr);
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - @prot로 vmalloc에 mapping한다.
+ */
void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot)
{
return __ioremap_caller(phys_addr, size, prot,
@@ -81,6 +99,12 @@ void iounmap(volatile void __iomem *io_addr)
}
EXPORT_SYMBOL(iounmap);
+/*
+ * IAMROOT, 2022.07.16:
+ * - @phys_addr이 이미 lm mapping이 되있다면 return va.
+ * 아니면 normal prot로 vmalloc에 mapping해서 가져온다.
+ * - normal memory 속성이 즉 cache
+ */
void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
{
/* For normal memory we already have a cacheable mapping. */
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 438cfe87bb2d..d45e5ef5a5a6 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -1049,6 +1049,11 @@ EXPORT_SYMBOL(of_io_request_and_map);
* It returns -ENODEV if "dma-ranges" property was not found for this
* device in the DT.
*/
+/*
+ * IAMROOT, 2022.07.16:
+ * dma-ranges = <0xc0000000 0x00000000 0x3f000000>;
+ * ^dma ^phy ^size
+ */
int of_dma_get_range(struct device_node *np, const struct bus_dma_region **map)
{
struct device_node *node = of_node_get(np);
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 9da8835ba5a5..f028a7eb6a8d 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -327,6 +327,32 @@ static DEFINE_MUTEX(of_rmem_assigned_device_mutex);
*
* Returns error code or zero on success.
*/
+
+/*
+ * IAMROOT, 2022.07.16:
+ *
+ * reserved-memory {
+ * #address-cells = <2>;
+ * #size-cells = <2>;
+ * ranges;
+ *
+ * bman_fbpr: bman-fbpr {
+ * compatible = "shared-dma-pool";
+ * size = <0 0x1000000>;
+ * alignment = <0 0x1000000>;
+ * no-map;
+ * };
+ * };
+ *
+ * bman: bman@1890000 {
+ * compatible = "fsl,bman";
+ * reg = <0x0 0x1890000 0x0 0x10000>;
+ * interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ * memory-region = <&bman_fbpr>;
+ * ^..idx = 0
+ * };
+ *
+ */
int of_reserved_mem_device_init_by_idx(struct device *dev,
struct device_node *np, int idx)
{
diff --git a/include/asm-generic/bitops/fls64.h b/include/asm-generic/bitops/fls64.h
index 68c60f7d48b3..a0ea171dd2bc 100644
--- a/include/asm-generic/bitops/fls64.h
+++ b/include/asm-generic/bitops/fls64.h
@@ -32,6 +32,10 @@ static __always_inline int fls64(__u64 x)
* long형이 64bit일 경우 __builtin_clzl(__fls)로만으로 처리가 가능하므로,
* 해당 함수 처리조건인 0검사, __가 없는 fls는 0번 bit가 1인것을 고려한 + 1처리를
* 해준다.
+ * ex) x == 0. return 0
+ * x = 1, return 1
+ * x = 2, return 2
+ * x = 3, return 2
*/
static __always_inline int fls64(__u64 x)
{
diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index 18aade195884..b5e16bda5e46 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -24,6 +24,11 @@ struct bus_dma_region {
u64 offset;
};
+/*
+ * IAMROOT, 2022.07.16:
+ * - @paddr이 @dev의 dma_range_map중에 범위에 있는 주소인지 확인해서 offset을 계산후
+ * return 한다.
+ */
static inline dma_addr_t translate_phys_to_dma(struct device *dev,
phys_addr_t paddr)
{
@@ -55,6 +60,12 @@ static inline phys_addr_t translate_dma_to_phys(struct device *dev,
#define phys_to_dma_unencrypted phys_to_dma
#endif
#else
+
+/*
+ * IAMROOT, 2022.07.16:
+ * - dma_range_map이 있는 경우 @paddr이 map에 있는지 확인후 offset을 고려해서 return하고
+ * 아니면 즉시 paddr을 return한다.
+ */
static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
phys_addr_t paddr)
{
@@ -69,6 +80,11 @@ static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
* phys_to_dma_unencrypted is for use on special unencrypted memory like swiotlb
* buffers.
*/
+/*
+ * IAMROOT, 2022.07.16:
+ * - dma_range_map이 있는 경우 @paddr이 map에 있는지 확인후 offset을 고려해서 return하고
+ * 아니면 즉시 paddr을 return한다.
+ */
static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
{
return __sme_set(phys_to_dma_unencrypted(dev, paddr));
diff --git a/include/linux/dma-map-ops.h b/include/linux/dma-map-ops.h
index 0d5b06b3a4a6..936b2c397c4c 100644
--- a/include/linux/dma-map-ops.h
+++ b/include/linux/dma-map-ops.h
@@ -75,6 +75,10 @@ struct dma_map_ops {
#ifdef CONFIG_DMA_OPS
#include <asm/dma-mapping.h>
+/*
+ * IAMROOT, 2022.07.16:
+ * - dev에서 dma_ops를 지원했으면 그걸 가져오고 아니면 arch것을 가져온다.
+ */
static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
{
if (dev->dma_ops)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index dca2b1355bb1..580d65d8269b 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -412,6 +412,10 @@ static inline void dma_sync_sgtable_for_device(struct device *dev,
#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0)
#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
+/*
+ * IAMROOT, 2022.07.16:
+ * - driver에서 사용하는 dma 할당자.
+ */
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
@@ -553,6 +557,10 @@ static inline void *dmam_alloc_coherent(struct device *dev, size_t size,
(gfp & __GFP_NOWARN) ? DMA_ATTR_NO_WARN : 0);
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - wc dma
+ */
static inline void *dma_alloc_wc(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t gfp)
{
diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c
index 25fc85a7aebe..086cf6e5876a 100644
--- a/kernel/dma/coherent.c
+++ b/kernel/dma/coherent.c
@@ -20,6 +20,10 @@ struct dma_coherent_mem {
bool use_dev_dma_pfn_offset;
};
+/*
+ * IAMROOT, 2022.07.16:
+ * - dt에서 지정한 reserved memory.
+ */
static inline struct dma_coherent_mem *dev_get_coherent_memory(struct device *dev)
{
if (dev && dev->dma_mem)
@@ -27,6 +31,10 @@ static inline struct dma_coherent_mem *dev_get_coherent_memory(struct device *de
return NULL;
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - @mem의 debice_base를 가져온다.
+ */
static inline dma_addr_t dma_get_device_base(struct device *dev,
struct dma_coherent_mem * mem)
{
@@ -35,6 +43,12 @@ static inline dma_addr_t dma_get_device_base(struct device *dev,
return mem->device_base;
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - @device_addr, @size로 vmalloc공간에 write combine 방식으로 mapping을 한다.
+ * dma 구조체 정보를 return한다.
+ * - device driver 전용 dma memory를 구성한다.
+ */
static struct dma_coherent_mem *dma_init_coherent_memory(phys_addr_t phys_addr,
dma_addr_t device_addr, size_t size, bool use_dma_pfn_offset)
{
@@ -46,10 +60,18 @@ static struct dma_coherent_mem *dma_init_coherent_memory(phys_addr_t phys_addr,
if (!size)
return ERR_PTR(-EINVAL);
+/*
+ * IAMROOT, 2022.07.16:
+ * - va를 가져온다.
+ */
mem_base = memremap(phys_addr, size, MEMREMAP_WC);
if (!mem_base)
return ERR_PTR(-EINVAL);
+/*
+ * IAMROOT, 2022.07.16:
+ * - dma 자료구조를 slab에서 가져오고 초기화한다.
+ */
dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dma_mem)
goto out_unmap_membase;
@@ -85,6 +107,10 @@ static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
kfree(mem);
}
+/*
+ * IAMROOT, 2022.07.16:
+ * @dev에 @mem을 등록한다.
+ */
static int dma_assign_coherent_memory(struct device *dev,
struct dma_coherent_mem *mem)
{
@@ -115,6 +141,10 @@ static int dma_assign_coherent_memory(struct device *dev,
* As a simplification for the platforms, only *one* such region of memory may
* be declared per device.
*/
+/*
+ * IAMROOT, 2022.07.16:
+ * - custom 방식의 dma declear.
+ */
int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
dma_addr_t device_addr, size_t size)
{
@@ -131,6 +161,10 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
return ret;
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - bitmap에서 size를 할당할수있는 영역을 얻어오고 얻어온 va를 return한다.
+ */
static void *__dma_alloc_from_coherent(struct device *dev,
struct dma_coherent_mem *mem,
ssize_t size, dma_addr_t *dma_handle)
@@ -177,6 +211,10 @@ static void *__dma_alloc_from_coherent(struct device *dev,
* Returns 0 if dma_alloc_coherent should continue with allocating from
* generic memory areas, or !0 if dma_alloc_coherent should return @ret.
*/
+/*
+ * IAMROOT, 2022.07.16:
+ * - bitmap을 통해서 요청 공간만큼 memory를 할당해온다.
+ */
int dma_alloc_from_dev_coherent(struct device *dev, ssize_t size,
dma_addr_t *dma_handle, void **ret)
{
@@ -301,6 +339,10 @@ int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *vaddr,
vaddr, size, ret);
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - global dma.
+ */
int dma_init_global_coherent(phys_addr_t phys_addr, size_t size)
{
struct dma_coherent_mem *mem;
@@ -326,6 +368,10 @@ int dma_init_global_coherent(phys_addr_t phys_addr, size_t size)
static struct reserved_mem *dma_reserved_default_memory __initdata;
#endif
+/*
+ * IAMROOT, 2022.07.16:
+ * - device tree에서 등록된 dma.
+ */
static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
{
if (!rmem->priv) {
@@ -353,6 +399,38 @@ static const struct reserved_mem_ops rmem_dma_ops = {
.device_release = rmem_dma_device_release,
};
+/*
+ * IAMROOT, 2022.07.16:
+ * - cma로 사용하는 case
+ * reserved-memory {
+ * #address-cells = <2>;
+ * #size-cells = <2>;
+ * ranges;
+ * linux,cma {
+ * compatible = "shared-dma-pool";
+ * reusable;
+ * size = <0x0 0x800000>;
+ * alignment = <0x0 0x400000>;
+ * linux,cma-default;
+ * };
+ * };
+ *
+ * - dma로만 사용하는 case.
+ * reserved_memory: reserved-memory {
+ * #address-cells = <2>;
+ * #size-cells = <2>;
+ * ranges;
+ *
+ * mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+ * compatible = "shared-dma-pool";
+ * reg = <0x00 0xa0000000 0x00 0x100000>;
+ * no-map;
+ * };
+ * };
+ *
+ * - 각 device driver들은 of_reserved_mem_device_init()을 통해서 어떤 reserved memory를 사용할지
+ * 결정한다.
+ */
static int __init rmem_dma_setup(struct reserved_mem *rmem)
{
unsigned long node = rmem->fdt_node;
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index cd1d5be4400d..086e9b6285ee 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -26,6 +26,11 @@
*/
unsigned int zone_dma_bits __ro_after_init = 24;
+/*
+ * IAMROOT, 2022.07.16:
+ * - dma_range_map이 있는 경우 @paddr이 map에 있는지 확인후 offset을 고려해서
+ * return하고 아니면 즉시 paddr을 return한다.
+ */
static inline dma_addr_t phys_to_dma_direct(struct device *dev,
phys_addr_t phys)
{
@@ -40,6 +45,14 @@ static inline struct page *dma_direct_to_page(struct device *dev,
return pfn_to_page(PHYS_PFN(dma_to_phys(dev, dma_addr)));
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - dma max를 구해 mask값을 적당히 2의 배수로 올림해서 가져온다.
+ * - ex) max_dma = 0x6000_0000
+ * fls(max_dma) = 31
+ * (1 << (31 - 1)) * 2 = 0x8000_0000
+ * 0x8000_0000 - 1 = 0x7fff_ffff
+ */
u64 dma_direct_get_required_mask(struct device *dev)
{
phys_addr_t phys = (phys_addr_t)(max_pfn - 1) << PAGE_SHIFT;
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 8349a9f2c345..bf0e4e22ad06 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -108,12 +108,27 @@ void *dmam_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
}
EXPORT_SYMBOL(dmam_alloc_attrs);
+/*
+ * IAMROOT, 2022.07.16:
+ * - direct 연결이 가능한지 확인한다.
+ * 1. ops가 없으면 1:1 mampping의 의미 이므로 가능.
+ * 2. bus dma limit >= dev dma max 이면 true.
+ */
static bool dma_go_direct(struct device *dev, dma_addr_t mask,
const struct dma_map_ops *ops)
{
+/*
+ * IAMROOT, 2022.07.16:
+ * - 1:1 이므로 ops가 불필요.
+ */
if (likely(!ops))
return true;
#ifdef CONFIG_DMA_OPS_BYPASS
+/*
+ * IAMROOT, 2022.07.16:
+ * - bus가 지원하는 폭이 dev의 max dma보다 크거나 같으면 true.
+ * 즉 bus 범위 >= dev 범위
+ */
if (dev->dma_ops_bypass)
return min_not_zero(mask, dev->bus_dma_limit) >=
dma_direct_get_required_mask(dev);
@@ -127,6 +142,13 @@ static bool dma_go_direct(struct device *dev, dma_addr_t mask,
* This allows IOMMU drivers to set a bypass mode if the DMA mask is large
* enough.
*/
+/*
+ * IAMROOT, 2022.07.16:
+ * - direct mapping
+ * 물리주소와 io주소가 동일하게 된다.
+ * - IOMMU없이 system memory를 그대로(1:1) 사용한다.
+ * IOMMU사용시 bypass mode를 지원한다면 사용한다.
+ */
static inline bool dma_alloc_direct(struct device *dev,
const struct dma_map_ops *ops)
{
@@ -489,6 +511,11 @@ u64 dma_get_required_mask(struct device *dev)
}
EXPORT_SYMBOL_GPL(dma_get_required_mask);
+/*
+ * IAMROOT, 2022.07.16:
+ * @attrs dma_alloc_wc에서 불러올경우 DMA_ATTR_WRITE_COMBINE이 추가된다.
+ * gfp에 __GFP_NO_WARN이 있었을경우 DMA_ATTR_NO_WARN이 추가 됬었다.
+ */
void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag, unsigned long attrs)
{
@@ -497,12 +524,20 @@ void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
WARN_ON_ONCE(!dev->coherent_dma_mask);
+/*
+ * IAMROOT, 2022.07.16:
+ * - dev 전용 coherent가 있으면 해당 영역에서 bitmap을 통해서 할당해온다.
+ */
if (dma_alloc_from_dev_coherent(dev, size, dma_handle, &cpu_addr))
return cpu_addr;
/* let the implementation decide on the zone to allocate from: */
flag &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
+/*
+ * IAMROOT, 2022.07.16:
+ * - direct alloc인지 ops alloc인지 판단해 alloc한다.
+ */
if (dma_alloc_direct(dev, ops))
cpu_addr = dma_direct_alloc(dev, size, dma_handle, flag, attrs);
else if (ops->alloc)
diff --git a/kernel/iomem.c b/kernel/iomem.c
index 62c92e43aa0d..cc5a3e123546 100644
--- a/kernel/iomem.c
+++ b/kernel/iomem.c
@@ -13,6 +13,11 @@ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
#endif
#ifndef arch_memremap_wb
+
+/*
+ * IAMROOT, 2022.07.16:
+ * - normal memory prot로 vmalloc에 mapping후 va를 받아온다.
+ */
static void *arch_memremap_wb(resource_size_t offset, unsigned long size)
{
return (__force void *)ioremap_cache(offset, size);
@@ -27,6 +32,11 @@ static bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
}
#endif
+/*
+ * IAMROOT, 2022.07.16:
+ * - @offset을 lm va로 return.
+ * - @offset 이 highmem이 아닌지 확인한다. highmem은 lm이 안된다.
+ */
static void *try_ram_remap(resource_size_t offset, size_t size,
unsigned long flags)
{
@@ -68,6 +78,17 @@ static void *try_ram_remap(resource_size_t offset, size_t size,
* be coalesced together (e.g. in the CPU's write buffers), but is otherwise
* uncached. Attempts to map System RAM with this mapping type will fail.
*/
+/*
+ * IAMROOT, 2022.07.16:
+ * - @flags에 따라 vmalloc mapping을 하여 va를 가져온다.
+ * 이미 mapping된경우 lm va를 가져온다.
+ *
+ * wb wt wc
+ * PROT_NORMAL | PROT_DEVICE_nGnRE | PROT_NORMAL_NC
+ * - 옵션만으로 봤을때 속도는 wb > wt > wc.
+ * 하지만 arm64에서는 wt를 지원안하므로 cache를 사용안하는 prot를 사용하여 실제
+ * 성능이 wb > wc > wt으로 될것이다.
+ */
void *memremap(resource_size_t offset, size_t size, unsigned long flags)
{
int is_ram = region_intersects(offset, size,
@@ -84,6 +105,14 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
}
/* Try all mapping types requested until one returns non-NULL */
+/*
+ * IAMROOT, 2022.07.16:
+ * - write back 요청 : 일반 DRAM으로 cache를 사용하는 memory로 mapping하겠다는것.
+ * 1. 이미 mapping된 상태 (REGION_INTERSECTS)
+ * address만 가져오면 된다.
+ * 2. 할당을 해야되는 상태
+ * normal memory prot로 vmalloc에 mapping한다.
+ */
if (flags & MEMREMAP_WB) {
/*
* MEMREMAP_WB is special in that it can be satisfied
@@ -103,6 +132,16 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
* address mapping. Enforce that this mapping is not aliasing
* System RAM.
*/
+/*
+ * IAMROOT, 2022.07.16:
+ * - papago
+ * 매핑이 아직 없고 다른 요청 플래그가 있으면 새 가상 주소 매핑을 설정하려고
+ * 합니다. 이 매핑이 시스템 RAM을 별칭으로 지정하지 않도록 합니다.
+ * - flags가 only writeback + a 인 상태에서 위에서 할당실패했으면 return.
+ * 할당이 실패한 상황.
+ * - flags가 only writeback이 아니면서 is_ram이 REGION_INTERSECTS면 return.
+ * 요청이 잘못된 상황
+ */
if (!addr && is_ram == REGION_INTERSECTS && flags != MEMREMAP_WB) {
WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
&offset, (unsigned long) size);
diff --git a/kernel/resource.c b/kernel/resource.c
index ca9f5198a01f..a8ea50779890 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -502,6 +502,14 @@ int __weak page_is_ram(unsigned long pfn)
}
EXPORT_SYMBOL_GPL(page_is_ram);
+/*
+ * IAMROOT, 2022.07.16:
+ * - iomem에서 영역이 겹치는지 확인한다.
+ * - 여기에서 등록하는건 물리주소, return은 가상주소.
+ * @return REGION_DISJOINT 겹친게 없거나 other만 겹쳤다면.
+ * REGION_INTERSECTS 같은 flags, desc과 겹쳤고, 그외 겹친 other가 없다면.
+ * REGION_MIXED 같은 flags, desc와 겹쳣고, 그 외 other와도 겹쳤다면.
+ */
static int __region_intersects(resource_size_t start, size_t size,
unsigned long flags, unsigned long desc)
{
@@ -512,6 +520,12 @@ static int __region_intersects(resource_size_t start, size_t size,
res.start = start;
res.end = start + size - 1;
+/*
+ * IAMROOT, 2022.07.16:
+ * - is_type : resoure와 요청범위의 flag와 desc가 일치하는지 확인한다.
+ * 일치한 상태에서(is_type = true) 범위가 겹치면 type++,
+ * 일치하지 않은 상태에서 겹치면 other++
+ */
for (p = iomem_resource.child; p ; p = p->sibling) {
bool is_type = (((p->flags & flags) == flags) &&
((desc == IORES_DESC_NONE) ||
@@ -521,12 +535,27 @@ static int __region_intersects(resource_size_t start, size_t size,
is_type ? type++ : other++;
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - type == 0, other == 0 or type ==0, other > 0
+ * 겹친게 없거나 다른 장치와 겹쳤으면 return.
+ */
if (type == 0)
return REGION_DISJOINT;
+/*
+ * IAMROOT, 2022.07.16:
+ * - type > 0, other == 0
+ * 같은 type과 겹쳤으면 return.
+ */
if (other == 0)
return REGION_INTERSECTS;
+/*
+ * IAMROOT, 2022.07.16:
+ * - tpye > 0, other > 0
+ * 같은 type 범위와, 같은 other 둘다 겹친게 있으면 return.
+ */
return REGION_MIXED;
}
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 663dd81967d4..69cfc3e3f4e8 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -1246,6 +1246,10 @@ enum {
REG_OP_RELEASE, /* clear all bits in region */
};
+/*
+ * IAMROOT, 2022.07.16:
+ * @reg_op에 따라 찾은 bitmap을 검색/할당/해제 한다.
+ */
static int __reg_op(unsigned long *bitmap, unsigned int pos, int order, int reg_op)
{
int nbits_reg; /* number of bits in region */
@@ -1312,6 +1316,10 @@ static int __reg_op(unsigned long *bitmap, unsigned int pos, int order, int reg_
* Return the bit offset in bitmap of the allocated region,
* or -errno on failure.
*/
+/*
+ * IAMROOT, 2022.07.16:
+ * 요청 @bits로 free공간을 찾은후 alloc한다.
+ */
int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order)
{
unsigned int pos, end; /* scans bitmap by regions of size order */
diff --git a/mm/memblock.c b/mm/memblock.c
index c58ff3807541..889ac14f99a7 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -2413,6 +2413,12 @@ bool __init_memblock memblock_is_memory(phys_addr_t addr)
return memblock_search(&memblock.memory, addr) != -1;
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - memblock을 @addr로 search한다. mapping된 정상적인 memblcok이 존재했을때
+ * nomap flag가 없다면 return true.
+ * - 즉 이미 mapping된 memblock인지 확인한다.
+ */
bool __init_memblock memblock_is_map_memory(phys_addr_t addr)
{
int i = memblock_search(&memblock.memory, addr);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 6e5511f59fcd..707ad0711173 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -333,6 +333,10 @@ static int vmap_range_noflush(unsigned long addr, unsigned long end,
return err;
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - mapping.
+ */
int ioremap_page_range(unsigned long addr, unsigned long end,
phys_addr_t phys_addr, pgprot_t prot)
{
@@ -2918,6 +2922,10 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
__builtin_return_address(0));
}
+/*
+ * IAMROOT, 2022.07.16:
+ * - vmalloc 공간에 요청 영역을 mapping한다.
+ */
struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
const void *caller)
{
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 631 |
247 | 커널 스터디 공개 노트 링크 [1] | 박동하 | 2016.05.20 | 233179 |
246 | [커널 17차] 41주차 | ㅇㅇㅇ | 2021.06.13 | 36553 |
245 | [커널 17차] 56주차 | ㅇㅇㅇ | 2021.10.03 | 27532 |
244 | [커널 18차] 1주차 | V4bel | 2021.05.29 | 3600 |
243 | [커널 17차 6조] 2주차 | 김정근 | 2020.08.31 | 2175 |
242 | [커널 17차 2조] 4주차 | wellbeing | 2020.09.12 | 1518 |
241 | 커널 스터디 13차 D조 스터디 로그 링크입니다. | 목태양 | 2016.05.15 | 1226 |
240 | 해킹&보안 1차 A팀 스터디로그 링크 | 수비니겨 | 2016.05.19 | 1186 |
239 | [커널 16차 B조] 1주차 [1] | kdy0252 | 2019.05.25 | 1084 |
238 | [커널 17차 A조] 20주차 | 주영 | 2021.01.11 | 1019 |
237 | [커널 20차] 24주차 | 이민찬 | 2023.10.22 | 855 |
236 | [커널 17차 2조] 5주차 | wellbeing | 2020.09.19 | 739 |
235 | [커널 17차 8조] 1주차 [3] | JSYoo5B | 2020.08.22 | 718 |
234 | [커널 19차] 0주차 - 오리엔테이션 | 리턴 | 2022.05.07 | 602 |
233 | [커널 17차] 26주차 | 주영 | 2021.03.01 | 541 |
232 | [커널 19차] 37 주차 | Min | 2023.02.04 | 479 |
231 | [커널 19차] 1주차 | 리턴 | 2022.05.16 | 461 |
230 | [커널 17차] 32주차 | ㅇㅇㅇ | 2021.04.11 | 445 |
229 | [커널 17차 A조] 12주차 | 주영 | 2020.11.16 | 410 |
.