~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/firmware/hvmloader/smp.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * smp.c: Secondary processor bringup and initialisation.
 
3
 *
 
4
 * Copyright (c) 2008, Citrix Systems, Inc.
 
5
 * 
 
6
 * Authors:
 
7
 *    Keir Fraser <keir.fraser@citrix.com>
 
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, write to the Free Software Foundation, Inc., 59 Temple
 
20
 * Place - Suite 330, Boston, MA 02111-1307 USA.
 
21
 */
 
22
 
 
23
#include "util.h"
 
24
#include "config.h"
 
25
#include "apic_regs.h"
 
26
 
 
27
#define AP_BOOT_EIP 0x1000
 
28
extern char ap_boot_start[], ap_boot_end[];
 
29
 
 
30
static int ap_callin, ap_cpuid;
 
31
 
 
32
asm (
 
33
    "    .text                       \n"
 
34
    "    .code16                     \n"
 
35
    "ap_boot_start: .code16          \n"
 
36
    "    mov   %cs,%ax               \n"
 
37
    "    mov   %ax,%ds               \n"
 
38
    "    lgdt  gdt_desr-ap_boot_start\n"
 
39
    "    xor   %ax, %ax              \n"
 
40
    "    inc   %ax                   \n"
 
41
    "    lmsw  %ax                   \n"
 
42
    "    ljmpl $0x08,$1f             \n"
 
43
    "gdt_desr:                       \n"
 
44
    "    .word gdt_end - gdt - 1     \n"
 
45
    "    .long gdt                   \n"
 
46
    "ap_boot_end: .code32            \n"
 
47
    "1:  mov   $0x10,%eax            \n"
 
48
    "    mov   %eax,%ds              \n"
 
49
    "    mov   %eax,%es              \n"
 
50
    "    mov   %eax,%ss              \n"
 
51
    "    movl  $stack_top,%esp       \n"
 
52
    "    movl  %esp,%ebp             \n"
 
53
    "    call  ap_start              \n"
 
54
    "1:  hlt                         \n"
 
55
    "    jmp  1b                     \n"
 
56
    "                                \n"
 
57
    "    .align 8                    \n"
 
58
    "gdt:                            \n"
 
59
    "    .quad 0x0000000000000000    \n"
 
60
    "    .quad 0x00cf9a000000ffff    \n" /* 0x08: Flat code segment */
 
61
    "    .quad 0x00cf92000000ffff    \n" /* 0x10: Flat data segment */
 
62
    "gdt_end:                        \n"
 
63
    "                                \n"
 
64
    "    .bss                        \n"
 
65
    "    .align    8                 \n"
 
66
    "stack:                          \n"
 
67
    "    .skip    0x4000             \n"
 
68
    "stack_top:                      \n"
 
69
    "    .text                       \n"
 
70
    );
 
71
 
 
72
void ap_start(void); /* non-static avoids unused-function compiler warning */
 
73
/*static*/ void ap_start(void)
 
74
{
 
75
    printf(" - CPU%d ... ", ap_cpuid);
 
76
    cacheattr_init();
 
77
    printf("done.\n");
 
78
    wmb();
 
79
    ap_callin = 1;
 
80
}
 
81
 
 
82
static void lapic_wait_ready(void)
 
83
{
 
84
    while ( lapic_read(APIC_ICR) & APIC_ICR_BUSY )
 
85
        cpu_relax();
 
86
}
 
87
 
 
88
static void boot_cpu(unsigned int cpu)
 
89
{
 
90
    unsigned int icr2 = SET_APIC_DEST_FIELD(LAPIC_ID(cpu));
 
91
 
 
92
    /* Initialise shared variables. */
 
93
    ap_cpuid = cpu;
 
94
    ap_callin = 0;
 
95
    wmb();
 
96
 
 
97
    /* Wake up the secondary processor: INIT-SIPI-SIPI... */
 
98
    lapic_wait_ready();
 
99
    lapic_write(APIC_ICR2, icr2);
 
100
    lapic_write(APIC_ICR, APIC_DM_INIT);
 
101
    lapic_wait_ready();
 
102
    lapic_write(APIC_ICR2, icr2);
 
103
    lapic_write(APIC_ICR, APIC_DM_STARTUP | (AP_BOOT_EIP >> 12));
 
104
    lapic_wait_ready();
 
105
    lapic_write(APIC_ICR2, icr2);
 
106
    lapic_write(APIC_ICR, APIC_DM_STARTUP | (AP_BOOT_EIP >> 12));
 
107
    lapic_wait_ready();
 
108
 
 
109
    /*
 
110
     * Wait for the secondary processor to complete initialisation.
 
111
     * Do not touch shared resources meanwhile.
 
112
     */
 
113
    while ( !ap_callin )
 
114
        cpu_relax();
 
115
 
 
116
    /* Take the secondary processor offline. */
 
117
    lapic_write(APIC_ICR2, icr2);
 
118
    lapic_write(APIC_ICR, APIC_DM_INIT);
 
119
    lapic_wait_ready();    
 
120
}
 
121
 
 
122
void smp_initialise(void)
 
123
{
 
124
    unsigned int i, nr_cpus = hvm_info->nr_vcpus;
 
125
 
 
126
    memcpy((void *)AP_BOOT_EIP, ap_boot_start, ap_boot_end - ap_boot_start);
 
127
 
 
128
    printf("Multiprocessor initialisation:\n");
 
129
    ap_start();
 
130
    for ( i = 1; i < nr_cpus; i++ )
 
131
        boot_cpu(i);
 
132
}