Search code examples
xv6

xv6: How mycpu() returns a distinct object/data for each CPU?


In xv6 rev-11, the last version of using x86 processor. In file proc.c, the function mycpu (2437) returns the current processor’s struct cpu

mycpu(void)
{
  int apicid, i;
  
  if(readeflags()&FL_IF)
    panic("mycpu called with interrupts enabled\n");
  
  apicid = lapicid();
  // APIC IDs are not guaranteed to be contiguous. Maybe we should have
  // a reverse map, or reserve a register to store &cpus[i].
  for (i = 0; i < ncpu; ++i) {
    if (cpus[i].apicid == apicid)
      return &cpus[i];
  }

I could not understand how mycpu() could return different cpu struct for different cpus, because they use the same variable lapic.

volatile uint *lapic;  // Initialized in mp.c

lapicid(void)
{
  if (!lapic)
    return 0;
  return lapic[ID] >> 24;
}

Solution

  • In x86 architectures, Each CPU's LAPIC is mapped to the same base memory address (MMIO), but each CPU is essentially accessing its own "private" view of that address, which corresponds to its own LAPIC.

    The design allows software to use a consistent memory address to communicate with the LAPIC regardless of which CPU it's running on.