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
This commit is contained in:
François Revol 2007-11-03 21:02:03 +00:00
parent 5a4ca4d18e
commit 1a8a803ee1
5 changed files with 188 additions and 160 deletions

View File

@ -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

View File

@ -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;

View File

@ -11,139 +11,114 @@
#include <arch_cpu.h>
/*
* 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 */

View File

@ -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
}

View File

@ -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 */