Skip to content

Commit e2cdcb2

Browse files
committed
Add guarded virtual memory support for z/OS
Add guarded virtual memory support to the z/OS vmem path so that object heap and sparse virtual memory reservations can use guarded storage for Balanced GC. This reduces MEMLIMIT pressure by keeping reserved regions guarded until they are committed for use. Introduce the OMRPORT_VMEM_MEMORY_MODE_GUARDED flag (currently supported only for Balanced GC) to indicate guarding of VLHGC heap and sparse virtual memory reservations. Guarded 1 MB pageable and 4 KB above-the-bar allocations are supported. Guard and unguard operations are implemented using IARV64 guarded storage support. Signed-off-by: Shubham Verma <shubhamv.sv@gmail.com>
1 parent 01e2beb commit e2cdcb2

6 files changed

Lines changed: 2715 additions & 1286 deletions

File tree

gc/base/MemoryManager.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ MM_MemoryManager::createVirtualMemoryForHeap(MM_EnvironmentBase *env, MM_MemoryH
8080

8181
uintptr_t allocateSize = size;
8282

83+
/*
84+
* Guard heap memory for Balanced.
85+
* This feature is supported on ZOS only.
86+
* Guarding object heap and sparse heap is necessary to not exceed MEMLIMIT.
87+
*/
88+
if (extensions->isVLHGC()) {
89+
mode |= OMRPORT_VMEM_MEMORY_MODE_GUARDED;
90+
}
91+
8392
uintptr_t concurrentScavengerPageSize = 0;
8493
if (extensions->isConcurrentScavengerHWSupported()) {
8594
OMRPORT_ACCESS_FROM_ENVIRONMENT(env);

gc/base/SparseVirtualMemory.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class MM_SparseVirtualMemory : public MM_VirtualMemory {
8787
MM_SparseVirtualMemory(MM_EnvironmentBase *env, uintptr_t pageSize, uintptr_t pageFlags, MM_Heap *in_heap)
8888
: MM_VirtualMemory(
8989
env, in_heap->getHeapRegionManager()->getRegionSize(), pageSize, pageFlags, 0,
90-
OMRPORT_VMEM_MEMORY_MODE_READ | OMRPORT_VMEM_MEMORY_MODE_WRITE | OMRPORT_VMEM_MEMORY_MODE_VIRTUAL)
90+
OMRPORT_VMEM_MEMORY_MODE_READ | OMRPORT_VMEM_MEMORY_MODE_WRITE | OMRPORT_VMEM_MEMORY_MODE_VIRTUAL | OMRPORT_VMEM_MEMORY_MODE_GUARDED)
9191
, _heap(in_heap)
9292
, _sparseDataPool(NULL)
9393
, _largeObjectVirtualMemoryMutex(NULL)

include_core/omrport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@
235235
#define OMRPORT_VMEM_ALLOCATE_TOP_DOWN 0x00000020
236236
#define OMRPORT_VMEM_ALLOCATE_PERSIST 0x00000040
237237
#define OMRPORT_VMEM_NO_AFFINITY 0x00000080
238+
#define OMRPORT_VMEM_MEMORY_MODE_GUARDED 0x00000100
238239
/** @} */
239240

240241
/**

port/zos390/omriarv64.c

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,61 @@ void * omrallocate_1M_pageable_pages_above_bar(int *numMBSegments, int *userExte
153153
return (void *)origin;
154154
}
155155

156+
#pragma prolog(omrallocate_1M_pageable_pages_guarded_above_bar,"MYPROLOG")
157+
#pragma epilog(omrallocate_1M_pageable_pages_guarded_above_bar,"MYEPILOG")
158+
159+
__asm(" IARV64 PLISTVER=MAX,MF=(L,SGETSTOR)":"DS"(sgetstor));
160+
161+
/*
162+
* Allocate 1MB pageable guarded pages above 2GB bar using IARV64 system macro.
163+
* Memory allocated is freed using omrfree_memory_above_bar().
164+
*
165+
* @params[in] numMBSegments Number of 1MB segments to be allocated
166+
* @params[in] userExtendedPrivateAreaMemoryType capability of OS: 0 - general, 1 - 2G-32G range, 2 - 2G-64G range
167+
*
168+
* @return pointer to memory allocated, NULL on failure.
169+
*/
170+
void *omrallocate_1M_pageable_pages_guarded_above_bar(int *numMBSegments, int *userExtendedPrivateAreaMemoryType, const char *ttkn) {
171+
long segments;
172+
long origin;
173+
long useMemoryType = *userExtendedPrivateAreaMemoryType;
174+
int iarv64_rc = 0;
175+
176+
__asm(" IARV64 PLISTVER=MAX,MF=(L,SGETSTOR)":"DS"(wgetstor));
177+
178+
segments = *numMBSegments;
179+
wgetstor = ngetstor;
180+
181+
switch (useMemoryType) {
182+
case ZOS64_VMEM_ABOVE_BAR_GENERAL:
183+
__asm(" IARV64 REQUEST=GETSTOR,COND=YES,SADMP=NO,CONTROL=UNAUTH,"\
184+
"GUARDSIZE64=(%2),"\
185+
"PAGEFRAMESIZE=PAGEABLE1MEG,TYPE=PAGEABLE,SEGMENTS=(%2),"\
186+
"ORIGIN=(%1),TTOKEN=(%4),RETCODE=%0,MF=(E,(%3))"\
187+
::"m"(iarv64_rc),"r"(&origin),"r"(&segments),"r"(&wgetstor),"r"(ttkn));
188+
break;
189+
case ZOS64_VMEM_2_TO_32G:
190+
__asm(" IARV64 REQUEST=GETSTOR,COND=YES,SADMP=NO,CONTROL=UNAUTH,USE2GTO32G=YES,"\
191+
"GUARDSIZE64=(%2),"\
192+
"PAGEFRAMESIZE=PAGEABLE1MEG,TYPE=PAGEABLE,SEGMENTS=(%2),"\
193+
"ORIGIN=(%1),TTOKEN=(%4),RETCODE=%0,MF=(E,(%3))"\
194+
::"m"(iarv64_rc),"r"(&origin),"r"(&segments),"r"(&wgetstor),"r"(ttkn));
195+
break;
196+
case ZOS64_VMEM_2_TO_64G:
197+
__asm(" IARV64 REQUEST=GETSTOR,COND=YES,SADMP=NO,CONTROL=UNAUTH,USE2GTO64G=YES,"\
198+
"GUARDSIZE64=(%2),"\
199+
"PAGEFRAMESIZE=PAGEABLE1MEG,TYPE=PAGEABLE,SEGMENTS=(%2),"\
200+
"ORIGIN=(%1),TTOKEN=(%4),RETCODE=%0,MF=(E,(%3))"\
201+
::"m"(iarv64_rc),"r"(&origin),"r"(&segments),"r"(&wgetstor),"r"(ttkn));
202+
break;
203+
}
204+
205+
if (0 != iarv64_rc) {
206+
return (void *)0;
207+
}
208+
return (void *)origin;
209+
}
210+
156211
#pragma prolog(omrallocate_2G_pages,"MYPROLOG")
157212
#pragma epilog(omrallocate_2G_pages,"MYEPILOG")
158213

@@ -253,6 +308,54 @@ void * omrallocate_4K_pages_in_userExtendedPrivateArea(int *numMBSegments, int *
253308
return (void *)origin;
254309
}
255310

311+
#pragma prolog(omrallocate_4K_pages_guarded_in_userExtendedPrivateArea,"MYPROLOG")
312+
#pragma epilog(omrallocate_4K_pages_guarded_in_userExtendedPrivateArea,"MYEPILOG")
313+
314+
__asm(" IARV64 PLISTVER=MAX,MF=(L,TGETSTOR)":"DS"(tgetstor));
315+
316+
/*
317+
* Allocate 4KB pages guarded in 2G-32G range using IARV64 system macro.
318+
* Memory allocated is freed using omrfree_memory_above_bar().
319+
*
320+
* @params[in] numMBSegments Number of 1MB segments to be allocated
321+
* @params[in] userExtendedPrivateAreaMemoryType capability of OS: 0 - general, 1 - 2G-32G range, 2 - 2G-64G range
322+
*
323+
* @return pointer to memory allocated, NULL on failure.
324+
*/
325+
void *omrallocate_4K_pages_guarded_in_userExtendedPrivateArea(int *numMBSegments, int *userExtendedPrivateAreaMemoryType, const char *ttkn) {
326+
long segments;
327+
long origin;
328+
long useMemoryType = *userExtendedPrivateAreaMemoryType;
329+
int iarv64_rc = 0;
330+
331+
__asm(" IARV64 PLISTVER=MAX,MF=(L,TGETSTOR)":"DS"(wgetstor));
332+
333+
segments = *numMBSegments;
334+
wgetstor = tgetstor;
335+
336+
switch (useMemoryType) {
337+
case ZOS64_VMEM_ABOVE_BAR_GENERAL:
338+
break;
339+
case ZOS64_VMEM_2_TO_32G:
340+
__asm(" IARV64 REQUEST=GETSTOR,COND=YES,SADMP=NO,CONTROL=UNAUTH,USE2GTO32G=YES,"\
341+
"GUARDSIZE64=(%2),PAGEFRAMESIZE=4K,SEGMENTS=(%2),"\
342+
"ORIGIN=(%1),TTOKEN=(%4),RETCODE=%0,MF=(E,(%3))"\
343+
::"m"(iarv64_rc),"r"(&origin),"r"(&segments),"r"(&wgetstor),"r"(ttkn));
344+
break;
345+
case ZOS64_VMEM_2_TO_64G:
346+
__asm(" IARV64 REQUEST=GETSTOR,COND=YES,SADMP=NO,CONTROL=UNAUTH,USE2GTO64G=YES,"\
347+
"GUARDSIZE64=(%2),PAGEFRAMESIZE=4K,SEGMENTS=(%2),"\
348+
"ORIGIN=(%1),TTOKEN=(%4),RETCODE=%0,MF=(E,(%3))"\
349+
::"m"(iarv64_rc),"r"(&origin),"r"(&segments),"r"(&wgetstor),"r"(ttkn));
350+
break;
351+
}
352+
353+
if (0 != iarv64_rc) {
354+
return (void *)0;
355+
}
356+
return (void *)origin;
357+
}
358+
256359
#pragma prolog(omrallocate_4K_pages_above_bar,"MYPROLOG")
257360
#pragma epilog(omrallocate_4K_pages_above_bar,"MYEPILOG")
258361

@@ -287,6 +390,33 @@ void * omrallocate_4K_pages_above_bar(int *numMBSegments, const char * ttkn) {
287390
return (void *)origin;
288391
}
289392

393+
#pragma prolog(omrallocate_4K_pages_guarded_above_bar,"MYPROLOG")
394+
#pragma epilog(omrallocate_4K_pages_guarded_above_bar,"MYEPILOG")
395+
396+
__asm(" IARV64 PLISTVER=MAX,MF=(L,EGETSTOR)":"DS"(egetstor));
397+
398+
void *omrallocate_4K_pages_guarded_above_bar(int *numMBSegments, const char *ttkn) {
399+
long segments;
400+
long origin;
401+
int iarv64_rc = 0;
402+
403+
__asm(" IARV64 PLISTVER=MAX,MF=(L,EGETSTOR)":"DS"(wgetstor));
404+
405+
segments = *numMBSegments;
406+
wgetstor = rgetstor;
407+
408+
__asm(" IARV64 REQUEST=GETSTOR,COND=YES,SADMP=NO,"\
409+
"GUARDSIZE=(%2),"\
410+
"CONTROL=UNAUTH,PAGEFRAMESIZE=4K,"\
411+
"SEGMENTS=(%2),ORIGIN=(%1),TTOKEN=(%4),RETCODE=%0,MF=(E,(%3))"\
412+
::"m"(iarv64_rc),"r"(&origin),"r"(&segments),"r"(&wgetstor),"r"(ttkn));
413+
414+
if (0 != iarv64_rc) {
415+
return (void *)0;
416+
}
417+
return (void *)origin;
418+
}
419+
290420
#pragma prolog(omrfree_memory_above_bar,"MYPROLOG")
291421
#pragma epilog(omrfree_memory_above_bar,"MYEPILOG")
292422

@@ -313,6 +443,67 @@ int omrfree_memory_above_bar(void *address, const char * ttkn){
313443
return iarv64_rc;
314444
}
315445

446+
#pragma prolog(omrremove_guard,"MYPROLOG")
447+
#pragma epilog(omrremove_guard,"MYEPILOG")
448+
449+
__asm(" IARV64 PLISTVER=MAX,MF=(L,FGETSTOR)":"DS"(fgetstor));
450+
451+
/*
452+
* Remove guard for memory allocated using IARV64 system macro.
453+
*
454+
* @params[in] address pointer to memory region to be freed
455+
* @params[in] numMBSegments Number of 1MB segments to be allocated
456+
*
457+
* @return non-zero if memory is not freed successfully, 0 otherwise.
458+
*/
459+
int omrremove_guard(void *address, int *numMBSegments){
460+
void * memObjConvertStart;
461+
int iarv64_rc = 0;
462+
long segments;
463+
464+
__asm(" IARV64 PLISTVER=MAX,MF=(L,FGETSTOR)":"DS"(wgetstor));
465+
466+
memObjConvertStart = address;
467+
wgetstor = fgetstor;
468+
segments = *numMBSegments;
469+
470+
__asm(" IARV64 REQUEST=CHANGEGUARD,CONVERT=FROMGUARD,COND=YES,"\
471+
"CONVERTSTART=(%2),CONVERTSIZE64=(%3),"\
472+
"RETCODE=%0,MF=(E,(%1))"\
473+
::"m"(iarv64_rc),"r"(&wgetstor),"r"(&memObjConvertStart),"r"(&segments));
474+
return iarv64_rc;
475+
}
476+
477+
#pragma prolog(omradd_guard,"MYPROLOG")
478+
#pragma epilog(omradd_guard,"MYEPILOG")
479+
480+
__asm(" IARV64 PLISTVER=MAX,MF=(L,DGETSTOR)":"DS"(dgetstor));
481+
482+
/*
483+
* Ass guard to memory allocated using IARV64 system macro.
484+
*
485+
* @params[in] address pointer to memory region to be freed
486+
*
487+
* @return non-zero if memory is not freed successfully, 0 otherwise.
488+
*/
489+
int omradd_guard(void *address, int *numMBSegments) {
490+
void * memObjConvertStart;
491+
int iarv64_rc = 0;
492+
long segments;
493+
494+
__asm(" IARV64 PLISTVER=MAX,MF=(L,DGETSTOR)":"DS"(wgetstor));
495+
496+
memObjConvertStart = address;
497+
wgetstor = dgetstor;
498+
segments = *numMBSegments;
499+
500+
__asm(" IARV64 REQUEST=CHANGEGUARD,CONVERT=TOGUARD,COND=YES,"\
501+
"CONVERTSTART=(%2),CONVERTSIZE64=(%3),"\
502+
"RETCODE=%0,MF=(E,(%1))"\
503+
::"m"(iarv64_rc),"r"(&wgetstor),"r"(&memObjConvertStart),"r"(&segments));
504+
return iarv64_rc;
505+
}
506+
316507
#pragma prolog(omrdiscard_data,"MYPROLOG")
317508
#pragma epilog(omrdiscard_data,"MYEPILOG")
318509

0 commit comments

Comments
 (0)