aboutsummaryrefslogtreecommitdiffstats
path: root/testhal/STM32F37x/SPI/chconf.h
blob: ead2c1de859c5c5f2143b6df1eb861b5d00a2bc2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
/*
    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/**
 * @file    templates/chconf.h
 * @brief   Configuration file template.
 * @details A copy of this file must be placed in each project directory, it
 *          contains the application specific kernel settings.
 *
 * @addtogroup config
 * @details Kernel related settings and hooks.
 * @{
 */

#ifndef _CHCONF_H_
#define _CHCONF_H_

/*===========================================================================*/
/**
 * @name System timers settings
 * @{
 */
/*===========================================================================*/

/**
 * @brief   System time counter resolution.
 * @note    Allowed values are 16 or 32 bits.
 */
#define CH_CFG_ST_RESOLUTION                32

/**
 * @brief   System tick frequency.
 * @details Frequency of the system timer that drives the system ticks. This
 *          setting also defines the system tick time unit.
 */
#define CH_CFG_ST_FREQUENCY                 10000

/**
 * @brief   Time delta constant for the tick-less mode.
 * @note    If this value is zero then the system uses the classic
 *          periodic tick. This value represents the minimum number
 *          of ticks that is safe to specify in a timeout directive.
 *          The value one is not valid, timeouts are rounded up to
 *          this value.
 */
#define CH_CFG_ST_TIMEDELTA                 2

/**
 * @brief   Realtime Counter frequency.
 * @details Frequency of the system counter used for realtime delays and
 *          measurements.
 */
#define CH_CFG_RTC_FREQUENCY                72000000

/** @} */

/*===========================================================================*/
/**
 * @name Kernel parameters and options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Round robin interval.
 * @details This constant is the number of system ticks allowed for the
 *          threads before preemption occurs. Setting this value to zero
 *          disables the preemption for threads with equal priority and the
 *          round robin becomes cooperative. Note that higher priority
 *          threads can still preempt, the kernel is always preemptive.
 * @note    Disabling the round robin preemption makes the kernel more compact
 *          and generally faster.
 * @note    The round robin preemption is not supported in tickless mode and
 *          must be set to zero in that case.
 */
#define CH_CFG_TIME_QUANTUM                 0

/**
 * @brief   Managed RAM size.
 * @details Size of the RAM area to be managed by the OS. If set to zero
 *          then the whole available RAM is used. The core memory is made
 *          available to the heap allocator and/or can be used directly through
 *          the simplified core memory allocator.
 *
 * @note    In order to let the OS manage the whole RAM the linker script must
 *          provide the @p __heap_base__ and @p __heap_end__ symbols.
 * @note    Requires @p CH_CFG_USE_MEMCORE.
 */
#define CH_CFG_MEMCORE_SIZE                 0

/**
 * @brief   Idle thread automatic spawn suppression.
 * @details When this option is activated the function @p chSysInit()
 *          does not spawn the idle thread. The application @p main()
 *          function becomes the idle thread and must implement an
 *          infinite loop. */
#define CH_CFG_NO_IDLE_THREAD               FALSE

/** @} */

/*===========================================================================*/
/**
 * @name Performance options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   OS optimization.
 * @details If enabled then time efficient rather than space efficient code
 *          is used when two possible implementations exist.
 *
 * @note    This is not related to the compiler optimization options.
 * @note    The default is @p TRUE.
 */
#define CH_CFG_OPTIMIZE_SPEED               TRUE

/** @} */

/*===========================================================================*/
/**
 * @name Subsystem options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Time Measurement APIs.
 * @details If enabled then the time measurement APIs are included in
 *          the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_TM                       TRUE

/**
 * @brief   Threads registry APIs.
 * @details If enabled then the registry APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_REGISTRY                 TRUE

/**
 * @brief   Threads synchronization APIs.
 * @details If enabled then the @p chThdWait() function is included in
 *          the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_WAITEXIT                 TRUE

/**
 * @brief   Semaphores APIs.
 * @details If enabled then the Semaphores APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_SEMAPHORES               TRUE

/**
 * @brief   Semaphores queuing mode.
 * @details If enabled then the threads are enqueued on semaphores by
 *          priority rather than in FIFO order.
 *
 * @note    The default is @p FALSE. Enable this if you have special
 *          requirements.
 * @note    Requires @p CH_CFG_USE_SEMAPHORES.
 */
