Commit 20c9f095c4536e64e60432a5c72fce38e8306cbb
1 parent
8d05ea8a
Implement Sparc64 CPU timers using ptimers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2860 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
100 additions
and
8 deletions
Makefile.target
| @@ -445,7 +445,7 @@ ifeq ($(TARGET_BASE_ARCH), sparc) | @@ -445,7 +445,7 @@ ifeq ($(TARGET_BASE_ARCH), sparc) | ||
| 445 | ifeq ($(TARGET_ARCH), sparc64) | 445 | ifeq ($(TARGET_ARCH), sparc64) |
| 446 | VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o | 446 | VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o |
| 447 | VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o | 447 | VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o |
| 448 | -VL_OBJS+= cirrus_vga.o parallel.o | 448 | +VL_OBJS+= cirrus_vga.o parallel.o ptimer.o |
| 449 | else | 449 | else |
| 450 | VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o | 450 | VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o |
| 451 | VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o | 451 | VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o |
hw/sun4u.c
| @@ -282,7 +282,35 @@ void qemu_system_powerdown(void) | @@ -282,7 +282,35 @@ void qemu_system_powerdown(void) | ||
| 282 | static void main_cpu_reset(void *opaque) | 282 | static void main_cpu_reset(void *opaque) |
| 283 | { | 283 | { |
| 284 | CPUState *env = opaque; | 284 | CPUState *env = opaque; |
| 285 | + | ||
| 285 | cpu_reset(env); | 286 | cpu_reset(env); |
| 287 | + ptimer_set_limit(env->tick, 0x7fffffffffffffffULL, 1); | ||
| 288 | + ptimer_run(env->tick, 0); | ||
| 289 | + ptimer_set_limit(env->stick, 0x7fffffffffffffffULL, 1); | ||
| 290 | + ptimer_run(env->stick, 0); | ||
| 291 | + ptimer_set_limit(env->hstick, 0x7fffffffffffffffULL, 1); | ||
| 292 | + ptimer_run(env->hstick, 0); | ||
| 293 | +} | ||
| 294 | + | ||
| 295 | +void tick_irq(void *opaque) | ||
| 296 | +{ | ||
| 297 | + CPUState *env = opaque; | ||
| 298 | + | ||
| 299 | + cpu_interrupt(env, CPU_INTERRUPT_TIMER); | ||
| 300 | +} | ||
| 301 | + | ||
| 302 | +void stick_irq(void *opaque) | ||
| 303 | +{ | ||
| 304 | + CPUState *env = opaque; | ||
| 305 | + | ||
| 306 | + cpu_interrupt(env, CPU_INTERRUPT_TIMER); | ||
| 307 | +} | ||
| 308 | + | ||
| 309 | +void hstick_irq(void *opaque) | ||
| 310 | +{ | ||
| 311 | + CPUState *env = opaque; | ||
| 312 | + | ||
| 313 | + cpu_interrupt(env, CPU_INTERRUPT_TIMER); | ||
| 286 | } | 314 | } |
| 287 | 315 | ||
| 288 | static const int ide_iobase[2] = { 0x1f0, 0x170 }; | 316 | static const int ide_iobase[2] = { 0x1f0, 0x170 }; |
| @@ -311,6 +339,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, | @@ -311,6 +339,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, | ||
| 311 | long prom_offset, initrd_size, kernel_size; | 339 | long prom_offset, initrd_size, kernel_size; |
| 312 | PCIBus *pci_bus; | 340 | PCIBus *pci_bus; |
| 313 | const sparc_def_t *def; | 341 | const sparc_def_t *def; |
| 342 | + QEMUBH *bh; | ||
| 314 | 343 | ||
| 315 | linux_boot = (kernel_filename != NULL); | 344 | linux_boot = (kernel_filename != NULL); |
| 316 | 345 | ||
| @@ -324,8 +353,20 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, | @@ -324,8 +353,20 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, | ||
| 324 | } | 353 | } |
| 325 | env = cpu_init(); | 354 | env = cpu_init(); |
| 326 | cpu_sparc_register(env, def); | 355 | cpu_sparc_register(env, def); |
| 356 | + bh = qemu_bh_new(tick_irq, env); | ||
| 357 | + env->tick = ptimer_init(bh); | ||
| 358 | + ptimer_set_period(env->tick, 1ULL); | ||
| 359 | + | ||
| 360 | + bh = qemu_bh_new(stick_irq, env); | ||
| 361 | + env->stick = ptimer_init(bh); | ||
| 362 | + ptimer_set_period(env->stick, 1ULL); | ||
| 363 | + | ||
| 364 | + bh = qemu_bh_new(hstick_irq, env); | ||
| 365 | + env->hstick = ptimer_init(bh); | ||
| 366 | + ptimer_set_period(env->hstick, 1ULL); | ||
| 327 | register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); | 367 | register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); |
| 328 | qemu_register_reset(main_cpu_reset, env); | 368 | qemu_register_reset(main_cpu_reset, env); |
| 369 | + main_cpu_reset(env); | ||
| 329 | 370 | ||
| 330 | /* allocate RAM */ | 371 | /* allocate RAM */ |
| 331 | cpu_register_physical_memory(0, ram_size, 0); | 372 | cpu_register_physical_memory(0, ram_size, 0); |
target-sparc/cpu.h
| @@ -226,10 +226,12 @@ typedef struct CPUSPARCState { | @@ -226,10 +226,12 @@ typedef struct CPUSPARCState { | ||
| 226 | uint64_t mgregs[8]; /* mmu general registers */ | 226 | uint64_t mgregs[8]; /* mmu general registers */ |
| 227 | uint64_t fprs; | 227 | uint64_t fprs; |
| 228 | uint64_t tick_cmpr, stick_cmpr; | 228 | uint64_t tick_cmpr, stick_cmpr; |
| 229 | + void *tick, *stick; | ||
| 229 | uint64_t gsr; | 230 | uint64_t gsr; |
| 230 | uint32_t gl; // UA2005 | 231 | uint32_t gl; // UA2005 |
| 231 | /* UA 2005 hyperprivileged registers */ | 232 | /* UA 2005 hyperprivileged registers */ |
| 232 | uint64_t hpstate, htstate[MAXTL], hintp, htba, hver, hstick_cmpr, ssr; | 233 | uint64_t hpstate, htstate[MAXTL], hintp, htba, hver, hstick_cmpr, ssr; |
| 234 | + void *hstick; // UA 2005 | ||
| 233 | #endif | 235 | #endif |
| 234 | #if !defined(TARGET_SPARC64) && !defined(reg_T2) | 236 | #if !defined(TARGET_SPARC64) && !defined(reg_T2) |
| 235 | target_ulong t2; | 237 | target_ulong t2; |
| @@ -292,6 +294,9 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); | @@ -292,6 +294,9 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); | ||
| 292 | void raise_exception(int tt); | 294 | void raise_exception(int tt); |
| 293 | void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, | 295 | void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, |
| 294 | int is_asi); | 296 | int is_asi); |
| 297 | +void do_tick_set_count(void *opaque, uint64_t count); | ||
| 298 | +uint64_t do_tick_get_count(void *opaque); | ||
| 299 | +void do_tick_set_limit(void *opaque, uint64_t limit); | ||
| 295 | 300 | ||
| 296 | #include "cpu-all.h" | 301 | #include "cpu-all.h" |
| 297 | 302 |
target-sparc/op.c
| @@ -1096,12 +1096,38 @@ void OPPROTO op_wrccr(void) | @@ -1096,12 +1096,38 @@ void OPPROTO op_wrccr(void) | ||
| 1096 | 1096 | ||
| 1097 | void OPPROTO op_rdtick(void) | 1097 | void OPPROTO op_rdtick(void) |
| 1098 | { | 1098 | { |
| 1099 | - T0 = 0; // XXX read cycle counter and bit 31 | 1099 | + T0 = do_tick_get_count(env->tick); |
| 1100 | } | 1100 | } |
| 1101 | 1101 | ||
| 1102 | void OPPROTO op_wrtick(void) | 1102 | void OPPROTO op_wrtick(void) |
| 1103 | { | 1103 | { |
| 1104 | - T0 = 0; // XXX write cycle counter and bit 31 | 1104 | + do_tick_set_count(env->tick, T0); |
| 1105 | +} | ||
| 1106 | + | ||
| 1107 | +void OPPROTO op_wrtick_cmpr(void) | ||
| 1108 | +{ | ||
| 1109 | + do_tick_set_limit(env->tick, T0); | ||
| 1110 | +} | ||
| 1111 | + | ||
| 1112 | +void OPPROTO op_rdstick(void) | ||
| 1113 | +{ | ||
| 1114 | + T0 = do_tick_get_count(env->stick); | ||
| 1115 | +} | ||
| 1116 | + | ||
| 1117 | +void OPPROTO op_wrstick(void) | ||
| 1118 | +{ | ||
| 1119 | + do_tick_set_count(env->stick, T0); | ||
| 1120 | + do_tick_set_count(env->hstick, T0); | ||
| 1121 | +} | ||
| 1122 | + | ||
| 1123 | +void OPPROTO op_wrstick_cmpr(void) | ||
| 1124 | +{ | ||
| 1125 | + do_tick_set_limit(env->stick, T0); | ||
| 1126 | +} | ||
| 1127 | + | ||
| 1128 | +void OPPROTO op_wrhstick_cmpr(void) | ||
| 1129 | +{ | ||
| 1130 | + do_tick_set_limit(env->hstick, T0); | ||
| 1105 | } | 1131 | } |
| 1106 | 1132 | ||
| 1107 | void OPPROTO op_rdtpc(void) | 1133 | void OPPROTO op_rdtpc(void) |
target-sparc/op_helper.c
| @@ -1133,3 +1133,20 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, | @@ -1133,3 +1133,20 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, | ||
| 1133 | raise_exception(TT_DATA_ACCESS); | 1133 | raise_exception(TT_DATA_ACCESS); |
| 1134 | } | 1134 | } |
| 1135 | #endif | 1135 | #endif |
| 1136 | + | ||
| 1137 | +#ifdef TARGET_SPARC64 | ||
| 1138 | +void do_tick_set_count(void *opaque, uint64_t count) | ||
| 1139 | +{ | ||
| 1140 | + ptimer_set_count(opaque, -count); | ||
| 1141 | +} | ||
| 1142 | + | ||
| 1143 | +uint64_t do_tick_get_count(void *opaque) | ||
| 1144 | +{ | ||
| 1145 | + return -ptimer_get_count(opaque); | ||
| 1146 | +} | ||
| 1147 | + | ||
| 1148 | +void do_tick_set_limit(void *opaque, uint64_t limit) | ||
| 1149 | +{ | ||
| 1150 | + ptimer_set_limit(opaque, -limit, 0); | ||
| 1151 | +} | ||
| 1152 | +#endif |
target-sparc/translate.c
| @@ -1202,7 +1202,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -1202,7 +1202,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 1202 | gen_movl_T0_reg(rd); | 1202 | gen_movl_T0_reg(rd); |
| 1203 | break; | 1203 | break; |
| 1204 | case 0x18: /* System tick */ | 1204 | case 0x18: /* System tick */ |
| 1205 | - gen_op_rdtick(); // XXX | 1205 | + gen_op_rdstick(); |
| 1206 | gen_movl_T0_reg(rd); | 1206 | gen_movl_T0_reg(rd); |
| 1207 | break; | 1207 | break; |
| 1208 | case 0x19: /* System tick compare */ | 1208 | case 0x19: /* System tick compare */ |
| @@ -1991,21 +1991,23 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -1991,21 +1991,23 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 1991 | if (!supervisor(dc)) | 1991 | if (!supervisor(dc)) |
| 1992 | goto illegal_insn; | 1992 | goto illegal_insn; |
| 1993 | #endif | 1993 | #endif |
| 1994 | - gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr)); | 1994 | + gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr)); |
| 1995 | + gen_op_wrtick_cmpr(); | ||
| 1995 | break; | 1996 | break; |
| 1996 | case 0x18: /* System tick */ | 1997 | case 0x18: /* System tick */ |
| 1997 | #if !defined(CONFIG_USER_ONLY) | 1998 | #if !defined(CONFIG_USER_ONLY) |
| 1998 | if (!supervisor(dc)) | 1999 | if (!supervisor(dc)) |
| 1999 | goto illegal_insn; | 2000 | goto illegal_insn; |
| 2000 | #endif | 2001 | #endif |
| 2001 | - gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr)); | 2002 | + gen_op_wrstick(); |
| 2002 | break; | 2003 | break; |
| 2003 | case 0x19: /* System tick compare */ | 2004 | case 0x19: /* System tick compare */ |
| 2004 | #if !defined(CONFIG_USER_ONLY) | 2005 | #if !defined(CONFIG_USER_ONLY) |
| 2005 | if (!supervisor(dc)) | 2006 | if (!supervisor(dc)) |
| 2006 | goto illegal_insn; | 2007 | goto illegal_insn; |
| 2007 | #endif | 2008 | #endif |
| 2008 | - gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr)); | 2009 | + gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr)); |
| 2010 | + gen_op_wrstick_cmpr(); | ||
| 2009 | break; | 2011 | break; |
| 2010 | 2012 | ||
| 2011 | case 0x10: /* Performance Control */ | 2013 | case 0x10: /* Performance Control */ |
| @@ -2155,7 +2157,8 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2155,7 +2157,8 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2155 | gen_op_movl_env_T0(offsetof(CPUSPARCState, htba)); | 2157 | gen_op_movl_env_T0(offsetof(CPUSPARCState, htba)); |
| 2156 | break; | 2158 | break; |
| 2157 | case 31: // hstick_cmpr | 2159 | case 31: // hstick_cmpr |
| 2158 | - gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr)); | 2160 | + gen_op_movtl_env_T0(offsetof(CPUSPARCState, hstick_cmpr)); |
| 2161 | + gen_op_wrhstick_cmpr(); | ||
| 2159 | break; | 2162 | break; |
| 2160 | case 6: // hver readonly | 2163 | case 6: // hver readonly |
| 2161 | default: | 2164 | default: |