]> git.proxmox.com Git - qemu.git/commitdiff
Implement Sparc64 CPU timers using ptimers
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 25 May 2007 18:50:28 +0000 (18:50 +0000)
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 25 May 2007 18:50:28 +0000 (18:50 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2860 c046a42c-6fe2-441c-8c8c-71466251a162

Makefile.target
hw/sun4u.c
target-sparc/cpu.h
target-sparc/op.c
target-sparc/op_helper.c
target-sparc/translate.c

index 98fe7e12bfc42a7376c19fe9953ff8e6095a13fd..d066cc03db87eec6752a06ce66187b3be8cb0aa7 100644 (file)
@@ -445,7 +445,7 @@ ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
 VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
-VL_OBJS+= cirrus_vga.o parallel.o
+VL_OBJS+= cirrus_vga.o parallel.o ptimer.o
 else
 VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
 VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o
index 952beff3cdf5e70e237abc3003a403ee1f98535f..a7b9ad8f012c2738105210df2ad72ecd7e87e924 100644 (file)
@@ -282,7 +282,35 @@ void qemu_system_powerdown(void)
 static void main_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
+
     cpu_reset(env);
+    ptimer_set_limit(env->tick, 0x7fffffffffffffffULL, 1);
+    ptimer_run(env->tick, 0);
+    ptimer_set_limit(env->stick, 0x7fffffffffffffffULL, 1);
+    ptimer_run(env->stick, 0);
+    ptimer_set_limit(env->hstick, 0x7fffffffffffffffULL, 1);
+    ptimer_run(env->hstick, 0);
+}
+
+void tick_irq(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+}
+
+void stick_irq(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+}
+
+void hstick_irq(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_interrupt(env, CPU_INTERRUPT_TIMER);
 }
 
 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,
     long prom_offset, initrd_size, kernel_size;
     PCIBus *pci_bus;
     const sparc_def_t *def;
+    QEMUBH *bh;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -324,8 +353,20 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
     }
     env = cpu_init();
     cpu_sparc_register(env, def);
+    bh = qemu_bh_new(tick_irq, env);
+    env->tick = ptimer_init(bh);
+    ptimer_set_period(env->tick, 1ULL);
+
+    bh = qemu_bh_new(stick_irq, env);
+    env->stick = ptimer_init(bh);
+    ptimer_set_period(env->stick, 1ULL);
+
+    bh = qemu_bh_new(hstick_irq, env);
+    env->hstick = ptimer_init(bh);
+    ptimer_set_period(env->hstick, 1ULL);
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
     qemu_register_reset(main_cpu_reset, env);
+    main_cpu_reset(env);
 
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, 0);
index b067d7b9bdd7e15f7a1682b745aba896a131c4ab..c5ccd28a82c734c2bff2abd56a4c4549fac27c52 100644 (file)
@@ -226,10 +226,12 @@ typedef struct CPUSPARCState {
     uint64_t mgregs[8]; /* mmu general registers */
     uint64_t fprs;
     uint64_t tick_cmpr, stick_cmpr;
+    void *tick, *stick;
     uint64_t gsr;
     uint32_t gl; // UA2005
     /* UA 2005 hyperprivileged registers */
     uint64_t hpstate, htstate[MAXTL], hintp, htba, hver, hstick_cmpr, ssr;
+    void *hstick; // UA 2005
 #endif
 #if !defined(TARGET_SPARC64) && !defined(reg_T2)
     target_ulong t2;
@@ -292,6 +294,9 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 void raise_exception(int tt);
 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
                           int is_asi);
+void do_tick_set_count(void *opaque, uint64_t count);
+uint64_t do_tick_get_count(void *opaque);
+void do_tick_set_limit(void *opaque, uint64_t limit);
 
 #include "cpu-all.h"
 
index 5fbbd6db0f4fd26b22e04e3d067cdfa7f953e776..c0aee8f4ac172f98e39dcb9e9bdceb84305867d4 100644 (file)
@@ -1096,12 +1096,38 @@ void OPPROTO op_wrccr(void)
 
 void OPPROTO op_rdtick(void)
 {
-    T0 = 0; // XXX read cycle counter and bit 31
+    T0 = do_tick_get_count(env->tick);
 }
 
 void OPPROTO op_wrtick(void)
 {
-    T0 = 0; // XXX write cycle counter and bit 31
+    do_tick_set_count(env->tick, T0);
+}
+
+void OPPROTO op_wrtick_cmpr(void)
+{
+    do_tick_set_limit(env->tick, T0);
+}
+
+void OPPROTO op_rdstick(void)
+{
+    T0 = do_tick_get_count(env->stick);
+}
+
+void OPPROTO op_wrstick(void)
+{
+    do_tick_set_count(env->stick, T0);
+    do_tick_set_count(env->hstick, T0);
+}
+
+void OPPROTO op_wrstick_cmpr(void)
+{
+    do_tick_set_limit(env->stick, T0);
+}
+
+void OPPROTO op_wrhstick_cmpr(void)
+{
+    do_tick_set_limit(env->hstick, T0);
 }
 
 void OPPROTO op_rdtpc(void)
index 93f61a8025aa00e7c66c3a6029f79f4dd23c0a6a..b2f982f4eeaaeafe4f53113bc245c2ef6614fe64 100644 (file)
@@ -1133,3 +1133,20 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
     raise_exception(TT_DATA_ACCESS);
 }
 #endif
+
+#ifdef TARGET_SPARC64
+void do_tick_set_count(void *opaque, uint64_t count)
+{
+    ptimer_set_count(opaque, -count);
+}
+
+uint64_t do_tick_get_count(void *opaque)
+{
+    return -ptimer_get_count(opaque);
+}
+
+void do_tick_set_limit(void *opaque, uint64_t limit)
+{
+    ptimer_set_limit(opaque, -limit, 0);
+}
+#endif
index 38d2a13195ed7cd7fc65e346b308958ba98b2459..8dbe3370fe8f589137a3821d3c071f44a4cc8749 100644 (file)
@@ -1202,7 +1202,7 @@ static void disas_sparc_insn(DisasContext * dc)
                     gen_movl_T0_reg(rd);
                     break;
                case 0x18: /* System tick */
-                    gen_op_rdtick(); // XXX
+                    gen_op_rdstick();
                     gen_movl_T0_reg(rd);
                     break;
                case 0x19: /* System tick compare */
@@ -1991,21 +1991,23 @@ static void disas_sparc_insn(DisasContext * dc)
                                if (!supervisor(dc))
                                    goto illegal_insn;
 #endif
-                               gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
+                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
+                                gen_op_wrtick_cmpr();
                                break;
                            case 0x18: /* System tick */
 #if !defined(CONFIG_USER_ONLY)
                                if (!supervisor(dc))
                                    goto illegal_insn;
 #endif
-                               gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
+                                gen_op_wrstick();
                                break;
                            case 0x19: /* System tick compare */
 #if !defined(CONFIG_USER_ONLY)
                                if (!supervisor(dc))
                                    goto illegal_insn;
 #endif
-                               gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
+                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
+                                gen_op_wrstick_cmpr();
                                break;
 
                            case 0x10: /* Performance Control */
@@ -2155,7 +2157,8 @@ static void disas_sparc_insn(DisasContext * dc)
                                 gen_op_movl_env_T0(offsetof(CPUSPARCState, htba));
                                 break;
                             case 31: // hstick_cmpr
-                                gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
+                                gen_op_movtl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
+                                gen_op_wrhstick_cmpr();
                                 break;
                             case 6: // hver readonly
                             default: