Esempio n. 1
0
/*
 * 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;
}
Esempio n. 5
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);
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}