mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-27 11:55:06 +00:00
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:
parent
3a648f0472
commit
8428d0f154
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=331878
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user