Changes to RISC-V supervisor mode
authorAndrew Waterman <waterman@s144.Millennium.Berkeley.EDU>
Fri, 11 Nov 2011 08:32:22 +0000 (00:32 -0800)
committerAndrew Waterman <waterman@s144.Millennium.Berkeley.EDU>
Fri, 11 Nov 2011 08:32:22 +0000 (00:32 -0800)
See commit comments in ISA simulator for details

kern/arch/riscv/boot.S
kern/arch/riscv/cboot.c
kern/arch/riscv/entry.S
kern/arch/riscv/kernel.ld
kern/arch/riscv/pcr.h
kern/arch/riscv/riscv.h
kern/arch/riscv/smp.c
kern/arch/riscv/time.c
kern/arch/riscv/trap.c

index 0aa0a24..14af7f1 100644 (file)
@@ -29,7 +29,8 @@ _start:
   la     t0, trap_entry
   mtpcr  t0, ASM_CR(PCR_EVEC)
 
   la     t0, trap_entry
   mtpcr  t0, ASM_CR(PCR_EVEC)
 
-  // enable traps
+  // clear IPIs and enable traps
+  mtpcr  zero, ASM_CR(PCR_CLR_IPI)
   li     t0, PCR0
   mtpcr  t0, ASM_CR(PCR_SR)
 
   li     t0, PCR0
   mtpcr  t0, ASM_CR(PCR_SR)
 
@@ -43,19 +44,26 @@ _start:
   li     t1, KERN_LOAD_ADDR
   sub    sp, sp, t1
 
   li     t1, KERN_LOAD_ADDR
   sub    sp, sp, t1
 
+  // get memory size and core count from first two words of memory
+  lw     s0, 0(zero)
+  lw     s1, 4(zero)
+
   // set up initial page mappings
   // set up initial page mappings
-  la     a0, l1pt
-  sub    a0, a0, t1
-  la     a1, l1pt_boot
+  move   a0, s0
+  la     a1, l1pt
   sub    a1, a1, t1
   sub    a1, a1, t1
+  la     a2, l1pt_boot
+  sub    a2, a2, t1
 #ifdef __riscv64
 #ifdef __riscv64
-  la     a2, l2pt
-  sub    a2, a1, t1
+  la     a3, l2pt
+  sub    a3, a3, t1
 #endif
   jal    pagetable_init
   jal    enable_mmu
 
   // relocate stack and call into C code using absolute jump, not pc-relative
 #endif
   jal    pagetable_init
   jal    enable_mmu
 
   // relocate stack and call into C code using absolute jump, not pc-relative
+  move   a0, s0
+  move   a1, s1
   la     sp, bootstacktop
   la     t0, cmain
   jr     t0
   la     sp, bootstacktop
   la     t0, cmain
   jr     t0
index 54d46f4..952677c 100644 (file)
@@ -9,23 +9,22 @@
 
 #define MAX_KERNBASE_SIZE (KERN_VMAP_TOP - KERNBASE)
 
 
 #define MAX_KERNBASE_SIZE (KERN_VMAP_TOP - KERNBASE)
 
+uint32_t num_cpus = 1;   // this must not be in BSS
+
 static uint64_t
 static uint64_t
-mem_size(void)
+mem_size(uint64_t sz_mb)
 {
 {
-       uint64_t sz = MIN(mfpcr(PCR_MEMSIZE)*PGSIZE, MAX_KERNBASE_SIZE);
-#ifndef __riscv64
-       // limit memory size for RV32
-       sz = MIN(sz, L1PGSIZE*NPTENTRIES);
-#endif
-       return sz;
+       uint64_t sz = (uint64_t)sz_mb * 1024 * 1024;
+       return MIN(sz,  MIN(MAX_KERNBASE_SIZE, (uint64_t)L1PGSIZE * NPTENTRIES));
 }
 
 }
 
