⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tpm-tis-device

📁 xen 3.2.2 源码
💻
📖 第 1 页 / 共 3 页
字号:
+ */+static uint32_t tpm_data_read(tpmState *s, uint8_t locty)+{+    uint32_t ret, len;++    /* try to receive data, if none are there it is ok */+    tis_attempt_receive(s, locty);++    if (s->loc[locty].state != STATE_COMPLETION) {+        return 0xff;+    }++    len = tpm_get_size_from_buffer(s->buffer.buf);+    ret = s->buffer.buf[s->offset++];+    if (s->offset >= len) {+        s->loc[locty].sts = STS_VALID ;+        s->offset = 0;+    }+#ifdef DEBUG_TPM+    fprintf(logfile,"tpm_data_read byte x%02x   [%d]\n",ret,s->offset-1);+#endif+    return ret;+}++++/* raise an interrupt if allowed */+static void tis_raise_irq(tpmState *s, uint8_t locty, uint32_t irqmask)+{+    if (!s->irq_pending &&+        (s->loc[locty].inte & INT_ENABLED) &&+        (s->loc[locty].inte & irqmask)) {+        if ((irqmask & s->loc[locty].ints) == 0) {+#ifdef DEBUG_TPM+            fprintf(logfile,"Raising IRQ for flag %08x\n",irqmask);+#endif+            s->set_irq(s->irq_opaque, s->irq, 1);+            s->irq_pending = 1;+            s->loc[locty].ints |= irqmask;+        }+    }+}++/* abort execution of command */+static void tis_abort(tpmState *s)+{+    s->offset = 0;+    s->active_loc = s->next_locty;++    /*+     * Need to react differently depending on who's aborting now and+     * which locality will become active afterwards.+     */+    if (s->aborting_locty == s->next_locty) {+        s->loc[s->aborting_locty].state = STATE_READY;+        s->loc[s->aborting_locty].sts   = STS_COMMAND_READY;+        tis_raise_irq(s, s->aborting_locty, INT_COMMAND_READY);+    }++    /* locality after abort is another one than the current one */+    if (s->aborting_locty != s->next_locty && s->next_locty != NO_LOCALITY) {+        s->loc[s->aborting_locty].access &= ~ACCESS_ACTIVE_LOCALITY;+        s->loc[s->next_locty].access     |=  ACCESS_ACTIVE_LOCALITY;+        tis_raise_irq(s, s->next_locty, INT_LOCALITY_CHANGED);+    }++    s->aborting_locty = NO_LOCALITY; /* nobody's aborting a command anymore */++    qemu_del_timer(s->poll_timer);+}++/* abort current command */+static void tis_prep_abort(tpmState *s, uint8_t locty, uint8_t newlocty)+{+    s->aborting_locty = locty; /* current locality */+    s->next_locty = newlocty;  /* locality after successful abort */++    /*+     * only abort a command using an interrupt if currently executing+     * a command AND if there's a valid connection to the vTPM.+     */+    if (s->loc[locty].state == STATE_EXECUTION &&+        IS_COMM_WITH_VTPM(s)) {+        /* start timer and inside the timer wait for the result */+        s->poll_attempts = 0;+        tis_prep_next_interrupt(s);+    } else {+        tis_abort(s);+    }+}+++/*+ * Try to receive a response from the vTPM+ */+static void tis_attempt_receive(tpmState *s, uint8_t locty)+{+    /*+     * Attempt to read from the vTPM here if+     * - not aborting a command+     * - command has been sent and state is 'EXECUTION' now+     * - no data are already available (data have already been read)+     * - there's a communication path to the vTPM established+     */+    if (!IS_VALID_LOC(s->aborting_locty)) {+        if (s->loc[locty].state == STATE_EXECUTION) {+            if (0 == (s->loc[locty].sts & STS_DATA_AVAILABLE)){+                if (IS_COMM_WITH_VTPM(s)) {+                    int n = TPM_Receive(s, &s->buffer);+                    if (n > 0) {+                        s->loc[locty].sts = STS_VALID | STS_DATA_AVAILABLE;+                        s->loc[locty].state = STATE_COMPLETION;+                        close_vtpm_channel(s, FORCE_CLOSE);+                        tis_raise_irq(s, locty, INT_DATA_AVAILABLE);+                    }+                }+            }+        }+    }+}++/*+ * Read a register of the TIS interface+ * See specs pages 33-63 for description of the registers+ */+static uint32_t tis_mem_readl(void *opaque, target_phys_addr_t addr)+{+    tpmState *s = (tpmState *)opaque;+    uint16_t offset = addr & 0xffc;+    uint8_t shift = (addr & 0x3) * 8;+    uint32_t val = 0;+    uint8_t locty = locality_from_addr(addr);++    if (offset == TPM_REG_ACCESS) {+        if (s->active_loc == locty) {+            s->loc[locty].access |= (1 << 5);+         } else {+            s->loc[locty].access &= ~(1 << 5);+        }+        val = s->loc[locty].access;+    } else+    if (offset == TPM_REG_INT_ENABLE) {+        val = s->loc[locty].inte;+    } else+    if (offset == TPM_REG_INT_VECTOR) {+        val = s->irq;+    } else+    if (offset == TPM_REG_INT_STATUS) {+        tis_attempt_receive(s, locty);+        val = s->loc[locty].ints;+    } else+    if (offset == TPM_REG_INTF_CAPABILITY) {+        val = CAPABILITIES_SUPPORTED;+    } else+    if (offset == TPM_REG_STS) { /* status register */+        tis_attempt_receive(s, locty);+        val = (sizeof(s->buffer.buf) - s->offset) << 8 | s->loc[locty].sts;+    } else+    if (offset == TPM_REG_DATA_FIFO) {+      val = tpm_data_read(s, locty);+    } else+    if (offset == TPM_REG_DID_VID) {+        val = (TPM_DID << 16) | TPM_VID;+    } else+    if (offset == TPM_REG_RID) {+         val = TPM_RID;+    }++    if (shift)+        val >>= shift;++#ifdef DEBUG_TPM+    fprintf(logfile," read(%08x) = %08x\n",+            (int)addr,+            val);+#endif++    return val;+}++/*+ * Write a value to a register of the TIS interface+ * See specs pages 33-63 for description of the registers+ */+static void tis_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)+{+    tpmState* s=(tpmState*)opaque;+    uint16_t off = addr & 0xfff;+    uint8_t locty = locality_from_addr(addr);+    int n, c;+    uint32_t len;++#ifdef DEBUG_TPM+    fprintf(logfile,"write(%08x) = %08x\n",+            (int)addr,+            val);+#endif++    if (off == TPM_REG_ACCESS) {+        if (val & ACCESS_ACTIVE_LOCALITY) {+            /* give up locality if currently owned */+            if (s->active_loc == locty) {+                uint8_t newlocty = NO_LOCALITY;+                s->loc[locty].access &= ~(ACCESS_PENDING_REQUEST);+                /* anybody wants the locality ? */+                for (c = NUM_LOCALITIES - 1; c >= 0; c--) {+                    if (s->loc[c].access & ACCESS_REQUEST_USE) {+                        s->loc[c].access |= ACCESS_TPM_REG_VALID_STS;+                        s->loc[c].access &= ~ACCESS_REQUEST_USE;+                        newlocty = c;+                        break;+                    }+                }+                tis_prep_abort(s, locty, newlocty);+            }+        }+        if (val & ACCESS_BEEN_SEIZED) {+            /* clear the flag */+            s->loc[locty].access &= ~ACCESS_BEEN_SEIZED;+        }+        if (val & ACCESS_SEIZE) {+            if (locty > s->active_loc && IS_VALID_LOC(s->active_loc)) {+                s->loc[s->active_loc].access |= ACCESS_BEEN_SEIZED;+                s->loc[locty].access = ACCESS_TPM_REG_VALID_STS;+                tis_prep_abort(s, s->active_loc, locty);+            }+        }+        if (val & ACCESS_REQUEST_USE) {+            if (IS_VALID_LOC(s->active_loc)) {+                /* locality election */+                s->loc[s->active_loc].access |= ACCESS_PENDING_REQUEST;+            } else {+                /* no locality active -> make this one active now */+                s->loc[locty].access |= ACCESS_ACTIVE_LOCALITY;+                s->active_loc = locty;+                tis_raise_irq(s, locty, INT_LOCALITY_CHANGED);+            }+        }+    } else+    if (off == TPM_REG_INT_ENABLE) {+        s->loc[locty].inte = (val & (INT_ENABLED | (0x3 << 3) |+                                     INTERRUPTS_SUPPORTED));+    } else+    if (off == TPM_REG_INT_STATUS) {+        /* clearing of interrupt flags */+        if ((val & INTERRUPTS_SUPPORTED) &&+            (s->loc[locty].ints & INTERRUPTS_SUPPORTED)) {+            s->set_irq(s->irq_opaque, s->irq, 0);+            s->irq_pending = 0;+        }+        s->loc[locty].ints &= ~(val & INTERRUPTS_SUPPORTED);+    } else+    if (off == TPM_REG_STS) {+        if (val & STS_COMMAND_READY) {+            if (s->loc[locty].state == STATE_IDLE) {+                s->loc[locty].sts   = STS_COMMAND_READY;+                s->loc[locty].state = STATE_READY;+                tis_raise_irq(s, locty, INT_COMMAND_READY);+            } else if (s->loc[locty].state == STATE_COMPLETION ||+                       s->loc[locty].state == STATE_EXECUTION  ||+                       s->loc[locty].state == STATE_RECEPTION) {+                /* abort currently running command */+                tis_prep_abort(s, locty, locty);+            }+        }+        if (val & STS_TPM_GO) {+            n = TPM_Send(s, &s->buffer, locty, "tpm_data_write");+            if (n > 0) {+                /* sending of data was successful */+                s->offset = 0;+                s->loc[locty].state = STATE_EXECUTION;+                if (s->loc[locty].inte & (INT_ENABLED | INT_DATA_AVAILABLE)) {+                    s->poll_attempts = 0;+                    tis_prep_next_interrupt(s);+                }+            }+        }+        if (val & STS_RESPONSE_RETRY) {+            s->offset = 0;+        }+    } else if (off == TPM_REG_DATA_FIFO) {+        /* data fifo */+        if (s->loc[locty].state == STATE_IDLE ||+            s->loc[locty].state == STATE_EXECUTION ||+            s->loc[locty].state == STATE_COMPLETION) {+            /* drop the byte */+        } else {+#ifdef TPM_DEBUG+        fprintf(logfile,"Byte to send to TPM: %02x\n", val);+#endif+            s->loc[locty].state = STATE_RECEPTION;++            if (s->offset < sizeof(s->buffer.buf))+                s->buffer.buf[s->offset++] = (uint8_t)val;++            if (s->offset > 5) {+                /* we have a packet length - see if we have all of it */+                len = tpm_get_size_from_buffer(s->buffer.buf);+                if (len > s->offset) {+                    s->loc[locty].sts = STS_EXPECT | STS_VALID;+                } else {+                    s->loc[locty].sts = STS_VALID;+                }+            }+        }+    }+}++/*+ * Prepare the next interrupt for example after a command has+ * been sent out for the purpose of receiving the response.+ * Depending on how many interrupts (used for polling on the fd) have+ * already been schedule, this function determines the delta in time+ * to the next interrupt. This accomodates for commands that finish+ * quickly.+ */+static void tis_prep_next_interrupt(tpmState *s)+{+    int64_t expiration;+    int rate = 5; /* 5 times per second */++    /*+       poll often at the beginning for quickly finished commands,+       then back off+     */+    if (s->poll_attempts < 5) {+        rate = 20;+    } else if (s->poll_attempts < 10) {+        rate = 10;+    }++    expiration = qemu_get_clock(vm_clock) + (ticks_per_sec / rate);+    qemu_mod_timer(s->poll_timer, expiration);+    s->poll_attempts++;+}+++/*+ * The polling routine called when the 'timer interrupt' fires.+ * Tries to receive a command from the vTPM.+ */+static void tis_poll_timer(void *opaque)+{+    tpmState* s=(tpmState*)opaque;+    uint8_t locty = s->active_loc;++    if (!IS_VALID_LOC(locty) ||+        (!(s->loc[locty].inte & INT_ENABLED) &&+          (s->aborting_locty != NO_LOCALITY)) ||+        !IS_COMM_WITH_VTPM(s)) {+        /* no more interrupts requested, so no more polling needed */+        qemu_del_timer(s->poll_timer);+    }++    if (!IS_COMM_WITH_VTPM(s)) {+        if (s->aborting_locty != NO_LOCALITY) {+            tis_abort(s);+        }+        return;+    }++    if (s->aborting_locty != NO_LOCALITY) {+        int n = TPM_Receive(s, &s->buffer);+#ifdef DEBUG_TPM+        fprintf(logfile,"Receiving for abort.\n");+#endif+        if (n > 0) {+            close_vtpm_channel(s, FORCE_CLOSE);+            tis_abort(s);+#ifdef DEBUG_TPM+            fprintf(logfile,"Abort is complete.\n");+#endif+        } else {+            tis_prep_next_interrupt(s);+        }+    } else if (IS_VALID_LOC(locty)) {+        if (s->loc[locty].state == STATE_EXECUTION) {+           /* poll for result */+            int n = TPM_Receive(s, &s->buffer);+            if (n > 0) {+                s->loc[locty].sts = STS_VALID | STS_DATA_AVAILABLE;+                s->loc[locty].state = STATE_COMPLETION;+                close_vtpm_channel(s, FORCE_CLOSE);+                tis_raise_irq(s, locty, INT_DATA_AVAILABLE);+            } else {+                /* nothing received */+                tis_prep_next_interrupt(s);+            }+        }+    }+}+++static CPUReadMemoryFunc *tis_readfn[3]={+    tis_mem_readl,+    tis_mem_readl,+    tis_mem_readl+};+

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -