code wiki / (root) / nx_etg_probe_cpu_test.nx

nx_etg_probe_cpu_test.nx source

↩ module page · 183 lines · 8881 B

1// nx_etg_probe_cpu_test.nx -- KAT for E3 first real CPU probe. 2// 3// Verifies: 4// T1 Classifier taxonomy: each NX_ETG_OUTCOME_* the classifier 5// can emit is reachable on a deterministic synthetic input. 6// T2 Boundary cases: claim==0, measured==0 -> INCONCLUSIVE. 7// T3 CONFIRMED band: measured within (claim - low%, claim + high%). 8// T4 FALSIFIED: measured > claim * (1 + high/1000). 9// T5 VENDOR_LIED_OMISSION: measured < claim * (1 - low/1000). 10// T6 Real probe end-to-end: invokes nx_calibrate_run on qemu-RV64 11// with a deliberately permissive claim (100,000 ns) and asserts 12// the emitted entry is valid + the outcome is one of the 13// allowed verdicts (CONFIRMED / VENDOR_LIED_OMISSION / FALSIFIED). 14// The exact value of measured is non-deterministic under qemu, 15// so we don't assert on it -- we assert the PIPELINE is real. 16 17import "nx_syscalls.nx" 18import "nx_calibrate.nx" 19import "nx_etg.nx" 20import "nx_etg_probe_cpu.nx" 21 22func main() -> i64 { 23 // ----- T2 Boundary inconclusives ----- 24 let o_zc: i64 = nx_etg_classify_outcome(0, 100, 100, 100) 25 if o_zc != NX_ETG_OUTCOME_INCONCLUSIVE { return 1 } 26 let o_zm: i64 = nx_etg_classify_outcome(100, 0, 100, 100) 27 if o_zm != NX_ETG_OUTCOME_INCONCLUSIVE { return 2 } 28 29 // ----- T3 CONFIRMED band ----- 30 // claim 100, low 10%, high 10% -> CONFIRMED band [90, 110]. 31 let o_eq: i64 = nx_etg_classify_outcome(100, 100, 100, 100) 32 if o_eq != NX_ETG_OUTCOME_CONFIRMED { return 10 } 33 let o_lo_in: i64 = nx_etg_classify_outcome(100, 91, 100, 100) 34 if o_lo_in != NX_ETG_OUTCOME_CONFIRMED { return 11 } 35 let o_hi_in: i64 = nx_etg_classify_outcome(100, 109, 100, 100) 36 if o_hi_in != NX_ETG_OUTCOME_CONFIRMED { return 12 } 37 38 // ----- T4 FALSIFIED above tolerance ----- 39 let o_fal: i64 = nx_etg_classify_outcome(100, 150, 100, 100) 40 if o_fal != NX_ETG_OUTCOME_FALSIFIED { return 20 } 41 // Just above the boundary: 111 > 110 (= 100 * 1.10). 42 let o_fal_edge: i64 = nx_etg_classify_outcome(100, 111, 100, 100) 43 if o_fal_edge != NX_ETG_OUTCOME_FALSIFIED { return 21 } 44 45 // ----- T5 VENDOR_LIED_OMISSION below tolerance ----- 46 let o_lied: i64 = nx_etg_classify_outcome(100, 50, 100, 100) 47 if o_lied != NX_ETG_OUTCOME_VENDOR_LIED_OMISSION { return 30 } 48 // Just below the boundary: 89 < 90 (= 100 * 0.90). 49 let o_lied_edge: i64 = nx_etg_classify_outcome(100, 89, 100, 100) 50 if o_lied_edge != NX_ETG_OUTCOME_VENDOR_LIED_OMISSION { return 31 } 51 52 // ----- T1 Taxonomy reachability (covered by T2-T5) ----- 53 // Already exercised: INCONCLUSIVE, CONFIRMED, FALSIFIED, VENDOR_LIED_OMISSION. 54 // Remaining outcomes (THROTTLED / FUSED_OFF / RECLAIMED / etc.) require 55 // probe-family-specific classifier extensions; queued per per-probe brick. 56 57 // ----- T6 Real probe end-to-end on qemu-RV64 ----- 58 let e_buf: *u8 = sys_mmap(128) 59 let e: *NxEtgEntry = e_buf as *NxEtgEntry 60 // Claim 100_000 ns (100 μs) -- generous so qemu measurement 61 // doesn't FALSIFY by exceeding tolerance. Tolerances 90% / 90% 62 // so the band is very wide; expected outcomes are CONFIRMED or 63 // VENDOR_LIED_OMISSION on qemu (which is much faster than 100μs 64 // for a clock_gettime syscall). 65 let outcome: i64 = nx_etg_probe_cpu_syscall_roundtrip( 66 100000, // claim_ns: 100 μs 67 900, // low_thresh_per_1000 = 90% (claim*0.10 = 10_000 ns floor) 68 900, // high_thresh_per_1000 = 90% 69 e, 70 0xC0DEC0DE, // silicon serial (synthetic for KAT) 71 1, // selector version 72 20260520 // timestamp Q14 (2026-05-20 sentinel) 73 ) 74 // Outcome must be one of the valid verdicts the classifier can emit. 75 if nx_etg_outcome_is_valid(outcome) != 1 { return 40 } 76 // Outcome must specifically be CONFIRMED, VENDOR_LIED_OMISSION, 77 // FALSIFIED, or INCONCLUSIVE (the four the classifier can emit 78 // from a clean run). 79 var ok: i64 = 0 80 if outcome == NX_ETG_OUTCOME_CONFIRMED { ok = 1 } 81 if outcome == NX_ETG_OUTCOME_VENDOR_LIED_OMISSION { ok = 1 } 82 if outcome == NX_ETG_OUTCOME_FALSIFIED { ok = 1 } 83 if outcome == NX_ETG_OUTCOME_INCONCLUSIVE { ok = 1 } 84 if ok != 1 { return 41 } 85 // Entry was written with the claim we passed. 86 if e.claim_value != 100000 { return 42 } 87 if e.probe_kind != NX_ETG_PROBE_CPU_SYSCALL { return 43 } 88 if e.claim_source != NX_ETG_CLAIM_VENDOR_DOC { return 44 } 89 if e.silicon_serial_hash != 0xC0DEC0DE { return 45 } 90 if e.outcome != outcome { return 46 } 91 // Attestation hash deterministic + non-zero. 92 if e.attestation_hash == 0 { return 47 } 93 94 // ----- T7 Real probe: int_alu dependent-chain throughput ----- 95 let e7_buf: *u8 = sys_mmap(128) 96 let e7: *NxEtgEntry = e7_buf as *NxEtgEntry 97 // Generous claim 100,000 ps/op (= 100 ns/op) with wide tolerance. 98 // qemu emulation makes ADD considerably slower than native silicon 99 // but the measured value should still be a positive integer. 100 let outcome7: i64 = nx_etg_probe_cpu_int_alu( 101 100000, 990, 9000, e7, 0xC0DEC0DE, 1, 20260520 102 ) 103 if nx_etg_outcome_is_valid(outcome7) != 1 { return 50 } 104 if e7.probe_kind != NX_ETG_PROBE_CPU_ISA { return 51 } 105 if e7.claim_source != NX_ETG_CLAIM_VENDOR_DOC { return 52 } 106 if e7.claim_value != 100000 { return 53 } 107 if e7.measurement_value <= 0 { return 54 } 108 if e7.outcome != outcome7 { return 55 } 109 if e7.attestation_hash == 0 { return 56 } 110 111 // ----- T8 Real probe: linear memory-copy bandwidth ----- 112 let e8_buf: *u8 = sys_mmap(128) 113 let e8: *NxEtgEntry = e8_buf as *NxEtgEntry 114 // Claim 100 MiB/s with wide tolerance band; qemu emulation is much 115 // slower than native, so we accept any outcome and just gate on 116 // pipeline validity. 117 let outcome8: i64 = nx_etg_probe_cpu_mem_bw( 118 100, 900, 9000, e8, 0xC0DEC0DE, 1, 20260520 119 ) 120 if nx_etg_outcome_is_valid(outcome8) != 1 { return 60 } 121 if e8.probe_kind != NX_ETG_PROBE_STORAGE_RAM { return 61 } 122 if e8.claim_source != NX_ETG_CLAIM_VENDOR_DOC { return 62 } 123 if e8.claim_value != 100 { return 63 } 124 if e8.measurement_value < 0 { return 64 } 125 if e8.outcome != outcome8 { return 65 } 126 if e8.attestation_hash == 0 { return 66 } 127 128 // T9 cross-probe-attestation: e (syscall) and e7 (int_alu) carry 129 // different probe_kinds + measurement_values + outcomes -> their 130 // attestation hashes differ (no cross-probe aliasing). 131 if e.attestation_hash == e7.attestation_hash { return 70 } 132 if e7.attestation_hash == e8.attestation_hash { return 71 } 133 if e.attestation_hash == e8.attestation_hash { return 72 } 134 135 // ----- T10 Real probe: L1 cache latency ----- 136 let e10_buf: *u8 = sys_mmap(128) 137 let e10: *NxEtgEntry = e10_buf as *NxEtgEntry 138 // Claim 100 ns with very wide tolerance. Real L1 hit latency 139 // on native silicon is ~1-2 ns; under qemu it's much higher. 140 let outcome10: i64 = nx_etg_probe_cpu_cache_l1( 141 100, 990, 9000, e10, 0xC0DEC0DE, 1, 20260520 142 ) 143 if nx_etg_outcome_is_valid(outcome10) != 1 { return 80 } 144 if e10.probe_kind != NX_ETG_PROBE_CPU_CACHE { return 81 } 145 if e10.measurement_value < 0 { return 82 } 146 if e10.outcome != outcome10 { return 83 } 147 148 // ----- T11 Real probe: L2 cache latency ----- 149 let e11_buf: *u8 = sys_mmap(128) 150 let e11: *NxEtgEntry = e11_buf as *NxEtgEntry 151 let outcome11: i64 = nx_etg_probe_cpu_cache_l2( 152 100, 990, 9000, e11, 0xC0DEC0DE, 1, 20260520 153 ) 154 if nx_etg_outcome_is_valid(outcome11) != 1 { return 90 } 155 if e11.probe_kind != NX_ETG_PROBE_CPU_CACHE { return 91 } 156 if e11.measurement_value < 0 { return 92 } 157 158 // ----- T12 Real probe: RAM access latency ----- 159 let e12_buf: *u8 = sys_mmap(128) 160 let e12: *NxEtgEntry = e12_buf as *NxEtgEntry 161 let outcome12: i64 = nx_etg_probe_cpu_cache_ram( 162 100, 990, 9000, e12, 0xC0DEC0DE, 1, 20260520 163 ) 164 if nx_etg_outcome_is_valid(outcome12) != 1 { return 100 } 165 if e12.probe_kind != NX_ETG_PROBE_STORAGE_RAM { return 101 } 166 if e12.measurement_value < 0 { return 102 } 167 168 // ----- T13 Cache hierarchy monotone sanity: L1 <= L2 <= RAM ----- 169 // The substrate's empirical measurement of the cache hierarchy 170 // should observe L1 latency <= L2 latency <= RAM latency. If 171 // the silicon (or qemu) reports otherwise, the cost model picks 172 // it up via INCONCLUSIVE classification across replicas. For 173 // this KAT we just sanity-check the ordering is plausible 174 // (not strict equality, since qemu noise can flip nearby tiers). 175 if e10.measurement_value > 0 { 176 if e12.measurement_value > 0 { 177 // L1 should be no slower than RAM by a wide margin. 178 if e10.measurement_value > e12.measurement_value * 2 { return 110 } 179 } 180 } 181 182 return 0 183}