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
This commit is contained in:
parent
5a4ca4d18e
commit
1a8a803ee1
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user