Re: [Qemu-devel] [PATCH] Sparc32: dummy implementation of MXCC MMU breakpoint registers
Blue Swirl wrote: Add dummy registers for SuperSPARC MXCC MMU counter breakpoints. Signed-off-by: Blue Swirlblauwir...@gmail.com --- target-sparc/cpu.h |1 + target-sparc/op_helper.c | 26 -- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 320530e..b5d5291 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -403,6 +403,7 @@ typedef struct CPUSPARCState { uint32_t mmuregs[32]; uint64_t mxccdata[4]; uint64_t mxccregs[8]; +uint32_t mmubpctrv, mmubpctrc, mmubpctrs, mmubpaction; uint64_t mmubpregs[4]; uint64_t prom_addr; #endif diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index b38691e..e9cc1f5 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -1940,7 +1940,6 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) case 0x31: // Turbosparc RAM snoop case 0x32: // Turbosparc page table descriptor diagnostic case 0x39: /* data cache diagnostic register */ -case 0x4c: /* SuperSPARC MMU Breakpoint Action register */ ret = 0; break; case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */ @@ -1966,6 +1965,18 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) ret); } break; +case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */ +ret = env-mmubpctrv; +break; +case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */ +ret = env-mmubpctrc; +break; +case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */ +ret = env-mmubpctrs; +break; +case 0x4c: /* SuperSPARC MMU Breakpoint Action */ +ret = env-mmubpaction; +break; case 8: /* User code access, XXX */ default: do_unassigned_access(addr, 0, 0, asi, size); @@ -2304,7 +2315,6 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size) // descriptor diagnostic case 0x36: /* I-cache flash clear */ case 0x37: /* D-cache flash clear */ -case 0x4c: /* breakpoint action */ break; case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/ { @@ -2328,6 +2338,18 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size) env-mmuregs[reg]); } break; +case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */ +env-mmubpctrv = val 0x; +break; +case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */ +env-mmubpctrc = val 0x3; +break; +case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */ +env-mmubpctrs = val 0x3; +break; +case 0x4c: /* SuperSPARC MMU Breakpoint Action */ +env-mmubpaction = val 0x1fff; +break; case 8: /* User code access, XXX */ case 9: /* Supervisor code access, XXX */ default: The breakpoint action register is 64 bits wide.
Re: [Qemu-devel] [sparc] Floating point exception issue
Blue Swirl wrote: On Sat, Jan 22, 2011 at 3:30 PM, Mateusz Loskotmate...@loskot.net wrote: On 18/01/11 21:51, Blue Swirl wrote: On Tue, Jan 18, 2011 at 6:00 PM, Mateusz Loskotmate...@loskot.net wrote: On 18/01/11 17:36, Blue Swirl wrote: On Tue, Jan 18, 2011 at 3:27 PM, Mateusz Loskotmate...@loskot.net wrote: Hi, Recently, I have reported mysterious issues on NetBSD 5.1 emulated on SPARC. The whole first thread is here: http://lists.gnu.org/archive/html/qemu-devel/2011-01/msg01509.html I decided to investigate the problem deeper and with great help from NetBSD folks, I managed to find reproducible test case. Initially, it was AWK command: # echo NaN | awk '{print test}' awk: floating point exception 8 source line number 1 and next it boiled down to simple C program (see below). Details of the investigation are archived in the NetBSD Problem Report #44389 here: http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=44389 Here is final version of the test program which reproduces the problem: #includestdio.h #includestdlib.h #includemath.h #includeerrno.h int is_number(const char *s) { double r; char *ep; errno = 0; r = strtod(s,ep); if (r == HUGE_VAL) printf(X:%g\n, r); if (ep == s || r == HUGE_VAL || errno == ERANGE) return 0; while (*ep == ' ' || *ep == '\t' || *ep == '\n') ep++; if (*ep == '\0') return 1; else return 0; } int main(int argc, char **argv) { double v; if (is_number(NaN)) { printf(is a number\n); v = atof(NaN); } else { printf(not a number\n); v = 0.0; } printf(%.4f\n, v); return 0; } On NetBSD/SPARC, the program receives SIGFPE: $ gcc ./nan_test_2.c $ ./a.out [1] Floating point exception (core dumped) ./a.out Specifically, it's caused by r == HUGE_VAL condition in if (ep == s || r == HUGE_VAL || errno == ERANGE) where r is NaN. All the signs indicate there is a bug in QEMU. I'll install 5.1, but on 4.0 which I had installed, the program works fine: $ ./sigfpe is a number nan I just tested on NetBSD 5.0/SPARC under QEMU 0.13 (same version I use with NetBSD 5.1/SPARC) and it works well indeed: mloskot@qemu-netbsd-50-sparc:~/tmp# ./a.out is a number nan mloskot@qemu-netbsd-50-sparc:~/tmp# Hmm, this is becoming interesting. I run QEMU 0.13 on Windows Vista (64-bit). Perhaps host system and QEMU binaries are relevant here. I will try on Linux host system later tonight. BTW, here are my images: http://mateusz.loskot.net/tmp/qemu/ The problem was with NaN handling in fcmped instruction. I've committed a patch that fixes the problem, please test. Thanks for reporting and the test case. FYI, this problem seems to be occurring in qemu on Windows only. I tested git version dated before you applied the fix and built on Linux and the problem does not happening there. No, it was generic problem. I could reproduce it with your test case and with a small assembler program which only used fcmped using user emulator. There is still a floating point exception problem that may or may not be related. Booting an ss5-170 with a real sun ROM image still fails FP tests: 4.1.1 fpureg regfile Pass 4.1.2 fpureg misalign Pass 4.1.3 fpureg single precision Pass 4.1.4 fpureg double precision Pass 4.2.1 fpuexceptions single precision Failed Exception Didn't Block Store : 0 : exp= , obs= 4.2.2 fpuexceptions double precision Failed Exception Didn't Block Store : 0 : exp= , obs=
[Qemu-devel] [PATCH] target-sparc/translate.c microSPARC II mask fix
Fix microSPARC II SFSR mask. diff -p -u -r1.96 translate.c --- target-sparc/translate.c5 Mar 2008 17:59:48 - 1.96 +++ target-sparc/translate.c6 Mar 2008 02:15:30 - @@ -4259,7 +4259,7 @@ static const sparc_def_t sparc_defs[] = .mmu_bm = 0x4000, .mmu_ctpr_mask = 0x00c0, .mmu_cxr_mask = 0x00ff, -.mmu_sfsr_mask = 0x00016bff, +.mmu_sfsr_mask = 0x00016fff, .mmu_trcr_mask = 0x00ff, }, {
[Qemu-devel] [PATCH] hw/sun4m.c show IRQ set or reset
Show which CPU IRQ is actually being set or reset when debugging. diff -p -u -r1.86 sun4m.c --- hw/sun4m.c 2 Mar 2008 08:48:47 - 1.86 +++ hw/sun4m.c 3 Mar 2008 00:35:29 - @@ -258,12 +258,15 @@ void cpu_check_irqs(CPUState *env) int old_interrupt = env-interrupt_index; env-interrupt_index = TT_EXTINT | i; -if (old_interrupt != env-interrupt_index) +if (old_interrupt != env-interrupt_index) { +DPRINTF(Set CPU IRQ %d\n, i); cpu_interrupt(env, CPU_INTERRUPT_HARD); +} break; } } } else if (!env-pil_in (env-interrupt_index ~15) == TT_EXTINT) { +DPRINTF(Reset CPU IRQ %d\n, env-interrupt_index 15); env-interrupt_index = 0; cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); }
[Qemu-devel] [PATCH] hw/slavio_timer.c remove unneeded qemu_irq_lower
Remove unneeded qemu_irq_lower because user mode timers don't support IRQs and the IRQ is lowered when switching to user mode. diff -p -u -r1.30 slavio_timer.c --- hw/slavio_timer.c 26 Jan 2008 09:13:46 - 1.30 +++ hw/slavio_timer.c 3 Mar 2008 00:35:28 - @@ -192,7 +192,6 @@ static void slavio_timer_mem_writel(void uint64_t count; // set user counter MSW, reset counter -qemu_irq_lower(s-irq); s-limit = TIMER_MAX_COUNT64; s-counthigh = val (TIMER_MAX_COUNT64 32); s-reached = 0; @@ -218,7 +217,6 @@ static void slavio_timer_mem_writel(void uint64_t count; // set user counter LSW, reset counter -qemu_irq_lower(s-irq); s-limit = TIMER_MAX_COUNT64; s-count = val TIMER_MAX_COUNT64; s-reached = 0;
Re: [Qemu-devel] qemu-system-sparc and Solaris 1.1.2 / SunOS 4.1.4
Andrew Warkentin wrote: SunOS might run in TME (http://people.csail.mit.edu/fredette/tme/). I don't think anything other than Linux runs in QEMU's Sun emulation (or for that matter, any of the non-PC QEMU emulators). Unfortunately TME only emulates a SPARCstation2 (sun4c). I have only been able to get linux running with QEMU and it seems stable. I have tried numerous versions of solaris and bsd without success. I have been unable to get any version of an Open Boot PROM for any machine working. We are at the point now where the images actually run but fail the self tests and hang while accessing the floppy during the initialization stage. QEMU hardware emulation is just not good enough for for this yet. I would like to see QEMU emulation good enough to be able to run Open Boot PROM images well enough to load an OS. At that point solaris and bsd will probably work and OpenBIOS can be fixed.
Re: [Qemu-devel] qemu-system-sparc and Solaris 1.1.2 / SunOS 4.1.4
Jan Holzhueter wrote: Hi everyone, we are planing to get rid of some old sparc hardware. The problem is that there are applications on it that require sun4m and Solaris 1.1.2 / SunOS 4.1.4. As known qemu-system-sparc is not able to boot the Solaris Kernel at the moment. I get as far as: [sparc] Booting file 'cdrom' with parameters '' Not a bootable ELF image Not a Linux kernel image Not a bootable a.out image Not a bootable ELF image Not a Linux kernel image Loading a.out image... Loaded 7680 bytes entry point is 0x4000 Jumping to entry point... checksum 60746d10 != 86693bac, trying to boot anyway Unhandled Exception 0x0007 PC = 0x002002bc NPC = 0x002002c0 Stopping execution My question is how far away are you form getting it to work and in what time frame could it be done? This is a bigger project for us. So it might even be possible ( nothing confirmed yet I have to check back with some people ) to donate some money to get it to work. It doesn't need to work for all Solaris. We just need Solaris 1.1.2. If someone needs some installation Medium or feedback let me know. Greetings Jan Holzhüter This may be an openbios issue. Changing openbios boot.c cdrom oldpath to sd(0,2,0):d gets past this error but it still doesn't boot.
[Qemu-devel] [PATCH] sparc32 mmu register fixes
This patch gets openboot prom mmu register self tests passing for lx, ss4, ss5 and ss10 prom images. Index: target-sparc/cpu.h === RCS file: /sources/qemu/qemu/target-sparc/cpu.h,v retrieving revision 1.61 diff -p -u -r1.61 cpu.h --- target-sparc/cpu.h 28 Nov 2007 20:54:33 - 1.61 +++ target-sparc/cpu.h 11 Feb 2008 00:07:10 - @@ -198,6 +198,10 @@ typedef struct CPUSPARCState { int interrupt_request; int halted; uint32_t mmu_bm; +uint32_t mmu_ctpr_mask; +uint32_t mmu_cxr_mask; +uint32_t mmu_sfsr_mask; +uint32_t mmu_trcr_mask; /* NOTE: we allow 8 more registers to handle wrapping */ target_ulong regbase[NWINDOWS * 16 + 8]; Index: target-sparc/helper.c === RCS file: /sources/qemu/qemu/target-sparc/helper.c,v retrieving revision 1.33 diff -p -u -r1.33 helper.c --- target-sparc/helper.c 25 Dec 2007 07:49:10 - 1.33 +++ target-sparc/helper.c 11 Feb 2008 00:07:11 - @@ -129,7 +129,7 @@ int get_physical_address (CPUState *env, /* SPARC reference MMU table walk: Context table-L1-L2-PTE */ /* Context base + context number */ -pde_ptr = ((env-mmuregs[1] ~63) 4) + (env-mmuregs[2] 2); +pde_ptr = (env-mmuregs[1] 4) + (env-mmuregs[2] 2); pde = ldl_phys(pde_ptr); /* Ctx pde */ Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.65 diff -p -u -r1.65 op_helper.c --- target-sparc/op_helper.c1 Jan 2008 17:07:39 - 1.65 +++ target-sparc/op_helper.c11 Feb 2008 00:07:12 - @@ -591,7 +591,7 @@ void helper_st_asi(int asi, int size) oldreg = env-mmuregs[reg]; switch(reg) { -case 0: +case 0: // Control Register env-mmuregs[reg] = (env-mmuregs[reg] 0xff00) | (T1 0x00ff); // Mappings generated during no-fault mode or MMU @@ -600,21 +600,27 @@ void helper_st_asi(int asi, int size) (env-mmuregs[reg] (MMU_E | MMU_NF | env-mmu_bm))) tlb_flush(env, 1); break; -case 2: -env-mmuregs[reg] = T1; +case 1: // Context Table Pointer Register +env-mmuregs[reg] = T1 env-mmu_ctpr_mask; +break; +case 2: // Context Register +env-mmuregs[reg] = T1 env-mmu_cxr_mask; if (oldreg != env-mmuregs[reg]) { /* we flush when the MMU context changes because QEMU has no MMU context support */ tlb_flush(env, 1); } break; -case 3: -case 4: +case 3: // Synchronous Fault Status Register with Clear +case 4: // Synchronous Fault Address Register +break; +case 0x10: // TLB Replacement Control Register +env-mmuregs[reg] = T1 env-mmu_trcr_mask; break; -case 0x13: -env-mmuregs[3] = T1; +case 0x13: // Synchronous Fault Status Register with Read and Clear +env-mmuregs[3] = T1 env-mmu_sfsr_mask; break; -case 0x14: +case 0x14: // Synchronous Fault Address Register env-mmuregs[4] = T1; break; default: Index: target-sparc/translate.c === RCS file: /sources/qemu/qemu/target-sparc/translate.c,v retrieving revision 1.86 diff -p -u -r1.86 translate.c --- target-sparc/translate.c1 Feb 2008 10:50:11 - 1.86 +++ target-sparc/translate.c11 Feb 2008 00:07:14 - @@ -62,6 +62,10 @@ struct sparc_def_t { uint32_t fpu_version; uint32_t mmu_version; uint32_t mmu_bm; +uint32_t mmu_ctpr_mask; +uint32_t mmu_cxr_mask; +uint32_t mmu_sfsr_mask; +uint32_t mmu_trcr_mask; }; static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name); @@ -3758,6 +3762,10 @@ CPUSPARCState *cpu_sparc_init(const char env-fsr = def-fpu_version; #if !defined(TARGET_SPARC64) env-mmu_bm = def-mmu_bm; +env-mmu_ctpr_mask = def-mmu_ctpr_mask; +env-mmu_cxr_mask = def-mmu_cxr_mask; +env-mmu_sfsr_mask = def-mmu_sfsr_mask; +env-mmu_trcr_mask = def-mmu_trcr_mask; env-mmuregs[0] |= def-mmu_version; cpu_sparc_set_id(env, 0); #endif @@ -3887,6 +3895,10 @@ static const sparc_def_t sparc_defs[] = .fpu_version = 4 17, /* FPU version 4 (Meiko) */ .mmu_version = 0x00 24, /* Impl 0, ver 0 */ .mmu_bm = 0x4000, +.mmu_ctpr_mask = 0x0070, +.mmu_cxr_mask = 0x003f, +
Re: [Qemu-devel] [PATCH] hw/sun4m.c fix power addresses
Blue Swirl wrote: On 1/25/08, Robert Reif [EMAIL PROTECTED] wrote: Blue Swirl wrote: On 1/24/08, Robert Reif [EMAIL PROTECTED] wrote: diff -p -u -r1.81 sun4m.c This breaks my tests, so I guess a fix is also needed for OpenBIOS. Probably, they were tested using ss5/170 and ss10 openboot images. I just noticed that we have confused the devices that OBP calls 'power' and 'power-management'. Power or Aux 2 or Software Powerdown Control can be used to reset or power down the system. OBP trees confirm that it is located at 0x7191 on SS-5 and 0xff1a01000 on SS-10/20. It does not exist on SS-600. Power-management a.k.a. APC is used to halt the CPU when idle. It is located at 0x6a00 on SS-5. It does not exist on SS-x0 or SS-600. So, Aux2 on SS-10/20 and APC on SS-5 should move to the correct locations. Now, what to do with the rest? These are motherboard devices, they cannot be added to or removed from real life hardware. Leaving the devices out to improve historical accuracy would mean that the system can't be reset or powered down on SS-600, and on SS-10/20/600 Qemu will consume 100% of host CPU even when the target is idling. This would not be an improvement in usability for sure. I have a patch waiting to fix the power/aux2 and also aux1. It adds a seperate address for auxio. power and AUX2 are the same devices on ss5,10 and 20 but at different addresse/offsets. 600mp doesn't have it. auxio is AUX1 and are the sort of the same devices on an ss5 and 10/20 but at different address/offsets. 600mp doesn't have it. The AUX1 bit layout of an ss5 (SLAVIO) is also different from a 10/20 (SEC). I'm not sure how power-management fits in there other than it's an sbus device: ffd50130 [EMAIL PROTECTED],a00
Re: [Qemu-devel] [PATCH] hw/slavio_timer.c user timer mode change fix
Blue Swirl wrote: On 1/23/08, Robert Reif [EMAIL PROTECTED] wrote: Change ptimer limit only when mode changes. Update timer configuration register user timer bits properly. The patch does not apply. It should apply on top of the first user timer patch that is in CVS now.
Re: [Qemu-devel] [PATCH] hw/slavio_timer.c user timer mode change fix
Rediffed against cvs. diff -p -u -r1.29 slavio_timer.c --- hw/slavio_timer.c 25 Jan 2008 19:51:27 - 1.29 +++ hw/slavio_timer.c 25 Jan 2008 21:50:35 - @@ -199,10 +199,8 @@ static void slavio_timer_mem_writel(void count = ((uint64_t)s-counthigh 32) | s-count; DPRINTF(processor %d user timer set to %016llx\n, s-slave_index, count); -if (s-timer) { +if (s-timer) ptimer_set_count(s-timer, LIMIT_TO_PERIODS(s-limit - count)); -ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 0); -} } else { // set limit, reset counter qemu_irq_lower(s-irq); @@ -227,10 +225,8 @@ static void slavio_timer_mem_writel(void count = ((uint64_t)s-counthigh) 32 | s-count; DPRINTF(processor %d user timer set to %016llx\n, s-slave_index, count); -if (s-timer) { +if (s-timer) ptimer_set_count(s-timer, LIMIT_TO_PERIODS(s-limit - count)); -ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 0); -} } else DPRINTF(not user timer\n); break; @@ -265,22 +261,38 @@ static void slavio_timer_mem_writel(void unsigned int i; for (i = 0; i s-num_slaves; i++) { -if (val (1 i)) { -qemu_irq_lower(s-slave[i]-irq); -s-slave[i]-limit = -1ULL; -} else { -ptimer_stop(s-slave[i]-timer); -} -if ((val (1 i)) != (s-slave_mode (1 i))) { -ptimer_stop(s-slave[i]-timer); -ptimer_set_limit(s-slave[i]-timer, - LIMIT_TO_PERIODS(s-slave[i]-limit), 1); -DPRINTF(processor %d timer changed\n, -s-slave[i]-slave_index); -ptimer_run(s-slave[i]-timer, 0); +unsigned int processor = 1 i; +// check for a change in timer mode for this processor +if ((val processor) != (s-slave_mode processor)) { +if (val processor) { // counter - user timer +qemu_irq_lower(s-slave[i]-irq); +// counters are always running +ptimer_stop(s-slave[i]-timer); +s-slave[i]-running = 0; +// user timer limit is always the same +s-slave[i]-limit = TIMER_MAX_COUNT64; +ptimer_set_limit(s-slave[i]-timer, + LIMIT_TO_PERIODS(s-slave[i]-limit), 1); +// set this processors user timer bit in config +// register +s-slave_mode |= processor; +DPRINTF(processor %d changed from counter to user +timer\n, s-slave[i]-slave_index); +} else { // user timer - counter +// stop the user timer if it is running +if (s-slave[i]-running) +ptimer_stop(s-slave[i]-timer); +// start the counter +ptimer_run(s-slave[i]-timer, 0); +s-slave[i]-running = 1; +// clear this processors user timer bit in config +// register +s-slave_mode = ~processor; +DPRINTF(processor %d changed from user timer to +counter\n, s-slave[i]-slave_index); +} } } -s-slave_mode = val ((1 s-num_slaves) - 1); } else DPRINTF(not system timer\n); break;
Re: [Qemu-devel] [PATCH] hw/sun4m.c fix power addresses
Blue Swirl wrote: On 1/24/08, Robert Reif [EMAIL PROTECTED] wrote: diff -p -u -r1.81 sun4m.c This breaks my tests, so I guess a fix is also needed for OpenBIOS. Probably, they were tested using ss5/170 and ss10 openboot images.
Re: [Qemu-devel] qemu cpu-all.h cpu-exec.c qemu-doc.texi vl.c
Exactly which version of gcc is this? It appears to work fine with at least some gcc 3 versions. gcc (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5) Standard Red Hat 9.
[Qemu-devel] [PATCH] hs/iommu.c add turboSPARC mask id register
Add microSPARC II and turboSPARC mask ID register support. Index: hw/iommu.c === RCS file: /sources/qemu/qemu/hw/iommu.c,v retrieving revision 1.25 diff -p -u -r1.25 iommu.c --- hw/iommu.c 1 Jan 2008 17:06:38 - 1.25 +++ hw/iommu.c 23 Jan 2008 14:06:26 - @@ -34,7 +34,7 @@ do { printf(IOMMU: fmt , ##args); } w #define DPRINTF(fmt, args...) #endif -#define IOMMU_NREGS (3*4096/4) +#define IOMMU_NREGS (4*4096/4) #define IOMMU_CTRL (0x 2) #define IOMMU_CTRL_IMPL 0xf000 /* Implementation */ #define IOMMU_CTRL_VERS 0x0f00 /* Version */ @@ -95,6 +95,12 @@ do { printf(IOMMU: fmt , ##args); } w #define IOMMU_ARBEN_MASK0x001f #define IOMMU_MID 0x0008 +#define IOMMU_MASK_ID (0x3018 2) /* Mask ID */ +#define IOMMU_MASK_ID_MASK 0x00ff + +#define IOMMU_MSII_MASK 0x2600 /* microSPARC II mask number */ +#define IOMMU_TS_MASK 0x2300 /* turboSPARC mask number */ + /* The format of an iopte in the page tables */ #define IOPTE_PAGE 0xff00 /* Physical page number (PA[35:12]) */ #define IOPTE_CACHE 0x0080 /* Cached (in vme IOCACHE or @@ -206,6 +212,9 @@ static void iommu_mem_writel(void *opaqu // addresses, fault cause and address stored to MMU/IOMMU s-regs[saddr] = (val IOMMU_ARBEN_MASK) | IOMMU_MID; break; +case IOMMU_MASK_ID: +s-regs[saddr] |= (val IOMMU_MASK_ID_MASK); +break; default: s-regs[saddr] = val; break; @@ -337,6 +346,7 @@ static void iommu_reset(void *opaque) s-regs[IOMMU_CTRL] = s-version; s-regs[IOMMU_ARBEN] = IOMMU_MID; s-regs[IOMMU_AFSR] = IOMMU_AFSR_RESV; +s-regs[IOMMU_MASK_ID] = IOMMU_TS_MASK; qemu_irq_lower(s-irq); }
Re: [Qemu-devel] qemu cpu-all.h cpu-exec.c qemu-doc.texi vl.c
Thiemo Seufer wrote: CVSROOT:/sources/qemu Module name:qemu Changes by: Thiemo Seufer ths 08/01/23 19:01:12 Modified files: . : cpu-all.h cpu-exec.c qemu-doc.texi vl.c Log message: Add option to disable TB cache, by Herve Poussineau. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/qemu/cpu-all.h?cvsroot=qemur1=1.81r2=1.82 http://cvs.savannah.gnu.org/viewcvs/qemu/cpu-exec.c?cvsroot=qemur1=1.130r2=1.131 http://cvs.savannah.gnu.org/viewcvs/qemu/qemu-doc.texi?cvsroot=qemur1=1.182r2=1.183 http://cvs.savannah.gnu.org/viewcvs/qemu/vl.c?cvsroot=qemur1=1.400r2=1.401 This gives the following compile errror: gcc -Wall -O2 -g -fno-strict-aliasing -fomit-frame-pointer -I. -I.. -I/home/wine/qemu/target-i386 -I/home/wine/qemu -MMD -MP -DNEED_CPU_H -I/home/wine/qemu/linux-user -I/home/wine/qemu/linux-user/i386 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -I/home/wine/qemu/fpu -DHAS_AUDIO -DHAS_AUDIO_CHOICE -I/home/wine/qemu/slirp-c -o cpu-exec.o /home/wine/qemu/cpu-exec.c /home/wine/qemu/cpu-exec.c: In function `cmp1': /home/wine/qemu/cpu-exec.c:143: unable to find a register to spill in class `DIREG' /home/wine/qemu/cpu-exec.c:143: this is the insn: (insn 21 78 23 (parallel[ (set (reg:SI 2 ecx [64]) (unspec:SI[ (mem:BLK (reg/f:SI 1 edx [66]) [0 A8]) (reg:QI 0 al [68]) (const_int 1 [0x1]) (reg:SI 2 ecx [67]) ] 0)) (use (reg:SI 19 dirflag)) (clobber (reg/f:SI 1 edx [66])) (clobber (reg:CC 17 flags)) ] ) 623 {strlenqi_1} (insn_list 15 (insn_list 17 (insn_list 19 (insn_list 20 (nil) (expr_list:REG_DEAD (reg:SI 19 dirflag) (expr_list:REG_DEAD (reg:SI 2 ecx [67]) (expr_list:REG_DEAD (reg:QI 0 al [68]) (expr_list:REG_DEAD (reg/f:SI 1 edx [66]) (expr_list:REG_UNUSED (reg/f:SI 1 edx [66]) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil /home/wine/qemu/cpu-exec.c:143: confused by earlier errors, bailing out make[1]: *** [cpu-exec.o] Error 1 make[1]: Leaving directory `/home/wine/qemu/i386-linux-user' make: *** [subdir-i386-linux-user] Error 2
[Qemu-devel] [PATCH] hw/sun4m.c fix power addresses
diff -p -u -r1.81 sun4m.c --- hw/sun4m.c 17 Jan 2008 21:04:16 - 1.81 +++ hw/sun4m.c 24 Jan 2008 05:06:38 - @@ -687,7 +687,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0x7840, .esp_base = 0x7880, .le_base = 0x78c0, -.power_base = 0x7a00, +.power_base = 0x7191, .ecc_base = -1, .sun4c_intctl_base = -1, .sun4c_counter_base = -1, @@ -727,7 +727,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0xef040ULL, .esp_base = 0xef080ULL, .le_base = 0xef0c0ULL, -.power_base = 0xefa00ULL, +.power_base = 0xff1a01000ULL, .ecc_base = 0xfULL, .ecc_version = 0x1000, // version 0, implementation 1 .sun4c_intctl_base = -1, @@ -811,7 +811,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0xef040ULL, .esp_base = 0xef080ULL, .le_base = 0xef0c0ULL, -.power_base = 0xefa00ULL, +.power_base = 0xff1a01000ULL, .ecc_base = 0xfULL, .ecc_version = 0x2000, // version 0, implementation 2 .sun4c_intctl_base = -1,
[Qemu-devel] [PATCH] hw/slavio_timer.c user timer limit bit fix
Set limit bit when user timer expires. Clear limit bit when user timer count set. Set ptimer count when user timer count set. Index: hw/slavio_timer.c === RCS file: /sources/qemu/qemu/hw/slavio_timer.c,v retrieving revision 1.28 diff -p -u -r1.28 slavio_timer.c --- hw/slavio_timer.c 1 Jan 2008 17:06:38 - 1.28 +++ hw/slavio_timer.c 23 Jan 2008 02:33:57 - @@ -122,10 +122,9 @@ static void slavio_timer_irq(void *opaqu slavio_timer_get_out(s); DPRINTF(callback: count %x%08x\n, s-counthigh, s-count); -if (!slavio_timer_is_user(s)) { -s-reached = TIMER_REACHED; +s-reached = TIMER_REACHED; +if (!slavio_timer_is_user(s)) qemu_irq_raise(s-irq); -} } static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) @@ -141,7 +140,7 @@ static uint32_t slavio_timer_mem_readl(v if (slavio_timer_is_user(s)) { // read user timer MSW slavio_timer_get_out(s); -ret = s-counthigh; +ret = s-counthigh | s-reached; } else { // read limit // clear irq @@ -155,7 +154,7 @@ static uint32_t slavio_timer_mem_readl(v // of counter (user mode) slavio_timer_get_out(s); if (slavio_timer_is_user(s)) // read user timer LSW -ret = s-count TIMER_COUNT_MASK32; +ret = s-count TIMER_MAX_COUNT64; else // read limit ret = (s-count TIMER_MAX_COUNT32) | s-reached; break; @@ -190,12 +189,19 @@ static void slavio_timer_mem_writel(void switch (saddr) { case TIMER_LIMIT: if (slavio_timer_is_user(s)) { +uint64_t count; // set user counter MSW, reset counter qemu_irq_lower(s-irq); s-limit = TIMER_MAX_COUNT64; -DPRINTF(processor %d user timer reset\n, s-slave_index); -if (s-timer) -ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 1); +s-counthigh = val (TIMER_MAX_COUNT64 32); +s-reached = 0; +count = ((uint64_t)s-counthigh 32) | s-count; +DPRINTF(processor %d user timer set to %016llx\n, s-slave_index, +count); +if (s-timer) { +ptimer_set_count(s-timer, LIMIT_TO_PERIODS(s-limit - count)); +ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 0); +} } else { // set limit, reset counter qemu_irq_lower(s-irq); @@ -210,12 +216,19 @@ static void slavio_timer_mem_writel(void break; case TIMER_COUNTER: if (slavio_timer_is_user(s)) { +uint64_t count; // set user counter LSW, reset counter qemu_irq_lower(s-irq); s-limit = TIMER_MAX_COUNT64; -DPRINTF(processor %d user timer reset\n, s-slave_index); -if (s-timer) -ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 1); +s-count = val TIMER_MAX_COUNT64; +s-reached = 0; +count = ((uint64_t)s-counthigh) 32 | s-count; +DPRINTF(processor %d user timer set to %016llx\n, s-slave_index, +count); +if (s-timer) { +ptimer_set_count(s-timer, LIMIT_TO_PERIODS(s-limit - count)); +ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 0); +} } else DPRINTF(not user timer\n); break;
[Qemu-devel] [PATCH] hw/slavio_timer.c user timer mode change fix
Change ptimer limit only when mode changes. Update timer configuration register user timer bits properly. --- hw/slavio_timer.c.old 2008-01-22 21:35:33.0 -0500 +++ hw/slavio_timer.c 2008-01-22 21:36:13.0 -0500 @@ -198,10 +198,8 @@ static void slavio_timer_mem_writel(void count = ((uint64_t)s-counthigh 32) | s-count; DPRINTF(processor %d user timer set to %016llx\n, s-slave_index, count); -if (s-timer) { +if (s-timer) ptimer_set_count(s-timer, LIMIT_TO_PERIODS(s-limit - count)); -ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 0); -} } else { // set limit, reset counter qemu_irq_lower(s-irq); @@ -225,10 +223,8 @@ static void slavio_timer_mem_writel(void count = ((uint64_t)s-counthigh) 32 | s-count; DPRINTF(processor %d user timer set to %016llx\n, s-slave_index, count); -if (s-timer) { +if (s-timer) ptimer_set_count(s-timer, LIMIT_TO_PERIODS(s-limit - count)); -ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 0); -} } else DPRINTF(not user timer\n); break; @@ -263,22 +259,38 @@ static void slavio_timer_mem_writel(void unsigned int i; for (i = 0; i s-num_slaves; i++) { -if (val (1 i)) { -qemu_irq_lower(s-slave[i]-irq); -s-slave[i]-limit = -1ULL; -} else { -ptimer_stop(s-slave[i]-timer); -} -if ((val (1 i)) != (s-slave_mode (1 i))) { -ptimer_stop(s-slave[i]-timer); -ptimer_set_limit(s-slave[i]-timer, - LIMIT_TO_PERIODS(s-slave[i]-limit), 1); -DPRINTF(processor %d timer changed\n, -s-slave[i]-slave_index); -ptimer_run(s-slave[i]-timer, 0); +unsigned int processor = 1 i; +// check for a change in timer mode for this processor +if ((val processor) != (s-slave_mode processor)) { +if (val processor) { // counter - user timer +qemu_irq_lower(s-slave[i]-irq); +// counters are always running +ptimer_stop(s-slave[i]-timer); +s-slave[i]-running = 0; +// user timer limit is always the same +s-slave[i]-limit = TIMER_MAX_COUNT64; +ptimer_set_limit(s-slave[i]-timer, + LIMIT_TO_PERIODS(s-slave[i]-limit), 1); +// set this processors user timer bit in config +// register +s-slave_mode |= processor; +DPRINTF(processor %d changed from counter to user +timer\n, s-slave[i]-slave_index); +} else { // user timer - counter +// stop the user timer if it is running +if (s-slave[i]-running) +ptimer_stop(s-slave[i]-timer); +// start the counter +ptimer_run(s-slave[i]-timer, 0); +s-slave[i]-running = 1; +// clear this processors user timer bit in config +// register +s-slave_mode = ~processor; +DPRINTF(processor %d changed from user timer to +counter\n, s-slave[i]-slave_index); +} } } -s-slave_mode = val ((1 s-num_slaves) - 1); } else DPRINTF(not system timer\n); break;
[Qemu-devel] [PATCH] sparc32: add ecc irq
Index: hw/eccmemctl.c === RCS file: /sources/qemu/qemu/hw/eccmemctl.c,v retrieving revision 1.2 diff -p -u -r1.2 eccmemctl.c --- hw/eccmemctl.c 1 Jan 2008 17:06:38 - 1.2 +++ hw/eccmemctl.c 6 Jan 2008 15:03:52 - @@ -68,7 +68,7 @@ #define ECC_FAR0_TYPE 0x00f0 /* Transaction type */ #define ECC_FAR0_SIZE 0x0700 /* Transaction size */ #define ECC_FAR0_CACHE 0x0800 /* Mapped cacheable */ -#define ECC_FAR0_LOCK 0x1000 /* Error occurred in attomic cycle */ +#define ECC_FAR0_LOCK 0x1000 /* Error occurred in atomic cycle */ #define ECC_FAR0_BMODE 0x2000 /* Boot mode */ #define ECC_FAR0_VADDR 0x003fc000 /* VA[12-19] (superset bits) */ #define ECC_FAR0_S 0x0800 /* Supervisor mode */ @@ -90,6 +90,7 @@ #define ECC_ADDR_MASK (ECC_SIZE - 1) typedef struct ECCState { +qemu_irq irq; uint32_t regs[ECC_NREGS]; } ECCState; @@ -222,7 +223,7 @@ static void ecc_reset(void *opaque) s-regs[i] = 0; } -void * ecc_init(target_phys_addr_t base, uint32_t version) +void * ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version) { int ecc_io_memory; ECCState *s; @@ -232,6 +233,7 @@ void * ecc_init(target_phys_addr_t base, return NULL; s-regs[0] = version; +s-irq = irq; ecc_io_memory = cpu_register_io_memory(0, ecc_mem_read, ecc_mem_write, s); cpu_register_physical_memory(base, ECC_SIZE, ecc_io_memory); Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.80 diff -p -u -r1.80 sun4m.c --- hw/sun4m.c 6 Jan 2008 07:50:38 - 1.80 +++ hw/sun4m.c 6 Jan 2008 15:03:52 - @@ -91,7 +91,7 @@ struct hwdef { // IRQ numbers are not PIL ones, but master interrupt controller // register bit numbers int intctl_g_intr, esp_irq, le_irq, clock_irq, clock1_irq; -int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq; +int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq, ecc_irq; int machine_id; // For NVRAM uint32_t iommu_version; uint32_t intbit_to_level[32]; @@ -528,7 +528,8 @@ static void sun4m_hw_init(const struct h graphic_height, graphic_depth, hwdef-machine_id, Sun4m); if (hwdef-ecc_base != (target_phys_addr_t)-1) -ecc_init(hwdef-ecc_base, hwdef-ecc_version); +ecc_init(hwdef-ecc_base, slavio_irq[hwdef-ecc_irq], + hwdef-ecc_version); } static void sun4c_hw_init(const struct hwdef *hwdef, int RAM_size, @@ -742,6 +743,7 @@ static const struct hwdef hwdefs[] = { .fd_irq = 22, .me_irq = 30, .cs_irq = -1, +.ecc_irq = 28, .machine_id = 0x72, .iommu_version = 0x0300, .intbit_to_level = { @@ -783,6 +785,7 @@ static const struct hwdef hwdefs[] = { .fd_irq = 22, .me_irq = 30, .cs_irq = -1, +.ecc_irq = 28, .machine_id = 0x71, .iommu_version = 0x0100, .intbit_to_level = { @@ -824,6 +827,7 @@ static const struct hwdef hwdefs[] = { .fd_irq = 22, .me_irq = 30, .cs_irq = -1, +.ecc_irq = 28, .machine_id = 0x72, .iommu_version = 0x1300, .intbit_to_level = { Index: hw/sun4m.h === RCS file: /sources/qemu/qemu/hw/sun4m.h,v retrieving revision 1.8 diff -p -u -r1.8 sun4m.h --- hw/sun4m.h 1 Jan 2008 17:04:45 - 1.8 +++ hw/sun4m.h 6 Jan 2008 15:03:53 - @@ -81,6 +81,6 @@ void lance_init(NICInfo *nd, target_phys qemu_irq irq, qemu_irq *reset); /* eccmemctl.c */ -void *ecc_init(target_phys_addr_t base, uint32_t version); +void *ecc_init(target_phys_addr_t base, qemu_irq irq, uint32_t version); #endif
[Qemu-devel] [PATCH] hw/sun4m.c make error messages consistent
Make these 3 error messages consistent with the other 20 in the same file. diff -p -u -r1.79 sun4m.c --- hw/sun4m.c 1 Jan 2008 20:57:25 - 1.79 +++ hw/sun4m.c 5 Jan 2008 22:26:07 - @@ -385,7 +385,7 @@ static void sun4m_hw_init(const struct h for(i = 0; i smp_cpus; i++) { env = cpu_init(cpu_model); if (!env) { -fprintf(stderr, Unable to find Sparc CPU definition\n); +fprintf(stderr, qemu: Unable to find Sparc CPU definition\n); exit(1); } cpu_sparc_set_id(env, i); @@ -554,7 +554,7 @@ static void sun4c_hw_init(const struct h env = cpu_init(cpu_model); if (!env) { -fprintf(stderr, Unable to find Sparc CPU definition\n); +fprintf(stderr, qemu: Unable to find Sparc CPU definition\n); exit(1); } @@ -1041,7 +1041,7 @@ static void sun4d_hw_init(const struct s for (i = 0; i smp_cpus; i++) { env = cpu_init(cpu_model); if (!env) { -fprintf(stderr, Unable to find Sparc CPU definition\n); +fprintf(stderr, qemu: Unable to find Sparc CPU definition\n); exit(1); } cpu_sparc_set_id(env, i);
Re: [Qemu-devel] [PATCH] fix possible NULL pointer use in hw/ptimer.c
Paul Brook wrote: What about a meaningful exit message? Out of memory is a fairly comprehensive description of the problem. In fact I'd say it's much more informative than random widget the user doesn't know or care about failed to initialize. If the user requested a target parameter that is beyond the capabilities of the host system, a meaningful error message can be generated that instructs the user on how to possibly correct the problem.
[Qemu-devel] [PATCH] sparc32: fix per cpu counter/timer
Sun4m SMP machines support a maximum of 4 CPUs. Linux knows this and uses fixed size arrays for per-cpu counter/timers and interrupt controllers. Sun4m uni-processor machines use the slaveio chip which has a single per-cpu counter/timer and interrupt controller. However it does not fully decode the address so the same counter/timer or interrupt controller can be accesses from multiple addresses. This patch changes the per-cpu counter/timer to work the way the real hardware works: 4 per-cpu counter/timers for SMP and 1 counter/timer for UP mapped at multiple addresses. This patch also fixes a number of per-cpu user timer bugs: limit bit set when limit reached, count saved and used when written, limit bit reset on count write and system timer configuration register updated properly for per-cpu user timer mode. Sun4d currently uses the sun4m counter/timer code. They are simular but not the same. This patch will break the broken sun4d implementation further. The real fix is to create a proper sun4d counter/timer implementation. Since the sun4d implementation doesn't currently work anyway, this shouldn't be an issue. Index: hw/sbi.c === RCS file: /sources/qemu/qemu/hw/sbi.c,v retrieving revision 1.2 diff -p -u -r1.2 sbi.c --- hw/sbi.c1 Jan 2008 17:06:38 - 1.2 +++ hw/sbi.c5 Jan 2008 00:43:27 - @@ -34,15 +34,13 @@ do { printf(IRQ: fmt , ##args); } whi #define DPRINTF(fmt, args...) #endif -#define MAX_CPUS 16 - #define SBI_NREGS 16 typedef struct SBIState { uint32_t regs[SBI_NREGS]; -uint32_t intreg_pending[MAX_CPUS]; -qemu_irq *cpu_irqs[MAX_CPUS]; -uint32_t pil_out[MAX_CPUS]; +uint32_t intreg_pending[MAX_SUN4D_CPUS]; +qemu_irq *cpu_irqs[MAX_SUN4D_CPUS]; +uint32_t pil_out[MAX_SUN4D_CPUS]; } SBIState; #define SBI_SIZE (SBI_NREGS * 4) @@ -107,7 +105,7 @@ static void sbi_save(QEMUFile *f, void * SBIState *s = opaque; unsigned int i; -for (i = 0; i MAX_CPUS; i++) { +for (i = 0; i MAX_SUN4D_CPUS; i++) { qemu_put_be32s(f, s-intreg_pending[i]); } } @@ -120,7 +118,7 @@ static int sbi_load(QEMUFile *f, void *o if (version_id != 1) return -EINVAL; -for (i = 0; i MAX_CPUS; i++) { +for (i = 0; i MAX_SUN4D_CPUS; i++) { qemu_get_be32s(f, s-intreg_pending[i]); } sbi_check_interrupts(s); @@ -133,7 +131,7 @@ static void sbi_reset(void *opaque) SBIState *s = opaque; unsigned int i; -for (i = 0; i MAX_CPUS; i++) { +for (i = 0; i MAX_SUN4D_CPUS; i++) { s-intreg_pending[i] = 0; } sbi_check_interrupts(s); @@ -150,7 +148,7 @@ void *sbi_init(target_phys_addr_t addr, if (!s) return NULL; -for (i = 0; i MAX_CPUS; i++) { +for (i = 0; i MAX_SUN4D_CPUS; i++) { s-cpu_irqs[i] = parent_irq[i]; } @@ -160,7 +158,7 @@ void *sbi_init(target_phys_addr_t addr, register_savevm(sbi, addr, 1, sbi_save, sbi_load, s); qemu_register_reset(sbi_reset, s); *irq = qemu_allocate_irqs(sbi_set_irq, s, 32); -*cpu_irq = qemu_allocate_irqs(sbi_set_timer_irq_cpu, s, MAX_CPUS); +*cpu_irq = qemu_allocate_irqs(sbi_set_timer_irq_cpu, s, MAX_SUN4D_CPUS); sbi_reset(s); return s; Index: hw/slavio_intctl.c === RCS file: /sources/qemu/qemu/hw/slavio_intctl.c,v retrieving revision 1.29 diff -p -u -r1.29 slavio_intctl.c --- hw/slavio_intctl.c 1 Jan 2008 20:57:25 - 1.29 +++ hw/slavio_intctl.c 5 Jan 2008 00:43:27 - @@ -46,21 +46,20 @@ do { printf(IRQ: fmt , ##args); } whi * */ -#define MAX_CPUS 16 #define MAX_PILS 16 typedef struct SLAVIO_INTCTLState { -uint32_t intreg_pending[MAX_CPUS]; +uint32_t intreg_pending[MAX_SUN4M_CPUS]; uint32_t intregm_pending; uint32_t intregm_disabled; uint32_t target_cpu; #ifdef DEBUG_IRQ_COUNT uint64_t irq_count[32]; #endif -qemu_irq *cpu_irqs[MAX_CPUS]; +qemu_irq *cpu_irqs[MAX_SUN4M_CPUS]; const uint32_t *intbit_to_level; uint32_t cputimer_lbit, cputimer_mbit; -uint32_t pil_out[MAX_CPUS]; +uint32_t pil_out[MAX_SUN4M_CPUS]; } SLAVIO_INTCTLState; #define INTCTL_MAXADDR 0xf @@ -84,7 +83,7 @@ static uint32_t slavio_intctl_mem_readl( uint32_t saddr, ret; int cpu; -cpu = (addr (MAX_CPUS - 1) * TARGET_PAGE_SIZE) 12; +cpu = (addr (MAX_SUN4M_CPUS - 1) * TARGET_PAGE_SIZE) 12; saddr = (addr INTCTL_MAXADDR) 2; switch (saddr) { case 0: @@ -105,7 +104,7 @@ static void slavio_intctl_mem_writel(voi uint32_t saddr; int cpu; -cpu = (addr (MAX_CPUS - 1) * TARGET_PAGE_SIZE) 12; +cpu = (addr (MAX_SUN4M_CPUS - 1) * TARGET_PAGE_SIZE) 12; saddr = (addr INTCTL_MAXADDR) 2; DPRINTF(write cpu %d reg 0x TARGET_FMT_plx = %x\n, cpu, addr, val); switch (saddr) { @@ -190,7 +189,7 @@ static void
Re: [Qemu-devel] [RFC] 64 bit i/o
Paul Brook wrote: On Wednesday 02 January 2008, Robert Reif wrote: Sparc32 has a 64 bit counter that should be read and written as 64 bits but that isn't supported in QEMU. I did a quick hack to add 64 bit i/o and converted sparc32 to use it and it seems to work. I'm suppling the sparc changes to get comments on if this is worth pursuing. Couldn't you just latch the value when one half is accessed? Paul In this one specific case you could do that but this is not the only case in sparc32 (TOD, MXCC, ...) and other architectures with 64 bit hardware have similar requirements. This is a generic solution that fills a hole in the qemu implementation.
[Qemu-devel] [PATCH] fix possible NULL pointer use in vl.c
diff -p -u -r1.392 vl.c --- vl.c28 Dec 2007 20:59:23 - 1.392 +++ vl.c3 Jan 2008 02:20:42 - @@ -985,6 +985,8 @@ QEMUTimer *qemu_new_timer(QEMUClock *clo QEMUTimer *ts; ts = qemu_mallocz(sizeof(QEMUTimer)); +if (!ts) +return NULL; ts-clock = clock; ts-cb = cb; ts-opaque = opaque;
[Qemu-devel] [PATCH] fix possible NULL pointer use in hw/ptimer.c
diff -p -u -r1.5 ptimer.c --- hw/ptimer.c 17 Nov 2007 17:14:47 - 1.5 +++ hw/ptimer.c 3 Jan 2008 02:27:18 - @@ -185,6 +185,8 @@ ptimer_state *ptimer_init(QEMUBH *bh) ptimer_state *s; s = (ptimer_state *)qemu_mallocz(sizeof(ptimer_state)); +if (!s) +return NULL; s-bh = bh; s-timer = qemu_new_timer(vm_clock, ptimer_tick, s); return s;
Re: [Qemu-devel] [PATCH] fix possible NULL pointer use in hw/ptimer.c
Paul Brook wrote: s = (ptimer_state *)qemu_mallocz(sizeof(ptimer_state)); +if (!s) +return NULL; None of the callers bother to check the return value, And even if they did I don't think there's any point trying to gracefully handle OOM. Just abort and be done with it. I am in the process of fixing the sparc ptimer caller to gracefully handle OOM. We currently don't check the return value in the init function where the new timer is created but do check it wherever it is used which is backwards and wasteful. You would prefer that qemu just segfaults rather than die gracefully?
[Qemu-devel] [PATCH] sparc32: fix power address
Fix obio/power address for ss10 and ss20. ss600mp doesn't have obio/power so fix slavio_misc to work without it. Index: hw/slavio_misc.c === RCS file: /sources/qemu/qemu/hw/slavio_misc.c,v retrieving revision 1.16 diff -p -u -r1.16 slavio_misc.c --- hw/slavio_misc.c1 Dec 2007 15:02:20 - 1.16 +++ hw/slavio_misc.c31 Dec 2007 02:55:57 - @@ -146,7 +146,7 @@ static void slavio_misc_mem_writeb(void s-mctrl = val 0xff; break; default: -if (addr == s-power_base) { +if (s-power_base != -1 addr == s-power_base) { MISC_DPRINTF(Write power management %2.2x\n, val 0xff); cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT); } @@ -181,7 +181,7 @@ static uint32_t slavio_misc_mem_readb(vo MISC_DPRINTF(Read modem control %2.2x\n, ret); break; default: -if (addr == s-power_base) { +if (s-power_base != -1 addr == s-power_base) { MISC_DPRINTF(Read power management %2.2x\n, ret); } break; @@ -366,7 +366,9 @@ void *slavio_misc_init(target_phys_addr_ cpu_register_physical_memory(base + MISC_MDM, MISC_SIZE, slavio_misc_io_memory); // Power management -cpu_register_physical_memory(power_base, MISC_SIZE, slavio_misc_io_memory); +if (power_base != -1) +cpu_register_physical_memory(power_base, MISC_SIZE, + slavio_misc_io_memory); s-power_base = power_base; /* 16 bit registers */ Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.77 diff -p -u -r1.77 sun4m.c --- hw/sun4m.c 29 Dec 2007 20:09:57 - 1.77 +++ hw/sun4m.c 31 Dec 2007 02:55:58 - @@ -724,7 +724,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0xef040ULL, .esp_base = 0xef080ULL, .le_base = 0xef0c0ULL, -.power_base = 0xefa00ULL, +.power_base = 0xff1a01000ULL, .ecc_base = 0xfULL, .ecc_version = 0x1000, // version 0, implementation 1 .sun4c_intctl_base = -1, @@ -765,7 +765,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0xef0081000ULL, .esp_base = 0xef008ULL, .le_base = 0xef006ULL, -.power_base = 0xefa00ULL, +.power_base = -1, .ecc_base = 0xfULL, .ecc_version = 0x, // version 0, implementation 0 .sun4c_intctl_base = -1, @@ -806,7 +806,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0xef040ULL, .esp_base = 0xef080ULL, .le_base = 0xef0c0ULL, -.power_base = 0xefa00ULL, +.power_base = 0xff1a01000ULL, .ecc_base = 0xfULL, .ecc_version = 0x2000, // version 0, implementation 2 .sun4c_intctl_base = -1,
[Qemu-devel] [PATCH] sparc32: better unassigned memory debug message
Pass the asi number in is_asi. This works because asi 0 is not a valid asi. Print out the type of access (read, write, exec). diff -p -u -r1.61 op_helper.c --- target-sparc/op_helper.c10 Dec 2007 19:58:20 - 1.61 +++ target-sparc/op_helper.c28 Dec 2007 17:07:49 - @@ -416,7 +416,7 @@ void helper_ld_asi(int asi, int size, in break; case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ default: -do_unassigned_access(T0, 0, 0, 1); +do_unassigned_access(T0, 0, 0, asi); ret = 0; break; } @@ -717,7 +717,7 @@ void helper_st_asi(int asi, int size) case 9: /* Supervisor code access, XXX */ case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ default: -do_unassigned_access(T0, 1, 0, 1); +do_unassigned_access(T0, 1, 0, asi); return; } } @@ -1832,6 +1832,17 @@ void do_unassigned_access(target_phys_ad generated code */ saved_env = env; env = cpu_single_env; +#ifdef DEBUG_UNASSIGNED +if (is_asi) +printf(Unassigned mem %s access to TARGET_FMT_plx asi 0x%02x from + TARGET_FMT_lx \n, + is_exec ? exec : is_write ? write : read, addr, is_asi, + env-pc); +else +printf(Unassigned mem %s access to TARGET_FMT_plx from + TARGET_FMT_lx \n, + is_exec ? exec : is_write ? write : read, addr, env-pc); +#endif if (env-mmuregs[3]) /* Fault status register */ env-mmuregs[3] = 1; /* overflow (not read before another fault) */ if (is_asi) @@ -1845,10 +1856,6 @@ void do_unassigned_access(target_phys_ad env-mmuregs[3] |= (5 2) | 2; env-mmuregs[4] = addr; /* Fault address register */ if ((env-mmuregs[0] MMU_E) !(env-mmuregs[0] MMU_NF)) { -#ifdef DEBUG_UNASSIGNED -printf(Unassigned mem access to TARGET_FMT_plx from TARGET_FMT_lx - \n, addr, env-pc); -#endif if (is_exec) raise_exception(TT_CODE_ACCESS); else
[Qemu-devel] [PATCH] sparc32: add asi debug info
Add asi debug info printing. diff -p -u -r1.61 op_helper.c --- target-sparc/op_helper.c10 Dec 2007 19:58:20 - 1.61 +++ target-sparc/op_helper.c28 Dec 2007 17:23:29 - @@ -6,6 +6,7 @@ //#define DEBUG_MXCC //#define DEBUG_UNALIGNED //#define DEBUG_UNASSIGNED +//#define DEBUG_ASI #ifdef DEBUG_MMU #define DPRINTF_MMU(fmt, args...) \ @@ -21,6 +22,13 @@ do { printf(MXCC: fmt , ##args); } wh #define DPRINTF_MXCC(fmt, args...) #endif +#ifdef DEBUG_ASI +#define DPRINTF_ASI(fmt, args...) \ +do { printf(ASI: fmt , ##args); } while (0) +#else +#define DPRINTF_ASI(fmt, args...) +#endif + void raise_exception(int tt) { env-exception_index = tt; @@ -229,11 +237,34 @@ static void dump_mxcc(CPUState *env) } #endif +#ifdef DEBUG_ASI +static void dump_asi(const char * txt, uint32_t addr, int asi, int size, + uint32_t r1, uint32_t r2) +{ +switch (size) +{ +case 1: +DPRINTF_ASI(%s %08x asi 0x%02x = %02x\n, txt, addr, asi, r1 0xff); +break; +case 2: +DPRINTF_ASI(%s %08x asi 0x%02x = %04x\n, txt, addr, asi, r1 0x); +break; +case 4: +DPRINTF_ASI(%s %08x asi 0x%02x = %08x\n, txt, addr, asi, r1); +break; +case 8: +DPRINTF_ASI(%s %08x asi 0x%02x = %016llx\n, txt, addr, asi, +r2 | ((uint64_t)r1 32)); +break; +} +} +#endif + void helper_ld_asi(int asi, int size, int sign) { uint32_t ret = 0; uint64_t tmp; -#ifdef DEBUG_MXCC +#if defined(DEBUG_MXCC) || defined(DEBUG_ASI) uint32_t last_T0 = T0; #endif @@ -435,6 +466,10 @@ void helper_ld_asi(int asi, int size, in } else T1 = ret; + +#ifdef DEBUG_ASI +dump_asi(read , last_T0, asi, size, T1, T0); +#endif } void helper_st_asi(int asi, int size) @@ -542,8 +577,8 @@ void helper_st_asi(int asi, int size) #ifdef DEBUG_MMU dump_mmu(env); #endif -return; } +break; case 4: /* write MMU regs */ { int reg = (T0 8) 0x1f; @@ -587,8 +622,8 @@ void helper_st_asi(int asi, int size) #ifdef DEBUG_MMU dump_mmu(env); #endif -return; } +break; case 0xa: /* User data access */ switch(size) { case 1: @@ -646,7 +681,7 @@ void helper_st_asi(int asi, int size) stl_kernel(dst, temp); } } -return; +break; case 0x1f: /* Block fill, stda access */ { // value (T1, T2) @@ -661,7 +696,7 @@ void helper_st_asi(int asi, int size) for (i = 0; i 32; i += 8, dst += 8) stq_kernel(dst, val); } -return; +break; case 0x20: /* MMU passthrough */ { switch(size) { @@ -680,7 +715,7 @@ void helper_st_asi(int asi, int size) break; } } -return; +break; case 0x2e: /* MMU passthrough, 0xe */ case 0x2f: /* MMU passthrough, 0xf */ { @@ -705,7 +740,7 @@ void helper_st_asi(int asi, int size) break; } } -return; +break; case 0x30: /* store buffer tags */ case 0x31: /* store buffer data or Ross RT620 I-cache flush */ case 0x32: /* store buffer control */ @@ -718,8 +753,11 @@ void helper_st_asi(int asi, int size) case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ default: do_unassigned_access(T0, 1, 0, 1); -return; +break; } +#ifdef DEBUG_ASI +dump_asi(write, T0, asi, size, T1, T2); +#endif } #endif /* CONFIG_USER_ONLY */
[Qemu-devel] [PATCH] sparc32: set SS-5 iommu version to turbosparc to match default cpu
diff -p -u -r1.73 sun4m.c --- hw/sun4m.c 28 Dec 2007 20:59:23 - 1.73 +++ hw/sun4m.c 28 Dec 2007 21:25:06 - @@ -698,7 +698,7 @@ static const struct hwdef hwdefs[] = { .me_irq = 30, .cs_irq = 5, .machine_id = 0x80, -.iommu_version = 0x0400, +.iommu_version = 0x0500, .intbit_to_level = { 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12, 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
[Qemu-devel] [PATCH] hw/m48t59.c make debug printing consistent
This patch adds __func__ to 3 of the 4 debug printfs to make it consistent with the the one that already uses it. diff -p -u -r1.17 m48t59.c --- hw/m48t59.c 17 Nov 2007 17:14:43 - 1.17 +++ hw/m48t59.c 27 Dec 2007 23:34:11 - @@ -451,7 +451,7 @@ uint32_t m48t59_read (void *opaque, uint break; } if (addr 0x1FF9 addr 0x2000) - NVRAM_PRINTF(0x%08x = 0x%08x\n, addr, retval); + NVRAM_PRINTF(%s: 0x%08x = 0x%08x\n, __func__, addr, retval); return retval; } @@ -476,7 +476,7 @@ static void NVRAM_writeb (void *opaque, m48t59_t *NVRAM = opaque; addr -= NVRAM-io_base; -NVRAM_PRINTF(0x%08x = 0x%08x\n, addr, val); +NVRAM_PRINTF(%s: 0x%08x = 0x%08x\n, __func__, addr, val); switch (addr) { case 0: NVRAM-addr = ~0x00FF; @@ -509,7 +509,7 @@ static uint32_t NVRAM_readb (void *opaqu retval = -1; break; } -NVRAM_PRINTF(0x%08x = 0x%08x\n, addr, retval); +NVRAM_PRINTF(%s: 0x%08x = 0x%08x\n, __func__, addr, retval); return retval; }
[Qemu-devel] [PATCH] fix hw/slavio_intctl.c system read address mask
diff -p -u -r1.24 slavio_intctl.c --- hw/slavio_intctl.c 17 Nov 2007 21:01:04 - 1.24 +++ hw/slavio_intctl.c 28 Dec 2007 01:46:54 - @@ -145,7 +145,7 @@ static uint32_t slavio_intctlm_mem_readl SLAVIO_INTCTLState *s = opaque; uint32_t saddr, ret; -saddr = (addr INTCTLM_MAXADDR) 2; +saddr = (addr INTCTLM_MASK) 2; switch (saddr) { case 0: ret = s-intregm_pending ~MASTER_DISABLE;
[Qemu-devel] [PATCH] sparc32: all registers set to 0 on reset
All registers are set to 0 on reset. This requires my prevoius patch which isn't in CVS yet. diff -p -u -r1.23 slavio_timer.c --- hw/slavio_timer.c 17 Dec 2007 18:21:57 - 1.23 +++ hw/slavio_timer.c 19 Dec 2007 12:28:30 - @@ -306,13 +369,11 @@ static void slavio_timer_reset(void *opa { SLAVIO_TIMERState *s = opaque; -if (slavio_timer_is_user(s)) -s-limit = TIMER_MAX_COUNT64; -else -s-limit = TIMER_MAX_COUNT32; +s-limit = 0; s-count = 0; s-reached = 0; -ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 1); +s-slave_mode = 0; +ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1); ptimer_run(s-timer, 0); s-running = 1; qemu_irq_lower(s-irq);
[Qemu-devel] [PATCH] sparc32: fix count calculation when limit = 0
Fix count calculation when counter limit set to 0. diff -p -u -r1.23 slavio_timer.c --- hw/slavio_timer.c 17 Dec 2007 18:21:57 - 1.23 +++ hw/slavio_timer.c 18 Dec 2007 02:23:37 - @@ -97,9 +97,14 @@ static int slavio_timer_is_user(SLAVIO_T // Convert from ptimer countdown units static void slavio_timer_get_out(SLAVIO_TIMERState *s) { -uint64_t count; +uint64_t count, limit; -count = s-limit - PERIODS_TO_LIMIT(ptimer_get_count(s-timer)); +if (s-limit == 0) /* free-run processor or system counter */ +limit = TIMER_MAX_COUNT32; +else +limit = s-limit; + +count = limit - PERIODS_TO_LIMIT(ptimer_get_count(s-timer)); DPRINTF(get_out: limit % PRIx64 count %x%08x\n, s-limit, s-counthigh, s-count); s-count = count TIMER_COUNT_MASK32;
[Qemu-devel] [PATCH] sparc32: make number of per CPU timers match number of CPUs
Only create as many per CPU timers as there are CPUs. Index: hw/slavio_timer.c === RCS file: /sources/qemu/qemu/hw/slavio_timer.c,v retrieving revision 1.21 diff -p -u -r1.21 slavio_timer.c --- hw/slavio_timer.c 1 Dec 2007 15:58:22 - 1.21 +++ hw/slavio_timer.c 16 Dec 2007 22:53:33 - @@ -61,6 +61,7 @@ typedef struct SLAVIO_TIMERState { struct SLAVIO_TIMERState *master; int slave_index; // system only +unsigned int num_slaves; struct SLAVIO_TIMERState *slave[MAX_CPUS]; uint32_t slave_mode; } SLAVIO_TIMERState; @@ -352,14 +353,16 @@ static SLAVIO_TIMERState *slavio_timer_i } void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, - qemu_irq *cpu_irqs) + qemu_irq *cpu_irqs, unsigned int num_cpus) { SLAVIO_TIMERState *master; unsigned int i; master = slavio_timer_init(base + SYS_TIMER_OFFSET, master_irq, NULL, 0); -for (i = 0; i MAX_CPUS; i++) { +master-num_slaves = num_cpus; + +for (i = 0; i master-num_slaves; i++) { master-slave[i] = slavio_timer_init(base + (target_phys_addr_t) CPU_TIMER_OFFSET(i), cpu_irqs[i], master, i); Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.69 diff -p -u -r1.69 sun4m.c --- hw/sun4m.c 10 Dec 2007 20:00:11 - 1.69 +++ hw/sun4m.c 16 Dec 2007 22:53:33 - @@ -436,7 +436,7 @@ static void sun4m_hw_init(const struct h hwdef-nvram_size, 8); slavio_timer_init_all(hwdef-counter_base, slavio_irq[hwdef-clock1_irq], - slavio_cpu_irq); + slavio_cpu_irq, smp_cpus); slavio_serial_ms_kbd_init(hwdef-ms_kb_base, slavio_irq[hwdef-ms_kb_irq], nographic); Index: hw/sun4m.h === RCS file: /sources/qemu/qemu/hw/sun4m.h,v retrieving revision 1.4 diff -p -u -r1.4 sun4m.h --- hw/sun4m.h 9 Dec 2007 17:03:50 - 1.4 +++ hw/sun4m.h 16 Dec 2007 22:53:33 - @@ -36,7 +36,7 @@ void slavio_irq_info(void *opaque); /* slavio_timer.c */ void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, - qemu_irq *cpu_irqs); + qemu_irq *cpu_irqs, unsigned int num_cpus); /* slavio_serial.c */ SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
Re: [Qemu-devel] [PATCH] sparc32: make number of per CPU timers match number of CPUs
Robert Reif wrote: Only create as many per CPU timers as there are CPUs. This time with the right patch. Index: hw/slavio_timer.c === RCS file: /sources/qemu/qemu/hw/slavio_timer.c,v retrieving revision 1.21 diff -p -u -r1.21 slavio_timer.c --- hw/slavio_timer.c 1 Dec 2007 15:58:22 - 1.21 +++ hw/slavio_timer.c 16 Dec 2007 23:14:34 - @@ -61,6 +61,7 @@ typedef struct SLAVIO_TIMERState { struct SLAVIO_TIMERState *master; int slave_index; // system only +unsigned int num_slaves; struct SLAVIO_TIMERState *slave[MAX_CPUS]; uint32_t slave_mode; } SLAVIO_TIMERState; @@ -230,7 +231,7 @@ static void slavio_timer_mem_writel(void if (s-master == NULL) { unsigned int i; -for (i = 0; i MAX_CPUS; i++) { +for (i = 0; i s-num_slaves; i++) { if (val (1 i)) { qemu_irq_lower(s-slave[i]-irq); s-slave[i]-limit = -1ULL; @@ -244,7 +245,7 @@ static void slavio_timer_mem_writel(void ptimer_run(s-slave[i]-timer, 0); } } -s-slave_mode = val ((1 MAX_CPUS) - 1); +s-slave_mode = val ((1 s-num_slaves) - 1); } else DPRINTF(not system timer\n); break; @@ -352,14 +353,16 @@ static SLAVIO_TIMERState *slavio_timer_i } void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, - qemu_irq *cpu_irqs) + qemu_irq *cpu_irqs, unsigned int num_cpus) { SLAVIO_TIMERState *master; unsigned int i; master = slavio_timer_init(base + SYS_TIMER_OFFSET, master_irq, NULL, 0); -for (i = 0; i MAX_CPUS; i++) { +master-num_slaves = num_cpus; + +for (i = 0; i master-num_slaves; i++) { master-slave[i] = slavio_timer_init(base + (target_phys_addr_t) CPU_TIMER_OFFSET(i), cpu_irqs[i], master, i); Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.69 diff -p -u -r1.69 sun4m.c --- hw/sun4m.c 10 Dec 2007 20:00:11 - 1.69 +++ hw/sun4m.c 16 Dec 2007 23:14:35 - @@ -436,7 +436,7 @@ static void sun4m_hw_init(const struct h hwdef-nvram_size, 8); slavio_timer_init_all(hwdef-counter_base, slavio_irq[hwdef-clock1_irq], - slavio_cpu_irq); + slavio_cpu_irq, smp_cpus); slavio_serial_ms_kbd_init(hwdef-ms_kb_base, slavio_irq[hwdef-ms_kb_irq], nographic); Index: hw/sun4m.h === RCS file: /sources/qemu/qemu/hw/sun4m.h,v retrieving revision 1.4 diff -p -u -r1.4 sun4m.h --- hw/sun4m.h 9 Dec 2007 17:03:50 - 1.4 +++ hw/sun4m.h 16 Dec 2007 23:14:35 - @@ -36,7 +36,7 @@ void slavio_irq_info(void *opaque); /* slavio_timer.c */ void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, - qemu_irq *cpu_irqs); + qemu_irq *cpu_irqs, unsigned int num_cpus); /* slavio_serial.c */ SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
[Qemu-devel] [PATCH] sparc32: fix setting counter limit to 0
Set the proper limit when set to 0. Index: hw/slavio_timer.c === RCS file: /sources/qemu/qemu/hw/slavio_timer.c,v retrieving revision 1.21 diff -p -u -r1.21 slavio_timer.c --- hw/slavio_timer.c 1 Dec 2007 15:58:22 - 1.21 +++ hw/slavio_timer.c 16 Dec 2007 23:28:13 - @@ -174,7 +175,6 @@ static void slavio_timer_mem_writel(void { SLAVIO_TIMERState *s = opaque; uint32_t saddr; -int reload = 0; DPRINTF(write TARGET_FMT_plx %08x\n, addr, val); saddr = (addr TIMER_MAXADDR) 2; @@ -190,9 +190,10 @@ static void slavio_timer_mem_writel(void // set limit, reset counter qemu_irq_lower(s-irq); s-limit = val TIMER_MAX_COUNT32; -if (!s-limit) -s-limit = TIMER_MAX_COUNT32; -ptimer_set_limit(s-timer, s-limit 9, 1); +if (s-limit == 0) /* free-run */ +ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1); +else +ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 1); } break; case TIMER_COUNTER: @@ -208,9 +209,10 @@ static void slavio_timer_mem_writel(void case TIMER_COUNTER_NORST: // set limit without resetting counter s-limit = val TIMER_MAX_COUNT32; -if (!s-limit) -s-limit = TIMER_MAX_COUNT32; -ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), reload); +if (s-limit == 0) /* free-run */ +ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0); +else +ptimer_set_limit(s-timer, LIMIT_TO_PERIODS(s-limit), 0); break; case TIMER_STATUS: if (slavio_timer_is_user(s)) {
Re: [Qemu-devel] high resolution timer question
Blue Swirl wrote: On 12/10/07, Robert Reif [EMAIL PROTECTED] wrote: Writing data to a serial port on the sparc emulation happens immediately. I would like to throttle the write speed to match the actual baud rate. What's the best way to do this in qemu? Will QEMUTimer work for a 1 millisecond timer? Do you mean that you want the serial port to match the host speed so that for example, at 9600 baud, target would only receive 9600 bits per second? Or do you mean that the emulated CPU should see bits arriving at the same rate that the real CPU would see compared to CPU execution speed? On the positive side, this would fix a bug with serial interrupts arriving too fast which can trigger Linux panics. But this would also complicate the design because currently the devices do not need to emulate any internal buffers. The problem I'm having is with sparc32 using a sun openboot image in nographics mode where the prom uses serial port A as the system console. The serial port output shows up in the host terminal window that qemu was started in. Characters written to serial port A are not reliably making it to the screen. Turning on serial debugging shows that the characters are written to the serial port. The characters do make it to the screen when debugging. If characters are not queued, then that might explain the loss but it looks like the characters are going to a write(fd, ...) so is stdio loosing the characters? I thought slowing down the rate to realistic speeds might help but that doesn't seem to be where the problem really is.
Re: [Qemu-devel] high resolution timer question
Robert Reif wrote: The problem I'm having is with sparc32 using a sun openboot image in nographics mode where the prom uses serial port A as the system console. The serial port output shows up in the host terminal window that qemu was started in. Characters written to serial port A are not reliably making it to the screen. Turning on serial debugging shows that the characters are written to the serial port. The characters do make it to the screen when debugging. The problem seems to be caused by multiple streams outputting to the screen. It looks like different ways of outputting to the same device may use different streams!
Re: [Qemu-devel] high resolution timer question
Robert Reif wrote: Characters written to serial port A are not reliably making it to the screen. Turning on serial debugging shows that the characters are written to the serial port. The characters do make it to the screen when debugging. The problem seems to be caused by multiple streams outputting to the screen. It looks like different ways of outputting to the same device may use different streams! Please disregard this possible cause. I left a debugging printf in by accident. The real problem is still there though.
[Qemu-devel] high resolution timer question
Writing data to a serial port on the sparc emulation happens immediately. I would like to throttle the write speed to match the actual baud rate. What's the best way to do this in qemu? Will QEMUTimer work for a 1 millisecond timer?
[Qemu-devel] [PATCH] sparc32 sun4m eccmemctl
This patch adds sparc32 sun4m SMP ECC memory controller support. Three files are attached: The first is a diff to existing code. The second is a diff for the new eccmemctl.c. The third is the openboot outputs for the 3 systems that support this chip. This patch is necessary for using sun openboot prom images because they expect the device to be present and will fault when it's not there. A prom node will need to be added to openbios for this chip. Index: Makefile.target === RCS file: /sources/qemu/qemu/Makefile.target,v retrieving revision 1.230 diff -p -u -r1.230 Makefile.target --- Makefile.target 2 Dec 2007 02:20:02 - 1.230 +++ Makefile.target 9 Dec 2007 14:03:20 - @@ -482,7 +482,7 @@ VL_OBJS+= cirrus_vga.o parallel.o ptimer 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 -VL_OBJS+= cs4231.o ptimer.o +VL_OBJS+= cs4231.o ptimer.o eccmemctl.o endif endif ifeq ($(TARGET_BASE_ARCH), arm) Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.67 diff -p -u -r1.67 sun4m.c --- hw/sun4m.c 4 Dec 2007 20:58:31 - 1.67 +++ hw/sun4m.c 9 Dec 2007 14:03:24 - @@ -82,6 +82,8 @@ struct hwdef { uint32_t intbit_to_level[32]; uint64_t max_mem; const char * const default_cpu_model; +target_phys_addr_t ecc_base; +uint32_t ecc_version; }; /* TSC handling */ @@ -479,6 +481,9 @@ static void sun4m_hw_init(const struct h nvram_init(nvram, (uint8_t *)nd_table[0].macaddr, kernel_cmdline, boot_device, RAM_size, kernel_size, graphic_width, graphic_height, graphic_depth, hwdef-machine_id); + +if (hwdef-ecc_base != (target_phys_addr_t)-1) +ecc_init(hwdef-ecc_base, hwdef-ecc_version); } static const struct hwdef hwdefs[] = { @@ -517,6 +522,7 @@ static const struct hwdef hwdefs[] = { }, .max_mem = 0x1000, .default_cpu_model = Fujitsu MB86904, +.ecc_base = -1, }, /* SS-10 */ { @@ -553,6 +559,8 @@ static const struct hwdef hwdefs[] = { }, .max_mem = 0x, // XXX actually first 62GB ok .default_cpu_model = TI SuperSparc II, +.ecc_base = 0xfULL, +.ecc_version = 0x1000, // version 0, implementation 1 }, /* SS-600MP */ { @@ -589,6 +597,8 @@ static const struct hwdef hwdefs[] = { }, .max_mem = 0x, // XXX actually first 62GB ok .default_cpu_model = TI SuperSparc II, +.ecc_base = 0xfULL, +.ecc_version = 0x, // version 0, implementation 0 }, }; Index: hw/sun4m.h === RCS file: /sources/qemu/qemu/hw/sun4m.h,v retrieving revision 1.3 diff -p -u -r1.3 sun4m.h --- hw/sun4m.h 4 Dec 2007 20:58:31 - 1.3 +++ hw/sun4m.h 9 Dec 2007 14:03:24 - @@ -72,4 +72,7 @@ void espdma_memory_write(void *opaque, u void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque, qemu_irq irq, qemu_irq *reset); +/* eccmemctl.c */ +void *ecc_init(target_phys_addr_t base, uint32_t version); + #endif --- qemu/hw/eccmemctl.c 1969-12-31 19:00:00.0 -0500 +++ qemu.ecc/hw/eccmemctl.c 2007-12-09 09:12:16.0 -0500 @@ -0,0 +1,266 @@ +/* + * QEMU Sparc Sun4m ECC memory controller emulation + * + * Copyright (c) 2007 Robert Reif + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the Software), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include hw.h +#include sun4m.h +#include sysemu.h + +//#define DEBUG_ECC + +#ifdef DEBUG_ECC +#define DPRINTF(fmt, args...) \ +do { printf(ECC: fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +/* There are 3 versions
[Qemu-devel] [PATCH] sparc32 add a few more ASI
diff -p -u -r1.60 op_helper.c --- target-sparc/op_helper.c28 Nov 2007 18:08:28 - 1.60 +++ target-sparc/op_helper.c9 Dec 2007 20:33:02 - @@ -411,6 +411,9 @@ void helper_ld_asi(int asi, int size, in break; } break; +case 0x39: /* data cache diagnostic register */ +ret = 0; +break; case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ default: do_unassigned_access(T0, 0, 0, 1); @@ -703,9 +706,13 @@ void helper_st_asi(int asi, int size) } } return; -case 0x31: /* Ross RT620 I-cache flush */ +case 0x30: /* store buffer tags */ +case 0x31: /* store buffer data or Ross RT620 I-cache flush */ +case 0x32: /* store buffer control */ case 0x36: /* I-cache flash clear */ case 0x37: /* D-cache flash clear */ +case 0x38: /* breakpoint diagnostics */ +case 0x4c: /* breakpoint action */ break; case 9: /* Supervisor code access, XXX */ case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
[Qemu-devel] [PATCH] sparc32 add SPARCstation 20 machine type
Index: vl.c === RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.377 diff -p -u -r1.377 vl.c --- vl.c6 Dec 2007 22:11:20 - 1.377 +++ vl.c10 Dec 2007 01:17:59 - @@ -7838,6 +7838,7 @@ static void register_machines(void) qemu_register_machine(ss5_machine); qemu_register_machine(ss10_machine); qemu_register_machine(ss600mp_machine); +qemu_register_machine(ss20_machine); #endif #elif defined(TARGET_ARM) qemu_register_machine(integratorcp_machine); Index: hw/boards.h === RCS file: /sources/qemu/qemu/hw/boards.h,v retrieving revision 1.4 diff -p -u -r1.4 boards.h --- hw/boards.h 25 Nov 2007 01:57:38 - 1.4 +++ hw/boards.h 10 Dec 2007 01:17:59 - @@ -52,7 +52,7 @@ extern QEMUMachine shix_machine; extern QEMUMachine r2d_machine; /* sun4m.c */ -extern QEMUMachine ss5_machine, ss10_machine, ss600mp_machine; +extern QEMUMachine ss5_machine, ss10_machine, ss600mp_machine, ss20_machine; /* sun4u.c */ extern QEMUMachine sun4u_machine; Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.68 diff -p -u -r1.68 sun4m.c --- hw/sun4m.c 9 Dec 2007 17:03:50 - 1.68 +++ hw/sun4m.c 10 Dec 2007 01:17:59 - @@ -600,6 +600,44 @@ static const struct hwdef hwdefs[] = { .max_mem = 0x, // XXX actually first 62GB ok .default_cpu_model = TI SuperSparc II, }, +/* SS-20 */ +{ +.iommu_base = 0xfe000ULL, +.tcx_base = 0xe2000ULL, +.cs_base = -1, +.slavio_base = 0xff000ULL, +.ms_kb_base = 0xff100ULL, +.serial_base = 0xff110ULL, +.nvram_base = 0xff120ULL, +.fd_base = 0xff170ULL, +.counter_base = 0xff130ULL, +.intctl_base = 0xff140ULL, +.dma_base = 0xef040ULL, +.esp_base = 0xef080ULL, +.le_base = 0xef0c0ULL, +.power_base = 0xefa00ULL, +.ecc_base = 0xfULL, +.ecc_version = 0x2000, // version 0, implementation 2 +.vram_size= 0x0010, +.nvram_size = 0x2000, +.esp_irq = 18, +.le_irq = 16, +.clock_irq = 7, +.clock1_irq = 19, +.ms_kb_irq = 14, +.ser_irq = 15, +.fd_irq = 22, +.me_irq = 30, +.cs_irq = -1, +.machine_id = 0x72, +.iommu_version = 0x1300, +.intbit_to_level = { +2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12, +6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0, +}, +.max_mem = 0x, // XXX actually first 62GB ok +.default_cpu_model = TI SuperSparc II, +}, }; /* SPARCstation 5 hardware initialisation */ @@ -632,6 +670,16 @@ static void ss600mp_init(int RAM_size, i kernel_cmdline, initrd_filename, cpu_model); } +/* SPARCstation 20 hardware initialisation */ +static void ss20_init(int RAM_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +sun4m_hw_init(hwdefs[3], RAM_size, boot_device, ds, kernel_filename, + kernel_cmdline, initrd_filename, cpu_model); +} + QEMUMachine ss5_machine = { SS-5, Sun4m platform, SPARCstation 5, @@ -649,3 +697,10 @@ QEMUMachine ss600mp_machine = { Sun4m platform, SPARCserver 600MP, ss600mp_init, }; + +QEMUMachine ss20_machine = { +SS-20, +Sun4m platform, SPARCstation 20, +ss20_init, +}; +
Re: [Qemu-devel] [PATCH] sparc32 machine specific maximums
Blue Swirl wrote: On 12/4/07, Robert Reif [EMAIL PROTECTED] wrote: I would be surprised if an SMP kernel actually worked on a multi CPU SS5. Prepare for a surprise: That's interesting because the fact that it works shows how inaccurate the emulation is. Now could you please really surprise me by booting Solaris 2.5 using a real sun openprom image ;-)
Re: [Qemu-devel] [PATCH] sparc32 machine specific maximums
Blue Swirl wrote: On 12/3/07, Robert Reif [EMAIL PROTECTED] wrote: This patch sets the maximum number of CPUs and memory to what is supported by the actual hardware. While it's not historically accurate to emulate a Sparcstation 5 with 16 CPUs and 2 gigabytes of memory, it doesn't break anything to have this capability. We don't throttle the power of the CPU, speed of the network, serial or disk devices either, so they may be unrealistically fast. The timers are not accurate at all compared to CPU execution speed. Currently the memory on SS-5 machine is limited by the location of IOMMU and that the memory lies in one linear bank starting from zero. With more advanced banking and 4G patches, the entire physical address space could be filled with RAM. I would be surprised if an SMP kernel actually worked on a multi CPU SS5. Currently OSs like solaris and bsd that actually use more than a minimal amount of hardware don't work in QEMU. That's because QEMUs system emulation is both incomplete and inaccurate. If you want to make a 16 CPU, 64 Gb machine, define a QEMU specific machine. There are no real 32 bit sparc systems like that. I would like to see real sun openboot ROM images work on realistic emulated hardware so QEMU could be used for real OS development.
[Qemu-devel] [PATCH] sparc32 machine specific maximums
This patch sets the maximum number of CPUs and memory to what is supported by the actual hardware. Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.66 diff -p -u -r1.66 sun4m.c --- hw/sun4m.c 2 Dec 2007 04:51:10 - 1.66 +++ hw/sun4m.c 2 Dec 2007 23:03:18 - @@ -82,6 +82,7 @@ struct hwdef { uint32_t intbit_to_level[32]; uint64_t max_mem; const char * const default_cpu_model; +unsigned int max_cpus; }; /* TSC handling */ @@ -345,10 +346,16 @@ static void sun4m_hw_init(const struct h if (!cpu_model) cpu_model = hwdef-default_cpu_model; +if (smp_cpus hwdef-max_cpus) { +fprintf(stderr, qemu: Too many CPUs for this machine: %d, maximum %d\n, +smp_cpus, hwdef-max_cpus); +exit(1); +} + for(i = 0; i smp_cpus; i++) { env = cpu_init(cpu_model); if (!env) { -fprintf(stderr, Unable to find Sparc CPU definition\n); +fprintf(stderr, qemu: Unable to find Sparc CPU definition\n); exit(1); } cpu_sparc_set_id(env, i); @@ -514,8 +521,9 @@ static const struct hwdef hwdefs[] = { 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12, 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0, }, -.max_mem = 0x1000, +.max_mem = 0x1000, // 256M (8 32M SIMMs) .default_cpu_model = Fujitsu MB86904, +.max_cpus = 1, }, /* SS-10 */ { @@ -550,8 +558,9 @@ static const struct hwdef hwdefs[] = { 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12, 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0, }, -.max_mem = 0x, // XXX actually first 62GB ok +.max_mem = 0x2000, // 512M (8 64M SIMMs) .default_cpu_model = TI SuperSparc II, +.max_cpus = 4, }, /* SS-600MP */ { @@ -586,8 +595,9 @@ static const struct hwdef hwdefs[] = { 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12, 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0, }, -.max_mem = 0x, // XXX actually first 62GB ok +.max_mem = 0x4000, // 1G (64 16M SIMMs) .default_cpu_model = TI SuperSparc II, +.max_cpus = 4, }, };
[Qemu-devel] [PATCH] sparc32 iommu fix
Set initial value of AFSR register properly. Index: hw/iommu.c === RCS file: /sources/qemu/qemu/hw/iommu.c,v retrieving revision 1.19 diff -p -u -r1.19 iommu.c --- hw/iommu.c 17 Nov 2007 17:14:42 - 1.19 +++ hw/iommu.c 21 Nov 2007 04:30:28 - @@ -311,6 +311,7 @@ static void iommu_reset(void *opaque) s-iostart = 0; s-regs[IOMMU_CTRL] = s-version; s-regs[IOMMU_ARBEN] = IOMMU_MID; +s-regs[IOMMU_AFSR] = 0x0080; } void *iommu_init(target_phys_addr_t addr, uint32_t version)
[Qemu-devel] [PATCH] sparc32 MMU fixes
This patch adds support for some more MMU registers: 0x10 TLB replacement control 0x13 read/write access to 0x03 SFSR 0x14 read/write access to 0x04 SFAR Only support for 1 real register was added (0x10) but 16 were added to CPUSPARCState because we don't check for invalid register accesses yet. Different CPUs use different registers and there isn't enough documentation to work out what is valid or not so we just waste some space. This patch also preserves the bits we are not interested in for tlb flushing in the processor control register (0x00). Index: target-sparc/cpu.h === RCS file: /sources/qemu/qemu/target-sparc/cpu.h,v retrieving revision 1.58 diff -p -u -r1.58 cpu.h --- target-sparc/cpu.h 10 Nov 2007 15:15:54 - 1.58 +++ target-sparc/cpu.h 20 Nov 2007 01:23:33 - @@ -215,7 +215,7 @@ typedef struct CPUSPARCState { uint64_t dtlb_tag[64]; uint64_t dtlb_tte[64]; #else -uint32_t mmuregs[16]; +uint32_t mmuregs[32]; uint64_t mxccdata[4]; uint64_t mxccregs[8]; #endif Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.57 diff -p -u -r1.57 op_helper.c --- target-sparc/op_helper.c19 Nov 2007 19:14:10 - 1.57 +++ target-sparc/op_helper.c20 Nov 2007 01:23:33 - @@ -248,11 +248,15 @@ void helper_ld_asi(int asi, int size, in break; case 4: /* read MMU regs */ { -int reg = (T0 8) 0xf; +int reg = (T0 8) 0x1f; ret = env-mmuregs[reg]; if (reg == 3) /* Fault status cleared on read */ -env-mmuregs[reg] = 0; +env-mmuregs[3] = 0; +else if (reg == 0x13) /* Fault status read */ +ret = env-mmuregs[3]; +else if (reg == 0x14) /* Fault address read */ +ret = env-mmuregs[4]; DPRINTF_MMU(mmu_read: reg[%d] = 0x%08x\n, reg, ret); } break; @@ -493,17 +497,18 @@ void helper_st_asi(int asi, int size) } case 4: /* write MMU regs */ { -int reg = (T0 8) 0xf; +int reg = (T0 8) 0x1f; uint32_t oldreg; oldreg = env-mmuregs[reg]; switch(reg) { case 0: -env-mmuregs[reg] = ~(MMU_E | MMU_NF | env-mmu_bm); -env-mmuregs[reg] |= T1 (MMU_E | MMU_NF | env-mmu_bm); +env-mmuregs[reg] = (env-mmuregs[reg] 0xff00) | +(T1 0x00ff); // Mappings generated during no-fault mode or MMU // disabled mode are invalid in normal mode -if (oldreg != env-mmuregs[reg]) +if ((oldreg (MMU_E | MMU_NF | env-mmu_bm)) != +(env-mmuregs[reg] (MMU_E | MMU_NF | env-mmu_bm))) tlb_flush(env, 1); break; case 2: @@ -517,6 +522,12 @@ void helper_st_asi(int asi, int size) case 3: case 4: break; +case 0x13: +env-mmuregs[3] = T1; +break; +case 0x14: +env-mmuregs[4] = T1; +break; default: env-mmuregs[reg] = T1; break;
Re: [Qemu-devel] [RFC][PATCH] fix sparc32 mxcc 64 bit read word order
Blue Swirl wrote: On 11/16/07, Robert Reif [EMAIL PROTECTED] wrote: This patch fixes the word order for 64 bit reads of the mxcc registers. Otherwise everything seems OK, but it breaks NetBSD version 3 on SS10: clock0 at obio0 slot 0 offset 0x20: mk48t08 timer0 at obio0 slot 0 offset 0x30data fault: pc=0xf0111a0c addr=0x0 sfsr=126PERR=0,LVL=1,AT=1,FT=1,FAV,OW panic: kernel fault halted halt, power off Without the patch I get: clock0 at obio0 slot 0 offset 0x20: mk48t08 timer0 at obio0 slot 0 offset 0x30: delay constant 99 zs0 at obio0 slot 0 offset 0x10 level 12 softpri 6 zstty0 at zs0 channel 0 (console i/o) zstty1 at zs0 channel 1 scsi-disk: Unsupported command length, command 79 This is a classic case of two wrongs make a right. OpenBios need to be fixed to set mbus module id to start at 8, not 0 for mbus based machines. Index: drivers/obio.c === --- drivers/obio.c (revision 178) +++ drivers/obio.c (working copy) @@ -891,7 +891,15 @@ push_str(cache-coherence?); fword(property); -PUSH(i); + switch (machine_id) { +case 0x71: +case 0x72: +PUSH(i + 8); +break; +case 0x80: +PUSH(i); +break; +} fword(encode-int); push_str(mid); fword(property);
Re: [Qemu-devel] [RFC][PATCH] fix sparc32 mxcc 64 bit read word order
Blue Swirl wrote: On 11/18/07, Robert Reif [EMAIL PROTECTED] wrote: Blue Swirl wrote: On 11/16/07, Robert Reif [EMAIL PROTECTED] wrote: This patch fixes the word order for 64 bit reads of the mxcc registers. Otherwise everything seems OK, but it breaks NetBSD version 3 on SS10: clock0 at obio0 slot 0 offset 0x20: mk48t08 timer0 at obio0 slot 0 offset 0x30data fault: pc=0xf0111a0c addr=0x0 sfsr=126PERR=0,LVL=1,AT=1,FT=1,FAV,OW panic: kernel fault halted halt, power off Without the patch I get: clock0 at obio0 slot 0 offset 0x20: mk48t08 timer0 at obio0 slot 0 offset 0x30: delay constant 99 zs0 at obio0 slot 0 offset 0x10 level 12 softpri 6 zstty0 at zs0 channel 0 (console i/o) zstty1 at zs0 channel 1 scsi-disk: Unsupported command length, command 79 This is a classic case of two wrongs make a right. OpenBios need to be fixed to set mbus module id to start at 8, not 0 for mbus based machines. Turbosparc manual says that the module id is hardwired to 0x8, so would it be OK if mid was i + 8 for all machines? Probably but I don't know for sure. I just fired up a SPARCclassic X which has a microSPARC CPU and the mid was 0. You may need to check the CPU type for the SS5. I don't have the time right now to dig out a microSPARC SS5 to check it out.
Re: [Qemu-devel] [PATCH] add iommu version to sparc32
Add iommu version to sparc32. Also reset iommu after initialization. Should the version be tied to CPU model instead of machine type? At least for Turbosparc this seems to be the case. On SMP systems the IOMMU is on the system board in a separate ASIC. On single CPU systems the IOMMU is integrated into the CPU. Without checking the FEH, the SS 5 was the only single CPU system that shipped with more than one family of CPUs (MicroSparc II and TurboSparc and they do have different IOMMU versions). That could be special cased. Unfortunately QEMU will allow you to specify unrealistic systems. We should probably add allowable CPU types to specific machine types to catch this.
Re: [Qemu-devel] [RFC][PATCH] fix sparc32 mxcc 64 bit read word order
This patch fixes the word order for 64 bit reads of the mxcc registers. Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.52 diff -p -u -r1.52 op_helper.c --- target-sparc/op_helper.c11 Nov 2007 19:46:09 - 1.52 +++ target-sparc/op_helper.c15 Nov 2007 23:04:48 - @@ -196,8 +196,8 @@ void helper_ld_asi(int asi, int size, in switch (T0) { case 0x01c00a00: /* MXCC control register */ if (size == 8) { -ret = env-mxccregs[3]; -T0 = env-mxccregs[3] 32; +ret = env-mxccregs[3] 32; +T0 = env-mxccregs[3]; } else DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); break; @@ -209,8 +209,8 @@ void helper_ld_asi(int asi, int size, in break; case 0x01c00f00: /* MBus port address register */ if (size == 8) { -ret = env-mxccregs[7]; -T0 = env-mxccregs[7] 32; +ret = env-mxccregs[7] 32; +T0 = env-mxccregs[7]; } else DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); break;
[Qemu-devel] [PATCH] sparc32 fix MXCC error bit clearing
Fix MXCC error register bit clearing. Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.52 diff -p -u -r1.52 op_helper.c --- target-sparc/op_helper.c11 Nov 2007 19:46:09 - 1.52 +++ target-sparc/op_helper.c15 Nov 2007 23:28:12 - @@ -438,13 +446,11 @@ void helper_st_asi(int asi, int size) DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00e00: /* MXCC error register */ +// writing a 1 bit clears the error if (size == 8) -env-mxccregs[6] = ((uint64_t)T1 32) | T2; +env-mxccregs[6] = ~(((uint64_t)T1 32) | T2); else DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); -if (env-mxccregs[6] == 0xULL) { -// this is probably a reset -} break; case 0x01c00f00: /* MBus port address register */ if (size == 8)
[Qemu-devel] [PATCH] sparc32 add new MXCC register
Add new MXCC register. Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.52 diff -r1.52 op_helper.c 209a210,217 case 0x01c00c00: /* Module reset register */ if (size == 8) { ret = env-mxccregs[5] 32; T0 = env-mxccregs[5]; // should we do something here? } else DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); break;
[Qemu-devel] [PATCH] sparc32 remove unnecessary 0xffffffff
Remove unnecessary masking of lower word with 0x. Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.52 diff -p -u -r1.52 op_helper.c --- target-sparc/op_helper.c11 Nov 2007 19:46:09 - 1.52 +++ target-sparc/op_helper.c15 Nov 2007 23:10:36 - @@ -263,7 +263,7 @@ void helper_ld_asi(int asi, int size, in case 8: tmp = ldq_code(T0 ~7); ret = tmp 32; -T0 = tmp 0x; +T0 = tmp; break; } break; @@ -282,7 +282,7 @@ void helper_ld_asi(int asi, int size, in case 8: tmp = ldq_user(T0 ~7); ret = tmp 32; -T0 = tmp 0x; +T0 = tmp; break; } break; @@ -301,7 +301,7 @@ void helper_ld_asi(int asi, int size, in case 8: tmp = ldq_kernel(T0 ~7); ret = tmp 32; -T0 = tmp 0x; +T0 = tmp; break; } break; @@ -325,7 +325,7 @@ void helper_ld_asi(int asi, int size, in case 8: tmp = ldq_phys(T0 ~7); ret = tmp 32; -T0 = tmp 0x; +T0 = tmp; break; } break; @@ -349,7 +349,7 @@ void helper_ld_asi(int asi, int size, in tmp = ldq_phys((target_phys_addr_t)(T0 ~7) | ((target_phys_addr_t)(asi 0xf) 32)); ret = tmp 32; -T0 = tmp 0x; +T0 = tmp; break; } break;
[Qemu-devel] [PATCH] add iommu version to sparc32
Add iommu version to sparc32. Also reset iommu after initialization. Index: hw/iommu.c === RCS file: /sources/qemu/qemu/hw/iommu.c,v retrieving revision 1.17 diff -p -u -r1.17 iommu.c --- hw/iommu.c 6 Oct 2007 11:28:21 - 1.17 +++ hw/iommu.c 12 Nov 2007 22:54:57 - @@ -37,7 +37,6 @@ do { printf(IOMMU: fmt , ##args); } w #define IOMMU_CTRL (0x 2) #define IOMMU_CTRL_IMPL 0xf000 /* Implementation */ #define IOMMU_CTRL_VERS 0x0f00 /* Version */ -#define IOMMU_VERSION 0x0400 #define IOMMU_CTRL_RNGE 0x001c /* Mapping RANGE */ #define IOMMU_RNGE_16MB 0x /* 0xff00 - 0x */ #define IOMMU_RNGE_32MB 0x0004 /* 0xfe00 - 0x */ @@ -104,6 +103,7 @@ typedef struct IOMMUState { target_phys_addr_t addr; uint32_t regs[IOMMU_NREGS]; target_phys_addr_t iostart; +uint32_t version; } IOMMUState; static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr) @@ -158,7 +158,7 @@ static void iommu_mem_writew(void *opaqu break; } DPRINTF(iostart = TARGET_FMT_plx \n, s-iostart); -s-regs[saddr] = ((val IOMMU_CTRL_MASK) | IOMMU_VERSION); +s-regs[saddr] = ((val IOMMU_CTRL_MASK) | s-version); break; case IOMMU_BASE: s-regs[saddr] = val IOMMU_BASE_MASK; @@ -308,10 +308,11 @@ static void iommu_reset(void *opaque) memset(s-regs, 0, IOMMU_NREGS * 4); s-iostart = 0; -s-regs[IOMMU_CTRL] = IOMMU_VERSION; +s-regs[IOMMU_CTRL] = s-version; +s-regs[IOMMU_ARBEN] = IOMMU_MID; } -void *iommu_init(target_phys_addr_t addr) +void *iommu_init(target_phys_addr_t addr, uint32_t version) { IOMMUState *s; int iommu_io_memory; @@ -321,12 +322,14 @@ void *iommu_init(target_phys_addr_t addr return NULL; s-addr = addr; +s-version = version; iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s); cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory); register_savevm(iommu, addr, 2, iommu_save, iommu_load, s); qemu_register_reset(iommu_reset, s); +iommu_reset(s); return s; } Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.60 diff -p -u -r1.60 sun4m.c --- hw/sun4m.c 11 Nov 2007 17:56:38 - 1.60 +++ hw/sun4m.c 12 Nov 2007 22:54:57 - @@ -69,6 +69,7 @@ struct hwdef { int intctl_g_intr, esp_irq, le_irq, clock_irq, clock1_irq; int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq; int machine_id; // For NVRAM +uint32_t iommu_version; uint32_t intbit_to_level[32]; }; @@ -343,7 +344,7 @@ static void *sun4m_hw_init(const struct /* allocate RAM */ cpu_register_physical_memory(0, RAM_size, 0); -iommu = iommu_init(hwdef-iommu_base); +iommu = iommu_init(hwdef-iommu_base, hwdef-iommu_version); slavio_intctl = slavio_intctl_init(hwdef-intctl_base, hwdef-intctl_base + 0x1ULL, hwdef-intbit_to_level[0], @@ -509,6 +510,7 @@ static const struct hwdef hwdefs[] = { .me_irq = 30, .cs_irq = 5, .machine_id = 0x80, +.iommu_version = 0x0400, .intbit_to_level = { 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12, 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0, @@ -542,6 +544,7 @@ static const struct hwdef hwdefs[] = { .me_irq = 30, .cs_irq = -1, .machine_id = 0x72, +.iommu_version = 0x0300, .intbit_to_level = { 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12, 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0, @@ -575,6 +578,7 @@ static const struct hwdef hwdefs[] = { .me_irq = 30, .cs_irq = -1, .machine_id = 0x71, +.iommu_version = 0x0100, .intbit_to_level = { 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12, 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
[Qemu-devel] [PATCH] sparc32 asi cleanups and debug printf
This patch makes debugging asi and mxcc accesses easier to follow. Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.51 diff -p -u -r1.51 op_helper.c --- target-sparc/op_helper.c7 Nov 2007 17:03:37 - 1.51 +++ target-sparc/op_helper.c10 Nov 2007 18:22:34 - @@ -6,6 +6,7 @@ //#define DEBUG_MXCC //#define DEBUG_UNALIGNED //#define DEBUG_UNASSIGNED +//#define DEBUG_ASI #ifdef DEBUG_MMU #define DPRINTF_MMU(fmt, args...) \ @@ -187,7 +188,7 @@ void helper_ld_asi(int asi, int size, in { uint32_t ret = 0; uint64_t tmp; -#ifdef DEBUG_MXCC +#if defined(DEBUG_MXCC) || defined(DEBUG_ASI) uint32_t last_T0 = T0; #endif @@ -199,26 +200,34 @@ void helper_ld_asi(int asi, int size, in ret = env-mxccregs[3]; T0 = env-mxccregs[3] 32; } else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(read %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00a04: /* MXCC control register */ if (size == 4) ret = env-mxccregs[3]; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(read %08x: unimplemented access size: %d\n, T0, size); +break; +case 0x01c00c00: /* Module reset register */ +if (size == 8) { +ret = env-mxccregs[5]; +T0 = env-mxccregs[5] 32; +// should we do something here? +} else +DPRINTF_MXCC(read %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00f00: /* MBus port address register */ if (size == 8) { ret = env-mxccregs[7]; T0 = env-mxccregs[7] 32; } else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(read %08x: unimplemented access size: %d\n, T0, size); break; default: -DPRINTF_MXCC(%08x: unimplemented address, size: %d\n, T0, size); +DPRINTF_MXCC(read %08x: unimplemented address, size: %d\n, T0, size); break; } -DPRINTF_MXCC(asi = %d, size = %d, sign = %d, T0 = %08x - ret = %08x, +DPRINTF_MXCC(read(asi %d, size %d, sign %d) T0 = %08x - ret = %08x, T0 = %08x\n, asi, size, sign, last_T0, ret, T0); #ifdef DEBUG_MXCC dump_mxcc(env); @@ -355,6 +364,10 @@ void helper_ld_asi(int asi, int size, in break; case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ default: +#ifdef DEBUG_ASI +printf(read: %08x asi 0x%02x size %d unsupported address, + last_T0, asi, size); +#endif do_unassigned_access(T0, 0, 0, 1); ret = 0; break; @@ -374,6 +387,11 @@ void helper_ld_asi(int asi, int size, in } else T1 = ret; + +#ifdef DEBUG_ASI +printf(helper_ld_asi(asi 0x%02x, size %d, sign %d) T0 = %08x - + T0 = %08x T1 = %08x\n, asi, size, sign, last_T0, T0, T1); +#endif } void helper_st_asi(int asi, int size) @@ -385,31 +403,31 @@ void helper_st_asi(int asi, int size) if (size == 8) env-mxccdata[0] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(write %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c8: /* MXCC stream data register 1 */ if (size == 8) env-mxccdata[1] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(write %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00010: /* MXCC stream data register 2 */ if (size == 8) env-mxccdata[2] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(write %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00018: /* MXCC stream data register 3 */ if (size == 8) env-mxccdata[3] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(write %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00100: /* MXCC stream source */ if (size == 8) env-mxccregs[0] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +
Re: [Qemu-devel] [PATCH] sparc32 asi cleanups and debug printf
Blue Swirl wrote: DPRINTF_ASI would be nice. Here is a revised patch: Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.51 diff -p -u -r1.51 op_helper.c --- target-sparc/op_helper.c7 Nov 2007 17:03:37 - 1.51 +++ target-sparc/op_helper.c10 Nov 2007 21:24:04 - @@ -6,6 +6,7 @@ //#define DEBUG_MXCC //#define DEBUG_UNALIGNED //#define DEBUG_UNASSIGNED +//#define DEBUG_ASI #ifdef DEBUG_MMU #define DPRINTF_MMU(fmt, args...) \ @@ -21,6 +22,13 @@ do { printf(MXCC: fmt , ##args); } wh #define DPRINTF_MXCC(fmt, args...) #endif +#ifdef DEBUG_ASI +#define DPRINTF_ASI(fmt, args...) \ +do { printf(ASI: fmt , ##args); } while (0) +#else +#define DPRINTF_ASI(fmt, args...) +#endif + void raise_exception(int tt) { env-exception_index = tt; @@ -187,7 +195,7 @@ void helper_ld_asi(int asi, int size, in { uint32_t ret = 0; uint64_t tmp; -#ifdef DEBUG_MXCC +#if defined(DEBUG_MXCC) || defined(DEBUG_ASI) uint32_t last_T0 = T0; #endif @@ -199,26 +207,34 @@ void helper_ld_asi(int asi, int size, in ret = env-mxccregs[3]; T0 = env-mxccregs[3] 32; } else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(read %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00a04: /* MXCC control register */ if (size == 4) ret = env-mxccregs[3]; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(read %08x: unimplemented access size: %d\n, T0, size); +break; +case 0x01c00c00: /* Module reset register */ +if (size == 8) { +ret = env-mxccregs[5]; +T0 = env-mxccregs[5] 32; +// should we do something here? +} else +DPRINTF_MXCC(read %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00f00: /* MBus port address register */ if (size == 8) { ret = env-mxccregs[7]; T0 = env-mxccregs[7] 32; } else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(read %08x: unimplemented access size: %d\n, T0, size); break; default: -DPRINTF_MXCC(%08x: unimplemented address, size: %d\n, T0, size); +DPRINTF_MXCC(read %08x: unimplemented address, size: %d\n, T0, size); break; } -DPRINTF_MXCC(asi = %d, size = %d, sign = %d, T0 = %08x - ret = %08x, +DPRINTF_MXCC(read(asi %d, size %d, sign %d) T0 = %08x - ret = %08x, T0 = %08x\n, asi, size, sign, last_T0, ret, T0); #ifdef DEBUG_MXCC dump_mxcc(env); @@ -355,6 +371,8 @@ void helper_ld_asi(int asi, int size, in break; case 0x21 ... 0x2d: /* MMU passthrough, unassigned */ default: +DPRINTF_ASI(read: %08x asi 0x%02x size %d unsupported address, + last_T0, asi, size); do_unassigned_access(T0, 0, 0, 1); ret = 0; break; @@ -374,6 +392,9 @@ void helper_ld_asi(int asi, int size, in } else T1 = ret; + +DPRINTF_ASI(helper_ld_asi(asi 0x%02x, size %d, sign %d) T0 = %08x - + T0 = %08x T1 = %08x\n, asi, size, sign, last_T0, T0, T1); } void helper_st_asi(int asi, int size) @@ -385,31 +406,31 @@ void helper_st_asi(int asi, int size) if (size == 8) env-mxccdata[0] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(write %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c8: /* MXCC stream data register 1 */ if (size == 8) env-mxccdata[1] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(write %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00010: /* MXCC stream data register 2 */ if (size == 8) env-mxccdata[2] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(write %08x: unimplemented access size: %d\n, T0, size); break; case 0x01c00018: /* MXCC stream data register 3 */ if (size == 8) env-mxccdata[3] = ((uint64_t)T1 32) | T2; else -DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +DPRINTF_MXCC(write %08x: unimplemented access
Re: [Qemu-devel] [PATCH] sparc32 boot mode flag fix
This patch also performs a CPU reset after the CPU is registered rather than before. Why is this change needed? Reset should be doing CPU dependent stuff and the CPU dependent setup is performed when the CPU is registered.
[Qemu-devel] [PATCH] sparc32 boot mode flag fix
This patch adds CPU dependent boot mode flag support. Different CPUs use different bits for the boot mode flag. The constant MMU_BM is replaced with a variable which is set for the selected CPU. This patch also removes the MMU flags from being saved in the translation block code as a result of an off line discussion with Paul Brook. This patch also performs a CPU reset after the CPU is registered rather than before. This patch has successfully booted the debian installer and the initrd kernel in sparc-test successfully for both an ss5 and ss10. It also makes running an ss10 openboot rom image behave a little better. Index: cpu-exec.c === RCS file: /sources/qemu/qemu/cpu-exec.c,v retrieving revision 1.120 diff -p -u -r1.120 cpu-exec.c --- cpu-exec.c 14 Oct 2007 07:07:04 - 1.120 +++ cpu-exec.c 6 Nov 2007 00:12:56 - @@ -181,10 +181,8 @@ static inline TranslationBlock *tb_find_ flags = (((env-pstate PS_PEF) 1) | ((env-fprs FPRS_FEF) 2)) | (env-pstate PS_PRIV) | ((env-lsu (DMMU_E | IMMU_E)) 2); #else -// FPU enable . MMU Boot . MMU enabled . MMU no-fault . Supervisor -flags = (env-psref 4) | (((env-mmuregs[0] MMU_BM) 14) 3) -| ((env-mmuregs[0] (MMU_E | MMU_NF)) 1) -| env-psrs; +// FPU enable . Supervisor +flags = (env-psref 4) | env-psrs; #endif cs_base = env-npc; pc = env-pc; Index: target-sparc/cpu.h === RCS file: /sources/qemu/qemu/target-sparc/cpu.h,v retrieving revision 1.56 diff -p -u -r1.56 cpu.h --- target-sparc/cpu.h 14 Oct 2007 17:07:21 - 1.56 +++ target-sparc/cpu.h 6 Nov 2007 00:13:00 - @@ -147,7 +147,6 @@ /* MMU */ #define MMU_E (10) #define MMU_NF(11) -#define MMU_BM(114) #define PTE_ENTRYTYPE_MASK 3 #define PTE_ACCESS_MASK0x1c @@ -200,6 +199,7 @@ typedef struct CPUSPARCState { int interrupt_index; int interrupt_request; int halted; +uint32_t mmu_bm; /* NOTE: we allow 8 more registers to handle wrapping */ target_ulong regbase[NWINDOWS * 16 + 8]; Index: target-sparc/helper.c === RCS file: /sources/qemu/qemu/target-sparc/helper.c,v retrieving revision 1.28 diff -p -u -r1.28 helper.c --- target-sparc/helper.c 14 Oct 2007 07:07:08 - 1.28 +++ target-sparc/helper.c 6 Nov 2007 00:13:00 - @@ -114,7 +114,7 @@ int get_physical_address (CPUState *env, if ((env-mmuregs[0] MMU_E) == 0) { /* MMU disabled */ // Boot mode: instruction fetches are taken from PROM -if (rw == 2 (env-mmuregs[0] MMU_BM)) { +if (rw == 2 (env-mmuregs[0] env-mmu_bm)) { *physical = 0xff000ULL | (address 0x3ULL); *prot = PAGE_READ | PAGE_EXEC; return 0; Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.50 diff -p -u -r1.50 op_helper.c --- target-sparc/op_helper.c29 Oct 2007 14:39:49 - 1.50 +++ target-sparc/op_helper.c6 Nov 2007 00:13:01 - @@ -493,8 +493,8 @@ void helper_st_asi(int asi, int size) oldreg = env-mmuregs[reg]; switch(reg) { case 0: -env-mmuregs[reg] = ~(MMU_E | MMU_NF | MMU_BM); -env-mmuregs[reg] |= T1 (MMU_E | MMU_NF | MMU_BM); +env-mmuregs[reg] = ~(MMU_E | MMU_NF | env-mmu_bm); +env-mmuregs[reg] |= T1 (MMU_E | MMU_NF | env-mmu_bm); // Mappings generated during no-fault mode or MMU // disabled mode are invalid in normal mode if (oldreg != env-mmuregs[reg]) Index: target-sparc/translate.c === RCS file: /sources/qemu/qemu/target-sparc/translate.c,v retrieving revision 1.78 diff -p -u -r1.78 translate.c --- target-sparc/translate.c17 Oct 2007 17:34:57 - 1.78 +++ target-sparc/translate.c6 Nov 2007 00:13:03 - @@ -59,6 +59,7 @@ struct sparc_def_t { target_ulong iu_version; uint32_t fpu_version; uint32_t mmu_version; +uint32_t mmu_bm; }; static uint16_t *gen_opc_ptr; @@ -3482,7 +3483,7 @@ void cpu_reset(CPUSPARCState *env) #else env-pc = 0; env-mmuregs[0] = ~(MMU_E | MMU_NF); -env-mmuregs[0] |= MMU_BM; +env-mmuregs[0] |= env-mmu_bm; #endif env-npc = env-pc + 4; #endif @@ -3496,7 +3497,6 @@ CPUSPARCState *cpu_sparc_init(void) if (!env) return NULL; cpu_exec_init(env); -cpu_reset(env); return (env); } @@ -3515,30 +3515,35 @@ static const sparc_def_t sparc_defs[] = .iu_version = 0x04 24, /* Impl 0, ver 4 */ .fpu_version = 4 17, /* FPU version 4 (Meiko) */ .mmu_version = 0x04 24, /*
[Qemu-devel] [PATCH] sparc32: hw/slavio_misc.c sysctrl register is 32 bits
The sysctrl register is actually 32 bits. Add code to access it as 32 bits. Index: hw/slavio_misc.c === RCS file: /sources/qemu/qemu/hw/slavio_misc.c,v retrieving revision 1.10 diff -p -u -r1.10 slavio_misc.c --- hw/slavio_misc.c6 Oct 2007 11:28:21 - 1.10 +++ hw/slavio_misc.c4 Nov 2007 15:21:17 - @@ -44,10 +44,12 @@ typedef struct MiscState { qemu_irq irq; uint8_t config; uint8_t aux1, aux2; -uint8_t diag, mctrl, sysctrl; +uint8_t diag, mctrl; +uint32_t sysctrl; } MiscState; #define MISC_SIZE 1 +#define SYSCTRL_SIZE 4 static void slavio_misc_update_irq(void *opaque) { @@ -116,13 +118,6 @@ static void slavio_misc_mem_writeb(void MISC_DPRINTF(Write modem control %2.2x\n, val 0xff); s-mctrl = val 0xff; break; -case 0x1f0: -MISC_DPRINTF(Write system control %2.2x\n, val 0xff); -if (val 1) { -s-sysctrl = 0x2; -qemu_system_reset_request(); -} -break; case 0xa00: MISC_DPRINTF(Write power management %2.2x\n, val 0xff); cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT); @@ -156,10 +151,6 @@ static uint32_t slavio_misc_mem_readb(vo ret = s-mctrl; MISC_DPRINTF(Read modem control %2.2x\n, ret); break; -case 0x1f0: -MISC_DPRINTF(Read system control %2.2x\n, ret); -ret = s-sysctrl; -break; case 0xa00: MISC_DPRINTF(Read power management %2.2x\n, ret); break; @@ -178,6 +169,47 @@ static CPUWriteMemoryFunc *slavio_misc_m slavio_misc_mem_writeb, slavio_misc_mem_writeb, }; + +static uint32_t slavio_misc_mem_readl(void *opaque, target_phys_addr_t addr) +{ +MiscState *s = opaque; +uint32_t ret = 0; + +switch (addr) { +case 0x1f0: +MISC_DPRINTF(Read system control %08x\n, ret); +ret = s-sysctrl; +break; +} +return ret; +} + +static void slavio_misc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +MiscState *s = opaque; + +switch (addr) { +case 0x1f0: +MISC_DPRINTF(Write system control %08x\n, val); +if (val 1) { +s-sysctrl = 0x2; +qemu_system_reset_request(); +} +break; +} +} + +static CPUReadMemoryFunc *slavio_misc_mem_read32[3] = { +slavio_misc_mem_readl, +slavio_misc_mem_readl, +slavio_misc_mem_readl, +}; + +static CPUWriteMemoryFunc *slavio_misc_mem_write32[3] = { +slavio_misc_mem_writel, +slavio_misc_mem_writel, +slavio_misc_mem_writel, +}; static void slavio_misc_save(QEMUFile *f, void *opaque) { @@ -191,7 +223,7 @@ static void slavio_misc_save(QEMUFile *f qemu_put_8s(f, s-aux2); qemu_put_8s(f, s-diag); qemu_put_8s(f, s-mctrl); -qemu_put_8s(f, s-sysctrl); +qemu_put_be32s(f, s-sysctrl); } static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id) @@ -208,20 +240,21 @@ static int slavio_misc_load(QEMUFile *f, qemu_get_8s(f, s-aux2); qemu_get_8s(f, s-diag); qemu_get_8s(f, s-mctrl); -qemu_get_8s(f, s-sysctrl); +qemu_get_be32s(f, s-sysctrl); return 0; } void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t power_base, qemu_irq irq) { -int slavio_misc_io_memory; +int slavio_misc_io_memory, slavio_misc_io_memory32; MiscState *s; s = qemu_mallocz(sizeof(MiscState)); if (!s) return NULL; +/* 8 bit registers */ slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read, slavio_misc_mem_write, s); // Slavio control cpu_register_physical_memory(base + 0x180, MISC_SIZE, @@ -238,12 +271,15 @@ void *slavio_misc_init(target_phys_addr_ // Modem control cpu_register_physical_memory(base + 0x1b0, MISC_SIZE, slavio_misc_io_memory); -// System control -cpu_register_physical_memory(base + 0x1f0, MISC_SIZE, - slavio_misc_io_memory); // Power management cpu_register_physical_memory(power_base, MISC_SIZE, slavio_misc_io_memory); +/* 32 bit registers */ +slavio_misc_io_memory32 = cpu_register_io_memory(0, slavio_misc_mem_read32, slavio_misc_mem_write32, s); +// System control +cpu_register_physical_memory(base + 0x1f0, SYSCTRL_SIZE, + slavio_misc_io_memory32); + s-irq = irq; register_savevm(slavio_misc, base, 1, slavio_misc_save, slavio_misc_load, s);
Re: [Qemu-devel] [PATCH] sparc32: hw/slavio_misc.c sysctrl register is 32 bits
Please use this version. The previous version didn't mask off the top address bit. The sysctrl register is actually 32 bits. Add code to access it as 32 bits. Index: hw/slavio_misc.c === RCS file: /sources/qemu/qemu/hw/slavio_misc.c,v retrieving revision 1.10 diff -p -u -r1.10 slavio_misc.c --- hw/slavio_misc.c6 Oct 2007 11:28:21 - 1.10 +++ hw/slavio_misc.c4 Nov 2007 15:29:45 - @@ -44,10 +44,12 @@ typedef struct MiscState { qemu_irq irq; uint8_t config; uint8_t aux1, aux2; -uint8_t diag, mctrl, sysctrl; +uint8_t diag, mctrl; +uint32_t sysctrl; } MiscState; #define MISC_SIZE 1 +#define SYSCTRL_SIZE 4 static void slavio_misc_update_irq(void *opaque) { @@ -116,13 +118,6 @@ static void slavio_misc_mem_writeb(void MISC_DPRINTF(Write modem control %2.2x\n, val 0xff); s-mctrl = val 0xff; break; -case 0x1f0: -MISC_DPRINTF(Write system control %2.2x\n, val 0xff); -if (val 1) { -s-sysctrl = 0x2; -qemu_system_reset_request(); -} -break; case 0xa00: MISC_DPRINTF(Write power management %2.2x\n, val 0xff); cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT); @@ -156,10 +151,6 @@ static uint32_t slavio_misc_mem_readb(vo ret = s-mctrl; MISC_DPRINTF(Read modem control %2.2x\n, ret); break; -case 0x1f0: -MISC_DPRINTF(Read system control %2.2x\n, ret); -ret = s-sysctrl; -break; case 0xa00: MISC_DPRINTF(Read power management %2.2x\n, ret); break; @@ -178,6 +169,47 @@ static CPUWriteMemoryFunc *slavio_misc_m slavio_misc_mem_writeb, slavio_misc_mem_writeb, }; + +static uint32_t slavio_misc_mem_readl(void *opaque, target_phys_addr_t addr) +{ +MiscState *s = opaque; +uint32_t ret = 0; + +switch (addr 0xfff) { +case 0x1f0: +MISC_DPRINTF(Read system control %08x\n, ret); +ret = s-sysctrl; +break; +} +return ret; +} + +static void slavio_misc_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +MiscState *s = opaque; + +switch (addr 0xfff) { +case 0x1f0: +MISC_DPRINTF(Write system control %08x\n, val); +if (val 1) { +s-sysctrl = 0x2; +qemu_system_reset_request(); +} +break; +} +} + +static CPUReadMemoryFunc *slavio_misc_mem_read32[3] = { +slavio_misc_mem_readl, +slavio_misc_mem_readl, +slavio_misc_mem_readl, +}; + +static CPUWriteMemoryFunc *slavio_misc_mem_write32[3] = { +slavio_misc_mem_writel, +slavio_misc_mem_writel, +slavio_misc_mem_writel, +}; static void slavio_misc_save(QEMUFile *f, void *opaque) { @@ -191,7 +223,7 @@ static void slavio_misc_save(QEMUFile *f qemu_put_8s(f, s-aux2); qemu_put_8s(f, s-diag); qemu_put_8s(f, s-mctrl); -qemu_put_8s(f, s-sysctrl); +qemu_put_be32s(f, s-sysctrl); } static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id) @@ -208,20 +240,21 @@ static int slavio_misc_load(QEMUFile *f, qemu_get_8s(f, s-aux2); qemu_get_8s(f, s-diag); qemu_get_8s(f, s-mctrl); -qemu_get_8s(f, s-sysctrl); +qemu_get_be32s(f, s-sysctrl); return 0; } void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t power_base, qemu_irq irq) { -int slavio_misc_io_memory; +int slavio_misc_io_memory, slavio_misc_io_memory32; MiscState *s; s = qemu_mallocz(sizeof(MiscState)); if (!s) return NULL; +/* 8 bit registers */ slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read, slavio_misc_mem_write, s); // Slavio control cpu_register_physical_memory(base + 0x180, MISC_SIZE, @@ -238,12 +271,15 @@ void *slavio_misc_init(target_phys_addr_ // Modem control cpu_register_physical_memory(base + 0x1b0, MISC_SIZE, slavio_misc_io_memory); -// System control -cpu_register_physical_memory(base + 0x1f0, MISC_SIZE, - slavio_misc_io_memory); // Power management cpu_register_physical_memory(power_base, MISC_SIZE, slavio_misc_io_memory); +/* 32 bit registers */ +slavio_misc_io_memory32 = cpu_register_io_memory(0, slavio_misc_mem_read32, slavio_misc_mem_write32, s); +// System control +cpu_register_physical_memory(base + 0x1f0, SYSCTRL_SIZE, + slavio_misc_io_memory32); + s-irq = irq; register_savevm(slavio_misc, base, 1, slavio_misc_save, slavio_misc_load, s);
[Qemu-devel] sparc hflags support?
I'm looking at adding more complete support for different sparc32 CPUs, MMUs, cache controllers and systems. Each CPU/MMU/cache controller combination is slightly different and requires its own unique state. For example the two CPUs currently supported save the boot mode in different bits in the MMU control register: 0x2000 for the SuperSparc and 0x4000 for the TurboSparc. Others bits will need to be saved in the MMU and cache controllers as better hardware emulation is added. It looks like other architectures handle this by computing hflags in the target directories but sparc determines the flags value to save in common code. Are there plans to add hflags support to sparc? I'm willing work on it but I don't have the experience yet to tackle a job like this without help.
Re: [Qemu-devel] [RFC] sparc32 MXCC support
Blue Swirl wrote: On 10/13/07, Robert Reif [EMAIL PROTECTED] wrote: I'm trying to add SuperSparc II MXCC support and need some feedback. Is there a better way to read and write physical memory in 64bit chunks? I'm not sure what I'm doing is portable between 32/64 and big/little endian. Thank you for your effort. Applying the patch allows NetBSD on SS-10 to boot as far as on SS-5, previously it crashed. I think the code is portable, but I think changing the register type to uint32_t and using a DPRINTF system like used in for example hw/iommu.c should make the code slightly clearer. I don't have access to chip specs but from reading linux and *bsd code it appears that the registers are 64 bits wide but sometimes accessed as 32 bits to get only the bottom 32 bits. Do you mean using two uint32_t for a 64 bit register? How about a union of 2 uint32_t and a uint64_t. Is that portable? Never mind. I just found out there is an ldq_phys and stq_phys. I'll use those. I looked at DPRINTF but would need a DPRINTF_MMU and DPRINTF_MXCC ... Would that be acceptable? For the memory access, ldl/q_phys/stl/q_phys is used in other block copy routines. For longer blocks or if the address can be unaligned, cpu_physical_memory_read() could be a better choice. +int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def, int cpu); unsigned int cpu? OK +printf(ERROR: helper_ld_asi(asi = %d, size = %d, sign = %d) T0 = %08x: unsupported size\n, asi, size, sign, T0); If it's an error to access the registers with different size, you should use do_unassigned_access() to report this. These are more for me to make sure I catch all the necessary accesses without adding unnecessary code. linux 2.4 and netbsd only use the ones I have implemented. openboot uses more and also some undocumented ones which are caught by this but I don't know how to handle them yet. I will use do_unassigned_access where necessary now. Thanks for the review.
[Qemu-devel] [PATCH] sparc32: add MXCC support
Updated patch base of feedback. This patch adds SuperSparc MXCC support. DPRINTF_MMU and DPRINTF_MXCC added. I decided not to use do_unassigned_access() at this time because I don't know what real hardware does. Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.55 diff -p -u -r1.55 sun4m.c --- hw/sun4m.c 6 Oct 2007 11:28:21 - 1.55 +++ hw/sun4m.c 14 Oct 2007 15:07:52 - @@ -327,7 +327,7 @@ static void *sun4m_hw_init(const struct for(i = 0; i smp_cpus; i++) { env = cpu_init(); -cpu_sparc_register(env, def); +cpu_sparc_register(env, def, i); envs[i] = env; if (i == 0) { qemu_register_reset(main_cpu_reset, env); Index: linux-user/main.c === RCS file: /sources/qemu/qemu/linux-user/main.c,v retrieving revision 1.132 diff -p -u -r1.132 main.c --- linux-user/main.c 12 Oct 2007 06:47:46 - 1.132 +++ linux-user/main.c 14 Oct 2007 15:07:53 - @@ -2139,7 +2139,7 @@ int main(int argc, char **argv) fprintf(stderr, Unable to find Sparc CPU definition\n); exit(1); } -cpu_sparc_register(env, def); +cpu_sparc_register(env, def, 0); env-pc = regs-pc; env-npc = regs-npc; env-y = regs-y; Index: target-sparc/cpu.h === RCS file: /sources/qemu/qemu/target-sparc/cpu.h,v retrieving revision 1.53 diff -p -u -r1.53 cpu.h --- target-sparc/cpu.h 12 Oct 2007 06:47:46 - 1.53 +++ target-sparc/cpu.h 14 Oct 2007 15:07:53 - @@ -210,6 +210,8 @@ typedef struct CPUSPARCState { uint64_t dtlb_tte[64]; #else uint32_t mmuregs[16]; +uint64_t mxccdata[4]; +uint64_t mxccregs[8]; #endif /* temporary float registers */ float32 ft0, ft1; @@ -266,7 +268,7 @@ int cpu_sparc_close(CPUSPARCState *s); int sparc_find_by_name (const unsigned char *name, const sparc_def_t **def); void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); -int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def); +int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def, unsigned int cpu); #define GET_PSR(env) (env-version | (env-psr PSR_ICC) | \ (env-psref? PSR_EF : 0) |\ Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.41 diff -p -u -r1.41 op_helper.c --- target-sparc/op_helper.c1 Oct 2007 17:07:58 - 1.41 +++ target-sparc/op_helper.c14 Oct 2007 15:07:54 - @@ -2,9 +2,24 @@ //#define DEBUG_PCALL //#define DEBUG_MMU +//#define DEBUG_MXCC //#define DEBUG_UNALIGNED //#define DEBUG_UNASSIGNED +#ifdef DEBUG_MMU +#define DPRINTF_MMU(fmt, args...) \ +do { printf(MMU: fmt , ##args); } while (0) +#else +#define DPRINTF_MMU(fmt, args...) +#endif + +#ifdef DEBUG_MXCC +#define DPRINTF_MXCC(fmt, args...) \ +do { printf(MXCC: fmt , ##args); } while (0) +#else +#define DPRINTF_MXCC(fmt, args...) +#endif + void raise_exception(int tt) { env-exception_index = tt; @@ -139,12 +154,57 @@ GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, #ifndef TARGET_SPARC64 #ifndef CONFIG_USER_ONLY + +#ifdef DEBUG_MXCC +void dump_mxcc(CPUState *env) +{ +printf(mxccdata: %016llx %016llx %016llx %016llx\n, +env-mxccdata[0], env-mxccdata[1], env-mxccdata[2], env-mxccdata[3]); +printf(mxccregs: %016llx %016llx %016llx %016llx\n + %016llx %016llx %016llx %016llx\n, +env-mxccregs[0], env-mxccregs[1], env-mxccregs[2], env-mxccregs[3], +env-mxccregs[4], env-mxccregs[5], env-mxccregs[6], env-mxccregs[7]); +} +#endif + void helper_ld_asi(int asi, int size, int sign) { uint32_t ret = 0; +#ifdef DEBUG_MXCC +uint32_t last_T0 = T0; +#endif switch (asi) { case 2: /* SuperSparc MXCC registers */ +switch (T0) { +case 0x01c00a00: /* MXCC control register */ +if (size == 8) { +ret = env-mxccregs[3]; +T0 = env-mxccregs[3] 32; +} else +DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +break; +case 0x01c00a04: /* MXCC control register */ +if (size == 4) +ret = env-mxccregs[3]; +else +DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0, size); +break; +case 0x01c00f00: /* MBus port address register */ +if (size == 8) { +ret = env-mxccregs[7]; +T0 = env-mxccregs[7] 32; +} else +DPRINTF_MXCC(%08x: unimplemented access size: %d\n, T0,
[Qemu-devel] [PATCH] sparc32 use stq_* for 64bit stores
Use stq_* for 64 bit stores. This fixes one bug where T1 was used twice rather than T1 and T2. Should the address be 64 bit alligned? i.e. T0 ~7 rather than T0 ~3? Should these unaligned address cause traps? Index: target-sparc/op_helper.c === RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.44 diff -p -u -r1.44 op_helper.c --- target-sparc/op_helper.c14 Oct 2007 17:07:21 - 1.44 +++ target-sparc/op_helper.c14 Oct 2007 18:28:37 - @@ -515,8 +515,7 @@ void helper_st_asi(int asi, int size) stl_user(T0 ~3, T1); break; case 8: -stl_user(T0 ~3, T1); -stl_user((T0 + 4) ~3, T2); +stq_user(T0 ~3, ((uint64_t)T1 32) | T2); break; } break; @@ -533,8 +532,7 @@ void helper_st_asi(int asi, int size) stl_kernel(T0 ~3, T1); break; case 8: -stl_kernel(T0 ~3, T1); -stl_kernel((T0 + 4) ~3, T2); +stq_kernel(T0 ~3, ((uint64_t)T1 32) | T2); break; } break; @@ -591,8 +589,7 @@ void helper_st_asi(int asi, int size) stl_phys(T0 ~3, T1); break; case 8: -stl_phys(T0 ~3, T1); -stl_phys((T0 + 4) ~3, T2); +stq_phys(T0 ~3, ((uint64_t)T1 32) | T2); break; } } @@ -615,10 +612,8 @@ void helper_st_asi(int asi, int size) | ((target_phys_addr_t)(asi 0xf) 32), T1); break; case 8: -stl_phys((target_phys_addr_t)(T0 ~3) - | ((target_phys_addr_t)(asi 0xf) 32), T1); -stl_phys((target_phys_addr_t)((T0 + 4) ~3) - | ((target_phys_addr_t)(asi 0xf) 32), T1); +stq_phys((target_phys_addr_t)(T0 ~3) + | ((target_phys_addr_t)(asi 0xf) 32), ((uint64_t)T1 32) | T2); break; } }
Re: [Qemu-devel] [PATCH] sparc32 use stq_* for 64bit stores
Blue Swirl wrote: On 10/14/07, Robert Reif [EMAIL PROTECTED] wrote: Should the address be 64 bit alligned? i.e. T0 ~7 rather than T0 ~3? Should these unaligned address cause traps? Yes, but the checks are already generated from translate.c (gen_op_check_align_T0_7). De we to align then again?
[Qemu-devel] [PATCH] sparc32 slaveio_timer user timer fixes
Some more user timer fixes. Index: hw/slavio_timer.c === RCS file: /sources/qemu/qemu/hw/slavio_timer.c,v retrieving revision 1.17 diff -p -u -r1.17 slavio_timer.c --- hw/slavio_timer.c 6 Oct 2007 11:28:21 - 1.17 +++ hw/slavio_timer.c 6 Oct 2007 12:28:53 - @@ -54,16 +54,24 @@ typedef struct SLAVIO_TIMERState { ptimer_state *timer; uint32_t count, counthigh, reached; uint64_t limit; -int stopped; -int mode; // 0 = processor, 1 = user, 2 = system +// processor only +int running; +struct SLAVIO_TIMERState *master; +int slave_index; +// system only struct SLAVIO_TIMERState *slave[MAX_CPUS]; uint32_t slave_mode; } SLAVIO_TIMERState; #define TIMER_MAXADDR 0x1f -#define TIMER_SIZE (TIMER_MAXADDR + 1) +#define SYS_TIMER_SIZE 0x14 #define CPU_TIMER_SIZE 0x10 +static int slavio_timer_is_user(SLAVIO_TIMERState *s) +{ +return s-master (s-master-slave_mode (1 s-slave_index)); +} + // Update count, set irq, update expire_time // Convert from ptimer countdown units static void slavio_timer_get_out(SLAVIO_TIMERState *s) @@ -84,9 +92,10 @@ static void slavio_timer_irq(void *opaqu slavio_timer_get_out(s); DPRINTF(callback: count %x%08x\n, s-counthigh, s-count); -s-reached = 0x8000; -if (s-mode != 1) +if (!slavio_timer_is_user(s)) { +s-reached = 0x8000; qemu_irq_raise(s-irq); +} } static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) @@ -99,35 +108,39 @@ static uint32_t slavio_timer_mem_readl(v case 0: // read limit (system counter mode) or read most signifying // part of counter (user mode) -if (s-mode != 1) { +if (slavio_timer_is_user(s)) { +// read user timer MSW +slavio_timer_get_out(s); +ret = s-counthigh; +} else { +// read limit // clear irq qemu_irq_lower(s-irq); s-reached = 0; ret = s-limit 0x7fff; } -else { -slavio_timer_get_out(s); -ret = s-counthigh 0x7fff; -} break; case 1: // read counter and reached bit (system mode) or read lsbits // of counter (user mode) slavio_timer_get_out(s); -if (s-mode != 1) -ret = (s-count 0x7fff) | s-reached; -else -ret = s-count; +if (slavio_timer_is_user(s)) // read user timer LSW +ret = s-count 0xffe00; +else // read limit +ret = (s-count 0x7e00) | s-reached; break; case 3: +// only available in processor counter/timer // read start/stop status -ret = s-stopped; +ret = s-running; break; case 4: +// only available in system counter // read user/system mode ret = s-slave_mode; break; default: +DPRINTF(invalid read address TARGET_FMT_plx \n, addr); ret = 0; break; } @@ -146,20 +159,31 @@ static void slavio_timer_mem_writel(void saddr = (addr TIMER_MAXADDR) 2; switch (saddr) { case 0: -if (s-mode == 1) { -// set user counter limit MSW, reset counter +if (slavio_timer_is_user(s)) { +// set user counter MSW, reset counter qemu_irq_lower(s-irq); -s-limit = 0xfe00ULL; -s-limit |= (uint64_t)val 32; +s-limit = 0x7e00ULL; +DPRINTF(processor %d user timer reset\n, s-slave_index); +ptimer_set_limit(s-timer, s-limit 9, 1); +} else { +// set limit, reset counter +qemu_irq_lower(s-irq); +s-limit = val 0x7e00ULL; if (!s-limit) -s-limit = 0x7e00ULL; +s-limit = 0x7e00ULL; ptimer_set_limit(s-timer, s-limit 9, 1); -break; } -// set limit, reset counter -reload = 1; -qemu_irq_lower(s-irq); -// fall through +break; +case 1: +if (slavio_timer_is_user(s)) { +// set user counter LSW, reset counter +qemu_irq_lower(s-irq); +s-limit = 0x7e00ULL; +DPRINTF(processor %d user timer reset\n, s-slave_index); +ptimer_set_limit(s-timer, s-limit 9, 1); +} else +DPRINTF(not user timer\n); +break; case 2: // set limit without resetting counter s-limit = val 0x7e00ULL; @@ -167,52 +191,42 @@ static void slavio_timer_mem_writel(void s-limit = 0x7e00ULL; ptimer_set_limit(s-timer, s-limit 9, reload); break; -case 1: -// set user counter limit LSW, reset counter -if (s-mode == 1) { -
[Qemu-devel] [PATCH] Add support to sparc for loading a real bios image.
Add support to sparc for loading a real bios image. Index: hw/sun4m.c === RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.52 diff -p -u -r1.52 sun4m.c --- hw/sun4m.c 5 Oct 2007 13:08:35 - 1.52 +++ hw/sun4m.c 6 Oct 2007 00:05:16 - @@ -49,7 +49,7 @@ #define KERNEL_LOAD_ADDR 0x4000 #define CMDLINE_ADDR 0x007ff000 #define INITRD_LOAD_ADDR 0x0080 -#define PROM_SIZE_MAX(256 * 1024) +#define PROM_SIZE_MAX(512 * 1024) #define PROM_PADDR 0xff000ULL #define PROM_VADDR 0xffd0 #define PROM_FILENAME openbios-sparc32 @@ -435,9 +435,12 @@ static void sun4m_load_kernel(long vram_ snprintf(buf, sizeof(buf), %s/%s, bios_dir, bios_name); ret = load_elf(buf, PROM_PADDR - PROM_VADDR, NULL, NULL, NULL); if (ret 0) { - fprintf(stderr, qemu: could not load prom '%s'\n, +ret = load_image(buf, phys_ram_base + prom_offset); + if (ret 0) { + fprintf(stderr, qemu: could not load prom '%s'\n, buf); - exit(1); + exit(1); + } } kernel_size = 0;
[Qemu-devel] sparc32 CVS broken
Sparc32 CVS exits after illegal instruction trap. [H[JNvram id QEMU_BIOS, version 1, machine id 0x80 CPUs: 1 Welcome to OpenBIOS v1.0RC1 built on Aug 11 2007 08:00 Type 'help' for detailed information [sparc] Kernel already loaded qemu: fatal: Trap 0x02 while interrupts disabled, Error state pc: ffd0108c npc: ffd01090 General Registers: %g0: %g1: 0002 %g2: 04401fc2 %g3: ffd7f018 %g4: 0028 %g5: %g6: %g7: Current Register Window: %o0: 000a %o1: 0022d570 %o2: ffd3b8a6 %o3: ffdd2ce0 %o4: ffd08568 %o5: ffd08578 %o6: ffdd2a30 %o7: ffd0100c %l0: ffd7f15c %l1: 4000 %l2: 4004 %l3: ffd3c000 %l4: ffd7f000 %l5: ffd7f000 %l6: ffd80c00 %l7: ffd0 %i0: ffd7f15c %i1: %i2: %i3: %i4: %i5: %i6: ffdd2c98 %i7: ffd06310 Floating Point Registers: %f00: 0.00 0.00 0.00 0.00 %f04: 0.00 0.00 0.00 0.00 %f08: 0.00 0.00 0.00 0.00 %f12: 0.00 0.00 0.00 0.00 %f16: 0.00 0.00 0.00 0.00 %f20: 0.00 0.00 0.00 0.00 %f24: 0.00 0.00 0.00 0.00 %f28: 0.00 0.00 0.00 0.00 psr: 0x04401fc2 - Z--- SP- wim: 0x0010 fsr: 0x0008 ./qemu-nog: line 4: 5400 Aborted qemu-system-sparc -kernel vmlinux-2.6.11+tcx -initrd linux.img -append root=/dev/ram console=ttyS0 video=tcxfb:off -nographic
[Qemu-devel] sparc32 counter/timer issues
I'm trying to run a real ss10 openboot prom image rather than the supplied prom image and found some issues with the way counters and timers are implemented. It appears that the processor and system counter/timers are not independent. The system config register actually configures the processor counter/timers and the config register is actually a bit mask of the counter/timer to configure. 1, 2, 4, and 8 are used to as config values for each processor counter/timer and 0xf is used for setting all of them. This isn't apparent in the slaveio documentation because it is for a single cpu only. Because the system config register configures the processor timers, it needs access to all the processor timers (or the processor timers need access to the system timer). This isn't how it's currently implemented.
Re: [Qemu-devel] sparc32 counter/timer issues
With the patch and ss10 boot prom I get: TIMER: write 000ff13c TIMER: write 000ff1310010 0001 TIMER: write 000ff130 TIMER: write 000ff134 TIMER: write 000ff13c 0001 TIMER: write 000ff130 TIMER: write 000ff134 TIMER: get_out: limit 7e00 count 0 TIMER: read 000ff130 = with the last two lines repeating forever.
[Qemu-devel] sparc32 networking working?
I'm trying to use sparc32 on linux i686 RH9 and am unable to to get this working with current CVS. My old scripts that didn't set any networking options no longer work. When running a debian sparc netinst cd the setup finds a dhcp connection but is unable to connect to the internet. Adding -user to the command line causes it to output this: Invalid vlan (0) with no nics Adding -nic lance to the command line cause it to output this: qemu-system-sparc: invalid option -- '-nic' Any idea on what to do next. If I remember correctly, the last time I tried this (a few months ago) I was able to successfully do a debian network install.
[Qemu-devel] Current CVS build errors on RH9
It's been a few months since I comipled from source so I just tried with current CVS and got these errors on RH9: /home/wine/qemu/linux-user/syscall.c: In function `sys_tgkill': /home/wine/qemu/linux-user/syscall.c:170: `__NR_tgkill' undeclared (first use in this function) /home/wine/qemu/linux-user/syscall.c:170: (Each undeclared identifier is reported only once /home/wine/qemu/linux-user/syscall.c:170: for each function it appears in.) in various subdirectories and: /home/wine/qemu/vl.c:59:24: linux/hpet.h: No such file or directory /home/wine/qemu/vl.c: In function `hpet_start_timer': /home/wine/qemu/vl.c:1222: storage size of `info' isn't known /home/wine/qemu/vl.c:1230: `HPET_IRQFREQ' undeclared (first use in this function) /home/wine/qemu/vl.c:1230: (Each undeclared identifier is reported only once /home/wine/qemu/vl.c:1230: for each function it appears in.) /home/wine/qemu/vl.c:1239: `HPET_INFO' undeclared (first use in this function) /home/wine/qemu/vl.c:1244: `HPET_EPI' undeclared (first use in this function) /home/wine/qemu/vl.c:1249: `HPET_IE_ON' undeclared (first use in this function) /home/wine/qemu/vl.c:1222: warning: unused variable `info' in various other subdirectories.