lkml.org 
[lkml]   [2023]   [Apr]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRE: [RFC PATCH V4 08/17] x86/hyperv: Initialize cpu and memory for sev-snp enlightened guest
    Date
    From: Tianyu Lan <ltykernel@gmail.com> Sent: Monday, April 3, 2023 10:44 AM
    >
    > Read processor amd memory info from specific address which are
    > populated by Hyper-V. Initialize smp cpu related ops, pvalidate
    > system memory and add it into e820 table.
    >
    > Signed-off-by: Tianyu Lan <tiala@microsoft.com>
    > ---
    > arch/x86/hyperv/ivm.c | 78 +++++++++++++++++++++++++++++++++
    > arch/x86/include/asm/mshyperv.h | 16 +++++++
    > arch/x86/kernel/cpu/mshyperv.c | 3 ++
    > 3 files changed, 97 insertions(+)
    >
    > diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
    > index 368b2731950e..fa4de2761460 100644
    > --- a/arch/x86/hyperv/ivm.c
    > +++ b/arch/x86/hyperv/ivm.c
    > @@ -17,6 +17,11 @@
    > #include <asm/mem_encrypt.h>
    > #include <asm/mshyperv.h>
    > #include <asm/hypervisor.h>
    > +#include <asm/coco.h>
    > +#include <asm/io_apic.h>
    > +#include <asm/sev.h>
    > +#include <asm/realmode.h>
    > +#include <asm/e820/api.h>
    >
    > #ifdef CONFIG_AMD_MEM_ENCRYPT
    >
    > @@ -57,6 +62,22 @@ union hv_ghcb {
    >
    > static u16 hv_ghcb_version __ro_after_init;
    >
    > +static u32 processor_count;
    > +
    > +static __init void hv_snp_get_smp_config(unsigned int early)
    > +{
    > + if (!early) {
    > + while (num_processors < processor_count) {
    > + early_per_cpu(x86_cpu_to_apicid, num_processors) = num_processors;
    > + early_per_cpu(x86_bios_cpu_apicid, num_processors) = num_processors;
    > + physid_set(num_processors, phys_cpu_present_map);
    > + set_cpu_possible(num_processors, true);
    > + set_cpu_present(num_processors, true);
    > + num_processors++;
    > + }
    > + }
    > +}
    > +
    > u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
    > {
    > union hv_ghcb *hv_ghcb;
    > @@ -356,6 +377,63 @@ static bool hv_is_private_mmio(u64 addr)
    > return false;
    > }
    >
    > +__init void hv_sev_init_mem_and_cpu(void)
    > +{
    > + struct memory_map_entry *entry;
    > + struct e820_entry *e820_entry;
    > + u64 e820_end;
    > + u64 ram_end;
    > + u64 page;
    > +
    > + /*
    > + * Hyper-V enlightened snp guest boots kernel
    > + * directly without bootloader and so roms,
    > + * bios regions and reserve resources are not
    > + * available. Set these callback to NULL.
    > + */
    > + x86_platform.legacy.reserve_bios_regions = 0;
    > + x86_init.resources.probe_roms = x86_init_noop;
    > + x86_init.resources.reserve_resources = x86_init_noop;
    > + x86_init.mpparse.find_smp_config = x86_init_noop;
    > + x86_init.mpparse.get_smp_config = hv_snp_get_smp_config;
    > +
    > + /*
    > + * Hyper-V SEV-SNP enlightened guest doesn't support ioapic
    > + * and legacy APIC page read/write. Switch to hv apic here.
    > + */
    > + disable_ioapic_support();
    > +
    > + /* Read processor number and memory layout. */
    > + processor_count = *(u32 *)__va(EN_SEV_SNP_PROCESSOR_INFO_ADDR);
    > + entry = (struct memory_map_entry *)(__va(EN_SEV_SNP_PROCESSOR_INFO_ADDR)
    > + + sizeof(struct memory_map_entry));

    Why is the first map entry being skipped?

    > +
    > + /*
    > + * E820 table in the memory just describes memory for
    > + * kernel, ACPI table, cmdline, boot params and ramdisk.
    > + * Hyper-V popoulates the rest memory layout in the EN_SEV_
    > + * SNP_PROCESSOR_INFO_ADDR.
    > + */
    > + for (; entry->numpages != 0; entry++) {
    > + e820_entry = &e820_table->entries[
    > + e820_table->nr_entries - 1];
    > + e820_end = e820_entry->addr + e820_entry->size;
    > + ram_end = (entry->starting_gpn +
    > + entry->numpages) * PAGE_SIZE;
    > +
    > + if (e820_end < entry->starting_gpn * PAGE_SIZE)
    > + e820_end = entry->starting_gpn * PAGE_SIZE;
    > +
    > + if (e820_end < ram_end) {
    > + pr_info("Hyper-V: add e820 entry [mem %#018Lx-%#018Lx]\n", e820_end, ram_end - 1);
    > + e820__range_add(e820_end, ram_end - e820_end,
    > + E820_TYPE_RAM);
    > + for (page = e820_end; page < ram_end; page += PAGE_SIZE)
    > + pvalidate((unsigned long)__va(page), RMP_PG_SIZE_4K, true);
    > + }
    > + }
    > +}
    > +
    > void __init hv_vtom_init(void)
    > {
    > /*
    > diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
    > index 3c15e23162e7..a4a59007b5f2 100644
    > --- a/arch/x86/include/asm/mshyperv.h
    > +++ b/arch/x86/include/asm/mshyperv.h
    > @@ -41,6 +41,20 @@ extern bool hv_isolation_type_en_snp(void);
    >
    > extern union hv_ghcb * __percpu *hv_ghcb_pg;
    >
    > +/*
    > + * Hyper-V puts processor and memory layout info
    > + * to this address in SEV-SNP enlightened guest.
    > + */
    > +#define EN_SEV_SNP_PROCESSOR_INFO_ADDR 0x802000
    > +
    > +struct memory_map_entry {
    > + u64 starting_gpn;
    > + u64 numpages;
    > + u16 type;
    > + u16 flags;
    > + u32 reserved;
    > +};
    > +
    > int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
    > int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
    > int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);
    > @@ -246,12 +260,14 @@ void hv_ghcb_msr_read(u64 msr, u64 *value);
    > bool hv_ghcb_negotiate_protocol(void);
    > void hv_ghcb_terminate(unsigned int set, unsigned int reason);
    > void hv_vtom_init(void);
    > +void hv_sev_init_mem_and_cpu(void);
    > #else
    > static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
    > static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
    > static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
    > static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
    > static inline void hv_vtom_init(void) {}
    > +static inline void hv_sev_init_mem_and_cpu(void) {}
    > #endif
    >
    > extern bool hv_isolation_type_snp(void);
    > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
    > index 2f2dcb2370b6..71820bbf9e90 100644
    > --- a/arch/x86/kernel/cpu/mshyperv.c
    > +++ b/arch/x86/kernel/cpu/mshyperv.c
    > @@ -529,6 +529,9 @@ static void __init ms_hyperv_init_platform(void)
    > if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT))
    > mark_tsc_unstable("running on Hyper-V");
    >
    > + if (hv_isolation_type_en_snp())
    > + hv_sev_init_mem_and_cpu();

    This looks good now. Moving the code into a separate function in
    ivm.c works well.

    > +
    > hardlockup_detector_disable();
    > }
    >
    > --
    > 2.25.1

    \
     
     \ /
      Last update: 2023-04-12 16:40    [W:4.567 / U:0.156 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site