summaryrefslogtreecommitdiffstats
path: root/sys/amd64/vmm
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-12-20 04:57:45 +0000
committerneel <neel@FreeBSD.org>2014-12-20 04:57:45 +0000
commite4f07b01b400017b362112cff0817979ec5b286e (patch)
treebde9abc04d3a98e222ade5c35465998461e1306e /sys/amd64/vmm
parent31045cef3fe333785e7e55ae1f80fcb379c647c1 (diff)
downloadFreeBSD-src-e4f07b01b400017b362112cff0817979ec5b286e.zip
FreeBSD-src-e4f07b01b400017b362112cff0817979ec5b286e.tar.gz
Various 8259 device model improvements:
- implement 8259 "polled" mode. - set 'atpic->sfn' if bit 4 in ICW4 is set during master initialization. - report error if guest tries to enable the "special mask" mode. Differential Revision: https://reviews.freebsd.org/D1328 Reviewed by: tychon Reported by: grehan Tested by: grehan MFC after: 1 week
Diffstat (limited to 'sys/amd64/vmm')
-rw-r--r--sys/amd64/vmm/io/vatpic.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/sys/amd64/vmm/io/vatpic.c b/sys/amd64/vmm/io/vatpic.c
index c6d4590..74a7027 100644
--- a/sys/amd64/vmm/io/vatpic.c
+++ b/sys/amd64/vmm/io/vatpic.c
@@ -112,6 +112,16 @@ struct vatpic {
static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate);
+static __inline bool
+master_atpic(struct vatpic *vatpic, struct atpic *atpic)
+{
+
+ if (atpic == &vatpic->atpic[0])
+ return (true);
+ else
+ return (false);
+}
+
static __inline int
vatpic_get_highest_isrpin(struct atpic *atpic)
{
@@ -250,6 +260,7 @@ vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
atpic->mask = 0;
atpic->lowprio = 7;
atpic->rd_cmd_reg = 0;
+ atpic->poll = 0;
if ((val & ICW1_SNGL) != 0) {
VATPIC_CTR0(vatpic, "vatpic cascade mode required");
@@ -301,6 +312,15 @@ vatpic_icw4(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
if ((val & ICW4_AEOI) != 0)
atpic->aeoi = true;
+ if ((val & ICW4_SFNM) != 0) {
+ if (master_atpic(vatpic, atpic)) {
+ atpic->sfn = true;
+ } else {
+ VATPIC_CTR1(vatpic, "Ignoring special fully nested "
+ "mode on slave atpic: %#x", val);
+ }
+ }
+
atpic->icw_num = 0;
atpic->ready = true;
@@ -354,11 +374,17 @@ vatpic_ocw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
{
VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val);
- atpic->poll = ((val & OCW3_P) != 0);
+ if (val & OCW3_ESMM) {
+ VATPIC_CTR0(vatpic, "atpic special mask mode not implemented");
+ return (-1);
+ }
if (val & OCW3_RR) {
/* read register command */
atpic->rd_cmd_reg = val & OCW3_RIS;
+
+ /* Polling mode */
+ atpic->poll = ((val & OCW3_P) != 0);
}
return (0);
@@ -578,12 +604,19 @@ static int
vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port,
int bytes, uint32_t *eax)
{
+ int pin;
+
VATPIC_LOCK(vatpic);
if (atpic->poll) {
- VATPIC_CTR0(vatpic, "vatpic polled mode not supported");
- VATPIC_UNLOCK(vatpic);
- return (-1);
+ atpic->poll = 0;
+ pin = vatpic_get_highest_irrpin(atpic);
+ if (pin >= 0) {
+ vatpic_pin_accepted(atpic, pin);
+ *eax = 0x80 | pin;
+ } else {
+ *eax = 0;
+ }
} else {
if (port & ICU_IMR_OFFSET) {
/* read interrrupt mask register */
OpenPOWER on IntegriCloud