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