problem sending INIT_SIPI_SIPI through code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I am trying to execute a c program to send the INIT-SIPI-SIPI sequence to
a core after making it go offline (echo 0 > /sys/devices/system/cpu/cpu3/online). But it seems
that the program is not working because when it reads back the apic register just after writing to it
the value is not the same as what was written.Following is the code for the program. The apic id
of the core to be restarted is 5 as seen from cat /proc/cpuinfo. Please let me know if I am doing something wrong.

Thanks
- Vaibhav Jain

Code :

typedef unsigned int u32;

#define MAP_LEN                 0x1000  //4 KB page
#define BUFLEN 100
#define APIC_BASE               0xfee00000
#define APIC_ICR_low            0xfee00300
#define APIC_ICR_high           0xfee00310
#define APIC_ICR_init             0x00004500
#define APIC_ICR_start           0x00004600
#define BOUNCE_CODE        0x1000

int apic_reset_cpu(cpu);

int main()
{
  int cpu;
 
  //make sure we have root permissions
  if(iopl(3))
  {
    printf("Cannot get I/O permissions (being root helps)\n");
    return -1;
  }

  cpu = 5;
 
if ((apic_reset_cpu(cpu)) != 0)
    printf("INIT & Startup failed!\n");
 
  printf("INIT / SIPI sequence complete\n");
 
  return 0;
}


int apic_reset_cpu(int cpu)
{
  unsigned long tmpaddress, apic_icr, *apic_phy_addr;
  int fd, sleep_now=0;

   //open the main memory file
  fd = open ( "/dev/mem", O_RDWR); 

  printf("Assuming APIC physical base: %lx \n", APIC_BASE);
  tmpaddress = (unsigned long) mmap(NULL, MAP_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)APIC_BASE);
 
  if(tmpaddress == (unsigned long)MAP_FAILED) //check if it worked
  {
    perror("Mapping memory for absolute memory access failed.\n");
    return -3;
  }
 
  //prep ICR high
  apic_icr = tmpaddress;
  apic_icr +=0x310;
  apic_phy_addr = (unsigned long *) apic_icr;
  *apic_phy_addr = cpu << 24;
 
  //read the value back
   printf("\nICR high = %lx\n",*apic_phy_addr);
 
  //prep ICR low Send INIT and wait
  apic_icr = tmpaddress;
  apic_icr += 0x300;
  apic_phy_addr = (unsigned long *) apic_icr;
  *apic_phy_addr = APIC_ICR_init;
  sleep_now = usleep( 10000 ); //sleep 10 ms

  printf("\nINIT SENT\n");

//read the value back
 printf("\nICR low = %lx\n",*apic_phy_addr);

 //prep ICR high again*
  apic_icr = tmpaddress;
  apic_icr +=0x310;
  apic_phy_addr = (unsigned long *) apic_icr;
  *apic_phy_addr = cpu << 24;


  //prep for SIPI
  apic_icr = tmpaddress;
  apic_icr += 0x300;
  apic_phy_addr = (unsigned long *) apic_icr;
  *apic_phy_addr = APIC_ICR_start | (BOUNCE_CODE >> 12);
  sleep_now = usleep( 500 ); //sleep 500 usec

  printf("\nSIPI SENT\n");
 
 //read the value back
  printf("\nICR low = %lx\n",*apic_phy_addr);

  *apic_phy_addr = APIC_ICR_start | (BOUNCE_CODE >> 12);

  printf("\nSIPI SENT AGAIN\n");
 
 //read the value back
  printf("\nICR low = %lx\n",*apic_phy_addr);
  printf("Unmapping APIC Base page\n");

  tmpaddress &= 0xfffff000;
  munmap(tmpaddress, MAP_LEN); 
 
  return 0;
}
 
_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux