63 lines
2 KiB
C
63 lines
2 KiB
C
// Map a forked child's REAL capabilities on a fresh DP (concurrency step 2).
|
|
// The leaf-only contract forbids "i32/i64 libcalls" -- but libcalls use the
|
|
// child's OWN $E0-$FF DP scratch (write-before-read), which a fresh page
|
|
// provides, so a child that CALLS A FUNCTION doing an i32 multiply (a real
|
|
// __mulsi3 libcall) may already work without any DP-scratch setup. This probe
|
|
// tests exactly that: a non-leaf child that JSLs a helper which does a genuine
|
|
// 32-bit multiply. It deliberately does NOT touch &global (needs $BE) or a
|
|
// function pointer (needs $B8 / the __jsl_indir operand) -- those are tested
|
|
// separately, since they can wild-jump. Reading a global's VALUE (gA/gB) is
|
|
// plain absolute/DBR addressing, not a 32-bit &global pointer.
|
|
//
|
|
// 0x025060 0001 child entered
|
|
// 0x025062 0001 mul32(gA,gB) == 300000 (function call + i32 libcall worked)
|
|
// 0x025064 E0DD child reached end (no crash)
|
|
// 0x025066 5050 parent reaped the child
|
|
#include <stdint.h>
|
|
|
|
extern int fork(void *subr);
|
|
extern int wait(int *status);
|
|
extern __attribute__((noreturn)) void _exit(int status);
|
|
|
|
#define M(a) (*(volatile uint16_t *)(a))
|
|
#define BAD 0xDEAD
|
|
|
|
static volatile uint32_t gA = 100000;
|
|
static volatile uint32_t gB = 3;
|
|
|
|
|
|
static uint32_t __attribute__((noinline)) mul32(uint32_t x, uint32_t y) {
|
|
return x * y; // real __mulsi3 libcall (uses $E0-$FF)
|
|
}
|
|
|
|
|
|
static void child(void) {
|
|
uint32_t r;
|
|
M(0x025060UL) = 0x0001; // child entered on its fresh DP
|
|
r = mul32(gA, gB); // fn-call + i32 libcall
|
|
if (r == 300000UL) {
|
|
M(0x025062UL) = 0x0001;
|
|
}
|
|
M(0x025064UL) = 0xE0DD; // reached end -> no crash
|
|
_exit(0);
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
int pid;
|
|
int st;
|
|
|
|
M(0x025060UL) = BAD;
|
|
M(0x025062UL) = BAD;
|
|
M(0x025064UL) = BAD;
|
|
M(0x025066UL) = BAD;
|
|
|
|
pid = fork((void *)child);
|
|
if (pid > 0) {
|
|
wait(&st);
|
|
M(0x025066UL) = 0x5050;
|
|
}
|
|
for (volatile unsigned long j = 0; j < 300000UL; j++) {
|
|
}
|
|
return 0;
|
|
}
|