diff options
author | H. Peter Anvin <hpa@zytor.com> | 2012-05-21 15:17:50 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2012-05-21 15:17:50 -0400 |
commit | d13a822e6d08733cc69dd8c2f5d82eacb1474295 (patch) | |
tree | 2b39613c0d8cce9eb3b15adb1525a2c72f46d392 /arch/x86 | |
parent | 29d679ffd850ea37a303bb930142be14982611e4 (diff) | |
parent | 76e10d158efb6d4516018846f60c2ab5501900bc (diff) |
Merge commit 'v3.4' into x86/urgent
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Makefile | 3 | ||||
-rw-r--r-- | arch/x86/boot/compressed/Makefile | 9 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 14 | ||||
-rw-r--r-- | arch/x86/kernel/kvm.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/setup_percpu.c | 14 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 1 | ||||
-rw-r--r-- | arch/x86/tools/.gitignore | 1 | ||||
-rw-r--r-- | arch/x86/tools/Makefile | 4 | ||||
-rw-r--r-- | arch/x86/tools/relocs.c (renamed from arch/x86/boot/compressed/relocs.c) | 242 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 42 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 7 |
11 files changed, 268 insertions, 78 deletions
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 41a7237606a3..94e91e401da9 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile | |||
@@ -134,6 +134,9 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) | |||
134 | KBUILD_CFLAGS += $(mflags-y) | 134 | KBUILD_CFLAGS += $(mflags-y) |
135 | KBUILD_AFLAGS += $(mflags-y) | 135 | KBUILD_AFLAGS += $(mflags-y) |
136 | 136 | ||
137 | archscripts: | ||
138 | $(Q)$(MAKE) $(build)=arch/x86/tools relocs | ||
139 | |||
137 | ### | 140 | ### |
138 | # Syscall table generation | 141 | # Syscall table generation |
139 | 142 | ||
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index fd55a2ff3ad8..e398bb5d63bb 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -40,13 +40,12 @@ OBJCOPYFLAGS_vmlinux.bin := -R .comment -S | |||
40 | $(obj)/vmlinux.bin: vmlinux FORCE | 40 | $(obj)/vmlinux.bin: vmlinux FORCE |
41 | $(call if_changed,objcopy) | 41 | $(call if_changed,objcopy) |
42 | 42 | ||
43 | targets += vmlinux.bin.all vmlinux.relocs | ||
43 | 44 | ||
44 | targets += vmlinux.bin.all vmlinux.relocs relocs | 45 | CMD_RELOCS = arch/x86/tools/relocs |
45 | hostprogs-$(CONFIG_X86_NEED_RELOCS) += relocs | ||
46 | |||
47 | quiet_cmd_relocs = RELOCS $@ | 46 | quiet_cmd_relocs = RELOCS $@ |
48 | cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< | 47 | cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< |
49 | $(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE | 48 | $(obj)/vmlinux.relocs: vmlinux FORCE |
50 | $(call if_changed,relocs) | 49 | $(call if_changed,relocs) |
51 | 50 | ||
52 | vmlinux.bin.all-y := $(obj)/vmlinux.bin | 51 | vmlinux.bin.all-y := $(obj)/vmlinux.bin |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index d086a09c087d..11c9166c3337 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -945,9 +945,10 @@ struct mce_info { | |||
945 | atomic_t inuse; | 945 | atomic_t inuse; |
946 | struct task_struct *t; | 946 | struct task_struct *t; |
947 | __u64 paddr; | 947 | __u64 paddr; |
948 | int restartable; | ||
948 | } mce_info[MCE_INFO_MAX]; | 949 | } mce_info[MCE_INFO_MAX]; |
949 | 950 | ||
950 | static void mce_save_info(__u64 addr) | 951 | static void mce_save_info(__u64 addr, int c) |
951 | { | 952 | { |
952 | struct mce_info *mi; | 953 | struct mce_info *mi; |
953 | 954 | ||
@@ -955,6 +956,7 @@ static void mce_save_info(__u64 addr) | |||
955 | if (atomic_cmpxchg(&mi->inuse, 0, 1) == 0) { | 956 | if (atomic_cmpxchg(&mi->inuse, 0, 1) == 0) { |
956 | mi->t = current; | 957 | mi->t = current; |
957 | mi->paddr = addr; | 958 | mi->paddr = addr; |
959 | mi->restartable = c; | ||
958 | return; | 960 | return; |
959 | } | 961 | } |
960 | } | 962 | } |
@@ -1130,7 +1132,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1130 | mce_panic("Fatal machine check on current CPU", &m, msg); | 1132 | mce_panic("Fatal machine check on current CPU", &m, msg); |
1131 | if (worst == MCE_AR_SEVERITY) { | 1133 | if (worst == MCE_AR_SEVERITY) { |
1132 | /* schedule action before return to userland */ | 1134 | /* schedule action before return to userland */ |
1133 | mce_save_info(m.addr); | 1135 | mce_save_info(m.addr, m.mcgstatus & MCG_STATUS_RIPV); |
1134 | set_thread_flag(TIF_MCE_NOTIFY); | 1136 | set_thread_flag(TIF_MCE_NOTIFY); |
1135 | } else if (kill_it) { | 1137 | } else if (kill_it) { |
1136 | force_sig(SIGBUS, current); | 1138 | force_sig(SIGBUS, current); |
@@ -1179,7 +1181,13 @@ void mce_notify_process(void) | |||
1179 | 1181 | ||
1180 | pr_err("Uncorrected hardware memory error in user-access at %llx", | 1182 | pr_err("Uncorrected hardware memory error in user-access at %llx", |
1181 | mi->paddr); | 1183 | mi->paddr); |
1182 | if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0) { | 1184 | /* |
1185 | * We must call memory_failure() here even if the current process is | ||
1186 | * doomed. We still need to mark the page as poisoned and alert any | ||
1187 | * other users of the page. | ||
1188 | */ | ||
1189 | if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 || | ||
1190 | mi->restartable == 0) { | ||
1183 | pr_err("Memory error not recovered"); | 1191 | pr_err("Memory error not recovered"); |
1184 | force_sig(SIGBUS, current); | 1192 | force_sig(SIGBUS, current); |
1185 | } | 1193 | } |
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index b8ba6e4a27e4..e554e5ad2fe8 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c | |||
@@ -79,7 +79,6 @@ struct kvm_task_sleep_node { | |||
79 | u32 token; | 79 | u32 token; |
80 | int cpu; | 80 | int cpu; |
81 | bool halted; | 81 | bool halted; |
82 | struct mm_struct *mm; | ||
83 | }; | 82 | }; |
84 | 83 | ||
85 | static struct kvm_task_sleep_head { | 84 | static struct kvm_task_sleep_head { |
@@ -126,9 +125,7 @@ void kvm_async_pf_task_wait(u32 token) | |||
126 | 125 | ||
127 | n.token = token; | 126 | n.token = token; |
128 | n.cpu = smp_processor_id(); | 127 | n.cpu = smp_processor_id(); |
129 | n.mm = current->active_mm; | ||
130 | n.halted = idle || preempt_count() > 1; | 128 | n.halted = idle || preempt_count() > 1; |
131 | atomic_inc(&n.mm->mm_count); | ||
132 | init_waitqueue_head(&n.wq); | 129 | init_waitqueue_head(&n.wq); |
133 | hlist_add_head(&n.link, &b->list); | 130 | hlist_add_head(&n.link, &b->list); |
134 | spin_unlock(&b->lock); | 131 | spin_unlock(&b->lock); |
@@ -161,9 +158,6 @@ EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait); | |||
161 | static void apf_task_wake_one(struct kvm_task_sleep_node *n) | 158 | static void apf_task_wake_one(struct kvm_task_sleep_node *n) |
162 | { | 159 | { |
163 | hlist_del_init(&n->link); | 160 | hlist_del_init(&n->link); |
164 | if (!n->mm) | ||
165 | return; | ||
166 | mmdrop(n->mm); | ||
167 | if (n->halted) | 161 | if (n->halted) |
168 | smp_send_reschedule(n->cpu); | 162 | smp_send_reschedule(n->cpu); |
169 | else if (waitqueue_active(&n->wq)) | 163 | else if (waitqueue_active(&n->wq)) |
@@ -207,7 +201,7 @@ again: | |||
207 | * async PF was not yet handled. | 201 | * async PF was not yet handled. |
208 | * Add dummy entry for the token. | 202 | * Add dummy entry for the token. |
209 | */ | 203 | */ |
210 | n = kmalloc(sizeof(*n), GFP_ATOMIC); | 204 | n = kzalloc(sizeof(*n), GFP_ATOMIC); |
211 | if (!n) { | 205 | if (!n) { |
212 | /* | 206 | /* |
213 | * Allocation failed! Busy wait while other cpu | 207 | * Allocation failed! Busy wait while other cpu |
@@ -219,7 +213,6 @@ again: | |||
219 | } | 213 | } |
220 | n->token = token; | 214 | n->token = token; |
221 | n->cpu = smp_processor_id(); | 215 | n->cpu = smp_processor_id(); |
222 | n->mm = NULL; | ||
223 | init_waitqueue_head(&n->wq); | 216 | init_waitqueue_head(&n->wq); |
224 | hlist_add_head(&n->link, &b->list); | 217 | hlist_add_head(&n->link, &b->list); |
225 | } else | 218 | } else |
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 71f4727da373..5a98aa272184 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
@@ -185,10 +185,22 @@ void __init setup_per_cpu_areas(void) | |||
185 | #endif | 185 | #endif |
186 | rc = -EINVAL; | 186 | rc = -EINVAL; |
187 | if (pcpu_chosen_fc != PCPU_FC_PAGE) { | 187 | if (pcpu_chosen_fc != PCPU_FC_PAGE) { |
188 | const size_t atom_size = cpu_has_pse ? PMD_SIZE : PAGE_SIZE; | ||
189 | const size_t dyn_size = PERCPU_MODULE_RESERVE + | 188 | const size_t dyn_size = PERCPU_MODULE_RESERVE + |
190 | PERCPU_DYNAMIC_RESERVE - PERCPU_FIRST_CHUNK_RESERVE; | 189 | PERCPU_DYNAMIC_RESERVE - PERCPU_FIRST_CHUNK_RESERVE; |
190 | size_t atom_size; | ||
191 | 191 | ||
192 | /* | ||
193 | * On 64bit, use PMD_SIZE for atom_size so that embedded | ||
194 | * percpu areas are aligned to PMD. This, in the future, | ||
195 | * can also allow using PMD mappings in vmalloc area. Use | ||
196 | * PAGE_SIZE on 32bit as vmalloc space is highly contended | ||
197 | * and large vmalloc area allocs can easily fail. | ||
198 | */ | ||
199 | #ifdef CONFIG_X86_64 | ||
200 | atom_size = PMD_SIZE; | ||
201 | #else | ||
202 | atom_size = PAGE_SIZE; | ||
203 | #endif | ||
192 | rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, | 204 | rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE, |
193 | dyn_size, atom_size, | 205 | dyn_size, atom_size, |
194 | pcpu_cpu_distance, | 206 | pcpu_cpu_distance, |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 91a5e989abcf..185a2b823a2d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -6581,6 +6581,7 @@ void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, | |||
6581 | kvm_inject_page_fault(vcpu, &fault); | 6581 | kvm_inject_page_fault(vcpu, &fault); |
6582 | } | 6582 | } |
6583 | vcpu->arch.apf.halted = false; | 6583 | vcpu->arch.apf.halted = false; |
6584 | vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; | ||
6584 | } | 6585 | } |
6585 | 6586 | ||
6586 | bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu) | 6587 | bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu) |
diff --git a/arch/x86/tools/.gitignore b/arch/x86/tools/.gitignore new file mode 100644 index 000000000000..be0ed065249b --- /dev/null +++ b/arch/x86/tools/.gitignore | |||
@@ -0,0 +1 @@ | |||
relocs | |||
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile index d511aa97533a..733057b435b0 100644 --- a/arch/x86/tools/Makefile +++ b/arch/x86/tools/Makefile | |||
@@ -36,3 +36,7 @@ HOSTCFLAGS_insn_sanity.o := -Wall -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x | |||
36 | $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c | 36 | $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c |
37 | 37 | ||
38 | $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c | 38 | $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c |
39 | |||
40 | HOST_EXTRACFLAGS += -I$(srctree)/tools/include | ||
41 | hostprogs-y += relocs | ||
42 | relocs: $(obj)/relocs | ||
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/tools/relocs.c index fb7117a4ade1..b43cfcd9bf40 100644 --- a/arch/x86/boot/compressed/relocs.c +++ b/arch/x86/tools/relocs.c | |||
@@ -18,6 +18,8 @@ static void die(char *fmt, ...); | |||
18 | static Elf32_Ehdr ehdr; | 18 | static Elf32_Ehdr ehdr; |
19 | static unsigned long reloc_count, reloc_idx; | 19 | static unsigned long reloc_count, reloc_idx; |
20 | static unsigned long *relocs; | 20 | static unsigned long *relocs; |
21 | static unsigned long reloc16_count, reloc16_idx; | ||
22 | static unsigned long *relocs16; | ||
21 | 23 | ||
22 | struct section { | 24 | struct section { |
23 | Elf32_Shdr shdr; | 25 | Elf32_Shdr shdr; |
@@ -28,52 +30,86 @@ struct section { | |||
28 | }; | 30 | }; |
29 | static struct section *secs; | 31 | static struct section *secs; |
30 | 32 | ||
33 | enum symtype { | ||
34 | S_ABS, | ||
35 | S_REL, | ||
36 | S_SEG, | ||
37 | S_LIN, | ||
38 | S_NSYMTYPES | ||
39 | }; | ||
40 | |||
41 | static const char * const sym_regex_kernel[S_NSYMTYPES] = { | ||
31 | /* | 42 | /* |
32 | * Following symbols have been audited. There values are constant and do | 43 | * Following symbols have been audited. There values are constant and do |
33 | * not change if bzImage is loaded at a different physical address than | 44 | * not change if bzImage is loaded at a different physical address than |
34 | * the address for which it has been compiled. Don't warn user about | 45 | * the address for which it has been compiled. Don't warn user about |
35 | * absolute relocations present w.r.t these symbols. | 46 | * absolute relocations present w.r.t these symbols. |
36 | */ | 47 | */ |
37 | static const char abs_sym_regex[] = | 48 | [S_ABS] = |
38 | "^(xen_irq_disable_direct_reloc$|" | 49 | "^(xen_irq_disable_direct_reloc$|" |
39 | "xen_save_fl_direct_reloc$|" | 50 | "xen_save_fl_direct_reloc$|" |
40 | "VDSO|" | 51 | "VDSO|" |
41 | "__crc_)"; | 52 | "__crc_)", |
42 | static regex_t abs_sym_regex_c; | ||
43 | static int is_abs_reloc(const char *sym_name) | ||
44 | { | ||
45 | return !regexec(&abs_sym_regex_c, sym_name, 0, NULL, 0); | ||
46 | } | ||
47 | 53 | ||
48 | /* | 54 | /* |
49 | * These symbols are known to be relative, even if the linker marks them | 55 | * These symbols are known to be relative, even if the linker marks them |
50 | * as absolute (typically defined outside any section in the linker script.) | 56 | * as absolute (typically defined outside any section in the linker script.) |
51 | */ | 57 | */ |
52 | static const char rel_sym_regex[] = | 58 | [S_REL] = |
53 | "^_end$"; | 59 | "^(__init_(begin|end)|" |
54 | static regex_t rel_sym_regex_c; | 60 | "__x86_cpu_dev_(start|end)|" |
55 | static int is_rel_reloc(const char *sym_name) | 61 | "(__parainstructions|__alt_instructions)(|_end)|" |
62 | "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|" | ||
63 | "_end)$" | ||
64 | }; | ||
65 | |||
66 | |||
67 | static const char * const sym_regex_realmode[S_NSYMTYPES] = { | ||
68 | /* | ||
69 | * These are 16-bit segment symbols when compiling 16-bit code. | ||
70 | */ | ||
71 | [S_SEG] = | ||
72 | "^real_mode_seg$", | ||
73 | |||
74 | /* | ||
75 | * These are offsets belonging to segments, as opposed to linear addresses, | ||
76 | * when compiling 16-bit code. | ||
77 | */ | ||
78 | [S_LIN] = | ||
79 | "^pa_", | ||
80 | }; | ||
81 | |||
82 | static const char * const *sym_regex; | ||
83 | |||
84 | static regex_t sym_regex_c[S_NSYMTYPES]; | ||
85 | static int is_reloc(enum symtype type, const char *sym_name) | ||
56 | { | 86 | { |
57 | return !regexec(&rel_sym_regex_c, sym_name, 0, NULL, 0); | 87 | return sym_regex[type] && |
88 | !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0); | ||
58 | } | 89 | } |
59 | 90 | ||
60 | static void regex_init(void) | 91 | static void regex_init(int use_real_mode) |
61 | { | 92 | { |
62 | char errbuf[128]; | 93 | char errbuf[128]; |
63 | int err; | 94 | int err; |
64 | 95 | int i; | |
65 | err = regcomp(&abs_sym_regex_c, abs_sym_regex, | 96 | |
66 | REG_EXTENDED|REG_NOSUB); | 97 | if (use_real_mode) |
67 | if (err) { | 98 | sym_regex = sym_regex_realmode; |
68 | regerror(err, &abs_sym_regex_c, errbuf, sizeof errbuf); | 99 | else |
69 | die("%s", errbuf); | 100 | sym_regex = sym_regex_kernel; |
70 | } | ||
71 | 101 | ||
72 | err = regcomp(&rel_sym_regex_c, rel_sym_regex, | 102 | for (i = 0; i < S_NSYMTYPES; i++) { |
73 | REG_EXTENDED|REG_NOSUB); | 103 | if (!sym_regex[i]) |
74 | if (err) { | 104 | continue; |
75 | regerror(err, &rel_sym_regex_c, errbuf, sizeof errbuf); | 105 | |
76 | die("%s", errbuf); | 106 | err = regcomp(&sym_regex_c[i], sym_regex[i], |
107 | REG_EXTENDED|REG_NOSUB); | ||
108 | |||
109 | if (err) { | ||
110 | regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf); | ||
111 | die("%s", errbuf); | ||
112 | } | ||
77 | } | 113 | } |
78 | } | 114 | } |
79 | 115 | ||
@@ -154,6 +190,10 @@ static const char *rel_type(unsigned type) | |||
154 | REL_TYPE(R_386_RELATIVE), | 190 | REL_TYPE(R_386_RELATIVE), |
155 | REL_TYPE(R_386_GOTOFF), | 191 | REL_TYPE(R_386_GOTOFF), |
156 | REL_TYPE(R_386_GOTPC), | 192 | REL_TYPE(R_386_GOTPC), |
193 | REL_TYPE(R_386_8), | ||
194 | REL_TYPE(R_386_PC8), | ||
195 | REL_TYPE(R_386_16), | ||
196 | REL_TYPE(R_386_PC16), | ||
157 | #undef REL_TYPE | 197 | #undef REL_TYPE |
158 | }; | 198 | }; |
159 | const char *name = "unknown type rel type name"; | 199 | const char *name = "unknown type rel type name"; |
@@ -189,7 +229,7 @@ static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) | |||
189 | name = sym_strtab + sym->st_name; | 229 | name = sym_strtab + sym->st_name; |
190 | } | 230 | } |
191 | else { | 231 | else { |
192 | name = sec_name(secs[sym->st_shndx].shdr.sh_name); | 232 | name = sec_name(sym->st_shndx); |
193 | } | 233 | } |
194 | return name; | 234 | return name; |
195 | } | 235 | } |
@@ -472,7 +512,7 @@ static void print_absolute_relocs(void) | |||
472 | * Before warning check if this absolute symbol | 512 | * Before warning check if this absolute symbol |
473 | * relocation is harmless. | 513 | * relocation is harmless. |
474 | */ | 514 | */ |
475 | if (is_abs_reloc(name) || is_rel_reloc(name)) | 515 | if (is_reloc(S_ABS, name) || is_reloc(S_REL, name)) |
476 | continue; | 516 | continue; |
477 | 517 | ||
478 | if (!printed) { | 518 | if (!printed) { |
@@ -496,7 +536,8 @@ static void print_absolute_relocs(void) | |||
496 | printf("\n"); | 536 | printf("\n"); |
497 | } | 537 | } |
498 | 538 | ||
499 | static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | 539 | static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym), |
540 | int use_real_mode) | ||
500 | { | 541 | { |
501 | int i; | 542 | int i; |
502 | /* Walk through the relocations */ | 543 | /* Walk through the relocations */ |
@@ -521,30 +562,67 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | |||
521 | Elf32_Rel *rel; | 562 | Elf32_Rel *rel; |
522 | Elf32_Sym *sym; | 563 | Elf32_Sym *sym; |
523 | unsigned r_type; | 564 | unsigned r_type; |
565 | const char *symname; | ||
566 | int shn_abs; | ||
567 | |||
524 | rel = &sec->reltab[j]; | 568 | rel = &sec->reltab[j]; |
525 | sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; | 569 | sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; |
526 | r_type = ELF32_R_TYPE(rel->r_info); | 570 | r_type = ELF32_R_TYPE(rel->r_info); |
527 | /* Don't visit relocations to absolute symbols */ | 571 | |
528 | if (sym->st_shndx == SHN_ABS && | 572 | shn_abs = sym->st_shndx == SHN_ABS; |
529 | !is_rel_reloc(sym_name(sym_strtab, sym))) { | 573 | |
530 | continue; | ||
531 | } | ||
532 | switch (r_type) { | 574 | switch (r_type) { |
533 | case R_386_NONE: | 575 | case R_386_NONE: |
534 | case R_386_PC32: | 576 | case R_386_PC32: |
577 | case R_386_PC16: | ||
578 | case R_386_PC8: | ||
535 | /* | 579 | /* |
536 | * NONE can be ignored and and PC relative | 580 | * NONE can be ignored and and PC relative |
537 | * relocations don't need to be adjusted. | 581 | * relocations don't need to be adjusted. |
538 | */ | 582 | */ |
539 | break; | 583 | break; |
584 | |||
585 | case R_386_16: | ||
586 | symname = sym_name(sym_strtab, sym); | ||
587 | if (!use_real_mode) | ||
588 | goto bad; | ||
589 | if (shn_abs) { | ||
590 | if (is_reloc(S_ABS, symname)) | ||
591 | break; | ||
592 | else if (!is_reloc(S_SEG, symname)) | ||
593 | goto bad; | ||
594 | } else { | ||
595 | if (is_reloc(S_LIN, symname)) | ||
596 | goto bad; | ||
597 | else | ||
598 | break; | ||
599 | } | ||
600 | visit(rel, sym); | ||
601 | break; | ||
602 | |||
540 | case R_386_32: | 603 | case R_386_32: |
541 | /* Visit relocations that need to be adjusted */ | 604 | symname = sym_name(sym_strtab, sym); |
605 | if (shn_abs) { | ||
606 | if (is_reloc(S_ABS, symname)) | ||
607 | break; | ||
608 | else if (!is_reloc(S_REL, symname)) | ||
609 | goto bad; | ||
610 | } else { | ||
611 | if (use_real_mode && | ||
612 | !is_reloc(S_LIN, symname)) | ||
613 | break; | ||
614 | } | ||
542 | visit(rel, sym); | 615 | visit(rel, sym); |
543 | break; | 616 | break; |
544 | default: | 617 | default: |
545 | die("Unsupported relocation type: %s (%d)\n", | 618 | die("Unsupported relocation type: %s (%d)\n", |
546 | rel_type(r_type), r_type); | 619 | rel_type(r_type), r_type); |
547 | break; | 620 | break; |
621 | bad: | ||
622 | symname = sym_name(sym_strtab, sym); | ||
623 | die("Invalid %s %s relocation: %s\n", | ||
624 | shn_abs ? "absolute" : "relative", | ||
625 | rel_type(r_type), symname); | ||
548 | } | 626 | } |
549 | } | 627 | } |
550 | } | 628 | } |
@@ -552,13 +630,19 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | |||
552 | 630 | ||
553 | static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) | 631 | static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) |
554 | { | 632 | { |
555 | reloc_count += 1; | 633 | if (ELF32_R_TYPE(rel->r_info) == R_386_16) |
634 | reloc16_count++; | ||
635 | else | ||
636 | reloc_count++; | ||
556 | } | 637 | } |
557 | 638 | ||
558 | static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) | 639 | static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) |
559 | { | 640 | { |
560 | /* Remember the address that needs to be adjusted. */ | 641 | /* Remember the address that needs to be adjusted. */ |
561 | relocs[reloc_idx++] = rel->r_offset; | 642 | if (ELF32_R_TYPE(rel->r_info) == R_386_16) |
643 | relocs16[reloc16_idx++] = rel->r_offset; | ||
644 | else | ||
645 | relocs[reloc_idx++] = rel->r_offset; | ||
562 | } | 646 | } |
563 | 647 | ||
564 | static int cmp_relocs(const void *va, const void *vb) | 648 | static int cmp_relocs(const void *va, const void *vb) |
@@ -568,23 +652,41 @@ static int cmp_relocs(const void *va, const void *vb) | |||
568 | return (*a == *b)? 0 : (*a > *b)? 1 : -1; | 652 | return (*a == *b)? 0 : (*a > *b)? 1 : -1; |
569 | } | 653 | } |
570 | 654 | ||
571 | static void emit_relocs(int as_text) | 655 | static int write32(unsigned int v, FILE *f) |
656 | { | ||
657 | unsigned char buf[4]; | ||
658 | |||
659 | put_unaligned_le32(v, buf); | ||
660 | return fwrite(buf, 1, 4, f) == 4 ? 0 : -1; | ||
661 | } | ||
662 | |||
663 | static void emit_relocs(int as_text, int use_real_mode) | ||
572 | { | 664 | { |
573 | int i; | 665 | int i; |
574 | /* Count how many relocations I have and allocate space for them. */ | 666 | /* Count how many relocations I have and allocate space for them. */ |
575 | reloc_count = 0; | 667 | reloc_count = 0; |
576 | walk_relocs(count_reloc); | 668 | walk_relocs(count_reloc, use_real_mode); |
577 | relocs = malloc(reloc_count * sizeof(relocs[0])); | 669 | relocs = malloc(reloc_count * sizeof(relocs[0])); |
578 | if (!relocs) { | 670 | if (!relocs) { |
579 | die("malloc of %d entries for relocs failed\n", | 671 | die("malloc of %d entries for relocs failed\n", |
580 | reloc_count); | 672 | reloc_count); |
581 | } | 673 | } |
674 | |||
675 | relocs16 = malloc(reloc16_count * sizeof(relocs[0])); | ||
676 | if (!relocs16) { | ||
677 | die("malloc of %d entries for relocs16 failed\n", | ||
678 | reloc16_count); | ||
679 | } | ||
582 | /* Collect up the relocations */ | 680 | /* Collect up the relocations */ |
583 | reloc_idx = 0; | 681 | reloc_idx = 0; |
584 | walk_relocs(collect_reloc); | 682 | walk_relocs(collect_reloc, use_real_mode); |
683 | |||
684 | if (reloc16_count && !use_real_mode) | ||
685 | die("Segment relocations found but --realmode not specified\n"); | ||
585 | 686 | ||
586 | /* Order the relocations for more efficient processing */ | 687 | /* Order the relocations for more efficient processing */ |
587 | qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); | 688 | qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); |
689 | qsort(relocs16, reloc16_count, sizeof(relocs16[0]), cmp_relocs); | ||
588 | 690 | ||
589 | /* Print the relocations */ | 691 | /* Print the relocations */ |
590 | if (as_text) { | 692 | if (as_text) { |
@@ -593,58 +695,83 @@ static void emit_relocs(int as_text) | |||
593 | */ | 695 | */ |
594 | printf(".section \".data.reloc\",\"a\"\n"); | 696 | printf(".section \".data.reloc\",\"a\"\n"); |
595 | printf(".balign 4\n"); | 697 | printf(".balign 4\n"); |
596 | for (i = 0; i < reloc_count; i++) { | 698 | if (use_real_mode) { |
597 | printf("\t .long 0x%08lx\n", relocs[i]); | 699 | printf("\t.long %lu\n", reloc16_count); |
700 | for (i = 0; i < reloc16_count; i++) | ||
701 | printf("\t.long 0x%08lx\n", relocs16[i]); | ||
702 | printf("\t.long %lu\n", reloc_count); | ||
703 | for (i = 0; i < reloc_count; i++) { | ||
704 | printf("\t.long 0x%08lx\n", relocs[i]); | ||
705 | } | ||
706 | } else { | ||
707 | /* Print a stop */ | ||
708 | printf("\t.long 0x%08lx\n", (unsigned long)0); | ||
709 | for (i = 0; i < reloc_count; i++) { | ||
710 | printf("\t.long 0x%08lx\n", relocs[i]); | ||
711 | } | ||
598 | } | 712 | } |
713 | |||
599 | printf("\n"); | 714 | printf("\n"); |
600 | } | 715 | } |
601 | else { | 716 | else { |
602 | unsigned char buf[4]; | 717 | if (use_real_mode) { |
603 | /* Print a stop */ | 718 | write32(reloc16_count, stdout); |
604 | fwrite("\0\0\0\0", 4, 1, stdout); | 719 | for (i = 0; i < reloc16_count; i++) |
605 | /* Now print each relocation */ | 720 | write32(relocs16[i], stdout); |
606 | for (i = 0; i < reloc_count; i++) { | 721 | write32(reloc_count, stdout); |
607 | put_unaligned_le32(relocs[i], buf); | 722 | |
608 | fwrite(buf, 4, 1, stdout); | 723 | /* Now print each relocation */ |
724 | for (i = 0; i < reloc_count; i++) | ||
725 | write32(relocs[i], stdout); | ||
726 | } else { | ||
727 | /* Print a stop */ | ||
728 | write32(0, stdout); | ||
729 | |||
730 | /* Now print each relocation */ | ||
731 | for (i = 0; i < reloc_count; i++) { | ||
732 | write32(relocs[i], stdout); | ||
733 | } | ||
609 | } | 734 | } |
610 | } | 735 | } |
611 | } | 736 | } |
612 | 737 | ||
613 | static void usage(void) | 738 | static void usage(void) |
614 | { | 739 | { |
615 | die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n"); | 740 | die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); |
616 | } | 741 | } |
617 | 742 | ||
618 | int main(int argc, char **argv) | 743 | int main(int argc, char **argv) |
619 | { | 744 | { |
620 | int show_absolute_syms, show_absolute_relocs; | 745 | int show_absolute_syms, show_absolute_relocs; |
621 | int as_text; | 746 | int as_text, use_real_mode; |
622 | const char *fname; | 747 | const char *fname; |
623 | FILE *fp; | 748 | FILE *fp; |
624 | int i; | 749 | int i; |
625 | 750 | ||
626 | regex_init(); | ||
627 | |||
628 | show_absolute_syms = 0; | 751 | show_absolute_syms = 0; |
629 | show_absolute_relocs = 0; | 752 | show_absolute_relocs = 0; |
630 | as_text = 0; | 753 | as_text = 0; |
754 | use_real_mode = 0; | ||
631 | fname = NULL; | 755 | fname = NULL; |
632 | for (i = 1; i < argc; i++) { | 756 | for (i = 1; i < argc; i++) { |
633 | char *arg = argv[i]; | 757 | char *arg = argv[i]; |
634 | if (*arg == '-') { | 758 | if (*arg == '-') { |
635 | if (strcmp(argv[1], "--abs-syms") == 0) { | 759 | if (strcmp(arg, "--abs-syms") == 0) { |
636 | show_absolute_syms = 1; | 760 | show_absolute_syms = 1; |
637 | continue; | 761 | continue; |
638 | } | 762 | } |
639 | 763 | if (strcmp(arg, "--abs-relocs") == 0) { | |
640 | if (strcmp(argv[1], "--abs-relocs") == 0) { | ||
641 | show_absolute_relocs = 1; | 764 | show_absolute_relocs = 1; |
642 | continue; | 765 | continue; |
643 | } | 766 | } |
644 | else if (strcmp(argv[1], "--text") == 0) { | 767 | if (strcmp(arg, "--text") == 0) { |
645 | as_text = 1; | 768 | as_text = 1; |
646 | continue; | 769 | continue; |
647 | } | 770 | } |
771 | if (strcmp(arg, "--realmode") == 0) { | ||
772 | use_real_mode = 1; | ||
773 | continue; | ||
774 | } | ||
648 | } | 775 | } |
649 | else if (!fname) { | 776 | else if (!fname) { |
650 | fname = arg; | 777 | fname = arg; |
@@ -655,6 +782,7 @@ int main(int argc, char **argv) | |||
655 | if (!fname) { | 782 | if (!fname) { |
656 | usage(); | 783 | usage(); |
657 | } | 784 | } |
785 | regex_init(use_real_mode); | ||
658 | fp = fopen(fname, "r"); | 786 | fp = fopen(fname, "r"); |
659 | if (!fp) { | 787 | if (!fp) { |
660 | die("Cannot open %s: %s\n", | 788 | die("Cannot open %s: %s\n", |
@@ -673,6 +801,6 @@ int main(int argc, char **argv) | |||
673 | print_absolute_relocs(); | 801 | print_absolute_relocs(); |
674 | return 0; | 802 | return 0; |
675 | } | 803 | } |
676 | emit_relocs(as_text); | 804 | emit_relocs(as_text, use_real_mode); |
677 | return 0; | 805 | return 0; |
678 | } | 806 | } |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index a8f8844b8d32..95dccce8e979 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <asm/stackprotector.h> | 63 | #include <asm/stackprotector.h> |
64 | #include <asm/hypervisor.h> | 64 | #include <asm/hypervisor.h> |
65 | #include <asm/mwait.h> | 65 | #include <asm/mwait.h> |
66 | #include <asm/pci_x86.h> | ||
66 | 67 | ||
67 | #ifdef CONFIG_ACPI | 68 | #ifdef CONFIG_ACPI |
68 | #include <linux/acpi.h> | 69 | #include <linux/acpi.h> |
@@ -809,9 +810,40 @@ static void xen_io_delay(void) | |||
809 | } | 810 | } |
810 | 811 | ||
811 | #ifdef CONFIG_X86_LOCAL_APIC | 812 | #ifdef CONFIG_X86_LOCAL_APIC |
813 | static unsigned long xen_set_apic_id(unsigned int x) | ||
814 | { | ||
815 | WARN_ON(1); | ||
816 | return x; | ||
817 | } | ||
818 | static unsigned int xen_get_apic_id(unsigned long x) | ||
819 | { | ||
820 | return ((x)>>24) & 0xFFu; | ||
821 | } | ||
812 | static u32 xen_apic_read(u32 reg) | 822 | static u32 xen_apic_read(u32 reg) |
813 | { | 823 | { |
814 | return 0; | 824 | struct xen_platform_op op = { |
825 | .cmd = XENPF_get_cpuinfo, | ||
826 | .interface_version = XENPF_INTERFACE_VERSION, | ||
827 | .u.pcpu_info.xen_cpuid = 0, | ||
828 | }; | ||
829 | int ret = 0; | ||
830 | |||
831 | /* Shouldn't need this as APIC is turned off for PV, and we only | ||
832 | * get called on the bootup processor. But just in case. */ | ||
833 | if (!xen_initial_domain() || smp_processor_id()) | ||
834 | return 0; | ||
835 | |||
836 | if (reg == APIC_LVR) | ||
837 | return 0x10; | ||
838 | |||
839 | if (reg != APIC_ID) | ||
840 | return 0; | ||
841 | |||
842 | ret = HYPERVISOR_dom0_op(&op); | ||
843 | if (ret) | ||
844 | return 0; | ||
845 | |||
846 | return op.u.pcpu_info.apic_id << 24; | ||
815 | } | 847 | } |
816 | 848 | ||
817 | static void xen_apic_write(u32 reg, u32 val) | 849 | static void xen_apic_write(u32 reg, u32 val) |
@@ -849,6 +881,8 @@ static void set_xen_basic_apic_ops(void) | |||
849 | apic->icr_write = xen_apic_icr_write; | 881 | apic->icr_write = xen_apic_icr_write; |
850 | apic->wait_icr_idle = xen_apic_wait_icr_idle; | 882 | apic->wait_icr_idle = xen_apic_wait_icr_idle; |
851 | apic->safe_wait_icr_idle = xen_safe_apic_wait_icr_idle; | 883 | apic->safe_wait_icr_idle = xen_safe_apic_wait_icr_idle; |
884 | apic->set_apic_id = xen_set_apic_id; | ||
885 | apic->get_apic_id = xen_get_apic_id; | ||
852 | } | 886 | } |
853 | 887 | ||
854 | #endif | 888 | #endif |
@@ -1365,8 +1399,10 @@ asmlinkage void __init xen_start_kernel(void) | |||
1365 | /* Make sure ACS will be enabled */ | 1399 | /* Make sure ACS will be enabled */ |
1366 | pci_request_acs(); | 1400 | pci_request_acs(); |
1367 | } | 1401 | } |
1368 | 1402 | #ifdef CONFIG_PCI | |
1369 | 1403 | /* PCI BIOS service won't work from a PV guest. */ | |
1404 | pci_probe &= ~PCI_PROBE_BIOS; | ||
1405 | #endif | ||
1370 | xen_raw_console_write("about to get started...\n"); | 1406 | xen_raw_console_write("about to get started...\n"); |
1371 | 1407 | ||
1372 | xen_setup_runstate_info(0); | 1408 | xen_setup_runstate_info(0); |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index b8e279479a6b..69f5857660ac 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -353,8 +353,13 @@ static pteval_t pte_mfn_to_pfn(pteval_t val) | |||
353 | { | 353 | { |
354 | if (val & _PAGE_PRESENT) { | 354 | if (val & _PAGE_PRESENT) { |
355 | unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; | 355 | unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; |
356 | unsigned long pfn = mfn_to_pfn(mfn); | ||
357 | |||
356 | pteval_t flags = val & PTE_FLAGS_MASK; | 358 | pteval_t flags = val & PTE_FLAGS_MASK; |
357 | val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags; | 359 | if (unlikely(pfn == ~0)) |
360 | val = flags & ~_PAGE_PRESENT; | ||
361 | else | ||
362 | val = ((pteval_t)pfn << PAGE_SHIFT) | flags; | ||
358 | } | 363 | } |
359 | 364 | ||
360 | return val; | 365 | return val; |