FPPS4/sys/kern/kern_budget.pas

1053 lines
23 KiB
Plaintext

unit kern_budget;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
type
p_budget_resource=^t_budget_resource;
t_budget_resource=packed record
resid:Integer;
attr :Integer;
limit:QWORD; //cpuset
used :QWORD;
end;
//budget resid
const
SCE_KERNEL_BUDGET_INVALID =0;
SCE_KERNEL_BUDGET_MEMORY_DMEM =1;
SCE_KERNEL_BUDGET_MEMORY_VMEM =2;
SCE_KERNEL_BUDGET_MEMORY_MLOCK=3;
SCE_KERNEL_BUDGET_CPU_SET =4;
SCE_KERNEL_BUDGET_FD_FILE =5;
SCE_KERNEL_BUDGET_FD_SOCKET =6;
SCE_KERNEL_BUDGET_FD_EQUEUE =7;
SCE_KERNEL_BUDGET_FD_PIPE =8;
SCE_KERNEL_BUDGET_FD_DEVICE =9;
SCE_KERNEL_BUDGET_THREADS =10;
SCE_KERNEL_BUDGET_FD_IPCSOCKET=11;
//budget proc_type
PTYPE_BIG_APP = 0; //SCE_APPLICATION_TYPE_GAME
PTYPE_MINI_APP = 1; //SCE_APPLICATION_TYPE_MINI
PTYPE_SYSTEM = 2; //SCE_APPLICATION_TYPE_DAEMON
PTYPE_NONGAME_MINI_APP = 3;
function sys_budget_create(name:pchar;ptype:DWORD;new:Pointer;count:DWORD;prev:Pointer):Integer;
function sys_budget_delete(key:Integer):Integer;
function sys_budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer;
function sys_budget_set(key:Integer):Integer;
function sys_budget_get_ptype(pid:Integer):Integer;
function sys_budget_get_ptype_of_budget(key:Integer):Integer;
function sys_budget_getid():Integer;
//internals
type
t_budget_info=packed record
zero :QWORD;
dmem_alloc:QWORD;
malloc :QWORD;
mlock :QWORD;
end;
const
field_dmem_alloc=1;
field_mlock =2;
field_malloc =3;
const
FMEM_BASE =$4000000; //64MB Minimum reserved size of flex memory at system startup
bigapp_size =$4000000;
bigapp_max_fmem_size=$20000000; //512MB Maximum possible size of flex memory
DUH_D1xxx:Boolean =False; //Development Mode in the DUH-D1xxx series
var
FMEM_LIMIT :QWORD=0;
DMEM_LIMIT :QWORD=$180000000; // 6144MB
game_fmem_size:QWORD=bigapp_size;
ExtendedSize :QWORD=0;
//148000000 5248MB
//170000000 5888MB
//124000000 4672MB
BigAppMemory :QWORD=$170000000; // dmem_size + game_fmem_size
g_self_loading :Integer=0;
g_ext_game_fmem:Integer=0; //Enabling extended fmem size +256MB
IGNORE_EXTENDED_DMEM_BASE:Integer=0;
const
M2MB_DEFAULT =0; //Default =0 (ATTRIBUTE2:0x00000)
M2MB_DISABLE =1; //NotUsed =32768 (ATTRIBUTE2:0x08000)
M2MB_READONLY=2; //Text_rodata=65536 (ATTRIBUTE2:0x10000)
M2MB_ENABLE =3; //All_section=98304 (ATTRIBUTE2:0x18000)
var
g_mode_2mb :Integer=M2MB_DISABLE;
g_mode_2mb_size:Integer=0;
g_mode_2mb_rsrv:Integer=0;
function vm_budget_limit (ptype,field:Integer):QWORD;
function vm_budget_used (ptype,field:Integer):QWORD;
function vm_budget_reserve(ptype,field:Integer;len:QWORD):Integer;
procedure vm_budget_release(ptype,field:Integer;len:QWORD);
procedure init_bigapp_limits;
procedure set_bigapp_cred_limits;
procedure set_bigapp_limits(size,is_2MB_align:QWORD);
function dmem_process_relocated():Integer;
function get_mlock_avail():QWORD;
function get_mlock_total():QWORD;
const
//app_state
as_start =1;
as_stop =2;
as_begin_game_app_mount =3;
as___end_game_app_mount =4;
as_begin_mini_app_mount =5;
as___end_mini_app_mount =6;
as__enable_ext_game_fmem=7;
as_disable_ext_game_fmem=8;
function kern_app_state_change(state:Integer):Integer;
function sys_app_state_change (state:Integer):Integer;
procedure reset_2mb_mode;
function kern_reserve_2mb_page(size:QWORD;mode:Integer):Integer;
function sys_reserve_2mb_page (size:QWORD;mode:Integer):Integer;
implementation
uses
errno,
sys_bootparam,
kern_thr,
kern_proc,
kern_rwlock,
systm,
vmparam,
elf64,
subr_dynlib,
kern_authinfo;
var
budget_limit :t_budget_info;
budget_reserve:t_budget_info;
budget_lock :Pointer;
procedure vm_set_budget_limit(ptype,field:Integer;value:QWORD);
begin
case field of
field_dmem_alloc:Writeln('vm_set_budget_limit(dmem_alloc,0x',HexStr(value,16),')');
field_mlock :Writeln('vm_set_budget_limit(mlock ,0x',HexStr(value,16),')');
field_malloc :Writeln('vm_set_budget_limit(malloc ,0x',HexStr(value,16),')');
else;
end;
rw_wlock(budget_lock);
//TODO: ptype/budget_id ignored
PQWORD(@budget_limit)[field]:=value;
rw_wunlock(budget_lock);
end;
function vm_budget_limit(ptype,field:Integer):QWORD;
begin
rw_wlock(budget_lock);
//TODO: ptype/budget_id ignored
Result:=PQWORD(@budget_limit)[field];
rw_wunlock(budget_lock);
end;
function vm_budget_used(ptype,field:Integer):QWORD;
begin
rw_wlock(budget_lock);
//TODO: ptype/budget_id ignored
Result:=PQWORD(@budget_reserve)[field];
rw_wunlock(budget_lock);
end;
function vm_budget_reserve(ptype,field:Integer;len:QWORD):Integer;
var
rsv,limit:QWORD;
begin
if (ptype<PTYPE_BIG_APP) or (len=0) then
begin
Result:=0;
end else
begin
rw_wlock(budget_lock);
//TODO: ptype/budget_id ignored
rsv :=PQWORD(@budget_reserve)[field];
limit:=PQWORD(@budget_limit )[field];
{
if field=3 then
begin
Writeln('vm_budget_reserve:',' rsv=0x',HexStr(rsv,10),' limit=0x',HexStr(limit,10),' len=0x',HexStr(len,10));
end;
}
if (rsv <= limit) and
(len <= (limit - rsv)) then
begin
PQWORD(@budget_reserve)[field]:=rsv + len;
Result:=0;
end else
begin
Result:=ENOMEM;
end;
rw_wunlock(budget_lock);
end;
end;
procedure vm_budget_release(ptype,field:Integer;len:QWORD);
var
rsv,size:QWORD;
begin
if (ptype > -1) and (len<>0) then
begin
rw_wlock(budget_lock);
//TODO: ptype/budget_id ignored
rsv:=PQWORD(@budget_reserve)[field];
size:=0;
if (len <= rsv) then
begin
size:=rsv - len;
end;
PQWORD(@budget_reserve)[field]:=size;
rw_wunlock(budget_lock);
end;
end;
procedure init_bigapp_limits;
var
dmem_size :QWORD;
limit_value:QWORD;
m_256 :QWORD;
begin
if (p_neomode<>0) then
begin
BigAppMemory:=$170000000; //5888MB
end else
begin
BigAppMemory:=$148000000; //5248MB
end;
dmem_size:=BigAppMemory - game_fmem_size;
//[0..dmem_size),[game_fmem_size..BigAppMemory)
//TODO: realloc dmem (DMEM_LIMIT->dmem_size)
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
limit_value:=dmem_size;
if (FMEM_LIMIT <= dmem_size) then
begin
limit_value:=FMEM_LIMIT;
end;
DMEM_LIMIT:=dmem_size;
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_value);
vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE);
vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256));
end;
procedure set_bigapp_cred_limits;
var
size :QWORD;
limit_value:QWORD;
m_256 :QWORD;
ret :Boolean;
begin
ret:=is_sce_prog_attr_20_800000(@g_appinfo);
if (ret) then
begin
size:=$a0000000; //2GB
end else
begin
ret:=is_sce_prog_attr_20_400000(@g_appinfo);
if ret then
begin
size:=$30000000; //768MB
end else
begin
size:=QWORD(-1);
end;
end;
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
limit_value:=size;
if (DMEM_LIMIT < size) then
begin
limit_value:=DMEM_LIMIT;
end;
FMEM_LIMIT:=size;
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_value);
vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE);
vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256));
end;
procedure set_bigapp_limits(size,is_2MB_align:QWORD);
var
m_256 :QWORD;
limit_value:QWORD;
begin
if (game_fmem_size<>size) then
begin
if (size < game_fmem_size) then
begin
//expand
//TODO: realloc fmem (game_fmem_size->size) (switch_from_fmem)
limit_value :=BigAppMemory - size;
//TODO: realloc dmem (DMEM_LIMIT->limit_value)
game_fmem_size:=size;
DMEM_LIMIT :=limit_value;
end else
begin
//shrink
if (is_2MB_align<>0) and
((game_fmem_size and PAGE_2MB_MASK)<>0) then
begin
Writeln(stderr,'game_fmem_size is not multiple of 2MB: 0x',HexStr(game_fmem_size,8));
end;
limit_value :=BigAppMemory - size;
//TODO: realloc dmem (DMEM_LIMIT->limit_value)
//TODO: realloc fmem (game_fmem_size->size) (switch_to_fmem)
game_fmem_size:=size;
DMEM_LIMIT :=limit_value;
end;
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
limit_value:=FMEM_LIMIT;
if (DMEM_LIMIT < FMEM_LIMIT) then
begin
limit_value:=DMEM_LIMIT;
end;
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_value);
vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE);
vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256));
end;
end;
function expand_and_reserve_game_fmem(size:QWORD):QWORD;
var
dmem_size:QWORD;
begin
if (size <= QWORD(bigapp_max_fmem_size - game_fmem_size)) then
begin
dmem_size:=BigAppMemory - (game_fmem_size + size);
//TODO: realloc dmem (DMEM_LIMIT->dmem_size)
DMEM_LIMIT:=dmem_size;
//TODO: realloc fmem (game_fmem_size->(game_fmem_size + size))
game_fmem_size:=(game_fmem_size + size);
Exit(BigAppMemory - game_fmem_size);
end;
Writeln(stderr,'expand_and_reserve_game_fmem=',size);
Assert(false,'expand_and_reserve_game_fmem');
end;
function expand_budget_limit(size:QWORD):QWORD;
var
m_256 :QWORD;
limit_value:QWORD;
begin
Result:=expand_and_reserve_game_fmem(size);
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
limit_value:=FMEM_LIMIT;
if (DMEM_LIMIT < FMEM_LIMIT) then
begin
limit_value:=DMEM_LIMIT;
end;
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_value);
vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE);
vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256));
if (vm_budget_reserve(PTYPE_BIG_APP,field_mlock,size)<>0) then
begin
Writeln(stderr,'wrong MLOCK budget accounting');
Assert(false,'wrong MLOCK budget accounting');
end;
end;
function allocate_extended_page_table_pool(ExtendedCpuPageTable:QWORD;
ExtendedGpuPageTable:QWORD;
param_3:QWORD):Integer;
var
GpuPages:QWORD;
CpuPages:QWORD;
GpuPagesSize:QWORD;
size:QWORD;
begin
Result:=0;
GpuPages:=(ExtendedGpuPageTable + $7fffff) shr 23;
CpuPages:=(ExtendedCpuPageTable + $1fffff) shr 21;
GpuPagesSize:=GpuPages * $4000;
if ((GpuPagesSize or CpuPages)<> 0) then
begin
size:=0;
if (param_3=0) then
begin
size:=(QWORD(ord(p_neomode=0)) * $800000) + GpuPagesSize + (CpuPages * $1000);
if (QWORD(bigapp_max_fmem_size - game_fmem_size) < size) then
begin
Writeln('[KERNEL] WARNING: Failed to allocate extended page table pool. shortage = '
,(game_fmem_size - bigapp_max_fmem_size) + $fffff + (size shr 20),
'MiB');
Exit(ENOMEM);
end;
param_3:=expand_budget_limit(size);
end;
//reserved physical pages
ExtendedSize:=size;
end;
end;
function dmem_process_relocated():Integer;
label
_no_mem_param,
_next;
var
proc_param:TSceProcParam;
mem_param:TSceKernelMemParam;
mem_param_size:QWORD;
size :QWORD;
m_256 :QWORD;
FMEM_SIZE:QWORD;
dmem_size:QWORD;
mmap_flags:Integer;
ExtendedCpuPageTable:QWORD;
ExtendedPageTable :QWORD;
ExtendedGpuPageTable:QWORD;
FlexibleMemorySize :QWORD;
ExtendedMemory1:Boolean;
ExtendedMemory2:Boolean;
begin
Result:=0;
if (p_proc.p_budget_ptype=PTYPE_BIG_APP) then
begin
mmap_flags:=g_appinfo.mmap_flags and 1;
end else
begin
mmap_flags:=0;
end;
proc_param:=Default(TSceProcParam);
Result:=copy_proc_param(@proc_param);
if (Result=ENOENT) then
begin
_no_mem_param:
mem_param:=Default(TSceKernelMemParam);
Result:=0;
end else
begin
if (Result=0) then
begin
if (proc_param._sceKernelMemParam=nil) then goto _no_mem_param;
mem_param_size:=fuword64(proc_param._sceKernelMemParam^.Size);
if (mem_param_size=QWORD($ffffffffffffffff)) then
begin
Result:=EACCES;
end else
begin
if (mem_param_size>sizeof(TSceKernelMemParam)) then
begin
mem_param_size:=sizeof(TSceKernelMemParam);
end;
mem_param:=Default(TSceKernelMemParam);
Result:=copyin(proc_param._sceKernelMemParam,@mem_param,mem_param_size);
if (Result=0) then goto _next;
end;
end;
//
Writeln('[KERNEL] ERROR: failed to load memory parameter: ',Result);
end;
_next:
if (Byte((mmap_flags xor 1) or ord(g_self_loading=0))=0) then
begin
g_self_loading:=0;
ExtendedMemory1:=true;
if (p_proc.p_sdk_version < $5000000) then
begin
if (mem_param.sceKernelExtendedMemory1=nil) then
begin
ExtendedMemory1:=False;
end else
begin
ExtendedMemory1:=fubyte(mem_param.sceKernelExtendedMemory1^)=1;
end;
end;
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
//SCE_KERNEL_EXTENDED_DMEM_NEO_256
if (p_neomode<>0) and //only neomode
((not ExtendedMemory1) or (IGNORE_EXTENDED_DMEM_BASE<>0)) then
begin
//Subtract 256MB if the extended mode is disabled or ignored
BigAppMemory:=BigAppMemory - $10000000 {+ ((ret or $10)=$19) * (-0x10000000)};
dmem_size:=BigAppMemory - game_fmem_size;
//TODO: realloc dmem (DMEM_LIMIT->dmem_size)
size:=dmem_size;
if (FMEM_LIMIT <= dmem_size) then
begin
size:=FMEM_LIMIT;
end;
DMEM_LIMIT:=dmem_size;
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,size);
vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE);
vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256));
end;
ExtendedMemory2:=true;
if (p_proc.p_sdk_version < $5000000) then
begin
if (mem_param.sceKernelExtendedMemory2<>nil) then
begin
ExtendedMemory2:=False;
end else
begin
ExtendedMemory2:=fubyte(mem_param.sceKernelExtendedMemory2^)=1;
end;
end;
//SCE_KERNEL_EXTENDED_DMEM_BASE_128
if (p_neomode=0) and //only base mode
(IGNORE_EXTENDED_DMEM_BASE=0) then //extend mode not ignored
begin
if DUH_D1xxx then
begin
//
if (ExtendedMemory2) then
begin
Writeln('[System] : SCE_KERNEL_EXTENDED_DMEM_BASE_128 was ignored');
end;
//
end else
if (not ExtendedMemory2) then
begin
//Subtract 128MB if the extended mode is disabled
BigAppMemory:=BigAppMemory -$8000000 {+ ((ret and $ffffffe7)=1) * (-$8000000)};
dmem_size:=BigAppMemory - game_fmem_size;
//TODO: realloc dmem (DMEM_LIMIT->dmem_size)
size:=dmem_size;
if (FMEM_LIMIT <= dmem_size) then
begin
size:=FMEM_LIMIT;
end;
DMEM_LIMIT:=dmem_size;
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,size);
vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE);
vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256));
end;
end;
if (mem_param.sceKernelExtendedCpuPageTable=nil) then
begin
ExtendedCpuPageTable:=QWORD(Int64(-1));
end else
begin
ExtendedCpuPageTable:=fuword64(mem_param.sceKernelExtendedCpuPageTable^);
end;
if (mem_param.sceKernelExtendedPageTable=nil) then
begin
ExtendedPageTable:=QWORD(Int64(-1));
end else
begin
ExtendedPageTable:=fuword64(mem_param.sceKernelExtendedPageTable^);
end;
if (int64(ExtendedCpuPageTable) < 0) and
(int64(ExtendedPageTable) < 1) then
begin
ExtendedCpuPageTable:=0;
end else
if (ExtendedCpuPageTable > $1000000000) then
begin
ExtendedCpuPageTable:=0;
Writeln(stderr,'[KERNEL] ERROR: The extended CPU page table pool must be smaller than 64GiB');
Result:=ENOMEM;
end;
if (mem_param.sceKernelExtendedGpuPageTable=nil) then
begin
ExtendedGpuPageTable:=QWORD(Int64(-1));
end else
begin
ExtendedGpuPageTable:=fuword64(mem_param.sceKernelExtendedGpuPageTable^);
end;
ExtendedGpuPageTable:=(not SarInt64(ExtendedGpuPageTable,63)) and ExtendedGpuPageTable;
// MAX 64GB
if (ExtendedGpuPageTable < $1000000001) then
begin
ExtendedSize:=0;
FMEM_SIZE:=bigapp_max_fmem_size;
if (Result=0) then
begin
Result:=allocate_extended_page_table_pool(ExtendedCpuPageTable,ExtendedGpuPageTable,0);
FMEM_SIZE:=bigapp_max_fmem_size;
if (Result=0) then
begin
if (mem_param.sceKernelFlexibleMemorySize=nil) then
begin
Result:=0;
end else
begin
FlexibleMemorySize:=fuword64(mem_param.sceKernelFlexibleMemorySize^);
Result:=0;
FMEM_SIZE:=bigapp_max_fmem_size;
if (FlexibleMemorySize<>QWORD($ffffffffffffffff)) then
begin
FMEM_SIZE:=FMEM_BASE + FlexibleMemorySize;
if (bigapp_max_fmem_size < FMEM_SIZE) or
(FMEM_SIZE < bigapp_size) or
((FMEM_SIZE and QWORD(not PAGE_MASK))<>FMEM_SIZE) then
begin
Writeln(stderr,'[KERNEL] ERROR: invalid FMEM size (0x',HexStr(FlexibleMemorySize,16),') is specified.');
Result:=EINVAL;
FMEM_SIZE:=bigapp_max_fmem_size;
end;
end;
end;
end;
end;
end else
begin
Writeln('[KERNEL] ERROR: The extended GPU page table pool must be smaller than 64GiB');
Result:=ENOMEM;
ExtendedSize:=0;
FMEM_SIZE:=bigapp_max_fmem_size;
end;
if (FMEM_SIZE < game_fmem_size) then
begin
Writeln(stderr,'[KERNEL] ERROR: The executable file size (= 0x',HexStr(game_fmem_size,16),
') < specified FMEM size (=0x',HexStr(FMEM_SIZE,16),')');
if (Result=0) then
begin
Result:=Integer($a0020326);
end;
end else
if (Result=0) then
begin
Result:=0;
set_bigapp_limits(FMEM_SIZE,0);
end;
end else
if (ExtendedSize=0) and
(mmap_flags<>0) then
begin
if (mem_param.sceKernelExtendedPageTable=nil) then
begin
ExtendedPageTable:=QWORD(Int64(-1));
end else
begin
ExtendedPageTable:=fuword64(mem_param.sceKernelExtendedPageTable^);
end;
if (Int64(ExtendedPageTable) < 1) or
(ExtendedPageTable=$100000000) then
begin
if (Int64(ExtendedPageTable) > 0) then
begin
allocate_extended_page_table_pool(ExtendedPageTable,0,0);
end;
end else
begin
Writeln(stderr,'[KERNEL] ERROR: failed to extend page table pool: ',Result);
end;
end;
Writeln('DMEM_LIMIT =0x',HexStr(DMEM_LIMIT,16));
Writeln('FMEM_LIMIT =0x',HexStr(FMEM_LIMIT,16));
Writeln('BigAppMem =0x',HexStr(BigAppMemory,16));
Writeln('game_fmem_size =0x',HexStr(game_fmem_size,16));
//
Writeln('vm_budget_dmem_alloc=0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_dmem_alloc),16));
Writeln('vm_budget_mlock =0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_mlock ),16));
Writeln('vm_budget_malloc =0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_malloc ),16));
end;
function get_mlock_avail():QWORD;
var
used :QWORD;
limit:QWORD;
begin
Result:=0;
used :=vm_budget_used (p_proc.p_budget_ptype,field_mlock);
limit:=vm_budget_limit(p_proc.p_budget_ptype,field_mlock);
if (limit>used) then
begin
Result:=limit-used;
end;
end;
function get_mlock_total():QWORD;
begin
Result:=vm_budget_limit(p_proc.p_budget_ptype,field_mlock)
end;
function sys_budget_create(name:pchar;ptype:DWORD;new:Pointer;count:DWORD;prev:Pointer):Integer;
begin
//name != null
//ptype -> [0..3] (proc_type)
//new -> p_budget_resource
//count -> [0..11] (new/prev)
//prev -> p_budget_resource
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
end;
function sys_budget_delete(key:Integer):Integer;
begin
//key -> id_table
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
end;
function sys_budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer;
begin
//key -> [-2..-5] (budget limits [0..3]) else -> id_table
//ptr -> p_budget_resource
//psize -> in/out size
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
end;
function sys_budget_set(key:Integer):Integer;
begin
//key -> id_table
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
end;
function sys_budget_get_ptype(pid:Integer):Integer;
var
td:p_kthread;
begin
//sceKernelGetProcessType
td:=curkthread;
if (td=nil) then Exit(-1);
if (pid<>-1) and
(pid<>p_proc.p_pid) then
begin
Exit(ENOSYS);
end;
td^.td_retval[0]:=p_proc.p_budget_ptype;
Result:=0;
end;
function sys_budget_get_ptype_of_budget(key:Integer):Integer;
begin
//key -> id_table
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
end;
function sys_budget_getid():Integer;
begin
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
end;
//
function kern_app_state_change(state:Integer):Integer;
var
used:QWORD;
begin
Result:=0;
case state of
as_start:
begin
g_self_loading:=1;
//app_state_counter+1
end;
as_stop:
begin
g_self_loading:=0;
//app_state_counter-1
end;
as_begin_game_app_mount:
begin
used:=vm_budget_used(PTYPE_BIG_APP,field_mlock);
if (used<>0) then
begin
Writeln(stderr,'BUDGET_MEMORY_MLOCK of game is being used: ',used,' bytes');
Assert(false,'BUDGET_MEMORY_MLOCK');
end;
end;
as___end_game_app_mount:
begin
//game_mounts_exist
reset_2mb_mode;
vm_budget_release(PTYPE_BIG_APP,field_mlock,ExtendedSize);
ExtendedSize:=0;
used:=vm_budget_used(PTYPE_BIG_APP,field_mlock);
if (used<>0) then
begin
Writeln(stderr,'BUDGET_MEMORY_MLOCK of game is being used: ',used,' bytes');
Assert(false,'BUDGET_MEMORY_MLOCK');
end;
set_bigapp_limits(bigapp_size,0);
end;
as_begin_mini_app_mount:; //nothing
as___end_mini_app_mount:; //nothing
as__enable_ext_game_fmem:
begin
if (g_ext_game_fmem<>0) then
begin
Writeln(stderr,'ext_game_fmem is already enabled');
Assert (false ,'ext_game_fmem is already enabled');
end;
g_ext_game_fmem:=1;
end;
as_disable_ext_game_fmem:
begin
g_ext_game_fmem:=0;
end;
else;
end;
end;
//sceKernelNotifyAppStateChanged
function sys_app_state_change(state:Integer):Integer;
begin
//sceSblACMgrIsSyscoreProcess
Exit(EPERM);
end;
procedure reset_2mb_mode;
var
size:QWORD;
begin
if (Int64(g_mode_2mb_size) < 1) then
begin
g_mode_2mb_size:=0;
g_mode_2mb_rsrv:=0;
end else
if (g_mode_2mb_size<>g_mode_2mb_rsrv) then
begin
Writeln(stderr,'2mpage budget');
Assert(false,'2mpage budget');
end else
begin
size:=g_mode_2mb_size;
g_mode_2mb_rsrv:=0;
g_mode_2mb_size:=0;
vm_budget_release(PTYPE_BIG_APP,field_mlock,size);
end;
g_mode_2mb:=M2MB_DISABLE;
end;
function kern_reserve_2mb_page(size:QWORD;mode:Integer):Integer;
var
save_game_fmem_size:QWORD;
size2:QWORD;
mode2:Integer;
begin
Result:=0;
save_game_fmem_size:=game_fmem_size;
if not ((g_mode_2mb=M2MB_DISABLE) and (g_mode_2mb_size=0)) then
begin
Exit(EPERM);
end;
if (game_fmem_size<>bigapp_size) then
begin
Writeln(stderr,'[KERNEL] WARNING: The last bigapp termination handling was incomplete.');
Exit(EPERM);
end;
mode2:=M2MB_DISABLE;
if (Int64(size) > PAGE_2MB_MASK) then
begin
mode2:=mode;
end;
if ((mode or 1)<>3) then
begin
mode2:=mode;
end;
if (mode2=M2MB_DEFAULT) then
begin
g_mode_2mb :=M2MB_DEFAULT;
g_mode_2mb_size:=0;
end else
if (mode2=M2MB_DISABLE) then
begin
g_mode_2mb :=M2MB_DISABLE;
g_mode_2mb_size:=-1;
end else
begin
if (Int64(size) > $1bffffff) then
begin
Exit(EINVAL);
end;
if ((mode2 or 1)<>3) then
begin
Exit(EINVAL);
end;
if (Int64(size) > -1) then
begin
size2:=size;
end else
begin
size2:=size + PAGE_2MB_MASK;
end;
size2:=size2 and QWORD(not PAGE_2MB_MASK);
if (bigapp_max_fmem_size < (game_fmem_size + size2)) then
begin
size:=bigapp_max_fmem_size;
end else
begin
size:=game_fmem_size + size2;
end;
set_bigapp_limits(size,0);
if (vm_budget_reserve(PTYPE_BIG_APP,field_mlock,size2)<>0) then
begin
set_bigapp_limits(save_game_fmem_size,0);
Exit(ENOMEM);
end;
g_mode_2mb :=mode2;
g_mode_2mb_size:=size2;
g_mode_2mb_rsrv:=size2;
end;
end;
function sys_reserve_2mb_page(size:QWORD;mode:Integer):Integer;
begin
//sceSblACMgrIsSyscoreProcess
Exit(EPERM);
end;
end.