16842bc34SLaurent Vivier /* 26842bc34SLaurent Vivier * processor control and status function 3b1a6fd7dSThomas Huth * 4b1a6fd7dSThomas Huth * This code is free software; you can redistribute it and/or modify it 5b1a6fd7dSThomas Huth * under the terms of the GNU Library General Public License version 2. 66842bc34SLaurent Vivier */ 76842bc34SLaurent Vivier 86842bc34SLaurent Vivier #include <libcflat.h> 96842bc34SLaurent Vivier #include <asm/processor.h> 106842bc34SLaurent Vivier #include <asm/ptrace.h> 11f4d8d939SSuraj Jitindar Singh #include <asm/setup.h> 12f4d8d939SSuraj Jitindar Singh #include <asm/barrier.h> 13*ba33a96fSNicholas Piggin #include <asm/hcall.h> 14*ba33a96fSNicholas Piggin #include <asm/handlers.h> 156842bc34SLaurent Vivier 166842bc34SLaurent Vivier static struct { 176842bc34SLaurent Vivier void (*func)(struct pt_regs *, void *data); 186842bc34SLaurent Vivier void *data; 196842bc34SLaurent Vivier } handlers[16]; 206842bc34SLaurent Vivier 216842bc34SLaurent Vivier void handle_exception(int trap, void (*func)(struct pt_regs *, void *), 226842bc34SLaurent Vivier void * data) 236842bc34SLaurent Vivier { 245d571097SNicholas Piggin assert(!(trap & ~0xf00)); 255d571097SNicholas Piggin 266842bc34SLaurent Vivier trap >>= 8; 276842bc34SLaurent Vivier 285d571097SNicholas Piggin if (func && handlers[trap].func) { 295d571097SNicholas Piggin printf("exception handler installed twice %#x\n", trap); 305d571097SNicholas Piggin abort(); 315d571097SNicholas Piggin } 326842bc34SLaurent Vivier handlers[trap].func = func; 336842bc34SLaurent Vivier handlers[trap].data = data; 346842bc34SLaurent Vivier } 356842bc34SLaurent Vivier 366842bc34SLaurent Vivier void do_handle_exception(struct pt_regs *regs) 376842bc34SLaurent Vivier { 386842bc34SLaurent Vivier unsigned char v; 396842bc34SLaurent Vivier 406842bc34SLaurent Vivier v = regs->trap >> 8; 416842bc34SLaurent Vivier 426842bc34SLaurent Vivier if (v < 16 && handlers[v].func) { 436842bc34SLaurent Vivier handlers[v].func(regs, handlers[v].data); 446842bc34SLaurent Vivier return; 456842bc34SLaurent Vivier } 466842bc34SLaurent Vivier 478e458b76SNicholas Piggin printf("unhandled cpu exception %#lx at NIA:0x%016lx MSR:0x%016lx\n", regs->trap, regs->nip, regs->msr); 486842bc34SLaurent Vivier abort(); 496842bc34SLaurent Vivier } 50f4d8d939SSuraj Jitindar Singh 51f4d8d939SSuraj Jitindar Singh void delay(uint64_t cycles) 52f4d8d939SSuraj Jitindar Singh { 53f4d8d939SSuraj Jitindar Singh uint64_t start = get_tb(); 54f4d8d939SSuraj Jitindar Singh 55f4d8d939SSuraj Jitindar Singh while ((get_tb() - start) < cycles) 56f4d8d939SSuraj Jitindar Singh cpu_relax(); 57f4d8d939SSuraj Jitindar Singh } 58f4d8d939SSuraj Jitindar Singh 59f4d8d939SSuraj Jitindar Singh void udelay(uint64_t us) 60f4d8d939SSuraj Jitindar Singh { 61f4d8d939SSuraj Jitindar Singh delay((us * tb_hz) / 1000000); 62f4d8d939SSuraj Jitindar Singh } 63*ba33a96fSNicholas Piggin 64*ba33a96fSNicholas Piggin void sleep_tb(uint64_t cycles) 65*ba33a96fSNicholas Piggin { 66*ba33a96fSNicholas Piggin uint64_t start, end, now; 67*ba33a96fSNicholas Piggin 68*ba33a96fSNicholas Piggin start = now = get_tb(); 69*ba33a96fSNicholas Piggin end = start + cycles; 70*ba33a96fSNicholas Piggin 71*ba33a96fSNicholas Piggin while (end > now) { 72*ba33a96fSNicholas Piggin uint64_t left = end - now; 73*ba33a96fSNicholas Piggin 74*ba33a96fSNicholas Piggin /* TODO: Could support large decrementer */ 75*ba33a96fSNicholas Piggin if (left > 0x7fffffff) 76*ba33a96fSNicholas Piggin left = 0x7fffffff; 77*ba33a96fSNicholas Piggin 78*ba33a96fSNicholas Piggin /* DEC won't fire until H_CEDE is called because EE=0 */ 79*ba33a96fSNicholas Piggin asm volatile ("mtdec %0" : : "r" (left)); 80*ba33a96fSNicholas Piggin handle_exception(0x900, &dec_handler_oneshot, NULL); 81*ba33a96fSNicholas Piggin /* 82*ba33a96fSNicholas Piggin * H_CEDE is called with MSR[EE] clear and enables it as part 83*ba33a96fSNicholas Piggin * of the hcall, returning with EE enabled. The dec interrupt 84*ba33a96fSNicholas Piggin * is then taken immediately and the handler disables EE. 85*ba33a96fSNicholas Piggin * 86*ba33a96fSNicholas Piggin * If H_CEDE returned for any other interrupt than dec 87*ba33a96fSNicholas Piggin * expiring, that is considered an unhandled interrupt and 88*ba33a96fSNicholas Piggin * the test case would be stopped. 89*ba33a96fSNicholas Piggin */ 90*ba33a96fSNicholas Piggin if (hcall(H_CEDE) != H_SUCCESS) { 91*ba33a96fSNicholas Piggin printf("H_CEDE failed\n"); 92*ba33a96fSNicholas Piggin abort(); 93*ba33a96fSNicholas Piggin } 94*ba33a96fSNicholas Piggin handle_exception(0x900, NULL, NULL); 95*ba33a96fSNicholas Piggin 96*ba33a96fSNicholas Piggin now = get_tb(); 97*ba33a96fSNicholas Piggin } 98*ba33a96fSNicholas Piggin } 99*ba33a96fSNicholas Piggin 100*ba33a96fSNicholas Piggin void usleep(uint64_t us) 101*ba33a96fSNicholas Piggin { 102*ba33a96fSNicholas Piggin sleep_tb((us * tb_hz) / 1000000); 103*ba33a96fSNicholas Piggin } 104