1845a180fSFrançois Revol /*
24e44040dSFrançois Revol * Copyright 2007, François Revol, revol@free.fr.
34e44040dSFrançois Revol * Distributed under the terms of the MIT License.
44e44040dSFrançois Revol *
5845a180fSFrançois Revol * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de.
6845a180fSFrançois Revol * Distributed under the terms of the MIT License.
7845a180fSFrançois Revol *
8845a180fSFrançois Revol * Copyright 2001, Travis Geiselbrecht. All rights reserved.
9845a180fSFrançois Revol * Distributed under the terms of the NewOS License.
10845a180fSFrançois Revol */
11845a180fSFrançois Revol
12845a180fSFrançois Revol
13845a180fSFrançois Revol #include <KernelExport.h>
14845a180fSFrançois Revol
15845a180fSFrançois Revol #include <arch_platform.h>
16845a180fSFrançois Revol #include <arch_thread.h>
17845a180fSFrançois Revol #include <arch/cpu.h>
18845a180fSFrançois Revol #include <boot/kernel_args.h>
195222f12aSFrançois Revol #include <commpage.h>
205222f12aSFrançois Revol #include <elf.h>
21845a180fSFrançois Revol
224e44040dSFrançois Revol extern struct m68k_cpu_ops cpu_ops_030;
234e44040dSFrançois Revol extern struct m68k_cpu_ops cpu_ops_040;
244e44040dSFrançois Revol extern struct m68k_cpu_ops cpu_ops_060;
254e44040dSFrançois Revol
264e44040dSFrançois Revol struct m68k_cpu_ops cpu_ops;
274e44040dSFrançois Revol
28f0c5a3daSFrançois Revol int arch_cpu_type;
29f0c5a3daSFrançois Revol int arch_fpu_type;
30f0c5a3daSFrançois Revol int arch_mmu_type;
31f0c5a3daSFrançois Revol int arch_platform;
32f0c5a3daSFrançois Revol
33845a180fSFrançois Revol status_t
arch_cpu_preboot_init_percpu(kernel_args * args,int curr_cpu)34845a180fSFrançois Revol arch_cpu_preboot_init_percpu(kernel_args *args, int curr_cpu)
35845a180fSFrançois Revol {
36845a180fSFrançois Revol // enable FPU
37829748d8SFrançois Revol //ppc:set_msr(get_msr() | MSR_FP_AVAILABLE);
38845a180fSFrançois Revol
39845a180fSFrançois Revol // The current thread must be NULL for all CPUs till we have threads.
40845a180fSFrançois Revol // Some boot code relies on this.
41845a180fSFrançois Revol arch_thread_set_current_thread(NULL);
42845a180fSFrançois Revol
43845a180fSFrançois Revol return B_OK;
44845a180fSFrançois Revol }
45845a180fSFrançois Revol
46845a180fSFrançois Revol
47845a180fSFrançois Revol status_t
arch_cpu_init_percpu(kernel_args * args,int curr_cpu)481fd024beSFrançois Revol arch_cpu_init_percpu(kernel_args *args, int curr_cpu)
491fd024beSFrançois Revol {
501fd024beSFrançois Revol //detect_cpu(curr_cpu);
511fd024beSFrançois Revol
521fd024beSFrançois Revol // we only support one anyway...
531fd024beSFrançois Revol return 0;
541fd024beSFrançois Revol }
551fd024beSFrançois Revol
561fd024beSFrançois Revol
571fd024beSFrançois Revol status_t
arch_cpu_init(kernel_args * args)58845a180fSFrançois Revol arch_cpu_init(kernel_args *args)
59845a180fSFrançois Revol {
60a3dc7ef0SFrançois Revol arch_cpu_type = args->arch_args.cpu_type;
61a3dc7ef0SFrançois Revol arch_fpu_type = args->arch_args.fpu_type;
62a3dc7ef0SFrançois Revol arch_mmu_type = args->arch_args.mmu_type;
63a3dc7ef0SFrançois Revol arch_platform = args->arch_args.platform;
64f0c5a3daSFrançois Revol arch_platform = args->arch_args.machine;
654e44040dSFrançois Revol
66a3dc7ef0SFrançois Revol switch (arch_cpu_type) {
67a3dc7ef0SFrançois Revol case 68020:
68a3dc7ef0SFrançois Revol case 68030:
6936ee9f5cSFrançois Revol memcpy(&cpu_ops, &cpu_ops_030, sizeof(cpu_ops));
704e44040dSFrançois Revol break;
71b061bf24SFrançois Revol
72a3dc7ef0SFrançois Revol case 68040:
73b061bf24SFrançois Revol memcpy(&cpu_ops, &cpu_ops_040, sizeof(cpu_ops));
744e44040dSFrançois Revol break;
75b061bf24SFrançois Revol
764e44040dSFrançois Revol #ifdef SUPPORTS_060
77a3dc7ef0SFrançois Revol case 68060:
78b061bf24SFrançois Revol memcpy(&cpu_ops, &cpu_ops_060, sizeof(cpu_ops));
794e44040dSFrançois Revol break;
804e44040dSFrançois Revol #endif
814e44040dSFrançois Revol default:
82a3dc7ef0SFrançois Revol panic("unknown cpu_type %d\n", arch_cpu_type);
834e44040dSFrançois Revol }
84a3dc7ef0SFrançois Revol
85845a180fSFrançois Revol return B_OK;
86845a180fSFrançois Revol }
87845a180fSFrançois Revol
88845a180fSFrançois Revol
89845a180fSFrançois Revol status_t
arch_cpu_init_post_vm(kernel_args * args)90845a180fSFrançois Revol arch_cpu_init_post_vm(kernel_args *args)
91845a180fSFrançois Revol {
92845a180fSFrançois Revol return B_OK;
93845a180fSFrançois Revol }
94845a180fSFrançois Revol
95845a180fSFrançois Revol status_t
arch_cpu_init_post_modules(kernel_args * args)96845a180fSFrançois Revol arch_cpu_init_post_modules(kernel_args *args)
97845a180fSFrançois Revol {
985222f12aSFrançois Revol // add the functions to the commpage image
995222f12aSFrançois Revol image_id image = get_commpage_image();
1005222f12aSFrançois Revol
101845a180fSFrançois Revol return B_OK;
102845a180fSFrançois Revol }
103845a180fSFrançois Revol
104845a180fSFrançois Revol
105845a180fSFrançois Revol void
arch_cpu_sync_icache(void * address,size_t len)106845a180fSFrançois Revol arch_cpu_sync_icache(void *address, size_t len)
107845a180fSFrançois Revol {
108a3dc7ef0SFrançois Revol cpu_ops.flush_icache((addr_t)address, len);
109845a180fSFrançois Revol }
110845a180fSFrançois Revol
111845a180fSFrançois Revol
112845a180fSFrançois Revol void
arch_cpu_memory_read_barrier(void)113807cf76dSFrançois Revol arch_cpu_memory_read_barrier(void)
114807cf76dSFrançois Revol {
115807cf76dSFrançois Revol asm volatile ("nop;" : : : "memory");
116b061bf24SFrançois Revol #warning M68k: check arch_cpu_memory_read_barrier (FNOP ?)
117807cf76dSFrançois Revol }
118807cf76dSFrançois Revol
119807cf76dSFrançois Revol
120807cf76dSFrançois Revol void
arch_cpu_memory_write_barrier(void)121807cf76dSFrançois Revol arch_cpu_memory_write_barrier(void)
122807cf76dSFrançois Revol {
123807cf76dSFrançois Revol asm volatile ("nop;" : : : "memory");
124b061bf24SFrançois Revol #warning M68k: check arch_cpu_memory_write_barrier (FNOP ?)
125807cf76dSFrançois Revol }
126807cf76dSFrançois Revol
127807cf76dSFrançois Revol
128807cf76dSFrançois Revol void
arch_cpu_invalidate_TLB_range(addr_t start,addr_t end)129845a180fSFrançois Revol arch_cpu_invalidate_TLB_range(addr_t start, addr_t end)
130845a180fSFrançois Revol {
1314237dbd0SFrançois Revol int32 num_pages = end / B_PAGE_SIZE - start / B_PAGE_SIZE;
1324e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
1334237dbd0SFrançois Revol while (num_pages-- >= 0) {
1344e44040dSFrançois Revol cpu_ops.flush_atc_addr(start);
1354e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
136845a180fSFrançois Revol start += B_PAGE_SIZE;
137845a180fSFrançois Revol }
1384e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
139845a180fSFrançois Revol }
140845a180fSFrançois Revol
141845a180fSFrançois Revol
142845a180fSFrançois Revol void
arch_cpu_invalidate_TLB_list(addr_t pages[],int num_pages)143845a180fSFrançois Revol arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages)
144845a180fSFrançois Revol {
145845a180fSFrançois Revol int i;
146845a180fSFrançois Revol
1474e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
148845a180fSFrançois Revol for (i = 0; i < num_pages; i++) {
1494e44040dSFrançois Revol cpu_ops.flush_atc_addr(pages[i]);
1504e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
151845a180fSFrançois Revol }
1524e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
153845a180fSFrançois Revol }
154845a180fSFrançois Revol
155845a180fSFrançois Revol
156845a180fSFrançois Revol void
arch_cpu_global_TLB_invalidate(void)157845a180fSFrançois Revol arch_cpu_global_TLB_invalidate(void)
158845a180fSFrançois Revol {
1594e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
1604e44040dSFrançois Revol cpu_ops.flush_atc_all();
1614e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
162845a180fSFrançois Revol }
163845a180fSFrançois Revol
164845a180fSFrançois Revol
165845a180fSFrançois Revol void
arch_cpu_user_TLB_invalidate(void)166845a180fSFrançois Revol arch_cpu_user_TLB_invalidate(void)
167845a180fSFrançois Revol {
1684e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
1694e44040dSFrançois Revol cpu_ops.flush_atc_user();
1704e44040dSFrançois Revol cpu_ops.flush_insn_pipeline();
171845a180fSFrançois Revol }
172845a180fSFrançois Revol
173845a180fSFrançois Revol
174845a180fSFrançois Revol status_t
arch_cpu_shutdown(bool reboot)175845a180fSFrançois Revol arch_cpu_shutdown(bool reboot)
176845a180fSFrançois Revol {
177845a180fSFrançois Revol M68KPlatform::Default()->ShutDown(reboot);
178845a180fSFrançois Revol return B_ERROR;
179845a180fSFrançois Revol }
180845a180fSFrançois Revol
181845a180fSFrançois Revol
182845a180fSFrançois Revol // The purpose of this function is to trick the compiler. When setting the
183845a180fSFrançois Revol // page_handler to a label that is obviously (to the compiler) never used,
184845a180fSFrançois Revol // it may reorganize the control flow, so that the labeled part is optimized
185845a180fSFrançois Revol // away.
186845a180fSFrançois Revol // By invoking the function like this
187845a180fSFrançois Revol //
188845a180fSFrançois Revol // if (m68k_set_fault_handler(faultHandler, (addr_t)&&error))
189845a180fSFrançois Revol // goto error;
190845a180fSFrançois Revol //
191845a180fSFrançois Revol // the compiler has to keep the labeled code, since it can't guess the return
192845a180fSFrançois Revol // value of this (non-inlinable) function. At least in my tests it worked that
193845a180fSFrançois Revol // way, and I hope it will continue to work like this in the future.
194845a180fSFrançois Revol //
195845a180fSFrançois Revol bool
m68k_set_fault_handler(addr_t * handlerLocation,addr_t handler)196845a180fSFrançois Revol m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler)
197845a180fSFrançois Revol {
198*ea2abd11SIngo Weinhold // TODO: This doesn't work correctly with gcc 4 anymore!
199845a180fSFrançois Revol *handlerLocation = handler;
200845a180fSFrançois Revol return false;
201845a180fSFrançois Revol }
202