-void pagetable_init(pte_t* l1pt, pte_t* l1pt_boot, pte_t* l2pt)
+void pagetable_init(uint32_t memsize_mb, pte_t* l1pt, pte_t* l1pt_boot,
+                    pte_t* l2pt)
 {
        static_assert(KERNBASE % L1PGSIZE == 0);
        // The boot L1 PT retains the identity mapping [0,memsize-1],
        // whereas the post-boot L1 PT does not.
 {
        static_assert(KERNBASE % L1PGSIZE == 0);
        // The boot L1 PT retains the identity mapping [0,memsize-1],
        // whereas the post-boot L1 PT does not.
-       uint64_t memsize = mem_size();
+       uint64_t memsize = mem_size(memsize_mb);
        for(uint64_t pa = 0; pa < memsize+L1PGSIZE-1; pa += L1PGSIZE)
        {
                pte_t pte = PTE(LA2PPN(pa), PTE_KERN_RW | PTE_E);
        for(uint64_t pa = 0; pa < memsize+L1PGSIZE-1; pa += L1PGSIZE)
        {
                pte_t pte = PTE(LA2PPN(pa), PTE_KERN_RW | PTE_E);
@@ -56,12 +55,14 @@ void pagetable_init(pte_t* l1pt, pte_t* l1pt_boot, pte_t* l2pt)
 }
 
 void
 }
 
 void
-cmain()
+cmain(uint32_t memsize_mb, uint32_t num_cores)
 {
        multiboot_info_t mbi;
        memset(&mbi, 0, sizeof(mbi));
        mbi.flags = 0x00000001;
 {
        multiboot_info_t mbi;
        memset(&mbi, 0, sizeof(mbi));
        mbi.flags = 0x00000001;
-       mbi.mem_lower = (unsigned long)(mem_size() / 1024);
+       mbi.mem_lower = mem_size(memsize_mb) / 1024;
+
+       num_cpus = num_cores;
 
        extern void kernel_init(multiboot_info_t *mboot_info);
        // kernel_init expects a pre-relocation mbi address
 
        extern void kernel_init(multiboot_info_t *mboot_info);
        // kernel_init expects a pre-relocation mbi address
index 24f7949..c301061 100644 (file)
@@ -183,7 +183,6 @@ trap_entry:
   STORE  x3,35*REGBYTES(x2)
 
   # get faulting insn, if it wasn't a fetch-related trap
   STORE  x3,35*REGBYTES(x2)
 
   # get faulting insn, if it wasn't a fetch-related trap
-  and   x3, x3, CAUSE_EXCCODE
   li    x5, CAUSE_MISALIGNED_FETCH
   li    x6, CAUSE_FAULT_FETCH
   beq   x3, x5, 1f
   li    x5, CAUSE_MISALIGNED_FETCH
   li    x6, CAUSE_FAULT_FETCH
   beq   x3, x5, 1f
index 7b471fa..e6b4d35 100644 (file)
@@ -6,9 +6,9 @@ ENTRY(_start)
 
 SECTIONS
 {
 
 SECTIONS
 {
-       /* Link the kernel for 0xC01000C0, but load it at 0x001000C0) */
+       /* Link the kernel for 0xFFFFFFFF80002000, but load it at 0x2000) */
 
 
-       .text 0xFFFFFFFF80000000 : AT(0) {
+       .text 0xFFFFFFFF80002000 : AT(0x2000) {
                *(.text .stub .text.* .gnu.linkonce.t.*)
        }
 
                *(.text .stub .text.* .gnu.linkonce.t.*)
        }
 
index 99be591..f2ebaab 100644 (file)
 #define PCR_COUNT    4
 #define PCR_COMPARE  5
 #define PCR_CAUSE    6
 #define PCR_COUNT    4
 #define PCR_COMPARE  5
 #define PCR_CAUSE    6
-#define PCR_IPI      7
-#define PCR_MEMSIZE  8
-#define PCR_PTBR     9
+#define PCR_PTBR     7
+#define PCR_SEND_IPI 8
+#define PCR_CLR_IPI  9
 #define PCR_COREID   10
 #define PCR_COREID   10
-#define PCR_NUMCORES 12
+#define PCR_K0       12
+#define PCR_K1       13
 #define PCR_TOHOST   16
 #define PCR_FROMHOST 17
 #define PCR_CONSOLE  18
 #define PCR_TOHOST   16
 #define PCR_FROMHOST 17
 #define PCR_CONSOLE  18
-#define PCR_K0       24
-#define PCR_K1       25
-
-#define CR_FSR       0
-#define CR_TID       29
-
-#define MEMSIZE_SHIFT 12
-
-#define TIMER_PERIOD 0x1000
 
 #define IPI_IRQ   5
 #define TIMER_IRQ 7
 
 #define IPI_IRQ   5
 #define TIMER_IRQ 7
-#define NIRQ 8
-
-#define CAUSE_EXCCODE 0x000000FF
-#define CAUSE_IP      0x0000FF00
-#define CAUSE_EXCCODE_SHIFT 0
-#define CAUSE_IP_SHIFT      8
 
 #define CAUSE_MISALIGNED_FETCH 0
 #define CAUSE_FAULT_FETCH 1
 #define CAUSE_ILLEGAL_INSTRUCTION 2
 #define CAUSE_PRIVILEGED_INSTRUCTION 3
 #define CAUSE_FP_DISABLED 4
 
 #define CAUSE_MISALIGNED_FETCH 0
 #define CAUSE_FAULT_FETCH 1
 #define CAUSE_ILLEGAL_INSTRUCTION 2
 #define CAUSE_PRIVILEGED_INSTRUCTION 3
 #define CAUSE_FP_DISABLED 4
-#define CAUSE_INTERRUPT 5
 #define CAUSE_SYSCALL 6
 #define CAUSE_BREAKPOINT 7
 #define CAUSE_MISALIGNED_LOAD 8
 #define CAUSE_SYSCALL 6
 #define CAUSE_BREAKPOINT 7
 #define CAUSE_MISALIGNED_LOAD 8
 #define CAUSE_FAULT_LOAD 10
 #define CAUSE_FAULT_STORE 11
 #define CAUSE_VECTOR_DISABLED 12
 #define CAUSE_FAULT_LOAD 10
 #define CAUSE_FAULT_STORE 11
 #define CAUSE_VECTOR_DISABLED 12
-#define NUM_CAUSES 13
+#define CAUSE_IRQ0 16
+#define CAUSE_IRQ1 17
+#define CAUSE_IRQ2 18
+#define CAUSE_IRQ3 19
+#define CAUSE_IRQ4 20
+#define CAUSE_IRQ5 21
+#define CAUSE_IRQ6 22
+#define CAUSE_IRQ7 23
+#define NUM_CAUSES 24
 
 #define ASM_CR(r)   _ASM_CR(r)
 #define _ASM_CR(r)  cr##r
 
 #define ASM_CR(r)   _ASM_CR(r)
 #define _ASM_CR(r)  cr##r
index 19a7d51..7be96e8 100644 (file)
@@ -6,39 +6,33 @@
 static __inline void
 lcr3(uintptr_t val)
 {
 static __inline void
 lcr3(uintptr_t val)
 {
-  mtpcr(PCR_PTBR, val);
+       mtpcr(PCR_PTBR, val);
 }
 
 static __inline uintptr_t
 rcr3(void)
 {
 }
 
 static __inline uintptr_t
 rcr3(void)
 {
-  return mfpcr(PCR_PTBR);
+       return mfpcr(PCR_PTBR);
 }
 
 static __inline uintptr_t
 read_pc(void)
 {
 }
 
 static __inline uintptr_t
 read_pc(void)
 {
-  uintptr_t pc;
+       uintptr_t pc;
        asm ("rdnpc %0" : "=r"(pc));
        asm ("rdnpc %0" : "=r"(pc));
-  return pc;
-}
-
-static __inline uintptr_t
-num_cores(void)
-{
-       return mfpcr(PCR_NUMCORES);
+       return pc;
 }
 
 static __inline void
 send_ipi(uint32_t who)
 {
 }
 
 static __inline void
 send_ipi(uint32_t who)
 {
-       mtpcr(PCR_IPI, who);
+       mtpcr(PCR_SEND_IPI, who);
 }
 
 static __inline void
 clear_ipi()
 {
 }
 
 static __inline void
 clear_ipi()
 {
-       mfpcr(PCR_IPI);
+       mtpcr(PCR_CLR_IPI, 0);
 }
 
 #endif
 }
 
 #endif
index 1ced0a9..d3279ef 100644 (file)
@@ -8,20 +8,19 @@
 #include <atomic.h>
 #include <pmap.h>
 
 #include <atomic.h>
 #include <pmap.h>
 
-volatile uint32_t num_cpus;
+static volatile uint32_t num_cpus_booted = 1;
 
 void
 smp_boot(void)
 {
        smp_percpu_init();
 
 
 void
 smp_boot(void)
 {
        smp_percpu_init();
 
-       num_cpus = 1;
        printd("Cores, report in!\n");
 
        printd("Cores, report in!\n");
 
-       for(uintptr_t i = 1, ncores = num_cores(); i < ncores; i++)
+       for(uint32_t i = 1; i < num_cpus; i++)
                send_ipi(i);
        
                send_ipi(i);
        
-       while(*(volatile uint32_t*)&num_cpus < num_cores());
+       while(num_cpus_booted < num_cpus);
 
        printd("%d cores reporting!\n", num_cpus);
 }
 
        printd("%d cores reporting!\n", num_cpus);
 }
@@ -29,13 +28,9 @@ smp_boot(void)
 void
 smp_init(void)
 {
 void
 smp_init(void)
 {
-       static spinlock_t report_in_lock = SPINLOCK_INITIALIZER;
-
        smp_percpu_init();
        smp_percpu_init();
-       spin_lock(&report_in_lock);
-       num_cpus++;
-       spin_unlock(&report_in_lock);
 
 
+       __sync_fetch_and_add(&num_cpus_booted, 1);
        printd("Good morning, Vietnam! (core id = %d)\n",core_id());
 
        smp_idle();
        printd("Good morning, Vietnam! (core id = %d)\n",core_id());
 
        smp_idle();
index 2059017..4b1e1af 100644 (file)
@@ -9,9 +9,9 @@ system_timing_t system_timing = {0};
 
 void
 timer_init(void)
 
 void
 timer_init(void)
-{      
-  mtpcr(PCR_COUNT, 0);
-  mtpcr(PCR_COMPARE, 0);
+{
+       mtpcr(PCR_COUNT, 0);
+       mtpcr(PCR_COMPARE, 0);
        mtpcr(PCR_SR, mfpcr(PCR_SR) | (SR_IM & (1 << (TIMER_IRQ+SR_IM_SHIFT))));
 
        system_timing.tsc_freq = TSC_HZ;
        mtpcr(PCR_SR, mfpcr(PCR_SR) | (SR_IM & (1 << (TIMER_IRQ+SR_IM_SHIFT))));
 
        system_timing.tsc_freq = TSC_HZ;
index 446d9b9..a8b3f0a 100644 (file)
@@ -172,6 +172,11 @@ static kernel_message_t *get_next_amsg(struct kernel_msg_list *list_head,
 static void
 handle_ipi(trapframe_t* tf)
 {
 static void
 handle_ipi(trapframe_t* tf)
 {
+       if (!in_kernel(tf))
+               set_current_tf(&per_cpu_info[core_id()], tf);
+       else if((void*)tf->epc == &cpu_halt) // break out of the cpu_halt loop
+               advance_pc(tf);
+       
        clear_ipi();
 
        per_cpu_info_t *myinfo = &per_cpu_info[core_id()];
        clear_ipi();
 
        per_cpu_info_t *myinfo = &per_cpu_info[core_id()];
@@ -273,38 +278,14 @@ unhandled_trap(trapframe_t* state, const char* name)
 }
 
 static void
 }
 
 static void
-handle_timer_interrupt(trapframe_t* state)
-{
-       timer_interrupt(state, NULL);
-}
-
-static void
-handle_interrupt(trapframe_t* tf)
+handle_timer_interrupt(trapframe_t* tf)
 {
        if (!in_kernel(tf))
                set_current_tf(&per_cpu_info[core_id()], tf);
        else if((void*)tf->epc == &cpu_halt) // break out of the cpu_halt loop
                advance_pc(tf);
        
 {
        if (!in_kernel(tf))
                set_current_tf(&per_cpu_info[core_id()], tf);
        else if((void*)tf->epc == &cpu_halt) // break out of the cpu_halt loop
                advance_pc(tf);
        
-       typedef void (*trap_handler)(trapframe_t*);
-       
-       const static trap_handler trap_handlers[NIRQ] = {
-         [TIMER_IRQ] = handle_timer_interrupt,
-         [IPI_IRQ] = handle_ipi,
-       };
-
-       uintptr_t interrupts = (tf->cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
-
-       for(uintptr_t i = 0; interrupts; interrupts >>= 1, i++)
-       {
-               if(interrupts & 1)
-               {
-                       if(trap_handlers[i])
-                               trap_handlers[i](tf);
-                       else
-                               panic("Bad interrupt %d", i);
-               }
-       }
+       timer_interrupt(tf, NULL);
 }
 
 static void
 }
 
 static void
@@ -408,18 +389,18 @@ handle_trap(trapframe_t* tf)
          [CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction,
          [CAUSE_PRIVILEGED_INSTRUCTION] = handle_illegal_instruction,
          [CAUSE_FP_DISABLED] = handle_fp_disabled,
          [CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction,
          [CAUSE_PRIVILEGED_INSTRUCTION] = handle_illegal_instruction,
          [CAUSE_FP_DISABLED] = handle_fp_disabled,
-         [CAUSE_INTERRUPT] = handle_interrupt,
          [CAUSE_SYSCALL] = handle_syscall,
          [CAUSE_BREAKPOINT] = handle_breakpoint,
          [CAUSE_MISALIGNED_LOAD] = handle_misaligned_load,
          [CAUSE_MISALIGNED_STORE] = handle_misaligned_store,
          [CAUSE_FAULT_LOAD] = handle_fault_load,
          [CAUSE_FAULT_STORE] = handle_fault_store,
          [CAUSE_SYSCALL] = handle_syscall,
          [CAUSE_BREAKPOINT] = handle_breakpoint,
          [CAUSE_MISALIGNED_LOAD] = handle_misaligned_load,
          [CAUSE_MISALIGNED_STORE] = handle_misaligned_store,
          [CAUSE_FAULT_LOAD] = handle_fault_load,
          [CAUSE_FAULT_STORE] = handle_fault_store,
+         [CAUSE_IRQ0 + IPI_IRQ] = handle_ipi,
+         [CAUSE_IRQ0 + TIMER_IRQ] = handle_timer_interrupt,
        };
        
        };
        
-       int exccode = (tf->cause & CAUSE_EXCCODE) >> CAUSE_EXCCODE_SHIFT;
-       assert(exccode < NUM_CAUSES && trap_handlers[exccode]);
-       trap_handlers[exccode](tf);
+       assert(tf->cause < NUM_CAUSES && trap_handlers[tf->cause]);
+       trap_handlers[tf->cause](tf);
        
        /* Return to the current process, which should be runnable.  If we're the
         * kernel, we should just return naturally.  Note that current and tf need
        
        /* Return to the current process, which should be runnable.  If we're the
         * kernel, we should just return naturally.  Note that current and tf need