Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/platform/efi/efi_32.c
10820 views
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 <[email protected]>
8
* Copyright (C) 1999-2002 Hewlett-Packard Co.
9
* David Mosberger-Tang <[email protected]>
10
* Stephane Eranian <[email protected]>
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: <[email protected]>
19
* Skip non-WB memory and ignore empty memory ranges.
20
*/
21
22
#include <linux/kernel.h>
23
#include <linux/types.h>
24
#include <linux/ioport.h>
25
#include <linux/efi.h>
26
27
#include <asm/io.h>
28
#include <asm/page.h>
29
#include <asm/pgtable.h>
30
#include <asm/tlbflush.h>
31
#include <asm/efi.h>
32
33
/*
34
* To make EFI call EFI runtime service in physical addressing mode we need
35
* prelog/epilog before/after the invocation to disable interrupt, to
36
* claim EFI runtime service handler exclusively and to duplicate a memory in
37
* low memory space say 0 - 3G.
38
*/
39
40
static unsigned long efi_rt_eflags;
41
static pgd_t efi_bak_pg_dir_pointer[2];
42
43
void efi_call_phys_prelog(void)
44
{
45
unsigned long cr4;
46
unsigned long temp;
47
struct desc_ptr gdt_descr;
48
49
local_irq_save(efi_rt_eflags);
50
51
/*
52
* If I don't have PAE, I should just duplicate two entries in page
53
* directory. If I have PAE, I just need to duplicate one entry in
54
* page directory.
55
*/
56
cr4 = read_cr4_safe();
57
58
if (cr4 & X86_CR4_PAE) {
59
efi_bak_pg_dir_pointer[0].pgd =
60
swapper_pg_dir[pgd_index(0)].pgd;
61
swapper_pg_dir[0].pgd =
62
swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
63
} else {
64
efi_bak_pg_dir_pointer[0].pgd =
65
swapper_pg_dir[pgd_index(0)].pgd;
66
efi_bak_pg_dir_pointer[1].pgd =
67
swapper_pg_dir[pgd_index(0x400000)].pgd;
68
swapper_pg_dir[pgd_index(0)].pgd =
69
swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
70
temp = PAGE_OFFSET + 0x400000;
71
swapper_pg_dir[pgd_index(0x400000)].pgd =
72
swapper_pg_dir[pgd_index(temp)].pgd;
73
}
74
75
/*
76
* After the lock is released, the original page table is restored.
77
*/
78
__flush_tlb_all();
79
80
gdt_descr.address = __pa(get_cpu_gdt_table(0));
81
gdt_descr.size = GDT_SIZE - 1;
82
load_gdt(&gdt_descr);
83
}
84
85
void efi_call_phys_epilog(void)
86
{
87
unsigned long cr4;
88
struct desc_ptr gdt_descr;
89
90
gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
91
gdt_descr.size = GDT_SIZE - 1;
92
load_gdt(&gdt_descr);
93
94
cr4 = read_cr4_safe();
95
96
if (cr4 & X86_CR4_PAE) {
97
swapper_pg_dir[pgd_index(0)].pgd =
98
efi_bak_pg_dir_pointer[0].pgd;
99
} else {
100
swapper_pg_dir[pgd_index(0)].pgd =
101
efi_bak_pg_dir_pointer[0].pgd;
102
swapper_pg_dir[pgd_index(0x400000)].pgd =
103
efi_bak_pg_dir_pointer[1].pgd;
104
}
105
106
/*
107
* After the lock is released, the original page table is restored.
108
*/
109
__flush_tlb_all();
110
111
local_irq_restore(efi_rt_eflags);
112
}
113
114