diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 17585ee0d9f72f14b6bf7b53d3a4b5bca528af8c..5a8e7ce3ce9ae715e1ed3b6d54d8ff1ee3c6aa00 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -14,7 +14,13 @@ config LEON2 config LEON3 bool "LEON3" help - Configure for LEON2. + Configure for LEON3. + +config LEON4 + bool "LEON4" + help + Configure for LEON4. + endchoice diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile index 7073823f983d2f732ab482e5730e65eea6db9447..571d6508cacca69468b92cdbe52131f2cf11bb21 100644 --- a/arch/sparc/Makefile +++ b/arch/sparc/Makefile @@ -1,5 +1,7 @@ # gcc (7.2.0) -ARCH_CFLAGS = -mcpu=leon3 -mfix-gr712rc +# +#ARCH_CFLAGS = -mcpu=leon3 -mfix-gr712rc +ARCH_CFLAGS = -mcpu=leon3 -mhard-float # gcc (4.x) #ARCH_CFLAGS = -mcpu=v8 -mfix-gr712rc # clang diff --git a/arch/sparc/include/asm/irq.h b/arch/sparc/include/asm/irq.h index 4c3394ec03ebd370e0f4f6c682aca77325864192..cf4d575703c3ea98eb291e24ba64437ea14a4997 100644 --- a/arch/sparc/include/asm/irq.h +++ b/arch/sparc/include/asm/irq.h @@ -11,11 +11,11 @@ void leon_irq_init(void); -/* in the LEON3, interrupts 1-15 are primary, 16-31 are extended */ -#ifdef CONFIG_LEON3 +/* in the LEON3 and LEON4, interrupts 1-15 are primary, 16-31 are extended */ +#if defined(CONFIG_LEON3) || defined(CONFIG_LEON4) #define LEON_WANT_EIRQ(x) (x) #define LEON_REAL_EIRQ(x) (x) -#endif /* CONFIG_LEON3 */ +#endif /* CONFIG_LEON3 || CONFIG_LEON4 */ /* in the LEON2, interrupts 1-15 are primary, 0-31 are extended, we treat them * as IRLs 16...n */ diff --git a/arch/sparc/include/asm/leon_reg.h b/arch/sparc/include/asm/leon_reg.h index 1d8d29708d6b570a1ab5685c6b9d9cc93358aac5..92c18c3d139869a4bcbcac444ed8568890b99461 100644 --- a/arch/sparc/include/asm/leon_reg.h +++ b/arch/sparc/include/asm/leon_reg.h @@ -24,6 +24,13 @@ #include <kernel/types.h> +#define LEON4_BASE_ADDRESS_IRQAMP 0xFF904000 +#define LEON4_BASE_ADDRESS_GPTIMER 0xFF908000 +#define LEON4_BASE_ADDRESS_GPTIMER1 0xFF909000 +#define LEON4_BASE_ADDRESS_GPTIMER2 0xFF90A000 +#define LEON4_BASE_ADDRESS_GPTIMER3 0xFF90B000 +#define LEON4_BASE_ADDRESS_GPTIMER4 0xFF90C000 + #define LEON3_BASE_ADDRESS_APB 0x80000000 @@ -165,6 +172,84 @@ struct leon3_irqctrl_registermap { }; +/* XXX */ +struct leon4_irqctrl_registermap { + uint32_t irq_level; /* 0x00 */ + uint32_t irq_pending; /* 0x04 */ + uint32_t irq_force; /* 0x08 */ + uint32_t irq_clear; /* 0x0C */ + uint32_t mp_status; /* 0x10 */ + uint32_t mp_broadcast; /* 0x14 */ + uint32_t error_mode_status; /* 0x18 */ + uint32_t watchdog_control; /* 0x1C */ + uint32_t asym_mp_control; /* 0x20 */ + uint32_t irq_ctrl_select; /* 0x24 */ + uint32_t unused01; /* 0x28 */ + uint32_t unused02; /* 0x2C */ + uint32_t unused03; /* 0x30 */ + uint32_t unused04; /* 0x34 */ + uint32_t unused05; /* 0x38 */ + uint32_t unused06; /* 0x3C */ + uint32_t irq_mpmask[4]; /* 0x40 CPU 0 */ + /* 0x44 CPU 1 */ + /* 0x48 CPU 2 */ + /* 0x4C CPU 3 */ + uint32_t unused13; /* 0x50 */ + uint32_t unused14; /* 0x54 */ + uint32_t unused15; /* 0x58 */ + uint32_t unused16; /* 0x5C */ + uint32_t unused17; /* 0x60 */ + uint32_t unused18; /* 0x64 */ + uint32_t unused19; /* 0x68 */ + uint32_t unused20; /* 0x6C */ + uint32_t unused21; /* 0x70 */ + uint32_t unused22; /* 0x74 */ + uint32_t unused23; /* 0x78 */ + uint32_t unused24; /* 0x7C */ + uint32_t irq_mpforce[4]; /* 0x80 CPU 0*/ + /* 0x84 CPU 1*/ + /* 0x88 CPU 2*/ + /* 0x8C CPU 3*/ + uint32_t unused27; /* 0x90 */ + uint32_t unused28; /* 0x94 */ + uint32_t unused29; /* 0x98 */ + uint32_t unused30; /* 0x9C */ + uint32_t unused31; /* 0xA0 */ + uint32_t unused32; /* 0xA4 */ + uint32_t unused33; /* 0xA8 */ + uint32_t unused34; /* 0xAC */ + uint32_t unused35; /* 0xB0 */ + uint32_t unused36; /* 0xB4 */ + uint32_t unused37; /* 0xB8 */ + uint32_t unused38; /* 0xBC */ + uint32_t extended_irq_id[4]; /* 0xC0 CPU 0*/ + /* 0xC4 CPU 1*/ + /* 0xC8 CPU 2*/ + /* 0xCC CPU 3*/ + uint32_t unused39; /* 0xD0 */ + uint32_t unused40; /* 0xD4 */ + uint32_t unused41; /* 0xD8 */ + uint32_t unused42; /* 0xDC */ + uint32_t unused43; /* 0xE0 */ + uint32_t unused44; /* 0xE4 */ + uint32_t unused45; /* 0xE8 */ + uint32_t unused46; /* 0xEC */ + uint32_t unused47; /* 0xF0 */ + uint32_t unused48; /* 0xF4 */ + uint32_t unused49; /* 0xF8 */ + uint32_t unused50; /* 0xFC */ + uint32_t irq_timestamp0_cntr; /* 0x100 */ /* XXX rework these */ + uint32_t irq_timestamp0_ctrl; /* 0x104 */ + uint32_t irq_assert_timestamp0_ctrl; /* 0x108 */ + uint32_t irq_ack_timestamp0_ctrl; /* 0x10C */ + uint32_t irq_timestamp1_cntr; /* 0x110 */ + uint32_t irq_timestamp1_ctrl; /* 0x114 */ + uint32_t irq_assert_timestamp1_ctrl; /* 0x118 */ + uint32_t irq_ack_timestamp1_ctrl; /* 0x11C */ + uint32_t unused51[60]; /* 0x120 */ + /* XXX missing */ +}; + struct leon3_ahbstat_registermap { uint32_t status; diff --git a/arch/sparc/include/asm/time.h b/arch/sparc/include/asm/time.h index 611bd75614489c2e906b853d4a85cb6db7ca3a7d..b61755c3de0bbfa92a4aeeacf3900bc7b566ec23 100644 --- a/arch/sparc/include/asm/time.h +++ b/arch/sparc/include/asm/time.h @@ -46,7 +46,12 @@ #define GRTIMER_MSEC_PER_CYCLE ( 1000.0 / GRTIMER_CYCLES_PER_SEC) #define GRTIMER_USEC_PER_CYCLE (1000000.0 / GRTIMER_CYCLES_PER_SEC) +/* yeah...need to work on that ...*/ +#if defined (CONFIG_LEON4) +#define CPU_CYCLES_TO_NS(x) ((x) * (1000000000 / SPARC_CPU_CPS)) + +#else /* this will definitely break if we run at GHz clock speeds * note that the order is important, otherwise we may encounter integer * overflow on multiplication @@ -54,6 +59,7 @@ #define CPU_CYCLES_TO_NS(x) (((x) >= 1000UL) \ ? (((x) / (SPARC_CPU_CPS / 1000000UL)) * 1000UL) \ : (((x) * 1000UL) / (SPARC_CPU_CPS / 1000000UL))) +#endif compile_time_assert((SPARC_CPU_CPS <= 1000000000UL), CPU_CYCLES_TO_NS_NEEDS_FIXUP); diff --git a/arch/sparc/kernel/bootmem.c b/arch/sparc/kernel/bootmem.c index 867373144b05d18185186e1269fd7ddb4ab6ac88..8ab6f2d78d1deeca783096662884ada18fcf434a 100644 --- a/arch/sparc/kernel/bootmem.c +++ b/arch/sparc/kernel/bootmem.c @@ -57,7 +57,8 @@ static void *bootmem_alloc_internal(size_t size) #endif #if (BOOTMEM_CHUNKSIZE > PAGE_SIZE) - return page_map_reserve_chunk(BOOTMEM_CHUNKSIZE); + return page_map_reserve_chunk(size); /* XXX patched for 740 test */ + //return page_map_reserve_chunk(BOOTMEM_CHUNKSIZE); #else return page_alloc(); #endif diff --git a/arch/sparc/kernel/clockevent.c b/arch/sparc/kernel/clockevent.c index 5e7080637127efce1e25e507c0c642cc348d4973..5f77e63f5f0b5192a83d2e042f3bb668407de18f 100644 --- a/arch/sparc/kernel/clockevent.c +++ b/arch/sparc/kernel/clockevent.c @@ -9,23 +9,38 @@ #include <kernel/irq.h> #include <errno.h> -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined(CONFIG_LEON4) #include <gptimer.h> #include <asm/time.h> /* XXX: want AMBA PNP autodetect later...) */ +/* XXX: patched to use gptimer 0 on leon4, but there are a total of 5 timer + * blocks + */ +#define LEON3_GPTIMERS 5 #define LEON3_GPTIMERS 4 + +#ifdef CONFIG_LEON4 +#define GPTIMER_0_IRQ 1 +#endif +#ifdef CONFIG_LEON3 #define GPTIMER_0_IRQ 8 +#endif static struct gpclkdevs { struct gptimer_unit *gptu; struct clock_event_device dev[LEON3_GPTIMERS]; } _gp_clk_ev = { +#ifdef CONFIG_LEON3 .gptu = (struct gptimer_unit *) LEON3_BASE_ADDRESS_GPTIMER +#endif +#ifdef CONFIG_LEON4 + .gptu = (struct gptimer_unit *) LEON4_BASE_ADDRESS_GPTIMER +#endif }; @@ -255,7 +270,7 @@ static void leon_setup_clockdevs(void) void sparc_clockevent_init(void) { -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined(CONFIG_LEON4) leon_setup_clockdevs(); #endif /* CONFIG_LEON3 */ } diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index 8a1173585a5dec524eb67b3bb276a60676be965b..0f31bc4aba8b28f9ae8a8900d8490734d8266502 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -92,7 +92,18 @@ static struct leon3_irqctrl_registermap *leon_irqctrl_regs; #endif /* CONFIG_LEON3 */ -#define CPU_AFFINITY_NONE (-1) +#ifdef CONFIG_LEON4 + +#define IRL_SIZE LEON3_IRL_SIZE +#define EIRL_SIZE LEON3_IRL_SIZE + +static struct leon4_irqctrl_registermap *leon_irqctrl_regs; + +#endif /* CONFIG_LEON4 */ + + + +#define CPU_AFFINITY_NONE (-1) /* XXX */ static int irq_cpu_affinity[IRL_SIZE + EIRL_SIZE]; @@ -370,7 +381,7 @@ EXPORT_SYMBOL(arch_local_irq_restore); static void leon_clear_irq(unsigned int irq) { -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) iowrite32be((1 << irq), &leon_irqctrl_regs->irq_clear); #endif /* CONFIG_LEON3 */ @@ -401,7 +412,7 @@ static void leon_unmask_irq(unsigned int irq, int cpu) uint32_t mask; -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) mask = ioread32be(&leon_irqctrl_regs->irq_mpmask[cpu]); mask |= (1 << irq); iowrite32be(mask, &leon_irqctrl_regs->irq_mpmask[cpu]); @@ -433,7 +444,7 @@ static void leon_mask_irq(unsigned int irq, int cpu) uint32_t mask; -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) mask = ioread32be(&leon_irqctrl_regs->irq_mpmask[cpu]); mask &= ~(1 << irq); @@ -599,7 +610,7 @@ __attribute__((unused)) static int leon_eirq_dispatch(unsigned int irq) { unsigned int eirq; -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) int cpu; #endif /* CONFIG_LEON3 */ @@ -612,7 +623,7 @@ static int leon_eirq_dispatch(unsigned int irq) irqstat.irl_irq[irq]++; #endif /* CONFIG_IRQ_STATS_COLLECT */ -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) cpu = leon3_cpuid(); #endif /* CONFIG_LEON3 */ @@ -621,7 +632,7 @@ static int leon_eirq_dispatch(unsigned int irq) /* XXX this is a potential death trap :) */ while (1) { -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) /* no pending EIRQs remain */ if (!(leon_irqctrl_regs->irq_pending >> IRL_SIZE)) break; @@ -714,7 +725,7 @@ int irl_register_handler(unsigned int irq, spin_lock_restore_irq(psr_flags); -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) /* XXX for now, just register to the current CPU if no affinity is set */ cpu = irq_cpu_affinity[irq]; @@ -794,7 +805,7 @@ static int eirl_register_handler(unsigned int irq, &eirl_vector[LEON_REAL_EIRQ(irq)]); spin_lock_restore_irq(psr_flags); -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) /* XXX for now, just register to the current CPU if no affinity is set */ cpu = irq_cpu_affinity[irq]; @@ -1021,8 +1032,8 @@ static void leon_setup_eirq(void) { unsigned int eirq; -#ifdef CONFIG_LEON3 - /* probe for extended IRQ controller, see GR712UM, p75 */ +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) + /* probe for extended IRQ controller, see GR712UM, p75; GR740UM p309*/ eirq = (ioread32be(&leon_irqctrl_regs->mp_status) >> 16) & 0xf; #endif /* CONFIG_LEON3 */ #ifdef CONFIG_LEON2 @@ -1047,6 +1058,14 @@ static void leon_setup_eirq(void) BUG_ON(catch_interrupt((int) leon_eirq_dispatch, leon_eirq)); #endif /* CONFIG_ARCH_CUSTOM_BOOT_CODE */ +#ifdef CONFIG_LEON4 + /* XXX enable for all cpus in the system */ + leon_enable_irq(leon_eirq, 0); + leon_enable_irq(leon_eirq, 1); + leon_enable_irq(leon_eirq, 2); + leon_enable_irq(leon_eirq, 3); +#endif /* CONFIG_LEON3 */ + #ifdef CONFIG_LEON3 /* XXX enable for all cpus in the system */ leon_enable_irq(leon_eirq, 0); @@ -1073,7 +1092,7 @@ static void leon_irq_set_level(uint32_t irq_mask, uint32_t level) uint32_t flags; -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) flags = ioread32be(&leon_irqctrl_regs->irq_level); #endif /* CONFIG_LEON3 */ #ifdef CONFIG_LEON2 @@ -1085,7 +1104,7 @@ static void leon_irq_set_level(uint32_t irq_mask, uint32_t level) else flags |= irq_mask; -#ifdef CONFIG_LEON3 +#if defined(CONFIG_LEON3) || defined (CONFIG_LEON4) iowrite32be(flags, &leon_irqctrl_regs->irq_level); #endif /* CONFIG_LEON3 */ #ifdef CONFIG_LEON2 @@ -1197,6 +1216,20 @@ static struct irq_dev leon_irq = { void leon_irq_init(void) { +#ifdef CONFIG_LEON4 + /* XXX should determine that from AMBA PNP scan */ + leon_irqctrl_regs = (struct leon4_irqctrl_registermap *) + LEON4_BASE_ADDRESS_IRQAMP; + + /* mask all interrupts on this (boot) CPU */ + iowrite32be(0, &leon_irqctrl_regs->irq_mpmask[leon3_cpuid()]); /*XXX leon3_ */ + + /* XXX MASK FOR ALL CPUS CONFIGURED FOR THE SYSTEM (dummy for N==4)*/ + iowrite32be(0, &leon_irqctrl_regs->irq_mpmask[1]); + iowrite32be(0, &leon_irqctrl_regs->irq_mpmask[2]); + iowrite32be(0, &leon_irqctrl_regs->irq_mpmask[3]); + +#endif /* CONFIG_LEON3 */ #ifdef CONFIG_LEON3 /* XXX should determine that from AMBA PNP scan */ leon_irqctrl_regs = (struct leon3_irqctrl_registermap *) diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index dc5096d8b396c789888cdc966bb9627529165192..6cca9384589fad33ea3761f65b3dc4f3e54135df 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -56,8 +56,6 @@ static void reserve_kernel_stack(void) /* the (aligned) top of the stack */ _kernel_stack_top = (void *) (char *) _kernel_stack_bottom + k_stack_sz; _kernel_stack_top = ALIGN_PTR(_kernel_stack_top, STACK_ALIGN); - - printk("xxxxx reserved %p to %p\n", _kernel_stack_top, _kernel_stack_bottom); } @@ -74,6 +72,9 @@ static void mem_init(void) #ifdef CONFIG_MPPB sp_banks[0].base_addr = 0x40000000; sp_banks[0].num_bytes = 0x10000000; +#elif CONFIG_LEON4 + sp_banks[0].base_addr = 0x00000000; + sp_banks[0].num_bytes = 0x10000000; #else /* e.g. GR712 eval */ sp_banks[0].base_addr = 0x40000000; sp_banks[0].num_bytes = 0x00800000; @@ -89,14 +90,19 @@ static void mem_init(void) } -int cpu1_ready; +int cpu_ready[4]; #include <asm/io.h> /* wake a cpu by writing to the multiprocessor status register */ void cpu_wake(uint32_t cpu_id) { +#ifdef CONFIG_LEON3 iowrite32be(cpu_id, (uint32_t *) 0x80000210); +#endif +#ifdef CONFIG_LEON4 + iowrite32be(cpu_id, (uint32_t *) 0xFF904010); +#endif } /** XXX crappy */ @@ -105,14 +111,26 @@ static void boot_cpus(void) printk("booting cpu1\n"); cpu_wake(0x2); /*cpu 1 */ - while (!ioread32be(&cpu1_ready)); + while (!ioread32be(&cpu_ready[1])); printk("cpu1 booted\n"); + + printk("booting cpu2\n"); + cpu_wake(0x4); /*cpu 2 */ + + while (!ioread32be(&cpu_ready[2])); + printk("cpu2 booted\n"); + + + printk("booting cpu3\n"); + cpu_wake(0x8); /*cpu 3 */ + + while (!ioread32be(&cpu_ready[3])); + printk("cpu3 booted\n"); } #include <asm/processor.h> #include <kernel/kthread.h> -extern struct task_struct *kernel[]; void smp_cpu_entry(void) { @@ -123,17 +141,18 @@ void smp_cpu_entry(void) BUG_ON(!leon3_cpuid()); /* signal ready */ - iowrite32be(0x1, &cpu1_ready); + iowrite32be(0x1, &cpu_ready[leon3_cpuid()]); - while (ioread32be(&cpu1_ready) != 0x2); - BUG_ON(clockevents_offer_device()); + while (ioread32be(&cpu_ready[leon3_cpuid()]) != 0x2); + BUG_ON(clockevents_offer_device()); /* XXX CLOCK */ kthread_init_main(); - iowrite32be(0x3, &cpu1_ready); - while (ioread32be(&cpu1_ready) != 0x4); + iowrite32be(0x3, &cpu_ready[leon3_cpuid()]); + while (ioread32be(&cpu_ready[leon3_cpuid()]) != 0x4); + while(1) { // printk("x"); -// cpu_relax(); + cpu_relax(); } // printk("1\n"); } @@ -165,4 +184,5 @@ void setup_arch(void) sparc_clockevent_init(); boot_cpus(); + } diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 2b57684db1221a212221a36e8cdca768b3f582e7..a45d01028173a3300a07337a2f20304a90f2bcc7 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -27,9 +27,62 @@ static void leon_grtimer_longcount_init(void) #endif +#ifdef CONFIG_LEON4 +/** + * @brief start the up-counters in %asr22-23 of the LEON4 + * + * @warn the counter apparently cannot be reset in software. this sucks big time + * + * @note to pause the up-counter, the MSB of asr22 of ALL processors must be set + * @see GR740UM p 72. + */ + +static uint64_t boot_time; + +static inline uint64_t leon4_get_upcount(void) +{ + uint64_t time = 0; + + __asm__ __volatile__ ( + "rd %%asr22, %H0 \n\t" + "rd %%asr23, %L0 \n\t" + :"=r" (time) + ); + + time &= (0x1ULL << 56) - 1ULL; + /* Need this for wrap-around detection. Note that 56 bits last for + * ~10 years @ 250 MHz, but you never know... + */ + if (boot_time > time) { + /* XXX set wrap-around status (message) somewhere */ + boot_time = time; + boot_time &= (0x1ULL << 56) - 1ULL; + } + + return time - boot_time; +} + + +static void leon4_init_upcount(void) +{ + __asm__ __volatile__ ( + "wr %%g0, %%asr22 \n\t" + "rd %%asr22, %H0 \n\t" + "rd %%asr23, %L0 \n\t" + :"=r" (boot_time) + ); + boot_time &= (0x1ULL << 56) - 1ULL; +} + +#endif + +/* XXX I really need to rework the ktime interface so that all + * basic times are in nanoseconds. double-word divisions area + * REALLY expensive (doubles the overhead...) + */ static void leon_get_uptime(uint32_t *seconds, uint32_t *nanoseconds) { #ifdef CONFIG_LEON3 @@ -38,7 +91,20 @@ static void leon_get_uptime(uint32_t *seconds, uint32_t *nanoseconds) grtimer_longcount_get_uptime(grtimer_longcount, &up); (*seconds) = up.coarse; (*nanoseconds) = CPU_CYCLES_TO_NS(up.fine); +#elif CONFIG_LEON4 + + uint64_t sec; + uint64_t nsec; + + nsec = CPU_CYCLES_TO_NS(leon4_get_upcount()); + + sec = nsec / 1000000000ULL; + /* likely faster than using modulo */ + nsec = nsec % 1000000000ULL; + + (*seconds) = (uint32_t) sec; + (*nanoseconds) = (uint32_t) nsec; #else printk("%s:%s not implemented\n", __FILE__, __func__); BUG(); @@ -80,5 +146,10 @@ void sparc_uptime_init(void) #ifdef CONFIG_LEON3 leon_grtimer_longcount_init(); #endif + +#ifdef CONFIG_LEON4 + leon4_init_upcount(); +#endif + time_init(&uptime_clock); } diff --git a/init/main.c b/init/main.c index 05778b6eedfd37b8a573dfd328178c806f4718b1..735d8037b2a76561d68fbcd546b07256b010365a 100644 --- a/init/main.c +++ b/init/main.c @@ -46,8 +46,46 @@ volatile int inc; volatile int xa, xb, xc; + +#define BUFLEN 1024*1024 +uint32_t *common; +uint32_t *cpu[4]; + +ktime per_loop_avg[4]; + +int copytask(void *data) +{ + int i; + ktime cnt = 0; + ktime start, stop; + ktime total = 0; + + +// printk("CPU %d\n", leon3_cpuid()); + cpu[leon3_cpuid()] = kmalloc(BUFLEN * sizeof(uint32_t)); + + if (!cpu[leon3_cpuid()]) + return; + + while (1) { + start = ktime_get(); + for (i = 0 ; i < BUFLEN; i++) + cpu[leon3_cpuid()][i] = cpu[3-leon3_cpuid()][i]; + + stop = ktime_get(); + + total += stop - start; + cnt++; + + per_loop_avg[leon3_cpuid()] = (total / cnt) / (ktime) (BUFLEN); + } +} + int task1(void *data) { + + + while (1) { xa++; @@ -71,11 +109,19 @@ int task2(void *data) } static int cnt; static ktime buf[1024]; -int task3(void *data) +int res(void *data) { ktime last = 0; while (1) { + + printk("%llu %llu %llu %llu %llu\n", + ktime_to_ms(ktime_get()), + per_loop_avg[0], + per_loop_avg[1], + per_loop_avg[2], + per_loop_avg[3]); + sched_yield(); #if 0 ktime now; if (cnt < 1024) { @@ -131,7 +177,7 @@ int task0(void *data) printk("%d %d %d %llu irq: %s %d per sec; sched %llu us %llu per call, calls %d cpu %d\n", a, b, c, ktime_get(), buf1, (curr -last), ktime_to_us(sched_last_time), sched_last_time /sched_ev, sched_ev - last_call, leon3_cpuid()); last = curr; last_call = sched_ev; -// sched_yield(); + sched_yield(); } } @@ -154,7 +200,7 @@ arch_initcall(kernel_init); /** XXX dummy **/ -extern int cpu1_ready; +extern int cpu_ready[4]; /** * @brief kernel main functionputchar( *((char *) data) ); */ @@ -251,7 +297,6 @@ int kernel_main(void) - cpu1_ready = 2; #if 1 { struct sched_attr attr; @@ -300,18 +345,18 @@ int kernel_main(void) #endif #endif -#if 1 +#if 0 t = kthread_create(task0, NULL, 0, "res"); sched_get_attr(t, &attr); attr.policy = SCHED_EDF; attr.period = ms_to_ktime(1000); attr.deadline_rel = ms_to_ktime(900); - attr.wcet = ms_to_ktime(800); + attr.wcet = ms_to_ktime(500); sched_set_attr(t, &attr); kthread_wake_up(t); #endif -#if 1 +#if 0 t = kthread_create(task1, NULL, 1, "print3"); sched_get_attr(t, &attr); attr.policy = SCHED_EDF; @@ -322,16 +367,91 @@ int kernel_main(void) kthread_wake_up(t); #endif + + cpu_ready[1] = 2; + while (ioread32be(&cpu_ready[1]) != 0x3); + iowrite32be(0x4, &cpu_ready[1]); + + cpu_ready[2] = 2; + while (ioread32be(&cpu_ready[2]) != 0x3); + iowrite32be(0x4, &cpu_ready[2]); + + cpu_ready[3] = 2; + while (ioread32be(&cpu_ready[3]) != 0x3); + iowrite32be(0x4, &cpu_ready[3]); + + + #endif + printk("requesting common\n"); + common = kmalloc (BUFLEN * sizeof(uint32_t)); + printk("starting threads\n"); +#if 1 + t = kthread_create(res, NULL, 3, "cpu0"); + sched_get_attr(t, &attr); + attr.policy = SCHED_EDF; + attr.period = ms_to_ktime(1000); + attr.deadline_rel = ms_to_ktime(990); + attr.wcet = ms_to_ktime(50); + sched_set_attr(t, &attr); + kthread_wake_up(t); +#endif +#if 1 + t = kthread_create(copytask, NULL, 0, "cpu0"); + sched_get_attr(t, &attr); + attr.policy = SCHED_EDF; + attr.period = ms_to_ktime(1000); + attr.deadline_rel = ms_to_ktime(900); + attr.wcet = ms_to_ktime(800); + sched_set_attr(t, &attr); + kthread_wake_up(t); +#endif +#if 1 + t = kthread_create(copytask, NULL, 1, "cpu1"); + sched_get_attr(t, &attr); + attr.policy = SCHED_EDF; + attr.period = ms_to_ktime(1000); + attr.deadline_rel = ms_to_ktime(900); + attr.wcet = ms_to_ktime(800); + sched_set_attr(t, &attr); + kthread_wake_up(t); +#endif +#if 1 + t = kthread_create(copytask, NULL, 2, "cpu2"); + sched_get_attr(t, &attr); + attr.policy = SCHED_EDF; + attr.period = ms_to_ktime(1000); + attr.deadline_rel = ms_to_ktime(900); + attr.wcet = ms_to_ktime(800); + sched_set_attr(t, &attr); + kthread_wake_up(t); +#endif +#if 1 + t = kthread_create(copytask, NULL, 3, "cpu3"); + sched_get_attr(t, &attr); + attr.policy = SCHED_EDF; + attr.period = ms_to_ktime(1000); + attr.deadline_rel = ms_to_ktime(900); + attr.wcet = ms_to_ktime(800); + sched_set_attr(t, &attr); + kthread_wake_up(t); +#endif } #endif - while (ioread32be(&cpu1_ready) != 0x3); - iowrite32be(0x4, &cpu1_ready); + + + while (1) { + // res(NULL); + cpu_relax(); + } + + + while(1) { #if 0 int val = inc; diff --git a/kernel/kthread.c b/kernel/kthread.c index ae16357677f6ac80e5b836c610edd4d0342359a0..a56d9fac627382d2df62bfd8fdf306a626f31a7a 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -41,7 +41,7 @@ static struct spinlock kthread_spinlock; #include <asm/processor.h> -struct thread_info *current_set[2]; /* XXX */ +struct thread_info *current_set[4]; /* XXX */ /** diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 093d17fad3a1020b53a7f88f74f2a38b7621d78b..12f178b09b7520b68658d6e25cb0afb4a9fc3cd6 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -47,7 +47,7 @@ void schedule(void) ktime now; - static int once[2]; + static int once[4]; if (!once[leon3_cpuid()]) { // tick_set_mode(TICK_MODE_PERIODIC); diff --git a/kernel/sched/edf.c b/kernel/sched/edf.c index 89c678816cea57f652e9e6b9b92711f25fb3aba2..847dec749199b7800c4c36f57f62a68b5c88d3d2 100644 --- a/kernel/sched/edf.c +++ b/kernel/sched/edf.c @@ -230,7 +230,7 @@ static int edf_schedulable(struct task_queue *tq, const struct task_struct *task - if (u > 1.9) { + if (u > 3.9) { printk("I am NOT schedul-ableh: %f ", u); BUG(); return -EINVAL; diff --git a/kernel/tick.c b/kernel/tick.c index 582176da1e9ebc2260ae021ace96f5ca69e7b299..3d51f599180183f84a16f098fbebfbdfcbbe195d 100644 --- a/kernel/tick.c +++ b/kernel/tick.c @@ -24,7 +24,7 @@ static unsigned long tick_period_min_ns = 1000000UL; /* XXX */ -static struct clock_event_device *tick_device[2]; +static struct clock_event_device *tick_device[4]; #include <asm/processor.h> diff --git a/lib/mm.c b/lib/mm.c index ebb49ff65676a82900f7e4c77b7995c6093dcfa8..2eed81187fb0e53f46e52b825b70af7c5293659f 100644 --- a/lib/mm.c +++ b/lib/mm.c @@ -73,7 +73,13 @@ struct mm_blk_lnk { static bool mm_blk_addr_valid(struct mm_pool *mp, struct mm_blk_lnk *blk) { - return ((unsigned long) blk - (1UL << mp->max_order) < mp->base); + if ((unsigned long) blk >= mp->base) + if ((unsigned long) blk < mp->base + (1UL << mp->max_order)) + return true; + + return false; + +// return ((unsigned long) blk - (1UL << mp->max_order) < mp->base); } diff --git a/lib/vsnprintf.c b/lib/vsnprintf.c index 2f32fabcec79c0d2d7853657a692c33fdf86d564..32992017398f6104770a8bd1f1b84222da08c1e3 100644 --- a/lib/vsnprintf.c +++ b/lib/vsnprintf.c @@ -61,7 +61,13 @@ struct fmt_spec { #define TREADY 4 +#if defined(CONFIG_LEON3) static volatile int *console = (int *)0x80000100; +#endif + +#if defined(CONFIG_LEON4) +static volatile int *console = (int *)0xFF900000; +#endif static int putchar(int c) {