2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Microkernel interface to common profiling.
35 #include <profiling/profile-mk.h>
37 #include <kern/cpu_number.h>
38 #include <kern/processor.h>
40 #include <kern/misc_protos.h>
41 #include <vm/vm_kern.h>
42 #include <mach/vm_param.h>
44 #include <device/ds_routines.h>
45 #include <device/io_req.h>
46 #include <device/buf.h>
48 extern char etext
[], pstart
[];
51 struct profile_vars
*_profile_vars_cpus
[NCPUS
] = { &_profile_vars
};
52 struct profile_vars _profile_vars_aux
[NCPUS
-1];
56 _profile_alloc_pages (size_t size
)
61 * For the MK, we can't support allocating pages at runtime, because we
62 * might be at interrupt level, so abort if we didn't size the table
66 if (PROFILE_VARS(0)->active
) {
67 panic("Call to _profile_alloc_pages while profiling is running.");
70 if (kmem_alloc(kernel_map
, &addr
, size
)) {
71 panic("Could not allocate memory for profiling");
74 memset((void *)addr
, '\0', size
);
75 if (PROFILE_VARS(0)->debug
) {
76 printf("Allocated %d bytes for profiling, address 0x%x\n", (int)size
, (int)addr
);
79 return((caddr_t
)addr
);
83 _profile_free_pages(void *addr
, size_t size
)
85 if (PROFILE_VARS(0)->debug
) {
86 printf("Freed %d bytes for profiling, address 0x%x\n", (int)size
, (int)addr
);
89 kmem_free(kernel_map
, (vm_offset_t
)addr
, size
);
93 void _profile_error(struct profile_vars
*pv
)
95 panic("Fatal error in profiling");
101 prof_uptrint_t textsize
;
102 prof_uptrint_t monsize
;
103 prof_uptrint_t lowpc
;
104 prof_uptrint_t highpc
;
106 struct profile_vars
*pv
;
109 * round lowpc and highpc to multiples of the density we're using
110 * so the rest of the scaling (here and in gprof) stays in ints.
113 lowpc
= ROUNDDOWN((prof_uptrint_t
)&pstart
[0], HISTFRACTION
*sizeof(LHISTCOUNTER
));
114 highpc
= ROUNDUP((prof_uptrint_t
)&etext
[0], HISTFRACTION
*sizeof(LHISTCOUNTER
));
115 textsize
= highpc
- lowpc
;
116 monsize
= (textsize
/ HISTFRACTION
) * sizeof(LHISTCOUNTER
);
118 for (i
= 0; i
< NCPUS
; i
++) {
119 pv
= PROFILE_VARS(i
);
123 _profile_vars_cpus
[i
] = pv
= &_profile_vars_aux
[i
-i
];
130 pv
->page_size
= PAGE_SIZE
;
131 _profile_md_init(pv
, PROFILE_GPROF
, PROFILE_ALLOC_MEM_YES
);
133 /* Profil related variables */
134 pv
->profil_buf
= _profile_alloc (pv
, monsize
, ACONTEXT_PROFIL
);
135 pv
->profil_info
.highpc
= highpc
;
136 pv
->profil_info
.lowpc
= lowpc
;
137 pv
->profil_info
.text_len
= textsize
;
138 pv
->profil_info
.profil_len
= monsize
;
139 pv
->profil_info
.counter_size
= sizeof(LHISTCOUNTER
);
140 pv
->profil_info
.scale
= 0x10000 / HISTFRACTION
;
141 pv
->stats
.profil_buckets
= monsize
/ sizeof(LHISTCOUNTER
);
143 /* Other gprof variables */
144 pv
->stats
.my_cpu
= i
;
145 pv
->stats
.max_cpu
= NCPUS
;
150 pv
->check_funcs
= 1; /* for now */
153 printf("Profiling kernel, s_textsize=%ld, monsize=%ld [0x%lx..0x%lx], cpu = %d\n",
165 /* driver component */
168 gprofprobe(caddr_t port
, void *ctlr
)
180 /* struct bus_device *gprofinfo[NGPROF]; */
181 struct bus_device
*gprofinfo
[1];
183 struct bus_driver gprof_driver
= {
184 gprofprobe
, 0, gprofattach
, 0, 0, "gprof", gprofinfo
, "gprofc", 0, 0};
192 ior
->io_error
= D_SUCCESS
;
197 gprofclose(dev_t dev
)
203 gprofstrategy(io_req_t ior
)
205 void *sys_ptr
= (void *)0;
207 long count
= _profile_kgmon(!(ior
->io_op
& IO_READ
),
212 (void (*)(kgmon_control_t
))0);
215 ior
->io_error
= D_INVALID_RECNUM
;
218 if (count
> 0 && sys_ptr
!= (void *)0) {
219 if (ior
->io_op
& IO_READ
) {
220 memcpy((void *)ior
->io_data
, sys_ptr
, count
);
222 memcpy(sys_ptr
, (void *)ior
->io_data
, count
);
226 ior
->io_error
= D_SUCCESS
;
227 ior
->io_residual
= ior
->io_count
- count
;
237 return(block_io(gprofstrategy
, minphys
, ior
));
241 gprofwrite(dev_t dev
,
244 return (block_io(gprofstrategy
, minphys
, ior
));