#include <stdio.h>
/*
 * DF-5801: release-build arithmetic twin of sys/vm/vm_page.c:vm_page_bits().
 * The kernel's only guard is `KASSERT(base + size <= PAGE_SIZE, ...)`,
 * which sys/sys/systm.h:116-119 compiles to nothing unless INVARIANTS is
 * set. This program (built with the guest's own cc at -O2) documents what
 * a release kernel computes for the same inputs the KLD rig passes.
 */
int bits(int base, int size){
    int first_bit = base >> 9;
    int last_bit  = (base + size - 1) >> 9;
    return (2 << last_bit) - (1 << first_bit);
}
int main(void){
    printf("legal  bits(0,4096)        = 0x%x\n", bits(0,4096));
    printf("oob    bits(0,8192)        = 0x%x  (size beyond page)\n", bits(0,8192));
    printf("oob    bits(0,4096+512)    = 0x%x  (setter over-validates page)\n", bits(0,4608));
    printf("oob    bits(4096,1)        = 0x%x  (phantom bit 8)\n", bits(4096,1));
    printf("ub     bits(-512,1024)     = 0x%x  (1<<-1 shift UB)\n", (unsigned)bits(-512,1024));
    printf("ub     bits(0,1<<30)       = 0x%x  (2<<30 signed ovf)\n", (unsigned)bits(0,1<<30));
    return 0;
}