#define CH_CFG_USE_SEMAPHORES_PRIORITY      FALSE

/**
 * @brief   Mutexes APIs.
 * @details If enabled then the mutexes APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_MUTEXES                  TRUE

/**
 * @brief   Conditional Variables APIs.
 * @details If enabled then the conditional variables APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_MUTEXES.
 */
#define CH_CFG_USE_CONDVARS                 TRUE

/**
 * @brief   Conditional Variables APIs with timeout.
 * @details If enabled then the conditional variables APIs with timeout
 *          specification are included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_CONDVARS.
 */
#define CH_CFG_USE_CONDVARS_TIMEOUT         TRUE

/**
 * @brief   Events Flags APIs.
 * @details If enabled then the event flags APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_EVENTS                   TRUE

/**
 * @brief   Events Flags APIs with timeout.
 * @details If enabled then the events APIs with timeout specification
 *          are included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_EVENTS.
 */
#define CH_CFG_USE_EVENTS_TIMEOUT           TRUE

/**
 * @brief   Synchronous Messages APIs.
 * @details If enabled then the synchronous messages APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_MESSAGES                 TRUE

/**
 * @brief   Synchronous Messages queuing mode.
 * @details If enabled then messages are served by priority rather than in
 *          FIFO order.
 *
 * @note    The default is @p FALSE. Enable this if you have special
 *          requirements.
 * @note    Requires @p CH_CFG_USE_MESSAGES.
 */
#define CH_CFG_USE_MESSAGES_PRIORITY        FALSE

/**
 * @brief   Mailboxes APIs.
 * @details If enabled then the asynchronous messages (mailboxes) APIs are
 *          included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_SEMAPHORES.
 */
#define CH_CFG_USE_MAILBOXES                TRUE

/**
 * @brief   I/O Queues APIs.
 * @details If enabled then the I/O queues APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_QUEUES                   TRUE

/**
 * @brief   Core Memory Manager APIs.
 * @details If enabled then the core memory manager APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_MEMCORE                  TRUE

/**
 * @brief   Heap Allocator APIs.
 * @details If enabled then the memory heap allocator APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
 *          @p CH_CFG_USE_SEMAPHORES.
 * @note    Mutexes are recommended.
 */
#define CH_CFG_USE_HEAP                     TRUE

/**
 * @brief   Memory Pools Allocator APIs.
 * @details If enabled then the memory pools allocator APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_MEMPOOLS                 TRUE

/**
 * @brief   Dynamic Threads APIs.
 * @details If enabled then the dynamic threads creation APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_WAITEXIT.
 * @note    Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
 */
#define CH_CFG_USE_DYNAMIC                  TRUE

/** @} */

/*===========================================================================*/
/**
 * @name Debug options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Debug option, kernel statistics.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_STATISTICS                   TRUE

/**
 * @brief   Debug option, system state check.
 * @details If enabled the correct call protocol for system APIs is checked
 *          at runtime.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_SYSTEM_STATE_CHECK           TRUE

/**
 * @brief   Debug option, parameters checks.
 * @details If enabled then the checks on the API functions input
 *          parameters are activated.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_ENABLE_CHECKS                TRUE

/**
 * @brief   Debug option, consistency checks.
 * @details If enabled then all the assertions in the kernel code are
 *          activated. This includes consistency checks inside the kernel,
 *          runtime anomalies and port-defined checks.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_ENABLE_ASSERTS               TRUE

/**
 * @brief   Debug option, trace buffer.
 * @details If enabled then the context switch circular trace buffer is
 *          activated.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_ENABLE_TRACE                 TRUE

/**
 * @brief   Debug option, stack checks.
 * @details If enabled then a runtime stack check is performed.
 *
 * @note    The default is @p FALSE.
 * @note    The stack check is performed in a architecture/port dependent way.
 *          It may not be implemented or some ports.
 * @note    The default failure mode is to halt the system with the global
 *          @p panic_msg variable set to @p NULL.
 */
