diff options
Diffstat (limited to 'arch/x86')
55 files changed, 1248 insertions, 1070 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index efb42949cc09..67d6af3581bc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -26,6 +26,8 @@ config X86 | |||
26 | select HAVE_IOREMAP_PROT | 26 | select HAVE_IOREMAP_PROT |
27 | select HAVE_KPROBES | 27 | select HAVE_KPROBES |
28 | select HAVE_MEMBLOCK | 28 | select HAVE_MEMBLOCK |
29 | select HAVE_MEMBLOCK_NODE_MAP | ||
30 | select ARCH_DISCARD_MEMBLOCK | ||
29 | select ARCH_WANT_OPTIONAL_GPIOLIB | 31 | select ARCH_WANT_OPTIONAL_GPIOLIB |
30 | select ARCH_WANT_FRAME_POINTERS | 32 | select ARCH_WANT_FRAME_POINTERS |
31 | select HAVE_DMA_ATTRS | 33 | select HAVE_DMA_ATTRS |
@@ -204,9 +206,6 @@ config ZONE_DMA32 | |||
204 | bool | 206 | bool |
205 | default X86_64 | 207 | default X86_64 |
206 | 208 | ||
207 | config ARCH_POPULATES_NODE_MAP | ||
208 | def_bool y | ||
209 | |||
210 | config AUDIT_ARCH | 209 | config AUDIT_ARCH |
211 | bool | 210 | bool |
212 | default X86_64 | 211 | default X86_64 |
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 908b96957d88..37782566af24 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h | |||
@@ -117,7 +117,7 @@ static inline void early_memtest(unsigned long start, unsigned long end) | |||
117 | 117 | ||
118 | extern unsigned long e820_end_of_ram_pfn(void); | 118 | extern unsigned long e820_end_of_ram_pfn(void); |
119 | extern unsigned long e820_end_of_low_ram_pfn(void); | 119 | extern unsigned long e820_end_of_low_ram_pfn(void); |
120 | extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); | 120 | extern u64 early_reserve_e820(u64 sizet, u64 align); |
121 | 121 | ||
122 | void memblock_x86_fill(void); | 122 | void memblock_x86_fill(void); |
123 | void memblock_find_dma_reserve(void); | 123 | void memblock_find_dma_reserve(void); |
diff --git a/arch/x86/include/asm/insn.h b/arch/x86/include/asm/insn.h index 88c765e16410..74df3f1eddfd 100644 --- a/arch/x86/include/asm/insn.h +++ b/arch/x86/include/asm/insn.h | |||
@@ -137,6 +137,13 @@ static inline int insn_is_avx(struct insn *insn) | |||
137 | return (insn->vex_prefix.value != 0); | 137 | return (insn->vex_prefix.value != 0); |
138 | } | 138 | } |
139 | 139 | ||
140 | /* Ensure this instruction is decoded completely */ | ||
141 | static inline int insn_complete(struct insn *insn) | ||
142 | { | ||
143 | return insn->opcode.got && insn->modrm.got && insn->sib.got && | ||
144 | insn->displacement.got && insn->immediate.got; | ||
145 | } | ||
146 | |||
140 | static inline insn_byte_t insn_vex_m_bits(struct insn *insn) | 147 | static inline insn_byte_t insn_vex_m_bits(struct insn *insn) |
141 | { | 148 | { |
142 | if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ | 149 | if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ |
diff --git a/arch/x86/include/asm/memblock.h b/arch/x86/include/asm/memblock.h deleted file mode 100644 index 0cd3800f33b9..000000000000 --- a/arch/x86/include/asm/memblock.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | #ifndef _X86_MEMBLOCK_H | ||
2 | #define _X86_MEMBLOCK_H | ||
3 | |||
4 | #define ARCH_DISCARD_MEMBLOCK | ||
5 | |||
6 | u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align); | ||
7 | |||
8 | void memblock_x86_reserve_range(u64 start, u64 end, char *name); | ||
9 | void memblock_x86_free_range(u64 start, u64 end); | ||
10 | struct range; | ||
11 | int __get_free_all_memory_range(struct range **range, int nodeid, | ||
12 | unsigned long start_pfn, unsigned long end_pfn); | ||
13 | int get_free_all_memory_range(struct range **rangep, int nodeid); | ||
14 | |||
15 | void memblock_x86_register_active_regions(int nid, unsigned long start_pfn, | ||
16 | unsigned long last_pfn); | ||
17 | u64 memblock_x86_hole_size(u64 start, u64 end); | ||
18 | u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align); | ||
19 | u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit); | ||
20 | u64 memblock_x86_memory_in_range(u64 addr, u64 limit); | ||
21 | bool memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align); | ||
22 | |||
23 | #endif | ||
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index f61c62f7d5d8..096c975e099f 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h | |||
@@ -57,6 +57,7 @@ | |||
57 | (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX)) | 57 | (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX)) |
58 | 58 | ||
59 | #define ARCH_PERFMON_BRANCH_MISSES_RETIRED 6 | 59 | #define ARCH_PERFMON_BRANCH_MISSES_RETIRED 6 |
60 | #define ARCH_PERFMON_EVENTS_COUNT 7 | ||
60 | 61 | ||
61 | /* | 62 | /* |
62 | * Intel "Architectural Performance Monitoring" CPUID | 63 | * Intel "Architectural Performance Monitoring" CPUID |
@@ -72,6 +73,19 @@ union cpuid10_eax { | |||
72 | unsigned int full; | 73 | unsigned int full; |
73 | }; | 74 | }; |
74 | 75 | ||
76 | union cpuid10_ebx { | ||
77 | struct { | ||
78 | unsigned int no_unhalted_core_cycles:1; | ||
79 | unsigned int no_instructions_retired:1; | ||
80 | unsigned int no_unhalted_reference_cycles:1; | ||
81 | unsigned int no_llc_reference:1; | ||
82 | unsigned int no_llc_misses:1; | ||
83 | unsigned int no_branch_instruction_retired:1; | ||
84 | unsigned int no_branch_misses_retired:1; | ||
85 | } split; | ||
86 | unsigned int full; | ||
87 | }; | ||
88 | |||
75 | union cpuid10_edx { | 89 | union cpuid10_edx { |
76 | struct { | 90 | struct { |
77 | unsigned int num_counters_fixed:5; | 91 | unsigned int num_counters_fixed:5; |
@@ -81,6 +95,15 @@ union cpuid10_edx { | |||
81 | unsigned int full; | 95 | unsigned int full; |
82 | }; | 96 | }; |
83 | 97 | ||
98 | struct x86_pmu_capability { | ||
99 | int version; | ||
100 | int num_counters_gp; | ||
101 | int num_counters_fixed; | ||
102 | int bit_width_gp; | ||
103 | int bit_width_fixed; | ||
104 | unsigned int events_mask; | ||
105 | int events_mask_len; | ||
106 | }; | ||
84 | 107 | ||
85 | /* | 108 | /* |
86 | * Fixed-purpose performance events: | 109 | * Fixed-purpose performance events: |
@@ -89,23 +112,24 @@ union cpuid10_edx { | |||
89 | /* | 112 | /* |
90 | * All 3 fixed-mode PMCs are configured via this single MSR: | 113 | * All 3 fixed-mode PMCs are configured via this single MSR: |
91 | */ | 114 | */ |
92 | #define MSR_ARCH_PERFMON_FIXED_CTR_CTRL 0x38d | 115 | #define MSR_ARCH_PERFMON_FIXED_CTR_CTRL 0x38d |
93 | 116 | ||
94 | /* | 117 | /* |
95 | * The counts are available in three separate MSRs: | 118 | * The counts are available in three separate MSRs: |
96 | */ | 119 | */ |
97 | 120 | ||
98 | /* Instr_Retired.Any: */ | 121 | /* Instr_Retired.Any: */ |
99 | #define MSR_ARCH_PERFMON_FIXED_CTR0 0x309 | 122 | #define MSR_ARCH_PERFMON_FIXED_CTR0 0x309 |
100 | #define X86_PMC_IDX_FIXED_INSTRUCTIONS (X86_PMC_IDX_FIXED + 0) | 123 | #define X86_PMC_IDX_FIXED_INSTRUCTIONS (X86_PMC_IDX_FIXED + 0) |
101 | 124 | ||
102 | /* CPU_CLK_Unhalted.Core: */ | 125 | /* CPU_CLK_Unhalted.Core: */ |
103 | #define MSR_ARCH_PERFMON_FIXED_CTR1 0x30a | 126 | #define MSR_ARCH_PERFMON_FIXED_CTR1 0x30a |
104 | #define X86_PMC_IDX_FIXED_CPU_CYCLES (X86_PMC_IDX_FIXED + 1) | 127 | #define X86_PMC_IDX_FIXED_CPU_CYCLES (X86_PMC_IDX_FIXED + 1) |
105 | 128 | ||
106 | /* CPU_CLK_Unhalted.Ref: */ | 129 | /* CPU_CLK_Unhalted.Ref: */ |
107 | #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b | 130 | #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b |
108 | #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) | 131 | #define X86_PMC_IDX_FIXED_REF_CYCLES (X86_PMC_IDX_FIXED + 2) |
132 | #define X86_PMC_MSK_FIXED_REF_CYCLES (1ULL << X86_PMC_IDX_FIXED_REF_CYCLES) | ||
109 | 133 | ||
110 | /* | 134 | /* |
111 | * We model BTS tracing as another fixed-mode PMC. | 135 | * We model BTS tracing as another fixed-mode PMC. |
@@ -202,6 +226,7 @@ struct perf_guest_switch_msr { | |||
202 | }; | 226 | }; |
203 | 227 | ||
204 | extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr); | 228 | extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr); |
229 | extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap); | ||
205 | #else | 230 | #else |
206 | static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr) | 231 | static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr) |
207 | { | 232 | { |
@@ -209,6 +234,11 @@ static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr) | |||
209 | return NULL; | 234 | return NULL; |
210 | } | 235 | } |
211 | 236 | ||
237 | static inline void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap) | ||
238 | { | ||
239 | memset(cap, 0, sizeof(*cap)); | ||
240 | } | ||
241 | |||
212 | static inline void perf_events_lapic_init(void) { } | 242 | static inline void perf_events_lapic_init(void) { } |
213 | #endif | 243 | #endif |
214 | 244 | ||
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 3d2661ca6542..6e76c191a835 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c | |||
@@ -88,13 +88,13 @@ static u32 __init allocate_aperture(void) | |||
88 | */ | 88 | */ |
89 | addr = memblock_find_in_range(GART_MIN_ADDR, GART_MAX_ADDR, | 89 | addr = memblock_find_in_range(GART_MIN_ADDR, GART_MAX_ADDR, |
90 | aper_size, aper_size); | 90 | aper_size, aper_size); |
91 | if (addr == MEMBLOCK_ERROR || addr + aper_size > GART_MAX_ADDR) { | 91 | if (!addr || addr + aper_size > GART_MAX_ADDR) { |
92 | printk(KERN_ERR | 92 | printk(KERN_ERR |
93 | "Cannot allocate aperture memory hole (%lx,%uK)\n", | 93 | "Cannot allocate aperture memory hole (%lx,%uK)\n", |
94 | addr, aper_size>>10); | 94 | addr, aper_size>>10); |
95 | return 0; | 95 | return 0; |
96 | } | 96 | } |
97 | memblock_x86_reserve_range(addr, addr + aper_size, "aperture64"); | 97 | memblock_reserve(addr, aper_size); |
98 | /* | 98 | /* |
99 | * Kmemleak should not scan this block as it may not be mapped via the | 99 | * Kmemleak should not scan this block as it may not be mapped via the |
100 | * kernel direct mapping. | 100 | * kernel direct mapping. |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index f98d84caf94c..2cd2d93643dc 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -876,8 +876,8 @@ void __irq_entry smp_apic_timer_interrupt(struct pt_regs *regs) | |||
876 | * Besides, if we don't timer interrupts ignore the global | 876 | * Besides, if we don't timer interrupts ignore the global |
877 | * interrupt lock, which is the WrongThing (tm) to do. | 877 | * interrupt lock, which is the WrongThing (tm) to do. |
878 | */ | 878 | */ |
879 | exit_idle(); | ||
880 | irq_enter(); | 879 | irq_enter(); |
880 | exit_idle(); | ||
881 | local_apic_timer_interrupt(); | 881 | local_apic_timer_interrupt(); |
882 | irq_exit(); | 882 | irq_exit(); |
883 | 883 | ||
@@ -1809,8 +1809,8 @@ void smp_spurious_interrupt(struct pt_regs *regs) | |||
1809 | { | 1809 | { |
1810 | u32 v; | 1810 | u32 v; |
1811 | 1811 | ||
1812 | exit_idle(); | ||
1813 | irq_enter(); | 1812 | irq_enter(); |
1813 | exit_idle(); | ||
1814 | /* | 1814 | /* |
1815 | * Check if this really is a spurious interrupt and ACK it | 1815 | * Check if this really is a spurious interrupt and ACK it |
1816 | * if it is a vectored one. Just in case... | 1816 | * if it is a vectored one. Just in case... |
@@ -1846,8 +1846,8 @@ void smp_error_interrupt(struct pt_regs *regs) | |||
1846 | "Illegal register address", /* APIC Error Bit 7 */ | 1846 | "Illegal register address", /* APIC Error Bit 7 */ |
1847 | }; | 1847 | }; |
1848 | 1848 | ||
1849 | exit_idle(); | ||
1850 | irq_enter(); | 1849 | irq_enter(); |
1850 | exit_idle(); | ||
1851 | /* First tickle the hardware, only then report what went on. -- REW */ | 1851 | /* First tickle the hardware, only then report what went on. -- REW */ |
1852 | v0 = apic_read(APIC_ESR); | 1852 | v0 = apic_read(APIC_ESR); |
1853 | apic_write(APIC_ESR, 0); | 1853 | apic_write(APIC_ESR, 0); |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 6d939d7847e2..898055585516 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -2421,8 +2421,8 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) | |||
2421 | unsigned vector, me; | 2421 | unsigned vector, me; |
2422 | 2422 | ||
2423 | ack_APIC_irq(); | 2423 | ack_APIC_irq(); |
2424 | exit_idle(); | ||
2425 | irq_enter(); | 2424 | irq_enter(); |
2425 | exit_idle(); | ||
2426 | 2426 | ||
2427 | me = smp_processor_id(); | 2427 | me = smp_processor_id(); |
2428 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { | 2428 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { |
diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c index 452932d34730..5da1269e8ddc 100644 --- a/arch/x86/kernel/check.c +++ b/arch/x86/kernel/check.c | |||
@@ -62,7 +62,8 @@ early_param("memory_corruption_check_size", set_corruption_check_size); | |||
62 | 62 | ||
63 | void __init setup_bios_corruption_check(void) | 63 | void __init setup_bios_corruption_check(void) |
64 | { | 64 | { |
65 | u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */ | 65 | phys_addr_t start, end; |
66 | u64 i; | ||
66 | 67 | ||
67 | if (memory_corruption_check == -1) { | 68 | if (memory_corruption_check == -1) { |
68 | memory_corruption_check = | 69 | memory_corruption_check = |
@@ -82,28 +83,23 @@ void __init setup_bios_corruption_check(void) | |||
82 | 83 | ||
83 | corruption_check_size = round_up(corruption_check_size, PAGE_SIZE); | 84 | corruption_check_size = round_up(corruption_check_size, PAGE_SIZE); |
84 | 85 | ||
85 | while (addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) { | 86 | for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) { |
86 | u64 size; | 87 | start = clamp_t(phys_addr_t, round_up(start, PAGE_SIZE), |
87 | addr = memblock_x86_find_in_range_size(addr, &size, PAGE_SIZE); | 88 | PAGE_SIZE, corruption_check_size); |
89 | end = clamp_t(phys_addr_t, round_down(end, PAGE_SIZE), | ||
90 | PAGE_SIZE, corruption_check_size); | ||
91 | if (start >= end) | ||
92 | continue; | ||
88 | 93 | ||
89 | if (addr == MEMBLOCK_ERROR) | 94 | memblock_reserve(start, end - start); |
90 | break; | 95 | scan_areas[num_scan_areas].addr = start; |
91 | 96 | scan_areas[num_scan_areas].size = end - start; | |
92 | if (addr >= corruption_check_size) | ||
93 | break; | ||
94 | |||
95 | if ((addr + size) > corruption_check_size) | ||
96 | size = corruption_check_size - addr; | ||
97 | |||
98 | memblock_x86_reserve_range(addr, addr + size, "SCAN RAM"); | ||
99 | scan_areas[num_scan_areas].addr = addr; | ||
100 | scan_areas[num_scan_areas].size = size; | ||
101 | num_scan_areas++; | ||
102 | 97 | ||
103 | /* Assume we've already mapped this early memory */ | 98 | /* Assume we've already mapped this early memory */ |
104 | memset(__va(addr), 0, size); | 99 | memset(__va(start), 0, end - start); |
105 | 100 | ||
106 | addr += size; | 101 | if (++num_scan_areas >= MAX_SCAN_AREAS) |
102 | break; | ||
107 | } | 103 | } |
108 | 104 | ||
109 | if (num_scan_areas) | 105 | if (num_scan_areas) |
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 787e06c84ea6..ce215616d5b9 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c | |||
@@ -397,8 +397,8 @@ static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt; | |||
397 | 397 | ||
398 | asmlinkage void smp_thermal_interrupt(struct pt_regs *regs) | 398 | asmlinkage void smp_thermal_interrupt(struct pt_regs *regs) |
399 | { | 399 | { |
400 | exit_idle(); | ||
401 | irq_enter(); | 400 | irq_enter(); |
401 | exit_idle(); | ||
402 | inc_irq_stat(irq_thermal_count); | 402 | inc_irq_stat(irq_thermal_count); |
403 | smp_thermal_vector(); | 403 | smp_thermal_vector(); |
404 | irq_exit(); | 404 | irq_exit(); |
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c index d746df2909c9..aa578cadb940 100644 --- a/arch/x86/kernel/cpu/mcheck/threshold.c +++ b/arch/x86/kernel/cpu/mcheck/threshold.c | |||
@@ -19,8 +19,8 @@ void (*mce_threshold_vector)(void) = default_threshold_interrupt; | |||
19 | 19 | ||
20 | asmlinkage void smp_threshold_interrupt(void) | 20 | asmlinkage void smp_threshold_interrupt(void) |
21 | { | 21 | { |
22 | exit_idle(); | ||
23 | irq_enter(); | 22 | irq_enter(); |
23 | exit_idle(); | ||
24 | inc_irq_stat(irq_threshold_count); | 24 | inc_irq_stat(irq_threshold_count); |
25 | mce_threshold_vector(); | 25 | mce_threshold_vector(); |
26 | irq_exit(); | 26 | irq_exit(); |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 2bda212a0010..5adce1040b11 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -484,18 +484,195 @@ static inline int is_x86_event(struct perf_event *event) | |||
484 | return event->pmu == &pmu; | 484 | return event->pmu == &pmu; |
485 | } | 485 | } |
486 | 486 | ||
487 | /* | ||
488 | * Event scheduler state: | ||
489 | * | ||
490 | * Assign events iterating over all events and counters, beginning | ||
491 | * with events with least weights first. Keep the current iterator | ||
492 | * state in struct sched_state. | ||
493 | */ | ||
494 | struct sched_state { | ||
495 | int weight; | ||
496 | int event; /* event index */ | ||
497 | int counter; /* counter index */ | ||
498 | int unassigned; /* number of events to be assigned left */ | ||
499 | unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | ||
500 | }; | ||
501 | |||
502 | /* Total max is X86_PMC_IDX_MAX, but we are O(n!) limited */ | ||
503 | #define SCHED_STATES_MAX 2 | ||
504 | |||
505 | struct perf_sched { | ||
506 | int max_weight; | ||
507 | int max_events; | ||
508 | struct event_constraint **constraints; | ||
509 | struct sched_state state; | ||
510 | int saved_states; | ||
511 | struct sched_state saved[SCHED_STATES_MAX]; | ||
512 | }; | ||
513 | |||
514 | /* | ||
515 | * Initialize interator that runs through all events and counters. | ||
516 | */ | ||
517 | static void perf_sched_init(struct perf_sched *sched, struct event_constraint **c, | ||
518 | int num, int wmin, int wmax) | ||
519 | { | ||
520 | int idx; | ||
521 | |||
522 | memset(sched, 0, sizeof(*sched)); | ||
523 | sched->max_events = num; | ||
524 | sched->max_weight = wmax; | ||
525 | sched->constraints = c; | ||
526 | |||
527 | for (idx = 0; idx < num; idx++) { | ||
528 | if (c[idx]->weight == wmin) | ||
529 | break; | ||
530 | } | ||
531 | |||
532 | sched->state.event = idx; /* start with min weight */ | ||
533 | sched->state.weight = wmin; | ||
534 | sched->state.unassigned = num; | ||
535 | } | ||
536 | |||
537 | static void perf_sched_save_state(struct perf_sched *sched) | ||
538 | { | ||
539 | if (WARN_ON_ONCE(sched->saved_states >= SCHED_STATES_MAX)) | ||
540 | return; | ||
541 | |||
542 | sched->saved[sched->saved_states] = sched->state; | ||
543 | sched->saved_states++; | ||
544 | } | ||
545 | |||
546 | static bool perf_sched_restore_state(struct perf_sched *sched) | ||
547 | { | ||
548 | if (!sched->saved_states) | ||
549 | return false; | ||
550 | |||
551 | sched->saved_states--; | ||
552 | sched->state = sched->saved[sched->saved_states]; | ||
553 | |||
554 | /* continue with next counter: */ | ||
555 | clear_bit(sched->state.counter++, sched->state.used); | ||
556 | |||
557 | return true; | ||
558 | } | ||
559 | |||
560 | /* | ||
561 | * Select a counter for the current event to schedule. Return true on | ||
562 | * success. | ||
563 | */ | ||
564 | static bool __perf_sched_find_counter(struct perf_sched *sched) | ||
565 | { | ||
566 | struct event_constraint *c; | ||
567 | int idx; | ||
568 | |||
569 | if (!sched->state.unassigned) | ||
570 | return false; | ||
571 | |||
572 | if (sched->state.event >= sched->max_events) | ||
573 | return false; | ||
574 | |||
575 | c = sched->constraints[sched->state.event]; | ||
576 | |||
577 | /* Prefer fixed purpose counters */ | ||
578 | if (x86_pmu.num_counters_fixed) { | ||
579 | idx = X86_PMC_IDX_FIXED; | ||
580 | for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_MAX) { | ||
581 | if (!__test_and_set_bit(idx, sched->state.used)) | ||
582 | goto done; | ||
583 | } | ||
584 | } | ||
585 | /* Grab the first unused counter starting with idx */ | ||
586 | idx = sched->state.counter; | ||
587 | for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_FIXED) { | ||
588 | if (!__test_and_set_bit(idx, sched->state.used)) | ||
589 | goto done; | ||
590 | } | ||
591 | |||
592 | return false; | ||
593 | |||
594 | done: | ||
595 | sched->state.counter = idx; | ||
596 | |||
597 | if (c->overlap) | ||
598 | perf_sched_save_state(sched); | ||
599 | |||
600 | return true; | ||
601 | } | ||
602 | |||
603 | static bool perf_sched_find_counter(struct perf_sched *sched) | ||
604 | { | ||
605 | while (!__perf_sched_find_counter(sched)) { | ||
606 | if (!perf_sched_restore_state(sched)) | ||
607 | return false; | ||
608 | } | ||
609 | |||
610 | return true; | ||
611 | } | ||
612 | |||
613 | /* | ||
614 | * Go through all unassigned events and find the next one to schedule. | ||
615 | * Take events with the least weight first. Return true on success. | ||
616 | */ | ||
617 | static bool perf_sched_next_event(struct perf_sched *sched) | ||
618 | { | ||
619 | struct event_constraint *c; | ||
620 | |||
621 | if (!sched->state.unassigned || !--sched->state.unassigned) | ||
622 | return false; | ||
623 | |||
624 | do { | ||
625 | /* next event */ | ||
626 | sched->state.event++; | ||
627 | if (sched->state.event >= sched->max_events) { | ||
628 | /* next weight */ | ||
629 | sched->state.event = 0; | ||
630 | sched->state.weight++; | ||
631 | if (sched->state.weight > sched->max_weight) | ||
632 | return false; | ||
633 | } | ||
634 | c = sched->constraints[sched->state.event]; | ||
635 | } while (c->weight != sched->state.weight); | ||
636 | |||
637 | sched->state.counter = 0; /* start with first counter */ | ||
638 | |||
639 | return true; | ||
640 | } | ||
641 | |||
642 | /* | ||
643 | * Assign a counter for each event. | ||
644 | */ | ||
645 | static int perf_assign_events(struct event_constraint **constraints, int n, | ||
646 | int wmin, int wmax, int *assign) | ||
647 | { | ||
648 | struct perf_sched sched; | ||
649 | |||
650 | perf_sched_init(&sched, constraints, n, wmin, wmax); | ||
651 | |||
652 | do { | ||
653 | if (!perf_sched_find_counter(&sched)) | ||
654 | break; /* failed */ | ||
655 | if (assign) | ||
656 | assign[sched.state.event] = sched.state.counter; | ||
657 | } while (perf_sched_next_event(&sched)); | ||
658 | |||
659 | return sched.state.unassigned; | ||
660 | } | ||
661 | |||
487 | int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | 662 | int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) |
488 | { | 663 | { |
489 | struct event_constraint *c, *constraints[X86_PMC_IDX_MAX]; | 664 | struct event_constraint *c, *constraints[X86_PMC_IDX_MAX]; |
490 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 665 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
491 | int i, j, w, wmax, num = 0; | 666 | int i, wmin, wmax, num = 0; |
492 | struct hw_perf_event *hwc; | 667 | struct hw_perf_event *hwc; |
493 | 668 | ||
494 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); | 669 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); |
495 | 670 | ||
496 | for (i = 0; i < n; i++) { | 671 | for (i = 0, wmin = X86_PMC_IDX_MAX, wmax = 0; i < n; i++) { |
497 | c = x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]); | 672 | c = x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]); |
498 | constraints[i] = c; | 673 | constraints[i] = c; |
674 | wmin = min(wmin, c->weight); | ||
675 | wmax = max(wmax, c->weight); | ||
499 | } | 676 | } |
500 | 677 | ||
501 | /* | 678 | /* |
@@ -521,60 +698,12 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | |||
521 | if (assign) | 698 | if (assign) |
522 | assign[i] = hwc->idx; | 699 | assign[i] = hwc->idx; |
523 | } | 700 | } |
524 | if (i == n) | ||
525 | goto done; | ||
526 | |||
527 | /* | ||
528 | * begin slow path | ||
529 | */ | ||
530 | |||
531 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); | ||
532 | 701 | ||
533 | /* | 702 | /* slow path */ |
534 | * weight = number of possible counters | 703 | if (i != n) |
535 | * | 704 | num = perf_assign_events(constraints, n, wmin, wmax, assign); |
536 | * 1 = most constrained, only works on one counter | ||
537 | * wmax = least constrained, works on any counter | ||
538 | * | ||
539 | * assign events to counters starting with most | ||
540 | * constrained events. | ||
541 | */ | ||
542 | wmax = x86_pmu.num_counters; | ||
543 | 705 | ||
544 | /* | 706 | /* |
545 | * when fixed event counters are present, | ||
546 | * wmax is incremented by 1 to account | ||
547 | * for one more choice | ||
548 | */ | ||
549 | if (x86_pmu.num_counters_fixed) | ||
550 | wmax++; | ||
551 | |||
552 | for (w = 1, num = n; num && w <= wmax; w++) { | ||
553 | /* for each event */ | ||
554 | for (i = 0; num && i < n; i++) { | ||
555 | c = constraints[i]; | ||
556 | hwc = &cpuc->event_list[i]->hw; | ||
557 | |||
558 | if (c->weight != w) | ||
559 | continue; | ||
560 | |||
561 | for_each_set_bit(j, c->idxmsk, X86_PMC_IDX_MAX) { | ||
562 | if (!test_bit(j, used_mask)) | ||
563 | break; | ||
564 | } | ||
565 | |||
566 | if (j == X86_PMC_IDX_MAX) | ||
567 | break; | ||
568 | |||
569 | __set_bit(j, used_mask); | ||
570 | |||
571 | if (assign) | ||
572 | assign[i] = j; | ||
573 | num--; | ||
574 | } | ||
575 | } | ||
576 | done: | ||
577 | /* | ||
578 | * scheduling failed or is just a simulation, | 707 | * scheduling failed or is just a simulation, |
579 | * free resources if necessary | 708 | * free resources if necessary |
580 | */ | 709 | */ |
@@ -1119,6 +1248,7 @@ static void __init pmu_check_apic(void) | |||
1119 | 1248 | ||
1120 | static int __init init_hw_perf_events(void) | 1249 | static int __init init_hw_perf_events(void) |
1121 | { | 1250 | { |
1251 | struct x86_pmu_quirk *quirk; | ||
1122 | struct event_constraint *c; | 1252 | struct event_constraint *c; |
1123 | int err; | 1253 | int err; |
1124 | 1254 | ||
@@ -1147,8 +1277,8 @@ static int __init init_hw_perf_events(void) | |||
1147 | 1277 | ||
1148 | pr_cont("%s PMU driver.\n", x86_pmu.name); | 1278 | pr_cont("%s PMU driver.\n", x86_pmu.name); |
1149 | 1279 | ||
1150 | if (x86_pmu.quirks) | 1280 | for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next) |
1151 | x86_pmu.quirks(); | 1281 | quirk->func(); |
1152 | 1282 | ||
1153 | if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) { | 1283 | if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) { |
1154 | WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!", | 1284 | WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!", |
@@ -1171,12 +1301,18 @@ static int __init init_hw_perf_events(void) | |||
1171 | 1301 | ||
1172 | unconstrained = (struct event_constraint) | 1302 | unconstrained = (struct event_constraint) |
1173 | __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1, | 1303 | __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1, |
1174 | 0, x86_pmu.num_counters); | 1304 | 0, x86_pmu.num_counters, 0); |
1175 | 1305 | ||
1176 | if (x86_pmu.event_constraints) { | 1306 | if (x86_pmu.event_constraints) { |
1307 | /* | ||
1308 | * event on fixed counter2 (REF_CYCLES) only works on this | ||
1309 | * counter, so do not extend mask to generic counters | ||
1310 | */ | ||
1177 | for_each_event_constraint(c, x86_pmu.event_constraints) { | 1311 | for_each_event_constraint(c, x86_pmu.event_constraints) { |
1178 | if (c->cmask != X86_RAW_EVENT_MASK) | 1312 | if (c->cmask != X86_RAW_EVENT_MASK |
1313 | || c->idxmsk64 == X86_PMC_MSK_FIXED_REF_CYCLES) { | ||
1179 | continue; | 1314 | continue; |
1315 | } | ||
1180 | 1316 | ||
1181 | c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1; | 1317 | c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1; |
1182 | c->weight += x86_pmu.num_counters; | 1318 | c->weight += x86_pmu.num_counters; |
@@ -1566,3 +1702,15 @@ unsigned long perf_misc_flags(struct pt_regs *regs) | |||
1566 | 1702 | ||
1567 | return misc; | 1703 | return misc; |
1568 | } | 1704 | } |
1705 | |||
1706 | void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap) | ||
1707 | { | ||
1708 | cap->version = x86_pmu.version; | ||
1709 | cap->num_counters_gp = x86_pmu.num_counters; | ||
1710 | cap->num_counters_fixed = x86_pmu.num_counters_fixed; | ||
1711 | cap->bit_width_gp = x86_pmu.cntval_bits; | ||
1712 | cap->bit_width_fixed = x86_pmu.cntval_bits; | ||
1713 | cap->events_mask = (unsigned int)x86_pmu.events_maskl; | ||
1714 | cap->events_mask_len = x86_pmu.events_mask_len; | ||
1715 | } | ||
1716 | EXPORT_SYMBOL_GPL(perf_get_x86_pmu_capability); | ||
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index b9698d40ac4b..8944062f46e2 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
@@ -45,6 +45,7 @@ struct event_constraint { | |||
45 | u64 code; | 45 | u64 code; |
46 | u64 cmask; | 46 | u64 cmask; |
47 | int weight; | 47 | int weight; |
48 | int overlap; | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | struct amd_nb { | 51 | struct amd_nb { |
@@ -151,15 +152,40 @@ struct cpu_hw_events { | |||
151 | void *kfree_on_online; | 152 | void *kfree_on_online; |
152 | }; | 153 | }; |
153 | 154 | ||
154 | #define __EVENT_CONSTRAINT(c, n, m, w) {\ | 155 | #define __EVENT_CONSTRAINT(c, n, m, w, o) {\ |
155 | { .idxmsk64 = (n) }, \ | 156 | { .idxmsk64 = (n) }, \ |
156 | .code = (c), \ | 157 | .code = (c), \ |
157 | .cmask = (m), \ | 158 | .cmask = (m), \ |
158 | .weight = (w), \ | 159 | .weight = (w), \ |
160 | .overlap = (o), \ | ||
159 | } | 161 | } |
160 | 162 | ||
161 | #define EVENT_CONSTRAINT(c, n, m) \ | 163 | #define EVENT_CONSTRAINT(c, n, m) \ |
162 | __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n)) | 164 | __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n), 0) |
165 | |||
166 | /* | ||
167 | * The overlap flag marks event constraints with overlapping counter | ||
168 | * masks. This is the case if the counter mask of such an event is not | ||
169 | * a subset of any other counter mask of a constraint with an equal or | ||
170 | * higher weight, e.g.: | ||
171 | * | ||
172 | * c_overlaps = EVENT_CONSTRAINT_OVERLAP(0, 0x09, 0); | ||
173 | * c_another1 = EVENT_CONSTRAINT(0, 0x07, 0); | ||
174 | * c_another2 = EVENT_CONSTRAINT(0, 0x38, 0); | ||
175 | * | ||
176 | * The event scheduler may not select the correct counter in the first | ||
177 | * cycle because it needs to know which subsequent events will be | ||
178 | * scheduled. It may fail to schedule the events then. So we set the | ||
179 | * overlap flag for such constraints to give the scheduler a hint which | ||
180 | * events to select for counter rescheduling. | ||
181 | * | ||
182 | * Care must be taken as the rescheduling algorithm is O(n!) which | ||
183 | * will increase scheduling cycles for an over-commited system | ||
184 | * dramatically. The number of such EVENT_CONSTRAINT_OVERLAP() macros | ||
185 | * and its counter masks must be kept at a minimum. | ||
186 | */ | ||
187 | #define EVENT_CONSTRAINT_OVERLAP(c, n, m) \ | ||
188 | __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n), 1) | ||
163 | 189 | ||
164 | /* | 190 | /* |
165 | * Constraint on the Event code. | 191 | * Constraint on the Event code. |
@@ -235,6 +261,11 @@ union perf_capabilities { | |||
235 | u64 capabilities; | 261 | u64 capabilities; |
236 | }; | 262 | }; |
237 | 263 | ||
264 | struct x86_pmu_quirk { | ||
265 | struct x86_pmu_quirk *next; | ||
266 | void (*func)(void); | ||
267 | }; | ||
268 | |||
238 | /* | 269 | /* |
239 | * struct x86_pmu - generic x86 pmu | 270 | * struct x86_pmu - generic x86 pmu |
240 | */ | 271 | */ |
@@ -259,6 +290,11 @@ struct x86_pmu { | |||
259 | int num_counters_fixed; | 290 | int num_counters_fixed; |
260 | int cntval_bits; | 291 | int cntval_bits; |
261 | u64 cntval_mask; | 292 | u64 cntval_mask; |
293 | union { | ||
294 | unsigned long events_maskl; | ||
295 | unsigned long events_mask[BITS_TO_LONGS(ARCH_PERFMON_EVENTS_COUNT)]; | ||
296 | }; | ||
297 | int events_mask_len; | ||
262 | int apic; | 298 | int apic; |
263 | u64 max_period; | 299 | u64 max_period; |
264 | struct event_constraint * | 300 | struct event_constraint * |
@@ -268,7 +304,7 @@ struct x86_pmu { | |||
268 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, | 304 | void (*put_event_constraints)(struct cpu_hw_events *cpuc, |
269 | struct perf_event *event); | 305 | struct perf_event *event); |
270 | struct event_constraint *event_constraints; | 306 | struct event_constraint *event_constraints; |
271 | void (*quirks)(void); | 307 | struct x86_pmu_quirk *quirks; |
272 | int perfctr_second_write; | 308 | int perfctr_second_write; |
273 | 309 | ||
274 | int (*cpu_prepare)(int cpu); | 310 | int (*cpu_prepare)(int cpu); |
@@ -309,6 +345,15 @@ struct x86_pmu { | |||
309 | struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr); | 345 | struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr); |
310 | }; | 346 | }; |
311 | 347 | ||
348 | #define x86_add_quirk(func_) \ | ||
349 | do { \ | ||
350 | static struct x86_pmu_quirk __quirk __initdata = { \ | ||
351 | .func = func_, \ | ||
352 | }; \ | ||
353 | __quirk.next = x86_pmu.quirks; \ | ||
354 | x86_pmu.quirks = &__quirk; \ | ||
355 | } while (0) | ||
356 | |||
312 | #define ERF_NO_HT_SHARING 1 | 357 | #define ERF_NO_HT_SHARING 1 |
313 | #define ERF_HAS_RSP_1 2 | 358 | #define ERF_HAS_RSP_1 2 |
314 | 359 | ||
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index aeefd45697a2..0397b23be8e9 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c | |||
@@ -492,7 +492,7 @@ static __initconst const struct x86_pmu amd_pmu = { | |||
492 | static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0); | 492 | static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0); |
493 | static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0); | 493 | static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0); |
494 | static struct event_constraint amd_f15_PMC3 = EVENT_CONSTRAINT(0, 0x08, 0); | 494 | static struct event_constraint amd_f15_PMC3 = EVENT_CONSTRAINT(0, 0x08, 0); |
495 | static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT(0, 0x09, 0); | 495 | static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT_OVERLAP(0, 0x09, 0); |
496 | static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0); | 496 | static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0); |
497 | static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0); | 497 | static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0); |
498 | 498 | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 8d601b18bf9f..3bd37bdf1b8e 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -28,6 +28,7 @@ static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly = | |||
28 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, | 28 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, |
29 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, | 29 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, |
30 | [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, | 30 | [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, |
31 | [PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding */ | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | static struct event_constraint intel_core_event_constraints[] __read_mostly = | 34 | static struct event_constraint intel_core_event_constraints[] __read_mostly = |
@@ -45,12 +46,7 @@ static struct event_constraint intel_core2_event_constraints[] __read_mostly = | |||
45 | { | 46 | { |
46 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | 47 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
47 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | 48 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
48 | /* | 49 | FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ |
49 | * Core2 has Fixed Counter 2 listed as CPU_CLK_UNHALTED.REF and event | ||
50 | * 0x013c as CPU_CLK_UNHALTED.BUS and specifies there is a fixed | ||
51 | * ratio between these counters. | ||
52 | */ | ||
53 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | ||
54 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ | 50 | INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ |
55 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ | 51 | INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ |
56 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ | 52 | INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ |
@@ -68,7 +64,7 @@ static struct event_constraint intel_nehalem_event_constraints[] __read_mostly = | |||
68 | { | 64 | { |
69 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | 65 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
70 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | 66 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
71 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | 67 | FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ |
72 | INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */ | 68 | INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */ |
73 | INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ | 69 | INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ |
74 | INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ | 70 | INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ |
@@ -90,7 +86,7 @@ static struct event_constraint intel_westmere_event_constraints[] __read_mostly | |||
90 | { | 86 | { |
91 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | 87 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
92 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | 88 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
93 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | 89 | FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ |
94 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ | 90 | INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */ |
95 | INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ | 91 | INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ |
96 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ | 92 | INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ |
@@ -102,7 +98,7 @@ static struct event_constraint intel_snb_event_constraints[] __read_mostly = | |||
102 | { | 98 | { |
103 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | 99 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
104 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | 100 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
105 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | 101 | FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ |
106 | INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */ | 102 | INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */ |
107 | INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */ | 103 | INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */ |
108 | INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */ | 104 | INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */ |
@@ -125,7 +121,7 @@ static struct event_constraint intel_gen_event_constraints[] __read_mostly = | |||
125 | { | 121 | { |
126 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ | 122 | FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ |
127 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ | 123 | FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ |
128 | /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */ | 124 | FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ |
129 | EVENT_CONSTRAINT_END | 125 | EVENT_CONSTRAINT_END |
130 | }; | 126 | }; |
131 | 127 | ||
@@ -1169,7 +1165,7 @@ again: | |||
1169 | */ | 1165 | */ |
1170 | c = &unconstrained; | 1166 | c = &unconstrained; |
1171 | } else if (intel_try_alt_er(event, orig_idx)) { | 1167 | } else if (intel_try_alt_er(event, orig_idx)) { |
1172 | raw_spin_unlock(&era->lock); | 1168 | raw_spin_unlock_irqrestore(&era->lock, flags); |
1173 | goto again; | 1169 | goto again; |
1174 | } | 1170 | } |
1175 | raw_spin_unlock_irqrestore(&era->lock, flags); | 1171 | raw_spin_unlock_irqrestore(&era->lock, flags); |
@@ -1519,7 +1515,7 @@ static __initconst const struct x86_pmu intel_pmu = { | |||
1519 | .guest_get_msrs = intel_guest_get_msrs, | 1515 | .guest_get_msrs = intel_guest_get_msrs, |
1520 | }; | 1516 | }; |
1521 | 1517 | ||
1522 | static void intel_clovertown_quirks(void) | 1518 | static __init void intel_clovertown_quirk(void) |
1523 | { | 1519 | { |
1524 | /* | 1520 | /* |
1525 | * PEBS is unreliable due to: | 1521 | * PEBS is unreliable due to: |
@@ -1545,19 +1541,60 @@ static void intel_clovertown_quirks(void) | |||
1545 | x86_pmu.pebs_constraints = NULL; | 1541 | x86_pmu.pebs_constraints = NULL; |
1546 | } | 1542 | } |
1547 | 1543 | ||
1548 | static void intel_sandybridge_quirks(void) | 1544 | static __init void intel_sandybridge_quirk(void) |
1549 | { | 1545 | { |
1550 | printk(KERN_WARNING "PEBS disabled due to CPU errata.\n"); | 1546 | printk(KERN_WARNING "PEBS disabled due to CPU errata.\n"); |
1551 | x86_pmu.pebs = 0; | 1547 | x86_pmu.pebs = 0; |
1552 | x86_pmu.pebs_constraints = NULL; | 1548 | x86_pmu.pebs_constraints = NULL; |
1553 | } | 1549 | } |
1554 | 1550 | ||
1551 | static const struct { int id; char *name; } intel_arch_events_map[] __initconst = { | ||
1552 | { PERF_COUNT_HW_CPU_CYCLES, "cpu cycles" }, | ||
1553 | { PERF_COUNT_HW_INSTRUCTIONS, "instructions" }, | ||
1554 | { PERF_COUNT_HW_BUS_CYCLES, "bus cycles" }, | ||
1555 | { PERF_COUNT_HW_CACHE_REFERENCES, "cache references" }, | ||
1556 | { PERF_COUNT_HW_CACHE_MISSES, "cache misses" }, | ||
1557 | { PERF_COUNT_HW_BRANCH_INSTRUCTIONS, "branch instructions" }, | ||
1558 | { PERF_COUNT_HW_BRANCH_MISSES, "branch misses" }, | ||
1559 | }; | ||
1560 | |||
1561 | static __init void intel_arch_events_quirk(void) | ||
1562 | { | ||
1563 | int bit; | ||
1564 | |||
1565 | /* disable event that reported as not presend by cpuid */ | ||
1566 | for_each_set_bit(bit, x86_pmu.events_mask, ARRAY_SIZE(intel_arch_events_map)) { | ||
1567 | intel_perfmon_event_map[intel_arch_events_map[bit].id] = 0; | ||
1568 | printk(KERN_WARNING "CPUID marked event: \'%s\' unavailable\n", | ||
1569 | intel_arch_events_map[bit].name); | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | static __init void intel_nehalem_quirk(void) | ||
1574 | { | ||
1575 | union cpuid10_ebx ebx; | ||
1576 | |||
1577 | ebx.full = x86_pmu.events_maskl; | ||
1578 | if (ebx.split.no_branch_misses_retired) { | ||
1579 | /* | ||
1580 | * Erratum AAJ80 detected, we work it around by using | ||
1581 | * the BR_MISP_EXEC.ANY event. This will over-count | ||
1582 | * branch-misses, but it's still much better than the | ||
1583 | * architectural event which is often completely bogus: | ||
1584 | */ | ||
1585 | intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89; | ||
1586 | ebx.split.no_branch_misses_retired = 0; | ||
1587 | x86_pmu.events_maskl = ebx.full; | ||
1588 | printk(KERN_INFO "CPU erratum AAJ80 worked around\n"); | ||
1589 | } | ||
1590 | } | ||
1591 | |||
1555 | __init int intel_pmu_init(void) | 1592 | __init int intel_pmu_init(void) |
1556 | { | 1593 | { |
1557 | union cpuid10_edx edx; | 1594 | union cpuid10_edx edx; |
1558 | union cpuid10_eax eax; | 1595 | union cpuid10_eax eax; |
1596 | union cpuid10_ebx ebx; | ||
1559 | unsigned int unused; | 1597 | unsigned int unused; |
1560 | unsigned int ebx; | ||
1561 | int version; | 1598 | int version; |
1562 | 1599 | ||
1563 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { | 1600 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { |
@@ -1574,8 +1611,8 @@ __init int intel_pmu_init(void) | |||
1574 | * Check whether the Architectural PerfMon supports | 1611 | * Check whether the Architectural PerfMon supports |
1575 | * Branch Misses Retired hw_event or not. | 1612 | * Branch Misses Retired hw_event or not. |
1576 | */ | 1613 | */ |
1577 | cpuid(10, &eax.full, &ebx, &unused, &edx.full); | 1614 | cpuid(10, &eax.full, &ebx.full, &unused, &edx.full); |
1578 | if (eax.split.mask_length <= ARCH_PERFMON_BRANCH_MISSES_RETIRED) | 1615 | if (eax.split.mask_length < ARCH_PERFMON_EVENTS_COUNT) |
1579 | return -ENODEV; | 1616 | return -ENODEV; |
1580 | 1617 | ||
1581 | version = eax.split.version_id; | 1618 | version = eax.split.version_id; |
@@ -1589,6 +1626,9 @@ __init int intel_pmu_init(void) | |||
1589 | x86_pmu.cntval_bits = eax.split.bit_width; | 1626 | x86_pmu.cntval_bits = eax.split.bit_width; |
1590 | x86_pmu.cntval_mask = (1ULL << eax.split.bit_width) - 1; | 1627 | x86_pmu.cntval_mask = (1ULL << eax.split.bit_width) - 1; |
1591 | 1628 | ||
1629 | x86_pmu.events_maskl = ebx.full; | ||
1630 | x86_pmu.events_mask_len = eax.split.mask_length; | ||
1631 | |||
1592 | /* | 1632 | /* |
1593 | * Quirk: v2 perfmon does not report fixed-purpose events, so | 1633 | * Quirk: v2 perfmon does not report fixed-purpose events, so |
1594 | * assume at least 3 events: | 1634 | * assume at least 3 events: |
@@ -1608,6 +1648,8 @@ __init int intel_pmu_init(void) | |||
1608 | 1648 | ||
1609 | intel_ds_init(); | 1649 | intel_ds_init(); |
1610 | 1650 | ||
1651 | x86_add_quirk(intel_arch_events_quirk); /* Install first, so it runs last */ | ||
1652 | |||
1611 | /* | 1653 | /* |
1612 | * Install the hw-cache-events table: | 1654 | * Install the hw-cache-events table: |
1613 | */ | 1655 | */ |
@@ -1617,7 +1659,7 @@ __init int intel_pmu_init(void) | |||
1617 | break; | 1659 | break; |
1618 | 1660 | ||
1619 | case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ | 1661 | case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ |
1620 | x86_pmu.quirks = intel_clovertown_quirks; | 1662 | x86_add_quirk(intel_clovertown_quirk); |
1621 | case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ | 1663 | case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ |
1622 | case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ | 1664 | case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ |
1623 | case 29: /* six-core 45 nm xeon "Dunnington" */ | 1665 | case 29: /* six-core 45 nm xeon "Dunnington" */ |
@@ -1651,17 +1693,8 @@ __init int intel_pmu_init(void) | |||
1651 | /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */ | 1693 | /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */ |
1652 | intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x1803fb1; | 1694 | intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x1803fb1; |
1653 | 1695 | ||
1654 | if (ebx & 0x40) { | 1696 | x86_add_quirk(intel_nehalem_quirk); |
1655 | /* | ||
1656 | * Erratum AAJ80 detected, we work it around by using | ||
1657 | * the BR_MISP_EXEC.ANY event. This will over-count | ||
1658 | * branch-misses, but it's still much better than the | ||
1659 | * architectural event which is often completely bogus: | ||
1660 | */ | ||
1661 | intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89; | ||
1662 | 1697 | ||
1663 | pr_cont("erratum AAJ80 worked around, "); | ||
1664 | } | ||
1665 | pr_cont("Nehalem events, "); | 1698 | pr_cont("Nehalem events, "); |
1666 | break; | 1699 | break; |
1667 | 1700 | ||
@@ -1701,7 +1734,7 @@ __init int intel_pmu_init(void) | |||
1701 | break; | 1734 | break; |
1702 | 1735 | ||
1703 | case 42: /* SandyBridge */ | 1736 | case 42: /* SandyBridge */ |
1704 | x86_pmu.quirks = intel_sandybridge_quirks; | 1737 | x86_add_quirk(intel_sandybridge_quirk); |
1705 | case 45: /* SandyBridge, "Romely-EP" */ | 1738 | case 45: /* SandyBridge, "Romely-EP" */ |
1706 | memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, | 1739 | memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, |
1707 | sizeof(hw_cache_event_ids)); | 1740 | sizeof(hw_cache_event_ids)); |
@@ -1738,5 +1771,6 @@ __init int intel_pmu_init(void) | |||
1738 | break; | 1771 | break; |
1739 | } | 1772 | } |
1740 | } | 1773 | } |
1774 | |||
1741 | return 0; | 1775 | return 0; |
1742 | } | 1776 | } |
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index 3b97a80ce329..c99f9ed013d5 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c | |||
@@ -116,16 +116,16 @@ void show_registers(struct pt_regs *regs) | |||
116 | for (i = 0; i < code_len; i++, ip++) { | 116 | for (i = 0; i < code_len; i++, ip++) { |
117 | if (ip < (u8 *)PAGE_OFFSET || | 117 | if (ip < (u8 *)PAGE_OFFSET || |
118 | probe_kernel_address(ip, c)) { | 118 | probe_kernel_address(ip, c)) { |
119 | printk(" Bad EIP value."); | 119 | printk(KERN_CONT " Bad EIP value."); |
120 | break; | 120 | break; |
121 | } | 121 | } |
122 | if (ip == (u8 *)regs->ip) | 122 | if (ip == (u8 *)regs->ip) |
123 | printk("<%02x> ", c); | 123 | printk(KERN_CONT "<%02x> ", c); |
124 | else | 124 | else |
125 | printk("%02x ", c); | 125 | printk(KERN_CONT "%02x ", c); |
126 | } | 126 | } |
127 | } | 127 | } |
128 | printk("\n"); | 128 | printk(KERN_CONT "\n"); |
129 | } | 129 | } |
130 | 130 | ||
131 | int is_valid_bugaddr(unsigned long ip) | 131 | int is_valid_bugaddr(unsigned long ip) |
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 19853ad8afc5..6d728d9284bd 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c | |||
@@ -284,16 +284,16 @@ void show_registers(struct pt_regs *regs) | |||
284 | for (i = 0; i < code_len; i++, ip++) { | 284 | for (i = 0; i < code_len; i++, ip++) { |
285 | if (ip < (u8 *)PAGE_OFFSET || | 285 | if (ip < (u8 *)PAGE_OFFSET || |
286 | probe_kernel_address(ip, c)) { | 286 | probe_kernel_address(ip, c)) { |
287 | printk(" Bad RIP value."); | 287 | printk(KERN_CONT " Bad RIP value."); |
288 | break; | 288 | break; |
289 | } | 289 | } |
290 | if (ip == (u8 *)regs->ip) | 290 | if (ip == (u8 *)regs->ip) |
291 | printk("<%02x> ", c); | 291 | printk(KERN_CONT "<%02x> ", c); |
292 | else | 292 | else |
293 | printk("%02x ", c); | 293 | printk(KERN_CONT "%02x ", c); |
294 | } | 294 | } |
295 | } | 295 | } |
296 | printk("\n"); | 296 | printk(KERN_CONT "\n"); |
297 | } | 297 | } |
298 | 298 | ||
299 | int is_valid_bugaddr(unsigned long ip) | 299 | int is_valid_bugaddr(unsigned long ip) |
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 303a0e48f076..8071e2f3d6eb 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -738,35 +738,17 @@ core_initcall(e820_mark_nvs_memory); | |||
738 | /* | 738 | /* |
739 | * pre allocated 4k and reserved it in memblock and e820_saved | 739 | * pre allocated 4k and reserved it in memblock and e820_saved |
740 | */ | 740 | */ |
741 | u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align) | 741 | u64 __init early_reserve_e820(u64 size, u64 align) |
742 | { | 742 | { |
743 | u64 size = 0; | ||
744 | u64 addr; | 743 | u64 addr; |
745 | u64 start; | ||
746 | 744 | ||
747 | for (start = startt; ; start += size) { | 745 | addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE); |
748 | start = memblock_x86_find_in_range_size(start, &size, align); | 746 | if (addr) { |
749 | if (start == MEMBLOCK_ERROR) | 747 | e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED); |
750 | return 0; | 748 | printk(KERN_INFO "update e820_saved for early_reserve_e820\n"); |
751 | if (size >= sizet) | 749 | update_e820_saved(); |
752 | break; | ||
753 | } | 750 | } |
754 | 751 | ||
755 | #ifdef CONFIG_X86_32 | ||
756 | if (start >= MAXMEM) | ||
757 | return 0; | ||
758 | if (start + size > MAXMEM) | ||
759 | size = MAXMEM - start; | ||
760 | #endif | ||
761 | |||
762 | addr = round_down(start + size - sizet, align); | ||
763 | if (addr < start) | ||
764 | return 0; | ||
765 | memblock_x86_reserve_range(addr, addr + sizet, "new next"); | ||
766 | e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED); | ||
767 | printk(KERN_INFO "update e820_saved for early_reserve_e820\n"); | ||
768 | update_e820_saved(); | ||
769 | |||
770 | return addr; | 752 | return addr; |
771 | } | 753 | } |
772 | 754 | ||
@@ -1090,7 +1072,7 @@ void __init memblock_x86_fill(void) | |||
1090 | * We are safe to enable resizing, beause memblock_x86_fill() | 1072 | * We are safe to enable resizing, beause memblock_x86_fill() |
1091 | * is rather later for x86 | 1073 | * is rather later for x86 |
1092 | */ | 1074 | */ |
1093 | memblock_can_resize = 1; | 1075 | memblock_allow_resize(); |
1094 | 1076 | ||
1095 | for (i = 0; i < e820.nr_map; i++) { | 1077 | for (i = 0; i < e820.nr_map; i++) { |
1096 | struct e820entry *ei = &e820.map[i]; | 1078 | struct e820entry *ei = &e820.map[i]; |
@@ -1105,22 +1087,36 @@ void __init memblock_x86_fill(void) | |||
1105 | memblock_add(ei->addr, ei->size); | 1087 | memblock_add(ei->addr, ei->size); |
1106 | } | 1088 | } |
1107 | 1089 | ||
1108 | memblock_analyze(); | ||
1109 | memblock_dump_all(); | 1090 | memblock_dump_all(); |
1110 | } | 1091 | } |
1111 | 1092 | ||
1112 | void __init memblock_find_dma_reserve(void) | 1093 | void __init memblock_find_dma_reserve(void) |
1113 | { | 1094 | { |
1114 | #ifdef CONFIG_X86_64 | 1095 | #ifdef CONFIG_X86_64 |
1115 | u64 free_size_pfn; | 1096 | u64 nr_pages = 0, nr_free_pages = 0; |
1116 | u64 mem_size_pfn; | 1097 | unsigned long start_pfn, end_pfn; |
1098 | phys_addr_t start, end; | ||
1099 | int i; | ||
1100 | u64 u; | ||
1101 | |||
1117 | /* | 1102 | /* |
1118 | * need to find out used area below MAX_DMA_PFN | 1103 | * need to find out used area below MAX_DMA_PFN |
1119 | * need to use memblock to get free size in [0, MAX_DMA_PFN] | 1104 | * need to use memblock to get free size in [0, MAX_DMA_PFN] |
1120 | * at first, and assume boot_mem will not take below MAX_DMA_PFN | 1105 | * at first, and assume boot_mem will not take below MAX_DMA_PFN |
1121 | */ | 1106 | */ |
1122 | mem_size_pfn = memblock_x86_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT; | 1107 | for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) { |
1123 | free_size_pfn = memblock_x86_free_memory_in_range(0, MAX_DMA_PFN << PAGE_SHIFT) >> PAGE_SHIFT; | 1108 | start_pfn = min_t(unsigned long, start_pfn, MAX_DMA_PFN); |
1124 | set_dma_reserve(mem_size_pfn - free_size_pfn); | 1109 | end_pfn = min_t(unsigned long, end_pfn, MAX_DMA_PFN); |
1110 | nr_pages += end_pfn - start_pfn; | ||
1111 | } | ||
1112 | |||
1113 | for_each_free_mem_range(u, MAX_NUMNODES, &start, &end, NULL) { | ||
1114 | start_pfn = min_t(unsigned long, PFN_UP(start), MAX_DMA_PFN); | ||
1115 | end_pfn = min_t(unsigned long, PFN_DOWN(end), MAX_DMA_PFN); | ||
1116 | if (start_pfn < end_pfn) | ||
1117 | nr_free_pages += end_pfn - start_pfn; | ||
1118 | } | ||
1119 | |||
1120 | set_dma_reserve(nr_pages - nr_free_pages); | ||
1125 | #endif | 1121 | #endif |
1126 | } | 1122 | } |
diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index af0699ba48cf..48d9d4ea1020 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c | |||
@@ -52,5 +52,5 @@ void __init reserve_ebda_region(void) | |||
52 | lowmem = 0x9f000; | 52 | lowmem = 0x9f000; |
53 | 53 | ||
54 | /* reserve all memory between lowmem and the 1MB mark */ | 54 | /* reserve all memory between lowmem and the 1MB mark */ |
55 | memblock_x86_reserve_range(lowmem, 0x100000, "* BIOS reserved"); | 55 | memblock_reserve(lowmem, 0x100000 - lowmem); |
56 | } | 56 | } |
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 3bb08509a7a1..51ff18616d50 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c | |||
@@ -31,9 +31,8 @@ static void __init i386_default_early_setup(void) | |||
31 | 31 | ||
32 | void __init i386_start_kernel(void) | 32 | void __init i386_start_kernel(void) |
33 | { | 33 | { |
34 | memblock_init(); | 34 | memblock_reserve(__pa_symbol(&_text), |
35 | 35 | __pa_symbol(&__bss_stop) - __pa_symbol(&_text)); | |
36 | memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); | ||
37 | 36 | ||
38 | #ifdef CONFIG_BLK_DEV_INITRD | 37 | #ifdef CONFIG_BLK_DEV_INITRD |
39 | /* Reserve INITRD */ | 38 | /* Reserve INITRD */ |
@@ -42,7 +41,7 @@ void __init i386_start_kernel(void) | |||
42 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; | 41 | u64 ramdisk_image = boot_params.hdr.ramdisk_image; |
43 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; | 42 | u64 ramdisk_size = boot_params.hdr.ramdisk_size; |
44 | u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size); | 43 | u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size); |
45 | memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK"); | 44 | memblock_reserve(ramdisk_image, ramdisk_end - ramdisk_image); |
46 | } | 45 | } |
47 | #endif | 46 | #endif |
48 | 47 | ||
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 5655c2272adb..3a3b779f41d3 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
@@ -98,9 +98,8 @@ void __init x86_64_start_reservations(char *real_mode_data) | |||
98 | { | 98 | { |
99 | copy_bootdata(__va(real_mode_data)); | 99 | copy_bootdata(__va(real_mode_data)); |
100 | 100 | ||
101 | memblock_init(); | 101 | memblock_reserve(__pa_symbol(&_text), |
102 | 102 | __pa_symbol(&__bss_stop) - __pa_symbol(&_text)); | |
103 | memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); | ||
104 | 103 | ||
105 | #ifdef CONFIG_BLK_DEV_INITRD | 104 | #ifdef CONFIG_BLK_DEV_INITRD |
106 | /* Reserve INITRD */ | 105 | /* Reserve INITRD */ |
@@ -109,7 +108,7 @@ void __init x86_64_start_reservations(char *real_mode_data) | |||
109 | unsigned long ramdisk_image = boot_params.hdr.ramdisk_image; | 108 | unsigned long ramdisk_image = boot_params.hdr.ramdisk_image; |
110 | unsigned long ramdisk_size = boot_params.hdr.ramdisk_size; | 109 | unsigned long ramdisk_size = boot_params.hdr.ramdisk_size; |
111 | unsigned long ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size); | 110 | unsigned long ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size); |
112 | memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK"); | 111 | memblock_reserve(ramdisk_image, ramdisk_end - ramdisk_image); |
113 | } | 112 | } |
114 | #endif | 113 | #endif |
115 | 114 | ||
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 429e0c92924e..5d31e5bdbf85 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -181,8 +181,8 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs) | |||
181 | unsigned vector = ~regs->orig_ax; | 181 | unsigned vector = ~regs->orig_ax; |
182 | unsigned irq; | 182 | unsigned irq; |
183 | 183 | ||
184 | exit_idle(); | ||
185 | irq_enter(); | 184 | irq_enter(); |
185 | exit_idle(); | ||
186 | 186 | ||
187 | irq = __this_cpu_read(vector_irq[vector]); | 187 | irq = __this_cpu_read(vector_irq[vector]); |
188 | 188 | ||
@@ -209,10 +209,10 @@ void smp_x86_platform_ipi(struct pt_regs *regs) | |||
209 | 209 | ||
210 | ack_APIC_irq(); | 210 | ack_APIC_irq(); |
211 | 211 | ||
212 | exit_idle(); | ||
213 | |||
214 | irq_enter(); | 212 | irq_enter(); |
215 | 213 | ||
214 | exit_idle(); | ||
215 | |||
216 | inc_irq_stat(x86_platform_ipis); | 216 | inc_irq_stat(x86_platform_ipis); |
217 | 217 | ||
218 | if (x86_platform_ipi_callback) | 218 | if (x86_platform_ipi_callback) |
diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c index ea9d5f2f13ef..2889b3d43882 100644 --- a/arch/x86/kernel/jump_label.c +++ b/arch/x86/kernel/jump_label.c | |||
@@ -50,7 +50,7 @@ void arch_jump_label_transform(struct jump_entry *entry, | |||
50 | put_online_cpus(); | 50 | put_online_cpus(); |
51 | } | 51 | } |
52 | 52 | ||
53 | void arch_jump_label_transform_static(struct jump_entry *entry, | 53 | __init_or_module void arch_jump_label_transform_static(struct jump_entry *entry, |
54 | enum jump_label_type type) | 54 | enum jump_label_type type) |
55 | { | 55 | { |
56 | __jump_label_transform(entry, type, text_poke_early); | 56 | __jump_label_transform(entry, type, text_poke_early); |
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 0741b062a304..ca470e4c92dc 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c | |||
@@ -564,9 +564,7 @@ void __init default_get_smp_config(unsigned int early) | |||
564 | 564 | ||
565 | static void __init smp_reserve_memory(struct mpf_intel *mpf) | 565 | static void __init smp_reserve_memory(struct mpf_intel *mpf) |
566 | { | 566 | { |
567 | unsigned long size = get_mpc_size(mpf->physptr); | 567 | memblock_reserve(mpf->physptr, get_mpc_size(mpf->physptr)); |
568 | |||
569 | memblock_x86_reserve_range(mpf->physptr, mpf->physptr+size, "* MP-table mpc"); | ||
570 | } | 568 | } |
571 | 569 | ||
572 | static int __init smp_scan_config(unsigned long base, unsigned long length) | 570 | static int __init smp_scan_config(unsigned long base, unsigned long length) |
@@ -595,7 +593,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length) | |||
595 | mpf, (u64)virt_to_phys(mpf)); | 593 | mpf, (u64)virt_to_phys(mpf)); |
596 | 594 | ||
597 | mem = virt_to_phys(mpf); | 595 | mem = virt_to_phys(mpf); |
598 | memblock_x86_reserve_range(mem, mem + sizeof(*mpf), "* MP-table mpf"); | 596 | memblock_reserve(mem, sizeof(*mpf)); |
599 | if (mpf->physptr) | 597 | if (mpf->physptr) |
600 | smp_reserve_memory(mpf); | 598 | smp_reserve_memory(mpf); |
601 | 599 | ||
@@ -836,10 +834,8 @@ early_param("alloc_mptable", parse_alloc_mptable_opt); | |||
836 | 834 | ||
837 | void __init early_reserve_e820_mpc_new(void) | 835 | void __init early_reserve_e820_mpc_new(void) |
838 | { | 836 | { |
839 | if (enable_update_mptable && alloc_mptable) { | 837 | if (enable_update_mptable && alloc_mptable) |
840 | u64 startt = 0; | 838 | mpc_new_phys = early_reserve_e820(mpc_new_length, 4); |
841 | mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4); | ||
842 | } | ||
843 | } | 839 | } |
844 | 840 | ||
845 | static int __init update_mp_table(void) | 841 | static int __init update_mp_table(void) |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 795b79f984c2..485204f58cda 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -99,7 +99,8 @@ void cpu_idle(void) | |||
99 | 99 | ||
100 | /* endless idle loop with no priority at all */ | 100 | /* endless idle loop with no priority at all */ |
101 | while (1) { | 101 | while (1) { |
102 | tick_nohz_stop_sched_tick(1); | 102 | tick_nohz_idle_enter(); |
103 | rcu_idle_enter(); | ||
103 | while (!need_resched()) { | 104 | while (!need_resched()) { |
104 | 105 | ||
105 | check_pgt_cache(); | 106 | check_pgt_cache(); |
@@ -116,7 +117,8 @@ void cpu_idle(void) | |||
116 | pm_idle(); | 117 | pm_idle(); |
117 | start_critical_timings(); | 118 | start_critical_timings(); |
118 | } | 119 | } |
119 | tick_nohz_restart_sched_tick(); | 120 | rcu_idle_exit(); |
121 | tick_nohz_idle_exit(); | ||
120 | preempt_enable_no_resched(); | 122 | preempt_enable_no_resched(); |
121 | schedule(); | 123 | schedule(); |
122 | preempt_disable(); | 124 | preempt_disable(); |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 3bd7e6eebf31..64e926c89a6f 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -122,7 +122,7 @@ void cpu_idle(void) | |||
122 | 122 | ||
123 | /* endless idle loop with no priority at all */ | 123 | /* endless idle loop with no priority at all */ |
124 | while (1) { | 124 | while (1) { |
125 | tick_nohz_stop_sched_tick(1); | 125 | tick_nohz_idle_enter(); |
126 | while (!need_resched()) { | 126 | while (!need_resched()) { |
127 | 127 | ||
128 | rmb(); | 128 | rmb(); |
@@ -139,8 +139,14 @@ void cpu_idle(void) | |||
139 | enter_idle(); | 139 | enter_idle(); |
140 | /* Don't trace irqs off for idle */ | 140 | /* Don't trace irqs off for idle */ |
141 | stop_critical_timings(); | 141 | stop_critical_timings(); |
142 | |||
143 | /* enter_idle() needs rcu for notifiers */ | ||
144 | rcu_idle_enter(); | ||
145 | |||
142 | if (cpuidle_idle_call()) | 146 | if (cpuidle_idle_call()) |
143 | pm_idle(); | 147 | pm_idle(); |
148 | |||
149 | rcu_idle_exit(); | ||
144 | start_critical_timings(); | 150 | start_critical_timings(); |
145 | 151 | ||
146 | /* In many cases the interrupt that ended idle | 152 | /* In many cases the interrupt that ended idle |
@@ -149,7 +155,7 @@ void cpu_idle(void) | |||
149 | __exit_idle(); | 155 | __exit_idle(); |
150 | } | 156 | } |
151 | 157 | ||
152 | tick_nohz_restart_sched_tick(); | 158 | tick_nohz_idle_exit(); |
153 | preempt_enable_no_resched(); | 159 | preempt_enable_no_resched(); |
154 | schedule(); | 160 | schedule(); |
155 | preempt_disable(); | 161 | preempt_disable(); |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index cf0ef986cb6d..d05444ac2aea 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -306,7 +306,8 @@ static void __init cleanup_highmap(void) | |||
306 | static void __init reserve_brk(void) | 306 | static void __init reserve_brk(void) |
307 | { | 307 | { |
308 | if (_brk_end > _brk_start) | 308 | if (_brk_end > _brk_start) |
309 | memblock_x86_reserve_range(__pa(_brk_start), __pa(_brk_end), "BRK"); | 309 | memblock_reserve(__pa(_brk_start), |
310 | __pa(_brk_end) - __pa(_brk_start)); | ||
310 | 311 | ||
311 | /* Mark brk area as locked down and no longer taking any | 312 | /* Mark brk area as locked down and no longer taking any |
312 | new allocations */ | 313 | new allocations */ |
@@ -331,13 +332,13 @@ static void __init relocate_initrd(void) | |||
331 | ramdisk_here = memblock_find_in_range(0, end_of_lowmem, area_size, | 332 | ramdisk_here = memblock_find_in_range(0, end_of_lowmem, area_size, |
332 | PAGE_SIZE); | 333 | PAGE_SIZE); |
333 | 334 | ||
334 | if (ramdisk_here == MEMBLOCK_ERROR) | 335 | if (!ramdisk_here) |
335 | panic("Cannot find place for new RAMDISK of size %lld\n", | 336 | panic("Cannot find place for new RAMDISK of size %lld\n", |
336 | ramdisk_size); | 337 | ramdisk_size); |
337 | 338 | ||
338 | /* Note: this includes all the lowmem currently occupied by | 339 | /* Note: this includes all the lowmem currently occupied by |
339 | the initrd, we rely on that fact to keep the data intact. */ | 340 | the initrd, we rely on that fact to keep the data intact. */ |
340 | memblock_x86_reserve_range(ramdisk_here, ramdisk_here + area_size, "NEW RAMDISK"); | 341 | memblock_reserve(ramdisk_here, area_size); |
341 | initrd_start = ramdisk_here + PAGE_OFFSET; | 342 | initrd_start = ramdisk_here + PAGE_OFFSET; |
342 | initrd_end = initrd_start + ramdisk_size; | 343 | initrd_end = initrd_start + ramdisk_size; |
343 | printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n", | 344 | printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n", |
@@ -393,7 +394,7 @@ static void __init reserve_initrd(void) | |||
393 | initrd_start = 0; | 394 | initrd_start = 0; |
394 | 395 | ||
395 | if (ramdisk_size >= (end_of_lowmem>>1)) { | 396 | if (ramdisk_size >= (end_of_lowmem>>1)) { |
396 | memblock_x86_free_range(ramdisk_image, ramdisk_end); | 397 | memblock_free(ramdisk_image, ramdisk_end - ramdisk_image); |
397 | printk(KERN_ERR "initrd too large to handle, " | 398 | printk(KERN_ERR "initrd too large to handle, " |
398 | "disabling initrd\n"); | 399 | "disabling initrd\n"); |
399 | return; | 400 | return; |
@@ -416,7 +417,7 @@ static void __init reserve_initrd(void) | |||
416 | 417 | ||
417 | relocate_initrd(); | 418 | relocate_initrd(); |
418 | 419 | ||
419 | memblock_x86_free_range(ramdisk_image, ramdisk_end); | 420 | memblock_free(ramdisk_image, ramdisk_end - ramdisk_image); |
420 | } | 421 | } |
421 | #else | 422 | #else |
422 | static void __init reserve_initrd(void) | 423 | static void __init reserve_initrd(void) |
@@ -490,15 +491,13 @@ static void __init memblock_x86_reserve_range_setup_data(void) | |||
490 | { | 491 | { |
491 | struct setup_data *data; | 492 | struct setup_data *data; |
492 | u64 pa_data; | 493 | u64 pa_data; |
493 | char buf[32]; | ||
494 | 494 | ||
495 | if (boot_params.hdr.version < 0x0209) | 495 | if (boot_params.hdr.version < 0x0209) |
496 | return; | 496 | return; |
497 | pa_data = boot_params.hdr.setup_data; | 497 | pa_data = boot_params.hdr.setup_data; |
498 | while (pa_data) { | 498 | while (pa_data) { |
499 | data = early_memremap(pa_data, sizeof(*data)); | 499 | data = early_memremap(pa_data, sizeof(*data)); |
500 | sprintf(buf, "setup data %x", data->type); | 500 | memblock_reserve(pa_data, sizeof(*data) + data->len); |
501 | memblock_x86_reserve_range(pa_data, pa_data+sizeof(*data)+data->len, buf); | ||
502 | pa_data = data->next; | 501 | pa_data = data->next; |
503 | early_iounmap(data, sizeof(*data)); | 502 | early_iounmap(data, sizeof(*data)); |
504 | } | 503 | } |
@@ -554,7 +553,7 @@ static void __init reserve_crashkernel(void) | |||
554 | crash_base = memblock_find_in_range(alignment, | 553 | crash_base = memblock_find_in_range(alignment, |
555 | CRASH_KERNEL_ADDR_MAX, crash_size, alignment); | 554 | CRASH_KERNEL_ADDR_MAX, crash_size, alignment); |
556 | 555 | ||
557 | if (crash_base == MEMBLOCK_ERROR) { | 556 | if (!crash_base) { |
558 | pr_info("crashkernel reservation failed - No suitable area found.\n"); | 557 | pr_info("crashkernel reservation failed - No suitable area found.\n"); |
559 | return; | 558 | return; |
560 | } | 559 | } |
@@ -568,7 +567,7 @@ static void __init reserve_crashkernel(void) | |||
568 | return; | 567 | return; |
569 | } | 568 | } |
570 | } | 569 | } |
571 | memblock_x86_reserve_range(crash_base, crash_base + crash_size, "CRASH KERNEL"); | 570 | memblock_reserve(crash_base, crash_size); |
572 | 571 | ||
573 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " | 572 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " |
574 | "for crashkernel (System RAM: %ldMB)\n", | 573 | "for crashkernel (System RAM: %ldMB)\n", |
@@ -626,7 +625,7 @@ static __init void reserve_ibft_region(void) | |||
626 | addr = find_ibft_region(&size); | 625 | addr = find_ibft_region(&size); |
627 | 626 | ||
628 | if (size) | 627 | if (size) |
629 | memblock_x86_reserve_range(addr, addr + size, "* ibft"); | 628 | memblock_reserve(addr, size); |
630 | } | 629 | } |
631 | 630 | ||
632 | static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; | 631 | static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; |
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c index a91ae7709b49..a73b61055ad6 100644 --- a/arch/x86/kernel/trampoline.c +++ b/arch/x86/kernel/trampoline.c | |||
@@ -14,11 +14,11 @@ void __init setup_trampolines(void) | |||
14 | 14 | ||
15 | /* Has to be in very low memory so we can execute real-mode AP code. */ | 15 | /* Has to be in very low memory so we can execute real-mode AP code. */ |
16 | mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); | 16 | mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); |
17 | if (mem == MEMBLOCK_ERROR) | 17 | if (!mem) |
18 | panic("Cannot allocate trampoline\n"); | 18 | panic("Cannot allocate trampoline\n"); |
19 | 19 | ||
20 | x86_trampoline_base = __va(mem); | 20 | x86_trampoline_base = __va(mem); |
21 | memblock_x86_reserve_range(mem, mem + size, "TRAMPOLINE"); | 21 | memblock_reserve(mem, size); |
22 | 22 | ||
23 | printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n", | 23 | printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n", |
24 | x86_trampoline_base, (unsigned long long)mem, size); | 24 | x86_trampoline_base, (unsigned long long)mem, size); |
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 76e3f1cd0369..405f2620392f 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -338,11 +338,15 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) | |||
338 | return HRTIMER_NORESTART; | 338 | return HRTIMER_NORESTART; |
339 | } | 339 | } |
340 | 340 | ||
341 | static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) | 341 | static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) |
342 | { | 342 | { |
343 | struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; | ||
343 | struct kvm_timer *pt = &ps->pit_timer; | 344 | struct kvm_timer *pt = &ps->pit_timer; |
344 | s64 interval; | 345 | s64 interval; |
345 | 346 | ||
347 | if (!irqchip_in_kernel(kvm)) | ||
348 | return; | ||
349 | |||
346 | interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); | 350 | interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); |
347 | 351 | ||
348 | pr_debug("create pit timer, interval is %llu nsec\n", interval); | 352 | pr_debug("create pit timer, interval is %llu nsec\n", interval); |
@@ -394,13 +398,13 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) | |||
394 | /* FIXME: enhance mode 4 precision */ | 398 | /* FIXME: enhance mode 4 precision */ |
395 | case 4: | 399 | case 4: |
396 | if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) { | 400 | if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) { |
397 | create_pit_timer(ps, val, 0); | 401 | create_pit_timer(kvm, val, 0); |
398 | } | 402 | } |
399 | break; | 403 | break; |
400 | case 2: | 404 | case 2: |
401 | case 3: | 405 | case 3: |
402 | if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){ | 406 | if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){ |
403 | create_pit_timer(ps, val, 1); | 407 | create_pit_timer(kvm, val, 1); |
404 | } | 408 | } |
405 | break; | 409 | break; |
406 | default: | 410 | default: |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c38efd7b792e..4c938da2ba00 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -602,7 +602,6 @@ static void update_cpuid(struct kvm_vcpu *vcpu) | |||
602 | { | 602 | { |
603 | struct kvm_cpuid_entry2 *best; | 603 | struct kvm_cpuid_entry2 *best; |
604 | struct kvm_lapic *apic = vcpu->arch.apic; | 604 | struct kvm_lapic *apic = vcpu->arch.apic; |
605 | u32 timer_mode_mask; | ||
606 | 605 | ||
607 | best = kvm_find_cpuid_entry(vcpu, 1, 0); | 606 | best = kvm_find_cpuid_entry(vcpu, 1, 0); |
608 | if (!best) | 607 | if (!best) |
@@ -615,15 +614,12 @@ static void update_cpuid(struct kvm_vcpu *vcpu) | |||
615 | best->ecx |= bit(X86_FEATURE_OSXSAVE); | 614 | best->ecx |= bit(X86_FEATURE_OSXSAVE); |
616 | } | 615 | } |
617 | 616 | ||
618 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | 617 | if (apic) { |
619 | best->function == 0x1) { | 618 | if (best->ecx & bit(X86_FEATURE_TSC_DEADLINE_TIMER)) |
620 | best->ecx |= bit(X86_FEATURE_TSC_DEADLINE_TIMER); | 619 | apic->lapic_timer.timer_mode_mask = 3 << 17; |
621 | timer_mode_mask = 3 << 17; | 620 | else |
622 | } else | 621 | apic->lapic_timer.timer_mode_mask = 1 << 17; |
623 | timer_mode_mask = 1 << 17; | 622 | } |
624 | |||
625 | if (apic) | ||
626 | apic->lapic_timer.timer_mode_mask = timer_mode_mask; | ||
627 | } | 623 | } |
628 | 624 | ||
629 | int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | 625 | int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) |
@@ -2135,6 +2131,9 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
2135 | case KVM_CAP_TSC_CONTROL: | 2131 | case KVM_CAP_TSC_CONTROL: |
2136 | r = kvm_has_tsc_control; | 2132 | r = kvm_has_tsc_control; |
2137 | break; | 2133 | break; |
2134 | case KVM_CAP_TSC_DEADLINE_TIMER: | ||
2135 | r = boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER); | ||
2136 | break; | ||
2138 | default: | 2137 | default: |
2139 | r = 0; | 2138 | r = 0; |
2140 | break; | 2139 | break; |
diff --git a/arch/x86/lib/inat.c b/arch/x86/lib/inat.c index 46fc4ee09fc4..88ad5fbda6e1 100644 --- a/arch/x86/lib/inat.c +++ b/arch/x86/lib/inat.c | |||
@@ -82,9 +82,16 @@ insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m, | |||
82 | const insn_attr_t *table; | 82 | const insn_attr_t *table; |
83 | if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX) | 83 | if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX) |
84 | return 0; | 84 | return 0; |
85 | table = inat_avx_tables[vex_m][vex_p]; | 85 | /* At first, this checks the master table */ |
86 | table = inat_avx_tables[vex_m][0]; | ||
86 | if (!table) | 87 | if (!table) |
87 | return 0; | 88 | return 0; |
89 | if (!inat_is_group(table[opcode]) && vex_p) { | ||
90 | /* If this is not a group, get attribute directly */ | ||
91 | table = inat_avx_tables[vex_m][vex_p]; | ||
92 | if (!table) | ||
93 | return 0; | ||
94 | } | ||
88 | return table[opcode]; | 95 | return table[opcode]; |
89 | } | 96 | } |
90 | 97 | ||
diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c index 374562ed6704..5a1f9f3e3fbb 100644 --- a/arch/x86/lib/insn.c +++ b/arch/x86/lib/insn.c | |||
@@ -202,7 +202,7 @@ void insn_get_opcode(struct insn *insn) | |||
202 | m = insn_vex_m_bits(insn); | 202 | m = insn_vex_m_bits(insn); |
203 | p = insn_vex_p_bits(insn); | 203 | p = insn_vex_p_bits(insn); |
204 | insn->attr = inat_get_avx_attribute(op, m, p); | 204 | insn->attr = inat_get_avx_attribute(op, m, p); |
205 | if (!inat_accept_vex(insn->attr)) | 205 | if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr)) |
206 | insn->attr = 0; /* This instruction is bad */ | 206 | insn->attr = 0; /* This instruction is bad */ |
207 | goto end; /* VEX has only 1 byte for opcode */ | 207 | goto end; /* VEX has only 1 byte for opcode */ |
208 | } | 208 | } |
@@ -249,6 +249,8 @@ void insn_get_modrm(struct insn *insn) | |||
249 | pfx = insn_last_prefix(insn); | 249 | pfx = insn_last_prefix(insn); |
250 | insn->attr = inat_get_group_attribute(mod, pfx, | 250 | insn->attr = inat_get_group_attribute(mod, pfx, |
251 | insn->attr); | 251 | insn->attr); |
252 | if (insn_is_avx(insn) && !inat_accept_vex(insn->attr)) | ||
253 | insn->attr = 0; /* This is bad */ | ||
252 | } | 254 | } |
253 | } | 255 | } |
254 | 256 | ||
diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt index a793da5e560e..5b83c51c12e0 100644 --- a/arch/x86/lib/x86-opcode-map.txt +++ b/arch/x86/lib/x86-opcode-map.txt | |||
@@ -1,5 +1,11 @@ | |||
1 | # x86 Opcode Maps | 1 | # x86 Opcode Maps |
2 | # | 2 | # |
3 | # This is (mostly) based on following documentations. | ||
4 | # - Intel(R) 64 and IA-32 Architectures Software Developer's Manual Vol.2 | ||
5 | # (#325383-040US, October 2011) | ||
6 | # - Intel(R) Advanced Vector Extensions Programming Reference | ||
7 | # (#319433-011,JUNE 2011). | ||
8 | # | ||
3 | #<Opcode maps> | 9 | #<Opcode maps> |
4 | # Table: table-name | 10 | # Table: table-name |
5 | # Referrer: escaped-name | 11 | # Referrer: escaped-name |
@@ -15,10 +21,13 @@ | |||
15 | # EndTable | 21 | # EndTable |
16 | # | 22 | # |
17 | # AVX Superscripts | 23 | # AVX Superscripts |
18 | # (VEX): this opcode can accept VEX prefix. | 24 | # (v): this opcode requires VEX prefix. |
19 | # (oVEX): this opcode requires VEX prefix. | 25 | # (v1): this opcode only supports 128bit VEX. |
20 | # (o128): this opcode only supports 128bit VEX. | 26 | # |
21 | # (o256): this opcode only supports 256bit VEX. | 27 | # Last Prefix Superscripts |
28 | # - (66): the last prefix is 0x66 | ||
29 | # - (F3): the last prefix is 0xF3 | ||
30 | # - (F2): the last prefix is 0xF2 | ||
22 | # | 31 | # |
23 | 32 | ||
24 | Table: one byte opcode | 33 | Table: one byte opcode |
@@ -199,8 +208,8 @@ a0: MOV AL,Ob | |||
199 | a1: MOV rAX,Ov | 208 | a1: MOV rAX,Ov |
200 | a2: MOV Ob,AL | 209 | a2: MOV Ob,AL |
201 | a3: MOV Ov,rAX | 210 | a3: MOV Ov,rAX |
202 | a4: MOVS/B Xb,Yb | 211 | a4: MOVS/B Yb,Xb |
203 | a5: MOVS/W/D/Q Xv,Yv | 212 | a5: MOVS/W/D/Q Yv,Xv |
204 | a6: CMPS/B Xb,Yb | 213 | a6: CMPS/B Xb,Yb |
205 | a7: CMPS/W/D Xv,Yv | 214 | a7: CMPS/W/D Xv,Yv |
206 | a8: TEST AL,Ib | 215 | a8: TEST AL,Ib |
@@ -233,8 +242,8 @@ c0: Grp2 Eb,Ib (1A) | |||
233 | c1: Grp2 Ev,Ib (1A) | 242 | c1: Grp2 Ev,Ib (1A) |
234 | c2: RETN Iw (f64) | 243 | c2: RETN Iw (f64) |
235 | c3: RETN | 244 | c3: RETN |
236 | c4: LES Gz,Mp (i64) | 3bytes-VEX (Prefix) | 245 | c4: LES Gz,Mp (i64) | VEX+2byte (Prefix) |
237 | c5: LDS Gz,Mp (i64) | 2bytes-VEX (Prefix) | 246 | c5: LDS Gz,Mp (i64) | VEX+1byte (Prefix) |
238 | c6: Grp11 Eb,Ib (1A) | 247 | c6: Grp11 Eb,Ib (1A) |
239 | c7: Grp11 Ev,Iz (1A) | 248 | c7: Grp11 Ev,Iz (1A) |
240 | c8: ENTER Iw,Ib | 249 | c8: ENTER Iw,Ib |
@@ -320,14 +329,19 @@ AVXcode: 1 | |||
320 | # 3DNow! uses the last imm byte as opcode extension. | 329 | # 3DNow! uses the last imm byte as opcode extension. |
321 | 0f: 3DNow! Pq,Qq,Ib | 330 | 0f: 3DNow! Pq,Qq,Ib |
322 | # 0x0f 0x10-0x1f | 331 | # 0x0f 0x10-0x1f |
323 | 10: movups Vps,Wps (VEX) | movss Vss,Wss (F3),(VEX),(o128) | movupd Vpd,Wpd (66),(VEX) | movsd Vsd,Wsd (F2),(VEX),(o128) | 332 | # NOTE: According to Intel SDM opcode map, vmovups and vmovupd has no operands |
324 | 11: movups Wps,Vps (VEX) | movss Wss,Vss (F3),(VEX),(o128) | movupd Wpd,Vpd (66),(VEX) | movsd Wsd,Vsd (F2),(VEX),(o128) | 333 | # but it actually has operands. And also, vmovss and vmovsd only accept 128bit. |
325 | 12: movlps Vq,Mq (VEX),(o128) | movlpd Vq,Mq (66),(VEX),(o128) | movhlps Vq,Uq (VEX),(o128) | movddup Vq,Wq (F2),(VEX) | movsldup Vq,Wq (F3),(VEX) | 334 | # MOVSS/MOVSD has too many forms(3) on SDM. This map just shows a typical form. |
326 | 13: mpvlps Mq,Vq (VEX),(o128) | movlpd Mq,Vq (66),(VEX),(o128) | 335 | # Many AVX instructions lack v1 superscript, according to Intel AVX-Prgramming |
327 | 14: unpcklps Vps,Wq (VEX) | unpcklpd Vpd,Wq (66),(VEX) | 336 | # Reference A.1 |
328 | 15: unpckhps Vps,Wq (VEX) | unpckhpd Vpd,Wq (66),(VEX) | 337 | 10: vmovups Vps,Wps | vmovupd Vpd,Wpd (66) | vmovss Vx,Hx,Wss (F3),(v1) | vmovsd Vx,Hx,Wsd (F2),(v1) |
329 | 16: movhps Vq,Mq (VEX),(o128) | movhpd Vq,Mq (66),(VEX),(o128) | movlsps Vq,Uq (VEX),(o128) | movshdup Vq,Wq (F3),(VEX) | 338 | 11: vmovups Wps,Vps | vmovupd Wpd,Vpd (66) | vmovss Wss,Hx,Vss (F3),(v1) | vmovsd Wsd,Hx,Vsd (F2),(v1) |
330 | 17: movhps Mq,Vq (VEX),(o128) | movhpd Mq,Vq (66),(VEX),(o128) | 339 | 12: vmovlps Vq,Hq,Mq (v1) | vmovhlps Vq,Hq,Uq (v1) | vmovlpd Vq,Hq,Mq (66),(v1) | vmovsldup Vx,Wx (F3) | vmovddup Vx,Wx (F2) |
340 | 13: vmovlps Mq,Vq (v1) | vmovlpd Mq,Vq (66),(v1) | ||
341 | 14: vunpcklps Vx,Hx,Wx | vunpcklpd Vx,Hx,Wx (66) | ||
342 | 15: vunpckhps Vx,Hx,Wx | vunpckhpd Vx,Hx,Wx (66) | ||
343 | 16: vmovhps Vdq,Hq,Mq (v1) | vmovlhps Vdq,Hq,Uq (v1) | vmovhpd Vdq,Hq,Mq (66),(v1) | vmovshdup Vx,Wx (F3) | ||
344 | 17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1) | ||
331 | 18: Grp16 (1A) | 345 | 18: Grp16 (1A) |
332 | 19: | 346 | 19: |
333 | 1a: | 347 | 1a: |
@@ -345,14 +359,14 @@ AVXcode: 1 | |||
345 | 25: | 359 | 25: |
346 | 26: | 360 | 26: |
347 | 27: | 361 | 27: |
348 | 28: movaps Vps,Wps (VEX) | movapd Vpd,Wpd (66),(VEX) | 362 | 28: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66) |
349 | 29: movaps Wps,Vps (VEX) | movapd Wpd,Vpd (66),(VEX) | 363 | 29: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66) |
350 | 2a: cvtpi2ps Vps,Qpi | cvtsi2ss Vss,Ed/q (F3),(VEX),(o128) | cvtpi2pd Vpd,Qpi (66) | cvtsi2sd Vsd,Ed/q (F2),(VEX),(o128) | 364 | 2a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1) |
351 | 2b: movntps Mps,Vps (VEX) | movntpd Mpd,Vpd (66),(VEX) | 365 | 2b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66) |
352 | 2c: cvttps2pi Ppi,Wps | cvttss2si Gd/q,Wss (F3),(VEX),(o128) | cvttpd2pi Ppi,Wpd (66) | cvttsd2si Gd/q,Wsd (F2),(VEX),(o128) | 366 | 2c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) | vcvttsd2si Gy,Wsd (F2),(v1) |
353 | 2d: cvtps2pi Ppi,Wps | cvtss2si Gd/q,Wss (F3),(VEX),(o128) | cvtpd2pi Qpi,Wpd (66) | cvtsd2si Gd/q,Wsd (F2),(VEX),(o128) | 367 | 2d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | vcvtsd2si Gy,Wsd (F2),(v1) |
354 | 2e: ucomiss Vss,Wss (VEX),(o128) | ucomisd Vsd,Wsd (66),(VEX),(o128) | 368 | 2e: vucomiss Vss,Wss (v1) | vucomisd Vsd,Wsd (66),(v1) |
355 | 2f: comiss Vss,Wss (VEX),(o128) | comisd Vsd,Wsd (66),(VEX),(o128) | 369 | 2f: vcomiss Vss,Wss (v1) | vcomisd Vsd,Wsd (66),(v1) |
356 | # 0x0f 0x30-0x3f | 370 | # 0x0f 0x30-0x3f |
357 | 30: WRMSR | 371 | 30: WRMSR |
358 | 31: RDTSC | 372 | 31: RDTSC |
@@ -388,65 +402,66 @@ AVXcode: 1 | |||
388 | 4e: CMOVLE/NG Gv,Ev | 402 | 4e: CMOVLE/NG Gv,Ev |
389 | 4f: CMOVNLE/G Gv,Ev | 403 | 4f: CMOVNLE/G Gv,Ev |
390 | # 0x0f 0x50-0x5f | 404 | # 0x0f 0x50-0x5f |
391 | 50: movmskps Gd/q,Ups (VEX) | movmskpd Gd/q,Upd (66),(VEX) | 405 | 50: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66) |
392 | 51: sqrtps Vps,Wps (VEX) | sqrtss Vss,Wss (F3),(VEX),(o128) | sqrtpd Vpd,Wpd (66),(VEX) | sqrtsd Vsd,Wsd (F2),(VEX),(o128) | 406 | 51: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | vsqrtsd Vsd,Hsd,Wsd (F2),(v1) |
393 | 52: rsqrtps Vps,Wps (VEX) | rsqrtss Vss,Wss (F3),(VEX),(o128) | 407 | 52: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1) |
394 | 53: rcpps Vps,Wps (VEX) | rcpss Vss,Wss (F3),(VEX),(o128) | 408 | 53: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1) |
395 | 54: andps Vps,Wps (VEX) | andpd Vpd,Wpd (66),(VEX) | 409 | 54: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66) |
396 | 55: andnps Vps,Wps (VEX) | andnpd Vpd,Wpd (66),(VEX) | 410 | 55: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66) |
397 | 56: orps Vps,Wps (VEX) | orpd Vpd,Wpd (66),(VEX) | 411 | 56: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66) |
398 | 57: xorps Vps,Wps (VEX) | xorpd Vpd,Wpd (66),(VEX) | 412 | 57: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66) |
399 | 58: addps Vps,Wps (VEX) | addss Vss,Wss (F3),(VEX),(o128) | addpd Vpd,Wpd (66),(VEX) | addsd Vsd,Wsd (F2),(VEX),(o128) | 413 | 58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1) |
400 | 59: mulps Vps,Wps (VEX) | mulss Vss,Wss (F3),(VEX),(o128) | mulpd Vpd,Wpd (66),(VEX) | mulsd Vsd,Wsd (F2),(VEX),(o128) | 414 | 59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1) |
401 | 5a: cvtps2pd Vpd,Wps (VEX) | cvtss2sd Vsd,Wss (F3),(VEX),(o128) | cvtpd2ps Vps,Wpd (66),(VEX) | cvtsd2ss Vsd,Wsd (F2),(VEX),(o128) | 415 | 5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1) |
402 | 5b: cvtdq2ps Vps,Wdq (VEX) | cvtps2dq Vdq,Wps (66),(VEX) | cvttps2dq Vdq,Wps (F3),(VEX) | 416 | 5b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3) |
403 | 5c: subps Vps,Wps (VEX) | subss Vss,Wss (F3),(VEX),(o128) | subpd Vpd,Wpd (66),(VEX) | subsd Vsd,Wsd (F2),(VEX),(o128) | 417 | 5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1) |
404 | 5d: minps Vps,Wps (VEX) | minss Vss,Wss (F3),(VEX),(o128) | minpd Vpd,Wpd (66),(VEX) | minsd Vsd,Wsd (F2),(VEX),(o128) | 418 | 5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1) |
405 | 5e: divps Vps,Wps (VEX) | divss Vss,Wss (F3),(VEX),(o128) | divpd Vpd,Wpd (66),(VEX) | divsd Vsd,Wsd (F2),(VEX),(o128) | 419 | 5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1) |
406 | 5f: maxps Vps,Wps (VEX) | maxss Vss,Wss (F3),(VEX),(o128) | maxpd Vpd,Wpd (66),(VEX) | maxsd Vsd,Wsd (F2),(VEX),(o128) | 420 | 5f: vmaxps Vps,Hps,Wps | vmaxpd Vpd,Hpd,Wpd (66) | vmaxss Vss,Hss,Wss (F3),(v1) | vmaxsd Vsd,Hsd,Wsd (F2),(v1) |
407 | # 0x0f 0x60-0x6f | 421 | # 0x0f 0x60-0x6f |
408 | 60: punpcklbw Pq,Qd | punpcklbw Vdq,Wdq (66),(VEX),(o128) | 422 | 60: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1) |
409 | 61: punpcklwd Pq,Qd | punpcklwd Vdq,Wdq (66),(VEX),(o128) | 423 | 61: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1) |
410 | 62: punpckldq Pq,Qd | punpckldq Vdq,Wdq (66),(VEX),(o128) | 424 | 62: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1) |
411 | 63: packsswb Pq,Qq | packsswb Vdq,Wdq (66),(VEX),(o128) | 425 | 63: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1) |
412 | 64: pcmpgtb Pq,Qq | pcmpgtb Vdq,Wdq (66),(VEX),(o128) | 426 | 64: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1) |
413 | 65: pcmpgtw Pq,Qq | pcmpgtw Vdq,Wdq (66),(VEX),(o128) | 427 | 65: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1) |
414 | 66: pcmpgtd Pq,Qq | pcmpgtd Vdq,Wdq (66),(VEX),(o128) | 428 | 66: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1) |
415 | 67: packuswb Pq,Qq | packuswb Vdq,Wdq (66),(VEX),(o128) | 429 | 67: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1) |
416 | 68: punpckhbw Pq,Qd | punpckhbw Vdq,Wdq (66),(VEX),(o128) | 430 | 68: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1) |
417 | 69: punpckhwd Pq,Qd | punpckhwd Vdq,Wdq (66),(VEX),(o128) | 431 | 69: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1) |
418 | 6a: punpckhdq Pq,Qd | punpckhdq Vdq,Wdq (66),(VEX),(o128) | 432 | 6a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1) |
419 | 6b: packssdw Pq,Qd | packssdw Vdq,Wdq (66),(VEX),(o128) | 433 | 6b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1) |
420 | 6c: punpcklqdq Vdq,Wdq (66),(VEX),(o128) | 434 | 6c: vpunpcklqdq Vx,Hx,Wx (66),(v1) |
421 | 6d: punpckhqdq Vdq,Wdq (66),(VEX),(o128) | 435 | 6d: vpunpckhqdq Vx,Hx,Wx (66),(v1) |
422 | 6e: movd/q/ Pd,Ed/q | movd/q Vdq,Ed/q (66),(VEX),(o128) | 436 | 6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1) |
423 | 6f: movq Pq,Qq | movdqa Vdq,Wdq (66),(VEX) | movdqu Vdq,Wdq (F3),(VEX) | 437 | 6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3) |
424 | # 0x0f 0x70-0x7f | 438 | # 0x0f 0x70-0x7f |
425 | 70: pshufw Pq,Qq,Ib | pshufd Vdq,Wdq,Ib (66),(VEX),(o128) | pshufhw Vdq,Wdq,Ib (F3),(VEX),(o128) | pshuflw VdqWdq,Ib (F2),(VEX),(o128) | 439 | 70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1) |
426 | 71: Grp12 (1A) | 440 | 71: Grp12 (1A) |
427 | 72: Grp13 (1A) | 441 | 72: Grp13 (1A) |
428 | 73: Grp14 (1A) | 442 | 73: Grp14 (1A) |
429 | 74: pcmpeqb Pq,Qq | pcmpeqb Vdq,Wdq (66),(VEX),(o128) | 443 | 74: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1) |
430 | 75: pcmpeqw Pq,Qq | pcmpeqw Vdq,Wdq (66),(VEX),(o128) | 444 | 75: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1) |
431 | 76: pcmpeqd Pq,Qq | pcmpeqd Vdq,Wdq (66),(VEX),(o128) | 445 | 76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1) |
432 | 77: emms/vzeroupper/vzeroall (VEX) | 446 | # Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX. |
433 | 78: VMREAD Ed/q,Gd/q | 447 | 77: emms | vzeroupper | vzeroall |
434 | 79: VMWRITE Gd/q,Ed/q | 448 | 78: VMREAD Ey,Gy |
449 | 79: VMWRITE Gy,Ey | ||
435 | 7a: | 450 | 7a: |
436 | 7b: | 451 | 7b: |
437 | 7c: haddps Vps,Wps (F2),(VEX) | haddpd Vpd,Wpd (66),(VEX) | 452 | 7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2) |
438 | 7d: hsubps Vps,Wps (F2),(VEX) | hsubpd Vpd,Wpd (66),(VEX) | 453 | 7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2) |
439 | 7e: movd/q Ed/q,Pd | movd/q Ed/q,Vdq (66),(VEX),(o128) | movq Vq,Wq (F3),(VEX),(o128) | 454 | 7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1) |
440 | 7f: movq Qq,Pq | movdqa Wdq,Vdq (66),(VEX) | movdqu Wdq,Vdq (F3),(VEX) | 455 | 7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3) |
441 | # 0x0f 0x80-0x8f | 456 | # 0x0f 0x80-0x8f |
442 | 80: JO Jz (f64) | 457 | 80: JO Jz (f64) |
443 | 81: JNO Jz (f64) | 458 | 81: JNO Jz (f64) |
444 | 82: JB/JNAE/JC Jz (f64) | 459 | 82: JB/JC/JNAE Jz (f64) |
445 | 83: JNB/JAE/JNC Jz (f64) | 460 | 83: JAE/JNB/JNC Jz (f64) |
446 | 84: JZ/JE Jz (f64) | 461 | 84: JE/JZ Jz (f64) |
447 | 85: JNZ/JNE Jz (f64) | 462 | 85: JNE/JNZ Jz (f64) |
448 | 86: JBE/JNA Jz (f64) | 463 | 86: JBE/JNA Jz (f64) |
449 | 87: JNBE/JA Jz (f64) | 464 | 87: JA/JNBE Jz (f64) |
450 | 88: JS Jz (f64) | 465 | 88: JS Jz (f64) |
451 | 89: JNS Jz (f64) | 466 | 89: JNS Jz (f64) |
452 | 8a: JP/JPE Jz (f64) | 467 | 8a: JP/JPE Jz (f64) |
@@ -502,18 +517,18 @@ b8: JMPE | POPCNT Gv,Ev (F3) | |||
502 | b9: Grp10 (1A) | 517 | b9: Grp10 (1A) |
503 | ba: Grp8 Ev,Ib (1A) | 518 | ba: Grp8 Ev,Ib (1A) |
504 | bb: BTC Ev,Gv | 519 | bb: BTC Ev,Gv |
505 | bc: BSF Gv,Ev | 520 | bc: BSF Gv,Ev | TZCNT Gv,Ev (F3) |
506 | bd: BSR Gv,Ev | 521 | bd: BSR Gv,Ev | LZCNT Gv,Ev (F3) |
507 | be: MOVSX Gv,Eb | 522 | be: MOVSX Gv,Eb |
508 | bf: MOVSX Gv,Ew | 523 | bf: MOVSX Gv,Ew |
509 | # 0x0f 0xc0-0xcf | 524 | # 0x0f 0xc0-0xcf |
510 | c0: XADD Eb,Gb | 525 | c0: XADD Eb,Gb |
511 | c1: XADD Ev,Gv | 526 | c1: XADD Ev,Gv |
512 | c2: cmpps Vps,Wps,Ib (VEX) | cmpss Vss,Wss,Ib (F3),(VEX),(o128) | cmppd Vpd,Wpd,Ib (66),(VEX) | cmpsd Vsd,Wsd,Ib (F2),(VEX) | 527 | c2: vcmpps Vps,Hps,Wps,Ib | vcmppd Vpd,Hpd,Wpd,Ib (66) | vcmpss Vss,Hss,Wss,Ib (F3),(v1) | vcmpsd Vsd,Hsd,Wsd,Ib (F2),(v1) |
513 | c3: movnti Md/q,Gd/q | 528 | c3: movnti My,Gy |
514 | c4: pinsrw Pq,Rd/q/Mw,Ib | pinsrw Vdq,Rd/q/Mw,Ib (66),(VEX),(o128) | 529 | c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1) |
515 | c5: pextrw Gd,Nq,Ib | pextrw Gd,Udq,Ib (66),(VEX),(o128) | 530 | c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1) |
516 | c6: shufps Vps,Wps,Ib (VEX) | shufpd Vpd,Wpd,Ib (66),(VEX) | 531 | c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66) |
517 | c7: Grp9 (1A) | 532 | c7: Grp9 (1A) |
518 | c8: BSWAP RAX/EAX/R8/R8D | 533 | c8: BSWAP RAX/EAX/R8/R8D |
519 | c9: BSWAP RCX/ECX/R9/R9D | 534 | c9: BSWAP RCX/ECX/R9/R9D |
@@ -524,55 +539,55 @@ cd: BSWAP RBP/EBP/R13/R13D | |||
524 | ce: BSWAP RSI/ESI/R14/R14D | 539 | ce: BSWAP RSI/ESI/R14/R14D |
525 | cf: BSWAP RDI/EDI/R15/R15D | 540 | cf: BSWAP RDI/EDI/R15/R15D |
526 | # 0x0f 0xd0-0xdf | 541 | # 0x0f 0xd0-0xdf |
527 | d0: addsubps Vps,Wps (F2),(VEX) | addsubpd Vpd,Wpd (66),(VEX) | 542 | d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2) |
528 | d1: psrlw Pq,Qq | psrlw Vdq,Wdq (66),(VEX),(o128) | 543 | d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1) |
529 | d2: psrld Pq,Qq | psrld Vdq,Wdq (66),(VEX),(o128) | 544 | d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1) |
530 | d3: psrlq Pq,Qq | psrlq Vdq,Wdq (66),(VEX),(o128) | 545 | d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1) |
531 | d4: paddq Pq,Qq | paddq Vdq,Wdq (66),(VEX),(o128) | 546 | d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1) |
532 | d5: pmullw Pq,Qq | pmullw Vdq,Wdq (66),(VEX),(o128) | 547 | d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1) |
533 | d6: movq Wq,Vq (66),(VEX),(o128) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2) | 548 | d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2) |
534 | d7: pmovmskb Gd,Nq | pmovmskb Gd,Udq (66),(VEX),(o128) | 549 | d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1) |
535 | d8: psubusb Pq,Qq | psubusb Vdq,Wdq (66),(VEX),(o128) | 550 | d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1) |
536 | d9: psubusw Pq,Qq | psubusw Vdq,Wdq (66),(VEX),(o128) | 551 | d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1) |
537 | da: pminub Pq,Qq | pminub Vdq,Wdq (66),(VEX),(o128) | 552 | da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1) |
538 | db: pand Pq,Qq | pand Vdq,Wdq (66),(VEX),(o128) | 553 | db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) |
539 | dc: paddusb Pq,Qq | paddusb Vdq,Wdq (66),(VEX),(o128) | 554 | dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1) |
540 | dd: paddusw Pq,Qq | paddusw Vdq,Wdq (66),(VEX),(o128) | 555 | dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1) |
541 | de: pmaxub Pq,Qq | pmaxub Vdq,Wdq (66),(VEX),(o128) | 556 | de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1) |
542 | df: pandn Pq,Qq | pandn Vdq,Wdq (66),(VEX),(o128) | 557 | df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) |
543 | # 0x0f 0xe0-0xef | 558 | # 0x0f 0xe0-0xef |
544 | e0: pavgb Pq,Qq | pavgb Vdq,Wdq (66),(VEX),(o128) | 559 | e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1) |
545 | e1: psraw Pq,Qq | psraw Vdq,Wdq (66),(VEX),(o128) | 560 | e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1) |
546 | e2: psrad Pq,Qq | psrad Vdq,Wdq (66),(VEX),(o128) | 561 | e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1) |
547 | e3: pavgw Pq,Qq | pavgw Vdq,Wdq (66),(VEX),(o128) | 562 | e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1) |
548 | e4: pmulhuw Pq,Qq | pmulhuw Vdq,Wdq (66),(VEX),(o128) | 563 | e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1) |
549 | e5: pmulhw Pq,Qq | pmulhw Vdq,Wdq (66),(VEX),(o128) | 564 | e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1) |
550 | e6: cvtpd2dq Vdq,Wpd (F2),(VEX) | cvttpd2dq Vdq,Wpd (66),(VEX) | cvtdq2pd Vpd,Wdq (F3),(VEX) | 565 | e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2) |
551 | e7: movntq Mq,Pq | movntdq Mdq,Vdq (66),(VEX) | 566 | e7: movntq Mq,Pq | vmovntdq Mx,Vx (66) |
552 | e8: psubsb Pq,Qq | psubsb Vdq,Wdq (66),(VEX),(o128) | 567 | e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1) |
553 | e9: psubsw Pq,Qq | psubsw Vdq,Wdq (66),(VEX),(o128) | 568 | e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1) |
554 | ea: pminsw Pq,Qq | pminsw Vdq,Wdq (66),(VEX),(o128) | 569 | ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1) |
555 | eb: por Pq,Qq | por Vdq,Wdq (66),(VEX),(o128) | 570 | eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) |
556 | ec: paddsb Pq,Qq | paddsb Vdq,Wdq (66),(VEX),(o128) | 571 | ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1) |
557 | ed: paddsw Pq,Qq | paddsw Vdq,Wdq (66),(VEX),(o128) | 572 | ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1) |
558 | ee: pmaxsw Pq,Qq | pmaxsw Vdq,Wdq (66),(VEX),(o128) | 573 | ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1) |
559 | ef: pxor Pq,Qq | pxor Vdq,Wdq (66),(VEX),(o128) | 574 | ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) |
560 | # 0x0f 0xf0-0xff | 575 | # 0x0f 0xf0-0xff |
561 | f0: lddqu Vdq,Mdq (F2),(VEX) | 576 | f0: vlddqu Vx,Mx (F2) |
562 | f1: psllw Pq,Qq | psllw Vdq,Wdq (66),(VEX),(o128) | 577 | f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1) |
563 | f2: pslld Pq,Qq | pslld Vdq,Wdq (66),(VEX),(o128) | 578 | f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1) |
564 | f3: psllq Pq,Qq | psllq Vdq,Wdq (66),(VEX),(o128) | 579 | f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1) |
565 | f4: pmuludq Pq,Qq | pmuludq Vdq,Wdq (66),(VEX),(o128) | 580 | f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1) |
566 | f5: pmaddwd Pq,Qq | pmaddwd Vdq,Wdq (66),(VEX),(o128) | 581 | f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1) |
567 | f6: psadbw Pq,Qq | psadbw Vdq,Wdq (66),(VEX),(o128) | 582 | f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1) |
568 | f7: maskmovq Pq,Nq | maskmovdqu Vdq,Udq (66),(VEX),(o128) | 583 | f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1) |
569 | f8: psubb Pq,Qq | psubb Vdq,Wdq (66),(VEX),(o128) | 584 | f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1) |
570 | f9: psubw Pq,Qq | psubw Vdq,Wdq (66),(VEX),(o128) | 585 | f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1) |
571 | fa: psubd Pq,Qq | psubd Vdq,Wdq (66),(VEX),(o128) | 586 | fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1) |
572 | fb: psubq Pq,Qq | psubq Vdq,Wdq (66),(VEX),(o128) | 587 | fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1) |
573 | fc: paddb Pq,Qq | paddb Vdq,Wdq (66),(VEX),(o128) | 588 | fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1) |
574 | fd: paddw Pq,Qq | paddw Vdq,Wdq (66),(VEX),(o128) | 589 | fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1) |
575 | fe: paddd Pq,Qq | paddd Vdq,Wdq (66),(VEX),(o128) | 590 | fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1) |
576 | ff: | 591 | ff: |
577 | EndTable | 592 | EndTable |
578 | 593 | ||
@@ -580,155 +595,193 @@ Table: 3-byte opcode 1 (0x0f 0x38) | |||
580 | Referrer: 3-byte escape 1 | 595 | Referrer: 3-byte escape 1 |
581 | AVXcode: 2 | 596 | AVXcode: 2 |
582 | # 0x0f 0x38 0x00-0x0f | 597 | # 0x0f 0x38 0x00-0x0f |
583 | 00: pshufb Pq,Qq | pshufb Vdq,Wdq (66),(VEX),(o128) | 598 | 00: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1) |
584 | 01: phaddw Pq,Qq | phaddw Vdq,Wdq (66),(VEX),(o128) | 599 | 01: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1) |
585 | 02: phaddd Pq,Qq | phaddd Vdq,Wdq (66),(VEX),(o128) | 600 | 02: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1) |
586 | 03: phaddsw Pq,Qq | phaddsw Vdq,Wdq (66),(VEX),(o128) | 601 | 03: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1) |
587 | 04: pmaddubsw Pq,Qq | pmaddubsw Vdq,Wdq (66),(VEX),(o128) | 602 | 04: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1) |
588 | 05: phsubw Pq,Qq | phsubw Vdq,Wdq (66),(VEX),(o128) | 603 | 05: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1) |
589 | 06: phsubd Pq,Qq | phsubd Vdq,Wdq (66),(VEX),(o128) | 604 | 06: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1) |
590 | 07: phsubsw Pq,Qq | phsubsw Vdq,Wdq (66),(VEX),(o128) | 605 | 07: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1) |
591 | 08: psignb Pq,Qq | psignb Vdq,Wdq (66),(VEX),(o128) | 606 | 08: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1) |
592 | 09: psignw Pq,Qq | psignw Vdq,Wdq (66),(VEX),(o128) | 607 | 09: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1) |
593 | 0a: psignd Pq,Qq | psignd Vdq,Wdq (66),(VEX),(o128) | 608 | 0a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1) |
594 | 0b: pmulhrsw Pq,Qq | pmulhrsw Vdq,Wdq (66),(VEX),(o128) | 609 | 0b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1) |
595 | 0c: Vpermilps /r (66),(oVEX) | 610 | 0c: vpermilps Vx,Hx,Wx (66),(v) |
596 | 0d: Vpermilpd /r (66),(oVEX) | 611 | 0d: vpermilpd Vx,Hx,Wx (66),(v) |
597 | 0e: vtestps /r (66),(oVEX) | 612 | 0e: vtestps Vx,Wx (66),(v) |
598 | 0f: vtestpd /r (66),(oVEX) | 613 | 0f: vtestpd Vx,Wx (66),(v) |
599 | # 0x0f 0x38 0x10-0x1f | 614 | # 0x0f 0x38 0x10-0x1f |
600 | 10: pblendvb Vdq,Wdq (66) | 615 | 10: pblendvb Vdq,Wdq (66) |
601 | 11: | 616 | 11: |
602 | 12: | 617 | 12: |
603 | 13: | 618 | 13: vcvtph2ps Vx,Wx,Ib (66),(v) |
604 | 14: blendvps Vdq,Wdq (66) | 619 | 14: blendvps Vdq,Wdq (66) |
605 | 15: blendvpd Vdq,Wdq (66) | 620 | 15: blendvpd Vdq,Wdq (66) |
606 | 16: | 621 | 16: vpermps Vqq,Hqq,Wqq (66),(v) |
607 | 17: ptest Vdq,Wdq (66),(VEX) | 622 | 17: vptest Vx,Wx (66) |
608 | 18: vbroadcastss /r (66),(oVEX) | 623 | 18: vbroadcastss Vx,Wd (66),(v) |
609 | 19: vbroadcastsd /r (66),(oVEX),(o256) | 624 | 19: vbroadcastsd Vqq,Wq (66),(v) |
610 | 1a: vbroadcastf128 /r (66),(oVEX),(o256) | 625 | 1a: vbroadcastf128 Vqq,Mdq (66),(v) |
611 | 1b: | 626 | 1b: |
612 | 1c: pabsb Pq,Qq | pabsb Vdq,Wdq (66),(VEX),(o128) | 627 | 1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1) |
613 | 1d: pabsw Pq,Qq | pabsw Vdq,Wdq (66),(VEX),(o128) | 628 | 1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1) |
614 | 1e: pabsd Pq,Qq | pabsd Vdq,Wdq (66),(VEX),(o128) | 629 | 1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1) |
615 | 1f: | 630 | 1f: |
616 | # 0x0f 0x38 0x20-0x2f | 631 | # 0x0f 0x38 0x20-0x2f |
617 | 20: pmovsxbw Vdq,Udq/Mq (66),(VEX),(o128) | 632 | 20: vpmovsxbw Vx,Ux/Mq (66),(v1) |
618 | 21: pmovsxbd Vdq,Udq/Md (66),(VEX),(o128) | 633 | 21: vpmovsxbd Vx,Ux/Md (66),(v1) |
619 | 22: pmovsxbq Vdq,Udq/Mw (66),(VEX),(o128) | 634 | 22: vpmovsxbq Vx,Ux/Mw (66),(v1) |
620 | 23: pmovsxwd Vdq,Udq/Mq (66),(VEX),(o128) | 635 | 23: vpmovsxwd Vx,Ux/Mq (66),(v1) |
621 | 24: pmovsxwq Vdq,Udq/Md (66),(VEX),(o128) | 636 | 24: vpmovsxwq Vx,Ux/Md (66),(v1) |
622 | 25: pmovsxdq Vdq,Udq/Mq (66),(VEX),(o128) | 637 | 25: vpmovsxdq Vx,Ux/Mq (66),(v1) |
623 | 26: | 638 | 26: |
624 | 27: | 639 | 27: |
625 | 28: pmuldq Vdq,Wdq (66),(VEX),(o128) | 640 | 28: vpmuldq Vx,Hx,Wx (66),(v1) |
626 | 29: pcmpeqq Vdq,Wdq (66),(VEX),(o128) | 641 | 29: vpcmpeqq Vx,Hx,Wx (66),(v1) |
627 | 2a: movntdqa Vdq,Mdq (66),(VEX),(o128) | 642 | 2a: vmovntdqa Vx,Mx (66),(v1) |
628 | 2b: packusdw Vdq,Wdq (66),(VEX),(o128) | 643 | 2b: vpackusdw Vx,Hx,Wx (66),(v1) |
629 | 2c: vmaskmovps(ld) /r (66),(oVEX) | 644 | 2c: vmaskmovps Vx,Hx,Mx (66),(v) |
630 | 2d: vmaskmovpd(ld) /r (66),(oVEX) | 645 | 2d: vmaskmovpd Vx,Hx,Mx (66),(v) |
631 | 2e: vmaskmovps(st) /r (66),(oVEX) | 646 | 2e: vmaskmovps Mx,Hx,Vx (66),(v) |
632 | 2f: vmaskmovpd(st) /r (66),(oVEX) | 647 | 2f: vmaskmovpd Mx,Hx,Vx (66),(v) |
633 | # 0x0f 0x38 0x30-0x3f | 648 | # 0x0f 0x38 0x30-0x3f |
634 | 30: pmovzxbw Vdq,Udq/Mq (66),(VEX),(o128) | 649 | 30: vpmovzxbw Vx,Ux/Mq (66),(v1) |
635 | 31: pmovzxbd Vdq,Udq/Md (66),(VEX),(o128) | 650 | 31: vpmovzxbd Vx,Ux/Md (66),(v1) |
636 | 32: pmovzxbq Vdq,Udq/Mw (66),(VEX),(o128) | 651 | 32: vpmovzxbq Vx,Ux/Mw (66),(v1) |
637 | 33: pmovzxwd Vdq,Udq/Mq (66),(VEX),(o128) | 652 | 33: vpmovzxwd Vx,Ux/Mq (66),(v1) |
638 | 34: pmovzxwq Vdq,Udq/Md (66),(VEX),(o128) | 653 | 34: vpmovzxwq Vx,Ux/Md (66),(v1) |
639 | 35: pmovzxdq Vdq,Udq/Mq (66),(VEX),(o128) | 654 | 35: vpmovzxdq Vx,Ux/Mq (66),(v1) |
640 | 36: | 655 | 36: vpermd Vqq,Hqq,Wqq (66),(v) |
641 | 37: pcmpgtq Vdq,Wdq (66),(VEX),(o128) | 656 | 37: vpcmpgtq Vx,Hx,Wx (66),(v1) |
642 | 38: pminsb Vdq,Wdq (66),(VEX),(o128) | 657 | 38: vpminsb Vx,Hx,Wx (66),(v1) |
643 | 39: pminsd Vdq,Wdq (66),(VEX),(o128) | 658 | 39: vpminsd Vx,Hx,Wx (66),(v1) |
644 | 3a: pminuw Vdq,Wdq (66),(VEX),(o128) | 659 | 3a: vpminuw Vx,Hx,Wx (66),(v1) |
645 | 3b: pminud Vdq,Wdq (66),(VEX),(o128) | 660 | 3b: vpminud Vx,Hx,Wx (66),(v1) |
646 | 3c: pmaxsb Vdq,Wdq (66),(VEX),(o128) | 661 | 3c: vpmaxsb Vx,Hx,Wx (66),(v1) |
647 | 3d: pmaxsd Vdq,Wdq (66),(VEX),(o128) | 662 | 3d: vpmaxsd Vx,Hx,Wx (66),(v1) |
648 | 3e: pmaxuw Vdq,Wdq (66),(VEX),(o128) | 663 | 3e: vpmaxuw Vx,Hx,Wx (66),(v1) |
649 | 3f: pmaxud Vdq,Wdq (66),(VEX),(o128) | 664 | 3f: vpmaxud Vx,Hx,Wx (66),(v1) |
650 | # 0x0f 0x38 0x40-0x8f | 665 | # 0x0f 0x38 0x40-0x8f |
651 | 40: pmulld Vdq,Wdq (66),(VEX),(o128) | 666 | 40: vpmulld Vx,Hx,Wx (66),(v1) |
652 | 41: phminposuw Vdq,Wdq (66),(VEX),(o128) | 667 | 41: vphminposuw Vdq,Wdq (66),(v1) |
653 | 80: INVEPT Gd/q,Mdq (66) | 668 | 42: |
654 | 81: INVPID Gd/q,Mdq (66) | 669 | 43: |
670 | 44: | ||
671 | 45: vpsrlvd/q Vx,Hx,Wx (66),(v) | ||
672 | 46: vpsravd Vx,Hx,Wx (66),(v) | ||
673 | 47: vpsllvd/q Vx,Hx,Wx (66),(v) | ||
674 | # Skip 0x48-0x57 | ||
675 | 58: vpbroadcastd Vx,Wx (66),(v) | ||
676 | 59: vpbroadcastq Vx,Wx (66),(v) | ||
677 | 5a: vbroadcasti128 Vqq,Mdq (66),(v) | ||
678 | # Skip 0x5b-0x77 | ||
679 | 78: vpbroadcastb Vx,Wx (66),(v) | ||
680 | 79: vpbroadcastw Vx,Wx (66),(v) | ||
681 | # Skip 0x7a-0x7f | ||
682 | 80: INVEPT Gy,Mdq (66) | ||
683 | 81: INVPID Gy,Mdq (66) | ||
684 | 82: INVPCID Gy,Mdq (66) | ||
685 | 8c: vpmaskmovd/q Vx,Hx,Mx (66),(v) | ||
686 | 8e: vpmaskmovd/q Mx,Vx,Hx (66),(v) | ||
655 | # 0x0f 0x38 0x90-0xbf (FMA) | 687 | # 0x0f 0x38 0x90-0xbf (FMA) |
656 | 96: vfmaddsub132pd/ps /r (66),(VEX) | 688 | 90: vgatherdd/q Vx,Hx,Wx (66),(v) |
657 | 97: vfmsubadd132pd/ps /r (66),(VEX) | 689 | 91: vgatherqd/q Vx,Hx,Wx (66),(v) |
658 | 98: vfmadd132pd/ps /r (66),(VEX) | 690 | 92: vgatherdps/d Vx,Hx,Wx (66),(v) |
659 | 99: vfmadd132sd/ss /r (66),(VEX),(o128) | 691 | 93: vgatherqps/d Vx,Hx,Wx (66),(v) |
660 | 9a: vfmsub132pd/ps /r (66),(VEX) | 692 | 94: |
661 | 9b: vfmsub132sd/ss /r (66),(VEX),(o128) | 693 | 95: |
662 | 9c: vfnmadd132pd/ps /r (66),(VEX) | 694 | 96: vfmaddsub132ps/d Vx,Hx,Wx (66),(v) |
663 | 9d: vfnmadd132sd/ss /r (66),(VEX),(o128) | 695 | 97: vfmsubadd132ps/d Vx,Hx,Wx (66),(v) |
664 | 9e: vfnmsub132pd/ps /r (66),(VEX) | 696 | 98: vfmadd132ps/d Vx,Hx,Wx (66),(v) |
665 | 9f: vfnmsub132sd/ss /r (66),(VEX),(o128) | 697 | 99: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1) |
666 | a6: vfmaddsub213pd/ps /r (66),(VEX) | 698 | 9a: vfmsub132ps/d Vx,Hx,Wx (66),(v) |
667 | a7: vfmsubadd213pd/ps /r (66),(VEX) | 699 | 9b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1) |
668 | a8: vfmadd213pd/ps /r (66),(VEX) | 700 | 9c: vfnmadd132ps/d Vx,Hx,Wx (66),(v) |
669 | a9: vfmadd213sd/ss /r (66),(VEX),(o128) | 701 | 9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1) |
670 | aa: vfmsub213pd/ps /r (66),(VEX) | 702 | 9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v) |
671 | ab: vfmsub213sd/ss /r (66),(VEX),(o128) | 703 | 9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1) |
672 | ac: vfnmadd213pd/ps /r (66),(VEX) | 704 | a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v) |
673 | ad: vfnmadd213sd/ss /r (66),(VEX),(o128) | 705 | a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v) |
674 | ae: vfnmsub213pd/ps /r (66),(VEX) | 706 | a8: vfmadd213ps/d Vx,Hx,Wx (66),(v) |
675 | af: vfnmsub213sd/ss /r (66),(VEX),(o128) | 707 | a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1) |
676 | b6: vfmaddsub231pd/ps /r (66),(VEX) | 708 | aa: vfmsub213ps/d Vx,Hx,Wx (66),(v) |
677 | b7: vfmsubadd231pd/ps /r (66),(VEX) | 709 | ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1) |
678 | b8: vfmadd231pd/ps /r (66),(VEX) | 710 | ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v) |
679 | b9: vfmadd231sd/ss /r (66),(VEX),(o128) | 711 | ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1) |
680 | ba: vfmsub231pd/ps /r (66),(VEX) | 712 | ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v) |
681 | bb: vfmsub231sd/ss /r (66),(VEX),(o128) | 713 | af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1) |
682 | bc: vfnmadd231pd/ps /r (66),(VEX) | 714 | b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v) |
683 | bd: vfnmadd231sd/ss /r (66),(VEX),(o128) | 715 | b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v) |
684 | be: vfnmsub231pd/ps /r (66),(VEX) | 716 | b8: vfmadd231ps/d Vx,Hx,Wx (66),(v) |
685 | bf: vfnmsub231sd/ss /r (66),(VEX),(o128) | 717 | b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1) |
718 | ba: vfmsub231ps/d Vx,Hx,Wx (66),(v) | ||
719 | bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1) | ||
720 | bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v) | ||
721 | bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1) | ||
722 | be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) | ||
723 | bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) | ||
686 | # 0x0f 0x38 0xc0-0xff | 724 | # 0x0f 0x38 0xc0-0xff |
687 | db: aesimc Vdq,Wdq (66),(VEX),(o128) | 725 | db: VAESIMC Vdq,Wdq (66),(v1) |
688 | dc: aesenc Vdq,Wdq (66),(VEX),(o128) | 726 | dc: VAESENC Vdq,Hdq,Wdq (66),(v1) |
689 | dd: aesenclast Vdq,Wdq (66),(VEX),(o128) | 727 | dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) |
690 | de: aesdec Vdq,Wdq (66),(VEX),(o128) | 728 | de: VAESDEC Vdq,Hdq,Wdq (66),(v1) |
691 | df: aesdeclast Vdq,Wdq (66),(VEX),(o128) | 729 | df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1) |
692 | f0: MOVBE Gv,Mv | CRC32 Gd,Eb (F2) | 730 | f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) |
693 | f1: MOVBE Mv,Gv | CRC32 Gd,Ev (F2) | 731 | f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) |
732 | f3: ANDN Gy,By,Ey (v) | ||
733 | f4: Grp17 (1A) | ||
734 | f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v) | ||
735 | f6: MULX By,Gy,rDX,Ey (F2),(v) | ||
736 | f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v) | ||
694 | EndTable | 737 | EndTable |
695 | 738 | ||
696 | Table: 3-byte opcode 2 (0x0f 0x3a) | 739 | Table: 3-byte opcode 2 (0x0f 0x3a) |
697 | Referrer: 3-byte escape 2 | 740 | Referrer: 3-byte escape 2 |
698 | AVXcode: 3 | 741 | AVXcode: 3 |
699 | # 0x0f 0x3a 0x00-0xff | 742 | # 0x0f 0x3a 0x00-0xff |
700 | 04: vpermilps /r,Ib (66),(oVEX) | 743 | 00: vpermq Vqq,Wqq,Ib (66),(v) |
701 | 05: vpermilpd /r,Ib (66),(oVEX) | 744 | 01: vpermpd Vqq,Wqq,Ib (66),(v) |
702 | 06: vperm2f128 /r,Ib (66),(oVEX),(o256) | 745 | 02: vpblendd Vx,Hx,Wx,Ib (66),(v) |
703 | 08: roundps Vdq,Wdq,Ib (66),(VEX) | 746 | 03: |
704 | 09: roundpd Vdq,Wdq,Ib (66),(VEX) | 747 | 04: vpermilps Vx,Wx,Ib (66),(v) |
705 | 0a: roundss Vss,Wss,Ib (66),(VEX),(o128) | 748 | 05: vpermilpd Vx,Wx,Ib (66),(v) |
706 | 0b: roundsd Vsd,Wsd,Ib (66),(VEX),(o128) | 749 | 06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v) |
707 | 0c: blendps Vdq,Wdq,Ib (66),(VEX) | 750 | 07: |
708 | 0d: blendpd Vdq,Wdq,Ib (66),(VEX) | 751 | 08: vroundps Vx,Wx,Ib (66) |
709 | 0e: pblendw Vdq,Wdq,Ib (66),(VEX),(o128) | 752 | 09: vroundpd Vx,Wx,Ib (66) |
710 | 0f: palignr Pq,Qq,Ib | palignr Vdq,Wdq,Ib (66),(VEX),(o128) | 753 | 0a: vroundss Vss,Wss,Ib (66),(v1) |
711 | 14: pextrb Rd/Mb,Vdq,Ib (66),(VEX),(o128) | 754 | 0b: vroundsd Vsd,Wsd,Ib (66),(v1) |
712 | 15: pextrw Rd/Mw,Vdq,Ib (66),(VEX),(o128) | 755 | 0c: vblendps Vx,Hx,Wx,Ib (66) |
713 | 16: pextrd/pextrq Ed/q,Vdq,Ib (66),(VEX),(o128) | 756 | 0d: vblendpd Vx,Hx,Wx,Ib (66) |
714 | 17: extractps Ed,Vdq,Ib (66),(VEX),(o128) | 757 | 0e: vpblendw Vx,Hx,Wx,Ib (66),(v1) |
715 | 18: vinsertf128 /r,Ib (66),(oVEX),(o256) | 758 | 0f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1) |
716 | 19: vextractf128 /r,Ib (66),(oVEX),(o256) | 759 | 14: vpextrb Rd/Mb,Vdq,Ib (66),(v1) |
717 | 20: pinsrb Vdq,Rd/q/Mb,Ib (66),(VEX),(o128) | 760 | 15: vpextrw Rd/Mw,Vdq,Ib (66),(v1) |
718 | 21: insertps Vdq,Udq/Md,Ib (66),(VEX),(o128) | 761 | 16: vpextrd/q Ey,Vdq,Ib (66),(v1) |
719 | 22: pinsrd/pinsrq Vdq,Ed/q,Ib (66),(VEX),(o128) | 762 | 17: vextractps Ed,Vdq,Ib (66),(v1) |
720 | 40: dpps Vdq,Wdq,Ib (66),(VEX) | 763 | 18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) |
721 | 41: dppd Vdq,Wdq,Ib (66),(VEX),(o128) | 764 | 19: vextractf128 Wdq,Vqq,Ib (66),(v) |
722 | 42: mpsadbw Vdq,Wdq,Ib (66),(VEX),(o128) | 765 | 1d: vcvtps2ph Wx,Vx,Ib (66),(v) |
723 | 44: pclmulq Vdq,Wdq,Ib (66),(VEX),(o128) | 766 | 20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1) |
724 | 4a: vblendvps /r,Ib (66),(oVEX) | 767 | 21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1) |
725 | 4b: vblendvpd /r,Ib (66),(oVEX) | 768 | 22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1) |
726 | 4c: vpblendvb /r,Ib (66),(oVEX),(o128) | 769 | 38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) |
727 | 60: pcmpestrm Vdq,Wdq,Ib (66),(VEX),(o128) | 770 | 39: vextracti128 Wdq,Vqq,Ib (66),(v) |
728 | 61: pcmpestri Vdq,Wdq,Ib (66),(VEX),(o128) | 771 | 40: vdpps Vx,Hx,Wx,Ib (66) |
729 | 62: pcmpistrm Vdq,Wdq,Ib (66),(VEX),(o128) | 772 | 41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1) |
730 | 63: pcmpistri Vdq,Wdq,Ib (66),(VEX),(o128) | 773 | 42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) |
731 | df: aeskeygenassist Vdq,Wdq,Ib (66),(VEX),(o128) | 774 | 44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1) |
775 | 46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v) | ||
776 | 4a: vblendvps Vx,Hx,Wx,Lx (66),(v) | ||
777 | 4b: vblendvpd Vx,Hx,Wx,Lx (66),(v) | ||
778 | 4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1) | ||
779 | 60: vpcmpestrm Vdq,Wdq,Ib (66),(v1) | ||
780 | 61: vpcmpestri Vdq,Wdq,Ib (66),(v1) | ||
781 | 62: vpcmpistrm Vdq,Wdq,Ib (66),(v1) | ||
782 | 63: vpcmpistri Vdq,Wdq,Ib (66),(v1) | ||
783 | df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) | ||
784 | f0: RORX Gy,Ey,Ib (F2),(v) | ||
732 | EndTable | 785 | EndTable |
733 | 786 | ||
734 | GrpTable: Grp1 | 787 | GrpTable: Grp1 |
@@ -790,7 +843,7 @@ GrpTable: Grp5 | |||
790 | 2: CALLN Ev (f64) | 843 | 2: CALLN Ev (f64) |
791 | 3: CALLF Ep | 844 | 3: CALLF Ep |
792 | 4: JMPN Ev (f64) | 845 | 4: JMPN Ev (f64) |
793 | 5: JMPF Ep | 846 | 5: JMPF Mp |
794 | 6: PUSH Ev (d64) | 847 | 6: PUSH Ev (d64) |
795 | 7: | 848 | 7: |
796 | EndTable | 849 | EndTable |
@@ -807,7 +860,7 @@ EndTable | |||
807 | GrpTable: Grp7 | 860 | GrpTable: Grp7 |
808 | 0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B) | 861 | 0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B) |
809 | 1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001) | 862 | 1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001) |
810 | 2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | 863 | 2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) |
811 | 3: LIDT Ms | 864 | 3: LIDT Ms |
812 | 4: SMSW Mw/Rv | 865 | 4: SMSW Mw/Rv |
813 | 5: | 866 | 5: |
@@ -824,44 +877,45 @@ EndTable | |||
824 | 877 | ||
825 | GrpTable: Grp9 | 878 | GrpTable: Grp9 |
826 | 1: CMPXCHG8B/16B Mq/Mdq | 879 | 1: CMPXCHG8B/16B Mq/Mdq |
827 | 6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | 880 | 6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B) |
828 | 7: VMPTRST Mq | 881 | 7: VMPTRST Mq | VMPTRST Mq (F3) |
829 | EndTable | 882 | EndTable |
830 | 883 | ||
831 | GrpTable: Grp10 | 884 | GrpTable: Grp10 |
832 | EndTable | 885 | EndTable |
833 | 886 | ||
834 | GrpTable: Grp11 | 887 | GrpTable: Grp11 |
888 | # Note: the operands are given by group opcode | ||
835 | 0: MOV | 889 | 0: MOV |
836 | EndTable | 890 | EndTable |
837 | 891 | ||
838 | GrpTable: Grp12 | 892 | GrpTable: Grp12 |
839 | 2: psrlw Nq,Ib (11B) | psrlw Udq,Ib (66),(11B),(VEX),(o128) | 893 | 2: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1) |
840 | 4: psraw Nq,Ib (11B) | psraw Udq,Ib (66),(11B),(VEX),(o128) | 894 | 4: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1) |
841 | 6: psllw Nq,Ib (11B) | psllw Udq,Ib (66),(11B),(VEX),(o128) | 895 | 6: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1) |
842 | EndTable | 896 | EndTable |
843 | 897 | ||
844 | GrpTable: Grp13 | 898 | GrpTable: Grp13 |
845 | 2: psrld Nq,Ib (11B) | psrld Udq,Ib (66),(11B),(VEX),(o128) | 899 | 2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1) |
846 | 4: psrad Nq,Ib (11B) | psrad Udq,Ib (66),(11B),(VEX),(o128) | 900 | 4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) |
847 | 6: pslld Nq,Ib (11B) | pslld Udq,Ib (66),(11B),(VEX),(o128) | 901 | 6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1) |
848 | EndTable | 902 | EndTable |
849 | 903 | ||
850 | GrpTable: Grp14 | 904 | GrpTable: Grp14 |
851 | 2: psrlq Nq,Ib (11B) | psrlq Udq,Ib (66),(11B),(VEX),(o128) | 905 | 2: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1) |
852 | 3: psrldq Udq,Ib (66),(11B),(VEX),(o128) | 906 | 3: vpsrldq Hx,Ux,Ib (66),(11B),(v1) |
853 | 6: psllq Nq,Ib (11B) | psllq Udq,Ib (66),(11B),(VEX),(o128) | 907 | 6: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1) |
854 | 7: pslldq Udq,Ib (66),(11B),(VEX),(o128) | 908 | 7: vpslldq Hx,Ux,Ib (66),(11B),(v1) |
855 | EndTable | 909 | EndTable |
856 | 910 | ||
857 | GrpTable: Grp15 | 911 | GrpTable: Grp15 |
858 | 0: fxsave | 912 | 0: fxsave | RDFSBASE Ry (F3),(11B) |
859 | 1: fxstor | 913 | 1: fxstor | RDGSBASE Ry (F3),(11B) |
860 | 2: ldmxcsr (VEX) | 914 | 2: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B) |
861 | 3: stmxcsr (VEX) | 915 | 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) |
862 | 4: XSAVE | 916 | 4: XSAVE |
863 | 5: XRSTOR | lfence (11B) | 917 | 5: XRSTOR | lfence (11B) |
864 | 6: mfence (11B) | 918 | 6: XSAVEOPT | mfence (11B) |
865 | 7: clflush | sfence (11B) | 919 | 7: clflush | sfence (11B) |
866 | EndTable | 920 | EndTable |
867 | 921 | ||
@@ -872,6 +926,12 @@ GrpTable: Grp16 | |||
872 | 3: prefetch T2 | 926 | 3: prefetch T2 |
873 | EndTable | 927 | EndTable |
874 | 928 | ||
929 | GrpTable: Grp17 | ||
930 | 1: BLSR By,Ey (v) | ||
931 | 2: BLSMSK By,Ey (v) | ||
932 | 3: BLSI By,Ey (v) | ||
933 | EndTable | ||
934 | |||
875 | # AMD's Prefetch Group | 935 | # AMD's Prefetch Group |
876 | GrpTable: GrpP | 936 | GrpTable: GrpP |
877 | 0: PREFETCH | 937 | 0: PREFETCH |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 3d11327c9ab4..23d8e5fecf76 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
@@ -27,6 +27,4 @@ obj-$(CONFIG_AMD_NUMA) += amdtopology.o | |||
27 | obj-$(CONFIG_ACPI_NUMA) += srat.o | 27 | obj-$(CONFIG_ACPI_NUMA) += srat.o |
28 | obj-$(CONFIG_NUMA_EMU) += numa_emulation.o | 28 | obj-$(CONFIG_NUMA_EMU) += numa_emulation.o |
29 | 29 | ||
30 | obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o | ||
31 | |||
32 | obj-$(CONFIG_MEMTEST) += memtest.o | 30 | obj-$(CONFIG_MEMTEST) += memtest.o |
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 87488b93a65c..a298914058f9 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -67,7 +67,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse, | |||
67 | good_end = max_pfn_mapped << PAGE_SHIFT; | 67 | good_end = max_pfn_mapped << PAGE_SHIFT; |
68 | 68 | ||
69 | base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE); | 69 | base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE); |
70 | if (base == MEMBLOCK_ERROR) | 70 | if (!base) |
71 | panic("Cannot find space for the kernel page tables"); | 71 | panic("Cannot find space for the kernel page tables"); |
72 | 72 | ||
73 | pgt_buf_start = base >> PAGE_SHIFT; | 73 | pgt_buf_start = base >> PAGE_SHIFT; |
@@ -80,7 +80,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse, | |||
80 | 80 | ||
81 | void __init native_pagetable_reserve(u64 start, u64 end) | 81 | void __init native_pagetable_reserve(u64 start, u64 end) |
82 | { | 82 | { |
83 | memblock_x86_reserve_range(start, end, "PGTABLE"); | 83 | memblock_reserve(start, end - start); |
84 | } | 84 | } |
85 | 85 | ||
86 | struct map_range { | 86 | struct map_range { |
@@ -279,8 +279,8 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
279 | * pgt_buf_end) and free the other ones (pgt_buf_end - pgt_buf_top) | 279 | * pgt_buf_end) and free the other ones (pgt_buf_end - pgt_buf_top) |
280 | * so that they can be reused for other purposes. | 280 | * so that they can be reused for other purposes. |
281 | * | 281 | * |
282 | * On native it just means calling memblock_x86_reserve_range, on Xen it | 282 | * On native it just means calling memblock_reserve, on Xen it also |
283 | * also means marking RW the pagetable pages that we allocated before | 283 | * means marking RW the pagetable pages that we allocated before |
284 | * but that haven't been used. | 284 | * but that haven't been used. |
285 | * | 285 | * |
286 | * In fact on xen we mark RO the whole range pgt_buf_start - | 286 | * In fact on xen we mark RO the whole range pgt_buf_start - |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 29f7c6d98179..0c1da394a634 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -427,23 +427,17 @@ static void __init add_one_highpage_init(struct page *page) | |||
427 | void __init add_highpages_with_active_regions(int nid, | 427 | void __init add_highpages_with_active_regions(int nid, |
428 | unsigned long start_pfn, unsigned long end_pfn) | 428 | unsigned long start_pfn, unsigned long end_pfn) |
429 | { | 429 | { |
430 | struct range *range; | 430 | phys_addr_t start, end; |
431 | int nr_range; | 431 | u64 i; |
432 | int i; | 432 | |
433 | 433 | for_each_free_mem_range(i, nid, &start, &end, NULL) { | |
434 | nr_range = __get_free_all_memory_range(&range, nid, start_pfn, end_pfn); | 434 | unsigned long pfn = clamp_t(unsigned long, PFN_UP(start), |
435 | 435 | start_pfn, end_pfn); | |
436 | for (i = 0; i < nr_range; i++) { | 436 | unsigned long e_pfn = clamp_t(unsigned long, PFN_DOWN(end), |
437 | struct page *page; | 437 | start_pfn, end_pfn); |
438 | int node_pfn; | 438 | for ( ; pfn < e_pfn; pfn++) |
439 | 439 | if (pfn_valid(pfn)) | |
440 | for (node_pfn = range[i].start; node_pfn < range[i].end; | 440 | add_one_highpage_init(pfn_to_page(pfn)); |
441 | node_pfn++) { | ||
442 | if (!pfn_valid(node_pfn)) | ||
443 | continue; | ||
444 | page = pfn_to_page(node_pfn); | ||
445 | add_one_highpage_init(page); | ||
446 | } | ||
447 | } | 441 | } |
448 | } | 442 | } |
449 | #else | 443 | #else |
@@ -650,18 +644,18 @@ void __init initmem_init(void) | |||
650 | highstart_pfn = highend_pfn = max_pfn; | 644 | highstart_pfn = highend_pfn = max_pfn; |
651 | if (max_pfn > max_low_pfn) | 645 | if (max_pfn > max_low_pfn) |
652 | highstart_pfn = max_low_pfn; | 646 | highstart_pfn = max_low_pfn; |
653 | memblock_x86_register_active_regions(0, 0, highend_pfn); | ||
654 | sparse_memory_present_with_active_regions(0); | ||
655 | printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", | 647 | printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", |
656 | pages_to_mb(highend_pfn - highstart_pfn)); | 648 | pages_to_mb(highend_pfn - highstart_pfn)); |
657 | num_physpages = highend_pfn; | 649 | num_physpages = highend_pfn; |
658 | high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1; | 650 | high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1; |
659 | #else | 651 | #else |
660 | memblock_x86_register_active_regions(0, 0, max_low_pfn); | ||
661 | sparse_memory_present_with_active_regions(0); | ||
662 | num_physpages = max_low_pfn; | 652 | num_physpages = max_low_pfn; |
663 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1; | 653 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1; |
664 | #endif | 654 | #endif |
655 | |||
656 | memblock_set_node(0, (phys_addr_t)ULLONG_MAX, 0); | ||
657 | sparse_memory_present_with_active_regions(0); | ||
658 | |||
665 | #ifdef CONFIG_FLATMEM | 659 | #ifdef CONFIG_FLATMEM |
666 | max_mapnr = num_physpages; | 660 | max_mapnr = num_physpages; |
667 | #endif | 661 | #endif |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index bbaaa005bf0e..a8a56ce3a962 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -608,7 +608,7 @@ kernel_physical_mapping_init(unsigned long start, | |||
608 | #ifndef CONFIG_NUMA | 608 | #ifndef CONFIG_NUMA |
609 | void __init initmem_init(void) | 609 | void __init initmem_init(void) |
610 | { | 610 | { |
611 | memblock_x86_register_active_regions(0, 0, max_pfn); | 611 | memblock_set_node(0, (phys_addr_t)ULLONG_MAX, 0); |
612 | } | 612 | } |
613 | #endif | 613 | #endif |
614 | 614 | ||
diff --git a/arch/x86/mm/memblock.c b/arch/x86/mm/memblock.c deleted file mode 100644 index 992da5ec5a64..000000000000 --- a/arch/x86/mm/memblock.c +++ /dev/null | |||
@@ -1,348 +0,0 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/types.h> | ||
3 | #include <linux/init.h> | ||
4 | #include <linux/bitops.h> | ||
5 | #include <linux/memblock.h> | ||
6 | #include <linux/bootmem.h> | ||
7 | #include <linux/mm.h> | ||
8 | #include <linux/range.h> | ||
9 | |||
10 | /* Check for already reserved areas */ | ||
11 | bool __init memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align) | ||
12 | { | ||
13 | struct memblock_region *r; | ||
14 | u64 addr = *addrp, last; | ||
15 | u64 size = *sizep; | ||
16 | bool changed = false; | ||
17 | |||
18 | again: | ||
19 | last = addr + size; | ||
20 | for_each_memblock(reserved, r) { | ||
21 | if (last > r->base && addr < r->base) { | ||
22 | size = r->base - addr; | ||
23 | changed = true; | ||
24 | goto again; | ||
25 | } | ||
26 | if (last > (r->base + r->size) && addr < (r->base + r->size)) { | ||
27 | addr = round_up(r->base + r->size, align); | ||
28 | size = last - addr; | ||
29 | changed = true; | ||
30 | goto again; | ||
31 | } | ||
32 | if (last <= (r->base + r->size) && addr >= r->base) { | ||
33 | *sizep = 0; | ||
34 | return false; | ||
35 | } | ||
36 | } | ||
37 | if (changed) { | ||
38 | *addrp = addr; | ||
39 | *sizep = size; | ||
40 | } | ||
41 | return changed; | ||
42 | } | ||
43 | |||
44 | /* | ||
45 | * Find next free range after start, and size is returned in *sizep | ||
46 | */ | ||
47 | u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align) | ||
48 | { | ||
49 | struct memblock_region *r; | ||
50 | |||
51 | for_each_memblock(memory, r) { | ||
52 | u64 ei_start = r->base; | ||
53 | u64 ei_last = ei_start + r->size; | ||
54 | u64 addr; | ||
55 | |||
56 | addr = round_up(ei_start, align); | ||
57 | if (addr < start) | ||
58 | addr = round_up(start, align); | ||
59 | if (addr >= ei_last) | ||
60 | continue; | ||
61 | *sizep = ei_last - addr; | ||
62 | while (memblock_x86_check_reserved_size(&addr, sizep, align)) | ||
63 | ; | ||
64 | |||
65 | if (*sizep) | ||
66 | return addr; | ||
67 | } | ||
68 | |||
69 | return MEMBLOCK_ERROR; | ||
70 | } | ||
71 | |||
72 | static __init struct range *find_range_array(int count) | ||
73 | { | ||
74 | u64 end, size, mem; | ||
75 | struct range *range; | ||
76 | |||
77 | size = sizeof(struct range) * count; | ||
78 | end = memblock.current_limit; | ||
79 | |||
80 | mem = memblock_find_in_range(0, end, size, sizeof(struct range)); | ||
81 | if (mem == MEMBLOCK_ERROR) | ||
82 | panic("can not find more space for range array"); | ||
83 | |||
84 | /* | ||
85 | * This range is tempoaray, so don't reserve it, it will not be | ||
86 | * overlapped because We will not alloccate new buffer before | ||
87 | * We discard this one | ||
88 | */ | ||
89 | range = __va(mem); | ||
90 | memset(range, 0, size); | ||
91 | |||
92 | return range; | ||
93 | } | ||
94 | |||
95 | static void __init memblock_x86_subtract_reserved(struct range *range, int az) | ||
96 | { | ||
97 | u64 final_start, final_end; | ||
98 | struct memblock_region *r; | ||
99 | |||
100 | /* Take out region array itself at first*/ | ||
101 | memblock_free_reserved_regions(); | ||
102 | |||
103 | memblock_dbg("Subtract (%ld early reservations)\n", memblock.reserved.cnt); | ||
104 | |||
105 | for_each_memblock(reserved, r) { | ||
106 | memblock_dbg(" [%010llx-%010llx]\n", (u64)r->base, (u64)r->base + r->size - 1); | ||
107 | final_start = PFN_DOWN(r->base); | ||
108 | final_end = PFN_UP(r->base + r->size); | ||
109 | if (final_start >= final_end) | ||
110 | continue; | ||
111 | subtract_range(range, az, final_start, final_end); | ||
112 | } | ||
113 | |||
114 | /* Put region array back ? */ | ||
115 | memblock_reserve_reserved_regions(); | ||
116 | } | ||
117 | |||
118 | struct count_data { | ||
119 | int nr; | ||
120 | }; | ||
121 | |||
122 | static int __init count_work_fn(unsigned long start_pfn, | ||
123 | unsigned long end_pfn, void *datax) | ||
124 | { | ||
125 | struct count_data *data = datax; | ||
126 | |||
127 | data->nr++; | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int __init count_early_node_map(int nodeid) | ||
133 | { | ||
134 | struct count_data data; | ||
135 | |||
136 | data.nr = 0; | ||
137 | work_with_active_regions(nodeid, count_work_fn, &data); | ||
138 | |||
139 | return data.nr; | ||
140 | } | ||
141 | |||
142 | int __init __get_free_all_memory_range(struct range **rangep, int nodeid, | ||
143 | unsigned long start_pfn, unsigned long end_pfn) | ||
144 | { | ||
145 | int count; | ||
146 | struct range *range; | ||
147 | int nr_range; | ||
148 | |||
149 | count = (memblock.reserved.cnt + count_early_node_map(nodeid)) * 2; | ||
150 | |||
151 | range = find_range_array(count); | ||
152 | nr_range = 0; | ||
153 | |||
154 | /* | ||
155 | * Use early_node_map[] and memblock.reserved.region to get range array | ||
156 | * at first | ||
157 | */ | ||
158 | nr_range = add_from_early_node_map(range, count, nr_range, nodeid); | ||
159 | subtract_range(range, count, 0, start_pfn); | ||
160 | subtract_range(range, count, end_pfn, -1ULL); | ||
161 | |||
162 | memblock_x86_subtract_reserved(range, count); | ||
163 | nr_range = clean_sort_range(range, count); | ||
164 | |||
165 | *rangep = range; | ||
166 | return nr_range; | ||
167 | } | ||
168 | |||
169 | int __init get_free_all_memory_range(struct range **rangep, int nodeid) | ||
170 | { | ||
171 | unsigned long end_pfn = -1UL; | ||
172 | |||
173 | #ifdef CONFIG_X86_32 | ||
174 | end_pfn = max_low_pfn; | ||
175 | #endif | ||
176 | return __get_free_all_memory_range(rangep, nodeid, 0, end_pfn); | ||
177 | } | ||
178 | |||
179 | static u64 __init __memblock_x86_memory_in_range(u64 addr, u64 limit, bool get_free) | ||
180 | { | ||
181 | int i, count; | ||
182 | struct range *range; | ||
183 | int nr_range; | ||
184 | u64 final_start, final_end; | ||
185 | u64 free_size; | ||
186 | struct memblock_region *r; | ||
187 | |||
188 | count = (memblock.reserved.cnt + memblock.memory.cnt) * 2; | ||
189 | |||
190 | range = find_range_array(count); | ||
191 | nr_range = 0; | ||
192 | |||
193 | addr = PFN_UP(addr); | ||
194 | limit = PFN_DOWN(limit); | ||
195 | |||
196 | for_each_memblock(memory, r) { | ||
197 | final_start = PFN_UP(r->base); | ||
198 | final_end = PFN_DOWN(r->base + r->size); | ||
199 | if (final_start >= final_end) | ||
200 | continue; | ||
201 | if (final_start >= limit || final_end <= addr) | ||
202 | continue; | ||
203 | |||
204 | nr_range = add_range(range, count, nr_range, final_start, final_end); | ||
205 | } | ||
206 | subtract_range(range, count, 0, addr); | ||
207 | subtract_range(range, count, limit, -1ULL); | ||
208 | |||
209 | /* Subtract memblock.reserved.region in range ? */ | ||
210 | if (!get_free) | ||
211 | goto sort_and_count_them; | ||
212 | for_each_memblock(reserved, r) { | ||
213 | final_start = PFN_DOWN(r->base); | ||
214 | final_end = PFN_UP(r->base + r->size); | ||
215 | if (final_start >= final_end) | ||
216 | continue; | ||
217 | if (final_start >= limit || final_end <= addr) | ||
218 | continue; | ||
219 | |||
220 | subtract_range(range, count, final_start, final_end); | ||
221 | } | ||
222 | |||
223 | sort_and_count_them: | ||
224 | nr_range = clean_sort_range(range, count); | ||
225 | |||
226 | free_size = 0; | ||
227 | for (i = 0; i < nr_range; i++) | ||
228 | free_size += range[i].end - range[i].start; | ||
229 | |||
230 | return free_size << PAGE_SHIFT; | ||
231 | } | ||
232 | |||
233 | u64 __init memblock_x86_free_memory_in_range(u64 addr, u64 limit) | ||
234 | { | ||
235 | return __memblock_x86_memory_in_range(addr, limit, true); | ||
236 | } | ||
237 | |||
238 | u64 __init memblock_x86_memory_in_range(u64 addr, u64 limit) | ||
239 | { | ||
240 | return __memblock_x86_memory_in_range(addr, limit, false); | ||
241 | } | ||
242 | |||
243 | void __init memblock_x86_reserve_range(u64 start, u64 end, char *name) | ||
244 | { | ||
245 | if (start == end) | ||
246 | return; | ||
247 | |||
248 | if (WARN_ONCE(start > end, "memblock_x86_reserve_range: wrong range [%#llx, %#llx)\n", start, end)) | ||
249 | return; | ||
250 | |||
251 | memblock_dbg(" memblock_x86_reserve_range: [%#010llx-%#010llx] %16s\n", start, end - 1, name); | ||
252 | |||
253 | memblock_reserve(start, end - start); | ||
254 | } | ||
255 | |||
256 | void __init memblock_x86_free_range(u64 start, u64 end) | ||
257 | { | ||
258 | if (start == end) | ||
259 | return; | ||
260 | |||
261 | if (WARN_ONCE(start > end, "memblock_x86_free_range: wrong range [%#llx, %#llx)\n", start, end)) | ||
262 | return; | ||
263 | |||
264 | memblock_dbg(" memblock_x86_free_range: [%#010llx-%#010llx]\n", start, end - 1); | ||
265 | |||
266 | memblock_free(start, end - start); | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * Need to call this function after memblock_x86_register_active_regions, | ||
271 | * so early_node_map[] is filled already. | ||
272 | */ | ||
273 | u64 __init memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align) | ||
274 | { | ||
275 | u64 addr; | ||
276 | addr = find_memory_core_early(nid, size, align, start, end); | ||
277 | if (addr != MEMBLOCK_ERROR) | ||
278 | return addr; | ||
279 | |||
280 | /* Fallback, should already have start end within node range */ | ||
281 | return memblock_find_in_range(start, end, size, align); | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * Finds an active region in the address range from start_pfn to last_pfn and | ||
286 | * returns its range in ei_startpfn and ei_endpfn for the memblock entry. | ||
287 | */ | ||
288 | static int __init memblock_x86_find_active_region(const struct memblock_region *ei, | ||
289 | unsigned long start_pfn, | ||
290 | unsigned long last_pfn, | ||
291 | unsigned long *ei_startpfn, | ||
292 | unsigned long *ei_endpfn) | ||
293 | { | ||
294 | u64 align = PAGE_SIZE; | ||
295 | |||
296 | *ei_startpfn = round_up(ei->base, align) >> PAGE_SHIFT; | ||
297 | *ei_endpfn = round_down(ei->base + ei->size, align) >> PAGE_SHIFT; | ||
298 | |||
299 | /* Skip map entries smaller than a page */ | ||
300 | if (*ei_startpfn >= *ei_endpfn) | ||
301 | return 0; | ||
302 | |||
303 | /* Skip if map is outside the node */ | ||
304 | if (*ei_endpfn <= start_pfn || *ei_startpfn >= last_pfn) | ||
305 | return 0; | ||
306 | |||
307 | /* Check for overlaps */ | ||
308 | if (*ei_startpfn < start_pfn) | ||
309 | *ei_startpfn = start_pfn; | ||
310 | if (*ei_endpfn > last_pfn) | ||
311 | *ei_endpfn = last_pfn; | ||
312 | |||
313 | return 1; | ||
314 | } | ||
315 | |||
316 | /* Walk the memblock.memory map and register active regions within a node */ | ||
317 | void __init memblock_x86_register_active_regions(int nid, unsigned long start_pfn, | ||
318 | unsigned long last_pfn) | ||
319 | { | ||
320 | unsigned long ei_startpfn; | ||
321 | unsigned long ei_endpfn; | ||
322 | struct memblock_region *r; | ||
323 | |||
324 | for_each_memblock(memory, r) | ||
325 | if (memblock_x86_find_active_region(r, start_pfn, last_pfn, | ||
326 | &ei_startpfn, &ei_endpfn)) | ||
327 | add_active_range(nid, ei_startpfn, ei_endpfn); | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Find the hole size (in bytes) in the memory range. | ||
332 | * @start: starting address of the memory range to scan | ||
333 | * @end: ending address of the memory range to scan | ||
334 | */ | ||
335 | u64 __init memblock_x86_hole_size(u64 start, u64 end) | ||
336 | { | ||
337 | unsigned long start_pfn = start >> PAGE_SHIFT; | ||
338 | unsigned long last_pfn = end >> PAGE_SHIFT; | ||
339 | unsigned long ei_startpfn, ei_endpfn, ram = 0; | ||
340 | struct memblock_region *r; | ||
341 | |||
342 | for_each_memblock(memory, r) | ||
343 | if (memblock_x86_find_active_region(r, start_pfn, last_pfn, | ||
344 | &ei_startpfn, &ei_endpfn)) | ||
345 | ram += ei_endpfn - ei_startpfn; | ||
346 | |||
347 | return end - start - ((u64)ram << PAGE_SHIFT); | ||
348 | } | ||
diff --git a/arch/x86/mm/memtest.c b/arch/x86/mm/memtest.c index 92faf3a1c53e..c80b9fb95734 100644 --- a/arch/x86/mm/memtest.c +++ b/arch/x86/mm/memtest.c | |||
@@ -34,7 +34,7 @@ static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad) | |||
34 | (unsigned long long) pattern, | 34 | (unsigned long long) pattern, |
35 | (unsigned long long) start_bad, | 35 | (unsigned long long) start_bad, |
36 | (unsigned long long) end_bad); | 36 | (unsigned long long) end_bad); |
37 | memblock_x86_reserve_range(start_bad, end_bad, "BAD RAM"); | 37 | memblock_reserve(start_bad, end_bad - start_bad); |
38 | } | 38 | } |
39 | 39 | ||
40 | static void __init memtest(u64 pattern, u64 start_phys, u64 size) | 40 | static void __init memtest(u64 pattern, u64 start_phys, u64 size) |
@@ -70,24 +70,19 @@ static void __init memtest(u64 pattern, u64 start_phys, u64 size) | |||
70 | 70 | ||
71 | static void __init do_one_pass(u64 pattern, u64 start, u64 end) | 71 | static void __init do_one_pass(u64 pattern, u64 start, u64 end) |
72 | { | 72 | { |
73 | u64 size = 0; | 73 | u64 i; |
74 | 74 | phys_addr_t this_start, this_end; | |
75 | while (start < end) { | 75 | |
76 | start = memblock_x86_find_in_range_size(start, &size, 1); | 76 | for_each_free_mem_range(i, MAX_NUMNODES, &this_start, &this_end, NULL) { |
77 | 77 | this_start = clamp_t(phys_addr_t, this_start, start, end); | |
78 | /* done ? */ | 78 | this_end = clamp_t(phys_addr_t, this_end, start, end); |
79 | if (start >= end) | 79 | if (this_start < this_end) { |
80 | break; | 80 | printk(KERN_INFO " %010llx - %010llx pattern %016llx\n", |
81 | if (start + size > end) | 81 | (unsigned long long)this_start, |
82 | size = end - start; | 82 | (unsigned long long)this_end, |
83 | 83 | (unsigned long long)cpu_to_be64(pattern)); | |
84 | printk(KERN_INFO " %010llx - %010llx pattern %016llx\n", | 84 | memtest(pattern, this_start, this_end - this_start); |
85 | (unsigned long long) start, | 85 | } |
86 | (unsigned long long) start + size, | ||
87 | (unsigned long long) cpu_to_be64(pattern)); | ||
88 | memtest(pattern, start, size); | ||
89 | |||
90 | start += size; | ||
91 | } | 86 | } |
92 | } | 87 | } |
93 | 88 | ||
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index fbeaaf416610..496f494593bf 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c | |||
@@ -192,8 +192,6 @@ int __init numa_add_memblk(int nid, u64 start, u64 end) | |||
192 | /* Initialize NODE_DATA for a node on the local memory */ | 192 | /* Initialize NODE_DATA for a node on the local memory */ |
193 | static void __init setup_node_data(int nid, u64 start, u64 end) | 193 | static void __init setup_node_data(int nid, u64 start, u64 end) |
194 | { | 194 | { |
195 | const u64 nd_low = PFN_PHYS(MAX_DMA_PFN); | ||
196 | const u64 nd_high = PFN_PHYS(max_pfn_mapped); | ||
197 | const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE); | 195 | const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE); |
198 | bool remapped = false; | 196 | bool remapped = false; |
199 | u64 nd_pa; | 197 | u64 nd_pa; |
@@ -224,17 +222,12 @@ static void __init setup_node_data(int nid, u64 start, u64 end) | |||
224 | nd_pa = __pa(nd); | 222 | nd_pa = __pa(nd); |
225 | remapped = true; | 223 | remapped = true; |
226 | } else { | 224 | } else { |
227 | nd_pa = memblock_x86_find_in_range_node(nid, nd_low, nd_high, | 225 | nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); |
228 | nd_size, SMP_CACHE_BYTES); | 226 | if (!nd_pa) { |
229 | if (nd_pa == MEMBLOCK_ERROR) | ||
230 | nd_pa = memblock_find_in_range(nd_low, nd_high, | ||
231 | nd_size, SMP_CACHE_BYTES); | ||
232 | if (nd_pa == MEMBLOCK_ERROR) { | ||
233 | pr_err("Cannot find %zu bytes in node %d\n", | 227 | pr_err("Cannot find %zu bytes in node %d\n", |
234 | nd_size, nid); | 228 | nd_size, nid); |
235 | return; | 229 | return; |
236 | } | 230 | } |
237 | memblock_x86_reserve_range(nd_pa, nd_pa + nd_size, "NODE_DATA"); | ||
238 | nd = __va(nd_pa); | 231 | nd = __va(nd_pa); |
239 | } | 232 | } |
240 | 233 | ||
@@ -371,8 +364,7 @@ void __init numa_reset_distance(void) | |||
371 | 364 | ||
372 | /* numa_distance could be 1LU marking allocation failure, test cnt */ | 365 | /* numa_distance could be 1LU marking allocation failure, test cnt */ |
373 | if (numa_distance_cnt) | 366 | if (numa_distance_cnt) |
374 | memblock_x86_free_range(__pa(numa_distance), | 367 | memblock_free(__pa(numa_distance), size); |
375 | __pa(numa_distance) + size); | ||
376 | numa_distance_cnt = 0; | 368 | numa_distance_cnt = 0; |
377 | numa_distance = NULL; /* enable table creation */ | 369 | numa_distance = NULL; /* enable table creation */ |
378 | } | 370 | } |
@@ -395,13 +387,13 @@ static int __init numa_alloc_distance(void) | |||
395 | 387 | ||
396 | phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), | 388 | phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), |
397 | size, PAGE_SIZE); | 389 | size, PAGE_SIZE); |
398 | if (phys == MEMBLOCK_ERROR) { | 390 | if (!phys) { |
399 | pr_warning("NUMA: Warning: can't allocate distance table!\n"); | 391 | pr_warning("NUMA: Warning: can't allocate distance table!\n"); |
400 | /* don't retry until explicitly reset */ | 392 | /* don't retry until explicitly reset */ |
401 | numa_distance = (void *)1LU; | 393 | numa_distance = (void *)1LU; |
402 | return -ENOMEM; | 394 | return -ENOMEM; |
403 | } | 395 | } |
404 | memblock_x86_reserve_range(phys, phys + size, "NUMA DIST"); | 396 | memblock_reserve(phys, size); |
405 | 397 | ||
406 | numa_distance = __va(phys); | 398 | numa_distance = __va(phys); |
407 | numa_distance_cnt = cnt; | 399 | numa_distance_cnt = cnt; |
@@ -482,8 +474,8 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi) | |||
482 | numaram = 0; | 474 | numaram = 0; |
483 | } | 475 | } |
484 | 476 | ||
485 | e820ram = max_pfn - (memblock_x86_hole_size(0, | 477 | e820ram = max_pfn - absent_pages_in_range(0, max_pfn); |
486 | PFN_PHYS(max_pfn)) >> PAGE_SHIFT); | 478 | |
487 | /* We seem to lose 3 pages somewhere. Allow 1M of slack. */ | 479 | /* We seem to lose 3 pages somewhere. Allow 1M of slack. */ |
488 | if ((s64)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) { | 480 | if ((s64)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) { |
489 | printk(KERN_ERR "NUMA: nodes only cover %LuMB of your %LuMB e820 RAM. Not used.\n", | 481 | printk(KERN_ERR "NUMA: nodes only cover %LuMB of your %LuMB e820 RAM. Not used.\n", |
@@ -505,13 +497,10 @@ static int __init numa_register_memblks(struct numa_meminfo *mi) | |||
505 | if (WARN_ON(nodes_empty(node_possible_map))) | 497 | if (WARN_ON(nodes_empty(node_possible_map))) |
506 | return -EINVAL; | 498 | return -EINVAL; |
507 | 499 | ||
508 | for (i = 0; i < mi->nr_blks; i++) | 500 | for (i = 0; i < mi->nr_blks; i++) { |
509 | memblock_x86_register_active_regions(mi->blk[i].nid, | 501 | struct numa_memblk *mb = &mi->blk[i]; |
510 | mi->blk[i].start >> PAGE_SHIFT, | 502 | memblock_set_node(mb->start, mb->end - mb->start, mb->nid); |
511 | mi->blk[i].end >> PAGE_SHIFT); | 503 | } |
512 | |||
513 | /* for out of order entries */ | ||
514 | sort_node_map(); | ||
515 | 504 | ||
516 | /* | 505 | /* |
517 | * If sections array is gonna be used for pfn -> nid mapping, check | 506 | * If sections array is gonna be used for pfn -> nid mapping, check |
@@ -545,6 +534,8 @@ static int __init numa_register_memblks(struct numa_meminfo *mi) | |||
545 | setup_node_data(nid, start, end); | 534 | setup_node_data(nid, start, end); |
546 | } | 535 | } |
547 | 536 | ||
537 | /* Dump memblock with node info and return. */ | ||
538 | memblock_dump_all(); | ||
548 | return 0; | 539 | return 0; |
549 | } | 540 | } |
550 | 541 | ||
@@ -582,7 +573,7 @@ static int __init numa_init(int (*init_func)(void)) | |||
582 | nodes_clear(node_possible_map); | 573 | nodes_clear(node_possible_map); |
583 | nodes_clear(node_online_map); | 574 | nodes_clear(node_online_map); |
584 | memset(&numa_meminfo, 0, sizeof(numa_meminfo)); | 575 | memset(&numa_meminfo, 0, sizeof(numa_meminfo)); |
585 | remove_all_active_ranges(); | 576 | WARN_ON(memblock_set_node(0, ULLONG_MAX, MAX_NUMNODES)); |
586 | numa_reset_distance(); | 577 | numa_reset_distance(); |
587 | 578 | ||
588 | ret = init_func(); | 579 | ret = init_func(); |
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 3adebe7e536a..534255a36b6b 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c | |||
@@ -199,23 +199,23 @@ void __init init_alloc_remap(int nid, u64 start, u64 end) | |||
199 | 199 | ||
200 | /* allocate node memory and the lowmem remap area */ | 200 | /* allocate node memory and the lowmem remap area */ |
201 | node_pa = memblock_find_in_range(start, end, size, LARGE_PAGE_BYTES); | 201 | node_pa = memblock_find_in_range(start, end, size, LARGE_PAGE_BYTES); |
202 | if (node_pa == MEMBLOCK_ERROR) { | 202 | if (!node_pa) { |
203 | pr_warning("remap_alloc: failed to allocate %lu bytes for node %d\n", | 203 | pr_warning("remap_alloc: failed to allocate %lu bytes for node %d\n", |
204 | size, nid); | 204 | size, nid); |
205 | return; | 205 | return; |
206 | } | 206 | } |
207 | memblock_x86_reserve_range(node_pa, node_pa + size, "KVA RAM"); | 207 | memblock_reserve(node_pa, size); |
208 | 208 | ||
209 | remap_pa = memblock_find_in_range(min_low_pfn << PAGE_SHIFT, | 209 | remap_pa = memblock_find_in_range(min_low_pfn << PAGE_SHIFT, |
210 | max_low_pfn << PAGE_SHIFT, | 210 | max_low_pfn << PAGE_SHIFT, |
211 | size, LARGE_PAGE_BYTES); | 211 | size, LARGE_PAGE_BYTES); |
212 | if (remap_pa == MEMBLOCK_ERROR) { | 212 | if (!remap_pa) { |
213 | pr_warning("remap_alloc: failed to allocate %lu bytes remap area for node %d\n", | 213 | pr_warning("remap_alloc: failed to allocate %lu bytes remap area for node %d\n", |
214 | size, nid); | 214 | size, nid); |
215 | memblock_x86_free_range(node_pa, node_pa + size); | 215 | memblock_free(node_pa, size); |
216 | return; | 216 | return; |
217 | } | 217 | } |
218 | memblock_x86_reserve_range(remap_pa, remap_pa + size, "KVA PG"); | 218 | memblock_reserve(remap_pa, size); |
219 | remap_va = phys_to_virt(remap_pa); | 219 | remap_va = phys_to_virt(remap_pa); |
220 | 220 | ||
221 | /* perform actual remap */ | 221 | /* perform actual remap */ |
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index dd27f401f0a0..92e27119ee1a 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -19,7 +19,7 @@ unsigned long __init numa_free_all_bootmem(void) | |||
19 | for_each_online_node(i) | 19 | for_each_online_node(i) |
20 | pages += free_all_bootmem_node(NODE_DATA(i)); | 20 | pages += free_all_bootmem_node(NODE_DATA(i)); |
21 | 21 | ||
22 | pages += free_all_memory_core_early(MAX_NUMNODES); | 22 | pages += free_low_memory_core_early(MAX_NUMNODES); |
23 | 23 | ||
24 | return pages; | 24 | return pages; |
25 | } | 25 | } |
diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c index d0ed086b6247..46db56845f18 100644 --- a/arch/x86/mm/numa_emulation.c +++ b/arch/x86/mm/numa_emulation.c | |||
@@ -28,6 +28,16 @@ static int __init emu_find_memblk_by_nid(int nid, const struct numa_meminfo *mi) | |||
28 | return -ENOENT; | 28 | return -ENOENT; |
29 | } | 29 | } |
30 | 30 | ||
31 | static u64 mem_hole_size(u64 start, u64 end) | ||
32 | { | ||
33 | unsigned long start_pfn = PFN_UP(start); | ||
34 | unsigned long end_pfn = PFN_DOWN(end); | ||
35 | |||
36 | if (start_pfn < end_pfn) | ||
37 | return PFN_PHYS(absent_pages_in_range(start_pfn, end_pfn)); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
31 | /* | 41 | /* |
32 | * Sets up nid to range from @start to @end. The return value is -errno if | 42 | * Sets up nid to range from @start to @end. The return value is -errno if |
33 | * something went wrong, 0 otherwise. | 43 | * something went wrong, 0 otherwise. |
@@ -89,7 +99,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei, | |||
89 | * Calculate target node size. x86_32 freaks on __udivdi3() so do | 99 | * Calculate target node size. x86_32 freaks on __udivdi3() so do |
90 | * the division in ulong number of pages and convert back. | 100 | * the division in ulong number of pages and convert back. |
91 | */ | 101 | */ |
92 | size = max_addr - addr - memblock_x86_hole_size(addr, max_addr); | 102 | size = max_addr - addr - mem_hole_size(addr, max_addr); |
93 | size = PFN_PHYS((unsigned long)(size >> PAGE_SHIFT) / nr_nodes); | 103 | size = PFN_PHYS((unsigned long)(size >> PAGE_SHIFT) / nr_nodes); |
94 | 104 | ||
95 | /* | 105 | /* |
@@ -135,8 +145,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei, | |||
135 | * Continue to add memory to this fake node if its | 145 | * Continue to add memory to this fake node if its |
136 | * non-reserved memory is less than the per-node size. | 146 | * non-reserved memory is less than the per-node size. |
137 | */ | 147 | */ |
138 | while (end - start - | 148 | while (end - start - mem_hole_size(start, end) < size) { |
139 | memblock_x86_hole_size(start, end) < size) { | ||
140 | end += FAKE_NODE_MIN_SIZE; | 149 | end += FAKE_NODE_MIN_SIZE; |
141 | if (end > limit) { | 150 | if (end > limit) { |
142 | end = limit; | 151 | end = limit; |
@@ -150,7 +159,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei, | |||
150 | * this one must extend to the boundary. | 159 | * this one must extend to the boundary. |
151 | */ | 160 | */ |
152 | if (end < dma32_end && dma32_end - end - | 161 | if (end < dma32_end && dma32_end - end - |
153 | memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE) | 162 | mem_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE) |
154 | end = dma32_end; | 163 | end = dma32_end; |
155 | 164 | ||
156 | /* | 165 | /* |
@@ -158,8 +167,7 @@ static int __init split_nodes_interleave(struct numa_meminfo *ei, | |||
158 | * next node, this one must extend to the end of the | 167 | * next node, this one must extend to the end of the |
159 | * physical node. | 168 | * physical node. |
160 | */ | 169 | */ |
161 | if (limit - end - | 170 | if (limit - end - mem_hole_size(end, limit) < size) |
162 | memblock_x86_hole_size(end, limit) < size) | ||
163 | end = limit; | 171 | end = limit; |
164 | 172 | ||
165 | ret = emu_setup_memblk(ei, pi, nid++ % nr_nodes, | 173 | ret = emu_setup_memblk(ei, pi, nid++ % nr_nodes, |
@@ -180,7 +188,7 @@ static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size) | |||
180 | { | 188 | { |
181 | u64 end = start + size; | 189 | u64 end = start + size; |
182 | 190 | ||
183 | while (end - start - memblock_x86_hole_size(start, end) < size) { | 191 | while (end - start - mem_hole_size(start, end) < size) { |
184 | end += FAKE_NODE_MIN_SIZE; | 192 | end += FAKE_NODE_MIN_SIZE; |
185 | if (end > max_addr) { | 193 | if (end > max_addr) { |
186 | end = max_addr; | 194 | end = max_addr; |
@@ -211,8 +219,7 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei, | |||
211 | * creates a uniform distribution of node sizes across the entire | 219 | * creates a uniform distribution of node sizes across the entire |
212 | * machine (but not necessarily over physical nodes). | 220 | * machine (but not necessarily over physical nodes). |
213 | */ | 221 | */ |
214 | min_size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / | 222 | min_size = (max_addr - addr - mem_hole_size(addr, max_addr)) / MAX_NUMNODES; |
215 | MAX_NUMNODES; | ||
216 | min_size = max(min_size, FAKE_NODE_MIN_SIZE); | 223 | min_size = max(min_size, FAKE_NODE_MIN_SIZE); |
217 | if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size) | 224 | if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size) |
218 | min_size = (min_size + FAKE_NODE_MIN_SIZE) & | 225 | min_size = (min_size + FAKE_NODE_MIN_SIZE) & |
@@ -252,7 +259,7 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei, | |||
252 | * this one must extend to the boundary. | 259 | * this one must extend to the boundary. |
253 | */ | 260 | */ |
254 | if (end < dma32_end && dma32_end - end - | 261 | if (end < dma32_end && dma32_end - end - |
255 | memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE) | 262 | mem_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE) |
256 | end = dma32_end; | 263 | end = dma32_end; |
257 | 264 | ||
258 | /* | 265 | /* |
@@ -260,8 +267,7 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei, | |||
260 | * next node, this one must extend to the end of the | 267 | * next node, this one must extend to the end of the |
261 | * physical node. | 268 | * physical node. |
262 | */ | 269 | */ |
263 | if (limit - end - | 270 | if (limit - end - mem_hole_size(end, limit) < size) |
264 | memblock_x86_hole_size(end, limit) < size) | ||
265 | end = limit; | 271 | end = limit; |
266 | 272 | ||
267 | ret = emu_setup_memblk(ei, pi, nid++ % MAX_NUMNODES, | 273 | ret = emu_setup_memblk(ei, pi, nid++ % MAX_NUMNODES, |
@@ -351,11 +357,11 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) | |||
351 | 357 | ||
352 | phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), | 358 | phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), |
353 | phys_size, PAGE_SIZE); | 359 | phys_size, PAGE_SIZE); |
354 | if (phys == MEMBLOCK_ERROR) { | 360 | if (!phys) { |
355 | pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n"); | 361 | pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n"); |
356 | goto no_emu; | 362 | goto no_emu; |
357 | } | 363 | } |
358 | memblock_x86_reserve_range(phys, phys + phys_size, "TMP NUMA DIST"); | 364 | memblock_reserve(phys, phys_size); |
359 | phys_dist = __va(phys); | 365 | phys_dist = __va(phys); |
360 | 366 | ||
361 | for (i = 0; i < numa_dist_cnt; i++) | 367 | for (i = 0; i < numa_dist_cnt; i++) |
@@ -424,7 +430,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) | |||
424 | 430 | ||
425 | /* free the copied physical distance table */ | 431 | /* free the copied physical distance table */ |
426 | if (phys_dist) | 432 | if (phys_dist) |
427 | memblock_x86_free_range(__pa(phys_dist), __pa(phys_dist) + phys_size); | 433 | memblock_free(__pa(phys_dist), phys_size); |
428 | return; | 434 | return; |
429 | 435 | ||
430 | no_emu: | 436 | no_emu: |
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index bfab3fa10edc..7b65f752c5f8 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -568,8 +568,8 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; | |||
568 | break; | 568 | break; |
569 | } | 569 | } |
570 | if (filter[i].jt != 0) { | 570 | if (filter[i].jt != 0) { |
571 | if (filter[i].jf) | 571 | if (filter[i].jf && f_offset) |
572 | t_offset += is_near(f_offset) ? 2 : 6; | 572 | t_offset += is_near(f_offset) ? 2 : 5; |
573 | EMIT_COND_JMP(t_op, t_offset); | 573 | EMIT_COND_JMP(t_op, t_offset); |
574 | if (filter[i].jf) | 574 | if (filter[i].jf) |
575 | EMIT_JMP(f_offset); | 575 | EMIT_JMP(f_offset); |
diff --git a/arch/x86/oprofile/Makefile b/arch/x86/oprofile/Makefile index 446902b2a6b6..1599f568f0e2 100644 --- a/arch/x86/oprofile/Makefile +++ b/arch/x86/oprofile/Makefile | |||
@@ -4,9 +4,8 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ | |||
4 | oprof.o cpu_buffer.o buffer_sync.o \ | 4 | oprof.o cpu_buffer.o buffer_sync.o \ |
5 | event_buffer.o oprofile_files.o \ | 5 | event_buffer.o oprofile_files.o \ |
6 | oprofilefs.o oprofile_stats.o \ | 6 | oprofilefs.o oprofile_stats.o \ |
7 | timer_int.o ) | 7 | timer_int.o nmi_timer_int.o ) |
8 | 8 | ||
9 | oprofile-y := $(DRIVER_OBJS) init.o backtrace.o | 9 | oprofile-y := $(DRIVER_OBJS) init.o backtrace.o |
10 | oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_amd.o \ | 10 | oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_amd.o \ |
11 | op_model_ppro.o op_model_p4.o | 11 | op_model_ppro.o op_model_p4.o |
12 | oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o | ||
diff --git a/arch/x86/oprofile/init.c b/arch/x86/oprofile/init.c index f148cf652678..9e138d00ad36 100644 --- a/arch/x86/oprofile/init.c +++ b/arch/x86/oprofile/init.c | |||
@@ -16,37 +16,23 @@ | |||
16 | * with the NMI mode driver. | 16 | * with the NMI mode driver. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #ifdef CONFIG_X86_LOCAL_APIC | ||
19 | extern int op_nmi_init(struct oprofile_operations *ops); | 20 | extern int op_nmi_init(struct oprofile_operations *ops); |
20 | extern int op_nmi_timer_init(struct oprofile_operations *ops); | ||
21 | extern void op_nmi_exit(void); | 21 | extern void op_nmi_exit(void); |
22 | extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth); | 22 | #else |
23 | static int op_nmi_init(struct oprofile_operations *ops) { return -ENODEV; } | ||
24 | static void op_nmi_exit(void) { } | ||
25 | #endif | ||
23 | 26 | ||
24 | static int nmi_timer; | 27 | extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth); |
25 | 28 | ||
26 | int __init oprofile_arch_init(struct oprofile_operations *ops) | 29 | int __init oprofile_arch_init(struct oprofile_operations *ops) |
27 | { | 30 | { |
28 | int ret; | ||
29 | |||
30 | ret = -ENODEV; | ||
31 | |||
32 | #ifdef CONFIG_X86_LOCAL_APIC | ||
33 | ret = op_nmi_init(ops); | ||
34 | #endif | ||
35 | nmi_timer = (ret != 0); | ||
36 | #ifdef CONFIG_X86_IO_APIC | ||
37 | if (nmi_timer) | ||
38 | ret = op_nmi_timer_init(ops); | ||
39 | #endif | ||
40 | ops->backtrace = x86_backtrace; | 31 | ops->backtrace = x86_backtrace; |
41 | 32 | return op_nmi_init(ops); | |
42 | return ret; | ||
43 | } | 33 | } |
44 | 34 | ||
45 | |||
46 | void oprofile_arch_exit(void) | 35 | void oprofile_arch_exit(void) |
47 | { | 36 | { |
48 | #ifdef CONFIG_X86_LOCAL_APIC | 37 | op_nmi_exit(); |
49 | if (!nmi_timer) | ||
50 | op_nmi_exit(); | ||
51 | #endif | ||
52 | } | 38 | } |
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 75f9528e0372..26b8a8514ee5 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c | |||
@@ -595,24 +595,36 @@ static int __init p4_init(char **cpu_type) | |||
595 | return 0; | 595 | return 0; |
596 | } | 596 | } |
597 | 597 | ||
598 | static int force_arch_perfmon; | 598 | enum __force_cpu_type { |
599 | static int force_cpu_type(const char *str, struct kernel_param *kp) | 599 | reserved = 0, /* do not force */ |
600 | timer, | ||
601 | arch_perfmon, | ||
602 | }; | ||
603 | |||
604 | static int force_cpu_type; | ||
605 | |||
606 | static int set_cpu_type(const char *str, struct kernel_param *kp) | ||
600 | { | 607 | { |
601 | if (!strcmp(str, "arch_perfmon")) { | 608 | if (!strcmp(str, "timer")) { |
602 | force_arch_perfmon = 1; | 609 | force_cpu_type = timer; |
610 | printk(KERN_INFO "oprofile: forcing NMI timer mode\n"); | ||
611 | } else if (!strcmp(str, "arch_perfmon")) { | ||
612 | force_cpu_type = arch_perfmon; | ||
603 | printk(KERN_INFO "oprofile: forcing architectural perfmon\n"); | 613 | printk(KERN_INFO "oprofile: forcing architectural perfmon\n"); |
614 | } else { | ||
615 | force_cpu_type = 0; | ||
604 | } | 616 | } |
605 | 617 | ||
606 | return 0; | 618 | return 0; |
607 | } | 619 | } |
608 | module_param_call(cpu_type, force_cpu_type, NULL, NULL, 0); | 620 | module_param_call(cpu_type, set_cpu_type, NULL, NULL, 0); |
609 | 621 | ||
610 | static int __init ppro_init(char **cpu_type) | 622 | static int __init ppro_init(char **cpu_type) |
611 | { | 623 | { |
612 | __u8 cpu_model = boot_cpu_data.x86_model; | 624 | __u8 cpu_model = boot_cpu_data.x86_model; |
613 | struct op_x86_model_spec *spec = &op_ppro_spec; /* default */ | 625 | struct op_x86_model_spec *spec = &op_ppro_spec; /* default */ |
614 | 626 | ||
615 | if (force_arch_perfmon && cpu_has_arch_perfmon) | 627 | if (force_cpu_type == arch_perfmon && cpu_has_arch_perfmon) |
616 | return 0; | 628 | return 0; |
617 | 629 | ||
618 | /* | 630 | /* |
@@ -679,6 +691,9 @@ int __init op_nmi_init(struct oprofile_operations *ops) | |||
679 | if (!cpu_has_apic) | 691 | if (!cpu_has_apic) |
680 | return -ENODEV; | 692 | return -ENODEV; |
681 | 693 | ||
694 | if (force_cpu_type == timer) | ||
695 | return -ENODEV; | ||
696 | |||
682 | switch (vendor) { | 697 | switch (vendor) { |
683 | case X86_VENDOR_AMD: | 698 | case X86_VENDOR_AMD: |
684 | /* Needs to be at least an Athlon (or hammer in 32bit mode) */ | 699 | /* Needs to be at least an Athlon (or hammer in 32bit mode) */ |
diff --git a/arch/x86/oprofile/nmi_timer_int.c b/arch/x86/oprofile/nmi_timer_int.c deleted file mode 100644 index 7f8052cd6620..000000000000 --- a/arch/x86/oprofile/nmi_timer_int.c +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /** | ||
2 | * @file nmi_timer_int.c | ||
3 | * | ||
4 | * @remark Copyright 2003 OProfile authors | ||
5 | * @remark Read the file COPYING | ||
6 | * | ||
7 | * @author Zwane Mwaikambo <zwane@linuxpower.ca> | ||
8 | */ | ||
9 | |||
10 | #include <linux/init.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/oprofile.h> | ||
14 | #include <linux/rcupdate.h> | ||
15 | #include <linux/kdebug.h> | ||
16 | |||
17 | #include <asm/nmi.h> | ||
18 | #include <asm/apic.h> | ||
19 | #include <asm/ptrace.h> | ||
20 | |||
21 | static int profile_timer_exceptions_notify(unsigned int val, struct pt_regs *regs) | ||
22 | { | ||
23 | oprofile_add_sample(regs, 0); | ||
24 | return NMI_HANDLED; | ||
25 | } | ||
26 | |||
27 | static int timer_start(void) | ||
28 | { | ||
29 | if (register_nmi_handler(NMI_LOCAL, profile_timer_exceptions_notify, | ||
30 | 0, "oprofile-timer")) | ||
31 | return 1; | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | |||
36 | static void timer_stop(void) | ||
37 | { | ||
38 | unregister_nmi_handler(NMI_LOCAL, "oprofile-timer"); | ||
39 | synchronize_sched(); /* Allow already-started NMIs to complete. */ | ||
40 | } | ||
41 | |||
42 | |||
43 | int __init op_nmi_timer_init(struct oprofile_operations *ops) | ||
44 | { | ||
45 | ops->start = timer_start; | ||
46 | ops->stop = timer_stop; | ||
47 | ops->cpu_type = "timer"; | ||
48 | printk(KERN_INFO "oprofile: using NMI timer interrupt.\n"); | ||
49 | return 0; | ||
50 | } | ||
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 37718f0f053d..4a01967f02e7 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -352,8 +352,7 @@ void __init efi_memblock_x86_reserve_range(void) | |||
352 | boot_params.efi_info.efi_memdesc_size; | 352 | boot_params.efi_info.efi_memdesc_size; |
353 | memmap.desc_version = boot_params.efi_info.efi_memdesc_version; | 353 | memmap.desc_version = boot_params.efi_info.efi_memdesc_version; |
354 | memmap.desc_size = boot_params.efi_info.efi_memdesc_size; | 354 | memmap.desc_size = boot_params.efi_info.efi_memdesc_size; |
355 | memblock_x86_reserve_range(pmap, pmap + memmap.nr_map * memmap.desc_size, | 355 | memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); |
356 | "EFI memmap"); | ||
357 | } | 356 | } |
358 | 357 | ||
359 | #if EFI_DEBUG | 358 | #if EFI_DEBUG |
@@ -397,16 +396,14 @@ void __init efi_reserve_boot_services(void) | |||
397 | if ((start+size >= virt_to_phys(_text) | 396 | if ((start+size >= virt_to_phys(_text) |
398 | && start <= virt_to_phys(_end)) || | 397 | && start <= virt_to_phys(_end)) || |
399 | !e820_all_mapped(start, start+size, E820_RAM) || | 398 | !e820_all_mapped(start, start+size, E820_RAM) || |
400 | memblock_x86_check_reserved_size(&start, &size, | 399 | memblock_is_region_reserved(start, size)) { |
401 | 1<<EFI_PAGE_SHIFT)) { | ||
402 | /* Could not reserve, skip it */ | 400 | /* Could not reserve, skip it */ |
403 | md->num_pages = 0; | 401 | md->num_pages = 0; |
404 | memblock_dbg(PFX "Could not reserve boot range " | 402 | memblock_dbg(PFX "Could not reserve boot range " |
405 | "[0x%010llx-0x%010llx]\n", | 403 | "[0x%010llx-0x%010llx]\n", |
406 | start, start+size-1); | 404 | start, start+size-1); |
407 | } else | 405 | } else |
408 | memblock_x86_reserve_range(start, start+size, | 406 | memblock_reserve(start, size); |
409 | "EFI Boot"); | ||
410 | } | 407 | } |
411 | } | 408 | } |
412 | 409 | ||
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile index f82082677337..d511aa97533a 100644 --- a/arch/x86/tools/Makefile +++ b/arch/x86/tools/Makefile | |||
@@ -18,14 +18,21 @@ chkobjdump = $(srctree)/arch/x86/tools/chkobjdump.awk | |||
18 | quiet_cmd_posttest = TEST $@ | 18 | quiet_cmd_posttest = TEST $@ |
19 | cmd_posttest = ($(OBJDUMP) -v | $(AWK) -f $(chkobjdump)) || $(OBJDUMP) -d -j .text $(objtree)/vmlinux | $(AWK) -f $(distill_awk) | $(obj)/test_get_len $(posttest_64bit) $(posttest_verbose) | 19 | cmd_posttest = ($(OBJDUMP) -v | $(AWK) -f $(chkobjdump)) || $(OBJDUMP) -d -j .text $(objtree)/vmlinux | $(AWK) -f $(distill_awk) | $(obj)/test_get_len $(posttest_64bit) $(posttest_verbose) |
20 | 20 | ||
21 | posttest: $(obj)/test_get_len vmlinux | 21 | quiet_cmd_sanitytest = TEST $@ |
22 | cmd_sanitytest = $(obj)/insn_sanity $(posttest_64bit) -m 1000000 | ||
23 | |||
24 | posttest: $(obj)/test_get_len vmlinux $(obj)/insn_sanity | ||
22 | $(call cmd,posttest) | 25 | $(call cmd,posttest) |
26 | $(call cmd,sanitytest) | ||
23 | 27 | ||
24 | hostprogs-y := test_get_len | 28 | hostprogs-y += test_get_len insn_sanity |
25 | 29 | ||
26 | # -I needed for generated C source and C source which in the kernel tree. | 30 | # -I needed for generated C source and C source which in the kernel tree. |
27 | HOSTCFLAGS_test_get_len.o := -Wall -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x86/include/ -I$(srctree)/arch/x86/lib/ -I$(srctree)/include/ | 31 | HOSTCFLAGS_test_get_len.o := -Wall -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x86/include/ -I$(srctree)/arch/x86/lib/ -I$(srctree)/include/ |
28 | 32 | ||
33 | HOSTCFLAGS_insn_sanity.o := -Wall -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x86/include/ -I$(srctree)/arch/x86/lib/ -I$(srctree)/include/ | ||
34 | |||
29 | # Dependencies are also needed. | 35 | # Dependencies are also needed. |
30 | $(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 |
31 | 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 | ||
diff --git a/arch/x86/tools/gen-insn-attr-x86.awk b/arch/x86/tools/gen-insn-attr-x86.awk index eaf11f52fc0b..5f6a5b6c3a15 100644 --- a/arch/x86/tools/gen-insn-attr-x86.awk +++ b/arch/x86/tools/gen-insn-attr-x86.awk | |||
@@ -47,7 +47,7 @@ BEGIN { | |||
47 | sep_expr = "^\\|$" | 47 | sep_expr = "^\\|$" |
48 | group_expr = "^Grp[0-9A-Za-z]+" | 48 | group_expr = "^Grp[0-9A-Za-z]+" |
49 | 49 | ||
50 | imm_expr = "^[IJAO][a-z]" | 50 | imm_expr = "^[IJAOL][a-z]" |
51 | imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" | 51 | imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" |
52 | imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" | 52 | imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" |
53 | imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)" | 53 | imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)" |
@@ -59,6 +59,7 @@ BEGIN { | |||
59 | imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)" | 59 | imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)" |
60 | imm_flag["Ob"] = "INAT_MOFFSET" | 60 | imm_flag["Ob"] = "INAT_MOFFSET" |
61 | imm_flag["Ov"] = "INAT_MOFFSET" | 61 | imm_flag["Ov"] = "INAT_MOFFSET" |
62 | imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" | ||
62 | 63 | ||
63 | modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])" | 64 | modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])" |
64 | force64_expr = "\\([df]64\\)" | 65 | force64_expr = "\\([df]64\\)" |
@@ -70,8 +71,12 @@ BEGIN { | |||
70 | lprefix3_expr = "\\(F2\\)" | 71 | lprefix3_expr = "\\(F2\\)" |
71 | max_lprefix = 4 | 72 | max_lprefix = 4 |
72 | 73 | ||
73 | vexok_expr = "\\(VEX\\)" | 74 | # All opcodes starting with lower-case 'v' or with (v1) superscript |
74 | vexonly_expr = "\\(oVEX\\)" | 75 | # accepts VEX prefix |
76 | vexok_opcode_expr = "^v.*" | ||
77 | vexok_expr = "\\(v1\\)" | ||
78 | # All opcodes with (v) superscript supports *only* VEX prefix | ||
79 | vexonly_expr = "\\(v\\)" | ||
75 | 80 | ||
76 | prefix_expr = "\\(Prefix\\)" | 81 | prefix_expr = "\\(Prefix\\)" |
77 | prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" | 82 | prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" |
@@ -85,8 +90,8 @@ BEGIN { | |||
85 | prefix_num["SEG=GS"] = "INAT_PFX_GS" | 90 | prefix_num["SEG=GS"] = "INAT_PFX_GS" |
86 | prefix_num["SEG=SS"] = "INAT_PFX_SS" | 91 | prefix_num["SEG=SS"] = "INAT_PFX_SS" |
87 | prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" | 92 | prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" |
88 | prefix_num["2bytes-VEX"] = "INAT_PFX_VEX2" | 93 | prefix_num["VEX+1byte"] = "INAT_PFX_VEX2" |
89 | prefix_num["3bytes-VEX"] = "INAT_PFX_VEX3" | 94 | prefix_num["VEX+2byte"] = "INAT_PFX_VEX3" |
90 | 95 | ||
91 | clear_vars() | 96 | clear_vars() |
92 | } | 97 | } |
@@ -310,12 +315,10 @@ function convert_operands(count,opnd, i,j,imm,mod) | |||
310 | if (match(opcode, fpu_expr)) | 315 | if (match(opcode, fpu_expr)) |
311 | flags = add_flags(flags, "INAT_MODRM") | 316 | flags = add_flags(flags, "INAT_MODRM") |
312 | 317 | ||
313 | # check VEX only code | 318 | # check VEX codes |
314 | if (match(ext, vexonly_expr)) | 319 | if (match(ext, vexonly_expr)) |
315 | flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") | 320 | flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") |
316 | 321 | else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr)) | |
317 | # check VEX only code | ||
318 | if (match(ext, vexok_expr)) | ||
319 | flags = add_flags(flags, "INAT_VEXOK") | 322 | flags = add_flags(flags, "INAT_VEXOK") |
320 | 323 | ||
321 | # check prefixes | 324 | # check prefixes |
diff --git a/arch/x86/tools/insn_sanity.c b/arch/x86/tools/insn_sanity.c new file mode 100644 index 000000000000..cc2f8c131286 --- /dev/null +++ b/arch/x86/tools/insn_sanity.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | * x86 decoder sanity test - based on test_get_insn.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | * | ||
18 | * Copyright (C) IBM Corporation, 2009 | ||
19 | * Copyright (C) Hitachi, Ltd., 2011 | ||
20 | */ | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include <stdio.h> | ||
24 | #include <string.h> | ||
25 | #include <assert.h> | ||
26 | #include <unistd.h> | ||
27 | #include <sys/types.h> | ||
28 | #include <sys/stat.h> | ||
29 | #include <fcntl.h> | ||
30 | |||
31 | #define unlikely(cond) (cond) | ||
32 | #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) | ||
33 | |||
34 | #include <asm/insn.h> | ||
35 | #include <inat.c> | ||
36 | #include <insn.c> | ||
37 | |||
38 | /* | ||
39 | * Test of instruction analysis against tampering. | ||
40 | * Feed random binary to instruction decoder and ensure not to | ||
41 | * access out-of-instruction-buffer. | ||
42 | */ | ||
43 | |||
44 | #define DEFAULT_MAX_ITER 10000 | ||
45 | #define INSN_NOP 0x90 | ||
46 | |||
47 | static const char *prog; /* Program name */ | ||
48 | static int verbose; /* Verbosity */ | ||
49 | static int x86_64; /* x86-64 bit mode flag */ | ||
50 | static unsigned int seed; /* Random seed */ | ||
51 | static unsigned long iter_start; /* Start of iteration number */ | ||
52 | static unsigned long iter_end = DEFAULT_MAX_ITER; /* End of iteration number */ | ||
53 | static FILE *input_file; /* Input file name */ | ||
54 | |||
55 | static void usage(const char *err) | ||
56 | { | ||
57 | if (err) | ||
58 | fprintf(stderr, "Error: %s\n\n", err); | ||
59 | fprintf(stderr, "Usage: %s [-y|-n|-v] [-s seed[,no]] [-m max] [-i input]\n", prog); | ||
60 | fprintf(stderr, "\t-y 64bit mode\n"); | ||
61 | fprintf(stderr, "\t-n 32bit mode\n"); | ||
62 | fprintf(stderr, "\t-v Verbosity(-vv dumps any decoded result)\n"); | ||
63 | fprintf(stderr, "\t-s Give a random seed (and iteration number)\n"); | ||
64 | fprintf(stderr, "\t-m Give a maximum iteration number\n"); | ||
65 | fprintf(stderr, "\t-i Give an input file with decoded binary\n"); | ||
66 | exit(1); | ||
67 | } | ||
68 | |||
69 | static void dump_field(FILE *fp, const char *name, const char *indent, | ||
70 | struct insn_field *field) | ||
71 | { | ||
72 | fprintf(fp, "%s.%s = {\n", indent, name); | ||
73 | fprintf(fp, "%s\t.value = %d, bytes[] = {%x, %x, %x, %x},\n", | ||
74 | indent, field->value, field->bytes[0], field->bytes[1], | ||
75 | field->bytes[2], field->bytes[3]); | ||
76 | fprintf(fp, "%s\t.got = %d, .nbytes = %d},\n", indent, | ||
77 | field->got, field->nbytes); | ||
78 | } | ||
79 | |||
80 | static void dump_insn(FILE *fp, struct insn *insn) | ||
81 | { | ||
82 | fprintf(fp, "Instruction = {\n"); | ||
83 | dump_field(fp, "prefixes", "\t", &insn->prefixes); | ||
84 | dump_field(fp, "rex_prefix", "\t", &insn->rex_prefix); | ||
85 | dump_field(fp, "vex_prefix", "\t", &insn->vex_prefix); | ||
86 | dump_field(fp, "opcode", "\t", &insn->opcode); | ||
87 | dump_field(fp, "modrm", "\t", &insn->modrm); | ||
88 | dump_field(fp, "sib", "\t", &insn->sib); | ||
89 | dump_field(fp, "displacement", "\t", &insn->displacement); | ||
90 | dump_field(fp, "immediate1", "\t", &insn->immediate1); | ||
91 | dump_field(fp, "immediate2", "\t", &insn->immediate2); | ||
92 | fprintf(fp, "\t.attr = %x, .opnd_bytes = %d, .addr_bytes = %d,\n", | ||
93 | insn->attr, insn->opnd_bytes, insn->addr_bytes); | ||
94 | fprintf(fp, "\t.length = %d, .x86_64 = %d, .kaddr = %p}\n", | ||
95 | insn->length, insn->x86_64, insn->kaddr); | ||
96 | } | ||
97 | |||
98 | static void dump_stream(FILE *fp, const char *msg, unsigned long nr_iter, | ||
99 | unsigned char *insn_buf, struct insn *insn) | ||
100 | { | ||
101 | int i; | ||
102 | |||
103 | fprintf(fp, "%s:\n", msg); | ||
104 | |||
105 | dump_insn(fp, insn); | ||
106 | |||
107 | fprintf(fp, "You can reproduce this with below command(s);\n"); | ||
108 | |||
109 | /* Input a decoded instruction sequence directly */ | ||
110 | fprintf(fp, " $ echo "); | ||
111 | for (i = 0; i < MAX_INSN_SIZE; i++) | ||
112 | fprintf(fp, " %02x", insn_buf[i]); | ||
113 | fprintf(fp, " | %s -i -\n", prog); | ||
114 | |||
115 | if (!input_file) { | ||
116 | fprintf(fp, "Or \n"); | ||
117 | /* Give a seed and iteration number */ | ||
118 | fprintf(fp, " $ %s -s 0x%x,%lu\n", prog, seed, nr_iter); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | static void init_random_seed(void) | ||
123 | { | ||
124 | int fd; | ||
125 | |||
126 | fd = open("/dev/urandom", O_RDONLY); | ||
127 | if (fd < 0) | ||
128 | goto fail; | ||
129 | |||
130 | if (read(fd, &seed, sizeof(seed)) != sizeof(seed)) | ||
131 | goto fail; | ||
132 | |||
133 | close(fd); | ||
134 | return; | ||
135 | fail: | ||
136 | usage("Failed to open /dev/urandom"); | ||
137 | } | ||
138 | |||
139 | /* Read given instruction sequence from the input file */ | ||
140 | static int read_next_insn(unsigned char *insn_buf) | ||
141 | { | ||
142 | char buf[256] = "", *tmp; | ||
143 | int i; | ||
144 | |||
145 | tmp = fgets(buf, ARRAY_SIZE(buf), input_file); | ||
146 | if (tmp == NULL || feof(input_file)) | ||
147 | return 0; | ||
148 | |||
149 | for (i = 0; i < MAX_INSN_SIZE; i++) { | ||
150 | insn_buf[i] = (unsigned char)strtoul(tmp, &tmp, 16); | ||
151 | if (*tmp != ' ') | ||
152 | break; | ||
153 | } | ||
154 | |||
155 | return i; | ||
156 | } | ||
157 | |||
158 | static int generate_insn(unsigned char *insn_buf) | ||
159 | { | ||
160 | int i; | ||
161 | |||
162 | if (input_file) | ||
163 | return read_next_insn(insn_buf); | ||
164 | |||
165 | /* Fills buffer with random binary up to MAX_INSN_SIZE */ | ||
166 | for (i = 0; i < MAX_INSN_SIZE - 1; i += 2) | ||
167 | *(unsigned short *)(&insn_buf[i]) = random() & 0xffff; | ||
168 | |||
169 | while (i < MAX_INSN_SIZE) | ||
170 | insn_buf[i++] = random() & 0xff; | ||
171 | |||
172 | return i; | ||
173 | } | ||
174 | |||
175 | static void parse_args(int argc, char **argv) | ||
176 | { | ||
177 | int c; | ||
178 | char *tmp = NULL; | ||
179 | int set_seed = 0; | ||
180 | |||
181 | prog = argv[0]; | ||
182 | while ((c = getopt(argc, argv, "ynvs:m:i:")) != -1) { | ||
183 | switch (c) { | ||
184 | case 'y': | ||
185 | x86_64 = 1; | ||
186 | break; | ||
187 | case 'n': | ||
188 | x86_64 = 0; | ||
189 | break; | ||
190 | case 'v': | ||
191 | verbose++; | ||
192 | break; | ||
193 | case 'i': | ||
194 | if (strcmp("-", optarg) == 0) | ||
195 | input_file = stdin; | ||
196 | else | ||
197 | input_file = fopen(optarg, "r"); | ||
198 | if (!input_file) | ||
199 | usage("Failed to open input file"); | ||
200 | break; | ||
201 | case 's': | ||
202 | seed = (unsigned int)strtoul(optarg, &tmp, 0); | ||
203 | if (*tmp == ',') { | ||
204 | optarg = tmp + 1; | ||
205 | iter_start = strtoul(optarg, &tmp, 0); | ||
206 | } | ||
207 | if (*tmp != '\0' || tmp == optarg) | ||
208 | usage("Failed to parse seed"); | ||
209 | set_seed = 1; | ||
210 | break; | ||
211 | case 'm': | ||
212 | iter_end = strtoul(optarg, &tmp, 0); | ||
213 | if (*tmp != '\0' || tmp == optarg) | ||
214 | usage("Failed to parse max_iter"); | ||
215 | break; | ||
216 | default: | ||
217 | usage(NULL); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | /* Check errors */ | ||
222 | if (iter_end < iter_start) | ||
223 | usage("Max iteration number must be bigger than iter-num"); | ||
224 | |||
225 | if (set_seed && input_file) | ||
226 | usage("Don't use input file (-i) with random seed (-s)"); | ||
227 | |||
228 | /* Initialize random seed */ | ||
229 | if (!input_file) { | ||
230 | if (!set_seed) /* No seed is given */ | ||
231 | init_random_seed(); | ||
232 | srand(seed); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | int main(int argc, char **argv) | ||
237 | { | ||
238 | struct insn insn; | ||
239 | int insns = 0; | ||
240 | int errors = 0; | ||
241 | unsigned long i; | ||
242 | unsigned char insn_buf[MAX_INSN_SIZE * 2]; | ||
243 | |||
244 | parse_args(argc, argv); | ||
245 | |||
246 | /* Prepare stop bytes with NOPs */ | ||
247 | memset(insn_buf + MAX_INSN_SIZE, INSN_NOP, MAX_INSN_SIZE); | ||
248 | |||
249 | for (i = 0; i < iter_end; i++) { | ||
250 | if (generate_insn(insn_buf) <= 0) | ||
251 | break; | ||
252 | |||
253 | if (i < iter_start) /* Skip to given iteration number */ | ||
254 | continue; | ||
255 | |||
256 | /* Decode an instruction */ | ||
257 | insn_init(&insn, insn_buf, x86_64); | ||
258 | insn_get_length(&insn); | ||
259 | |||
260 | if (insn.next_byte <= insn.kaddr || | ||
261 | insn.kaddr + MAX_INSN_SIZE < insn.next_byte) { | ||
262 | /* Access out-of-range memory */ | ||
263 | dump_stream(stderr, "Error: Found an access violation", i, insn_buf, &insn); | ||
264 | errors++; | ||
265 | } else if (verbose && !insn_complete(&insn)) | ||
266 | dump_stream(stdout, "Info: Found an undecodable input", i, insn_buf, &insn); | ||
267 | else if (verbose >= 2) | ||
268 | dump_insn(stdout, &insn); | ||
269 | insns++; | ||
270 | } | ||
271 | |||
272 | fprintf(stdout, "%s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n", (errors) ? "Failure" : "Success", insns, (input_file) ? "given" : "random", errors, seed); | ||
273 | |||
274 | return errors ? 1 : 0; | ||
275 | } | ||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 1f928659c338..12eb07bfb267 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1215,8 +1215,6 @@ asmlinkage void __init xen_start_kernel(void) | |||
1215 | local_irq_disable(); | 1215 | local_irq_disable(); |
1216 | early_boot_irqs_disabled = true; | 1216 | early_boot_irqs_disabled = true; |
1217 | 1217 | ||
1218 | memblock_init(); | ||
1219 | |||
1220 | xen_raw_console_write("mapping kernel into physical memory\n"); | 1218 | xen_raw_console_write("mapping kernel into physical memory\n"); |
1221 | pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages); | 1219 | pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages); |
1222 | xen_ident_map_ISA(); | 1220 | xen_ident_map_ISA(); |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 87f6673b1207..f4bf8aa574f4 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -1774,10 +1774,8 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, | |||
1774 | __xen_write_cr3(true, __pa(pgd)); | 1774 | __xen_write_cr3(true, __pa(pgd)); |
1775 | xen_mc_issue(PARAVIRT_LAZY_CPU); | 1775 | xen_mc_issue(PARAVIRT_LAZY_CPU); |
1776 | 1776 | ||
1777 | memblock_x86_reserve_range(__pa(xen_start_info->pt_base), | 1777 | memblock_reserve(__pa(xen_start_info->pt_base), |
1778 | __pa(xen_start_info->pt_base + | 1778 | xen_start_info->nr_pt_frames * PAGE_SIZE); |
1779 | xen_start_info->nr_pt_frames * PAGE_SIZE), | ||
1780 | "XEN PAGETABLES"); | ||
1781 | 1779 | ||
1782 | return pgd; | 1780 | return pgd; |
1783 | } | 1781 | } |
@@ -1853,10 +1851,8 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, | |||
1853 | PFN_DOWN(__pa(initial_page_table))); | 1851 | PFN_DOWN(__pa(initial_page_table))); |
1854 | xen_write_cr3(__pa(initial_page_table)); | 1852 | xen_write_cr3(__pa(initial_page_table)); |
1855 | 1853 | ||
1856 | memblock_x86_reserve_range(__pa(xen_start_info->pt_base), | 1854 | memblock_reserve(__pa(xen_start_info->pt_base), |
1857 | __pa(xen_start_info->pt_base + | 1855 | xen_start_info->nr_pt_frames * PAGE_SIZE)); |
1858 | xen_start_info->nr_pt_frames * PAGE_SIZE), | ||
1859 | "XEN PAGETABLES"); | ||
1860 | 1856 | ||
1861 | return initial_page_table; | 1857 | return initial_page_table; |
1862 | } | 1858 | } |
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 1093f80c162d..e03c63692176 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c | |||
@@ -75,7 +75,7 @@ static void __init xen_add_extra_mem(u64 start, u64 size) | |||
75 | if (i == XEN_EXTRA_MEM_MAX_REGIONS) | 75 | if (i == XEN_EXTRA_MEM_MAX_REGIONS) |
76 | printk(KERN_WARNING "Warning: not enough extra memory regions\n"); | 76 | printk(KERN_WARNING "Warning: not enough extra memory regions\n"); |
77 | 77 | ||
78 | memblock_x86_reserve_range(start, start + size, "XEN EXTRA"); | 78 | memblock_reserve(start, size); |
79 | 79 | ||
80 | xen_max_p2m_pfn = PFN_DOWN(start + size); | 80 | xen_max_p2m_pfn = PFN_DOWN(start + size); |
81 | 81 | ||
@@ -173,9 +173,21 @@ static unsigned long __init xen_get_max_pages(void) | |||
173 | domid_t domid = DOMID_SELF; | 173 | domid_t domid = DOMID_SELF; |
174 | int ret; | 174 | int ret; |
175 | 175 | ||
176 | ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid); | 176 | /* |
177 | if (ret > 0) | 177 | * For the initial domain we use the maximum reservation as |
178 | max_pages = ret; | 178 | * the maximum page. |
179 | * | ||
180 | * For guest domains the current maximum reservation reflects | ||
181 | * the current maximum rather than the static maximum. In this | ||
182 | * case the e820 map provided to us will cover the static | ||
183 | * maximum region. | ||
184 | */ | ||
185 | if (xen_initial_domain()) { | ||
186 | ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid); | ||
187 | if (ret > 0) | ||
188 | max_pages = ret; | ||
189 | } | ||
190 | |||
179 | return min(max_pages, MAX_DOMAIN_PAGES); | 191 | return min(max_pages, MAX_DOMAIN_PAGES); |
180 | } | 192 | } |
181 | 193 | ||
@@ -299,9 +311,8 @@ char * __init xen_memory_setup(void) | |||
299 | * - xen_start_info | 311 | * - xen_start_info |
300 | * See comment above "struct start_info" in <xen/interface/xen.h> | 312 | * See comment above "struct start_info" in <xen/interface/xen.h> |
301 | */ | 313 | */ |
302 | memblock_x86_reserve_range(__pa(xen_start_info->mfn_list), | 314 | memblock_reserve(__pa(xen_start_info->mfn_list), |
303 | __pa(xen_start_info->pt_base), | 315 | xen_start_info->pt_base - xen_start_info->mfn_list); |
304 | "XEN START INFO"); | ||
305 | 316 | ||
306 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | 317 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); |
307 | 318 | ||