mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 10:53:16 +01:00
Added a device attribute to capabilities - In progress
Followed the kernel physical memory reservation convention with devices. Devices that are possessable by userspace are created as boot-time capabilities and placed under the kernel resources devmem_free capability list. Any userspace container that is defined with the possession of the device would delete the device capability making it unavailable to further requests.
This commit is contained in:
@@ -267,18 +267,24 @@ int memcap_unmap(struct cap_list *used_list,
|
||||
const unsigned long unmap_end)
|
||||
{
|
||||
struct capability *cap, *n;
|
||||
int err;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If a used list was supplied, check that the
|
||||
* range does not intersect with the used list.
|
||||
* This is an optional sanity check.
|
||||
*/
|
||||
if (used_list)
|
||||
list_foreach_removable_struct(cap, n, &used_list->caps, list)
|
||||
if (used_list) {
|
||||
list_foreach_removable_struct(cap, n,
|
||||
&used_list->caps,
|
||||
list) {
|
||||
if (set_intersection(unmap_start, unmap_end,
|
||||
cap->start, cap->end))
|
||||
return -EPERM;
|
||||
cap->start, cap->end)) {
|
||||
ret = -EPERM;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list_foreach_removable_struct(cap, n, &cap_list->caps, list) {
|
||||
/* Check for intersection */
|
||||
@@ -287,12 +293,59 @@ int memcap_unmap(struct cap_list *used_list,
|
||||
if ((err = memcap_unmap_range(cap, cap_list,
|
||||
unmap_start,
|
||||
unmap_end))) {
|
||||
return err;
|
||||
goto out_err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EEXIST;
|
||||
ret = -EEXIST;
|
||||
|
||||
out_err:
|
||||
if (ret == -ENOMEM)
|
||||
printk("%s: FATAL: Insufficient boot memory "
|
||||
"to split capability\n", __KERNELNAME__);
|
||||
else if (ret == -EPERM)
|
||||
printk("%s: FATAL: %s memory capability range "
|
||||
"overlaps with an already used range. "
|
||||
"start=0x%lx, end=0x%lx\n", __KERNELNAME__,
|
||||
cap_type(cap) == CAP_TYPE_MAP_VIRTMEM ?
|
||||
"Virtual" : "Physical",
|
||||
__pfn_to_addr(cap->start),
|
||||
__pfn_to_addr(cap->end));
|
||||
else if (ret == -EEXIST)
|
||||
printk("%s: FATAL: %s memory capability range "
|
||||
"does not match with any available free range. "
|
||||
"start=0x%lx, end=0x%lx\n", __KERNELNAME__,
|
||||
cap_type(cap) == CAP_TYPE_MAP_VIRTMEM ?
|
||||
"Virtual" : "Physical",
|
||||
__pfn_to_addr(cap->start),
|
||||
__pfn_to_addr(cap->end));
|
||||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds a device memory capability and deletes it from
|
||||
* the available device capabilities list
|
||||
*/
|
||||
int memcap_request_device(struct cap_list *cap_list,
|
||||
struct cap_info *devcap)
|
||||
{
|
||||
list_foreach_removable_struct(cap, n, &cap_list->caps, list) {
|
||||
if (cap->start == devcap->start &&
|
||||
cap->end == devcap->end &&
|
||||
cap->uattr == devcap->uattr) {
|
||||
/* Unlink only. This is boot memory */
|
||||
list_remove(&cap);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
printk("%s: FATAL: Device memory requested "
|
||||
"does not match any available device "
|
||||
"capabilities start=0x%lx, end=0x%lx "
|
||||
"uattr=0x%lx\n", __KERNELNAME__,
|
||||
__pfn_to_addr(devcap->start),
|
||||
__pfn_to_addr(devcap->end), devcap->uattr);
|
||||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -417,6 +470,8 @@ void init_kernel_resources(struct kernel_resources *kres)
|
||||
memcap_unmap(0, &kres->physmem_free, kernel_area->start,
|
||||
kernel_area->end);
|
||||
|
||||
/* Set up platform-specific device capabilities */
|
||||
platform_setup_device_caps(kres);
|
||||
|
||||
/* TODO:
|
||||
* Add all virtual memory areas used by the kernel
|
||||
@@ -746,7 +801,6 @@ void init_resource_allocators(struct boot_resources *bootres,
|
||||
kres->pmd_cache =
|
||||
init_resource_cache(bootres->npmds,
|
||||
PMD_SIZE, kres, 1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -785,61 +839,19 @@ int process_cap_info(struct cap_info *cap,
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cap_type(cap)) {
|
||||
case CAP_TYPE_MAP_VIRTMEM:
|
||||
if ((ret = memcap_unmap(&kres->virtmem_used, &kres->virtmem_free,
|
||||
cap->start, cap->end))) {
|
||||
if (ret == -ENOMEM)
|
||||
printk("%s: FATAL: Insufficient boot memory "
|
||||
"to split capability\n",
|
||||
__KERNELNAME__);
|
||||
if (ret == -EPERM)
|
||||
printk("%s: FATAL: Virtual memory capability range "
|
||||
"overlaps with an already used range. "
|
||||
"start=0x%lx, end=0x%lx\n",
|
||||
__KERNELNAME__,
|
||||
__pfn_to_addr(cap->start),
|
||||
__pfn_to_addr(cap->end));
|
||||
if (ret == -EEXIST)
|
||||
printk("%s: FATAL: Virtual memory capability range "
|
||||
"does not match with any available free range. "
|
||||
"start=0x%lx, end=0x%lx\n",
|
||||
__KERNELNAME__,
|
||||
__pfn_to_addr(cap->start),
|
||||
__pfn_to_addr(cap->end));
|
||||
|
||||
BUG();
|
||||
}
|
||||
break;
|
||||
|
||||
case CAP_TYPE_MAP_PHYSMEM:
|
||||
if ((ret = memcap_unmap(&kres->physmem_used, &kres->physmem_free,
|
||||
cap->start, cap->end))) {
|
||||
if (ret == -ENOMEM)
|
||||
printk("%s: FATAL: Insufficient boot memory "
|
||||
"to split capability\n",
|
||||
__KERNELNAME__);
|
||||
if (ret == -EPERM)
|
||||
printk("%s: FATAL: Physical memory capability range "
|
||||
"overlaps with an already used range. "
|
||||
"start=0x%lx, end=0x%lx\n",
|
||||
__KERNELNAME__,
|
||||
__pfn_to_addr(cap->start),
|
||||
__pfn_to_addr(cap->end));
|
||||
if (ret == -EEXIST)
|
||||
printk("%s: FATAL: Physical memory capability range "
|
||||
"does not match with any available free range. "
|
||||
"start=0x%lx, end=0x%lx\n",
|
||||
__KERNELNAME__,
|
||||
__pfn_to_addr(cap->start),
|
||||
__pfn_to_addr(cap->end));
|
||||
|
||||
BUG();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
if (cap_type(cap) == CAP_TYPE_MAP_VIRTMEM) {
|
||||
memcap_unmap(&kres->virtmem_used,
|
||||
&kres->virtmem_free,
|
||||
cap->start, cap->end)
|
||||
} else if (cap_type(cap) == CAP_TYPE_MAP_PHYSMEM) {
|
||||
if (!cap_devmem(cap))
|
||||
memcap_unmap(&kres->physmem_used,
|
||||
&kres->physmem_free,
|
||||
cap->start, cap->end)
|
||||
else /* Delete device from free list */
|
||||
memcap_request_device(&kres->devmem_free, cap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
|
||||
#include <l4/generic/capability.h>
|
||||
#include <l4/generic/cap-types.h>
|
||||
#include <l4/generic/platform.h>
|
||||
#include <l4/generic/space.h>
|
||||
#include <l4/generic/irq.h>
|
||||
@@ -19,11 +20,92 @@
|
||||
#include INC_PLAT(irq.h)
|
||||
#include INC_ARCH(asm.h)
|
||||
|
||||
/*
|
||||
* The devices that are used by the kernel are mapped
|
||||
* independent of these capabilities, but these provide a
|
||||
* concise description of what is used by the kernel.
|
||||
*/
|
||||
int platform_setup_device_caps(struct kernel_resources *kres)
|
||||
{
|
||||
struct capability *uart[4], *timer[2], *irqctrl[2], *sysctrl;
|
||||
|
||||
#if 0
|
||||
/* Setup kernel capability for uart0 as used */
|
||||
uart[0] = alloc_bootmem(sizeof(*uart[0]), 0);
|
||||
uart[0]->start = __pfn(PB926_UART0_BASE);
|
||||
uart[0]->end = uart[0]->start + 1;
|
||||
uart[0]->uattr = CAP_DEVTYPE_UART;
|
||||
link_init(&uart[0]->list);
|
||||
cap_list_insert(uart[0], &kres->devmem_used);
|
||||
|
||||
/* Setup timer0 capability as used */
|
||||
timer[0] = alloc_bootmem(sizeof(*timer[0]), 0);
|
||||
timer[0]->start = __pfn(PB926_TIMER01_BASE);
|
||||
timer[0]->end = timer[0]->start + 1;
|
||||
timer[0]->uattr = CAP_DEVTYPE_TIMER;
|
||||
link_init(&timer[0]->list);
|
||||
cap_list_insert(timer[0], &kres->devmem_used);
|
||||
|
||||
/* Setup irq controller 0 and 1 as used */
|
||||
irqctrl[0] = alloc_bootmem(sizeof(*irqctrl[0]), 0);
|
||||
irqctrl[0]->start = __pfn(PB926_VIC_BASE);
|
||||
irqctrl[0]->end = irqctrl[0]->start + 1;
|
||||
irqctrl[0]->uattr = CAP_DEVTYPE_IRQCTRL;
|
||||
link_init(&irqctrl[0]->list);
|
||||
cap_list_insert(irqctrl[0], &kres->devmem_used);
|
||||
|
||||
irqctrl[1] = alloc_bootmem(sizeof(*irqctrl[1]), 0);
|
||||
irqctrl[1]->start = __pfn(PB926_SIC_BASE);
|
||||
irqctrl[1]->end = irqctrl[1]->start + 1;
|
||||
irqctrl[1]->uattr = CAP_DEVTYPE_IRQCTRL;
|
||||
link_init(&irqctrl[1]->list);
|
||||
cap_list_insert(irqctrl[1], &kres->devmem_used);
|
||||
|
||||
/* Set up system controller as used */
|
||||
sysctrl = alloc_bootmem(sizeof(*sysctrl), 0);
|
||||
sysctrl->start = __pfn(PB926_SYSCTRL_BASE);
|
||||
sysctrl->end = sysctrl->start + 1;
|
||||
sysctrl->uattr = CAP_DEVTYPE_SYSCTRL;
|
||||
link_init(&sysctrl->list);
|
||||
cap_list_insert(sysctrl, &kres->devmem_used);
|
||||
#endif
|
||||
|
||||
/* Setup capabilities for other uarts as free */
|
||||
uart[1] = alloc_bootmem(sizeof(*uart[i]), 0);
|
||||
uart[1]->start = __pfn(PB926_UART1_BASE);
|
||||
uart[1]->end = uart[1]->start + 1;
|
||||
uart[1]->uattr = CAP_DEVTYPE_UART;
|
||||
link_init(&uart[1]->list);
|
||||
cap_list_insert(uart[1], &kres->devmem_free);
|
||||
|
||||
uart[2] = alloc_bootmem(sizeof(*uart[2]), 0);
|
||||
uart[2]->start = __pfn(PB926_UART2_BASE);
|
||||
uart[2]->end = uart[2]->start + 1;
|
||||
uart[2]->uattr = CAP_DEVTYPE_UART;
|
||||
link_init(&uart[2]->list);
|
||||
cap_list_insert(uart[2], &kres->devmem_free);
|
||||
|
||||
uart[3] = alloc_bootmem(sizeof(*uart[3]), 0);
|
||||
uart[3]->start = __pfn(PB926_UART3_BASE);
|
||||
uart[3]->end = uart[3]->start + 1;
|
||||
uart[3]->uattr = CAP_DEVTYPE_UART;
|
||||
link_init(&uart[3]->list);
|
||||
cap_list_insert(uart[3], &kres->devmem_free);
|
||||
|
||||
/* Setup timer1 capability as free */
|
||||
timer[1] = alloc_bootmem(sizeof(*timer[1]), 0);
|
||||
timer[1]->start = __pfn(PB926_TIMER12_BASE);
|
||||
timer[1]->end = timer[1]->start + 1;
|
||||
timer[1]->uattr = CAP_DEVTYPE_TIMER;
|
||||
link_init(&timer[1]->list);
|
||||
cap_list_insert(timer[1], &kres->devmem_free);
|
||||
}
|
||||
|
||||
/* We will use UART0 for kernel as well as user tasks, so map it to kernel and user space */
|
||||
void init_platform_console(void)
|
||||
{
|
||||
add_boot_mapping(PB926_UART0_BASE, PLATFORM_CONSOLE0_BASE, PAGE_SIZE,
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
|
||||
/*
|
||||
* Map same UART IO area to userspace so that primitive uart-based
|
||||
@@ -31,7 +113,7 @@ void init_platform_console(void)
|
||||
* removed in the future, when file-based io is implemented.
|
||||
*/
|
||||
add_boot_mapping(PB926_UART0_BASE, USERSPACE_UART_BASE, PAGE_SIZE,
|
||||
MAP_USR_IO_FLAGS);
|
||||
MAP_USR_IO_FLAGS);
|
||||
|
||||
uart_init();
|
||||
}
|
||||
@@ -44,19 +126,20 @@ void init_platform_console(void)
|
||||
void init_platform_timer(void)
|
||||
{
|
||||
add_boot_mapping(PB926_TIMER01_BASE, PLATFORM_TIMER0_BASE, PAGE_SIZE,
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
|
||||
add_boot_mapping(PB926_SYSCTRL_BASE, PB926_SYSCTRL_VBASE, PAGE_SIZE,
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
|
||||
add_boot_mapping(PB926_SYSCTRL_BASE, PB926_SYSCTRL_VBASE, PAGE_SIZE,
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
timer_init();
|
||||
}
|
||||
|
||||
void init_platform_irq_controller()
|
||||
{
|
||||
add_boot_mapping(PB926_VIC_BASE, PLATFORM_IRQCTRL_BASE, PAGE_SIZE,
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
add_boot_mapping(PB926_SIC_BASE, PLATFORM_SIRQCTRL_BASE, PAGE_SIZE,
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
MAP_IO_DEFAULT_FLAGS);
|
||||
irq_controllers_init();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user