[U-Boot] [PATCH 29/33] x86: Add LAPIC setup code

Bin Meng bmeng.cn at gmail.com
Wed Nov 12 09:14:01 CET 2014


Hi Simon,

On Wed, Nov 12, 2014 at 8:18 AM, Simon Glass <sjg at chromium.org> wrote:
> Add code to set up the Local Advanced Peripheral Interrupt Controller.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
>  arch/x86/cpu/Makefile        |   1 +
>  arch/x86/cpu/lapic.c         |  68 ++++++++++++++++++++++++
>  arch/x86/include/asm/lapic.h | 123 +++++++++++++++++++++++++++++++++++++++++++
>  arch/x86/include/asm/post.h  |   1 +
>  4 files changed, 193 insertions(+)
>  create mode 100644 arch/x86/cpu/lapic.c
>
> diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
> index 1327f08..adfd258 100644
> --- a/arch/x86/cpu/Makefile
> +++ b/arch/x86/cpu/Makefile
> @@ -11,5 +11,6 @@
>  extra-y        = start.o
>  obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
>  obj-y  += interrupts.o cpu.o call64.o
> +obj-y += lapic.o
>  obj-$(CONFIG_PCI) += pci.o
>  obj-y += turbo.o
> diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c
> new file mode 100644
> index 0000000..8191d84
> --- /dev/null
> +++ b/arch/x86/cpu/lapic.c
> @@ -0,0 +1,68 @@
> +/*
> + * From coreboot file of same name
> + *
> + * Copyright (C) 2008-2009 coresystems GmbH
> + * Copyright (C) 2014 Google, Inc
> + *
> + * SPDX-License-Identifier:    GPL-2.0
> + */
> +
> +#include <common.h>
> +#include <asm/msr.h>
> +#include <asm/io.h>
> +#include <asm/lapic.h>
> +#include <asm/post.h>
> +
> +void lapic_setup(void)
> +{
> +#if NEED_LAPIC == 1
> +       /* Only Pentium Pro and later have those MSR stuff */
> +       msr_t msr;
> +
> +       debug("Setting up local apic: ");
> +
> +       /* Enable the local apic */
> +       msr = msr_read(LAPIC_BASE_MSR);
> +       msr.lo |= LAPIC_BASE_MSR_ENABLE;
> +       msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
> +       msr.lo |= LAPIC_DEFAULT_BASE;
> +       msr_write(LAPIC_BASE_MSR, msr);
> +

Please replace above wih enable_lapic() which is already defined in
lapic.h in your last patch series.

> +       /*
> +        * Set Task Priority to 'accept all'.
> +        */
> +       lapic_write_around(LAPIC_TASKPRI,
> +                          lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
> +
> +       /* Put the local apic in virtual wire mode */
> +       lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
> +                               ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
> +       lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
> +                       ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
> +                         LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
> +                         LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
> +                         LAPIC_DELIVERY_MODE_MASK)) |
> +                       (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
> +                        LAPIC_DELIVERY_MODE_EXTINT));
> +       lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
> +                       ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
> +                         LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
> +                         LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
> +                         LAPIC_DELIVERY_MODE_MASK)) |
> +               (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
> +                       LAPIC_DELIVERY_MODE_NMI));
> +
> +       debug("apic_id: 0x%02lx, ", lapicid());
> +#else /* !NEED_LLAPIC */
> +       /* Only Pentium Pro and later have those MSR stuff */
> +       msr_t msr;
> +
> +       debug("Disabling local apic:");
> +
> +       msr = msr_read(LAPIC_BASE_MSR);
> +       msr.lo &= ~LAPIC_BASE_MSR_ENABLE;
> +       msr_write(LAPIC_BASE_MSR, msr);

Please replace above wih disable_lapic() which is already defined in
lapic.h in your last patch series.

