replace x86_read/write_per_cpu with a common function.
[deliverable/linux.git] / arch / x86 / kernel / efi_32.c
CommitLineData
1da177e4
LT
1/*
2 * Extensible Firmware Interface
3 *
4 * Based on Extensible Firmware Interface Specification version 1.0
5 *
6 * Copyright (C) 1999 VA Linux Systems
7 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
8 * Copyright (C) 1999-2002 Hewlett-Packard Co.
9 * David Mosberger-Tang <davidm@hpl.hp.com>
10 * Stephane Eranian <eranian@hpl.hp.com>
11 *
12 * All EFI Runtime Services are not implemented yet as EFI only
13 * supports physical mode addressing on SoftSDV. This is to be fixed
14 * in a future version. --drummond 1999-07-20
15 *
16 * Implemented EFI runtime services and virtual mode calls. --davidm
17 *
18 * Goutham Rao: <goutham.rao@intel.com>
19 * Skip non-WB memory and ignore empty memory ranges.
20 */
21
1da177e4
LT
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/mm.h>
25#include <linux/types.h>
26#include <linux/time.h>
27#include <linux/spinlock.h>
28#include <linux/bootmem.h>
29#include <linux/ioport.h>
30#include <linux/module.h>
31#include <linux/efi.h>
1bc3b91a 32#include <linux/kexec.h>
1da177e4
LT
33
34#include <asm/setup.h>
35#include <asm/io.h>
36#include <asm/page.h>
37#include <asm/pgtable.h>
38#include <asm/processor.h>
39#include <asm/desc.h>
40#include <asm/tlbflush.h>
41
1da177e4
LT
42#define PFX "EFI: "
43
1da177e4
LT
44/*
45 * To make EFI call EFI runtime service in physical addressing mode we need
46 * prelog/epilog before/after the invocation to disable interrupt, to
47 * claim EFI runtime service handler exclusively and to duplicate a memory in
48 * low memory space say 0 - 3G.
49 */
50
51static unsigned long efi_rt_eflags;
52static DEFINE_SPINLOCK(efi_rt_lock);
53static pgd_t efi_bak_pg_dir_pointer[2];
54
e429795c 55void efi_call_phys_prelog(void) __acquires(efi_rt_lock)
1da177e4
LT
56{
57 unsigned long cr4;
58 unsigned long temp;
6b68f01b 59 struct desc_ptr gdt_descr;
1da177e4
LT
60
61 spin_lock(&efi_rt_lock);
62 local_irq_save(efi_rt_eflags);
63
64 /*
65 * If I don't have PSE, I should just duplicate two entries in page
66 * directory. If I have PSE, I just need to duplicate one entry in
67 * page directory.
68 */
4bb0d3ec 69 cr4 = read_cr4();
1da177e4
LT
70
71 if (cr4 & X86_CR4_PSE) {
72 efi_bak_pg_dir_pointer[0].pgd =
73 swapper_pg_dir[pgd_index(0)].pgd;
74 swapper_pg_dir[0].pgd =
75 swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
76 } else {
77 efi_bak_pg_dir_pointer[0].pgd =
78 swapper_pg_dir[pgd_index(0)].pgd;
79 efi_bak_pg_dir_pointer[1].pgd =
80 swapper_pg_dir[pgd_index(0x400000)].pgd;
81 swapper_pg_dir[pgd_index(0)].pgd =
82 swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
83 temp = PAGE_OFFSET + 0x400000;
84 swapper_pg_dir[pgd_index(0x400000)].pgd =
85 swapper_pg_dir[pgd_index(temp)].pgd;
86 }
87
88 /*
89 * After the lock is released, the original page table is restored.
90 */
91 local_flush_tlb();
92
4fbb5968
RR
93 gdt_descr.address = __pa(get_cpu_gdt_table(0));
94 gdt_descr.size = GDT_SIZE - 1;
95 load_gdt(&gdt_descr);
1da177e4
LT
96}
97
e429795c 98void efi_call_phys_epilog(void) __releases(efi_rt_lock)
1da177e4
LT
99{
100 unsigned long cr4;
6b68f01b 101 struct desc_ptr gdt_descr;
1da177e4 102
4fbb5968
RR
103 gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
104 gdt_descr.size = GDT_SIZE - 1;
105 load_gdt(&gdt_descr);
2b932f6c 106
4bb0d3ec 107 cr4 = read_cr4();
1da177e4
LT
108
109 if (cr4 & X86_CR4_PSE) {
110 swapper_pg_dir[pgd_index(0)].pgd =
111 efi_bak_pg_dir_pointer[0].pgd;
112 } else {
113 swapper_pg_dir[pgd_index(0)].pgd =
114 efi_bak_pg_dir_pointer[0].pgd;
115 swapper_pg_dir[pgd_index(0x400000)].pgd =
116 efi_bak_pg_dir_pointer[1].pgd;
117 }
118
119 /*
120 * After the lock is released, the original page table is restored.
121 */
122 local_flush_tlb();
123
124 local_irq_restore(efi_rt_eflags);
125 spin_unlock(&efi_rt_lock);
126}
127
1da177e4
LT
128/*
129 * We need to map the EFI memory map again after paging_init().
130 */
131void __init efi_map_memmap(void)
132{
133 memmap.map = NULL;
134
7ae65fd3
MT
135 memmap.map = bt_ioremap((unsigned long) memmap.phys_map,
136 (memmap.nr_map * memmap.desc_size));
1da177e4
LT
137 if (memmap.map == NULL)
138 printk(KERN_ERR PFX "Could not remap the EFI memmap!\n");
7ae65fd3
MT
139
140 memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
1da177e4 141}
This page took 0.294717 seconds and 5 git commands to generate.