/* * Initialize an offtab to support the specified number of offsets read * to or written from fd at byte position fdpos. */ void offtab_init(struct offtab *offtab, uint32_t n_offsets, uint32_t window_size, int fd, off_t fdpos) { assert(offtab != NULL); assert(0 < n_offsets); assert(0 <= fd); assert(0 <= fdpos); offtab->ot_n_offsets = n_offsets; if ((window_size == 0) || (n_offsets < window_size)) offtab->ot_window_size = n_offsets; else offtab->ot_window_size = window_size; assert(offtab->ot_window_size <= offtab->ot_n_offsets); offtab->ot_window_start = (uint32_t)-1; __CTASSERT(MAX_WINDOW_SIZE <= (SIZE_MAX / sizeof(uint64_t))); offtab->ot_window = malloc(offtab->ot_window_size * sizeof(uint64_t)); if (offtab->ot_window == NULL) err(1, "malloc offset table"); offtab->ot_blkno = (uint32_t)-1; offtab->ot_fd = fd; offtab->ot_fdpos = fdpos; offtab->ot_report = &offtab_bug; offtab->ot_reportx = &offtab_bugx; offtab->ot_mode = OFFTAB_MODE_NONE; }
static int process_machdep_write_xmmregs(struct lwp *l, struct xmmregs *regs) { __CTASSERT(sizeof *regs == sizeof (struct fxsave)); process_write_fpregs_xmm(l, (const struct fxsave *)regs); return 0; }
int process_write_fpregs(struct lwp *l, const struct fpreg *regs, size_t sz) { __CTASSERT(sizeof *regs == sizeof (struct save87)); process_write_fpregs_s87(l, (const struct save87 *)regs); return 0; }
int process_read_fpregs(struct lwp *l, struct fpreg *regs, size_t *sz) { __CTASSERT(sizeof *regs == sizeof (struct save87)); process_read_fpregs_s87(l, (struct save87 *)regs); return 0; }
static void offtab_compute_window_position(struct offtab *offtab, uint32_t window_start, size_t *bytes, off_t *pos) { const uint32_t window_size = offtab_compute_window_size(offtab, window_start); __CTASSERT(MAX_WINDOW_SIZE <= (SIZE_MAX / sizeof(uint64_t))); *bytes = (window_size * sizeof(uint64_t)); assert(window_start <= offtab->ot_n_offsets); __CTASSERT(MAX_N_OFFSETS <= (OFF_MAX / sizeof(uint64_t))); const off_t window_offset = ((off_t)window_start * (off_t)sizeof(uint64_t)); /* XXX This assertion is not justified. */ assert(offtab->ot_fdpos <= (OFF_MAX - window_offset)); *pos = (offtab->ot_fdpos + window_offset); }
struct cpu_info * cpu_info_alloc(struct pmap_tlb_info *ti, cpuid_t cpu_id, cpuid_t cpu_package_id, cpuid_t cpu_core_id, cpuid_t cpu_smt_id) { KASSERT(cpu_id < MAXCPUS); #ifdef MIPS64_OCTEON vaddr_t exc_page = MIPS_UTLB_MISS_EXC_VEC + 0x1000*cpu_id; __CTASSERT(sizeof(struct cpu_info) + sizeof(struct pmap_tlb_info) <= 0x1000 - 0x280); struct cpu_info * const ci = ((struct cpu_info *)(exc_page + 0x1000)) - 1; memset((void *)exc_page, 0, PAGE_SIZE); if (ti == NULL) { ti = ((struct pmap_tlb_info *)ci) - 1; pmap_tlb_info_init(ti); } #else const vaddr_t cpu_info_offset = (vaddr_t)&cpu_info_store & PAGE_MASK; struct pglist pglist; int error; /* * Grab a page from the first 512MB (mappable by KSEG0) to use to store * exception vectors and cpu_info for this cpu. */ error = uvm_pglistalloc(PAGE_SIZE, 0, MIPS_KSEG1_START - MIPS_KSEG0_START, PAGE_SIZE, PAGE_SIZE, &pglist, 1, false); if (error) return NULL; const paddr_t pa = VM_PAGE_TO_PHYS(TAILQ_FIRST(&pglist)); const vaddr_t va = MIPS_PHYS_TO_KSEG0(pa); struct cpu_info * const ci = (void *) (va + cpu_info_offset); memset((void *)va, 0, PAGE_SIZE); /* * If we weren't passed a pmap_tlb_info to use, the caller wants us * to take care of that for him. Since we have room left over in the * page we just allocated, just use a piece of that for it. */ if (ti == NULL) { if (cpu_info_offset >= sizeof(*ti)) { ti = (void *) va; } else { KASSERT(PAGE_SIZE - cpu_info_offset + sizeof(*ci) >= sizeof(*ti)); ti = (struct pmap_tlb_info *)(va + PAGE_SIZE) - 1; } pmap_tlb_info_init(ti); } /* * Attach its TLB info (which must be direct-mapped) */ #ifdef _LP64 KASSERT(MIPS_KSEG0_P(ti) || MIPS_XKPHYS_P(ti)); #else KASSERT(MIPS_KSEG0_P(ti)); #endif #endif /* MIPS64_OCTEON */ KASSERT(cpu_id != 0); ci->ci_cpuid = cpu_id; ci->ci_pmap_kern_segtab = &pmap_kern_segtab, ci->ci_data.cpu_package_id = cpu_package_id; ci->ci_data.cpu_core_id = cpu_core_id; ci->ci_data.cpu_smt_id = cpu_smt_id; ci->ci_cpu_freq = cpu_info_store.ci_cpu_freq; ci->ci_cctr_freq = cpu_info_store.ci_cctr_freq; ci->ci_cycles_per_hz = cpu_info_store.ci_cycles_per_hz; ci->ci_divisor_delay = cpu_info_store.ci_divisor_delay; ci->ci_divisor_recip = cpu_info_store.ci_divisor_recip; ci->ci_cpuwatch_count = cpu_info_store.ci_cpuwatch_count; pmap_md_alloc_ephemeral_address_space(ci); mi_cpu_attach(ci); pmap_tlb_info_attach(ti, ci); return ci; }
int main(int argc, char **argv) { char *rdev, *fsname, buf[LFS_SBPAD]; size_t rdevlen; daddr_t newsize, newnsegs; int devfd, rootfd; int ch, i, verbose; off_t secsize, sboff; struct disk_geom geo; struct dkwedge_info dkw; struct lfs *fs; struct statvfs vfs; /* Initialize and parse arguments */ verbose = 0; newsize = 0; while ((ch = getopt(argc, argv, "s:v")) != -1) { switch(ch) { case 's': /* New size, in sectors */ newsize = strtoll(optarg, NULL, 10); break; case 'v': ++verbose; break; default: usage(); } } fsname = argv[optind]; if (fsname == NULL) usage(); /* * If the user did not supply a filesystem size, use the * length of the mounted partition. */ if (statvfs(fsname, &vfs) < 0) err(1, "%s", fsname); rdevlen = strlen(vfs.f_mntfromname) + 2; rdev = malloc(rdevlen); snprintf(rdev, rdevlen, "/dev/r%s", vfs.f_mntfromname + 5); devfd = open(rdev, O_RDONLY); if (devfd < 0) err(1, "open raw device"); /* * Read the disklabel to find the sector size. Check the * given size against the partition size. We can skip some * error checking here since we know the fs is mountable. */ if (getdiskinfo(rdev, devfd, NULL, &geo, &dkw) == -1) err(1, "%s: could not get info", rdev); secsize = geo.dg_secsize; if (newsize > dkw.dkw_size) errx(1, "new size must be <= the partition size"); if (newsize == 0) newsize = dkw.dkw_size; /* Open the root of the filesystem so we can fcntl() it */ rootfd = open(fsname, O_RDONLY); if (rootfd < 0) err(1, "open filesystem root"); /* Read the superblock, finding alternates if necessary */ fs = (struct lfs *)malloc(sizeof(*fs)); for (sboff = LFS_LABELPAD;;) { pread(devfd, buf, sboff, LFS_SBPAD); __CTASSERT(sizeof(struct dlfs) == sizeof(struct dlfs64)); memcpy(&fs->lfs_dlfs_u, buf, sizeof(struct dlfs)); if (sboff == LFS_LABELPAD && lfs_fsbtob(fs, 1) > LFS_LABELPAD) sboff = lfs_fsbtob(fs, (off_t)lfs_sb_getsboff(fs, 0)); else break; } close(devfd); /* Calculate new number of segments. */ newnsegs = (newsize * secsize) / lfs_sb_getssize(fs); if (newnsegs == lfs_sb_getnseg(fs)) { errx(0, "the filesystem is unchanged."); } /* * If the new filesystem is smaller than the old, we have to * invalidate the segments that extend beyond the new boundary. * Make the cleaner do this for us. * (XXX make the kernel able to do this instead?) */ for (i = lfs_sb_getnseg(fs) - 1; i >= newnsegs; --i) { char cmd[128]; /* If it's already empty, don't call the cleaner */ if (fcntl(rootfd, LFCNINVAL, &i) == 0) continue; snprintf(cmd, sizeof(cmd), "/libexec/lfs_cleanerd -q -i %d %s", i, fsname); if (system(cmd) != 0) err(1, "invalidating segment %d", i); } /* Tell the filesystem to resize itself. */ if (fcntl(rootfd, LFCNRESIZE, &newnsegs) == -1) { err(1, "resizing"); } if (verbose) printf("Successfully resized %s from %u to %lld segments\n", fsname, lfs_sb_getnseg(fs), (long long)newnsegs); return 0; }