Example #1
0
/** Install I/O Permission bitmap.
 *
 * Current task's I/O permission bitmap, if any, is installed
 * in the current CPU's TSS.
 *
 * Interrupts must be disabled prior this call.
 *
 */
void io_perm_bitmap_install(void)
{
    /* First, copy the I/O Permission Bitmap. */
    irq_spinlock_lock(&TASK->lock, false);

    size_t ver = TASK->arch.iomapver;
    size_t elements = TASK->arch.iomap.elements;

    if (elements > 0) {
        ASSERT(TASK->arch.iomap.bits);

        bitmap_t iomap;
        bitmap_initialize(&iomap, TSS_IOMAP_SIZE * 8,
                          CPU->arch.tss->iomap);
        bitmap_copy(&iomap, &TASK->arch.iomap, elements);

        /*
         * Set the trailing bits in the last byte of the map to disable
         * I/O access.
         */
        bitmap_set_range(&iomap, elements,
                         ALIGN_UP(elements, 8) - elements);

        /*
         * It is safe to set the trailing eight bits because of the
         * extra convenience byte in TSS_IOMAP_SIZE.
         */
        bitmap_set_range(&iomap, ALIGN_UP(elements, 8), 8);
    }

    irq_spinlock_unlock(&TASK->lock, false);

    /*
     * Second, adjust TSS segment limit.
     * Take the extra ending byte with all bits set into account.
     */
    ptr_16_64_t cpugdtr;
    gdtr_store(&cpugdtr);

    descriptor_t *gdt_p = (descriptor_t *) cpugdtr.base;
    size_t size = bitmap_size(elements);
    gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + size);
    gdtr_load(&cpugdtr);

    /*
     * Before we load new TSS limit, the current TSS descriptor
     * type must be changed to describe inactive TSS.
     */
    tss_descriptor_t *tss_desc = (tss_descriptor_t *) &gdt_p[TSS_DES];
    tss_desc->type = AR_TSS;
    tr_load(GDT_SELECTOR(TSS_DES));

    /*
     * Update the generation count so that faults caused by
     * early accesses can be serviced.
     */
    CPU->arch.iomapver_copy = ver;
}
Example #2
0
/** Enable I/O space range for task.
 *
 * Interrupts are disabled and task is locked.
 *
 * @param task   Task.
 * @param ioaddr Starting I/O space address.
 * @param size   Size of the enabled I/O range.
 *
 * @return EOK on success or an error code from errno.h.
 *
 */
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
	size_t elements = ioaddr + size;
	if (elements > IO_PORTS)
		return ENOENT;
	
	if (task->arch.iomap.elements < elements) {
		/*
		 * The I/O permission bitmap is too small and needs to be grown.
		 */
		
		void *store = malloc(bitmap_size(elements), FRAME_ATOMIC);
		if (!store)
			return ENOMEM;
		
		bitmap_t oldiomap;
		bitmap_initialize(&oldiomap, task->arch.iomap.elements,
		    task->arch.iomap.bits);
		
		bitmap_initialize(&task->arch.iomap, elements, store);
		
		/*
		 * Mark the new range inaccessible.
		 */
		bitmap_set_range(&task->arch.iomap, oldiomap.elements,
		    elements - oldiomap.elements);
		
		/*
		 * In case there really existed smaller iomap,
		 * copy its contents and deallocate it.
		 */
		if (oldiomap.bits) {
			bitmap_copy(&task->arch.iomap, &oldiomap,
			    oldiomap.elements);
			
			free(oldiomap.bits);
		}
	}
	
	/*
	 * Enable the range and we are done.
	 */
	bitmap_clear_range(&task->arch.iomap, (size_t) ioaddr, size);
	
	/*
	 * Increment I/O Permission bitmap generation counter.
	 */
	task->arch.iomapver++;
	
	return EOK;
}
Example #3
0
/** Mark frame in zone unavailable to allocation. */
NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t index)
{
	ASSERT(zone->flags & ZONE_AVAILABLE);
	
	frame_t *frame = zone_get_frame(zone, index);
	if (frame->refcount > 0)
		return;
	
	frame->refcount = 1;
	bitmap_set_range(&zone->bitmap, index, 1);
	
	zone->free_count--;
	reserve_force_alloc(1);
}
Example #4
0
/* Allocate and initialize data needed for global pseudo live
   analysis.  */
static void
initiate_live_solver (void)
{
  bitmap_initialize (&all_hard_regs_bitmap, &reg_obstack);
  bitmap_set_range (&all_hard_regs_bitmap, 0, FIRST_PSEUDO_REGISTER);
  bb_data = XNEWVEC (struct bb_data_pseudos, last_basic_block_for_fn (cfun));
  bitmap_initialize (&all_blocks, &reg_obstack);

  basic_block bb;
  FOR_ALL_BB_FN (bb, cfun)
    {
      bb_data_t bb_info = get_bb_data (bb);
      bb_info->bb = bb;
      bitmap_initialize (&bb_info->killed_pseudos, &reg_obstack);
      bitmap_initialize (&bb_info->gen_pseudos, &reg_obstack);
      bitmap_set_bit (&all_blocks, bb->index);
    }
Example #5
0
/** Enable I/O space range for task.
 *
 * Interrupts are disabled and task is locked.
 *
 * @param task	 Task.
 * @param ioaddr Starting I/O space address.
 * @param size	 Size of the enabled I/O range.
 *
 * @return EOK on success or an error code from errno.h.
 */
int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
    if (!task->arch.iomap) {
        task->arch.iomap = malloc(sizeof(bitmap_t), 0);
        if (task->arch.iomap == NULL)
            return ENOMEM;

        void *store = malloc(bitmap_size(IO_MEMMAP_PAGES), 0);
        if (store == NULL)
            return ENOMEM;

        bitmap_initialize(task->arch.iomap, IO_MEMMAP_PAGES, store);
        bitmap_clear_range(task->arch.iomap, 0, IO_MEMMAP_PAGES);
    }

    uintptr_t iopage = ioaddr / PORTS_PER_PAGE;
    size = ALIGN_UP(size + ioaddr - 4 * iopage, PORTS_PER_PAGE);
    bitmap_set_range(task->arch.iomap, iopage, size / 4);

    return EOK;
}
Example #6
0
/** Disable I/O space range for task.
 *
 * Interrupts are disabled and task is locked.
 *
 * @param task   Task.
 * @param ioaddr Starting I/O space address.
 * @param size   Size of the enabled I/O range.
 *
 * @return EOK on success or an error code from errno.h.
 *
 */
int ddi_iospace_disable_arch(task_t *task, uintptr_t ioaddr, size_t size)
{
	size_t elements = ioaddr + size;
	if (elements > IO_PORTS)
		return ENOENT;
	
	if (ioaddr >= task->arch.iomap.elements)
		return EINVAL;	

	if (task->arch.iomap.elements < elements)
		size -= elements - task->arch.iomap.elements;

	/*
	 * Disable the range.
	 */
	bitmap_set_range(&task->arch.iomap, (size_t) ioaddr, size);
	
	/*
	 * Increment I/O Permission bitmap generation counter.
	 */
	task->arch.iomapver++;
	
	return 0;
}