[U-Boot] [PATCH v2 1/4] x86: Implement reset_cpu() correctly for modern CPUs

Simon Glass sjg at chromium.org
Thu Apr 30 06:21:34 CEST 2015


On 28 April 2015 at 21:55, Bin Meng <bmeng.cn at gmail.com> wrote:
> On Wed, Apr 29, 2015 at 10:11 AM, Simon Glass <sjg at chromium.org> wrote:
>> The existing code is pretty ancient and is unreliable on modern hardware.
>> Generally it will hang.
>>
>> We can use port 0xcf9 to initiate reset on more modern hardware (say in the
>> last 10 years). Update the reset_cpu() function to do this, and add a new
>> 'full reset' function to perform a full power cycle.
>>
>> Signed-off-by: Simon Glass <sjg at chromium.org>
>> ---
>>
>> Changes in v2:
>> - Update reset comments to indicate the datasheet section
>> - Correct full reset code
>>
>>  arch/x86/cpu/cpu.c               | 22 +++++++++-------------
>>  arch/x86/include/asm/processor.h | 19 +++++++++++++++++++
>>  2 files changed, 28 insertions(+), 13 deletions(-)
>>
>> diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
>> index c9614f1..02e66d8 100644
>> --- a/arch/x86/cpu/cpu.c
>> +++ b/arch/x86/cpu/cpu.c
>> @@ -380,21 +380,17 @@ void  flush_cache(unsigned long dummy1, unsigned long dummy2)
>>         asm("wbinvd\n");
>>  }
>>
>> -void __attribute__ ((regparm(0))) generate_gpf(void);
>> -
>> -/* segment 0x70 is an arbitrary segment which does not exist */
>> -asm(".globl generate_gpf\n"
>> -       ".hidden generate_gpf\n"
>> -       ".type generate_gpf, @function\n"
>> -       "generate_gpf:\n"
>> -       "ljmp   $0x70, $0x47114711\n");
>> -
>>  __weak void reset_cpu(ulong addr)
>>  {
>> -       printf("Resetting using x86 Triple Fault\n");
>> -       set_vector(13, generate_gpf);   /* general protection fault handler */
>> -       set_vector(8, generate_gpf);    /* double fault handler */
>> -       generate_gpf();                 /* start the show */
>> +       /* Do a hard reset through the chipset's reset control register */
>> +       outb(SYS_RST | RST_CPU, PORT_RESET);
>> +       for (;;)
>> +               cpu_hlt();
>> +}
>> +
>> +void x86_full_reset(void)
>> +{
>> +       outb(FULL_RST | SYS_RST | RST_CPU, PORT_RESET);
>>  }
>>
>>  int dcache_status(void)
>> diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
>> index 3e26202..3575d34 100644
>> --- a/arch/x86/include/asm/processor.h
>> +++ b/arch/x86/include/asm/processor.h
>> @@ -25,8 +25,27 @@
>>
>>  #ifndef __ASSEMBLY__
>>
>> +/*
>> + * This register is documented in (for example) the Intel Atom Processor E3800
>> + * Product Family Datasheet in "PCU - Power Management Controller (PMC)".
>> + *
>> + * RST_CNT: Reset Control Register (RST_CNT) Offset cf9.
>> + *
>> + * The naming follows Intel's naming.
>> + */
>>  #define PORT_RESET             0xcf9
>>
>> +enum {
>> +       SYS_RST         = 1 << 1,       /* 0 for soft reset, 1 for hard reset */
>> +       RST_CPU         = 1 << 2,       /* initiate reset */
>> +       FULL_RST        = 1 << 3,       /* full power cycle */
>> +};
>> +
>> +/**
>> + * x86_full_reset() - reset everything: perform a full power cycle
>> + */
>> +void x86_full_reset(void);
>> +
>>  static inline __attribute__((always_inline)) void cpu_hlt(void)
>>  {
>>         asm("hlt");
>> --
>
> Reviewed-by: Bin Meng <bmeng.cn at gmail.com>

Applied to u-boot-x86.


More information about the U-Boot mailing list