Some work in progress of the MTRR support. Shouldn't do any harm yet :-)

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15525 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-12-13 00:06:52 +00:00
parent b7e7814c79
commit 2ed21b8525
16 changed files with 299 additions and 114 deletions
+1 -1
View File
@@ -126,7 +126,7 @@ arch_vm_unset_memory_type(vm_area *area)
status_t
arch_vm_set_memory_type(vm_area *area, uint32 type)
arch_vm_set_memory_type(vm_area *area, addr_t physicalBase, uint32 type)
{
if (type == 0)
return B_OK;
+28 -6
View File
@@ -103,22 +103,44 @@ x86_count_mtrrs(void)
status_t
x86_set_mtrr(uint32 index, addr_t base, addr_t length, uint32 type)
x86_enable_mtrrs(void)
{
if (load_cpu_module() == NULL)
return B_UNSUPPORTED;
return B_NOT_SUPPORTED;
return sCpuModule->set_mtrr(index, base, length, type);
return sCpuModule->enable_mtrrs();
}
status_t
x86_unset_mtrr(uint32 index)
x86_disable_mtrrs(void)
{
if (load_cpu_module() == NULL)
return B_UNSUPPORTED;
return B_NOT_SUPPORTED;
return sCpuModule->unset_mtrr(index);
sCpuModule->disable_mtrrs();
return B_OK;
}
status_t
x86_set_mtrr(uint32 index, addr_t base, addr_t length, uint32 type)
{
if (load_cpu_module() == NULL)
return B_NOT_SUPPORTED;
sCpuModule->set_mtrr(index, base, length, type);
return B_OK;
}
status_t
x86_get_mtrr(uint32 index, addr_t *_base, addr_t *_length, uint32 *_type)
{
if (load_cpu_module() == NULL)
return B_NOT_SUPPORTED;
return sCpuModule->get_mtrr(index, _base, _length, _type);
}
+65 -51
View File
@@ -30,26 +30,27 @@
#endif
static uint32 *sMTRRBitmap;
struct set_mtrr_parameter {
int32 index;
addr_t base;
addr_t length;
uint8 type;
};
static uint32 sMTRRBitmap;
static int32 sMTRRCount;
static spinlock sMTRRLock;
static status_t
init_mtrr_bitmap(void)
init_mtrr(void)
{
if (sMTRRBitmap != NULL)
return B_OK;
sMTRRCount = x86_count_mtrrs();
if (sMTRRCount == 0)
return B_UNSUPPORTED;
return B_NOT_SUPPORTED;
sMTRRBitmap = malloc(sMTRRCount / 8);
if (sMTRRBitmap == NULL)
return B_NO_MEMORY;
memset(sMTRRBitmap, 0, sMTRRCount / 8);
sMTRRBitmap = 0;
return B_OK;
}
@@ -57,28 +58,22 @@ init_mtrr_bitmap(void)
static int32
allocate_mtrr(void)
{
int32 count = sMTRRCount / 32;
int32 i, j;
int32 index;
cpu_status state = disable_interrupts();
acquire_spinlock(&sMTRRLock);
for (i = 0; i < count; i++) {
if (sMTRRBitmap[i] == 0xffffffff)
// find free bit
for (index = 0; index < 32; index++) {
if (sMTRRBitmap & (1UL << index))
continue;
// find free bit
sMTRRBitmap |= 1UL << index;
for (j = 0; j < 32; j++) {
if (sMTRRBitmap[i] & (1UL << j))
continue;
sMTRRBitmap[i] |= 1UL << j;
release_spinlock(&sMTRRLock);
restore_interrupts(state);
return i * 32 + j;
}
release_spinlock(&sMTRRLock);
restore_interrupts(state);
return index;
}
release_spinlock(&sMTRRLock);
@@ -91,19 +86,38 @@ allocate_mtrr(void)
static void
free_mtrr(int32 index)
{
int32 i = index / 32;
int32 j = index - i * 32;
cpu_status state = disable_interrupts();
acquire_spinlock(&sMTRRLock);
sMTRRBitmap[i] &= ~(1UL << j);
sMTRRBitmap &= ~(1UL << index);
release_spinlock(&sMTRRLock);
restore_interrupts(state);
}
static void
unset_mtrr(void *_index, int cpu)
{
int32 index = (int32)_index;
x86_set_mtrr(index, 0, 0, 0);
}
static void
set_mtrr(void *_parameter, int cpu)
{
struct set_mtrr_parameter *parameter = (struct set_mtrr_parameter *)_parameter;
x86_set_mtrr(parameter->index, parameter->base, parameter->length,
parameter->type);
}
// #pragma mark -
status_t
arch_vm_init(kernel_args *args)
{
@@ -182,58 +196,58 @@ arch_vm_unset_memory_type(vm_area *area)
if (area->memory_type.type == 0)
return;
x86_unset_mtrr(area->memory_type.index);
call_all_cpus(&unset_mtrr, (void *)(int32)area->memory_type.index);
free_mtrr(area->memory_type.index);
}
status_t
arch_vm_set_memory_type(vm_area *area, uint32 type)
arch_vm_set_memory_type(vm_area *area, addr_t physicalBase, uint32 type)
{
status_t status;
int32 index;
struct set_mtrr_parameter parameter;
if (type == 0)
return B_OK;
switch (type) {
case B_MTR_UC: // uncacheable
type = 0;
parameter.type = 0;
break;
case B_MTR_WC: // write combining
type = 1;
parameter.type = 1;
break;
case B_MTR_WT: // write through
type = 4;
parameter.type = 4;
break;
case B_MTR_WP: // write protected
type = 5;
parameter.type = 5;
break;
case B_MTR_WB: // write back
type = 6;
parameter.type = 6;
break;
default:
return B_BAD_VALUE;
}
if (sMTRRBitmap == NULL) {
status = init_mtrr_bitmap();
if (sMTRRCount == 0) {
status_t status = init_mtrr();
if (status < B_OK)
return status;
}
index = allocate_mtrr();
if (index < 0)
parameter.index = allocate_mtrr();
if (parameter.index < 0)
return B_ERROR;
status = x86_set_mtrr(index, area->base, area->size, type);
if (status != B_OK) {
area->memory_type.type = (uint16)type;
area->memory_type.index = (uint16)index;
} else
free_mtrr(index);
parameter.base = physicalBase;
parameter.length = area->size;
dprintf("memory type: %u, index: %ld\n", area->memory_type.type, index);
return status;
call_all_cpus(&set_mtrr, &parameter);
area->memory_type.type = parameter.type;
area->memory_type.index = (uint16)parameter.index;
dprintf("memory type: %u, index: %ld\n", area->memory_type.type, parameter.index);
return B_OK;
}
+7
View File
@@ -439,6 +439,13 @@ debug_init_post_vm(kernel_args *args)
}
status_t
debug_init_post_modules(struct kernel_args *args)
{
return frame_buffer_console_init_post_modules(args);
}
// #pragma mark - public API
@@ -7,6 +7,7 @@
#include <kernel.h>
#include <lock.h>
#include <boot_item.h>
#include <vm.h>
#include <fs/devfs.h>
#include <boot/kernel_args.h>
@@ -110,7 +111,7 @@ render_glyph(int32 x, int32 y, uint8 glyph, uint8 attr)
+ x * CHAR_WIDTH * sConsole.bytes_per_pixel);
uint8 *color = get_palette_entry(foreground_color(attr));
uint8 *backgroundColor = get_palette_entry(background_color(attr));
for (y = 0; y < CHAR_HEIGHT; y++) {
uint8 bits = FONT[CHAR_HEIGHT * glyph + y];
for (x = 0; x < CHAR_WIDTH; x++) {
@@ -122,7 +123,7 @@ render_glyph(int32 x, int32 y, uint8 glyph, uint8 attr)
}
bits >>= 1;
}
base += sConsole.bytes_per_row;
}
} else {
@@ -426,6 +427,19 @@ frame_buffer_console_init(kernel_args *args)
}
status_t
frame_buffer_console_init_post_modules(kernel_args *args)
{
if (sConsole.frame_buffer == NULL)
return B_OK;
// try to set frame buffer memory to write combined
return vm_set_area_memory_type(sConsole.area,
args->frame_buffer.physical_buffer.start, B_MTR_WC);
}
// #pragma mark -
+16
View File
@@ -225,6 +225,22 @@ int_io_interrupt_handler(int vector)
int status = B_UNHANDLED_INTERRUPT;
struct io_handler *io;
#if 0
{
static int low[2];
static int high[2];
static int counter;
int32 cpu = smp_get_current_cpu();
if (vector > 0xf0 - 32)
high[cpu]++;
else
low[cpu]++;
dprintf("got vector %d at CPU %ld\n", vector, cpu);
//if ((counter++ % 10) == 0)
dprintf("ints: %d/%d (high: %d/%d)\n", low[0], low[1], high[0], high[1]);
}
#endif
acquire_spinlock(&io_vectors[vector].vector_lock);
// The list can be empty at this place
+2 -21
View File
@@ -215,27 +215,8 @@ main2(void *unused)
TRACE(("Mount boot file system\n"));
vfs_mount_boot_file_system(&sKernelArgs);
//module_test();
#if 0
// XXX remove
vfs_test();
#endif
#if 0
// XXX remove
thread_test();
#endif
#if 0
vm_test();
#endif
#if 0
panic("debugger_test\n");
#endif
#if 0
cbuf_test();
#endif
#if 0
port_test();
#endif
debug_init_post_modules(&sKernelArgs);
// start the init process
{
const char *shellArgs[] = {"/bin/sh", "/boot/beos/system/boot/Bootscript", NULL};
+40 -16
View File
@@ -935,20 +935,22 @@ vm_create_anonymous_area(aspace_id aid, const char *name, void **address,
area_id
vm_map_physical_memory(aspace_id aid, const char *name, void **_address,
uint32 addressSpec, addr_t size, uint32 protection, addr_t phys_addr)
vm_map_physical_memory(aspace_id areaID, const char *name, void **_address,
uint32 addressSpec, addr_t size, uint32 protection,
addr_t physicalAddress)
{
vm_area *area;
vm_cache *cache;
vm_cache_ref *cache_ref;
vm_cache_ref *cacheRef;
vm_store *store;
addr_t map_offset;
addr_t mapOffset;
status_t status;
vm_address_space *aspace = vm_get_aspace_by_id(aid);
vm_address_space *aspace = vm_get_aspace_by_id(areaID);
TRACE(("vm_map_physical_memory(aspace = %ld, \"%s\", virtual = %p, spec = %ld,"
" size = %lu, protection = %ld, phys = %p)\n",
aid, name, _address, addressSpec, size, protection, (void *)phys_addr));
areaID, name, _address, addressSpec, size, protection,
(void *)physicalAddress));
if (!arch_vm_supports_protection(protection))
return B_NOT_SUPPORTED;
@@ -958,33 +960,36 @@ vm_map_physical_memory(aspace_id aid, const char *name, void **_address,
// if the physical address is somewhat inside a page,
// move the actual area down to align on a page boundary
map_offset = phys_addr % B_PAGE_SIZE;
size += map_offset;
phys_addr -= map_offset;
mapOffset = physicalAddress % B_PAGE_SIZE;
size += mapOffset;
physicalAddress -= mapOffset;
size = PAGE_ALIGN(size);
// create an device store object
store = vm_store_create_device(phys_addr);
// TODO: panic???
store = vm_store_create_device(physicalAddress);
if (store == NULL)
panic("vm_map_physical_memory: vm_store_create_device returned NULL");
cache = vm_cache_create(store);
if (cache == NULL)
panic("vm_map_physical_memory: vm_cache_create returned NULL");
cache_ref = vm_cache_ref_create(cache);
if (cache_ref == NULL)
cacheRef = vm_cache_ref_create(cache);
if (cacheRef == NULL)
panic("vm_map_physical_memory: vm_cache_ref_create returned NULL");
// tell the page scanner to skip over this area, it's pages are special
cache->scan_skip = 1;
vm_cache_acquire_ref(cache_ref, true);
vm_cache_acquire_ref(cacheRef, true);
status = map_backing_store(aspace, store, _address, 0, size,
addressSpec & ~B_MTR_MASK, 0, protection, REGION_NO_PRIVATE_MAP, &area, name);
vm_cache_release_ref(cache_ref);
vm_cache_release_ref(cacheRef);
if (status >= B_OK && (addressSpec & B_MTR_MASK) != 0) {
// set requested memory type
status = arch_vm_set_memory_type(area, addressSpec & B_MTR_MASK);
status = arch_vm_set_memory_type(area, physicalAddress,
addressSpec & B_MTR_MASK);
if (status < B_OK)
vm_put_area(area);
}
@@ -1003,7 +1008,7 @@ vm_map_physical_memory(aspace_id aid, const char *name, void **_address,
// modify the pointer returned to be offset back into the new area
// the same way the physical address in was offset
*_address = (void *)((addr_t)*_address + map_offset);
*_address = (void *)((addr_t)*_address + mapOffset);
return area->id;
}
@@ -2750,6 +2755,25 @@ vm_try_reserve_memory(size_t amount)
}
status_t
vm_set_area_memory_type(area_id id, addr_t physicalBase, uint32 type)
{
vm_area *area = vm_get_area(id);
if (area == NULL)
return B_BAD_VALUE;
status_t status = arch_vm_set_memory_type(area, physicalBase, type);
if (status < B_OK)
goto out;
arch_cpu_invalidate_TLB_range(area->base, area->size);
out:
vm_put_area(area);
return status;
}
/** This function enforces some protection properties:
* - if B_WRITE_AREA is set, B_WRITE_KERNEL_AREA is set as well
* - if only B_READ_AREA has been set, B_KERNEL_READ_AREA is also set