Message ID | 20230818095041.1973309-33-xiaoyao.li@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | TDX QEMU support | expand |
On Fri, Aug 18, 2023 at 05:50:15AM -0400, Xiaoyao Li wrote: > The RAM of TDX VM can be classified into two types: > > - TDX_RAM_UNACCEPTED: default type of TDX memory, which needs to be > accepted by TDX guest before it can be used and will be all-zeros > after being accepted. > > - TDX_RAM_ADDED: the RAM that is ADD'ed to TD guest before running, and > can be used directly. E.g., TD HOB and TEMP MEM that needed by TDVF. > > Maintain TdxRamEntries[] which grabs the initial RAM info from e820 table > and mark each RAM range as default type TDX_RAM_UNACCEPTED. > > Then turn the range of TD HOB and TEMP MEM to TDX_RAM_ADDED since these > ranges will be ADD'ed before TD runs and no need to be accepted runtime. > > The TdxRamEntries[] are later used to setup the memory TD resource HOB > that passes memory info from QEMU to TDVF. > > Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> > Acked-by: Gerd Hoffmann <kraxel@redhat.com> > > --- > Changes from RFC v4: > - simplify the algorithm of tdx_accept_ram_range() (Suggested-by: Gerd Hoffman) > (1) Change the existing entry to cover the accepted ram range. > (2) If there is room before the accepted ram range add a > TDX_RAM_UNACCEPTED entry for that. > (3) If there is room after the accepted ram range add a > TDX_RAM_UNACCEPTED entry for that. > --- > target/i386/kvm/tdx.c | 110 ++++++++++++++++++++++++++++++++++++++++++ > target/i386/kvm/tdx.h | 14 ++++++ > 2 files changed, 124 insertions(+) > > diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c > index bb806736b4ff..ed617ebab266 100644 > --- a/target/i386/kvm/tdx.c > +++ b/target/i386/kvm/tdx.c > +static int tdx_accept_ram_range(uint64_t address, uint64_t length) > +{ > + uint64_t head_start, tail_start, head_length, tail_length; > + uint64_t tmp_address, tmp_length; > + TdxRamEntry *e; > + int i; > + > + for (i = 0; i < tdx_guest->nr_ram_entries; i++) { > + e = &tdx_guest->ram_entries[i]; > + > + if (address + length <= e->address || > + e->address + e->length <= address) { > + continue; Indented too far > + } > + > + /* > + * The to-be-accepted ram range must be fully contained by one > + * RAM entry. > + */ > + if (e->address > address || > + e->address + e->length < address + length) { > + return -EINVAL; > + } > + > + if (e->type == TDX_RAM_ADDED) { > + return -EINVAL; > + } > + > + break; > + } > + > + if (i == tdx_guest->nr_ram_entries) { > + return -1; > + } > + > + tmp_address = e->address; > + tmp_length = e->length; > + > + e->address = address; > + e->length = length; > + e->type = TDX_RAM_ADDED; > + > + head_length = address - tmp_address; > + if (head_length > 0) { > + head_start = tmp_address; > + tdx_add_ram_entry(head_start, head_length, TDX_RAM_UNACCEPTED); > + } > + > + tail_start = address + length; > + if (tail_start < tmp_address + tmp_length) { > + tail_length = tmp_address + tmp_length - tail_start; > + tdx_add_ram_entry(tail_start, tail_length, TDX_RAM_UNACCEPTED); > + } > + > + return 0; > +} With regards, Daniel
On Fri, Aug 18, 2023 at 05:50:15AM -0400, Xiaoyao Li <xiaoyao.li@intel.com> wrote: > diff --git a/target/i386/kvm/tdx.h b/target/i386/kvm/tdx.h > index e9d2888162ce..9b3c427766ef 100644 > --- a/target/i386/kvm/tdx.h > +++ b/target/i386/kvm/tdx.h > @@ -15,6 +15,17 @@ typedef struct TdxGuestClass { > ConfidentialGuestSupportClass parent_class; > } TdxGuestClass; > > +enum TdxRamType{ > + TDX_RAM_UNACCEPTED, > + TDX_RAM_ADDED, > +}; > + > +typedef struct TdxRamEntry { > + uint64_t address; > + uint64_t length; > + uint32_t type; nitpick: enum TdxRamType. and related function arguments.
On 8/21/2023 5:38 PM, Daniel P. Berrangé wrote: >> diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c >> index bb806736b4ff..ed617ebab266 100644 >> --- a/target/i386/kvm/tdx.c >> +++ b/target/i386/kvm/tdx.c >> +static int tdx_accept_ram_range(uint64_t address, uint64_t length) >> +{ >> + uint64_t head_start, tail_start, head_length, tail_length; >> + uint64_t tmp_address, tmp_length; >> + TdxRamEntry *e; >> + int i; >> + >> + for (i = 0; i < tdx_guest->nr_ram_entries; i++) { >> + e = &tdx_guest->ram_entries[i]; >> + >> + if (address + length <= e->address || >> + e->address + e->length <= address) { >> + continue; > Indented too far > Fixed. Thanks! -Xiaoyao
On 8/22/2023 7:40 AM, Isaku Yamahata wrote: > On Fri, Aug 18, 2023 at 05:50:15AM -0400, > Xiaoyao Li <xiaoyao.li@intel.com> wrote: > >> diff --git a/target/i386/kvm/tdx.h b/target/i386/kvm/tdx.h >> index e9d2888162ce..9b3c427766ef 100644 >> --- a/target/i386/kvm/tdx.h >> +++ b/target/i386/kvm/tdx.h >> @@ -15,6 +15,17 @@ typedef struct TdxGuestClass { >> ConfidentialGuestSupportClass parent_class; >> } TdxGuestClass; >> >> +enum TdxRamType{ >> + TDX_RAM_UNACCEPTED, >> + TDX_RAM_ADDED, >> +}; >> + >> +typedef struct TdxRamEntry { >> + uint64_t address; >> + uint64_t length; >> + uint32_t type; > > nitpick: enum TdxRamType. and related function arguments. > Will do it. Thanks!
diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index bb806736b4ff..ed617ebab266 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -22,6 +22,7 @@ #include "exec/address-spaces.h" #include "exec/ramblock.h" +#include "hw/i386/e820_memory_layout.h" #include "hw/i386/x86.h" #include "hw/i386/tdvf.h" #include "kvm_i386.h" @@ -454,11 +455,116 @@ static void update_tdx_cpuid_lookup_by_tdx_caps(void) (tdx_caps->xfam_fixed1 & CPUID_XSTATE_XSS_MASK) >> 32; } +static void tdx_add_ram_entry(uint64_t address, uint64_t length, uint32_t type) +{ + uint32_t nr_entries = tdx_guest->nr_ram_entries; + tdx_guest->ram_entries = g_renew(TdxRamEntry, tdx_guest->ram_entries, + nr_entries + 1); + + tdx_guest->ram_entries[nr_entries].address = address; + tdx_guest->ram_entries[nr_entries].length = length; + tdx_guest->ram_entries[nr_entries].type = type; + tdx_guest->nr_ram_entries++; +} + +static int tdx_accept_ram_range(uint64_t address, uint64_t length) +{ + uint64_t head_start, tail_start, head_length, tail_length; + uint64_t tmp_address, tmp_length; + TdxRamEntry *e; + int i; + + for (i = 0; i < tdx_guest->nr_ram_entries; i++) { + e = &tdx_guest->ram_entries[i]; + + if (address + length <= e->address || + e->address + e->length <= address) { + continue; + } + + /* + * The to-be-accepted ram range must be fully contained by one + * RAM entry. + */ + if (e->address > address || + e->address + e->length < address + length) { + return -EINVAL; + } + + if (e->type == TDX_RAM_ADDED) { + return -EINVAL; + } + + break; + } + + if (i == tdx_guest->nr_ram_entries) { + return -1; + } + + tmp_address = e->address; + tmp_length = e->length; + + e->address = address; + e->length = length; + e->type = TDX_RAM_ADDED; + + head_length = address - tmp_address; + if (head_length > 0) { + head_start = tmp_address; + tdx_add_ram_entry(head_start, head_length, TDX_RAM_UNACCEPTED); + } + + tail_start = address + length; + if (tail_start < tmp_address + tmp_length) { + tail_length = tmp_address + tmp_length - tail_start; + tdx_add_ram_entry(tail_start, tail_length, TDX_RAM_UNACCEPTED); + } + + return 0; +} + +static int tdx_ram_entry_compare(const void *lhs_, const void* rhs_) +{ + const TdxRamEntry *lhs = lhs_; + const TdxRamEntry *rhs = rhs_; + + if (lhs->address == rhs->address) { + return 0; + } + if (le64_to_cpu(lhs->address) > le64_to_cpu(rhs->address)) { + return 1; + } + return -1; +} + +static void tdx_init_ram_entries(void) +{ + unsigned i, j, nr_e820_entries; + + nr_e820_entries = e820_get_num_entries(); + tdx_guest->ram_entries = g_new(TdxRamEntry, nr_e820_entries); + + for (i = 0, j = 0; i < nr_e820_entries; i++) { + uint64_t addr, len; + + if (e820_get_entry(i, E820_RAM, &addr, &len)) { + tdx_guest->ram_entries[j].address = addr; + tdx_guest->ram_entries[j].length = len; + tdx_guest->ram_entries[j].type = TDX_RAM_UNACCEPTED; + j++; + } + } + tdx_guest->nr_ram_entries = j; +} + static void tdx_finalize_vm(Notifier *notifier, void *unused) { TdxFirmware *tdvf = &tdx_guest->tdvf; TdxFirmwareEntry *entry; + tdx_init_ram_entries(); + for_each_tdx_fw_entry(tdvf, entry) { switch (entry->type) { case TDVF_SECTION_TYPE_BFV: @@ -469,12 +575,16 @@ static void tdx_finalize_vm(Notifier *notifier, void *unused) case TDVF_SECTION_TYPE_TEMP_MEM: entry->mem_ptr = qemu_ram_mmap(-1, entry->size, qemu_real_host_page_size(), 0, 0); + tdx_accept_ram_range(entry->address, entry->size); break; default: error_report("Unsupported TDVF section %d", entry->type); exit(1); } } + + qsort(tdx_guest->ram_entries, tdx_guest->nr_ram_entries, + sizeof(TdxRamEntry), &tdx_ram_entry_compare); } static Notifier tdx_machine_done_notify = { diff --git a/target/i386/kvm/tdx.h b/target/i386/kvm/tdx.h index e9d2888162ce..9b3c427766ef 100644 --- a/target/i386/kvm/tdx.h +++ b/target/i386/kvm/tdx.h @@ -15,6 +15,17 @@ typedef struct TdxGuestClass { ConfidentialGuestSupportClass parent_class; } TdxGuestClass; +enum TdxRamType{ + TDX_RAM_UNACCEPTED, + TDX_RAM_ADDED, +}; + +typedef struct TdxRamEntry { + uint64_t address; + uint64_t length; + uint32_t type; +} TdxRamEntry; + typedef struct TdxGuest { ConfidentialGuestSupport parent_obj; @@ -27,6 +38,9 @@ typedef struct TdxGuest { uint8_t mrownerconfig[48]; /* sha348 digest */ TdxFirmware tdvf; + + uint32_t nr_ram_entries; + TdxRamEntry *ram_entries; } TdxGuest; #ifdef CONFIG_TDX