+static u32 processor_count;Folks, please minimize indentation:
+
+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++;
+ }
+ }
+}
if (early)
return;
It would also be nice to see*some* explanation in the changelog or
comments about why it's best and correct to just do nothing if early==1.
Also, this_consumes_ data from hv_sev_init_mem_and_cpu(). It would
make more sense to me to have them ordered the other way.
hv_sev_init_mem_and_cpu() first, this second.
u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)This is one of those places that vertical alignment adds clarity:
{
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;
+ x86_init.resources.probe_roms = x86_init_noop;See? 3 noops and only one actual implemented function. Clear as day now.
+ 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 ioapicDo these systems have X86_FEATURE_APIC set? Why is this needed in
+ * and legacy APIC page read/write. Switch to hv apic here.
+ */
+ disable_ioapic_support();
addition to the architectural enumeration that already exists?
Is there any other place in the kernel that has this one-off disabling
of the APIC?
+ /* Read processor number and memory layout. */Ick.
+ 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));
There are a lot of ways to do this. But, this is an awfully ugly way.
struct snp_processor_info {
u32 processor_count;
struct memory_map_entry[] entries;
}
struct snp_processor_info *snp_pi =
__va(EN_SEV_SNP_PROCESSOR_INFO_ADDR);
processor_count = snp_pi->processor_count;
Then, have your for() loop through snp_pi->entries;
Actually, I'm not_quite_ sure that processor_count and entries are next
to each other. But, either way, I do think a struct makes sense.
Also, what guarantees that EN_SEV_SNP_PROCESSOR_INFO_ADDR is mapped?
It's up above 8MB which I don't remember off the top of my head as being
a special address.
+ /*Really? That is not very cool. We need a better explanation of why
+ * 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.
+ */
there was no way to use the decades-old e820 or EFI memory map and why
this needs to be a special snowflake.
+ for (; entry->numpages != 0; entry++) {Oh, is this just about having a pre-accepted area and a non-accepted
+ 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);
+ }
+ }
+}
area? Is this basically another one-off implementation of unaccepted
memory ... that doesn't use the EFI standard?