mirror of
https://github.com/drasko/codezero.git
synced 2026-04-17 17:29:04 +02:00
Reverted all changes - userspace devices mapped at initialization.
This is much simpler, no device map/unmap maintenance at run-time, no lazy device mapping etc.
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#define IRQ_CONTROL_REGISTER 0
|
#define IRQ_CONTROL_REGISTER 0
|
||||||
#define IRQ_CONTROL_RELEASE 1
|
#define IRQ_CONTROL_RELEASE 1
|
||||||
|
#define IRQ_CONTROL_WAIT 2
|
||||||
|
|
||||||
|
|
||||||
#endif /* __API_IRQ_H__ */
|
#endif /* __API_IRQ_H__ */
|
||||||
|
|||||||
@@ -105,6 +105,6 @@ int cap_cap_check(struct ktcb *task, unsigned int req, unsigned int flags);
|
|||||||
int cap_mutex_check(unsigned long mutex_address, int mutex_op);
|
int cap_mutex_check(unsigned long mutex_address, int mutex_op);
|
||||||
|
|
||||||
int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
||||||
unsigned int flags, l4id_t irq, struct capability **cap);
|
unsigned int flags, l4id_t irq);
|
||||||
|
|
||||||
#endif /* __GENERIC_CAPABILITY_H__ */
|
#endif /* __GENERIC_CAPABILITY_H__ */
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ struct irq_desc {
|
|||||||
/* Notification slot for this irq */
|
/* Notification slot for this irq */
|
||||||
int task_notify_slot;
|
int task_notify_slot;
|
||||||
|
|
||||||
/* Device virtual address */
|
|
||||||
unsigned long device_virtual;
|
|
||||||
|
|
||||||
/* Device capability */
|
|
||||||
struct capability *devcap;
|
|
||||||
|
|
||||||
/* NOTE: This could be a list for multiple handlers for shared irqs */
|
/* NOTE: This could be a list for multiple handlers for shared irqs */
|
||||||
irq_handler_t handler;
|
irq_handler_t handler;
|
||||||
};
|
};
|
||||||
@@ -74,8 +68,8 @@ static inline void irq_disable(int irq_index)
|
|||||||
this_chip->ops.ack_and_mask(irq_index - this_chip->start);
|
this_chip->ops.ack_and_mask(irq_index - this_chip->start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_generic_map_device(struct irq_desc *desc);
|
|
||||||
int irq_register(struct ktcb *task, int notify_slot, l4id_t irq_index);
|
int irq_register(struct ktcb *task, int notify_slot, l4id_t irq_index);
|
||||||
|
int irq_thread_notify(struct irq_desc *desc);
|
||||||
|
|
||||||
void do_irq(void);
|
void do_irq(void);
|
||||||
void irq_controllers_init(void);
|
void irq_controllers_init(void);
|
||||||
|
|||||||
@@ -73,6 +73,8 @@
|
|||||||
#define MR0_REGISTER r3
|
#define MR0_REGISTER r3
|
||||||
#define MR_RETURN_REGISTER r3
|
#define MR_RETURN_REGISTER r3
|
||||||
|
|
||||||
|
#define TASK_NOTIFY_MAX 8
|
||||||
|
|
||||||
/* Primaries aren't used for memcopy. Those ops use this as a parameter */
|
/* Primaries aren't used for memcopy. Those ops use this as a parameter */
|
||||||
#define L4_UTCB_FULL_BUFFER_SIZE (MR_REST * sizeof(int))
|
#define L4_UTCB_FULL_BUFFER_SIZE (MR_REST * sizeof(int))
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ struct utcb {
|
|||||||
u32 mr[MR_TOTAL]; /* MRs that are mapped to real registers */
|
u32 mr[MR_TOTAL]; /* MRs that are mapped to real registers */
|
||||||
u32 saved_tag; /* Saved tag field for stacked ipcs */
|
u32 saved_tag; /* Saved tag field for stacked ipcs */
|
||||||
u32 saved_sender; /* Saved sender field for stacked ipcs */
|
u32 saved_sender; /* Saved sender field for stacked ipcs */
|
||||||
u8 notify_slot[8]; /* Irq notification slots */
|
u8 notify[TASK_NOTIFY_MAX]; /* Irq notification slots */
|
||||||
u32 mr_rest[MR_REST]; /* Complete the utcb for up to 64 words */
|
u32 mr_rest[MR_REST]; /* Complete the utcb for up to 64 words */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* Address allocation pool
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007 - 2009 Bahadir Balban
|
|
||||||
*/
|
|
||||||
#ifndef __KERNEL_ADDR_H__
|
|
||||||
#define __KERNEL_ADDR_H__
|
|
||||||
|
|
||||||
#include <lib/idpool.h>
|
|
||||||
|
|
||||||
/* Address pool to allocate from a range of addresses */
|
|
||||||
struct address_pool {
|
|
||||||
struct id_pool idpool;
|
|
||||||
unsigned long start;
|
|
||||||
unsigned long end;
|
|
||||||
};
|
|
||||||
|
|
||||||
void *kernel_new_address(int npages);
|
|
||||||
int kernel_delete_address(void *addr, int npages);
|
|
||||||
|
|
||||||
void *address_new(struct address_pool *pool, int npages);
|
|
||||||
int address_del(struct address_pool *, void *addr, int npages);
|
|
||||||
|
|
||||||
#endif /* __KERNEL_ADDR_H__ */
|
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
#define PB926_SIC_VOFFSET 0x00003000
|
#define PB926_SIC_VOFFSET 0x00003000
|
||||||
#define PB926_SYSREGS_VOFFSET 0x00004000
|
#define PB926_SYSREGS_VOFFSET 0x00004000
|
||||||
#define PB926_SYSCTRL_VOFFSET 0x00005000
|
#define PB926_SYSCTRL_VOFFSET 0x00005000
|
||||||
|
#define PB926_TIMER23_VOFFSET 0x00006000
|
||||||
|
|
||||||
#define PLATFORM_CONSOLE_VIRTUAL (IO_AREA0_VADDR + PB926_UART0_VOFFSET)
|
#define PLATFORM_CONSOLE_VIRTUAL (IO_AREA0_VADDR + PB926_UART0_VOFFSET)
|
||||||
#define PLATFORM_TIMER0_VIRTUAL (IO_AREA0_VADDR + PB926_TIMER01_VOFFSET)
|
#define PLATFORM_TIMER0_VIRTUAL (IO_AREA0_VADDR + PB926_TIMER01_VOFFSET)
|
||||||
|
|||||||
@@ -69,9 +69,7 @@ int irq_thread_notify(struct irq_desc *desc)
|
|||||||
* Register the given globally unique irq number with the
|
* Register the given globally unique irq number with the
|
||||||
* current thread with given flags
|
* current thread with given flags
|
||||||
*/
|
*/
|
||||||
int irq_control_register(struct ktcb *task, int slot, l4id_t irqnum,
|
int irq_control_register(struct ktcb *task, int slot, l4id_t irqnum)
|
||||||
unsigned long device_virtual,
|
|
||||||
struct capability *devcap)
|
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@@ -87,12 +85,18 @@ int irq_control_register(struct ktcb *task, int slot, l4id_t irqnum,
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* Register the irq for thread notification */
|
/* Register the irq for thread notification */
|
||||||
if ((err = irq_register(current, slot, irqnum, devcap)) < 0)
|
if ((err = irq_register(current, slot, irqnum)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int irq_wait()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register/deregister device irqs. Optional synchronous and
|
* Register/deregister device irqs. Optional synchronous and
|
||||||
* asynchronous irq handling.
|
* asynchronous irq handling.
|
||||||
@@ -101,17 +105,19 @@ int sys_irq_control(unsigned int req, unsigned int flags, l4id_t irqno)
|
|||||||
{
|
{
|
||||||
/* Currently a task is allowed to register only for itself */
|
/* Currently a task is allowed to register only for itself */
|
||||||
struct ktcb *task = current;
|
struct ktcb *task = current;
|
||||||
struct capability *devcap;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = cap_irq_check(task, req, flags, irqno, &devcap)) < 0)
|
if ((err = cap_irq_check(task, req, flags, irqno)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
switch (req) {
|
switch (req) {
|
||||||
case IRQ_CONTROL_REGISTER:
|
case IRQ_CONTROL_REGISTER:
|
||||||
if ((err = irq_control_register(task, slot, flags,
|
if ((err = irq_control_register(task, flags, irqno)) < 0)
|
||||||
irqno, devcap)) < 0)
|
|
||||||
return err;
|
return err;
|
||||||
|
break;
|
||||||
|
case IRQ_CONTROL_WAIT:
|
||||||
|
irq_wait();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -877,8 +877,7 @@ int cap_thread_check(struct ktcb *task,
|
|||||||
|
|
||||||
|
|
||||||
int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
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 = {
|
struct sys_irqctrl_args args = {
|
||||||
.registrant = registrant,
|
.registrant = registrant,
|
||||||
@@ -896,8 +895,8 @@ int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
|||||||
* Find the device capability and
|
* Find the device capability and
|
||||||
* check that it allows irq registration
|
* check that it allows irq registration
|
||||||
*/
|
*/
|
||||||
if (!(*device_cap = cap_find(current, cap_match_devmem,
|
if (!cap_find(current, cap_match_devmem,
|
||||||
&args, CAP_TYPE_MAP_PHYSMEM)))
|
&args, CAP_TYPE_MAP_PHYSMEM))
|
||||||
return -ENOCAP;
|
return -ENOCAP;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -940,7 +939,7 @@ int cap_thread_check(struct ktcb *task,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
int cap_irq_check(struct ktcb *registrant, unsigned int req,
|
||||||
unsigned int flags, l4id_t irq, struct capability **cap)
|
unsigned int flags, l4id_t irq)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,34 +15,6 @@
|
|||||||
#include INC_PLAT(irq.h)
|
#include INC_PLAT(irq.h)
|
||||||
#include INC_ARCH(exception.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.
|
* Registers a userspace thread as an irq handler.
|
||||||
*
|
*
|
||||||
@@ -54,8 +26,7 @@ void irq_generic_map_device(struct irq_desc *desc)
|
|||||||
* If the irq does not have these set up, we cannot allow
|
* If the irq does not have these set up, we cannot allow
|
||||||
* the irq registry.
|
* the irq registry.
|
||||||
*/
|
*/
|
||||||
int irq_register(struct ktcb *task, int notify_slot,
|
int irq_register(struct ktcb *task, int notify_slot, l4id_t irq_index)
|
||||||
l4id_t irq_index, struct capability *device)
|
|
||||||
{
|
{
|
||||||
struct irq_desc *this_desc = irq_desc_array + irq_index;
|
struct irq_desc *this_desc = irq_desc_array + irq_index;
|
||||||
|
|
||||||
@@ -67,17 +38,6 @@ int irq_register(struct ktcb *task, int notify_slot,
|
|||||||
this_desc->task = task;
|
this_desc->task = task;
|
||||||
this_desc->task_notify_slot = notify_slot;
|
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 */
|
/* Enable the irq */
|
||||||
irq_enable(irq_index);
|
irq_enable(irq_index);
|
||||||
|
|
||||||
|
|||||||
@@ -416,19 +416,6 @@ int free_boot_memory(struct kernel_resources *kres)
|
|||||||
return 0;
|
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
|
* Initializes kernel caplists, and sets up total of physical
|
||||||
* and virtual memory as single capabilities of the kernel.
|
* and virtual memory as single capabilities of the kernel.
|
||||||
@@ -448,9 +435,6 @@ void init_kernel_resources(struct kernel_resources *kres)
|
|||||||
kres->mutex_ids.nwords = SYSTEM_IDS_MAX;
|
kres->mutex_ids.nwords = SYSTEM_IDS_MAX;
|
||||||
kres->capability_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 */
|
/* Initialize container head */
|
||||||
container_head_init(&kres->containers);
|
container_head_init(&kres->containers);
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* This module allocates an unused address range from
|
|
||||||
* a given memory region defined as the pool range.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007 - 2009 Bahadir Balban
|
|
||||||
*/
|
|
||||||
#include <lib/bit.h>
|
|
||||||
#include <l4/macros.h>
|
|
||||||
#include <l4/types.h>
|
|
||||||
#include INC_GLUE(memory.h)
|
|
||||||
#include <lib/addr.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
extern struct kernel_resources kres;
|
|
||||||
|
|
||||||
void *address_new(struct address_pool *pool, int npages)
|
|
||||||
{
|
|
||||||
unsigned int pfn;
|
|
||||||
|
|
||||||
if ((int)(pfn = ids_new_contiguous(pool->idpool, npages)) < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return (void *)__pfn_to_addr(pfn) + pool->start;
|
|
||||||
}
|
|
||||||
|
|
||||||
int address_del(struct address_pool *pool, void *addr, int npages)
|
|
||||||
{
|
|
||||||
unsigned long pfn = __pfn(page_align(addr) - pool->start);
|
|
||||||
|
|
||||||
if (ids_del_contiguous(pool->idpool, pfn, npages) < 0) {
|
|
||||||
printf("%s: Invalid address range returned to "
|
|
||||||
"virtual address pool.\n", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *kernel_new_address(int npages)
|
|
||||||
{
|
|
||||||
return address_new(&kres->kernel_address_pool, npages);
|
|
||||||
}
|
|
||||||
|
|
||||||
int kernel_delete_address(void *addr, int npages)
|
|
||||||
{
|
|
||||||
address_del(&kres->kernel_address_pool, addr, npages);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -139,13 +139,13 @@ void wake_up_all(struct waitqueue_head *wqh, unsigned int flags)
|
|||||||
/* Wake up single waiter */
|
/* Wake up single waiter */
|
||||||
void wake_up(struct waitqueue_head *wqh, unsigned int flags)
|
void wake_up(struct waitqueue_head *wqh, unsigned int flags)
|
||||||
{
|
{
|
||||||
unsigned int irqflags;
|
unsigned long irqflags;
|
||||||
|
|
||||||
BUG_ON(wqh->sleepers < 0);
|
BUG_ON(wqh->sleepers < 0);
|
||||||
|
|
||||||
/* Irq version */
|
/* Irq version */
|
||||||
if (flags & WAKEUP_IRQ)
|
if (flags & WAKEUP_IRQ)
|
||||||
spin_lock_irq(&wqh->lock, &irqflags);
|
spin_lock_irq(&wqh->slock, &irqflags);
|
||||||
else
|
else
|
||||||
spin_lock(&wqh->slock);
|
spin_lock(&wqh->slock);
|
||||||
if (wqh->sleepers > 0) {
|
if (wqh->sleepers > 0) {
|
||||||
@@ -161,7 +161,7 @@ void wake_up(struct waitqueue_head *wqh, unsigned int flags)
|
|||||||
sleeper->flags |= TASK_INTERRUPTED;
|
sleeper->flags |= TASK_INTERRUPTED;
|
||||||
//printk("(%d) Waking up (%d)\n", current->tid, sleeper->tid);
|
//printk("(%d) Waking up (%d)\n", current->tid, sleeper->tid);
|
||||||
if (flags & WAKEUP_IRQ)
|
if (flags & WAKEUP_IRQ)
|
||||||
spin_unlock_irqrestore(&wqh->slock, irqflags);
|
spin_unlock_irq(&wqh->slock, irqflags);
|
||||||
else
|
else
|
||||||
spin_unlock(&wqh->slock);
|
spin_unlock(&wqh->slock);
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ void wake_up(struct waitqueue_head *wqh, unsigned int flags)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (flags & WAKEUP_IRQ)
|
if (flags & WAKEUP_IRQ)
|
||||||
spin_unlock_irqrestore(&wqh->slock, irqflags);
|
spin_unlock_irq(&wqh->slock, irqflags);
|
||||||
else
|
else
|
||||||
spin_unlock(&wqh->slock);
|
spin_unlock(&wqh->slock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,13 +54,10 @@ static int platform_timer_handler(struct irq_desc *desc)
|
|||||||
/*
|
/*
|
||||||
* Timer handler for userspace
|
* Timer handler for userspace
|
||||||
*/
|
*/
|
||||||
static int platform_user_timer_irq_handler(struct irq_desc *desc)
|
static int platform_timer_user_handler(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
/* Lazily map the device to process kernel tables */
|
|
||||||
irq_generic_map_device(desc);
|
|
||||||
|
|
||||||
/* Ack the device irq */
|
/* Ack the device irq */
|
||||||
sp804_irq_handler(desc->device_virtual);
|
sp804_irq_handler(PLATFORM_TIMER1_VIRTUAL);
|
||||||
|
|
||||||
/* Notify the userspace */
|
/* Notify the userspace */
|
||||||
irq_thread_notify(desc);
|
irq_thread_notify(desc);
|
||||||
@@ -82,7 +79,8 @@ struct irq_desc irq_desc_array[IRQS_MAX] = {
|
|||||||
[IRQ_TIMER1] = {
|
[IRQ_TIMER1] = {
|
||||||
.name = "Timer1",
|
.name = "Timer1",
|
||||||
.chip = &irq_chip_array[0],
|
.chip = &irq_chip_array[0],
|
||||||
.handler = platform_user_timer_handler
|
.handler = platform_timer_user_handler,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -121,10 +121,18 @@ void init_platform_irq_controller()
|
|||||||
irq_controllers_init();
|
irq_controllers_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init_platform_devices()
|
||||||
|
{
|
||||||
|
/* Add userspace devices here as you develop their irq handlers */
|
||||||
|
add_boot_mapping(PB926_TIMER23_BASE, PLATFORM_TIMER1_VIRTUAL,
|
||||||
|
PAGE_SIZE, MAP_IO_DEFAULT_FLAGS);
|
||||||
|
}
|
||||||
|
|
||||||
void platform_init(void)
|
void platform_init(void)
|
||||||
{
|
{
|
||||||
init_platform_console();
|
init_platform_console();
|
||||||
init_platform_timer();
|
init_platform_timer();
|
||||||
init_platform_irq_controller();
|
init_platform_irq_controller();
|
||||||
|
init_platform_devices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user