#define CH_DBG_ENABLE_STACK_CHECK           TRUE

/**
 * @brief   Debug option, stacks initialization.
 * @details If enabled then the threads working area is filled with a byte
 *          value when a thread is created. This can be useful for the
 *          runtime measurement of the used stack.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_FILL_THREADS                 TRUE

/**
 * @brief   Debug option, threads profiling.
 * @details If enabled then a field is added to the @p thread_t structure that
 *          counts the system ticks occurred while executing the thread.
 *
 * @note    The default is @p FALSE.
 * @note    This debug option is not currently compatible with the
 *          tickless mode.
 */
#define CH_DBG_THREADS_PROFILING            FALSE

/** @} */

/*===========================================================================*/
/**
 * @name Kernel hooks
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Threads descriptor structure extension.
 * @details User fields added to the end of the @p thread_t structure.
 */
#define CH_CFG_THREAD_EXTRA_FIELDS                                          \
  /* Add threads custom fields here.*/

/**
 * @brief   Threads initialization hook.
 * @details User initialization code added to the @p chThdInit() API.
 *
 * @note    It is invoked from within @p chThdInit() and implicitly from all
 *          the threads creation APIs.
 */
#define CH_CFG_THREAD_INIT_HOOK(tp) {                                       \
  /* Add threads initialization code here.*/                                \
}

/**
 * @brief   Threads finalization hook.
 * @details User finalization code added to the @p chThdExit() API.
 *
 * @note    It is inserted into lock zone.
 * @note    It is also invoked when the threads simply return in order to
 *          terminate.
 */
#define CH_CFG_THREAD_EXIT_HOOK(tp) {                                       \
  /* Add threads finalization code here.*/                                  \
}

/**
 * @brief   Context switch hook.
 * @details This hook is invoked just before switching between threads.
 */
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) {                              \
  /* System halt code here.*/                                               \
}

/**
 * @brief   Idle thread enter hook.
 * @note    This hook is invoked within a critical zone, no OS functions
 *          should be invoked from here.
 * @note    This macro can be used to activate a power saving mode.
 */
#define CH_CFG_IDLE_ENTER_HOOK() {                                         \
}

/**
 * @brief   Idle thread leave hook.
 * @note    This hook is invoked within a critical zone, no OS functions
 *          should be invoked from here.
 * @note    This macro can be used to deactivate a power saving mode.
 */
#define CH_CFG_IDLE_LEAVE_HOOK() {                                         \
}

/**
 * @brief   Idle Loop hook.
 * @details This hook is continuously invoked by the idle thread loop.
 */
#define CH_CFG_IDLE_LOOP_HOOK() {                                           \
  /* Idle loop code here.*/                                                 \
}

/**
 * @brief   System tick event hook.
 * @details This hook is invoked in the system tick handler immediately
 *          after processing the virtual timers queue.
 */
#define CH_CFG_SYSTEM_TICK_HOOK() {                                         \
  /* System tick event code here.*/                                         \
}

/**
 * @brief   System halt hook.
 * @details This hook is invoked in case to a system halting error before
 *          the system is halted.
 */
#define CH_CFG_SYSTEM_HALT_HOOK(reason) {                                   \
  /* System halt code here.*/                                               \
}

/** @} */

/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h).    */
/*===========================================================================*/

#endif  /* _CHCONF_H_ */

