xref: /haiku/src/system/kernel/commpage.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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