From 1a8a803ee16d8293866f5d3553b57558c3995520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Sat, 3 Nov 2007 21:02:03 +0000 Subject: [PATCH] WIP Abstracted cpu and mmu version dependant stuff (compatibility where are you) into ops like func arrays. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22821 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/m68k/arch_cpu.h | 93 ++++---- .../kernel/arch/m68k/arch_kernel_args.h | 4 + headers/private/kernel/arch/m68k/arch_mmu.h | 211 ++++++++---------- .../private/kernel/arch/m68k/arch_thread.h | 20 +- headers/private/kernel/arch/m68k/arch_vm.h | 20 ++ 5 files changed, 188 insertions(+), 160 deletions(-) diff --git a/headers/private/kernel/arch/m68k/arch_cpu.h b/headers/private/kernel/arch/m68k/arch_cpu.h index a70f3246f5..92fa937bd1 100644 --- a/headers/private/kernel/arch/m68k/arch_cpu.h +++ b/headers/private/kernel/arch/m68k/arch_cpu.h @@ -219,11 +219,17 @@ extern bool m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler) } #endif -/* flushes insn pipeline */ -#define m68k_nop() asm volatile("nop") -/* no FC bit needed */ -#define pflush(addr) asm volatile("pflush #0,#0,(%0)" :: "a" (addr)) -#define pflusha() asm volatile("pflusha") +struct m68k_cpu_ops { + void (*flush_insn_pipeline)(void); + void (*flush_atc_all)(void); + void (*flush_atc_user)(void); + void (*flush_atc_addr)(void *addr); + void (*flush_dcache)(void *address, size_t len); + void (*flush_icache)(void *address, size_t len); + void (*idle)(void); +}; + +extern struct m68k_cpu_ops cpu_ops; //#define @@ -234,51 +240,56 @@ extern bool m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler) #define ppc_sync() asm volatile("sync") #define tlbia() asm volatile("tlbia") #define tlbie(addr) asm volatile("tlbie %0" :: "r" (addr)) - - -// PowerPC processor version (the upper 16 bits of the PVR). -enum m68k_processor_version { - MPC601 = 0x0001, - MPC603 = 0x0003, - MPC604 = 0x0004, - MPC602 = 0x0005, - MPC603e = 0x0006, - MPC603ev = 0x0007, - MPC750 = 0x0008, - MPC604ev = 0x0009, - MPC7400 = 0x000c, - MPC620 = 0x0014, - IBM403 = 0x0020, - IBM401A1 = 0x0021, - IBM401B2 = 0x0022, - IBM401C2 = 0x0023, - IBM401D2 = 0x0024, - IBM401E2 = 0x0025, - IBM401F2 = 0x0026, - IBM401G2 = 0x0027, - IBMPOWER3 = 0x0041, - MPC860 = 0x0050, - MPC8240 = 0x0081, - IBM405GP = 0x4011, - IBM405L = 0x4161, - IBM750FX = 0x7000, - MPC7450 = 0x8000, - MPC7455 = 0x8001, - MPC7457 = 0x8002, - MPC7447A = 0x8003, - MPC7448 = 0x8004, - MPC7410 = 0x800c, - MPC8245 = 0x8081, -}; #endif +// m68k processor version. +enum m68k_processor_version { + /* those two we don't support */ + CPU_68000 = 0x0000, + CPU_68010 = 0x0001, + /* maybe with a pmmu and fpu */ + CPU_68020 = 0x0002, + /* should work */ + CPU_68030 = 0x0003, + CPU_68040 = 0x0004, + CPU_68060 = 0x0006, + /* mask */ + CPU_MASK = 0x000F +}; + +enum m68k_fpu_version { + /* we don't support */ + FPU_NONE = 0x0000, + FPU_68881 = 0x0010, + FPU_68882 = 0x0020, + FPU_030 = 0x0030, + FPU_040 = 0x0040, + FPU_060 = 0x0060, + FPU_MASK = 0x00F0 +}; + +enum m68k_mmu_version { + MMU_NONE = 0x0000, + MMU_68551 = 0x0100, + MMU_68030 = 0x0300, + MMU_68040 = 0x0400, + MMU_68060 = 0x0600, + MMU_MASK = 0x0F00 +}; + +extern int arch_cpu_type; +extern int arch_fpu_type; +extern int arch_mmu_type; +extern int arch_platform; /* Use of (some) special purpose registers. + XXX: those regs aren't implemented/accessed the same way on different cpus... SRP[63-32]: current struct thread* SRP[31-0] : CAAR : can we use it ?? + MSP : PPC: SPRG0: per CPU physical address pointer to an ppc_cpu_exception_context diff --git a/headers/private/kernel/arch/m68k/arch_kernel_args.h b/headers/private/kernel/arch/m68k/arch_kernel_args.h index 294a63ea65..f9d990b6e9 100644 --- a/headers/private/kernel/arch/m68k/arch_kernel_args.h +++ b/headers/private/kernel/arch/m68k/arch_kernel_args.h @@ -15,6 +15,10 @@ // kernel args typedef struct { + int cpu_type; + int fpu_type; + int mmu_type; + int platform; // architecture specific uint64 cpu_frequency; uint64 bus_frequency; diff --git a/headers/private/kernel/arch/m68k/arch_mmu.h b/headers/private/kernel/arch/m68k/arch_mmu.h index a02bd9b59f..3550307854 100644 --- a/headers/private/kernel/arch/m68k/arch_mmu.h +++ b/headers/private/kernel/arch/m68k/arch_mmu.h @@ -11,139 +11,114 @@ #include +/* + * cf. + * "mc68030 Enhanced 32-bit Microprocessor User's Manual" + * (3rd edition), Section 9 + * "mc68040 Enhanced 32-bit Microprocessor User's Manual" + * Section 9 + * + * The 030 pmmu can support up to 6-level translation tree, + * each level using an size-selectable index from the + * virtual address, short (4-bit) and long (8-bit) page table + * and page entry descriptors, early tree termination, and selectable + * page size from 256 bytes to 32K. + * There is optionally a separate Supervisor Root Pointer to separate + * the user and kernel trees. + * + * The 040 pmmu however is way more limited in its abilities. + * It has a fixed 3-level page tree, with 7/7/6 bit splitting for + * 4K pages. The opcodes are also different so we will need specific + * routines. Both supervisor and root pointers must be used so we can't + * reuse one of them. + * + * + * We settle to: + * - 1 bit index for the first level to easily split kernel and user + * part of the tree, with the possibility to force supervisor only for + * the kernel tree. The use of SRP to point to a 2nd tree is avoided as + * it is not available on 68060, plus that makes a spare 64bit reg to + * stuff things in. + * - 9 bit page directory + * - 10 bit page tables + * - 12 bit page index (4K pages, a common value). + */ -/*** BAT - block address translation ***/ -enum bat_length { - BAT_LENGTH_128kB = 0x0000, - BAT_LENGTH_256kB = 0x0001, - BAT_LENGTH_512kB = 0x0003, - BAT_LENGTH_1MB = 0x0007, - BAT_LENGTH_2MB = 0x000f, - BAT_LENGTH_4MB = 0x001f, - BAT_LENGTH_8MB = 0x003f, - BAT_LENGTH_16MB = 0x007f, - BAT_LENGTH_32MB = 0x00ff, - BAT_LENGTH_64MB = 0x01ff, - BAT_LENGTH_128MB = 0x03ff, - BAT_LENGTH_256MB = 0x07ff, + +enum descriptor_types { + DT_INVALID = 0, // invalid entry + DT_PAGE, // page descriptor + DT_VALID_4, // short page table descriptor + DT_VALID_8, // long page table descriptor }; -enum bat_protection { - BAT_READ_ONLY = 1, - BAT_READ_WRITE = 2, +#if 0 +/* This is the normal layout of the descriptors, as per documentation. + * When page size > 256, several bits are unused in the LSB of page + * addresses, which we can use in addition of other unused bits. + * the structs dedlared later reflect this for 4K pages. + */ + +struct short_page_directory_entry { + // upper 32 bits + uint32 type : 2; + uint32 write_protect : 1; + uint32 used : 1; + uint32 address : 28; }; -struct block_address_translation { - // upper 32 bit - uint32 page_index : 15; // BEPI, block effective page index - uint32 _reserved0 : 4; - uint32 length : 11; - uint32 kernel_valid : 1; // Vs, Supervisor-state valid - uint32 user_valid : 1; // Vp, User-state valid - // lower 32 bit - uint32 physical_block_number : 15; // BPRN - uint32 write_through : 1; // WIMG - uint32 caching_inhibited : 1; - uint32 memory_coherent : 1; - uint32 guarded : 1; - uint32 _reserved1 : 1; - uint32 protection : 2; - - block_address_translation() - { - Clear(); - } - - void SetVirtualAddress(void *address) - { - page_index = uint32(address) >> 17; - } - - void SetPhysicalAddress(void *address) - { - physical_block_number = uint32(address) >> 17; - } - - void Clear() - { - memset((void *)this, 0, sizeof(block_address_translation)); - } +struct long_page_directory_entry { + // upper 32 bits + uint32 type : 2; + uint32 write_protect : 1; + uint32 used : 1; + uint32 _zero1 : 4; + uint32 supervisor : 1; + uint32 _zero2 : 1; + uint32 _ones : 6; + uint32 limit : 15; + uint32 low_up : 1; // limit is lower(1)/upper(0) + // lower 32 bits + uint32 unused : 4; // + uint32 address : 28; }; -struct segment_descriptor { - uint32 type : 1; // 0 for page translation descriptors - uint32 kernel_protection_key : 1; // Ks, Supervisor-state protection key - uint32 user_protection_key : 1; // Kp, User-state protection key - uint32 no_execute_protection : 1; - uint32 _reserved : 4; - uint32 virtual_segment_id : 24; - - segment_descriptor() - { - Clear(); - } - - segment_descriptor(uint32 value) - { - *((uint32 *)this) = value; - } - - void Clear() - { - memset((void *)this, 0, sizeof(segment_descriptor)); - } +struct short_page_table_entry { + uint32 type : 2; + uint32 write_protect : 1; + uint32 used : 1; + uint32 modified : 1; + uint32 _zero1 : 1; + uint32 cache_inhibit : 1; + uint32 _zero2 : 1; + uint32 address : 24; }; - -/*** PTE - page table entry ***/ - -enum pte_protection { - PTE_READ_ONLY = 3, - PTE_READ_WRITE = 2, +struct long_page_table_entry { + // upper 32 bits + uint32 type : 2; + uint32 write_protect : 1; + uint32 used : 1; + uint32 modified : 1; + uint32 _zero1 : 1; + uint32 cache_inhibit : 1; + uint32 _zero2 : 1; + uint32 supervisor : 1; + uint32 _zero3 : 1; + uint32 _ones : 6; + // limit only used on early table terminators, else unused + uint32 limit : 15; + uint32 low_up : 1; // limit is lower(1)/upper(0) + // lower 32 bits + uint32 unused : 8; // + uint32 address : 24; }; +#endif -struct page_table_entry { - // upper 32 bit - uint32 valid : 1; - uint32 virtual_segment_id : 24; - uint32 secondary_hash : 1; - uint32 abbr_page_index : 6; - // lower 32 bit - uint32 physical_page_number : 20; - uint32 _reserved0 : 3; - uint32 referenced : 1; - uint32 changed : 1; - uint32 write_through : 1; // WIMG - uint32 caching_inhibited : 1; - uint32 memory_coherent : 1; - uint32 guarded : 1; - uint32 _reserved1 : 1; - uint32 page_protection : 2; - - static uint32 PrimaryHash(uint32 virtualSegmentID, uint32 virtualAddress); - static uint32 SecondaryHash(uint32 virtualSegmentID, uint32 virtualAddress); - static uint32 SecondaryHash(uint32 primaryHash); -}; - -struct page_table_entry_group { - struct page_table_entry entry[8]; -}; extern void m68k_get_page_table(page_table_entry_group **_pageTable, size_t *_size); extern void m68k_set_page_table(page_table_entry_group *pageTable, size_t size); -static inline segment_descriptor -m68k_get_segment_register(void *virtualAddress) -{ - return (segment_descriptor)get_sr(virtualAddress); -} - - -static inline void -m68k_set_segment_register(void *virtualAddress, segment_descriptor segment) -{ - set_sr(virtualAddress, *(uint32 *)&segment); -} #endif /* _KERNEL_ARCH_M68K_MMU_H */ diff --git a/headers/private/kernel/arch/m68k/arch_thread.h b/headers/private/kernel/arch/m68k/arch_thread.h index b63e9ac876..1c14f672bc 100644 --- a/headers/private/kernel/arch/m68k/arch_thread.h +++ b/headers/private/kernel/arch/m68k/arch_thread.h @@ -19,6 +19,24 @@ void m68k_push_iframe(struct iframe_stack *stack, struct iframe *frame); void m68k_pop_iframe(struct iframe_stack *stack); struct iframe *m68k_get_user_iframe(void); +/* as we won't support SMP on m68k (yet?) we can use a global here */ +extern struct thread *gCurrentThread; + +extern inline struct thread * +arch_thread_get_current_thread(void) +{ + return gCurrentThread; +} + + +extern inline void +arch_thread_set_current_thread(struct thread *t) +{ + gCurrentThread = t; +} + +#if 0 +/* this would only work on 030... */ extern inline struct thread * arch_thread_get_current_thread(void) @@ -37,7 +55,7 @@ arch_thread_set_current_thread(struct thread *t) "move %1,(4,%0)\n" \ "pmove (%0),%%srp" : : "a"(&v), "d"(t)); } - +#endif #ifdef __cplusplus } diff --git a/headers/private/kernel/arch/m68k/arch_vm.h b/headers/private/kernel/arch/m68k/arch_vm.h index 2b2ecd0d45..379c9227eb 100644 --- a/headers/private/kernel/arch/m68k/arch_vm.h +++ b/headers/private/kernel/arch/m68k/arch_vm.h @@ -12,4 +12,24 @@ #define PAGE_SHIFT 12 + +struct m68k_vm_ops { + void *(*m68k_translation_map_get_pgdir)(vm_translation_map *map); + status_t (*arch_vm_translation_map_init_map)(vm_translation_map *map, bool kernel); + status_t (*arch_vm_translation_map_init_kernel_map_post_sem)(vm_translation_map *map); + status_t (*arch_vm_translation_map_init)(kernel_args *args); + status_t (*arch_vm_translation_map_init_post_area)(kernel_args *args); + status_t (*arch_vm_translation_map_init_post_sem)(kernel_args *args); + status_t (*arch_vm_translation_map_early_map)(kernel_args *ka, addr_t virtualAddress, addr_t physicalAddress, + uint8 attributes, addr_t (*get_free_page)(kernel_args *)); + status_t (*arch_vm_translation_map_early_query)(addr_t va, addr_t *out_physical); +#if 0 /* ppc stuff only ? */ + status_t (*m68k_map_address_range)(addr_t virtualAddress, addr_t physicalAddress, + size_t size); + void (*m68k_unmap_address_range)(addr_t virtualAddress, size_t size); + status_t (*m68k_remap_address_range)(addr_t *_virtualAddress, size_t size, bool unmap); +#endif +}; + + #endif /* ARCH_M68K_VM_H */