1 /* 2 * Copyright 2007, Travis Geiselbrecht. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <commpage.h> 7 8 #include <string.h> 9 10 #include <KernelExport.h> 11 12 #include <elf.h> 13 #include <vm.h> 14 #include <vm_types.h> 15 16 17 static area_id sCommPageArea; 18 static area_id sUserCommPageArea; 19 static addr_t* sCommPageAddress; 20 static addr_t* sUserCommPageAddress; 21 static void* sFreeCommPageSpace; 22 static image_id sCommPageImage; 23 24 25 #define ALIGN_ENTRY(pointer) (void*)ROUNDUP((addr_t)(pointer), 8) 26 27 28 void* 29 allocate_commpage_entry(int entry, size_t size) 30 { 31 void* space = sFreeCommPageSpace; 32 sFreeCommPageSpace = ALIGN_ENTRY((addr_t)sFreeCommPageSpace + size); 33 sCommPageAddress[entry] = (addr_t)sUserCommPageAddress 34 + ((addr_t)space - (addr_t)sCommPageAddress); 35 dprintf("allocate_commpage_entry(%d, %lu) -> %p\n", entry, size, (void*)sCommPageAddress[entry]); 36 return space; 37 } 38 39 40 void* 41 fill_commpage_entry(int entry, const void* copyFrom, size_t size) 42 { 43 void* space = allocate_commpage_entry(entry, size); 44 memcpy(space, copyFrom, size); 45 return space; 46 } 47 48 49 image_id 50 get_commpage_image() 51 { 52 return sCommPageImage; 53 } 54 55 56 status_t 57 commpage_init(void) 58 { 59 // create a read/write kernel area 60 sCommPageArea = create_area("commpage", (void **)&sCommPageAddress, 61 B_ANY_ADDRESS, COMMPAGE_SIZE, B_FULL_LOCK, 62 B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA); 63 64 // clone it at a fixed address with user read/only permissions 65 sUserCommPageAddress = (addr_t*)USER_COMMPAGE_ADDR; 66 sUserCommPageArea = clone_area("user_commpage", 67 (void **)&sUserCommPageAddress, B_EXACT_ADDRESS, 68 B_READ_AREA | B_EXECUTE_AREA, sCommPageArea); 69 70 // zero it out 71 memset(sCommPageAddress, 0, COMMPAGE_SIZE); 72 73 // fill in some of the table 74 sCommPageAddress[0] = COMMPAGE_SIGNATURE; 75 sCommPageAddress[1] = COMMPAGE_VERSION; 76 77 // the next slot to allocate space is after the table 78 sFreeCommPageSpace = ALIGN_ENTRY(&sCommPageAddress[COMMPAGE_TABLE_ENTRIES]); 79 80 // create the image for the commpage 81 sCommPageImage = elf_create_memory_image("commpage", USER_COMMPAGE_ADDR, 82 COMMPAGE_SIZE, 0, 0); 83 elf_add_memory_image_symbol(sCommPageImage, "commpage_table", 84 USER_COMMPAGE_ADDR, COMMPAGE_TABLE_ENTRIES * sizeof(addr_t), 85 B_SYMBOL_TYPE_DATA); 86 87 arch_commpage_init(); 88 89 return B_OK; 90 } 91 92 93 status_t 94 commpage_init_post_cpus(void) 95 { 96 return arch_commpage_init_post_cpus(); 97 } 98