Changeset View
Standalone View
sys/amd64/amd64/mp_machdep.c
Show First 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
#include <machine/psl.h> | #include <machine/psl.h> | ||||
#include <machine/smp.h> | #include <machine/smp.h> | ||||
#include <machine/specialreg.h> | #include <machine/specialreg.h> | ||||
#include <machine/tss.h> | #include <machine/tss.h> | ||||
#include <x86/ucode.h> | #include <x86/ucode.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <x86/init.h> | #include <x86/init.h> | ||||
#include <dev/hyperv/vmbus/hyperv_var.h> | |||||
#include <dev/hyperv/vmbus/vmbus_var.h> | |||||
#ifdef DEV_ACPI | #ifdef DEV_ACPI | ||||
#include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
#include <dev/acpica/acpivar.h> | #include <dev/acpica/acpivar.h> | ||||
#endif | #endif | ||||
#define WARMBOOT_TARGET 0 | #define WARMBOOT_TARGET 0 | ||||
#define WARMBOOT_OFF (KERNBASE + 0x0467) | #define WARMBOOT_OFF (KERNBASE + 0x0467) | ||||
#define WARMBOOT_SEG (KERNBASE + 0x0469) | #define WARMBOOT_SEG (KERNBASE + 0x0469) | ||||
Show All 11 Lines | |||||
static char *doublefault_stack; | static char *doublefault_stack; | ||||
static char *mce_stack; | static char *mce_stack; | ||||
static char *nmi_stack; | static char *nmi_stack; | ||||
static char *dbg_stack; | static char *dbg_stack; | ||||
void *bootpcpu; | void *bootpcpu; | ||||
extern u_int mptramp_la57; | extern u_int mptramp_la57; | ||||
extern u_int mptramp_nx; | extern u_int mptramp_nx; | ||||
extern int hv_synic_done; | |||||
/* | /* | ||||
* Local data and functions. | * Local data and functions. | ||||
*/ | */ | ||||
static int start_ap(int apic_id, vm_paddr_t boot_address); | static int start_ap(int apic_id, vm_paddr_t boot_address); | ||||
/* | /* | ||||
* Initialize the IPI handlers and start up the AP's. | * Initialize the IPI handlers and start up the AP's. | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | cpu_mp_start(void) | ||||
assign_cpu_ids(); | assign_cpu_ids(); | ||||
mptramp_la57 = la57; | mptramp_la57 = la57; | ||||
mptramp_nx = pg_nx != 0; | mptramp_nx = pg_nx != 0; | ||||
MPASS(kernel_pmap->pm_cr3 < (1UL << 32)); | MPASS(kernel_pmap->pm_cr3 < (1UL << 32)); | ||||
mptramp_pagetables = kernel_pmap->pm_cr3; | mptramp_pagetables = kernel_pmap->pm_cr3; | ||||
/* Start each Application Processor */ | /* Start each Application Processor */ | ||||
kib: Stray change | |||||
start_all_aps(); | start_all_aps(); | ||||
set_interrupt_apic_ids(); | set_interrupt_apic_ids(); | ||||
#if defined(DEV_ACPI) && MAXMEMDOM > 1 | #if defined(DEV_ACPI) && MAXMEMDOM > 1 | ||||
acpi_pxm_set_cpu_locality(); | acpi_pxm_set_cpu_locality(); | ||||
#endif | #endif | ||||
} | } | ||||
▲ Show 20 Lines • Show All 317 Lines • ▼ Show 20 Lines | start_ap(int apic_id, vm_paddr_t boot_address) | ||||
return 0; /* return FAILURE */ | return 0; /* return FAILURE */ | ||||
} | } | ||||
/* | /* | ||||
* Flush the TLB on other CPU's | * Flush the TLB on other CPU's | ||||
*/ | */ | ||||
/* | /* | ||||
* Invalidation request. PCPU pc_smp_tlb_op uses u_int instead of the | |||||
* enum to avoid both namespace and ABI issues (with enums). | |||||
*/ | |||||
enum invl_op_codes { | |||||
INVL_OP_TLB = 1, | |||||
INVL_OP_TLB_INVPCID = 2, | |||||
INVL_OP_TLB_INVPCID_PTI = 3, | |||||
INVL_OP_TLB_PCID = 4, | |||||
INVL_OP_PGRNG = 5, | |||||
INVL_OP_PGRNG_INVPCID = 6, | |||||
INVL_OP_PGRNG_PCID = 7, | |||||
INVL_OP_PG = 8, | |||||
INVL_OP_PG_INVPCID = 9, | |||||
INVL_OP_PG_PCID = 10, | |||||
INVL_OP_CACHE = 11, | |||||
}; | |||||
kibUnsubmitted Not Done Inline ActionsThe move of the enum to pmap.h should be a separate change. kib: The move of the enum to pmap.h should be a separate change. | |||||
/* | |||||
* These variables are initialized at startup to reflect how each of | * These variables are initialized at startup to reflect how each of | ||||
* the different kinds of invalidations should be performed on the | * the different kinds of invalidations should be performed on the | ||||
* current machine and environment. | * current machine and environment. | ||||
*/ | */ | ||||
static enum invl_op_codes invl_op_tlb; | static enum invl_op_codes invl_op_tlb; | ||||
static enum invl_op_codes invl_op_pgrng; | static enum invl_op_codes invl_op_pgrng; | ||||
static enum invl_op_codes invl_op_pg; | static enum invl_op_codes invl_op_pg; | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
* Interrupts must be enabled when calling the function with smp | * Interrupts must be enabled when calling the function with smp | ||||
* started, to avoid deadlock with other IPIs that are protected with | * started, to avoid deadlock with other IPIs that are protected with | ||||
* smp_ipi_mtx spinlock at the initiator side. | * smp_ipi_mtx spinlock at the initiator side. | ||||
* | * | ||||
* Function must be called with the thread pinned, and it unpins on | * Function must be called with the thread pinned, and it unpins on | ||||
* completion. | * completion. | ||||
*/ | */ | ||||
static void | static void | ||||
smp_targeted_tlb_shootdown(pmap_t pmap, vm_offset_t addr1, vm_offset_t addr2, | smp_targeted_tlb_shootdown(pmap_t pmap, vm_offset_t addr1, vm_offset_t addr2, | ||||
Not Done Inline ActionsI suggest you to convert this function ifunc and provide a complete separate implementation for hyperv. Not last because now kernel cannot be compiled without hyperv support. kib: I suggest you to convert this function ifunc and provide a complete separate implementation for… | |||||
Not Done Inline ActionsStill not fixed. Now I think ifunc would not help. Instead, you need e.g. a pointer to system smp_targeted_tlb_shootdown function, inited by our mp_machdep.c for normal IPIs, and set to HyperV method on HyperV. As is this cannot be merged, unconditional dependency of kernel on hyperv code is not a way forward. kib: Still not fixed. Now I think ifunc would not help. Instead, you need e.g. a pointer to system… | |||||
Not Done Inline ActionsI have tried with function pointer, but the system is hitting panic: Please let me know, where should it be initialized. The trace : Booting [/boot/kernel/kernel]... Fatal trap 12: page fault while in kernel mode = DPL 0, pres 1, long 1, def32 0, gran 1 processor eflags = resume, IOPL = 0 schakrabarti_microsoft.com: I have tried with function pointer, but the system is hitting panic:
I have commented hyper-v… | |||||
smp_invl_cb_t curcpu_cb, enum invl_op_codes op) | smp_invl_cb_t curcpu_cb, enum invl_op_codes op) | ||||
Done Inline ActionsWhy do you call it legacy? It is anything but legacy. kib: Why do you call it legacy? It is anything but legacy. | |||||
{ | { | ||||
cpuset_t mask; | cpuset_t mask, pv_cpu_mask; | ||||
uint32_t generation, *p_cpudone; | uint32_t generation, *p_cpudone; | ||||
int cpu; | int cpu; | ||||
bool is_all; | bool is_all; | ||||
/* | /* | ||||
* It is not necessary to signal other CPUs while booting or | * It is not necessary to signal other CPUs while booting or | ||||
* when in the debugger. | * when in the debugger. | ||||
*/ | */ | ||||
if (__predict_false(kdb_active || KERNEL_PANICKED() || !smp_started)) | if (__predict_false(kdb_active || KERNEL_PANICKED() || !smp_started)) | ||||
goto local_cb; | goto local_cb; | ||||
KASSERT(curthread->td_pinned > 0, ("curthread not pinned")); | KASSERT(curthread->td_pinned > 0, ("curthread not pinned")); | ||||
/* | /* | ||||
* Make a stable copy of the set of CPUs on which the pmap is active. | * Make a stable copy of the set of CPUs on which the pmap is active. | ||||
* See if we have to interrupt other CPUs. | * See if we have to interrupt other CPUs. | ||||
*/ | */ | ||||
CPU_COPY(pmap_invalidate_cpu_mask(pmap), &mask); | CPU_COPY(pmap_invalidate_cpu_mask(pmap), &mask); | ||||
CPU_COPY(&mask, &pv_cpu_mask); | |||||
is_all = CPU_CMP(&mask, &all_cpus) == 0; | is_all = CPU_CMP(&mask, &all_cpus) == 0; | ||||
CPU_CLR(curcpu, &mask); | CPU_CLR(curcpu, &mask); | ||||
if (CPU_EMPTY(&mask)) | if (CPU_EMPTY(&mask)) | ||||
goto local_cb; | goto local_cb; | ||||
/* | /* | ||||
* Initiator must have interrupts enabled, which prevents | * Initiator must have interrupts enabled, which prevents | ||||
* non-invalidation IPIs that take smp_ipi_mtx spinlock, | * non-invalidation IPIs that take smp_ipi_mtx spinlock, | ||||
* from deadlocking with us. On the other hand, preemption | * from deadlocking with us. On the other hand, preemption | ||||
* must be disabled to pin initiator to the instance of the | * must be disabled to pin initiator to the instance of the | ||||
* pcpu pc_smp_tlb data and scoreboard line. | * pcpu pc_smp_tlb data and scoreboard line. | ||||
*/ | */ | ||||
KASSERT((read_rflags() & PSL_I) != 0, | KASSERT((read_rflags() & PSL_I) != 0, | ||||
("smp_targeted_tlb_shootdown: interrupts disabled")); | ("smp_targeted_tlb_shootdown: interrupts disabled")); | ||||
critical_enter(); | critical_enter(); | ||||
if (vm_guest == VM_GUEST_HV && hv_synic_done) { | |||||
if(hv_vm_tlb_flush_dummy(pmap, addr1, addr2, pv_cpu_mask, op) != 0) | |||||
goto tlb_nopv; | |||||
goto hv_end; | |||||
} | |||||
tlb_nopv: | |||||
PCPU_SET(smp_tlb_addr1, addr1); | PCPU_SET(smp_tlb_addr1, addr1); | ||||
PCPU_SET(smp_tlb_addr2, addr2); | PCPU_SET(smp_tlb_addr2, addr2); | ||||
PCPU_SET(smp_tlb_pmap, pmap); | PCPU_SET(smp_tlb_pmap, pmap); | ||||
generation = PCPU_GET(smp_tlb_gen); | generation = PCPU_GET(smp_tlb_gen); | ||||
if (++generation == 0) | if (++generation == 0) | ||||
generation = 1; | generation = 1; | ||||
PCPU_SET(smp_tlb_gen, generation); | PCPU_SET(smp_tlb_gen, generation); | ||||
PCPU_SET(smp_tlb_op, op); | PCPU_SET(smp_tlb_op, op); | ||||
Show All 24 Lines | while (atomic_load_int(p_cpudone) != generation) | ||||
ia32_pause(); | ia32_pause(); | ||||
} | } | ||||
/* | /* | ||||
* Unpin before leaving critical section. If the thread owes | * Unpin before leaving critical section. If the thread owes | ||||
* preemption, this allows scheduler to select thread on any | * preemption, this allows scheduler to select thread on any | ||||
* CPU from its cpuset. | * CPU from its cpuset. | ||||
*/ | */ | ||||
hv_end: | |||||
sched_unpin(); | sched_unpin(); | ||||
critical_exit(); | critical_exit(); | ||||
return; | return; | ||||
local_cb: | local_cb: | ||||
critical_enter(); | critical_enter(); | ||||
curcpu_cb(pmap, addr1, addr2); | curcpu_cb(pmap, addr1, addr2); | ||||
▲ Show 20 Lines • Show All 396 Lines • Show Last 20 Lines |
Stray change