1 /*
2 * smp.c: Secondary processor bringup and initialisation.
3 *
4 * Copyright (c) 2008, Citrix Systems, Inc.
5 *
6 * Authors:
7 * Keir Fraser <keir@xen.org>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "util.h"
23 #include "config.h"
24 #include "apic_regs.h"
25 #include "hypercall.h"
26
27 #include <xen/asm/x86-defns.h>
28 #include <xen/hvm/hvm_vcpu.h>
29
30 #include <xen/vcpu.h>
31
32 static int ap_callin;
33
cpu_setup(unsigned int cpu)34 static void __attribute__((regparm(1))) cpu_setup(unsigned int cpu)
35 {
36 printf(" - CPU%d ... ", cpu);
37 cacheattr_init();
38 printf("done.\n");
39
40 if ( !cpu ) /* Used on the BSP too */
41 return;
42
43 wmb();
44 ap_callin = 1;
45
46 /* After this point, the BSP will shut us down. */
47
48 for ( ;; )
49 asm volatile ( "hlt" );
50 }
51
boot_cpu(unsigned int cpu)52 static void boot_cpu(unsigned int cpu)
53 {
54 static uint8_t ap_stack[PAGE_SIZE] __attribute__ ((aligned (16)));
55 static struct vcpu_hvm_context ap;
56
57 /* Initialise shared variables. */
58 ap_callin = 0;
59 wmb();
60
61 /* Wake up the secondary processor */
62 ap = (struct vcpu_hvm_context) {
63 .mode = VCPU_HVM_MODE_32B,
64 .cpu_regs.x86_32 = {
65 .eip = (unsigned long)cpu_setup,
66 .esp = (unsigned long)ap_stack + ARRAY_SIZE(ap_stack),
67
68 .eax = cpu,
69
70 /* Protected Mode, no paging. */
71 .cr0 = X86_CR0_PE,
72
73 /* 32bit Flat Mode */
74 .cs_limit = -1U,
75 .ds_limit = -1U,
76 .ss_limit = -1U,
77 .es_limit = -1U,
78 .tr_limit = 0x67,
79 .cs_ar = 0xc9b,
80 .ds_ar = 0xc93,
81 .es_ar = 0xc93,
82 .ss_ar = 0xc93,
83 .tr_ar = 0x8b,
84 },
85 };
86
87 if ( hypercall_vcpu_op(VCPUOP_initialise, cpu, &ap) )
88 BUG();
89 if ( hypercall_vcpu_op(VCPUOP_up, cpu, NULL) )
90 BUG();
91
92 /*
93 * Wait for the secondary processor to complete initialisation.
94 * Do not touch shared resources meanwhile.
95 */
96 while ( !ap_callin )
97 cpu_relax();
98
99 /* Take the secondary processor offline. */
100 if ( hypercall_vcpu_op(VCPUOP_down, cpu, NULL) )
101 BUG();
102 }
103
smp_initialise(void)104 void smp_initialise(void)
105 {
106 unsigned int i, nr_cpus = hvm_info->nr_vcpus;
107
108 printf("Multiprocessor initialisation:\n");
109 cpu_setup(0);
110 for ( i = 1; i < nr_cpus; i++ )
111 boot_cpu(i);
112 }
113
114 /*
115 * Local variables:
116 * mode: C
117 * c-file-style: "BSD"
118 * c-basic-offset: 4
119 * tab-width: 4
120 * indent-tabs-mode: nil
121 * End:
122 */
123