fix __AROS_SETVECADDR invocations.
[AROS.git] / rom / kernel / kernel_mm.c
blobf476d86c7ca9ad9d2a5f697d8f373e22e4d616e9
1 /*
2 Copyright © 2010-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Page-based memory allocator, low-level routines.
6 Lang: english
7 */
9 #include <aros/config.h>
10 #include <exec/alerts.h>
11 #include <exec/execbase.h>
12 #include <proto/arossupport.h>
13 #include <proto/exec.h>
15 #include <inttypes.h>
17 #include <kernel_base.h>
18 #include <kernel_intern.h>
19 #include <kernel_debug.h>
20 #include <kernel_mm.h>
22 #define D(x)
24 void *mm_AllocPages(void *addr, uintptr_t length, uint32_t flags, struct KernelBase *KernelBase)
26 APTR res = NULL;
27 struct MemHeader *mh;
28 ULONG physFlags = flags & MEMF_PHYSICAL_MASK;
31 * Loop over MemHeader structures.
32 * We only add MemHeaders and never remove them, so i hope Forbid()/Permit()
33 * is not really necessary here.
35 ForeachNode(&SysBase->MemList, mh)
38 * Check for the right requirements and enough free memory.
39 * The requirements are OK if there's no bit in the
40 * 'physFlags' that isn't set in the 'mh->mh_Attributes'.
42 if ((physFlags & ~mh->mh_Attributes) || mh->mh_Free < length)
43 continue;
45 if (addr)
48 * If we have starting address, only one MemHeader can be
49 * appropriate for us. We look for it and attempt to allocate
50 * the given region from it.
52 if (addr >= mh->mh_Lower || addr + length <= mh->mh_Upper)
54 res = mm_AllocAbs(mh, addr, length);
55 break;
58 else
61 * Otherwise try to allocate pages from every MemHeader.
62 * Note that we still may fail if the memory is fragmented too much.
64 res = mm_Allocate(mh, length, flags);
65 if (res)
66 break;
70 return res;
73 void mm_FreePages(void *addr, uintptr_t length, struct KernelBase *KernelBase)
75 struct MemHeader *mh;
77 ForeachNode(&SysBase->MemList, mh)
79 D(bug("[KrnFreePages] Checking MemHeader 0x%p... ", mh));
81 /* Test if the memory belongs to this MemHeader. */
82 if (mh->mh_Lower <= addr && mh->mh_Upper > addr)
84 D(bug("[KrnFreePages] Match!\n"));
86 /* Test if it really fits into this MemHeader. */
87 if ((addr + length) > mh->mh_Upper)
88 /* Something is completely wrong. */
89 Alert(AN_MemCorrupt|AT_DeadEnd);
91 mm_Free(mh, addr, length);
92 break;
95 D(bug("[KrnFreePages] No match!\n"));
99 /* Allocate a space usable by exec.library/Allocate() inside kernel's MemHeader. */
100 struct MemHeader *mm_AllocExecHeader(struct MemHeader *mh, STRPTR name, IPTR maxsize)
102 struct MemHeader *bootmh = mm_Allocate(mh, maxsize, MEMF_ANY);
104 if (bootmh)
106 bootmh->mh_Node.ln_Succ = NULL;
107 bootmh->mh_Node.ln_Pred = NULL;
108 bootmh->mh_Node.ln_Name = name;
109 bootmh->mh_Node.ln_Type = mh->mh_Node.ln_Type;
110 bootmh->mh_Node.ln_Pri = mh->mh_Node.ln_Pri;
111 bootmh->mh_Attributes = mh->mh_Attributes;
112 bootmh->mh_First = (APTR)((IPTR)bootmh + MEMHEADER_TOTAL);
113 bootmh->mh_First->mc_Next = NULL;
114 bootmh->mh_First->mc_Bytes = maxsize - MEMHEADER_TOTAL;
117 * mh_Lower and mh_Upper are informational only. Since our MemHeader resides
118 * inside the region it describes, the region includes MemHeader.
120 bootmh->mh_Lower = (APTR)((IPTR)bootmh);
121 bootmh->mh_Upper = (APTR)((IPTR)bootmh + maxsize);
122 bootmh->mh_Free = bootmh->mh_First->mc_Bytes;
125 return bootmh;