source: trunk/src/win32k/k32/k32AllocMemEx.cpp@ 10367

Last change on this file since 10367 was 5179, checked in by bird, 25 years ago

Implemented the API. And extending the it to take alignment flags too.

File size: 9.9 KB
Line 
1/* $Id: k32AllocMemEx.cpp,v 1.5 2001-02-19 05:49:05 bird Exp $
2 *
3 * k32AllocMemEx - Equivalent to DosAllocMem, but this one
4 * uses the address in ppv.
5 *
6 * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12
13/*******************************************************************************
14* Defined Constants And Macros *
15*******************************************************************************/
16#define INCL_DOSMEMMGR
17#define INCL_DOSERRORS
18#define INCL_OS2KRNL_VM
19#define INCL_OS2KRNL_TK
20
21#define NO_WIN32K_LIB_FUNCTIONS
22
23
24
25/*******************************************************************************
26* Header Files *
27*******************************************************************************/
28#include <os2.h>
29#include "devSegDf.h" /* Win32k segment definitions. */
30#include "OS2Krnl.h"
31#include "win32k.h"
32#include "k32.h"
33#include "options.h"
34#include "dev32.h"
35#include "log.h"
36#include "macros.h"
37
38
39/* nasty! These should be imported from the kernel later! */
40/*
41 * These are unchanged from Warp3 to Warp 4.51.
42 */
43ULONG vmApiF0[] =
44{
45 0, /* 0 */
46 VMA_READ, /* PAG_READ */
47 VMA_WRITE | VMA_READ, /* PAG_WRITE */
48 VMA_WRITE | VMA_READ, /* PAG_READ | PAG_WRITE */
49 VMA_EXECUTE, /* PAG_EXECUTE */
50 VMA_EXECUTE | VMA_READ, /* PAG_READ | PAG_EXECUTE */
51 VMA_WRITE | VMA_EXECUTE | VMA_READ, /* PAG_WRITE | PAG_EXECUTE */
52 VMA_WRITE | VMA_EXECUTE | VMA_READ, /* PAG_READ | PAG_WRITE | PAG_EXECUTE */
53 VMA_GUARD, /* PAG_GUARD */
54 VMA_READ | VMA_GUARD, /* PAG_READ | PAG_GUARD */
55 VMA_WRITE | VMA_READ | VMA_GUARD, /* PAG_WRITE | PAG_GUARD */
56 VMA_WRITE | VMA_READ | VMA_GUARD, /* PAG_READ | PAG_WRITE | PAG_GUARD */
57 VMA_EXECUTE | VMA_GUARD, /* PAG_EXECUTE | PAG_GUARD */
58 VMA_EXECUTE | VMA_READ | VMA_GUARD, /* PAG_READ | PAG_EXECUTE | PAG_GUARD */
59 VMA_WRITE | VMA_EXECUTE | VMA_READ | VMA_GUARD, /* PAG_WRITE | PAG_EXECUTE | PAG_GUARD */
60 VMA_WRITE | VMA_EXECUTE | VMA_READ | VMA_GUARD /* PAG_READ | PAG_WRITE | PAG_EXECUTE | PAG_GUARD */
61};
62
63ULONG vmApiF1[] =
64{
65 0, /* 0 */
66 0, /* PAG_COMMIT */
67 VMA_DECOMMIT, /* PAG_DECOMMIT */
68 VMA_DECOMMIT, /* PAG_COMMIT | PAG_DECOMMIT */
69 VMA_SELALLOC, /* OBJ_TILE */
70 VMA_SELALLOC, /* PAG_COMMIT | OBJ_TILE */
71 VMA_DECOMMIT | VMA_SELALLOC, /* PAG_DECOMMIT | OBJ_TILE */
72 VMA_DECOMMIT | VMA_SELALLOC, /* PAG_COMMIT | PAG_DECOMMIT | OBJ_TILE */
73 VMA_PROTECTED, /* OBJ_PROTECTED */
74 VMA_PROTECTED, /* PAG_COMMIT | OBJ_PROTECTED */
75 VMA_PROTECTED | VMA_DECOMMIT, /* PAG_DECOMMIT | OBJ_PROTECTED */
76 VMA_PROTECTED | VMA_DECOMMIT, /* PAG_COMMIT | PAG_DECOMMIT | OBJ_PROTECTED */
77 VMA_PROTECTED | VMA_SELALLOC, /* OBJ_TILE | OBJ_PROTECTED */
78 VMA_PROTECTED | VMA_SELALLOC, /* PAG_COMMIT | OBJ_TILE | OBJ_PROTECTED */
79 VMA_PROTECTED | VMA_DECOMMIT | VMA_SELALLOC, /* PAG_DECOMMIT | OBJ_TILE | OBJ_PROTECTED */
80 VMA_PROTECTED | VMA_DECOMMIT | VMA_SELALLOC /* PAG_COMMIT | PAG_DECOMMIT | OBJ_TILE | OBJ_PROTECTED */
81};
82
83
84/**
85 * Extended edition of DosAllocMem:
86 * Allows you to suggest an address where you want the memory allocated.
87 * Specify 64KB alignment.
88 * @returns OS2 returncode.
89 * ERROR_INVALID_PARAMETER Some input parameter is bad.
90 * ERROR_INVALID_ADDRESS *pvv is wrong.
91 * @param ppv Pointer to a pointer.
92 * If OBJ_LOCATION is specified this *ppv holds a suggested address of the memory block.
93 * @param cb Size of the memory block.
94 * @param flFlags Flags just as for DosAllocMem and two more:
95 * OBJ_ALIGN64K Align on 64 boundrary. Default in compatibility region.
96 * OBJ_ALIGNPAGE Page align the memory. (only high region) Default in 32-bit region.
97 * OBJ_LOCATION *ppv specifies a suggested address of the memory block.
98 * @param ulCS CS where the memoryobject was requested.
99 * @param ulEIP EIP where the memoryobject was requested.
100 * @sketch
101 * @status partially implemented.
102 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
103 * @remark Seems like I have to solve that "Grow private arena" problem which
104 * applies when we allocate at a specific address.
105 * I'll look into it ASAP and add a fix for this in the loader too.
106 */
107APIRET k32AllocMemEx(PPVOID ppv, ULONG cb, ULONG flFlags, ULONG ulCS, ULONG ulEIP)
108{
109 APIRET rc;
110 ULONG flVMFlags;
111 ULONG flSelFlags;
112 VMAC vmac = {0};
113 ULONG cbCommit;
114 HMTE hMTE;
115
116
117 kprintf(("k32AllocMemEx(ppv=0x%08x, cb=0x%x, flFlags=0x%08x, ulCS=0x%04x, ulEIP=0x%08x)\n",
118 ppv, cb, flFlags, ulCS, ulEIP));
119
120 /** @sketch
121 * General parameter validations:
122 * Only allowable flFlagss - DosAllocMem + our own.
123 * At least one access flag must be set.
124 * OBJ_TILE don't work OBJ_ANY or OBJ_ALIGNPAGE.
125 * Must be larger than 0 bytes.
126 * Caller CS and EIP must not be 0.
127 * Align size and check if it's resonable.
128 * If address is specified Then
129 * Check that the memory block is within possible private address space.
130 */
131 if ( (flFlags & ~(PAG_READ | PAG_WRITE | PAG_EXECUTE | PAG_GUARD | PAG_COMMIT
132 | OBJ_ANY | OBJ_TILE | OBJ_SELMAPALL | OBJ_ALIGNMASK | OBJ_LOCATION))
133 || (flFlags & (PAG_READ | PAG_WRITE | PAG_EXECUTE)) == 0
134 || ((flFlags & OBJ_TILE) && ((flFlags & OBJ_ANY) || (flFlags & OBJ_ALIGNMASK) == OBJ_ALIGNPAGE))
135 || cb == 0
136 || ulCS == 0 || ulEIP == 0
137 )
138 {
139 kprintf(("k32AllocMemEx: Bad param (1)\n"));
140 return ERROR_INVALID_PARAMETER;
141 }
142
143 cb = PAGEALIGNUP(cb);
144 if (cb >= VirtualAddressLimit)
145 {
146 kprintf(("k32AllocMemEx: Bad size cb=%d\n", cb));
147 return ERROR_NOT_ENOUGH_MEMORY;
148 }
149
150 if (flFlags & OBJ_LOCATION)
151 {
152 rc = TKFuULongNF(SSToDS(&vmac.ac_va), ppv);
153 if (rc)
154 {
155 kprintf(("k32AllocMemEx: Failed to fetch *ppv. rc=%d\n", rc));
156 return rc;
157 }
158 kprintf(("k32AllocMemEx: Location *ppv =0x%08x\n", vmac.ac_va));
159 if ( vmac.ac_va < 0x10000
160 || vmac.ac_va + cb < vmac.ac_va
161 || vmac.ac_va + cb > ((vmac.ac_va >= 0x20000000 && pahvmhShr) ? pahvmhShr : pahvmShr)->ah_laddrMax
162 )
163 {
164 kprintf(("k32AllocMemEx: *ppv has an invalid address. *ppv=0x%08x\n", vmac.ac_va));
165 return ERROR_INVALID_ADDRESS;
166 }
167 }
168
169
170 /** @sketch
171 * Get the hMTE of the executable object we're called from - may fail.
172 * Determin size of precommitted memory.
173 * Determin VM Flags:
174 * Default
175 * Handle OBJ_ANY (only applies if there are high arenas).
176 * Access flags are determined using vmApiF0.
177 * Commit, decommit, tile and unused protected flags using vmApiF1.
178 * Set Alignment flags if specified.
179 * If location specified Then Set location specific and arena flags correctly.
180 * Else set the location any flag.
181 * Determin SEL Flags.
182 */
183 hMTE = VMGetOwner(ulCS, ulEIP);
184
185 cbCommit = flFlags & PAG_COMMIT ? cb : 0;
186
187 flVMFlags = VMA_USER | VMA_ZEROFILL | VMA_LOWMEM2 | VMA_ARENAPRIVATE /* 0x02010084*/
188 | ((flFlags & OBJ_ANY) && pahvmhShr ? VMA_ARENAHIGHA : VMA_SELALLOC | VMA_ALIGNSEL)
189 | vmApiF0[flFlags & (PAG_READ | PAG_WRITE | PAG_EXECUTE | PAG_GUARD)]
190 | vmApiF1[(flFlags & (PAG_COMMIT | PAG_DECOMMIT | OBJ_TILE | OBJ_PROTECTED)) >> 4];
191
192 if ( (flVMFlags & VMA_SELALLOC)
193 || (flFlags & OBJ_ALIGNMASK) == OBJ_ALIGN64K)
194 flVMFlags |= VMA_ALIGNSEL;
195 else if ((flFlags & OBJ_ALIGNMASK) == OBJ_ALIGNPAGE)
196 flVMFlags |= VMA_ALIGNPAGE;
197
198 if (flFlags & OBJ_LOCATION)
199 {
200 flVMFlags |= VMA_LOCSPECIFIC;
201 if (vmac.ac_va < 0x20000000)
202 flVMFlags &= ~VMA_ARENAHIGHA;
203 }
204 else
205 flVMFlags |= VMA_LOCANY;
206
207 flSelFlags = 0;
208 if (flVMFlags & VMA_SELALLOC)
209 flSelFlags = SELAF_SELMAP | SELAF_DPL3 | /* 0x0460 */
210 (flVMFlags & VMA_WRITE ? SELAF_WRITE : 0);
211
212
213 /** @sketch
214 * Call VMAllocMem.
215 * If success Then
216 * Try set return variable.
217 * Free Memory on failure and return rc from previous operation.
218 * Endif
219 * Return return code.
220 */
221 kprintf(("k32AllocMemEx: cb=0x%08x flVMFlags=0x%08x flSelFlags=0x%08x, hMTE=%04d vmac.ac_va=0x%08x\n",
222 cb, flVMFlags, flSelFlags, hMTE, vmac.ac_va));
223 rc = VMAllocMem(cb,
224 cbCommit,
225 flVMFlags,
226 0,
227 0,
228 hMTE,
229 flSelFlags,
230 0,
231 (PVMAC)SSToDS(&vmac));
232
233 if (rc == NO_ERROR)
234 {
235 rc = TKSuULongNF(ppv, SSToDS(&vmac.ac_va));
236 if (rc)
237 {
238 kprintf(("k32AllocMemEx: Failed to set *ppv. rc=%d\n", rc));
239 VMFreeMem(vmac.ac_va, 0, 0);
240 }
241 }
242 else
243 kprintf(("k32AllocMemEx: VMAllocMem failed with rc=%d\n", rc));
244
245 kprintf(("k32AllocMemEx: returns rc=%d (*ppv=0x%08x)\n", rc, vmac.ac_va));
246 return rc;
247}
248
Note: See TracBrowser for help on using the repository browser.