Commit ffab1be7 authored by Marc-André Lureau's avatar Marc-André Lureau Committed by Michael S. Tsirkin
Browse files

tpm: clear RAM when "memory overwrite" requested



Note: the "Platform Reset Attack Mitigation" specification isn't
explicit about NVDIMM, since they could have different usages. It uses
the term "system memory" generally (and also "volatile memory RAM" in
its introduction). For initial support, I propose to consider
non-volatile memory as not being subject to the memory clear. There is
an on-going discussion in the TCG "pcclientwg" working group for
future revisions.

CPU cache clearing is done unconditionally in edk2 since commit
d20ae95a13e851 (edk2-stable201811).

Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Tested-by: default avatarStefan Berger <stefanb@linux.ibm.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent ec86c0f6
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -233,6 +233,9 @@ static void tpm_crb_reset(void *dev)
{
    CRBState *s = CRB(dev);

    if (s->ppi_enabled) {
        tpm_ppi_reset(&s->ppi);
    }
    tpm_backend_reset(s->tpmbe);

    memset(s->regs, 0, sizeof(s->regs));
+22 −0
Original line number Diff line number Diff line
@@ -16,8 +16,30 @@
#include "qapi/error.h"
#include "cpu.h"
#include "sysemu/memory_mapping.h"
#include "sysemu/reset.h"
#include "migration/vmstate.h"
#include "tpm_ppi.h"
#include "trace.h"

void tpm_ppi_reset(TPMPPI *tpmppi)
{
    if (tpmppi->buf[0x15a /* movv, docs/specs/tpm.txt */] & 0x1) {
        GuestPhysBlockList guest_phys_blocks;
        GuestPhysBlock *block;

        guest_phys_blocks_init(&guest_phys_blocks);
        guest_phys_blocks_append(&guest_phys_blocks);
        QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) {
            trace_tpm_ppi_memset(block->host_addr,
                                 block->target_end - block->target_start);
            memset(block->host_addr, 0,
                   block->target_end - block->target_start);
            memory_region_set_dirty(block->mr, 0,
                                    block->target_end - block->target_start);
        }
        guest_phys_blocks_free(&guest_phys_blocks);
    }
}

void tpm_ppi_init(TPMPPI *tpmppi, struct MemoryRegion *m,
                  hwaddr addr, Object *obj)
+10 −0
Original line number Diff line number Diff line
@@ -33,4 +33,14 @@ typedef struct TPMPPI {
void tpm_ppi_init(TPMPPI *tpmppi, struct MemoryRegion *m,
                  hwaddr addr, Object *obj);

/**
 * tpm_ppi_reset:
 * @tpmppi: a TPMPPI
 *
 * Function to call on machine reset. It will check if the "Memory
 * overwrite" variable is set, and perform a memory clear on volatile
 * memory if requested.
 **/
void tpm_ppi_reset(TPMPPI *tpmppi);

#endif /* TPM_TPM_PPI_H */
+3 −0
Original line number Diff line number Diff line
@@ -872,6 +872,9 @@ static void tpm_tis_reset(DeviceState *dev)
    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),
                            TPM_TIS_BUFFER_MAX);

    if (s->ppi_enabled) {
        tpm_ppi_reset(&s->ppi);
    }
    tpm_backend_reset(s->be_driver);

    s->active_locty = TPM_TIS_NO_LOCALITY;
+3 −0
Original line number Diff line number Diff line
@@ -51,3 +51,6 @@ tpm_tis_mmio_write_init_abort(void) "Initiating abort"
tpm_tis_mmio_write_lowering_irq(void) "Lowering IRQ"
tpm_tis_mmio_write_data2send(uint32_t value, unsigned size) "Data to send to TPM: 0x%08x (size=%d)"
tpm_tis_pre_save(uint8_t locty, uint32_t rw_offset) "locty: %d, rw_offset = %u"

# hw/tpm/tpm_ppi.c
tpm_ppi_memset(uint8_t *ptr, size_t size) "memset: %p %zu"