2010年02月09日
情報科学類 オペレーティングシステム II
筑波大学 システム情報工学研究科
コンピュータサイエンス専攻, 電子・情報工学系
新城 靖
<yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/literacy-2009/2010-02-09
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
arch/x86/mm/fault.c: do_page_fault(struct pt_regs *regs, unsigned long error_code)do_page_fault() は、CPUアーキテクチャによって違う。 x86 の ハードウェアの割り込み 14 により呼ばれる。次の条件で生じる。
| Bit 2 | Bit 1 | Bit 0 | |
|---|---|---|---|
| 0 | カーネル | 読み込み | ページがない |
| 1 | ユーザ | 書き込み | 保護違反 |
arch/x86/mm/fault.c
944: do_page_fault(struct pt_regs *regs, unsigned long error_code)
945: {
946: struct vm_area_struct *vma;
947: struct task_struct *tsk;
948: unsigned long address;
949: struct mm_struct *mm;
950: int write;
951: int fault;
952:
953: tsk = current;
954: mm = tsk->mm;
...
957: address = read_cr2();
...
1072: vma = find_vma(mm, address);
1073: if (unlikely(!vma)) {
1074: bad_area(regs, error_code, address);
1075: return;
1076: }
1077: if (likely(vma->vm_start <= address))
1078: goto good_area;
1079: if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) {
1080: bad_area(regs, error_code, address);
1081: return;
1082: }
...
1095: if (unlikely(expand_stack(vma, address))) {
1096: bad_area(regs, error_code, address);
1097: return;
1098: }
...
1104: good_area:
1105: write = error_code & PF_WRITE;
1106:
1107: if (unlikely(access_error(error_code, write, vma))) {
1108: bad_area_access_error(regs, error_code, address);
1109: return;
1110: }
..
1117: fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
...
1137: }
mm/memory.c
2963: int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
2964: unsqigned long address, unsigned int flags)
2965: {
2966: pgd_t *pgd;
2967: pud_t *pud;
2968: pmd_t *pmd;
2969: pte_t *pte;
...
2978: pgd = pgd_offset(mm, address);
2979: pud = pud_alloc(mm, pgd, address);
2980: if (!pud)
2981: return VM_FAULT_OOM;
2982: pmd = pmd_alloc(mm, pud, address);
2983: if (!pmd)
2984: return VM_FAULT_OOM;
2985: pte = pte_alloc_map(mm, pmd, address);
2986: if (!pte)
2987: return VM_FAULT_OOM;
2988:
2989: return handle_pte_fault(mm, vma, address, pte, pmd, flags);
2990: }
2907: static inline int handle_pte_fault(struct mm_struct *mm,
2908: struct vm_area_struct *vma, unsigned long address,
2909: pte_t *pte, pmd_t *pmd, unsigned int flags)
2910: {
2911: pte_t entry;
2912: spinlock_t *ptl;
2913:
2914: entry = *pte;
...
2916: if (pte_none(entry)) {
2917: if (vma->vm_ops) {
2918: if (likely(vma->vm_ops->fault))
2919: return do_linear_fault(mm, vma, address,
2920: pte, pmd, flags, entry);
2921: }
2922: return do_anonymous_page(mm, vma, address,
2923: pte, pmd, flags);
2924: }
...
2928: return do_swap_page(mm, vma, address,
2929: pte, pmd, flags, entry);
...
2958: }
vma->vm_ops->fault という関数があれば、
do_linear_fault() で処理する。
% date
Mon Feb 8 23:33:36 JST 2010
% hwclock --show
Mon Feb 8 23:33:40 2010 -0.748647 seconds
%
wdrivers/char/rtc.c
1299: static void rtc_get_rtc_time(struct rtc_time *rtc_tm)
1300: {
1301: unsigned long uip_watchdog = jiffies, flags;
1302: unsigned char ctrl;
...
1327: spin_lock_irqsave(&rtc_lock, flags);
1328: rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
1329: rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
1330: rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
1331: rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
1332: rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
1333: rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
1334: /* Only set from 2.6.16 onwards */
1335: rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK);
...
1340: ctrl = CMOS_READ(RTC_CONTROL);
1341: spin_unlock_irqrestore(&rtc_lock, flags);
1342:
1343: if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
1344: rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
1345: rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
1346: rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
1347: rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
1348: rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
1349: rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
1350: rtc_tm->tm_wday = bcd2bin(rtc_tm->tm_wday);
1351: }
1361: rtc_tm->tm_year += epoch - 1900;
1362: if (rtc_tm->tm_year <= 69)
1363: rtc_tm->tm_year += 100;
1364:
1365: rtc_tm->tm_mon--;
1366: }
arch/x86/include/asm/mc146818rtc.h
94: #define CMOS_READ(addr) rtc_cmos_read(addr)
95: #define CMOS_WRITE(val, addr) rtc_cmos_write(val, addr)
arch/x86/kernel/rtc.c
146: unsigned char rtc_cmos_read(unsigned char addr)
147: {
148: unsigned char val;
149:
150: lock_cmos_prefix(addr);
151: outb(addr, RTC_PORT(0));
152: val = inb(RTC_PORT(1));
153: lock_cmos_suffix(addr);
154:
155: return val;
156: }
include/linux/mc146818rtc.h
43: #define RTC_SECONDS 0
45: #define RTC_MINUTES 2
47: #define RTC_HOURS 4
...
52: #define RTC_DAY_OF_WEEK 6
53: #define RTC_DAY_OF_MONTH 7
54: #define RTC_MONTH 8
55: #define RTC_YEAR 9
86: #define RTC_CONTROL RTC_REG_B
92: # define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
arch/x86/include/asm/mc146818rtc.h
13: #define RTC_PORT(x) (0x70 + (x))
14: #define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
outb(unsigned char value, int port) ポート番号 port に 1 バイトの value を出力する unsigned char inb(int port) ポート番号 port から 1 バイトの value を入力してその値を返す
asm ( アセンブラの命令列 : 出力オペランド(省略可) : 入力オペランド(省略可) : 破壊するレジスタ(省略可) )
"制約"(Cの値)
= があると、書き込み専用
arch/x86/include/asm/io_32.h
126: #define __BUILDIO(bwl, bw, type) \
127: static inline void out##bwl(unsigned type value, int port) \
128: { \
129: out##bwl##_local(value, port); \
130: } \
131: \
132: static inline unsigned type in##bwl(int port) \
133: { \
134: return in##bwl##_local(port); \
135: }
136:
137: #define BUILDIO(bwl, bw, type) \
138: static inline void out##bwl##_local(unsigned type value, int port) \
139: { \
140: asm volatile("out" #bwl " %" #bw "0, %w1" \
141: : : "a"(value), "Nd"(port)); \
142: } \
143: \
144: static inline unsigned type in##bwl##_local(int port) \
145: { \
146: unsigned type value; \
147: asm volatile("in" #bwl " %w1, %" #bw "0" \
148: : "=a"(value) : "Nd"(port)); \
149: return value; \
150: } \
151: \
...
192: BUILDIO(b, b, char)
193: BUILDIO(w, w, short)
194: BUILDIO(l, , int)
unsigned char hh;
outb( /*(a)*/, 0x70 );
hh = inb( /*(b)*/ );