From: Tianyu Lan <ltykernel@xxxxxxxxx> Sent: Saturday, January 21, 2023 6:46 PM > > 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@xxxxxxxxxxxxx> > --- > arch/x86/kernel/cpu/mshyperv.c | 85 ++++++++++++++++++++++++++++++++++ > 1 file changed, 85 insertions(+) > > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c > index ace5901ba0fc..b1871a7bb4c9 100644 > --- a/arch/x86/kernel/cpu/mshyperv.c > +++ b/arch/x86/kernel/cpu/mshyperv.c > @@ -32,6 +32,12 @@ > #include <asm/nmi.h> > #include <clocksource/hyperv_timer.h> > #include <asm/numa.h> > +#include <asm/coco.h> > +#include <asm/io_apic.h> > +#include <asm/svm.h> > +#include <asm/sev.h> > +#include <asm/realmode.h> > +#include <asm/e820/api.h> > > /* Is Linux running as the root partition? */ > bool hv_root_partition; > @@ -251,6 +257,30 @@ static void __init hv_smp_prepare_cpus(unsigned int max_cpus) > } > #endif > > +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++; > + } > + } > +} > + > +struct memory_map_entry { > + u64 starting_gpn; > + u64 numpages; > + u16 type; > + u16 flags; > + u32 reserved; > +}; Am I correct that this structure is defined by Hyper-V? If so, it seems like it should go in hyperv-tlfs.h, along with the definition of EN_SEV_SNP_PROCESSOR_INFO_ADDR (which is also defined by Hyper-V?) > + > static void __init ms_hyperv_init_platform(void) > { > int hv_max_functions_eax; > @@ -258,6 +288,11 @@ static void __init ms_hyperv_init_platform(void) > int hv_host_info_ebx; > int hv_host_info_ecx; > int hv_host_info_edx; > + struct memory_map_entry *entry; > + struct e820_entry *e820_entry; > + u64 e820_end; > + u64 ram_end; > + u64 page; > > #ifdef CONFIG_PARAVIRT > pv_info.name = "Hyper-V"; > @@ -466,6 +501,56 @@ static void __init ms_hyperv_init_platform(void) > if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT)) > mark_tsc_unstable("running on Hyper-V"); > > + if (isolation_type_en_snp()) { The above doesn't compile. The function name is hv_isolation_type_en_snp(). > + /* > + * 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 = x86_init_noop; > + 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)); > + > + /* > + * 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); > + } > + } > + } > + For SNP vTOM mode, most of the supporting code is placed in arch/x86/hyperv/ivm.c, which is built only if CONFIG_HYPERV is defined. arch/x86/kernel/cpu/mshyperv.c is built for *any* flavor of guest (i.e., CONFIG_HYPERVISOR_GUEST). I'm thinking all this code should go as a supporting function in ivm.c, to avoid overloading mshyperv.c. Take a look at how hv_vtom_init() is handled in my patch set. Breaking it out as a separate supporting function might also help reduce the deep indentation problem a bit. :-) > hardlockup_detector_disable(); > } > > -- > 2.25.1