/** @} */
s="p">} else if ( !strcmp(s, "ht") ) { if ( !acpi_force ) disable_acpi(); acpi_ht = 1; } else if ( !strcmp(s, "noirq") ) { acpi_noirq_set(); } } static void __init do_initcalls(void) { initcall_t *call; for ( call = &__initcall_start; call < &__initcall_end; call++ ) (*call)(); } #define EARLY_FAIL() for ( ; ; ) __asm__ __volatile__ ( "hlt" ) static struct e820entry e820_raw[E820MAX]; static unsigned long initial_images_start, initial_images_end; unsigned long initial_images_nrpages(void) { unsigned long s = initial_images_start + PAGE_SIZE - 1; unsigned long e = initial_images_end; return ((e >> PAGE_SHIFT) - (s >> PAGE_SHIFT)); } void discard_initial_images(void) { init_domheap_pages(initial_images_start, initial_images_end); } extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[]; static void __init percpu_init_areas(void) { unsigned int i, data_size = __per_cpu_data_end - __per_cpu_start; BUG_ON(data_size > PERCPU_SIZE); for_each_cpu ( i ) { memguard_unguard_range(__per_cpu_start + (i << PERCPU_SHIFT), 1 << PERCPU_SHIFT); if ( i != 0 ) memcpy(__per_cpu_start + (i << PERCPU_SHIFT), __per_cpu_start, data_size); } } static void __init percpu_guard_areas(void) { memguard_guard_range(__per_cpu_start, __per_cpu_end - __per_cpu_start); } static void __init percpu_free_unused_areas(void) { unsigned int i, first_unused; /* Find first unused CPU number. */ for ( i = 0; i < NR_CPUS; i++ ) if ( !cpu_possible(i) ) break; first_unused = i; /* Check that there are no holes in cpu_possible_map. */ for ( ; i < NR_CPUS; i++ ) BUG_ON(cpu_possible(i)); #ifndef MEMORY_GUARD init_xenheap_pages(__pa(__per_cpu_start) + (first_unused << PERCPU_SHIFT), __pa(__per_cpu_end)); #endif } /* Fetch acm policy module from multiboot modules. */ static void extract_acm_policy( multiboot_info_t *mbi, unsigned int *initrdidx, char **_policy_start, unsigned long *_policy_len) { int i; module_t *mod = (module_t *)__va(mbi->mods_addr); unsigned long start, policy_len; char *policy_start; /* * Try all modules and see whichever could be the binary policy. * Adjust the initrdidx if module[1] is the binary policy. */ for ( i = mbi->mods_count-1; i >= 1; i-- ) { start = initial_images_start + (mod[i].mod_start-mod[0].mod_start); #if defined(__i386__) policy_start = (char *)start; #elif defined(__x86_64__) policy_start = __va(start); #endif policy_len = mod[i].mod_end - mod[i].mod_start; if ( acm_is_policy(policy_start, policy_len) ) { printk("Policy len 0x%lx, start at %p - module %d.\n", policy_len, policy_start, i); *_policy_start = policy_start; *_policy_len = policy_len; if ( i == 1 ) *initrdidx = (mbi->mods_count > 2) ? 2 : 0; break; } } } static void __init init_idle_domain(void) { struct domain *idle_domain; /* Domain creation requires that scheduler structures are initialised. */ scheduler_init(); idle_domain = domain_create(IDLE_DOMAIN_ID, 0); if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) ) BUG(); set_current(idle_domain->vcpu[0]); idle_vcpu[0] = this_cpu(curr_vcpu) = current; setup_idle_pagetable(); } static void srat_detect_node(int cpu) { unsigned node; u8 apicid = x86_cpu_to_apicid[cpu]; node = apicid_to_node[apicid]; if ( node == NUMA_NO_NODE ) node = 0; numa_set_node(cpu, node); if ( acpi_numa > 0 ) printk(KERN_INFO "CPU %d APIC %d -> Node %d\n", cpu, apicid, node); } void __init move_memory(unsigned long dst, unsigned long src_start, unsigned long src_end) { #if defined(CONFIG_X86_32) memmove((void *)dst, /* use low mapping */ (void *)src_start, /* use low mapping */ src_end - src_start); #elif defined(CONFIG_X86_64) memmove(__va(dst), __va(src_start), src_end - src_start); #endif } void __init __start_xen(multiboot_info_t *mbi) { char __cmdline[] = "", *cmdline = __cmdline; unsigned long _initrd_start = 0, _initrd_len = 0; unsigned int initrdidx = 1; char *_policy_start = NULL; unsigned long _policy_len = 0; module_t *mod = (module_t *)__va(mbi->mods_addr); unsigned long nr_pages, modules_length; paddr_t s, e; int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0; struct ns16550_defaults ns16550 = { .data_bits = 8, .parity = 'n', .stop_bits = 1 }; extern void early_page_fault(void); set_intr_gate(TRAP_page_fault, &early_page_fault); /* Parse the command-line options. */ if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) ) cmdline = __va(mbi->cmdline); cmdline_parse(cmdline); set_current((struct vcpu *)0xfffff000); /* debug sanity */ idle_vcpu[0] = current; set_processor_id(0); /* needed early, for smp_processor_id() */ smp_prepare_boot_cpu(); /* We initialise the serial devices very early so we can get debugging. */ ns16550.io_base = 0x3f8; ns16550.irq = 4; ns16550_init(0, &ns16550); ns16550.io_base = 0x2f8; ns16550.irq = 3; ns16550_init(1, &ns16550); serial_init_preirq(); init_console(); printk("Command line: %s\n", cmdline); /* Check that we have at least one Multiboot module. */ if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) ) { printk("FATAL ERROR: dom0 kernel not specified." " Check bootloader configuration.\n"); EARLY_FAIL(); } if ( ((unsigned long)cpu0_stack & (STACK_SIZE-1)) != 0 ) { printk("FATAL ERROR: Misaligned CPU0 stack.\n"); EARLY_FAIL(); } /* * Since there are some stubs getting built on the stacks which use * direct calls/jumps, the heap must be confined to the lower 2G so * that those branches can reach their targets. */ if ( opt_xenheap_megabytes > 2048 ) opt_xenheap_megabytes = 2048; xenheap_phys_end = opt_xenheap_megabytes << 20; if ( mbi->flags & MBI_MEMMAP ) { while ( bytes < mbi->mmap_length ) { memory_map_t *map = __va(mbi->mmap_addr + bytes); /* * This is a gross workaround for a BIOS bug. Some bootloaders do * not write e820 map entries into pre-zeroed memory. This is * okay if the BIOS fills in all fields of the map entry, but * some broken BIOSes do not bother to write the high word of * the length field if the length is smaller than 4GB. We * detect and fix this by flagging sections below 4GB that * appear to be larger than 4GB in size. */ if ( (map->base_addr_high == 0) && (map->length_high != 0) ) { e820_warn = 1; map->length_high = 0; } e820_raw[e820_raw_nr].addr = ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low; e820_raw[e820_raw_nr].size = ((u64)map->length_high << 32) | (u64)map->length_low; e820_raw[e820_raw_nr].type = (map->type > E820_NVS) ? E820_RESERVED : map->type; e820_raw_nr++; bytes += map->size + 4; } } else if ( mbi->flags & MBI_MEMLIMITS ) { e820_raw[0].addr = 0; e820_raw[0].size = mbi->mem_lower << 10; e820_raw[0].type = E820_RAM; e820_raw[1].addr = 0x100000; e820_raw[1].size = mbi->mem_upper << 10; e820_raw[1].type = E820_RAM; e820_raw_nr = 2; } else { printk("FATAL ERROR: Bootloader provided no memory information.\n"); for ( ; ; ) ; } if ( e820_warn ) printk("WARNING: Buggy e820 map detected and fixed " "(truncated length fields).\n"); /* Ensure that all E820 RAM regions are page-aligned and -sized. */ for ( i = 0; i < e820_raw_nr; i++ ) { uint64_t s, e; if ( e820_raw[i].type != E820_RAM ) continue; s = PFN_UP(e820_raw[i].addr); e = PFN_DOWN(e820_raw[i].addr + e820_raw[i].size); e820_raw[i].size = 0; /* discarded later */ if ( s < e ) { e820_raw[i].addr = s << PAGE_SHIFT; e820_raw[i].size = (e - s) << PAGE_SHIFT; } } /* Sanitise the raw E820 map to produce a final clean version. */ max_page = init_e820(e820_raw, &e820_raw_nr); modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start; /* Find a large enough RAM extent to stash the DOM0 modules. */ for ( i = 0; ; i++ ) { if ( i == e820.nr_map ) { printk("Not enough memory to stash the DOM0 kernel image.\n"); for ( ; ; ) ; } if ( (e820.map[i].type == E820_RAM) && (e820.map[i].size >= modules_length) && ((e820.map[i].addr + e820.map[i].size) >= (xenheap_phys_end + modules_length)) ) break; } /* Stash as near as possible to the beginning of the RAM extent. */ initial_images_start = e820.map[i].addr; if ( initial_images_start < xenheap_phys_end ) initial_images_start = xenheap_phys_end; initial_images_end = initial_images_start + modules_length; move_memory(initial_images_start, mod[0].mod_start, mod[mbi->mods_count-1].mod_end); /* Initialise boot-time allocator with all RAM situated after modules. */ xenheap_phys_start = init_boot_allocator(__pa(&_end)); nr_pages = 0; for ( i = 0; i < e820.nr_map; i++ ) { if ( e820.map[i].type != E820_RAM ) continue; nr_pages += e820.map[i].size >> PAGE_SHIFT; /* Initialise boot heap, skipping Xen heap and dom0 modules. */ s = e820.map[i].addr; e = s + e820.map[i].size; if ( s < xenheap_phys_end ) s = xenheap_phys_end; if ( (s < initial_images_end) && (e > initial_images_start) ) s = initial_images_end; init_boot_pages(s, e); #if defined(CONFIG_X86_64) /* * x86/64 maps all registered RAM. Points to note: * 1. The initial pagetable already maps low 1GB, so skip that. * 2. We must map *only* RAM areas, taking care to avoid I/O holes. * Failure to do this can cause coherency problems and deadlocks * due to cache-attribute mismatches (e.g., AMD/AGP Linux bug). */ { /* Calculate page-frame range, discarding partial frames. */ unsigned long start, end; unsigned long init_mapped = 1UL << (30 - PAGE_SHIFT); /* 1GB */ start = PFN_UP(e820.map[i].addr); end = PFN_DOWN(e820.map[i].addr + e820.map[i].size); /* Clip the range to exclude what the bootstrapper initialised. */ if ( start < init_mapped ) start = init_mapped; if ( end <= start ) continue; /* Request the mapping. */ map_pages_to_xen( PAGE_OFFSET + (start << PAGE_SHIFT), start, end-start, PAGE_HYPERVISOR); } #endif } if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0) { unsigned long kdump_start, kdump_size, k; /* Mark images pages as free for now. */ init_boot_pages(initial_images_start, initial_images_end); kdump_start = kexec_crash_area.start; kdump_size = kexec_crash_area.size; printk("Kdump: %luMB (%lukB) at 0x%lx\n", kdump_size >> 20, kdump_size >> 10, kdump_start); if ( (kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK) ) panic("Kdump parameters not page aligned\n"); kdump_start >>= PAGE_SHIFT; kdump_size >>= PAGE_SHIFT; /* Allocate pages for Kdump memory area. */ if ( !reserve_boot_pages(kdump_start, kdump_size) ) panic("Unable to reserve Kdump memory\n"); /* Allocate pages for relocated initial images. */ k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0; k += (initial_images_end - initial_images_start) >> PAGE_SHIFT; #if defined(CONFIG_X86_32) /* Must allocate within bootstrap 1:1 limits. */ k = alloc_boot_low_pages(k, 1); /* 0x0 - HYPERVISOR_VIRT_START */ #else k = alloc_boot_pages(k, 1); #endif if ( k == 0 ) panic("Unable to allocate initial images memory\n"); move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end); initial_images_end -= initial_images_start; initial_images_start = k << PAGE_SHIFT; initial_images_end += initial_images_start; } memguard_init(); percpu_guard_areas(); printk("System RAM: %luMB (%lukB)\n", nr_pages >> (20 - PAGE_SHIFT), nr_pages << (PAGE_SHIFT - 10)); total_pages = nr_pages; /* Sanity check for unwanted bloat of certain hypercall structures. */ BUILD_BUG_ON(sizeof(((struct xen_platform_op *)0)->u) != sizeof(((struct xen_platform_op *)0)->u.pad)); BUILD_BUG_ON(sizeof(((struct xen_domctl *)0)->u) != sizeof(((struct xen_domctl *)0)->u.pad)); BUILD_BUG_ON(sizeof(((struct xen_sysctl *)0)->u) != sizeof(((struct xen_sysctl *)0)->u.pad)); BUILD_BUG_ON(sizeof(start_info_t) > PAGE_SIZE); BUILD_BUG_ON(sizeof(shared_info_t) > PAGE_SIZE); BUILD_BUG_ON(sizeof(struct vcpu_info) != 64); #ifdef CONFIG_COMPAT BUILD_BUG_ON(sizeof(((struct compat_platform_op *)0)->u) != sizeof(((struct compat_platform_op *)0)->u.pad)); BUILD_BUG_ON(sizeof(start_info_compat_t) > PAGE_SIZE); BUILD_BUG_ON(sizeof(struct compat_vcpu_info) != 64); #endif /* Check definitions in public headers match internal defs. */ BUILD_BUG_ON(__HYPERVISOR_VIRT_START != HYPERVISOR_VIRT_START); #ifdef HYPERVISOR_VIRT_END BUILD_BUG_ON(__HYPERVISOR_VIRT_END != HYPERVISOR_VIRT_END); #endif BUILD_BUG_ON(MACH2PHYS_VIRT_START != RO_MPT_VIRT_START); BUILD_BUG_ON(MACH2PHYS_VIRT_END != RO_MPT_VIRT_END); init_frametable(); acpi_boot_table_init(); acpi_numa_init(); numa_initmem_init(0, max_page); end_boot_allocator(); /* Initialise the Xen heap, skipping RAM holes. */ nr_pages = 0; for ( i = 0; i < e820.nr_map; i++ ) { if ( e820.map[i].type != E820_RAM ) continue; s = e820.map[i].addr; e = s + e820.map[i].size; if ( s < xenheap_phys_start ) s = xenheap_phys_start; if ( e > xenheap_phys_end ) e = xenheap_phys_end; if ( s < e ) { nr_pages += (e - s) >> PAGE_SHIFT; init_xenheap_pages(s, e); } } printk("Xen heap: %luMB (%lukB)\n", nr_pages >> (20 - PAGE_SHIFT), nr_pages << (PAGE_SHIFT - 10)); early_boot = 0; early_cpu_init(); paging_init(); /* Unmap the first page of CPU0's stack. */ memguard_guard_stack(cpu0_stack); open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period); if ( opt_watchdog ) nmi_watchdog = NMI_LOCAL_APIC; sort_exception_tables(); find_smp_config(); smp_alloc_memory(); dmi_scan_machine(); generic_apic_probe(); acpi_boot_init(); init_cpu_to_node(); if ( smp_found_config ) get_smp_config(); init_apic_mappings(); init_IRQ(); percpu_init_areas(); init_idle_domain(); trap_init(); rcu_init(); timer_init(); early_time_init(); arch_init_memory(); identify_cpu(&boot_cpu_data); if ( cpu_has_fxsr ) set_in_cr4(X86_CR4_OSFXSR); if ( cpu_has_xmm ) set_in_cr4(X86_CR4_OSXMMEXCPT); if ( opt_nosmp ) max_cpus = 0; smp_prepare_cpus(max_cpus); /* * Initialise higher-level timer functions. We do this fairly late * (post-SMP) because the time bases and scale factors need to be updated * regularly, and SMP initialisation can cause a long delay with * interrupts not yet enabled. */ init_xen_time(); initialize_keytable(); serial_init_postirq(); BUG_ON(!local_irq_is_enabled()); for_each_present_cpu ( i ) { if ( num_online_cpus() >= max_cpus ) break; if ( !cpu_online(i) ) { rcu_online_cpu(i); __cpu_up(i); } /* Set up cpu_to_node[]. */ srat_detect_node(i); /* Set up node_to_cpumask based on cpu_to_node[]. */ numa_add_cpu(i); } printk("Brought up %ld CPUs\n", (long)num_online_cpus()); smp_cpus_done(max_cpus); percpu_free_unused_areas(); initialise_gdb(); /* could be moved earlier */ do_initcalls(); if ( opt_watchdog ) watchdog_enable(); /* Extract policy from multiboot. */ extract_acm_policy(mbi, &initrdidx, &_policy_start, &_policy_len); /* initialize access control security module */ acm_init(_policy_start, _policy_len); /* Create initial domain 0. */ dom0 = domain_create(0, 0); if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) ) panic("Error creating domain 0\n"); dom0->is_privileged = 1; /* Post-create hook sets security label. */ acm_post_domain0_create(dom0->domain_id); /* Grab the DOM0 command line. */ cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL); if ( cmdline != NULL ) { static char dom0_cmdline[MAX_GUEST_CMDLINE]; /* Skip past the image name and copy to a local buffer. */ while ( *cmdline == ' ' ) cmdline++; if ( (cmdline = strchr(cmdline, ' ')) != NULL ) { while ( *cmdline == ' ' ) cmdline++; safe_strcpy(dom0_cmdline, cmdline); } /* Append any extra parameters. */ if ( skip_ioapic_setup && !strstr(dom0_cmdline, "noapic") ) safe_strcat(dom0_cmdline, " noapic"); if ( acpi_skip_timer_override && !strstr(dom0_cmdline, "acpi_skip_timer_override") ) safe_strcat(dom0_cmdline, " acpi_skip_timer_override"); if ( (strlen(acpi_param) != 0) && !strstr(dom0_cmdline, "acpi=") ) { safe_strcat(dom0_cmdline, " acpi="); safe_strcat(dom0_cmdline, acpi_param); } cmdline = dom0_cmdline; } if ( (initrdidx > 0) && (initrdidx < mbi->mods_count) ) { _initrd_start = initial_images_start + (mod[initrdidx].mod_start - mod[0].mod_start); _initrd_len = mod[initrdidx].mod_end - mod[initrdidx].mod_start; } /* * We're going to setup domain0 using the module(s) that we stashed safely * above our heap. The second module, if present, is an initrd ramdisk. */ if ( construct_dom0(dom0, initial_images_start, mod[0].mod_end-mod[0].mod_start, _initrd_start, _initrd_len, cmdline) != 0) panic("Could not set up DOM0 guest OS\n"); /* Scrub RAM that is still free and so may go to an unprivileged domain. */ scrub_heap_pages(); init_trace_bufs(); console_endboot(); /* Hide UART from DOM0 if we're using it */ serial_endboot(); domain_unpause_by_systemcontroller(dom0); startup_cpu_idle_loop(); } void arch_get_xen_caps(xen_capabilities_info_t *info) { int major = xen_major_version(); int minor = xen_minor_version(); char s[32]; (*info)[0] = '\0'; #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE) snprintf(s, sizeof(s), "xen-%d.%d-x86_32 ", major, minor); safe_strcat(*info, s); if ( hvm_enabled ) { snprintf(s, sizeof(s), "hvm-%d.%d-x86_32 ", major, minor); safe_strcat(*info, s); } #elif defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE) snprintf(s, sizeof(s), "xen-%d.%d-x86_32p ", major, minor); safe_strcat(*info, s); if ( hvm_enabled ) { snprintf(s, sizeof(s), "hvm-%d.%d-x86_32 ", major, minor); safe_strcat(*info, s); snprintf(s, sizeof(s), "hvm-%d.%d-x86_32p ", major, minor); safe_strcat(*info, s); } #elif defined(CONFIG_X86_64) snprintf(s, sizeof(s), "xen-%d.%d-x86_64 ", major, minor); safe_strcat(*info, s); #ifdef CONFIG_COMPAT snprintf(s, sizeof(s), "xen-%d.%d-x86_32p ", major, minor); safe_strcat(*info, s); #endif if ( hvm_enabled ) { snprintf(s, sizeof(s), "hvm-%d.%d-x86_32 ", major, minor); safe_strcat(*info, s); snprintf(s, sizeof(s), "hvm-%d.%d-x86_32p ", major, minor); safe_strcat(*info, s); snprintf(s, sizeof(s), "hvm-%d.%d-x86_64 ", major, minor); safe_strcat(*info, s); } #endif } /* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */