unify amd64 and i386 cpu_reset() in x86/cpu_machdep.c

Because I didn't see any reason not too.
I've been making some changes to the code and couldn't help but notice
that the i386 and am64 code was nearly identical.

MFC after:	17 days
This commit is contained in:
Andriy Gapon 2018-04-02 13:45:23 +00:00
parent 3a648f0472
commit 8428d0f154
3 changed files with 143 additions and 272 deletions

View File

@ -84,13 +84,6 @@ __FBSDID("$FreeBSD$");
#include <isa/isareg.h>
static void cpu_reset_real(void);
#ifdef SMP
static void cpu_reset_proxy(void);
static u_int cpu_reset_proxyid;
static volatile u_int cpu_reset_proxy_active;
#endif
_Static_assert(OFFSETOF_CURTHREAD == offsetof(struct pcpu, pc_curthread),
"OFFSETOF_CURTHREAD does not correspond with offset of pc_curthread.");
_Static_assert(OFFSETOF_CURPCB == offsetof(struct pcpu, pc_curpcb),
@ -565,129 +558,6 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
return (0);
}
#ifdef SMP
static void
cpu_reset_proxy()
{
cpu_reset_proxy_active = 1;
while (cpu_reset_proxy_active == 1)
ia32_pause(); /* Wait for other cpu to see that we've started */
printf("cpu_reset_proxy: Stopped CPU %d\n", cpu_reset_proxyid);
DELAY(1000000);
cpu_reset_real();
}
#endif
void
cpu_reset()
{
#ifdef SMP
cpuset_t map;
u_int cnt;
if (smp_started) {
map = all_cpus;
CPU_CLR(PCPU_GET(cpuid), &map);
CPU_NAND(&map, &stopped_cpus);
if (!CPU_EMPTY(&map)) {
printf("cpu_reset: Stopping other CPUs\n");
stop_cpus(map);
}
if (PCPU_GET(cpuid) != 0) {
cpu_reset_proxyid = PCPU_GET(cpuid);
cpustop_restartfunc = cpu_reset_proxy;
cpu_reset_proxy_active = 0;
printf("cpu_reset: Restarting BSP\n");
/* Restart CPU #0. */
CPU_SETOF(0, &started_cpus);
wmb();
cnt = 0;
while (cpu_reset_proxy_active == 0 && cnt < 10000000) {
ia32_pause();
cnt++; /* Wait for BSP to announce restart */
}
if (cpu_reset_proxy_active == 0) {
printf("cpu_reset: Failed to restart BSP\n");
} else {
cpu_reset_proxy_active = 2;
while (1)
ia32_pause();
/* NOTREACHED */
}
}
DELAY(1000000);
}
#endif
cpu_reset_real();
/* NOTREACHED */
}
static void
cpu_reset_real()
{
struct region_descriptor null_idt;
int b;
disable_intr();
/*
* Attempt to do a CPU reset via the keyboard controller,
* do not turn off GateA20, as any machine that fails
* to do the reset here would then end up in no man's land.
*/
outb(IO_KBD + 4, 0xFE);
DELAY(500000); /* wait 0.5 sec to see if that did it */
/*
* Attempt to force a reset via the Reset Control register at
* I/O port 0xcf9. Bit 2 forces a system reset when it
* transitions from 0 to 1. Bit 1 selects the type of reset
* to attempt: 0 selects a "soft" reset, and 1 selects a
* "hard" reset. We try a "hard" reset. The first write sets
* bit 1 to select a "hard" reset and clears bit 2. The
* second write forces a 0 -> 1 transition in bit 2 to trigger
* a reset.
*/
outb(0xcf9, 0x2);
outb(0xcf9, 0x6);
DELAY(500000); /* wait 0.5 sec to see if that did it */
/*
* Attempt to force a reset via the Fast A20 and Init register
* at I/O port 0x92. Bit 1 serves as an alternate A20 gate.
* Bit 0 asserts INIT# when set to 1. We are careful to only
* preserve bit 1 while setting bit 0. We also must clear bit
* 0 before setting it if it isn't already clear.
*/
b = inb(0x92);
if (b != 0xff) {
if ((b & 0x1) != 0)
outb(0x92, b & 0xfe);
outb(0x92, b | 0x1);
DELAY(500000); /* wait 0.5 sec to see if that did it */
}
printf("No known reset method worked, attempting CPU shutdown\n");
DELAY(1000000); /* wait 1 sec for printf to complete */
/* Wipe the IDT. */
null_idt.rd_limit = 0;
null_idt.rd_base = 0;
lidt(&null_idt);
/* "good night, sweet prince .... <THUNK!>" */
breakpoint();
/* NOTREACHED */
while(1);
}
/*
* Software interrupt handler for queued VM system processing.
*/

View File

@ -103,13 +103,6 @@ _Static_assert(OFFSETOF_CURPCB == offsetof(struct pcpu, pc_curpcb),
_Static_assert(__OFFSETOF_MONITORBUF == offsetof(struct pcpu, pc_monitorbuf),
"__OFFSETOF_MONINORBUF does not correspond with offset of pc_monitorbuf.");
static void cpu_reset_real(void);
#ifdef SMP
static void cpu_reset_proxy(void);
static u_int cpu_reset_proxyid;
static volatile u_int cpu_reset_proxy_active;
#endif
union savefpu *
get_pcb_user_save_td(struct thread *td)
{
@ -577,141 +570,6 @@ kvtop(void *addr)
return (pa);
}
#ifdef SMP
static void
cpu_reset_proxy()
{
cpu_reset_proxy_active = 1;
while (cpu_reset_proxy_active == 1)
ia32_pause(); /* Wait for other cpu to see that we've started */
printf("cpu_reset_proxy: Stopped CPU %d\n", cpu_reset_proxyid);
DELAY(1000000);
cpu_reset_real();
}
#endif
void
cpu_reset()
{
#ifdef SMP
cpuset_t map;
u_int cnt;
if (smp_started) {
map = all_cpus;
CPU_CLR(PCPU_GET(cpuid), &map);
CPU_NAND(&map, &stopped_cpus);
if (!CPU_EMPTY(&map)) {
printf("cpu_reset: Stopping other CPUs\n");
stop_cpus(map);
}
if (PCPU_GET(cpuid) != 0) {
cpu_reset_proxyid = PCPU_GET(cpuid);
cpustop_restartfunc = cpu_reset_proxy;
cpu_reset_proxy_active = 0;
printf("cpu_reset: Restarting BSP\n");
/* Restart CPU #0. */
CPU_SETOF(0, &started_cpus);
wmb();
cnt = 0;
while (cpu_reset_proxy_active == 0 && cnt < 10000000) {
ia32_pause();
cnt++; /* Wait for BSP to announce restart */
}
if (cpu_reset_proxy_active == 0) {
printf("cpu_reset: Failed to restart BSP\n");
} else {
cpu_reset_proxy_active = 2;
while (1)
ia32_pause();
/* NOTREACHED */
}
}
DELAY(1000000);
}
#endif
cpu_reset_real();
/* NOTREACHED */
}
static void
cpu_reset_real()
{
struct region_descriptor null_idt;
int b;
disable_intr();
#ifdef CPU_ELAN
if (elan_mmcr != NULL)
elan_mmcr->RESCFG = 1;
#endif
if (cpu == CPU_GEODE1100) {
/* Attempt Geode's own reset */
outl(0xcf8, 0x80009044ul);
outl(0xcfc, 0xf);
}
#if !defined(BROKEN_KEYBOARD_RESET)
/*
* Attempt to do a CPU reset via the keyboard controller,
* do not turn off GateA20, as any machine that fails
* to do the reset here would then end up in no man's land.
*/
outb(IO_KBD + 4, 0xFE);
DELAY(500000); /* wait 0.5 sec to see if that did it */
#endif
/*
* Attempt to force a reset via the Reset Control register at
* I/O port 0xcf9. Bit 2 forces a system reset when it
* transitions from 0 to 1. Bit 1 selects the type of reset
* to attempt: 0 selects a "soft" reset, and 1 selects a
* "hard" reset. We try a "hard" reset. The first write sets
* bit 1 to select a "hard" reset and clears bit 2. The
* second write forces a 0 -> 1 transition in bit 2 to trigger
* a reset.
*/
outb(0xcf9, 0x2);
outb(0xcf9, 0x6);
DELAY(500000); /* wait 0.5 sec to see if that did it */
/*
* Attempt to force a reset via the Fast A20 and Init register
* at I/O port 0x92. Bit 1 serves as an alternate A20 gate.
* Bit 0 asserts INIT# when set to 1. We are careful to only
* preserve bit 1 while setting bit 0. We also must clear bit
* 0 before setting it if it isn't already clear.
*/
b = inb(0x92);
if (b != 0xff) {
if ((b & 0x1) != 0)
outb(0x92, b & 0xfe);
outb(0x92, b | 0x1);
DELAY(500000); /* wait 0.5 sec to see if that did it */
}
printf("No known reset method worked, attempting CPU shutdown\n");
DELAY(1000000); /* wait 1 sec for printf to complete */
/* Wipe the IDT. */
null_idt.rd_limit = 0;
null_idt.rd_base = 0;
lidt(&null_idt);
/* "good night, sweet prince .... <THUNK!>" */
breakpoint();
/* NOTREACHED */
while(1);
}
/*
* Get an sf_buf from the freelist. May block if none are available.
*/

View File

@ -96,10 +96,18 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_pager.h>
#include <vm/vm_param.h>
#include <isa/isareg.h>
#define STATE_RUNNING 0x0
#define STATE_MWAIT 0x1
#define STATE_SLEEPING 0x2
#ifdef SMP
static u_int cpu_reset_proxyid;
static volatile u_int cpu_reset_proxy_active;
#endif
/*
* Machine dependent boot() routine
*
@ -242,6 +250,141 @@ cpu_halt(void)
halt();
}
static void
cpu_reset_real()
{
struct region_descriptor null_idt;
int b;
disable_intr();
#ifdef CPU_ELAN
if (elan_mmcr != NULL)
elan_mmcr->RESCFG = 1;
#endif
#ifdef __i386__
if (cpu == CPU_GEODE1100) {
/* Attempt Geode's own reset */
outl(0xcf8, 0x80009044ul);
outl(0xcfc, 0xf);
}
#endif
#if !defined(BROKEN_KEYBOARD_RESET)
/*
* Attempt to do a CPU reset via the keyboard controller,
* do not turn off GateA20, as any machine that fails
* to do the reset here would then end up in no man's land.
*/
outb(IO_KBD + 4, 0xFE);
DELAY(500000); /* wait 0.5 sec to see if that did it */
#endif
/*
* Attempt to force a reset via the Reset Control register at
* I/O port 0xcf9. Bit 2 forces a system reset when it
* transitions from 0 to 1. Bit 1 selects the type of reset
* to attempt: 0 selects a "soft" reset, and 1 selects a
* "hard" reset. We try a "hard" reset. The first write sets
* bit 1 to select a "hard" reset and clears bit 2. The
* second write forces a 0 -> 1 transition in bit 2 to trigger
* a reset.
*/
outb(0xcf9, 0x2);
outb(0xcf9, 0x6);
DELAY(500000); /* wait 0.5 sec to see if that did it */
/*
* Attempt to force a reset via the Fast A20 and Init register
* at I/O port 0x92. Bit 1 serves as an alternate A20 gate.
* Bit 0 asserts INIT# when set to 1. We are careful to only
* preserve bit 1 while setting bit 0. We also must clear bit
* 0 before setting it if it isn't already clear.
*/
b = inb(0x92);
if (b != 0xff) {
if ((b & 0x1) != 0)
outb(0x92, b & 0xfe);
outb(0x92, b | 0x1);
DELAY(500000); /* wait 0.5 sec to see if that did it */
}
printf("No known reset method worked, attempting CPU shutdown\n");
DELAY(1000000); /* wait 1 sec for printf to complete */
/* Wipe the IDT. */
null_idt.rd_limit = 0;
null_idt.rd_base = 0;
lidt(&null_idt);
/* "good night, sweet prince .... <THUNK!>" */
breakpoint();
/* NOTREACHED */
while(1);
}
#ifdef SMP
static void
cpu_reset_proxy()
{
cpu_reset_proxy_active = 1;
while (cpu_reset_proxy_active == 1)
ia32_pause(); /* Wait for other cpu to see that we've started */
printf("cpu_reset_proxy: Stopped CPU %d\n", cpu_reset_proxyid);
DELAY(1000000);
cpu_reset_real();
}
#endif
void
cpu_reset()
{
#ifdef SMP
cpuset_t map;
u_int cnt;
if (smp_started) {
map = all_cpus;
CPU_CLR(PCPU_GET(cpuid), &map);
CPU_NAND(&map, &stopped_cpus);
if (!CPU_EMPTY(&map)) {
printf("cpu_reset: Stopping other CPUs\n");
stop_cpus(map);
}
if (PCPU_GET(cpuid) != 0) {
cpu_reset_proxyid = PCPU_GET(cpuid);
cpustop_restartfunc = cpu_reset_proxy;
cpu_reset_proxy_active = 0;
printf("cpu_reset: Restarting BSP\n");
/* Restart CPU #0. */
CPU_SETOF(0, &started_cpus);
wmb();
cnt = 0;
while (cpu_reset_proxy_active == 0 && cnt < 10000000) {
ia32_pause();
cnt++; /* Wait for BSP to announce restart */
}
if (cpu_reset_proxy_active == 0) {
printf("cpu_reset: Failed to restart BSP\n");
} else {
cpu_reset_proxy_active = 2;
while (1)
ia32_pause();
/* NOTREACHED */
}
}
DELAY(1000000);
}
#endif
cpu_reset_real();
/* NOTREACHED */
}
bool
cpu_mwait_usable(void)
{