Files
Snapintosh/tools/test-pmc-enable.c
Acelogic 1510d8c6ce Snapintosh public release
An EL2 monitor/hypervisor and toolchain that boots macOS 27 on the ASUS A16
(Snapdragon X2 Elite), with an Adreno Metal plug-in and IOGPU kext, and
air2ir3, an AIR to Mesa ir3 shader compiler.

MIT, with GPL-2.0 components listed in LICENSE and THIRD_PARTY_NOTICES.md.
No Apple, Qualcomm, ASUS or Microsoft binaries are included.
2026-10-21 21:26:36 -04:00

134 lines
5.8 KiB
C

/* SPDX-License-Identifier: MIT */
/* Voter/RMBS/boost/BWR enables, separate from votes and completion. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "device.h"
static unsigned checks;
#define CHECK(x) do { checks++; if (!(x)) { \
fprintf(stderr,"line %u: %s\n",__LINE__,#x); exit(1); } } while (0)
static struct device_state state,saved,other;
static const struct device_model model={DEVICE_PMC_ENABLE_POLICY_V1,
0x3028ac000,0x1000,{0,0,0,0,0}};
static const unsigned offsets[]={0,4,8,12,0x24,0x28,0x20};
static const unsigned masks[]={15,15,15,15,3,0x3f,7};
static enum device_result access_word(unsigned off,unsigned width,int write,uint64_t *v)
{
return device_model_access_state(&model,&state,off,width,write,v);
}
int main(int argc,char **argv)
{
CHECK(device_models_valid(&model,1,0,0));
CHECK(device_model_start(&model,&state,0,24000000)==DEVICE_OK);
if (argc==2 && !strcmp(argv[1],"--masks")) {
for (unsigned off=0;off<0x1000;off+=4) {
uint64_t v=0,mask=0;
if (access_word(off,4,0,&v)!=DEVICE_OK) continue;
for (unsigned bit=0;bit<64;bit++) {
v=1UL<<bit;
if (access_word(off,4,1,&v)==DEVICE_OK) mask|=1UL<<bit;
}
printf("%u %llu\n",off,(unsigned long long)mask);
}
return 0;
}
/* restorePMC enables static PMP, CLPC, AP (bits 0, 1, 3) on all four
* rails. Each read/modify/write must preserve previous voters/rails. */
const unsigned static_bits[]={0,1,3};
for (unsigned pass=0;pass<2;pass++) for (unsigned voter=0;voter<3;voter++) {
for (unsigned rail=0;rail<4;rail++) {
uint64_t v=UINT64_MAX;saved=state;
CHECK(access_word(4*rail,4,0,&v)==DEVICE_OK);
v|=1U<<static_bits[voter];
CHECK(access_word(4*rail,4,1,&v)==DEVICE_OK);
saved.pmc_enable[rail]|=1U<<static_bits[voter];
CHECK(!memcmp(&state,&saved,sizeof(state)));
}
}
for (unsigned rail=0;rail<4;rail++) CHECK(state.pmc_enable[rail]==0xb);
uint64_t v=UINT64_MAX;
CHECK(access_word(0x24,4,0,&v)==DEVICE_OK && v==0);
v=(v&~3UL)|3;
CHECK(access_word(0x24,4,1,&v)==DEVICE_OK);
CHECK(access_word(0x24,4,0,&v)==DEVICE_OK && v==3);
/* The stopped ANS stateChange enables boost bit 4. Independent
* DISPEXT0 BWR bit 2 and later boost bits must preserve prior state. */
v=0;
CHECK(access_word(0x28,4,0,&v)==DEVICE_OK && v==0);
v|=1U<<4;
CHECK(access_word(0x28,4,1,&v)==DEVICE_OK);
v=1U<<2;
CHECK(access_word(0x20,4,1,&v)==DEVICE_OK);
CHECK(access_word(0x28,4,0,&v)==DEVICE_OK && v==0x10);
v|=1U<<2;
CHECK(access_word(0x28,4,1,&v)==DEVICE_OK);
CHECK(access_word(0x20,4,0,&v)==DEVICE_OK && v==4);
CHECK(state.pmc_enable[4]==3 && state.pmc_enable[5]==0x14);
unsigned words=0;
for (unsigned off=0;off<0x1000;off+=4) {
int index=-1;
for (unsigned i=0;i<7;i++) if (off==offsets[i]) index=(int)i;
v=0x13579bdf;saved=state;
if (index<0) {
for (int write=0;write<=1;write++) {
CHECK(access_word(off,4,write,&v)==DEVICE_UNKNOWN_REGISTER);
CHECK(v==0x13579bdf && !memcmp(&state,&saved,sizeof(state)));
}
continue;
}
words++;unsigned mask=masks[index];
/* Every combination includes individual enable/disable, dynamic
* GFX bit 2 and mixed settings. No vote data is produced. */
for (unsigned pattern=0;pattern<=mask;pattern++) {
v=pattern;saved=state;
CHECK(access_word(off,4,1,&v)==DEVICE_OK);
saved.pmc_enable[index]=pattern;
CHECK(!memcmp(&state,&saved,sizeof(state)));
v=UINT64_MAX;
CHECK(access_word(off,4,0,&v)==DEVICE_OK && v==pattern);
}
for (unsigned bit=0;bit<64;bit++) {
v=1UL<<bit;if (!(v&~(uint64_t)mask)) continue;
v|=mask;uint64_t input=v;saved=state;
CHECK(access_word(off,4,1,&v)==DEVICE_BAD_VALUE);
CHECK(v==input && !memcmp(&state,&saved,sizeof(state)));
}
for (unsigned width=1;width<=16;width*=2) {
if (width==4) continue;
for (int write=0;write<=1;write++) {
v=1;saved=state;
CHECK(access_word(off,width,write,&v)==DEVICE_BAD_WIDTH);
CHECK(v==1 && !memcmp(&state,&saved,sizeof(state)));
}
}
for (unsigned delta=1;delta<=3;delta++) for (int write=0;write<=1;write++) {
v=1;saved=state;
CHECK(access_word(off+delta,4,write,&v)==DEVICE_BAD_WIDTH);
CHECK(v==1 && !memcmp(&state,&saved,sizeof(state)));
}
}
CHECK(words==7);
CHECK(device_model_start(&model,&other,0,24000000)==DEVICE_OK);
for (unsigned i=0;i<7;i++) CHECK(other.pmc_enable[i]==0);
v=1;saved=state;
CHECK(access_word(0x1000,4,1,&v)==DEVICE_NOT_FOUND);
CHECK(device_model_access_state(&model,0,0,4,1,&v)==DEVICE_BAD_CONFIG);
CHECK(device_model_access_state(&model,&state,0,4,1,0)==DEVICE_BAD_CONFIG);
for (unsigned i=0;i<5;i++) {
struct device_model bad=model;bad.config[i]=1;
CHECK(!device_models_valid(&bad,1,0,0));
CHECK(device_model_start(&bad,&state,0,24000000)==DEVICE_BAD_CONFIG);
CHECK(device_model_access_state(&bad,&state,0,4,1,&v)==DEVICE_BAD_CONFIG);
CHECK(!memcmp(&state,&saved,sizeof(state)));
}
struct device_model bad=model;bad.span=0x4000;
CHECK(!device_models_valid(&bad,1,0,0));
state.dram_policy=0xfeed;state.pmc_enable[0]=0xf;
state.pmgr_policy[5]=0xfeedbeef;saved=state;
for (unsigned i=0;i<7;i++) saved.pmc_enable[i]=0;
CHECK(device_model_start(&model,&state,123,24000000)==DEVICE_OK);
CHECK(!memcmp(&state,&saved,sizeof(state)));
printf("PMC voter/RMBS/boost/BWR enable policy: %u checks passed\n",checks);
return 0;
}