> +#endif /* !NEED_LAPIC */
> +       debug("done.\n");
> +       post_code(POST_LAPIC);
> +}
> diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h
> index 948e643..ab00a18 100644
> --- a/arch/x86/include/asm/lapic.h
> +++ b/arch/x86/include/asm/lapic.h
> @@ -14,6 +14,13 @@
>  #include <asm/msr.h>
>  #include <asm/processor.h>
>
> +/* See if I need to initialize the local apic */
> +#if CONFIG_SMP || CONFIG_IOAPIC
> +#  define NEED_LAPIC 1
> +#else
> +#  define NEED_LAPIC 0
> +#endif
> +
>  static inline __attribute__((always_inline))
>                 unsigned long lapic_read(unsigned long reg)
>  {
> @@ -56,4 +63,120 @@ static inline __attribute__((always_inline)) unsigned long lapicid(void)
>         return lapic_read(LAPIC_ID) >> 24;
>  }
>
> +#if !CONFIG_AP_IN_SIPI_WAIT
> +/* If we need to go back to sipi wait, we use the long non-inlined version of
> + * this function in lapic_cpu_init.c
> + */
> +static inline __attribute__((always_inline)) void stop_this_cpu(void)
> +{
> +       /* Called by an AP when it is ready to halt and wait for a new task */
> +       for (;;)
> +               cpu_hlt();
> +}
> +#else
> +void stop_this_cpu(void);
> +#endif
> +
> +#if !defined(__PRE_RAM__)

__PRE_RAM__ is a coreboot stuff. Please clean it up.

> +
> +#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
> +                                                       sizeof(*(ptr))))
> +
> +struct __xchg_dummy { unsigned long a[100]; };
> +#define __xg(x) ((struct __xchg_dummy *)(x))
> +
> +/*
> + * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
> + * Note 2: xchg has side effect, so that attribute volatile is necessary,
> + *       but generally the primitive is invalid, *ptr is output argument. --ANK
> + */
> +static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
> +                                  int size)
> +{
> +       switch (size) {
> +       case 1:
> +               __asm__ __volatile__("xchgb %b0,%1"
> +                       : "=q" (x)
> +                       : "m" (*__xg(ptr)), "0" (x)
> +                       : "memory");
> +               break;
> +       case 2:
> +               __asm__ __volatile__("xchgw %w0,%1"
> +                       : "=r" (x)
> +                       : "m" (*__xg(ptr)), "0" (x)
> +                       : "memory");
> +               break;
> +       case 4:
> +               __asm__ __volatile__("xchgl %0,%1"
> +                       : "=r" (x)
> +                       : "m" (*__xg(ptr)), "0" (x)
> +                       : "memory");
> +               break;
> +       }
> +
> +       return x;
> +}
> +
> +static inline void lapic_write_atomic(unsigned long reg, unsigned long v)
> +{
> +       (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
> +}
> +
> +
> +#ifdef X86_GOOD_APIC
> +# define FORCE_READ_AROUND_WRITE 0
> +# define lapic_read_around(x) lapic_read(x)
> +# define lapic_write_around(x, y) lapic_write((x), (y))
> +#else
> +# define FORCE_READ_AROUND_WRITE 1
> +# define lapic_read_around(x) lapic_read(x)
> +# define lapic_write_around(x, y) lapic_write_atomic((x), (y))
> +#endif
> +
> +static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
> +{
> +       int timeout;
> +       unsigned long status;
> +       int result;
> +       lapic_wait_icr_idle();
> +       lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
> +       lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
> +       timeout = 0;
> +       do {
> +               status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
> +       } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
> +
> +       result = -1;
> +       if (status == LAPIC_ICR_RR_VALID) {
> +               *pvalue = lapic_read(LAPIC_RRR);
> +               result = 0;
> +       }
> +       return result;
> +}
> +
> +
> +void lapic_setup(void);
> +
> +#if CONFIG_SMP
> +struct device;
> +int start_cpu(struct device *cpu);
> +#endif /* CONFIG_SMP */
> +
> +#endif /* !__PRE_RAM__ */
> +
> +int boot_cpu(void);
> +
> +/**
> + * struct x86_cpu_priv - Information about a single CPU
> + *
> + * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
> + * just a number representing the CPU core
> + *
> + * TODO: Move this to driver model once lifecycle is understood
> + */
> +struct x86_cpu_priv {
> +       int apic_id;
> +       int start_err;
> +};
> +
>  #endif
> diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h
> index ce68839..6d2ae5d 100644
> --- a/arch/x86/include/asm/post.h
> +++ b/arch/x86/include/asm/post.h
> @@ -30,6 +30,7 @@
>  #define POST_PRE_MRC           0x2e
>  #define POST_MRC               0x2f
>  #define POST_DRAM              0x2f
> +#define POST_LAPIC             0x30
>
>  #define POST_RAM_FAILURE       0xea
>
> --

Regards,
Bin


More information about the U-Boot mailing list