Initial SPARC SMP support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1694 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
b9788fc4c4
commit
ba3c64fb47
@ -16,6 +16,7 @@ version 0.7.3:
|
|||||||
- MIPS User Linux emulation
|
- MIPS User Linux emulation
|
||||||
- MIPS fixes to boot Linux (Daniel Jacobowitz)
|
- MIPS fixes to boot Linux (Daniel Jacobowitz)
|
||||||
- NX bit support
|
- NX bit support
|
||||||
|
- Initial SPARC SMP support (Blue Swirl)
|
||||||
|
|
||||||
version 0.7.2:
|
version 0.7.2:
|
||||||
|
|
||||||
|
@ -734,6 +734,7 @@ extern int code_copy_enabled;
|
|||||||
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
|
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
|
||||||
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
|
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
|
||||||
#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
|
#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
|
||||||
|
#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
|
||||||
|
|
||||||
void cpu_interrupt(CPUState *s, int mask);
|
void cpu_interrupt(CPUState *s, int mask);
|
||||||
void cpu_reset_interrupt(CPUState *env, int mask);
|
void cpu_reset_interrupt(CPUState *env, int mask);
|
||||||
|
12
cpu-exec.c
12
cpu-exec.c
@ -274,6 +274,15 @@ int cpu_exec(CPUState *env1)
|
|||||||
return EXCP_HALTED;
|
return EXCP_HALTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#elif defined(TARGET_SPARC)
|
||||||
|
if (env1->halted) {
|
||||||
|
if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||||
|
(env1->psret != 0)) {
|
||||||
|
env1->halted = 0;
|
||||||
|
} else {
|
||||||
|
return EXCP_HALTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
#elif defined(TARGET_ARM)
|
#elif defined(TARGET_ARM)
|
||||||
if (env1->halted) {
|
if (env1->halted) {
|
||||||
/* An interrupt wakes the CPU even if the I and F CPSR bits are
|
/* An interrupt wakes the CPU even if the I and F CPSR bits are
|
||||||
@ -522,6 +531,9 @@ int cpu_exec(CPUState *env1)
|
|||||||
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
|
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
|
||||||
//do_interrupt(0, 0, 0, 0, 0);
|
//do_interrupt(0, 0, 0, 0, 0);
|
||||||
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
|
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
|
||||||
|
} else if (interrupt_request & CPU_INTERRUPT_HALT) {
|
||||||
|
env1->halted = 1;
|
||||||
|
return EXCP_HALTED;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_ARM)
|
#elif defined(TARGET_ARM)
|
||||||
if (interrupt_request & CPU_INTERRUPT_FIQ
|
if (interrupt_request & CPU_INTERRUPT_FIQ
|
||||||
|
@ -53,6 +53,7 @@ typedef struct SLAVIO_INTCTLState {
|
|||||||
#ifdef DEBUG_IRQ_COUNT
|
#ifdef DEBUG_IRQ_COUNT
|
||||||
uint64_t irq_count[32];
|
uint64_t irq_count[32];
|
||||||
#endif
|
#endif
|
||||||
|
CPUState *cpu_envs[MAX_CPUS];
|
||||||
} SLAVIO_INTCTLState;
|
} SLAVIO_INTCTLState;
|
||||||
|
|
||||||
#define INTCTL_MAXADDR 0xf
|
#define INTCTL_MAXADDR 0xf
|
||||||
@ -96,6 +97,7 @@ static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint
|
|||||||
case 2: // set softint
|
case 2: // set softint
|
||||||
val &= 0xfffe0000;
|
val &= 0xfffe0000;
|
||||||
s->intreg_pending[cpu] |= val;
|
s->intreg_pending[cpu] |= val;
|
||||||
|
slavio_check_interrupts(s);
|
||||||
DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
|
DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -216,7 +218,7 @@ static void slavio_check_interrupts(void *opaque)
|
|||||||
CPUState *env;
|
CPUState *env;
|
||||||
SLAVIO_INTCTLState *s = opaque;
|
SLAVIO_INTCTLState *s = opaque;
|
||||||
uint32_t pending = s->intregm_pending;
|
uint32_t pending = s->intregm_pending;
|
||||||
unsigned int i, max = 0;
|
unsigned int i, j, max = 0;
|
||||||
|
|
||||||
pending &= ~s->intregm_disabled;
|
pending &= ~s->intregm_disabled;
|
||||||
|
|
||||||
@ -227,9 +229,15 @@ static void slavio_check_interrupts(void *opaque)
|
|||||||
max = intbit_to_level[i];
|
max = intbit_to_level[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
env = first_cpu;
|
env = s->cpu_envs[s->target_cpu];
|
||||||
|
if (!env) {
|
||||||
|
DPRINTF("No CPU %d, not triggered (pending %x)\n", s->target_cpu, pending);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (env->halted)
|
||||||
|
env->halted = 0;
|
||||||
if (env->interrupt_index == 0) {
|
if (env->interrupt_index == 0) {
|
||||||
DPRINTF("Triggered pil %d\n", max);
|
DPRINTF("Triggered CPU %d pil %d\n", s->target_cpu, max);
|
||||||
#ifdef DEBUG_IRQ_COUNT
|
#ifdef DEBUG_IRQ_COUNT
|
||||||
s->irq_count[max]++;
|
s->irq_count[max]++;
|
||||||
#endif
|
#endif
|
||||||
@ -239,8 +247,34 @@ static void slavio_check_interrupts(void *opaque)
|
|||||||
else
|
else
|
||||||
DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
|
DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
|
DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_CPUS; i++) {
|
||||||
|
max = 0;
|
||||||
|
env = s->cpu_envs[i];
|
||||||
|
if (!env)
|
||||||
|
continue;
|
||||||
|
for (j = 17; j < 32; j++) {
|
||||||
|
if (s->intreg_pending[i] & (1 << j)) {
|
||||||
|
if (max < j - 16)
|
||||||
|
max = j - 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (max > 0) {
|
||||||
|
if (env->halted)
|
||||||
|
env->halted = 0;
|
||||||
|
if (env->interrupt_index == 0) {
|
||||||
|
DPRINTF("Triggered softint %d for cpu %d (pending %x)\n", max, i, pending);
|
||||||
|
#ifdef DEBUG_IRQ_COUNT
|
||||||
|
s->irq_count[max]++;
|
||||||
|
#endif
|
||||||
|
env->interrupt_index = TT_EXTINT | max;
|
||||||
|
cpu_interrupt(env, CPU_INTERRUPT_HARD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -251,7 +285,7 @@ void slavio_pic_set_irq(void *opaque, int irq, int level)
|
|||||||
{
|
{
|
||||||
SLAVIO_INTCTLState *s = opaque;
|
SLAVIO_INTCTLState *s = opaque;
|
||||||
|
|
||||||
DPRINTF("Set irq %d level %d\n", irq, level);
|
DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level);
|
||||||
if (irq < 32) {
|
if (irq < 32) {
|
||||||
uint32_t mask = 1 << irq;
|
uint32_t mask = 1 << irq;
|
||||||
uint32_t pil = intbit_to_level[irq];
|
uint32_t pil = intbit_to_level[irq];
|
||||||
@ -269,6 +303,29 @@ void slavio_pic_set_irq(void *opaque, int irq, int level)
|
|||||||
slavio_check_interrupts(s);
|
slavio_check_interrupts(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu)
|
||||||
|
{
|
||||||
|
SLAVIO_INTCTLState *s = opaque;
|
||||||
|
|
||||||
|
DPRINTF("Set cpu %d local irq %d level %d\n", cpu, irq, level);
|
||||||
|
if (cpu == (unsigned int)-1) {
|
||||||
|
slavio_pic_set_irq(opaque, irq, level);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (irq < 32) {
|
||||||
|
uint32_t pil = intbit_to_level[irq];
|
||||||
|
if (pil > 0) {
|
||||||
|
if (level) {
|
||||||
|
s->intreg_pending[cpu] |= 1 << pil;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s->intreg_pending[cpu] &= ~(1 << pil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slavio_check_interrupts(s);
|
||||||
|
}
|
||||||
|
|
||||||
static void slavio_intctl_save(QEMUFile *f, void *opaque)
|
static void slavio_intctl_save(QEMUFile *f, void *opaque)
|
||||||
{
|
{
|
||||||
SLAVIO_INTCTLState *s = opaque;
|
SLAVIO_INTCTLState *s = opaque;
|
||||||
@ -312,6 +369,12 @@ static void slavio_intctl_reset(void *opaque)
|
|||||||
s->target_cpu = 0;
|
s->target_cpu = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env)
|
||||||
|
{
|
||||||
|
SLAVIO_INTCTLState *s = opaque;
|
||||||
|
s->cpu_envs[cpu] = env;
|
||||||
|
}
|
||||||
|
|
||||||
void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
|
void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
|
||||||
{
|
{
|
||||||
int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
|
int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
|
||||||
|
@ -124,9 +124,8 @@ static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32
|
|||||||
case 0xa000000:
|
case 0xa000000:
|
||||||
MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
|
MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
|
||||||
#if 0
|
#if 0
|
||||||
// XXX: halting CPU does not work
|
// XXX almost works
|
||||||
raise_exception(EXCP_HLT);
|
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
|
||||||
cpu_loop_exit();
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,8 @@
|
|||||||
#ifdef DEBUG_SERIAL
|
#ifdef DEBUG_SERIAL
|
||||||
#define SER_DPRINTF(fmt, args...) \
|
#define SER_DPRINTF(fmt, args...) \
|
||||||
do { printf("SER: " fmt , ##args); } while (0)
|
do { printf("SER: " fmt , ##args); } while (0)
|
||||||
|
#define pic_set_irq(irq, level) \
|
||||||
|
do { printf("SER: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
|
||||||
#else
|
#else
|
||||||
#define SER_DPRINTF(fmt, args...)
|
#define SER_DPRINTF(fmt, args...)
|
||||||
#endif
|
#endif
|
||||||
@ -174,6 +176,50 @@ static void slavio_serial_reset(void *opaque)
|
|||||||
slavio_serial_reset_chn(&s->chn[1]);
|
slavio_serial_reset_chn(&s->chn[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void clr_rxint(ChannelState *s)
|
||||||
|
{
|
||||||
|
s->rxint = 0;
|
||||||
|
if (s->chn == 0)
|
||||||
|
s->rregs[3] &= ~0x20;
|
||||||
|
else {
|
||||||
|
s->otherchn->rregs[3] &= ~4;
|
||||||
|
}
|
||||||
|
slavio_serial_update_irq(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_rxint(ChannelState *s)
|
||||||
|
{
|
||||||
|
s->rxint = 1;
|
||||||
|
if (s->chn == 0)
|
||||||
|
s->rregs[3] |= 0x20;
|
||||||
|
else {
|
||||||
|
s->otherchn->rregs[3] |= 4;
|
||||||
|
}
|
||||||
|
slavio_serial_update_irq(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clr_txint(ChannelState *s)
|
||||||
|
{
|
||||||
|
s->txint = 0;
|
||||||
|
if (s->chn == 0)
|
||||||
|
s->rregs[3] &= ~0x10;
|
||||||
|
else {
|
||||||
|
s->otherchn->rregs[3] &= ~2;
|
||||||
|
}
|
||||||
|
slavio_serial_update_irq(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_txint(ChannelState *s)
|
||||||
|
{
|
||||||
|
s->txint = 1;
|
||||||
|
if (s->chn == 0)
|
||||||
|
s->rregs[3] |= 0x10;
|
||||||
|
else {
|
||||||
|
s->otherchn->rregs[3] |= 2;
|
||||||
|
}
|
||||||
|
slavio_serial_update_irq(s);
|
||||||
|
}
|
||||||
|
|
||||||
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
|
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
SerialState *ser = opaque;
|
SerialState *ser = opaque;
|
||||||
@ -198,10 +244,14 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint
|
|||||||
newreg |= 0x8;
|
newreg |= 0x8;
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
s->rxint = 0;
|
clr_rxint(s);
|
||||||
break;
|
break;
|
||||||
case 0x28:
|
case 0x28:
|
||||||
s->txint = 0;
|
clr_txint(s);
|
||||||
|
break;
|
||||||
|
case 0x38:
|
||||||
|
clr_rxint(s);
|
||||||
|
clr_txint(s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -247,12 +297,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint
|
|||||||
s->txint = 1;
|
s->txint = 1;
|
||||||
s->rregs[0] |= 4; // Tx buffer empty
|
s->rregs[0] |= 4; // Tx buffer empty
|
||||||
s->rregs[1] |= 1; // All sent
|
s->rregs[1] |= 1; // All sent
|
||||||
// Interrupts reported only on channel A
|
set_txint(s);
|
||||||
if (s->chn == 0)
|
|
||||||
s->rregs[3] |= 0x10;
|
|
||||||
else {
|
|
||||||
s->otherchn->rregs[3] |= 2;
|
|
||||||
}
|
|
||||||
slavio_serial_update_irq(s);
|
slavio_serial_update_irq(s);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -280,6 +325,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
|
|||||||
return ret;
|
return ret;
|
||||||
case 1:
|
case 1:
|
||||||
s->rregs[0] &= ~1;
|
s->rregs[0] &= ~1;
|
||||||
|
clr_rxint(s);
|
||||||
if (s->type == kbd)
|
if (s->type == kbd)
|
||||||
ret = get_queue(s);
|
ret = get_queue(s);
|
||||||
else
|
else
|
||||||
@ -304,16 +350,10 @@ static int serial_can_receive(void *opaque)
|
|||||||
|
|
||||||
static void serial_receive_byte(ChannelState *s, int ch)
|
static void serial_receive_byte(ChannelState *s, int ch)
|
||||||
{
|
{
|
||||||
|
SER_DPRINTF("put ch %d\n", ch);
|
||||||
s->rregs[0] |= 1;
|
s->rregs[0] |= 1;
|
||||||
// Interrupts reported only on channel A
|
|
||||||
if (s->chn == 0)
|
|
||||||
s->rregs[3] |= 0x20;
|
|
||||||
else {
|
|
||||||
s->otherchn->rregs[3] |= 4;
|
|
||||||
}
|
|
||||||
s->rx = ch;
|
s->rx = ch;
|
||||||
s->rxint = 1;
|
set_rxint(s);
|
||||||
slavio_serial_update_irq(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial_receive_break(ChannelState *s)
|
static void serial_receive_break(ChannelState *s)
|
||||||
|
@ -42,6 +42,9 @@ do { printf("TIMER: " fmt , ##args); } while (0)
|
|||||||
* The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
|
* The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
|
||||||
* are zero. Bit 31 is 1 when count has been reached.
|
* are zero. Bit 31 is 1 when count has been reached.
|
||||||
*
|
*
|
||||||
|
* Per-CPU timers interrupt local CPU, system timer uses normal
|
||||||
|
* interrupt routing.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct SLAVIO_TIMERState {
|
typedef struct SLAVIO_TIMERState {
|
||||||
@ -53,11 +56,11 @@ typedef struct SLAVIO_TIMERState {
|
|||||||
int irq;
|
int irq;
|
||||||
int reached, stopped;
|
int reached, stopped;
|
||||||
int mode; // 0 = processor, 1 = user, 2 = system
|
int mode; // 0 = processor, 1 = user, 2 = system
|
||||||
|
unsigned int cpu;
|
||||||
} SLAVIO_TIMERState;
|
} SLAVIO_TIMERState;
|
||||||
|
|
||||||
#define TIMER_MAXADDR 0x1f
|
#define TIMER_MAXADDR 0x1f
|
||||||
#define CNT_FREQ 2000000
|
#define CNT_FREQ 2000000
|
||||||
#define MAX_CPUS 16
|
|
||||||
|
|
||||||
// Update count, set irq, update expire_time
|
// Update count, set irq, update expire_time
|
||||||
static void slavio_timer_get_out(SLAVIO_TIMERState *s)
|
static void slavio_timer_get_out(SLAVIO_TIMERState *s)
|
||||||
@ -73,7 +76,7 @@ static void slavio_timer_get_out(SLAVIO_TIMERState *s)
|
|||||||
else
|
else
|
||||||
ticks = qemu_get_clock(vm_clock) - s->tick_offset;
|
ticks = qemu_get_clock(vm_clock) - s->tick_offset;
|
||||||
|
|
||||||
out = (ticks >= s->expire_time);
|
out = (ticks > s->expire_time);
|
||||||
if (out)
|
if (out)
|
||||||
s->reached = 0x80000000;
|
s->reached = 0x80000000;
|
||||||
if (!s->limit)
|
if (!s->limit)
|
||||||
@ -100,7 +103,7 @@ static void slavio_timer_get_out(SLAVIO_TIMERState *s)
|
|||||||
DPRINTF("irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
|
DPRINTF("irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
|
||||||
|
|
||||||
if (s->mode != 1)
|
if (s->mode != 1)
|
||||||
pic_set_irq(s->irq, out);
|
pic_set_irq_cpu(s->irq, out, s->cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
// timer callback
|
// timer callback
|
||||||
@ -127,7 +130,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
|
|||||||
// part of counter (user mode)
|
// part of counter (user mode)
|
||||||
if (s->mode != 1) {
|
if (s->mode != 1) {
|
||||||
// clear irq
|
// clear irq
|
||||||
pic_set_irq(s->irq, 0);
|
pic_set_irq_cpu(s->irq, 0, s->cpu);
|
||||||
s->count_load_time = qemu_get_clock(vm_clock);
|
s->count_load_time = qemu_get_clock(vm_clock);
|
||||||
s->reached = 0;
|
s->reached = 0;
|
||||||
return s->limit;
|
return s->limit;
|
||||||
@ -263,7 +266,7 @@ static void slavio_timer_reset(void *opaque)
|
|||||||
slavio_timer_get_out(s);
|
slavio_timer_get_out(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void slavio_timer_init_internal(uint32_t addr, int irq, int mode)
|
void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu)
|
||||||
{
|
{
|
||||||
int slavio_timer_io_memory;
|
int slavio_timer_io_memory;
|
||||||
SLAVIO_TIMERState *s;
|
SLAVIO_TIMERState *s;
|
||||||
@ -273,6 +276,7 @@ static void slavio_timer_init_internal(uint32_t addr, int irq, int mode)
|
|||||||
return;
|
return;
|
||||||
s->irq = irq;
|
s->irq = irq;
|
||||||
s->mode = mode;
|
s->mode = mode;
|
||||||
|
s->cpu = cpu;
|
||||||
s->irq_timer = qemu_new_timer(vm_clock, slavio_timer_irq, s);
|
s->irq_timer = qemu_new_timer(vm_clock, slavio_timer_irq, s);
|
||||||
|
|
||||||
slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
|
slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
|
||||||
@ -282,14 +286,3 @@ static void slavio_timer_init_internal(uint32_t addr, int irq, int mode)
|
|||||||
qemu_register_reset(slavio_timer_reset, s);
|
qemu_register_reset(slavio_timer_reset, s);
|
||||||
slavio_timer_reset(s);
|
slavio_timer_reset(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_CPUS; i++) {
|
|
||||||
slavio_timer_init_internal(addr1 + i * TARGET_PAGE_SIZE, irq1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
slavio_timer_init_internal(addr2, irq2, 2);
|
|
||||||
}
|
|
||||||
|
28
hw/sun4m.c
28
hw/sun4m.c
@ -56,6 +56,7 @@
|
|||||||
#define PHYS_JJ_FDC 0x71400000 /* Floppy */
|
#define PHYS_JJ_FDC 0x71400000 /* Floppy */
|
||||||
#define PHYS_JJ_FLOPPY_IRQ 22
|
#define PHYS_JJ_FLOPPY_IRQ 22
|
||||||
#define PHYS_JJ_ME_IRQ 30 /* Module error, power fail */
|
#define PHYS_JJ_ME_IRQ 30 /* Module error, power fail */
|
||||||
|
#define MAX_CPUS 16
|
||||||
|
|
||||||
/* TSC handling */
|
/* TSC handling */
|
||||||
|
|
||||||
@ -128,6 +129,8 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
|
|||||||
nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
|
nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
|
||||||
nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */
|
nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */
|
||||||
// NVRAM_size, arch not applicable
|
// NVRAM_size, arch not applicable
|
||||||
|
m48t59_write(nvram, 0x2D, smp_cpus & 0xff);
|
||||||
|
m48t59_write(nvram, 0x2E, 0);
|
||||||
m48t59_write(nvram, 0x2F, nographic & 0xff);
|
m48t59_write(nvram, 0x2F, nographic & 0xff);
|
||||||
nvram_set_lword(nvram, 0x30, RAM_size);
|
nvram_set_lword(nvram, 0x30, RAM_size);
|
||||||
m48t59_write(nvram, 0x34, boot_device & 0xff);
|
m48t59_write(nvram, 0x34, boot_device & 0xff);
|
||||||
@ -179,6 +182,11 @@ void pic_set_irq(int irq, int level)
|
|||||||
slavio_pic_set_irq(slavio_intctl, irq, level);
|
slavio_pic_set_irq(slavio_intctl, irq, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pic_set_irq_cpu(int irq, int level, unsigned int cpu)
|
||||||
|
{
|
||||||
|
slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu);
|
||||||
|
}
|
||||||
|
|
||||||
static void *tcx;
|
static void *tcx;
|
||||||
|
|
||||||
void vga_update_display()
|
void vga_update_display()
|
||||||
@ -222,7 +230,7 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
|
|||||||
const char *kernel_filename, const char *kernel_cmdline,
|
const char *kernel_filename, const char *kernel_cmdline,
|
||||||
const char *initrd_filename)
|
const char *initrd_filename)
|
||||||
{
|
{
|
||||||
CPUState *env;
|
CPUState *env, *envs[MAX_CPUS];
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int ret, linux_boot;
|
int ret, linux_boot;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -230,19 +238,31 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
|
|||||||
|
|
||||||
linux_boot = (kernel_filename != NULL);
|
linux_boot = (kernel_filename != NULL);
|
||||||
|
|
||||||
|
/* init CPUs */
|
||||||
|
for(i = 0; i < smp_cpus; i++) {
|
||||||
env = cpu_init();
|
env = cpu_init();
|
||||||
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
|
envs[i] = env;
|
||||||
|
if (i != 0)
|
||||||
|
env->halted = 1;
|
||||||
|
register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
|
||||||
qemu_register_reset(main_cpu_reset, env);
|
qemu_register_reset(main_cpu_reset, env);
|
||||||
|
}
|
||||||
/* allocate RAM */
|
/* allocate RAM */
|
||||||
cpu_register_physical_memory(0, ram_size, 0);
|
cpu_register_physical_memory(0, ram_size, 0);
|
||||||
|
|
||||||
iommu = iommu_init(PHYS_JJ_IOMMU);
|
iommu = iommu_init(PHYS_JJ_IOMMU);
|
||||||
slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
|
slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
|
||||||
|
for(i = 0; i < smp_cpus; i++) {
|
||||||
|
slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
tcx = tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
|
tcx = tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
|
||||||
lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
|
lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
|
||||||
nvram = m48t59_init(0, PHYS_JJ_EEPROM, 0, PHYS_JJ_EEPROM_SIZE, 8);
|
nvram = m48t59_init(0, PHYS_JJ_EEPROM, 0, PHYS_JJ_EEPROM_SIZE, 8);
|
||||||
slavio_timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ, PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
|
for (i = 0; i < MAX_CPUS; i++) {
|
||||||
|
slavio_timer_init(PHYS_JJ_CLOCK + i * TARGET_PAGE_SIZE, PHYS_JJ_CLOCK_IRQ, 0, i);
|
||||||
|
}
|
||||||
|
slavio_timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ, 2, (unsigned int)-1);
|
||||||
slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ);
|
slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ);
|
||||||
// Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
|
// Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
|
||||||
// Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
|
// Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
|
||||||
|
@ -259,6 +259,10 @@ static void do_info_cpus(void)
|
|||||||
term_printf(" nip=0x" TARGET_FMT_lx, env->nip);
|
term_printf(" nip=0x" TARGET_FMT_lx, env->nip);
|
||||||
if (env->halted)
|
if (env->halted)
|
||||||
term_printf(" (halted)");
|
term_printf(" (halted)");
|
||||||
|
#elif defined(TARGET_SPARC)
|
||||||
|
term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc);
|
||||||
|
if (env->halted)
|
||||||
|
term_printf(" (halted)");
|
||||||
#endif
|
#endif
|
||||||
term_printf("\n");
|
term_printf("\n");
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,7 @@ typedef struct CPUSPARCState {
|
|||||||
int exception_index;
|
int exception_index;
|
||||||
int interrupt_index;
|
int interrupt_index;
|
||||||
int interrupt_request;
|
int interrupt_request;
|
||||||
|
int halted;
|
||||||
/* NOTE: we allow 8 more registers to handle wrapping */
|
/* NOTE: we allow 8 more registers to handle wrapping */
|
||||||
target_ulong regbase[NWINDOWS * 16 + 8];
|
target_ulong regbase[NWINDOWS * 16 + 8];
|
||||||
|
|
||||||
|
7
vl.c
7
vl.c
@ -153,6 +153,11 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS];
|
|||||||
USBDevice *vm_usb_hub;
|
USBDevice *vm_usb_hub;
|
||||||
static VLANState *first_vlan;
|
static VLANState *first_vlan;
|
||||||
int smp_cpus = 1;
|
int smp_cpus = 1;
|
||||||
|
#ifdef TARGET_SPARC
|
||||||
|
#define MAX_CPUS 16
|
||||||
|
#else
|
||||||
|
#define MAX_CPUS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
/* x86 ISA bus support */
|
/* x86 ISA bus support */
|
||||||
@ -4547,7 +4552,7 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case QEMU_OPTION_smp:
|
case QEMU_OPTION_smp:
|
||||||
smp_cpus = atoi(optarg);
|
smp_cpus = atoi(optarg);
|
||||||
if (smp_cpus < 1 || smp_cpus > 8) {
|
if (smp_cpus < 1 || smp_cpus > MAX_CPUS) {
|
||||||
fprintf(stderr, "Invalid number of CPUs\n");
|
fprintf(stderr, "Invalid number of CPUs\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
5
vl.h
5
vl.h
@ -806,6 +806,7 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
|
|||||||
/* sun4m.c */
|
/* sun4m.c */
|
||||||
extern QEMUMachine sun4m_machine;
|
extern QEMUMachine sun4m_machine;
|
||||||
uint32_t iommu_translate(uint32_t addr);
|
uint32_t iommu_translate(uint32_t addr);
|
||||||
|
void pic_set_irq_cpu(int irq, int level, unsigned int cpu);
|
||||||
|
|
||||||
/* iommu.c */
|
/* iommu.c */
|
||||||
void *iommu_init(uint32_t addr);
|
void *iommu_init(uint32_t addr);
|
||||||
@ -823,16 +824,18 @@ void tcx_screen_dump(void *opaque, const char *filename);
|
|||||||
|
|
||||||
/* slavio_intctl.c */
|
/* slavio_intctl.c */
|
||||||
void *slavio_intctl_init();
|
void *slavio_intctl_init();
|
||||||
|
void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env);
|
||||||
void slavio_pic_info(void *opaque);
|
void slavio_pic_info(void *opaque);
|
||||||
void slavio_irq_info(void *opaque);
|
void slavio_irq_info(void *opaque);
|
||||||
void slavio_pic_set_irq(void *opaque, int irq, int level);
|
void slavio_pic_set_irq(void *opaque, int irq, int level);
|
||||||
|
void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu);
|
||||||
|
|
||||||
/* magic-load.c */
|
/* magic-load.c */
|
||||||
int load_elf(const char *filename, uint8_t *addr);
|
int load_elf(const char *filename, uint8_t *addr);
|
||||||
int load_aout(const char *filename, uint8_t *addr);
|
int load_aout(const char *filename, uint8_t *addr);
|
||||||
|
|
||||||
/* slavio_timer.c */
|
/* slavio_timer.c */
|
||||||
void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2);
|
void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu);
|
||||||
|
|
||||||
/* slavio_serial.c */
|
/* slavio_serial.c */
|
||||||
SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2);
|
SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2);
|
||||||
|
Loading…
Reference in New Issue
Block a user