* Changed the meaning of the {KERNEL,USER}_STACK_SIZE macros to not

include the guard pages. Adjusted the kernel and boot loader code
  accordingly -- the guard pages size is added/not removed respectively.
  The stack size passed to _kern_spawn_thread() is now the actually usable
  size, and it is no longer possible to specify a size smaller than or
  equal to the guard pages size.
* vm_create_anonymous_area(): Precommit two pages maximum -- a stack with
  only one page usable size obviously doesn't need two pages.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26819 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-08-05 17:19:46 +00:00
parent afa9fe8958
commit 57f2b5a013
14 changed files with 78 additions and 57 deletions
+5 -4
View File
@@ -27,12 +27,13 @@
// At least, you then know that the stack overflows in this case :)
/** Size of the kernel stack */
#ifndef DEBUG_KERNEL_STACKS
# define KERNEL_STACK_SIZE (B_PAGE_SIZE * 3) // 12 kB
#define KERNEL_STACK_SIZE (B_PAGE_SIZE * 3) // 12 kB
#ifdef DEBUG_KERNEL_STACKS
# define KERNEL_STACK_GUARD_PAGES 1
#else
# define KERNEL_STACK_SIZE (B_PAGE_SIZE * 4) // 12 kB + one guard page
# define KERNEL_STACK_GUARD_PAGES 0
#endif
#define KERNEL_STACK_GUARD_PAGES 1
/** Size of the environmental variables space for a process */
#define ENV_SIZE (B_PAGE_SIZE * 8)
+8 -5
View File
@@ -14,11 +14,14 @@
#define THREAD_CONTINUED 0x4
/** Size of the stack given to teams in user space */
#define USER_MAIN_THREAD_STACK_SIZE (16 * 1024 * 1024) // 16 MB
#define USER_STACK_SIZE (256 * 1024) // 256 kB
#define MIN_USER_STACK_SIZE (4 * 1024) // 4 KB
#define MAX_USER_STACK_SIZE (16 * 1024 * 1024) // 16 MB
#define USER_STACK_GUARD_PAGES 4 // 16 kB
#define USER_STACK_GUARD_PAGES 4 // 16 kB
#define USER_MAIN_THREAD_STACK_SIZE (16 * 1024 * 1024 \
- USER_STACK_GUARD_PAGES * B_PAGE_SIZE) // 16 MB
#define USER_STACK_SIZE (256 * 1024 \
- USER_STACK_GUARD_PAGES * B_PAGE_SIZE) // 256 kB
#define MIN_USER_STACK_SIZE (4 * 1024) // 4 KB
#define MAX_USER_STACK_SIZE (16 * 1024 * 1024 \
- USER_STACK_GUARD_PAGES * B_PAGE_SIZE) // 16 MB
struct thread_creation_attributes {
+15 -13
View File
@@ -57,12 +57,12 @@
* 0xdNNNNN video buffer usually there, as per v_bas_ad
* (=Logbase() but Physbase() is better)
*
* The first 32 MB (2) are identity mapped (0x0 - 0x1000000); paging
* is turned on. The kernel is mapped at 0x80000000, all other stuff
* mapped by the loader (kernel args, modules, driver settings, ...)
* comes after 0x81000000 which means that there is currently only
* The first 32 MB (2) are identity mapped (0x0 - 0x1000000); paging
* is turned on. The kernel is mapped at 0x80000000, all other stuff
* mapped by the loader (kernel args, modules, driver settings, ...)
* comes after 0x81000000 which means that there is currently only
* 1 MB reserved for the kernel itself (see kMaxKernelSize).
*
*
* (1) no need for user stack, we are already in supervisor mode in the
* loader.
* (2) maps the whole regular ST space; transparent translation registers
@@ -143,9 +143,9 @@ extern "C" addr_t
mmu_get_next_page_tables()
{
#if 0
TRACE(("mmu_get_next_page_tables, sNextPageTableAddress %p, kPageTableRegionEnd %p\n",
TRACE(("mmu_get_next_page_tables, sNextPageTableAddress %p, kPageTableRegionEnd %p\n",
sNextPageTableAddress, kPageTableRegionEnd));
addr_t address = sNextPageTableAddress;
if (address >= kPageTableRegionEnd)
return (uint32 *)get_next_physical_page();
@@ -492,7 +492,7 @@ mmu_init_for_kernel(void)
// seg 0x10 - kernel 4GB data
set_segment_descriptor(&virtualGDT[2], 0, 0xffffffff, DT_DATA_WRITEABLE,
DPL_KERNEL);
// seg 0x1b - ring 3 user 4GB code
set_segment_descriptor(&virtualGDT[3], 0, 0xffffffff, DT_CODE_READABLE,
DPL_USER);
@@ -613,10 +613,12 @@ mmu_init(void)
// set virtual addr for interrupt vector table
gKernelArgs.arch_args.vir_vbr = gKernelArgs.arch_args.vir_pgroot
+ VBR_PAGE_OFFSET;
// map in a kernel stack
gKernelArgs.cpu_kstack[0].start = (addr_t)mmu_allocate(NULL, KERNEL_STACK_SIZE);
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE;
gKernelArgs.cpu_kstack[0].start = (addr_t)mmu_allocate(NULL,
KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
TRACE(("kernel stack at 0x%lx to 0x%lx\n", gKernelArgs.cpu_kstack[0].start,
gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size));
@@ -633,9 +635,9 @@ mmu_init(void)
gKernelArgs.physical_memory_range[1].size =
fastram_top - ATARI_FASTRAM_BASE;
gKernelArgs.num_physical_memory_ranges++;
}
// mark the video area allocated
addr_t video_base = *TOSVAR_memtop;
video_base &= ~(B_PAGE_SIZE-1);
+4 -3
View File
@@ -302,7 +302,7 @@ get_memory_map(extended_memory **_extendedMemory)
dprintf("extended memory info (from 0xe820):\n");
for (uint32 i = 0; i < count; i++) {
dprintf(" base 0x%08Lx, len 0x%08Lx, type %lu (%s)\n",
block[i].base_addr, block[i].length,
block[i].base_addr, block[i].length,
block[i].type, e820_memory_type(block[i].type));
}
#endif
@@ -606,8 +606,9 @@ mmu_init(void)
// map in a kernel stack
gKernelArgs.cpu_kstack[0].start = (addr_t)mmu_allocate(NULL,
KERNEL_STACK_SIZE);
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE;
KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
TRACE(("kernel stack at 0x%lx to 0x%lx\n", gKernelArgs.cpu_kstack[0].start,
gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size));
+11 -5
View File
@@ -396,8 +396,10 @@ smp_init_other_cpus(void)
for (uint32 i = 1; i < gKernelArgs.num_cpus; i++) {
// create a final stack the trampoline code will put the ap processor on
gKernelArgs.cpu_kstack[i].start = (addr_t)mmu_allocate(NULL, KERNEL_STACK_SIZE);
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE;
gKernelArgs.cpu_kstack[i].start = (addr_t)mmu_allocate(NULL,
KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
}
}
@@ -438,14 +440,18 @@ smp_boot_other_cpus(void)
// set this stack up
finalStack = (uint32 *)gKernelArgs.cpu_kstack[i].start;
memset(finalStack, 0, KERNEL_STACK_SIZE);
tempStack = (finalStack + KERNEL_STACK_SIZE / sizeof(uint32)) - 1;
memset((uint8*)finalStack + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0,
KERNEL_STACK_SIZE);
tempStack = (finalStack
+ (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE)
/ sizeof(uint32)) - 1;
*tempStack = (uint32)&smp_cpu_ready;
// set the trampoline stack up
tempStack = (uint32 *)(trampolineStack + B_PAGE_SIZE - 4);
// final location of the stack
*tempStack = ((uint32)finalStack) + KERNEL_STACK_SIZE - sizeof(uint32);
*tempStack = ((uint32)finalStack) + KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE - sizeof(uint32);
tempStack--;
// page dir
*tempStack = gKernelArgs.arch_args.phys_pgdir;
@@ -76,7 +76,7 @@ boot_arch_cpu_init(void)
gKernelArgs.arch_args.cpu_frequency = clockFrequency;
gKernelArgs.arch_args.bus_frequency = busFrequency;
gKernelArgs.arch_args.time_base_frequency = timeBaseFrequency;
TRACE((" CPU clock frequency: %ld\n", clockFrequency));
TRACE((" bus clock frequency: %ld\n", busFrequency));
TRACE((" time base frequency: %ld\n", timeBaseFrequency));
@@ -84,7 +84,7 @@ boot_arch_cpu_init(void)
cpuCount++;
}
if (cpuCount == 0) {
printf("boot_arch_cpu_init(): Found no CPUs!\n");
return B_ERROR;
@@ -95,7 +95,8 @@ boot_arch_cpu_init(void)
// allocate the kernel stacks (the memory stuff is already initialized
// at this point)
addr_t stack = (addr_t)arch_mmu_allocate((void*)0x80000000,
cpuCount * KERNEL_STACK_SIZE, B_READ_AREA | B_WRITE_AREA, false);
cpuCount * (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE),
B_READ_AREA | B_WRITE_AREA, false);
if (!stack) {
printf("boot_arch_cpu_init(): Failed to allocate kernel stack(s)!\n");
return B_NO_MEMORY;
@@ -103,8 +104,9 @@ boot_arch_cpu_init(void)
for (int i = 0; i < cpuCount; i++) {
gKernelArgs.cpu_kstack[i].start = stack;
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE;
stack += KERNEL_STACK_SIZE;
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
stack += KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
}
return B_OK;
+1 -1
View File
@@ -180,7 +180,7 @@ return 0;
kprintf(" kernel stack: %p to %p\n",
(void *)thread->kernel_stack_base,
(void *)(thread->kernel_stack_base + KERNEL_STACK_SIZE));
(void *)(thread->kernel_stack_top));
if (thread->user_stack_base != 0) {
kprintf(" user stack: %p to %p\n",
(void *)thread->user_stack_base,
+4 -4
View File
@@ -110,7 +110,7 @@ m68k_next_page_directory(struct thread *from, struct thread *to)
// the one we're switching to is kernel space
return m68k_translation_map_get_pgdir(&vm_kernel_address_space()->translation_map);
}
return m68k_translation_map_get_pgdir(&to->team->address_space->translation_map);
}
@@ -150,15 +150,15 @@ arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void),
void (*entry_func)(void), void (*exit_func)(void))
{
addr_t *kstack = (addr_t *)t->kernel_stack_base;
addr_t *kstackTop = kstack + KERNEL_STACK_SIZE / sizeof(addr_t);
addr_t *kstackTop = (addr_t *)t->kernel_stack_base;
// clear the kernel stack
#ifdef DEBUG_KERNEL_STACKS
# ifdef STACK_GROWS_DOWNWARDS
memset((void *)((addr_t)kstack + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE), 0,
KERNEL_STACK_SIZE - KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
KERNEL_STACK_SIZE);
# else
memset(kstack, 0, KERNEL_STACK_SIZE - KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
memset(kstack, 0, KERNEL_STACK_SIZE);
# endif
#else
memset(kstack, 0, KERNEL_STACK_SIZE);
+1 -1
View File
@@ -179,7 +179,7 @@ return 0;
kprintf(" kernel stack: %p to %p\n",
(void *)thread->kernel_stack_base,
(void *)(thread->kernel_stack_base + KERNEL_STACK_SIZE));
(void *)(thread->kernel_stack_top));
if (thread->user_stack_base != 0) {
kprintf(" user stack: %p to %p\n",
(void *)thread->user_stack_base,
+6 -6
View File
@@ -122,15 +122,15 @@ arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void),
void (*entry_func)(void), void (*exit_func)(void))
{
addr_t *kstack = (addr_t *)t->kernel_stack_base;
addr_t *kstackTop = kstack + KERNEL_STACK_SIZE / sizeof(addr_t);
addr_t *kstackTop = (addr_t *)t->kernel_stack_top;
// clear the kernel stack
#ifdef DEBUG_KERNEL_STACKS
# ifdef STACK_GROWS_DOWNWARDS
memset((void *)((addr_t)kstack + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE), 0,
KERNEL_STACK_SIZE - KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
KERNEL_STACK_SIZE);
# else
memset(kstack, 0, KERNEL_STACK_SIZE - KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
memset(kstack, 0, KERNEL_STACK_SIZE);
# endif
#else
memset(kstack, 0, KERNEL_STACK_SIZE);
@@ -180,9 +180,9 @@ void
arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
{
// set the new kernel stack in the EAR register.
// this is used in the exception handler code to decide what kernel stack to
// switch to if the exception had happened when the processor was in user mode
asm("mtear %0" :: "g"(t_to->kernel_stack_base + KERNEL_STACK_SIZE - 8));
// this is used in the exception handler code to decide what kernel stack to
// switch to if the exception had happened when the processor was in user mode
asm("mtear %0" :: "g"(t_to->kernel_stack_top - 8));
// switch the asids if we need to
if (t_to->team->address_space != NULL) {
+2 -2
View File
@@ -261,9 +261,9 @@ arch_thread_init_kthread_stack(struct thread *t, int (*start_func)(void),
#ifdef DEBUG_KERNEL_STACKS
# ifdef STACK_GROWS_DOWNWARDS
memset((void *)((addr_t)kstack + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE), 0,
KERNEL_STACK_SIZE - KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
KERNEL_STACK_SIZE);
# else
memset(kstack, 0, KERNEL_STACK_SIZE - KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE);
memset(kstack, 0, KERNEL_STACK_SIZE);
# endif
#else
memset(kstack, 0, KERNEL_STACK_SIZE);
+4 -2
View File
@@ -985,10 +985,12 @@ team_create_thread_start(void *args)
// ToDo: ENV_SIZE is a) limited, and b) not used after libroot copied it to the heap
// ToDo: we could reserve the whole USER_STACK_REGION upfront...
sizeLeft = PAGE_ALIGN(USER_MAIN_THREAD_STACK_SIZE + TLS_SIZE
sizeLeft = PAGE_ALIGN(USER_MAIN_THREAD_STACK_SIZE
+ USER_STACK_GUARD_PAGES * B_PAGE_SIZE + TLS_SIZE
+ sizeof(struct user_space_program_args) + teamArgs->flat_args_size);
t->user_stack_base = USER_STACK_REGION + USER_STACK_REGION_SIZE - sizeLeft;
t->user_stack_size = USER_MAIN_THREAD_STACK_SIZE;
t->user_stack_size = USER_MAIN_THREAD_STACK_SIZE
+ USER_STACK_GUARD_PAGES * B_PAGE_SIZE;
// the exact location at the end of the user stack area
sprintf(ustack_name, "%s_main_stack", team->name);
+5 -2
View File
@@ -391,7 +391,8 @@ create_thread(thread_creation_attributes& attributes, bool kernel)
thread->id);
thread->kernel_stack_area = create_area(stack_name,
(void **)&thread->kernel_stack_base, B_ANY_KERNEL_ADDRESS,
KERNEL_STACK_SIZE, B_FULL_LOCK,
KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE,
B_FULL_LOCK,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_KERNEL_STACK_AREA);
if (thread->kernel_stack_area < 0) {
@@ -405,7 +406,8 @@ create_thread(thread_creation_attributes& attributes, bool kernel)
return status;
}
thread->kernel_stack_top = thread->kernel_stack_base + KERNEL_STACK_SIZE;
thread->kernel_stack_top = thread->kernel_stack_base + KERNEL_STACK_SIZE
+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
state = disable_interrupts();
GRAB_THREAD_LOCK();
@@ -499,6 +501,7 @@ create_thread(thread_creation_attributes& attributes, bool kernel)
thread->user_stack_size = USER_STACK_SIZE;
else
thread->user_stack_size = PAGE_ALIGN(attributes.stack_size);
thread->user_stack_size += USER_STACK_GUARD_PAGES * B_PAGE_SIZE;
snprintf(stack_name, B_OS_NAME_LENGTH, "%s_%ld_stack",
attributes.name, thread->id);
+5 -4
View File
@@ -1576,6 +1576,7 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
vm_cache *cache;
vm_page *page = NULL;
bool isStack = (protection & B_STACK_AREA) != 0;
page_num_t guardPages;
bool canOvercommit = false;
addr_t physicalBase = 0;
@@ -1693,10 +1694,10 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
// create an anonymous cache
// if it's a stack, make sure that two pages are available at least
status = VMCacheFactory::CreateAnonymousCache(cache,
canOvercommit, isStack ? 2 : 0,
isStack ? ((protection & B_USER_PROTECTION) != 0 ?
USER_STACK_GUARD_PAGES : KERNEL_STACK_GUARD_PAGES) : 0,
guardPages = isStack ? ((protection & B_USER_PROTECTION) != 0
? USER_STACK_GUARD_PAGES : KERNEL_STACK_GUARD_PAGES) : 0;
status = VMCacheFactory::CreateAnonymousCache(cache, canOvercommit,
isStack ? (min_c(2, size / B_PAGE_SIZE - guardPages)) : 0, guardPages,
wiring == B_NO_LOCK);
if (status != B_OK)
goto err1;