cpu/x86/lapic: Support x86_64 and clean up code
Most LAPIC registers are 32bit, and thus the use of long is valid on x86_32, however it doesn't work on x86_64. * Don't use long as it is 64bit on x86_64, which breaks interrupts in QEMU and thus SeaBIOS wouldn't time out the boot menu * Get rid of unused defines * Get rid of unused atomic xchg code Tested on QEMU Q35 with x86_64 enabled: Interrupts work again. Tested on QEMU Q35 with x86_32 enabled: Interrupts are still working. Tested on Lenovo T410 with x86_64 enabled. Change-Id: Iaed1ad956d090625c7bb5cd9cf55cbae16dd82bd Signed-off-by: Patrick Rudolph <siro@das-labor.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/36777 Reviewed-by: Angel Pons <th3fanbus@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
6f1d35e72d
commit
fc57d6c4c2
|
@ -228,7 +228,7 @@ static void model_2065x_init(struct device *cpu)
|
||||||
/* Print processor name */
|
/* Print processor name */
|
||||||
fill_processor_name(processor_name);
|
fill_processor_name(processor_name);
|
||||||
printk(BIOS_INFO, "CPU: %s.\n", processor_name);
|
printk(BIOS_INFO, "CPU: %s.\n", processor_name);
|
||||||
printk(BIOS_INFO, "CPU:lapic=%ld, boot_cpu=%d\n", lapicid(),
|
printk(BIOS_INFO, "CPU:lapic=%d, boot_cpu=%d\n", lapicid(),
|
||||||
boot_cpu());
|
boot_cpu());
|
||||||
|
|
||||||
/* Setup Page Attribute Tables (PAT) */
|
/* Setup Page Attribute Tables (PAT) */
|
||||||
|
|
|
@ -47,6 +47,6 @@ void do_lapic_init(void)
|
||||||
LAPIC_DELIVERY_MODE_NMI)
|
LAPIC_DELIVERY_MODE_NMI)
|
||||||
);
|
);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, " apic_id: 0x%02lx ", lapicid());
|
printk(BIOS_DEBUG, " apic_id: 0x%02x ", lapicid());
|
||||||
printk(BIOS_INFO, "done.\n");
|
printk(BIOS_INFO, "done.\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ static void recover_lowest_1M(void)
|
||||||
static int lapic_start_cpu(unsigned long apicid)
|
static int lapic_start_cpu(unsigned long apicid)
|
||||||
{
|
{
|
||||||
int timeout;
|
int timeout;
|
||||||
unsigned long send_status, accept_status;
|
uint32_t send_status, accept_status;
|
||||||
int j, maxlvt;
|
int j, maxlvt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -123,11 +123,11 @@ static int lapic_start_cpu(unsigned long apicid)
|
||||||
printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
|
printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
|
||||||
"Disabling\n", apicid);
|
"Disabling\n", apicid);
|
||||||
// too bad.
|
// too bad.
|
||||||
printk(BIOS_ERR, "ESR is 0x%lx\n", lapic_read(LAPIC_ESR));
|
printk(BIOS_ERR, "ESR is 0x%x\n", lapic_read(LAPIC_ESR));
|
||||||
if (lapic_read(LAPIC_ESR)) {
|
if (lapic_read(LAPIC_ESR)) {
|
||||||
printk(BIOS_ERR, "Try to reset ESR\n");
|
printk(BIOS_ERR, "Try to reset ESR\n");
|
||||||
lapic_write_around(LAPIC_ESR, 0);
|
lapic_write_around(LAPIC_ESR, 0);
|
||||||
printk(BIOS_ERR, "ESR is 0x%lx\n",
|
printk(BIOS_ERR, "ESR is 0x%x\n",
|
||||||
lapic_read(LAPIC_ESR));
|
lapic_read(LAPIC_ESR));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -216,7 +216,7 @@ static int lapic_start_cpu(unsigned long apicid)
|
||||||
if (send_status)
|
if (send_status)
|
||||||
printk(BIOS_WARNING, "APIC never delivered???\n");
|
printk(BIOS_WARNING, "APIC never delivered???\n");
|
||||||
if (accept_status)
|
if (accept_status)
|
||||||
printk(BIOS_WARNING, "APIC delivery error (%lx).\n",
|
printk(BIOS_WARNING, "APIC delivery error (%x).\n",
|
||||||
accept_status);
|
accept_status);
|
||||||
if (send_status || accept_status)
|
if (send_status || accept_status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
#ifndef CPU_X86_LAPIC_H
|
#ifndef CPU_X86_LAPIC_H
|
||||||
#define CPU_X86_LAPIC_H
|
#define CPU_X86_LAPIC_H
|
||||||
|
|
||||||
|
#include <arch/mmio.h>
|
||||||
#include <cpu/x86/lapic_def.h>
|
#include <cpu/x86/lapic_def.h>
|
||||||
#include <cpu/x86/msr.h>
|
#include <cpu/x86/msr.h>
|
||||||
#include <halt.h>
|
#include <halt.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
static __always_inline unsigned long lapic_read(unsigned long reg)
|
static __always_inline uint32_t lapic_read(unsigned int reg)
|
||||||
{
|
{
|
||||||
return *((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg));
|
return read32((volatile void *)(LAPIC_DEFAULT_BASE + reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline void lapic_write(unsigned long reg, unsigned long v)
|
static __always_inline void lapic_write(unsigned int reg, uint32_t v)
|
||||||
{
|
{
|
||||||
*((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg)) = v;
|
write32((volatile void *)(LAPIC_DEFAULT_BASE + reg), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline void lapic_wait_icr_idle(void)
|
static __always_inline void lapic_wait_icr_idle(void)
|
||||||
|
@ -39,7 +41,7 @@ static inline void disable_lapic(void)
|
||||||
wrmsr(LAPIC_BASE_MSR, msr);
|
wrmsr(LAPIC_BASE_MSR, msr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline unsigned long lapicid(void)
|
static __always_inline unsigned int lapicid(void)
|
||||||
{
|
{
|
||||||
return lapic_read(LAPIC_ID) >> 24;
|
return lapic_read(LAPIC_ID) >> 24;
|
||||||
}
|
}
|
||||||
|
@ -57,58 +59,19 @@ static __always_inline void stop_this_cpu(void)
|
||||||
void stop_this_cpu(void);
|
void stop_this_cpu(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
|
static inline void lapic_write_atomic(unsigned long reg, uint32_t v)
|
||||||
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) {
|
volatile uint32_t *ptr;
|
||||||
case 1:
|
|
||||||
__asm__ __volatile__("xchgb %b0,%1"
|
ptr = (volatile uint32_t *)(LAPIC_DEFAULT_BASE + reg);
|
||||||
: "=q" (x)
|
|
||||||
: "m" (*__xg(ptr)), "0" (x)
|
asm volatile ("xchgl %0, %1\n"
|
||||||
: "memory");
|
: "+r" (v), "+m" (*(ptr))
|
||||||
break;
|
: : "memory", "cc");
|
||||||
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_read_around(x) lapic_read(x)
|
||||||
# define lapic_write_around(x, y) lapic_write_atomic((x), (y))
|
# define lapic_write_around(x, y) lapic_write_atomic((x), (y))
|
||||||
#endif
|
|
||||||
|
|
||||||
void do_lapic_init(void);
|
void do_lapic_init(void);
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@ static void callout_ap_entry(void *unused)
|
||||||
Status = amd_late_run_ap_task(agesadata.ConfigPtr);
|
Status = amd_late_run_ap_task(agesadata.ConfigPtr);
|
||||||
|
|
||||||
if (Status)
|
if (Status)
|
||||||
printk(BIOS_DEBUG, "There was a problem with %lx returned %s\n",
|
printk(BIOS_DEBUG, "There was a problem with %x returned %s\n",
|
||||||
lapicid(), decodeAGESA_STATUS(Status));
|
lapicid(), decodeAGESA_STATUS(Status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue