~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/ia64/kernel/machine_kexec.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * arch/ia64/kernel/machine_kexec.c
 
3
 *
 
4
 * Handle transition of Linux booting another kernel
 
5
 * Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P.
 
6
 * Copyright (C) 2005 Khalid Aziz <khalid.aziz@hp.com>
 
7
 * Copyright (C) 2006 Intel Corp, Zou Nan hai <nanhai.zou@intel.com>
 
8
 *
 
9
 * This source code is licensed under the GNU General Public License,
 
10
 * Version 2.  See the file COPYING for more details.
 
11
 */
 
12
 
 
13
#include <linux/mm.h>
 
14
#include <linux/kexec.h>
 
15
#include <linux/cpu.h>
 
16
#include <linux/irq.h>
 
17
#include <linux/efi.h>
 
18
#include <linux/numa.h>
 
19
#include <linux/mmzone.h>
 
20
 
 
21
#include <asm/numa.h>
 
22
#include <asm/mmu_context.h>
 
23
#include <asm/setup.h>
 
24
#include <asm/delay.h>
 
25
#include <asm/meminit.h>
 
26
#include <asm/processor.h>
 
27
#include <asm/sal.h>
 
28
#include <asm/mca.h>
 
29
 
 
30
typedef NORET_TYPE void (*relocate_new_kernel_t)(
 
31
                                        unsigned long indirection_page,
 
32
                                        unsigned long start_address,
 
33
                                        struct ia64_boot_param *boot_param,
 
34
                                        unsigned long pal_addr) ATTRIB_NORET;
 
35
 
 
36
struct kimage *ia64_kimage;
 
37
 
 
38
struct resource efi_memmap_res = {
 
39
        .name  = "EFI Memory Map",
 
40
        .start = 0,
 
41
        .end   = 0,
 
42
        .flags = IORESOURCE_BUSY | IORESOURCE_MEM
 
43
};
 
44
 
 
45
struct resource boot_param_res = {
 
46
        .name  = "Boot parameter",
 
47
        .start = 0,
 
48
        .end   = 0,
 
49
        .flags = IORESOURCE_BUSY | IORESOURCE_MEM
 
50
};
 
51
 
 
52
 
 
53
/*
 
54
 * Do what every setup is needed on image and the
 
55
 * reboot code buffer to allow us to avoid allocations
 
56
 * later.
 
57
 */
 
58
int machine_kexec_prepare(struct kimage *image)
 
59
{
 
60
        void *control_code_buffer;
 
61
        const unsigned long *func;
 
62
 
 
63
        func = (unsigned long *)&relocate_new_kernel;
 
64
        /* Pre-load control code buffer to minimize work in kexec path */
 
65
        control_code_buffer = page_address(image->control_code_page);
 
66
        memcpy((void *)control_code_buffer, (const void *)func[0],
 
67
                        relocate_new_kernel_size);
 
68
        flush_icache_range((unsigned long)control_code_buffer,
 
69
                        (unsigned long)control_code_buffer + relocate_new_kernel_size);
 
70
        ia64_kimage = image;
 
71
 
 
72
        return 0;
 
73
}
 
74
 
 
75
void machine_kexec_cleanup(struct kimage *image)
 
76
{
 
77
}
 
78
 
 
79
/*
 
80
 * Do not allocate memory (or fail in any way) in machine_kexec().
 
81
 * We are past the point of no return, committed to rebooting now.
 
82
 */
 
83
static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
 
84
{
 
85
        struct kimage *image = arg;
 
86
        relocate_new_kernel_t rnk;
 
87
        void *pal_addr = efi_get_pal_addr();
 
88
        unsigned long code_addr = (unsigned long)page_address(image->control_code_page);
 
89
        int ii;
 
90
        u64 fp, gp;
 
91
        ia64_fptr_t *init_handler = (ia64_fptr_t *)ia64_os_init_on_kdump;
 
92
 
 
93
        BUG_ON(!image);
 
94
        if (image->type == KEXEC_TYPE_CRASH) {
 
95
                crash_save_this_cpu();
 
96
                current->thread.ksp = (__u64)info->sw - 16;
 
97
 
 
98
                /* Register noop init handler */
 
99
                fp = ia64_tpa(init_handler->fp);
 
100
                gp = ia64_tpa(ia64_getreg(_IA64_REG_GP));
 
101
                ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, fp, gp, 0, fp, gp, 0);
 
102
        } else {
 
103
                /* Unregister init handlers of current kernel */
 
104
                ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, 0, 0, 0, 0, 0, 0);
 
105
        }
 
106
 
 
107
        /* Unregister mca handler - No more recovery on current kernel */
 
108
        ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, 0, 0, 0, 0, 0, 0);
 
109
 
 
110
        /* Interrupts aren't acceptable while we reboot */
 
111
        local_irq_disable();
 
112
 
 
113
        /* Mask CMC and Performance Monitor interrupts */
 
114
        ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);
 
115
        ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);
 
116
 
 
117
        /* Mask ITV and Local Redirect Registers */
 
118
        ia64_set_itv(1 << 16);
 
119
        ia64_set_lrr0(1 << 16);
 
120
        ia64_set_lrr1(1 << 16);
 
121
 
 
122
        /* terminate possible nested in-service interrupts */
 
123
        for (ii = 0; ii < 16; ii++)
 
124
                ia64_eoi();
 
125
 
 
126
        /* unmask TPR and clear any pending interrupts */
 
127
        ia64_setreg(_IA64_REG_CR_TPR, 0);
 
128
        ia64_srlz_d();
 
129
        while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR)
 
130
                ia64_eoi();
 
131
        platform_kernel_launch_event();
 
132
        rnk = (relocate_new_kernel_t)&code_addr;
 
133
        (*rnk)(image->head, image->start, ia64_boot_param,
 
134
                     GRANULEROUNDDOWN((unsigned long) pal_addr));
 
135
        BUG();
 
136
}
 
137
 
 
138
void machine_kexec(struct kimage *image)
 
139
{
 
140
        BUG_ON(!image);
 
141
        unw_init_running(ia64_machine_kexec, image);
 
142
        for(;;);
 
143
}
 
144
 
 
145
void arch_crash_save_vmcoreinfo(void)
 
146
{
 
147
#if defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_SPARSEMEM)
 
148
        VMCOREINFO_SYMBOL(pgdat_list);
 
149
        VMCOREINFO_LENGTH(pgdat_list, MAX_NUMNODES);
 
150
#endif
 
151
#ifdef CONFIG_NUMA
 
152
        VMCOREINFO_SYMBOL(node_memblk);
 
153
        VMCOREINFO_LENGTH(node_memblk, NR_NODE_MEMBLKS);
 
154
        VMCOREINFO_STRUCT_SIZE(node_memblk_s);
 
155
        VMCOREINFO_OFFSET(node_memblk_s, start_paddr);
 
156
        VMCOREINFO_OFFSET(node_memblk_s, size);
 
157
#endif
 
158
#ifdef CONFIG_PGTABLE_3
 
159
        VMCOREINFO_CONFIG(PGTABLE_3);
 
160
#elif  CONFIG_PGTABLE_4
 
161
        VMCOREINFO_CONFIG(PGTABLE_4);
 
162
#endif
 
163
}
 
164
 
 
165
unsigned long paddr_vmcoreinfo_note(void)
 
166
{
 
167
        return ia64_tpa((unsigned long)(char *)&vmcoreinfo_note);
 
168
}
 
169