arch/x86/kvm/lapic.c
Source file repositories/reference/linux-study-clean/arch/x86/kvm/lapic.c
File Facts
- System
- Linux kernel
- Corpus path
arch/x86/kvm/lapic.c- Extension
.c- Size
- 98516 bytes
- Lines
- 3629
- Domain
- Architecture Layer
- Bucket
- arch/x86
- Inferred role
- Architecture Layer: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/kvm_host.hlinux/kvm.hlinux/mm.hlinux/highmem.hlinux/smp.hlinux/hrtimer.hlinux/io.hlinux/export.hlinux/math64.hlinux/slab.hasm/apic.hasm/processor.hasm/mce.hasm/msr.hasm/page.hasm/current.hasm/apicdef.hasm/delay.hlinux/atomic.hlinux/jump_label.hregs.hirq.hioapic.htrace.hx86.hxen.hcpuid.hhyperv.hsmm.h
Detected Declarations
function kvm_lapic_set_regfunction kvm_lapic_get_reg64function kvm_lapic_set_reg64function kvm_apic_pending_eoifunction kvm_lapic_advertise_suppress_eoi_broadcastfunction kvm_lapic_suppress_eoi_broadcastfunction apic_enabledfunction kvm_x2apic_idfunction kvm_can_post_timer_interruptfunction kvm_can_use_hv_timerfunction kvm_use_posted_timer_interruptfunction kvm_apic_calc_x2apic_ldrfunction kvm_apic_map_get_logical_destfunction kvm_recalculate_phys_mapfunction architecturalfunction kvm_recalculate_logical_mapfunction kvm_recalculate_apic_mapfunction registersfunction kvm_for_each_vcpufunction apic_set_spivfunction kvm_apic_set_xapic_idfunction kvm_apic_set_ldrfunction kvm_apic_set_dfrfunction kvm_apic_set_x2apic_idfunction apic_lvt_enabledfunction apic_lvtt_oneshotfunction apic_lvtt_periodfunction apic_lvtt_tscdeadlinefunction apic_lvt_nmi_modefunction kvm_lapic_lvt_supportedfunction kvm_apic_calc_nr_lvt_entriesfunction kvm_apic_set_versionfunction kvm_apic_after_set_mcg_capfunction count_vectorsfunction __kvm_apic_update_irrfunction kvm_apic_update_irrfunction apic_search_irrfunction apic_find_highest_irrfunction apic_clear_irrfunction kvm_apic_clear_irrfunction apic_set_isrfunction apic_find_highest_isrfunction apic_clear_isrfunction kvm_lapic_find_highest_irrfunction kvm_apic_set_irqfunction __pv_send_ipifunction for_each_set_bitfunction kvm_pv_send_ipi
Annotated Snippet
if (offset <= max_apic_id) {
u8 cluster_size = min(max_apic_id - offset + 1, 16U);
offset = array_index_nospec(offset, map->max_apic_id + 1);
*cluster = &map->phys_map[offset];
*mask = dest_id & (0xffff >> (16 - cluster_size));
} else {
*mask = 0;
}
return true;
}
case KVM_APIC_MODE_XAPIC_FLAT:
*cluster = map->xapic_flat_map;
*mask = dest_id & 0xff;
return true;
case KVM_APIC_MODE_XAPIC_CLUSTER:
*cluster = map->xapic_cluster_map[(dest_id >> 4) & 0xf];
*mask = dest_id & 0xf;
return true;
case KVM_APIC_MODE_MAP_DISABLED:
return false;
default:
WARN_ON_ONCE(1);
return false;
}
}
static int kvm_recalculate_phys_map(struct kvm_apic_map *new,
struct kvm_vcpu *vcpu,
bool *xapic_id_mismatch)
{
struct kvm_lapic *apic = vcpu->arch.apic;
u32 x2apic_id = kvm_x2apic_id(apic);
u32 xapic_id = kvm_xapic_id(apic);
u32 physical_id;
/*
* For simplicity, KVM always allocates enough space for all possible
* xAPIC IDs. Yell, but don't kill the VM, as KVM can continue on
* without the optimized map.
*/
if (WARN_ON_ONCE(xapic_id > new->max_apic_id))
return -EINVAL;
/*
* Bail if a vCPU was added and/or enabled its APIC between allocating
* the map and doing the actual calculations for the map. Note, KVM
* hardcodes the x2APIC ID to vcpu_id, i.e. there's no TOCTOU bug if
* the compiler decides to reload x2apic_id after this check.
*/
if (x2apic_id > new->max_apic_id)
return -E2BIG;
/*
* Deliberately truncate the vCPU ID when detecting a mismatched APIC
* ID to avoid false positives if the vCPU ID, i.e. x2APIC ID, is a
* 32-bit value. Any unwanted aliasing due to truncation results will
* be detected below.
*/
if (!apic_x2apic_mode(apic) && xapic_id != (u8)vcpu->vcpu_id)
*xapic_id_mismatch = true;
/*
* Apply KVM's hotplug hack if userspace has enable 32-bit APIC IDs.
* Allow sending events to vCPUs by their x2APIC ID even if the target
* vCPU is in legacy xAPIC mode, and silently ignore aliased xAPIC IDs
* (the x2APIC ID is truncated to 8 bits, causing IDs > 0xff to wrap
* and collide).
*
* Honor the architectural (and KVM's non-optimized) behavior if
* userspace has not enabled 32-bit x2APIC IDs. Each APIC is supposed
* to process messages independently. If multiple vCPUs have the same
* effective APIC ID, e.g. due to the x2APIC wrap or because the guest
* manually modified its xAPIC IDs, events targeting that ID are
* supposed to be recognized by all vCPUs with said ID.
*/
if (vcpu->kvm->arch.x2apic_format) {
/* See also kvm_apic_match_physical_addr(). */
if (apic_x2apic_mode(apic) || x2apic_id > 0xff)
new->phys_map[x2apic_id] = apic;
if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id])
new->phys_map[xapic_id] = apic;
} else {
/*
* Disable the optimized map if the physical APIC ID is already
* mapped, i.e. is aliased to multiple vCPUs. The optimized
* map requires a strict 1:1 mapping between IDs and vCPUs.
*/
Annotation
- Immediate include surface: `linux/kvm_host.h`, `linux/kvm.h`, `linux/mm.h`, `linux/highmem.h`, `linux/smp.h`, `linux/hrtimer.h`, `linux/io.h`, `linux/export.h`.
- Detected declarations: `function kvm_lapic_set_reg`, `function kvm_lapic_get_reg64`, `function kvm_lapic_set_reg64`, `function kvm_apic_pending_eoi`, `function kvm_lapic_advertise_suppress_eoi_broadcast`, `function kvm_lapic_suppress_eoi_broadcast`, `function apic_enabled`, `function kvm_x2apic_id`, `function kvm_can_post_timer_interrupt`, `function kvm_can_use_hv_timer`.
- Atlas domain: Architecture Layer / arch/x86.
- Implementation status: integration implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.