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

Last change on this file 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.