diff options
author | neel <neel@FreeBSD.org> | 2014-12-31 04:12:38 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-12-31 04:12:38 +0000 |
commit | eb8065a6a6ca8a4894af3382dbfbea4135bffd0a (patch) | |
tree | 2144f4e52d66d14aedf101861a998d0da2912967 /sys/amd64 | |
parent | 27e956ad1b0a1f1b86e8038a8be1b31a7d7f5877 (diff) | |
download | FreeBSD-src-eb8065a6a6ca8a4894af3382dbfbea4135bffd0a.zip FreeBSD-src-eb8065a6a6ca8a4894af3382dbfbea4135bffd0a.tar.gz |
MFC r276323
Implement "special mask mode" in vatpic.
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/vmm/io/vatpic.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/sys/amd64/vmm/io/vatpic.c b/sys/amd64/vmm/io/vatpic.c index 74a7027..328c35f 100644 --- a/sys/amd64/vmm/io/vatpic.c +++ b/sys/amd64/vmm/io/vatpic.c @@ -73,6 +73,7 @@ struct atpic { uint8_t request; /* Interrupt Request Register (IIR) */ uint8_t service; /* Interrupt Service (ISR) */ uint8_t mask; /* Interrupt Mask Register (IMR) */ + uint8_t smm; /* special mask mode */ int acnt[8]; /* sum of pin asserts and deasserts */ int lowprio; /* lowest priority irq */ @@ -131,8 +132,16 @@ vatpic_get_highest_isrpin(struct atpic *atpic) ATPIC_PIN_FOREACH(pin, atpic, i) { bit = (1 << pin); - if (atpic->service & bit) - return (pin); + if (atpic->service & bit) { + /* + * An IS bit that is masked by an IMR bit will not be + * cleared by a non-specific EOI in Special Mask Mode. + */ + if (atpic->smm && (atpic->mask & bit) != 0) + continue; + else + return (pin); + } } return (-1); @@ -153,6 +162,15 @@ vatpic_get_highest_irrpin(struct atpic *atpic) if (atpic->sfn) serviced &= ~(1 << 2); + /* + * In 'Special Mask Mode', when a mask bit is set in OCW1 it inhibits + * further interrupts at that level and enables interrupts from all + * other levels that are not masked. In other words the ISR has no + * bearing on the levels that can generate interrupts. + */ + if (atpic->smm) + serviced = 0; + ATPIC_PIN_FOREACH(pin, atpic, tmp) { bit = 1 << pin; @@ -261,6 +279,7 @@ vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) atpic->lowprio = 7; atpic->rd_cmd_reg = 0; atpic->poll = 0; + atpic->smm = 0; if ((val & ICW1_SNGL) != 0) { VATPIC_CTR0(vatpic, "vatpic cascade mode required"); @@ -375,8 +394,10 @@ vatpic_ocw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val); if (val & OCW3_ESMM) { - VATPIC_CTR0(vatpic, "atpic special mask mode not implemented"); - return (-1); + atpic->smm = val & OCW3_SMM ? 1 : 0; + VATPIC_CTR2(vatpic, "%s atpic special mask mode %s", + master_atpic(vatpic, atpic) ? "master" : "slave", + atpic->smm ? "enabled" : "disabled"); } if (val & OCW3_RR) { |