static int pin_and_count_noncontigs (char *addr, u_int datalen) { u_int data, next, ppn, prev_ppn; u_int noncontigs = 0; data = (u_int) addr; prev_ppn = si->si_nppages; while (datalen > 0) { ppn = PGNO (*va2ptep (data)); if (ppn != (prev_ppn + 1)) { noncontigs++; } ppage_pin (&ppages[ppn]); prev_ppn = ppn; /* go to start of next page of data */ next = (data & ~PGMASK) + NBPG; if (next - data >= datalen) break; datalen -= next - data; data = next; } return (noncontigs); }
static msgringent * msgringent_setup (msgringent * u_msgringent) { msgringent *ktmp; Pte *pte = NULL; int scatptr = 0; int total_len = 0; ktmp = (msgringent *) malloc (sizeof (msgringent)); if (ktmp == NULL) { warn ("msgringent_setup: failed malloc"); return (NULL); } ktmp->appaddr = u_msgringent; ktmp->owner = NULL; ktmp->body.n = 0; /* Verify and translate owner field */ if ((((u_int) u_msgringent->owner % sizeof (int)) || ! (pte = va2ptep ((u_int) u_msgringent->owner)) || ((*pte & WRITE_MASK) != WRITE_MASK))) { warn ("msgringent_setup: owner field failed\n"); msgringent_free (ktmp); return (NULL); } ktmp->owner = (u_int *) pa2kva (va2pa (u_msgringent->owner)); ppage_pin (kva2pp ((u_long) ktmp->owner)); /* Verify and translate data field */ if (u_msgringent->body.n > 1) { warn ("msgringent_setup: not allowed to setup disjoint message body\n"); msgringent_free (ktmp); return (NULL); } scatptr = 0; total_len = 0; { int len = u_msgringent->body.r[0].sz; caddr_t addr = u_msgringent->body.r[0].data; u_int pagebound = NBPG-(((u_long)addr)&(NBPG - 1)); while (len > 0) { u_int slen = min (len, pagebound); if (!(pte = va2ptep ((u_int) addr)) || ((*pte & READ_MASK) != READ_MASK)) { /* physical page is not accessible */ warn ("msgringent_setup: can't read scatter ptr\n"); msgringent_free (ktmp); return (NULL); } ktmp->body.r[scatptr].data = (char *) pa2kva (va2pa (addr)); ktmp->body.r[scatptr].sz = slen; ktmp->body.n++; /* pin the page to prevent re-allocation */ ppage_pin (kva2pp ((u_long) ktmp->body.r[scatptr].data)); len -= slen; addr += slen; total_len += slen; pagebound = NBPG; scatptr++; if (scatptr > IPC_MAX_SCATTER_PTR || total_len > IPC_MAX_MSG_SIZE) { msgringent_free (ktmp); warn ("msgringent_setup: message body too big\n"); return (NULL); } } } return (ktmp); }