diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Kconfig.debug | 5 | ||||
-rw-r--r-- | arch/x86/crypto/aesni-intel_glue.c | 16 | ||||
-rw-r--r-- | arch/x86/entry/syscalls/syscall_32.tbl | 1 | ||||
-rw-r--r-- | arch/x86/entry/syscalls/syscall_64.tbl | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/cpu_device_id.h | 5 | ||||
-rw-r--r-- | arch/x86/kernel/apic/vector.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/match.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/topology.c | 53 | ||||
-rw-r--r-- | arch/x86/um/asm/ptrace.h | 6 | ||||
-rw-r--r-- | arch/x86/um/bugs_32.c | 1 | ||||
-rw-r--r-- | arch/x86/um/bugs_64.c | 1 | ||||
-rw-r--r-- | arch/x86/um/elfcore.c | 1 | ||||
-rw-r--r-- | arch/x86/um/fault.c | 1 | ||||
-rw-r--r-- | arch/x86/um/os-Linux/mcontext.c | 1 | ||||
-rw-r--r-- | arch/x86/um/os-Linux/registers.c | 2 | ||||
-rw-r--r-- | arch/x86/um/os-Linux/tls.c | 1 | ||||
-rw-r--r-- | arch/x86/um/ptrace_32.c | 2 | ||||
-rw-r--r-- | arch/x86/um/shared/sysdep/archsetjmp.h | 7 | ||||
-rw-r--r-- | arch/x86/um/shared/sysdep/kernel-offsets.h | 3 | ||||
-rw-r--r-- | arch/x86/um/signal.c | 14 | ||||
-rw-r--r-- | arch/x86/um/tls_32.c | 19 | ||||
-rw-r--r-- | arch/x86/um/user-offsets.c | 3 | ||||
-rw-r--r-- | arch/x86/um/vdso/um_vdso.c | 10 | ||||
-rw-r--r-- | arch/x86/xen/enlighten.c | 33 | ||||
-rw-r--r-- | arch/x86/xen/p2m.c | 11 |
25 files changed, 153 insertions, 57 deletions
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index c5d614d28a75..74777a97e394 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -248,6 +248,7 @@ config UNWINDER_ORC config UNWINDER_FRAME_POINTER bool "Frame pointer unwinder" + select ARCH_WANT_FRAME_POINTERS select FRAME_POINTER help This option enables the frame pointer unwinder for unwinding kernel @@ -271,7 +272,3 @@ config UNWINDER_GUESS overhead. endchoice - -config FRAME_POINTER - depends on !UNWINDER_ORC && !UNWINDER_GUESS - bool diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 5b25d2a58aeb..ef031655b2d3 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -1223,14 +1223,14 @@ DEFINE_XTS_ALG(vaes_avx10_512, "xts-aes-vaes-avx10_512", 800); * implementation with ymm registers (256-bit vectors) will be used instead. */ static const struct x86_cpu_id zmm_exclusion_list[] = { - { .vendor = X86_VENDOR_INTEL, .family = 6, .model = INTEL_FAM6_SKYLAKE_X }, - { .vendor = X86_VENDOR_INTEL, .family = 6, .model = INTEL_FAM6_ICELAKE_X }, - { .vendor = X86_VENDOR_INTEL, .family = 6, .model = INTEL_FAM6_ICELAKE_D }, - { .vendor = X86_VENDOR_INTEL, .family = 6, .model = INTEL_FAM6_ICELAKE }, - { .vendor = X86_VENDOR_INTEL, .family = 6, .model = INTEL_FAM6_ICELAKE_L }, - { .vendor = X86_VENDOR_INTEL, .family = 6, .model = INTEL_FAM6_ICELAKE_NNPI }, - { .vendor = X86_VENDOR_INTEL, .family = 6, .model = INTEL_FAM6_TIGERLAKE_L }, - { .vendor = X86_VENDOR_INTEL, .family = 6, .model = INTEL_FAM6_TIGERLAKE }, + X86_MATCH_VFM(INTEL_SKYLAKE_X, 0), + X86_MATCH_VFM(INTEL_ICELAKE_X, 0), + X86_MATCH_VFM(INTEL_ICELAKE_D, 0), + X86_MATCH_VFM(INTEL_ICELAKE, 0), + X86_MATCH_VFM(INTEL_ICELAKE_L, 0), + X86_MATCH_VFM(INTEL_ICELAKE_NNPI, 0), + X86_MATCH_VFM(INTEL_TIGERLAKE_L, 0), + X86_MATCH_VFM(INTEL_TIGERLAKE, 0), /* Allow Rocket Lake and later, and Sapphire Rapids and later. */ /* Also allow AMD CPUs (starting with Zen 4, the first with AVX-512). */ {}, diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index 5f8591ce7f25..7fd1f57ad3d3 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -466,3 +466,4 @@ 459 i386 lsm_get_self_attr sys_lsm_get_self_attr 460 i386 lsm_set_self_attr sys_lsm_set_self_attr 461 i386 lsm_list_modules sys_lsm_list_modules +462 i386 mseal sys_mseal diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index cc78226ffc35..a396f6e6ab5b 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -383,6 +383,7 @@ 459 common lsm_get_self_attr sys_lsm_get_self_attr 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules +462 common mseal sys_mseal # # Due to a historical design error, certain syscalls are numbered differently diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h index 970a232009c3..b6325ee30871 100644 --- a/arch/x86/include/asm/cpu_device_id.h +++ b/arch/x86/include/asm/cpu_device_id.h @@ -53,6 +53,9 @@ #define X86_CENTAUR_FAM6_C7_D 0xd #define X86_CENTAUR_FAM6_NANO 0xf +/* x86_cpu_id::flags */ +#define X86_CPU_ID_FLAG_ENTRY_VALID BIT(0) + #define X86_STEPPINGS(mins, maxs) GENMASK(maxs, mins) /** * X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE - Base macro for CPU matching @@ -79,6 +82,7 @@ .model = _model, \ .steppings = _steppings, \ .feature = _feature, \ + .flags = X86_CPU_ID_FLAG_ENTRY_VALID, \ .driver_data = (unsigned long) _data \ } @@ -89,6 +93,7 @@ .model = _model, \ .steppings = _steppings, \ .feature = _feature, \ + .flags = X86_CPU_ID_FLAG_ENTRY_VALID, \ .driver_data = (unsigned long) _data \ } diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 9eec52925fa3..557318145038 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -1035,7 +1035,8 @@ static void __vector_schedule_cleanup(struct apic_chip_data *apicd) add_timer_on(&cl->timer, cpu); } } else { - apicd->prev_vector = 0; + pr_warn("IRQ %u schedule cleanup for offline CPU %u\n", apicd->irq, cpu); + free_moved_vector(apicd); } raw_spin_unlock(&vector_lock); } @@ -1072,6 +1073,7 @@ void irq_complete_move(struct irq_cfg *cfg) */ void irq_force_complete_move(struct irq_desc *desc) { + unsigned int cpu = smp_processor_id(); struct apic_chip_data *apicd; struct irq_data *irqd; unsigned int vector; @@ -1096,10 +1098,11 @@ void irq_force_complete_move(struct irq_desc *desc) goto unlock; /* - * If prev_vector is empty, no action required. + * If prev_vector is empty or the descriptor is neither currently + * nor previously on the outgoing CPU no action required. */ vector = apicd->prev_vector; - if (!vector) + if (!vector || (apicd->cpu != cpu && apicd->prev_cpu != cpu)) goto unlock; /* diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c index 8651643bddae..8e7de733320a 100644 --- a/arch/x86/kernel/cpu/match.c +++ b/arch/x86/kernel/cpu/match.c @@ -38,9 +38,7 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) const struct x86_cpu_id *m; struct cpuinfo_x86 *c = &boot_cpu_data; - for (m = match; - m->vendor | m->family | m->model | m->steppings | m->feature; - m++) { + for (m = match; m->flags & X86_CPU_ID_FLAG_ENTRY_VALID; m++) { if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor) continue; if (m->family != X86_FAMILY_ANY && c->x86 != m->family) diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index d17c9b71eb4a..621a151ccf7d 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -128,6 +128,9 @@ static void topo_set_cpuids(unsigned int cpu, u32 apic_id, u32 acpi_id) static __init bool check_for_real_bsp(u32 apic_id) { + bool is_bsp = false, has_apic_base = boot_cpu_data.x86 >= 6; + u64 msr; + /* * There is no real good way to detect whether this a kdump() * kernel, but except on the Voyager SMP monstrosity which is not @@ -144,17 +147,61 @@ static __init bool check_for_real_bsp(u32 apic_id) if (topo_info.real_bsp_apic_id != BAD_APICID) return false; + /* + * Check whether the enumeration order is broken by evaluating the + * BSP bit in the APICBASE MSR. If the CPU does not have the + * APICBASE MSR then the BSP detection is not possible and the + * kernel must rely on the firmware enumeration order. + */ + if (has_apic_base) { + rdmsrl(MSR_IA32_APICBASE, msr); + is_bsp = !!(msr & MSR_IA32_APICBASE_BSP); + } + if (apic_id == topo_info.boot_cpu_apic_id) { - topo_info.real_bsp_apic_id = apic_id; - return false; + /* + * If the boot CPU has the APIC BSP bit set then the + * firmware enumeration is agreeing. If the CPU does not + * have the APICBASE MSR then the only choice is to trust + * the enumeration order. + */ + if (is_bsp || !has_apic_base) { + topo_info.real_bsp_apic_id = apic_id; + return false; + } + /* + * If the boot APIC is enumerated first, but the APICBASE + * MSR does not have the BSP bit set, then there is no way + * to discover the real BSP here. Assume a crash kernel and + * limit the number of CPUs to 1 as an INIT to the real BSP + * would reset the machine. + */ + pr_warn("Enumerated BSP APIC %x is not marked in APICBASE MSR\n", apic_id); + pr_warn("Assuming crash kernel. Limiting to one CPU to prevent machine INIT\n"); + set_nr_cpu_ids(1); + goto fwbug; } - pr_warn("Boot CPU APIC ID not the first enumerated APIC ID: %x > %x\n", + pr_warn("Boot CPU APIC ID not the first enumerated APIC ID: %x != %x\n", topo_info.boot_cpu_apic_id, apic_id); + + if (is_bsp) { + /* + * The boot CPU has the APIC BSP bit set. Use it and complain + * about the broken firmware enumeration. + */ + topo_info.real_bsp_apic_id = topo_info.boot_cpu_apic_id; + goto fwbug; + } + pr_warn("Crash kernel detected. Disabling real BSP to prevent machine INIT\n"); topo_info.real_bsp_apic_id = apic_id; return true; + +fwbug: + pr_warn(FW_BUG "APIC enumeration order not specification compliant\n"); + return false; } static unsigned int topo_unit_count(u32 lvlid, enum x86_topology_domains at_level, diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h index 83822fd42204..2fef3da55533 100644 --- a/arch/x86/um/asm/ptrace.h +++ b/arch/x86/um/asm/ptrace.h @@ -54,6 +54,8 @@ extern int ptrace_get_thread_area(struct task_struct *child, int idx, extern int ptrace_set_thread_area(struct task_struct *child, int idx, struct user_desc __user *user_desc); +extern int arch_switch_tls(struct task_struct *to); + #else #define PT_REGS_R8(r) UPT_R8(&(r)->regs) @@ -83,5 +85,9 @@ extern long arch_prctl(struct task_struct *task, int option, unsigned long __user *addr); #endif + #define user_stack_pointer(regs) PT_REGS_SP(regs) + +extern void arch_switch_to(struct task_struct *to); + #endif /* __UM_X86_PTRACE_H */ diff --git a/arch/x86/um/bugs_32.c b/arch/x86/um/bugs_32.c index 33daff4dade4..d29929efcc07 100644 --- a/arch/x86/um/bugs_32.c +++ b/arch/x86/um/bugs_32.c @@ -3,6 +3,7 @@ * Licensed under the GPL */ +#include <arch.h> #include <signal.h> #include <kern_util.h> #include <longjmp.h> diff --git a/arch/x86/um/bugs_64.c b/arch/x86/um/bugs_64.c index 8cc8256c698d..b01295e8a676 100644 --- a/arch/x86/um/bugs_64.c +++ b/arch/x86/um/bugs_64.c @@ -4,6 +4,7 @@ * Licensed under the GPL */ +#include <arch.h> #include <sysdep/ptrace.h> void arch_check_bugs(void) diff --git a/arch/x86/um/elfcore.c b/arch/x86/um/elfcore.c index 650cdbbdaf45..ef50662fc40d 100644 --- a/arch/x86/um/elfcore.c +++ b/arch/x86/um/elfcore.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include <linux/elf.h> +#include <linux/elfcore.h> #include <linux/coredump.h> #include <linux/fs.h> #include <linux/mm.h> diff --git a/arch/x86/um/fault.c b/arch/x86/um/fault.c index 84ac7f7b0257..0dde4d613a87 100644 --- a/arch/x86/um/fault.c +++ b/arch/x86/um/fault.c @@ -3,6 +3,7 @@ * Licensed under the GPL */ +#include <arch.h> #include <sysdep/ptrace.h> /* These two are from asm-um/uaccess.h and linux/module.h, check them. */ diff --git a/arch/x86/um/os-Linux/mcontext.c b/arch/x86/um/os-Linux/mcontext.c index 49c3744cac37..e80ab7d28117 100644 --- a/arch/x86/um/os-Linux/mcontext.c +++ b/arch/x86/um/os-Linux/mcontext.c @@ -3,6 +3,7 @@ #define __FRAME_OFFSETS #include <asm/ptrace.h> #include <sysdep/ptrace.h> +#include <sysdep/mcontext.h> void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc) { diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c index df8f4b4bf98b..f3638dd09cec 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c @@ -17,7 +17,7 @@ #include <linux/elf.h> #include <registers.h> -int have_xstate_support; +static int have_xstate_support; int save_i387_registers(int pid, unsigned long *fp_regs) { diff --git a/arch/x86/um/os-Linux/tls.c b/arch/x86/um/os-Linux/tls.c index 3e1b1bf6acbc..eed9efe29ade 100644 --- a/arch/x86/um/os-Linux/tls.c +++ b/arch/x86/um/os-Linux/tls.c @@ -6,6 +6,7 @@ #include <sys/syscall.h> #include <unistd.h> +#include <os.h> #include <sysdep/tls.h> #ifndef PTRACE_GET_THREAD_AREA diff --git a/arch/x86/um/ptrace_32.c b/arch/x86/um/ptrace_32.c index 7f1abde2c84b..b0a71c6cdc6e 100644 --- a/arch/x86/um/ptrace_32.c +++ b/arch/x86/um/ptrace_32.c @@ -10,8 +10,6 @@ #include <registers.h> #include <skas.h> -extern int arch_switch_tls(struct task_struct *to); - void arch_switch_to(struct task_struct *to) { int err = arch_switch_tls(to); diff --git a/arch/x86/um/shared/sysdep/archsetjmp.h b/arch/x86/um/shared/sysdep/archsetjmp.h index 166cedbab926..8c81d1a604a9 100644 --- a/arch/x86/um/shared/sysdep/archsetjmp.h +++ b/arch/x86/um/shared/sysdep/archsetjmp.h @@ -1,6 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __X86_UM_SYSDEP_ARCHSETJMP_H +#define __X86_UM_SYSDEP_ARCHSETJMP_H + #ifdef __i386__ #include "archsetjmp_32.h" #else #include "archsetjmp_64.h" #endif + +unsigned long get_thread_reg(int reg, jmp_buf *buf); + +#endif /* __X86_UM_SYSDEP_ARCHSETJMP_H */ diff --git a/arch/x86/um/shared/sysdep/kernel-offsets.h b/arch/x86/um/shared/sysdep/kernel-offsets.h index a004bffb7b8d..48de3a71f845 100644 --- a/arch/x86/um/shared/sysdep/kernel-offsets.h +++ b/arch/x86/um/shared/sysdep/kernel-offsets.h @@ -6,6 +6,9 @@ #include <linux/kbuild.h> #include <asm/mman.h> +/* workaround for a warning with -Wmissing-prototypes */ +void foo(void); + void foo(void) { #include <common-offsets.h> diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c index 263e1d08f216..2cc8c2309022 100644 --- a/arch/x86/um/signal.c +++ b/arch/x86/um/signal.c @@ -8,6 +8,7 @@ #include <linux/personality.h> #include <linux/ptrace.h> #include <linux/kernel.h> +#include <linux/syscalls.h> #include <asm/unistd.h> #include <linux/uaccess.h> #include <asm/ucontext.h> @@ -155,7 +156,7 @@ static int copy_sc_from_user(struct pt_regs *regs, struct sigcontext __user *from) { struct sigcontext sc; - int err, pid; + int err; /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; @@ -201,10 +202,10 @@ static int copy_sc_from_user(struct pt_regs *regs, #undef GETREG - pid = userspace_pid[current_thread_info()->cpu]; #ifdef CONFIG_X86_32 if (have_fpx_regs) { struct user_fxsr_struct fpx; + int pid = userspace_pid[current_thread_info()->cpu]; err = copy_from_user(&fpx, &((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0], @@ -240,7 +241,7 @@ static int copy_sc_to_user(struct sigcontext __user *to, { struct sigcontext sc; struct faultinfo * fi = ¤t->thread.arch.faultinfo; - int err, pid; + int err; memset(&sc, 0, sizeof(struct sigcontext)); #define PUTREG(regno, regname) sc.regname = regs->regs.gp[HOST_##regno] @@ -288,10 +289,9 @@ static int copy_sc_to_user(struct sigcontext __user *to, if (err) return 1; - pid = userspace_pid[current_thread_info()->cpu]; - #ifdef CONFIG_X86_32 if (have_fpx_regs) { + int pid = userspace_pid[current_thread_info()->cpu]; struct user_fxsr_struct fpx; err = save_fpx_registers(pid, (unsigned long *) &fpx); @@ -450,7 +450,7 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig, return 0; } -long sys_sigreturn(void) +SYSCALL_DEFINE0(sigreturn) { unsigned long sp = PT_REGS_SP(¤t->thread.regs); struct sigframe __user *frame = (struct sigframe __user *)(sp - 8); @@ -557,7 +557,7 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig, } #endif -long sys_rt_sigreturn(void) +SYSCALL_DEFINE0(rt_sigreturn) { unsigned long sp = PT_REGS_SP(¤t->thread.regs); struct rt_sigframe __user *frame = diff --git a/arch/x86/um/tls_32.c b/arch/x86/um/tls_32.c index 66162eafd8e8..d301deee041f 100644 --- a/arch/x86/um/tls_32.c +++ b/arch/x86/um/tls_32.c @@ -20,7 +20,7 @@ static int host_supports_tls = -1; int host_gdt_entry_tls_min; -int do_set_thread_area(struct user_desc *info) +static int do_set_thread_area(struct user_desc *info) { int ret; u32 cpu; @@ -36,22 +36,6 @@ int do_set_thread_area(struct user_desc *info) return ret; } -int do_get_thread_area(struct user_desc *info) -{ - int ret; - u32 cpu; - - cpu = get_cpu(); - ret = os_get_thread_area(info, userspace_pid[cpu]); - put_cpu(); - - if (ret) - printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, " - "index = %d\n", ret, info->entry_number); - - return ret; -} - /* * sys_get_thread_area: get a yet unused TLS descriptor index. * XXX: Consider leaving one free slot for glibc usage at first place. This must @@ -231,7 +215,6 @@ out: return ret; } -/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */ static int get_tls_entry(struct task_struct *task, struct user_desc *info, int idx) { diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index e54a9814ccf1..1c77d9946199 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -14,6 +14,9 @@ COMMENT(#val " / sizeof(unsigned long)"); \ DEFINE(sym, val / sizeof(unsigned long)) +/* workaround for a warning with -Wmissing-prototypes */ +void foo(void); + void foo(void) { #ifdef __i386__ diff --git a/arch/x86/um/vdso/um_vdso.c b/arch/x86/um/vdso/um_vdso.c index ff0f3b4b6c45..cbae2584124f 100644 --- a/arch/x86/um/vdso/um_vdso.c +++ b/arch/x86/um/vdso/um_vdso.c @@ -13,6 +13,12 @@ #include <linux/getcpu.h> #include <asm/unistd.h> +/* workaround for -Wmissing-prototypes warnings */ +int __vdso_clock_gettime(clockid_t clock, struct __kernel_old_timespec *ts); +int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz); +__kernel_old_time_t __vdso_time(__kernel_old_time_t *t); +long __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused); + int __vdso_clock_gettime(clockid_t clock, struct __kernel_old_timespec *ts) { long ret; @@ -54,7 +60,7 @@ __kernel_old_time_t __vdso_time(__kernel_old_time_t *t) __kernel_old_time_t time(__kernel_old_time_t *t) __attribute__((weak, alias("__vdso_time"))); long -__vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused) +__vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused) { /* * UML does not support SMP, we can cheat here. :) @@ -68,5 +74,5 @@ __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused) return 0; } -long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache) +long getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *tcache) __attribute__((weak, alias("__vdso_getcpu"))); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 5f3a69f6ec34..0305485edcd3 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -379,3 +379,36 @@ void __init xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns) memblock_reserve(PFN_PHYS(start_pfn), PFN_PHYS(n_pfns)); } + +#ifdef CONFIG_XEN_UNPOPULATED_ALLOC +int __init arch_xen_unpopulated_init(struct resource **res) +{ + unsigned int i; + + if (!xen_domain()) + return -ENODEV; + + /* Must be set strictly before calling xen_free_unpopulated_pages(). */ + *res = &iomem_resource; + + /* + * Initialize with pages from the extra memory regions (see + * arch/x86/xen/setup.c). + */ + for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) { + unsigned int j; + + for (j = 0; j < xen_extra_mem[i].n_pfns; j++) { + struct page *pg = + pfn_to_page(xen_extra_mem[i].start_pfn + j); + + xen_free_unpopulated_pages(1, &pg); + } + + /* Zero so region is not also added to the balloon driver. */ + xen_extra_mem[i].n_pfns = 0; + } + + return 0; +} +#endif diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 9bdc3b656b2c..99918beccd80 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -555,7 +555,6 @@ int xen_alloc_p2m_entry(unsigned long pfn) /* Separately check the mid mfn level */ unsigned long missing_mfn; unsigned long mid_mfn_mfn; - unsigned long old_mfn; mid_mfn = alloc_p2m_page(); if (!mid_mfn) @@ -565,12 +564,12 @@ int xen_alloc_p2m_entry(unsigned long pfn) missing_mfn = virt_to_mfn(p2m_mid_missing_mfn); mid_mfn_mfn = virt_to_mfn(mid_mfn); - old_mfn = cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn); - if (old_mfn != missing_mfn) { - free_p2m_page(mid_mfn); - mid_mfn = mfn_to_virt(old_mfn); - } else { + /* try_cmpxchg() updates missing_mfn on failure. */ + if (try_cmpxchg(top_mfn_p, &missing_mfn, mid_mfn_mfn)) { p2m_top_mfn_p[topidx] = mid_mfn; + } else { + free_p2m_page(mid_mfn); + mid_mfn = mfn_to_virt(missing_mfn); } } } else { |