mirror of
https://github.com/drasko/codezero.git
synced 2026-01-15 12:23:15 +01:00
Made changes to map devices dynamically upon irq registration.
All will be reverted since mapping devices statically is much simpler.
This commit is contained in:
@@ -877,7 +877,8 @@ int cap_thread_check(struct ktcb *task,
|
||||
|
||||
|
||||
int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
||||
unsigned int flags, l4id_t irq)
|
||||
unsigned int flags, l4id_t irq,
|
||||
struct capability **device_cap)
|
||||
{
|
||||
struct sys_irqctrl_args args = {
|
||||
.registrant = registrant,
|
||||
@@ -895,8 +896,8 @@ int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
||||
* Find the device capability and
|
||||
* check that it allows irq registration
|
||||
*/
|
||||
if (!(cap_find(current, cap_match_devmem,
|
||||
&args, CAP_TYPE_MAP_PHYSMEM)))
|
||||
if (!(*device_cap = cap_find(current, cap_match_devmem,
|
||||
&args, CAP_TYPE_MAP_PHYSMEM)))
|
||||
return -ENOCAP;
|
||||
|
||||
return 0;
|
||||
@@ -939,7 +940,7 @@ int cap_thread_check(struct ktcb *task,
|
||||
}
|
||||
|
||||
int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
||||
unsigned int flags, l4id_t irq)
|
||||
unsigned int flags, l4id_t irq, struct capability **cap)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Kernel irq handling (core irqs like timer).
|
||||
* Also thread-level irq handling.
|
||||
* Generic kernel irq handling.
|
||||
*
|
||||
* Copyright (C) 2007 - 2009 Bahadir Balban
|
||||
*/
|
||||
@@ -12,31 +11,76 @@
|
||||
#include <l4/generic/irq.h>
|
||||
#include <l4/lib/mutex.h>
|
||||
#include <l4/lib/printk.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include INC_PLAT(irq.h)
|
||||
#include INC_ARCH(exception.h)
|
||||
|
||||
/*
|
||||
* Checks that a device was validly registered for the irq,
|
||||
* and lazily maps it to currently interrupted process.
|
||||
*/
|
||||
void irq_generic_map_device(struct irq_desc *desc)
|
||||
{
|
||||
/*
|
||||
* Check that irq is registered with a
|
||||
* valid device capability and virtual address
|
||||
*/
|
||||
if (!desc->devcap || !KERN_ADDR(devcap->device_virtual)) {
|
||||
printk("Spurious irq. %s irq occured but "
|
||||
"no device capability or valid virtual device "
|
||||
"address associated with the irq.\n",
|
||||
desc->name);
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Check and lazy map device */
|
||||
if (check_access(desc->device_virtual,
|
||||
desc->devcap->end - desc->devcap->start,
|
||||
MAP_SVC_RW_FLAGS, 0) < 0) {
|
||||
add_mapping(__pfn_to_addr(devcap->start),
|
||||
desc->device_virtual, MAP_SVC_RW_FLAGS,
|
||||
desc->devcap->end - desc->devcap->start);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Registers a userspace thread as an irq handler.
|
||||
*
|
||||
* A userspace irq thread should have a low-level, device-specific
|
||||
* irq handler as an in-kernel counterpart. This and its irq chip
|
||||
* must have been set up at compile-time. These handlers should
|
||||
* also know how to notify their userspace threads.
|
||||
*
|
||||
* If the irq does not have these set up, we cannot allow
|
||||
* the irq registry.
|
||||
*/
|
||||
int irq_register(struct ktcb *task, int notify_slot,
|
||||
l4id_t irq_index, irq_handler_t handler)
|
||||
l4id_t irq_index, struct capability *device)
|
||||
{
|
||||
struct irq_desc *this_desc = irq_desc_array + irq_index;
|
||||
struct irq_chip *current_chip = irq_chip_array;
|
||||
|
||||
for (int i = 0; i < IRQ_CHIPS_MAX; i++) {
|
||||
if (irq_index >= current_chip->start &&
|
||||
irq_index < current_chip->end) {
|
||||
this_desc->chip = current_chip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Setup the handler */
|
||||
this_desc->handler = handler;
|
||||
/* Kernel counterpart not set up, don't allow */
|
||||
if (!this_desc->handler || !this_desc->chip)
|
||||
return -ENOIRQ;
|
||||
|
||||
/* Setup the slot to notify the task */
|
||||
/* Setup the task and notify slot */
|
||||
this_desc->task = task;
|
||||
this_desc->task_notify_slot = notify_slot;
|
||||
|
||||
/*
|
||||
* Setup capability and allocate virtual kernel address.
|
||||
*
|
||||
* This is required so that the irq handler may reach
|
||||
* the device from the kernel at any runnable process.
|
||||
*/
|
||||
this_desc->devcap = device;
|
||||
if (!(this_desc->device_virtual =
|
||||
kernel_new_address(device->end - device->start)))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Enable the irq */
|
||||
irq_enable(irq_index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -416,6 +416,19 @@ int free_boot_memory(struct kernel_resources *kres)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kernel_address_pool_init(struct kernel_resources *kres)
|
||||
{
|
||||
/* Initialize id pool spinlock */
|
||||
spin_lock_init(&kres->kernel_address_pool.idpool.lock);
|
||||
|
||||
/* Initialize id pool number of words */
|
||||
kres->kernel_address_pool.idpool.nwords = SYSTEM_IDS_MAX;
|
||||
|
||||
/* Initialize address pool start and end ranges */
|
||||
kres->kernel_address_pool.start = page_align_up(_end);
|
||||
kres->kernel_address_pool.end = KERNEL_AREA_END;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes kernel caplists, and sets up total of physical
|
||||
* and virtual memory as single capabilities of the kernel.
|
||||
@@ -435,6 +448,9 @@ void init_kernel_resources(struct kernel_resources *kres)
|
||||
kres->mutex_ids.nwords = SYSTEM_IDS_MAX;
|
||||
kres->capability_ids.nwords = SYSTEM_IDS_MAX;
|
||||
|
||||
/* Initialize kernel's virtual address pool */
|
||||
kernel_address_pool_init(kres);
|
||||
|
||||
/* Initialize container head */
|
||||
container_head_init(&kres->containers);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user