mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-12-29 15:10:57 +01:00
Ensure that the i8254 timecounter doesn't go backards. It sometimes
went backwards when interrupts were masked for more than one i8254 interrupt period. It sometimes went backwards when the i8254 counter was reprogrammed. Neither of these should happen in normal operation. Update the i8254 timecounter support variables atomically. Calling timecounter functions from fast interrupt handlers may actually work in all cases now.
This commit is contained in:
parent
cc59ec0b9e
commit
a6796db6ce
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=39503
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $
|
||||
* $Id: clock.c,v 1.125 1998/09/06 22:41:41 tegge Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -198,11 +198,26 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD,
|
||||
static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (!i8254_ticked)
|
||||
i8254_offset += timer0_max_count;
|
||||
else
|
||||
i8254_ticked = 0;
|
||||
i8254_lastcount = 0;
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
disable_intr();
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $
|
||||
* $Id: clock.c,v 1.125 1998/09/06 22:41:41 tegge Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -198,11 +198,26 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD,
|
||||
static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (!i8254_ticked)
|
||||
i8254_offset += timer0_max_count;
|
||||
else
|
||||
i8254_ticked = 0;
|
||||
i8254_lastcount = 0;
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
disable_intr();
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $
|
||||
* $Id: clock.c,v 1.125 1998/09/06 22:41:41 tegge Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -198,11 +198,26 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD,
|
||||
static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (!i8254_ticked)
|
||||
i8254_offset += timer0_max_count;
|
||||
else
|
||||
i8254_ticked = 0;
|
||||
i8254_lastcount = 0;
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
disable_intr();
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $
|
||||
* $Id: clock.c,v 1.125 1998/09/06 22:41:41 tegge Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -198,11 +198,26 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD,
|
||||
static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (!i8254_ticked)
|
||||
i8254_offset += timer0_max_count;
|
||||
else
|
||||
i8254_ticked = 0;
|
||||
i8254_lastcount = 0;
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
disable_intr();
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $Id: clock.c,v 1.124 1998/06/09 13:10:46 phk Exp $
|
||||
* $Id: clock.c,v 1.125 1998/09/06 22:41:41 tegge Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -198,11 +198,26 @@ SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD,
|
||||
static void
|
||||
clkintr(struct clockframe frame)
|
||||
{
|
||||
if (!i8254_ticked)
|
||||
i8254_offset += timer0_max_count;
|
||||
else
|
||||
i8254_ticked = 0;
|
||||
i8254_lastcount = 0;
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
/*
|
||||
* Maintain i8254_offset and related variables. Optimize
|
||||
* the usual case where i8254 counter rollover has not been
|
||||
* detected in i8254_get_timecount() by pretending that we
|
||||
* read the counter when it rolled over. Otherwise, call
|
||||
* i8254_get_timecount() to do most of the work. The
|
||||
* hardware counter must be read to ensure monotonicity
|
||||
* despite multiple rollovers and misbehaving hardware.
|
||||
*/
|
||||
disable_intr();
|
||||
if (i8254_ticked) {
|
||||
i8254_get_timecount(NULL);
|
||||
i8254_ticked = 0;
|
||||
} else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
enable_intr();
|
||||
}
|
||||
timer_func(&frame);
|
||||
switch (timer0_state) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user