Unify assembler function handling
Instead of adding regparm(0) to each assembler function called by coreboot, add an asmlinkage macro (like the Linux kernel does) that can be different per architecture (and that is empty on ARM right now) Change-Id: I7ad10c463f6c552f1201f77ae24ed354ac48e2d9 Signed-off-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/1973 Reviewed-by: David Hendricks <dhendrix@chromium.org> Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
c269a9b51c
commit
399486e8fb
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Google, Inc
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_CPU_H__
|
||||||
|
#define __ARCH_CPU_H__
|
||||||
|
|
||||||
|
#define asmlinkage
|
||||||
|
|
||||||
|
#endif
|
|
@ -748,7 +748,7 @@ extern int lowmem_backup_size;
|
||||||
#define WAKEUP_BASE 0x600
|
#define WAKEUP_BASE 0x600
|
||||||
|
|
||||||
void (*acpi_do_wakeup)(u32 vector, u32 backup_source, u32 backup_target,
|
void (*acpi_do_wakeup)(u32 vector, u32 backup_source, u32 backup_target,
|
||||||
u32 backup_size) __attribute__((regparm(0))) = (void *)WAKEUP_BASE;
|
u32 backup_size) asmlinkage = (void *)WAKEUP_BASE;
|
||||||
|
|
||||||
extern unsigned char __wakeup, __wakeup_size;
|
extern unsigned char __wakeup, __wakeup_size;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef ARCH_CPU_H
|
#ifndef ARCH_CPU_H
|
||||||
#define ARCH_CPU_H
|
#define ARCH_CPU_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EFLAGS bits
|
* EFLAGS bits
|
||||||
*/
|
*/
|
||||||
|
@ -205,6 +207,9 @@ static void inline get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
|
||||||
c->x86_model += ((tfms >> 16) & 0xF) << 4;
|
c->x86_model += ((tfms >> 16) & 0xF) << 4;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define asmlinkage __attribute__((regparm(0)))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* ARCH_CPU_H */
|
#endif /* ARCH_CPU_H */
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
#ifndef __ARCH_STAGES_H
|
#ifndef __ARCH_STAGES_H
|
||||||
#define __ARCH_STAGES_H
|
#define __ARCH_STAGES_H
|
||||||
void __attribute__((regparm(0))) copy_and_run(unsigned cpu_reset);
|
|
||||||
void __attribute__((regparm(0))) copy_and_run_ap_code_in_car(unsigned ret_addr);
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
|
void asmlinkage copy_and_run(unsigned cpu_reset);
|
||||||
|
void asmlinkage copy_and_run_ap_code_in_car(unsigned ret_addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,7 +41,7 @@ static void cbfs_and_run_core(const char *filename, unsigned ebp)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __attribute__((regparm(0))) copy_and_run(unsigned cpu_reset)
|
void asmlinkage copy_and_run(unsigned cpu_reset)
|
||||||
{
|
{
|
||||||
// FIXME fix input parameters instead normalizing them here.
|
// FIXME fix input parameters instead normalizing them here.
|
||||||
if (cpu_reset == 1) cpu_reset = -1;
|
if (cpu_reset == 1) cpu_reset = -1;
|
||||||
|
@ -51,7 +51,7 @@ void __attribute__((regparm(0))) copy_and_run(unsigned cpu_reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_AP_CODE_IN_CAR
|
#if CONFIG_AP_CODE_IN_CAR
|
||||||
void __attribute__((regparm(0))) copy_and_run_ap_code_in_car(unsigned ret_addr)
|
void asmlinkage copy_and_run_ap_code_in_car(unsigned ret_addr)
|
||||||
{
|
{
|
||||||
cbfs_and_run_core(CONFIG_CBFS_PREFIX "/coreboot_ap", ret_addr);
|
cbfs_and_run_core(CONFIG_CBFS_PREFIX "/coreboot_ap", ret_addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,7 +408,7 @@ static __inline__ __attribute__((always_inline)) void writecr4(unsigned long Dat
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* C entry point of secondary cpus */
|
/* C entry point of secondary cpus */
|
||||||
void __attribute__((regparm(0))) secondary_cpu_init(unsigned int index)
|
void asmlinkage secondary_cpu_init(unsigned int index)
|
||||||
{
|
{
|
||||||
atomic_inc(&active_cpus);
|
atomic_inc(&active_cpus);
|
||||||
#if CONFIG_SERIAL_CPU_INIT
|
#if CONFIG_SERIAL_CPU_INIT
|
||||||
|
|
|
@ -38,11 +38,11 @@
|
||||||
X86EMU_sysEnv _X86EMU_env;
|
X86EMU_sysEnv _X86EMU_env;
|
||||||
|
|
||||||
void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
u32 esi, u32 edi) __attribute__((regparm(0))) =
|
u32 esi, u32 edi) asmlinkage =
|
||||||
(void *)&__realmode_call;
|
(void *)&__realmode_call;
|
||||||
|
|
||||||
void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
u32 esi, u32 edi) __attribute__((regparm(0))) =
|
u32 esi, u32 edi) asmlinkage =
|
||||||
(void *)&__realmode_interrupt;
|
(void *)&__realmode_interrupt;
|
||||||
|
|
||||||
static void setup_rombios(void)
|
static void setup_rombios(void)
|
||||||
|
@ -406,7 +406,7 @@ void do_vsmbios(void)
|
||||||
/* interrupt_handler() is called from assembler code only,
|
/* interrupt_handler() is called from assembler code only,
|
||||||
* so there is no use in putting the prototype into a header file.
|
* so there is no use in putting the prototype into a header file.
|
||||||
*/
|
*/
|
||||||
int __attribute__((regparm(0))) interrupt_handler(u32 intnumber,
|
int asmlinkage interrupt_handler(u32 intnumber,
|
||||||
u32 gsfs, u32 dses,
|
u32 gsfs, u32 dses,
|
||||||
u32 edi, u32 esi,
|
u32 edi, u32 esi,
|
||||||
u32 ebp, u32 esp,
|
u32 ebp, u32 esp,
|
||||||
|
@ -414,7 +414,7 @@ int __attribute__((regparm(0))) interrupt_handler(u32 intnumber,
|
||||||
u32 ecx, u32 eax,
|
u32 ecx, u32 eax,
|
||||||
u32 cs_ip, u16 stackflags);
|
u32 cs_ip, u16 stackflags);
|
||||||
|
|
||||||
int __attribute__((regparm(0))) interrupt_handler(u32 intnumber,
|
int asmlinkage interrupt_handler(u32 intnumber,
|
||||||
u32 gsfs, u32 dses,
|
u32 gsfs, u32 dses,
|
||||||
u32 edi, u32 esi,
|
u32 edi, u32 esi,
|
||||||
u32 ebp, u32 esp,
|
u32 ebp, u32 esp,
|
||||||
|
|
|
@ -18,6 +18,11 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __DEVICE_OPROM_REALMODE_X86_H__
|
||||||
|
#define __DEVICE_OPROM_REALMODE_X86_H__
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
#define REALMODE_BASE ((void *)0x600)
|
#define REALMODE_BASE ((void *)0x600)
|
||||||
|
|
||||||
struct realmode_idt {
|
struct realmode_idt {
|
||||||
|
@ -33,10 +38,10 @@ extern unsigned char __realmode_call, __realmode_interrupt;
|
||||||
extern unsigned char __buffer;
|
extern unsigned char __buffer;
|
||||||
|
|
||||||
extern void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
extern void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
u32 esi, u32 edi) __attribute__((regparm(0)));
|
u32 esi, u32 edi) asmlinkage;
|
||||||
|
|
||||||
extern void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
extern void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
u32 esi, u32 edi) __attribute__((regparm(0)));
|
u32 esi, u32 edi) asmlinkage;
|
||||||
|
|
||||||
#define FAKE_MEMORY_SIZE (1024*1024) // only 1MB
|
#define FAKE_MEMORY_SIZE (1024*1024) // only 1MB
|
||||||
#define INITIAL_EBDA_SEGMENT 0xF600
|
#define INITIAL_EBDA_SEGMENT 0xF600
|
||||||
|
@ -47,3 +52,4 @@ int int12_handler(void);
|
||||||
int int16_handler(void);
|
int int16_handler(void);
|
||||||
int int1a_handler(void);
|
int int1a_handler(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
void cpu_initialize(unsigned int cpu_index);
|
void cpu_initialize(unsigned int cpu_index);
|
||||||
struct bus;
|
struct bus;
|
||||||
void initialize_cpus(struct bus *cpu_bus);
|
void initialize_cpus(struct bus *cpu_bus);
|
||||||
void __attribute__((regparm(0))) secondary_cpu_init(unsigned int cpu_index);
|
void asmlinkage secondary_cpu_init(unsigned int cpu_index);
|
||||||
|
|
||||||
#if CONFIG_HAVE_SMI_HANDLER
|
#if CONFIG_HAVE_SMI_HANDLER
|
||||||
void smm_init(void);
|
void smm_init(void);
|
||||||
|
|
|
@ -17,26 +17,21 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
/* GCC's libgcc handling is quite broken. While the libgcc functions
|
/* GCC's libgcc handling is quite broken. While the libgcc functions
|
||||||
* are always regparm(0) the code that calls them uses whatever the
|
* are always regparm(0) the code that calls them uses whatever the
|
||||||
* compiler call specifies. Therefore we need a wrapper around those
|
* compiler call specifies. Therefore we need a wrapper around those
|
||||||
* functions. See gcc bug PR41055 for more information.
|
* functions. See gcc bug PR41055 for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if CONFIG_ARCH_X86
|
/* TODO: maybe this code should move to arch/x86 as architecture
|
||||||
|
* specific implementations may vary
|
||||||
|
*/
|
||||||
#define WRAP_LIBGCC_CALL(type, name) \
|
#define WRAP_LIBGCC_CALL(type, name) \
|
||||||
type __real_##name(type a, type b) __attribute__((regparm(0))); \
|
type __real_##name(type a, type b) asmlinkage; \
|
||||||
type __wrap_##name(type a, type b); \
|
type __wrap_##name(type a, type b); \
|
||||||
type __wrap_##name(type a, type b) { return __real_##name(a, b); }
|
type __wrap_##name(type a, type b) { return __real_##name(a, b); }
|
||||||
#elif CONFIG_ARCH_ARMV7
|
|
||||||
#define WRAP_LIBGCC_CALL(type, name) \
|
|
||||||
type __real_##name(type a, type b); \
|
|
||||||
type __wrap_##name(type a, type b); \
|
|
||||||
type __wrap_##name(type a, type b) { return __real_##name(a, b); }
|
|
||||||
#else
|
|
||||||
#error Architecture unsupported.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
WRAP_LIBGCC_CALL(long long, __divdi3)
|
WRAP_LIBGCC_CALL(long long, __divdi3)
|
||||||
WRAP_LIBGCC_CALL(unsigned long long, __udivdi3)
|
WRAP_LIBGCC_CALL(unsigned long long, __udivdi3)
|
||||||
|
|
Loading…
Reference in New Issue